1 /*
2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /*
7
8 ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95).
9 This cipher is widely believed and has been tested to be equivalent
10 with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark
11 of RSA Data Security)
12
13 */
14 #include <k5-int.h>
15 #include <arcfour.h>
16
17 /* salt string used for exportable ARCFOUR */
18 static const char *l40 = "fortybits";
19
20 void
krb5_arcfour_encrypt_length(enc,hash,inputlen,length)21 krb5_arcfour_encrypt_length(enc, hash, inputlen, length)
22 const struct krb5_enc_provider *enc;
23 const struct krb5_hash_provider *hash;
24 size_t inputlen;
25 size_t *length;
26 {
27 size_t blocksize, hashsize;
28
29 blocksize = enc->block_size;
30 hashsize = hash->hashsize;
31
32 /* checksum + (confounder + inputlen, in even blocksize) */
33 *length = hashsize + krb5_roundup(8 + inputlen, blocksize);
34 }
35
36 krb5_keyusage
krb5int_arcfour_translate_usage(krb5_keyusage usage)37 krb5int_arcfour_translate_usage(krb5_keyusage usage)
38 {
39 switch (usage) {
40 case 1: /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */
41 return 1;
42 case 2: /* ticket from kdc */
43 return 2;
44 case 3: /* as-rep encrypted part */
45 return 8;
46 case 4: /* tgs-req authz data */
47 return 4;
48 case 5: /* tgs-req authz data in subkey */
49 return 5;
50 case 6: /* tgs-req authenticator cksum */
51 return 6;
52 case 7: /* tgs-req authenticator */
53 return 7;
54 case 8:
55 return 8;
56 case 9: /* tgs-rep encrypted with subkey */
57 return 8;
58 case 10: /* ap-rep authentication cksum */
59 return 10; /* xxx Microsoft never uses this*/
60 case 11: /* app-req authenticator */
61 return 11;
62 case 12: /* app-rep encrypted part */
63 return 12;
64 case 23: /* sign wrap token*/
65 return 13;
66 default:
67 return usage;
68 }
69 }
70
71 krb5_error_code
krb5_arcfour_encrypt(context,enc,hash,key,usage,ivec,input,output)72 krb5_arcfour_encrypt(context, enc, hash, key, usage, ivec, input, output)
73 krb5_context context;
74 const struct krb5_enc_provider *enc;
75 const struct krb5_hash_provider *hash;
76 const krb5_keyblock *key;
77 krb5_keyusage usage;
78 const krb5_data *ivec;
79 const krb5_data *input;
80 krb5_data *output;
81 {
82 krb5_keyblock k1, k2, k3;
83 krb5_keyblock *kptr;
84 krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder;
85 krb5_keyusage ms_usage;
86 size_t keybytes, blocksize, hashsize;
87 krb5_error_code ret = 0;
88
89 blocksize = enc->block_size;
90 keybytes = enc->keybytes;
91 hashsize = hash->hashsize;
92
93 bzero(&d2, sizeof(krb5_data));
94 bzero(&k2, sizeof(krb5_keyblock));
95 /*
96 * d1 is the contents buffer for key k1.
97 * k1 = HMAC(input_key, salt)
98 */
99 d1.length=keybytes;
100 d1.data=MALLOC(d1.length);
101 if (d1.data == NULL)
102 return (ENOMEM);
103 bcopy(key, &k1, sizeof (krb5_keyblock));
104 k1.length=d1.length;
105 k1.contents= (void *) d1.data;
106
107 /*
108 * d2 is the contents of key 'k2', which is used to generate the
109 * checksum field. 'd2' == 'd1' when not using the exportable
110 * enctype. This is only needed when using the exportable
111 * enctype.
112 */
113 if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) {
114 d2.length=keybytes;
115 d2.data=MALLOC(d2.length);
116 if (d2.data == NULL) {
117 FREE(d1.data, d1.length);
118 return (ENOMEM);
119 }
120 bcopy(key, &k2, sizeof (krb5_keyblock));
121 k2.length=d2.length;
122 k2.contents=(void *) d2.data;
123 }
124
125 /*
126 * d3 will hold the contents of the final key used for the
127 * encryption step. 'k3' is the key structure that has 'd3'
128 * as its 'contents' field.
129 * k3 = HMAC(k1, checksum)
130 */
131 d3.length=keybytes;
132 d3.data=MALLOC(d3.length);
133 if (d3.data == NULL) {
134 FREE(d1.data, d1.length);
135 if (d2.data)
136 FREE(d2.data, d2.length);
137 return (ENOMEM);
138 }
139 bcopy(key, &k3, sizeof (krb5_keyblock));
140 k3.length=d3.length;
141 k3.contents= (void *) d3.data;
142
143 salt.length=14;
144 salt.data=MALLOC(salt.length);
145
146 if (salt.data == NULL) {
147 FREE(d1.data, d1.length);
148 if (d2.data)
149 FREE(d2.data, d2.length);
150 FREE(d3.data, d3.length);
151 return (ENOMEM);
152 }
153
154 /* is "input" already blocksize aligned? if it is, then we need this
155 step, otherwise we do not */
156 plaintext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize);
157 plaintext.data=MALLOC(plaintext.length);
158
159 if (plaintext.data == NULL) {
160 FREE(d1.data, d1.length);
161 if (d2.data)
162 FREE(d2.data, d2.length);
163 FREE(d3.data, d3.length);
164 FREE(salt.data, salt.length);
165 return(ENOMEM);
166 }
167 bzero(plaintext.data, plaintext.length);
168
169 /* setup convienient pointers into the allocated data */
170 checksum.length=hashsize;
171 checksum.data=output->data;
172
173 ciphertext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize);
174 ciphertext.data=output->data+hashsize;
175
176 confounder.length=CONFOUNDERLENGTH;
177 confounder.data=plaintext.data;
178
179 output->length = plaintext.length+hashsize;
180
181 /* begin the encryption, computer K1 */
182 ms_usage=krb5int_arcfour_translate_usage(usage);
183 if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
184 (void) strncpy(salt.data, l40, salt.length);
185 salt.data[10]=ms_usage & 0xff;
186 salt.data[11]=(ms_usage >> 8) & 0xff;
187 salt.data[12]=(ms_usage >> 16) & 0xff;
188 salt.data[13]=(ms_usage >> 24) & 0xff;
189 } else {
190 salt.length=4;
191 salt.data[0]=ms_usage & 0xff;
192 salt.data[1]=(ms_usage >> 8) & 0xff;
193 salt.data[2]=(ms_usage >> 16) & 0xff;
194 salt.data[3]=(ms_usage >> 24) & 0xff;
195 }
196
197 #ifdef _KERNEL
198 ret = krb5_hmac(context, key, &salt, &d1);
199 #else
200 ret = krb5_hmac(context, hash, key, 1, &salt, &d1);
201 #endif /* _KERNEL */
202 if (ret != 0)
203 goto cleanup;
204
205 if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) {
206 bcopy(k1.contents, k2.contents, k2.length);
207 (void) memset(k1.contents+7, 0xab, 9);
208 kptr = &k2;
209 } else {
210 kptr = &k1;
211 }
212
213 /* create a confounder block */
214 ret=krb5_c_random_make_octets(context, &confounder);
215 bcopy(input->data, plaintext.data+confounder.length, input->length);
216 if (ret)
217 goto cleanup;
218
219 /*
220 * Compute the HMAC checksum field.
221 * checksum = HMAC(k1/k2, plaintext);
222 * k2 used when key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP
223 */
224 #ifdef _KERNEL
225 ret = krb5_hmac(context, kptr, &plaintext, &checksum);
226 #else
227 ret = krb5_hmac(context, hash, kptr, 1, &plaintext, &checksum);
228 #endif /* _KERNEL */
229 if (ret)
230 goto cleanup;
231
232 /*
233 * The final encryption key is the HMAC of the checksum
234 * using k1
235 *
236 * k3 = HMAC(k1, checksum);
237 * == or (in other terms) ==
238 * k3 = HMAC((HMAC(input_key,salt), HMAC(k1, plaintext));
239 */
240 #ifdef _KERNEL
241 ret = krb5_hmac(context, &k1, &checksum, &d3);
242 #else
243 ret = krb5_hmac(context, hash, &k1, 1, &checksum, &d3);
244 #endif /* _KERNEL */
245 if (ret)
246 goto cleanup;
247
248 ret = (*(enc->encrypt))(context, &k3, ivec, &plaintext, &ciphertext);
249
250 cleanup:
251 bzero(d1.data, d1.length);
252 if (d2.data) {
253 bzero(d2.data, d2.length);
254 FREE(d2.data, d2.length);
255 }
256 bzero(d3.data, d3.length);
257 bzero(salt.data, salt.length);
258 bzero(plaintext.data, plaintext.length);
259
260 FREE(d1.data, d1.length);
261 FREE(d3.data, d3.length);
262 FREE(salt.data, salt.length);
263 FREE(plaintext.data, plaintext.length);
264 return (ret);
265 }
266
267 /* This is the arcfour-hmac decryption routine */
268 krb5_error_code
krb5_arcfour_decrypt(context,enc,hash,key,usage,ivec,input,output)269 krb5_arcfour_decrypt(context, enc, hash, key, usage, ivec, input, output)
270 krb5_context context;
271 const struct krb5_enc_provider *enc;
272 const struct krb5_hash_provider *hash;
273 const krb5_keyblock *key;
274 krb5_keyusage usage;
275 const krb5_data *ivec;
276 const krb5_data *input;
277 krb5_data *output;
278 {
279 krb5_keyblock k1,k2,k3, *kptr;
280 krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum;
281 krb5_keyusage ms_usage;
282 size_t keybytes, hashsize;
283 krb5_error_code ret;
284
285 keybytes = enc->keybytes;
286 hashsize = hash->hashsize;
287
288 /* Verify input and output lengths. */
289 if (input->length < hashsize + CONFOUNDERLENGTH)
290 return KRB5_BAD_MSIZE;
291 if (output->length < input->length - hashsize - CONFOUNDERLENGTH)
292 return KRB5_BAD_MSIZE;
293
294 bzero(&d2, sizeof(krb5_data));
295 bzero(&k2, sizeof(krb5_keyblock));
296 /*
297 * d1 is the contents buffer for key k1.
298 * k1 = HMAC(input_key, salt)
299 */
300 d1.length=keybytes;
301 d1.data=MALLOC(d1.length);
302 if (d1.data == NULL)
303 return (ENOMEM);
304 (void) bcopy(key, &k1, sizeof (krb5_keyblock));
305 k1.length=d1.length;
306 k1.contents= (void *) d1.data;
307
308 /*
309 * d2 is the contents of key 'k2', which is used to generate the
310 * checksum field. 'd2' == 'd1' when not using the exportable
311 * enctype. This is only needed when using the exportable
312 * enctype.
313 */
314 if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) {
315 d2.length=keybytes;
316 d2.data=MALLOC(d2.length);
317 if (d2.data == NULL) {
318 FREE(d1.data, d1.length);
319 return (ENOMEM);
320 }
321 (void) bcopy(key, &k2, sizeof(krb5_keyblock));
322 k2.length=d2.length;
323 k2.contents= (void *) d2.data;
324 }
325
326 /*
327 * d3 will hold the contents of the final key used for the
328 * encryption step. 'k3' is the key structure that has 'd3'
329 * as its 'contents' field.
330 * k3 = HMAC(k1, checksum)
331 */
332 d3.length=keybytes;
333 d3.data=MALLOC(d3.length);
334 if (d3.data == NULL) {
335 FREE(d1.data, d1.length);
336 if (d2.data)
337 FREE(d2.data, d2.length);
338 return (ENOMEM);
339 }
340 bcopy(key, &k3, sizeof(krb5_keyblock));
341 k3.length=d3.length;
342 k3.contents= (void *) d3.data;
343
344 salt.length=14;
345 salt.data=MALLOC(salt.length);
346 if(salt.data==NULL) {
347 FREE(d1.data, d1.length);
348 if (d2.data)
349 FREE(d2.data, d2.length);
350 FREE(d3.data, d3.length);
351 return (ENOMEM);
352 }
353
354 ciphertext.length=input->length-hashsize;
355 ciphertext.data=input->data+hashsize;
356
357 plaintext.length=ciphertext.length;
358 plaintext.data=MALLOC(plaintext.length);
359 if (plaintext.data == NULL) {
360 FREE(d1.data, d1.length);
361 if (d2.data)
362 FREE(d2.data, d2.length);
363 FREE(d3.data, d3.length);
364 FREE(salt.data, salt.length);
365 return (ENOMEM);
366 }
367
368 checksum.length=hashsize;
369 checksum.data=input->data;
370
371 /* compute the salt */
372 ms_usage=krb5int_arcfour_translate_usage(usage);
373 if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
374 (void) strncpy(salt.data, l40, salt.length);
375 salt.data[10]=ms_usage & 0xff;
376 salt.data[11]=(ms_usage>>8) & 0xff;
377 salt.data[12]=(ms_usage>>16) & 0xff;
378 salt.data[13]=(ms_usage>>24) & 0xff;
379 } else {
380 salt.length=4;
381 salt.data[0]=ms_usage & 0xff;
382 salt.data[1]=(ms_usage>>8) & 0xff;
383 salt.data[2]=(ms_usage>>16) & 0xff;
384 salt.data[3]=(ms_usage>>24) & 0xff;
385 }
386
387 #ifdef _KERNEL
388 ret=krb5_hmac(context, key, &salt, &d1);
389 #else
390 ret=krb5_hmac(context, hash, key, 1, &salt, &d1);
391 #endif /* _KERNEL */
392 if (ret)
393 goto cleanup;
394
395 if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
396 bcopy(k1.contents, k2.contents, d1.length);
397 (void) memset(k1.contents+7, 0xab, 9);
398 kptr = &k2;
399 } else {
400 kptr = &k1;
401 }
402
403 #ifdef _KERNEL
404 ret = krb5_hmac(context, &k1, &checksum, &d3);
405 #else
406 ret = krb5_hmac(context, hash, &k1, 1, &checksum, &d3);
407 #endif /* _KERNEL */
408
409 if (ret)
410 goto cleanup;
411
412 ret=(*(enc->decrypt))(context, &k3, ivec, &ciphertext, &plaintext);
413 if (ret)
414 goto cleanup;
415
416 #ifdef _KERNEL
417 ret = krb5_hmac(context, kptr, &plaintext, &d1);
418 #else
419 ret = krb5_hmac(context, hash, kptr, 1, &plaintext, &d1);
420 #endif /* _KERNEL */
421
422 if (ret)
423 goto cleanup;
424
425 if (bcmp(checksum.data, d1.data, hashsize) != 0) {
426 ret=KRB5KRB_AP_ERR_BAD_INTEGRITY;
427 goto cleanup;
428 }
429
430 bcopy(plaintext.data+CONFOUNDERLENGTH, output->data,
431 (plaintext.length-CONFOUNDERLENGTH));
432 output->length=plaintext.length-CONFOUNDERLENGTH;
433
434 cleanup:
435 bzero(d1.data, d1.length);
436 if (d2.data) {
437 bzero(d2.data, d2.length);
438 FREE(d2.data, d2.length);
439 }
440 bzero(d3.data, d2.length);
441 bzero(salt.data, salt.length);
442 bzero(plaintext.data, plaintext.length);
443
444 FREE(d1.data, d1.length);
445 FREE(d3.data, d3.length);
446 FREE(salt.data, salt.length);
447 FREE(plaintext.data, plaintext.length);
448
449 return (ret);
450 }
451
452