xref: /freebsd/crypto/krb5/src/lib/crypto/builtin/des/f_cksum.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/crypto/builtin/des/f_cksum.c */
3 /*
4  * Copyright (C) 1990 by the Massachusetts Institute of Technology.
5  * All rights reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 /* DES implementation donated by Dennis Ferguson */
28 
29 /*
30  * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode
31  */
32 #include "crypto_int.h"
33 #include "des_int.h"
34 #include "f_tables.h"
35 
36 #ifdef K5_BUILTIN_DES
37 
38 /*
39  * This routine performs DES cipher-block-chaining checksum operation,
40  * a.k.a.  Message Authentication Code.  It ALWAYS encrypts from input
41  * to a single 64 bit output MAC checksum.
42  *
43  * The key schedule is passed as an arg, as well as the cleartext or
44  * ciphertext. The cleartext and ciphertext should be in host order.
45  *
46  * NOTE-- the output is ALWAYS 8 bytes long.  If not enough space was
47  * provided, your program will get trashed.
48  *
49  * The input is null padded, at the end (highest addr), to an integral
50  * multiple of eight bytes.
51  */
52 
53 unsigned long
mit_des_cbc_cksum(const krb5_octet * in,krb5_octet * out,unsigned long length,const mit_des_key_schedule schedule,const krb5_octet * ivec)54 mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out,
55                   unsigned long length, const mit_des_key_schedule schedule,
56                   const krb5_octet *ivec)
57 {
58     unsigned DES_INT32 left, right;
59     const unsigned DES_INT32 *kp;
60     const unsigned char *ip;
61     unsigned char *op;
62     DES_INT32 len;
63 
64     /*
65      * Initialize left and right with the contents of the initial
66      * vector.
67      */
68     ip = ivec;
69     GET_HALF_BLOCK(left, ip);
70     GET_HALF_BLOCK(right, ip);
71 
72     /*
73      * Suitably initialized, now work the length down 8 bytes
74      * at a time.
75      */
76     ip = in;
77     len = length;
78     while (len > 0) {
79         /*
80          * Get more input, xor it in.  If the length is
81          * greater than or equal to 8 this is straight
82          * forward.  Otherwise we have to fart around.
83          */
84         if (len >= 8) {
85             unsigned DES_INT32 temp;
86             GET_HALF_BLOCK(temp, ip);
87             left  ^= temp;
88             GET_HALF_BLOCK(temp, ip);
89             right ^= temp;
90             len -= 8;
91         } else {
92             /*
93              * Oh, shoot.  We need to pad the
94              * end with zeroes.  Work backwards
95              * to do this.
96              */
97             ip += (int) len;
98             switch(len) {
99             case 7:
100                 right ^= (*(--ip) & FF_UINT32) <<  8;
101             case 6:
102                 right ^= (*(--ip) & FF_UINT32) << 16;
103             case 5:
104                 right ^= (*(--ip) & FF_UINT32) << 24;
105             case 4:
106                 left  ^=  *(--ip) & FF_UINT32;
107             case 3:
108                 left  ^= (*(--ip) & FF_UINT32) <<  8;
109             case 2:
110                 left  ^= (*(--ip) & FF_UINT32) << 16;
111             case 1:
112                 left  ^= (*(--ip) & FF_UINT32) << 24;
113                 break;
114             }
115             len = 0;
116         }
117 
118         /*
119          * Encrypt what we have
120          */
121         kp = (const unsigned DES_INT32 *)schedule;
122         DES_DO_ENCRYPT(left, right, kp);
123     }
124 
125     /*
126      * Done.  Left and right have the checksum.  Put it into
127      * the output.
128      */
129     op = out;
130     PUT_HALF_BLOCK(left, op);
131     PUT_HALF_BLOCK(right, op);
132 
133     /*
134      * Return right.  I'll bet the MIT code returns this
135      * inconsistantly (with the low order byte of the checksum
136      * not always in the low order byte of the DES_INT32).  We won't.
137      */
138     return right & 0xFFFFFFFFUL;
139 }
140 
141 #endif /* K5_BUILTIN_DES */
142