This commit was manufactured by cvs2svn to create tag
[heimdal.git] / lib / krb5 / crypto.c
blob045d0543a2a4ec1c8a051a108ceb82aa3f7f560d
1 /*
2 * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
39 #include "krb5_locl.h"
40 RCSID("$Id$");
42 #undef CRYPTO_DEBUG
43 #ifdef CRYPTO_DEBUG
44 static void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*);
45 #endif
48 struct key_data {
49 krb5_keyblock *key;
50 krb5_data *schedule;
53 struct key_usage {
54 unsigned usage;
55 struct key_data key;
58 struct krb5_crypto_data {
59 struct encryption_type *et;
60 struct key_data key;
61 int num_key_usage;
62 struct key_usage *key_usage;
65 #define CRYPTO_ETYPE(C) ((C)->et->type)
67 /* bits for `flags' below */
68 #define F_KEYED 1 /* checksum is keyed */
69 #define F_CPROOF 2 /* checksum is collision proof */
70 #define F_DERIVED 4 /* uses derived keys */
71 #define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
72 #define F_PSEUDO 16 /* not a real protocol type */
74 struct salt_type {
75 krb5_salttype type;
76 const char *name;
77 krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
78 krb5_salt, krb5_keyblock*);
81 struct key_type {
82 krb5_keytype type; /* XXX */
83 const char *name;
84 size_t bits;
85 size_t size;
86 size_t schedule_size;
87 #if 0
88 krb5_enctype best_etype;
89 #endif
90 void (*random_key)(krb5_context, krb5_keyblock*);
91 void (*schedule)(krb5_context, struct key_data *);
92 struct salt_type *string_to_key;
95 struct checksum_type {
96 krb5_cksumtype type;
97 const char *name;
98 size_t blocksize;
99 size_t checksumsize;
100 unsigned flags;
101 void (*checksum)(krb5_context, struct key_data*, void*, size_t, Checksum*);
102 krb5_error_code (*verify)(krb5_context, struct key_data*,
103 void*, size_t, Checksum*);
106 struct encryption_type {
107 krb5_enctype type;
108 const char *name;
109 size_t blocksize;
110 size_t confoundersize;
111 struct key_type *keytype;
112 struct checksum_type *cksumtype;
113 struct checksum_type *keyed_checksum;
114 unsigned flags;
115 void (*encrypt)(struct key_data *, void *, size_t, int);
118 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
119 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
120 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
122 static struct checksum_type *_find_checksum(krb5_cksumtype type);
123 static struct encryption_type *_find_enctype(krb5_enctype type);
124 static struct key_type *_find_keytype(krb5_keytype type);
125 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
126 unsigned, struct key_data**);
127 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
129 /************************************************************
131 ************************************************************/
133 static void
134 DES_random_key(krb5_context context,
135 krb5_keyblock *key)
137 des_cblock *k = key->keyvalue.data;
138 do {
139 krb5_generate_random_block(k, sizeof(des_cblock));
140 des_set_odd_parity(k);
141 } while(des_is_weak_key(k));
144 static void
145 DES_schedule(krb5_context context,
146 struct key_data *key)
148 des_set_key(key->key->keyvalue.data, key->schedule->data);
151 static krb5_error_code
152 DES_string_to_key(krb5_context context,
153 krb5_enctype enctype,
154 krb5_data password,
155 krb5_salt salt,
156 krb5_keyblock *key)
158 char *s;
159 size_t len;
160 des_cblock tmp;
161 len = password.length + salt.saltvalue.length + 1;
162 s = malloc(len);
163 if(s == NULL)
164 return ENOMEM;
165 memcpy(s, password.data, password.length);
166 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
167 s[len - 1] = '\0';
168 des_string_to_key(s, &tmp);
169 key->keytype = enctype;
170 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
171 memset(&tmp, 0, sizeof(tmp));
172 memset(s, 0, len);
173 free(s);
174 return 0;
177 /* This defines the Andrew string_to_key function. It accepts a password
178 * string as input and converts its via a one-way encryption algorithm to a DES
179 * encryption key. It is compatible with the original Andrew authentication
180 * service password database.
184 * Short passwords, i.e 8 characters or less.
186 static void
187 DES_AFS3_CMU_string_to_key (krb5_data pw,
188 krb5_data cell,
189 des_cblock *key)
191 char password[8+1]; /* crypt is limited to 8 chars anyway */
192 int i;
194 for(i = 0; i < 8; i++) {
195 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
196 ((i < cell.length) ? ((char*)cell.data)[i] : 0);
197 password[i] = c ? c : 'X';
199 password[8] = '\0';
201 memcpy(key, crypt(password, "#~") + 2, sizeof(des_cblock));
203 /* parity is inserted into the LSB so left shift each byte up one
204 bit. This allows ascii characters with a zero MSB to retain as
205 much significance as possible. */
206 for (i = 0; i < sizeof(des_cblock); i++)
207 ((unsigned char*)key)[i] <<= 1;
208 des_set_odd_parity (key);
212 * Long passwords, i.e 9 characters or more.
214 static void
215 DES_AFS3_Transarc_string_to_key (krb5_data pw,
216 krb5_data cell,
217 des_cblock *key)
219 des_key_schedule schedule;
220 des_cblock temp_key;
221 des_cblock ivec;
222 char password[512];
223 size_t passlen;
225 memcpy(password, pw.data, min(pw.length, sizeof(password)));
226 if(pw.length < sizeof(password))
227 memcpy(password + pw.length,
228 cell.data, min(cell.length,
229 sizeof(password) - pw.length));
230 passlen = min(sizeof(password), pw.length + cell.length);
231 memcpy(&ivec, "kerberos", 8);
232 memcpy(&temp_key, "kerberos", 8);
233 des_set_odd_parity (&temp_key);
234 des_set_key (&temp_key, schedule);
235 des_cbc_cksum ((des_cblock *)password, &ivec, passlen, schedule, &ivec);
237 memcpy(&temp_key, &ivec, 8);
238 des_set_odd_parity (&temp_key);
239 des_set_key (&temp_key, schedule);
240 des_cbc_cksum ((des_cblock *)password, key, passlen, schedule, &ivec);
241 memset(&schedule, 0, sizeof(schedule));
242 memset(&temp_key, 0, sizeof(temp_key));
243 memset(&ivec, 0, sizeof(ivec));
244 memset(password, 0, sizeof(password));
246 des_set_odd_parity (key);
249 static krb5_error_code
250 DES_AFS3_string_to_key(krb5_context context,
251 krb5_enctype enctype,
252 krb5_data password,
253 krb5_salt salt,
254 krb5_keyblock *key)
256 des_cblock tmp;
257 if(password.length > 8)
258 DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
259 else
260 DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
261 key->keytype = enctype;
262 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
263 memset(&key, 0, sizeof(key));
264 return 0;
267 static void
268 DES3_random_key(krb5_context context,
269 krb5_keyblock *key)
271 des_cblock *k = key->keyvalue.data;
272 do {
273 krb5_generate_random_block(k, 3 * sizeof(des_cblock));
274 des_set_odd_parity(&k[0]);
275 des_set_odd_parity(&k[1]);
276 des_set_odd_parity(&k[2]);
277 } while(des_is_weak_key(&k[0]) ||
278 des_is_weak_key(&k[1]) ||
279 des_is_weak_key(&k[2]));
282 static void
283 DES3_schedule(krb5_context context,
284 struct key_data *key)
286 des_cblock *k = key->key->keyvalue.data;
287 des_key_schedule *s = key->schedule->data;
288 des_set_key(&k[0], s[0]);
289 des_set_key(&k[1], s[1]);
290 des_set_key(&k[2], s[2]);
294 * A = A xor B. A & B are 8 bytes.
297 static void
298 xor (des_cblock *key, const unsigned char *b)
300 unsigned char *a = (unsigned char*)key;
301 a[0] ^= b[0];
302 a[1] ^= b[1];
303 a[2] ^= b[2];
304 a[3] ^= b[3];
305 a[4] ^= b[4];
306 a[5] ^= b[5];
307 a[6] ^= b[6];
308 a[7] ^= b[7];
311 static krb5_error_code
312 DES3_string_to_key(krb5_context context,
313 krb5_enctype enctype,
314 krb5_data password,
315 krb5_salt salt,
316 krb5_keyblock *key)
318 char *str;
319 size_t len;
320 unsigned char tmp[24];
321 des_cblock keys[3];
323 len = password.length + salt.saltvalue.length;
324 str = malloc(len);
325 if(str == NULL)
326 return ENOMEM;
327 memcpy(str, password.data, password.length);
328 memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
330 des_cblock ivec;
331 des_key_schedule s[3];
332 int i;
334 _krb5_n_fold(str, len, tmp, 24);
336 for(i = 0; i < 3; i++){
337 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
338 des_set_odd_parity(keys + i);
339 if(des_is_weak_key(keys + i))
340 xor(keys + i, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
341 des_set_key(keys + i, s[i]);
343 memset(&ivec, 0, sizeof(ivec));
344 des_ede3_cbc_encrypt((void*)tmp, (void*)tmp, sizeof(tmp),
345 s[0], s[1], s[2], &ivec, DES_ENCRYPT);
346 memset(s, 0, sizeof(s));
347 memset(&ivec, 0, sizeof(ivec));
348 for(i = 0; i < 3; i++){
349 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
350 des_set_odd_parity(keys + i);
351 if(des_is_weak_key(keys + i))
352 xor(keys + i, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
354 memset(tmp, 0, sizeof(tmp));
356 key->keytype = enctype;
357 krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
358 memset(keys, 0, sizeof(keys));
359 memset(str, 0, len);
360 free(str);
361 return 0;
364 static krb5_error_code
365 DES3_string_to_key_derived(krb5_context context,
366 krb5_enctype enctype,
367 krb5_data password,
368 krb5_salt salt,
369 krb5_keyblock *key)
371 krb5_error_code ret;
372 size_t len = password.length + salt.saltvalue.length;
373 char *s = malloc(len);
375 if(s == NULL)
376 return ENOMEM;
377 memcpy(s, password.data, password.length);
378 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
379 ret = krb5_string_to_key_derived(context,
381 len,
382 enctype,
383 key);
384 memset(s, 0, len);
385 free(s);
386 return ret;
389 extern struct salt_type des_salt[],
390 des3_salt[], des3_salt_derived[];
392 struct key_type keytype_null = {
393 KEYTYPE_NULL,
394 "null",
398 NULL,
399 NULL,
400 NULL
403 struct key_type keytype_des = {
404 KEYTYPE_DES,
405 "des",
407 sizeof(des_cblock),
408 sizeof(des_key_schedule),
409 DES_random_key,
410 DES_schedule,
411 des_salt
414 struct key_type keytype_des3 = {
415 KEYTYPE_DES3,
416 "des3",
417 168,
418 3 * sizeof(des_cblock),
419 3 * sizeof(des_key_schedule),
420 DES3_random_key,
421 DES3_schedule,
422 des3_salt
425 struct key_type keytype_des3_derived = {
426 KEYTYPE_DES3,
427 "des3",
428 168,
429 3 * sizeof(des_cblock),
430 3 * sizeof(des_key_schedule),
431 DES3_random_key,
432 DES3_schedule,
433 des3_salt_derived
436 struct key_type *keytypes[] = {
437 &keytype_null,
438 &keytype_des,
439 &keytype_des3_derived,
440 &keytype_des3
443 static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
445 static struct key_type *
446 _find_keytype(krb5_keytype type)
448 int i;
449 for(i = 0; i < num_keytypes; i++)
450 if(keytypes[i]->type == type)
451 return keytypes[i];
452 return NULL;
456 struct salt_type des_salt[] = {
458 KRB5_PW_SALT,
459 "pw-salt",
460 DES_string_to_key
463 KRB5_AFS3_SALT,
464 "afs3-salt",
465 DES_AFS3_string_to_key
467 { 0 }
470 struct salt_type des3_salt[] = {
472 KRB5_PW_SALT,
473 "pw-salt",
474 DES3_string_to_key
476 { 0 }
479 struct salt_type des3_salt_derived[] = {
481 KRB5_PW_SALT,
482 "pw-salt",
483 DES3_string_to_key_derived
485 { 0 }
488 krb5_error_code
489 krb5_salttype_to_string (krb5_context context,
490 krb5_enctype etype,
491 krb5_salttype stype,
492 char **string)
494 struct encryption_type *e;
495 struct salt_type *st;
497 e = _find_enctype (etype);
498 if (e == NULL)
499 return KRB5_PROG_ETYPE_NOSUPP;
500 for (st = e->keytype->string_to_key; st && st->type; st++) {
501 if (st->type == stype) {
502 *string = strdup (st->name);
503 if (*string == NULL)
504 return ENOMEM;
505 return 0;
508 return HEIM_ERR_SALTTYPE_NOSUPP;
511 krb5_error_code
512 krb5_get_pw_salt(krb5_context context,
513 krb5_const_principal principal,
514 krb5_salt *salt)
516 size_t len;
517 int i;
518 krb5_error_code ret;
519 char *p;
521 salt->salttype = KRB5_PW_SALT;
522 len = strlen(principal->realm);
523 for (i = 0; i < principal->name.name_string.len; ++i)
524 len += strlen(principal->name.name_string.val[i]);
525 ret = krb5_data_alloc (&salt->saltvalue, len);
526 if (ret)
527 return ret;
528 p = salt->saltvalue.data;
529 memcpy (p, principal->realm, strlen(principal->realm));
530 p += strlen(principal->realm);
531 for (i = 0; i < principal->name.name_string.len; ++i) {
532 memcpy (p,
533 principal->name.name_string.val[i],
534 strlen(principal->name.name_string.val[i]));
535 p += strlen(principal->name.name_string.val[i]);
537 return 0;
540 krb5_error_code
541 krb5_free_salt(krb5_context context,
542 krb5_salt salt)
544 krb5_data_free(&salt.saltvalue);
545 return 0;
548 krb5_error_code
549 krb5_string_to_key_data (krb5_context context,
550 krb5_enctype enctype,
551 krb5_data password,
552 krb5_principal principal,
553 krb5_keyblock *key)
555 krb5_error_code ret;
556 krb5_salt salt;
558 ret = krb5_get_pw_salt(context, principal, &salt);
559 if(ret)
560 return ret;
561 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
562 krb5_free_salt(context, salt);
563 return ret;
566 krb5_error_code
567 krb5_string_to_key (krb5_context context,
568 krb5_enctype enctype,
569 const char *password,
570 krb5_principal principal,
571 krb5_keyblock *key)
573 krb5_data pw;
574 pw.data = (void*)password;
575 pw.length = strlen(password);
576 return krb5_string_to_key_data(context, enctype, pw, principal, key);
579 krb5_error_code
580 krb5_string_to_key_data_salt (krb5_context context,
581 krb5_enctype enctype,
582 krb5_data password,
583 krb5_salt salt,
584 krb5_keyblock *key)
586 struct encryption_type *et =_find_enctype(enctype);
587 struct salt_type *st;
588 if(et == NULL)
589 return KRB5_PROG_ETYPE_NOSUPP;
590 for(st = et->keytype->string_to_key; st && st->type; st++)
591 if(st->type == salt.salttype)
592 return (*st->string_to_key)(context, enctype, password, salt, key);
593 return HEIM_ERR_SALTTYPE_NOSUPP;
596 krb5_error_code
597 krb5_string_to_key_salt (krb5_context context,
598 krb5_enctype enctype,
599 const char *password,
600 krb5_salt salt,
601 krb5_keyblock *key)
603 krb5_data pw;
604 pw.data = (void*)password;
605 pw.length = strlen(password);
606 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
609 krb5_error_code
610 krb5_keytype_to_string(krb5_context context,
611 krb5_keytype keytype,
612 char **string)
614 struct key_type *kt = _find_keytype(keytype);
615 if(kt == NULL)
616 return KRB5_PROG_KEYTYPE_NOSUPP;
617 *string = strdup(kt->name);
618 if(*string == NULL)
619 return ENOMEM;
620 return 0;
623 krb5_error_code
624 krb5_string_to_keytype(krb5_context context,
625 const char *string,
626 krb5_keytype *keytype)
628 int i;
629 for(i = 0; i < num_keytypes; i++)
630 if(strcasecmp(keytypes[i]->name, string) == 0){
631 *keytype = keytypes[i]->type;
632 return 0;
634 return KRB5_PROG_KEYTYPE_NOSUPP;
637 krb5_error_code
638 krb5_generate_random_keyblock(krb5_context context,
639 krb5_enctype type,
640 krb5_keyblock *key)
642 krb5_error_code ret;
643 struct encryption_type *et = _find_enctype(type);
644 if(et == NULL)
645 return KRB5_PROG_ETYPE_NOSUPP;
646 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
647 if(ret)
648 return ret;
649 key->keytype = type;
650 if(et->keytype->random_key)
651 (*et->keytype->random_key)(context, key);
652 else
653 krb5_generate_random_block(key->keyvalue.data,
654 key->keyvalue.length);
655 return 0;
658 static krb5_error_code
659 _key_schedule(krb5_context context,
660 struct key_data *key)
662 krb5_error_code ret;
663 struct encryption_type *et = _find_enctype(key->key->keytype);
664 struct key_type *kt = et->keytype;
666 if(kt->schedule == NULL)
667 return 0;
668 ALLOC(key->schedule, 1);
669 if(key->schedule == NULL)
670 return ENOMEM;
671 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
672 if(ret) {
673 free(key->schedule);
674 key->schedule = NULL;
675 return ret;
677 (*kt->schedule)(context, key);
678 return 0;
681 /************************************************************
683 ************************************************************/
685 static void
686 NONE_checksum(krb5_context context,
687 struct key_data *key,
688 void *data,
689 size_t len,
690 Checksum *C)
694 static void
695 CRC32_checksum(krb5_context context,
696 struct key_data *key,
697 void *data,
698 size_t len,
699 Checksum *C)
701 u_int32_t crc;
702 unsigned char *r = C->checksum.data;
703 _krb5_crc_init_table ();
704 crc = _krb5_crc_update (data, len, 0);
705 r[0] = crc & 0xff;
706 r[1] = (crc >> 8) & 0xff;
707 r[2] = (crc >> 16) & 0xff;
708 r[3] = (crc >> 24) & 0xff;
711 static void
712 RSA_MD4_checksum(krb5_context context,
713 struct key_data *key,
714 void *data,
715 size_t len,
716 Checksum *C)
718 struct md4 m;
719 md4_init(&m);
720 md4_update(&m, data, len);
721 md4_finito(&m, C->checksum.data);
724 static void
725 RSA_MD4_DES_checksum(krb5_context context,
726 struct key_data *key,
727 void *data,
728 size_t len,
729 Checksum *cksum)
731 struct md4 md4;
732 des_cblock ivec;
733 unsigned char *p = cksum->checksum.data;
735 krb5_generate_random_block(p, 8);
736 md4_init(&md4);
737 md4_update(&md4, p, 8);
738 md4_update(&md4, data, len);
739 md4_finito(&md4, p + 8);
740 memset (&ivec, 0, sizeof(ivec));
741 des_cbc_encrypt((des_cblock*)p,
742 (des_cblock*)p,
743 24,
744 key->schedule->data,
745 &ivec,
746 DES_ENCRYPT);
749 static krb5_error_code
750 RSA_MD4_DES_verify(krb5_context context,
751 struct key_data *key,
752 void *data,
753 size_t len,
754 Checksum *C)
756 struct md4 md4;
757 unsigned char tmp[24];
758 unsigned char res[16];
759 des_cblock ivec;
760 krb5_error_code ret = 0;
762 memset(&ivec, 0, sizeof(ivec));
763 des_cbc_encrypt(C->checksum.data,
764 (void*)tmp,
765 C->checksum.length,
766 key->schedule->data,
767 &ivec,
768 DES_DECRYPT);
769 md4_init(&md4);
770 md4_update(&md4, tmp, 8); /* confounder */
771 md4_update(&md4, data, len);
772 md4_finito(&md4, res);
773 if(memcmp(res, tmp + 8, sizeof(res)) != 0)
774 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
775 memset(tmp, 0, sizeof(tmp));
776 memset(res, 0, sizeof(res));
777 return ret;
780 static void
781 RSA_MD5_checksum(krb5_context context,
782 struct key_data *key,
783 void *data,
784 size_t len,
785 Checksum *C)
787 struct md5 m;
788 md5_init(&m);
789 md5_update(&m, data, len);
790 md5_finito(&m, C->checksum.data);
793 static void
794 RSA_MD5_DES_checksum(krb5_context context,
795 struct key_data *key,
796 void *data,
797 size_t len,
798 Checksum *C)
800 struct md5 md5;
801 des_cblock ivec;
802 unsigned char *p = C->checksum.data;
804 krb5_generate_random_block(p, 8);
805 md5_init(&md5);
806 md5_update(&md5, p, 8);
807 md5_update(&md5, data, len);
808 md5_finito(&md5, p + 8);
809 memset (&ivec, 0, sizeof(ivec));
810 des_cbc_encrypt((des_cblock*)p,
811 (des_cblock*)p,
812 24,
813 key->schedule->data,
814 &ivec,
815 DES_ENCRYPT);
818 static krb5_error_code
819 RSA_MD5_DES_verify(krb5_context context,
820 struct key_data *key,
821 void *data,
822 size_t len,
823 Checksum *C)
825 struct md5 md5;
826 unsigned char tmp[24];
827 unsigned char res[16];
828 des_cblock ivec;
829 des_key_schedule *sched = key->schedule->data;
830 krb5_error_code ret = 0;
832 memset(&ivec, 0, sizeof(ivec));
833 des_cbc_encrypt(C->checksum.data,
834 (void*)tmp,
835 C->checksum.length,
836 sched[0],
837 &ivec,
838 DES_DECRYPT);
839 md5_init(&md5);
840 md5_update(&md5, tmp, 8); /* confounder */
841 md5_update(&md5, data, len);
842 md5_finito(&md5, res);
843 if(memcmp(res, tmp + 8, sizeof(res)) != 0)
844 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
845 memset(tmp, 0, sizeof(tmp));
846 memset(res, 0, sizeof(res));
847 return ret;
850 static void
851 RSA_MD5_DES3_checksum(krb5_context context,
852 struct key_data *key,
853 void *data,
854 size_t len,
855 Checksum *C)
857 struct md5 md5;
858 des_cblock ivec;
859 unsigned char *p = C->checksum.data;
860 des_key_schedule *sched = key->schedule->data;
862 krb5_generate_random_block(p, 8);
863 md5_init(&md5);
864 md5_update(&md5, p, 8);
865 md5_update(&md5, data, len);
866 md5_finito(&md5, p + 8);
867 memset (&ivec, 0, sizeof(ivec));
868 des_ede3_cbc_encrypt((des_cblock*)p,
869 (des_cblock*)p,
870 24,
871 sched[0], sched[1], sched[2],
872 &ivec,
873 DES_ENCRYPT);
876 static krb5_error_code
877 RSA_MD5_DES3_verify(krb5_context context,
878 struct key_data *key,
879 void *data,
880 size_t len,
881 Checksum *C)
883 struct md5 md5;
884 unsigned char tmp[24];
885 unsigned char res[16];
886 des_cblock ivec;
887 des_key_schedule *sched = key->schedule->data;
888 krb5_error_code ret = 0;
890 memset(&ivec, 0, sizeof(ivec));
891 des_ede3_cbc_encrypt(C->checksum.data,
892 (void*)tmp,
893 C->checksum.length,
894 sched[0], sched[1], sched[2],
895 &ivec,
896 DES_DECRYPT);
897 md5_init(&md5);
898 md5_update(&md5, tmp, 8); /* confounder */
899 md5_update(&md5, data, len);
900 md5_finito(&md5, res);
901 if(memcmp(res, tmp + 8, sizeof(res)) != 0)
902 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
903 memset(tmp, 0, sizeof(tmp));
904 memset(res, 0, sizeof(res));
905 return ret;
908 static void
909 SHA1_checksum(krb5_context context,
910 struct key_data *key,
911 void *data,
912 size_t len,
913 Checksum *C)
915 struct sha m;
916 sha_init(&m);
917 sha_update(&m, data, len);
918 sha_finito(&m, C->checksum.data);
921 /* HMAC according to RFC2104 */
922 static void
923 hmac(krb5_context context,
924 struct checksum_type *cm,
925 void *data,
926 size_t len,
927 struct key_data *keyblock,
928 Checksum *result)
930 unsigned char *ipad, *opad;
931 unsigned char *key;
932 size_t key_len;
933 int i;
935 if(keyblock->key->keyvalue.length > cm->blocksize){
936 (*cm->checksum)(context,
937 keyblock,
938 keyblock->key->keyvalue.data,
939 keyblock->key->keyvalue.length,
940 result);
941 key = result->checksum.data;
942 key_len = result->checksum.length;
943 } else {
944 key = keyblock->key->keyvalue.data;
945 key_len = keyblock->key->keyvalue.length;
947 ipad = malloc(cm->blocksize + len);
948 opad = malloc(cm->blocksize + cm->checksumsize);
949 memset(ipad, 0x36, cm->blocksize);
950 memset(opad, 0x5c, cm->blocksize);
951 for(i = 0; i < key_len; i++){
952 ipad[i] ^= key[i];
953 opad[i] ^= key[i];
955 memcpy(ipad + cm->blocksize, data, len);
956 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, result);
957 memcpy(opad + cm->blocksize, result->checksum.data,
958 result->checksum.length);
959 (*cm->checksum)(context, keyblock, opad,
960 cm->blocksize + cm->checksumsize, result);
961 memset(ipad, 0, cm->blocksize + len);
962 free(ipad);
963 memset(opad, 0, cm->blocksize + cm->checksumsize);
964 free(opad);
967 static void
968 HMAC_SHA1_DES3_checksum(krb5_context context,
969 struct key_data *key,
970 void *data,
971 size_t len,
972 Checksum *result)
974 struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
975 /* iovec? */
976 unsigned char *p = malloc(4 + len);
977 _krb5_put_int(p, len, 4);
978 memcpy(p + 4, data , len);
979 hmac(context, c, p, 4 + len, key, result);
980 memset(p, 0, 4 + len);
981 free(p);
984 struct checksum_type checksum_none = {
985 CKSUMTYPE_NONE,
986 "none",
990 NONE_checksum,
991 NULL
993 struct checksum_type checksum_crc32 = {
994 CKSUMTYPE_CRC32,
995 "crc32",
999 CRC32_checksum,
1000 NULL
1002 struct checksum_type checksum_rsa_md4 = {
1003 CKSUMTYPE_RSA_MD4,
1004 "rsa-md4",
1007 F_CPROOF,
1008 RSA_MD4_checksum,
1009 NULL
1011 struct checksum_type checksum_rsa_md4_des = {
1012 CKSUMTYPE_RSA_MD4_DES,
1013 "rsa-md4-des",
1016 F_KEYED | F_CPROOF | F_VARIANT,
1017 RSA_MD4_DES_checksum,
1018 RSA_MD4_DES_verify
1020 #if 0
1021 struct checksum_type checksum_des_mac = {
1022 CKSUMTYPE_DES_MAC,
1023 "des-mac",
1027 DES_MAC_checksum,
1029 struct checksum_type checksum_des_mac_k = {
1030 CKSUMTYPE_DES_MAC_K,
1031 "des-mac-k",
1035 DES_MAC_K_checksum,
1037 struct checksum_type checksum_rsa_md4_des_k = {
1038 CKSUMTYPE_RSA_MD4_DES_K,
1039 "rsa-md4-des-k",
1043 RSA_MD4_DES_K_checksum,
1044 RSA_MD4_DES_K_verify,
1046 #endif
1047 struct checksum_type checksum_rsa_md5 = {
1048 CKSUMTYPE_RSA_MD5,
1049 "rsa-md5",
1052 F_CPROOF,
1053 RSA_MD5_checksum,
1054 NULL
1056 struct checksum_type checksum_rsa_md5_des = {
1057 CKSUMTYPE_RSA_MD5_DES,
1058 "rsa-md5-des",
1061 F_KEYED | F_CPROOF | F_VARIANT,
1062 RSA_MD5_DES_checksum,
1063 RSA_MD5_DES_verify,
1065 struct checksum_type checksum_rsa_md5_des3 = {
1066 CKSUMTYPE_RSA_MD5_DES3,
1067 "rsa-md5-des3",
1070 F_KEYED | F_CPROOF | F_VARIANT,
1071 RSA_MD5_DES3_checksum,
1072 RSA_MD5_DES3_verify,
1074 struct checksum_type checksum_sha1 = {
1075 CKSUMTYPE_SHA1,
1076 "sha1",
1079 F_CPROOF,
1080 SHA1_checksum,
1081 NULL
1083 struct checksum_type checksum_hmac_sha1_des3 = {
1084 CKSUMTYPE_HMAC_SHA1_DES3,
1085 "hmac-sha1-des3",
1088 F_KEYED | F_CPROOF | F_DERIVED,
1089 HMAC_SHA1_DES3_checksum,
1090 NULL
1093 struct checksum_type *checksum_types[] = {
1094 &checksum_none,
1095 &checksum_crc32,
1096 &checksum_rsa_md4,
1097 &checksum_rsa_md4_des,
1098 #if 0
1099 &checksum_des_mac,
1100 &checksum_des_mac_k,
1101 &checksum_rsa_md4_des_k,
1102 #endif
1103 &checksum_rsa_md5,
1104 &checksum_rsa_md5_des,
1105 &checksum_rsa_md5_des3,
1106 &checksum_sha1,
1107 &checksum_hmac_sha1_des3
1110 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1112 static struct checksum_type *
1113 _find_checksum(krb5_cksumtype type)
1115 int i;
1116 for(i = 0; i < num_checksums; i++)
1117 if(checksum_types[i]->type == type)
1118 return checksum_types[i];
1119 return NULL;
1122 static krb5_error_code
1123 get_checksum_key(krb5_context context,
1124 krb5_crypto crypto,
1125 unsigned usage, /* not krb5_key_usage */
1126 struct checksum_type *ct,
1127 struct key_data **key)
1129 krb5_error_code ret = 0;
1131 if(ct->flags & F_DERIVED)
1132 ret = _get_derived_key(context, crypto, usage, key);
1133 else if(ct->flags & F_VARIANT) {
1134 int i;
1136 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1137 if(*key == NULL)
1138 return ENOMEM;
1139 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1140 if(ret)
1141 return ret;
1142 for(i = 0; i < (*key)->key->keyvalue.length; i++)
1143 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1144 } else {
1145 *key = &crypto->key;
1147 if(ret == 0)
1148 ret = _key_schedule(context, *key);
1149 return ret;
1152 static krb5_error_code
1153 do_checksum (krb5_context context,
1154 struct checksum_type *ct,
1155 krb5_crypto crypto,
1156 unsigned usage,
1157 void *data,
1158 size_t len,
1159 Checksum *result)
1161 krb5_error_code ret;
1162 struct key_data *dkey;
1163 int keyed_checksum;
1165 keyed_checksum = (ct->flags & F_KEYED) != 0;
1166 if(keyed_checksum && crypto == NULL)
1167 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1168 if(keyed_checksum)
1169 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1170 else
1171 dkey = NULL;
1172 result->cksumtype = ct->type;
1173 krb5_data_alloc(&result->checksum, ct->checksumsize);
1174 (*ct->checksum)(context, dkey, data, len, result);
1175 return 0;
1178 static krb5_error_code
1179 create_checksum(krb5_context context,
1180 krb5_crypto crypto,
1181 unsigned usage, /* not krb5_key_usage */
1182 krb5_cksumtype type, /* if crypto == NULL */
1183 void *data,
1184 size_t len,
1185 Checksum *result)
1187 struct checksum_type *ct;
1189 if(crypto) {
1190 ct = crypto->et->keyed_checksum;
1191 if(ct == NULL)
1192 ct = crypto->et->cksumtype;
1193 } else
1194 ct = _find_checksum(type);
1195 if(ct == NULL)
1196 return KRB5_PROG_SUMTYPE_NOSUPP;
1197 return do_checksum (context, ct, crypto, usage, data, len, result);
1200 krb5_error_code
1201 krb5_create_checksum(krb5_context context,
1202 krb5_crypto crypto,
1203 unsigned usage_or_type,
1204 void *data,
1205 size_t len,
1206 Checksum *result)
1208 return create_checksum(context, crypto,
1209 CHECKSUM_USAGE(usage_or_type),
1210 usage_or_type, data, len, result);
1213 static krb5_error_code
1214 verify_checksum(krb5_context context,
1215 krb5_crypto crypto,
1216 unsigned usage, /* not krb5_key_usage */
1217 void *data,
1218 size_t len,
1219 Checksum *cksum)
1221 krb5_error_code ret;
1222 struct key_data *dkey;
1223 int keyed_checksum;
1224 Checksum c;
1225 struct checksum_type *ct;
1227 ct = _find_checksum(cksum->cksumtype);
1228 if(ct == NULL)
1229 return KRB5_PROG_SUMTYPE_NOSUPP;
1230 if(ct->checksumsize != cksum->checksum.length)
1231 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1232 keyed_checksum = (ct->flags & F_KEYED) != 0;
1233 if(keyed_checksum && crypto == NULL)
1234 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1235 if(keyed_checksum)
1236 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1237 else
1238 dkey = NULL;
1239 if(ct->verify)
1240 return (*ct->verify)(context, dkey, data, len, cksum);
1242 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1243 if (ret)
1244 return ret;
1246 (*ct->checksum)(context, dkey, data, len, &c);
1248 if(c.checksum.length != cksum->checksum.length ||
1249 memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length))
1250 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1251 else
1252 ret = 0;
1253 krb5_data_free (&c.checksum);
1254 return ret;
1257 krb5_error_code
1258 krb5_verify_checksum(krb5_context context,
1259 krb5_crypto crypto,
1260 krb5_key_usage usage,
1261 void *data,
1262 size_t len,
1263 Checksum *cksum)
1265 return verify_checksum(context, crypto,
1266 CHECKSUM_USAGE(usage), data, len, cksum);
1269 krb5_error_code
1270 krb5_checksumsize(krb5_context context,
1271 krb5_cksumtype type,
1272 size_t *size)
1274 struct checksum_type *ct = _find_checksum(type);
1275 if(ct == NULL)
1276 return KRB5_PROG_SUMTYPE_NOSUPP;
1277 *size = ct->checksumsize;
1278 return 0;
1281 krb5_boolean
1282 krb5_checksum_is_keyed(krb5_context context,
1283 krb5_cksumtype type)
1285 struct checksum_type *ct = _find_checksum(type);
1286 if(ct == NULL)
1287 return KRB5_PROG_SUMTYPE_NOSUPP;
1288 return ct->flags & F_KEYED;
1291 krb5_boolean
1292 krb5_checksum_is_collision_proof(krb5_context context,
1293 krb5_cksumtype type)
1295 struct checksum_type *ct = _find_checksum(type);
1296 if(ct == NULL)
1297 return KRB5_PROG_SUMTYPE_NOSUPP;
1298 return ct->flags & F_CPROOF;
1301 /************************************************************
1303 ************************************************************/
1305 static void
1306 NULL_encrypt(struct key_data *key,
1307 void *data,
1308 size_t len,
1309 krb5_boolean encrypt)
1313 static void
1314 DES_CBC_encrypt_null_ivec(struct key_data *key,
1315 void *data,
1316 size_t len,
1317 krb5_boolean encrypt)
1319 des_cblock ivec;
1320 des_key_schedule *s = key->schedule->data;
1321 memset(&ivec, 0, sizeof(ivec));
1322 des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1325 static void
1326 DES_CBC_encrypt_key_ivec(struct key_data *key,
1327 void *data,
1328 size_t len,
1329 krb5_boolean encrypt)
1331 des_cblock ivec;
1332 des_key_schedule *s = key->schedule->data;
1333 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
1334 des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1337 static void
1338 DES3_CBC_encrypt(struct key_data *key,
1339 void *data,
1340 size_t len,
1341 krb5_boolean encrypt)
1343 des_cblock ivec;
1344 des_key_schedule *s = key->schedule->data;
1345 memset(&ivec, 0, sizeof(ivec));
1346 des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], &ivec, encrypt);
1350 * these should currently be in reverse preference order.
1353 static struct encryption_type etypes[] = {
1355 ETYPE_NULL,
1356 "null",
1359 &keytype_null,
1360 &checksum_none,
1361 NULL,
1363 NULL_encrypt,
1366 ETYPE_DES_CBC_CRC,
1367 "des-cbc-crc",
1370 &keytype_des,
1371 &checksum_crc32,
1372 NULL,
1374 DES_CBC_encrypt_key_ivec,
1377 ETYPE_DES_CBC_MD4,
1378 "des-cbc-md4",
1381 &keytype_des,
1382 &checksum_rsa_md4,
1383 &checksum_rsa_md4_des,
1385 DES_CBC_encrypt_null_ivec,
1388 ETYPE_DES_CBC_MD5,
1389 "des-cbc-md5",
1392 &keytype_des,
1393 &checksum_rsa_md5,
1394 &checksum_rsa_md5_des,
1396 DES_CBC_encrypt_null_ivec,
1399 ETYPE_DES3_CBC_MD5,
1400 "des3-cbc-md5",
1403 &keytype_des3,
1404 &checksum_rsa_md5,
1405 &checksum_rsa_md5_des3,
1407 DES3_CBC_encrypt,
1409 #if NEW_DES3_CODE
1411 ETYPE_DES3_CBC_SHA1,
1412 "des3-cbc-sha1",
1415 &keytype_des3_derived,
1416 &checksum_sha1,
1417 &checksum_hmac_sha1_des3,
1418 F_DERIVED,
1419 DES3_CBC_encrypt,
1421 #else
1423 ETYPE_NEW_DES3_CBC_SHA1,
1424 "new-des3-cbc-sha1",
1427 &keytype_des3_derived,
1428 &checksum_sha1,
1429 &checksum_hmac_sha1_des3,
1430 F_DERIVED,
1431 DES3_CBC_encrypt,
1434 ETYPE_DES3_CBC_SHA1,
1435 "des3-cbc-sha1",
1438 &keytype_des3,
1439 &checksum_sha1,
1440 &checksum_hmac_sha1_des3,
1442 DES3_CBC_encrypt,
1444 #endif
1446 ETYPE_DES_CBC_NONE,
1447 "des-cbc-none",
1450 &keytype_des,
1451 &checksum_none,
1452 NULL,
1453 F_PSEUDO,
1454 DES_CBC_encrypt_null_ivec,
1457 ETYPE_DES3_CBC_NONE,
1458 "des3-cbc-none",
1461 &keytype_des3_derived,
1462 &checksum_none,
1463 NULL,
1464 F_PSEUDO,
1465 DES_CBC_encrypt_null_ivec,
1469 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
1472 static struct encryption_type *
1473 _find_enctype(krb5_enctype type)
1475 int i;
1476 for(i = 0; i < num_etypes; i++)
1477 if(etypes[i].type == type)
1478 return &etypes[i];
1479 return NULL;
1483 krb5_error_code
1484 krb5_enctype_to_string(krb5_context context,
1485 krb5_enctype etype,
1486 char **string)
1488 struct encryption_type *e;
1489 e = _find_enctype(etype);
1490 if(e == NULL)
1491 return KRB5_PROG_ETYPE_NOSUPP;
1492 *string = strdup(e->name);
1493 if(*string == NULL)
1494 return ENOMEM;
1495 return 0;
1498 krb5_error_code
1499 krb5_string_to_enctype(krb5_context context,
1500 const char *string,
1501 krb5_enctype *etype)
1503 int i;
1504 for(i = 0; i < num_etypes; i++)
1505 if(strcasecmp(etypes[i].name, string) == 0){
1506 *etype = etypes[i].type;
1507 return 0;
1509 return KRB5_PROG_ETYPE_NOSUPP;
1512 krb5_error_code
1513 krb5_enctype_to_keytype(krb5_context context,
1514 krb5_enctype etype,
1515 krb5_keytype *keytype)
1517 struct encryption_type *e = _find_enctype(etype);
1518 krb5_warnx(context, "krb5_enctype_to_keytype(%u)", etype);
1519 if(e == NULL)
1520 return KRB5_PROG_ETYPE_NOSUPP;
1521 *keytype = e->keytype->type; /* XXX */
1522 return 0;
1525 #if 0
1526 krb5_error_code
1527 krb5_keytype_to_enctype(krb5_context context,
1528 krb5_keytype keytype,
1529 krb5_enctype *etype)
1531 struct key_type *kt = _find_keytype(keytype);
1532 krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
1533 if(kt == NULL)
1534 return KRB5_PROG_KEYTYPE_NOSUPP;
1535 *etype = kt->best_etype;
1536 return 0;
1538 #endif
1540 krb5_error_code
1541 krb5_keytype_to_enctypes (krb5_context context,
1542 krb5_keytype keytype,
1543 unsigned *len,
1544 int **val)
1546 int i;
1547 unsigned n = 0;
1548 int *ret;
1550 for (i = num_etypes - 1; i >= 0; --i) {
1551 if (etypes[i].keytype->type == keytype
1552 && !(etypes[i].flags & F_PSEUDO))
1553 ++n;
1555 ret = malloc(n * sizeof(int));
1556 if (ret == NULL && n != 0)
1557 return ENOMEM;
1558 n = 0;
1559 for (i = num_etypes - 1; i >= 0; --i) {
1560 if (etypes[i].keytype->type == keytype
1561 && !(etypes[i].flags & F_PSEUDO))
1562 ret[n++] = etypes[i].type;
1564 *len = n;
1565 *val = ret;
1566 return 0;
1569 krb5_error_code
1570 krb5_enctype_valid(krb5_context context,
1571 krb5_enctype etype)
1573 return _find_enctype(etype) != NULL;
1576 /* if two enctypes have compatible keys */
1577 krb5_boolean
1578 krb5_enctypes_comptible_keys(krb5_context context,
1579 krb5_enctype etype1,
1580 krb5_enctype etype2)
1582 struct encryption_type *e1 = _find_enctype(etype1);
1583 struct encryption_type *e2 = _find_enctype(etype2);
1584 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
1587 static krb5_boolean
1588 derived_crypto(krb5_context context,
1589 krb5_crypto crypto)
1591 return (crypto->et->flags & F_DERIVED) != 0;
1595 #define CHECKSUMSIZE(C) ((C)->checksumsize)
1596 #define CHECKSUMTYPE(C) ((C)->type)
1598 static krb5_error_code
1599 encrypt_internal_derived(krb5_context context,
1600 krb5_crypto crypto,
1601 unsigned usage,
1602 void *data,
1603 size_t len,
1604 krb5_data *result)
1606 size_t sz, block_sz, checksum_sz;
1607 Checksum cksum;
1608 unsigned char *p, *q;
1609 krb5_error_code ret;
1610 struct key_data *dkey;
1611 struct encryption_type *et = crypto->et;
1613 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1615 sz = et->confoundersize + 4 /* length */ + len;
1616 block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
1617 p = calloc(1, block_sz + checksum_sz);
1618 if(p == NULL)
1619 return ENOMEM;
1621 q = p;
1622 krb5_generate_random_block(q, et->confoundersize); /* XXX */
1623 q += et->confoundersize;
1624 _krb5_put_int(q, len, 4);
1625 q += 4;
1626 memcpy(q, data, len);
1628 ret = create_checksum(context,
1629 crypto,
1630 INTEGRITY_USAGE(usage),
1633 block_sz,
1634 &cksum);
1635 if(ret == 0 && cksum.checksum.length != checksum_sz)
1636 ret = KRB5_CRYPTO_INTERNAL;
1637 if(ret) {
1638 memset(p, 0, block_sz + checksum_sz);
1639 free(p);
1640 return ret;
1642 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
1643 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1644 if(ret) {
1645 memset(p, 0, block_sz + checksum_sz);
1646 free(p);
1647 return ret;
1649 ret = _key_schedule(context, dkey);
1650 if(ret) {
1651 memset(p, 0, block_sz);
1652 free(p);
1653 return ret;
1655 #ifdef CRYPTO_DEBUG
1656 krb5_crypto_debug(context, 1, block_sz, dkey->key);
1657 #endif
1658 (*et->encrypt)(dkey, p, block_sz, 1);
1659 result->data = p;
1660 result->length = block_sz + checksum_sz;
1661 return 0;
1664 static krb5_error_code
1665 encrypt_internal(krb5_context context,
1666 krb5_crypto crypto,
1667 void *data,
1668 size_t len,
1669 krb5_data *result)
1671 size_t sz, block_sz, checksum_sz;
1672 Checksum cksum;
1673 unsigned char *p, *q;
1674 krb5_error_code ret;
1675 struct encryption_type *et = crypto->et;
1677 checksum_sz = CHECKSUMSIZE(et->cksumtype);
1679 sz = et->confoundersize + checksum_sz + len;
1680 block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
1681 p = calloc(1, block_sz);
1682 if(p == NULL)
1683 return ENOMEM;
1685 q = p;
1686 krb5_generate_random_block(q, et->confoundersize); /* XXX */
1687 q += et->confoundersize;
1688 memset(q, 0, checksum_sz);
1689 q += checksum_sz;
1690 memcpy(q, data, len);
1692 ret = create_checksum(context,
1693 NULL,
1695 CHECKSUMTYPE(et->cksumtype),
1697 block_sz,
1698 &cksum);
1699 if(ret == 0 && cksum.checksum.length != checksum_sz) {
1700 free_Checksum (&cksum);
1701 ret = KRB5_CRYPTO_INTERNAL;
1703 if(ret) {
1704 memset(p, 0, block_sz);
1705 free(p);
1706 free_Checksum(&cksum);
1707 return ret;
1709 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
1710 free_Checksum(&cksum);
1711 ret = _key_schedule(context, &crypto->key);
1712 if(ret) {
1713 memset(p, 0, block_sz);
1714 free(p);
1715 return ret;
1717 #ifdef CRYPTO_DEBUG
1718 krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
1719 #endif
1720 (*et->encrypt)(&crypto->key, p, block_sz, 1);
1721 result->data = p;
1722 result->length = block_sz;
1723 return 0;
1726 static krb5_error_code
1727 decrypt_internal_derived(krb5_context context,
1728 krb5_crypto crypto,
1729 unsigned usage,
1730 void *data,
1731 size_t len,
1732 krb5_data *result)
1734 size_t checksum_sz;
1735 Checksum cksum;
1736 unsigned char *p;
1737 krb5_error_code ret;
1738 struct key_data *dkey;
1739 struct encryption_type *et = crypto->et;
1740 unsigned long l;
1742 p = malloc(len);
1743 if(p == NULL)
1744 return ENOMEM;
1745 memcpy(p, data, len);
1747 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1748 len -= checksum_sz;
1750 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1751 if(ret) {
1752 free(p);
1753 return ret;
1755 ret = _key_schedule(context, dkey);
1756 if(ret) {
1757 free(p);
1758 return ret;
1760 #ifdef CRYPTO_DEBUG
1761 krb5_crypto_debug(context, 0, len, dkey->key);
1762 #endif
1763 (*et->encrypt)(dkey, p, len, 0);
1765 cksum.checksum.data = p + len;
1766 cksum.checksum.length = checksum_sz;
1768 ret = verify_checksum(context,
1769 crypto,
1770 INTEGRITY_USAGE(usage),
1772 len,
1773 &cksum);
1774 if(ret) {
1775 free(p);
1776 return ret;
1778 _krb5_get_int(p + et->confoundersize, &l, 4);
1779 memmove(p, p + et->confoundersize + 4, l);
1780 result->data = realloc(p, l);
1781 if(p == NULL) {
1782 free(p);
1783 return ENOMEM;
1785 result->length = l;
1786 return 0;
1789 static krb5_error_code
1790 decrypt_internal(krb5_context context,
1791 krb5_crypto crypto,
1792 void *data,
1793 size_t len,
1794 krb5_data *result)
1796 krb5_error_code ret;
1797 unsigned char *p;
1798 Checksum cksum;
1799 size_t checksum_sz, l;
1800 struct encryption_type *et = crypto->et;
1802 checksum_sz = CHECKSUMSIZE(et->cksumtype);
1803 p = malloc(len);
1804 if(p == NULL)
1805 return ENOMEM;
1806 memcpy(p, data, len);
1808 ret = _key_schedule(context, &crypto->key);
1809 if(ret) {
1810 free(p);
1811 return ret;
1813 #ifdef CRYPTO_DEBUG
1814 krb5_crypto_debug(context, 0, len, crypto->key.key);
1815 #endif
1816 (*et->encrypt)(&crypto->key, p, len, 0);
1817 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1818 if(ret) {
1819 free(p);
1820 return ret;
1822 memset(p + et->confoundersize, 0, checksum_sz);
1823 cksum.cksumtype = CHECKSUMTYPE(et->cksumtype);
1824 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
1825 free_Checksum(&cksum);
1826 if(ret) {
1827 free(p);
1828 return ret;
1830 l = len - et->confoundersize - checksum_sz;
1831 memmove(p, p + et->confoundersize + checksum_sz, l);
1832 result->data = realloc(p, l);
1833 if(result->data == NULL) {
1834 free(p);
1835 return ENOMEM;
1837 result->length = l;
1838 return 0;
1841 krb5_error_code
1842 krb5_encrypt(krb5_context context,
1843 krb5_crypto crypto,
1844 unsigned usage,
1845 void *data,
1846 size_t len,
1847 krb5_data *result)
1849 if(derived_crypto(context, crypto))
1850 return encrypt_internal_derived(context, crypto, usage,
1851 data, len, result);
1852 else
1853 return encrypt_internal(context, crypto, data, len, result);
1856 krb5_error_code
1857 krb5_encrypt_EncryptedData(krb5_context context,
1858 krb5_crypto crypto,
1859 unsigned usage,
1860 void *data,
1861 size_t len,
1862 int kvno,
1863 EncryptedData *result)
1865 result->etype = CRYPTO_ETYPE(crypto);
1866 if(kvno){
1867 ALLOC(result->kvno, 1);
1868 *result->kvno = kvno;
1869 }else
1870 result->kvno = NULL;
1871 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
1874 krb5_error_code
1875 krb5_decrypt(krb5_context context,
1876 krb5_crypto crypto,
1877 unsigned usage,
1878 void *data,
1879 size_t len,
1880 krb5_data *result)
1882 if(derived_crypto(context, crypto))
1883 return decrypt_internal_derived(context, crypto, usage,
1884 data, len, result);
1885 else
1886 return decrypt_internal(context, crypto, data, len, result);
1889 krb5_error_code
1890 krb5_decrypt_EncryptedData(krb5_context context,
1891 krb5_crypto crypto,
1892 unsigned usage,
1893 EncryptedData *e,
1894 krb5_data *result)
1896 return krb5_decrypt(context, crypto, usage,
1897 e->cipher.data, e->cipher.length, result);
1900 /************************************************************
1902 ************************************************************/
1904 void
1905 krb5_generate_random_block(void *buf, size_t len)
1907 des_cblock key, out;
1908 static des_cblock counter;
1909 static des_key_schedule schedule;
1910 int i;
1911 static int initialized = 0;
1913 if(!initialized) {
1914 des_new_random_key(&key);
1915 des_set_key(&key, schedule);
1916 memset(&key, 0, sizeof(key));
1917 des_new_random_key(&counter);
1919 while(len > 0) {
1920 des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT);
1921 for(i = 7; i >=0; i--)
1922 if(counter[i]++)
1923 break;
1924 memcpy(buf, out, min(len, sizeof(out)));
1925 len -= min(len, sizeof(out));
1926 buf = (char*)buf + sizeof(out);
1930 /* XXX should be moved someplace else */
1931 static void
1932 DES3_postproc(krb5_context context,
1933 unsigned char *k, size_t len, struct key_data *key)
1935 unsigned char x[24];
1936 int ki = 0, xi = 0, kb = 8, xb = 8;
1937 memset(x, 0, sizeof(x));
1938 /* insert a parity bit after every seven bits (I'm not
1939 convinced that the first 21 bytes has more entropy than the
1940 who 24 byte block...) */
1941 while(xi < 24) {
1942 unsigned u = k[ki] & ((1 << kb) - 1);
1943 if(kb == xb)
1944 x[xi] |= u;
1945 else if(kb > xb)
1946 x[xi] |= u >> (kb - xb);
1947 else /* kb < xb */
1948 x[xi] |= u << (xb - kb);
1950 if(kb < xb - 1) {
1951 xb -= kb;
1952 kb = 8;
1953 ki++;
1954 } else {
1955 kb -= xb - 1;
1956 xb = 8;
1957 xi++;
1960 k = key->key->keyvalue.data;
1961 memcpy(k, x, 24);
1962 memset(x, 0, sizeof(x));
1963 krb5_free_data(context, key->schedule);
1964 key->schedule = NULL;
1965 des_set_odd_parity((des_cblock*)k);
1966 des_set_odd_parity((des_cblock*)(k + 8));
1967 des_set_odd_parity((des_cblock*)(k + 16));
1970 static krb5_error_code
1971 derive_key(krb5_context context,
1972 struct encryption_type *et,
1973 struct key_data *key,
1974 void *constant,
1975 size_t len)
1977 unsigned char *k;
1978 unsigned int nblocks = 0, i;
1979 krb5_error_code ret = 0;
1981 struct key_type *kt = et->keytype;
1982 ret = _key_schedule(context, key);
1983 if(ret)
1984 return ret;
1985 if(et->blocksize * 8 < kt->bits ||
1986 len != et->blocksize) {
1987 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
1988 k = malloc(nblocks * et->blocksize);
1989 if(k == NULL)
1990 return ENOMEM;
1991 _krb5_n_fold(constant, len, k, et->blocksize);
1992 for(i = 0; i < nblocks; i++) {
1993 if(i > 0)
1994 memcpy(k + i * et->blocksize,
1995 k + (i - 1) * et->blocksize,
1996 et->blocksize);
1997 (*et->encrypt)(key, k + i * et->blocksize, et->blocksize, 1);
1999 } else {
2000 void *c = malloc(len);
2001 if(c == NULL)
2002 return ENOMEM;
2003 memcpy(c, constant, len);
2004 (*et->encrypt)(key, c, len, 1);
2005 k = malloc((kt->bits + 7) / 8);
2006 if(k == NULL)
2007 return ENOMEM;
2008 _krb5_n_fold(c, len, k, kt->bits);
2009 free(c);
2012 /* XXX keytype dependent post-processing */
2013 switch(kt->type) {
2014 case KEYTYPE_DES3:
2015 DES3_postproc(context, k, nblocks * et->blocksize, key);
2016 break;
2017 default:
2018 krb5_warnx(context, "derive_key() called with unknown keytype (%u)",
2019 kt->type);
2020 ret = KRB5_CRYPTO_INTERNAL;
2021 break;
2023 memset(k, 0, nblocks * et->blocksize);
2024 free(k);
2025 return ret;
2028 static struct key_data *
2029 _new_derived_key(krb5_crypto crypto, unsigned usage)
2031 struct key_usage *d = crypto->key_usage;
2032 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
2033 if(d == NULL)
2034 return NULL;
2035 crypto->key_usage = d;
2036 d += crypto->num_key_usage++;
2037 memset(d, 0, sizeof(*d));
2038 d->usage = usage;
2039 return &d->key;
2042 static krb5_error_code
2043 _get_derived_key(krb5_context context,
2044 krb5_crypto crypto,
2045 unsigned usage,
2046 struct key_data **key)
2048 int i;
2049 struct key_data *d;
2050 unsigned char constant[4];
2051 for(i = 0; i < crypto->num_key_usage; i++)
2052 if(crypto->key_usage[i].usage == usage) {
2053 *key = &crypto->key_usage[i].key;
2054 return 0;
2056 d = _new_derived_key(crypto, usage);
2057 if(d == NULL)
2058 return ENOMEM;
2059 krb5_copy_keyblock(context, crypto->key.key, &d->key);
2060 _krb5_put_int(constant, usage, 4);
2061 derive_key(context, crypto->et, d, constant, sizeof(constant));
2062 *key = d;
2063 return 0;
2067 krb5_error_code
2068 krb5_crypto_init(krb5_context context,
2069 krb5_keyblock *key,
2070 krb5_enctype etype,
2071 krb5_crypto *crypto)
2073 krb5_error_code ret;
2074 ALLOC(*crypto, 1);
2075 if(*crypto == NULL)
2076 return ENOMEM;
2077 if(etype == ETYPE_NULL)
2078 etype = key->keytype;
2079 (*crypto)->et = _find_enctype(etype);
2080 if((*crypto)->et == NULL) {
2081 free(*crypto);
2082 return KRB5_PROG_ETYPE_NOSUPP;
2084 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2085 if(ret) {
2086 free(*crypto);
2087 return ret;
2089 (*crypto)->key.schedule = NULL;
2090 (*crypto)->num_key_usage = 0;
2091 (*crypto)->key_usage = NULL;
2092 return 0;
2095 static void
2096 free_key_data(krb5_context context, struct key_data *key)
2098 krb5_free_keyblock(context, key->key);
2099 if(key->schedule) {
2100 memset(key->schedule->data, 0, key->schedule->length);
2101 krb5_free_data(context, key->schedule);
2105 static void
2106 free_key_usage(krb5_context context, struct key_usage *ku)
2108 free_key_data(context, &ku->key);
2111 krb5_error_code
2112 krb5_crypto_destroy(krb5_context context,
2113 krb5_crypto crypto)
2115 int i;
2117 for(i = 0; i < crypto->num_key_usage; i++)
2118 free_key_usage(context, &crypto->key_usage[i]);
2119 free(crypto->key_usage);
2120 free_key_data(context, &crypto->key);
2121 free (crypto);
2122 return 0;
2125 krb5_error_code
2126 krb5_string_to_key_derived(krb5_context context,
2127 const void *str,
2128 size_t len,
2129 krb5_enctype etype,
2130 krb5_keyblock *key)
2132 struct encryption_type *et = _find_enctype(etype);
2133 krb5_error_code ret;
2134 struct key_data kd;
2136 if(et == NULL)
2137 return KRB5_PROG_ETYPE_NOSUPP;
2138 ALLOC(kd.key, 1);
2139 kd.key->keytype = etype;
2140 krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
2141 _krb5_n_fold(str, len, kd.key->keyvalue.data, kd.key->keyvalue.length);
2142 ret = derive_key(context,
2144 &kd,
2145 "kerberos", /* XXX well known constant */
2146 strlen("kerberos"));
2147 ret = krb5_copy_keyblock_contents(context, kd.key, key);
2148 free_key_data(context, &kd);
2149 return ret;
2153 * Return the size of an encrypted packet of length `data_len'
2156 size_t
2157 krb5_get_wrapped_length (krb5_context context,
2158 krb5_crypto crypto,
2159 size_t data_len)
2161 struct encryption_type *et = crypto->et;
2162 size_t blocksize = et->blocksize;
2163 size_t res;
2165 res = et->confoundersize + et->cksumtype->checksumsize + data_len;
2166 res = (res + blocksize - 1) / blocksize * blocksize;
2167 return res;
2170 #ifdef CRYPTO_DEBUG
2172 static krb5_error_code
2173 krb5_get_keyid(krb5_context context,
2174 krb5_keyblock *key,
2175 u_int32_t *keyid)
2177 struct md5 md5;
2178 unsigned char tmp[16];
2179 md5_init(&md5);
2180 md5_update(&md5, key->keyvalue.data, key->keyvalue.length);
2181 md5_finito(&md5, tmp);
2182 *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
2183 return 0;
2186 static void
2187 krb5_crypto_debug(krb5_context context,
2188 int encrypt,
2189 size_t len,
2190 krb5_keyblock *key)
2192 u_int32_t keyid;
2193 char *kt;
2194 krb5_get_keyid(context, key, &keyid);
2195 krb5_enctype_to_string(context, key->keytype, &kt);
2196 krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
2197 encrypt ? "encrypting" : "decrypting",
2198 (unsigned long)len,
2199 keyid,
2200 kt);
2201 free(kt);
2204 #endif /* CRYPTO_DEBUG */