]> git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/nfs_gss_crypto.c
xnu-3248.60.10.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 * 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;
191 des3_cbc_key_schedule sched;
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));
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));
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);
225 bzero(&sched, sizeof (sched));
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
284 /*
285 * Initialize an MD5 DES CBC context with a schedule.
286 */
287
288 void MD5_DESCBC_Init(MD5_DESCBC_CTX *ctx, des_cbc_key_schedule *sched)
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 {
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 */
316 des_cbc_cksum((des_cblock *) md5_digest, (des_cblock *)digest,
317 sizeof (md5_digest), ctx->sched);
318 }
319