]>
Commit | Line | Data |
---|---|---|
b0d623f7 A |
1 | /* |
2 | * Copyright (c) 2008 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | ||
29 | ||
30 | /* | |
31 | * Copyright (C) 1998 by the FundsXpress, INC. | |
32 | * | |
33 | * All rights reserved. | |
34 | * | |
35 | * Export of this software from the United States of America may require | |
36 | * a specific license from the United States Government. It is the | |
37 | * responsibility of any person or organization contemplating export to | |
38 | * obtain such a license before exporting. | |
39 | * | |
40 | * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and | |
41 | * distribute this software and its documentation for any purpose and | |
42 | * without fee is hereby granted, provided that the above copyright | |
43 | * notice appear in all copies and that both that copyright notice and | |
44 | * this permission notice appear in supporting documentation, and that | |
45 | * the name of FundsXpress. not be used in advertising or publicity pertaining | |
46 | * to distribution of the software without specific, written prior | |
47 | * permission. FundsXpress makes no representations about the suitability of | |
48 | * this software for any purpose. It is provided "as is" without express | |
49 | * or implied warranty. | |
50 | * | |
51 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
52 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
53 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
54 | */ | |
55 | ||
56 | #include "nfs_gss_crypto.h" | |
57 | ||
58 | ||
59 | /* | |
60 | n-fold(k-bits): | |
61 | l = lcm(n,k) | |
62 | r = l/k | |
63 | s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1) | |
64 | compute the 1's complement sum: | |
65 | n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1] | |
66 | */ | |
67 | ||
68 | /* representation: msb first, assume n and k are multiples of 8, and | |
69 | that k>=16. this is the case of all the cryptosystems which are | |
70 | likely to be used. this function can be replaced if that | |
71 | assumption ever fails. */ | |
72 | ||
73 | /* input length is in bits */ | |
74 | ||
75 | void | |
76 | krb5_nfold(unsigned int inbits, const unsigned char *in, unsigned int outbits, | |
77 | unsigned char *out) | |
78 | { | |
79 | int a,b,c,lcm; | |
80 | int byte, i, msbit; | |
81 | ||
82 | /* the code below is more readable if I make these bytes | |
83 | instead of bits */ | |
84 | ||
85 | inbits >>= 3; | |
86 | outbits >>= 3; | |
87 | ||
88 | /* first compute lcm(n,k) */ | |
89 | ||
90 | a = outbits; | |
91 | b = inbits; | |
92 | ||
93 | while(b != 0) { | |
94 | c = b; | |
95 | b = a%b; | |
96 | a = c; | |
97 | } | |
98 | ||
99 | lcm = outbits*inbits/a; | |
100 | ||
101 | /* now do the real work */ | |
102 | ||
103 | memset(out, 0, outbits); | |
104 | byte = 0; | |
105 | ||
106 | /* this will end up cycling through k lcm(k,n)/k times, which | |
107 | is correct */ | |
108 | for (i=lcm-1; i>=0; i--) { | |
109 | /* compute the msbit in k which gets added into this byte */ | |
110 | msbit = (/* first, start with the msbit in the first, unrotated | |
111 | byte */ | |
112 | ((inbits<<3)-1) | |
113 | /* then, for each byte, shift to the right for each | |
114 | repetition */ | |
115 | +(((inbits<<3)+13)*(i/inbits)) | |
116 | /* last, pick out the correct byte within that | |
117 | shifted repetition */ | |
118 | +((inbits-(i%inbits))<<3) | |
119 | )%(inbits<<3); | |
120 | ||
121 | /* pull out the byte value itself */ | |
122 | byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| | |
123 | (in[((inbits)-(msbit>>3))%inbits])) | |
124 | >>((msbit&7)+1))&0xff; | |
125 | ||
126 | /* do the addition */ | |
127 | byte += out[i%outbits]; | |
128 | out[i%outbits] = byte&0xff; | |
129 | ||
130 | #if 0 | |
131 | printf("msbit[%d] = %d\tbyte = %02x\tsum = %03x\n", i, msbit, | |
132 | (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| | |
133 | (in[((inbits)-(msbit>>3))%inbits])) | |
134 | >>((msbit&7)+1))&0xff, byte); | |
135 | #endif | |
136 | ||
137 | /* keep around the carry bit, if any */ | |
138 | byte >>= 8; | |
139 | ||
140 | #if 0 | |
141 | printf("carry=%d\n", byte); | |
142 | #endif | |
143 | } | |
144 | ||
145 | /* if there's a carry bit left over, add it back in */ | |
146 | if (byte) { | |
147 | for (i=outbits-1; i>=0; i--) { | |
148 | /* do the addition */ | |
149 | byte += out[i]; | |
150 | out[i] = byte&0xff; | |
151 | ||
152 | /* keep around the carry bit, if any */ | |
153 | byte >>= 8; | |
154 | } | |
155 | } | |
156 | } | |
157 | ||
158 | /* | |
159 | * Given 21 bytes of random bits, make a triple DES key. | |
160 | */ | |
161 | ||
162 | void | |
163 | des3_make_key(const unsigned char randombits[21], des_cblock key[3]) | |
164 | { | |
165 | int i; | |
166 | ||
167 | for (i = 0; i < 3; i++) { | |
168 | memcpy(&key[i], &randombits[i*7], 7); | |
169 | key[i][7] = (((key[i][0] & 1) << 1) | | |
170 | ((key[i][1] & 1) << 2) | | |
171 | ((key[i][2] & 1) << 3) | | |
172 | ((key[i][3] & 1) << 4) | | |
173 | ((key[i][4] & 1) << 5) | | |
174 | ((key[i][5] & 1) << 6) | | |
175 | ((key[i][6] & 1) << 7)); | |
176 | des_fixup_key_parity(&key[i]); | |
177 | } | |
178 | } | |
179 | ||
b0d623f7 A |
180 | /* |
181 | * Key derivation for triple DES. | |
182 | * Given the session key in in key, produce a new key in out key using | |
183 | * the supplied constant. | |
184 | */ | |
185 | ||
186 | int | |
187 | des3_derive_key(des_cblock inkey[3], des_cblock outkey[3], | |
188 | const unsigned char *constant, int clen) | |
189 | { | |
190 | des_cblock inblock, outblock, ivec; | |
316670eb | 191 | des3_cbc_key_schedule sched; |
b0d623f7 A |
192 | unsigned char rawkey[21]; |
193 | size_t n, keybytes = sizeof(rawkey); | |
194 | ||
195 | /* initialize the input block */ | |
196 | ||
197 | if (clen == sizeof(des_cblock)) { | |
198 | memcpy(inblock, constant, clen); | |
199 | } else { | |
200 | krb5_nfold(clen*8, constant, sizeof(des_cblock)*8, inblock); | |
201 | } | |
202 | ||
203 | /* loop encrypting the blocks until enough key bytes are generated */ | |
204 | ||
205 | bzero(ivec, sizeof(ivec)); | |
316670eb | 206 | des3_cbc_key_sched(inkey, &sched); |
b0d623f7 | 207 | for (n = 0; n < sizeof(rawkey); n += sizeof(des_cblock)) { |
316670eb | 208 | des3_cbc_encrypt(&inblock, &outblock, sizeof(outblock), &sched, &ivec, NULL, 1); |
b0d623f7 A |
209 | if ((keybytes - n) <= sizeof (des_cblock)) { |
210 | memcpy(rawkey+n, outblock, (keybytes - n)); | |
211 | break; | |
212 | } | |
213 | memcpy(rawkey+n, outblock, sizeof(des_cblock)); | |
214 | memcpy(inblock, outblock, sizeof(des_cblock)); | |
215 | } | |
216 | ||
217 | /* postprocess the key */ | |
218 | des3_make_key(rawkey, outkey); | |
219 | ||
220 | /* clean memory, free resources and exit */ | |
221 | ||
222 | bzero(inblock, sizeof (des_cblock)); | |
223 | bzero(outblock, sizeof (des_cblock)); | |
224 | bzero(rawkey, keybytes); | |
316670eb | 225 | bzero(&sched, sizeof (sched)); |
b0d623f7 A |
226 | |
227 | return(0); | |
228 | } | |
229 | ||
230 | /* | |
231 | * Initialize a context for HMAC SHA1 | |
232 | * if drived is true we derive a new key | |
233 | * based on KG_USAGE_SIGN | |
234 | */ | |
235 | ||
236 | void | |
237 | HMAC_SHA1_DES3KD_Init(HMAC_SHA1_DES3KD_CTX *ctx, des_cblock key[3], int derive) | |
238 | { | |
239 | unsigned char ipad[64]; | |
240 | size_t i, j; | |
241 | ||
242 | SHA1Init(&ctx->sha1_ctx); | |
243 | if (derive) | |
244 | des3_derive_key(key, ctx->dk, KEY_USAGE_DES3_SIGN, KEY_USAGE_LEN); | |
245 | else | |
246 | memcpy(ctx->dk, key, 3*sizeof(des_cblock)); | |
247 | memset(ipad, 0x36, sizeof(ipad)); | |
248 | for (i = 0; i < 3; i++) | |
249 | for (j = 0; j < sizeof(des_cblock); j++) | |
250 | ipad[j + i * sizeof(des_cblock)] ^= ctx->dk[i][j]; | |
251 | SHA1Update(&ctx->sha1_ctx, ipad, sizeof(ipad)); | |
252 | } | |
253 | ||
254 | /* | |
255 | * Update the HMAC SHA1 context with the supplied data. | |
256 | */ | |
257 | void | |
258 | HMAC_SHA1_DES3KD_Update(HMAC_SHA1_DES3KD_CTX *ctx, void *data, size_t len) | |
259 | { | |
260 | SHA1Update(&ctx->sha1_ctx, data, len); | |
261 | } | |
262 | ||
263 | /* | |
264 | * Finish the context and produce the HMAC SHA1 digest. | |
265 | */ | |
266 | ||
267 | void | |
268 | HMAC_SHA1_DES3KD_Final(void *digest, HMAC_SHA1_DES3KD_CTX *ctx) | |
269 | { | |
270 | unsigned char opad[64]; | |
271 | size_t i, j; | |
272 | ||
273 | SHA1Final(digest, &ctx->sha1_ctx); | |
274 | memset(opad, 0x5c, sizeof(opad)); | |
275 | for (i = 0; i < 3; i++) | |
276 | for (j = 0; j < sizeof(des_cblock); j++) | |
277 | opad[j + i * sizeof(des_cblock)] ^= ctx->dk[i][j]; | |
278 | SHA1Init(&ctx->sha1_ctx); | |
279 | SHA1Update(&ctx->sha1_ctx, opad, sizeof(opad)); | |
280 | SHA1Update(&ctx->sha1_ctx, digest, SHA1_RESULTLEN); | |
281 | SHA1Final(digest, &ctx->sha1_ctx); | |
282 | } | |
283 | ||
b0d623f7 A |
284 | /* |
285 | * Initialize an MD5 DES CBC context with a schedule. | |
286 | */ | |
287 | ||
316670eb | 288 | void MD5_DESCBC_Init(MD5_DESCBC_CTX *ctx, des_cbc_key_schedule *sched) |
b0d623f7 A |
289 | { |
290 | MD5Init(&ctx->md5_ctx); | |
291 | ctx->sched = sched; | |
292 | } | |
293 | ||
294 | /* | |
295 | * Update MD5 DES CBC context with the supplied data. | |
296 | */ | |
297 | ||
298 | void MD5_DESCBC_Update(MD5_DESCBC_CTX *ctx, void *data, size_t len) | |
299 | { | |
300 | MD5Update(&ctx->md5_ctx, data, len); | |
301 | } | |
302 | ||
303 | /* | |
304 | * Finalize the context and extract the digest. | |
305 | */ | |
306 | ||
307 | void MD5_DESCBC_Final(void *digest, MD5_DESCBC_CTX *ctx) | |
308 | { | |
b0d623f7 A |
309 | unsigned char md5_digest[MD5_DIGEST_LENGTH]; |
310 | ||
311 | MD5Final(md5_digest, &ctx->md5_ctx); | |
312 | ||
313 | /* | |
314 | * Now get the DES CBC checksum for the digest. | |
315 | */ | |
316670eb A |
316 | des_cbc_cksum((des_cblock *) md5_digest, (des_cblock *)digest, |
317 | sizeof (md5_digest), ctx->sched); | |
b0d623f7 A |
318 | } |
319 |