2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
31 * Copyright (C) 1998 by the FundsXpress, INC.
33 * All rights reserved.
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.
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.
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.
56 #include "nfs_gss_crypto.h"
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]
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. */
73 /* input length is in bits */
76 krb5_nfold(unsigned int inbits
, const unsigned char *in
, unsigned int outbits
,
82 /* the code below is more readable if I make these bytes
88 /* first compute lcm(n,k) */
99 lcm
= outbits
*inbits
/a
;
101 /* now do the real work */
103 memset(out
, 0, outbits
);
106 /* this will end up cycling through k lcm(k,n)/k times, which
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
113 /* then, for each byte, shift to the right for each
115 +(((inbits
<<3)+13)*(i
/inbits
))
116 /* last, pick out the correct byte within that
117 shifted repetition */
118 +((inbits
-(i%inbits
))<<3)
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;
126 /* do the addition */
127 byte
+= out
[i%outbits
];
128 out
[i%outbits
] = byte
&0xff;
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
);
137 /* keep around the carry bit, if any */
141 printf("carry=%d\n", byte
);
145 /* if there's a carry bit left over, add it back in */
147 for (i
=outbits
-1; i
>=0; i
--) {
148 /* do the addition */
152 /* keep around the carry bit, if any */
159 * Given 21 bytes of random bits, make a triple DES key.
163 des3_make_key(const unsigned char randombits
[21], des_cblock key
[3])
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
]);
181 * Make a triple des key schedule, from a triple des key.
185 des3_key_sched(des_cblock key
[3], des_key_schedule sched
[3])
190 for (i
= 0; i
< 3; i
++)
191 rc
|= des_key_sched(&key
[i
], sched
[i
]);
197 * Triple DES cipher block chaining mode encryption.
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
)
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
;
212 in
=(unsigned char *)input
;
213 out
=(unsigned char *)output
;
214 retval
=(unsigned char *)retvec
;
215 iv
=(unsigned char *)ivec
;
220 for (l
-=8; l
>=0; l
-=8) {
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
);
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
);
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]);
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]);
261 l2cn(tout0
,tout1
,out
,l
+8);
270 tin0
=tin1
=tout0
=tout1
=xor0
=xor1
=0;
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.
281 des3_derive_key(des_cblock inkey
[3], des_cblock outkey
[3],
282 const unsigned char *constant
, int clen
)
284 des_cblock inblock
, outblock
, ivec
;
285 des_key_schedule sched
[3];
286 unsigned char rawkey
[21];
287 size_t n
, keybytes
= sizeof(rawkey
);
289 /* initialize the input block */
291 if (clen
== sizeof(des_cblock
)) {
292 memcpy(inblock
, constant
, clen
);
294 krb5_nfold(clen
*8, constant
, sizeof(des_cblock
)*8, inblock
);
297 /* loop encrypting the blocks until enough key bytes are generated */
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
));
307 memcpy(rawkey
+n
, outblock
, sizeof(des_cblock
));
308 memcpy(inblock
, outblock
, sizeof(des_cblock
));
311 /* postprocess the key */
312 des3_make_key(rawkey
, outkey
);
314 /* clean memory, free resources and exit */
316 bzero(inblock
, sizeof (des_cblock
));
317 bzero(outblock
, sizeof (des_cblock
));
318 bzero(rawkey
, keybytes
);
319 bzero(sched
, sizeof (sched
));
325 * Initialize a context for HMAC SHA1
326 * if drived is true we derive a new key
327 * based on KG_USAGE_SIGN
331 HMAC_SHA1_DES3KD_Init(HMAC_SHA1_DES3KD_CTX
*ctx
, des_cblock key
[3], int derive
)
333 unsigned char ipad
[64];
336 SHA1Init(&ctx
->sha1_ctx
);
338 des3_derive_key(key
, ctx
->dk
, KEY_USAGE_DES3_SIGN
, KEY_USAGE_LEN
);
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
));
349 * Update the HMAC SHA1 context with the supplied data.
352 HMAC_SHA1_DES3KD_Update(HMAC_SHA1_DES3KD_CTX
*ctx
, void *data
, size_t len
)
354 SHA1Update(&ctx
->sha1_ctx
, data
, len
);
358 * Finish the context and produce the HMAC SHA1 digest.
362 HMAC_SHA1_DES3KD_Final(void *digest
, HMAC_SHA1_DES3KD_CTX
*ctx
)
364 unsigned char opad
[64];
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
);
379 * XXX This function borrowed from OpenBSD.
380 * It will likely be moved into kernel crypto.
383 des_cbc_cksum(des_cblock
*input
, des_cblock
*output
,
384 int32_t length
, des_key_schedule schedule
, des_cblock
*ivec
)
386 register DES_LONG tout0
,tout1
,tin0
,tin1
;
387 register int32_t l
=length
;
389 unsigned char *in
,*out
,*iv
;
391 in
=(unsigned char *)input
;
392 out
=(unsigned char *)output
;
393 iv
=(unsigned char *)ivec
;
402 c2ln(in
,tin0
,tin1
,l
);
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 */
415 tout0
=tin0
=tin1
=tin
[0]=tin
[1]=0;
420 * XXX This function borrowed from OpenBSD.
421 * It will likely be moved into kernel crypto.
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
)
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
;
435 in
=(unsigned char *)input
;
436 out
=(unsigned char *)output
;
437 retval
=(unsigned char *)retvec
;
438 iv
=(unsigned char *)ivec
;
443 for (l
-=8; l
>=0; l
-=8) {
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
);
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
);
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
);
479 c2l(in
,tin0
); tin
[0]=tin0
;
480 c2l(in
,tin1
); tin
[1]=tin1
;
481 des_encrypt1((DES_LONG
*)tin
,schedule
,DES_DECRYPT
);
484 l2cn(tout0
,tout1
,out
,l
+8);
493 tin0
=tin1
=tout0
=tout1
=xor0
=xor1
=0;
498 * Initialize an MD5 DES CBC context with a schedule.
501 void MD5_DESCBC_Init(MD5_DESCBC_CTX
*ctx
, des_key_schedule
*sched
)
503 MD5Init(&ctx
->md5_ctx
);
508 * Update MD5 DES CBC context with the supplied data.
511 void MD5_DESCBC_Update(MD5_DESCBC_CTX
*ctx
, void *data
, size_t len
)
513 MD5Update(&ctx
->md5_ctx
, data
, len
);
517 * Finalize the context and extract the digest.
520 void MD5_DESCBC_Final(void *digest
, MD5_DESCBC_CTX
*ctx
)
523 unsigned char md5_digest
[MD5_DIGEST_LENGTH
];
525 MD5Final(md5_digest
, &ctx
->md5_ctx
);
528 * Now get the DES CBC checksum for the digest.
530 bzero(iv0
, sizeof (iv0
));
531 (void) des_cbc_cksum((des_cblock
*) md5_digest
, (des_cblock
*)digest
,
532 sizeof (md5_digest
), *ctx
->sched
, &iv0
);