heimdal: added verbose logging of hemimdal crypto errors
[heimdal.git] / lib / krb5 / crypto.c
blob47f910260e36a0f734cd5268a63db1b1e7e5ac2b
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 */
70 #define F_WEAK 128 /* enctype is considered weak */
72 struct salt_type {
73 krb5_salttype type;
74 const char *name;
75 krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
76 krb5_salt, krb5_data, krb5_keyblock*);
79 struct key_type {
80 krb5_keytype type; /* XXX */
81 const char *name;
82 size_t bits;
83 size_t size;
84 size_t schedule_size;
85 void (*random_key)(krb5_context, krb5_keyblock*);
86 void (*schedule)(krb5_context, struct key_type *, struct key_data *);
87 struct salt_type *string_to_key;
88 void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
89 void (*cleanup)(krb5_context, struct key_data *);
90 const EVP_CIPHER *(*evp)(void);
93 struct checksum_type {
94 krb5_cksumtype type;
95 const char *name;
96 size_t blocksize;
97 size_t checksumsize;
98 unsigned flags;
99 krb5_error_code (*checksum)(krb5_context context,
100 struct key_data *key,
101 const void *buf, size_t len,
102 unsigned usage,
103 Checksum *csum);
104 krb5_error_code (*verify)(krb5_context context,
105 struct key_data *key,
106 const void *buf, size_t len,
107 unsigned usage,
108 Checksum *csum);
111 struct encryption_type {
112 krb5_enctype type;
113 const char *name;
114 size_t blocksize;
115 size_t padsize;
116 size_t confoundersize;
117 struct key_type *keytype;
118 struct checksum_type *checksum;
119 struct checksum_type *keyed_checksum;
120 unsigned flags;
121 krb5_error_code (*encrypt)(krb5_context context,
122 struct key_data *key,
123 void *data, size_t len,
124 krb5_boolean encryptp,
125 int usage,
126 void *ivec);
127 size_t prf_length;
128 krb5_error_code (*prf)(krb5_context,
129 krb5_crypto, const krb5_data *, krb5_data *);
132 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
133 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
134 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
136 static struct checksum_type *_find_checksum(krb5_cksumtype type);
137 static struct encryption_type *_find_enctype(krb5_enctype type);
138 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
139 unsigned, struct key_data**);
140 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
141 static krb5_error_code derive_key(krb5_context context,
142 struct encryption_type *et,
143 struct key_data *key,
144 const void *constant,
145 size_t len);
146 static krb5_error_code hmac(krb5_context context,
147 struct checksum_type *cm,
148 const void *data,
149 size_t len,
150 unsigned usage,
151 struct key_data *keyblock,
152 Checksum *result);
153 static void free_key_data(krb5_context,
154 struct key_data *,
155 struct encryption_type *);
156 static void free_key_schedule(krb5_context,
157 struct key_data *,
158 struct encryption_type *);
159 static krb5_error_code usage2arcfour (krb5_context, unsigned *);
160 static void xor (DES_cblock *, const unsigned char *);
162 /************************************************************
164 ************************************************************/
166 struct evp_schedule {
167 EVP_CIPHER_CTX ectx;
168 EVP_CIPHER_CTX dctx;
172 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
174 #ifdef HEIM_WEAK_CRYPTO
175 static void
176 krb5_DES_random_key(krb5_context context,
177 krb5_keyblock *key)
179 DES_cblock *k = key->keyvalue.data;
180 do {
181 krb5_generate_random_block(k, sizeof(DES_cblock));
182 DES_set_odd_parity(k);
183 } while(DES_is_weak_key(k));
186 static void
187 krb5_DES_schedule_old(krb5_context context,
188 struct key_type *kt,
189 struct key_data *key)
191 DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
194 #ifdef ENABLE_AFS_STRING_TO_KEY
196 /* This defines the Andrew string_to_key function. It accepts a password
197 * string as input and converts it via a one-way encryption algorithm to a DES
198 * encryption key. It is compatible with the original Andrew authentication
199 * service password database.
203 * Short passwords, i.e 8 characters or less.
205 static void
206 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
207 krb5_data cell,
208 DES_cblock *key)
210 char password[8+1]; /* crypt is limited to 8 chars anyway */
211 int i;
213 for(i = 0; i < 8; i++) {
214 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
215 ((i < cell.length) ?
216 tolower(((unsigned char*)cell.data)[i]) : 0);
217 password[i] = c ? c : 'X';
219 password[8] = '\0';
221 memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
223 /* parity is inserted into the LSB so left shift each byte up one
224 bit. This allows ascii characters with a zero MSB to retain as
225 much significance as possible. */
226 for (i = 0; i < sizeof(DES_cblock); i++)
227 ((unsigned char*)key)[i] <<= 1;
228 DES_set_odd_parity (key);
232 * Long passwords, i.e 9 characters or more.
234 static void
235 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
236 krb5_data cell,
237 DES_cblock *key)
239 DES_key_schedule schedule;
240 DES_cblock temp_key;
241 DES_cblock ivec;
242 char password[512];
243 size_t passlen;
245 memcpy(password, pw.data, min(pw.length, sizeof(password)));
246 if(pw.length < sizeof(password)) {
247 int len = min(cell.length, sizeof(password) - pw.length);
248 int i;
250 memcpy(password + pw.length, cell.data, len);
251 for (i = pw.length; i < pw.length + len; ++i)
252 password[i] = tolower((unsigned char)password[i]);
254 passlen = min(sizeof(password), pw.length + cell.length);
255 memcpy(&ivec, "kerberos", 8);
256 memcpy(&temp_key, "kerberos", 8);
257 DES_set_odd_parity (&temp_key);
258 DES_set_key_unchecked (&temp_key, &schedule);
259 DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
261 memcpy(&temp_key, &ivec, 8);
262 DES_set_odd_parity (&temp_key);
263 DES_set_key_unchecked (&temp_key, &schedule);
264 DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
265 memset(&schedule, 0, sizeof(schedule));
266 memset(&temp_key, 0, sizeof(temp_key));
267 memset(&ivec, 0, sizeof(ivec));
268 memset(password, 0, sizeof(password));
270 DES_set_odd_parity (key);
273 static krb5_error_code
274 DES_AFS3_string_to_key(krb5_context context,
275 krb5_enctype enctype,
276 krb5_data password,
277 krb5_salt salt,
278 krb5_data opaque,
279 krb5_keyblock *key)
281 DES_cblock tmp;
282 if(password.length > 8)
283 krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
284 else
285 krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
286 key->keytype = enctype;
287 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
288 memset(&key, 0, sizeof(key));
289 return 0;
291 #endif /* ENABLE_AFS_STRING_TO_KEY */
293 static void
294 DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
296 DES_key_schedule schedule;
297 int i;
298 int reverse = 0;
299 unsigned char *p;
301 unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
302 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
303 memset(key, 0, 8);
305 p = (unsigned char*)key;
306 for (i = 0; i < length; i++) {
307 unsigned char tmp = data[i];
308 if (!reverse)
309 *p++ ^= (tmp << 1);
310 else
311 *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
312 if((i % 8) == 7)
313 reverse = !reverse;
315 DES_set_odd_parity(key);
316 if(DES_is_weak_key(key))
317 (*key)[7] ^= 0xF0;
318 DES_set_key_unchecked(key, &schedule);
319 DES_cbc_cksum((void*)data, key, length, &schedule, key);
320 memset(&schedule, 0, sizeof(schedule));
321 DES_set_odd_parity(key);
322 if(DES_is_weak_key(key))
323 (*key)[7] ^= 0xF0;
326 static krb5_error_code
327 krb5_DES_string_to_key(krb5_context context,
328 krb5_enctype enctype,
329 krb5_data password,
330 krb5_salt salt,
331 krb5_data opaque,
332 krb5_keyblock *key)
334 unsigned char *s;
335 size_t len;
336 DES_cblock tmp;
338 #ifdef ENABLE_AFS_STRING_TO_KEY
339 if (opaque.length == 1) {
340 unsigned long v;
341 _krb5_get_int(opaque.data, &v, 1);
342 if (v == 1)
343 return DES_AFS3_string_to_key(context, enctype, password,
344 salt, opaque, key);
346 #endif
348 len = password.length + salt.saltvalue.length;
349 s = malloc(len);
350 if(len > 0 && s == NULL) {
351 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
352 return ENOMEM;
354 memcpy(s, password.data, password.length);
355 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
356 DES_string_to_key_int(s, len, &tmp);
357 key->keytype = enctype;
358 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
359 memset(&tmp, 0, sizeof(tmp));
360 memset(s, 0, len);
361 free(s);
362 return 0;
365 static void
366 krb5_DES_random_to_key(krb5_context context,
367 krb5_keyblock *key,
368 const void *data,
369 size_t size)
371 DES_cblock *k = key->keyvalue.data;
372 memcpy(k, data, key->keyvalue.length);
373 DES_set_odd_parity(k);
374 if(DES_is_weak_key(k))
375 xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
377 #endif
383 static void
384 DES3_random_key(krb5_context context,
385 krb5_keyblock *key)
387 DES_cblock *k = key->keyvalue.data;
388 do {
389 krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
390 DES_set_odd_parity(&k[0]);
391 DES_set_odd_parity(&k[1]);
392 DES_set_odd_parity(&k[2]);
393 } while(DES_is_weak_key(&k[0]) ||
394 DES_is_weak_key(&k[1]) ||
395 DES_is_weak_key(&k[2]));
399 * A = A xor B. A & B are 8 bytes.
402 static void
403 xor (DES_cblock *key, const unsigned char *b)
405 unsigned char *a = (unsigned char*)key;
406 a[0] ^= b[0];
407 a[1] ^= b[1];
408 a[2] ^= b[2];
409 a[3] ^= b[3];
410 a[4] ^= b[4];
411 a[5] ^= b[5];
412 a[6] ^= b[6];
413 a[7] ^= b[7];
416 #ifdef DES3_OLD_ENCTYPE
417 static krb5_error_code
418 DES3_string_to_key(krb5_context context,
419 krb5_enctype enctype,
420 krb5_data password,
421 krb5_salt salt,
422 krb5_data opaque,
423 krb5_keyblock *key)
425 char *str;
426 size_t len;
427 unsigned char tmp[24];
428 DES_cblock keys[3];
429 krb5_error_code ret;
431 len = password.length + salt.saltvalue.length;
432 str = malloc(len);
433 if(len != 0 && str == NULL) {
434 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
435 return ENOMEM;
437 memcpy(str, password.data, password.length);
438 memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
440 DES_cblock ivec;
441 DES_key_schedule s[3];
442 int i;
444 ret = _krb5_n_fold(str, len, tmp, 24);
445 if (ret) {
446 memset(str, 0, len);
447 free(str);
448 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
449 return ret;
452 for(i = 0; i < 3; i++){
453 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
454 DES_set_odd_parity(keys + i);
455 if(DES_is_weak_key(keys + i))
456 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
457 DES_set_key_unchecked(keys + i, &s[i]);
459 memset(&ivec, 0, sizeof(ivec));
460 DES_ede3_cbc_encrypt(tmp,
461 tmp, sizeof(tmp),
462 &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
463 memset(s, 0, sizeof(s));
464 memset(&ivec, 0, sizeof(ivec));
465 for(i = 0; i < 3; i++){
466 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
467 DES_set_odd_parity(keys + i);
468 if(DES_is_weak_key(keys + i))
469 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
471 memset(tmp, 0, sizeof(tmp));
473 key->keytype = enctype;
474 krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
475 memset(keys, 0, sizeof(keys));
476 memset(str, 0, len);
477 free(str);
478 return 0;
480 #endif
482 static krb5_error_code
483 DES3_string_to_key_derived(krb5_context context,
484 krb5_enctype enctype,
485 krb5_data password,
486 krb5_salt salt,
487 krb5_data opaque,
488 krb5_keyblock *key)
490 krb5_error_code ret;
491 size_t len = password.length + salt.saltvalue.length;
492 char *s;
494 s = malloc(len);
495 if(len != 0 && s == NULL) {
496 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
497 return ENOMEM;
499 memcpy(s, password.data, password.length);
500 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
501 ret = krb5_string_to_key_derived(context,
503 len,
504 enctype,
505 key);
506 memset(s, 0, len);
507 free(s);
508 return ret;
511 static void
512 DES3_random_to_key(krb5_context context,
513 krb5_keyblock *key,
514 const void *data,
515 size_t size)
517 unsigned char *x = key->keyvalue.data;
518 const u_char *q = data;
519 DES_cblock *k;
520 int i, j;
522 memset(x, 0, sizeof(x));
523 for (i = 0; i < 3; ++i) {
524 unsigned char foo;
525 for (j = 0; j < 7; ++j) {
526 unsigned char b = q[7 * i + j];
528 x[8 * i + j] = b;
530 foo = 0;
531 for (j = 6; j >= 0; --j) {
532 foo |= q[7 * i + j] & 1;
533 foo <<= 1;
535 x[8 * i + 7] = foo;
537 k = key->keyvalue.data;
538 for (i = 0; i < 3; i++) {
539 DES_set_odd_parity(&k[i]);
540 if(DES_is_weak_key(&k[i]))
541 xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
546 * ARCFOUR
549 static krb5_error_code
550 ARCFOUR_string_to_key(krb5_context context,
551 krb5_enctype enctype,
552 krb5_data password,
553 krb5_salt salt,
554 krb5_data opaque,
555 krb5_keyblock *key)
557 krb5_error_code ret;
558 uint16_t *s = NULL;
559 size_t len, i;
560 EVP_MD_CTX *m;
562 m = EVP_MD_CTX_create();
563 if (m == NULL) {
564 ret = ENOMEM;
565 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
566 goto out;
569 EVP_DigestInit_ex(m, EVP_md4(), NULL);
571 ret = wind_utf8ucs2_length(password.data, &len);
572 if (ret) {
573 krb5_set_error_message (context, ret,
574 N_("Password not an UCS2 string", ""));
575 goto out;
578 s = malloc (len * sizeof(s[0]));
579 if (len != 0 && s == NULL) {
580 krb5_set_error_message (context, ENOMEM,
581 N_("malloc: out of memory", ""));
582 ret = ENOMEM;
583 goto out;
586 ret = wind_utf8ucs2(password.data, s, &len);
587 if (ret) {
588 krb5_set_error_message (context, ret,
589 N_("Password not an UCS2 string", ""));
590 goto out;
593 /* LE encoding */
594 for (i = 0; i < len; i++) {
595 unsigned char p;
596 p = (s[i] & 0xff);
597 EVP_DigestUpdate (m, &p, 1);
598 p = (s[i] >> 8) & 0xff;
599 EVP_DigestUpdate (m, &p, 1);
602 key->keytype = enctype;
603 ret = krb5_data_alloc (&key->keyvalue, 16);
604 if (ret) {
605 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
606 goto out;
608 EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
610 out:
611 EVP_MD_CTX_destroy(m);
612 if (s)
613 memset (s, 0, len);
614 free (s);
615 return ret;
619 * AES
622 int _krb5_AES_string_to_default_iterator = 4096;
624 static krb5_error_code
625 AES_string_to_key(krb5_context context,
626 krb5_enctype enctype,
627 krb5_data password,
628 krb5_salt salt,
629 krb5_data opaque,
630 krb5_keyblock *key)
632 krb5_error_code ret;
633 uint32_t iter;
634 struct encryption_type *et;
635 struct key_data kd;
637 if (opaque.length == 0)
638 iter = _krb5_AES_string_to_default_iterator;
639 else if (opaque.length == 4) {
640 unsigned long v;
641 _krb5_get_int(opaque.data, &v, 4);
642 iter = ((uint32_t)v);
643 } else
644 return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
646 et = _find_enctype(enctype);
647 if (et == NULL)
648 return KRB5_PROG_KEYTYPE_NOSUPP;
650 kd.schedule = NULL;
651 ALLOC(kd.key, 1);
652 if(kd.key == NULL) {
653 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
654 return ENOMEM;
656 kd.key->keytype = enctype;
657 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
658 if (ret) {
659 krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
660 return ret;
663 ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
664 salt.saltvalue.data, salt.saltvalue.length,
665 iter,
666 et->keytype->size, kd.key->keyvalue.data);
667 if (ret != 1) {
668 free_key_data(context, &kd, et);
669 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
670 "Error calculating s2k");
671 return KRB5_PROG_KEYTYPE_NOSUPP;
674 ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
675 if (ret == 0)
676 ret = krb5_copy_keyblock_contents(context, kd.key, key);
677 free_key_data(context, &kd, et);
679 return ret;
682 static void
683 evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd)
685 struct evp_schedule *key = kd->schedule->data;
686 const EVP_CIPHER *c = (*kt->evp)();
688 EVP_CIPHER_CTX_init(&key->ectx);
689 EVP_CIPHER_CTX_init(&key->dctx);
691 EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
692 EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
695 static void
696 evp_cleanup(krb5_context context, struct key_data *kd)
698 struct evp_schedule *key = kd->schedule->data;
699 EVP_CIPHER_CTX_cleanup(&key->ectx);
700 EVP_CIPHER_CTX_cleanup(&key->dctx);
707 #ifdef HEIM_WEAK_CRYPTO
708 static struct salt_type des_salt[] = {
710 KRB5_PW_SALT,
711 "pw-salt",
712 krb5_DES_string_to_key
714 #ifdef ENABLE_AFS_STRING_TO_KEY
716 KRB5_AFS3_SALT,
717 "afs3-salt",
718 DES_AFS3_string_to_key
720 #endif
721 { 0 }
723 #endif
725 #ifdef DES3_OLD_ENCTYPE
726 static struct salt_type des3_salt[] = {
728 KRB5_PW_SALT,
729 "pw-salt",
730 DES3_string_to_key
732 { 0 }
734 #endif
736 static struct salt_type des3_salt_derived[] = {
738 KRB5_PW_SALT,
739 "pw-salt",
740 DES3_string_to_key_derived
742 { 0 }
745 static struct salt_type AES_salt[] = {
747 KRB5_PW_SALT,
748 "pw-salt",
749 AES_string_to_key
751 { 0 }
754 static struct salt_type arcfour_salt[] = {
756 KRB5_PW_SALT,
757 "pw-salt",
758 ARCFOUR_string_to_key
760 { 0 }
767 static struct key_type keytype_null = {
768 KEYTYPE_NULL,
769 "null",
773 NULL,
774 NULL,
775 NULL
778 #ifdef HEIM_WEAK_CRYPTO
779 static struct key_type keytype_des_old = {
780 KEYTYPE_DES,
781 "des-old",
784 sizeof(DES_key_schedule),
785 krb5_DES_random_key,
786 krb5_DES_schedule_old,
787 des_salt,
788 krb5_DES_random_to_key
791 static struct key_type keytype_des = {
792 KEYTYPE_DES,
793 "des",
796 sizeof(struct evp_schedule),
797 krb5_DES_random_key,
798 evp_schedule,
799 des_salt,
800 krb5_DES_random_to_key,
801 evp_cleanup,
802 EVP_des_cbc
804 #endif /* HEIM_WEAK_CRYPTO */
806 #ifdef DES3_OLD_ENCTYPE
807 static struct key_type keytype_des3 = {
808 KEYTYPE_DES3,
809 "des3",
810 168,
812 sizeof(struct evp_schedule),
813 DES3_random_key,
814 evp_schedule,
815 des3_salt,
816 DES3_random_to_key,
817 evp_cleanup,
818 EVP_des_ede3_cbc
820 #endif
822 static struct key_type keytype_des3_derived = {
823 KEYTYPE_DES3,
824 "des3",
825 168,
827 sizeof(struct evp_schedule),
828 DES3_random_key,
829 evp_schedule,
830 des3_salt_derived,
831 DES3_random_to_key,
832 evp_cleanup,
833 EVP_des_ede3_cbc
836 static struct key_type keytype_aes128 = {
837 KEYTYPE_AES128,
838 "aes-128",
839 128,
841 sizeof(struct evp_schedule),
842 NULL,
843 evp_schedule,
844 AES_salt,
845 NULL,
846 evp_cleanup,
847 EVP_aes_128_cbc
850 static struct key_type keytype_aes256 = {
851 KEYTYPE_AES256,
852 "aes-256",
853 256,
855 sizeof(struct evp_schedule),
856 NULL,
857 evp_schedule,
858 AES_salt,
859 NULL,
860 evp_cleanup,
861 EVP_aes_256_cbc
864 static struct key_type keytype_arcfour = {
865 KEYTYPE_ARCFOUR,
866 "arcfour",
867 128,
869 sizeof(struct evp_schedule),
870 NULL,
871 evp_schedule,
872 arcfour_salt,
873 NULL,
874 evp_cleanup,
875 EVP_rc4
878 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
879 krb5_salttype_to_string (krb5_context context,
880 krb5_enctype etype,
881 krb5_salttype stype,
882 char **string)
884 struct encryption_type *e;
885 struct salt_type *st;
887 e = _find_enctype (etype);
888 if (e == NULL) {
889 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
890 "encryption type %d not supported",
891 etype);
892 return KRB5_PROG_ETYPE_NOSUPP;
894 for (st = e->keytype->string_to_key; st && st->type; st++) {
895 if (st->type == stype) {
896 *string = strdup (st->name);
897 if (*string == NULL) {
898 krb5_set_error_message (context, ENOMEM,
899 N_("malloc: out of memory", ""));
900 return ENOMEM;
902 return 0;
905 krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
906 "salttype %d not supported", stype);
907 return HEIM_ERR_SALTTYPE_NOSUPP;
910 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
911 krb5_string_to_salttype (krb5_context context,
912 krb5_enctype etype,
913 const char *string,
914 krb5_salttype *salttype)
916 struct encryption_type *e;
917 struct salt_type *st;
919 e = _find_enctype (etype);
920 if (e == NULL) {
921 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
922 N_("encryption type %d not supported", ""),
923 etype);
924 return KRB5_PROG_ETYPE_NOSUPP;
926 for (st = e->keytype->string_to_key; st && st->type; st++) {
927 if (strcasecmp (st->name, string) == 0) {
928 *salttype = st->type;
929 return 0;
932 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
933 N_("salttype %s not supported", ""), string);
934 return HEIM_ERR_SALTTYPE_NOSUPP;
937 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
938 krb5_get_pw_salt(krb5_context context,
939 krb5_const_principal principal,
940 krb5_salt *salt)
942 size_t len;
943 int i;
944 krb5_error_code ret;
945 char *p;
947 salt->salttype = KRB5_PW_SALT;
948 len = strlen(principal->realm);
949 for (i = 0; i < principal->name.name_string.len; ++i)
950 len += strlen(principal->name.name_string.val[i]);
951 ret = krb5_data_alloc (&salt->saltvalue, len);
952 if (ret)
953 return ret;
954 p = salt->saltvalue.data;
955 memcpy (p, principal->realm, strlen(principal->realm));
956 p += strlen(principal->realm);
957 for (i = 0; i < principal->name.name_string.len; ++i) {
958 memcpy (p,
959 principal->name.name_string.val[i],
960 strlen(principal->name.name_string.val[i]));
961 p += strlen(principal->name.name_string.val[i]);
963 return 0;
966 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
967 krb5_free_salt(krb5_context context,
968 krb5_salt salt)
970 krb5_data_free(&salt.saltvalue);
971 return 0;
974 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
975 krb5_string_to_key_data (krb5_context context,
976 krb5_enctype enctype,
977 krb5_data password,
978 krb5_principal principal,
979 krb5_keyblock *key)
981 krb5_error_code ret;
982 krb5_salt salt;
984 ret = krb5_get_pw_salt(context, principal, &salt);
985 if(ret)
986 return ret;
987 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
988 krb5_free_salt(context, salt);
989 return ret;
992 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
993 krb5_string_to_key (krb5_context context,
994 krb5_enctype enctype,
995 const char *password,
996 krb5_principal principal,
997 krb5_keyblock *key)
999 krb5_data pw;
1000 pw.data = rk_UNCONST(password);
1001 pw.length = strlen(password);
1002 return krb5_string_to_key_data(context, enctype, pw, principal, key);
1005 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1006 krb5_string_to_key_data_salt (krb5_context context,
1007 krb5_enctype enctype,
1008 krb5_data password,
1009 krb5_salt salt,
1010 krb5_keyblock *key)
1012 krb5_data opaque;
1013 krb5_data_zero(&opaque);
1014 return krb5_string_to_key_data_salt_opaque(context, enctype, password,
1015 salt, opaque, key);
1019 * Do a string -> key for encryption type `enctype' operation on
1020 * `password' (with salt `salt' and the enctype specific data string
1021 * `opaque'), returning the resulting key in `key'
1024 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1025 krb5_string_to_key_data_salt_opaque (krb5_context context,
1026 krb5_enctype enctype,
1027 krb5_data password,
1028 krb5_salt salt,
1029 krb5_data opaque,
1030 krb5_keyblock *key)
1032 struct encryption_type *et =_find_enctype(enctype);
1033 struct salt_type *st;
1034 if(et == NULL) {
1035 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1036 N_("encryption type %d not supported", ""),
1037 enctype);
1038 return KRB5_PROG_ETYPE_NOSUPP;
1040 for(st = et->keytype->string_to_key; st && st->type; st++)
1041 if(st->type == salt.salttype)
1042 return (*st->string_to_key)(context, enctype, password,
1043 salt, opaque, key);
1044 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
1045 N_("salt type %d not supported", ""),
1046 salt.salttype);
1047 return HEIM_ERR_SALTTYPE_NOSUPP;
1051 * Do a string -> key for encryption type `enctype' operation on the
1052 * string `password' (with salt `salt'), returning the resulting key
1053 * in `key'
1056 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1057 krb5_string_to_key_salt (krb5_context context,
1058 krb5_enctype enctype,
1059 const char *password,
1060 krb5_salt salt,
1061 krb5_keyblock *key)
1063 krb5_data pw;
1064 pw.data = rk_UNCONST(password);
1065 pw.length = strlen(password);
1066 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
1069 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1070 krb5_string_to_key_salt_opaque (krb5_context context,
1071 krb5_enctype enctype,
1072 const char *password,
1073 krb5_salt salt,
1074 krb5_data opaque,
1075 krb5_keyblock *key)
1077 krb5_data pw;
1078 pw.data = rk_UNCONST(password);
1079 pw.length = strlen(password);
1080 return krb5_string_to_key_data_salt_opaque(context, enctype,
1081 pw, salt, opaque, key);
1084 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1085 krb5_enctype_keysize(krb5_context context,
1086 krb5_enctype type,
1087 size_t *keysize)
1089 struct encryption_type *et = _find_enctype(type);
1090 if(et == NULL) {
1091 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1092 N_("encryption type %d not supported", ""),
1093 type);
1094 return KRB5_PROG_ETYPE_NOSUPP;
1096 *keysize = et->keytype->size;
1097 return 0;
1100 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1101 krb5_enctype_keybits(krb5_context context,
1102 krb5_enctype type,
1103 size_t *keybits)
1105 struct encryption_type *et = _find_enctype(type);
1106 if(et == NULL) {
1107 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1108 "encryption type %d not supported",
1109 type);
1110 return KRB5_PROG_ETYPE_NOSUPP;
1112 *keybits = et->keytype->bits;
1113 return 0;
1116 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1117 krb5_generate_random_keyblock(krb5_context context,
1118 krb5_enctype type,
1119 krb5_keyblock *key)
1121 krb5_error_code ret;
1122 struct encryption_type *et = _find_enctype(type);
1123 if(et == NULL) {
1124 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1125 N_("encryption type %d not supported", ""),
1126 type);
1127 return KRB5_PROG_ETYPE_NOSUPP;
1129 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
1130 if(ret)
1131 return ret;
1132 key->keytype = type;
1133 if(et->keytype->random_key)
1134 (*et->keytype->random_key)(context, key);
1135 else
1136 krb5_generate_random_block(key->keyvalue.data,
1137 key->keyvalue.length);
1138 return 0;
1141 static krb5_error_code
1142 _key_schedule(krb5_context context,
1143 struct key_data *key)
1145 krb5_error_code ret;
1146 struct encryption_type *et = _find_enctype(key->key->keytype);
1147 struct key_type *kt;
1149 if (et == NULL) {
1150 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
1151 N_("encryption type %d not supported", ""),
1152 key->key->keytype);
1153 return KRB5_PROG_ETYPE_NOSUPP;
1156 kt = et->keytype;
1158 if(kt->schedule == NULL)
1159 return 0;
1160 if (key->schedule != NULL)
1161 return 0;
1162 ALLOC(key->schedule, 1);
1163 if(key->schedule == NULL) {
1164 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1165 return ENOMEM;
1167 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
1168 if(ret) {
1169 free(key->schedule);
1170 key->schedule = NULL;
1171 return ret;
1173 (*kt->schedule)(context, kt, key);
1174 return 0;
1177 /************************************************************
1179 ************************************************************/
1181 static krb5_error_code
1182 NONE_checksum(krb5_context context,
1183 struct key_data *key,
1184 const void *data,
1185 size_t len,
1186 unsigned usage,
1187 Checksum *C)
1189 return 0;
1192 #if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO)
1194 static krb5_error_code
1195 des_checksum(krb5_context context,
1196 const EVP_MD *evp_md,
1197 struct key_data *key,
1198 const void *data,
1199 size_t len,
1200 Checksum *cksum)
1202 struct evp_schedule *ctx = key->schedule->data;
1203 EVP_MD_CTX *m;
1204 DES_cblock ivec;
1205 unsigned char *p = cksum->checksum.data;
1207 krb5_generate_random_block(p, 8);
1209 m = EVP_MD_CTX_create();
1210 if (m == NULL) {
1211 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1212 return ENOMEM;
1215 EVP_DigestInit_ex(m, evp_md, NULL);
1216 EVP_DigestUpdate(m, p, 8);
1217 EVP_DigestUpdate(m, data, len);
1218 EVP_DigestFinal_ex (m, p + 8, NULL);
1219 EVP_MD_CTX_destroy(m);
1220 memset (&ivec, 0, sizeof(ivec));
1221 EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
1222 EVP_Cipher(&ctx->ectx, p, p, 24);
1224 return 0;
1227 static krb5_error_code
1228 des_verify(krb5_context context,
1229 const EVP_MD *evp_md,
1230 struct key_data *key,
1231 const void *data,
1232 size_t len,
1233 Checksum *C)
1235 struct evp_schedule *ctx = key->schedule->data;
1236 EVP_MD_CTX *m;
1237 unsigned char tmp[24];
1238 unsigned char res[16];
1239 DES_cblock ivec;
1240 krb5_error_code ret = 0;
1242 m = EVP_MD_CTX_create();
1243 if (m == NULL) {
1244 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1245 return ENOMEM;
1248 memset(&ivec, 0, sizeof(ivec));
1249 EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
1250 EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
1252 EVP_DigestInit_ex(m, evp_md, NULL);
1253 EVP_DigestUpdate(m, tmp, 8); /* confounder */
1254 EVP_DigestUpdate(m, data, len);
1255 EVP_DigestFinal_ex (m, res, NULL);
1256 EVP_MD_CTX_destroy(m);
1257 if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) {
1258 krb5_clear_error_message (context);
1259 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1261 memset(tmp, 0, sizeof(tmp));
1262 memset(res, 0, sizeof(res));
1263 return ret;
1266 #endif
1268 #ifdef HEIM_WEAK_CRYPTO
1270 static krb5_error_code
1271 CRC32_checksum(krb5_context context,
1272 struct key_data *key,
1273 const void *data,
1274 size_t len,
1275 unsigned usage,
1276 Checksum *C)
1278 uint32_t crc;
1279 unsigned char *r = C->checksum.data;
1280 _krb5_crc_init_table ();
1281 crc = _krb5_crc_update (data, len, 0);
1282 r[0] = crc & 0xff;
1283 r[1] = (crc >> 8) & 0xff;
1284 r[2] = (crc >> 16) & 0xff;
1285 r[3] = (crc >> 24) & 0xff;
1286 return 0;
1289 static krb5_error_code
1290 RSA_MD4_checksum(krb5_context context,
1291 struct key_data *key,
1292 const void *data,
1293 size_t len,
1294 unsigned usage,
1295 Checksum *C)
1297 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
1298 krb5_abortx(context, "md4 checksum failed");
1299 return 0;
1302 static krb5_error_code
1303 RSA_MD4_DES_checksum(krb5_context context,
1304 struct key_data *key,
1305 const void *data,
1306 size_t len,
1307 unsigned usage,
1308 Checksum *cksum)
1310 return des_checksum(context, EVP_md4(), key, data, len, cksum);
1313 static krb5_error_code
1314 RSA_MD4_DES_verify(krb5_context context,
1315 struct key_data *key,
1316 const void *data,
1317 size_t len,
1318 unsigned usage,
1319 Checksum *C)
1321 return des_verify(context, EVP_md5(), key, data, len, C);
1324 static krb5_error_code
1325 RSA_MD5_DES_checksum(krb5_context context,
1326 struct key_data *key,
1327 const void *data,
1328 size_t len,
1329 unsigned usage,
1330 Checksum *C)
1332 return des_checksum(context, EVP_md5(), key, data, len, C);
1335 static krb5_error_code
1336 RSA_MD5_DES_verify(krb5_context context,
1337 struct key_data *key,
1338 const void *data,
1339 size_t len,
1340 unsigned usage,
1341 Checksum *C)
1343 return des_verify(context, EVP_md5(), key, data, len, C);
1346 #endif /* HEIM_WEAK_CRYPTO */
1348 #ifdef DES3_OLD_ENCTYPE
1349 static krb5_error_code
1350 RSA_MD5_DES3_checksum(krb5_context context,
1351 struct key_data *key,
1352 const void *data,
1353 size_t len,
1354 unsigned usage,
1355 Checksum *C)
1357 return des_checksum(context, EVP_md5(), key, data, len, C);
1360 static krb5_error_code
1361 RSA_MD5_DES3_verify(krb5_context context,
1362 struct key_data *key,
1363 const void *data,
1364 size_t len,
1365 unsigned usage,
1366 Checksum *C)
1368 return des_verify(context, EVP_md5(), key, data, len, C);
1370 #endif
1372 static krb5_error_code
1373 SHA1_checksum(krb5_context context,
1374 struct key_data *key,
1375 const void *data,
1376 size_t len,
1377 unsigned usage,
1378 Checksum *C)
1380 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
1381 krb5_abortx(context, "sha1 checksum failed");
1382 return 0;
1385 /* HMAC according to RFC2104 */
1386 static krb5_error_code
1387 hmac(krb5_context context,
1388 struct checksum_type *cm,
1389 const void *data,
1390 size_t len,
1391 unsigned usage,
1392 struct key_data *keyblock,
1393 Checksum *result)
1395 unsigned char *ipad, *opad;
1396 unsigned char *key;
1397 size_t key_len;
1398 int i;
1400 ipad = malloc(cm->blocksize + len);
1401 if (ipad == NULL)
1402 return ENOMEM;
1403 opad = malloc(cm->blocksize + cm->checksumsize);
1404 if (opad == NULL) {
1405 free(ipad);
1406 return ENOMEM;
1408 memset(ipad, 0x36, cm->blocksize);
1409 memset(opad, 0x5c, cm->blocksize);
1411 if(keyblock->key->keyvalue.length > cm->blocksize){
1412 (*cm->checksum)(context,
1413 keyblock,
1414 keyblock->key->keyvalue.data,
1415 keyblock->key->keyvalue.length,
1416 usage,
1417 result);
1418 key = result->checksum.data;
1419 key_len = result->checksum.length;
1420 } else {
1421 key = keyblock->key->keyvalue.data;
1422 key_len = keyblock->key->keyvalue.length;
1424 for(i = 0; i < key_len; i++){
1425 ipad[i] ^= key[i];
1426 opad[i] ^= key[i];
1428 memcpy(ipad + cm->blocksize, data, len);
1429 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1430 usage, result);
1431 memcpy(opad + cm->blocksize, result->checksum.data,
1432 result->checksum.length);
1433 (*cm->checksum)(context, keyblock, opad,
1434 cm->blocksize + cm->checksumsize, usage, result);
1435 memset(ipad, 0, cm->blocksize + len);
1436 free(ipad);
1437 memset(opad, 0, cm->blocksize + cm->checksumsize);
1438 free(opad);
1440 return 0;
1443 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1444 krb5_hmac(krb5_context context,
1445 krb5_cksumtype cktype,
1446 const void *data,
1447 size_t len,
1448 unsigned usage,
1449 krb5_keyblock *key,
1450 Checksum *result)
1452 struct checksum_type *c = _find_checksum(cktype);
1453 struct key_data kd;
1454 krb5_error_code ret;
1456 if (c == NULL) {
1457 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1458 N_("checksum type %d not supported", ""),
1459 cktype);
1460 return KRB5_PROG_SUMTYPE_NOSUPP;
1463 kd.key = key;
1464 kd.schedule = NULL;
1466 ret = hmac(context, c, data, len, usage, &kd, result);
1468 if (kd.schedule)
1469 krb5_free_data(context, kd.schedule);
1471 return ret;
1474 static krb5_error_code
1475 SP_HMAC_SHA1_checksum(krb5_context context,
1476 struct key_data *key,
1477 const void *data,
1478 size_t len,
1479 unsigned usage,
1480 Checksum *result)
1482 struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1483 Checksum res;
1484 char sha1_data[20];
1485 krb5_error_code ret;
1487 res.checksum.data = sha1_data;
1488 res.checksum.length = sizeof(sha1_data);
1490 ret = hmac(context, c, data, len, usage, key, &res);
1491 if (ret)
1492 krb5_abortx(context, "hmac failed");
1493 memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
1494 return 0;
1498 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1501 static krb5_error_code
1502 HMAC_MD5_checksum(krb5_context context,
1503 struct key_data *key,
1504 const void *data,
1505 size_t len,
1506 unsigned usage,
1507 Checksum *result)
1509 EVP_MD_CTX *m;
1510 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1511 const char signature[] = "signaturekey";
1512 Checksum ksign_c;
1513 struct key_data ksign;
1514 krb5_keyblock kb;
1515 unsigned char t[4];
1516 unsigned char tmp[16];
1517 unsigned char ksign_c_data[16];
1518 krb5_error_code ret;
1520 m = EVP_MD_CTX_create();
1521 if (m == NULL) {
1522 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1523 return ENOMEM;
1525 ksign_c.checksum.length = sizeof(ksign_c_data);
1526 ksign_c.checksum.data = ksign_c_data;
1527 ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1528 if (ret) {
1529 EVP_MD_CTX_destroy(m);
1530 return ret;
1532 ksign.key = &kb;
1533 kb.keyvalue = ksign_c.checksum;
1534 EVP_DigestInit_ex(m, EVP_md5(), NULL);
1535 t[0] = (usage >> 0) & 0xFF;
1536 t[1] = (usage >> 8) & 0xFF;
1537 t[2] = (usage >> 16) & 0xFF;
1538 t[3] = (usage >> 24) & 0xFF;
1539 EVP_DigestUpdate(m, t, 4);
1540 EVP_DigestUpdate(m, data, len);
1541 EVP_DigestFinal_ex (m, tmp, NULL);
1542 EVP_MD_CTX_destroy(m);
1544 ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1545 if (ret)
1546 return ret;
1547 return 0;
1550 static struct checksum_type checksum_none = {
1551 CKSUMTYPE_NONE,
1552 "none",
1556 NONE_checksum,
1557 NULL
1559 #ifdef HEIM_WEAK_CRYPTO
1560 static struct checksum_type checksum_crc32 = {
1561 CKSUMTYPE_CRC32,
1562 "crc32",
1566 CRC32_checksum,
1567 NULL
1569 static struct checksum_type checksum_rsa_md4 = {
1570 CKSUMTYPE_RSA_MD4,
1571 "rsa-md4",
1574 F_CPROOF,
1575 RSA_MD4_checksum,
1576 NULL
1578 static struct checksum_type checksum_rsa_md4_des = {
1579 CKSUMTYPE_RSA_MD4_DES,
1580 "rsa-md4-des",
1583 F_KEYED | F_CPROOF | F_VARIANT,
1584 RSA_MD4_DES_checksum,
1585 RSA_MD4_DES_verify
1587 static struct checksum_type checksum_rsa_md5_des = {
1588 CKSUMTYPE_RSA_MD5_DES,
1589 "rsa-md5-des",
1592 F_KEYED | F_CPROOF | F_VARIANT,
1593 RSA_MD5_DES_checksum,
1594 RSA_MD5_DES_verify
1596 #endif /* HEIM_WEAK_CRYPTO */
1598 static krb5_error_code
1599 RSA_MD5_checksum(krb5_context context,
1600 struct key_data *key,
1601 const void *data,
1602 size_t len,
1603 unsigned usage,
1604 Checksum *C)
1606 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
1607 krb5_abortx(context, "md5 checksum failed");
1608 return 0;
1611 static struct checksum_type checksum_rsa_md5 = {
1612 CKSUMTYPE_RSA_MD5,
1613 "rsa-md5",
1616 F_CPROOF,
1617 RSA_MD5_checksum,
1618 NULL
1621 #ifdef DES3_OLD_ENCTYPE
1622 static struct checksum_type checksum_rsa_md5_des3 = {
1623 CKSUMTYPE_RSA_MD5_DES3,
1624 "rsa-md5-des3",
1627 F_KEYED | F_CPROOF | F_VARIANT,
1628 RSA_MD5_DES3_checksum,
1629 RSA_MD5_DES3_verify
1631 #endif
1632 static struct checksum_type checksum_sha1 = {
1633 CKSUMTYPE_SHA1,
1634 "sha1",
1637 F_CPROOF,
1638 SHA1_checksum,
1639 NULL
1641 static struct checksum_type checksum_hmac_sha1_des3 = {
1642 CKSUMTYPE_HMAC_SHA1_DES3,
1643 "hmac-sha1-des3",
1646 F_KEYED | F_CPROOF | F_DERIVED,
1647 SP_HMAC_SHA1_checksum,
1648 NULL
1651 static struct checksum_type checksum_hmac_sha1_aes128 = {
1652 CKSUMTYPE_HMAC_SHA1_96_AES_128,
1653 "hmac-sha1-96-aes128",
1656 F_KEYED | F_CPROOF | F_DERIVED,
1657 SP_HMAC_SHA1_checksum,
1658 NULL
1661 static struct checksum_type checksum_hmac_sha1_aes256 = {
1662 CKSUMTYPE_HMAC_SHA1_96_AES_256,
1663 "hmac-sha1-96-aes256",
1666 F_KEYED | F_CPROOF | F_DERIVED,
1667 SP_HMAC_SHA1_checksum,
1668 NULL
1671 static struct checksum_type checksum_hmac_md5 = {
1672 CKSUMTYPE_HMAC_MD5,
1673 "hmac-md5",
1676 F_KEYED | F_CPROOF,
1677 HMAC_MD5_checksum,
1678 NULL
1681 static struct checksum_type *checksum_types[] = {
1682 &checksum_none,
1683 #ifdef HEIM_WEAK_CRYPTO
1684 &checksum_crc32,
1685 &checksum_rsa_md4,
1686 &checksum_rsa_md4_des,
1687 &checksum_rsa_md5_des,
1688 #endif
1689 #ifdef DES3_OLD_ENCTYPE
1690 &checksum_rsa_md5_des3,
1691 #endif
1692 &checksum_rsa_md5,
1693 &checksum_sha1,
1694 &checksum_hmac_sha1_des3,
1695 &checksum_hmac_sha1_aes128,
1696 &checksum_hmac_sha1_aes256,
1697 &checksum_hmac_md5
1700 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1702 static struct checksum_type *
1703 _find_checksum(krb5_cksumtype type)
1705 int i;
1706 for(i = 0; i < num_checksums; i++)
1707 if(checksum_types[i]->type == type)
1708 return checksum_types[i];
1709 return NULL;
1712 static krb5_error_code
1713 get_checksum_key(krb5_context context,
1714 krb5_crypto crypto,
1715 unsigned usage, /* not krb5_key_usage */
1716 struct checksum_type *ct,
1717 struct key_data **key)
1719 krb5_error_code ret = 0;
1721 if(ct->flags & F_DERIVED)
1722 ret = _get_derived_key(context, crypto, usage, key);
1723 else if(ct->flags & F_VARIANT) {
1724 int i;
1726 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1727 if(*key == NULL) {
1728 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1729 return ENOMEM;
1731 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1732 if(ret)
1733 return ret;
1734 for(i = 0; i < (*key)->key->keyvalue.length; i++)
1735 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1736 } else {
1737 *key = &crypto->key;
1739 if(ret == 0)
1740 ret = _key_schedule(context, *key);
1741 return ret;
1744 static krb5_error_code
1745 create_checksum (krb5_context context,
1746 struct checksum_type *ct,
1747 krb5_crypto crypto,
1748 unsigned usage,
1749 void *data,
1750 size_t len,
1751 Checksum *result)
1753 krb5_error_code ret;
1754 struct key_data *dkey;
1755 int keyed_checksum;
1757 if (ct->flags & F_DISABLED) {
1758 krb5_clear_error_message (context);
1759 return KRB5_PROG_SUMTYPE_NOSUPP;
1761 keyed_checksum = (ct->flags & F_KEYED) != 0;
1762 if(keyed_checksum && crypto == NULL) {
1763 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1764 N_("Checksum type %s is keyed but no "
1765 "crypto context (key) was passed in", ""),
1766 ct->name);
1767 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1769 if(keyed_checksum) {
1770 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1771 if (ret)
1772 return ret;
1773 } else
1774 dkey = NULL;
1775 result->cksumtype = ct->type;
1776 ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1777 if (ret)
1778 return (ret);
1779 return (*ct->checksum)(context, dkey, data, len, usage, result);
1782 static int
1783 arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
1785 return (ct->type == CKSUMTYPE_HMAC_MD5) &&
1786 (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
1789 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1790 krb5_create_checksum(krb5_context context,
1791 krb5_crypto crypto,
1792 krb5_key_usage usage,
1793 int type,
1794 void *data,
1795 size_t len,
1796 Checksum *result)
1798 struct checksum_type *ct = NULL;
1799 unsigned keyusage;
1801 /* type 0 -> pick from crypto */
1802 if (type) {
1803 ct = _find_checksum(type);
1804 } else if (crypto) {
1805 ct = crypto->et->keyed_checksum;
1806 if (ct == NULL)
1807 ct = crypto->et->checksum;
1810 if(ct == NULL) {
1811 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1812 N_("checksum type %d not supported", ""),
1813 type);
1814 return KRB5_PROG_SUMTYPE_NOSUPP;
1817 if (arcfour_checksum_p(ct, crypto)) {
1818 keyusage = usage;
1819 usage2arcfour(context, &keyusage);
1820 } else
1821 keyusage = CHECKSUM_USAGE(usage);
1823 return create_checksum(context, ct, crypto, keyusage,
1824 data, len, result);
1827 static krb5_error_code
1828 verify_checksum(krb5_context context,
1829 krb5_crypto crypto,
1830 unsigned usage, /* not krb5_key_usage */
1831 void *data,
1832 size_t len,
1833 Checksum *cksum)
1835 krb5_error_code ret;
1836 struct key_data *dkey;
1837 int keyed_checksum;
1838 Checksum c;
1839 struct checksum_type *ct;
1841 ct = _find_checksum(cksum->cksumtype);
1842 if (ct == NULL || (ct->flags & F_DISABLED)) {
1843 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1844 N_("checksum type %d not supported", ""),
1845 cksum->cksumtype);
1846 return KRB5_PROG_SUMTYPE_NOSUPP;
1848 if(ct->checksumsize != cksum->checksum.length) {
1849 krb5_clear_error_message (context);
1850 krb5_set_error_message (context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
1851 N_("Decrypt integrity check failed for checksum type %s, length was %u, expected %u", ""),
1852 ct->name, (unsigned)cksum->checksum.length, (unsigned)ct->checksumsize);
1854 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1856 keyed_checksum = (ct->flags & F_KEYED) != 0;
1857 if(keyed_checksum) {
1858 struct checksum_type *kct;
1859 if (crypto == NULL) {
1860 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1861 N_("Checksum type %s is keyed but no "
1862 "crypto context (key) was passed in", ""),
1863 ct->name);
1864 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1866 kct = crypto->et->keyed_checksum;
1867 if (kct != NULL && kct->type != ct->type) {
1868 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1869 N_("Checksum type %s is keyed, but "
1870 "the key type %s passed didnt have that checksum "
1871 "type as the keyed type", ""),
1872 ct->name, crypto->et->name);
1873 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1876 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1877 if (ret)
1878 return ret;
1879 } else
1880 dkey = NULL;
1881 if(ct->verify) {
1882 ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
1883 if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
1884 krb5_set_error_message (context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
1885 N_("Decrypt integrity check failed for checksum type %s, key type %s", ""),
1886 ct->name, crypto->et->name);
1890 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1891 if (ret)
1892 return ret;
1894 ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
1895 if (ret) {
1896 krb5_data_free(&c.checksum);
1897 return ret;
1900 if(c.checksum.length != cksum->checksum.length ||
1901 ct_memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
1902 krb5_clear_error_message (context);
1903 krb5_set_error_message (context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
1904 N_("Decrypt integrity check failed for checksum type %s, key type %s", ""),
1905 ct->name, crypto->et->name);
1906 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1907 } else {
1908 ret = 0;
1910 krb5_data_free (&c.checksum);
1911 return ret;
1914 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1915 krb5_verify_checksum(krb5_context context,
1916 krb5_crypto crypto,
1917 krb5_key_usage usage,
1918 void *data,
1919 size_t len,
1920 Checksum *cksum)
1922 struct checksum_type *ct;
1923 unsigned keyusage;
1925 ct = _find_checksum(cksum->cksumtype);
1926 if(ct == NULL) {
1927 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1928 N_("checksum type %d not supported", ""),
1929 cksum->cksumtype);
1930 return KRB5_PROG_SUMTYPE_NOSUPP;
1933 if (arcfour_checksum_p(ct, crypto)) {
1934 keyusage = usage;
1935 usage2arcfour(context, &keyusage);
1936 } else
1937 keyusage = CHECKSUM_USAGE(usage);
1939 return verify_checksum(context, crypto, keyusage,
1940 data, len, cksum);
1943 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1944 krb5_crypto_get_checksum_type(krb5_context context,
1945 krb5_crypto crypto,
1946 krb5_cksumtype *type)
1948 struct checksum_type *ct = NULL;
1950 if (crypto != NULL) {
1951 ct = crypto->et->keyed_checksum;
1952 if (ct == NULL)
1953 ct = crypto->et->checksum;
1956 if (ct == NULL) {
1957 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1958 N_("checksum type not found", ""));
1959 return KRB5_PROG_SUMTYPE_NOSUPP;
1962 *type = ct->type;
1964 return 0;
1968 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1969 krb5_checksumsize(krb5_context context,
1970 krb5_cksumtype type,
1971 size_t *size)
1973 struct checksum_type *ct = _find_checksum(type);
1974 if(ct == NULL) {
1975 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1976 N_("checksum type %d not supported", ""),
1977 type);
1978 return KRB5_PROG_SUMTYPE_NOSUPP;
1980 *size = ct->checksumsize;
1981 return 0;
1984 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
1985 krb5_checksum_is_keyed(krb5_context context,
1986 krb5_cksumtype type)
1988 struct checksum_type *ct = _find_checksum(type);
1989 if(ct == NULL) {
1990 if (context)
1991 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1992 N_("checksum type %d not supported", ""),
1993 type);
1994 return KRB5_PROG_SUMTYPE_NOSUPP;
1996 return ct->flags & F_KEYED;
1999 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2000 krb5_checksum_is_collision_proof(krb5_context context,
2001 krb5_cksumtype type)
2003 struct checksum_type *ct = _find_checksum(type);
2004 if(ct == NULL) {
2005 if (context)
2006 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2007 N_("checksum type %d not supported", ""),
2008 type);
2009 return KRB5_PROG_SUMTYPE_NOSUPP;
2011 return ct->flags & F_CPROOF;
2014 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2015 krb5_checksum_disable(krb5_context context,
2016 krb5_cksumtype type)
2018 struct checksum_type *ct = _find_checksum(type);
2019 if(ct == NULL) {
2020 if (context)
2021 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2022 N_("checksum type %d not supported", ""),
2023 type);
2024 return KRB5_PROG_SUMTYPE_NOSUPP;
2026 ct->flags |= F_DISABLED;
2027 return 0;
2030 /************************************************************
2032 ************************************************************/
2034 static krb5_error_code
2035 NULL_encrypt(krb5_context context,
2036 struct key_data *key,
2037 void *data,
2038 size_t len,
2039 krb5_boolean encryptp,
2040 int usage,
2041 void *ivec)
2043 return 0;
2046 static krb5_error_code
2047 evp_encrypt(krb5_context context,
2048 struct key_data *key,
2049 void *data,
2050 size_t len,
2051 krb5_boolean encryptp,
2052 int usage,
2053 void *ivec)
2055 struct evp_schedule *ctx = key->schedule->data;
2056 EVP_CIPHER_CTX *c;
2057 c = encryptp ? &ctx->ectx : &ctx->dctx;
2058 if (ivec == NULL) {
2059 /* alloca ? */
2060 size_t len2 = EVP_CIPHER_CTX_iv_length(c);
2061 void *loiv = malloc(len2);
2062 if (loiv == NULL) {
2063 krb5_clear_error_message(context);
2064 return ENOMEM;
2066 memset(loiv, 0, len2);
2067 EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
2068 free(loiv);
2069 } else
2070 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2071 EVP_Cipher(c, data, data, len);
2072 return 0;
2075 static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
2077 static krb5_error_code
2078 evp_encrypt_cts(krb5_context context,
2079 struct key_data *key,
2080 void *data,
2081 size_t len,
2082 krb5_boolean encryptp,
2083 int usage,
2084 void *ivec)
2086 size_t i, blocksize;
2087 struct evp_schedule *ctx = key->schedule->data;
2088 char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
2089 EVP_CIPHER_CTX *c;
2090 unsigned char *p;
2092 c = encryptp ? &ctx->ectx : &ctx->dctx;
2094 blocksize = EVP_CIPHER_CTX_block_size(c);
2096 if (len < blocksize) {
2097 krb5_set_error_message(context, EINVAL,
2098 "message block too short");
2099 return EINVAL;
2100 } else if (len == blocksize) {
2101 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2102 EVP_Cipher(c, data, data, len);
2103 return 0;
2106 if (ivec)
2107 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2108 else
2109 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2111 if (encryptp) {
2113 p = data;
2114 i = ((len - 1) / blocksize) * blocksize;
2115 EVP_Cipher(c, p, p, i);
2116 p += i - blocksize;
2117 len -= i;
2118 memcpy(ivec2, p, blocksize);
2120 for (i = 0; i < len; i++)
2121 tmp[i] = p[i + blocksize] ^ ivec2[i];
2122 for (; i < blocksize; i++)
2123 tmp[i] = 0 ^ ivec2[i];
2125 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2126 EVP_Cipher(c, p, tmp, blocksize);
2128 memcpy(p + blocksize, ivec2, len);
2129 if (ivec)
2130 memcpy(ivec, p, blocksize);
2131 } else {
2132 char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH];
2134 p = data;
2135 if (len > blocksize * 2) {
2136 /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
2137 i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
2138 memcpy(ivec2, p + i - blocksize, blocksize);
2139 EVP_Cipher(c, p, p, i);
2140 p += i;
2141 len -= i + blocksize;
2142 } else {
2143 if (ivec)
2144 memcpy(ivec2, ivec, blocksize);
2145 else
2146 memcpy(ivec2, zero_ivec, blocksize);
2147 len -= blocksize;
2150 memcpy(tmp, p, blocksize);
2151 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2152 EVP_Cipher(c, tmp2, p, blocksize);
2154 memcpy(tmp3, p + blocksize, len);
2155 memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
2157 for (i = 0; i < len; i++)
2158 p[i + blocksize] = tmp2[i] ^ tmp3[i];
2160 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2161 EVP_Cipher(c, p, tmp3, blocksize);
2163 for (i = 0; i < blocksize; i++)
2164 p[i] ^= ivec2[i];
2165 if (ivec)
2166 memcpy(ivec, tmp, blocksize);
2168 return 0;
2171 #ifdef HEIM_WEAK_CRYPTO
2172 static krb5_error_code
2173 evp_des_encrypt_null_ivec(krb5_context context,
2174 struct key_data *key,
2175 void *data,
2176 size_t len,
2177 krb5_boolean encryptp,
2178 int usage,
2179 void *ignore_ivec)
2181 struct evp_schedule *ctx = key->schedule->data;
2182 EVP_CIPHER_CTX *c;
2183 DES_cblock ivec;
2184 memset(&ivec, 0, sizeof(ivec));
2185 c = encryptp ? &ctx->ectx : &ctx->dctx;
2186 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2187 EVP_Cipher(c, data, data, len);
2188 return 0;
2191 static krb5_error_code
2192 evp_des_encrypt_key_ivec(krb5_context context,
2193 struct key_data *key,
2194 void *data,
2195 size_t len,
2196 krb5_boolean encryptp,
2197 int usage,
2198 void *ignore_ivec)
2200 struct evp_schedule *ctx = key->schedule->data;
2201 EVP_CIPHER_CTX *c;
2202 DES_cblock ivec;
2203 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2204 c = encryptp ? &ctx->ectx : &ctx->dctx;
2205 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2206 EVP_Cipher(c, data, data, len);
2207 return 0;
2210 static krb5_error_code
2211 DES_CFB64_encrypt_null_ivec(krb5_context context,
2212 struct key_data *key,
2213 void *data,
2214 size_t len,
2215 krb5_boolean encryptp,
2216 int usage,
2217 void *ignore_ivec)
2219 DES_cblock ivec;
2220 int num = 0;
2221 DES_key_schedule *s = key->schedule->data;
2222 memset(&ivec, 0, sizeof(ivec));
2224 DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
2225 return 0;
2228 static krb5_error_code
2229 DES_PCBC_encrypt_key_ivec(krb5_context context,
2230 struct key_data *key,
2231 void *data,
2232 size_t len,
2233 krb5_boolean encryptp,
2234 int usage,
2235 void *ignore_ivec)
2237 DES_cblock ivec;
2238 DES_key_schedule *s = key->schedule->data;
2239 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2241 DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
2242 return 0;
2244 #endif
2247 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
2249 * warning: not for small children
2252 static krb5_error_code
2253 ARCFOUR_subencrypt(krb5_context context,
2254 struct key_data *key,
2255 void *data,
2256 size_t len,
2257 unsigned usage,
2258 void *ivec)
2260 EVP_CIPHER_CTX ctx;
2261 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2262 Checksum k1_c, k2_c, k3_c, cksum;
2263 struct key_data ke;
2264 krb5_keyblock kb;
2265 unsigned char t[4];
2266 unsigned char *cdata = data;
2267 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2268 krb5_error_code ret;
2270 t[0] = (usage >> 0) & 0xFF;
2271 t[1] = (usage >> 8) & 0xFF;
2272 t[2] = (usage >> 16) & 0xFF;
2273 t[3] = (usage >> 24) & 0xFF;
2275 k1_c.checksum.length = sizeof(k1_c_data);
2276 k1_c.checksum.data = k1_c_data;
2278 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2279 if (ret)
2280 krb5_abortx(context, "hmac failed");
2282 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2284 k2_c.checksum.length = sizeof(k2_c_data);
2285 k2_c.checksum.data = k2_c_data;
2287 ke.key = &kb;
2288 kb.keyvalue = k2_c.checksum;
2290 cksum.checksum.length = 16;
2291 cksum.checksum.data = data;
2293 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2294 if (ret)
2295 krb5_abortx(context, "hmac failed");
2297 ke.key = &kb;
2298 kb.keyvalue = k1_c.checksum;
2300 k3_c.checksum.length = sizeof(k3_c_data);
2301 k3_c.checksum.data = k3_c_data;
2303 ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
2304 if (ret)
2305 krb5_abortx(context, "hmac failed");
2307 EVP_CIPHER_CTX_init(&ctx);
2309 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
2310 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
2311 EVP_CIPHER_CTX_cleanup(&ctx);
2313 memset (k1_c_data, 0, sizeof(k1_c_data));
2314 memset (k2_c_data, 0, sizeof(k2_c_data));
2315 memset (k3_c_data, 0, sizeof(k3_c_data));
2316 return 0;
2319 static krb5_error_code
2320 ARCFOUR_subdecrypt(krb5_context context,
2321 struct key_data *key,
2322 void *data,
2323 size_t len,
2324 unsigned usage,
2325 void *ivec)
2327 EVP_CIPHER_CTX ctx;
2328 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2329 Checksum k1_c, k2_c, k3_c, cksum;
2330 struct key_data ke;
2331 krb5_keyblock kb;
2332 unsigned char t[4];
2333 unsigned char *cdata = data;
2334 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2335 unsigned char cksum_data[16];
2336 krb5_error_code ret;
2338 t[0] = (usage >> 0) & 0xFF;
2339 t[1] = (usage >> 8) & 0xFF;
2340 t[2] = (usage >> 16) & 0xFF;
2341 t[3] = (usage >> 24) & 0xFF;
2343 k1_c.checksum.length = sizeof(k1_c_data);
2344 k1_c.checksum.data = k1_c_data;
2346 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2347 if (ret)
2348 krb5_abortx(context, "hmac failed");
2350 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2352 k2_c.checksum.length = sizeof(k2_c_data);
2353 k2_c.checksum.data = k2_c_data;
2355 ke.key = &kb;
2356 kb.keyvalue = k1_c.checksum;
2358 k3_c.checksum.length = sizeof(k3_c_data);
2359 k3_c.checksum.data = k3_c_data;
2361 ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
2362 if (ret)
2363 krb5_abortx(context, "hmac failed");
2365 EVP_CIPHER_CTX_init(&ctx);
2366 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
2367 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
2368 EVP_CIPHER_CTX_cleanup(&ctx);
2370 ke.key = &kb;
2371 kb.keyvalue = k2_c.checksum;
2373 cksum.checksum.length = 16;
2374 cksum.checksum.data = cksum_data;
2376 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2377 if (ret)
2378 krb5_abortx(context, "hmac failed");
2380 memset (k1_c_data, 0, sizeof(k1_c_data));
2381 memset (k2_c_data, 0, sizeof(k2_c_data));
2382 memset (k3_c_data, 0, sizeof(k3_c_data));
2384 if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
2385 krb5_clear_error_message (context);
2386 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
2387 } else {
2388 return 0;
2393 * convert the usage numbers used in
2394 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2395 * draft-brezak-win2k-krb-rc4-hmac-04.txt
2398 static krb5_error_code
2399 usage2arcfour (krb5_context context, unsigned *usage)
2401 switch (*usage) {
2402 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2403 *usage = 8;
2404 return 0;
2405 case KRB5_KU_USAGE_SEAL : /* 22 */
2406 *usage = 13;
2407 return 0;
2408 case KRB5_KU_USAGE_SIGN : /* 23 */
2409 *usage = 15;
2410 return 0;
2411 case KRB5_KU_USAGE_SEQ: /* 24 */
2412 *usage = 0;
2413 return 0;
2414 default :
2415 return 0;
2419 static krb5_error_code
2420 ARCFOUR_encrypt(krb5_context context,
2421 struct key_data *key,
2422 void *data,
2423 size_t len,
2424 krb5_boolean encryptp,
2425 int usage,
2426 void *ivec)
2428 krb5_error_code ret;
2429 unsigned keyusage = usage;
2431 if((ret = usage2arcfour (context, &keyusage)) != 0)
2432 return ret;
2434 if (encryptp)
2435 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
2436 else
2437 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
2445 static krb5_error_code
2446 AES_PRF(krb5_context context,
2447 krb5_crypto crypto,
2448 const krb5_data *in,
2449 krb5_data *out)
2451 struct checksum_type *ct = crypto->et->checksum;
2452 krb5_error_code ret;
2453 Checksum result;
2454 krb5_keyblock *derived;
2456 result.cksumtype = ct->type;
2457 ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2458 if (ret) {
2459 krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
2460 return ret;
2463 ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2464 if (ret) {
2465 krb5_data_free(&result.checksum);
2466 return ret;
2469 if (result.checksum.length < crypto->et->blocksize)
2470 krb5_abortx(context, "internal prf error");
2472 derived = NULL;
2473 ret = krb5_derive_key(context, crypto->key.key,
2474 crypto->et->type, "prf", 3, &derived);
2475 if (ret)
2476 krb5_abortx(context, "krb5_derive_key");
2478 ret = krb5_data_alloc(out, crypto->et->blocksize);
2479 if (ret)
2480 krb5_abortx(context, "malloc failed");
2483 const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
2484 EVP_CIPHER_CTX ctx;
2486 EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
2487 EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
2488 EVP_Cipher(&ctx, out->data, result.checksum.data,
2489 crypto->et->blocksize);
2490 EVP_CIPHER_CTX_cleanup(&ctx);
2493 krb5_data_free(&result.checksum);
2494 krb5_free_keyblock(context, derived);
2496 return ret;
2500 * these should currently be in reverse preference order.
2501 * (only relevant for !F_PSEUDO) */
2503 static struct encryption_type enctype_null = {
2504 ETYPE_NULL,
2505 "null",
2509 &keytype_null,
2510 &checksum_none,
2511 NULL,
2512 F_DISABLED,
2513 NULL_encrypt,
2515 NULL
2517 static struct encryption_type enctype_arcfour_hmac_md5 = {
2518 ETYPE_ARCFOUR_HMAC_MD5,
2519 "arcfour-hmac-md5",
2523 &keytype_arcfour,
2524 &checksum_hmac_md5,
2525 NULL,
2526 F_SPECIAL,
2527 ARCFOUR_encrypt,
2529 NULL
2531 #ifdef DES3_OLD_ENCTYPE
2532 static struct encryption_type enctype_des3_cbc_md5 = {
2533 ETYPE_DES3_CBC_MD5,
2534 "des3-cbc-md5",
2538 &keytype_des3,
2539 &checksum_rsa_md5,
2540 &checksum_rsa_md5_des3,
2542 evp_encrypt,
2544 NULL
2546 #endif
2547 static struct encryption_type enctype_des3_cbc_sha1 = {
2548 ETYPE_DES3_CBC_SHA1,
2549 "des3-cbc-sha1",
2553 &keytype_des3_derived,
2554 &checksum_sha1,
2555 &checksum_hmac_sha1_des3,
2556 F_DERIVED,
2557 evp_encrypt,
2559 NULL
2561 #ifdef DES3_OLD_ENCTYPE
2562 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2563 ETYPE_OLD_DES3_CBC_SHA1,
2564 "old-des3-cbc-sha1",
2568 &keytype_des3,
2569 &checksum_sha1,
2570 &checksum_hmac_sha1_des3,
2572 evp_encrypt,
2574 NULL
2576 #endif
2577 static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2578 ETYPE_AES128_CTS_HMAC_SHA1_96,
2579 "aes128-cts-hmac-sha1-96",
2583 &keytype_aes128,
2584 &checksum_sha1,
2585 &checksum_hmac_sha1_aes128,
2586 F_DERIVED,
2587 evp_encrypt_cts,
2589 AES_PRF
2591 static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2592 ETYPE_AES256_CTS_HMAC_SHA1_96,
2593 "aes256-cts-hmac-sha1-96",
2597 &keytype_aes256,
2598 &checksum_sha1,
2599 &checksum_hmac_sha1_aes256,
2600 F_DERIVED,
2601 evp_encrypt_cts,
2603 AES_PRF
2605 static struct encryption_type enctype_des3_cbc_none = {
2606 ETYPE_DES3_CBC_NONE,
2607 "des3-cbc-none",
2611 &keytype_des3_derived,
2612 &checksum_none,
2613 NULL,
2614 F_PSEUDO,
2615 evp_encrypt,
2617 NULL
2619 #ifdef HEIM_WEAK_CRYPTO
2620 static struct encryption_type enctype_des_cbc_crc = {
2621 ETYPE_DES_CBC_CRC,
2622 "des-cbc-crc",
2626 &keytype_des,
2627 &checksum_crc32,
2628 NULL,
2629 F_DISABLED|F_WEAK,
2630 evp_des_encrypt_key_ivec,
2632 NULL
2634 static struct encryption_type enctype_des_cbc_md4 = {
2635 ETYPE_DES_CBC_MD4,
2636 "des-cbc-md4",
2640 &keytype_des,
2641 &checksum_rsa_md4,
2642 &checksum_rsa_md4_des,
2643 F_DISABLED|F_WEAK,
2644 evp_des_encrypt_null_ivec,
2646 NULL
2648 static struct encryption_type enctype_des_cbc_md5 = {
2649 ETYPE_DES_CBC_MD5,
2650 "des-cbc-md5",
2654 &keytype_des,
2655 &checksum_rsa_md5,
2656 &checksum_rsa_md5_des,
2657 F_DISABLED|F_WEAK,
2658 evp_des_encrypt_null_ivec,
2660 NULL
2662 static struct encryption_type enctype_des_cbc_none = {
2663 ETYPE_DES_CBC_NONE,
2664 "des-cbc-none",
2668 &keytype_des,
2669 &checksum_none,
2670 NULL,
2671 F_PSEUDO|F_DISABLED|F_WEAK,
2672 evp_des_encrypt_null_ivec,
2674 NULL
2676 static struct encryption_type enctype_des_cfb64_none = {
2677 ETYPE_DES_CFB64_NONE,
2678 "des-cfb64-none",
2682 &keytype_des_old,
2683 &checksum_none,
2684 NULL,
2685 F_PSEUDO|F_DISABLED|F_WEAK,
2686 DES_CFB64_encrypt_null_ivec,
2688 NULL
2690 static struct encryption_type enctype_des_pcbc_none = {
2691 ETYPE_DES_PCBC_NONE,
2692 "des-pcbc-none",
2696 &keytype_des_old,
2697 &checksum_none,
2698 NULL,
2699 F_PSEUDO|F_DISABLED|F_WEAK,
2700 DES_PCBC_encrypt_key_ivec,
2702 NULL
2704 #endif /* HEIM_WEAK_CRYPTO */
2706 static struct encryption_type *etypes[] = {
2707 &enctype_aes256_cts_hmac_sha1,
2708 &enctype_aes128_cts_hmac_sha1,
2709 &enctype_des3_cbc_sha1,
2710 &enctype_des3_cbc_none, /* used by the gss-api mech */
2711 &enctype_arcfour_hmac_md5,
2712 #ifdef DES3_OLD_ENCTYPE
2713 &enctype_des3_cbc_md5,
2714 &enctype_old_des3_cbc_sha1,
2715 #endif
2716 #ifdef HEIM_WEAK_CRYPTO
2717 &enctype_des_cbc_crc,
2718 &enctype_des_cbc_md4,
2719 &enctype_des_cbc_md5,
2720 &enctype_des_cbc_none,
2721 &enctype_des_cfb64_none,
2722 &enctype_des_pcbc_none,
2723 #endif
2724 &enctype_null
2727 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2730 static struct encryption_type *
2731 _find_enctype(krb5_enctype type)
2733 int i;
2734 for(i = 0; i < num_etypes; i++)
2735 if(etypes[i]->type == type)
2736 return etypes[i];
2737 return NULL;
2741 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2742 krb5_enctype_to_string(krb5_context context,
2743 krb5_enctype etype,
2744 char **string)
2746 struct encryption_type *e;
2747 e = _find_enctype(etype);
2748 if(e == NULL) {
2749 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2750 N_("encryption type %d not supported", ""),
2751 etype);
2752 *string = NULL;
2753 return KRB5_PROG_ETYPE_NOSUPP;
2755 *string = strdup(e->name);
2756 if(*string == NULL) {
2757 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2758 return ENOMEM;
2760 return 0;
2763 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2764 krb5_string_to_enctype(krb5_context context,
2765 const char *string,
2766 krb5_enctype *etype)
2768 int i;
2769 for(i = 0; i < num_etypes; i++)
2770 if(strcasecmp(etypes[i]->name, string) == 0){
2771 *etype = etypes[i]->type;
2772 return 0;
2774 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2775 N_("encryption type %s not supported", ""),
2776 string);
2777 return KRB5_PROG_ETYPE_NOSUPP;
2780 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2781 krb5_enctype_to_keytype(krb5_context context,
2782 krb5_enctype etype,
2783 krb5_keytype *keytype)
2785 struct encryption_type *e = _find_enctype(etype);
2786 if(e == NULL) {
2787 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2788 N_("encryption type %d not supported", ""),
2789 etype);
2790 return KRB5_PROG_ETYPE_NOSUPP;
2792 *keytype = e->keytype->type; /* XXX */
2793 return 0;
2796 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2797 krb5_enctype_valid(krb5_context context,
2798 krb5_enctype etype)
2800 struct encryption_type *e = _find_enctype(etype);
2801 if(e == NULL) {
2802 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2803 N_("encryption type %d not supported", ""),
2804 etype);
2805 return KRB5_PROG_ETYPE_NOSUPP;
2807 if (e->flags & F_DISABLED) {
2808 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2809 N_("encryption type %s is disabled", ""),
2810 e->name);
2811 return KRB5_PROG_ETYPE_NOSUPP;
2813 return 0;
2817 * Return the coresponding encryption type for a checksum type.
2819 * @param context Kerberos context
2820 * @param ctype The checksum type to get the result enctype for
2821 * @param etype The returned encryption, when the matching etype is
2822 * not found, etype is set to ETYPE_NULL.
2824 * @return Return an error code for an failure or 0 on success.
2825 * @ingroup krb5_crypto
2829 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2830 krb5_cksumtype_to_enctype(krb5_context context,
2831 krb5_cksumtype ctype,
2832 krb5_enctype *etype)
2834 int i;
2836 *etype = ETYPE_NULL;
2838 for(i = 0; i < num_etypes; i++) {
2839 if(etypes[i]->keyed_checksum &&
2840 etypes[i]->keyed_checksum->type == ctype)
2842 *etype = etypes[i]->type;
2843 return 0;
2847 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2848 N_("checksum type %d not supported", ""),
2849 (int)ctype);
2850 return KRB5_PROG_SUMTYPE_NOSUPP;
2854 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2855 krb5_cksumtype_valid(krb5_context context,
2856 krb5_cksumtype ctype)
2858 struct checksum_type *c = _find_checksum(ctype);
2859 if (c == NULL) {
2860 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2861 N_("checksum type %d not supported", ""),
2862 ctype);
2863 return KRB5_PROG_SUMTYPE_NOSUPP;
2865 if (c->flags & F_DISABLED) {
2866 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2867 N_("checksum type %s is disabled", ""),
2868 c->name);
2869 return KRB5_PROG_SUMTYPE_NOSUPP;
2871 return 0;
2875 static krb5_boolean
2876 derived_crypto(krb5_context context,
2877 krb5_crypto crypto)
2879 return (crypto->et->flags & F_DERIVED) != 0;
2882 static krb5_boolean
2883 special_crypto(krb5_context context,
2884 krb5_crypto crypto)
2886 return (crypto->et->flags & F_SPECIAL) != 0;
2889 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2890 #define CHECKSUMTYPE(C) ((C)->type)
2892 static krb5_error_code
2893 encrypt_internal_derived(krb5_context context,
2894 krb5_crypto crypto,
2895 unsigned usage,
2896 const void *data,
2897 size_t len,
2898 krb5_data *result,
2899 void *ivec)
2901 size_t sz, block_sz, checksum_sz, total_sz;
2902 Checksum cksum;
2903 unsigned char *p, *q;
2904 krb5_error_code ret;
2905 struct key_data *dkey;
2906 const struct encryption_type *et = crypto->et;
2908 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2910 sz = et->confoundersize + len;
2911 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2912 total_sz = block_sz + checksum_sz;
2913 p = calloc(1, total_sz);
2914 if(p == NULL) {
2915 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2916 return ENOMEM;
2919 q = p;
2920 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2921 q += et->confoundersize;
2922 memcpy(q, data, len);
2924 ret = create_checksum(context,
2925 et->keyed_checksum,
2926 crypto,
2927 INTEGRITY_USAGE(usage),
2929 block_sz,
2930 &cksum);
2931 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2932 free_Checksum (&cksum);
2933 krb5_clear_error_message (context);
2934 ret = KRB5_CRYPTO_INTERNAL;
2936 if(ret)
2937 goto fail;
2938 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2939 free_Checksum (&cksum);
2940 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2941 if(ret)
2942 goto fail;
2943 ret = _key_schedule(context, dkey);
2944 if(ret)
2945 goto fail;
2946 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2947 if (ret)
2948 goto fail;
2949 result->data = p;
2950 result->length = total_sz;
2951 return 0;
2952 fail:
2953 memset(p, 0, total_sz);
2954 free(p);
2955 return ret;
2959 static krb5_error_code
2960 encrypt_internal(krb5_context context,
2961 krb5_crypto crypto,
2962 const void *data,
2963 size_t len,
2964 krb5_data *result,
2965 void *ivec)
2967 size_t sz, block_sz, checksum_sz;
2968 Checksum cksum;
2969 unsigned char *p, *q;
2970 krb5_error_code ret;
2971 const struct encryption_type *et = crypto->et;
2973 checksum_sz = CHECKSUMSIZE(et->checksum);
2975 sz = et->confoundersize + checksum_sz + len;
2976 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2977 p = calloc(1, block_sz);
2978 if(p == NULL) {
2979 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2980 return ENOMEM;
2983 q = p;
2984 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2985 q += et->confoundersize;
2986 memset(q, 0, checksum_sz);
2987 q += checksum_sz;
2988 memcpy(q, data, len);
2990 ret = create_checksum(context,
2991 et->checksum,
2992 crypto,
2995 block_sz,
2996 &cksum);
2997 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2998 krb5_clear_error_message (context);
2999 free_Checksum(&cksum);
3000 ret = KRB5_CRYPTO_INTERNAL;
3002 if(ret)
3003 goto fail;
3004 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
3005 free_Checksum(&cksum);
3006 ret = _key_schedule(context, &crypto->key);
3007 if(ret)
3008 goto fail;
3009 ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
3010 if (ret) {
3011 memset(p, 0, block_sz);
3012 free(p);
3013 return ret;
3015 result->data = p;
3016 result->length = block_sz;
3017 return 0;
3018 fail:
3019 memset(p, 0, block_sz);
3020 free(p);
3021 return ret;
3024 static krb5_error_code
3025 encrypt_internal_special(krb5_context context,
3026 krb5_crypto crypto,
3027 int usage,
3028 const void *data,
3029 size_t len,
3030 krb5_data *result,
3031 void *ivec)
3033 struct encryption_type *et = crypto->et;
3034 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3035 size_t sz = len + cksum_sz + et->confoundersize;
3036 char *tmp, *p;
3037 krb5_error_code ret;
3039 tmp = malloc (sz);
3040 if (tmp == NULL) {
3041 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3042 return ENOMEM;
3044 p = tmp;
3045 memset (p, 0, cksum_sz);
3046 p += cksum_sz;
3047 krb5_generate_random_block(p, et->confoundersize);
3048 p += et->confoundersize;
3049 memcpy (p, data, len);
3050 ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
3051 if (ret) {
3052 memset(tmp, 0, sz);
3053 free(tmp);
3054 return ret;
3056 result->data = tmp;
3057 result->length = sz;
3058 return 0;
3061 static krb5_error_code
3062 decrypt_internal_derived(krb5_context context,
3063 krb5_crypto crypto,
3064 unsigned usage,
3065 void *data,
3066 size_t len,
3067 krb5_data *result,
3068 void *ivec)
3070 size_t checksum_sz;
3071 Checksum cksum;
3072 unsigned char *p;
3073 krb5_error_code ret;
3074 struct key_data *dkey;
3075 struct encryption_type *et = crypto->et;
3076 unsigned long l;
3078 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
3079 if (len < checksum_sz + et->confoundersize) {
3080 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3081 N_("Encrypted data shorter then "
3082 "checksum + confunder", ""));
3083 return KRB5_BAD_MSIZE;
3086 if (((len - checksum_sz) % et->padsize) != 0) {
3087 krb5_clear_error_message(context);
3088 return KRB5_BAD_MSIZE;
3091 p = malloc(len);
3092 if(len != 0 && p == NULL) {
3093 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3094 return ENOMEM;
3096 memcpy(p, data, len);
3098 len -= checksum_sz;
3100 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3101 if(ret) {
3102 free(p);
3103 return ret;
3105 ret = _key_schedule(context, dkey);
3106 if(ret) {
3107 free(p);
3108 return ret;
3110 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3111 if (ret) {
3112 free(p);
3113 return ret;
3116 cksum.checksum.data = p + len;
3117 cksum.checksum.length = checksum_sz;
3118 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3120 ret = verify_checksum(context,
3121 crypto,
3122 INTEGRITY_USAGE(usage),
3124 len,
3125 &cksum);
3126 if(ret) {
3127 free(p);
3128 return ret;
3130 l = len - et->confoundersize;
3131 memmove(p, p + et->confoundersize, l);
3132 result->data = realloc(p, l);
3133 if(result->data == NULL && l != 0) {
3134 free(p);
3135 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3136 return ENOMEM;
3138 result->length = l;
3139 return 0;
3142 static krb5_error_code
3143 decrypt_internal(krb5_context context,
3144 krb5_crypto crypto,
3145 void *data,
3146 size_t len,
3147 krb5_data *result,
3148 void *ivec)
3150 krb5_error_code ret;
3151 unsigned char *p;
3152 Checksum cksum;
3153 size_t checksum_sz, l;
3154 struct encryption_type *et = crypto->et;
3156 if ((len % et->padsize) != 0) {
3157 krb5_clear_error_message(context);
3158 return KRB5_BAD_MSIZE;
3160 checksum_sz = CHECKSUMSIZE(et->checksum);
3161 if (len < checksum_sz + et->confoundersize) {
3162 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3163 N_("Encrypted data shorter then "
3164 "checksum + confunder", ""));
3165 return KRB5_BAD_MSIZE;
3168 p = malloc(len);
3169 if(len != 0 && p == NULL) {
3170 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3171 return ENOMEM;
3173 memcpy(p, data, len);
3175 ret = _key_schedule(context, &crypto->key);
3176 if(ret) {
3177 free(p);
3178 return ret;
3180 ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
3181 if (ret) {
3182 free(p);
3183 return ret;
3185 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
3186 if(ret) {
3187 free(p);
3188 return ret;
3190 memset(p + et->confoundersize, 0, checksum_sz);
3191 cksum.cksumtype = CHECKSUMTYPE(et->checksum);
3192 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
3193 free_Checksum(&cksum);
3194 if(ret) {
3195 free(p);
3196 return ret;
3198 l = len - et->confoundersize - checksum_sz;
3199 memmove(p, p + et->confoundersize + checksum_sz, l);
3200 result->data = realloc(p, l);
3201 if(result->data == NULL && l != 0) {
3202 free(p);
3203 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3204 return ENOMEM;
3206 result->length = l;
3207 return 0;
3210 static krb5_error_code
3211 decrypt_internal_special(krb5_context context,
3212 krb5_crypto crypto,
3213 int usage,
3214 void *data,
3215 size_t len,
3216 krb5_data *result,
3217 void *ivec)
3219 struct encryption_type *et = crypto->et;
3220 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3221 size_t sz = len - cksum_sz - et->confoundersize;
3222 unsigned char *p;
3223 krb5_error_code ret;
3225 if ((len % et->padsize) != 0) {
3226 krb5_clear_error_message(context);
3227 return KRB5_BAD_MSIZE;
3229 if (len < cksum_sz + et->confoundersize) {
3230 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3231 N_("Encrypted data shorter then "
3232 "checksum + confunder", ""));
3233 return KRB5_BAD_MSIZE;
3236 p = malloc (len);
3237 if (p == NULL) {
3238 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3239 return ENOMEM;
3241 memcpy(p, data, len);
3243 ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
3244 if (ret) {
3245 free(p);
3246 return ret;
3249 memmove (p, p + cksum_sz + et->confoundersize, sz);
3250 result->data = realloc(p, sz);
3251 if(result->data == NULL && sz != 0) {
3252 free(p);
3253 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3254 return ENOMEM;
3256 result->length = sz;
3257 return 0;
3260 static krb5_crypto_iov *
3261 find_iv(krb5_crypto_iov *data, int num_data, int type)
3263 int i;
3264 for (i = 0; i < num_data; i++)
3265 if (data[i].flags == type)
3266 return &data[i];
3267 return NULL;
3271 * Inline encrypt a kerberos message
3273 * @param context Kerberos context
3274 * @param crypto Kerberos crypto context
3275 * @param usage Key usage for this buffer
3276 * @param data array of buffers to process
3277 * @param num_data length of array
3278 * @param ivec initial cbc/cts vector
3280 * @return Return an error code or 0.
3281 * @ingroup krb5_crypto
3283 * Kerberos encrypted data look like this:
3285 * 1. KRB5_CRYPTO_TYPE_HEADER
3286 * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
3287 * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
3288 * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
3289 * commonly used headers and trailers.
3290 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
3291 * 4. KRB5_CRYPTO_TYPE_TRAILER
3294 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3295 krb5_encrypt_iov_ivec(krb5_context context,
3296 krb5_crypto crypto,
3297 unsigned usage,
3298 krb5_crypto_iov *data,
3299 int num_data,
3300 void *ivec)
3302 size_t headersz, trailersz, len;
3303 int i;
3304 size_t sz, block_sz, pad_sz;
3305 Checksum cksum;
3306 unsigned char *p, *q;
3307 krb5_error_code ret;
3308 struct key_data *dkey;
3309 const struct encryption_type *et = crypto->et;
3310 krb5_crypto_iov *tiv, *piv, *hiv;
3312 if (num_data < 0) {
3313 krb5_clear_error_message(context);
3314 return KRB5_CRYPTO_INTERNAL;
3317 if(!derived_crypto(context, crypto)) {
3318 krb5_clear_error_message(context);
3319 return KRB5_CRYPTO_INTERNAL;
3322 headersz = et->confoundersize;
3323 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3325 for (len = 0, i = 0; i < num_data; i++) {
3326 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3327 continue;
3328 len += data[i].data.length;
3331 sz = headersz + len;
3332 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3334 pad_sz = block_sz - sz;
3336 /* header */
3338 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3339 if (hiv == NULL || hiv->data.length != headersz)
3340 return KRB5_BAD_MSIZE;
3342 krb5_generate_random_block(hiv->data.data, hiv->data.length);
3344 /* padding */
3345 piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
3346 /* its ok to have no TYPE_PADDING if there is no padding */
3347 if (piv == NULL && pad_sz != 0)
3348 return KRB5_BAD_MSIZE;
3349 if (piv) {
3350 if (piv->data.length < pad_sz)
3351 return KRB5_BAD_MSIZE;
3352 piv->data.length = pad_sz;
3353 if (pad_sz)
3354 memset(piv->data.data, pad_sz, pad_sz);
3355 else
3356 piv = NULL;
3359 /* trailer */
3360 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3361 if (tiv == NULL || tiv->data.length != trailersz)
3362 return KRB5_BAD_MSIZE;
3365 * XXX replace with EVP_Sign? at least make create_checksum an iov
3366 * function.
3367 * XXX CTS EVP is broken, can't handle multi buffers :(
3370 len = block_sz;
3371 for (i = 0; i < num_data; i++) {
3372 if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3373 continue;
3374 len += data[i].data.length;
3377 p = q = malloc(len);
3379 memcpy(q, hiv->data.data, hiv->data.length);
3380 q += hiv->data.length;
3381 for (i = 0; i < num_data; i++) {
3382 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3383 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3384 continue;
3385 memcpy(q, data[i].data.data, data[i].data.length);
3386 q += data[i].data.length;
3388 if (piv)
3389 memset(q, 0, piv->data.length);
3391 ret = create_checksum(context,
3392 et->keyed_checksum,
3393 crypto,
3394 INTEGRITY_USAGE(usage),
3396 len,
3397 &cksum);
3398 free(p);
3399 if(ret == 0 && cksum.checksum.length != trailersz) {
3400 free_Checksum (&cksum);
3401 krb5_clear_error_message (context);
3402 ret = KRB5_CRYPTO_INTERNAL;
3404 if(ret)
3405 return ret;
3407 /* save cksum at end */
3408 memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
3409 free_Checksum (&cksum);
3411 /* XXX replace with EVP_Cipher */
3412 p = q = malloc(block_sz);
3413 if(p == NULL)
3414 return ENOMEM;
3416 memcpy(q, hiv->data.data, hiv->data.length);
3417 q += hiv->data.length;
3419 for (i = 0; i < num_data; i++) {
3420 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3421 continue;
3422 memcpy(q, data[i].data.data, data[i].data.length);
3423 q += data[i].data.length;
3425 if (piv)
3426 memset(q, 0, piv->data.length);
3429 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3430 if(ret) {
3431 free(p);
3432 return ret;
3434 ret = _key_schedule(context, dkey);
3435 if(ret) {
3436 free(p);
3437 return ret;
3440 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
3441 if (ret) {
3442 free(p);
3443 return ret;
3446 /* now copy data back to buffers */
3447 q = p;
3449 memcpy(hiv->data.data, q, hiv->data.length);
3450 q += hiv->data.length;
3452 for (i = 0; i < num_data; i++) {
3453 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3454 continue;
3455 memcpy(data[i].data.data, q, data[i].data.length);
3456 q += data[i].data.length;
3458 if (piv)
3459 memcpy(piv->data.data, q, pad_sz);
3461 free(p);
3463 return ret;
3467 * Inline decrypt a Kerberos message.
3469 * @param context Kerberos context
3470 * @param crypto Kerberos crypto context
3471 * @param usage Key usage for this buffer
3472 * @param data array of buffers to process
3473 * @param num_data length of array
3474 * @param ivec initial cbc/cts vector
3476 * @return Return an error code or 0.
3477 * @ingroup krb5_crypto
3479 * 1. KRB5_CRYPTO_TYPE_HEADER
3480 * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
3481 * any order, however the receiver have to aware of the
3482 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
3483 * protocol headers and trailers. The output data will be of same
3484 * size as the input data or shorter.
3487 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3488 krb5_decrypt_iov_ivec(krb5_context context,
3489 krb5_crypto crypto,
3490 unsigned usage,
3491 krb5_crypto_iov *data,
3492 unsigned int num_data,
3493 void *ivec)
3495 unsigned int i;
3496 size_t headersz, trailersz, len;
3497 Checksum cksum;
3498 unsigned char *p, *q;
3499 krb5_error_code ret;
3500 struct key_data *dkey;
3501 struct encryption_type *et = crypto->et;
3502 krb5_crypto_iov *tiv, *hiv;
3504 if (num_data < 0) {
3505 krb5_clear_error_message(context);
3506 return KRB5_CRYPTO_INTERNAL;
3509 if(!derived_crypto(context, crypto)) {
3510 krb5_clear_error_message(context);
3511 return KRB5_CRYPTO_INTERNAL;
3514 headersz = et->confoundersize;
3516 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3517 if (hiv == NULL || hiv->data.length != headersz)
3518 return KRB5_BAD_MSIZE;
3520 /* trailer */
3521 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3523 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3524 if (tiv->data.length != trailersz)
3525 return KRB5_BAD_MSIZE;
3527 /* Find length of data we will decrypt */
3529 len = headersz;
3530 for (i = 0; i < num_data; i++) {
3531 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3532 continue;
3533 len += data[i].data.length;
3536 if ((len % et->padsize) != 0) {
3537 krb5_clear_error_message(context);
3538 return KRB5_BAD_MSIZE;
3541 /* XXX replace with EVP_Cipher */
3543 p = q = malloc(len);
3544 if (p == NULL)
3545 return ENOMEM;
3547 memcpy(q, hiv->data.data, hiv->data.length);
3548 q += hiv->data.length;
3550 for (i = 0; i < num_data; i++) {
3551 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3552 continue;
3553 memcpy(q, data[i].data.data, data[i].data.length);
3554 q += data[i].data.length;
3557 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3558 if(ret) {
3559 free(p);
3560 return ret;
3562 ret = _key_schedule(context, dkey);
3563 if(ret) {
3564 free(p);
3565 return ret;
3568 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3569 if (ret) {
3570 free(p);
3571 return ret;
3574 /* copy data back to buffers */
3575 memcpy(hiv->data.data, p, hiv->data.length);
3576 q = p + hiv->data.length;
3577 for (i = 0; i < num_data; i++) {
3578 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3579 continue;
3580 memcpy(data[i].data.data, q, data[i].data.length);
3581 q += data[i].data.length;
3584 free(p);
3586 /* check signature */
3587 for (i = 0; i < num_data; i++) {
3588 if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3589 continue;
3590 len += data[i].data.length;
3593 p = q = malloc(len);
3594 if (p == NULL)
3595 return ENOMEM;
3597 memcpy(q, hiv->data.data, hiv->data.length);
3598 q += hiv->data.length;
3599 for (i = 0; i < num_data; i++) {
3600 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3601 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3602 continue;
3603 memcpy(q, data[i].data.data, data[i].data.length);
3604 q += data[i].data.length;
3607 cksum.checksum.data = tiv->data.data;
3608 cksum.checksum.length = tiv->data.length;
3609 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3611 ret = verify_checksum(context,
3612 crypto,
3613 INTEGRITY_USAGE(usage),
3615 len,
3616 &cksum);
3617 free(p);
3618 return ret;
3622 * Create a Kerberos message checksum.
3624 * @param context Kerberos context
3625 * @param crypto Kerberos crypto context
3626 * @param usage Key usage for this buffer
3627 * @param data array of buffers to process
3628 * @param num_data length of array
3629 * @param type output data
3631 * @return Return an error code or 0.
3632 * @ingroup krb5_crypto
3635 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3636 krb5_create_checksum_iov(krb5_context context,
3637 krb5_crypto crypto,
3638 unsigned usage,
3639 krb5_crypto_iov *data,
3640 unsigned int num_data,
3641 krb5_cksumtype *type)
3643 Checksum cksum;
3644 krb5_crypto_iov *civ;
3645 krb5_error_code ret;
3646 int i;
3647 size_t len;
3648 char *p, *q;
3650 if (num_data < 0) {
3651 krb5_clear_error_message(context);
3652 return KRB5_CRYPTO_INTERNAL;
3655 if(!derived_crypto(context, crypto)) {
3656 krb5_clear_error_message(context);
3657 return KRB5_CRYPTO_INTERNAL;
3660 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3661 if (civ == NULL)
3662 return KRB5_BAD_MSIZE;
3664 len = 0;
3665 for (i = 0; i < num_data; i++) {
3666 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3667 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3668 continue;
3669 len += data[i].data.length;
3672 p = q = malloc(len);
3674 for (i = 0; i < num_data; i++) {
3675 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3676 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3677 continue;
3678 memcpy(q, data[i].data.data, data[i].data.length);
3679 q += data[i].data.length;
3682 ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
3683 free(p);
3684 if (ret)
3685 return ret;
3687 if (type)
3688 *type = cksum.cksumtype;
3690 if (cksum.checksum.length > civ->data.length) {
3691 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3692 N_("Checksum larger then input buffer", ""));
3693 free_Checksum(&cksum);
3694 return KRB5_BAD_MSIZE;
3697 civ->data.length = cksum.checksum.length;
3698 memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
3699 free_Checksum(&cksum);
3701 return 0;
3705 * Verify a Kerberos message checksum.
3707 * @param context Kerberos context
3708 * @param crypto Kerberos crypto context
3709 * @param usage Key usage for this buffer
3710 * @param data array of buffers to process
3711 * @param num_data length of array
3712 * @param type return checksum type if not NULL
3714 * @return Return an error code or 0.
3715 * @ingroup krb5_crypto
3718 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3719 krb5_verify_checksum_iov(krb5_context context,
3720 krb5_crypto crypto,
3721 unsigned usage,
3722 krb5_crypto_iov *data,
3723 unsigned int num_data,
3724 krb5_cksumtype *type)
3726 struct encryption_type *et = crypto->et;
3727 Checksum cksum;
3728 krb5_crypto_iov *civ;
3729 krb5_error_code ret;
3730 int i;
3731 size_t len;
3732 char *p, *q;
3734 if (num_data < 0) {
3735 krb5_clear_error_message(context);
3736 return KRB5_CRYPTO_INTERNAL;
3739 if(!derived_crypto(context, crypto)) {
3740 krb5_clear_error_message(context);
3741 return KRB5_CRYPTO_INTERNAL;
3744 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3745 if (civ == NULL)
3746 return KRB5_BAD_MSIZE;
3748 len = 0;
3749 for (i = 0; i < num_data; i++) {
3750 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3751 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3752 continue;
3753 len += data[i].data.length;
3756 p = q = malloc(len);
3758 for (i = 0; i < num_data; i++) {
3759 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3760 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3761 continue;
3762 memcpy(q, data[i].data.data, data[i].data.length);
3763 q += data[i].data.length;
3766 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3767 cksum.checksum.length = civ->data.length;
3768 cksum.checksum.data = civ->data.data;
3770 ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
3771 free(p);
3773 if (ret == 0 && type)
3774 *type = cksum.cksumtype;
3776 return ret;
3780 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3781 krb5_crypto_length(krb5_context context,
3782 krb5_crypto crypto,
3783 int type,
3784 size_t *len)
3786 if (!derived_crypto(context, crypto)) {
3787 krb5_set_error_message(context, EINVAL, "not a derived crypto");
3788 return EINVAL;
3791 switch(type) {
3792 case KRB5_CRYPTO_TYPE_EMPTY:
3793 *len = 0;
3794 return 0;
3795 case KRB5_CRYPTO_TYPE_HEADER:
3796 *len = crypto->et->blocksize;
3797 return 0;
3798 case KRB5_CRYPTO_TYPE_DATA:
3799 case KRB5_CRYPTO_TYPE_SIGN_ONLY:
3800 /* len must already been filled in */
3801 return 0;
3802 case KRB5_CRYPTO_TYPE_PADDING:
3803 if (crypto->et->padsize > 1)
3804 *len = crypto->et->padsize;
3805 else
3806 *len = 0;
3807 return 0;
3808 case KRB5_CRYPTO_TYPE_TRAILER:
3809 *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
3810 return 0;
3811 case KRB5_CRYPTO_TYPE_CHECKSUM:
3812 if (crypto->et->keyed_checksum)
3813 *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
3814 else
3815 *len = CHECKSUMSIZE(crypto->et->checksum);
3816 return 0;
3818 krb5_set_error_message(context, EINVAL,
3819 "%d not a supported type", type);
3820 return EINVAL;
3824 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3825 krb5_crypto_length_iov(krb5_context context,
3826 krb5_crypto crypto,
3827 krb5_crypto_iov *data,
3828 unsigned int num_data)
3830 krb5_error_code ret;
3831 int i;
3833 for (i = 0; i < num_data; i++) {
3834 ret = krb5_crypto_length(context, crypto,
3835 data[i].flags,
3836 &data[i].data.length);
3837 if (ret)
3838 return ret;
3840 return 0;
3844 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3845 krb5_encrypt_ivec(krb5_context context,
3846 krb5_crypto crypto,
3847 unsigned usage,
3848 const void *data,
3849 size_t len,
3850 krb5_data *result,
3851 void *ivec)
3853 if(derived_crypto(context, crypto))
3854 return encrypt_internal_derived(context, crypto, usage,
3855 data, len, result, ivec);
3856 else if (special_crypto(context, crypto))
3857 return encrypt_internal_special (context, crypto, usage,
3858 data, len, result, ivec);
3859 else
3860 return encrypt_internal(context, crypto, data, len, result, ivec);
3863 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3864 krb5_encrypt(krb5_context context,
3865 krb5_crypto crypto,
3866 unsigned usage,
3867 const void *data,
3868 size_t len,
3869 krb5_data *result)
3871 return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
3874 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3875 krb5_encrypt_EncryptedData(krb5_context context,
3876 krb5_crypto crypto,
3877 unsigned usage,
3878 void *data,
3879 size_t len,
3880 int kvno,
3881 EncryptedData *result)
3883 result->etype = CRYPTO_ETYPE(crypto);
3884 if(kvno){
3885 ALLOC(result->kvno, 1);
3886 *result->kvno = kvno;
3887 }else
3888 result->kvno = NULL;
3889 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
3892 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3893 krb5_decrypt_ivec(krb5_context context,
3894 krb5_crypto crypto,
3895 unsigned usage,
3896 void *data,
3897 size_t len,
3898 krb5_data *result,
3899 void *ivec)
3901 if(derived_crypto(context, crypto))
3902 return decrypt_internal_derived(context, crypto, usage,
3903 data, len, result, ivec);
3904 else if (special_crypto (context, crypto))
3905 return decrypt_internal_special(context, crypto, usage,
3906 data, len, result, ivec);
3907 else
3908 return decrypt_internal(context, crypto, data, len, result, ivec);
3911 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3912 krb5_decrypt(krb5_context context,
3913 krb5_crypto crypto,
3914 unsigned usage,
3915 void *data,
3916 size_t len,
3917 krb5_data *result)
3919 return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
3920 NULL);
3923 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3924 krb5_decrypt_EncryptedData(krb5_context context,
3925 krb5_crypto crypto,
3926 unsigned usage,
3927 const EncryptedData *e,
3928 krb5_data *result)
3930 return krb5_decrypt(context, crypto, usage,
3931 e->cipher.data, e->cipher.length, result);
3934 /************************************************************
3936 ************************************************************/
3938 #define ENTROPY_NEEDED 128
3940 static int
3941 seed_something(void)
3943 char buf[1024], seedfile[256];
3945 /* If there is a seed file, load it. But such a file cannot be trusted,
3946 so use 0 for the entropy estimate */
3947 if (RAND_file_name(seedfile, sizeof(seedfile))) {
3948 int fd;
3949 fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
3950 if (fd >= 0) {
3951 ssize_t ret;
3952 rk_cloexec(fd);
3953 ret = read(fd, buf, sizeof(buf));
3954 if (ret > 0)
3955 RAND_add(buf, ret, 0.0);
3956 close(fd);
3957 } else
3958 seedfile[0] = '\0';
3959 } else
3960 seedfile[0] = '\0';
3962 /* Calling RAND_status() will try to use /dev/urandom if it exists so
3963 we do not have to deal with it. */
3964 if (RAND_status() != 1) {
3965 #ifndef _WIN32
3966 krb5_context context;
3967 const char *p;
3969 /* Try using egd */
3970 if (!krb5_init_context(&context)) {
3971 p = krb5_config_get_string(context, NULL, "libdefaults",
3972 "egd_socket", NULL);
3973 if (p != NULL)
3974 RAND_egd_bytes(p, ENTROPY_NEEDED);
3975 krb5_free_context(context);
3977 #else
3978 /* TODO: Once a Windows CryptoAPI RAND method is defined, we
3979 can use that and failover to another method. */
3980 #endif
3983 if (RAND_status() == 1) {
3984 /* Update the seed file */
3985 if (seedfile[0])
3986 RAND_write_file(seedfile);
3988 return 0;
3989 } else
3990 return -1;
3993 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
3994 krb5_generate_random_block(void *buf, size_t len)
3996 static int rng_initialized = 0;
3998 HEIMDAL_MUTEX_lock(&crypto_mutex);
3999 if (!rng_initialized) {
4000 if (seed_something())
4001 krb5_abortx(NULL, "Fatal: could not seed the "
4002 "random number generator");
4004 rng_initialized = 1;
4006 HEIMDAL_MUTEX_unlock(&crypto_mutex);
4007 if (RAND_bytes(buf, len) <= 0)
4008 krb5_abortx(NULL, "Failed to generate random block");
4011 static krb5_error_code
4012 derive_key(krb5_context context,
4013 struct encryption_type *et,
4014 struct key_data *key,
4015 const void *constant,
4016 size_t len)
4018 unsigned char *k = NULL;
4019 unsigned int nblocks = 0, i;
4020 krb5_error_code ret = 0;
4021 struct key_type *kt = et->keytype;
4023 ret = _key_schedule(context, key);
4024 if(ret)
4025 return ret;
4026 if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
4027 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
4028 k = malloc(nblocks * et->blocksize);
4029 if(k == NULL) {
4030 ret = ENOMEM;
4031 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4032 goto out;
4034 ret = _krb5_n_fold(constant, len, k, et->blocksize);
4035 if (ret) {
4036 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4037 goto out;
4040 for(i = 0; i < nblocks; i++) {
4041 if(i > 0)
4042 memcpy(k + i * et->blocksize,
4043 k + (i - 1) * et->blocksize,
4044 et->blocksize);
4045 (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
4046 1, 0, NULL);
4048 } else {
4049 /* this case is probably broken, but won't be run anyway */
4050 void *c = malloc(len);
4051 size_t res_len = (kt->bits + 7) / 8;
4053 if(len != 0 && c == NULL) {
4054 ret = ENOMEM;
4055 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4056 goto out;
4058 memcpy(c, constant, len);
4059 (*et->encrypt)(context, key, c, len, 1, 0, NULL);
4060 k = malloc(res_len);
4061 if(res_len != 0 && k == NULL) {
4062 free(c);
4063 ret = ENOMEM;
4064 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4065 goto out;
4067 ret = _krb5_n_fold(c, len, k, res_len);
4068 free(c);
4069 if (ret) {
4070 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4071 goto out;
4075 /* XXX keytype dependent post-processing */
4076 switch(kt->type) {
4077 case KEYTYPE_DES3:
4078 DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
4079 break;
4080 case KEYTYPE_AES128:
4081 case KEYTYPE_AES256:
4082 memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
4083 break;
4084 default:
4085 ret = KRB5_CRYPTO_INTERNAL;
4086 krb5_set_error_message(context, ret,
4087 N_("derive_key() called with unknown keytype (%u)", ""),
4088 kt->type);
4089 break;
4091 out:
4092 if (key->schedule) {
4093 free_key_schedule(context, key, et);
4094 key->schedule = NULL;
4096 if (k) {
4097 memset(k, 0, nblocks * et->blocksize);
4098 free(k);
4100 return ret;
4103 static struct key_data *
4104 _new_derived_key(krb5_crypto crypto, unsigned usage)
4106 struct key_usage *d = crypto->key_usage;
4107 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
4108 if(d == NULL)
4109 return NULL;
4110 crypto->key_usage = d;
4111 d += crypto->num_key_usage++;
4112 memset(d, 0, sizeof(*d));
4113 d->usage = usage;
4114 return &d->key;
4117 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4118 krb5_derive_key(krb5_context context,
4119 const krb5_keyblock *key,
4120 krb5_enctype etype,
4121 const void *constant,
4122 size_t constant_len,
4123 krb5_keyblock **derived_key)
4125 krb5_error_code ret;
4126 struct encryption_type *et;
4127 struct key_data d;
4129 *derived_key = NULL;
4131 et = _find_enctype (etype);
4132 if (et == NULL) {
4133 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4134 N_("encryption type %d not supported", ""),
4135 etype);
4136 return KRB5_PROG_ETYPE_NOSUPP;
4139 ret = krb5_copy_keyblock(context, key, &d.key);
4140 if (ret)
4141 return ret;
4143 d.schedule = NULL;
4144 ret = derive_key(context, et, &d, constant, constant_len);
4145 if (ret == 0)
4146 ret = krb5_copy_keyblock(context, d.key, derived_key);
4147 free_key_data(context, &d, et);
4148 return ret;
4151 static krb5_error_code
4152 _get_derived_key(krb5_context context,
4153 krb5_crypto crypto,
4154 unsigned usage,
4155 struct key_data **key)
4157 int i;
4158 struct key_data *d;
4159 unsigned char constant[5];
4161 for(i = 0; i < crypto->num_key_usage; i++)
4162 if(crypto->key_usage[i].usage == usage) {
4163 *key = &crypto->key_usage[i].key;
4164 return 0;
4166 d = _new_derived_key(crypto, usage);
4167 if(d == NULL) {
4168 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4169 return ENOMEM;
4171 krb5_copy_keyblock(context, crypto->key.key, &d->key);
4172 _krb5_put_int(constant, usage, 5);
4173 derive_key(context, crypto->et, d, constant, sizeof(constant));
4174 *key = d;
4175 return 0;
4179 * Create a crypto context used for all encryption and signature
4180 * operation. The encryption type to use is taken from the key, but
4181 * can be overridden with the enctype parameter. This can be useful
4182 * for encryptions types which is compatiable (DES for example).
4184 * To free the crypto context, use krb5_crypto_destroy().
4186 * @param context Kerberos context
4187 * @param key the key block information with all key data
4188 * @param etype the encryption type
4189 * @param crypto the resulting crypto context
4191 * @return Return an error code or 0.
4193 * @ingroup krb5_crypto
4196 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4197 krb5_crypto_init(krb5_context context,
4198 const krb5_keyblock *key,
4199 krb5_enctype etype,
4200 krb5_crypto *crypto)
4202 krb5_error_code ret;
4203 ALLOC(*crypto, 1);
4204 if(*crypto == NULL) {
4205 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4206 return ENOMEM;
4208 if(etype == ETYPE_NULL)
4209 etype = key->keytype;
4210 (*crypto)->et = _find_enctype(etype);
4211 if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
4212 free(*crypto);
4213 *crypto = NULL;
4214 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4215 N_("encryption type %d not supported", ""),
4216 etype);
4217 return KRB5_PROG_ETYPE_NOSUPP;
4219 if((*crypto)->et->keytype->size != key->keyvalue.length) {
4220 free(*crypto);
4221 *crypto = NULL;
4222 krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
4223 "encryption key has bad length");
4224 return KRB5_BAD_KEYSIZE;
4226 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
4227 if(ret) {
4228 free(*crypto);
4229 *crypto = NULL;
4230 return ret;
4232 (*crypto)->key.schedule = NULL;
4233 (*crypto)->num_key_usage = 0;
4234 (*crypto)->key_usage = NULL;
4235 return 0;
4238 static void
4239 free_key_schedule(krb5_context context,
4240 struct key_data *key,
4241 struct encryption_type *et)
4243 if (et->keytype->cleanup)
4244 (*et->keytype->cleanup)(context, key);
4245 memset(key->schedule->data, 0, key->schedule->length);
4246 krb5_free_data(context, key->schedule);
4249 static void
4250 free_key_data(krb5_context context, struct key_data *key,
4251 struct encryption_type *et)
4253 krb5_free_keyblock(context, key->key);
4254 if(key->schedule) {
4255 free_key_schedule(context, key, et);
4256 key->schedule = NULL;
4260 static void
4261 free_key_usage(krb5_context context, struct key_usage *ku,
4262 struct encryption_type *et)
4264 free_key_data(context, &ku->key, et);
4268 * Free a crypto context created by krb5_crypto_init().
4270 * @param context Kerberos context
4271 * @param crypto crypto context to free
4273 * @return Return an error code or 0.
4275 * @ingroup krb5_crypto
4278 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4279 krb5_crypto_destroy(krb5_context context,
4280 krb5_crypto crypto)
4282 int i;
4284 for(i = 0; i < crypto->num_key_usage; i++)
4285 free_key_usage(context, &crypto->key_usage[i], crypto->et);
4286 free(crypto->key_usage);
4287 free_key_data(context, &crypto->key, crypto->et);
4288 free (crypto);
4289 return 0;
4293 * Return the blocksize used algorithm referenced by the crypto context
4295 * @param context Kerberos context
4296 * @param crypto crypto context to query
4297 * @param blocksize the resulting blocksize
4299 * @return Return an error code or 0.
4301 * @ingroup krb5_crypto
4304 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4305 krb5_crypto_getblocksize(krb5_context context,
4306 krb5_crypto crypto,
4307 size_t *blocksize)
4309 *blocksize = crypto->et->blocksize;
4310 return 0;
4314 * Return the encryption type used by the crypto context
4316 * @param context Kerberos context
4317 * @param crypto crypto context to query
4318 * @param enctype the resulting encryption type
4320 * @return Return an error code or 0.
4322 * @ingroup krb5_crypto
4325 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4326 krb5_crypto_getenctype(krb5_context context,
4327 krb5_crypto crypto,
4328 krb5_enctype *enctype)
4330 *enctype = crypto->et->type;
4331 return 0;
4335 * Return the padding size used by the crypto context
4337 * @param context Kerberos context
4338 * @param crypto crypto context to query
4339 * @param padsize the return padding size
4341 * @return Return an error code or 0.
4343 * @ingroup krb5_crypto
4346 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4347 krb5_crypto_getpadsize(krb5_context context,
4348 krb5_crypto crypto,
4349 size_t *padsize)
4351 *padsize = crypto->et->padsize;
4352 return 0;
4356 * Return the confounder size used by the crypto context
4358 * @param context Kerberos context
4359 * @param crypto crypto context to query
4360 * @param confoundersize the returned confounder size
4362 * @return Return an error code or 0.
4364 * @ingroup krb5_crypto
4367 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4368 krb5_crypto_getconfoundersize(krb5_context context,
4369 krb5_crypto crypto,
4370 size_t *confoundersize)
4372 *confoundersize = crypto->et->confoundersize;
4373 return 0;
4378 * Disable encryption type
4380 * @param context Kerberos 5 context
4381 * @param enctype encryption type to disable
4383 * @return Return an error code or 0.
4385 * @ingroup krb5_crypto
4388 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4389 krb5_enctype_disable(krb5_context context,
4390 krb5_enctype enctype)
4392 struct encryption_type *et = _find_enctype(enctype);
4393 if(et == NULL) {
4394 if (context)
4395 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4396 N_("encryption type %d not supported", ""),
4397 enctype);
4398 return KRB5_PROG_ETYPE_NOSUPP;
4400 et->flags |= F_DISABLED;
4401 return 0;
4405 * Enable encryption type
4407 * @param context Kerberos 5 context
4408 * @param enctype encryption type to enable
4410 * @return Return an error code or 0.
4412 * @ingroup krb5_crypto
4415 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4416 krb5_enctype_enable(krb5_context context,
4417 krb5_enctype enctype)
4419 struct encryption_type *et = _find_enctype(enctype);
4420 if(et == NULL) {
4421 if (context)
4422 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4423 N_("encryption type %d not supported", ""),
4424 enctype);
4425 return KRB5_PROG_ETYPE_NOSUPP;
4427 et->flags &= ~F_DISABLED;
4428 return 0;
4432 * Enable or disable all weak encryption types
4434 * @param context Kerberos 5 context
4435 * @param enable true to enable, false to disable
4437 * @return Return an error code or 0.
4439 * @ingroup krb5_crypto
4442 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4443 krb5_allow_weak_crypto(krb5_context context,
4444 krb5_boolean enable)
4446 int i;
4448 for(i = 0; i < num_etypes; i++)
4449 if(etypes[i]->flags & F_WEAK) {
4450 if(enable)
4451 etypes[i]->flags &= ~F_DISABLED;
4452 else
4453 etypes[i]->flags |= F_DISABLED;
4455 return 0;
4459 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4460 krb5_string_to_key_derived(krb5_context context,
4461 const void *str,
4462 size_t len,
4463 krb5_enctype etype,
4464 krb5_keyblock *key)
4466 struct encryption_type *et = _find_enctype(etype);
4467 krb5_error_code ret;
4468 struct key_data kd;
4469 size_t keylen;
4470 u_char *tmp;
4472 if(et == NULL) {
4473 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4474 N_("encryption type %d not supported", ""),
4475 etype);
4476 return KRB5_PROG_ETYPE_NOSUPP;
4478 keylen = et->keytype->bits / 8;
4480 ALLOC(kd.key, 1);
4481 if(kd.key == NULL) {
4482 krb5_set_error_message (context, ENOMEM,
4483 N_("malloc: out of memory", ""));
4484 return ENOMEM;
4486 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
4487 if(ret) {
4488 free(kd.key);
4489 return ret;
4491 kd.key->keytype = etype;
4492 tmp = malloc (keylen);
4493 if(tmp == NULL) {
4494 krb5_free_keyblock(context, kd.key);
4495 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4496 return ENOMEM;
4498 ret = _krb5_n_fold(str, len, tmp, keylen);
4499 if (ret) {
4500 free(tmp);
4501 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4502 return ret;
4504 kd.schedule = NULL;
4505 DES3_random_to_key(context, kd.key, tmp, keylen);
4506 memset(tmp, 0, keylen);
4507 free(tmp);
4508 ret = derive_key(context,
4510 &kd,
4511 "kerberos", /* XXX well known constant */
4512 strlen("kerberos"));
4513 if (ret) {
4514 free_key_data(context, &kd, et);
4515 return ret;
4517 ret = krb5_copy_keyblock_contents(context, kd.key, key);
4518 free_key_data(context, &kd, et);
4519 return ret;
4522 static size_t
4523 wrapped_length (krb5_context context,
4524 krb5_crypto crypto,
4525 size_t data_len)
4527 struct encryption_type *et = crypto->et;
4528 size_t padsize = et->padsize;
4529 size_t checksumsize = CHECKSUMSIZE(et->checksum);
4530 size_t res;
4532 res = et->confoundersize + checksumsize + data_len;
4533 res = (res + padsize - 1) / padsize * padsize;
4534 return res;
4537 static size_t
4538 wrapped_length_dervied (krb5_context context,
4539 krb5_crypto crypto,
4540 size_t data_len)
4542 struct encryption_type *et = crypto->et;
4543 size_t padsize = et->padsize;
4544 size_t res;
4546 res = et->confoundersize + data_len;
4547 res = (res + padsize - 1) / padsize * padsize;
4548 if (et->keyed_checksum)
4549 res += et->keyed_checksum->checksumsize;
4550 else
4551 res += et->checksum->checksumsize;
4552 return res;
4556 * Return the size of an encrypted packet of length `data_len'
4559 size_t
4560 krb5_get_wrapped_length (krb5_context context,
4561 krb5_crypto crypto,
4562 size_t data_len)
4564 if (derived_crypto (context, crypto))
4565 return wrapped_length_dervied (context, crypto, data_len);
4566 else
4567 return wrapped_length (context, crypto, data_len);
4571 * Return the size of an encrypted packet of length `data_len'
4574 static size_t
4575 crypto_overhead (krb5_context context,
4576 krb5_crypto crypto)
4578 struct encryption_type *et = crypto->et;
4579 size_t res;
4581 res = CHECKSUMSIZE(et->checksum);
4582 res += et->confoundersize;
4583 if (et->padsize > 1)
4584 res += et->padsize;
4585 return res;
4588 static size_t
4589 crypto_overhead_dervied (krb5_context context,
4590 krb5_crypto crypto)
4592 struct encryption_type *et = crypto->et;
4593 size_t res;
4595 if (et->keyed_checksum)
4596 res = CHECKSUMSIZE(et->keyed_checksum);
4597 else
4598 res = CHECKSUMSIZE(et->checksum);
4599 res += et->confoundersize;
4600 if (et->padsize > 1)
4601 res += et->padsize;
4602 return res;
4605 size_t
4606 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
4608 if (derived_crypto (context, crypto))
4609 return crypto_overhead_dervied (context, crypto);
4610 else
4611 return crypto_overhead (context, crypto);
4615 * Converts the random bytestring to a protocol key according to
4616 * Kerberos crypto frame work. It may be assumed that all the bits of
4617 * the input string are equally random, even though the entropy
4618 * present in the random source may be limited.
4620 * @param context Kerberos 5 context
4621 * @param type the enctype resulting key will be of
4622 * @param data input random data to convert to a key
4623 * @param size size of input random data, at least krb5_enctype_keysize() long
4624 * @param key key, output key, free with krb5_free_keyblock_contents()
4626 * @return Return an error code or 0.
4628 * @ingroup krb5_crypto
4631 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4632 krb5_random_to_key(krb5_context context,
4633 krb5_enctype type,
4634 const void *data,
4635 size_t size,
4636 krb5_keyblock *key)
4638 krb5_error_code ret;
4639 struct encryption_type *et = _find_enctype(type);
4640 if(et == NULL) {
4641 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4642 N_("encryption type %d not supported", ""),
4643 type);
4644 return KRB5_PROG_ETYPE_NOSUPP;
4646 if ((et->keytype->bits + 7) / 8 > size) {
4647 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4648 N_("encryption key %s needs %d bytes "
4649 "of random to make an encryption key "
4650 "out of it", ""),
4651 et->name, (int)et->keytype->size);
4652 return KRB5_PROG_ETYPE_NOSUPP;
4654 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
4655 if(ret)
4656 return ret;
4657 key->keytype = type;
4658 if (et->keytype->random_to_key)
4659 (*et->keytype->random_to_key)(context, key, data, size);
4660 else
4661 memcpy(key->keyvalue.data, data, et->keytype->size);
4663 return 0;
4666 krb5_error_code
4667 _krb5_pk_octetstring2key(krb5_context context,
4668 krb5_enctype type,
4669 const void *dhdata,
4670 size_t dhsize,
4671 const heim_octet_string *c_n,
4672 const heim_octet_string *k_n,
4673 krb5_keyblock *key)
4675 struct encryption_type *et = _find_enctype(type);
4676 krb5_error_code ret;
4677 size_t keylen, offset;
4678 void *keydata;
4679 unsigned char counter;
4680 unsigned char shaoutput[SHA_DIGEST_LENGTH];
4681 EVP_MD_CTX *m;
4683 if(et == NULL) {
4684 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4685 N_("encryption type %d not supported", ""),
4686 type);
4687 return KRB5_PROG_ETYPE_NOSUPP;
4689 keylen = (et->keytype->bits + 7) / 8;
4691 keydata = malloc(keylen);
4692 if (keydata == NULL) {
4693 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4694 return ENOMEM;
4697 m = EVP_MD_CTX_create();
4698 if (m == NULL) {
4699 free(keydata);
4700 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4701 return ENOMEM;
4704 counter = 0;
4705 offset = 0;
4706 do {
4708 EVP_DigestInit_ex(m, EVP_sha1(), NULL);
4709 EVP_DigestUpdate(m, &counter, 1);
4710 EVP_DigestUpdate(m, dhdata, dhsize);
4712 if (c_n)
4713 EVP_DigestUpdate(m, c_n->data, c_n->length);
4714 if (k_n)
4715 EVP_DigestUpdate(m, k_n->data, k_n->length);
4717 EVP_DigestFinal_ex(m, shaoutput, NULL);
4719 memcpy((unsigned char *)keydata + offset,
4720 shaoutput,
4721 min(keylen - offset, sizeof(shaoutput)));
4723 offset += sizeof(shaoutput);
4724 counter++;
4725 } while(offset < keylen);
4726 memset(shaoutput, 0, sizeof(shaoutput));
4728 EVP_MD_CTX_destroy(m);
4730 ret = krb5_random_to_key(context, type, keydata, keylen, key);
4731 memset(keydata, 0, sizeof(keylen));
4732 free(keydata);
4733 return ret;
4736 static krb5_error_code
4737 encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
4739 KRB5PrincipalName pn;
4740 krb5_error_code ret;
4741 size_t size;
4743 pn.principalName = p->name;
4744 pn.realm = p->realm;
4746 ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
4747 &pn, &size, ret);
4748 if (ret) {
4749 krb5_data_zero(data);
4750 krb5_set_error_message(context, ret,
4751 N_("Failed to encode KRB5PrincipalName", ""));
4752 return ret;
4754 if (data->length != size)
4755 krb5_abortx(context, "asn1 compiler internal error");
4756 return 0;
4759 static krb5_error_code
4760 encode_otherinfo(krb5_context context,
4761 const AlgorithmIdentifier *ai,
4762 krb5_const_principal client,
4763 krb5_const_principal server,
4764 krb5_enctype enctype,
4765 const krb5_data *as_req,
4766 const krb5_data *pk_as_rep,
4767 const Ticket *ticket,
4768 krb5_data *other)
4770 PkinitSP80056AOtherInfo otherinfo;
4771 PkinitSuppPubInfo pubinfo;
4772 krb5_error_code ret;
4773 krb5_data pub;
4774 size_t size;
4776 krb5_data_zero(other);
4777 memset(&otherinfo, 0, sizeof(otherinfo));
4778 memset(&pubinfo, 0, sizeof(pubinfo));
4780 pubinfo.enctype = enctype;
4781 pubinfo.as_REQ = *as_req;
4782 pubinfo.pk_as_rep = *pk_as_rep;
4783 pubinfo.ticket = *ticket;
4784 ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
4785 &pubinfo, &size, ret);
4786 if (ret) {
4787 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4788 return ret;
4790 if (pub.length != size)
4791 krb5_abortx(context, "asn1 compiler internal error");
4793 ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
4794 if (ret) {
4795 free(pub.data);
4796 return ret;
4798 ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
4799 if (ret) {
4800 free(otherinfo.partyUInfo.data);
4801 free(pub.data);
4802 return ret;
4805 otherinfo.algorithmID = *ai;
4806 otherinfo.suppPubInfo = &pub;
4808 ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
4809 &otherinfo, &size, ret);
4810 free(otherinfo.partyUInfo.data);
4811 free(otherinfo.partyVInfo.data);
4812 free(pub.data);
4813 if (ret) {
4814 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4815 return ret;
4817 if (other->length != size)
4818 krb5_abortx(context, "asn1 compiler internal error");
4820 return 0;
4823 krb5_error_code
4824 _krb5_pk_kdf(krb5_context context,
4825 const struct AlgorithmIdentifier *ai,
4826 const void *dhdata,
4827 size_t dhsize,
4828 krb5_const_principal client,
4829 krb5_const_principal server,
4830 krb5_enctype enctype,
4831 const krb5_data *as_req,
4832 const krb5_data *pk_as_rep,
4833 const Ticket *ticket,
4834 krb5_keyblock *key)
4836 struct encryption_type *et;
4837 krb5_error_code ret;
4838 krb5_data other;
4839 size_t keylen, offset;
4840 uint32_t counter;
4841 unsigned char *keydata;
4842 unsigned char shaoutput[SHA_DIGEST_LENGTH];
4843 EVP_MD_CTX *m;
4845 if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) != 0) {
4846 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4847 N_("KDF not supported", ""));
4848 return KRB5_PROG_ETYPE_NOSUPP;
4850 if (ai->parameters != NULL &&
4851 (ai->parameters->length != 2 ||
4852 memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
4854 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4855 N_("kdf params not NULL or the NULL-type",
4856 ""));
4857 return KRB5_PROG_ETYPE_NOSUPP;
4860 et = _find_enctype(enctype);
4861 if(et == NULL) {
4862 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4863 N_("encryption type %d not supported", ""),
4864 enctype);
4865 return KRB5_PROG_ETYPE_NOSUPP;
4867 keylen = (et->keytype->bits + 7) / 8;
4869 keydata = malloc(keylen);
4870 if (keydata == NULL) {
4871 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4872 return ENOMEM;
4875 ret = encode_otherinfo(context, ai, client, server,
4876 enctype, as_req, pk_as_rep, ticket, &other);
4877 if (ret) {
4878 free(keydata);
4879 return ret;
4882 m = EVP_MD_CTX_create();
4883 if (m == NULL) {
4884 free(keydata);
4885 free(other.data);
4886 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4887 return ENOMEM;
4890 offset = 0;
4891 counter = 1;
4892 do {
4893 unsigned char cdata[4];
4895 EVP_DigestInit_ex(m, EVP_sha1(), NULL);
4896 _krb5_put_int(cdata, counter, 4);
4897 EVP_DigestUpdate(m, cdata, 4);
4898 EVP_DigestUpdate(m, dhdata, dhsize);
4899 EVP_DigestUpdate(m, other.data, other.length);
4901 EVP_DigestFinal_ex(m, shaoutput, NULL);
4903 memcpy((unsigned char *)keydata + offset,
4904 shaoutput,
4905 min(keylen - offset, sizeof(shaoutput)));
4907 offset += sizeof(shaoutput);
4908 counter++;
4909 } while(offset < keylen);
4910 memset(shaoutput, 0, sizeof(shaoutput));
4912 EVP_MD_CTX_destroy(m);
4913 free(other.data);
4915 ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
4916 memset(keydata, 0, sizeof(keylen));
4917 free(keydata);
4919 return ret;
4923 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4924 krb5_crypto_prf_length(krb5_context context,
4925 krb5_enctype type,
4926 size_t *length)
4928 struct encryption_type *et = _find_enctype(type);
4930 if(et == NULL || et->prf_length == 0) {
4931 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4932 N_("encryption type %d not supported", ""),
4933 type);
4934 return KRB5_PROG_ETYPE_NOSUPP;
4937 *length = et->prf_length;
4938 return 0;
4941 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
4942 krb5_crypto_prf(krb5_context context,
4943 const krb5_crypto crypto,
4944 const krb5_data *input,
4945 krb5_data *output)
4947 struct encryption_type *et = crypto->et;
4949 krb5_data_zero(output);
4951 if(et->prf == NULL) {
4952 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4953 "kerberos prf for %s not supported",
4954 et->name);
4955 return KRB5_PROG_ETYPE_NOSUPP;
4958 return (*et->prf)(context, crypto, input, output);
4961 static krb5_error_code
4962 krb5_crypto_prfplus(krb5_context context,
4963 const krb5_crypto crypto,
4964 const krb5_data *input,
4965 size_t length,
4966 krb5_data *output)
4968 krb5_error_code ret;
4969 krb5_data input2;
4970 unsigned char i = 1;
4971 unsigned char *p;
4973 krb5_data_zero(&input2);
4974 krb5_data_zero(output);
4976 krb5_clear_error_message(context);
4978 ret = krb5_data_alloc(output, length);
4979 if (ret) goto out;
4980 ret = krb5_data_alloc(&input2, input->length + 1);
4981 if (ret) goto out;
4983 krb5_clear_error_message(context);
4985 memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
4987 p = output->data;
4989 while (length) {
4990 krb5_data block;
4992 ((unsigned char *)input2.data)[0] = i++;
4994 ret = krb5_crypto_prf(context, crypto, &input2, &block);
4995 if (ret)
4996 goto out;
4998 if (block.length < length) {
4999 memcpy(p, block.data, block.length);
5000 length -= block.length;
5001 } else {
5002 memcpy(p, block.data, length);
5003 length = 0;
5005 p += block.length;
5006 krb5_data_free(&block);
5009 out:
5010 krb5_data_free(&input2);
5011 if (ret)
5012 krb5_data_free(output);
5013 return 0;
5017 * The FX-CF2 key derivation function, used in FAST and preauth framework.
5019 * @param context Kerberos 5 context
5020 * @param crypto1 first key to combine
5021 * @param crypto2 second key to combine
5022 * @param pepper1 factor to combine with first key to garante uniqueness
5023 * @param pepper2 factor to combine with second key to garante uniqueness
5024 * @param enctype the encryption type of the resulting key
5025 * @param res allocated key, free with krb5_free_keyblock_contents()
5027 * @return Return an error code or 0.
5029 * @ingroup krb5_crypto
5032 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
5033 krb5_crypto_fx_cf2(krb5_context context,
5034 const krb5_crypto crypto1,
5035 const krb5_crypto crypto2,
5036 krb5_data *pepper1,
5037 krb5_data *pepper2,
5038 krb5_enctype enctype,
5039 krb5_keyblock *res)
5041 krb5_error_code ret;
5042 krb5_data os1, os2;
5043 size_t i, keysize;
5045 memset(res, 0, sizeof(*res));
5047 ret = krb5_enctype_keysize(context, enctype, &keysize);
5048 if (ret)
5049 return ret;
5051 ret = krb5_data_alloc(&res->keyvalue, keysize);
5052 if (ret)
5053 goto out;
5054 ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
5055 if (ret)
5056 goto out;
5057 ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
5058 if (ret)
5059 goto out;
5061 res->keytype = enctype;
5063 unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
5064 for (i = 0; i < keysize; i++)
5065 p3[i] = p1[i] ^ p2[i];
5067 out:
5068 if (ret)
5069 krb5_data_free(&res->keyvalue);
5070 krb5_data_free(&os1);
5071 krb5_data_free(&os2);
5073 return ret;
5078 #ifndef HEIMDAL_SMALLER
5081 * Deprecated: keytypes doesn't exists, they are really enctypes.
5083 * @ingroup krb5_deprecated
5086 KRB5_DEPRECATED
5087 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
5088 krb5_keytype_to_enctypes (krb5_context context,
5089 krb5_keytype keytype,
5090 unsigned *len,
5091 krb5_enctype **val)
5093 int i;
5094 unsigned n = 0;
5095 krb5_enctype *ret;
5097 for (i = num_etypes - 1; i >= 0; --i) {
5098 if (etypes[i]->keytype->type == keytype
5099 && !(etypes[i]->flags & F_PSEUDO)
5100 && krb5_enctype_valid(context, etypes[i]->type) == 0)
5101 ++n;
5103 if (n == 0) {
5104 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
5105 "Keytype have no mapping");
5106 return KRB5_PROG_KEYTYPE_NOSUPP;
5109 ret = malloc(n * sizeof(*ret));
5110 if (ret == NULL && n != 0) {
5111 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
5112 return ENOMEM;
5114 n = 0;
5115 for (i = num_etypes - 1; i >= 0; --i) {
5116 if (etypes[i]->keytype->type == keytype
5117 && !(etypes[i]->flags & F_PSEUDO)
5118 && krb5_enctype_valid(context, etypes[i]->type) == 0)
5119 ret[n++] = etypes[i]->type;
5121 *len = n;
5122 *val = ret;
5123 return 0;
5127 * Deprecated: keytypes doesn't exists, they are really enctypes.
5129 * @ingroup krb5_deprecated
5132 /* if two enctypes have compatible keys */
5133 KRB5_DEPRECATED
5134 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
5135 krb5_enctypes_compatible_keys(krb5_context context,
5136 krb5_enctype etype1,
5137 krb5_enctype etype2)
5139 struct encryption_type *e1 = _find_enctype(etype1);
5140 struct encryption_type *e2 = _find_enctype(etype2);
5141 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
5144 #endif /* HEIMDAL_SMALLER */