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