]> git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/nfs_gss_crypto.c
xnu-1699.24.23.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_gss_crypto.c
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