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 * 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.
187 des3_derive_key(des_cblock inkey
[3], des_cblock outkey
[3],
188 const unsigned char *constant
, int clen
)
190 des_cblock inblock
, outblock
, ivec
;
191 des3_cbc_key_schedule sched
;
192 unsigned char rawkey
[21];
193 size_t n
, keybytes
= sizeof(rawkey
);
195 /* initialize the input block */
197 if (clen
== sizeof(des_cblock
)) {
198 memcpy(inblock
, constant
, clen
);
200 krb5_nfold(clen
*8, constant
, sizeof(des_cblock
)*8, inblock
);
203 /* loop encrypting the blocks until enough key bytes are generated */
205 bzero(ivec
, sizeof(ivec
));
206 des3_cbc_key_sched(inkey
, &sched
);
207 for (n
= 0; n
< sizeof(rawkey
); n
+= sizeof(des_cblock
)) {
208 des3_cbc_encrypt(&inblock
, &outblock
, sizeof(outblock
), &sched
, &ivec
, NULL
, 1);
209 if ((keybytes
- n
) <= sizeof (des_cblock
)) {
210 memcpy(rawkey
+n
, outblock
, (keybytes
- n
));
213 memcpy(rawkey
+n
, outblock
, sizeof(des_cblock
));
214 memcpy(inblock
, outblock
, sizeof(des_cblock
));
217 /* postprocess the key */
218 des3_make_key(rawkey
, outkey
);
220 /* clean memory, free resources and exit */
222 bzero(inblock
, sizeof (des_cblock
));
223 bzero(outblock
, sizeof (des_cblock
));
224 bzero(rawkey
, keybytes
);
225 bzero(&sched
, sizeof (sched
));
231 * Initialize a context for HMAC SHA1
232 * if drived is true we derive a new key
233 * based on KG_USAGE_SIGN
237 HMAC_SHA1_DES3KD_Init(HMAC_SHA1_DES3KD_CTX
*ctx
, des_cblock key
[3], int derive
)
239 unsigned char ipad
[64];
242 SHA1Init(&ctx
->sha1_ctx
);
244 des3_derive_key(key
, ctx
->dk
, KEY_USAGE_DES3_SIGN
, KEY_USAGE_LEN
);
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
));
255 * Update the HMAC SHA1 context with the supplied data.
258 HMAC_SHA1_DES3KD_Update(HMAC_SHA1_DES3KD_CTX
*ctx
, void *data
, size_t len
)
260 SHA1Update(&ctx
->sha1_ctx
, data
, len
);
264 * Finish the context and produce the HMAC SHA1 digest.
268 HMAC_SHA1_DES3KD_Final(void *digest
, HMAC_SHA1_DES3KD_CTX
*ctx
)
270 unsigned char opad
[64];
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
);
285 * Initialize an MD5 DES CBC context with a schedule.
288 void MD5_DESCBC_Init(MD5_DESCBC_CTX
*ctx
, des_cbc_key_schedule
*sched
)
290 MD5Init(&ctx
->md5_ctx
);
295 * Update MD5 DES CBC context with the supplied data.
298 void MD5_DESCBC_Update(MD5_DESCBC_CTX
*ctx
, void *data
, size_t len
)
300 MD5Update(&ctx
->md5_ctx
, data
, len
);
304 * Finalize the context and extract the digest.
307 void MD5_DESCBC_Final(void *digest
, MD5_DESCBC_CTX
*ctx
)
309 unsigned char md5_digest
[MD5_DIGEST_LENGTH
];
311 MD5Final(md5_digest
, &ctx
->md5_ctx
);
314 * Now get the DES CBC checksum for the digest.
316 des_cbc_cksum((des_cblock
*) md5_digest
, (des_cblock
*)digest
,
317 sizeof (md5_digest
), ctx
->sched
);