]>
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 | ||
180 | /* | |
181 | * Make a triple des key schedule, from a triple des key. | |
182 | */ | |
183 | ||
184 | int | |
185 | des3_key_sched(des_cblock key[3], des_key_schedule sched[3]) | |
186 | { | |
187 | int i; | |
188 | int rc = 0; | |
189 | ||
190 | for (i = 0; i < 3; i++) | |
191 | rc |= des_key_sched(&key[i], sched[i]); | |
192 | ||
193 | return (rc); | |
194 | } | |
195 | ||
196 | /* | |
197 | * Triple DES cipher block chaining mode encryption. | |
198 | */ | |
199 | ||
200 | void | |
201 | des3_cbc_encrypt(des_cblock *input, des_cblock *output, int32_t length, | |
202 | des_key_schedule schedule[3], des_cblock *ivec, des_cblock *retvec, int encrypt) | |
203 | { | |
204 | register DES_LONG tin0,tin1; | |
205 | register DES_LONG tout0,tout1,xor0,xor1; | |
206 | register unsigned char *in,*out,*retval; | |
207 | register int32_t l=length; | |
208 | DES_LONG tin[2]; | |
209 | unsigned char *iv; | |
210 | tin0 = tin1 = 0; | |
211 | ||
212 | in=(unsigned char *)input; | |
213 | out=(unsigned char *)output; | |
214 | retval=(unsigned char *)retvec; | |
215 | iv=(unsigned char *)ivec; | |
216 | ||
217 | if (encrypt) { | |
218 | c2l(iv,tout0); | |
219 | c2l(iv,tout1); | |
220 | for (l-=8; l>=0; l-=8) { | |
221 | c2l(in,tin0); | |
222 | c2l(in,tin1); | |
223 | tin0^=tout0; tin[0]=tin0; | |
224 | tin1^=tout1; tin[1]=tin1; | |
225 | des_encrypt3((DES_LONG *)tin,schedule[0], schedule[1], schedule[2]); | |
226 | tout0=tin[0]; l2c(tout0,out); | |
227 | tout1=tin[1]; l2c(tout1,out); | |
228 | } | |
229 | if (l != -8) { | |
230 | c2ln(in,tin0,tin1,l+8); | |
231 | tin0^=tout0; tin[0]=tin0; | |
232 | tin1^=tout1; tin[1]=tin1; | |
233 | des_encrypt3((DES_LONG *)tin,schedule[0], schedule[1], schedule[2]); | |
234 | tout0=tin[0]; l2c(tout0,out); | |
235 | tout1=tin[1]; l2c(tout1,out); | |
236 | } | |
237 | if (retval) { | |
238 | l2c(tout0,retval); | |
239 | l2c(tout1,retval); | |
240 | } | |
241 | } else { | |
242 | c2l(iv,xor0); | |
243 | c2l(iv,xor1); | |
244 | for (l-=8; l>=0; l-=8) { | |
245 | c2l(in,tin0); tin[0]=tin0; | |
246 | c2l(in,tin1); tin[1]=tin1; | |
247 | des_decrypt3((DES_LONG *)tin,schedule[0],schedule[1],schedule[2]); | |
248 | tout0=tin[0]^xor0; | |
249 | tout1=tin[1]^xor1; | |
250 | l2c(tout0,out); | |
251 | l2c(tout1,out); | |
252 | xor0=tin0; | |
253 | xor1=tin1; | |
254 | } | |
255 | if (l != -8) { | |
256 | c2l(in,tin0); tin[0]=tin0; | |
257 | c2l(in,tin1); tin[1]=tin1; | |
258 | des_decrypt3((DES_LONG *)tin,schedule[0],schedule[1],schedule[2]); | |
259 | tout0=tin[0]^xor0; | |
260 | tout1=tin[1]^xor1; | |
261 | l2cn(tout0,tout1,out,l+8); | |
262 | /* xor0=tin0; | |
263 | xor1=tin1; */ | |
264 | } | |
265 | if (retval) { | |
266 | l2c(tin0,retval); | |
267 | l2c(tin1,retval); | |
268 | } | |
269 | } | |
270 | tin0=tin1=tout0=tout1=xor0=xor1=0; | |
271 | tin[0]=tin[1]=0; | |
272 | } | |
273 | ||
274 | /* | |
275 | * Key derivation for triple DES. | |
276 | * Given the session key in in key, produce a new key in out key using | |
277 | * the supplied constant. | |
278 | */ | |
279 | ||
280 | int | |
281 | des3_derive_key(des_cblock inkey[3], des_cblock outkey[3], | |
282 | const unsigned char *constant, int clen) | |
283 | { | |
284 | des_cblock inblock, outblock, ivec; | |
285 | des_key_schedule sched[3]; | |
286 | unsigned char rawkey[21]; | |
287 | size_t n, keybytes = sizeof(rawkey); | |
288 | ||
289 | /* initialize the input block */ | |
290 | ||
291 | if (clen == sizeof(des_cblock)) { | |
292 | memcpy(inblock, constant, clen); | |
293 | } else { | |
294 | krb5_nfold(clen*8, constant, sizeof(des_cblock)*8, inblock); | |
295 | } | |
296 | ||
297 | /* loop encrypting the blocks until enough key bytes are generated */ | |
298 | ||
299 | bzero(ivec, sizeof(ivec)); | |
300 | des3_key_sched(inkey, sched); | |
301 | for (n = 0; n < sizeof(rawkey); n += sizeof(des_cblock)) { | |
302 | des3_cbc_encrypt(&inblock, &outblock, sizeof(outblock), sched, &ivec, NULL, 1); | |
303 | if ((keybytes - n) <= sizeof (des_cblock)) { | |
304 | memcpy(rawkey+n, outblock, (keybytes - n)); | |
305 | break; | |
306 | } | |
307 | memcpy(rawkey+n, outblock, sizeof(des_cblock)); | |
308 | memcpy(inblock, outblock, sizeof(des_cblock)); | |
309 | } | |
310 | ||
311 | /* postprocess the key */ | |
312 | des3_make_key(rawkey, outkey); | |
313 | ||
314 | /* clean memory, free resources and exit */ | |
315 | ||
316 | bzero(inblock, sizeof (des_cblock)); | |
317 | bzero(outblock, sizeof (des_cblock)); | |
318 | bzero(rawkey, keybytes); | |
319 | bzero(sched, sizeof (sched)); | |
320 | ||
321 | return(0); | |
322 | } | |
323 | ||
324 | /* | |
325 | * Initialize a context for HMAC SHA1 | |
326 | * if drived is true we derive a new key | |
327 | * based on KG_USAGE_SIGN | |
328 | */ | |
329 | ||
330 | void | |
331 | HMAC_SHA1_DES3KD_Init(HMAC_SHA1_DES3KD_CTX *ctx, des_cblock key[3], int derive) | |
332 | { | |
333 | unsigned char ipad[64]; | |
334 | size_t i, j; | |
335 | ||
336 | SHA1Init(&ctx->sha1_ctx); | |
337 | if (derive) | |
338 | des3_derive_key(key, ctx->dk, KEY_USAGE_DES3_SIGN, KEY_USAGE_LEN); | |
339 | else | |
340 | memcpy(ctx->dk, key, 3*sizeof(des_cblock)); | |
341 | memset(ipad, 0x36, sizeof(ipad)); | |
342 | for (i = 0; i < 3; i++) | |
343 | for (j = 0; j < sizeof(des_cblock); j++) | |
344 | ipad[j + i * sizeof(des_cblock)] ^= ctx->dk[i][j]; | |
345 | SHA1Update(&ctx->sha1_ctx, ipad, sizeof(ipad)); | |
346 | } | |
347 | ||
348 | /* | |
349 | * Update the HMAC SHA1 context with the supplied data. | |
350 | */ | |
351 | void | |
352 | HMAC_SHA1_DES3KD_Update(HMAC_SHA1_DES3KD_CTX *ctx, void *data, size_t len) | |
353 | { | |
354 | SHA1Update(&ctx->sha1_ctx, data, len); | |
355 | } | |
356 | ||
357 | /* | |
358 | * Finish the context and produce the HMAC SHA1 digest. | |
359 | */ | |
360 | ||
361 | void | |
362 | HMAC_SHA1_DES3KD_Final(void *digest, HMAC_SHA1_DES3KD_CTX *ctx) | |
363 | { | |
364 | unsigned char opad[64]; | |
365 | size_t i, j; | |
366 | ||
367 | SHA1Final(digest, &ctx->sha1_ctx); | |
368 | memset(opad, 0x5c, sizeof(opad)); | |
369 | for (i = 0; i < 3; i++) | |
370 | for (j = 0; j < sizeof(des_cblock); j++) | |
371 | opad[j + i * sizeof(des_cblock)] ^= ctx->dk[i][j]; | |
372 | SHA1Init(&ctx->sha1_ctx); | |
373 | SHA1Update(&ctx->sha1_ctx, opad, sizeof(opad)); | |
374 | SHA1Update(&ctx->sha1_ctx, digest, SHA1_RESULTLEN); | |
375 | SHA1Final(digest, &ctx->sha1_ctx); | |
376 | } | |
377 | ||
378 | /* | |
379 | * XXX This function borrowed from OpenBSD. | |
380 | * It will likely be moved into kernel crypto. | |
381 | */ | |
382 | DES_LONG | |
383 | des_cbc_cksum(des_cblock *input, des_cblock *output, | |
384 | int32_t length, des_key_schedule schedule, des_cblock *ivec) | |
385 | { | |
386 | register DES_LONG tout0,tout1,tin0,tin1; | |
387 | register int32_t l=length; | |
388 | DES_LONG tin[2]; | |
389 | unsigned char *in,*out,*iv; | |
390 | ||
391 | in=(unsigned char *)input; | |
392 | out=(unsigned char *)output; | |
393 | iv=(unsigned char *)ivec; | |
394 | ||
395 | c2l(iv,tout0); | |
396 | c2l(iv,tout1); | |
397 | for (; l>0; l-=8) { | |
398 | if (l >= 8) { | |
399 | c2l(in,tin0); | |
400 | c2l(in,tin1); | |
401 | } else | |
402 | c2ln(in,tin0,tin1,l); | |
403 | ||
404 | tin0^=tout0; tin[0]=tin0; | |
405 | tin1^=tout1; tin[1]=tin1; | |
406 | des_encrypt1((DES_LONG *)tin,schedule,DES_ENCRYPT); | |
407 | /* fix 15/10/91 eay - thanks to keithr@sco.COM */ | |
408 | tout0=tin[0]; | |
409 | tout1=tin[1]; | |
410 | } | |
411 | if (out != NULL) { | |
412 | l2c(tout0,out); | |
413 | l2c(tout1,out); | |
414 | } | |
415 | tout0=tin0=tin1=tin[0]=tin[1]=0; | |
416 | return(tout1); | |
417 | } | |
418 | ||
419 | /* | |
420 | * XXX This function borrowed from OpenBSD. | |
421 | * It will likely be moved into kernel crypto. | |
422 | */ | |
423 | void | |
424 | des_cbc_encrypt(des_cblock *input, des_cblock *output, int32_t length, | |
425 | des_key_schedule schedule, des_cblock *ivec, des_cblock *retvec, int encrypt) | |
426 | { | |
427 | register DES_LONG tin0,tin1; | |
428 | register DES_LONG tout0,tout1,xor0,xor1; | |
429 | register unsigned char *in,*out,*retval; | |
430 | register int32_t l=length; | |
431 | DES_LONG tin[2]; | |
432 | unsigned char *iv; | |
433 | tin0 = tin1 = 0; | |
434 | ||
435 | in=(unsigned char *)input; | |
436 | out=(unsigned char *)output; | |
437 | retval=(unsigned char *)retvec; | |
438 | iv=(unsigned char *)ivec; | |
439 | ||
440 | if (encrypt) { | |
441 | c2l(iv,tout0); | |
442 | c2l(iv,tout1); | |
443 | for (l-=8; l>=0; l-=8) { | |
444 | c2l(in,tin0); | |
445 | c2l(in,tin1); | |
446 | tin0^=tout0; tin[0]=tin0; | |
447 | tin1^=tout1; tin[1]=tin1; | |
448 | des_encrypt1((DES_LONG *)tin,schedule,DES_ENCRYPT); | |
449 | tout0=tin[0]; l2c(tout0,out); | |
450 | tout1=tin[1]; l2c(tout1,out); | |
451 | } | |
452 | if (l != -8) { | |
453 | c2ln(in,tin0,tin1,l+8); | |
454 | tin0^=tout0; tin[0]=tin0; | |
455 | tin1^=tout1; tin[1]=tin1; | |
456 | des_encrypt1((DES_LONG *)tin,schedule,DES_ENCRYPT); | |
457 | tout0=tin[0]; l2c(tout0,out); | |
458 | tout1=tin[1]; l2c(tout1,out); | |
459 | } | |
460 | if (retval) { | |
461 | l2c(tout0,retval); | |
462 | l2c(tout1,retval); | |
463 | } | |
464 | } else { | |
465 | c2l(iv,xor0); | |
466 | c2l(iv,xor1); | |
467 | for (l-=8; l>=0; l-=8) { | |
468 | c2l(in,tin0); tin[0]=tin0; | |
469 | c2l(in,tin1); tin[1]=tin1; | |
470 | des_encrypt1((DES_LONG *)tin,schedule,DES_DECRYPT); | |
471 | tout0=tin[0]^xor0; | |
472 | tout1=tin[1]^xor1; | |
473 | l2c(tout0,out); | |
474 | l2c(tout1,out); | |
475 | xor0=tin0; | |
476 | xor1=tin1; | |
477 | } | |
478 | if (l != -8) { | |
479 | c2l(in,tin0); tin[0]=tin0; | |
480 | c2l(in,tin1); tin[1]=tin1; | |
481 | des_encrypt1((DES_LONG *)tin,schedule,DES_DECRYPT); | |
482 | tout0=tin[0]^xor0; | |
483 | tout1=tin[1]^xor1; | |
484 | l2cn(tout0,tout1,out,l+8); | |
485 | /* xor0=tin0; | |
486 | xor1=tin1; */ | |
487 | } | |
488 | if (retval) { | |
489 | l2c(tin0,retval); | |
490 | l2c(tin1,retval); | |
491 | } | |
492 | } | |
493 | tin0=tin1=tout0=tout1=xor0=xor1=0; | |
494 | tin[0]=tin[1]=0; | |
495 | } | |
496 | ||
497 | /* | |
498 | * Initialize an MD5 DES CBC context with a schedule. | |
499 | */ | |
500 | ||
501 | void MD5_DESCBC_Init(MD5_DESCBC_CTX *ctx, des_key_schedule *sched) | |
502 | { | |
503 | MD5Init(&ctx->md5_ctx); | |
504 | ctx->sched = sched; | |
505 | } | |
506 | ||
507 | /* | |
508 | * Update MD5 DES CBC context with the supplied data. | |
509 | */ | |
510 | ||
511 | void MD5_DESCBC_Update(MD5_DESCBC_CTX *ctx, void *data, size_t len) | |
512 | { | |
513 | MD5Update(&ctx->md5_ctx, data, len); | |
514 | } | |
515 | ||
516 | /* | |
517 | * Finalize the context and extract the digest. | |
518 | */ | |
519 | ||
520 | void MD5_DESCBC_Final(void *digest, MD5_DESCBC_CTX *ctx) | |
521 | { | |
522 | des_cblock iv0; | |
523 | unsigned char md5_digest[MD5_DIGEST_LENGTH]; | |
524 | ||
525 | MD5Final(md5_digest, &ctx->md5_ctx); | |
526 | ||
527 | /* | |
528 | * Now get the DES CBC checksum for the digest. | |
529 | */ | |
530 | bzero(iv0, sizeof (iv0)); | |
531 | (void) des_cbc_cksum((des_cblock *) md5_digest, (des_cblock *)digest, | |
532 | sizeof (md5_digest), *ctx->sched, &iv0); | |
533 | } | |
534 |