update to pseudo-standard APIs for md4,md5,sha.
[heimdal.git] / lib / krb5 / crypto.c
blobf7eecb6a80b4c3d9f2509092d37b973bd90614df
1 /*
2 * Copyright (c) 1997 - 2000 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. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "krb5_locl.h"
35 RCSID("$Id$");
37 #undef CRYPTO_DEBUG
38 #ifdef CRYPTO_DEBUG
39 static void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*);
40 #endif
43 struct key_data {
44 krb5_keyblock *key;
45 krb5_data *schedule;
48 struct key_usage {
49 unsigned usage;
50 struct key_data key;
53 struct krb5_crypto_data {
54 struct encryption_type *et;
55 struct key_data key;
56 int num_key_usage;
57 struct key_usage *key_usage;
60 #define CRYPTO_ETYPE(C) ((C)->et->type)
62 /* bits for `flags' below */
63 #define F_KEYED 1 /* checksum is keyed */
64 #define F_CPROOF 2 /* checksum is collision proof */
65 #define F_DERIVED 4 /* uses derived keys */
66 #define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
67 #define F_PSEUDO 16 /* not a real protocol type */
69 struct salt_type {
70 krb5_salttype type;
71 const char *name;
72 krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
73 krb5_salt, krb5_keyblock*);
76 struct key_type {
77 krb5_keytype type; /* XXX */
78 const char *name;
79 size_t bits;
80 size_t size;
81 size_t schedule_size;
82 #if 0
83 krb5_enctype best_etype;
84 #endif
85 void (*random_key)(krb5_context, krb5_keyblock*);
86 void (*schedule)(krb5_context, struct key_data *);
87 struct salt_type *string_to_key;
90 struct checksum_type {
91 krb5_cksumtype type;
92 const char *name;
93 size_t blocksize;
94 size_t checksumsize;
95 unsigned flags;
96 void (*checksum)(krb5_context, struct key_data*, void*, size_t, Checksum*);
97 krb5_error_code (*verify)(krb5_context, struct key_data*,
98 void*, size_t, Checksum*);
101 struct encryption_type {
102 krb5_enctype type;
103 const char *name;
104 size_t blocksize;
105 size_t confoundersize;
106 struct key_type *keytype;
107 struct checksum_type *cksumtype;
108 struct checksum_type *keyed_checksum;
109 unsigned flags;
110 void (*encrypt)(struct key_data *, void *, size_t, int);
113 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
114 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
115 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
117 static struct checksum_type *_find_checksum(krb5_cksumtype type);
118 static struct encryption_type *_find_enctype(krb5_enctype type);
119 static struct key_type *_find_keytype(krb5_keytype type);
120 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
121 unsigned, struct key_data**);
122 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
124 /************************************************************
126 ************************************************************/
128 static void
129 DES_random_key(krb5_context context,
130 krb5_keyblock *key)
132 des_cblock *k = key->keyvalue.data;
133 do {
134 krb5_generate_random_block(k, sizeof(des_cblock));
135 des_set_odd_parity(k);
136 } while(des_is_weak_key(k));
139 static void
140 DES_schedule(krb5_context context,
141 struct key_data *key)
143 des_set_key(key->key->keyvalue.data, key->schedule->data);
146 static krb5_error_code
147 DES_string_to_key(krb5_context context,
148 krb5_enctype enctype,
149 krb5_data password,
150 krb5_salt salt,
151 krb5_keyblock *key)
153 char *s;
154 size_t len;
155 des_cblock tmp;
157 len = password.length + salt.saltvalue.length + 1;
158 s = malloc(len);
159 if(s == NULL)
160 return ENOMEM;
161 memcpy(s, password.data, password.length);
162 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
163 s[len - 1] = '\0';
164 des_string_to_key(s, &tmp);
165 key->keytype = enctype;
166 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
167 memset(&tmp, 0, sizeof(tmp));
168 memset(s, 0, len);
169 free(s);
170 return 0;
173 /* This defines the Andrew string_to_key function. It accepts a password
174 * string as input and converts its via a one-way encryption algorithm to a DES
175 * encryption key. It is compatible with the original Andrew authentication
176 * service password database.
180 * Short passwords, i.e 8 characters or less.
182 static void
183 DES_AFS3_CMU_string_to_key (krb5_data pw,
184 krb5_data cell,
185 des_cblock *key)
187 char password[8+1]; /* crypt is limited to 8 chars anyway */
188 int i;
190 for(i = 0; i < 8; i++) {
191 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
192 ((i < cell.length) ? ((char*)cell.data)[i] : 0);
193 password[i] = c ? c : 'X';
195 password[8] = '\0';
197 memcpy(key, crypt(password, "#~") + 2, sizeof(des_cblock));
199 /* parity is inserted into the LSB so left shift each byte up one
200 bit. This allows ascii characters with a zero MSB to retain as
201 much significance as possible. */
202 for (i = 0; i < sizeof(des_cblock); i++)
203 ((unsigned char*)key)[i] <<= 1;
204 des_set_odd_parity (key);
208 * Long passwords, i.e 9 characters or more.
210 static void
211 DES_AFS3_Transarc_string_to_key (krb5_data pw,
212 krb5_data cell,
213 des_cblock *key)
215 des_key_schedule schedule;
216 des_cblock temp_key;
217 des_cblock ivec;
218 char password[512];
219 size_t passlen;
221 memcpy(password, pw.data, min(pw.length, sizeof(password)));
222 if(pw.length < sizeof(password))
223 memcpy(password + pw.length,
224 cell.data, min(cell.length,
225 sizeof(password) - pw.length));
226 passlen = min(sizeof(password), pw.length + cell.length);
227 memcpy(&ivec, "kerberos", 8);
228 memcpy(&temp_key, "kerberos", 8);
229 des_set_odd_parity (&temp_key);
230 des_set_key (&temp_key, schedule);
231 des_cbc_cksum ((const void *)password, &ivec, passlen,
232 schedule, &ivec);
234 memcpy(&temp_key, &ivec, 8);
235 des_set_odd_parity (&temp_key);
236 des_set_key (&temp_key, schedule);
237 des_cbc_cksum ((const void *)password, key, passlen,
238 schedule, &ivec);
239 memset(&schedule, 0, sizeof(schedule));
240 memset(&temp_key, 0, sizeof(temp_key));
241 memset(&ivec, 0, sizeof(ivec));
242 memset(password, 0, sizeof(password));
244 des_set_odd_parity (key);
247 static krb5_error_code
248 DES_AFS3_string_to_key(krb5_context context,
249 krb5_enctype enctype,
250 krb5_data password,
251 krb5_salt salt,
252 krb5_keyblock *key)
254 des_cblock tmp;
255 if(password.length > 8)
256 DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
257 else
258 DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
259 key->keytype = enctype;
260 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
261 memset(&key, 0, sizeof(key));
262 return 0;
265 static void
266 DES3_random_key(krb5_context context,
267 krb5_keyblock *key)
269 des_cblock *k = key->keyvalue.data;
270 do {
271 krb5_generate_random_block(k, 3 * sizeof(des_cblock));
272 des_set_odd_parity(&k[0]);
273 des_set_odd_parity(&k[1]);
274 des_set_odd_parity(&k[2]);
275 } while(des_is_weak_key(&k[0]) ||
276 des_is_weak_key(&k[1]) ||
277 des_is_weak_key(&k[2]));
280 static void
281 DES3_schedule(krb5_context context,
282 struct key_data *key)
284 des_cblock *k = key->key->keyvalue.data;
285 des_key_schedule *s = key->schedule->data;
286 des_set_key(&k[0], s[0]);
287 des_set_key(&k[1], s[1]);
288 des_set_key(&k[2], s[2]);
292 * A = A xor B. A & B are 8 bytes.
295 static void
296 xor (des_cblock *key, const unsigned char *b)
298 unsigned char *a = (unsigned char*)key;
299 a[0] ^= b[0];
300 a[1] ^= b[1];
301 a[2] ^= b[2];
302 a[3] ^= b[3];
303 a[4] ^= b[4];
304 a[5] ^= b[5];
305 a[6] ^= b[6];
306 a[7] ^= b[7];
309 static krb5_error_code
310 DES3_string_to_key(krb5_context context,
311 krb5_enctype enctype,
312 krb5_data password,
313 krb5_salt salt,
314 krb5_keyblock *key)
316 char *str;
317 size_t len;
318 unsigned char tmp[24];
319 des_cblock keys[3];
321 len = password.length + salt.saltvalue.length;
322 str = malloc(len);
323 if(len != 0 && str == NULL)
324 return ENOMEM;
325 memcpy(str, password.data, password.length);
326 memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
328 des_cblock ivec;
329 des_key_schedule s[3];
330 int i;
332 _krb5_n_fold(str, len, tmp, 24);
334 for(i = 0; i < 3; i++){
335 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
336 des_set_odd_parity(keys + i);
337 if(des_is_weak_key(keys + i))
338 xor(keys + i, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
339 des_set_key(keys + i, s[i]);
341 memset(&ivec, 0, sizeof(ivec));
342 des_ede3_cbc_encrypt((const void *)tmp,
343 (void *)tmp, sizeof(tmp),
344 s[0], s[1], s[2], &ivec, DES_ENCRYPT);
345 memset(s, 0, sizeof(s));
346 memset(&ivec, 0, sizeof(ivec));
347 for(i = 0; i < 3; i++){
348 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
349 des_set_odd_parity(keys + i);
350 if(des_is_weak_key(keys + i))
351 xor(keys + i, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
353 memset(tmp, 0, sizeof(tmp));
355 key->keytype = enctype;
356 krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
357 memset(keys, 0, sizeof(keys));
358 memset(str, 0, len);
359 free(str);
360 return 0;
363 static krb5_error_code
364 DES3_string_to_key_derived(krb5_context context,
365 krb5_enctype enctype,
366 krb5_data password,
367 krb5_salt salt,
368 krb5_keyblock *key)
370 krb5_error_code ret;
371 size_t len = password.length + salt.saltvalue.length;
372 char *s;
374 s = malloc(len);
375 if(len != 0 && 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;
390 * ARCFOUR
393 static void
394 ARCFOUR_random_key(krb5_context context, krb5_keyblock *key)
396 krb5_generate_random_block (key->keyvalue.data,
397 key->keyvalue.length);
400 static void
401 ARCFOUR_schedule(krb5_context context, struct key_data *kd)
403 RC4_set_key (kd->schedule->data,
404 kd->key->keyvalue.length, kd->key->keyvalue.data);
407 static krb5_error_code
408 ARCFOUR_string_to_key(krb5_context context,
409 krb5_enctype enctype,
410 krb5_data password,
411 krb5_salt salt,
412 krb5_keyblock *key)
414 char *s, *p;
415 size_t len;
416 int i;
417 MD4_CTX m;
419 len = 2 * (password.length + salt.saltvalue.length);
420 s = malloc (len);
421 if (len != 0 && s == NULL)
422 return ENOMEM;
423 for (p = s, i = 0; i < password.length; ++i) {
424 *p++ = ((char *)password.data)[i];
425 *p++ = 0;
427 for (i = 0; i < salt.saltvalue.length; ++i) {
428 *p++ = ((char *)salt.saltvalue.data)[i];
429 *p++ = 0;
431 MD4Init (&m);
432 MD4Update (&m, s, len);
433 key->keytype = enctype;
434 krb5_data_alloc (&key->keyvalue, 16);
435 MD4Final (key->keyvalue.data, &m);
436 memset (s, 0, len);
437 free (s);
438 return 0;
441 extern struct salt_type des_salt[],
442 des3_salt[], des3_salt_derived[], arcfour_salt[];
444 struct key_type keytype_null = {
445 KEYTYPE_NULL,
446 "null",
450 NULL,
451 NULL,
452 NULL
455 struct key_type keytype_des = {
456 KEYTYPE_DES,
457 "des",
459 sizeof(des_cblock),
460 sizeof(des_key_schedule),
461 DES_random_key,
462 DES_schedule,
463 des_salt
466 struct key_type keytype_des3 = {
467 KEYTYPE_DES3,
468 "des3",
469 168,
470 3 * sizeof(des_cblock),
471 3 * sizeof(des_key_schedule),
472 DES3_random_key,
473 DES3_schedule,
474 des3_salt
477 struct key_type keytype_des3_derived = {
478 KEYTYPE_DES3,
479 "des3",
480 168,
481 3 * sizeof(des_cblock),
482 3 * sizeof(des_key_schedule),
483 DES3_random_key,
484 DES3_schedule,
485 des3_salt_derived
488 struct key_type keytype_arcfour = {
489 KEYTYPE_ARCFOUR,
490 "arcfour",
491 128,
493 sizeof(RC4_KEY),
494 ARCFOUR_random_key,
495 ARCFOUR_schedule,
496 arcfour_salt
499 struct key_type *keytypes[] = {
500 &keytype_null,
501 &keytype_des,
502 &keytype_des3_derived,
503 &keytype_des3,
504 &keytype_arcfour
507 static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
509 static struct key_type *
510 _find_keytype(krb5_keytype type)
512 int i;
513 for(i = 0; i < num_keytypes; i++)
514 if(keytypes[i]->type == type)
515 return keytypes[i];
516 return NULL;
520 struct salt_type des_salt[] = {
522 KRB5_PW_SALT,
523 "pw-salt",
524 DES_string_to_key
527 KRB5_AFS3_SALT,
528 "afs3-salt",
529 DES_AFS3_string_to_key
531 { 0 }
534 struct salt_type des3_salt[] = {
536 KRB5_PW_SALT,
537 "pw-salt",
538 DES3_string_to_key
540 { 0 }
543 struct salt_type des3_salt_derived[] = {
545 KRB5_PW_SALT,
546 "pw-salt",
547 DES3_string_to_key_derived
549 { 0 }
552 struct salt_type arcfour_salt[] = {
554 KRB5_PW_SALT,
555 "pw-salt",
556 ARCFOUR_string_to_key
558 { 0 }
561 krb5_error_code
562 krb5_salttype_to_string (krb5_context context,
563 krb5_enctype etype,
564 krb5_salttype stype,
565 char **string)
567 struct encryption_type *e;
568 struct salt_type *st;
570 e = _find_enctype (etype);
571 if (e == NULL)
572 return KRB5_PROG_ETYPE_NOSUPP;
573 for (st = e->keytype->string_to_key; st && st->type; st++) {
574 if (st->type == stype) {
575 *string = strdup (st->name);
576 if (*string == NULL)
577 return ENOMEM;
578 return 0;
581 return HEIM_ERR_SALTTYPE_NOSUPP;
584 krb5_error_code
585 krb5_string_to_salttype (krb5_context context,
586 krb5_enctype etype,
587 const char *string,
588 krb5_salttype *salttype)
590 struct encryption_type *e;
591 struct salt_type *st;
593 e = _find_enctype (etype);
594 if (e == NULL)
595 return KRB5_PROG_ETYPE_NOSUPP;
596 for (st = e->keytype->string_to_key; st && st->type; st++) {
597 if (strcasecmp (st->name, string) == 0) {
598 *salttype = st->type;
599 return 0;
602 return HEIM_ERR_SALTTYPE_NOSUPP;
605 krb5_error_code
606 krb5_get_pw_salt(krb5_context context,
607 krb5_const_principal principal,
608 krb5_salt *salt)
610 size_t len;
611 int i;
612 krb5_error_code ret;
613 char *p;
615 salt->salttype = KRB5_PW_SALT;
616 len = strlen(principal->realm);
617 for (i = 0; i < principal->name.name_string.len; ++i)
618 len += strlen(principal->name.name_string.val[i]);
619 ret = krb5_data_alloc (&salt->saltvalue, len);
620 if (ret)
621 return ret;
622 p = salt->saltvalue.data;
623 memcpy (p, principal->realm, strlen(principal->realm));
624 p += strlen(principal->realm);
625 for (i = 0; i < principal->name.name_string.len; ++i) {
626 memcpy (p,
627 principal->name.name_string.val[i],
628 strlen(principal->name.name_string.val[i]));
629 p += strlen(principal->name.name_string.val[i]);
631 return 0;
634 krb5_error_code
635 krb5_free_salt(krb5_context context,
636 krb5_salt salt)
638 krb5_data_free(&salt.saltvalue);
639 return 0;
642 krb5_error_code
643 krb5_string_to_key_data (krb5_context context,
644 krb5_enctype enctype,
645 krb5_data password,
646 krb5_principal principal,
647 krb5_keyblock *key)
649 krb5_error_code ret;
650 krb5_salt salt;
652 ret = krb5_get_pw_salt(context, principal, &salt);
653 if(ret)
654 return ret;
655 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
656 krb5_free_salt(context, salt);
657 return ret;
660 krb5_error_code
661 krb5_string_to_key (krb5_context context,
662 krb5_enctype enctype,
663 const char *password,
664 krb5_principal principal,
665 krb5_keyblock *key)
667 krb5_data pw;
668 pw.data = (void*)password;
669 pw.length = strlen(password);
670 return krb5_string_to_key_data(context, enctype, pw, principal, key);
673 krb5_error_code
674 krb5_string_to_key_data_salt (krb5_context context,
675 krb5_enctype enctype,
676 krb5_data password,
677 krb5_salt salt,
678 krb5_keyblock *key)
680 struct encryption_type *et =_find_enctype(enctype);
681 struct salt_type *st;
682 if(et == NULL)
683 return KRB5_PROG_ETYPE_NOSUPP;
684 for(st = et->keytype->string_to_key; st && st->type; st++)
685 if(st->type == salt.salttype)
686 return (*st->string_to_key)(context, enctype, password, salt, key);
687 return HEIM_ERR_SALTTYPE_NOSUPP;
690 krb5_error_code
691 krb5_string_to_key_salt (krb5_context context,
692 krb5_enctype enctype,
693 const char *password,
694 krb5_salt salt,
695 krb5_keyblock *key)
697 krb5_data pw;
698 pw.data = (void*)password;
699 pw.length = strlen(password);
700 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
703 krb5_error_code
704 krb5_keytype_to_string(krb5_context context,
705 krb5_keytype keytype,
706 char **string)
708 struct key_type *kt = _find_keytype(keytype);
709 if(kt == NULL)
710 return KRB5_PROG_KEYTYPE_NOSUPP;
711 *string = strdup(kt->name);
712 if(*string == NULL)
713 return ENOMEM;
714 return 0;
717 krb5_error_code
718 krb5_string_to_keytype(krb5_context context,
719 const char *string,
720 krb5_keytype *keytype)
722 int i;
723 for(i = 0; i < num_keytypes; i++)
724 if(strcasecmp(keytypes[i]->name, string) == 0){
725 *keytype = keytypes[i]->type;
726 return 0;
728 return KRB5_PROG_KEYTYPE_NOSUPP;
731 krb5_error_code
732 krb5_generate_random_keyblock(krb5_context context,
733 krb5_enctype type,
734 krb5_keyblock *key)
736 krb5_error_code ret;
737 struct encryption_type *et = _find_enctype(type);
738 if(et == NULL)
739 return KRB5_PROG_ETYPE_NOSUPP;
740 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
741 if(ret)
742 return ret;
743 key->keytype = type;
744 if(et->keytype->random_key)
745 (*et->keytype->random_key)(context, key);
746 else
747 krb5_generate_random_block(key->keyvalue.data,
748 key->keyvalue.length);
749 return 0;
752 static krb5_error_code
753 _key_schedule(krb5_context context,
754 struct key_data *key)
756 krb5_error_code ret;
757 struct encryption_type *et = _find_enctype(key->key->keytype);
758 struct key_type *kt = et->keytype;
760 if(kt->schedule == NULL)
761 return 0;
762 ALLOC(key->schedule, 1);
763 if(key->schedule == NULL)
764 return ENOMEM;
765 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
766 if(ret) {
767 free(key->schedule);
768 key->schedule = NULL;
769 return ret;
771 (*kt->schedule)(context, key);
772 return 0;
775 /************************************************************
777 ************************************************************/
779 static void
780 NONE_checksum(krb5_context context,
781 struct key_data *key,
782 void *data,
783 size_t len,
784 Checksum *C)
788 static void
789 CRC32_checksum(krb5_context context,
790 struct key_data *key,
791 void *data,
792 size_t len,
793 Checksum *C)
795 u_int32_t crc;
796 unsigned char *r = C->checksum.data;
797 _krb5_crc_init_table ();
798 crc = _krb5_crc_update (data, len, 0);
799 r[0] = crc & 0xff;
800 r[1] = (crc >> 8) & 0xff;
801 r[2] = (crc >> 16) & 0xff;
802 r[3] = (crc >> 24) & 0xff;
805 static void
806 RSA_MD4_checksum(krb5_context context,
807 struct key_data *key,
808 void *data,
809 size_t len,
810 Checksum *C)
812 MD4_CTX m;
814 MD4Init (&m);
815 MD4Update (&m, data, len);
816 MD4Final (C->checksum.data, &m);
819 static void
820 RSA_MD4_DES_checksum(krb5_context context,
821 struct key_data *key,
822 void *data,
823 size_t len,
824 Checksum *cksum)
826 MD4_CTX md4;
827 des_cblock ivec;
828 unsigned char *p = cksum->checksum.data;
830 krb5_generate_random_block(p, 8);
831 MD4Init (&md4);
832 MD4Update (&md4, p, 8);
833 MD4Update (&md4, data, len);
834 MD4Final (p + 8, &md4);
835 memset (&ivec, 0, sizeof(ivec));
836 des_cbc_encrypt((const void *)p,
837 (void *)p,
838 24,
839 key->schedule->data,
840 &ivec,
841 DES_ENCRYPT);
844 static krb5_error_code
845 RSA_MD4_DES_verify(krb5_context context,
846 struct key_data *key,
847 void *data,
848 size_t len,
849 Checksum *C)
851 MD4_CTX md4;
852 unsigned char tmp[24];
853 unsigned char res[16];
854 des_cblock ivec;
855 krb5_error_code ret = 0;
857 memset(&ivec, 0, sizeof(ivec));
858 des_cbc_encrypt(C->checksum.data,
859 (void*)tmp,
860 C->checksum.length,
861 key->schedule->data,
862 &ivec,
863 DES_DECRYPT);
864 MD4Init (&md4);
865 MD4Update (&md4, tmp, 8); /* confounder */
866 MD4Update (&md4, data, len);
867 MD4Final (res, &md4);
868 if(memcmp(res, tmp + 8, sizeof(res)) != 0)
869 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
870 memset(tmp, 0, sizeof(tmp));
871 memset(res, 0, sizeof(res));
872 return ret;
875 static void
876 RSA_MD5_checksum(krb5_context context,
877 struct key_data *key,
878 void *data,
879 size_t len,
880 Checksum *C)
882 MD5_CTX m;
884 MD5Init (&m);
885 MD5Update(&m, data, len);
886 MD5Final (C->checksum.data, &m);
889 static void
890 RSA_MD5_DES_checksum(krb5_context context,
891 struct key_data *key,
892 void *data,
893 size_t len,
894 Checksum *C)
896 MD5_CTX md5;
897 des_cblock ivec;
898 unsigned char *p = C->checksum.data;
900 krb5_generate_random_block(p, 8);
901 MD5Init (&md5);
902 MD5Update (&md5, p, 8);
903 MD5Update (&md5, data, len);
904 MD5Final (p + 8, &md5);
905 memset (&ivec, 0, sizeof(ivec));
906 des_cbc_encrypt((const void *)p,
907 (void *)p,
908 24,
909 key->schedule->data,
910 &ivec,
911 DES_ENCRYPT);
914 static krb5_error_code
915 RSA_MD5_DES_verify(krb5_context context,
916 struct key_data *key,
917 void *data,
918 size_t len,
919 Checksum *C)
921 MD5_CTX md5;
922 unsigned char tmp[24];
923 unsigned char res[16];
924 des_cblock ivec;
925 des_key_schedule *sched = key->schedule->data;
926 krb5_error_code ret = 0;
928 memset(&ivec, 0, sizeof(ivec));
929 des_cbc_encrypt(C->checksum.data,
930 (void*)tmp,
931 C->checksum.length,
932 sched[0],
933 &ivec,
934 DES_DECRYPT);
935 MD5Init (&md5);
936 MD5Update (&md5, tmp, 8); /* confounder */
937 MD5Update (&md5, data, len);
938 MD5Final (res, &md5);
939 if(memcmp(res, tmp + 8, sizeof(res)) != 0)
940 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
941 memset(tmp, 0, sizeof(tmp));
942 memset(res, 0, sizeof(res));
943 return ret;
946 static void
947 RSA_MD5_DES3_checksum(krb5_context context,
948 struct key_data *key,
949 void *data,
950 size_t len,
951 Checksum *C)
953 MD5_CTX md5;
954 des_cblock ivec;
955 unsigned char *p = C->checksum.data;
956 des_key_schedule *sched = key->schedule->data;
958 krb5_generate_random_block(p, 8);
959 MD5Init (&md5);
960 MD5Update (&md5, p, 8);
961 MD5Update (&md5, data, len);
962 MD5Final (p + 8, &md5);
963 memset (&ivec, 0, sizeof(ivec));
964 des_ede3_cbc_encrypt((const void *)p,
965 (void *)p,
966 24,
967 sched[0], sched[1], sched[2],
968 &ivec,
969 DES_ENCRYPT);
972 static krb5_error_code
973 RSA_MD5_DES3_verify(krb5_context context,
974 struct key_data *key,
975 void *data,
976 size_t len,
977 Checksum *C)
979 MD5_CTX md5;
980 unsigned char tmp[24];
981 unsigned char res[16];
982 des_cblock ivec;
983 des_key_schedule *sched = key->schedule->data;
984 krb5_error_code ret = 0;
986 memset(&ivec, 0, sizeof(ivec));
987 des_ede3_cbc_encrypt(C->checksum.data,
988 (void*)tmp,
989 C->checksum.length,
990 sched[0], sched[1], sched[2],
991 &ivec,
992 DES_DECRYPT);
993 MD5Init (&md5);
994 MD5Update (&md5, tmp, 8); /* confounder */
995 MD5Update (&md5, data, len);
996 MD5Final (res, &md5);
997 if(memcmp(res, tmp + 8, sizeof(res)) != 0)
998 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
999 memset(tmp, 0, sizeof(tmp));
1000 memset(res, 0, sizeof(res));
1001 return ret;
1004 static void
1005 SHA1_checksum(krb5_context context,
1006 struct key_data *key,
1007 void *data,
1008 size_t len,
1009 Checksum *C)
1011 SHA1_CTX m;
1013 SHA1Init(&m);
1014 SHA1Update(&m, data, len);
1015 SHA1Final(C->checksum.data, &m);
1018 /* HMAC according to RFC2104 */
1019 static void
1020 hmac(krb5_context context,
1021 struct checksum_type *cm,
1022 void *data,
1023 size_t len,
1024 struct key_data *keyblock,
1025 Checksum *result)
1027 unsigned char *ipad, *opad;
1028 unsigned char *key;
1029 size_t key_len;
1030 int i;
1032 if(keyblock->key->keyvalue.length > cm->blocksize){
1033 (*cm->checksum)(context,
1034 keyblock,
1035 keyblock->key->keyvalue.data,
1036 keyblock->key->keyvalue.length,
1037 result);
1038 key = result->checksum.data;
1039 key_len = result->checksum.length;
1040 } else {
1041 key = keyblock->key->keyvalue.data;
1042 key_len = keyblock->key->keyvalue.length;
1044 ipad = malloc(cm->blocksize + len);
1045 opad = malloc(cm->blocksize + cm->checksumsize);
1046 memset(ipad, 0x36, cm->blocksize);
1047 memset(opad, 0x5c, cm->blocksize);
1048 for(i = 0; i < key_len; i++){
1049 ipad[i] ^= key[i];
1050 opad[i] ^= key[i];
1052 memcpy(ipad + cm->blocksize, data, len);
1053 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, result);
1054 memcpy(opad + cm->blocksize, result->checksum.data,
1055 result->checksum.length);
1056 (*cm->checksum)(context, keyblock, opad,
1057 cm->blocksize + cm->checksumsize, result);
1058 memset(ipad, 0, cm->blocksize + len);
1059 free(ipad);
1060 memset(opad, 0, cm->blocksize + cm->checksumsize);
1061 free(opad);
1064 static void
1065 HMAC_SHA1_DES3_checksum(krb5_context context,
1066 struct key_data *key,
1067 void *data,
1068 size_t len,
1069 Checksum *result)
1071 struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1073 hmac(context, c, data, len, key, result);
1076 struct checksum_type checksum_none = {
1077 CKSUMTYPE_NONE,
1078 "none",
1082 NONE_checksum,
1083 NULL
1085 struct checksum_type checksum_crc32 = {
1086 CKSUMTYPE_CRC32,
1087 "crc32",
1091 CRC32_checksum,
1092 NULL
1094 struct checksum_type checksum_rsa_md4 = {
1095 CKSUMTYPE_RSA_MD4,
1096 "rsa-md4",
1099 F_CPROOF,
1100 RSA_MD4_checksum,
1101 NULL
1103 struct checksum_type checksum_rsa_md4_des = {
1104 CKSUMTYPE_RSA_MD4_DES,
1105 "rsa-md4-des",
1108 F_KEYED | F_CPROOF | F_VARIANT,
1109 RSA_MD4_DES_checksum,
1110 RSA_MD4_DES_verify
1112 #if 0
1113 struct checksum_type checksum_des_mac = {
1114 CKSUMTYPE_DES_MAC,
1115 "des-mac",
1119 DES_MAC_checksum,
1121 struct checksum_type checksum_des_mac_k = {
1122 CKSUMTYPE_DES_MAC_K,
1123 "des-mac-k",
1127 DES_MAC_K_checksum,
1129 struct checksum_type checksum_rsa_md4_des_k = {
1130 CKSUMTYPE_RSA_MD4_DES_K,
1131 "rsa-md4-des-k",
1135 RSA_MD4_DES_K_checksum,
1136 RSA_MD4_DES_K_verify,
1138 #endif
1139 struct checksum_type checksum_rsa_md5 = {
1140 CKSUMTYPE_RSA_MD5,
1141 "rsa-md5",
1144 F_CPROOF,
1145 RSA_MD5_checksum,
1146 NULL
1148 struct checksum_type checksum_rsa_md5_des = {
1149 CKSUMTYPE_RSA_MD5_DES,
1150 "rsa-md5-des",
1153 F_KEYED | F_CPROOF | F_VARIANT,
1154 RSA_MD5_DES_checksum,
1155 RSA_MD5_DES_verify,
1157 struct checksum_type checksum_rsa_md5_des3 = {
1158 CKSUMTYPE_RSA_MD5_DES3,
1159 "rsa-md5-des3",
1162 F_KEYED | F_CPROOF | F_VARIANT,
1163 RSA_MD5_DES3_checksum,
1164 RSA_MD5_DES3_verify,
1166 struct checksum_type checksum_sha1 = {
1167 CKSUMTYPE_SHA1,
1168 "sha1",
1171 F_CPROOF,
1172 SHA1_checksum,
1173 NULL
1175 struct checksum_type checksum_hmac_sha1_des3 = {
1176 CKSUMTYPE_HMAC_SHA1_DES3,
1177 "hmac-sha1-des3",
1180 F_KEYED | F_CPROOF | F_DERIVED,
1181 HMAC_SHA1_DES3_checksum,
1182 NULL
1185 struct checksum_type *checksum_types[] = {
1186 &checksum_none,
1187 &checksum_crc32,
1188 &checksum_rsa_md4,
1189 &checksum_rsa_md4_des,
1190 #if 0
1191 &checksum_des_mac,
1192 &checksum_des_mac_k,
1193 &checksum_rsa_md4_des_k,
1194 #endif
1195 &checksum_rsa_md5,
1196 &checksum_rsa_md5_des,
1197 &checksum_rsa_md5_des3,
1198 &checksum_sha1,
1199 &checksum_hmac_sha1_des3
1202 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1204 static struct checksum_type *
1205 _find_checksum(krb5_cksumtype type)
1207 int i;
1208 for(i = 0; i < num_checksums; i++)
1209 if(checksum_types[i]->type == type)
1210 return checksum_types[i];
1211 return NULL;
1214 static krb5_error_code
1215 get_checksum_key(krb5_context context,
1216 krb5_crypto crypto,
1217 unsigned usage, /* not krb5_key_usage */
1218 struct checksum_type *ct,
1219 struct key_data **key)
1221 krb5_error_code ret = 0;
1223 if(ct->flags & F_DERIVED)
1224 ret = _get_derived_key(context, crypto, usage, key);
1225 else if(ct->flags & F_VARIANT) {
1226 int i;
1228 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1229 if(*key == NULL)
1230 return ENOMEM;
1231 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1232 if(ret)
1233 return ret;
1234 for(i = 0; i < (*key)->key->keyvalue.length; i++)
1235 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1236 } else {
1237 *key = &crypto->key;
1239 if(ret == 0)
1240 ret = _key_schedule(context, *key);
1241 return ret;
1244 static krb5_error_code
1245 do_checksum (krb5_context context,
1246 struct checksum_type *ct,
1247 krb5_crypto crypto,
1248 unsigned usage,
1249 void *data,
1250 size_t len,
1251 Checksum *result)
1253 krb5_error_code ret;
1254 struct key_data *dkey;
1255 int keyed_checksum;
1257 keyed_checksum = (ct->flags & F_KEYED) != 0;
1258 if(keyed_checksum && crypto == NULL)
1259 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1260 if(keyed_checksum)
1261 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1262 else
1263 dkey = NULL;
1264 result->cksumtype = ct->type;
1265 krb5_data_alloc(&result->checksum, ct->checksumsize);
1266 (*ct->checksum)(context, dkey, data, len, result);
1267 return 0;
1270 static krb5_error_code
1271 create_checksum(krb5_context context,
1272 krb5_crypto crypto,
1273 unsigned usage, /* not krb5_key_usage */
1274 krb5_cksumtype type, /* if crypto == NULL */
1275 void *data,
1276 size_t len,
1277 Checksum *result)
1279 struct checksum_type *ct;
1281 if(crypto) {
1282 ct = crypto->et->keyed_checksum;
1283 if(ct == NULL)
1284 ct = crypto->et->cksumtype;
1285 } else
1286 ct = _find_checksum(type);
1287 if(ct == NULL)
1288 return KRB5_PROG_SUMTYPE_NOSUPP;
1289 return do_checksum (context, ct, crypto, usage, data, len, result);
1292 krb5_error_code
1293 krb5_create_checksum(krb5_context context,
1294 krb5_crypto crypto,
1295 unsigned usage_or_type,
1296 void *data,
1297 size_t len,
1298 Checksum *result)
1300 return create_checksum(context, crypto,
1301 CHECKSUM_USAGE(usage_or_type),
1302 usage_or_type, data, len, result);
1305 static krb5_error_code
1306 verify_checksum(krb5_context context,
1307 krb5_crypto crypto,
1308 unsigned usage, /* not krb5_key_usage */
1309 void *data,
1310 size_t len,
1311 Checksum *cksum)
1313 krb5_error_code ret;
1314 struct key_data *dkey;
1315 int keyed_checksum;
1316 Checksum c;
1317 struct checksum_type *ct;
1319 ct = _find_checksum(cksum->cksumtype);
1320 if(ct == NULL)
1321 return KRB5_PROG_SUMTYPE_NOSUPP;
1322 if(ct->checksumsize != cksum->checksum.length)
1323 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1324 keyed_checksum = (ct->flags & F_KEYED) != 0;
1325 if(keyed_checksum && crypto == NULL)
1326 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1327 if(keyed_checksum)
1328 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1329 else
1330 dkey = NULL;
1331 if(ct->verify)
1332 return (*ct->verify)(context, dkey, data, len, cksum);
1334 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1335 if (ret)
1336 return ret;
1338 (*ct->checksum)(context, dkey, data, len, &c);
1340 if(c.checksum.length != cksum->checksum.length ||
1341 memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length))
1342 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1343 else
1344 ret = 0;
1345 krb5_data_free (&c.checksum);
1346 return ret;
1349 krb5_error_code
1350 krb5_verify_checksum(krb5_context context,
1351 krb5_crypto crypto,
1352 krb5_key_usage usage,
1353 void *data,
1354 size_t len,
1355 Checksum *cksum)
1357 return verify_checksum(context, crypto,
1358 CHECKSUM_USAGE(usage), data, len, cksum);
1361 krb5_error_code
1362 krb5_checksumsize(krb5_context context,
1363 krb5_cksumtype type,
1364 size_t *size)
1366 struct checksum_type *ct = _find_checksum(type);
1367 if(ct == NULL)
1368 return KRB5_PROG_SUMTYPE_NOSUPP;
1369 *size = ct->checksumsize;
1370 return 0;
1373 krb5_boolean
1374 krb5_checksum_is_keyed(krb5_context context,
1375 krb5_cksumtype type)
1377 struct checksum_type *ct = _find_checksum(type);
1378 if(ct == NULL)
1379 return KRB5_PROG_SUMTYPE_NOSUPP;
1380 return ct->flags & F_KEYED;
1383 krb5_boolean
1384 krb5_checksum_is_collision_proof(krb5_context context,
1385 krb5_cksumtype type)
1387 struct checksum_type *ct = _find_checksum(type);
1388 if(ct == NULL)
1389 return KRB5_PROG_SUMTYPE_NOSUPP;
1390 return ct->flags & F_CPROOF;
1393 /************************************************************
1395 ************************************************************/
1397 static void
1398 NULL_encrypt(struct key_data *key,
1399 void *data,
1400 size_t len,
1401 krb5_boolean encrypt)
1405 static void
1406 DES_CBC_encrypt_null_ivec(struct key_data *key,
1407 void *data,
1408 size_t len,
1409 krb5_boolean encrypt)
1411 des_cblock ivec;
1412 des_key_schedule *s = key->schedule->data;
1413 memset(&ivec, 0, sizeof(ivec));
1414 des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1417 static void
1418 DES_CBC_encrypt_key_ivec(struct key_data *key,
1419 void *data,
1420 size_t len,
1421 krb5_boolean encrypt)
1423 des_cblock ivec;
1424 des_key_schedule *s = key->schedule->data;
1425 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
1426 des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1429 static void
1430 DES3_CBC_encrypt(struct key_data *key,
1431 void *data,
1432 size_t len,
1433 krb5_boolean encrypt)
1435 des_cblock ivec;
1436 des_key_schedule *s = key->schedule->data;
1437 memset(&ivec, 0, sizeof(ivec));
1438 des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], &ivec, encrypt);
1441 static void
1442 ARCFOUR_encrypt(struct key_data *key,
1443 void *data,
1444 size_t len,
1445 krb5_boolean encrypt)
1451 * these should currently be in reverse preference order.
1454 static struct encryption_type etypes[] = {
1456 ETYPE_NULL,
1457 "null",
1460 &keytype_null,
1461 &checksum_none,
1462 NULL,
1464 NULL_encrypt,
1467 ETYPE_DES_CBC_CRC,
1468 "des-cbc-crc",
1471 &keytype_des,
1472 &checksum_crc32,
1473 NULL,
1475 DES_CBC_encrypt_key_ivec,
1478 ETYPE_DES_CBC_MD4,
1479 "des-cbc-md4",
1482 &keytype_des,
1483 &checksum_rsa_md4,
1484 &checksum_rsa_md4_des,
1486 DES_CBC_encrypt_null_ivec,
1489 ETYPE_DES_CBC_MD5,
1490 "des-cbc-md5",
1493 &keytype_des,
1494 &checksum_rsa_md5,
1495 &checksum_rsa_md5_des,
1497 DES_CBC_encrypt_null_ivec,
1500 ETYPE_DES3_CBC_MD5,
1501 "des3-cbc-md5",
1504 &keytype_des3,
1505 &checksum_rsa_md5,
1506 &checksum_rsa_md5_des3,
1508 DES3_CBC_encrypt,
1511 ETYPE_DES3_CBC_SHA1,
1512 "des3-cbc-sha1",
1515 &keytype_des3_derived,
1516 &checksum_sha1,
1517 &checksum_hmac_sha1_des3,
1518 F_DERIVED,
1519 DES3_CBC_encrypt,
1522 ETYPE_OLD_DES3_CBC_SHA1,
1523 "old-des3-cbc-sha1",
1526 &keytype_des3,
1527 &checksum_sha1,
1528 &checksum_hmac_sha1_des3,
1530 DES3_CBC_encrypt,
1533 ETYPE_DES_CBC_NONE,
1534 "des-cbc-none",
1537 &keytype_des,
1538 &checksum_none,
1539 NULL,
1540 F_PSEUDO,
1541 DES_CBC_encrypt_null_ivec,
1544 ETYPE_DES3_CBC_NONE,
1545 "des3-cbc-none",
1548 &keytype_des3_derived,
1549 &checksum_none,
1550 NULL,
1551 F_PSEUDO,
1552 DES_CBC_encrypt_null_ivec,
1556 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
1559 static struct encryption_type *
1560 _find_enctype(krb5_enctype type)
1562 int i;
1563 for(i = 0; i < num_etypes; i++)
1564 if(etypes[i].type == type)
1565 return &etypes[i];
1566 return NULL;
1570 krb5_error_code
1571 krb5_enctype_to_string(krb5_context context,
1572 krb5_enctype etype,
1573 char **string)
1575 struct encryption_type *e;
1576 e = _find_enctype(etype);
1577 if(e == NULL)
1578 return KRB5_PROG_ETYPE_NOSUPP;
1579 *string = strdup(e->name);
1580 if(*string == NULL)
1581 return ENOMEM;
1582 return 0;
1585 krb5_error_code
1586 krb5_string_to_enctype(krb5_context context,
1587 const char *string,
1588 krb5_enctype *etype)
1590 int i;
1591 for(i = 0; i < num_etypes; i++)
1592 if(strcasecmp(etypes[i].name, string) == 0){
1593 *etype = etypes[i].type;
1594 return 0;
1596 return KRB5_PROG_ETYPE_NOSUPP;
1599 krb5_error_code
1600 krb5_enctype_to_keytype(krb5_context context,
1601 krb5_enctype etype,
1602 krb5_keytype *keytype)
1604 struct encryption_type *e = _find_enctype(etype);
1605 if(e == NULL)
1606 return KRB5_PROG_ETYPE_NOSUPP;
1607 *keytype = e->keytype->type; /* XXX */
1608 return 0;
1611 #if 0
1612 krb5_error_code
1613 krb5_keytype_to_enctype(krb5_context context,
1614 krb5_keytype keytype,
1615 krb5_enctype *etype)
1617 struct key_type *kt = _find_keytype(keytype);
1618 krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
1619 if(kt == NULL)
1620 return KRB5_PROG_KEYTYPE_NOSUPP;
1621 *etype = kt->best_etype;
1622 return 0;
1624 #endif
1626 krb5_error_code
1627 krb5_keytype_to_enctypes (krb5_context context,
1628 krb5_keytype keytype,
1629 unsigned *len,
1630 int **val)
1632 int i;
1633 unsigned n = 0;
1634 int *ret;
1636 for (i = num_etypes - 1; i >= 0; --i) {
1637 if (etypes[i].keytype->type == keytype
1638 && !(etypes[i].flags & F_PSEUDO))
1639 ++n;
1641 ret = malloc(n * sizeof(int));
1642 if (ret == NULL && n != 0)
1643 return ENOMEM;
1644 n = 0;
1645 for (i = num_etypes - 1; i >= 0; --i) {
1646 if (etypes[i].keytype->type == keytype
1647 && !(etypes[i].flags & F_PSEUDO))
1648 ret[n++] = etypes[i].type;
1650 *len = n;
1651 *val = ret;
1652 return 0;
1656 * First take the configured list of etypes for `keytype' if available,
1657 * else, do `krb5_keytype_to_enctypes'.
1660 krb5_error_code
1661 krb5_keytype_to_enctypes_default (krb5_context context,
1662 krb5_keytype keytype,
1663 unsigned *len,
1664 int **val)
1666 int i, n;
1667 int *ret;
1669 if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
1670 return krb5_keytype_to_enctypes (context, keytype, len, val);
1672 for (n = 0; context->etypes_des[n]; ++n)
1674 ret = malloc (n * sizeof(*ret));
1675 if (ret == NULL && n != 0)
1676 return ENOMEM;
1677 for (i = 0; i < n; ++i)
1678 ret[i] = context->etypes_des[i];
1679 *len = n;
1680 *val = ret;
1681 return 0;
1684 krb5_error_code
1685 krb5_enctype_valid(krb5_context context,
1686 krb5_enctype etype)
1688 return _find_enctype(etype) != NULL;
1691 /* if two enctypes have compatible keys */
1692 krb5_boolean
1693 krb5_enctypes_compatible_keys(krb5_context context,
1694 krb5_enctype etype1,
1695 krb5_enctype etype2)
1697 struct encryption_type *e1 = _find_enctype(etype1);
1698 struct encryption_type *e2 = _find_enctype(etype2);
1699 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
1702 static krb5_boolean
1703 derived_crypto(krb5_context context,
1704 krb5_crypto crypto)
1706 return (crypto->et->flags & F_DERIVED) != 0;
1710 #define CHECKSUMSIZE(C) ((C)->checksumsize)
1711 #define CHECKSUMTYPE(C) ((C)->type)
1713 static krb5_error_code
1714 encrypt_internal_derived(krb5_context context,
1715 krb5_crypto crypto,
1716 unsigned usage,
1717 void *data,
1718 size_t len,
1719 krb5_data *result)
1721 size_t sz, block_sz, checksum_sz;
1722 Checksum cksum;
1723 unsigned char *p, *q;
1724 krb5_error_code ret;
1725 struct key_data *dkey;
1726 struct encryption_type *et = crypto->et;
1728 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1730 sz = et->confoundersize + /* 4 - length */ len;
1731 block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
1732 p = calloc(1, block_sz + checksum_sz);
1733 if(p == NULL)
1734 return ENOMEM;
1736 q = p;
1737 krb5_generate_random_block(q, et->confoundersize); /* XXX */
1738 q += et->confoundersize;
1739 memcpy(q, data, len);
1741 ret = create_checksum(context,
1742 crypto,
1743 INTEGRITY_USAGE(usage),
1746 block_sz,
1747 &cksum);
1748 if(ret == 0 && cksum.checksum.length != checksum_sz)
1749 ret = KRB5_CRYPTO_INTERNAL;
1750 if(ret) {
1751 memset(p, 0, block_sz + checksum_sz);
1752 free(p);
1753 return ret;
1755 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
1756 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1757 if(ret) {
1758 memset(p, 0, block_sz + checksum_sz);
1759 free(p);
1760 return ret;
1762 ret = _key_schedule(context, dkey);
1763 if(ret) {
1764 memset(p, 0, block_sz);
1765 free(p);
1766 return ret;
1768 #ifdef CRYPTO_DEBUG
1769 krb5_crypto_debug(context, 1, block_sz, dkey->key);
1770 #endif
1771 (*et->encrypt)(dkey, p, block_sz, 1);
1772 result->data = p;
1773 result->length = block_sz + checksum_sz;
1774 return 0;
1777 static krb5_error_code
1778 encrypt_internal(krb5_context context,
1779 krb5_crypto crypto,
1780 void *data,
1781 size_t len,
1782 krb5_data *result)
1784 size_t sz, block_sz, checksum_sz;
1785 Checksum cksum;
1786 unsigned char *p, *q;
1787 krb5_error_code ret;
1788 struct encryption_type *et = crypto->et;
1790 checksum_sz = CHECKSUMSIZE(et->cksumtype);
1792 sz = et->confoundersize + checksum_sz + len;
1793 block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
1794 p = calloc(1, block_sz);
1795 if(p == NULL)
1796 return ENOMEM;
1798 q = p;
1799 krb5_generate_random_block(q, et->confoundersize); /* XXX */
1800 q += et->confoundersize;
1801 memset(q, 0, checksum_sz);
1802 q += checksum_sz;
1803 memcpy(q, data, len);
1805 ret = create_checksum(context,
1806 NULL,
1808 CHECKSUMTYPE(et->cksumtype),
1810 block_sz,
1811 &cksum);
1812 if(ret == 0 && cksum.checksum.length != checksum_sz) {
1813 free_Checksum (&cksum);
1814 ret = KRB5_CRYPTO_INTERNAL;
1816 if(ret) {
1817 memset(p, 0, block_sz);
1818 free(p);
1819 free_Checksum(&cksum);
1820 return ret;
1822 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
1823 free_Checksum(&cksum);
1824 ret = _key_schedule(context, &crypto->key);
1825 if(ret) {
1826 memset(p, 0, block_sz);
1827 free(p);
1828 return ret;
1830 #ifdef CRYPTO_DEBUG
1831 krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
1832 #endif
1833 (*et->encrypt)(&crypto->key, p, block_sz, 1);
1834 result->data = p;
1835 result->length = block_sz;
1836 return 0;
1839 static krb5_error_code
1840 decrypt_internal_derived(krb5_context context,
1841 krb5_crypto crypto,
1842 unsigned usage,
1843 void *data,
1844 size_t len,
1845 krb5_data *result)
1847 size_t checksum_sz;
1848 Checksum cksum;
1849 unsigned char *p;
1850 krb5_error_code ret;
1851 struct key_data *dkey;
1852 struct encryption_type *et = crypto->et;
1853 unsigned long l;
1855 p = malloc(len);
1856 if(len != 0 && p == NULL)
1857 return ENOMEM;
1858 memcpy(p, data, len);
1860 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1861 len -= checksum_sz;
1863 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1864 if(ret) {
1865 free(p);
1866 return ret;
1868 ret = _key_schedule(context, dkey);
1869 if(ret) {
1870 free(p);
1871 return ret;
1873 #ifdef CRYPTO_DEBUG
1874 krb5_crypto_debug(context, 0, len, dkey->key);
1875 #endif
1876 (*et->encrypt)(dkey, p, len, 0);
1878 cksum.checksum.data = p + len;
1879 cksum.checksum.length = checksum_sz;
1880 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1882 ret = verify_checksum(context,
1883 crypto,
1884 INTEGRITY_USAGE(usage),
1886 len,
1887 &cksum);
1888 if(ret) {
1889 free(p);
1890 return ret;
1892 l = len - et->confoundersize;
1893 memmove(p, p + et->confoundersize, l);
1894 result->data = realloc(p, l);
1895 if(p == NULL) {
1896 free(p);
1897 return ENOMEM;
1899 result->length = l;
1900 return 0;
1903 static krb5_error_code
1904 decrypt_internal(krb5_context context,
1905 krb5_crypto crypto,
1906 void *data,
1907 size_t len,
1908 krb5_data *result)
1910 krb5_error_code ret;
1911 unsigned char *p;
1912 Checksum cksum;
1913 size_t checksum_sz, l;
1914 struct encryption_type *et = crypto->et;
1916 checksum_sz = CHECKSUMSIZE(et->cksumtype);
1917 p = malloc(len);
1918 if(len != 0 && p == NULL)
1919 return ENOMEM;
1920 memcpy(p, data, len);
1922 ret = _key_schedule(context, &crypto->key);
1923 if(ret) {
1924 free(p);
1925 return ret;
1927 #ifdef CRYPTO_DEBUG
1928 krb5_crypto_debug(context, 0, len, crypto->key.key);
1929 #endif
1930 (*et->encrypt)(&crypto->key, p, len, 0);
1931 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1932 if(ret) {
1933 free(p);
1934 return ret;
1936 memset(p + et->confoundersize, 0, checksum_sz);
1937 cksum.cksumtype = CHECKSUMTYPE(et->cksumtype);
1938 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
1939 free_Checksum(&cksum);
1940 if(ret) {
1941 free(p);
1942 return ret;
1944 l = len - et->confoundersize - checksum_sz;
1945 memmove(p, p + et->confoundersize + checksum_sz, l);
1946 result->data = realloc(p, l);
1947 if(result->data == NULL) {
1948 free(p);
1949 return ENOMEM;
1951 result->length = l;
1952 return 0;
1955 krb5_error_code
1956 krb5_encrypt(krb5_context context,
1957 krb5_crypto crypto,
1958 unsigned usage,
1959 void *data,
1960 size_t len,
1961 krb5_data *result)
1963 if(derived_crypto(context, crypto))
1964 return encrypt_internal_derived(context, crypto, usage,
1965 data, len, result);
1966 else
1967 return encrypt_internal(context, crypto, data, len, result);
1970 krb5_error_code
1971 krb5_encrypt_EncryptedData(krb5_context context,
1972 krb5_crypto crypto,
1973 unsigned usage,
1974 void *data,
1975 size_t len,
1976 int kvno,
1977 EncryptedData *result)
1979 result->etype = CRYPTO_ETYPE(crypto);
1980 if(kvno){
1981 ALLOC(result->kvno, 1);
1982 *result->kvno = kvno;
1983 }else
1984 result->kvno = NULL;
1985 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
1988 krb5_error_code
1989 krb5_decrypt(krb5_context context,
1990 krb5_crypto crypto,
1991 unsigned usage,
1992 void *data,
1993 size_t len,
1994 krb5_data *result)
1996 if(derived_crypto(context, crypto))
1997 return decrypt_internal_derived(context, crypto, usage,
1998 data, len, result);
1999 else
2000 return decrypt_internal(context, crypto, data, len, result);
2003 krb5_error_code
2004 krb5_decrypt_EncryptedData(krb5_context context,
2005 krb5_crypto crypto,
2006 unsigned usage,
2007 EncryptedData *e,
2008 krb5_data *result)
2010 return krb5_decrypt(context, crypto, usage,
2011 e->cipher.data, e->cipher.length, result);
2014 /************************************************************
2016 ************************************************************/
2018 void
2019 krb5_generate_random_block(void *buf, size_t len)
2021 des_cblock key, out;
2022 static des_cblock counter;
2023 static des_key_schedule schedule;
2024 int i;
2025 static int initialized = 0;
2027 if(!initialized) {
2028 des_new_random_key(&key);
2029 des_set_key(&key, schedule);
2030 memset(&key, 0, sizeof(key));
2031 des_new_random_key(&counter);
2033 while(len > 0) {
2034 des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT);
2035 for(i = 7; i >=0; i--)
2036 if(counter[i]++)
2037 break;
2038 memcpy(buf, out, min(len, sizeof(out)));
2039 len -= min(len, sizeof(out));
2040 buf = (char*)buf + sizeof(out);
2044 static void
2045 DES3_postproc(krb5_context context,
2046 unsigned char *k, size_t len, struct key_data *key)
2048 unsigned char x[24];
2049 int i, j;
2051 memset(x, 0, sizeof(x));
2052 for (i = 0; i < 3; ++i) {
2053 unsigned char foo;
2055 for (j = 0; j < 7; ++j) {
2056 unsigned char b = k[7 * i + j];
2058 x[8 * i + j] = b;
2060 foo = 0;
2061 for (j = 6; j >= 0; --j) {
2062 foo |= k[7 * i + j] & 1;
2063 foo <<= 1;
2065 x[8 * i + 7] = foo;
2067 k = key->key->keyvalue.data;
2068 memcpy(k, x, 24);
2069 memset(x, 0, sizeof(x));
2070 if (key->schedule) {
2071 krb5_free_data(context, key->schedule);
2072 key->schedule = NULL;
2074 des_set_odd_parity((des_cblock*)k);
2075 des_set_odd_parity((des_cblock*)(k + 8));
2076 des_set_odd_parity((des_cblock*)(k + 16));
2079 static krb5_error_code
2080 derive_key(krb5_context context,
2081 struct encryption_type *et,
2082 struct key_data *key,
2083 void *constant,
2084 size_t len)
2086 unsigned char *k;
2087 unsigned int nblocks = 0, i;
2088 krb5_error_code ret = 0;
2090 struct key_type *kt = et->keytype;
2091 ret = _key_schedule(context, key);
2092 if(ret)
2093 return ret;
2094 if(et->blocksize * 8 < kt->bits ||
2095 len != et->blocksize) {
2096 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
2097 k = malloc(nblocks * et->blocksize);
2098 if(k == NULL)
2099 return ENOMEM;
2100 _krb5_n_fold(constant, len, k, et->blocksize);
2101 for(i = 0; i < nblocks; i++) {
2102 if(i > 0)
2103 memcpy(k + i * et->blocksize,
2104 k + (i - 1) * et->blocksize,
2105 et->blocksize);
2106 (*et->encrypt)(key, k + i * et->blocksize, et->blocksize, 1);
2108 } else {
2109 void *c = malloc(len);
2110 size_t res_len = (kt->bits + 7) / 8;
2112 if(len != 0 && c == NULL)
2113 return ENOMEM;
2114 memcpy(c, constant, len);
2115 (*et->encrypt)(key, c, len, 1);
2116 k = malloc(res_len);
2117 if(res_len != 0 && k == NULL)
2118 return ENOMEM;
2119 _krb5_n_fold(c, len, k, res_len);
2120 free(c);
2123 /* XXX keytype dependent post-processing */
2124 switch(kt->type) {
2125 case KEYTYPE_DES3:
2126 DES3_postproc(context, k, nblocks * et->blocksize, key);
2127 break;
2128 default:
2129 krb5_warnx(context, "derive_key() called with unknown keytype (%u)",
2130 kt->type);
2131 ret = KRB5_CRYPTO_INTERNAL;
2132 break;
2134 memset(k, 0, nblocks * et->blocksize);
2135 free(k);
2136 return ret;
2139 static struct key_data *
2140 _new_derived_key(krb5_crypto crypto, unsigned usage)
2142 struct key_usage *d = crypto->key_usage;
2143 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
2144 if(d == NULL)
2145 return NULL;
2146 crypto->key_usage = d;
2147 d += crypto->num_key_usage++;
2148 memset(d, 0, sizeof(*d));
2149 d->usage = usage;
2150 return &d->key;
2153 static krb5_error_code
2154 _get_derived_key(krb5_context context,
2155 krb5_crypto crypto,
2156 unsigned usage,
2157 struct key_data **key)
2159 int i;
2160 struct key_data *d;
2161 unsigned char constant[5];
2163 for(i = 0; i < crypto->num_key_usage; i++)
2164 if(crypto->key_usage[i].usage == usage) {
2165 *key = &crypto->key_usage[i].key;
2166 return 0;
2168 d = _new_derived_key(crypto, usage);
2169 if(d == NULL)
2170 return ENOMEM;
2171 krb5_copy_keyblock(context, crypto->key.key, &d->key);
2172 _krb5_put_int(constant, usage, 5);
2173 derive_key(context, crypto->et, d, constant, sizeof(constant));
2174 *key = d;
2175 return 0;
2179 krb5_error_code
2180 krb5_crypto_init(krb5_context context,
2181 krb5_keyblock *key,
2182 krb5_enctype etype,
2183 krb5_crypto *crypto)
2185 krb5_error_code ret;
2186 ALLOC(*crypto, 1);
2187 if(*crypto == NULL)
2188 return ENOMEM;
2189 if(etype == ETYPE_NULL)
2190 etype = key->keytype;
2191 (*crypto)->et = _find_enctype(etype);
2192 if((*crypto)->et == NULL) {
2193 free(*crypto);
2194 return KRB5_PROG_ETYPE_NOSUPP;
2196 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2197 if(ret) {
2198 free(*crypto);
2199 return ret;
2201 (*crypto)->key.schedule = NULL;
2202 (*crypto)->num_key_usage = 0;
2203 (*crypto)->key_usage = NULL;
2204 return 0;
2207 static void
2208 free_key_data(krb5_context context, struct key_data *key)
2210 krb5_free_keyblock(context, key->key);
2211 if(key->schedule) {
2212 memset(key->schedule->data, 0, key->schedule->length);
2213 krb5_free_data(context, key->schedule);
2217 static void
2218 free_key_usage(krb5_context context, struct key_usage *ku)
2220 free_key_data(context, &ku->key);
2223 krb5_error_code
2224 krb5_crypto_destroy(krb5_context context,
2225 krb5_crypto crypto)
2227 int i;
2229 for(i = 0; i < crypto->num_key_usage; i++)
2230 free_key_usage(context, &crypto->key_usage[i]);
2231 free(crypto->key_usage);
2232 free_key_data(context, &crypto->key);
2233 free (crypto);
2234 return 0;
2237 krb5_error_code
2238 krb5_string_to_key_derived(krb5_context context,
2239 const void *str,
2240 size_t len,
2241 krb5_enctype etype,
2242 krb5_keyblock *key)
2244 struct encryption_type *et = _find_enctype(etype);
2245 krb5_error_code ret;
2246 struct key_data kd;
2247 u_char *tmp;
2249 if(et == NULL)
2250 return KRB5_PROG_ETYPE_NOSUPP;
2251 ALLOC(kd.key, 1);
2252 kd.key->keytype = etype;
2253 tmp = malloc (et->keytype->bits / 8);
2254 _krb5_n_fold(str, len, tmp, et->keytype->bits / 8);
2255 krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
2256 kd.schedule = NULL;
2257 DES3_postproc (context, tmp, et->keytype->bits / 8, &kd); /* XXX */
2258 ret = derive_key(context,
2260 &kd,
2261 "kerberos", /* XXX well known constant */
2262 strlen("kerberos"));
2263 ret = krb5_copy_keyblock_contents(context, kd.key, key);
2264 free_key_data(context, &kd);
2265 return ret;
2269 * Return the size of an encrypted packet of length `data_len'
2272 size_t
2273 krb5_get_wrapped_length (krb5_context context,
2274 krb5_crypto crypto,
2275 size_t data_len)
2277 struct encryption_type *et = crypto->et;
2278 size_t blocksize = et->blocksize;
2279 size_t res;
2281 res = (data_len + blocksize - 1) / blocksize * blocksize;
2282 res = res + et->confoundersize + et->cksumtype->checksumsize;
2283 return res;
2286 #ifdef CRYPTO_DEBUG
2288 static krb5_error_code
2289 krb5_get_keyid(krb5_context context,
2290 krb5_keyblock *key,
2291 u_int32_t *keyid)
2293 MD5_CTX md5;
2294 unsigned char tmp[16];
2296 MD5Init (&md5);
2297 MD5Update (&md5, key->keyvalue.data, key->keyvalue.length);
2298 MD5Final (tmp, &md5);
2299 *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
2300 return 0;
2303 static void
2304 krb5_crypto_debug(krb5_context context,
2305 int encrypt,
2306 size_t len,
2307 krb5_keyblock *key)
2309 u_int32_t keyid;
2310 char *kt;
2311 krb5_get_keyid(context, key, &keyid);
2312 krb5_enctype_to_string(context, key->keytype, &kt);
2313 krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
2314 encrypt ? "encrypting" : "decrypting",
2315 (unsigned long)len,
2316 keyid,
2317 kt);
2318 free(kt);
2321 #endif /* CRYPTO_DEBUG */