Simplify subkey usage for tgs-req, don't rewrite tgs-rep-sub-key keyuage for arcfour...
[heimdal.git] / lib / krb5 / crypto.c
blob8cc7b06026ea2786cde447c3a182ae726c453be9
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
43 struct key_data {
44 krb5_keyblock *key;
45 krb5_data *schedule;
48 struct key_usage {
49 unsigned usage;
50 struct key_data key;
53 struct krb5_crypto_data {
54 struct encryption_type *et;
55 struct key_data key;
56 int num_key_usage;
57 struct key_usage *key_usage;
60 #define CRYPTO_ETYPE(C) ((C)->et->type)
62 /* bits for `flags' below */
63 #define F_KEYED 1 /* checksum is keyed */
64 #define F_CPROOF 2 /* checksum is collision proof */
65 #define F_DERIVED 4 /* uses derived keys */
66 #define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
67 #define F_PSEUDO 16 /* not a real protocol type */
68 #define F_SPECIAL 32 /* backwards */
69 #define F_DISABLED 64 /* enctype/checksum disabled */
71 struct salt_type {
72 krb5_salttype type;
73 const char *name;
74 krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
75 krb5_salt, krb5_data, krb5_keyblock*);
78 struct key_type {
79 krb5_keytype type; /* XXX */
80 const char *name;
81 size_t bits;
82 size_t size;
83 size_t schedule_size;
84 void (*random_key)(krb5_context, krb5_keyblock*);
85 void (*schedule)(krb5_context, struct key_type *, struct key_data *);
86 struct salt_type *string_to_key;
87 void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
88 void (*cleanup)(krb5_context, struct key_data *);
89 const EVP_CIPHER *(*evp)(void);
92 struct checksum_type {
93 krb5_cksumtype type;
94 const char *name;
95 size_t blocksize;
96 size_t checksumsize;
97 unsigned flags;
98 krb5_enctype (*checksum)(krb5_context context,
99 struct key_data *key,
100 const void *buf, size_t len,
101 unsigned usage,
102 Checksum *csum);
103 krb5_error_code (*verify)(krb5_context context,
104 struct key_data *key,
105 const void *buf, size_t len,
106 unsigned usage,
107 Checksum *csum);
110 struct encryption_type {
111 krb5_enctype type;
112 const char *name;
113 size_t blocksize;
114 size_t padsize;
115 size_t confoundersize;
116 struct key_type *keytype;
117 struct checksum_type *checksum;
118 struct checksum_type *keyed_checksum;
119 unsigned flags;
120 krb5_error_code (*encrypt)(krb5_context context,
121 struct key_data *key,
122 void *data, size_t len,
123 krb5_boolean encryptp,
124 int usage,
125 void *ivec);
126 size_t prf_length;
127 krb5_error_code (*prf)(krb5_context,
128 krb5_crypto, const krb5_data *, krb5_data *);
131 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
132 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
133 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
135 static struct checksum_type *_find_checksum(krb5_cksumtype type);
136 static struct encryption_type *_find_enctype(krb5_enctype type);
137 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
138 unsigned, struct key_data**);
139 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
140 static krb5_error_code derive_key(krb5_context context,
141 struct encryption_type *et,
142 struct key_data *key,
143 const void *constant,
144 size_t len);
145 static krb5_error_code hmac(krb5_context context,
146 struct checksum_type *cm,
147 const void *data,
148 size_t len,
149 unsigned usage,
150 struct key_data *keyblock,
151 Checksum *result);
152 static void free_key_data(krb5_context,
153 struct key_data *,
154 struct encryption_type *);
155 static void free_key_schedule(krb5_context,
156 struct key_data *,
157 struct encryption_type *);
158 static krb5_error_code usage2arcfour (krb5_context, unsigned *);
159 static void xor (DES_cblock *, const unsigned char *);
161 /************************************************************
163 ************************************************************/
165 struct evp_schedule {
166 EVP_CIPHER_CTX ectx;
167 EVP_CIPHER_CTX dctx;
171 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
173 #ifdef HEIM_WEAK_CRYPTO
174 static void
175 krb5_DES_random_key(krb5_context context,
176 krb5_keyblock *key)
178 DES_cblock *k = key->keyvalue.data;
179 do {
180 krb5_generate_random_block(k, sizeof(DES_cblock));
181 DES_set_odd_parity(k);
182 } while(DES_is_weak_key(k));
185 static void
186 krb5_DES_schedule_old(krb5_context context,
187 struct key_type *kt,
188 struct key_data *key)
190 DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
193 #ifdef ENABLE_AFS_STRING_TO_KEY
195 /* This defines the Andrew string_to_key function. It accepts a password
196 * string as input and converts it via a one-way encryption algorithm to a DES
197 * encryption key. It is compatible with the original Andrew authentication
198 * service password database.
202 * Short passwords, i.e 8 characters or less.
204 static void
205 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
206 krb5_data cell,
207 DES_cblock *key)
209 char password[8+1]; /* crypt is limited to 8 chars anyway */
210 int i;
212 for(i = 0; i < 8; i++) {
213 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
214 ((i < cell.length) ?
215 tolower(((unsigned char*)cell.data)[i]) : 0);
216 password[i] = c ? c : 'X';
218 password[8] = '\0';
220 memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
222 /* parity is inserted into the LSB so left shift each byte up one
223 bit. This allows ascii characters with a zero MSB to retain as
224 much significance as possible. */
225 for (i = 0; i < sizeof(DES_cblock); i++)
226 ((unsigned char*)key)[i] <<= 1;
227 DES_set_odd_parity (key);
231 * Long passwords, i.e 9 characters or more.
233 static void
234 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
235 krb5_data cell,
236 DES_cblock *key)
238 DES_key_schedule schedule;
239 DES_cblock temp_key;
240 DES_cblock ivec;
241 char password[512];
242 size_t passlen;
244 memcpy(password, pw.data, min(pw.length, sizeof(password)));
245 if(pw.length < sizeof(password)) {
246 int len = min(cell.length, sizeof(password) - pw.length);
247 int i;
249 memcpy(password + pw.length, cell.data, len);
250 for (i = pw.length; i < pw.length + len; ++i)
251 password[i] = tolower((unsigned char)password[i]);
253 passlen = min(sizeof(password), pw.length + cell.length);
254 memcpy(&ivec, "kerberos", 8);
255 memcpy(&temp_key, "kerberos", 8);
256 DES_set_odd_parity (&temp_key);
257 DES_set_key_unchecked (&temp_key, &schedule);
258 DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
260 memcpy(&temp_key, &ivec, 8);
261 DES_set_odd_parity (&temp_key);
262 DES_set_key_unchecked (&temp_key, &schedule);
263 DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
264 memset(&schedule, 0, sizeof(schedule));
265 memset(&temp_key, 0, sizeof(temp_key));
266 memset(&ivec, 0, sizeof(ivec));
267 memset(password, 0, sizeof(password));
269 DES_set_odd_parity (key);
272 static krb5_error_code
273 DES_AFS3_string_to_key(krb5_context context,
274 krb5_enctype enctype,
275 krb5_data password,
276 krb5_salt salt,
277 krb5_data opaque,
278 krb5_keyblock *key)
280 DES_cblock tmp;
281 if(password.length > 8)
282 krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
283 else
284 krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
285 key->keytype = enctype;
286 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
287 memset(&key, 0, sizeof(key));
288 return 0;
290 #endif /* ENABLE_AFS_STRING_TO_KEY */
292 static void
293 DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
295 DES_key_schedule schedule;
296 int i;
297 int reverse = 0;
298 unsigned char *p;
300 unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
301 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
302 memset(key, 0, 8);
304 p = (unsigned char*)key;
305 for (i = 0; i < length; i++) {
306 unsigned char tmp = data[i];
307 if (!reverse)
308 *p++ ^= (tmp << 1);
309 else
310 *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
311 if((i % 8) == 7)
312 reverse = !reverse;
314 DES_set_odd_parity(key);
315 if(DES_is_weak_key(key))
316 (*key)[7] ^= 0xF0;
317 DES_set_key_unchecked(key, &schedule);
318 DES_cbc_cksum((void*)data, key, length, &schedule, key);
319 memset(&schedule, 0, sizeof(schedule));
320 DES_set_odd_parity(key);
321 if(DES_is_weak_key(key))
322 (*key)[7] ^= 0xF0;
325 static krb5_error_code
326 krb5_DES_string_to_key(krb5_context context,
327 krb5_enctype enctype,
328 krb5_data password,
329 krb5_salt salt,
330 krb5_data opaque,
331 krb5_keyblock *key)
333 unsigned char *s;
334 size_t len;
335 DES_cblock tmp;
337 #ifdef ENABLE_AFS_STRING_TO_KEY
338 if (opaque.length == 1) {
339 unsigned long v;
340 _krb5_get_int(opaque.data, &v, 1);
341 if (v == 1)
342 return DES_AFS3_string_to_key(context, enctype, password,
343 salt, opaque, key);
345 #endif
347 len = password.length + salt.saltvalue.length;
348 s = malloc(len);
349 if(len > 0 && s == NULL) {
350 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
351 return ENOMEM;
353 memcpy(s, password.data, password.length);
354 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
355 DES_string_to_key_int(s, len, &tmp);
356 key->keytype = enctype;
357 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
358 memset(&tmp, 0, sizeof(tmp));
359 memset(s, 0, len);
360 free(s);
361 return 0;
364 static void
365 krb5_DES_random_to_key(krb5_context context,
366 krb5_keyblock *key,
367 const void *data,
368 size_t size)
370 DES_cblock *k = key->keyvalue.data;
371 memcpy(k, data, key->keyvalue.length);
372 DES_set_odd_parity(k);
373 if(DES_is_weak_key(k))
374 xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
376 #endif
382 static void
383 DES3_random_key(krb5_context context,
384 krb5_keyblock *key)
386 DES_cblock *k = key->keyvalue.data;
387 do {
388 krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
389 DES_set_odd_parity(&k[0]);
390 DES_set_odd_parity(&k[1]);
391 DES_set_odd_parity(&k[2]);
392 } while(DES_is_weak_key(&k[0]) ||
393 DES_is_weak_key(&k[1]) ||
394 DES_is_weak_key(&k[2]));
398 * A = A xor B. A & B are 8 bytes.
401 static void
402 xor (DES_cblock *key, const unsigned char *b)
404 unsigned char *a = (unsigned char*)key;
405 a[0] ^= b[0];
406 a[1] ^= b[1];
407 a[2] ^= b[2];
408 a[3] ^= b[3];
409 a[4] ^= b[4];
410 a[5] ^= b[5];
411 a[6] ^= b[6];
412 a[7] ^= b[7];
415 #ifdef DES3_OLD_ENCTYPE
416 static krb5_error_code
417 DES3_string_to_key(krb5_context context,
418 krb5_enctype enctype,
419 krb5_data password,
420 krb5_salt salt,
421 krb5_data opaque,
422 krb5_keyblock *key)
424 char *str;
425 size_t len;
426 unsigned char tmp[24];
427 DES_cblock keys[3];
428 krb5_error_code ret;
430 len = password.length + salt.saltvalue.length;
431 str = malloc(len);
432 if(len != 0 && str == NULL) {
433 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
434 return ENOMEM;
436 memcpy(str, password.data, password.length);
437 memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
439 DES_cblock ivec;
440 DES_key_schedule s[3];
441 int i;
443 ret = _krb5_n_fold(str, len, tmp, 24);
444 if (ret) {
445 memset(str, 0, len);
446 free(str);
447 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
448 return ret;
451 for(i = 0; i < 3; i++){
452 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
453 DES_set_odd_parity(keys + i);
454 if(DES_is_weak_key(keys + i))
455 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
456 DES_set_key_unchecked(keys + i, &s[i]);
458 memset(&ivec, 0, sizeof(ivec));
459 DES_ede3_cbc_encrypt(tmp,
460 tmp, sizeof(tmp),
461 &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
462 memset(s, 0, sizeof(s));
463 memset(&ivec, 0, sizeof(ivec));
464 for(i = 0; i < 3; i++){
465 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
466 DES_set_odd_parity(keys + i);
467 if(DES_is_weak_key(keys + i))
468 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
470 memset(tmp, 0, sizeof(tmp));
472 key->keytype = enctype;
473 krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
474 memset(keys, 0, sizeof(keys));
475 memset(str, 0, len);
476 free(str);
477 return 0;
479 #endif
481 static krb5_error_code
482 DES3_string_to_key_derived(krb5_context context,
483 krb5_enctype enctype,
484 krb5_data password,
485 krb5_salt salt,
486 krb5_data opaque,
487 krb5_keyblock *key)
489 krb5_error_code ret;
490 size_t len = password.length + salt.saltvalue.length;
491 char *s;
493 s = malloc(len);
494 if(len != 0 && s == NULL) {
495 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
496 return ENOMEM;
498 memcpy(s, password.data, password.length);
499 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
500 ret = krb5_string_to_key_derived(context,
502 len,
503 enctype,
504 key);
505 memset(s, 0, len);
506 free(s);
507 return ret;
510 static void
511 DES3_random_to_key(krb5_context context,
512 krb5_keyblock *key,
513 const void *data,
514 size_t size)
516 unsigned char *x = key->keyvalue.data;
517 const u_char *q = data;
518 DES_cblock *k;
519 int i, j;
521 memset(x, 0, sizeof(x));
522 for (i = 0; i < 3; ++i) {
523 unsigned char foo;
524 for (j = 0; j < 7; ++j) {
525 unsigned char b = q[7 * i + j];
527 x[8 * i + j] = b;
529 foo = 0;
530 for (j = 6; j >= 0; --j) {
531 foo |= q[7 * i + j] & 1;
532 foo <<= 1;
534 x[8 * i + 7] = foo;
536 k = key->keyvalue.data;
537 for (i = 0; i < 3; i++) {
538 DES_set_odd_parity(&k[i]);
539 if(DES_is_weak_key(&k[i]))
540 xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
545 * ARCFOUR
548 static krb5_error_code
549 ARCFOUR_string_to_key(krb5_context context,
550 krb5_enctype enctype,
551 krb5_data password,
552 krb5_salt salt,
553 krb5_data opaque,
554 krb5_keyblock *key)
556 krb5_error_code ret;
557 uint16_t *s = NULL;
558 size_t len, i;
559 EVP_MD_CTX *m;
561 m = EVP_MD_CTX_create();
562 if (m == NULL) {
563 ret = ENOMEM;
564 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
565 goto out;
568 EVP_DigestInit_ex(m, EVP_md4(), NULL);
570 ret = wind_utf8ucs2_length(password.data, &len);
571 if (ret) {
572 krb5_set_error_message (context, ret,
573 N_("Password not an UCS2 string", ""));
574 goto out;
577 s = malloc (len * sizeof(s[0]));
578 if (len != 0 && s == NULL) {
579 krb5_set_error_message (context, ENOMEM,
580 N_("malloc: out of memory", ""));
581 ret = ENOMEM;
582 goto out;
585 ret = wind_utf8ucs2(password.data, s, &len);
586 if (ret) {
587 krb5_set_error_message (context, ret,
588 N_("Password not an UCS2 string", ""));
589 goto out;
592 /* LE encoding */
593 for (i = 0; i < len; i++) {
594 unsigned char p;
595 p = (s[i] & 0xff);
596 EVP_DigestUpdate (m, &p, 1);
597 p = (s[i] >> 8) & 0xff;
598 EVP_DigestUpdate (m, &p, 1);
601 key->keytype = enctype;
602 ret = krb5_data_alloc (&key->keyvalue, 16);
603 if (ret) {
604 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
605 goto out;
607 EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
609 out:
610 EVP_MD_CTX_destroy(m);
611 if (s)
612 memset (s, 0, len);
613 free (s);
614 return ret;
618 * AES
621 int _krb5_AES_string_to_default_iterator = 4096;
623 static krb5_error_code
624 AES_string_to_key(krb5_context context,
625 krb5_enctype enctype,
626 krb5_data password,
627 krb5_salt salt,
628 krb5_data opaque,
629 krb5_keyblock *key)
631 krb5_error_code ret;
632 uint32_t iter;
633 struct encryption_type *et;
634 struct key_data kd;
636 if (opaque.length == 0)
637 iter = _krb5_AES_string_to_default_iterator;
638 else if (opaque.length == 4) {
639 unsigned long v;
640 _krb5_get_int(opaque.data, &v, 4);
641 iter = ((uint32_t)v);
642 } else
643 return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
645 et = _find_enctype(enctype);
646 if (et == NULL)
647 return KRB5_PROG_KEYTYPE_NOSUPP;
649 kd.schedule = NULL;
650 ALLOC(kd.key, 1);
651 if(kd.key == NULL) {
652 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
653 return ENOMEM;
655 kd.key->keytype = enctype;
656 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
657 if (ret) {
658 krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
659 return ret;
662 ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
663 salt.saltvalue.data, salt.saltvalue.length,
664 iter,
665 et->keytype->size, kd.key->keyvalue.data);
666 if (ret != 1) {
667 free_key_data(context, &kd, et);
668 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
669 "Error calculating s2k");
670 return KRB5_PROG_KEYTYPE_NOSUPP;
673 ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
674 if (ret == 0)
675 ret = krb5_copy_keyblock_contents(context, kd.key, key);
676 free_key_data(context, &kd, et);
678 return ret;
681 static void
682 evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd)
684 struct evp_schedule *key = kd->schedule->data;
685 const EVP_CIPHER *c = (*kt->evp)();
687 EVP_CIPHER_CTX_init(&key->ectx);
688 EVP_CIPHER_CTX_init(&key->dctx);
690 EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
691 EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
694 static void
695 evp_cleanup(krb5_context context, struct key_data *kd)
697 struct evp_schedule *key = kd->schedule->data;
698 EVP_CIPHER_CTX_cleanup(&key->ectx);
699 EVP_CIPHER_CTX_cleanup(&key->dctx);
706 #ifdef HEIM_WEAK_CRYPTO
707 static struct salt_type des_salt[] = {
709 KRB5_PW_SALT,
710 "pw-salt",
711 krb5_DES_string_to_key
713 #ifdef ENABLE_AFS_STRING_TO_KEY
715 KRB5_AFS3_SALT,
716 "afs3-salt",
717 DES_AFS3_string_to_key
719 #endif
720 { 0 }
722 #endif
724 #ifdef DES3_OLD_ENCTYPE
725 static struct salt_type des3_salt[] = {
727 KRB5_PW_SALT,
728 "pw-salt",
729 DES3_string_to_key
731 { 0 }
733 #endif
735 static struct salt_type des3_salt_derived[] = {
737 KRB5_PW_SALT,
738 "pw-salt",
739 DES3_string_to_key_derived
741 { 0 }
744 static struct salt_type AES_salt[] = {
746 KRB5_PW_SALT,
747 "pw-salt",
748 AES_string_to_key
750 { 0 }
753 static struct salt_type arcfour_salt[] = {
755 KRB5_PW_SALT,
756 "pw-salt",
757 ARCFOUR_string_to_key
759 { 0 }
766 static struct key_type keytype_null = {
767 KEYTYPE_NULL,
768 "null",
772 NULL,
773 NULL,
774 NULL
777 #ifdef HEIM_WEAK_CRYPTO
778 static struct key_type keytype_des_old = {
779 KEYTYPE_DES,
780 "des-old",
783 sizeof(DES_key_schedule),
784 krb5_DES_random_key,
785 krb5_DES_schedule_old,
786 des_salt,
787 krb5_DES_random_to_key
790 static struct key_type keytype_des = {
791 KEYTYPE_DES,
792 "des",
795 sizeof(struct evp_schedule),
796 krb5_DES_random_key,
797 evp_schedule,
798 des_salt,
799 krb5_DES_random_to_key,
800 evp_cleanup,
801 EVP_des_cbc
803 #endif /* HEIM_WEAK_CRYPTO */
805 #ifdef DES3_OLD_ENCTYPE
806 static struct key_type keytype_des3 = {
807 KEYTYPE_DES3,
808 "des3",
809 168,
811 sizeof(struct evp_schedule),
812 DES3_random_key,
813 evp_schedule,
814 des3_salt,
815 DES3_random_to_key,
816 evp_cleanup,
817 EVP_des_ede3_cbc
819 #endif
821 static struct key_type keytype_des3_derived = {
822 KEYTYPE_DES3,
823 "des3",
824 168,
826 sizeof(struct evp_schedule),
827 DES3_random_key,
828 evp_schedule,
829 des3_salt_derived,
830 DES3_random_to_key,
831 evp_cleanup,
832 EVP_des_ede3_cbc
835 static struct key_type keytype_aes128 = {
836 KEYTYPE_AES128,
837 "aes-128",
838 128,
840 sizeof(struct evp_schedule),
841 NULL,
842 evp_schedule,
843 AES_salt,
844 NULL,
845 evp_cleanup,
846 EVP_aes_128_cbc
849 static struct key_type keytype_aes256 = {
850 KEYTYPE_AES256,
851 "aes-256",
852 256,
854 sizeof(struct evp_schedule),
855 NULL,
856 evp_schedule,
857 AES_salt,
858 NULL,
859 evp_cleanup,
860 EVP_aes_256_cbc
863 static struct key_type keytype_arcfour = {
864 KEYTYPE_ARCFOUR,
865 "arcfour",
866 128,
868 sizeof(struct evp_schedule),
869 NULL,
870 evp_schedule,
871 arcfour_salt,
872 NULL,
873 evp_cleanup,
874 EVP_rc4
877 krb5_error_code KRB5_LIB_FUNCTION
878 krb5_salttype_to_string (krb5_context context,
879 krb5_enctype etype,
880 krb5_salttype stype,
881 char **string)
883 struct encryption_type *e;
884 struct salt_type *st;
886 e = _find_enctype (etype);
887 if (e == NULL) {
888 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
889 "encryption type %d not supported",
890 etype);
891 return KRB5_PROG_ETYPE_NOSUPP;
893 for (st = e->keytype->string_to_key; st && st->type; st++) {
894 if (st->type == stype) {
895 *string = strdup (st->name);
896 if (*string == NULL) {
897 krb5_set_error_message (context, ENOMEM,
898 N_("malloc: out of memory", ""));
899 return ENOMEM;
901 return 0;
904 krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
905 "salttype %d not supported", stype);
906 return HEIM_ERR_SALTTYPE_NOSUPP;
909 krb5_error_code KRB5_LIB_FUNCTION
910 krb5_string_to_salttype (krb5_context context,
911 krb5_enctype etype,
912 const char *string,
913 krb5_salttype *salttype)
915 struct encryption_type *e;
916 struct salt_type *st;
918 e = _find_enctype (etype);
919 if (e == NULL) {
920 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
921 N_("encryption type %d not supported", ""),
922 etype);
923 return KRB5_PROG_ETYPE_NOSUPP;
925 for (st = e->keytype->string_to_key; st && st->type; st++) {
926 if (strcasecmp (st->name, string) == 0) {
927 *salttype = st->type;
928 return 0;
931 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
932 N_("salttype %s not supported", ""), string);
933 return HEIM_ERR_SALTTYPE_NOSUPP;
936 krb5_error_code KRB5_LIB_FUNCTION
937 krb5_get_pw_salt(krb5_context context,
938 krb5_const_principal principal,
939 krb5_salt *salt)
941 size_t len;
942 int i;
943 krb5_error_code ret;
944 char *p;
946 salt->salttype = KRB5_PW_SALT;
947 len = strlen(principal->realm);
948 for (i = 0; i < principal->name.name_string.len; ++i)
949 len += strlen(principal->name.name_string.val[i]);
950 ret = krb5_data_alloc (&salt->saltvalue, len);
951 if (ret)
952 return ret;
953 p = salt->saltvalue.data;
954 memcpy (p, principal->realm, strlen(principal->realm));
955 p += strlen(principal->realm);
956 for (i = 0; i < principal->name.name_string.len; ++i) {
957 memcpy (p,
958 principal->name.name_string.val[i],
959 strlen(principal->name.name_string.val[i]));
960 p += strlen(principal->name.name_string.val[i]);
962 return 0;
965 krb5_error_code KRB5_LIB_FUNCTION
966 krb5_free_salt(krb5_context context,
967 krb5_salt salt)
969 krb5_data_free(&salt.saltvalue);
970 return 0;
973 krb5_error_code KRB5_LIB_FUNCTION
974 krb5_string_to_key_data (krb5_context context,
975 krb5_enctype enctype,
976 krb5_data password,
977 krb5_principal principal,
978 krb5_keyblock *key)
980 krb5_error_code ret;
981 krb5_salt salt;
983 ret = krb5_get_pw_salt(context, principal, &salt);
984 if(ret)
985 return ret;
986 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
987 krb5_free_salt(context, salt);
988 return ret;
991 krb5_error_code KRB5_LIB_FUNCTION
992 krb5_string_to_key (krb5_context context,
993 krb5_enctype enctype,
994 const char *password,
995 krb5_principal principal,
996 krb5_keyblock *key)
998 krb5_data pw;
999 pw.data = rk_UNCONST(password);
1000 pw.length = strlen(password);
1001 return krb5_string_to_key_data(context, enctype, pw, principal, key);
1004 krb5_error_code KRB5_LIB_FUNCTION
1005 krb5_string_to_key_data_salt (krb5_context context,
1006 krb5_enctype enctype,
1007 krb5_data password,
1008 krb5_salt salt,
1009 krb5_keyblock *key)
1011 krb5_data opaque;
1012 krb5_data_zero(&opaque);
1013 return krb5_string_to_key_data_salt_opaque(context, enctype, password,
1014 salt, opaque, key);
1018 * Do a string -> key for encryption type `enctype' operation on
1019 * `password' (with salt `salt' and the enctype specific data string
1020 * `opaque'), returning the resulting key in `key'
1023 krb5_error_code KRB5_LIB_FUNCTION
1024 krb5_string_to_key_data_salt_opaque (krb5_context context,
1025 krb5_enctype enctype,
1026 krb5_data password,
1027 krb5_salt salt,
1028 krb5_data opaque,
1029 krb5_keyblock *key)
1031 struct encryption_type *et =_find_enctype(enctype);
1032 struct salt_type *st;
1033 if(et == NULL) {
1034 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1035 N_("encryption type %d not supported", ""),
1036 enctype);
1037 return KRB5_PROG_ETYPE_NOSUPP;
1039 for(st = et->keytype->string_to_key; st && st->type; st++)
1040 if(st->type == salt.salttype)
1041 return (*st->string_to_key)(context, enctype, password,
1042 salt, opaque, key);
1043 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
1044 N_("salt type %d not supported", ""),
1045 salt.salttype);
1046 return HEIM_ERR_SALTTYPE_NOSUPP;
1050 * Do a string -> key for encryption type `enctype' operation on the
1051 * string `password' (with salt `salt'), returning the resulting key
1052 * in `key'
1055 krb5_error_code KRB5_LIB_FUNCTION
1056 krb5_string_to_key_salt (krb5_context context,
1057 krb5_enctype enctype,
1058 const char *password,
1059 krb5_salt salt,
1060 krb5_keyblock *key)
1062 krb5_data pw;
1063 pw.data = rk_UNCONST(password);
1064 pw.length = strlen(password);
1065 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
1068 krb5_error_code KRB5_LIB_FUNCTION
1069 krb5_string_to_key_salt_opaque (krb5_context context,
1070 krb5_enctype enctype,
1071 const char *password,
1072 krb5_salt salt,
1073 krb5_data opaque,
1074 krb5_keyblock *key)
1076 krb5_data pw;
1077 pw.data = rk_UNCONST(password);
1078 pw.length = strlen(password);
1079 return krb5_string_to_key_data_salt_opaque(context, enctype,
1080 pw, salt, opaque, key);
1083 krb5_error_code KRB5_LIB_FUNCTION
1084 krb5_enctype_keysize(krb5_context context,
1085 krb5_enctype type,
1086 size_t *keysize)
1088 struct encryption_type *et = _find_enctype(type);
1089 if(et == NULL) {
1090 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1091 N_("encryption type %d not supported", ""),
1092 type);
1093 return KRB5_PROG_ETYPE_NOSUPP;
1095 *keysize = et->keytype->size;
1096 return 0;
1099 krb5_error_code KRB5_LIB_FUNCTION
1100 krb5_enctype_keybits(krb5_context context,
1101 krb5_enctype type,
1102 size_t *keybits)
1104 struct encryption_type *et = _find_enctype(type);
1105 if(et == NULL) {
1106 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1107 "encryption type %d not supported",
1108 type);
1109 return KRB5_PROG_ETYPE_NOSUPP;
1111 *keybits = et->keytype->bits;
1112 return 0;
1115 krb5_error_code KRB5_LIB_FUNCTION
1116 krb5_generate_random_keyblock(krb5_context context,
1117 krb5_enctype type,
1118 krb5_keyblock *key)
1120 krb5_error_code ret;
1121 struct encryption_type *et = _find_enctype(type);
1122 if(et == NULL) {
1123 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1124 N_("encryption type %d not supported", ""),
1125 type);
1126 return KRB5_PROG_ETYPE_NOSUPP;
1128 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
1129 if(ret)
1130 return ret;
1131 key->keytype = type;
1132 if(et->keytype->random_key)
1133 (*et->keytype->random_key)(context, key);
1134 else
1135 krb5_generate_random_block(key->keyvalue.data,
1136 key->keyvalue.length);
1137 return 0;
1140 static krb5_error_code
1141 _key_schedule(krb5_context context,
1142 struct key_data *key)
1144 krb5_error_code ret;
1145 struct encryption_type *et = _find_enctype(key->key->keytype);
1146 struct key_type *kt;
1148 if (et == NULL) {
1149 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
1150 N_("encryption type %d not supported", ""),
1151 key->key->keytype);
1152 return KRB5_PROG_ETYPE_NOSUPP;
1155 kt = et->keytype;
1157 if(kt->schedule == NULL)
1158 return 0;
1159 if (key->schedule != NULL)
1160 return 0;
1161 ALLOC(key->schedule, 1);
1162 if(key->schedule == NULL) {
1163 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1164 return ENOMEM;
1166 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
1167 if(ret) {
1168 free(key->schedule);
1169 key->schedule = NULL;
1170 return ret;
1172 (*kt->schedule)(context, kt, key);
1173 return 0;
1176 /************************************************************
1178 ************************************************************/
1180 static krb5_error_code
1181 NONE_checksum(krb5_context context,
1182 struct key_data *key,
1183 const void *data,
1184 size_t len,
1185 unsigned usage,
1186 Checksum *C)
1188 return 0;
1191 #if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO)
1193 static krb5_error_code
1194 des_checksum(krb5_context context,
1195 const EVP_MD *evp_md,
1196 struct key_data *key,
1197 const void *data,
1198 size_t len,
1199 Checksum *cksum)
1201 struct evp_schedule *ctx = key->schedule->data;
1202 EVP_MD_CTX *m;
1203 DES_cblock ivec;
1204 unsigned char *p = cksum->checksum.data;
1206 krb5_generate_random_block(p, 8);
1208 m = EVP_MD_CTX_create();
1209 if (m == NULL) {
1210 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1211 return ENOMEM;
1214 EVP_DigestInit_ex(m, evp_md, NULL);
1215 EVP_DigestUpdate(m, p, 8);
1216 EVP_DigestUpdate(m, data, len);
1217 EVP_DigestFinal_ex (m, p + 8, NULL);
1218 EVP_MD_CTX_destroy(m);
1219 memset (&ivec, 0, sizeof(ivec));
1220 EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
1221 EVP_Cipher(&ctx->ectx, p, p, 24);
1223 return 0;
1226 static krb5_error_code
1227 des_verify(krb5_context context,
1228 const EVP_MD *evp_md,
1229 struct key_data *key,
1230 const void *data,
1231 size_t len,
1232 Checksum *C)
1234 struct evp_schedule *ctx = key->schedule->data;
1235 EVP_MD_CTX *m;
1236 unsigned char tmp[24];
1237 unsigned char res[16];
1238 DES_cblock ivec;
1239 krb5_error_code ret = 0;
1241 m = EVP_MD_CTX_create();
1242 if (m == NULL) {
1243 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1244 return ENOMEM;
1247 memset(&ivec, 0, sizeof(ivec));
1248 EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
1249 EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
1251 EVP_DigestInit_ex(m, evp_md, NULL);
1252 EVP_DigestUpdate(m, tmp, 8); /* confounder */
1253 EVP_DigestUpdate(m, data, len);
1254 EVP_DigestFinal_ex (m, res, NULL);
1255 EVP_MD_CTX_destroy(m);
1256 if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) {
1257 krb5_clear_error_message (context);
1258 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1260 memset(tmp, 0, sizeof(tmp));
1261 memset(res, 0, sizeof(res));
1262 return ret;
1265 #endif
1267 #ifdef HEIM_WEAK_CRYPTO
1269 static krb5_error_code
1270 CRC32_checksum(krb5_context context,
1271 struct key_data *key,
1272 const void *data,
1273 size_t len,
1274 unsigned usage,
1275 Checksum *C)
1277 uint32_t crc;
1278 unsigned char *r = C->checksum.data;
1279 _krb5_crc_init_table ();
1280 crc = _krb5_crc_update (data, len, 0);
1281 r[0] = crc & 0xff;
1282 r[1] = (crc >> 8) & 0xff;
1283 r[2] = (crc >> 16) & 0xff;
1284 r[3] = (crc >> 24) & 0xff;
1285 return 0;
1288 static krb5_error_code
1289 RSA_MD4_checksum(krb5_context context,
1290 struct key_data *key,
1291 const void *data,
1292 size_t len,
1293 unsigned usage,
1294 Checksum *C)
1296 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
1297 krb5_abortx(context, "md4 checksum failed");
1298 return 0;
1301 static krb5_error_code
1302 RSA_MD4_DES_checksum(krb5_context context,
1303 struct key_data *key,
1304 const void *data,
1305 size_t len,
1306 unsigned usage,
1307 Checksum *cksum)
1309 return des_checksum(context, EVP_md4(), key, data, len, cksum);
1312 static krb5_error_code
1313 RSA_MD4_DES_verify(krb5_context context,
1314 struct key_data *key,
1315 const void *data,
1316 size_t len,
1317 unsigned usage,
1318 Checksum *C)
1320 return des_verify(context, EVP_md5(), key, data, len, C);
1323 static krb5_error_code
1324 RSA_MD5_DES_checksum(krb5_context context,
1325 struct key_data *key,
1326 const void *data,
1327 size_t len,
1328 unsigned usage,
1329 Checksum *C)
1331 return des_checksum(context, EVP_md5(), key, data, len, C);
1334 static krb5_error_code
1335 RSA_MD5_DES_verify(krb5_context context,
1336 struct key_data *key,
1337 const void *data,
1338 size_t len,
1339 unsigned usage,
1340 Checksum *C)
1342 return des_verify(context, EVP_md5(), key, data, len, C);
1345 #endif /* HEIM_WEAK_CRYPTO */
1347 #ifdef DES3_OLD_ENCTYPE
1348 static krb5_error_code
1349 RSA_MD5_DES3_checksum(krb5_context context,
1350 struct key_data *key,
1351 const void *data,
1352 size_t len,
1353 unsigned usage,
1354 Checksum *C)
1356 return des_checksum(context, EVP_md5(), key, data, len, C);
1359 static krb5_error_code
1360 RSA_MD5_DES3_verify(krb5_context context,
1361 struct key_data *key,
1362 const void *data,
1363 size_t len,
1364 unsigned usage,
1365 Checksum *C)
1367 return des_verify(context, EVP_md5(), key, data, len, C);
1369 #endif
1371 static krb5_error_code
1372 SHA1_checksum(krb5_context context,
1373 struct key_data *key,
1374 const void *data,
1375 size_t len,
1376 unsigned usage,
1377 Checksum *C)
1379 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
1380 krb5_abortx(context, "sha1 checksum failed");
1381 return 0;
1384 /* HMAC according to RFC2104 */
1385 static krb5_error_code
1386 hmac(krb5_context context,
1387 struct checksum_type *cm,
1388 const void *data,
1389 size_t len,
1390 unsigned usage,
1391 struct key_data *keyblock,
1392 Checksum *result)
1394 unsigned char *ipad, *opad;
1395 unsigned char *key;
1396 size_t key_len;
1397 int i;
1399 ipad = malloc(cm->blocksize + len);
1400 if (ipad == NULL)
1401 return ENOMEM;
1402 opad = malloc(cm->blocksize + cm->checksumsize);
1403 if (opad == NULL) {
1404 free(ipad);
1405 return ENOMEM;
1407 memset(ipad, 0x36, cm->blocksize);
1408 memset(opad, 0x5c, cm->blocksize);
1410 if(keyblock->key->keyvalue.length > cm->blocksize){
1411 (*cm->checksum)(context,
1412 keyblock,
1413 keyblock->key->keyvalue.data,
1414 keyblock->key->keyvalue.length,
1415 usage,
1416 result);
1417 key = result->checksum.data;
1418 key_len = result->checksum.length;
1419 } else {
1420 key = keyblock->key->keyvalue.data;
1421 key_len = keyblock->key->keyvalue.length;
1423 for(i = 0; i < key_len; i++){
1424 ipad[i] ^= key[i];
1425 opad[i] ^= key[i];
1427 memcpy(ipad + cm->blocksize, data, len);
1428 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1429 usage, result);
1430 memcpy(opad + cm->blocksize, result->checksum.data,
1431 result->checksum.length);
1432 (*cm->checksum)(context, keyblock, opad,
1433 cm->blocksize + cm->checksumsize, usage, result);
1434 memset(ipad, 0, cm->blocksize + len);
1435 free(ipad);
1436 memset(opad, 0, cm->blocksize + cm->checksumsize);
1437 free(opad);
1439 return 0;
1442 krb5_error_code KRB5_LIB_FUNCTION
1443 krb5_hmac(krb5_context context,
1444 krb5_cksumtype cktype,
1445 const void *data,
1446 size_t len,
1447 unsigned usage,
1448 krb5_keyblock *key,
1449 Checksum *result)
1451 struct checksum_type *c = _find_checksum(cktype);
1452 struct key_data kd;
1453 krb5_error_code ret;
1455 if (c == NULL) {
1456 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1457 N_("checksum type %d not supported", ""),
1458 cktype);
1459 return KRB5_PROG_SUMTYPE_NOSUPP;
1462 kd.key = key;
1463 kd.schedule = NULL;
1465 ret = hmac(context, c, data, len, usage, &kd, result);
1467 if (kd.schedule)
1468 krb5_free_data(context, kd.schedule);
1470 return ret;
1473 static krb5_error_code
1474 SP_HMAC_SHA1_checksum(krb5_context context,
1475 struct key_data *key,
1476 const void *data,
1477 size_t len,
1478 unsigned usage,
1479 Checksum *result)
1481 struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1482 Checksum res;
1483 char sha1_data[20];
1484 krb5_error_code ret;
1486 res.checksum.data = sha1_data;
1487 res.checksum.length = sizeof(sha1_data);
1489 ret = hmac(context, c, data, len, usage, key, &res);
1490 if (ret)
1491 krb5_abortx(context, "hmac failed");
1492 memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
1493 return 0;
1497 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1500 static krb5_error_code
1501 HMAC_MD5_checksum(krb5_context context,
1502 struct key_data *key,
1503 const void *data,
1504 size_t len,
1505 unsigned usage,
1506 Checksum *result)
1508 EVP_MD_CTX *m;
1509 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1510 const char signature[] = "signaturekey";
1511 Checksum ksign_c;
1512 struct key_data ksign;
1513 krb5_keyblock kb;
1514 unsigned char t[4];
1515 unsigned char tmp[16];
1516 unsigned char ksign_c_data[16];
1517 krb5_error_code ret;
1519 m = EVP_MD_CTX_create();
1520 if (m == NULL) {
1521 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1522 return ENOMEM;
1524 ksign_c.checksum.length = sizeof(ksign_c_data);
1525 ksign_c.checksum.data = ksign_c_data;
1526 ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1527 if (ret) {
1528 EVP_MD_CTX_destroy(m);
1529 return ret;
1531 ksign.key = &kb;
1532 kb.keyvalue = ksign_c.checksum;
1533 EVP_DigestInit_ex(m, EVP_md5(), NULL);
1534 t[0] = (usage >> 0) & 0xFF;
1535 t[1] = (usage >> 8) & 0xFF;
1536 t[2] = (usage >> 16) & 0xFF;
1537 t[3] = (usage >> 24) & 0xFF;
1538 EVP_DigestUpdate(m, t, 4);
1539 EVP_DigestUpdate(m, data, len);
1540 EVP_DigestFinal_ex (m, tmp, NULL);
1541 EVP_MD_CTX_destroy(m);
1543 ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1544 if (ret)
1545 return ret;
1546 return 0;
1549 static struct checksum_type checksum_none = {
1550 CKSUMTYPE_NONE,
1551 "none",
1555 NONE_checksum,
1556 NULL
1558 #ifdef HEIM_WEAK_CRYPTO
1559 static struct checksum_type checksum_crc32 = {
1560 CKSUMTYPE_CRC32,
1561 "crc32",
1565 CRC32_checksum,
1566 NULL
1568 static struct checksum_type checksum_rsa_md4 = {
1569 CKSUMTYPE_RSA_MD4,
1570 "rsa-md4",
1573 F_CPROOF,
1574 RSA_MD4_checksum,
1575 NULL
1577 static struct checksum_type checksum_rsa_md4_des = {
1578 CKSUMTYPE_RSA_MD4_DES,
1579 "rsa-md4-des",
1582 F_KEYED | F_CPROOF | F_VARIANT,
1583 RSA_MD4_DES_checksum,
1584 RSA_MD4_DES_verify
1586 static struct checksum_type checksum_rsa_md5_des = {
1587 CKSUMTYPE_RSA_MD5_DES,
1588 "rsa-md5-des",
1591 F_KEYED | F_CPROOF | F_VARIANT,
1592 RSA_MD5_DES_checksum,
1593 RSA_MD5_DES_verify
1595 #endif /* HEIM_WEAK_CRYPTO */
1597 static krb5_error_code
1598 RSA_MD5_checksum(krb5_context context,
1599 struct key_data *key,
1600 const void *data,
1601 size_t len,
1602 unsigned usage,
1603 Checksum *C)
1605 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
1606 krb5_abortx(context, "md5 checksum failed");
1607 return 0;
1610 static struct checksum_type checksum_rsa_md5 = {
1611 CKSUMTYPE_RSA_MD5,
1612 "rsa-md5",
1615 F_CPROOF,
1616 RSA_MD5_checksum,
1617 NULL
1620 #ifdef DES3_OLD_ENCTYPE
1621 static struct checksum_type checksum_rsa_md5_des3 = {
1622 CKSUMTYPE_RSA_MD5_DES3,
1623 "rsa-md5-des3",
1626 F_KEYED | F_CPROOF | F_VARIANT,
1627 RSA_MD5_DES3_checksum,
1628 RSA_MD5_DES3_verify
1630 #endif
1631 static struct checksum_type checksum_sha1 = {
1632 CKSUMTYPE_SHA1,
1633 "sha1",
1636 F_CPROOF,
1637 SHA1_checksum,
1638 NULL
1640 static struct checksum_type checksum_hmac_sha1_des3 = {
1641 CKSUMTYPE_HMAC_SHA1_DES3,
1642 "hmac-sha1-des3",
1645 F_KEYED | F_CPROOF | F_DERIVED,
1646 SP_HMAC_SHA1_checksum,
1647 NULL
1650 static struct checksum_type checksum_hmac_sha1_aes128 = {
1651 CKSUMTYPE_HMAC_SHA1_96_AES_128,
1652 "hmac-sha1-96-aes128",
1655 F_KEYED | F_CPROOF | F_DERIVED,
1656 SP_HMAC_SHA1_checksum,
1657 NULL
1660 static struct checksum_type checksum_hmac_sha1_aes256 = {
1661 CKSUMTYPE_HMAC_SHA1_96_AES_256,
1662 "hmac-sha1-96-aes256",
1665 F_KEYED | F_CPROOF | F_DERIVED,
1666 SP_HMAC_SHA1_checksum,
1667 NULL
1670 static struct checksum_type checksum_hmac_md5 = {
1671 CKSUMTYPE_HMAC_MD5,
1672 "hmac-md5",
1675 F_KEYED | F_CPROOF,
1676 HMAC_MD5_checksum,
1677 NULL
1680 static struct checksum_type *checksum_types[] = {
1681 &checksum_none,
1682 #ifdef HEIM_WEAK_CRYPTO
1683 &checksum_crc32,
1684 &checksum_rsa_md4,
1685 &checksum_rsa_md4_des,
1686 &checksum_rsa_md5_des,
1687 #endif
1688 #ifdef DES3_OLD_ENCTYPE
1689 &checksum_rsa_md5_des3,
1690 #endif
1691 &checksum_rsa_md5,
1692 &checksum_sha1,
1693 &checksum_hmac_sha1_des3,
1694 &checksum_hmac_sha1_aes128,
1695 &checksum_hmac_sha1_aes256,
1696 &checksum_hmac_md5
1699 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1701 static struct checksum_type *
1702 _find_checksum(krb5_cksumtype type)
1704 int i;
1705 for(i = 0; i < num_checksums; i++)
1706 if(checksum_types[i]->type == type)
1707 return checksum_types[i];
1708 return NULL;
1711 static krb5_error_code
1712 get_checksum_key(krb5_context context,
1713 krb5_crypto crypto,
1714 unsigned usage, /* not krb5_key_usage */
1715 struct checksum_type *ct,
1716 struct key_data **key)
1718 krb5_error_code ret = 0;
1720 if(ct->flags & F_DERIVED)
1721 ret = _get_derived_key(context, crypto, usage, key);
1722 else if(ct->flags & F_VARIANT) {
1723 int i;
1725 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1726 if(*key == NULL) {
1727 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1728 return ENOMEM;
1730 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1731 if(ret)
1732 return ret;
1733 for(i = 0; i < (*key)->key->keyvalue.length; i++)
1734 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1735 } else {
1736 *key = &crypto->key;
1738 if(ret == 0)
1739 ret = _key_schedule(context, *key);
1740 return ret;
1743 static krb5_error_code
1744 create_checksum (krb5_context context,
1745 struct checksum_type *ct,
1746 krb5_crypto crypto,
1747 unsigned usage,
1748 void *data,
1749 size_t len,
1750 Checksum *result)
1752 krb5_error_code ret;
1753 struct key_data *dkey;
1754 int keyed_checksum;
1756 if (ct->flags & F_DISABLED) {
1757 krb5_clear_error_message (context);
1758 return KRB5_PROG_SUMTYPE_NOSUPP;
1760 keyed_checksum = (ct->flags & F_KEYED) != 0;
1761 if(keyed_checksum && crypto == NULL) {
1762 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1763 N_("Checksum type %s is keyed but no "
1764 "crypto context (key) was passed in", ""),
1765 ct->name);
1766 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1768 if(keyed_checksum) {
1769 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1770 if (ret)
1771 return ret;
1772 } else
1773 dkey = NULL;
1774 result->cksumtype = ct->type;
1775 ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1776 if (ret)
1777 return (ret);
1778 return (*ct->checksum)(context, dkey, data, len, usage, result);
1781 static int
1782 arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
1784 return (ct->type == CKSUMTYPE_HMAC_MD5) &&
1785 (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
1788 krb5_error_code KRB5_LIB_FUNCTION
1789 krb5_create_checksum(krb5_context context,
1790 krb5_crypto crypto,
1791 krb5_key_usage usage,
1792 int type,
1793 void *data,
1794 size_t len,
1795 Checksum *result)
1797 struct checksum_type *ct = NULL;
1798 unsigned keyusage;
1800 /* type 0 -> pick from crypto */
1801 if (type) {
1802 ct = _find_checksum(type);
1803 } else if (crypto) {
1804 ct = crypto->et->keyed_checksum;
1805 if (ct == NULL)
1806 ct = crypto->et->checksum;
1809 if(ct == NULL) {
1810 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1811 N_("checksum type %d not supported", ""),
1812 type);
1813 return KRB5_PROG_SUMTYPE_NOSUPP;
1816 if (arcfour_checksum_p(ct, crypto)) {
1817 keyusage = usage;
1818 usage2arcfour(context, &keyusage);
1819 } else
1820 keyusage = CHECKSUM_USAGE(usage);
1822 return create_checksum(context, ct, crypto, keyusage,
1823 data, len, result);
1826 static krb5_error_code
1827 verify_checksum(krb5_context context,
1828 krb5_crypto crypto,
1829 unsigned usage, /* not krb5_key_usage */
1830 void *data,
1831 size_t len,
1832 Checksum *cksum)
1834 krb5_error_code ret;
1835 struct key_data *dkey;
1836 int keyed_checksum;
1837 Checksum c;
1838 struct checksum_type *ct;
1840 ct = _find_checksum(cksum->cksumtype);
1841 if (ct == NULL || (ct->flags & F_DISABLED)) {
1842 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1843 N_("checksum type %d not supported", ""),
1844 cksum->cksumtype);
1845 return KRB5_PROG_SUMTYPE_NOSUPP;
1847 if(ct->checksumsize != cksum->checksum.length) {
1848 krb5_clear_error_message (context);
1849 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1851 keyed_checksum = (ct->flags & F_KEYED) != 0;
1852 if(keyed_checksum) {
1853 struct checksum_type *kct;
1854 if (crypto == NULL) {
1855 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1856 N_("Checksum type %s is keyed but no "
1857 "crypto context (key) was passed in", ""),
1858 ct->name);
1859 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1861 kct = crypto->et->keyed_checksum;
1862 if (kct != NULL && kct->type != ct->type) {
1863 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1864 N_("Checksum type %s is keyed, but "
1865 "the key type %s passed didnt have that checksum "
1866 "type as the keyed type", ""),
1867 ct->name, crypto->et->name);
1868 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1871 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1872 if (ret)
1873 return ret;
1874 } else
1875 dkey = NULL;
1876 if(ct->verify)
1877 return (*ct->verify)(context, dkey, data, len, usage, cksum);
1879 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1880 if (ret)
1881 return ret;
1883 ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
1884 if (ret) {
1885 krb5_data_free(&c.checksum);
1886 return ret;
1889 if(c.checksum.length != cksum->checksum.length ||
1890 ct_memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
1891 krb5_clear_error_message (context);
1892 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1893 } else {
1894 ret = 0;
1896 krb5_data_free (&c.checksum);
1897 return ret;
1900 krb5_error_code KRB5_LIB_FUNCTION
1901 krb5_verify_checksum(krb5_context context,
1902 krb5_crypto crypto,
1903 krb5_key_usage usage,
1904 void *data,
1905 size_t len,
1906 Checksum *cksum)
1908 struct checksum_type *ct;
1909 unsigned keyusage;
1911 ct = _find_checksum(cksum->cksumtype);
1912 if(ct == NULL) {
1913 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1914 N_("checksum type %d not supported", ""),
1915 cksum->cksumtype);
1916 return KRB5_PROG_SUMTYPE_NOSUPP;
1919 if (arcfour_checksum_p(ct, crypto)) {
1920 keyusage = usage;
1921 usage2arcfour(context, &keyusage);
1922 } else
1923 keyusage = CHECKSUM_USAGE(usage);
1925 return verify_checksum(context, crypto, keyusage,
1926 data, len, cksum);
1929 krb5_error_code KRB5_LIB_FUNCTION
1930 krb5_crypto_get_checksum_type(krb5_context context,
1931 krb5_crypto crypto,
1932 krb5_cksumtype *type)
1934 struct checksum_type *ct = NULL;
1936 if (crypto != NULL) {
1937 ct = crypto->et->keyed_checksum;
1938 if (ct == NULL)
1939 ct = crypto->et->checksum;
1942 if (ct == NULL) {
1943 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1944 N_("checksum type not found", ""));
1945 return KRB5_PROG_SUMTYPE_NOSUPP;
1948 *type = ct->type;
1950 return 0;
1954 krb5_error_code KRB5_LIB_FUNCTION
1955 krb5_checksumsize(krb5_context context,
1956 krb5_cksumtype type,
1957 size_t *size)
1959 struct checksum_type *ct = _find_checksum(type);
1960 if(ct == NULL) {
1961 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1962 N_("checksum type %d not supported", ""),
1963 type);
1964 return KRB5_PROG_SUMTYPE_NOSUPP;
1966 *size = ct->checksumsize;
1967 return 0;
1970 krb5_boolean KRB5_LIB_FUNCTION
1971 krb5_checksum_is_keyed(krb5_context context,
1972 krb5_cksumtype type)
1974 struct checksum_type *ct = _find_checksum(type);
1975 if(ct == NULL) {
1976 if (context)
1977 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1978 N_("checksum type %d not supported", ""),
1979 type);
1980 return KRB5_PROG_SUMTYPE_NOSUPP;
1982 return ct->flags & F_KEYED;
1985 krb5_boolean KRB5_LIB_FUNCTION
1986 krb5_checksum_is_collision_proof(krb5_context context,
1987 krb5_cksumtype type)
1989 struct checksum_type *ct = _find_checksum(type);
1990 if(ct == NULL) {
1991 if (context)
1992 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1993 N_("checksum type %d not supported", ""),
1994 type);
1995 return KRB5_PROG_SUMTYPE_NOSUPP;
1997 return ct->flags & F_CPROOF;
2000 krb5_error_code KRB5_LIB_FUNCTION
2001 krb5_checksum_disable(krb5_context context,
2002 krb5_cksumtype type)
2004 struct checksum_type *ct = _find_checksum(type);
2005 if(ct == NULL) {
2006 if (context)
2007 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2008 N_("checksum type %d not supported", ""),
2009 type);
2010 return KRB5_PROG_SUMTYPE_NOSUPP;
2012 ct->flags |= F_DISABLED;
2013 return 0;
2016 /************************************************************
2018 ************************************************************/
2020 static krb5_error_code
2021 NULL_encrypt(krb5_context context,
2022 struct key_data *key,
2023 void *data,
2024 size_t len,
2025 krb5_boolean encryptp,
2026 int usage,
2027 void *ivec)
2029 return 0;
2032 static krb5_error_code
2033 evp_encrypt(krb5_context context,
2034 struct key_data *key,
2035 void *data,
2036 size_t len,
2037 krb5_boolean encryptp,
2038 int usage,
2039 void *ivec)
2041 struct evp_schedule *ctx = key->schedule->data;
2042 EVP_CIPHER_CTX *c;
2043 c = encryptp ? &ctx->ectx : &ctx->dctx;
2044 if (ivec == NULL) {
2045 /* alloca ? */
2046 size_t len = EVP_CIPHER_CTX_iv_length(c);
2047 void *loiv = malloc(len);
2048 if (loiv == NULL) {
2049 krb5_clear_error_message(context);
2050 return ENOMEM;
2052 memset(loiv, 0, len);
2053 EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
2054 free(loiv);
2055 } else
2056 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2057 EVP_Cipher(c, data, data, len);
2058 return 0;
2061 static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
2063 static krb5_error_code
2064 evp_encrypt_cts(krb5_context context,
2065 struct key_data *key,
2066 void *data,
2067 size_t len,
2068 krb5_boolean encryptp,
2069 int usage,
2070 void *ivec)
2072 size_t i, blocksize;
2073 struct evp_schedule *ctx = key->schedule->data;
2074 char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
2075 EVP_CIPHER_CTX *c;
2076 unsigned char *p;
2078 c = encryptp ? &ctx->ectx : &ctx->dctx;
2080 blocksize = EVP_CIPHER_CTX_block_size(c);
2082 if (len < blocksize) {
2083 krb5_set_error_message(context, EINVAL,
2084 "message block too short");
2085 return EINVAL;
2086 } else if (len == blocksize) {
2087 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2088 EVP_Cipher(c, data, data, len);
2089 return 0;
2092 if (ivec)
2093 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2094 else
2095 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2097 if (encryptp) {
2099 p = data;
2100 i = ((len - 1) / blocksize) * blocksize;
2101 EVP_Cipher(c, p, p, i);
2102 p += i - blocksize;
2103 len -= i;
2104 memcpy(ivec2, p, blocksize);
2106 for (i = 0; i < len; i++)
2107 tmp[i] = p[i + blocksize] ^ ivec2[i];
2108 for (; i < blocksize; i++)
2109 tmp[i] = 0 ^ ivec2[i];
2111 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2112 EVP_Cipher(c, p, tmp, blocksize);
2114 memcpy(p + blocksize, ivec2, len);
2115 if (ivec)
2116 memcpy(ivec, p, blocksize);
2117 } else {
2118 char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH];
2120 p = data;
2121 if (len > blocksize * 2) {
2122 /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
2123 i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
2124 memcpy(ivec2, p + i - blocksize, blocksize);
2125 EVP_Cipher(c, p, p, i);
2126 p += i;
2127 len -= i + blocksize;
2128 } else {
2129 if (ivec)
2130 memcpy(ivec2, ivec, blocksize);
2131 else
2132 memcpy(ivec2, zero_ivec, blocksize);
2133 len -= blocksize;
2136 memcpy(tmp, p, blocksize);
2137 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2138 EVP_Cipher(c, tmp2, p, blocksize);
2140 memcpy(tmp3, p + blocksize, len);
2141 memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
2143 for (i = 0; i < len; i++)
2144 p[i + blocksize] = tmp2[i] ^ tmp3[i];
2146 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2147 EVP_Cipher(c, p, tmp3, blocksize);
2149 for (i = 0; i < blocksize; i++)
2150 p[i] ^= ivec2[i];
2151 if (ivec)
2152 memcpy(ivec, tmp, blocksize);
2154 return 0;
2157 #ifdef HEIM_WEAK_CRYPTO
2158 static krb5_error_code
2159 evp_des_encrypt_null_ivec(krb5_context context,
2160 struct key_data *key,
2161 void *data,
2162 size_t len,
2163 krb5_boolean encryptp,
2164 int usage,
2165 void *ignore_ivec)
2167 struct evp_schedule *ctx = key->schedule->data;
2168 EVP_CIPHER_CTX *c;
2169 DES_cblock ivec;
2170 memset(&ivec, 0, sizeof(ivec));
2171 c = encryptp ? &ctx->ectx : &ctx->dctx;
2172 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2173 EVP_Cipher(c, data, data, len);
2174 return 0;
2177 static krb5_error_code
2178 evp_des_encrypt_key_ivec(krb5_context context,
2179 struct key_data *key,
2180 void *data,
2181 size_t len,
2182 krb5_boolean encryptp,
2183 int usage,
2184 void *ignore_ivec)
2186 struct evp_schedule *ctx = key->schedule->data;
2187 EVP_CIPHER_CTX *c;
2188 DES_cblock ivec;
2189 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2190 c = encryptp ? &ctx->ectx : &ctx->dctx;
2191 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2192 EVP_Cipher(c, data, data, len);
2193 return 0;
2196 static krb5_error_code
2197 DES_CFB64_encrypt_null_ivec(krb5_context context,
2198 struct key_data *key,
2199 void *data,
2200 size_t len,
2201 krb5_boolean encryptp,
2202 int usage,
2203 void *ignore_ivec)
2205 DES_cblock ivec;
2206 int num = 0;
2207 DES_key_schedule *s = key->schedule->data;
2208 memset(&ivec, 0, sizeof(ivec));
2210 DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
2211 return 0;
2214 static krb5_error_code
2215 DES_PCBC_encrypt_key_ivec(krb5_context context,
2216 struct key_data *key,
2217 void *data,
2218 size_t len,
2219 krb5_boolean encryptp,
2220 int usage,
2221 void *ignore_ivec)
2223 DES_cblock ivec;
2224 DES_key_schedule *s = key->schedule->data;
2225 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2227 DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
2228 return 0;
2230 #endif
2233 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
2235 * warning: not for small children
2238 static krb5_error_code
2239 ARCFOUR_subencrypt(krb5_context context,
2240 struct key_data *key,
2241 void *data,
2242 size_t len,
2243 unsigned usage,
2244 void *ivec)
2246 EVP_CIPHER_CTX ctx;
2247 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2248 Checksum k1_c, k2_c, k3_c, cksum;
2249 struct key_data ke;
2250 krb5_keyblock kb;
2251 unsigned char t[4];
2252 unsigned char *cdata = data;
2253 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2254 krb5_error_code ret;
2256 t[0] = (usage >> 0) & 0xFF;
2257 t[1] = (usage >> 8) & 0xFF;
2258 t[2] = (usage >> 16) & 0xFF;
2259 t[3] = (usage >> 24) & 0xFF;
2261 k1_c.checksum.length = sizeof(k1_c_data);
2262 k1_c.checksum.data = k1_c_data;
2264 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2265 if (ret)
2266 krb5_abortx(context, "hmac failed");
2268 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2270 k2_c.checksum.length = sizeof(k2_c_data);
2271 k2_c.checksum.data = k2_c_data;
2273 ke.key = &kb;
2274 kb.keyvalue = k2_c.checksum;
2276 cksum.checksum.length = 16;
2277 cksum.checksum.data = data;
2279 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2280 if (ret)
2281 krb5_abortx(context, "hmac failed");
2283 ke.key = &kb;
2284 kb.keyvalue = k1_c.checksum;
2286 k3_c.checksum.length = sizeof(k3_c_data);
2287 k3_c.checksum.data = k3_c_data;
2289 ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
2290 if (ret)
2291 krb5_abortx(context, "hmac failed");
2293 EVP_CIPHER_CTX_init(&ctx);
2295 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
2296 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
2297 EVP_CIPHER_CTX_cleanup(&ctx);
2299 memset (k1_c_data, 0, sizeof(k1_c_data));
2300 memset (k2_c_data, 0, sizeof(k2_c_data));
2301 memset (k3_c_data, 0, sizeof(k3_c_data));
2302 return 0;
2305 static krb5_error_code
2306 ARCFOUR_subdecrypt(krb5_context context,
2307 struct key_data *key,
2308 void *data,
2309 size_t len,
2310 unsigned usage,
2311 void *ivec)
2313 EVP_CIPHER_CTX ctx;
2314 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2315 Checksum k1_c, k2_c, k3_c, cksum;
2316 struct key_data ke;
2317 krb5_keyblock kb;
2318 unsigned char t[4];
2319 unsigned char *cdata = data;
2320 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2321 unsigned char cksum_data[16];
2322 krb5_error_code ret;
2324 t[0] = (usage >> 0) & 0xFF;
2325 t[1] = (usage >> 8) & 0xFF;
2326 t[2] = (usage >> 16) & 0xFF;
2327 t[3] = (usage >> 24) & 0xFF;
2329 k1_c.checksum.length = sizeof(k1_c_data);
2330 k1_c.checksum.data = k1_c_data;
2332 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2333 if (ret)
2334 krb5_abortx(context, "hmac failed");
2336 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2338 k2_c.checksum.length = sizeof(k2_c_data);
2339 k2_c.checksum.data = k2_c_data;
2341 ke.key = &kb;
2342 kb.keyvalue = k1_c.checksum;
2344 k3_c.checksum.length = sizeof(k3_c_data);
2345 k3_c.checksum.data = k3_c_data;
2347 ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
2348 if (ret)
2349 krb5_abortx(context, "hmac failed");
2351 EVP_CIPHER_CTX_init(&ctx);
2352 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
2353 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
2354 EVP_CIPHER_CTX_cleanup(&ctx);
2356 ke.key = &kb;
2357 kb.keyvalue = k2_c.checksum;
2359 cksum.checksum.length = 16;
2360 cksum.checksum.data = cksum_data;
2362 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2363 if (ret)
2364 krb5_abortx(context, "hmac failed");
2366 memset (k1_c_data, 0, sizeof(k1_c_data));
2367 memset (k2_c_data, 0, sizeof(k2_c_data));
2368 memset (k3_c_data, 0, sizeof(k3_c_data));
2370 if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
2371 krb5_clear_error_message (context);
2372 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
2373 } else {
2374 return 0;
2379 * convert the usage numbers used in
2380 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2381 * draft-brezak-win2k-krb-rc4-hmac-04.txt
2384 static krb5_error_code
2385 usage2arcfour (krb5_context context, unsigned *usage)
2387 switch (*usage) {
2388 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2389 *usage = 8;
2390 return 0;
2391 case KRB5_KU_USAGE_SEAL : /* 22 */
2392 *usage = 13;
2393 return 0;
2394 case KRB5_KU_USAGE_SIGN : /* 23 */
2395 *usage = 15;
2396 return 0;
2397 case KRB5_KU_USAGE_SEQ: /* 24 */
2398 *usage = 0;
2399 return 0;
2400 default :
2401 return 0;
2405 static krb5_error_code
2406 ARCFOUR_encrypt(krb5_context context,
2407 struct key_data *key,
2408 void *data,
2409 size_t len,
2410 krb5_boolean encryptp,
2411 int usage,
2412 void *ivec)
2414 krb5_error_code ret;
2415 unsigned keyusage = usage;
2417 if((ret = usage2arcfour (context, &keyusage)) != 0)
2418 return ret;
2420 if (encryptp)
2421 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
2422 else
2423 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
2431 static krb5_error_code
2432 AES_PRF(krb5_context context,
2433 krb5_crypto crypto,
2434 const krb5_data *in,
2435 krb5_data *out)
2437 struct checksum_type *ct = crypto->et->checksum;
2438 krb5_error_code ret;
2439 Checksum result;
2440 krb5_keyblock *derived;
2442 result.cksumtype = ct->type;
2443 ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2444 if (ret) {
2445 krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
2446 return ret;
2449 ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2450 if (ret) {
2451 krb5_data_free(&result.checksum);
2452 return ret;
2455 if (result.checksum.length < crypto->et->blocksize)
2456 krb5_abortx(context, "internal prf error");
2458 derived = NULL;
2459 ret = krb5_derive_key(context, crypto->key.key,
2460 crypto->et->type, "prf", 3, &derived);
2461 if (ret)
2462 krb5_abortx(context, "krb5_derive_key");
2464 ret = krb5_data_alloc(out, crypto->et->blocksize);
2465 if (ret)
2466 krb5_abortx(context, "malloc failed");
2469 const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
2470 EVP_CIPHER_CTX ctx;
2472 EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
2473 EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
2474 EVP_Cipher(&ctx, out->data, result.checksum.data,
2475 crypto->et->blocksize);
2476 EVP_CIPHER_CTX_cleanup(&ctx);
2479 krb5_data_free(&result.checksum);
2480 krb5_free_keyblock(context, derived);
2482 return ret;
2486 * these should currently be in reverse preference order.
2487 * (only relevant for !F_PSEUDO) */
2489 static struct encryption_type enctype_null = {
2490 ETYPE_NULL,
2491 "null",
2495 &keytype_null,
2496 &checksum_none,
2497 NULL,
2498 F_DISABLED,
2499 NULL_encrypt,
2501 NULL
2503 static struct encryption_type enctype_arcfour_hmac_md5 = {
2504 ETYPE_ARCFOUR_HMAC_MD5,
2505 "arcfour-hmac-md5",
2509 &keytype_arcfour,
2510 &checksum_hmac_md5,
2511 NULL,
2512 F_SPECIAL,
2513 ARCFOUR_encrypt,
2515 NULL
2517 #ifdef DES3_OLD_ENCTYPE
2518 static struct encryption_type enctype_des3_cbc_md5 = {
2519 ETYPE_DES3_CBC_MD5,
2520 "des3-cbc-md5",
2524 &keytype_des3,
2525 &checksum_rsa_md5,
2526 &checksum_rsa_md5_des3,
2528 evp_encrypt,
2530 NULL
2532 #endif
2533 static struct encryption_type enctype_des3_cbc_sha1 = {
2534 ETYPE_DES3_CBC_SHA1,
2535 "des3-cbc-sha1",
2539 &keytype_des3_derived,
2540 &checksum_sha1,
2541 &checksum_hmac_sha1_des3,
2542 F_DERIVED,
2543 evp_encrypt,
2545 NULL
2547 #ifdef DES3_OLD_ENCTYPE
2548 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2549 ETYPE_OLD_DES3_CBC_SHA1,
2550 "old-des3-cbc-sha1",
2554 &keytype_des3,
2555 &checksum_sha1,
2556 &checksum_hmac_sha1_des3,
2558 evp_encrypt,
2560 NULL
2562 #endif
2563 static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2564 ETYPE_AES128_CTS_HMAC_SHA1_96,
2565 "aes128-cts-hmac-sha1-96",
2569 &keytype_aes128,
2570 &checksum_sha1,
2571 &checksum_hmac_sha1_aes128,
2572 F_DERIVED,
2573 evp_encrypt_cts,
2575 AES_PRF
2577 static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2578 ETYPE_AES256_CTS_HMAC_SHA1_96,
2579 "aes256-cts-hmac-sha1-96",
2583 &keytype_aes256,
2584 &checksum_sha1,
2585 &checksum_hmac_sha1_aes256,
2586 F_DERIVED,
2587 evp_encrypt_cts,
2589 AES_PRF
2591 static struct encryption_type enctype_des3_cbc_none = {
2592 ETYPE_DES3_CBC_NONE,
2593 "des3-cbc-none",
2597 &keytype_des3_derived,
2598 &checksum_none,
2599 NULL,
2600 F_PSEUDO,
2601 evp_encrypt,
2603 NULL
2605 #ifdef HEIM_WEAK_CRYPTO
2606 static struct encryption_type enctype_des_cbc_crc = {
2607 ETYPE_DES_CBC_CRC,
2608 "des-cbc-crc",
2612 &keytype_des,
2613 &checksum_crc32,
2614 NULL,
2615 F_DISABLED,
2616 evp_des_encrypt_key_ivec,
2618 NULL
2620 static struct encryption_type enctype_des_cbc_md4 = {
2621 ETYPE_DES_CBC_MD4,
2622 "des-cbc-md4",
2626 &keytype_des,
2627 &checksum_rsa_md4,
2628 &checksum_rsa_md4_des,
2629 F_DISABLED,
2630 evp_des_encrypt_null_ivec,
2632 NULL
2634 static struct encryption_type enctype_des_cbc_md5 = {
2635 ETYPE_DES_CBC_MD5,
2636 "des-cbc-md5",
2640 &keytype_des,
2641 &checksum_rsa_md5,
2642 &checksum_rsa_md5_des,
2643 F_DISABLED,
2644 evp_des_encrypt_null_ivec,
2646 NULL
2648 static struct encryption_type enctype_des_cbc_none = {
2649 ETYPE_DES_CBC_NONE,
2650 "des-cbc-none",
2654 &keytype_des,
2655 &checksum_none,
2656 NULL,
2657 F_PSEUDO|F_DISABLED,
2658 evp_des_encrypt_null_ivec,
2660 NULL
2662 static struct encryption_type enctype_des_cfb64_none = {
2663 ETYPE_DES_CFB64_NONE,
2664 "des-cfb64-none",
2668 &keytype_des_old,
2669 &checksum_none,
2670 NULL,
2671 F_PSEUDO|F_DISABLED,
2672 DES_CFB64_encrypt_null_ivec,
2674 NULL
2676 static struct encryption_type enctype_des_pcbc_none = {
2677 ETYPE_DES_PCBC_NONE,
2678 "des-pcbc-none",
2682 &keytype_des_old,
2683 &checksum_none,
2684 NULL,
2685 F_PSEUDO|F_DISABLED,
2686 DES_PCBC_encrypt_key_ivec,
2688 NULL
2690 #endif /* HEIM_WEAK_CRYPTO */
2692 static struct encryption_type *etypes[] = {
2693 &enctype_aes256_cts_hmac_sha1,
2694 &enctype_aes128_cts_hmac_sha1,
2695 &enctype_des3_cbc_sha1,
2696 &enctype_des3_cbc_none, /* used by the gss-api mech */
2697 &enctype_arcfour_hmac_md5,
2698 #ifdef DES3_OLD_ENCTYPE
2699 &enctype_des3_cbc_md5,
2700 &enctype_old_des3_cbc_sha1,
2701 #endif
2702 #ifdef HEIM_WEAK_CRYPTO
2703 &enctype_des_cbc_crc,
2704 &enctype_des_cbc_md4,
2705 &enctype_des_cbc_md5,
2706 &enctype_des_cbc_none,
2707 &enctype_des_cfb64_none,
2708 &enctype_des_pcbc_none,
2709 #endif
2710 &enctype_null
2713 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2716 static struct encryption_type *
2717 _find_enctype(krb5_enctype type)
2719 int i;
2720 for(i = 0; i < num_etypes; i++)
2721 if(etypes[i]->type == type)
2722 return etypes[i];
2723 return NULL;
2727 krb5_error_code KRB5_LIB_FUNCTION
2728 krb5_enctype_to_string(krb5_context context,
2729 krb5_enctype etype,
2730 char **string)
2732 struct encryption_type *e;
2733 e = _find_enctype(etype);
2734 if(e == NULL) {
2735 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2736 N_("encryption type %d not supported", ""),
2737 etype);
2738 *string = NULL;
2739 return KRB5_PROG_ETYPE_NOSUPP;
2741 *string = strdup(e->name);
2742 if(*string == NULL) {
2743 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2744 return ENOMEM;
2746 return 0;
2749 krb5_error_code KRB5_LIB_FUNCTION
2750 krb5_string_to_enctype(krb5_context context,
2751 const char *string,
2752 krb5_enctype *etype)
2754 int i;
2755 for(i = 0; i < num_etypes; i++)
2756 if(strcasecmp(etypes[i]->name, string) == 0){
2757 *etype = etypes[i]->type;
2758 return 0;
2760 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2761 N_("encryption type %s not supported", ""),
2762 string);
2763 return KRB5_PROG_ETYPE_NOSUPP;
2766 krb5_error_code KRB5_LIB_FUNCTION
2767 krb5_enctype_to_keytype(krb5_context context,
2768 krb5_enctype etype,
2769 krb5_keytype *keytype)
2771 struct encryption_type *e = _find_enctype(etype);
2772 if(e == NULL) {
2773 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2774 N_("encryption type %d not supported", ""),
2775 etype);
2776 return KRB5_PROG_ETYPE_NOSUPP;
2778 *keytype = e->keytype->type; /* XXX */
2779 return 0;
2782 krb5_error_code KRB5_LIB_FUNCTION
2783 krb5_enctype_valid(krb5_context context,
2784 krb5_enctype etype)
2786 struct encryption_type *e = _find_enctype(etype);
2787 if(e == NULL) {
2788 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2789 N_("encryption type %d not supported", ""),
2790 etype);
2791 return KRB5_PROG_ETYPE_NOSUPP;
2793 if (e->flags & F_DISABLED) {
2794 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2795 N_("encryption type %s is disabled", ""),
2796 e->name);
2797 return KRB5_PROG_ETYPE_NOSUPP;
2799 return 0;
2803 * Return the coresponding encryption type for a checksum type.
2805 * @param context Kerberos context
2806 * @param ctype The checksum type to get the result enctype for
2807 * @param etype The returned encryption, when the matching etype is
2808 * not found, etype is set to ETYPE_NULL.
2810 * @return Return an error code for an failure or 0 on success.
2811 * @ingroup krb5_crypto
2815 krb5_error_code KRB5_LIB_FUNCTION
2816 krb5_cksumtype_to_enctype(krb5_context context,
2817 krb5_cksumtype ctype,
2818 krb5_enctype *etype)
2820 int i;
2822 *etype = ETYPE_NULL;
2824 for(i = 0; i < num_etypes; i++) {
2825 if(etypes[i]->keyed_checksum &&
2826 etypes[i]->keyed_checksum->type == ctype)
2828 *etype = etypes[i]->type;
2829 return 0;
2833 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2834 N_("checksum type %d not supported", ""),
2835 (int)ctype);
2836 return KRB5_PROG_SUMTYPE_NOSUPP;
2840 krb5_error_code KRB5_LIB_FUNCTION
2841 krb5_cksumtype_valid(krb5_context context,
2842 krb5_cksumtype ctype)
2844 struct checksum_type *c = _find_checksum(ctype);
2845 if (c == NULL) {
2846 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2847 N_("checksum type %d not supported", ""),
2848 ctype);
2849 return KRB5_PROG_SUMTYPE_NOSUPP;
2851 if (c->flags & F_DISABLED) {
2852 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2853 N_("checksum type %s is disabled", ""),
2854 c->name);
2855 return KRB5_PROG_SUMTYPE_NOSUPP;
2857 return 0;
2861 static krb5_boolean
2862 derived_crypto(krb5_context context,
2863 krb5_crypto crypto)
2865 return (crypto->et->flags & F_DERIVED) != 0;
2868 static krb5_boolean
2869 special_crypto(krb5_context context,
2870 krb5_crypto crypto)
2872 return (crypto->et->flags & F_SPECIAL) != 0;
2875 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2876 #define CHECKSUMTYPE(C) ((C)->type)
2878 static krb5_error_code
2879 encrypt_internal_derived(krb5_context context,
2880 krb5_crypto crypto,
2881 unsigned usage,
2882 const void *data,
2883 size_t len,
2884 krb5_data *result,
2885 void *ivec)
2887 size_t sz, block_sz, checksum_sz, total_sz;
2888 Checksum cksum;
2889 unsigned char *p, *q;
2890 krb5_error_code ret;
2891 struct key_data *dkey;
2892 const struct encryption_type *et = crypto->et;
2894 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2896 sz = et->confoundersize + len;
2897 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2898 total_sz = block_sz + checksum_sz;
2899 p = calloc(1, total_sz);
2900 if(p == NULL) {
2901 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2902 return ENOMEM;
2905 q = p;
2906 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2907 q += et->confoundersize;
2908 memcpy(q, data, len);
2910 ret = create_checksum(context,
2911 et->keyed_checksum,
2912 crypto,
2913 INTEGRITY_USAGE(usage),
2915 block_sz,
2916 &cksum);
2917 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2918 free_Checksum (&cksum);
2919 krb5_clear_error_message (context);
2920 ret = KRB5_CRYPTO_INTERNAL;
2922 if(ret)
2923 goto fail;
2924 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2925 free_Checksum (&cksum);
2926 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2927 if(ret)
2928 goto fail;
2929 ret = _key_schedule(context, dkey);
2930 if(ret)
2931 goto fail;
2932 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2933 if (ret)
2934 goto fail;
2935 result->data = p;
2936 result->length = total_sz;
2937 return 0;
2938 fail:
2939 memset(p, 0, total_sz);
2940 free(p);
2941 return ret;
2945 static krb5_error_code
2946 encrypt_internal(krb5_context context,
2947 krb5_crypto crypto,
2948 const void *data,
2949 size_t len,
2950 krb5_data *result,
2951 void *ivec)
2953 size_t sz, block_sz, checksum_sz;
2954 Checksum cksum;
2955 unsigned char *p, *q;
2956 krb5_error_code ret;
2957 const struct encryption_type *et = crypto->et;
2959 checksum_sz = CHECKSUMSIZE(et->checksum);
2961 sz = et->confoundersize + checksum_sz + len;
2962 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2963 p = calloc(1, block_sz);
2964 if(p == NULL) {
2965 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2966 return ENOMEM;
2969 q = p;
2970 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2971 q += et->confoundersize;
2972 memset(q, 0, checksum_sz);
2973 q += checksum_sz;
2974 memcpy(q, data, len);
2976 ret = create_checksum(context,
2977 et->checksum,
2978 crypto,
2981 block_sz,
2982 &cksum);
2983 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2984 krb5_clear_error_message (context);
2985 free_Checksum(&cksum);
2986 ret = KRB5_CRYPTO_INTERNAL;
2988 if(ret)
2989 goto fail;
2990 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2991 free_Checksum(&cksum);
2992 ret = _key_schedule(context, &crypto->key);
2993 if(ret)
2994 goto fail;
2995 ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
2996 if (ret) {
2997 memset(p, 0, block_sz);
2998 free(p);
2999 return ret;
3001 result->data = p;
3002 result->length = block_sz;
3003 return 0;
3004 fail:
3005 memset(p, 0, block_sz);
3006 free(p);
3007 return ret;
3010 static krb5_error_code
3011 encrypt_internal_special(krb5_context context,
3012 krb5_crypto crypto,
3013 int usage,
3014 const void *data,
3015 size_t len,
3016 krb5_data *result,
3017 void *ivec)
3019 struct encryption_type *et = crypto->et;
3020 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3021 size_t sz = len + cksum_sz + et->confoundersize;
3022 char *tmp, *p;
3023 krb5_error_code ret;
3025 tmp = malloc (sz);
3026 if (tmp == NULL) {
3027 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3028 return ENOMEM;
3030 p = tmp;
3031 memset (p, 0, cksum_sz);
3032 p += cksum_sz;
3033 krb5_generate_random_block(p, et->confoundersize);
3034 p += et->confoundersize;
3035 memcpy (p, data, len);
3036 ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
3037 if (ret) {
3038 memset(tmp, 0, sz);
3039 free(tmp);
3040 return ret;
3042 result->data = tmp;
3043 result->length = sz;
3044 return 0;
3047 static krb5_error_code
3048 decrypt_internal_derived(krb5_context context,
3049 krb5_crypto crypto,
3050 unsigned usage,
3051 void *data,
3052 size_t len,
3053 krb5_data *result,
3054 void *ivec)
3056 size_t checksum_sz;
3057 Checksum cksum;
3058 unsigned char *p;
3059 krb5_error_code ret;
3060 struct key_data *dkey;
3061 struct encryption_type *et = crypto->et;
3062 unsigned long l;
3064 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
3065 if (len < checksum_sz + et->confoundersize) {
3066 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3067 N_("Encrypted data shorter then "
3068 "checksum + confunder", ""));
3069 return KRB5_BAD_MSIZE;
3072 if (((len - checksum_sz) % et->padsize) != 0) {
3073 krb5_clear_error_message(context);
3074 return KRB5_BAD_MSIZE;
3077 p = malloc(len);
3078 if(len != 0 && p == NULL) {
3079 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3080 return ENOMEM;
3082 memcpy(p, data, len);
3084 len -= checksum_sz;
3086 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3087 if(ret) {
3088 free(p);
3089 return ret;
3091 ret = _key_schedule(context, dkey);
3092 if(ret) {
3093 free(p);
3094 return ret;
3096 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3097 if (ret) {
3098 free(p);
3099 return ret;
3102 cksum.checksum.data = p + len;
3103 cksum.checksum.length = checksum_sz;
3104 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3106 ret = verify_checksum(context,
3107 crypto,
3108 INTEGRITY_USAGE(usage),
3110 len,
3111 &cksum);
3112 if(ret) {
3113 free(p);
3114 return ret;
3116 l = len - et->confoundersize;
3117 memmove(p, p + et->confoundersize, l);
3118 result->data = realloc(p, l);
3119 if(result->data == NULL && l != 0) {
3120 free(p);
3121 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3122 return ENOMEM;
3124 result->length = l;
3125 return 0;
3128 static krb5_error_code
3129 decrypt_internal(krb5_context context,
3130 krb5_crypto crypto,
3131 void *data,
3132 size_t len,
3133 krb5_data *result,
3134 void *ivec)
3136 krb5_error_code ret;
3137 unsigned char *p;
3138 Checksum cksum;
3139 size_t checksum_sz, l;
3140 struct encryption_type *et = crypto->et;
3142 if ((len % et->padsize) != 0) {
3143 krb5_clear_error_message(context);
3144 return KRB5_BAD_MSIZE;
3147 checksum_sz = CHECKSUMSIZE(et->checksum);
3148 p = malloc(len);
3149 if(len != 0 && p == NULL) {
3150 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3151 return ENOMEM;
3153 memcpy(p, data, len);
3155 ret = _key_schedule(context, &crypto->key);
3156 if(ret) {
3157 free(p);
3158 return ret;
3160 ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
3161 if (ret) {
3162 free(p);
3163 return ret;
3165 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
3166 if(ret) {
3167 free(p);
3168 return ret;
3170 memset(p + et->confoundersize, 0, checksum_sz);
3171 cksum.cksumtype = CHECKSUMTYPE(et->checksum);
3172 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
3173 free_Checksum(&cksum);
3174 if(ret) {
3175 free(p);
3176 return ret;
3178 l = len - et->confoundersize - checksum_sz;
3179 memmove(p, p + et->confoundersize + checksum_sz, l);
3180 result->data = realloc(p, l);
3181 if(result->data == NULL && l != 0) {
3182 free(p);
3183 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3184 return ENOMEM;
3186 result->length = l;
3187 return 0;
3190 static krb5_error_code
3191 decrypt_internal_special(krb5_context context,
3192 krb5_crypto crypto,
3193 int usage,
3194 void *data,
3195 size_t len,
3196 krb5_data *result,
3197 void *ivec)
3199 struct encryption_type *et = crypto->et;
3200 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3201 size_t sz = len - cksum_sz - et->confoundersize;
3202 unsigned char *p;
3203 krb5_error_code ret;
3205 if ((len % et->padsize) != 0) {
3206 krb5_clear_error_message(context);
3207 return KRB5_BAD_MSIZE;
3210 p = malloc (len);
3211 if (p == NULL) {
3212 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3213 return ENOMEM;
3215 memcpy(p, data, len);
3217 ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
3218 if (ret) {
3219 free(p);
3220 return ret;
3223 memmove (p, p + cksum_sz + et->confoundersize, sz);
3224 result->data = realloc(p, sz);
3225 if(result->data == NULL && sz != 0) {
3226 free(p);
3227 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3228 return ENOMEM;
3230 result->length = sz;
3231 return 0;
3234 static krb5_crypto_iov *
3235 find_iv(krb5_crypto_iov *data, int num_data, int type)
3237 int i;
3238 for (i = 0; i < num_data; i++)
3239 if (data[i].flags == type)
3240 return &data[i];
3241 return NULL;
3245 * Inline encrypt a kerberos message
3247 * @param context Kerberos context
3248 * @param crypto Kerberos crypto context
3249 * @param usage Key usage for this buffer
3250 * @param data array of buffers to process
3251 * @param num_data length of array
3252 * @param ivec initial cbc/cts vector
3254 * @return Return an error code or 0.
3255 * @ingroup krb5_crypto
3257 * Kerberos encrypted data look like this:
3259 * 1. KRB5_CRYPTO_TYPE_HEADER
3260 * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
3261 * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
3262 * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
3263 * commonly used headers and trailers.
3264 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
3265 * 4. KRB5_CRYPTO_TYPE_TRAILER
3268 krb5_error_code KRB5_LIB_FUNCTION
3269 krb5_encrypt_iov_ivec(krb5_context context,
3270 krb5_crypto crypto,
3271 unsigned usage,
3272 krb5_crypto_iov *data,
3273 int num_data,
3274 void *ivec)
3276 size_t headersz, trailersz, len;
3277 int i;
3278 size_t sz, block_sz, pad_sz;
3279 Checksum cksum;
3280 unsigned char *p, *q;
3281 krb5_error_code ret;
3282 struct key_data *dkey;
3283 const struct encryption_type *et = crypto->et;
3284 krb5_crypto_iov *tiv, *piv, *hiv;
3286 if (num_data < 0) {
3287 krb5_clear_error_message(context);
3288 return KRB5_CRYPTO_INTERNAL;
3291 if(!derived_crypto(context, crypto)) {
3292 krb5_clear_error_message(context);
3293 return KRB5_CRYPTO_INTERNAL;
3296 headersz = et->confoundersize;
3297 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3299 for (len = 0, i = 0; i < num_data; i++) {
3300 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3301 continue;
3302 len += data[i].data.length;
3305 sz = headersz + len;
3306 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3308 pad_sz = block_sz - sz;
3310 /* header */
3312 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3313 if (hiv == NULL || hiv->data.length != headersz)
3314 return KRB5_BAD_MSIZE;
3316 krb5_generate_random_block(hiv->data.data, hiv->data.length);
3318 /* padding */
3319 piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
3320 /* its ok to have no TYPE_PADDING if there is no padding */
3321 if (piv == NULL && pad_sz != 0)
3322 return KRB5_BAD_MSIZE;
3323 if (piv) {
3324 if (piv->data.length < pad_sz)
3325 return KRB5_BAD_MSIZE;
3326 piv->data.length = pad_sz;
3327 if (pad_sz)
3328 memset(piv->data.data, pad_sz, pad_sz);
3329 else
3330 piv = NULL;
3333 /* trailer */
3334 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3335 if (tiv == NULL || tiv->data.length != trailersz)
3336 return KRB5_BAD_MSIZE;
3339 * XXX replace with EVP_Sign? at least make create_checksum an iov
3340 * function.
3341 * XXX CTS EVP is broken, can't handle multi buffers :(
3344 len = block_sz;
3345 for (i = 0; i < num_data; i++) {
3346 if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3347 continue;
3348 len += data[i].data.length;
3351 p = q = malloc(len);
3353 memcpy(q, hiv->data.data, hiv->data.length);
3354 q += hiv->data.length;
3355 for (i = 0; i < num_data; i++) {
3356 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3357 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3358 continue;
3359 memcpy(q, data[i].data.data, data[i].data.length);
3360 q += data[i].data.length;
3362 if (piv)
3363 memset(q, 0, piv->data.length);
3365 ret = create_checksum(context,
3366 et->keyed_checksum,
3367 crypto,
3368 INTEGRITY_USAGE(usage),
3370 len,
3371 &cksum);
3372 free(p);
3373 if(ret == 0 && cksum.checksum.length != trailersz) {
3374 free_Checksum (&cksum);
3375 krb5_clear_error_message (context);
3376 ret = KRB5_CRYPTO_INTERNAL;
3378 if(ret)
3379 return ret;
3381 /* save cksum at end */
3382 memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
3383 free_Checksum (&cksum);
3385 /* XXX replace with EVP_Cipher */
3386 p = q = malloc(block_sz);
3387 if(p == NULL)
3388 return ENOMEM;
3390 memcpy(q, hiv->data.data, hiv->data.length);
3391 q += hiv->data.length;
3393 for (i = 0; i < num_data; i++) {
3394 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3395 continue;
3396 memcpy(q, data[i].data.data, data[i].data.length);
3397 q += data[i].data.length;
3399 if (piv)
3400 memset(q, 0, piv->data.length);
3403 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3404 if(ret) {
3405 free(p);
3406 return ret;
3408 ret = _key_schedule(context, dkey);
3409 if(ret) {
3410 free(p);
3411 return ret;
3414 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
3415 if (ret) {
3416 free(p);
3417 return ret;
3420 /* now copy data back to buffers */
3421 q = p;
3423 memcpy(hiv->data.data, q, hiv->data.length);
3424 q += hiv->data.length;
3426 for (i = 0; i < num_data; i++) {
3427 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3428 continue;
3429 memcpy(data[i].data.data, q, data[i].data.length);
3430 q += data[i].data.length;
3432 if (piv)
3433 memcpy(piv->data.data, q, pad_sz);
3435 free(p);
3437 return ret;
3441 * Inline decrypt a Kerberos message.
3443 * @param context Kerberos context
3444 * @param crypto Kerberos crypto context
3445 * @param usage Key usage for this buffer
3446 * @param data array of buffers to process
3447 * @param num_data length of array
3448 * @param ivec initial cbc/cts vector
3450 * @return Return an error code or 0.
3451 * @ingroup krb5_crypto
3453 * 1. KRB5_CRYPTO_TYPE_HEADER
3454 * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
3455 * any order, however the receiver have to aware of the
3456 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
3457 * protocol headers and trailers. The output data will be of same
3458 * size as the input data or shorter.
3461 krb5_error_code KRB5_LIB_FUNCTION
3462 krb5_decrypt_iov_ivec(krb5_context context,
3463 krb5_crypto crypto,
3464 unsigned usage,
3465 krb5_crypto_iov *data,
3466 unsigned int num_data,
3467 void *ivec)
3469 unsigned int i;
3470 size_t headersz, trailersz, len;
3471 Checksum cksum;
3472 unsigned char *p, *q;
3473 krb5_error_code ret;
3474 struct key_data *dkey;
3475 struct encryption_type *et = crypto->et;
3476 krb5_crypto_iov *tiv, *hiv;
3478 if (num_data < 0) {
3479 krb5_clear_error_message(context);
3480 return KRB5_CRYPTO_INTERNAL;
3483 if(!derived_crypto(context, crypto)) {
3484 krb5_clear_error_message(context);
3485 return KRB5_CRYPTO_INTERNAL;
3488 headersz = et->confoundersize;
3490 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3491 if (hiv == NULL || hiv->data.length != headersz)
3492 return KRB5_BAD_MSIZE;
3494 /* trailer */
3495 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3497 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3498 if (tiv->data.length != trailersz)
3499 return KRB5_BAD_MSIZE;
3501 /* Find length of data we will decrypt */
3503 len = headersz;
3504 for (i = 0; i < num_data; i++) {
3505 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3506 continue;
3507 len += data[i].data.length;
3510 if ((len % et->padsize) != 0) {
3511 krb5_clear_error_message(context);
3512 return KRB5_BAD_MSIZE;
3515 /* XXX replace with EVP_Cipher */
3517 p = q = malloc(len);
3518 if (p == NULL)
3519 return ENOMEM;
3521 memcpy(q, hiv->data.data, hiv->data.length);
3522 q += hiv->data.length;
3524 for (i = 0; i < num_data; i++) {
3525 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3526 continue;
3527 memcpy(q, data[i].data.data, data[i].data.length);
3528 q += data[i].data.length;
3531 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3532 if(ret) {
3533 free(p);
3534 return ret;
3536 ret = _key_schedule(context, dkey);
3537 if(ret) {
3538 free(p);
3539 return ret;
3542 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3543 if (ret) {
3544 free(p);
3545 return ret;
3548 /* copy data back to buffers */
3549 memcpy(hiv->data.data, p, hiv->data.length);
3550 q = p + hiv->data.length;
3551 for (i = 0; i < num_data; i++) {
3552 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3553 continue;
3554 memcpy(data[i].data.data, q, data[i].data.length);
3555 q += data[i].data.length;
3558 free(p);
3560 /* check signature */
3561 for (i = 0; i < num_data; i++) {
3562 if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3563 continue;
3564 len += data[i].data.length;
3567 p = q = malloc(len);
3568 if (p == NULL)
3569 return ENOMEM;
3571 memcpy(q, hiv->data.data, hiv->data.length);
3572 q += hiv->data.length;
3573 for (i = 0; i < num_data; i++) {
3574 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3575 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3576 continue;
3577 memcpy(q, data[i].data.data, data[i].data.length);
3578 q += data[i].data.length;
3581 cksum.checksum.data = tiv->data.data;
3582 cksum.checksum.length = tiv->data.length;
3583 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3585 ret = verify_checksum(context,
3586 crypto,
3587 INTEGRITY_USAGE(usage),
3589 len,
3590 &cksum);
3591 free(p);
3592 return ret;
3596 * Create a Kerberos message checksum.
3598 * @param context Kerberos context
3599 * @param crypto Kerberos crypto context
3600 * @param usage Key usage for this buffer
3601 * @param data array of buffers to process
3602 * @param num_data length of array
3603 * @param type output data
3605 * @return Return an error code or 0.
3606 * @ingroup krb5_crypto
3609 krb5_error_code KRB5_LIB_FUNCTION
3610 krb5_create_checksum_iov(krb5_context context,
3611 krb5_crypto crypto,
3612 unsigned usage,
3613 krb5_crypto_iov *data,
3614 unsigned int num_data,
3615 krb5_cksumtype *type)
3617 Checksum cksum;
3618 krb5_crypto_iov *civ;
3619 krb5_error_code ret;
3620 int i;
3621 size_t len;
3622 char *p, *q;
3624 if (num_data < 0) {
3625 krb5_clear_error_message(context);
3626 return KRB5_CRYPTO_INTERNAL;
3629 if(!derived_crypto(context, crypto)) {
3630 krb5_clear_error_message(context);
3631 return KRB5_CRYPTO_INTERNAL;
3634 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3635 if (civ == NULL)
3636 return KRB5_BAD_MSIZE;
3638 len = 0;
3639 for (i = 0; i < num_data; i++) {
3640 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3641 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3642 continue;
3643 len += data[i].data.length;
3646 p = q = malloc(len);
3648 for (i = 0; i < num_data; i++) {
3649 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3650 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3651 continue;
3652 memcpy(q, data[i].data.data, data[i].data.length);
3653 q += data[i].data.length;
3656 ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
3657 free(p);
3658 if (ret)
3659 return ret;
3661 if (type)
3662 *type = cksum.cksumtype;
3664 if (cksum.checksum.length > civ->data.length) {
3665 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3666 N_("Checksum larger then input buffer", ""));
3667 free_Checksum(&cksum);
3668 return KRB5_BAD_MSIZE;
3671 civ->data.length = cksum.checksum.length;
3672 memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
3673 free_Checksum(&cksum);
3675 return 0;
3679 * Verify a Kerberos message checksum.
3681 * @param context Kerberos context
3682 * @param crypto Kerberos crypto context
3683 * @param usage Key usage for this buffer
3684 * @param data array of buffers to process
3685 * @param num_data length of array
3686 * @param type return checksum type if not NULL
3688 * @return Return an error code or 0.
3689 * @ingroup krb5_crypto
3692 krb5_error_code KRB5_LIB_FUNCTION
3693 krb5_verify_checksum_iov(krb5_context context,
3694 krb5_crypto crypto,
3695 unsigned usage,
3696 krb5_crypto_iov *data,
3697 unsigned int num_data,
3698 krb5_cksumtype *type)
3700 struct encryption_type *et = crypto->et;
3701 Checksum cksum;
3702 krb5_crypto_iov *civ;
3703 krb5_error_code ret;
3704 int i;
3705 size_t len;
3706 char *p, *q;
3708 if (num_data < 0) {
3709 krb5_clear_error_message(context);
3710 return KRB5_CRYPTO_INTERNAL;
3713 if(!derived_crypto(context, crypto)) {
3714 krb5_clear_error_message(context);
3715 return KRB5_CRYPTO_INTERNAL;
3718 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3719 if (civ == NULL)
3720 return KRB5_BAD_MSIZE;
3722 len = 0;
3723 for (i = 0; i < num_data; i++) {
3724 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3725 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3726 continue;
3727 len += data[i].data.length;
3730 p = q = malloc(len);
3732 for (i = 0; i < num_data; i++) {
3733 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3734 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3735 continue;
3736 memcpy(q, data[i].data.data, data[i].data.length);
3737 q += data[i].data.length;
3740 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3741 cksum.checksum.length = civ->data.length;
3742 cksum.checksum.data = civ->data.data;
3744 ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
3745 free(p);
3747 if (ret == 0 && type)
3748 *type = cksum.cksumtype;
3750 return ret;
3754 krb5_error_code KRB5_LIB_FUNCTION
3755 krb5_crypto_length(krb5_context context,
3756 krb5_crypto crypto,
3757 int type,
3758 size_t *len)
3760 if (!derived_crypto(context, crypto)) {
3761 krb5_set_error_message(context, EINVAL, "not a derived crypto");
3762 return EINVAL;
3765 switch(type) {
3766 case KRB5_CRYPTO_TYPE_EMPTY:
3767 *len = 0;
3768 return 0;
3769 case KRB5_CRYPTO_TYPE_HEADER:
3770 *len = crypto->et->blocksize;
3771 return 0;
3772 case KRB5_CRYPTO_TYPE_DATA:
3773 case KRB5_CRYPTO_TYPE_SIGN_ONLY:
3774 /* len must already been filled in */
3775 return 0;
3776 case KRB5_CRYPTO_TYPE_PADDING:
3777 if (crypto->et->padsize > 1)
3778 *len = crypto->et->padsize;
3779 else
3780 *len = 0;
3781 return 0;
3782 case KRB5_CRYPTO_TYPE_TRAILER:
3783 *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
3784 return 0;
3785 case KRB5_CRYPTO_TYPE_CHECKSUM:
3786 if (crypto->et->keyed_checksum)
3787 *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
3788 else
3789 *len = CHECKSUMSIZE(crypto->et->checksum);
3790 return 0;
3792 krb5_set_error_message(context, EINVAL,
3793 "%d not a supported type", type);
3794 return EINVAL;
3798 krb5_error_code KRB5_LIB_FUNCTION
3799 krb5_crypto_length_iov(krb5_context context,
3800 krb5_crypto crypto,
3801 krb5_crypto_iov *data,
3802 unsigned int num_data)
3804 krb5_error_code ret;
3805 int i;
3807 for (i = 0; i < num_data; i++) {
3808 ret = krb5_crypto_length(context, crypto,
3809 data[i].flags,
3810 &data[i].data.length);
3811 if (ret)
3812 return ret;
3814 return 0;
3818 krb5_error_code KRB5_LIB_FUNCTION
3819 krb5_encrypt_ivec(krb5_context context,
3820 krb5_crypto crypto,
3821 unsigned usage,
3822 const void *data,
3823 size_t len,
3824 krb5_data *result,
3825 void *ivec)
3827 if(derived_crypto(context, crypto))
3828 return encrypt_internal_derived(context, crypto, usage,
3829 data, len, result, ivec);
3830 else if (special_crypto(context, crypto))
3831 return encrypt_internal_special (context, crypto, usage,
3832 data, len, result, ivec);
3833 else
3834 return encrypt_internal(context, crypto, data, len, result, ivec);
3837 krb5_error_code KRB5_LIB_FUNCTION
3838 krb5_encrypt(krb5_context context,
3839 krb5_crypto crypto,
3840 unsigned usage,
3841 const void *data,
3842 size_t len,
3843 krb5_data *result)
3845 return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
3848 krb5_error_code KRB5_LIB_FUNCTION
3849 krb5_encrypt_EncryptedData(krb5_context context,
3850 krb5_crypto crypto,
3851 unsigned usage,
3852 void *data,
3853 size_t len,
3854 int kvno,
3855 EncryptedData *result)
3857 result->etype = CRYPTO_ETYPE(crypto);
3858 if(kvno){
3859 ALLOC(result->kvno, 1);
3860 *result->kvno = kvno;
3861 }else
3862 result->kvno = NULL;
3863 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
3866 krb5_error_code KRB5_LIB_FUNCTION
3867 krb5_decrypt_ivec(krb5_context context,
3868 krb5_crypto crypto,
3869 unsigned usage,
3870 void *data,
3871 size_t len,
3872 krb5_data *result,
3873 void *ivec)
3875 if(derived_crypto(context, crypto))
3876 return decrypt_internal_derived(context, crypto, usage,
3877 data, len, result, ivec);
3878 else if (special_crypto (context, crypto))
3879 return decrypt_internal_special(context, crypto, usage,
3880 data, len, result, ivec);
3881 else
3882 return decrypt_internal(context, crypto, data, len, result, ivec);
3885 krb5_error_code KRB5_LIB_FUNCTION
3886 krb5_decrypt(krb5_context context,
3887 krb5_crypto crypto,
3888 unsigned usage,
3889 void *data,
3890 size_t len,
3891 krb5_data *result)
3893 return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
3894 NULL);
3897 krb5_error_code KRB5_LIB_FUNCTION
3898 krb5_decrypt_EncryptedData(krb5_context context,
3899 krb5_crypto crypto,
3900 unsigned usage,
3901 const EncryptedData *e,
3902 krb5_data *result)
3904 return krb5_decrypt(context, crypto, usage,
3905 e->cipher.data, e->cipher.length, result);
3908 /************************************************************
3910 ************************************************************/
3912 #define ENTROPY_NEEDED 128
3914 static int
3915 seed_something(void)
3917 char buf[1024], seedfile[256];
3919 /* If there is a seed file, load it. But such a file cannot be trusted,
3920 so use 0 for the entropy estimate */
3921 if (RAND_file_name(seedfile, sizeof(seedfile))) {
3922 int fd;
3923 fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
3924 if (fd >= 0) {
3925 ssize_t ret;
3926 rk_cloexec(fd);
3927 ret = read(fd, buf, sizeof(buf));
3928 if (ret > 0)
3929 RAND_add(buf, ret, 0.0);
3930 close(fd);
3931 } else
3932 seedfile[0] = '\0';
3933 } else
3934 seedfile[0] = '\0';
3936 /* Calling RAND_status() will try to use /dev/urandom if it exists so
3937 we do not have to deal with it. */
3938 if (RAND_status() != 1) {
3939 krb5_context context;
3940 const char *p;
3942 /* Try using egd */
3943 if (!krb5_init_context(&context)) {
3944 p = krb5_config_get_string(context, NULL, "libdefaults",
3945 "egd_socket", NULL);
3946 if (p != NULL)
3947 RAND_egd_bytes(p, ENTROPY_NEEDED);
3948 krb5_free_context(context);
3952 if (RAND_status() == 1) {
3953 /* Update the seed file */
3954 if (seedfile[0])
3955 RAND_write_file(seedfile);
3957 return 0;
3958 } else
3959 return -1;
3962 void KRB5_LIB_FUNCTION
3963 krb5_generate_random_block(void *buf, size_t len)
3965 static int rng_initialized = 0;
3967 HEIMDAL_MUTEX_lock(&crypto_mutex);
3968 if (!rng_initialized) {
3969 if (seed_something())
3970 krb5_abortx(NULL, "Fatal: could not seed the "
3971 "random number generator");
3973 rng_initialized = 1;
3975 HEIMDAL_MUTEX_unlock(&crypto_mutex);
3976 if (RAND_bytes(buf, len) != 1)
3977 krb5_abortx(NULL, "Failed to generate random block");
3980 static krb5_error_code
3981 derive_key(krb5_context context,
3982 struct encryption_type *et,
3983 struct key_data *key,
3984 const void *constant,
3985 size_t len)
3987 unsigned char *k = NULL;
3988 unsigned int nblocks = 0, i;
3989 krb5_error_code ret = 0;
3990 struct key_type *kt = et->keytype;
3992 ret = _key_schedule(context, key);
3993 if(ret)
3994 return ret;
3995 if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
3996 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
3997 k = malloc(nblocks * et->blocksize);
3998 if(k == NULL) {
3999 ret = ENOMEM;
4000 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4001 goto out;
4003 ret = _krb5_n_fold(constant, len, k, et->blocksize);
4004 if (ret) {
4005 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4006 goto out;
4009 for(i = 0; i < nblocks; i++) {
4010 if(i > 0)
4011 memcpy(k + i * et->blocksize,
4012 k + (i - 1) * et->blocksize,
4013 et->blocksize);
4014 (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
4015 1, 0, NULL);
4017 } else {
4018 /* this case is probably broken, but won't be run anyway */
4019 void *c = malloc(len);
4020 size_t res_len = (kt->bits + 7) / 8;
4022 if(len != 0 && c == NULL) {
4023 ret = ENOMEM;
4024 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4025 goto out;
4027 memcpy(c, constant, len);
4028 (*et->encrypt)(context, key, c, len, 1, 0, NULL);
4029 k = malloc(res_len);
4030 if(res_len != 0 && k == NULL) {
4031 free(c);
4032 ret = ENOMEM;
4033 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4034 goto out;
4036 ret = _krb5_n_fold(c, len, k, res_len);
4037 free(c);
4038 if (ret) {
4039 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4040 goto out;
4044 /* XXX keytype dependent post-processing */
4045 switch(kt->type) {
4046 case KEYTYPE_DES3:
4047 DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
4048 break;
4049 case KEYTYPE_AES128:
4050 case KEYTYPE_AES256:
4051 memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
4052 break;
4053 default:
4054 ret = KRB5_CRYPTO_INTERNAL;
4055 krb5_set_error_message(context, ret,
4056 N_("derive_key() called with unknown keytype (%u)", ""),
4057 kt->type);
4058 break;
4060 out:
4061 if (key->schedule) {
4062 free_key_schedule(context, key, et);
4063 key->schedule = NULL;
4065 if (k) {
4066 memset(k, 0, nblocks * et->blocksize);
4067 free(k);
4069 return ret;
4072 static struct key_data *
4073 _new_derived_key(krb5_crypto crypto, unsigned usage)
4075 struct key_usage *d = crypto->key_usage;
4076 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
4077 if(d == NULL)
4078 return NULL;
4079 crypto->key_usage = d;
4080 d += crypto->num_key_usage++;
4081 memset(d, 0, sizeof(*d));
4082 d->usage = usage;
4083 return &d->key;
4086 krb5_error_code KRB5_LIB_FUNCTION
4087 krb5_derive_key(krb5_context context,
4088 const krb5_keyblock *key,
4089 krb5_enctype etype,
4090 const void *constant,
4091 size_t constant_len,
4092 krb5_keyblock **derived_key)
4094 krb5_error_code ret;
4095 struct encryption_type *et;
4096 struct key_data d;
4098 *derived_key = NULL;
4100 et = _find_enctype (etype);
4101 if (et == NULL) {
4102 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4103 N_("encryption type %d not supported", ""),
4104 etype);
4105 return KRB5_PROG_ETYPE_NOSUPP;
4108 ret = krb5_copy_keyblock(context, key, &d.key);
4109 if (ret)
4110 return ret;
4112 d.schedule = NULL;
4113 ret = derive_key(context, et, &d, constant, constant_len);
4114 if (ret == 0)
4115 ret = krb5_copy_keyblock(context, d.key, derived_key);
4116 free_key_data(context, &d, et);
4117 return ret;
4120 static krb5_error_code
4121 _get_derived_key(krb5_context context,
4122 krb5_crypto crypto,
4123 unsigned usage,
4124 struct key_data **key)
4126 int i;
4127 struct key_data *d;
4128 unsigned char constant[5];
4130 for(i = 0; i < crypto->num_key_usage; i++)
4131 if(crypto->key_usage[i].usage == usage) {
4132 *key = &crypto->key_usage[i].key;
4133 return 0;
4135 d = _new_derived_key(crypto, usage);
4136 if(d == NULL) {
4137 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4138 return ENOMEM;
4140 krb5_copy_keyblock(context, crypto->key.key, &d->key);
4141 _krb5_put_int(constant, usage, 5);
4142 derive_key(context, crypto->et, d, constant, sizeof(constant));
4143 *key = d;
4144 return 0;
4148 * Create a crypto context used for all encryption and signature
4149 * operation. The encryption type to use is taken from the key, but
4150 * can be overridden with the enctype parameter. This can be useful
4151 * for encryptions types which is compatiable (DES for example).
4153 * To free the crypto context, use krb5_crypto_destroy().
4155 * @param context Kerberos context
4156 * @param key the key block information with all key data
4157 * @param etype the encryption type
4158 * @param crypto the resulting crypto context
4160 * @return Return an error code or 0.
4162 * @ingroup krb5_crypto
4165 krb5_error_code KRB5_LIB_FUNCTION
4166 krb5_crypto_init(krb5_context context,
4167 const krb5_keyblock *key,
4168 krb5_enctype etype,
4169 krb5_crypto *crypto)
4171 krb5_error_code ret;
4172 ALLOC(*crypto, 1);
4173 if(*crypto == NULL) {
4174 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4175 return ENOMEM;
4177 if(etype == ETYPE_NULL)
4178 etype = key->keytype;
4179 (*crypto)->et = _find_enctype(etype);
4180 if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
4181 free(*crypto);
4182 *crypto = NULL;
4183 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4184 N_("encryption type %d not supported", ""),
4185 etype);
4186 return KRB5_PROG_ETYPE_NOSUPP;
4188 if((*crypto)->et->keytype->size != key->keyvalue.length) {
4189 free(*crypto);
4190 *crypto = NULL;
4191 krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
4192 "encryption key has bad length");
4193 return KRB5_BAD_KEYSIZE;
4195 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
4196 if(ret) {
4197 free(*crypto);
4198 *crypto = NULL;
4199 return ret;
4201 (*crypto)->key.schedule = NULL;
4202 (*crypto)->num_key_usage = 0;
4203 (*crypto)->key_usage = NULL;
4204 return 0;
4207 static void
4208 free_key_schedule(krb5_context context,
4209 struct key_data *key,
4210 struct encryption_type *et)
4212 if (et->keytype->cleanup)
4213 (*et->keytype->cleanup)(context, key);
4214 memset(key->schedule->data, 0, key->schedule->length);
4215 krb5_free_data(context, key->schedule);
4218 static void
4219 free_key_data(krb5_context context, struct key_data *key,
4220 struct encryption_type *et)
4222 krb5_free_keyblock(context, key->key);
4223 if(key->schedule) {
4224 free_key_schedule(context, key, et);
4225 key->schedule = NULL;
4229 static void
4230 free_key_usage(krb5_context context, struct key_usage *ku,
4231 struct encryption_type *et)
4233 free_key_data(context, &ku->key, et);
4237 * Free a crypto context created by krb5_crypto_init().
4239 * @param context Kerberos context
4240 * @param crypto crypto context to free
4242 * @return Return an error code or 0.
4244 * @ingroup krb5_crypto
4247 krb5_error_code KRB5_LIB_FUNCTION
4248 krb5_crypto_destroy(krb5_context context,
4249 krb5_crypto crypto)
4251 int i;
4253 for(i = 0; i < crypto->num_key_usage; i++)
4254 free_key_usage(context, &crypto->key_usage[i], crypto->et);
4255 free(crypto->key_usage);
4256 free_key_data(context, &crypto->key, crypto->et);
4257 free (crypto);
4258 return 0;
4262 * Return the blocksize used algorithm referenced by the crypto context
4264 * @param context Kerberos context
4265 * @param crypto crypto context to query
4266 * @param blocksize the resulting blocksize
4268 * @return Return an error code or 0.
4270 * @ingroup krb5_crypto
4273 krb5_error_code KRB5_LIB_FUNCTION
4274 krb5_crypto_getblocksize(krb5_context context,
4275 krb5_crypto crypto,
4276 size_t *blocksize)
4278 *blocksize = crypto->et->blocksize;
4279 return 0;
4283 * Return the encryption type used by the crypto context
4285 * @param context Kerberos context
4286 * @param crypto crypto context to query
4287 * @param enctype the resulting encryption type
4289 * @return Return an error code or 0.
4291 * @ingroup krb5_crypto
4294 krb5_error_code KRB5_LIB_FUNCTION
4295 krb5_crypto_getenctype(krb5_context context,
4296 krb5_crypto crypto,
4297 krb5_enctype *enctype)
4299 *enctype = crypto->et->type;
4300 return 0;
4304 * Return the padding size used by the crypto context
4306 * @param context Kerberos context
4307 * @param crypto crypto context to query
4308 * @param padsize the return padding size
4310 * @return Return an error code or 0.
4312 * @ingroup krb5_crypto
4315 krb5_error_code KRB5_LIB_FUNCTION
4316 krb5_crypto_getpadsize(krb5_context context,
4317 krb5_crypto crypto,
4318 size_t *padsize)
4320 *padsize = crypto->et->padsize;
4321 return 0;
4325 * Return the confounder size used by the crypto context
4327 * @param context Kerberos context
4328 * @param crypto crypto context to query
4329 * @param confoundersize the returned confounder size
4331 * @return Return an error code or 0.
4333 * @ingroup krb5_crypto
4336 krb5_error_code KRB5_LIB_FUNCTION
4337 krb5_crypto_getconfoundersize(krb5_context context,
4338 krb5_crypto crypto,
4339 size_t *confoundersize)
4341 *confoundersize = crypto->et->confoundersize;
4342 return 0;
4347 * Disable encryption type
4349 * @param context Kerberos 5 context
4350 * @param enctype encryption type to disable
4352 * @return Return an error code or 0.
4354 * @ingroup krb5_crypto
4357 krb5_error_code KRB5_LIB_FUNCTION
4358 krb5_enctype_disable(krb5_context context,
4359 krb5_enctype enctype)
4361 struct encryption_type *et = _find_enctype(enctype);
4362 if(et == NULL) {
4363 if (context)
4364 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4365 N_("encryption type %d not supported", ""),
4366 enctype);
4367 return KRB5_PROG_ETYPE_NOSUPP;
4369 et->flags |= F_DISABLED;
4370 return 0;
4374 * Enable encryption type
4376 * @param context Kerberos 5 context
4377 * @param enctype encryption type to enable
4379 * @return Return an error code or 0.
4381 * @ingroup krb5_crypto
4384 krb5_error_code KRB5_LIB_FUNCTION
4385 krb5_enctype_enable(krb5_context context,
4386 krb5_enctype enctype)
4388 struct encryption_type *et = _find_enctype(enctype);
4389 if(et == NULL) {
4390 if (context)
4391 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4392 N_("encryption type %d not supported", ""),
4393 enctype);
4394 return KRB5_PROG_ETYPE_NOSUPP;
4396 et->flags &= ~F_DISABLED;
4397 return 0;
4401 krb5_error_code KRB5_LIB_FUNCTION
4402 krb5_string_to_key_derived(krb5_context context,
4403 const void *str,
4404 size_t len,
4405 krb5_enctype etype,
4406 krb5_keyblock *key)
4408 struct encryption_type *et = _find_enctype(etype);
4409 krb5_error_code ret;
4410 struct key_data kd;
4411 size_t keylen;
4412 u_char *tmp;
4414 if(et == NULL) {
4415 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4416 N_("encryption type %d not supported", ""),
4417 etype);
4418 return KRB5_PROG_ETYPE_NOSUPP;
4420 keylen = et->keytype->bits / 8;
4422 ALLOC(kd.key, 1);
4423 if(kd.key == NULL) {
4424 krb5_set_error_message (context, ENOMEM,
4425 N_("malloc: out of memory", ""));
4426 return ENOMEM;
4428 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
4429 if(ret) {
4430 free(kd.key);
4431 return ret;
4433 kd.key->keytype = etype;
4434 tmp = malloc (keylen);
4435 if(tmp == NULL) {
4436 krb5_free_keyblock(context, kd.key);
4437 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4438 return ENOMEM;
4440 ret = _krb5_n_fold(str, len, tmp, keylen);
4441 if (ret) {
4442 free(tmp);
4443 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4444 return ret;
4446 kd.schedule = NULL;
4447 DES3_random_to_key(context, kd.key, tmp, keylen);
4448 memset(tmp, 0, keylen);
4449 free(tmp);
4450 ret = derive_key(context,
4452 &kd,
4453 "kerberos", /* XXX well known constant */
4454 strlen("kerberos"));
4455 if (ret) {
4456 free_key_data(context, &kd, et);
4457 return ret;
4459 ret = krb5_copy_keyblock_contents(context, kd.key, key);
4460 free_key_data(context, &kd, et);
4461 return ret;
4464 static size_t
4465 wrapped_length (krb5_context context,
4466 krb5_crypto crypto,
4467 size_t data_len)
4469 struct encryption_type *et = crypto->et;
4470 size_t padsize = et->padsize;
4471 size_t checksumsize = CHECKSUMSIZE(et->checksum);
4472 size_t res;
4474 res = et->confoundersize + checksumsize + data_len;
4475 res = (res + padsize - 1) / padsize * padsize;
4476 return res;
4479 static size_t
4480 wrapped_length_dervied (krb5_context context,
4481 krb5_crypto crypto,
4482 size_t data_len)
4484 struct encryption_type *et = crypto->et;
4485 size_t padsize = et->padsize;
4486 size_t res;
4488 res = et->confoundersize + data_len;
4489 res = (res + padsize - 1) / padsize * padsize;
4490 if (et->keyed_checksum)
4491 res += et->keyed_checksum->checksumsize;
4492 else
4493 res += et->checksum->checksumsize;
4494 return res;
4498 * Return the size of an encrypted packet of length `data_len'
4501 size_t
4502 krb5_get_wrapped_length (krb5_context context,
4503 krb5_crypto crypto,
4504 size_t data_len)
4506 if (derived_crypto (context, crypto))
4507 return wrapped_length_dervied (context, crypto, data_len);
4508 else
4509 return wrapped_length (context, crypto, data_len);
4513 * Return the size of an encrypted packet of length `data_len'
4516 static size_t
4517 crypto_overhead (krb5_context context,
4518 krb5_crypto crypto)
4520 struct encryption_type *et = crypto->et;
4521 size_t res;
4523 res = CHECKSUMSIZE(et->checksum);
4524 res += et->confoundersize;
4525 if (et->padsize > 1)
4526 res += et->padsize;
4527 return res;
4530 static size_t
4531 crypto_overhead_dervied (krb5_context context,
4532 krb5_crypto crypto)
4534 struct encryption_type *et = crypto->et;
4535 size_t res;
4537 if (et->keyed_checksum)
4538 res = CHECKSUMSIZE(et->keyed_checksum);
4539 else
4540 res = CHECKSUMSIZE(et->checksum);
4541 res += et->confoundersize;
4542 if (et->padsize > 1)
4543 res += et->padsize;
4544 return res;
4547 size_t
4548 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
4550 if (derived_crypto (context, crypto))
4551 return crypto_overhead_dervied (context, crypto);
4552 else
4553 return crypto_overhead (context, crypto);
4557 * Converts the random bytestring to a protocol key according to
4558 * Kerberos crypto frame work. It may be assumed that all the bits of
4559 * the input string are equally random, even though the entropy
4560 * present in the random source may be limited.
4562 * @param context Kerberos 5 context
4563 * @param type the enctype resulting key will be of
4564 * @param data input random data to convert to a key
4565 * @param size size of input random data, at least krb5_enctype_keysize() long
4566 * @param key key, output key, free with krb5_free_keyblock_contents()
4568 * @return Return an error code or 0.
4570 * @ingroup krb5_crypto
4573 krb5_error_code KRB5_LIB_FUNCTION
4574 krb5_random_to_key(krb5_context context,
4575 krb5_enctype type,
4576 const void *data,
4577 size_t size,
4578 krb5_keyblock *key)
4580 krb5_error_code ret;
4581 struct encryption_type *et = _find_enctype(type);
4582 if(et == NULL) {
4583 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4584 N_("encryption type %d not supported", ""),
4585 type);
4586 return KRB5_PROG_ETYPE_NOSUPP;
4588 if ((et->keytype->bits + 7) / 8 > size) {
4589 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4590 N_("encryption key %s needs %d bytes "
4591 "of random to make an encryption key "
4592 "out of it", ""),
4593 et->name, (int)et->keytype->size);
4594 return KRB5_PROG_ETYPE_NOSUPP;
4596 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
4597 if(ret)
4598 return ret;
4599 key->keytype = type;
4600 if (et->keytype->random_to_key)
4601 (*et->keytype->random_to_key)(context, key, data, size);
4602 else
4603 memcpy(key->keyvalue.data, data, et->keytype->size);
4605 return 0;
4608 krb5_error_code
4609 _krb5_pk_octetstring2key(krb5_context context,
4610 krb5_enctype type,
4611 const void *dhdata,
4612 size_t dhsize,
4613 const heim_octet_string *c_n,
4614 const heim_octet_string *k_n,
4615 krb5_keyblock *key)
4617 struct encryption_type *et = _find_enctype(type);
4618 krb5_error_code ret;
4619 size_t keylen, offset;
4620 void *keydata;
4621 unsigned char counter;
4622 unsigned char shaoutput[SHA_DIGEST_LENGTH];
4623 EVP_MD_CTX *m;
4625 if(et == NULL) {
4626 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4627 N_("encryption type %d not supported", ""),
4628 type);
4629 return KRB5_PROG_ETYPE_NOSUPP;
4631 keylen = (et->keytype->bits + 7) / 8;
4633 keydata = malloc(keylen);
4634 if (keydata == NULL) {
4635 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4636 return ENOMEM;
4639 m = EVP_MD_CTX_create();
4640 if (m == NULL) {
4641 free(keydata);
4642 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4643 return ENOMEM;
4646 counter = 0;
4647 offset = 0;
4648 do {
4650 EVP_DigestInit_ex(m, EVP_sha1(), NULL);
4651 EVP_DigestUpdate(m, &counter, 1);
4652 EVP_DigestUpdate(m, dhdata, dhsize);
4654 if (c_n)
4655 EVP_DigestUpdate(m, c_n->data, c_n->length);
4656 if (k_n)
4657 EVP_DigestUpdate(m, k_n->data, k_n->length);
4659 EVP_DigestFinal_ex(m, shaoutput, NULL);
4661 memcpy((unsigned char *)keydata + offset,
4662 shaoutput,
4663 min(keylen - offset, sizeof(shaoutput)));
4665 offset += sizeof(shaoutput);
4666 counter++;
4667 } while(offset < keylen);
4668 memset(shaoutput, 0, sizeof(shaoutput));
4670 EVP_MD_CTX_destroy(m);
4672 ret = krb5_random_to_key(context, type, keydata, keylen, key);
4673 memset(keydata, 0, sizeof(keylen));
4674 free(keydata);
4675 return ret;
4678 static krb5_error_code
4679 encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
4681 KRB5PrincipalName pn;
4682 krb5_error_code ret;
4683 size_t size;
4685 pn.principalName = p->name;
4686 pn.realm = p->realm;
4688 ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
4689 &pn, &size, ret);
4690 if (ret) {
4691 krb5_data_zero(data);
4692 krb5_set_error_message(context, ret,
4693 N_("Failed to encode KRB5PrincipalName", ""));
4694 return ret;
4696 if (data->length != size)
4697 krb5_abortx(context, "asn1 compiler internal error");
4698 return 0;
4701 static krb5_error_code
4702 encode_otherinfo(krb5_context context,
4703 const AlgorithmIdentifier *ai,
4704 krb5_const_principal client,
4705 krb5_const_principal server,
4706 krb5_enctype enctype,
4707 const krb5_data *as_req,
4708 const krb5_data *pk_as_rep,
4709 const Ticket *ticket,
4710 krb5_data *other)
4712 PkinitSP80056AOtherInfo otherinfo;
4713 PkinitSuppPubInfo pubinfo;
4714 krb5_error_code ret;
4715 krb5_data pub;
4716 size_t size;
4718 krb5_data_zero(other);
4719 memset(&otherinfo, 0, sizeof(otherinfo));
4720 memset(&pubinfo, 0, sizeof(pubinfo));
4722 pubinfo.enctype = enctype;
4723 pubinfo.as_REQ = *as_req;
4724 pubinfo.pk_as_rep = *pk_as_rep;
4725 pubinfo.ticket = *ticket;
4726 ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
4727 &pubinfo, &size, ret);
4728 if (ret) {
4729 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4730 return ret;
4732 if (pub.length != size)
4733 krb5_abortx(context, "asn1 compiler internal error");
4735 ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
4736 if (ret) {
4737 free(pub.data);
4738 return ret;
4740 ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
4741 if (ret) {
4742 free(otherinfo.partyUInfo.data);
4743 free(pub.data);
4744 return ret;
4747 otherinfo.algorithmID = *ai;
4748 otherinfo.suppPubInfo = &pub;
4750 ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
4751 &otherinfo, &size, ret);
4752 free(otherinfo.partyUInfo.data);
4753 free(otherinfo.partyVInfo.data);
4754 free(pub.data);
4755 if (ret) {
4756 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4757 return ret;
4759 if (other->length != size)
4760 krb5_abortx(context, "asn1 compiler internal error");
4762 return 0;
4765 krb5_error_code
4766 _krb5_pk_kdf(krb5_context context,
4767 const struct AlgorithmIdentifier *ai,
4768 const void *dhdata,
4769 size_t dhsize,
4770 krb5_const_principal client,
4771 krb5_const_principal server,
4772 krb5_enctype enctype,
4773 const krb5_data *as_req,
4774 const krb5_data *pk_as_rep,
4775 const Ticket *ticket,
4776 krb5_keyblock *key)
4778 struct encryption_type *et;
4779 krb5_error_code ret;
4780 krb5_data other;
4781 size_t keylen, offset;
4782 uint32_t counter;
4783 unsigned char *keydata;
4784 unsigned char shaoutput[SHA_DIGEST_LENGTH];
4785 EVP_MD_CTX *m;
4787 if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) != 0) {
4788 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4789 N_("KDF not supported", ""));
4790 return KRB5_PROG_ETYPE_NOSUPP;
4792 if (ai->parameters != NULL &&
4793 (ai->parameters->length != 2 ||
4794 memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
4796 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4797 N_("kdf params not NULL or the NULL-type",
4798 ""));
4799 return KRB5_PROG_ETYPE_NOSUPP;
4802 et = _find_enctype(enctype);
4803 if(et == NULL) {
4804 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4805 N_("encryption type %d not supported", ""),
4806 enctype);
4807 return KRB5_PROG_ETYPE_NOSUPP;
4809 keylen = (et->keytype->bits + 7) / 8;
4811 keydata = malloc(keylen);
4812 if (keydata == NULL) {
4813 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4814 return ENOMEM;
4817 ret = encode_otherinfo(context, ai, client, server,
4818 enctype, as_req, pk_as_rep, ticket, &other);
4819 if (ret) {
4820 free(keydata);
4821 return ret;
4824 m = EVP_MD_CTX_create();
4825 if (m == NULL) {
4826 free(keydata);
4827 free(other.data);
4828 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4829 return ENOMEM;
4832 offset = 0;
4833 counter = 1;
4834 do {
4835 unsigned char cdata[4];
4837 EVP_DigestInit_ex(m, EVP_sha1(), NULL);
4838 _krb5_put_int(cdata, counter, 4);
4839 EVP_DigestUpdate(m, cdata, 4);
4840 EVP_DigestUpdate(m, dhdata, dhsize);
4841 EVP_DigestUpdate(m, other.data, other.length);
4843 EVP_DigestFinal_ex(m, shaoutput, NULL);
4845 memcpy((unsigned char *)keydata + offset,
4846 shaoutput,
4847 min(keylen - offset, sizeof(shaoutput)));
4849 offset += sizeof(shaoutput);
4850 counter++;
4851 } while(offset < keylen);
4852 memset(shaoutput, 0, sizeof(shaoutput));
4854 EVP_MD_CTX_destroy(m);
4855 free(other.data);
4857 ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
4858 memset(keydata, 0, sizeof(keylen));
4859 free(keydata);
4861 return ret;
4865 krb5_error_code KRB5_LIB_FUNCTION
4866 krb5_crypto_prf_length(krb5_context context,
4867 krb5_enctype type,
4868 size_t *length)
4870 struct encryption_type *et = _find_enctype(type);
4872 if(et == NULL || et->prf_length == 0) {
4873 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4874 N_("encryption type %d not supported", ""),
4875 type);
4876 return KRB5_PROG_ETYPE_NOSUPP;
4879 *length = et->prf_length;
4880 return 0;
4883 krb5_error_code KRB5_LIB_FUNCTION
4884 krb5_crypto_prf(krb5_context context,
4885 const krb5_crypto crypto,
4886 const krb5_data *input,
4887 krb5_data *output)
4889 struct encryption_type *et = crypto->et;
4891 krb5_data_zero(output);
4893 if(et->prf == NULL) {
4894 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4895 "kerberos prf for %s not supported",
4896 et->name);
4897 return KRB5_PROG_ETYPE_NOSUPP;
4900 return (*et->prf)(context, crypto, input, output);
4903 static krb5_error_code
4904 krb5_crypto_prfplus(krb5_context context,
4905 const krb5_crypto crypto,
4906 const krb5_data *input,
4907 size_t length,
4908 krb5_data *output)
4910 krb5_error_code ret;
4911 krb5_data input2;
4912 unsigned char i = 1;
4913 unsigned char *p;
4915 krb5_data_zero(&input2);
4916 krb5_data_zero(output);
4918 krb5_clear_error_message(context);
4920 ret = krb5_data_alloc(output, length);
4921 if (ret) goto out;
4922 ret = krb5_data_alloc(&input2, input->length + 1);
4923 if (ret) goto out;
4925 krb5_clear_error_message(context);
4927 memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
4929 p = output->data;
4931 while (length) {
4932 krb5_data block;
4934 ((unsigned char *)input2.data)[0] = i++;
4936 ret = krb5_crypto_prf(context, crypto, &input2, &block);
4937 if (ret)
4938 goto out;
4940 if (block.length < length) {
4941 memcpy(p, block.data, block.length);
4942 length -= block.length;
4943 } else {
4944 memcpy(p, block.data, length);
4945 length = 0;
4947 p += block.length;
4948 krb5_data_free(&block);
4951 out:
4952 krb5_data_free(&input2);
4953 if (ret)
4954 krb5_data_free(output);
4955 return 0;
4959 * The FX-CF2 key derivation function, used in FAST and preauth framework.
4961 * @param context Kerberos 5 context
4962 * @param crypto1 first key to combine
4963 * @param crypto2 second key to combine
4964 * @param pepper1 factor to combine with first key to garante uniqueness
4965 * @param pepper2 factor to combine with second key to garante uniqueness
4966 * @param enctype the encryption type of the resulting key
4967 * @param res allocated key, free with krb5_free_keyblock_contents()
4969 * @return Return an error code or 0.
4971 * @ingroup krb5_crypto
4974 krb5_error_code KRB5_LIB_FUNCTION
4975 krb5_crypto_fx_cf2(krb5_context context,
4976 const krb5_crypto crypto1,
4977 const krb5_crypto crypto2,
4978 krb5_data *pepper1,
4979 krb5_data *pepper2,
4980 krb5_enctype enctype,
4981 krb5_keyblock *res)
4983 krb5_error_code ret;
4984 krb5_data os1, os2;
4985 size_t i, keysize;
4987 memset(res, 0, sizeof(*res));
4989 ret = krb5_enctype_keysize(context, enctype, &keysize);
4990 if (ret)
4991 return ret;
4993 ret = krb5_data_alloc(&res->keyvalue, keysize);
4994 if (ret)
4995 goto out;
4996 ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
4997 if (ret)
4998 goto out;
4999 ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
5000 if (ret)
5001 goto out;
5003 res->keytype = enctype;
5005 unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
5006 for (i = 0; i < keysize; i++)
5007 p3[i] = p1[i] ^ p2[i];
5009 out:
5010 if (ret)
5011 krb5_data_free(&res->keyvalue);
5012 krb5_data_free(&os1);
5013 krb5_data_free(&os2);
5015 return ret;
5020 #ifndef HEIMDAL_SMALLER
5022 krb5_error_code KRB5_LIB_FUNCTION
5023 krb5_keytype_to_enctypes (krb5_context context,
5024 krb5_keytype keytype,
5025 unsigned *len,
5026 krb5_enctype **val)
5027 KRB5_DEPRECATED
5029 int i;
5030 unsigned n = 0;
5031 krb5_enctype *ret;
5033 for (i = num_etypes - 1; i >= 0; --i) {
5034 if (etypes[i]->keytype->type == keytype
5035 && !(etypes[i]->flags & F_PSEUDO)
5036 && krb5_enctype_valid(context, etypes[i]->type) == 0)
5037 ++n;
5039 if (n == 0) {
5040 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
5041 "Keytype have no mapping");
5042 return KRB5_PROG_KEYTYPE_NOSUPP;
5045 ret = malloc(n * sizeof(*ret));
5046 if (ret == NULL && n != 0) {
5047 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
5048 return ENOMEM;
5050 n = 0;
5051 for (i = num_etypes - 1; i >= 0; --i) {
5052 if (etypes[i]->keytype->type == keytype
5053 && !(etypes[i]->flags & F_PSEUDO)
5054 && krb5_enctype_valid(context, etypes[i]->type) == 0)
5055 ret[n++] = etypes[i]->type;
5057 *len = n;
5058 *val = ret;
5059 return 0;
5062 /* if two enctypes have compatible keys */
5063 krb5_boolean KRB5_LIB_FUNCTION
5064 krb5_enctypes_compatible_keys(krb5_context context,
5065 krb5_enctype etype1,
5066 krb5_enctype etype2)
5067 KRB5_DEPRECATED
5069 struct encryption_type *e1 = _find_enctype(etype1);
5070 struct encryption_type *e2 = _find_enctype(etype2);
5071 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
5074 #endif /* HEIMDAL_SMALLER */