allow compiling out weak enctype support
[heimdal.git] / lib / krb5 / crypto.c
blob8d17467971a3566a1aab5dfed771a3f16a8ab10b
1 /*
2 * Copyright (c) 1997 - 2008 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 #define KRB5_DEPRECATED
36 #include "krb5_locl.h"
37 #include <pkinit_asn1.h>
39 #ifndef HEIMDAL_SMALLER
40 #define DES3_OLD_ENCTYPE 1
41 #endif
44 #ifdef HAVE_OPENSSL /* XXX forward decl for hcrypto glue */
45 const EVP_CIPHER * _krb5_EVP_hcrypto_aes_128_cts(void);
46 const EVP_CIPHER * _krb5_EVP_hcrypto_aes_256_cts(void);
47 #define EVP_hcrypto_aes_128_cts _krb5_EVP_hcrypto_aes_128_cts
48 #define EVP_hcrypto_aes_256_cts _krb5_EVP_hcrypto_aes_256_cts
49 #else
50 #include <hcrypto/evp-hcrypto.h>
51 #endif
53 struct key_data {
54 krb5_keyblock *key;
55 krb5_data *schedule;
58 struct key_usage {
59 unsigned usage;
60 struct key_data key;
63 struct krb5_crypto_data {
64 struct encryption_type *et;
65 struct key_data key;
66 int num_key_usage;
67 struct key_usage *key_usage;
70 #define CRYPTO_ETYPE(C) ((C)->et->type)
72 /* bits for `flags' below */
73 #define F_KEYED 1 /* checksum is keyed */
74 #define F_CPROOF 2 /* checksum is collision proof */
75 #define F_DERIVED 4 /* uses derived keys */
76 #define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
77 #define F_PSEUDO 16 /* not a real protocol type */
78 #define F_SPECIAL 32 /* backwards */
79 #define F_DISABLED 64 /* enctype/checksum disabled */
81 struct salt_type {
82 krb5_salttype type;
83 const char *name;
84 krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
85 krb5_salt, krb5_data, krb5_keyblock*);
88 struct key_type {
89 krb5_keytype type; /* XXX */
90 const char *name;
91 size_t bits;
92 size_t size;
93 size_t schedule_size;
94 void (*random_key)(krb5_context, krb5_keyblock*);
95 void (*schedule)(krb5_context, struct key_type *, struct key_data *);
96 struct salt_type *string_to_key;
97 void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
98 void (*cleanup)(krb5_context, struct key_data *);
99 const EVP_CIPHER *(*evp)(void);
102 struct checksum_type {
103 krb5_cksumtype type;
104 const char *name;
105 size_t blocksize;
106 size_t checksumsize;
107 unsigned flags;
108 krb5_enctype (*checksum)(krb5_context context,
109 struct key_data *key,
110 const void *buf, size_t len,
111 unsigned usage,
112 Checksum *csum);
113 krb5_error_code (*verify)(krb5_context context,
114 struct key_data *key,
115 const void *buf, size_t len,
116 unsigned usage,
117 Checksum *csum);
120 struct encryption_type {
121 krb5_enctype type;
122 const char *name;
123 size_t blocksize;
124 size_t padsize;
125 size_t confoundersize;
126 struct key_type *keytype;
127 struct checksum_type *checksum;
128 struct checksum_type *keyed_checksum;
129 unsigned flags;
130 krb5_error_code (*encrypt)(krb5_context context,
131 struct key_data *key,
132 void *data, size_t len,
133 krb5_boolean encryptp,
134 int usage,
135 void *ivec);
136 size_t prf_length;
137 krb5_error_code (*prf)(krb5_context,
138 krb5_crypto, const krb5_data *, krb5_data *);
141 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
142 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
143 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
145 static struct checksum_type *_find_checksum(krb5_cksumtype type);
146 static struct encryption_type *_find_enctype(krb5_enctype type);
147 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
148 unsigned, struct key_data**);
149 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
150 static krb5_error_code derive_key(krb5_context context,
151 struct encryption_type *et,
152 struct key_data *key,
153 const void *constant,
154 size_t len);
155 static krb5_error_code hmac(krb5_context context,
156 struct checksum_type *cm,
157 const void *data,
158 size_t len,
159 unsigned usage,
160 struct key_data *keyblock,
161 Checksum *result);
162 static void free_key_data(krb5_context,
163 struct key_data *,
164 struct encryption_type *);
165 static void free_key_schedule(krb5_context,
166 struct key_data *,
167 struct encryption_type *);
168 static krb5_error_code usage2arcfour (krb5_context, unsigned *);
169 static void xor (DES_cblock *, const unsigned char *);
171 /************************************************************
173 ************************************************************/
175 struct evp_schedule {
176 EVP_CIPHER_CTX ectx;
177 EVP_CIPHER_CTX dctx;
181 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
183 #ifdef HEIM_WEAK_CRYPTO
184 static void
185 krb5_DES_random_key(krb5_context context,
186 krb5_keyblock *key)
188 DES_cblock *k = key->keyvalue.data;
189 do {
190 krb5_generate_random_block(k, sizeof(DES_cblock));
191 DES_set_odd_parity(k);
192 } while(DES_is_weak_key(k));
195 static void
196 krb5_DES_schedule_old(krb5_context context,
197 struct key_type *kt,
198 struct key_data *key)
200 DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
203 #ifdef ENABLE_AFS_STRING_TO_KEY
205 /* This defines the Andrew string_to_key function. It accepts a password
206 * string as input and converts it via a one-way encryption algorithm to a DES
207 * encryption key. It is compatible with the original Andrew authentication
208 * service password database.
212 * Short passwords, i.e 8 characters or less.
214 static void
215 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
216 krb5_data cell,
217 DES_cblock *key)
219 char password[8+1]; /* crypt is limited to 8 chars anyway */
220 int i;
222 for(i = 0; i < 8; i++) {
223 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
224 ((i < cell.length) ?
225 tolower(((unsigned char*)cell.data)[i]) : 0);
226 password[i] = c ? c : 'X';
228 password[8] = '\0';
230 memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
232 /* parity is inserted into the LSB so left shift each byte up one
233 bit. This allows ascii characters with a zero MSB to retain as
234 much significance as possible. */
235 for (i = 0; i < sizeof(DES_cblock); i++)
236 ((unsigned char*)key)[i] <<= 1;
237 DES_set_odd_parity (key);
241 * Long passwords, i.e 9 characters or more.
243 static void
244 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
245 krb5_data cell,
246 DES_cblock *key)
248 DES_key_schedule schedule;
249 DES_cblock temp_key;
250 DES_cblock ivec;
251 char password[512];
252 size_t passlen;
254 memcpy(password, pw.data, min(pw.length, sizeof(password)));
255 if(pw.length < sizeof(password)) {
256 int len = min(cell.length, sizeof(password) - pw.length);
257 int i;
259 memcpy(password + pw.length, cell.data, len);
260 for (i = pw.length; i < pw.length + len; ++i)
261 password[i] = tolower((unsigned char)password[i]);
263 passlen = min(sizeof(password), pw.length + cell.length);
264 memcpy(&ivec, "kerberos", 8);
265 memcpy(&temp_key, "kerberos", 8);
266 DES_set_odd_parity (&temp_key);
267 DES_set_key_unchecked (&temp_key, &schedule);
268 DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
270 memcpy(&temp_key, &ivec, 8);
271 DES_set_odd_parity (&temp_key);
272 DES_set_key_unchecked (&temp_key, &schedule);
273 DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
274 memset(&schedule, 0, sizeof(schedule));
275 memset(&temp_key, 0, sizeof(temp_key));
276 memset(&ivec, 0, sizeof(ivec));
277 memset(password, 0, sizeof(password));
279 DES_set_odd_parity (key);
282 static krb5_error_code
283 DES_AFS3_string_to_key(krb5_context context,
284 krb5_enctype enctype,
285 krb5_data password,
286 krb5_salt salt,
287 krb5_data opaque,
288 krb5_keyblock *key)
290 DES_cblock tmp;
291 if(password.length > 8)
292 krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
293 else
294 krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
295 key->keytype = enctype;
296 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
297 memset(&key, 0, sizeof(key));
298 return 0;
300 #endif /* ENABLE_AFS_STRING_TO_KEY */
302 static void
303 DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
305 DES_key_schedule schedule;
306 int i;
307 int reverse = 0;
308 unsigned char *p;
310 unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
311 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
312 memset(key, 0, 8);
314 p = (unsigned char*)key;
315 for (i = 0; i < length; i++) {
316 unsigned char tmp = data[i];
317 if (!reverse)
318 *p++ ^= (tmp << 1);
319 else
320 *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
321 if((i % 8) == 7)
322 reverse = !reverse;
324 DES_set_odd_parity(key);
325 if(DES_is_weak_key(key))
326 (*key)[7] ^= 0xF0;
327 DES_set_key_unchecked(key, &schedule);
328 DES_cbc_cksum((void*)data, key, length, &schedule, key);
329 memset(&schedule, 0, sizeof(schedule));
330 DES_set_odd_parity(key);
331 if(DES_is_weak_key(key))
332 (*key)[7] ^= 0xF0;
335 static krb5_error_code
336 krb5_DES_string_to_key(krb5_context context,
337 krb5_enctype enctype,
338 krb5_data password,
339 krb5_salt salt,
340 krb5_data opaque,
341 krb5_keyblock *key)
343 unsigned char *s;
344 size_t len;
345 DES_cblock tmp;
347 #ifdef ENABLE_AFS_STRING_TO_KEY
348 if (opaque.length == 1) {
349 unsigned long v;
350 _krb5_get_int(opaque.data, &v, 1);
351 if (v == 1)
352 return DES_AFS3_string_to_key(context, enctype, password,
353 salt, opaque, key);
355 #endif
357 len = password.length + salt.saltvalue.length;
358 s = malloc(len);
359 if(len > 0 && s == NULL) {
360 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
361 return ENOMEM;
363 memcpy(s, password.data, password.length);
364 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
365 DES_string_to_key_int(s, len, &tmp);
366 key->keytype = enctype;
367 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
368 memset(&tmp, 0, sizeof(tmp));
369 memset(s, 0, len);
370 free(s);
371 return 0;
374 static void
375 krb5_DES_random_to_key(krb5_context context,
376 krb5_keyblock *key,
377 const void *data,
378 size_t size)
380 DES_cblock *k = key->keyvalue.data;
381 memcpy(k, data, key->keyvalue.length);
382 DES_set_odd_parity(k);
383 if(DES_is_weak_key(k))
384 xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
386 #endif
392 static void
393 DES3_random_key(krb5_context context,
394 krb5_keyblock *key)
396 DES_cblock *k = key->keyvalue.data;
397 do {
398 krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
399 DES_set_odd_parity(&k[0]);
400 DES_set_odd_parity(&k[1]);
401 DES_set_odd_parity(&k[2]);
402 } while(DES_is_weak_key(&k[0]) ||
403 DES_is_weak_key(&k[1]) ||
404 DES_is_weak_key(&k[2]));
408 * A = A xor B. A & B are 8 bytes.
411 static void
412 xor (DES_cblock *key, const unsigned char *b)
414 unsigned char *a = (unsigned char*)key;
415 a[0] ^= b[0];
416 a[1] ^= b[1];
417 a[2] ^= b[2];
418 a[3] ^= b[3];
419 a[4] ^= b[4];
420 a[5] ^= b[5];
421 a[6] ^= b[6];
422 a[7] ^= b[7];
425 #ifdef DES3_OLD_ENCTYPE
426 static krb5_error_code
427 DES3_string_to_key(krb5_context context,
428 krb5_enctype enctype,
429 krb5_data password,
430 krb5_salt salt,
431 krb5_data opaque,
432 krb5_keyblock *key)
434 char *str;
435 size_t len;
436 unsigned char tmp[24];
437 DES_cblock keys[3];
438 krb5_error_code ret;
440 len = password.length + salt.saltvalue.length;
441 str = malloc(len);
442 if(len != 0 && str == NULL) {
443 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
444 return ENOMEM;
446 memcpy(str, password.data, password.length);
447 memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
449 DES_cblock ivec;
450 DES_key_schedule s[3];
451 int i;
453 ret = _krb5_n_fold(str, len, tmp, 24);
454 if (ret) {
455 memset(str, 0, len);
456 free(str);
457 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
458 return ret;
461 for(i = 0; i < 3; i++){
462 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
463 DES_set_odd_parity(keys + i);
464 if(DES_is_weak_key(keys + i))
465 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
466 DES_set_key_unchecked(keys + i, &s[i]);
468 memset(&ivec, 0, sizeof(ivec));
469 DES_ede3_cbc_encrypt(tmp,
470 tmp, sizeof(tmp),
471 &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
472 memset(s, 0, sizeof(s));
473 memset(&ivec, 0, sizeof(ivec));
474 for(i = 0; i < 3; i++){
475 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
476 DES_set_odd_parity(keys + i);
477 if(DES_is_weak_key(keys + i))
478 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
480 memset(tmp, 0, sizeof(tmp));
482 key->keytype = enctype;
483 krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
484 memset(keys, 0, sizeof(keys));
485 memset(str, 0, len);
486 free(str);
487 return 0;
489 #endif
491 static krb5_error_code
492 DES3_string_to_key_derived(krb5_context context,
493 krb5_enctype enctype,
494 krb5_data password,
495 krb5_salt salt,
496 krb5_data opaque,
497 krb5_keyblock *key)
499 krb5_error_code ret;
500 size_t len = password.length + salt.saltvalue.length;
501 char *s;
503 s = malloc(len);
504 if(len != 0 && s == NULL) {
505 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
506 return ENOMEM;
508 memcpy(s, password.data, password.length);
509 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
510 ret = krb5_string_to_key_derived(context,
512 len,
513 enctype,
514 key);
515 memset(s, 0, len);
516 free(s);
517 return ret;
520 static void
521 DES3_random_to_key(krb5_context context,
522 krb5_keyblock *key,
523 const void *data,
524 size_t size)
526 unsigned char *x = key->keyvalue.data;
527 const u_char *q = data;
528 DES_cblock *k;
529 int i, j;
531 memset(x, 0, sizeof(x));
532 for (i = 0; i < 3; ++i) {
533 unsigned char foo;
534 for (j = 0; j < 7; ++j) {
535 unsigned char b = q[7 * i + j];
537 x[8 * i + j] = b;
539 foo = 0;
540 for (j = 6; j >= 0; --j) {
541 foo |= q[7 * i + j] & 1;
542 foo <<= 1;
544 x[8 * i + 7] = foo;
546 k = key->keyvalue.data;
547 for (i = 0; i < 3; i++) {
548 DES_set_odd_parity(&k[i]);
549 if(DES_is_weak_key(&k[i]))
550 xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
555 * ARCFOUR
558 static krb5_error_code
559 ARCFOUR_string_to_key(krb5_context context,
560 krb5_enctype enctype,
561 krb5_data password,
562 krb5_salt salt,
563 krb5_data opaque,
564 krb5_keyblock *key)
566 krb5_error_code ret;
567 uint16_t *s = NULL;
568 size_t len, i;
569 EVP_MD_CTX *m;
571 m = EVP_MD_CTX_create();
572 if (m == NULL) {
573 ret = ENOMEM;
574 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
575 goto out;
578 EVP_DigestInit_ex(m, EVP_md4(), NULL);
580 ret = wind_utf8ucs2_length(password.data, &len);
581 if (ret) {
582 krb5_set_error_message (context, ret,
583 N_("Password not an UCS2 string", ""));
584 goto out;
587 s = malloc (len * sizeof(s[0]));
588 if (len != 0 && s == NULL) {
589 krb5_set_error_message (context, ENOMEM,
590 N_("malloc: out of memory", ""));
591 ret = ENOMEM;
592 goto out;
595 ret = wind_utf8ucs2(password.data, s, &len);
596 if (ret) {
597 krb5_set_error_message (context, ret,
598 N_("Password not an UCS2 string", ""));
599 goto out;
602 /* LE encoding */
603 for (i = 0; i < len; i++) {
604 unsigned char p;
605 p = (s[i] & 0xff);
606 EVP_DigestUpdate (m, &p, 1);
607 p = (s[i] >> 8) & 0xff;
608 EVP_DigestUpdate (m, &p, 1);
611 key->keytype = enctype;
612 ret = krb5_data_alloc (&key->keyvalue, 16);
613 if (ret) {
614 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
615 goto out;
617 EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
619 out:
620 EVP_MD_CTX_destroy(m);
621 if (s)
622 memset (s, 0, len);
623 free (s);
624 return ret;
628 * AES
631 int _krb5_AES_string_to_default_iterator = 4096;
633 static krb5_error_code
634 AES_string_to_key(krb5_context context,
635 krb5_enctype enctype,
636 krb5_data password,
637 krb5_salt salt,
638 krb5_data opaque,
639 krb5_keyblock *key)
641 krb5_error_code ret;
642 uint32_t iter;
643 struct encryption_type *et;
644 struct key_data kd;
646 if (opaque.length == 0)
647 iter = _krb5_AES_string_to_default_iterator;
648 else if (opaque.length == 4) {
649 unsigned long v;
650 _krb5_get_int(opaque.data, &v, 4);
651 iter = ((uint32_t)v);
652 } else
653 return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
655 et = _find_enctype(enctype);
656 if (et == NULL)
657 return KRB5_PROG_KEYTYPE_NOSUPP;
659 kd.schedule = NULL;
660 ALLOC(kd.key, 1);
661 if(kd.key == NULL) {
662 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
663 return ENOMEM;
665 kd.key->keytype = enctype;
666 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
667 if (ret) {
668 krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
669 return ret;
672 ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
673 salt.saltvalue.data, salt.saltvalue.length,
674 iter,
675 et->keytype->size, kd.key->keyvalue.data);
676 if (ret != 1) {
677 free_key_data(context, &kd, et);
678 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
679 "Error calculating s2k");
680 return KRB5_PROG_KEYTYPE_NOSUPP;
683 ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
684 if (ret == 0)
685 ret = krb5_copy_keyblock_contents(context, kd.key, key);
686 free_key_data(context, &kd, et);
688 return ret;
691 static void
692 evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd)
694 struct evp_schedule *key = kd->schedule->data;
695 const EVP_CIPHER *c = (*kt->evp)();
697 EVP_CIPHER_CTX_init(&key->ectx);
698 EVP_CIPHER_CTX_init(&key->dctx);
700 EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
701 EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
704 static void
705 evp_cleanup(krb5_context context, struct key_data *kd)
707 struct evp_schedule *key = kd->schedule->data;
708 EVP_CIPHER_CTX_cleanup(&key->ectx);
709 EVP_CIPHER_CTX_cleanup(&key->dctx);
716 #ifdef HEIM_WEAK_CRYPTO
717 static struct salt_type des_salt[] = {
719 KRB5_PW_SALT,
720 "pw-salt",
721 krb5_DES_string_to_key
723 #ifdef ENABLE_AFS_STRING_TO_KEY
725 KRB5_AFS3_SALT,
726 "afs3-salt",
727 DES_AFS3_string_to_key
729 #endif
730 { 0 }
732 #endif
734 #ifdef DES3_OLD_ENCTYPE
735 static struct salt_type des3_salt[] = {
737 KRB5_PW_SALT,
738 "pw-salt",
739 DES3_string_to_key
741 { 0 }
743 #endif
745 static struct salt_type des3_salt_derived[] = {
747 KRB5_PW_SALT,
748 "pw-salt",
749 DES3_string_to_key_derived
751 { 0 }
754 static struct salt_type AES_salt[] = {
756 KRB5_PW_SALT,
757 "pw-salt",
758 AES_string_to_key
760 { 0 }
763 static struct salt_type arcfour_salt[] = {
765 KRB5_PW_SALT,
766 "pw-salt",
767 ARCFOUR_string_to_key
769 { 0 }
776 static struct key_type keytype_null = {
777 KEYTYPE_NULL,
778 "null",
782 NULL,
783 NULL,
784 NULL
787 #ifdef HEIM_WEAK_CRYPTO
788 static struct key_type keytype_des_old = {
789 KEYTYPE_DES,
790 "des-old",
793 sizeof(DES_key_schedule),
794 krb5_DES_random_key,
795 krb5_DES_schedule_old,
796 des_salt,
797 krb5_DES_random_to_key
800 static struct key_type keytype_des = {
801 KEYTYPE_DES,
802 "des",
805 sizeof(struct evp_schedule),
806 krb5_DES_random_key,
807 evp_schedule,
808 des_salt,
809 krb5_DES_random_to_key,
810 evp_cleanup,
811 EVP_des_cbc
813 #endif /* HEIM_WEAK_CRYPTO */
815 #ifdef DES3_OLD_ENCTYPE
816 static struct key_type keytype_des3 = {
817 KEYTYPE_DES3,
818 "des3",
819 168,
821 sizeof(struct evp_schedule),
822 DES3_random_key,
823 evp_schedule,
824 des3_salt,
825 DES3_random_to_key,
826 evp_cleanup,
827 EVP_des_ede3_cbc
829 #endif
831 static struct key_type keytype_des3_derived = {
832 KEYTYPE_DES3,
833 "des3",
834 168,
836 sizeof(struct evp_schedule),
837 DES3_random_key,
838 evp_schedule,
839 des3_salt_derived,
840 DES3_random_to_key,
841 evp_cleanup,
842 EVP_des_ede3_cbc
845 static struct key_type keytype_aes128 = {
846 KEYTYPE_AES128,
847 "aes-128",
848 128,
850 sizeof(struct evp_schedule),
851 NULL,
852 evp_schedule,
853 AES_salt,
854 NULL,
855 evp_cleanup,
856 EVP_hcrypto_aes_128_cts
859 static struct key_type keytype_aes256 = {
860 KEYTYPE_AES256,
861 "aes-256",
862 256,
864 sizeof(struct evp_schedule),
865 NULL,
866 evp_schedule,
867 AES_salt,
868 NULL,
869 evp_cleanup,
870 EVP_hcrypto_aes_256_cts
873 static struct key_type keytype_arcfour = {
874 KEYTYPE_ARCFOUR,
875 "arcfour",
876 128,
878 sizeof(struct evp_schedule),
879 NULL,
880 evp_schedule,
881 arcfour_salt,
882 NULL,
883 evp_cleanup,
884 EVP_rc4
887 krb5_error_code KRB5_LIB_FUNCTION
888 krb5_salttype_to_string (krb5_context context,
889 krb5_enctype etype,
890 krb5_salttype stype,
891 char **string)
893 struct encryption_type *e;
894 struct salt_type *st;
896 e = _find_enctype (etype);
897 if (e == NULL) {
898 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
899 "encryption type %d not supported",
900 etype);
901 return KRB5_PROG_ETYPE_NOSUPP;
903 for (st = e->keytype->string_to_key; st && st->type; st++) {
904 if (st->type == stype) {
905 *string = strdup (st->name);
906 if (*string == NULL) {
907 krb5_set_error_message (context, ENOMEM,
908 N_("malloc: out of memory", ""));
909 return ENOMEM;
911 return 0;
914 krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
915 "salttype %d not supported", stype);
916 return HEIM_ERR_SALTTYPE_NOSUPP;
919 krb5_error_code KRB5_LIB_FUNCTION
920 krb5_string_to_salttype (krb5_context context,
921 krb5_enctype etype,
922 const char *string,
923 krb5_salttype *salttype)
925 struct encryption_type *e;
926 struct salt_type *st;
928 e = _find_enctype (etype);
929 if (e == NULL) {
930 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
931 N_("encryption type %d not supported", ""),
932 etype);
933 return KRB5_PROG_ETYPE_NOSUPP;
935 for (st = e->keytype->string_to_key; st && st->type; st++) {
936 if (strcasecmp (st->name, string) == 0) {
937 *salttype = st->type;
938 return 0;
941 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
942 N_("salttype %s not supported", ""), string);
943 return HEIM_ERR_SALTTYPE_NOSUPP;
946 krb5_error_code KRB5_LIB_FUNCTION
947 krb5_get_pw_salt(krb5_context context,
948 krb5_const_principal principal,
949 krb5_salt *salt)
951 size_t len;
952 int i;
953 krb5_error_code ret;
954 char *p;
956 salt->salttype = KRB5_PW_SALT;
957 len = strlen(principal->realm);
958 for (i = 0; i < principal->name.name_string.len; ++i)
959 len += strlen(principal->name.name_string.val[i]);
960 ret = krb5_data_alloc (&salt->saltvalue, len);
961 if (ret)
962 return ret;
963 p = salt->saltvalue.data;
964 memcpy (p, principal->realm, strlen(principal->realm));
965 p += strlen(principal->realm);
966 for (i = 0; i < principal->name.name_string.len; ++i) {
967 memcpy (p,
968 principal->name.name_string.val[i],
969 strlen(principal->name.name_string.val[i]));
970 p += strlen(principal->name.name_string.val[i]);
972 return 0;
975 krb5_error_code KRB5_LIB_FUNCTION
976 krb5_free_salt(krb5_context context,
977 krb5_salt salt)
979 krb5_data_free(&salt.saltvalue);
980 return 0;
983 krb5_error_code KRB5_LIB_FUNCTION
984 krb5_string_to_key_data (krb5_context context,
985 krb5_enctype enctype,
986 krb5_data password,
987 krb5_principal principal,
988 krb5_keyblock *key)
990 krb5_error_code ret;
991 krb5_salt salt;
993 ret = krb5_get_pw_salt(context, principal, &salt);
994 if(ret)
995 return ret;
996 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
997 krb5_free_salt(context, salt);
998 return ret;
1001 krb5_error_code KRB5_LIB_FUNCTION
1002 krb5_string_to_key (krb5_context context,
1003 krb5_enctype enctype,
1004 const char *password,
1005 krb5_principal principal,
1006 krb5_keyblock *key)
1008 krb5_data pw;
1009 pw.data = rk_UNCONST(password);
1010 pw.length = strlen(password);
1011 return krb5_string_to_key_data(context, enctype, pw, principal, key);
1014 krb5_error_code KRB5_LIB_FUNCTION
1015 krb5_string_to_key_data_salt (krb5_context context,
1016 krb5_enctype enctype,
1017 krb5_data password,
1018 krb5_salt salt,
1019 krb5_keyblock *key)
1021 krb5_data opaque;
1022 krb5_data_zero(&opaque);
1023 return krb5_string_to_key_data_salt_opaque(context, enctype, password,
1024 salt, opaque, key);
1028 * Do a string -> key for encryption type `enctype' operation on
1029 * `password' (with salt `salt' and the enctype specific data string
1030 * `opaque'), returning the resulting key in `key'
1033 krb5_error_code KRB5_LIB_FUNCTION
1034 krb5_string_to_key_data_salt_opaque (krb5_context context,
1035 krb5_enctype enctype,
1036 krb5_data password,
1037 krb5_salt salt,
1038 krb5_data opaque,
1039 krb5_keyblock *key)
1041 struct encryption_type *et =_find_enctype(enctype);
1042 struct salt_type *st;
1043 if(et == NULL) {
1044 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1045 N_("encryption type %d not supported", ""),
1046 enctype);
1047 return KRB5_PROG_ETYPE_NOSUPP;
1049 for(st = et->keytype->string_to_key; st && st->type; st++)
1050 if(st->type == salt.salttype)
1051 return (*st->string_to_key)(context, enctype, password,
1052 salt, opaque, key);
1053 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
1054 N_("salt type %d not supported", ""),
1055 salt.salttype);
1056 return HEIM_ERR_SALTTYPE_NOSUPP;
1060 * Do a string -> key for encryption type `enctype' operation on the
1061 * string `password' (with salt `salt'), returning the resulting key
1062 * in `key'
1065 krb5_error_code KRB5_LIB_FUNCTION
1066 krb5_string_to_key_salt (krb5_context context,
1067 krb5_enctype enctype,
1068 const char *password,
1069 krb5_salt salt,
1070 krb5_keyblock *key)
1072 krb5_data pw;
1073 pw.data = rk_UNCONST(password);
1074 pw.length = strlen(password);
1075 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
1078 krb5_error_code KRB5_LIB_FUNCTION
1079 krb5_string_to_key_salt_opaque (krb5_context context,
1080 krb5_enctype enctype,
1081 const char *password,
1082 krb5_salt salt,
1083 krb5_data opaque,
1084 krb5_keyblock *key)
1086 krb5_data pw;
1087 pw.data = rk_UNCONST(password);
1088 pw.length = strlen(password);
1089 return krb5_string_to_key_data_salt_opaque(context, enctype,
1090 pw, salt, opaque, key);
1093 krb5_error_code KRB5_LIB_FUNCTION
1094 krb5_enctype_keysize(krb5_context context,
1095 krb5_enctype type,
1096 size_t *keysize)
1098 struct encryption_type *et = _find_enctype(type);
1099 if(et == NULL) {
1100 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1101 N_("encryption type %d not supported", ""),
1102 type);
1103 return KRB5_PROG_ETYPE_NOSUPP;
1105 *keysize = et->keytype->size;
1106 return 0;
1109 krb5_error_code KRB5_LIB_FUNCTION
1110 krb5_enctype_keybits(krb5_context context,
1111 krb5_enctype type,
1112 size_t *keybits)
1114 struct encryption_type *et = _find_enctype(type);
1115 if(et == NULL) {
1116 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1117 "encryption type %d not supported",
1118 type);
1119 return KRB5_PROG_ETYPE_NOSUPP;
1121 *keybits = et->keytype->bits;
1122 return 0;
1125 krb5_error_code KRB5_LIB_FUNCTION
1126 krb5_generate_random_keyblock(krb5_context context,
1127 krb5_enctype type,
1128 krb5_keyblock *key)
1130 krb5_error_code ret;
1131 struct encryption_type *et = _find_enctype(type);
1132 if(et == NULL) {
1133 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1134 N_("encryption type %d not supported", ""),
1135 type);
1136 return KRB5_PROG_ETYPE_NOSUPP;
1138 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
1139 if(ret)
1140 return ret;
1141 key->keytype = type;
1142 if(et->keytype->random_key)
1143 (*et->keytype->random_key)(context, key);
1144 else
1145 krb5_generate_random_block(key->keyvalue.data,
1146 key->keyvalue.length);
1147 return 0;
1150 static krb5_error_code
1151 _key_schedule(krb5_context context,
1152 struct key_data *key)
1154 krb5_error_code ret;
1155 struct encryption_type *et = _find_enctype(key->key->keytype);
1156 struct key_type *kt;
1158 if (et == NULL) {
1159 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
1160 N_("encryption type %d not supported", ""),
1161 key->key->keytype);
1162 return KRB5_PROG_ETYPE_NOSUPP;
1165 kt = et->keytype;
1167 if(kt->schedule == NULL)
1168 return 0;
1169 if (key->schedule != NULL)
1170 return 0;
1171 ALLOC(key->schedule, 1);
1172 if(key->schedule == NULL) {
1173 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1174 return ENOMEM;
1176 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
1177 if(ret) {
1178 free(key->schedule);
1179 key->schedule = NULL;
1180 return ret;
1182 (*kt->schedule)(context, kt, key);
1183 return 0;
1186 /************************************************************
1188 ************************************************************/
1190 static krb5_error_code
1191 NONE_checksum(krb5_context context,
1192 struct key_data *key,
1193 const void *data,
1194 size_t len,
1195 unsigned usage,
1196 Checksum *C)
1198 return 0;
1201 #if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO)
1203 static krb5_error_code
1204 des_checksum(krb5_context context,
1205 const EVP_MD *evp_md,
1206 struct key_data *key,
1207 const void *data,
1208 size_t len,
1209 Checksum *cksum)
1211 struct evp_schedule *ctx = key->schedule->data;
1212 EVP_MD_CTX *m;
1213 DES_cblock ivec;
1214 unsigned char *p = cksum->checksum.data;
1216 krb5_generate_random_block(p, 8);
1218 m = EVP_MD_CTX_create();
1219 if (m == NULL) {
1220 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1221 return ENOMEM;
1224 EVP_DigestInit_ex(m, evp_md, NULL);
1225 EVP_DigestUpdate(m, p, 8);
1226 EVP_DigestUpdate(m, data, len);
1227 EVP_DigestFinal_ex (m, p + 8, NULL);
1228 EVP_MD_CTX_destroy(m);
1229 memset (&ivec, 0, sizeof(ivec));
1230 EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
1231 EVP_Cipher(&ctx->ectx, p, p, 24);
1233 return 0;
1236 static krb5_error_code
1237 des_verify(krb5_context context,
1238 const EVP_MD *evp_md,
1239 struct key_data *key,
1240 const void *data,
1241 size_t len,
1242 Checksum *C)
1244 struct evp_schedule *ctx = key->schedule->data;
1245 EVP_MD_CTX *m;
1246 unsigned char tmp[24];
1247 unsigned char res[16];
1248 DES_cblock ivec;
1249 krb5_error_code ret = 0;
1251 m = EVP_MD_CTX_create();
1252 if (m == NULL) {
1253 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1254 return ENOMEM;
1257 memset(&ivec, 0, sizeof(ivec));
1258 EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
1259 EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
1261 EVP_DigestInit_ex(m, evp_md, NULL);
1262 EVP_DigestUpdate(m, tmp, 8); /* confounder */
1263 EVP_DigestUpdate(m, data, len);
1264 EVP_DigestFinal_ex (m, res, NULL);
1265 EVP_MD_CTX_destroy(m);
1266 if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) {
1267 krb5_clear_error_message (context);
1268 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1270 memset(tmp, 0, sizeof(tmp));
1271 memset(res, 0, sizeof(res));
1272 return ret;
1275 #endif
1277 #ifdef HEIM_WEAK_CRYPTO
1279 static krb5_error_code
1280 CRC32_checksum(krb5_context context,
1281 struct key_data *key,
1282 const void *data,
1283 size_t len,
1284 unsigned usage,
1285 Checksum *C)
1287 uint32_t crc;
1288 unsigned char *r = C->checksum.data;
1289 _krb5_crc_init_table ();
1290 crc = _krb5_crc_update (data, len, 0);
1291 r[0] = crc & 0xff;
1292 r[1] = (crc >> 8) & 0xff;
1293 r[2] = (crc >> 16) & 0xff;
1294 r[3] = (crc >> 24) & 0xff;
1295 return 0;
1298 static krb5_error_code
1299 RSA_MD4_checksum(krb5_context context,
1300 struct key_data *key,
1301 const void *data,
1302 size_t len,
1303 unsigned usage,
1304 Checksum *C)
1306 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
1307 krb5_abortx(context, "md4 checksum failed");
1308 return 0;
1311 static krb5_error_code
1312 RSA_MD4_DES_checksum(krb5_context context,
1313 struct key_data *key,
1314 const void *data,
1315 size_t len,
1316 unsigned usage,
1317 Checksum *cksum)
1319 return des_checksum(context, EVP_md4(), key, data, len, cksum);
1322 static krb5_error_code
1323 RSA_MD4_DES_verify(krb5_context context,
1324 struct key_data *key,
1325 const void *data,
1326 size_t len,
1327 unsigned usage,
1328 Checksum *C)
1330 return des_verify(context, EVP_md5(), key, data, len, C);
1333 static krb5_error_code
1334 RSA_MD5_DES_checksum(krb5_context context,
1335 struct key_data *key,
1336 const void *data,
1337 size_t len,
1338 unsigned usage,
1339 Checksum *C)
1341 return des_checksum(context, EVP_md5(), key, data, len, C);
1344 static krb5_error_code
1345 RSA_MD5_DES_verify(krb5_context context,
1346 struct key_data *key,
1347 const void *data,
1348 size_t len,
1349 unsigned usage,
1350 Checksum *C)
1352 return des_verify(context, EVP_md5(), key, data, len, C);
1355 #endif /* HEIM_WEAK_CRYPTO */
1357 #ifdef DES3_OLD_ENCTYPE
1358 static krb5_error_code
1359 RSA_MD5_DES3_checksum(krb5_context context,
1360 struct key_data *key,
1361 const void *data,
1362 size_t len,
1363 unsigned usage,
1364 Checksum *C)
1366 return des_checksum(context, EVP_md5(), key, data, len, C);
1369 static krb5_error_code
1370 RSA_MD5_DES3_verify(krb5_context context,
1371 struct key_data *key,
1372 const void *data,
1373 size_t len,
1374 unsigned usage,
1375 Checksum *C)
1377 return des_verify(context, EVP_md5(), key, data, len, C);
1379 #endif
1381 static krb5_error_code
1382 SHA1_checksum(krb5_context context,
1383 struct key_data *key,
1384 const void *data,
1385 size_t len,
1386 unsigned usage,
1387 Checksum *C)
1389 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
1390 krb5_abortx(context, "sha1 checksum failed");
1391 return 0;
1394 /* HMAC according to RFC2104 */
1395 static krb5_error_code
1396 hmac(krb5_context context,
1397 struct checksum_type *cm,
1398 const void *data,
1399 size_t len,
1400 unsigned usage,
1401 struct key_data *keyblock,
1402 Checksum *result)
1404 unsigned char *ipad, *opad;
1405 unsigned char *key;
1406 size_t key_len;
1407 int i;
1409 ipad = malloc(cm->blocksize + len);
1410 if (ipad == NULL)
1411 return ENOMEM;
1412 opad = malloc(cm->blocksize + cm->checksumsize);
1413 if (opad == NULL) {
1414 free(ipad);
1415 return ENOMEM;
1417 memset(ipad, 0x36, cm->blocksize);
1418 memset(opad, 0x5c, cm->blocksize);
1420 if(keyblock->key->keyvalue.length > cm->blocksize){
1421 (*cm->checksum)(context,
1422 keyblock,
1423 keyblock->key->keyvalue.data,
1424 keyblock->key->keyvalue.length,
1425 usage,
1426 result);
1427 key = result->checksum.data;
1428 key_len = result->checksum.length;
1429 } else {
1430 key = keyblock->key->keyvalue.data;
1431 key_len = keyblock->key->keyvalue.length;
1433 for(i = 0; i < key_len; i++){
1434 ipad[i] ^= key[i];
1435 opad[i] ^= key[i];
1437 memcpy(ipad + cm->blocksize, data, len);
1438 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1439 usage, result);
1440 memcpy(opad + cm->blocksize, result->checksum.data,
1441 result->checksum.length);
1442 (*cm->checksum)(context, keyblock, opad,
1443 cm->blocksize + cm->checksumsize, usage, result);
1444 memset(ipad, 0, cm->blocksize + len);
1445 free(ipad);
1446 memset(opad, 0, cm->blocksize + cm->checksumsize);
1447 free(opad);
1449 return 0;
1452 krb5_error_code KRB5_LIB_FUNCTION
1453 krb5_hmac(krb5_context context,
1454 krb5_cksumtype cktype,
1455 const void *data,
1456 size_t len,
1457 unsigned usage,
1458 krb5_keyblock *key,
1459 Checksum *result)
1461 struct checksum_type *c = _find_checksum(cktype);
1462 struct key_data kd;
1463 krb5_error_code ret;
1465 if (c == NULL) {
1466 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1467 N_("checksum type %d not supported", ""),
1468 cktype);
1469 return KRB5_PROG_SUMTYPE_NOSUPP;
1472 kd.key = key;
1473 kd.schedule = NULL;
1475 ret = hmac(context, c, data, len, usage, &kd, result);
1477 if (kd.schedule)
1478 krb5_free_data(context, kd.schedule);
1480 return ret;
1483 static krb5_error_code
1484 SP_HMAC_SHA1_checksum(krb5_context context,
1485 struct key_data *key,
1486 const void *data,
1487 size_t len,
1488 unsigned usage,
1489 Checksum *result)
1491 struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1492 Checksum res;
1493 char sha1_data[20];
1494 krb5_error_code ret;
1496 res.checksum.data = sha1_data;
1497 res.checksum.length = sizeof(sha1_data);
1499 ret = hmac(context, c, data, len, usage, key, &res);
1500 if (ret)
1501 krb5_abortx(context, "hmac failed");
1502 memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
1503 return 0;
1507 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1510 static krb5_error_code
1511 HMAC_MD5_checksum(krb5_context context,
1512 struct key_data *key,
1513 const void *data,
1514 size_t len,
1515 unsigned usage,
1516 Checksum *result)
1518 EVP_MD_CTX *m;
1519 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1520 const char signature[] = "signaturekey";
1521 Checksum ksign_c;
1522 struct key_data ksign;
1523 krb5_keyblock kb;
1524 unsigned char t[4];
1525 unsigned char tmp[16];
1526 unsigned char ksign_c_data[16];
1527 krb5_error_code ret;
1529 m = EVP_MD_CTX_create();
1530 if (m == NULL) {
1531 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1532 return ENOMEM;
1534 ksign_c.checksum.length = sizeof(ksign_c_data);
1535 ksign_c.checksum.data = ksign_c_data;
1536 ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1537 if (ret) {
1538 EVP_MD_CTX_destroy(m);
1539 return ret;
1541 ksign.key = &kb;
1542 kb.keyvalue = ksign_c.checksum;
1543 EVP_DigestInit_ex(m, EVP_md5(), NULL);
1544 t[0] = (usage >> 0) & 0xFF;
1545 t[1] = (usage >> 8) & 0xFF;
1546 t[2] = (usage >> 16) & 0xFF;
1547 t[3] = (usage >> 24) & 0xFF;
1548 EVP_DigestUpdate(m, t, 4);
1549 EVP_DigestUpdate(m, data, len);
1550 EVP_DigestFinal_ex (m, tmp, NULL);
1551 EVP_MD_CTX_destroy(m);
1553 ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1554 if (ret)
1555 return ret;
1556 return 0;
1559 static struct checksum_type checksum_none = {
1560 CKSUMTYPE_NONE,
1561 "none",
1565 NONE_checksum,
1566 NULL
1568 #ifdef HEIM_WEAK_CRYPTO
1569 static struct checksum_type checksum_crc32 = {
1570 CKSUMTYPE_CRC32,
1571 "crc32",
1575 CRC32_checksum,
1576 NULL
1578 static struct checksum_type checksum_rsa_md4 = {
1579 CKSUMTYPE_RSA_MD4,
1580 "rsa-md4",
1583 F_CPROOF,
1584 RSA_MD4_checksum,
1585 NULL
1587 static struct checksum_type checksum_rsa_md4_des = {
1588 CKSUMTYPE_RSA_MD4_DES,
1589 "rsa-md4-des",
1592 F_KEYED | F_CPROOF | F_VARIANT,
1593 RSA_MD4_DES_checksum,
1594 RSA_MD4_DES_verify
1596 static struct checksum_type checksum_rsa_md5_des = {
1597 CKSUMTYPE_RSA_MD5_DES,
1598 "rsa-md5-des",
1601 F_KEYED | F_CPROOF | F_VARIANT,
1602 RSA_MD5_DES_checksum,
1603 RSA_MD5_DES_verify
1605 #endif /* HEIM_WEAK_CRYPTO */
1607 #if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO)
1609 static krb5_error_code
1610 RSA_MD5_checksum(krb5_context context,
1611 struct key_data *key,
1612 const void *data,
1613 size_t len,
1614 unsigned usage,
1615 Checksum *C)
1617 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
1618 krb5_abortx(context, "md5 checksum failed");
1619 return 0;
1622 static struct checksum_type checksum_rsa_md5 = {
1623 CKSUMTYPE_RSA_MD5,
1624 "rsa-md5",
1627 F_CPROOF,
1628 RSA_MD5_checksum,
1629 NULL
1631 #endif
1633 #ifdef DES3_OLD_ENCTYPE
1634 static struct checksum_type checksum_rsa_md5_des3 = {
1635 CKSUMTYPE_RSA_MD5_DES3,
1636 "rsa-md5-des3",
1639 F_KEYED | F_CPROOF | F_VARIANT,
1640 RSA_MD5_DES3_checksum,
1641 RSA_MD5_DES3_verify
1643 #endif
1644 static struct checksum_type checksum_sha1 = {
1645 CKSUMTYPE_SHA1,
1646 "sha1",
1649 F_CPROOF,
1650 SHA1_checksum,
1651 NULL
1653 static struct checksum_type checksum_hmac_sha1_des3 = {
1654 CKSUMTYPE_HMAC_SHA1_DES3,
1655 "hmac-sha1-des3",
1658 F_KEYED | F_CPROOF | F_DERIVED,
1659 SP_HMAC_SHA1_checksum,
1660 NULL
1663 static struct checksum_type checksum_hmac_sha1_aes128 = {
1664 CKSUMTYPE_HMAC_SHA1_96_AES_128,
1665 "hmac-sha1-96-aes128",
1668 F_KEYED | F_CPROOF | F_DERIVED,
1669 SP_HMAC_SHA1_checksum,
1670 NULL
1673 static struct checksum_type checksum_hmac_sha1_aes256 = {
1674 CKSUMTYPE_HMAC_SHA1_96_AES_256,
1675 "hmac-sha1-96-aes256",
1678 F_KEYED | F_CPROOF | F_DERIVED,
1679 SP_HMAC_SHA1_checksum,
1680 NULL
1683 static struct checksum_type checksum_hmac_md5 = {
1684 CKSUMTYPE_HMAC_MD5,
1685 "hmac-md5",
1688 F_KEYED | F_CPROOF,
1689 HMAC_MD5_checksum,
1690 NULL
1693 static struct checksum_type *checksum_types[] = {
1694 &checksum_none,
1695 #ifdef HEIM_WEAK_CRYPTO
1696 &checksum_crc32,
1697 &checksum_rsa_md4,
1698 &checksum_rsa_md4_des,
1699 &checksum_rsa_md5,
1700 &checksum_rsa_md5_des,
1701 #endif
1702 #ifdef DES3_OLD_ENCTYPE
1703 &checksum_rsa_md5_des3,
1704 #endif
1705 &checksum_sha1,
1706 &checksum_hmac_sha1_des3,
1707 &checksum_hmac_sha1_aes128,
1708 &checksum_hmac_sha1_aes256,
1709 &checksum_hmac_md5
1712 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1714 static struct checksum_type *
1715 _find_checksum(krb5_cksumtype type)
1717 int i;
1718 for(i = 0; i < num_checksums; i++)
1719 if(checksum_types[i]->type == type)
1720 return checksum_types[i];
1721 return NULL;
1724 static krb5_error_code
1725 get_checksum_key(krb5_context context,
1726 krb5_crypto crypto,
1727 unsigned usage, /* not krb5_key_usage */
1728 struct checksum_type *ct,
1729 struct key_data **key)
1731 krb5_error_code ret = 0;
1733 if(ct->flags & F_DERIVED)
1734 ret = _get_derived_key(context, crypto, usage, key);
1735 else if(ct->flags & F_VARIANT) {
1736 int i;
1738 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1739 if(*key == NULL) {
1740 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1741 return ENOMEM;
1743 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1744 if(ret)
1745 return ret;
1746 for(i = 0; i < (*key)->key->keyvalue.length; i++)
1747 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1748 } else {
1749 *key = &crypto->key;
1751 if(ret == 0)
1752 ret = _key_schedule(context, *key);
1753 return ret;
1756 static krb5_error_code
1757 create_checksum (krb5_context context,
1758 struct checksum_type *ct,
1759 krb5_crypto crypto,
1760 unsigned usage,
1761 void *data,
1762 size_t len,
1763 Checksum *result)
1765 krb5_error_code ret;
1766 struct key_data *dkey;
1767 int keyed_checksum;
1769 if (ct->flags & F_DISABLED) {
1770 krb5_clear_error_message (context);
1771 return KRB5_PROG_SUMTYPE_NOSUPP;
1773 keyed_checksum = (ct->flags & F_KEYED) != 0;
1774 if(keyed_checksum && crypto == NULL) {
1775 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1776 N_("Checksum type %s is keyed but no "
1777 "crypto context (key) was passed in", ""),
1778 ct->name);
1779 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1781 if(keyed_checksum) {
1782 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1783 if (ret)
1784 return ret;
1785 } else
1786 dkey = NULL;
1787 result->cksumtype = ct->type;
1788 ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1789 if (ret)
1790 return (ret);
1791 return (*ct->checksum)(context, dkey, data, len, usage, result);
1794 static int
1795 arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
1797 return (ct->type == CKSUMTYPE_HMAC_MD5) &&
1798 (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
1801 krb5_error_code KRB5_LIB_FUNCTION
1802 krb5_create_checksum(krb5_context context,
1803 krb5_crypto crypto,
1804 krb5_key_usage usage,
1805 int type,
1806 void *data,
1807 size_t len,
1808 Checksum *result)
1810 struct checksum_type *ct = NULL;
1811 unsigned keyusage;
1813 /* type 0 -> pick from crypto */
1814 if (type) {
1815 ct = _find_checksum(type);
1816 } else if (crypto) {
1817 ct = crypto->et->keyed_checksum;
1818 if (ct == NULL)
1819 ct = crypto->et->checksum;
1822 if(ct == NULL) {
1823 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1824 N_("checksum type %d not supported", ""),
1825 type);
1826 return KRB5_PROG_SUMTYPE_NOSUPP;
1829 if (arcfour_checksum_p(ct, crypto)) {
1830 keyusage = usage;
1831 usage2arcfour(context, &keyusage);
1832 } else
1833 keyusage = CHECKSUM_USAGE(usage);
1835 return create_checksum(context, ct, crypto, keyusage,
1836 data, len, result);
1839 static krb5_error_code
1840 verify_checksum(krb5_context context,
1841 krb5_crypto crypto,
1842 unsigned usage, /* not krb5_key_usage */
1843 void *data,
1844 size_t len,
1845 Checksum *cksum)
1847 krb5_error_code ret;
1848 struct key_data *dkey;
1849 int keyed_checksum;
1850 Checksum c;
1851 struct checksum_type *ct;
1853 ct = _find_checksum(cksum->cksumtype);
1854 if (ct == NULL || (ct->flags & F_DISABLED)) {
1855 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1856 N_("checksum type %d not supported", ""),
1857 cksum->cksumtype);
1858 return KRB5_PROG_SUMTYPE_NOSUPP;
1860 if(ct->checksumsize != cksum->checksum.length) {
1861 krb5_clear_error_message (context);
1862 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1864 keyed_checksum = (ct->flags & F_KEYED) != 0;
1865 if(keyed_checksum) {
1866 struct checksum_type *kct;
1867 if (crypto == NULL) {
1868 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1869 N_("Checksum type %s is keyed but no "
1870 "crypto context (key) was passed in", ""),
1871 ct->name);
1872 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1874 kct = crypto->et->keyed_checksum;
1875 if (kct != NULL && kct->type != ct->type) {
1876 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1877 N_("Checksum type %s is keyed, but "
1878 "the key type %s passed didnt have that checksum "
1879 "type as the keyed type", ""),
1880 ct->name, crypto->et->name);
1881 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1884 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1885 if (ret)
1886 return ret;
1887 } else
1888 dkey = NULL;
1889 if(ct->verify)
1890 return (*ct->verify)(context, dkey, data, len, usage, cksum);
1892 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1893 if (ret)
1894 return ret;
1896 ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
1897 if (ret) {
1898 krb5_data_free(&c.checksum);
1899 return ret;
1902 if(c.checksum.length != cksum->checksum.length ||
1903 ct_memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
1904 krb5_clear_error_message (context);
1905 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1906 } else {
1907 ret = 0;
1909 krb5_data_free (&c.checksum);
1910 return ret;
1913 krb5_error_code KRB5_LIB_FUNCTION
1914 krb5_verify_checksum(krb5_context context,
1915 krb5_crypto crypto,
1916 krb5_key_usage usage,
1917 void *data,
1918 size_t len,
1919 Checksum *cksum)
1921 struct checksum_type *ct;
1922 unsigned keyusage;
1924 ct = _find_checksum(cksum->cksumtype);
1925 if(ct == NULL) {
1926 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1927 N_("checksum type %d not supported", ""),
1928 cksum->cksumtype);
1929 return KRB5_PROG_SUMTYPE_NOSUPP;
1932 if (arcfour_checksum_p(ct, crypto)) {
1933 keyusage = usage;
1934 usage2arcfour(context, &keyusage);
1935 } else
1936 keyusage = CHECKSUM_USAGE(usage);
1938 return verify_checksum(context, crypto, keyusage,
1939 data, len, cksum);
1942 krb5_error_code KRB5_LIB_FUNCTION
1943 krb5_crypto_get_checksum_type(krb5_context context,
1944 krb5_crypto crypto,
1945 krb5_cksumtype *type)
1947 struct checksum_type *ct = NULL;
1949 if (crypto != NULL) {
1950 ct = crypto->et->keyed_checksum;
1951 if (ct == NULL)
1952 ct = crypto->et->checksum;
1955 if (ct == NULL) {
1956 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1957 N_("checksum type not found", ""));
1958 return KRB5_PROG_SUMTYPE_NOSUPP;
1961 *type = ct->type;
1963 return 0;
1967 krb5_error_code KRB5_LIB_FUNCTION
1968 krb5_checksumsize(krb5_context context,
1969 krb5_cksumtype type,
1970 size_t *size)
1972 struct checksum_type *ct = _find_checksum(type);
1973 if(ct == NULL) {
1974 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1975 N_("checksum type %d not supported", ""),
1976 type);
1977 return KRB5_PROG_SUMTYPE_NOSUPP;
1979 *size = ct->checksumsize;
1980 return 0;
1983 krb5_boolean KRB5_LIB_FUNCTION
1984 krb5_checksum_is_keyed(krb5_context context,
1985 krb5_cksumtype type)
1987 struct checksum_type *ct = _find_checksum(type);
1988 if(ct == NULL) {
1989 if (context)
1990 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1991 N_("checksum type %d not supported", ""),
1992 type);
1993 return KRB5_PROG_SUMTYPE_NOSUPP;
1995 return ct->flags & F_KEYED;
1998 krb5_boolean KRB5_LIB_FUNCTION
1999 krb5_checksum_is_collision_proof(krb5_context context,
2000 krb5_cksumtype type)
2002 struct checksum_type *ct = _find_checksum(type);
2003 if(ct == NULL) {
2004 if (context)
2005 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2006 N_("checksum type %d not supported", ""),
2007 type);
2008 return KRB5_PROG_SUMTYPE_NOSUPP;
2010 return ct->flags & F_CPROOF;
2013 krb5_error_code KRB5_LIB_FUNCTION
2014 krb5_checksum_disable(krb5_context context,
2015 krb5_cksumtype type)
2017 struct checksum_type *ct = _find_checksum(type);
2018 if(ct == NULL) {
2019 if (context)
2020 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2021 N_("checksum type %d not supported", ""),
2022 type);
2023 return KRB5_PROG_SUMTYPE_NOSUPP;
2025 ct->flags |= F_DISABLED;
2026 return 0;
2029 /************************************************************
2031 ************************************************************/
2033 static krb5_error_code
2034 NULL_encrypt(krb5_context context,
2035 struct key_data *key,
2036 void *data,
2037 size_t len,
2038 krb5_boolean encryptp,
2039 int usage,
2040 void *ivec)
2042 return 0;
2045 static krb5_error_code
2046 evp_encrypt(krb5_context context,
2047 struct key_data *key,
2048 void *data,
2049 size_t len,
2050 krb5_boolean encryptp,
2051 int usage,
2052 void *ivec)
2054 struct evp_schedule *ctx = key->schedule->data;
2055 EVP_CIPHER_CTX *c;
2056 c = encryptp ? &ctx->ectx : &ctx->dctx;
2057 if (ivec == NULL) {
2058 /* alloca ? */
2059 size_t len = EVP_CIPHER_CTX_iv_length(c);
2060 void *loiv = malloc(len);
2061 if (loiv == NULL) {
2062 krb5_clear_error_message(context);
2063 return ENOMEM;
2065 memset(loiv, 0, len);
2066 EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
2067 free(loiv);
2068 } else
2069 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2070 EVP_Cipher(c, data, data, len);
2071 return 0;
2074 #ifdef HEIM_WEAK_CRYPTO
2075 static krb5_error_code
2076 evp_des_encrypt_null_ivec(krb5_context context,
2077 struct key_data *key,
2078 void *data,
2079 size_t len,
2080 krb5_boolean encryptp,
2081 int usage,
2082 void *ignore_ivec)
2084 struct evp_schedule *ctx = key->schedule->data;
2085 EVP_CIPHER_CTX *c;
2086 DES_cblock ivec;
2087 memset(&ivec, 0, sizeof(ivec));
2088 c = encryptp ? &ctx->ectx : &ctx->dctx;
2089 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2090 EVP_Cipher(c, data, data, len);
2091 return 0;
2094 static krb5_error_code
2095 evp_des_encrypt_key_ivec(krb5_context context,
2096 struct key_data *key,
2097 void *data,
2098 size_t len,
2099 krb5_boolean encryptp,
2100 int usage,
2101 void *ignore_ivec)
2103 struct evp_schedule *ctx = key->schedule->data;
2104 EVP_CIPHER_CTX *c;
2105 DES_cblock ivec;
2106 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2107 c = encryptp ? &ctx->ectx : &ctx->dctx;
2108 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2109 EVP_Cipher(c, data, data, len);
2110 return 0;
2113 static krb5_error_code
2114 DES_CFB64_encrypt_null_ivec(krb5_context context,
2115 struct key_data *key,
2116 void *data,
2117 size_t len,
2118 krb5_boolean encryptp,
2119 int usage,
2120 void *ignore_ivec)
2122 DES_cblock ivec;
2123 int num = 0;
2124 DES_key_schedule *s = key->schedule->data;
2125 memset(&ivec, 0, sizeof(ivec));
2127 DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
2128 return 0;
2131 static krb5_error_code
2132 DES_PCBC_encrypt_key_ivec(krb5_context context,
2133 struct key_data *key,
2134 void *data,
2135 size_t len,
2136 krb5_boolean encryptp,
2137 int usage,
2138 void *ignore_ivec)
2140 DES_cblock ivec;
2141 DES_key_schedule *s = key->schedule->data;
2142 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2144 DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
2145 return 0;
2147 #endif
2150 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
2152 * warning: not for small children
2155 static krb5_error_code
2156 ARCFOUR_subencrypt(krb5_context context,
2157 struct key_data *key,
2158 void *data,
2159 size_t len,
2160 unsigned usage,
2161 void *ivec)
2163 EVP_CIPHER_CTX ctx;
2164 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2165 Checksum k1_c, k2_c, k3_c, cksum;
2166 struct key_data ke;
2167 krb5_keyblock kb;
2168 unsigned char t[4];
2169 unsigned char *cdata = data;
2170 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2171 krb5_error_code ret;
2173 t[0] = (usage >> 0) & 0xFF;
2174 t[1] = (usage >> 8) & 0xFF;
2175 t[2] = (usage >> 16) & 0xFF;
2176 t[3] = (usage >> 24) & 0xFF;
2178 k1_c.checksum.length = sizeof(k1_c_data);
2179 k1_c.checksum.data = k1_c_data;
2181 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2182 if (ret)
2183 krb5_abortx(context, "hmac failed");
2185 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2187 k2_c.checksum.length = sizeof(k2_c_data);
2188 k2_c.checksum.data = k2_c_data;
2190 ke.key = &kb;
2191 kb.keyvalue = k2_c.checksum;
2193 cksum.checksum.length = 16;
2194 cksum.checksum.data = data;
2196 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2197 if (ret)
2198 krb5_abortx(context, "hmac failed");
2200 ke.key = &kb;
2201 kb.keyvalue = k1_c.checksum;
2203 k3_c.checksum.length = sizeof(k3_c_data);
2204 k3_c.checksum.data = k3_c_data;
2206 ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
2207 if (ret)
2208 krb5_abortx(context, "hmac failed");
2210 EVP_CIPHER_CTX_init(&ctx);
2212 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
2213 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
2214 EVP_CIPHER_CTX_cleanup(&ctx);
2216 memset (k1_c_data, 0, sizeof(k1_c_data));
2217 memset (k2_c_data, 0, sizeof(k2_c_data));
2218 memset (k3_c_data, 0, sizeof(k3_c_data));
2219 return 0;
2222 static krb5_error_code
2223 ARCFOUR_subdecrypt(krb5_context context,
2224 struct key_data *key,
2225 void *data,
2226 size_t len,
2227 unsigned usage,
2228 void *ivec)
2230 EVP_CIPHER_CTX ctx;
2231 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2232 Checksum k1_c, k2_c, k3_c, cksum;
2233 struct key_data ke;
2234 krb5_keyblock kb;
2235 unsigned char t[4];
2236 unsigned char *cdata = data;
2237 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2238 unsigned char cksum_data[16];
2239 krb5_error_code ret;
2241 t[0] = (usage >> 0) & 0xFF;
2242 t[1] = (usage >> 8) & 0xFF;
2243 t[2] = (usage >> 16) & 0xFF;
2244 t[3] = (usage >> 24) & 0xFF;
2246 k1_c.checksum.length = sizeof(k1_c_data);
2247 k1_c.checksum.data = k1_c_data;
2249 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2250 if (ret)
2251 krb5_abortx(context, "hmac failed");
2253 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2255 k2_c.checksum.length = sizeof(k2_c_data);
2256 k2_c.checksum.data = k2_c_data;
2258 ke.key = &kb;
2259 kb.keyvalue = k1_c.checksum;
2261 k3_c.checksum.length = sizeof(k3_c_data);
2262 k3_c.checksum.data = k3_c_data;
2264 ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
2265 if (ret)
2266 krb5_abortx(context, "hmac failed");
2268 EVP_CIPHER_CTX_init(&ctx);
2269 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
2270 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
2271 EVP_CIPHER_CTX_cleanup(&ctx);
2273 ke.key = &kb;
2274 kb.keyvalue = k2_c.checksum;
2276 cksum.checksum.length = 16;
2277 cksum.checksum.data = cksum_data;
2279 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2280 if (ret)
2281 krb5_abortx(context, "hmac failed");
2283 memset (k1_c_data, 0, sizeof(k1_c_data));
2284 memset (k2_c_data, 0, sizeof(k2_c_data));
2285 memset (k3_c_data, 0, sizeof(k3_c_data));
2287 if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
2288 krb5_clear_error_message (context);
2289 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
2290 } else {
2291 return 0;
2296 * convert the usage numbers used in
2297 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2298 * draft-brezak-win2k-krb-rc4-hmac-04.txt
2301 static krb5_error_code
2302 usage2arcfour (krb5_context context, unsigned *usage)
2304 switch (*usage) {
2305 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2306 case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
2307 *usage = 8;
2308 return 0;
2309 case KRB5_KU_USAGE_SEAL : /* 22 */
2310 *usage = 13;
2311 return 0;
2312 case KRB5_KU_USAGE_SIGN : /* 23 */
2313 *usage = 15;
2314 return 0;
2315 case KRB5_KU_USAGE_SEQ: /* 24 */
2316 *usage = 0;
2317 return 0;
2318 default :
2319 return 0;
2323 static krb5_error_code
2324 ARCFOUR_encrypt(krb5_context context,
2325 struct key_data *key,
2326 void *data,
2327 size_t len,
2328 krb5_boolean encryptp,
2329 int usage,
2330 void *ivec)
2332 krb5_error_code ret;
2333 unsigned keyusage = usage;
2335 if((ret = usage2arcfour (context, &keyusage)) != 0)
2336 return ret;
2338 if (encryptp)
2339 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
2340 else
2341 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
2349 static krb5_error_code
2350 AES_PRF(krb5_context context,
2351 krb5_crypto crypto,
2352 const krb5_data *in,
2353 krb5_data *out)
2355 struct checksum_type *ct = crypto->et->checksum;
2356 krb5_error_code ret;
2357 Checksum result;
2358 krb5_keyblock *derived;
2360 result.cksumtype = ct->type;
2361 ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2362 if (ret) {
2363 krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
2364 return ret;
2367 ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2368 if (ret) {
2369 krb5_data_free(&result.checksum);
2370 return ret;
2373 if (result.checksum.length < crypto->et->blocksize)
2374 krb5_abortx(context, "internal prf error");
2376 derived = NULL;
2377 ret = krb5_derive_key(context, crypto->key.key,
2378 crypto->et->type, "prf", 3, &derived);
2379 if (ret)
2380 krb5_abortx(context, "krb5_derive_key");
2382 ret = krb5_data_alloc(out, crypto->et->blocksize);
2383 if (ret)
2384 krb5_abortx(context, "malloc failed");
2387 const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
2388 EVP_CIPHER_CTX ctx;
2390 EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
2391 EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
2392 EVP_Cipher(&ctx, out->data, result.checksum.data,
2393 crypto->et->blocksize);
2394 EVP_CIPHER_CTX_cleanup(&ctx);
2397 krb5_data_free(&result.checksum);
2398 krb5_free_keyblock(context, derived);
2400 return ret;
2404 * these should currently be in reverse preference order.
2405 * (only relevant for !F_PSEUDO) */
2407 static struct encryption_type enctype_null = {
2408 ETYPE_NULL,
2409 "null",
2413 &keytype_null,
2414 &checksum_none,
2415 NULL,
2416 F_DISABLED,
2417 NULL_encrypt,
2419 NULL
2421 static struct encryption_type enctype_arcfour_hmac_md5 = {
2422 ETYPE_ARCFOUR_HMAC_MD5,
2423 "arcfour-hmac-md5",
2427 &keytype_arcfour,
2428 &checksum_hmac_md5,
2429 NULL,
2430 F_SPECIAL,
2431 ARCFOUR_encrypt,
2433 NULL
2435 #ifdef DES3_OLD_ENCTYPE
2436 static struct encryption_type enctype_des3_cbc_md5 = {
2437 ETYPE_DES3_CBC_MD5,
2438 "des3-cbc-md5",
2442 &keytype_des3,
2443 &checksum_rsa_md5,
2444 &checksum_rsa_md5_des3,
2446 evp_encrypt,
2448 NULL
2450 #endif
2451 static struct encryption_type enctype_des3_cbc_sha1 = {
2452 ETYPE_DES3_CBC_SHA1,
2453 "des3-cbc-sha1",
2457 &keytype_des3_derived,
2458 &checksum_sha1,
2459 &checksum_hmac_sha1_des3,
2460 F_DERIVED,
2461 evp_encrypt,
2463 NULL
2465 #ifdef DES3_OLD_ENCTYPE
2466 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2467 ETYPE_OLD_DES3_CBC_SHA1,
2468 "old-des3-cbc-sha1",
2472 &keytype_des3,
2473 &checksum_sha1,
2474 &checksum_hmac_sha1_des3,
2476 evp_encrypt,
2478 NULL
2480 #endif
2481 static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2482 ETYPE_AES128_CTS_HMAC_SHA1_96,
2483 "aes128-cts-hmac-sha1-96",
2487 &keytype_aes128,
2488 &checksum_sha1,
2489 &checksum_hmac_sha1_aes128,
2490 F_DERIVED,
2491 evp_encrypt,
2493 AES_PRF
2495 static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2496 ETYPE_AES256_CTS_HMAC_SHA1_96,
2497 "aes256-cts-hmac-sha1-96",
2501 &keytype_aes256,
2502 &checksum_sha1,
2503 &checksum_hmac_sha1_aes256,
2504 F_DERIVED,
2505 evp_encrypt,
2507 AES_PRF
2509 static struct encryption_type enctype_des3_cbc_none = {
2510 ETYPE_DES3_CBC_NONE,
2511 "des3-cbc-none",
2515 &keytype_des3_derived,
2516 &checksum_none,
2517 NULL,
2518 F_PSEUDO,
2519 evp_encrypt,
2521 NULL
2523 #ifdef HEIM_WEAK_CRYPTO
2524 static struct encryption_type enctype_des_cbc_crc = {
2525 ETYPE_DES_CBC_CRC,
2526 "des-cbc-crc",
2530 &keytype_des,
2531 &checksum_crc32,
2532 NULL,
2533 F_DISABLED,
2534 evp_des_encrypt_key_ivec,
2536 NULL
2538 static struct encryption_type enctype_des_cbc_md4 = {
2539 ETYPE_DES_CBC_MD4,
2540 "des-cbc-md4",
2544 &keytype_des,
2545 &checksum_rsa_md4,
2546 &checksum_rsa_md4_des,
2547 F_DISABLED,
2548 evp_des_encrypt_null_ivec,
2550 NULL
2552 static struct encryption_type enctype_des_cbc_md5 = {
2553 ETYPE_DES_CBC_MD5,
2554 "des-cbc-md5",
2558 &keytype_des,
2559 &checksum_rsa_md5,
2560 &checksum_rsa_md5_des,
2561 F_DISABLED,
2562 evp_des_encrypt_null_ivec,
2564 NULL
2566 static struct encryption_type enctype_des_cbc_none = {
2567 ETYPE_DES_CBC_NONE,
2568 "des-cbc-none",
2572 &keytype_des,
2573 &checksum_none,
2574 NULL,
2575 F_PSEUDO|F_DISABLED,
2576 evp_des_encrypt_null_ivec,
2578 NULL
2580 static struct encryption_type enctype_des_cfb64_none = {
2581 ETYPE_DES_CFB64_NONE,
2582 "des-cfb64-none",
2586 &keytype_des_old,
2587 &checksum_none,
2588 NULL,
2589 F_PSEUDO|F_DISABLED,
2590 DES_CFB64_encrypt_null_ivec,
2592 NULL
2594 static struct encryption_type enctype_des_pcbc_none = {
2595 ETYPE_DES_PCBC_NONE,
2596 "des-pcbc-none",
2600 &keytype_des_old,
2601 &checksum_none,
2602 NULL,
2603 F_PSEUDO|F_DISABLED,
2604 DES_PCBC_encrypt_key_ivec,
2606 NULL
2608 #endif /* HEIM_WEAK_CRYPTO */
2610 static struct encryption_type *etypes[] = {
2611 &enctype_aes256_cts_hmac_sha1,
2612 &enctype_aes128_cts_hmac_sha1,
2613 &enctype_des3_cbc_sha1,
2614 &enctype_des3_cbc_none, /* used by the gss-api mech */
2615 &enctype_arcfour_hmac_md5,
2616 #ifdef DES3_OLD_ENCTYPE
2617 &enctype_des3_cbc_md5,
2618 &enctype_old_des3_cbc_sha1,
2619 #endif
2620 #ifdef HEIM_WEAK_CRYPTO
2621 &enctype_des_cbc_crc,
2622 &enctype_des_cbc_md4,
2623 &enctype_des_cbc_md5,
2624 &enctype_des_cbc_none,
2625 &enctype_des_cfb64_none,
2626 &enctype_des_pcbc_none,
2627 #endif
2628 &enctype_null
2631 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2634 static struct encryption_type *
2635 _find_enctype(krb5_enctype type)
2637 int i;
2638 for(i = 0; i < num_etypes; i++)
2639 if(etypes[i]->type == type)
2640 return etypes[i];
2641 return NULL;
2645 krb5_error_code KRB5_LIB_FUNCTION
2646 krb5_enctype_to_string(krb5_context context,
2647 krb5_enctype etype,
2648 char **string)
2650 struct encryption_type *e;
2651 e = _find_enctype(etype);
2652 if(e == NULL) {
2653 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2654 N_("encryption type %d not supported", ""),
2655 etype);
2656 *string = NULL;
2657 return KRB5_PROG_ETYPE_NOSUPP;
2659 *string = strdup(e->name);
2660 if(*string == NULL) {
2661 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2662 return ENOMEM;
2664 return 0;
2667 krb5_error_code KRB5_LIB_FUNCTION
2668 krb5_string_to_enctype(krb5_context context,
2669 const char *string,
2670 krb5_enctype *etype)
2672 int i;
2673 for(i = 0; i < num_etypes; i++)
2674 if(strcasecmp(etypes[i]->name, string) == 0){
2675 *etype = etypes[i]->type;
2676 return 0;
2678 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2679 N_("encryption type %s not supported", ""),
2680 string);
2681 return KRB5_PROG_ETYPE_NOSUPP;
2684 krb5_error_code KRB5_LIB_FUNCTION
2685 krb5_enctype_to_keytype(krb5_context context,
2686 krb5_enctype etype,
2687 krb5_keytype *keytype)
2689 struct encryption_type *e = _find_enctype(etype);
2690 if(e == NULL) {
2691 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2692 N_("encryption type %d not supported", ""),
2693 etype);
2694 return KRB5_PROG_ETYPE_NOSUPP;
2696 *keytype = e->keytype->type; /* XXX */
2697 return 0;
2700 krb5_error_code KRB5_LIB_FUNCTION
2701 krb5_enctype_valid(krb5_context context,
2702 krb5_enctype etype)
2704 struct encryption_type *e = _find_enctype(etype);
2705 if(e == NULL) {
2706 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2707 N_("encryption type %d not supported", ""),
2708 etype);
2709 return KRB5_PROG_ETYPE_NOSUPP;
2711 if (e->flags & F_DISABLED) {
2712 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2713 N_("encryption type %s is disabled", ""),
2714 e->name);
2715 return KRB5_PROG_ETYPE_NOSUPP;
2717 return 0;
2721 * Return the coresponding encryption type for a checksum type.
2723 * @param context Kerberos context
2724 * @param ctype The checksum type to get the result enctype for
2725 * @param etype The returned encryption, when the matching etype is
2726 * not found, etype is set to ETYPE_NULL.
2728 * @return Return an error code for an failure or 0 on success.
2729 * @ingroup krb5_crypto
2733 krb5_error_code KRB5_LIB_FUNCTION
2734 krb5_cksumtype_to_enctype(krb5_context context,
2735 krb5_cksumtype ctype,
2736 krb5_enctype *etype)
2738 int i;
2740 *etype = ETYPE_NULL;
2742 for(i = 0; i < num_etypes; i++) {
2743 if(etypes[i]->keyed_checksum &&
2744 etypes[i]->keyed_checksum->type == ctype)
2746 *etype = etypes[i]->type;
2747 return 0;
2751 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2752 N_("checksum type %d not supported", ""),
2753 (int)ctype);
2754 return KRB5_PROG_SUMTYPE_NOSUPP;
2758 krb5_error_code KRB5_LIB_FUNCTION
2759 krb5_cksumtype_valid(krb5_context context,
2760 krb5_cksumtype ctype)
2762 struct checksum_type *c = _find_checksum(ctype);
2763 if (c == NULL) {
2764 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2765 N_("checksum type %d not supported", ""),
2766 ctype);
2767 return KRB5_PROG_SUMTYPE_NOSUPP;
2769 if (c->flags & F_DISABLED) {
2770 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2771 N_("checksum type %s is disabled", ""),
2772 c->name);
2773 return KRB5_PROG_SUMTYPE_NOSUPP;
2775 return 0;
2779 static krb5_boolean
2780 derived_crypto(krb5_context context,
2781 krb5_crypto crypto)
2783 return (crypto->et->flags & F_DERIVED) != 0;
2786 static krb5_boolean
2787 special_crypto(krb5_context context,
2788 krb5_crypto crypto)
2790 return (crypto->et->flags & F_SPECIAL) != 0;
2793 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2794 #define CHECKSUMTYPE(C) ((C)->type)
2796 static krb5_error_code
2797 encrypt_internal_derived(krb5_context context,
2798 krb5_crypto crypto,
2799 unsigned usage,
2800 const void *data,
2801 size_t len,
2802 krb5_data *result,
2803 void *ivec)
2805 size_t sz, block_sz, checksum_sz, total_sz;
2806 Checksum cksum;
2807 unsigned char *p, *q;
2808 krb5_error_code ret;
2809 struct key_data *dkey;
2810 const struct encryption_type *et = crypto->et;
2812 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2814 sz = et->confoundersize + len;
2815 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2816 total_sz = block_sz + checksum_sz;
2817 p = calloc(1, total_sz);
2818 if(p == NULL) {
2819 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2820 return ENOMEM;
2823 q = p;
2824 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2825 q += et->confoundersize;
2826 memcpy(q, data, len);
2828 ret = create_checksum(context,
2829 et->keyed_checksum,
2830 crypto,
2831 INTEGRITY_USAGE(usage),
2833 block_sz,
2834 &cksum);
2835 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2836 free_Checksum (&cksum);
2837 krb5_clear_error_message (context);
2838 ret = KRB5_CRYPTO_INTERNAL;
2840 if(ret)
2841 goto fail;
2842 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2843 free_Checksum (&cksum);
2844 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2845 if(ret)
2846 goto fail;
2847 ret = _key_schedule(context, dkey);
2848 if(ret)
2849 goto fail;
2850 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2851 if (ret)
2852 goto fail;
2853 result->data = p;
2854 result->length = total_sz;
2855 return 0;
2856 fail:
2857 memset(p, 0, total_sz);
2858 free(p);
2859 return ret;
2863 static krb5_error_code
2864 encrypt_internal(krb5_context context,
2865 krb5_crypto crypto,
2866 const void *data,
2867 size_t len,
2868 krb5_data *result,
2869 void *ivec)
2871 size_t sz, block_sz, checksum_sz;
2872 Checksum cksum;
2873 unsigned char *p, *q;
2874 krb5_error_code ret;
2875 const struct encryption_type *et = crypto->et;
2877 checksum_sz = CHECKSUMSIZE(et->checksum);
2879 sz = et->confoundersize + checksum_sz + len;
2880 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2881 p = calloc(1, block_sz);
2882 if(p == NULL) {
2883 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2884 return ENOMEM;
2887 q = p;
2888 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2889 q += et->confoundersize;
2890 memset(q, 0, checksum_sz);
2891 q += checksum_sz;
2892 memcpy(q, data, len);
2894 ret = create_checksum(context,
2895 et->checksum,
2896 crypto,
2899 block_sz,
2900 &cksum);
2901 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2902 krb5_clear_error_message (context);
2903 free_Checksum(&cksum);
2904 ret = KRB5_CRYPTO_INTERNAL;
2906 if(ret)
2907 goto fail;
2908 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2909 free_Checksum(&cksum);
2910 ret = _key_schedule(context, &crypto->key);
2911 if(ret)
2912 goto fail;
2913 ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
2914 if (ret) {
2915 memset(p, 0, block_sz);
2916 free(p);
2917 return ret;
2919 result->data = p;
2920 result->length = block_sz;
2921 return 0;
2922 fail:
2923 memset(p, 0, block_sz);
2924 free(p);
2925 return ret;
2928 static krb5_error_code
2929 encrypt_internal_special(krb5_context context,
2930 krb5_crypto crypto,
2931 int usage,
2932 const void *data,
2933 size_t len,
2934 krb5_data *result,
2935 void *ivec)
2937 struct encryption_type *et = crypto->et;
2938 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2939 size_t sz = len + cksum_sz + et->confoundersize;
2940 char *tmp, *p;
2941 krb5_error_code ret;
2943 tmp = malloc (sz);
2944 if (tmp == NULL) {
2945 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2946 return ENOMEM;
2948 p = tmp;
2949 memset (p, 0, cksum_sz);
2950 p += cksum_sz;
2951 krb5_generate_random_block(p, et->confoundersize);
2952 p += et->confoundersize;
2953 memcpy (p, data, len);
2954 ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
2955 if (ret) {
2956 memset(tmp, 0, sz);
2957 free(tmp);
2958 return ret;
2960 result->data = tmp;
2961 result->length = sz;
2962 return 0;
2965 static krb5_error_code
2966 decrypt_internal_derived(krb5_context context,
2967 krb5_crypto crypto,
2968 unsigned usage,
2969 void *data,
2970 size_t len,
2971 krb5_data *result,
2972 void *ivec)
2974 size_t checksum_sz;
2975 Checksum cksum;
2976 unsigned char *p;
2977 krb5_error_code ret;
2978 struct key_data *dkey;
2979 struct encryption_type *et = crypto->et;
2980 unsigned long l;
2982 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2983 if (len < checksum_sz + et->confoundersize) {
2984 krb5_set_error_message(context, KRB5_BAD_MSIZE,
2985 N_("Encrypted data shorter then "
2986 "checksum + confunder", ""));
2987 return KRB5_BAD_MSIZE;
2990 if (((len - checksum_sz) % et->padsize) != 0) {
2991 krb5_clear_error_message(context);
2992 return KRB5_BAD_MSIZE;
2995 p = malloc(len);
2996 if(len != 0 && p == NULL) {
2997 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2998 return ENOMEM;
3000 memcpy(p, data, len);
3002 len -= checksum_sz;
3004 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3005 if(ret) {
3006 free(p);
3007 return ret;
3009 ret = _key_schedule(context, dkey);
3010 if(ret) {
3011 free(p);
3012 return ret;
3014 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3015 if (ret) {
3016 free(p);
3017 return ret;
3020 cksum.checksum.data = p + len;
3021 cksum.checksum.length = checksum_sz;
3022 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3024 ret = verify_checksum(context,
3025 crypto,
3026 INTEGRITY_USAGE(usage),
3028 len,
3029 &cksum);
3030 if(ret) {
3031 free(p);
3032 return ret;
3034 l = len - et->confoundersize;
3035 memmove(p, p + et->confoundersize, l);
3036 result->data = realloc(p, l);
3037 if(result->data == NULL && l != 0) {
3038 free(p);
3039 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3040 return ENOMEM;
3042 result->length = l;
3043 return 0;
3046 static krb5_error_code
3047 decrypt_internal(krb5_context context,
3048 krb5_crypto crypto,
3049 void *data,
3050 size_t len,
3051 krb5_data *result,
3052 void *ivec)
3054 krb5_error_code ret;
3055 unsigned char *p;
3056 Checksum cksum;
3057 size_t checksum_sz, l;
3058 struct encryption_type *et = crypto->et;
3060 if ((len % et->padsize) != 0) {
3061 krb5_clear_error_message(context);
3062 return KRB5_BAD_MSIZE;
3065 checksum_sz = CHECKSUMSIZE(et->checksum);
3066 p = malloc(len);
3067 if(len != 0 && p == NULL) {
3068 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3069 return ENOMEM;
3071 memcpy(p, data, len);
3073 ret = _key_schedule(context, &crypto->key);
3074 if(ret) {
3075 free(p);
3076 return ret;
3078 ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
3079 if (ret) {
3080 free(p);
3081 return ret;
3083 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
3084 if(ret) {
3085 free(p);
3086 return ret;
3088 memset(p + et->confoundersize, 0, checksum_sz);
3089 cksum.cksumtype = CHECKSUMTYPE(et->checksum);
3090 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
3091 free_Checksum(&cksum);
3092 if(ret) {
3093 free(p);
3094 return ret;
3096 l = len - et->confoundersize - checksum_sz;
3097 memmove(p, p + et->confoundersize + checksum_sz, l);
3098 result->data = realloc(p, l);
3099 if(result->data == NULL && l != 0) {
3100 free(p);
3101 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3102 return ENOMEM;
3104 result->length = l;
3105 return 0;
3108 static krb5_error_code
3109 decrypt_internal_special(krb5_context context,
3110 krb5_crypto crypto,
3111 int usage,
3112 void *data,
3113 size_t len,
3114 krb5_data *result,
3115 void *ivec)
3117 struct encryption_type *et = crypto->et;
3118 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3119 size_t sz = len - cksum_sz - et->confoundersize;
3120 unsigned char *p;
3121 krb5_error_code ret;
3123 if ((len % et->padsize) != 0) {
3124 krb5_clear_error_message(context);
3125 return KRB5_BAD_MSIZE;
3128 p = malloc (len);
3129 if (p == NULL) {
3130 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3131 return ENOMEM;
3133 memcpy(p, data, len);
3135 ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
3136 if (ret) {
3137 free(p);
3138 return ret;
3141 memmove (p, p + cksum_sz + et->confoundersize, sz);
3142 result->data = realloc(p, sz);
3143 if(result->data == NULL && sz != 0) {
3144 free(p);
3145 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3146 return ENOMEM;
3148 result->length = sz;
3149 return 0;
3152 static krb5_crypto_iov *
3153 find_iv(krb5_crypto_iov *data, int num_data, int type)
3155 int i;
3156 for (i = 0; i < num_data; i++)
3157 if (data[i].flags == type)
3158 return &data[i];
3159 return NULL;
3163 * Inline encrypt a kerberos message
3165 * @param context Kerberos context
3166 * @param crypto Kerberos crypto context
3167 * @param usage Key usage for this buffer
3168 * @param data array of buffers to process
3169 * @param num_data length of array
3170 * @param ivec initial cbc/cts vector
3172 * @return Return an error code or 0.
3173 * @ingroup krb5_crypto
3175 * Kerberos encrypted data look like this:
3177 * 1. KRB5_CRYPTO_TYPE_HEADER
3178 * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
3179 * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
3180 * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
3181 * commonly used headers and trailers.
3182 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
3183 * 4. KRB5_CRYPTO_TYPE_TRAILER
3186 krb5_error_code KRB5_LIB_FUNCTION
3187 krb5_encrypt_iov_ivec(krb5_context context,
3188 krb5_crypto crypto,
3189 unsigned usage,
3190 krb5_crypto_iov *data,
3191 int num_data,
3192 void *ivec)
3194 size_t headersz, trailersz, len;
3195 int i;
3196 size_t sz, block_sz, pad_sz;
3197 Checksum cksum;
3198 unsigned char *p, *q;
3199 krb5_error_code ret;
3200 struct key_data *dkey;
3201 const struct encryption_type *et = crypto->et;
3202 krb5_crypto_iov *tiv, *piv, *hiv;
3204 if (num_data < 0) {
3205 krb5_clear_error_message(context);
3206 return KRB5_CRYPTO_INTERNAL;
3209 if(!derived_crypto(context, crypto)) {
3210 krb5_clear_error_message(context);
3211 return KRB5_CRYPTO_INTERNAL;
3214 headersz = et->confoundersize;
3215 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3217 for (len = 0, i = 0; i < num_data; i++) {
3218 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3219 continue;
3220 len += data[i].data.length;
3223 sz = headersz + len;
3224 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3226 pad_sz = block_sz - sz;
3228 /* header */
3230 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3231 if (hiv == NULL || hiv->data.length != headersz)
3232 return KRB5_BAD_MSIZE;
3234 krb5_generate_random_block(hiv->data.data, hiv->data.length);
3236 /* padding */
3237 piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
3238 /* its ok to have no TYPE_PADDING if there is no padding */
3239 if (piv == NULL && pad_sz != 0)
3240 return KRB5_BAD_MSIZE;
3241 if (piv) {
3242 if (piv->data.length < pad_sz)
3243 return KRB5_BAD_MSIZE;
3244 piv->data.length = pad_sz;
3245 if (pad_sz)
3246 memset(piv->data.data, pad_sz, pad_sz);
3247 else
3248 piv = NULL;
3251 /* trailer */
3252 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3253 if (tiv == NULL || tiv->data.length != trailersz)
3254 return KRB5_BAD_MSIZE;
3257 * XXX replace with EVP_Sign? at least make create_checksum an iov
3258 * function.
3259 * XXX CTS EVP is broken, can't handle multi buffers :(
3262 len = block_sz;
3263 for (i = 0; i < num_data; i++) {
3264 if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3265 continue;
3266 len += data[i].data.length;
3269 p = q = malloc(len);
3271 memcpy(q, hiv->data.data, hiv->data.length);
3272 q += hiv->data.length;
3273 for (i = 0; i < num_data; i++) {
3274 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3275 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3276 continue;
3277 memcpy(q, data[i].data.data, data[i].data.length);
3278 q += data[i].data.length;
3280 if (piv)
3281 memset(q, 0, piv->data.length);
3283 ret = create_checksum(context,
3284 et->keyed_checksum,
3285 crypto,
3286 INTEGRITY_USAGE(usage),
3288 len,
3289 &cksum);
3290 free(p);
3291 if(ret == 0 && cksum.checksum.length != trailersz) {
3292 free_Checksum (&cksum);
3293 krb5_clear_error_message (context);
3294 ret = KRB5_CRYPTO_INTERNAL;
3296 if(ret)
3297 return ret;
3299 /* save cksum at end */
3300 memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
3301 free_Checksum (&cksum);
3303 /* XXX replace with EVP_Cipher */
3304 p = q = malloc(block_sz);
3305 if(p == NULL)
3306 return ENOMEM;
3308 memcpy(q, hiv->data.data, hiv->data.length);
3309 q += hiv->data.length;
3311 for (i = 0; i < num_data; i++) {
3312 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3313 continue;
3314 memcpy(q, data[i].data.data, data[i].data.length);
3315 q += data[i].data.length;
3317 if (piv)
3318 memset(q, 0, piv->data.length);
3321 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3322 if(ret) {
3323 free(p);
3324 return ret;
3326 ret = _key_schedule(context, dkey);
3327 if(ret) {
3328 free(p);
3329 return ret;
3332 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
3333 if (ret) {
3334 free(p);
3335 return ret;
3338 /* now copy data back to buffers */
3339 q = p;
3341 memcpy(hiv->data.data, q, hiv->data.length);
3342 q += hiv->data.length;
3344 for (i = 0; i < num_data; i++) {
3345 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3346 continue;
3347 memcpy(data[i].data.data, q, data[i].data.length);
3348 q += data[i].data.length;
3350 if (piv)
3351 memcpy(piv->data.data, q, pad_sz);
3353 free(p);
3355 return ret;
3359 * Inline decrypt a Kerberos message.
3361 * @param context Kerberos context
3362 * @param crypto Kerberos crypto context
3363 * @param usage Key usage for this buffer
3364 * @param data array of buffers to process
3365 * @param num_data length of array
3366 * @param ivec initial cbc/cts vector
3368 * @return Return an error code or 0.
3369 * @ingroup krb5_crypto
3371 * 1. KRB5_CRYPTO_TYPE_HEADER
3372 * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
3373 * any order, however the receiver have to aware of the
3374 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
3375 * protocol headers and trailers. The output data will be of same
3376 * size as the input data or shorter.
3379 krb5_error_code KRB5_LIB_FUNCTION
3380 krb5_decrypt_iov_ivec(krb5_context context,
3381 krb5_crypto crypto,
3382 unsigned usage,
3383 krb5_crypto_iov *data,
3384 unsigned int num_data,
3385 void *ivec)
3387 unsigned int i;
3388 size_t headersz, trailersz, len;
3389 Checksum cksum;
3390 unsigned char *p, *q;
3391 krb5_error_code ret;
3392 struct key_data *dkey;
3393 struct encryption_type *et = crypto->et;
3394 krb5_crypto_iov *tiv, *hiv;
3396 if (num_data < 0) {
3397 krb5_clear_error_message(context);
3398 return KRB5_CRYPTO_INTERNAL;
3401 if(!derived_crypto(context, crypto)) {
3402 krb5_clear_error_message(context);
3403 return KRB5_CRYPTO_INTERNAL;
3406 headersz = et->confoundersize;
3408 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3409 if (hiv == NULL || hiv->data.length != headersz)
3410 return KRB5_BAD_MSIZE;
3412 /* trailer */
3413 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3415 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3416 if (tiv->data.length != trailersz)
3417 return KRB5_BAD_MSIZE;
3419 /* Find length of data we will decrypt */
3421 len = headersz;
3422 for (i = 0; i < num_data; i++) {
3423 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3424 continue;
3425 len += data[i].data.length;
3428 if ((len % et->padsize) != 0) {
3429 krb5_clear_error_message(context);
3430 return KRB5_BAD_MSIZE;
3433 /* XXX replace with EVP_Cipher */
3435 p = q = malloc(len);
3436 if (p == NULL)
3437 return ENOMEM;
3439 memcpy(q, hiv->data.data, hiv->data.length);
3440 q += hiv->data.length;
3442 for (i = 0; i < num_data; i++) {
3443 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3444 continue;
3445 memcpy(q, data[i].data.data, data[i].data.length);
3446 q += data[i].data.length;
3449 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3450 if(ret) {
3451 free(p);
3452 return ret;
3454 ret = _key_schedule(context, dkey);
3455 if(ret) {
3456 free(p);
3457 return ret;
3460 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3461 if (ret) {
3462 free(p);
3463 return ret;
3466 /* copy data back to buffers */
3467 memcpy(hiv->data.data, p, hiv->data.length);
3468 q = p + hiv->data.length;
3469 for (i = 0; i < num_data; i++) {
3470 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3471 continue;
3472 memcpy(data[i].data.data, q, data[i].data.length);
3473 q += data[i].data.length;
3476 free(p);
3478 /* check signature */
3479 for (i = 0; i < num_data; i++) {
3480 if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3481 continue;
3482 len += data[i].data.length;
3485 p = q = malloc(len);
3486 if (p == NULL)
3487 return ENOMEM;
3489 memcpy(q, hiv->data.data, hiv->data.length);
3490 q += hiv->data.length;
3491 for (i = 0; i < num_data; i++) {
3492 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3493 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3494 continue;
3495 memcpy(q, data[i].data.data, data[i].data.length);
3496 q += data[i].data.length;
3499 cksum.checksum.data = tiv->data.data;
3500 cksum.checksum.length = tiv->data.length;
3501 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3503 ret = verify_checksum(context,
3504 crypto,
3505 INTEGRITY_USAGE(usage),
3507 len,
3508 &cksum);
3509 free(p);
3510 return ret;
3514 * Create a Kerberos message checksum.
3516 * @param context Kerberos context
3517 * @param crypto Kerberos crypto context
3518 * @param usage Key usage for this buffer
3519 * @param data array of buffers to process
3520 * @param num_data length of array
3521 * @param type output data
3523 * @return Return an error code or 0.
3524 * @ingroup krb5_crypto
3527 krb5_error_code KRB5_LIB_FUNCTION
3528 krb5_create_checksum_iov(krb5_context context,
3529 krb5_crypto crypto,
3530 unsigned usage,
3531 krb5_crypto_iov *data,
3532 unsigned int num_data,
3533 krb5_cksumtype *type)
3535 Checksum cksum;
3536 krb5_crypto_iov *civ;
3537 krb5_error_code ret;
3538 int i;
3539 size_t len;
3540 char *p, *q;
3542 if (num_data < 0) {
3543 krb5_clear_error_message(context);
3544 return KRB5_CRYPTO_INTERNAL;
3547 if(!derived_crypto(context, crypto)) {
3548 krb5_clear_error_message(context);
3549 return KRB5_CRYPTO_INTERNAL;
3552 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3553 if (civ == NULL)
3554 return KRB5_BAD_MSIZE;
3556 len = 0;
3557 for (i = 0; i < num_data; i++) {
3558 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3559 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3560 continue;
3561 len += data[i].data.length;
3564 p = q = malloc(len);
3566 for (i = 0; i < num_data; i++) {
3567 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3568 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3569 continue;
3570 memcpy(q, data[i].data.data, data[i].data.length);
3571 q += data[i].data.length;
3574 ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
3575 free(p);
3576 if (ret)
3577 return ret;
3579 if (type)
3580 *type = cksum.cksumtype;
3582 if (cksum.checksum.length > civ->data.length) {
3583 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3584 N_("Checksum larger then input buffer", ""));
3585 free_Checksum(&cksum);
3586 return KRB5_BAD_MSIZE;
3589 civ->data.length = cksum.checksum.length;
3590 memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
3591 free_Checksum(&cksum);
3593 return 0;
3597 * Verify a Kerberos message checksum.
3599 * @param context Kerberos context
3600 * @param crypto Kerberos crypto context
3601 * @param usage Key usage for this buffer
3602 * @param data array of buffers to process
3603 * @param num_data length of array
3604 * @param type return checksum type if not NULL
3606 * @return Return an error code or 0.
3607 * @ingroup krb5_crypto
3610 krb5_error_code KRB5_LIB_FUNCTION
3611 krb5_verify_checksum_iov(krb5_context context,
3612 krb5_crypto crypto,
3613 unsigned usage,
3614 krb5_crypto_iov *data,
3615 unsigned int num_data,
3616 krb5_cksumtype *type)
3618 struct encryption_type *et = crypto->et;
3619 Checksum cksum;
3620 krb5_crypto_iov *civ;
3621 krb5_error_code ret;
3622 int i;
3623 size_t len;
3624 char *p, *q;
3626 if (num_data < 0) {
3627 krb5_clear_error_message(context);
3628 return KRB5_CRYPTO_INTERNAL;
3631 if(!derived_crypto(context, crypto)) {
3632 krb5_clear_error_message(context);
3633 return KRB5_CRYPTO_INTERNAL;
3636 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3637 if (civ == NULL)
3638 return KRB5_BAD_MSIZE;
3640 len = 0;
3641 for (i = 0; i < num_data; i++) {
3642 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3643 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3644 continue;
3645 len += data[i].data.length;
3648 p = q = malloc(len);
3650 for (i = 0; i < num_data; i++) {
3651 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3652 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3653 continue;
3654 memcpy(q, data[i].data.data, data[i].data.length);
3655 q += data[i].data.length;
3658 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3659 cksum.checksum.length = civ->data.length;
3660 cksum.checksum.data = civ->data.data;
3662 ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
3663 free(p);
3665 if (ret == 0 && type)
3666 *type = cksum.cksumtype;
3668 return ret;
3672 krb5_error_code KRB5_LIB_FUNCTION
3673 krb5_crypto_length(krb5_context context,
3674 krb5_crypto crypto,
3675 int type,
3676 size_t *len)
3678 if (!derived_crypto(context, crypto)) {
3679 krb5_set_error_message(context, EINVAL, "not a derived crypto");
3680 return EINVAL;
3683 switch(type) {
3684 case KRB5_CRYPTO_TYPE_EMPTY:
3685 *len = 0;
3686 return 0;
3687 case KRB5_CRYPTO_TYPE_HEADER:
3688 *len = crypto->et->blocksize;
3689 return 0;
3690 case KRB5_CRYPTO_TYPE_DATA:
3691 case KRB5_CRYPTO_TYPE_SIGN_ONLY:
3692 /* len must already been filled in */
3693 return 0;
3694 case KRB5_CRYPTO_TYPE_PADDING:
3695 if (crypto->et->padsize > 1)
3696 *len = crypto->et->padsize;
3697 else
3698 *len = 0;
3699 return 0;
3700 case KRB5_CRYPTO_TYPE_TRAILER:
3701 *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
3702 return 0;
3703 case KRB5_CRYPTO_TYPE_CHECKSUM:
3704 if (crypto->et->keyed_checksum)
3705 *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
3706 else
3707 *len = CHECKSUMSIZE(crypto->et->checksum);
3708 return 0;
3710 krb5_set_error_message(context, EINVAL,
3711 "%d not a supported type", type);
3712 return EINVAL;
3716 krb5_error_code KRB5_LIB_FUNCTION
3717 krb5_crypto_length_iov(krb5_context context,
3718 krb5_crypto crypto,
3719 krb5_crypto_iov *data,
3720 unsigned int num_data)
3722 krb5_error_code ret;
3723 int i;
3725 for (i = 0; i < num_data; i++) {
3726 ret = krb5_crypto_length(context, crypto,
3727 data[i].flags,
3728 &data[i].data.length);
3729 if (ret)
3730 return ret;
3732 return 0;
3736 krb5_error_code KRB5_LIB_FUNCTION
3737 krb5_encrypt_ivec(krb5_context context,
3738 krb5_crypto crypto,
3739 unsigned usage,
3740 const void *data,
3741 size_t len,
3742 krb5_data *result,
3743 void *ivec)
3745 if(derived_crypto(context, crypto))
3746 return encrypt_internal_derived(context, crypto, usage,
3747 data, len, result, ivec);
3748 else if (special_crypto(context, crypto))
3749 return encrypt_internal_special (context, crypto, usage,
3750 data, len, result, ivec);
3751 else
3752 return encrypt_internal(context, crypto, data, len, result, ivec);
3755 krb5_error_code KRB5_LIB_FUNCTION
3756 krb5_encrypt(krb5_context context,
3757 krb5_crypto crypto,
3758 unsigned usage,
3759 const void *data,
3760 size_t len,
3761 krb5_data *result)
3763 return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
3766 krb5_error_code KRB5_LIB_FUNCTION
3767 krb5_encrypt_EncryptedData(krb5_context context,
3768 krb5_crypto crypto,
3769 unsigned usage,
3770 void *data,
3771 size_t len,
3772 int kvno,
3773 EncryptedData *result)
3775 result->etype = CRYPTO_ETYPE(crypto);
3776 if(kvno){
3777 ALLOC(result->kvno, 1);
3778 *result->kvno = kvno;
3779 }else
3780 result->kvno = NULL;
3781 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
3784 krb5_error_code KRB5_LIB_FUNCTION
3785 krb5_decrypt_ivec(krb5_context context,
3786 krb5_crypto crypto,
3787 unsigned usage,
3788 void *data,
3789 size_t len,
3790 krb5_data *result,
3791 void *ivec)
3793 if(derived_crypto(context, crypto))
3794 return decrypt_internal_derived(context, crypto, usage,
3795 data, len, result, ivec);
3796 else if (special_crypto (context, crypto))
3797 return decrypt_internal_special(context, crypto, usage,
3798 data, len, result, ivec);
3799 else
3800 return decrypt_internal(context, crypto, data, len, result, ivec);
3803 krb5_error_code KRB5_LIB_FUNCTION
3804 krb5_decrypt(krb5_context context,
3805 krb5_crypto crypto,
3806 unsigned usage,
3807 void *data,
3808 size_t len,
3809 krb5_data *result)
3811 return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
3812 NULL);
3815 krb5_error_code KRB5_LIB_FUNCTION
3816 krb5_decrypt_EncryptedData(krb5_context context,
3817 krb5_crypto crypto,
3818 unsigned usage,
3819 const EncryptedData *e,
3820 krb5_data *result)
3822 return krb5_decrypt(context, crypto, usage,
3823 e->cipher.data, e->cipher.length, result);
3826 /************************************************************
3828 ************************************************************/
3830 #define ENTROPY_NEEDED 128
3832 static int
3833 seed_something(void)
3835 char buf[1024], seedfile[256];
3837 /* If there is a seed file, load it. But such a file cannot be trusted,
3838 so use 0 for the entropy estimate */
3839 if (RAND_file_name(seedfile, sizeof(seedfile))) {
3840 int fd;
3841 fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
3842 if (fd >= 0) {
3843 ssize_t ret;
3844 rk_cloexec(fd);
3845 ret = read(fd, buf, sizeof(buf));
3846 if (ret > 0)
3847 RAND_add(buf, ret, 0.0);
3848 close(fd);
3849 } else
3850 seedfile[0] = '\0';
3851 } else
3852 seedfile[0] = '\0';
3854 /* Calling RAND_status() will try to use /dev/urandom if it exists so
3855 we do not have to deal with it. */
3856 if (RAND_status() != 1) {
3857 krb5_context context;
3858 const char *p;
3860 /* Try using egd */
3861 if (!krb5_init_context(&context)) {
3862 p = krb5_config_get_string(context, NULL, "libdefaults",
3863 "egd_socket", NULL);
3864 if (p != NULL)
3865 RAND_egd_bytes(p, ENTROPY_NEEDED);
3866 krb5_free_context(context);
3870 if (RAND_status() == 1) {
3871 /* Update the seed file */
3872 if (seedfile[0])
3873 RAND_write_file(seedfile);
3875 return 0;
3876 } else
3877 return -1;
3880 void KRB5_LIB_FUNCTION
3881 krb5_generate_random_block(void *buf, size_t len)
3883 static int rng_initialized = 0;
3885 HEIMDAL_MUTEX_lock(&crypto_mutex);
3886 if (!rng_initialized) {
3887 if (seed_something())
3888 krb5_abortx(NULL, "Fatal: could not seed the "
3889 "random number generator");
3891 rng_initialized = 1;
3893 HEIMDAL_MUTEX_unlock(&crypto_mutex);
3894 if (RAND_bytes(buf, len) != 1)
3895 krb5_abortx(NULL, "Failed to generate random block");
3898 static krb5_error_code
3899 derive_key(krb5_context context,
3900 struct encryption_type *et,
3901 struct key_data *key,
3902 const void *constant,
3903 size_t len)
3905 unsigned char *k = NULL;
3906 unsigned int nblocks = 0, i;
3907 krb5_error_code ret = 0;
3908 struct key_type *kt = et->keytype;
3910 ret = _key_schedule(context, key);
3911 if(ret)
3912 return ret;
3913 if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
3914 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
3915 k = malloc(nblocks * et->blocksize);
3916 if(k == NULL) {
3917 ret = ENOMEM;
3918 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3919 goto out;
3921 ret = _krb5_n_fold(constant, len, k, et->blocksize);
3922 if (ret) {
3923 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3924 goto out;
3927 for(i = 0; i < nblocks; i++) {
3928 if(i > 0)
3929 memcpy(k + i * et->blocksize,
3930 k + (i - 1) * et->blocksize,
3931 et->blocksize);
3932 (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
3933 1, 0, NULL);
3935 } else {
3936 /* this case is probably broken, but won't be run anyway */
3937 void *c = malloc(len);
3938 size_t res_len = (kt->bits + 7) / 8;
3940 if(len != 0 && c == NULL) {
3941 ret = ENOMEM;
3942 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3943 goto out;
3945 memcpy(c, constant, len);
3946 (*et->encrypt)(context, key, c, len, 1, 0, NULL);
3947 k = malloc(res_len);
3948 if(res_len != 0 && k == NULL) {
3949 free(c);
3950 ret = ENOMEM;
3951 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3952 goto out;
3954 ret = _krb5_n_fold(c, len, k, res_len);
3955 free(c);
3956 if (ret) {
3957 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3958 goto out;
3962 /* XXX keytype dependent post-processing */
3963 switch(kt->type) {
3964 case KEYTYPE_DES3:
3965 DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
3966 break;
3967 case KEYTYPE_AES128:
3968 case KEYTYPE_AES256:
3969 memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
3970 break;
3971 default:
3972 ret = KRB5_CRYPTO_INTERNAL;
3973 krb5_set_error_message(context, ret,
3974 N_("derive_key() called with unknown keytype (%u)", ""),
3975 kt->type);
3976 break;
3978 out:
3979 if (key->schedule) {
3980 free_key_schedule(context, key, et);
3981 key->schedule = NULL;
3983 if (k) {
3984 memset(k, 0, nblocks * et->blocksize);
3985 free(k);
3987 return ret;
3990 static struct key_data *
3991 _new_derived_key(krb5_crypto crypto, unsigned usage)
3993 struct key_usage *d = crypto->key_usage;
3994 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
3995 if(d == NULL)
3996 return NULL;
3997 crypto->key_usage = d;
3998 d += crypto->num_key_usage++;
3999 memset(d, 0, sizeof(*d));
4000 d->usage = usage;
4001 return &d->key;
4004 krb5_error_code KRB5_LIB_FUNCTION
4005 krb5_derive_key(krb5_context context,
4006 const krb5_keyblock *key,
4007 krb5_enctype etype,
4008 const void *constant,
4009 size_t constant_len,
4010 krb5_keyblock **derived_key)
4012 krb5_error_code ret;
4013 struct encryption_type *et;
4014 struct key_data d;
4016 *derived_key = NULL;
4018 et = _find_enctype (etype);
4019 if (et == NULL) {
4020 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4021 N_("encryption type %d not supported", ""),
4022 etype);
4023 return KRB5_PROG_ETYPE_NOSUPP;
4026 ret = krb5_copy_keyblock(context, key, &d.key);
4027 if (ret)
4028 return ret;
4030 d.schedule = NULL;
4031 ret = derive_key(context, et, &d, constant, constant_len);
4032 if (ret == 0)
4033 ret = krb5_copy_keyblock(context, d.key, derived_key);
4034 free_key_data(context, &d, et);
4035 return ret;
4038 static krb5_error_code
4039 _get_derived_key(krb5_context context,
4040 krb5_crypto crypto,
4041 unsigned usage,
4042 struct key_data **key)
4044 int i;
4045 struct key_data *d;
4046 unsigned char constant[5];
4048 for(i = 0; i < crypto->num_key_usage; i++)
4049 if(crypto->key_usage[i].usage == usage) {
4050 *key = &crypto->key_usage[i].key;
4051 return 0;
4053 d = _new_derived_key(crypto, usage);
4054 if(d == NULL) {
4055 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4056 return ENOMEM;
4058 krb5_copy_keyblock(context, crypto->key.key, &d->key);
4059 _krb5_put_int(constant, usage, 5);
4060 derive_key(context, crypto->et, d, constant, sizeof(constant));
4061 *key = d;
4062 return 0;
4066 krb5_error_code KRB5_LIB_FUNCTION
4067 krb5_crypto_init(krb5_context context,
4068 const krb5_keyblock *key,
4069 krb5_enctype etype,
4070 krb5_crypto *crypto)
4072 krb5_error_code ret;
4073 ALLOC(*crypto, 1);
4074 if(*crypto == NULL) {
4075 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4076 return ENOMEM;
4078 if(etype == ETYPE_NULL)
4079 etype = key->keytype;
4080 (*crypto)->et = _find_enctype(etype);
4081 if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
4082 free(*crypto);
4083 *crypto = NULL;
4084 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4085 N_("encryption type %d not supported", ""),
4086 etype);
4087 return KRB5_PROG_ETYPE_NOSUPP;
4089 if((*crypto)->et->keytype->size != key->keyvalue.length) {
4090 free(*crypto);
4091 *crypto = NULL;
4092 krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
4093 "encryption key has bad length");
4094 return KRB5_BAD_KEYSIZE;
4096 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
4097 if(ret) {
4098 free(*crypto);
4099 *crypto = NULL;
4100 return ret;
4102 (*crypto)->key.schedule = NULL;
4103 (*crypto)->num_key_usage = 0;
4104 (*crypto)->key_usage = NULL;
4105 return 0;
4108 static void
4109 free_key_schedule(krb5_context context,
4110 struct key_data *key,
4111 struct encryption_type *et)
4113 if (et->keytype->cleanup)
4114 (*et->keytype->cleanup)(context, key);
4115 memset(key->schedule->data, 0, key->schedule->length);
4116 krb5_free_data(context, key->schedule);
4119 static void
4120 free_key_data(krb5_context context, struct key_data *key,
4121 struct encryption_type *et)
4123 krb5_free_keyblock(context, key->key);
4124 if(key->schedule) {
4125 free_key_schedule(context, key, et);
4126 key->schedule = NULL;
4130 static void
4131 free_key_usage(krb5_context context, struct key_usage *ku,
4132 struct encryption_type *et)
4134 free_key_data(context, &ku->key, et);
4137 krb5_error_code KRB5_LIB_FUNCTION
4138 krb5_crypto_destroy(krb5_context context,
4139 krb5_crypto crypto)
4141 int i;
4143 for(i = 0; i < crypto->num_key_usage; i++)
4144 free_key_usage(context, &crypto->key_usage[i], crypto->et);
4145 free(crypto->key_usage);
4146 free_key_data(context, &crypto->key, crypto->et);
4147 free (crypto);
4148 return 0;
4151 krb5_error_code KRB5_LIB_FUNCTION
4152 krb5_crypto_getblocksize(krb5_context context,
4153 krb5_crypto crypto,
4154 size_t *blocksize)
4156 *blocksize = crypto->et->blocksize;
4157 return 0;
4160 krb5_error_code KRB5_LIB_FUNCTION
4161 krb5_crypto_getenctype(krb5_context context,
4162 krb5_crypto crypto,
4163 krb5_enctype *enctype)
4165 *enctype = crypto->et->type;
4166 return 0;
4169 krb5_error_code KRB5_LIB_FUNCTION
4170 krb5_crypto_getpadsize(krb5_context context,
4171 krb5_crypto crypto,
4172 size_t *padsize)
4174 *padsize = crypto->et->padsize;
4175 return 0;
4178 krb5_error_code KRB5_LIB_FUNCTION
4179 krb5_crypto_getconfoundersize(krb5_context context,
4180 krb5_crypto crypto,
4181 size_t *confoundersize)
4183 *confoundersize = crypto->et->confoundersize;
4184 return 0;
4189 * Disable encryption type
4191 * @param context Kerberos 5 context
4192 * @param enctype encryption type to disable
4194 * @return Return an error code or 0.
4196 * @ingroup krb5_crypto
4199 krb5_error_code KRB5_LIB_FUNCTION
4200 krb5_enctype_disable(krb5_context context,
4201 krb5_enctype enctype)
4203 struct encryption_type *et = _find_enctype(enctype);
4204 if(et == NULL) {
4205 if (context)
4206 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4207 N_("encryption type %d not supported", ""),
4208 enctype);
4209 return KRB5_PROG_ETYPE_NOSUPP;
4211 et->flags |= F_DISABLED;
4212 return 0;
4216 * Enable encryption type
4218 * @param context Kerberos 5 context
4219 * @param enctype encryption type to enable
4221 * @return Return an error code or 0.
4223 * @ingroup krb5_crypto
4226 krb5_error_code KRB5_LIB_FUNCTION
4227 krb5_enctype_enable(krb5_context context,
4228 krb5_enctype enctype)
4230 struct encryption_type *et = _find_enctype(enctype);
4231 if(et == NULL) {
4232 if (context)
4233 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4234 N_("encryption type %d not supported", ""),
4235 enctype);
4236 return KRB5_PROG_ETYPE_NOSUPP;
4238 et->flags &= ~F_DISABLED;
4239 return 0;
4243 krb5_error_code KRB5_LIB_FUNCTION
4244 krb5_string_to_key_derived(krb5_context context,
4245 const void *str,
4246 size_t len,
4247 krb5_enctype etype,
4248 krb5_keyblock *key)
4250 struct encryption_type *et = _find_enctype(etype);
4251 krb5_error_code ret;
4252 struct key_data kd;
4253 size_t keylen;
4254 u_char *tmp;
4256 if(et == NULL) {
4257 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4258 N_("encryption type %d not supported", ""),
4259 etype);
4260 return KRB5_PROG_ETYPE_NOSUPP;
4262 keylen = et->keytype->bits / 8;
4264 ALLOC(kd.key, 1);
4265 if(kd.key == NULL) {
4266 krb5_set_error_message (context, ENOMEM,
4267 N_("malloc: out of memory", ""));
4268 return ENOMEM;
4270 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
4271 if(ret) {
4272 free(kd.key);
4273 return ret;
4275 kd.key->keytype = etype;
4276 tmp = malloc (keylen);
4277 if(tmp == NULL) {
4278 krb5_free_keyblock(context, kd.key);
4279 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4280 return ENOMEM;
4282 ret = _krb5_n_fold(str, len, tmp, keylen);
4283 if (ret) {
4284 free(tmp);
4285 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4286 return ret;
4288 kd.schedule = NULL;
4289 DES3_random_to_key(context, kd.key, tmp, keylen);
4290 memset(tmp, 0, keylen);
4291 free(tmp);
4292 ret = derive_key(context,
4294 &kd,
4295 "kerberos", /* XXX well known constant */
4296 strlen("kerberos"));
4297 if (ret) {
4298 free_key_data(context, &kd, et);
4299 return ret;
4301 ret = krb5_copy_keyblock_contents(context, kd.key, key);
4302 free_key_data(context, &kd, et);
4303 return ret;
4306 static size_t
4307 wrapped_length (krb5_context context,
4308 krb5_crypto crypto,
4309 size_t data_len)
4311 struct encryption_type *et = crypto->et;
4312 size_t padsize = et->padsize;
4313 size_t checksumsize = CHECKSUMSIZE(et->checksum);
4314 size_t res;
4316 res = et->confoundersize + checksumsize + data_len;
4317 res = (res + padsize - 1) / padsize * padsize;
4318 return res;
4321 static size_t
4322 wrapped_length_dervied (krb5_context context,
4323 krb5_crypto crypto,
4324 size_t data_len)
4326 struct encryption_type *et = crypto->et;
4327 size_t padsize = et->padsize;
4328 size_t res;
4330 res = et->confoundersize + data_len;
4331 res = (res + padsize - 1) / padsize * padsize;
4332 if (et->keyed_checksum)
4333 res += et->keyed_checksum->checksumsize;
4334 else
4335 res += et->checksum->checksumsize;
4336 return res;
4340 * Return the size of an encrypted packet of length `data_len'
4343 size_t
4344 krb5_get_wrapped_length (krb5_context context,
4345 krb5_crypto crypto,
4346 size_t data_len)
4348 if (derived_crypto (context, crypto))
4349 return wrapped_length_dervied (context, crypto, data_len);
4350 else
4351 return wrapped_length (context, crypto, data_len);
4355 * Return the size of an encrypted packet of length `data_len'
4358 static size_t
4359 crypto_overhead (krb5_context context,
4360 krb5_crypto crypto)
4362 struct encryption_type *et = crypto->et;
4363 size_t res;
4365 res = CHECKSUMSIZE(et->checksum);
4366 res += et->confoundersize;
4367 if (et->padsize > 1)
4368 res += et->padsize;
4369 return res;
4372 static size_t
4373 crypto_overhead_dervied (krb5_context context,
4374 krb5_crypto crypto)
4376 struct encryption_type *et = crypto->et;
4377 size_t res;
4379 if (et->keyed_checksum)
4380 res = CHECKSUMSIZE(et->keyed_checksum);
4381 else
4382 res = CHECKSUMSIZE(et->checksum);
4383 res += et->confoundersize;
4384 if (et->padsize > 1)
4385 res += et->padsize;
4386 return res;
4389 size_t
4390 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
4392 if (derived_crypto (context, crypto))
4393 return crypto_overhead_dervied (context, crypto);
4394 else
4395 return crypto_overhead (context, crypto);
4399 * Converts the random bytestring to a protocol key according to
4400 * Kerberos crypto frame work. It may be assumed that all the bits of
4401 * the input string are equally random, even though the entropy
4402 * present in the random source may be limited.
4404 * @param context Kerberos 5 context
4405 * @param type the enctype resulting key will be of
4406 * @param data input random data to convert to a key
4407 * @param size size of input random data, at least krb5_enctype_keysize() long
4408 * @param key key, output key, free with krb5_free_keyblock_contents()
4410 * @return Return an error code or 0.
4412 * @ingroup krb5_crypto
4415 krb5_error_code KRB5_LIB_FUNCTION
4416 krb5_random_to_key(krb5_context context,
4417 krb5_enctype type,
4418 const void *data,
4419 size_t size,
4420 krb5_keyblock *key)
4422 krb5_error_code ret;
4423 struct encryption_type *et = _find_enctype(type);
4424 if(et == NULL) {
4425 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4426 N_("encryption type %d not supported", ""),
4427 type);
4428 return KRB5_PROG_ETYPE_NOSUPP;
4430 if ((et->keytype->bits + 7) / 8 > size) {
4431 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4432 N_("encryption key %s needs %d bytes "
4433 "of random to make an encryption key "
4434 "out of it", ""),
4435 et->name, (int)et->keytype->size);
4436 return KRB5_PROG_ETYPE_NOSUPP;
4438 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
4439 if(ret)
4440 return ret;
4441 key->keytype = type;
4442 if (et->keytype->random_to_key)
4443 (*et->keytype->random_to_key)(context, key, data, size);
4444 else
4445 memcpy(key->keyvalue.data, data, et->keytype->size);
4447 return 0;
4450 krb5_error_code
4451 _krb5_pk_octetstring2key(krb5_context context,
4452 krb5_enctype type,
4453 const void *dhdata,
4454 size_t dhsize,
4455 const heim_octet_string *c_n,
4456 const heim_octet_string *k_n,
4457 krb5_keyblock *key)
4459 struct encryption_type *et = _find_enctype(type);
4460 krb5_error_code ret;
4461 size_t keylen, offset;
4462 void *keydata;
4463 unsigned char counter;
4464 unsigned char shaoutput[SHA_DIGEST_LENGTH];
4465 EVP_MD_CTX *m;
4467 if(et == NULL) {
4468 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4469 N_("encryption type %d not supported", ""),
4470 type);
4471 return KRB5_PROG_ETYPE_NOSUPP;
4473 keylen = (et->keytype->bits + 7) / 8;
4475 keydata = malloc(keylen);
4476 if (keydata == NULL) {
4477 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4478 return ENOMEM;
4481 m = EVP_MD_CTX_create();
4482 if (m == NULL) {
4483 free(keydata);
4484 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4485 return ENOMEM;
4488 counter = 0;
4489 offset = 0;
4490 do {
4492 EVP_DigestInit_ex(m, EVP_sha1(), NULL);
4493 EVP_DigestUpdate(m, &counter, 1);
4494 EVP_DigestUpdate(m, dhdata, dhsize);
4496 if (c_n)
4497 EVP_DigestUpdate(m, c_n->data, c_n->length);
4498 if (k_n)
4499 EVP_DigestUpdate(m, k_n->data, k_n->length);
4501 EVP_DigestFinal_ex(m, shaoutput, NULL);
4503 memcpy((unsigned char *)keydata + offset,
4504 shaoutput,
4505 min(keylen - offset, sizeof(shaoutput)));
4507 offset += sizeof(shaoutput);
4508 counter++;
4509 } while(offset < keylen);
4510 memset(shaoutput, 0, sizeof(shaoutput));
4512 EVP_MD_CTX_destroy(m);
4514 ret = krb5_random_to_key(context, type, keydata, keylen, key);
4515 memset(keydata, 0, sizeof(keylen));
4516 free(keydata);
4517 return ret;
4520 static krb5_error_code
4521 encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
4523 KRB5PrincipalName pn;
4524 krb5_error_code ret;
4525 size_t size;
4527 pn.principalName = p->name;
4528 pn.realm = p->realm;
4530 ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
4531 &pn, &size, ret);
4532 if (ret) {
4533 krb5_data_zero(data);
4534 krb5_set_error_message(context, ret,
4535 N_("Failed to encode KRB5PrincipalName", ""));
4536 return ret;
4538 if (data->length != size)
4539 krb5_abortx(context, "asn1 compiler internal error");
4540 return 0;
4543 static krb5_error_code
4544 encode_otherinfo(krb5_context context,
4545 const AlgorithmIdentifier *ai,
4546 krb5_const_principal client,
4547 krb5_const_principal server,
4548 krb5_enctype enctype,
4549 const krb5_data *as_req,
4550 const krb5_data *pk_as_rep,
4551 const Ticket *ticket,
4552 krb5_data *other)
4554 PkinitSP80056AOtherInfo otherinfo;
4555 PkinitSuppPubInfo pubinfo;
4556 krb5_error_code ret;
4557 krb5_data pub;
4558 size_t size;
4560 krb5_data_zero(other);
4561 memset(&otherinfo, 0, sizeof(otherinfo));
4562 memset(&pubinfo, 0, sizeof(pubinfo));
4564 pubinfo.enctype = enctype;
4565 pubinfo.as_REQ = *as_req;
4566 pubinfo.pk_as_rep = *pk_as_rep;
4567 pubinfo.ticket = *ticket;
4568 ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
4569 &pubinfo, &size, ret);
4570 if (ret) {
4571 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4572 return ret;
4574 if (pub.length != size)
4575 krb5_abortx(context, "asn1 compiler internal error");
4577 ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
4578 if (ret) {
4579 free(pub.data);
4580 return ret;
4582 ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
4583 if (ret) {
4584 free(otherinfo.partyUInfo.data);
4585 free(pub.data);
4586 return ret;
4589 otherinfo.algorithmID = *ai;
4590 otherinfo.suppPubInfo = &pub;
4592 ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
4593 &otherinfo, &size, ret);
4594 free(otherinfo.partyUInfo.data);
4595 free(otherinfo.partyVInfo.data);
4596 free(pub.data);
4597 if (ret) {
4598 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4599 return ret;
4601 if (other->length != size)
4602 krb5_abortx(context, "asn1 compiler internal error");
4604 return 0;
4607 krb5_error_code
4608 _krb5_pk_kdf(krb5_context context,
4609 const struct AlgorithmIdentifier *ai,
4610 const void *dhdata,
4611 size_t dhsize,
4612 krb5_const_principal client,
4613 krb5_const_principal server,
4614 krb5_enctype enctype,
4615 const krb5_data *as_req,
4616 const krb5_data *pk_as_rep,
4617 const Ticket *ticket,
4618 krb5_keyblock *key)
4620 struct encryption_type *et;
4621 krb5_error_code ret;
4622 krb5_data other;
4623 size_t keylen, offset;
4624 uint32_t counter;
4625 unsigned char *keydata;
4626 unsigned char shaoutput[SHA_DIGEST_LENGTH];
4627 EVP_MD_CTX *m;
4629 if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) != 0) {
4630 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4631 N_("KDF not supported", ""));
4632 return KRB5_PROG_ETYPE_NOSUPP;
4634 if (ai->parameters != NULL &&
4635 (ai->parameters->length != 2 ||
4636 memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
4638 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4639 N_("kdf params not NULL or the NULL-type",
4640 ""));
4641 return KRB5_PROG_ETYPE_NOSUPP;
4644 et = _find_enctype(enctype);
4645 if(et == NULL) {
4646 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4647 N_("encryption type %d not supported", ""),
4648 enctype);
4649 return KRB5_PROG_ETYPE_NOSUPP;
4651 keylen = (et->keytype->bits + 7) / 8;
4653 keydata = malloc(keylen);
4654 if (keydata == NULL) {
4655 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4656 return ENOMEM;
4659 ret = encode_otherinfo(context, ai, client, server,
4660 enctype, as_req, pk_as_rep, ticket, &other);
4661 if (ret) {
4662 free(keydata);
4663 return ret;
4666 m = EVP_MD_CTX_create();
4667 if (m == NULL) {
4668 free(keydata);
4669 free(other.data);
4670 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4671 return ENOMEM;
4674 offset = 0;
4675 counter = 1;
4676 do {
4677 unsigned char cdata[4];
4679 EVP_DigestInit_ex(m, EVP_sha1(), NULL);
4680 _krb5_put_int(cdata, counter, 4);
4681 EVP_DigestUpdate(m, cdata, 4);
4682 EVP_DigestUpdate(m, dhdata, dhsize);
4683 EVP_DigestUpdate(m, other.data, other.length);
4685 EVP_DigestFinal_ex(m, shaoutput, NULL);
4687 memcpy((unsigned char *)keydata + offset,
4688 shaoutput,
4689 min(keylen - offset, sizeof(shaoutput)));
4691 offset += sizeof(shaoutput);
4692 counter++;
4693 } while(offset < keylen);
4694 memset(shaoutput, 0, sizeof(shaoutput));
4696 EVP_MD_CTX_destroy(m);
4697 free(other.data);
4699 ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
4700 memset(keydata, 0, sizeof(keylen));
4701 free(keydata);
4703 return ret;
4707 krb5_error_code KRB5_LIB_FUNCTION
4708 krb5_crypto_prf_length(krb5_context context,
4709 krb5_enctype type,
4710 size_t *length)
4712 struct encryption_type *et = _find_enctype(type);
4714 if(et == NULL || et->prf_length == 0) {
4715 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4716 N_("encryption type %d not supported", ""),
4717 type);
4718 return KRB5_PROG_ETYPE_NOSUPP;
4721 *length = et->prf_length;
4722 return 0;
4725 krb5_error_code KRB5_LIB_FUNCTION
4726 krb5_crypto_prf(krb5_context context,
4727 const krb5_crypto crypto,
4728 const krb5_data *input,
4729 krb5_data *output)
4731 struct encryption_type *et = crypto->et;
4733 krb5_data_zero(output);
4735 if(et->prf == NULL) {
4736 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4737 "kerberos prf for %s not supported",
4738 et->name);
4739 return KRB5_PROG_ETYPE_NOSUPP;
4742 return (*et->prf)(context, crypto, input, output);
4745 static krb5_error_code
4746 krb5_crypto_prfplus(krb5_context context,
4747 const krb5_crypto crypto,
4748 const krb5_data *input,
4749 size_t length,
4750 krb5_data *output)
4752 krb5_error_code ret;
4753 krb5_data input2;
4754 unsigned char i = 1;
4755 unsigned char *p;
4757 krb5_data_zero(&input2);
4758 krb5_data_zero(output);
4760 krb5_clear_error_message(context);
4762 ret = krb5_data_alloc(output, length);
4763 if (ret) goto out;
4764 ret = krb5_data_alloc(&input2, input->length + 1);
4765 if (ret) goto out;
4767 krb5_clear_error_message(context);
4769 memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
4771 p = output->data;
4773 while (length) {
4774 krb5_data block;
4776 ((unsigned char *)input2.data)[0] = i++;
4778 ret = krb5_crypto_prf(context, crypto, &input2, &block);
4779 if (ret)
4780 goto out;
4782 if (block.length < length) {
4783 memcpy(p, block.data, block.length);
4784 length -= block.length;
4785 } else {
4786 memcpy(p, block.data, length);
4787 length = 0;
4789 p += block.length;
4790 krb5_data_free(&block);
4793 out:
4794 krb5_data_free(&input2);
4795 if (ret)
4796 krb5_data_free(output);
4797 return 0;
4801 * The FX-CF2 key derivation function, used in FAST and preauth framework.
4803 * @param context Kerberos 5 context
4804 * @param crypto1 first key to combine
4805 * @param crypto2 second key to combine
4806 * @param pepper1 factor to combine with first key to garante uniqueness
4807 * @param pepper2 factor to combine with second key to garante uniqueness
4808 * @param enctype the encryption type of the resulting key
4809 * @param res allocated key, free with krb5_free_keyblock_contents()
4811 * @return Return an error code or 0.
4813 * @ingroup krb5_crypto
4816 krb5_error_code KRB5_LIB_FUNCTION
4817 krb5_crypto_fx_cf2(krb5_context context,
4818 const krb5_crypto crypto1,
4819 const krb5_crypto crypto2,
4820 krb5_data *pepper1,
4821 krb5_data *pepper2,
4822 krb5_enctype enctype,
4823 krb5_keyblock *res)
4825 krb5_error_code ret;
4826 krb5_data os1, os2;
4827 size_t i, keysize;
4829 memset(res, 0, sizeof(*res));
4831 ret = krb5_enctype_keysize(context, enctype, &keysize);
4832 if (ret)
4833 return ret;
4835 ret = krb5_data_alloc(&res->keyvalue, keysize);
4836 if (ret)
4837 goto out;
4838 ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
4839 if (ret)
4840 goto out;
4841 ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
4842 if (ret)
4843 goto out;
4845 res->keytype = enctype;
4847 unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
4848 for (i = 0; i < keysize; i++)
4849 p3[i] = p1[i] ^ p2[i];
4851 out:
4852 if (ret)
4853 krb5_data_free(&res->keyvalue);
4854 krb5_data_free(&os1);
4855 krb5_data_free(&os2);
4857 return ret;
4862 #ifndef HEIMDAL_SMALLER
4864 krb5_error_code KRB5_LIB_FUNCTION
4865 krb5_keytype_to_enctypes (krb5_context context,
4866 krb5_keytype keytype,
4867 unsigned *len,
4868 krb5_enctype **val)
4869 KRB5_DEPRECATED
4871 int i;
4872 unsigned n = 0;
4873 krb5_enctype *ret;
4875 for (i = num_etypes - 1; i >= 0; --i) {
4876 if (etypes[i]->keytype->type == keytype
4877 && !(etypes[i]->flags & F_PSEUDO)
4878 && krb5_enctype_valid(context, etypes[i]->type) == 0)
4879 ++n;
4881 if (n == 0) {
4882 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4883 "Keytype have no mapping");
4884 return KRB5_PROG_KEYTYPE_NOSUPP;
4887 ret = malloc(n * sizeof(*ret));
4888 if (ret == NULL && n != 0) {
4889 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
4890 return ENOMEM;
4892 n = 0;
4893 for (i = num_etypes - 1; i >= 0; --i) {
4894 if (etypes[i]->keytype->type == keytype
4895 && !(etypes[i]->flags & F_PSEUDO)
4896 && krb5_enctype_valid(context, etypes[i]->type) == 0)
4897 ret[n++] = etypes[i]->type;
4899 *len = n;
4900 *val = ret;
4901 return 0;
4904 /* if two enctypes have compatible keys */
4905 krb5_boolean KRB5_LIB_FUNCTION
4906 krb5_enctypes_compatible_keys(krb5_context context,
4907 krb5_enctype etype1,
4908 krb5_enctype etype2)
4909 KRB5_DEPRECATED
4911 struct encryption_type *e1 = _find_enctype(etype1);
4912 struct encryption_type *e2 = _find_enctype(etype2);
4913 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
4916 #endif /* HEIMDAL_SMALLER */