make paranoia check less paranoid
[heimdal.git] / lib / krb5 / crypto.c
blob3531b50150211803ee12fb95b4fa11a5cd7ea524
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 #include "krb5_locl.h"
35 RCSID("$Id$");
36 #include <pkinit_asn1.h>
38 #undef __attribute__
39 #define __attribute__(X)
41 #define WEAK_ENCTYPES 1
43 #ifndef HEIMDAL_SMALLER
44 #define DES3_OLD_ENCTYPE 1
45 #endif
48 #ifdef HAVE_OPENSSL /* XXX forward decl for hcrypto glue */
49 const EVP_CIPHER * _krb5_EVP_hcrypto_aes_128_cts(void);
50 const EVP_CIPHER * _krb5_EVP_hcrypto_aes_256_cts(void);
51 #define EVP_hcrypto_aes_128_cts _krb5_EVP_hcrypto_aes_128_cts
52 #define EVP_hcrypto_aes_256_cts _krb5_EVP_hcrypto_aes_256_cts
53 #endif
55 struct key_data {
56 krb5_keyblock *key;
57 krb5_data *schedule;
60 struct key_usage {
61 unsigned usage;
62 struct key_data key;
65 struct krb5_crypto_data {
66 struct encryption_type *et;
67 struct key_data key;
68 int num_key_usage;
69 struct key_usage *key_usage;
72 #define CRYPTO_ETYPE(C) ((C)->et->type)
74 /* bits for `flags' below */
75 #define F_KEYED 1 /* checksum is keyed */
76 #define F_CPROOF 2 /* checksum is collision proof */
77 #define F_DERIVED 4 /* uses derived keys */
78 #define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
79 #define F_PSEUDO 16 /* not a real protocol type */
80 #define F_SPECIAL 32 /* backwards */
81 #define F_DISABLED 64 /* enctype/checksum disabled */
83 struct salt_type {
84 krb5_salttype type;
85 const char *name;
86 krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
87 krb5_salt, krb5_data, krb5_keyblock*);
90 struct key_type {
91 krb5_keytype type; /* XXX */
92 const char *name;
93 size_t bits;
94 size_t size;
95 size_t schedule_size;
96 void (*random_key)(krb5_context, krb5_keyblock*);
97 void (*schedule)(krb5_context, struct key_type *, struct key_data *);
98 struct salt_type *string_to_key;
99 void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
100 void (*cleanup)(krb5_context, struct key_data *);
101 const EVP_CIPHER *(*evp)(void);
104 struct checksum_type {
105 krb5_cksumtype type;
106 const char *name;
107 size_t blocksize;
108 size_t checksumsize;
109 unsigned flags;
110 krb5_enctype (*checksum)(krb5_context context,
111 struct key_data *key,
112 const void *buf, size_t len,
113 unsigned usage,
114 Checksum *csum);
115 krb5_error_code (*verify)(krb5_context context,
116 struct key_data *key,
117 const void *buf, size_t len,
118 unsigned usage,
119 Checksum *csum);
122 struct encryption_type {
123 krb5_enctype type;
124 const char *name;
125 size_t blocksize;
126 size_t padsize;
127 size_t confoundersize;
128 struct key_type *keytype;
129 struct checksum_type *checksum;
130 struct checksum_type *keyed_checksum;
131 unsigned flags;
132 krb5_error_code (*encrypt)(krb5_context context,
133 struct key_data *key,
134 void *data, size_t len,
135 krb5_boolean encryptp,
136 int usage,
137 void *ivec);
138 size_t prf_length;
139 krb5_error_code (*prf)(krb5_context,
140 krb5_crypto, const krb5_data *, krb5_data *);
143 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
144 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
145 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
147 static struct checksum_type *_find_checksum(krb5_cksumtype type);
148 static struct encryption_type *_find_enctype(krb5_enctype type);
149 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
150 unsigned, struct key_data**);
151 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
152 static krb5_error_code derive_key(krb5_context context,
153 struct encryption_type *et,
154 struct key_data *key,
155 const void *constant,
156 size_t len);
157 static krb5_error_code hmac(krb5_context context,
158 struct checksum_type *cm,
159 const void *data,
160 size_t len,
161 unsigned usage,
162 struct key_data *keyblock,
163 Checksum *result);
164 static void free_key_data(krb5_context,
165 struct key_data *,
166 struct encryption_type *);
167 static void free_key_schedule(krb5_context,
168 struct key_data *,
169 struct encryption_type *);
170 static krb5_error_code usage2arcfour (krb5_context, unsigned *);
171 static void xor (DES_cblock *, const unsigned char *);
173 /************************************************************
175 ************************************************************/
177 struct evp_schedule {
178 EVP_CIPHER_CTX ectx;
179 EVP_CIPHER_CTX dctx;
183 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
185 #ifdef WEAK_ENCTYPES
186 static void
187 krb5_DES_random_key(krb5_context context,
188 krb5_keyblock *key)
190 DES_cblock *k = key->keyvalue.data;
191 do {
192 krb5_generate_random_block(k, sizeof(DES_cblock));
193 DES_set_odd_parity(k);
194 } while(DES_is_weak_key(k));
197 static void
198 krb5_DES_schedule_old(krb5_context context,
199 struct key_type *kt,
200 struct key_data *key)
202 DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
205 #ifdef ENABLE_AFS_STRING_TO_KEY
207 /* This defines the Andrew string_to_key function. It accepts a password
208 * string as input and converts it via a one-way encryption algorithm to a DES
209 * encryption key. It is compatible with the original Andrew authentication
210 * service password database.
214 * Short passwords, i.e 8 characters or less.
216 static void
217 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
218 krb5_data cell,
219 DES_cblock *key)
221 char password[8+1]; /* crypt is limited to 8 chars anyway */
222 int i;
224 for(i = 0; i < 8; i++) {
225 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
226 ((i < cell.length) ?
227 tolower(((unsigned char*)cell.data)[i]) : 0);
228 password[i] = c ? c : 'X';
230 password[8] = '\0';
232 memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
234 /* parity is inserted into the LSB so left shift each byte up one
235 bit. This allows ascii characters with a zero MSB to retain as
236 much significance as possible. */
237 for (i = 0; i < sizeof(DES_cblock); i++)
238 ((unsigned char*)key)[i] <<= 1;
239 DES_set_odd_parity (key);
243 * Long passwords, i.e 9 characters or more.
245 static void
246 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
247 krb5_data cell,
248 DES_cblock *key)
250 DES_key_schedule schedule;
251 DES_cblock temp_key;
252 DES_cblock ivec;
253 char password[512];
254 size_t passlen;
256 memcpy(password, pw.data, min(pw.length, sizeof(password)));
257 if(pw.length < sizeof(password)) {
258 int len = min(cell.length, sizeof(password) - pw.length);
259 int i;
261 memcpy(password + pw.length, cell.data, len);
262 for (i = pw.length; i < pw.length + len; ++i)
263 password[i] = tolower((unsigned char)password[i]);
265 passlen = min(sizeof(password), pw.length + cell.length);
266 memcpy(&ivec, "kerberos", 8);
267 memcpy(&temp_key, "kerberos", 8);
268 DES_set_odd_parity (&temp_key);
269 DES_set_key_unchecked (&temp_key, &schedule);
270 DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
272 memcpy(&temp_key, &ivec, 8);
273 DES_set_odd_parity (&temp_key);
274 DES_set_key_unchecked (&temp_key, &schedule);
275 DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
276 memset(&schedule, 0, sizeof(schedule));
277 memset(&temp_key, 0, sizeof(temp_key));
278 memset(&ivec, 0, sizeof(ivec));
279 memset(password, 0, sizeof(password));
281 DES_set_odd_parity (key);
284 static krb5_error_code
285 DES_AFS3_string_to_key(krb5_context context,
286 krb5_enctype enctype,
287 krb5_data password,
288 krb5_salt salt,
289 krb5_data opaque,
290 krb5_keyblock *key)
292 DES_cblock tmp;
293 if(password.length > 8)
294 krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
295 else
296 krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
297 key->keytype = enctype;
298 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
299 memset(&key, 0, sizeof(key));
300 return 0;
302 #endif /* ENABLE_AFS_STRING_TO_KEY */
304 static void
305 DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
307 DES_key_schedule schedule;
308 int i;
309 int reverse = 0;
310 unsigned char *p;
312 unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
313 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
314 memset(key, 0, 8);
316 p = (unsigned char*)key;
317 for (i = 0; i < length; i++) {
318 unsigned char tmp = data[i];
319 if (!reverse)
320 *p++ ^= (tmp << 1);
321 else
322 *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
323 if((i % 8) == 7)
324 reverse = !reverse;
326 DES_set_odd_parity(key);
327 if(DES_is_weak_key(key))
328 (*key)[7] ^= 0xF0;
329 DES_set_key_unchecked(key, &schedule);
330 DES_cbc_cksum((void*)data, key, length, &schedule, key);
331 memset(&schedule, 0, sizeof(schedule));
332 DES_set_odd_parity(key);
333 if(DES_is_weak_key(key))
334 (*key)[7] ^= 0xF0;
337 static krb5_error_code
338 krb5_DES_string_to_key(krb5_context context,
339 krb5_enctype enctype,
340 krb5_data password,
341 krb5_salt salt,
342 krb5_data opaque,
343 krb5_keyblock *key)
345 unsigned char *s;
346 size_t len;
347 DES_cblock tmp;
349 #ifdef ENABLE_AFS_STRING_TO_KEY
350 if (opaque.length == 1) {
351 unsigned long v;
352 _krb5_get_int(opaque.data, &v, 1);
353 if (v == 1)
354 return DES_AFS3_string_to_key(context, enctype, password,
355 salt, opaque, key);
357 #endif
359 len = password.length + salt.saltvalue.length;
360 s = malloc(len);
361 if(len > 0 && s == NULL) {
362 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
363 return ENOMEM;
365 memcpy(s, password.data, password.length);
366 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
367 DES_string_to_key_int(s, len, &tmp);
368 key->keytype = enctype;
369 krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
370 memset(&tmp, 0, sizeof(tmp));
371 memset(s, 0, len);
372 free(s);
373 return 0;
376 static void
377 krb5_DES_random_to_key(krb5_context context,
378 krb5_keyblock *key,
379 const void *data,
380 size_t size)
382 DES_cblock *k = key->keyvalue.data;
383 memcpy(k, data, key->keyvalue.length);
384 DES_set_odd_parity(k);
385 if(DES_is_weak_key(k))
386 xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
388 #endif
394 static void
395 DES3_random_key(krb5_context context,
396 krb5_keyblock *key)
398 DES_cblock *k = key->keyvalue.data;
399 do {
400 krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
401 DES_set_odd_parity(&k[0]);
402 DES_set_odd_parity(&k[1]);
403 DES_set_odd_parity(&k[2]);
404 } while(DES_is_weak_key(&k[0]) ||
405 DES_is_weak_key(&k[1]) ||
406 DES_is_weak_key(&k[2]));
410 * A = A xor B. A & B are 8 bytes.
413 static void
414 xor (DES_cblock *key, const unsigned char *b)
416 unsigned char *a = (unsigned char*)key;
417 a[0] ^= b[0];
418 a[1] ^= b[1];
419 a[2] ^= b[2];
420 a[3] ^= b[3];
421 a[4] ^= b[4];
422 a[5] ^= b[5];
423 a[6] ^= b[6];
424 a[7] ^= b[7];
427 #ifdef DES3_OLD_ENCTYPE
428 static krb5_error_code
429 DES3_string_to_key(krb5_context context,
430 krb5_enctype enctype,
431 krb5_data password,
432 krb5_salt salt,
433 krb5_data opaque,
434 krb5_keyblock *key)
436 char *str;
437 size_t len;
438 unsigned char tmp[24];
439 DES_cblock keys[3];
440 krb5_error_code ret;
442 len = password.length + salt.saltvalue.length;
443 str = malloc(len);
444 if(len != 0 && str == NULL) {
445 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
446 return ENOMEM;
448 memcpy(str, password.data, password.length);
449 memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
451 DES_cblock ivec;
452 DES_key_schedule s[3];
453 int i;
455 ret = _krb5_n_fold(str, len, tmp, 24);
456 if (ret) {
457 memset(str, 0, len);
458 free(str);
459 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
460 return ret;
463 for(i = 0; i < 3; i++){
464 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
465 DES_set_odd_parity(keys + i);
466 if(DES_is_weak_key(keys + i))
467 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
468 DES_set_key_unchecked(keys + i, &s[i]);
470 memset(&ivec, 0, sizeof(ivec));
471 DES_ede3_cbc_encrypt(tmp,
472 tmp, sizeof(tmp),
473 &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
474 memset(s, 0, sizeof(s));
475 memset(&ivec, 0, sizeof(ivec));
476 for(i = 0; i < 3; i++){
477 memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
478 DES_set_odd_parity(keys + i);
479 if(DES_is_weak_key(keys + i))
480 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
482 memset(tmp, 0, sizeof(tmp));
484 key->keytype = enctype;
485 krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
486 memset(keys, 0, sizeof(keys));
487 memset(str, 0, len);
488 free(str);
489 return 0;
491 #endif
493 static krb5_error_code
494 DES3_string_to_key_derived(krb5_context context,
495 krb5_enctype enctype,
496 krb5_data password,
497 krb5_salt salt,
498 krb5_data opaque,
499 krb5_keyblock *key)
501 krb5_error_code ret;
502 size_t len = password.length + salt.saltvalue.length;
503 char *s;
505 s = malloc(len);
506 if(len != 0 && s == NULL) {
507 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
508 return ENOMEM;
510 memcpy(s, password.data, password.length);
511 memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
512 ret = krb5_string_to_key_derived(context,
514 len,
515 enctype,
516 key);
517 memset(s, 0, len);
518 free(s);
519 return ret;
522 static void
523 DES3_random_to_key(krb5_context context,
524 krb5_keyblock *key,
525 const void *data,
526 size_t size)
528 unsigned char *x = key->keyvalue.data;
529 const u_char *q = data;
530 DES_cblock *k;
531 int i, j;
533 memset(x, 0, sizeof(x));
534 for (i = 0; i < 3; ++i) {
535 unsigned char foo;
536 for (j = 0; j < 7; ++j) {
537 unsigned char b = q[7 * i + j];
539 x[8 * i + j] = b;
541 foo = 0;
542 for (j = 6; j >= 0; --j) {
543 foo |= q[7 * i + j] & 1;
544 foo <<= 1;
546 x[8 * i + 7] = foo;
548 k = key->keyvalue.data;
549 for (i = 0; i < 3; i++) {
550 DES_set_odd_parity(&k[i]);
551 if(DES_is_weak_key(&k[i]))
552 xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
557 * ARCFOUR
560 static void
561 ARCFOUR_schedule(krb5_context context,
562 struct key_type *kt,
563 struct key_data *kd)
565 RC4_set_key (kd->schedule->data,
566 kd->key->keyvalue.length, kd->key->keyvalue.data);
569 static krb5_error_code
570 ARCFOUR_string_to_key(krb5_context context,
571 krb5_enctype enctype,
572 krb5_data password,
573 krb5_salt salt,
574 krb5_data opaque,
575 krb5_keyblock *key)
577 krb5_error_code ret;
578 uint16_t *s = NULL;
579 size_t len, i;
580 EVP_MD_CTX *m;
582 m = EVP_MD_CTX_create();
583 if (m == NULL) {
584 ret = ENOMEM;
585 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
586 goto out;
589 EVP_DigestInit_ex(m, EVP_md4(), NULL);
591 ret = wind_utf8ucs2_length(password.data, &len);
592 if (ret) {
593 krb5_set_error_message (context, ret,
594 N_("Password not an UCS2 string", ""));
595 goto out;
598 s = malloc (len * sizeof(s[0]));
599 if (len != 0 && s == NULL) {
600 krb5_set_error_message (context, ENOMEM,
601 N_("malloc: out of memory", ""));
602 ret = ENOMEM;
603 goto out;
606 ret = wind_utf8ucs2(password.data, s, &len);
607 if (ret) {
608 krb5_set_error_message (context, ret,
609 N_("Password not an UCS2 string", ""));
610 goto out;
613 /* LE encoding */
614 for (i = 0; i < len; i++) {
615 unsigned char p;
616 p = (s[i] & 0xff);
617 EVP_DigestUpdate (m, &p, 1);
618 p = (s[i] >> 8) & 0xff;
619 EVP_DigestUpdate (m, &p, 1);
622 key->keytype = enctype;
623 ret = krb5_data_alloc (&key->keyvalue, 16);
624 if (ret) {
625 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
626 goto out;
628 EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
630 out:
631 EVP_MD_CTX_destroy(m);
632 if (s)
633 memset (s, 0, len);
634 free (s);
635 return ret;
639 * AES
642 int _krb5_AES_string_to_default_iterator = 4096;
644 static krb5_error_code
645 AES_string_to_key(krb5_context context,
646 krb5_enctype enctype,
647 krb5_data password,
648 krb5_salt salt,
649 krb5_data opaque,
650 krb5_keyblock *key)
652 krb5_error_code ret;
653 uint32_t iter;
654 struct encryption_type *et;
655 struct key_data kd;
657 if (opaque.length == 0)
658 iter = _krb5_AES_string_to_default_iterator;
659 else if (opaque.length == 4) {
660 unsigned long v;
661 _krb5_get_int(opaque.data, &v, 4);
662 iter = ((uint32_t)v);
663 } else
664 return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
666 et = _find_enctype(enctype);
667 if (et == NULL)
668 return KRB5_PROG_KEYTYPE_NOSUPP;
670 kd.schedule = NULL;
671 ALLOC(kd.key, 1);
672 if(kd.key == NULL) {
673 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
674 return ENOMEM;
676 kd.key->keytype = enctype;
677 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
678 if (ret) {
679 krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
680 return ret;
683 ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
684 salt.saltvalue.data, salt.saltvalue.length,
685 iter,
686 et->keytype->size, kd.key->keyvalue.data);
687 if (ret != 1) {
688 free_key_data(context, &kd, et);
689 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
690 "Error calculating s2k");
691 return KRB5_PROG_KEYTYPE_NOSUPP;
694 ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
695 if (ret == 0)
696 ret = krb5_copy_keyblock_contents(context, kd.key, key);
697 free_key_data(context, &kd, et);
699 return ret;
702 static void
703 evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd)
705 struct evp_schedule *key = kd->schedule->data;
706 const EVP_CIPHER *c = (*kt->evp)();
708 EVP_CIPHER_CTX_init(&key->ectx);
709 EVP_CIPHER_CTX_init(&key->dctx);
711 EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
712 EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
715 static void
716 evp_cleanup(krb5_context context, struct key_data *kd)
718 struct evp_schedule *key = kd->schedule->data;
719 EVP_CIPHER_CTX_cleanup(&key->ectx);
720 EVP_CIPHER_CTX_cleanup(&key->dctx);
727 #ifdef WEAK_ENCTYPES
728 static struct salt_type des_salt[] = {
730 KRB5_PW_SALT,
731 "pw-salt",
732 krb5_DES_string_to_key
734 #ifdef ENABLE_AFS_STRING_TO_KEY
736 KRB5_AFS3_SALT,
737 "afs3-salt",
738 DES_AFS3_string_to_key
740 #endif
741 { 0 }
743 #endif
745 #ifdef DES3_OLD_ENCTYPE
746 static struct salt_type des3_salt[] = {
748 KRB5_PW_SALT,
749 "pw-salt",
750 DES3_string_to_key
752 { 0 }
754 #endif
756 static struct salt_type des3_salt_derived[] = {
758 KRB5_PW_SALT,
759 "pw-salt",
760 DES3_string_to_key_derived
762 { 0 }
765 static struct salt_type AES_salt[] = {
767 KRB5_PW_SALT,
768 "pw-salt",
769 AES_string_to_key
771 { 0 }
774 static struct salt_type arcfour_salt[] = {
776 KRB5_PW_SALT,
777 "pw-salt",
778 ARCFOUR_string_to_key
780 { 0 }
787 static struct key_type keytype_null = {
788 KEYTYPE_NULL,
789 "null",
793 NULL,
794 NULL,
795 NULL
798 #ifdef WEAK_ENCTYPES
799 static struct key_type keytype_des_old = {
800 KEYTYPE_DES,
801 "des-old",
804 sizeof(DES_key_schedule),
805 krb5_DES_random_key,
806 krb5_DES_schedule_old,
807 des_salt,
808 krb5_DES_random_to_key
811 static struct key_type keytype_des = {
812 KEYTYPE_DES,
813 "des",
816 sizeof(struct evp_schedule),
817 krb5_DES_random_key,
818 evp_schedule,
819 des_salt,
820 krb5_DES_random_to_key,
821 evp_cleanup,
822 EVP_des_cbc
824 #endif /* WEAK_ENCTYPES */
826 #ifdef DES3_OLD_ENCTYPE
827 static struct key_type keytype_des3 = {
828 KEYTYPE_DES3,
829 "des3",
830 168,
832 sizeof(struct evp_schedule),
833 DES3_random_key,
834 evp_schedule,
835 des3_salt,
836 DES3_random_to_key,
837 evp_cleanup,
838 EVP_des_ede3_cbc
840 #endif
842 static struct key_type keytype_des3_derived = {
843 KEYTYPE_DES3,
844 "des3",
845 168,
847 sizeof(struct evp_schedule),
848 DES3_random_key,
849 evp_schedule,
850 des3_salt_derived,
851 DES3_random_to_key,
852 evp_cleanup,
853 EVP_des_ede3_cbc
856 static struct key_type keytype_aes128 = {
857 KEYTYPE_AES128,
858 "aes-128",
859 128,
861 sizeof(struct evp_schedule),
862 NULL,
863 evp_schedule,
864 AES_salt,
865 NULL,
866 evp_cleanup,
867 EVP_hcrypto_aes_128_cts
870 static struct key_type keytype_aes256 = {
871 KEYTYPE_AES256,
872 "aes-256",
873 256,
875 sizeof(struct evp_schedule),
876 NULL,
877 evp_schedule,
878 AES_salt,
879 NULL,
880 evp_cleanup,
881 EVP_hcrypto_aes_256_cts
884 static struct key_type keytype_arcfour = {
885 KEYTYPE_ARCFOUR,
886 "arcfour",
887 128,
889 sizeof(RC4_KEY),
890 NULL,
891 ARCFOUR_schedule,
892 arcfour_salt
895 krb5_error_code KRB5_LIB_FUNCTION
896 krb5_salttype_to_string (krb5_context context,
897 krb5_enctype etype,
898 krb5_salttype stype,
899 char **string)
901 struct encryption_type *e;
902 struct salt_type *st;
904 e = _find_enctype (etype);
905 if (e == NULL) {
906 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
907 "encryption type %d not supported",
908 etype);
909 return KRB5_PROG_ETYPE_NOSUPP;
911 for (st = e->keytype->string_to_key; st && st->type; st++) {
912 if (st->type == stype) {
913 *string = strdup (st->name);
914 if (*string == NULL) {
915 krb5_set_error_message (context, ENOMEM,
916 N_("malloc: out of memory", ""));
917 return ENOMEM;
919 return 0;
922 krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
923 "salttype %d not supported", stype);
924 return HEIM_ERR_SALTTYPE_NOSUPP;
927 krb5_error_code KRB5_LIB_FUNCTION
928 krb5_string_to_salttype (krb5_context context,
929 krb5_enctype etype,
930 const char *string,
931 krb5_salttype *salttype)
933 struct encryption_type *e;
934 struct salt_type *st;
936 e = _find_enctype (etype);
937 if (e == NULL) {
938 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
939 N_("encryption type %d not supported", ""),
940 etype);
941 return KRB5_PROG_ETYPE_NOSUPP;
943 for (st = e->keytype->string_to_key; st && st->type; st++) {
944 if (strcasecmp (st->name, string) == 0) {
945 *salttype = st->type;
946 return 0;
949 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
950 N_("salttype %s not supported", ""), string);
951 return HEIM_ERR_SALTTYPE_NOSUPP;
954 krb5_error_code KRB5_LIB_FUNCTION
955 krb5_get_pw_salt(krb5_context context,
956 krb5_const_principal principal,
957 krb5_salt *salt)
959 size_t len;
960 int i;
961 krb5_error_code ret;
962 char *p;
964 salt->salttype = KRB5_PW_SALT;
965 len = strlen(principal->realm);
966 for (i = 0; i < principal->name.name_string.len; ++i)
967 len += strlen(principal->name.name_string.val[i]);
968 ret = krb5_data_alloc (&salt->saltvalue, len);
969 if (ret)
970 return ret;
971 p = salt->saltvalue.data;
972 memcpy (p, principal->realm, strlen(principal->realm));
973 p += strlen(principal->realm);
974 for (i = 0; i < principal->name.name_string.len; ++i) {
975 memcpy (p,
976 principal->name.name_string.val[i],
977 strlen(principal->name.name_string.val[i]));
978 p += strlen(principal->name.name_string.val[i]);
980 return 0;
983 krb5_error_code KRB5_LIB_FUNCTION
984 krb5_free_salt(krb5_context context,
985 krb5_salt salt)
987 krb5_data_free(&salt.saltvalue);
988 return 0;
991 krb5_error_code KRB5_LIB_FUNCTION
992 krb5_string_to_key_data (krb5_context context,
993 krb5_enctype enctype,
994 krb5_data password,
995 krb5_principal principal,
996 krb5_keyblock *key)
998 krb5_error_code ret;
999 krb5_salt salt;
1001 ret = krb5_get_pw_salt(context, principal, &salt);
1002 if(ret)
1003 return ret;
1004 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
1005 krb5_free_salt(context, salt);
1006 return ret;
1009 krb5_error_code KRB5_LIB_FUNCTION
1010 krb5_string_to_key (krb5_context context,
1011 krb5_enctype enctype,
1012 const char *password,
1013 krb5_principal principal,
1014 krb5_keyblock *key)
1016 krb5_data pw;
1017 pw.data = rk_UNCONST(password);
1018 pw.length = strlen(password);
1019 return krb5_string_to_key_data(context, enctype, pw, principal, key);
1022 krb5_error_code KRB5_LIB_FUNCTION
1023 krb5_string_to_key_data_salt (krb5_context context,
1024 krb5_enctype enctype,
1025 krb5_data password,
1026 krb5_salt salt,
1027 krb5_keyblock *key)
1029 krb5_data opaque;
1030 krb5_data_zero(&opaque);
1031 return krb5_string_to_key_data_salt_opaque(context, enctype, password,
1032 salt, opaque, key);
1036 * Do a string -> key for encryption type `enctype' operation on
1037 * `password' (with salt `salt' and the enctype specific data string
1038 * `opaque'), returning the resulting key in `key'
1041 krb5_error_code KRB5_LIB_FUNCTION
1042 krb5_string_to_key_data_salt_opaque (krb5_context context,
1043 krb5_enctype enctype,
1044 krb5_data password,
1045 krb5_salt salt,
1046 krb5_data opaque,
1047 krb5_keyblock *key)
1049 struct encryption_type *et =_find_enctype(enctype);
1050 struct salt_type *st;
1051 if(et == NULL) {
1052 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1053 N_("encryption type %d not supported", ""),
1054 enctype);
1055 return KRB5_PROG_ETYPE_NOSUPP;
1057 for(st = et->keytype->string_to_key; st && st->type; st++)
1058 if(st->type == salt.salttype)
1059 return (*st->string_to_key)(context, enctype, password,
1060 salt, opaque, key);
1061 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
1062 N_("salt type %d not supported", ""),
1063 salt.salttype);
1064 return HEIM_ERR_SALTTYPE_NOSUPP;
1068 * Do a string -> key for encryption type `enctype' operation on the
1069 * string `password' (with salt `salt'), returning the resulting key
1070 * in `key'
1073 krb5_error_code KRB5_LIB_FUNCTION
1074 krb5_string_to_key_salt (krb5_context context,
1075 krb5_enctype enctype,
1076 const char *password,
1077 krb5_salt salt,
1078 krb5_keyblock *key)
1080 krb5_data pw;
1081 pw.data = rk_UNCONST(password);
1082 pw.length = strlen(password);
1083 return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
1086 krb5_error_code KRB5_LIB_FUNCTION
1087 krb5_string_to_key_salt_opaque (krb5_context context,
1088 krb5_enctype enctype,
1089 const char *password,
1090 krb5_salt salt,
1091 krb5_data opaque,
1092 krb5_keyblock *key)
1094 krb5_data pw;
1095 pw.data = rk_UNCONST(password);
1096 pw.length = strlen(password);
1097 return krb5_string_to_key_data_salt_opaque(context, enctype,
1098 pw, salt, opaque, key);
1101 krb5_error_code KRB5_LIB_FUNCTION
1102 krb5_enctype_keysize(krb5_context context,
1103 krb5_enctype type,
1104 size_t *keysize)
1106 struct encryption_type *et = _find_enctype(type);
1107 if(et == NULL) {
1108 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1109 N_("encryption type %d not supported", ""),
1110 type);
1111 return KRB5_PROG_ETYPE_NOSUPP;
1113 *keysize = et->keytype->size;
1114 return 0;
1117 krb5_error_code KRB5_LIB_FUNCTION
1118 krb5_enctype_keybits(krb5_context context,
1119 krb5_enctype type,
1120 size_t *keybits)
1122 struct encryption_type *et = _find_enctype(type);
1123 if(et == NULL) {
1124 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1125 "encryption type %d not supported",
1126 type);
1127 return KRB5_PROG_ETYPE_NOSUPP;
1129 *keybits = et->keytype->bits;
1130 return 0;
1133 krb5_error_code KRB5_LIB_FUNCTION
1134 krb5_generate_random_keyblock(krb5_context context,
1135 krb5_enctype type,
1136 krb5_keyblock *key)
1138 krb5_error_code ret;
1139 struct encryption_type *et = _find_enctype(type);
1140 if(et == NULL) {
1141 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1142 N_("encryption type %d not supported", ""),
1143 type);
1144 return KRB5_PROG_ETYPE_NOSUPP;
1146 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
1147 if(ret)
1148 return ret;
1149 key->keytype = type;
1150 if(et->keytype->random_key)
1151 (*et->keytype->random_key)(context, key);
1152 else
1153 krb5_generate_random_block(key->keyvalue.data,
1154 key->keyvalue.length);
1155 return 0;
1158 static krb5_error_code
1159 _key_schedule(krb5_context context,
1160 struct key_data *key)
1162 krb5_error_code ret;
1163 struct encryption_type *et = _find_enctype(key->key->keytype);
1164 struct key_type *kt;
1166 if (et == NULL) {
1167 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
1168 N_("encryption type %d not supported", ""),
1169 key->key->keytype);
1170 return KRB5_PROG_ETYPE_NOSUPP;
1173 kt = et->keytype;
1175 if(kt->schedule == NULL)
1176 return 0;
1177 if (key->schedule != NULL)
1178 return 0;
1179 ALLOC(key->schedule, 1);
1180 if(key->schedule == NULL) {
1181 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1182 return ENOMEM;
1184 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
1185 if(ret) {
1186 free(key->schedule);
1187 key->schedule = NULL;
1188 return ret;
1190 (*kt->schedule)(context, kt, key);
1191 return 0;
1194 /************************************************************
1196 ************************************************************/
1198 static krb5_error_code
1199 NONE_checksum(krb5_context context,
1200 struct key_data *key,
1201 const void *data,
1202 size_t len,
1203 unsigned usage,
1204 Checksum *C)
1206 return 0;
1209 static krb5_error_code
1210 CRC32_checksum(krb5_context context,
1211 struct key_data *key,
1212 const void *data,
1213 size_t len,
1214 unsigned usage,
1215 Checksum *C)
1217 uint32_t crc;
1218 unsigned char *r = C->checksum.data;
1219 _krb5_crc_init_table ();
1220 crc = _krb5_crc_update (data, len, 0);
1221 r[0] = crc & 0xff;
1222 r[1] = (crc >> 8) & 0xff;
1223 r[2] = (crc >> 16) & 0xff;
1224 r[3] = (crc >> 24) & 0xff;
1225 return 0;
1228 static krb5_error_code
1229 RSA_MD4_checksum(krb5_context context,
1230 struct key_data *key,
1231 const void *data,
1232 size_t len,
1233 unsigned usage,
1234 Checksum *C)
1236 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
1237 krb5_abortx(context, "md4 checksum failed");
1238 return 0;
1241 static krb5_error_code
1242 des_checksum(krb5_context context,
1243 const EVP_MD *evp_md,
1244 struct key_data *key,
1245 const void *data,
1246 size_t len,
1247 Checksum *cksum)
1249 struct evp_schedule *ctx = key->schedule->data;
1250 EVP_MD_CTX *m;
1251 DES_cblock ivec;
1252 unsigned char *p = cksum->checksum.data;
1254 krb5_generate_random_block(p, 8);
1256 m = EVP_MD_CTX_create();
1257 if (m == NULL) {
1258 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1259 return ENOMEM;
1262 EVP_DigestInit_ex(m, evp_md, NULL);
1263 EVP_DigestUpdate(m, p, 8);
1264 EVP_DigestUpdate(m, data, len);
1265 EVP_DigestFinal_ex (m, p + 8, NULL);
1266 EVP_MD_CTX_destroy(m);
1267 memset (&ivec, 0, sizeof(ivec));
1268 EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
1269 EVP_Cipher(&ctx->ectx, p, p, 24);
1271 return 0;
1274 static krb5_error_code
1275 des_verify(krb5_context context,
1276 const EVP_MD *evp_md,
1277 struct key_data *key,
1278 const void *data,
1279 size_t len,
1280 Checksum *C)
1282 struct evp_schedule *ctx = key->schedule->data;
1283 EVP_MD_CTX *m;
1284 unsigned char tmp[24];
1285 unsigned char res[16];
1286 DES_cblock ivec;
1287 krb5_error_code ret = 0;
1289 m = EVP_MD_CTX_create();
1290 if (m == NULL) {
1291 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1292 return ENOMEM;
1295 memset(&ivec, 0, sizeof(ivec));
1296 EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
1297 EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
1299 EVP_DigestInit_ex(m, evp_md, NULL);
1300 EVP_DigestUpdate(m, tmp, 8); /* confounder */
1301 EVP_DigestUpdate(m, data, len);
1302 EVP_DigestFinal_ex (m, res, NULL);
1303 EVP_MD_CTX_destroy(m);
1304 if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
1305 krb5_clear_error_message (context);
1306 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1308 memset(tmp, 0, sizeof(tmp));
1309 memset(res, 0, sizeof(res));
1310 return ret;
1313 static krb5_error_code
1314 RSA_MD4_DES_checksum(krb5_context context,
1315 struct key_data *key,
1316 const void *data,
1317 size_t len,
1318 unsigned usage,
1319 Checksum *cksum)
1321 return des_checksum(context, EVP_md4(), key, data, len, cksum);
1324 static krb5_error_code
1325 RSA_MD4_DES_verify(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_verify(context, EVP_md5(), key, data, len, C);
1335 static krb5_error_code
1336 RSA_MD5_checksum(krb5_context context,
1337 struct key_data *key,
1338 const void *data,
1339 size_t len,
1340 unsigned usage,
1341 Checksum *C)
1343 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
1344 krb5_abortx(context, "md5 checksum failed");
1345 return 0;
1348 static krb5_error_code
1349 RSA_MD5_DES_checksum(krb5_context context,
1350 struct key_data *key,
1351 const void *data,
1352 size_t len,
1353 unsigned usage,
1354 Checksum *C)
1356 return des_checksum(context, EVP_md5(), key, data, len, C);
1359 static krb5_error_code
1360 RSA_MD5_DES_verify(krb5_context context,
1361 struct key_data *key,
1362 const void *data,
1363 size_t len,
1364 unsigned usage,
1365 Checksum *C)
1367 return des_verify(context, EVP_md5(), key, data, len, C);
1370 #ifdef DES3_OLD_ENCTYPE
1371 static krb5_error_code
1372 RSA_MD5_DES3_checksum(krb5_context context,
1373 struct key_data *key,
1374 const void *data,
1375 size_t len,
1376 unsigned usage,
1377 Checksum *C)
1379 return des_checksum(context, EVP_md5(), key, data, len, C);
1382 static krb5_error_code
1383 RSA_MD5_DES3_verify(krb5_context context,
1384 struct key_data *key,
1385 const void *data,
1386 size_t len,
1387 unsigned usage,
1388 Checksum *C)
1390 return des_verify(context, EVP_md5(), key, data, len, C);
1392 #endif
1394 static krb5_error_code
1395 SHA1_checksum(krb5_context context,
1396 struct key_data *key,
1397 const void *data,
1398 size_t len,
1399 unsigned usage,
1400 Checksum *C)
1402 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
1403 krb5_abortx(context, "sha1 checksum failed");
1404 return 0;
1407 /* HMAC according to RFC2104 */
1408 static krb5_error_code
1409 hmac(krb5_context context,
1410 struct checksum_type *cm,
1411 const void *data,
1412 size_t len,
1413 unsigned usage,
1414 struct key_data *keyblock,
1415 Checksum *result)
1417 unsigned char *ipad, *opad;
1418 unsigned char *key;
1419 size_t key_len;
1420 int i;
1422 ipad = malloc(cm->blocksize + len);
1423 if (ipad == NULL)
1424 return ENOMEM;
1425 opad = malloc(cm->blocksize + cm->checksumsize);
1426 if (opad == NULL) {
1427 free(ipad);
1428 return ENOMEM;
1430 memset(ipad, 0x36, cm->blocksize);
1431 memset(opad, 0x5c, cm->blocksize);
1433 if(keyblock->key->keyvalue.length > cm->blocksize){
1434 (*cm->checksum)(context,
1435 keyblock,
1436 keyblock->key->keyvalue.data,
1437 keyblock->key->keyvalue.length,
1438 usage,
1439 result);
1440 key = result->checksum.data;
1441 key_len = result->checksum.length;
1442 } else {
1443 key = keyblock->key->keyvalue.data;
1444 key_len = keyblock->key->keyvalue.length;
1446 for(i = 0; i < key_len; i++){
1447 ipad[i] ^= key[i];
1448 opad[i] ^= key[i];
1450 memcpy(ipad + cm->blocksize, data, len);
1451 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1452 usage, result);
1453 memcpy(opad + cm->blocksize, result->checksum.data,
1454 result->checksum.length);
1455 (*cm->checksum)(context, keyblock, opad,
1456 cm->blocksize + cm->checksumsize, usage, result);
1457 memset(ipad, 0, cm->blocksize + len);
1458 free(ipad);
1459 memset(opad, 0, cm->blocksize + cm->checksumsize);
1460 free(opad);
1462 return 0;
1465 krb5_error_code KRB5_LIB_FUNCTION
1466 krb5_hmac(krb5_context context,
1467 krb5_cksumtype cktype,
1468 const void *data,
1469 size_t len,
1470 unsigned usage,
1471 krb5_keyblock *key,
1472 Checksum *result)
1474 struct checksum_type *c = _find_checksum(cktype);
1475 struct key_data kd;
1476 krb5_error_code ret;
1478 if (c == NULL) {
1479 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1480 N_("checksum type %d not supported", ""),
1481 cktype);
1482 return KRB5_PROG_SUMTYPE_NOSUPP;
1485 kd.key = key;
1486 kd.schedule = NULL;
1488 ret = hmac(context, c, data, len, usage, &kd, result);
1490 if (kd.schedule)
1491 krb5_free_data(context, kd.schedule);
1493 return ret;
1496 static krb5_error_code
1497 SP_HMAC_SHA1_checksum(krb5_context context,
1498 struct key_data *key,
1499 const void *data,
1500 size_t len,
1501 unsigned usage,
1502 Checksum *result)
1504 struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1505 Checksum res;
1506 char sha1_data[20];
1507 krb5_error_code ret;
1509 res.checksum.data = sha1_data;
1510 res.checksum.length = sizeof(sha1_data);
1512 ret = hmac(context, c, data, len, usage, key, &res);
1513 if (ret)
1514 krb5_abortx(context, "hmac failed");
1515 memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
1516 return 0;
1520 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1523 static krb5_error_code
1524 HMAC_MD5_checksum(krb5_context context,
1525 struct key_data *key,
1526 const void *data,
1527 size_t len,
1528 unsigned usage,
1529 Checksum *result)
1531 EVP_MD_CTX *m;
1532 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1533 const char signature[] = "signaturekey";
1534 Checksum ksign_c;
1535 struct key_data ksign;
1536 krb5_keyblock kb;
1537 unsigned char t[4];
1538 unsigned char tmp[16];
1539 unsigned char ksign_c_data[16];
1540 krb5_error_code ret;
1542 m = EVP_MD_CTX_create();
1543 if (m == NULL) {
1544 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1545 return ENOMEM;
1547 ksign_c.checksum.length = sizeof(ksign_c_data);
1548 ksign_c.checksum.data = ksign_c_data;
1549 ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1550 if (ret) {
1551 EVP_MD_CTX_destroy(m);
1552 return ret;
1554 ksign.key = &kb;
1555 kb.keyvalue = ksign_c.checksum;
1556 EVP_DigestInit_ex(m, EVP_md5(), NULL);
1557 t[0] = (usage >> 0) & 0xFF;
1558 t[1] = (usage >> 8) & 0xFF;
1559 t[2] = (usage >> 16) & 0xFF;
1560 t[3] = (usage >> 24) & 0xFF;
1561 EVP_DigestUpdate(m, t, 4);
1562 EVP_DigestUpdate(m, data, len);
1563 EVP_DigestFinal_ex (m, tmp, NULL);
1564 EVP_MD_CTX_destroy(m);
1566 ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1567 if (ret)
1568 return ret;
1569 return 0;
1572 static struct checksum_type checksum_none = {
1573 CKSUMTYPE_NONE,
1574 "none",
1578 NONE_checksum,
1579 NULL
1581 static struct checksum_type checksum_crc32 = {
1582 CKSUMTYPE_CRC32,
1583 "crc32",
1587 CRC32_checksum,
1588 NULL
1590 static struct checksum_type checksum_rsa_md4 = {
1591 CKSUMTYPE_RSA_MD4,
1592 "rsa-md4",
1595 F_CPROOF,
1596 RSA_MD4_checksum,
1597 NULL
1599 static struct checksum_type checksum_rsa_md4_des = {
1600 CKSUMTYPE_RSA_MD4_DES,
1601 "rsa-md4-des",
1604 F_KEYED | F_CPROOF | F_VARIANT,
1605 RSA_MD4_DES_checksum,
1606 RSA_MD4_DES_verify
1608 static struct checksum_type checksum_rsa_md5 = {
1609 CKSUMTYPE_RSA_MD5,
1610 "rsa-md5",
1613 F_CPROOF,
1614 RSA_MD5_checksum,
1615 NULL
1617 static struct checksum_type checksum_rsa_md5_des = {
1618 CKSUMTYPE_RSA_MD5_DES,
1619 "rsa-md5-des",
1622 F_KEYED | F_CPROOF | F_VARIANT,
1623 RSA_MD5_DES_checksum,
1624 RSA_MD5_DES_verify
1626 #ifdef DES3_OLD_ENCTYPE
1627 static struct checksum_type checksum_rsa_md5_des3 = {
1628 CKSUMTYPE_RSA_MD5_DES3,
1629 "rsa-md5-des3",
1632 F_KEYED | F_CPROOF | F_VARIANT,
1633 RSA_MD5_DES3_checksum,
1634 RSA_MD5_DES3_verify
1636 #endif
1637 static struct checksum_type checksum_sha1 = {
1638 CKSUMTYPE_SHA1,
1639 "sha1",
1642 F_CPROOF,
1643 SHA1_checksum,
1644 NULL
1646 static struct checksum_type checksum_hmac_sha1_des3 = {
1647 CKSUMTYPE_HMAC_SHA1_DES3,
1648 "hmac-sha1-des3",
1651 F_KEYED | F_CPROOF | F_DERIVED,
1652 SP_HMAC_SHA1_checksum,
1653 NULL
1656 static struct checksum_type checksum_hmac_sha1_aes128 = {
1657 CKSUMTYPE_HMAC_SHA1_96_AES_128,
1658 "hmac-sha1-96-aes128",
1661 F_KEYED | F_CPROOF | F_DERIVED,
1662 SP_HMAC_SHA1_checksum,
1663 NULL
1666 static struct checksum_type checksum_hmac_sha1_aes256 = {
1667 CKSUMTYPE_HMAC_SHA1_96_AES_256,
1668 "hmac-sha1-96-aes256",
1671 F_KEYED | F_CPROOF | F_DERIVED,
1672 SP_HMAC_SHA1_checksum,
1673 NULL
1676 static struct checksum_type checksum_hmac_md5 = {
1677 CKSUMTYPE_HMAC_MD5,
1678 "hmac-md5",
1681 F_KEYED | F_CPROOF,
1682 HMAC_MD5_checksum,
1683 NULL
1686 static struct checksum_type *checksum_types[] = {
1687 &checksum_none,
1688 &checksum_crc32,
1689 &checksum_rsa_md4,
1690 &checksum_rsa_md4_des,
1691 &checksum_rsa_md5,
1692 &checksum_rsa_md5_des,
1693 #ifdef DES3_OLD_ENCTYPE
1694 &checksum_rsa_md5_des3,
1695 #endif
1696 &checksum_sha1,
1697 &checksum_hmac_sha1_des3,
1698 &checksum_hmac_sha1_aes128,
1699 &checksum_hmac_sha1_aes256,
1700 &checksum_hmac_md5
1703 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1705 static struct checksum_type *
1706 _find_checksum(krb5_cksumtype type)
1708 int i;
1709 for(i = 0; i < num_checksums; i++)
1710 if(checksum_types[i]->type == type)
1711 return checksum_types[i];
1712 return NULL;
1715 static krb5_error_code
1716 get_checksum_key(krb5_context context,
1717 krb5_crypto crypto,
1718 unsigned usage, /* not krb5_key_usage */
1719 struct checksum_type *ct,
1720 struct key_data **key)
1722 krb5_error_code ret = 0;
1724 if(ct->flags & F_DERIVED)
1725 ret = _get_derived_key(context, crypto, usage, key);
1726 else if(ct->flags & F_VARIANT) {
1727 int i;
1729 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1730 if(*key == NULL) {
1731 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1732 return ENOMEM;
1734 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1735 if(ret)
1736 return ret;
1737 for(i = 0; i < (*key)->key->keyvalue.length; i++)
1738 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1739 } else {
1740 *key = &crypto->key;
1742 if(ret == 0)
1743 ret = _key_schedule(context, *key);
1744 return ret;
1747 static krb5_error_code
1748 create_checksum (krb5_context context,
1749 struct checksum_type *ct,
1750 krb5_crypto crypto,
1751 unsigned usage,
1752 void *data,
1753 size_t len,
1754 Checksum *result)
1756 krb5_error_code ret;
1757 struct key_data *dkey;
1758 int keyed_checksum;
1760 if (ct->flags & F_DISABLED) {
1761 krb5_clear_error_message (context);
1762 return KRB5_PROG_SUMTYPE_NOSUPP;
1764 keyed_checksum = (ct->flags & F_KEYED) != 0;
1765 if(keyed_checksum && crypto == NULL) {
1766 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1767 N_("Checksum type %s is keyed but no "
1768 "crypto context (key) was passed in", ""),
1769 ct->name);
1770 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1772 if(keyed_checksum) {
1773 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1774 if (ret)
1775 return ret;
1776 } else
1777 dkey = NULL;
1778 result->cksumtype = ct->type;
1779 ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1780 if (ret)
1781 return (ret);
1782 return (*ct->checksum)(context, dkey, data, len, usage, result);
1785 static int
1786 arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
1788 return (ct->type == CKSUMTYPE_HMAC_MD5) &&
1789 (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
1792 krb5_error_code KRB5_LIB_FUNCTION
1793 krb5_create_checksum(krb5_context context,
1794 krb5_crypto crypto,
1795 krb5_key_usage usage,
1796 int type,
1797 void *data,
1798 size_t len,
1799 Checksum *result)
1801 struct checksum_type *ct = NULL;
1802 unsigned keyusage;
1804 /* type 0 -> pick from crypto */
1805 if (type) {
1806 ct = _find_checksum(type);
1807 } else if (crypto) {
1808 ct = crypto->et->keyed_checksum;
1809 if (ct == NULL)
1810 ct = crypto->et->checksum;
1813 if(ct == NULL) {
1814 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1815 N_("checksum type %d not supported", ""),
1816 type);
1817 return KRB5_PROG_SUMTYPE_NOSUPP;
1820 if (arcfour_checksum_p(ct, crypto)) {
1821 keyusage = usage;
1822 usage2arcfour(context, &keyusage);
1823 } else
1824 keyusage = CHECKSUM_USAGE(usage);
1826 return create_checksum(context, ct, crypto, keyusage,
1827 data, len, result);
1830 static krb5_error_code
1831 verify_checksum(krb5_context context,
1832 krb5_crypto crypto,
1833 unsigned usage, /* not krb5_key_usage */
1834 void *data,
1835 size_t len,
1836 Checksum *cksum)
1838 krb5_error_code ret;
1839 struct key_data *dkey;
1840 int keyed_checksum;
1841 Checksum c;
1842 struct checksum_type *ct;
1844 ct = _find_checksum(cksum->cksumtype);
1845 if (ct == NULL || (ct->flags & F_DISABLED)) {
1846 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1847 N_("checksum type %d not supported", ""),
1848 cksum->cksumtype);
1849 return KRB5_PROG_SUMTYPE_NOSUPP;
1851 if(ct->checksumsize != cksum->checksum.length) {
1852 krb5_clear_error_message (context);
1853 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1855 keyed_checksum = (ct->flags & F_KEYED) != 0;
1856 if(keyed_checksum) {
1857 struct checksum_type *kct;
1858 if (crypto == NULL) {
1859 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1860 N_("Checksum type %s is keyed but no "
1861 "crypto context (key) was passed in", ""),
1862 ct->name);
1863 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1865 kct = crypto->et->keyed_checksum;
1866 if (kct != NULL && kct->type != ct->type) {
1867 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1868 N_("Checksum type %s is keyed, but "
1869 "the key type %s passed didnt have that checksum "
1870 "type as the keyed type", ""),
1871 ct->name, crypto->et->name);
1872 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1875 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1876 if (ret)
1877 return ret;
1878 } else
1879 dkey = NULL;
1880 if(ct->verify)
1881 return (*ct->verify)(context, dkey, data, len, usage, cksum);
1883 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1884 if (ret)
1885 return ret;
1887 ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
1888 if (ret) {
1889 krb5_data_free(&c.checksum);
1890 return ret;
1893 if(c.checksum.length != cksum->checksum.length ||
1894 memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
1895 krb5_clear_error_message (context);
1896 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1897 } else {
1898 ret = 0;
1900 krb5_data_free (&c.checksum);
1901 return ret;
1904 krb5_error_code KRB5_LIB_FUNCTION
1905 krb5_verify_checksum(krb5_context context,
1906 krb5_crypto crypto,
1907 krb5_key_usage usage,
1908 void *data,
1909 size_t len,
1910 Checksum *cksum)
1912 struct checksum_type *ct;
1913 unsigned keyusage;
1915 ct = _find_checksum(cksum->cksumtype);
1916 if(ct == NULL) {
1917 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1918 N_("checksum type %d not supported", ""),
1919 cksum->cksumtype);
1920 return KRB5_PROG_SUMTYPE_NOSUPP;
1923 if (arcfour_checksum_p(ct, crypto)) {
1924 keyusage = usage;
1925 usage2arcfour(context, &keyusage);
1926 } else
1927 keyusage = CHECKSUM_USAGE(usage);
1929 return verify_checksum(context, crypto, keyusage,
1930 data, len, cksum);
1933 krb5_error_code KRB5_LIB_FUNCTION
1934 krb5_crypto_get_checksum_type(krb5_context context,
1935 krb5_crypto crypto,
1936 krb5_cksumtype *type)
1938 struct checksum_type *ct = NULL;
1940 if (crypto != NULL) {
1941 ct = crypto->et->keyed_checksum;
1942 if (ct == NULL)
1943 ct = crypto->et->checksum;
1946 if (ct == NULL) {
1947 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1948 N_("checksum type not found", ""));
1949 return KRB5_PROG_SUMTYPE_NOSUPP;
1952 *type = ct->type;
1954 return 0;
1958 krb5_error_code KRB5_LIB_FUNCTION
1959 krb5_checksumsize(krb5_context context,
1960 krb5_cksumtype type,
1961 size_t *size)
1963 struct checksum_type *ct = _find_checksum(type);
1964 if(ct == NULL) {
1965 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1966 N_("checksum type %d not supported", ""),
1967 type);
1968 return KRB5_PROG_SUMTYPE_NOSUPP;
1970 *size = ct->checksumsize;
1971 return 0;
1974 krb5_boolean KRB5_LIB_FUNCTION
1975 krb5_checksum_is_keyed(krb5_context context,
1976 krb5_cksumtype type)
1978 struct checksum_type *ct = _find_checksum(type);
1979 if(ct == NULL) {
1980 if (context)
1981 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1982 N_("checksum type %d not supported", ""),
1983 type);
1984 return KRB5_PROG_SUMTYPE_NOSUPP;
1986 return ct->flags & F_KEYED;
1989 krb5_boolean KRB5_LIB_FUNCTION
1990 krb5_checksum_is_collision_proof(krb5_context context,
1991 krb5_cksumtype type)
1993 struct checksum_type *ct = _find_checksum(type);
1994 if(ct == NULL) {
1995 if (context)
1996 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1997 N_("checksum type %d not supported", ""),
1998 type);
1999 return KRB5_PROG_SUMTYPE_NOSUPP;
2001 return ct->flags & F_CPROOF;
2004 krb5_error_code KRB5_LIB_FUNCTION
2005 krb5_checksum_disable(krb5_context context,
2006 krb5_cksumtype type)
2008 struct checksum_type *ct = _find_checksum(type);
2009 if(ct == NULL) {
2010 if (context)
2011 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2012 N_("checksum type %d not supported", ""),
2013 type);
2014 return KRB5_PROG_SUMTYPE_NOSUPP;
2016 ct->flags |= F_DISABLED;
2017 return 0;
2020 /************************************************************
2022 ************************************************************/
2024 static krb5_error_code
2025 NULL_encrypt(krb5_context context,
2026 struct key_data *key,
2027 void *data,
2028 size_t len,
2029 krb5_boolean encryptp,
2030 int usage,
2031 void *ivec)
2033 return 0;
2036 static krb5_error_code
2037 evp_encrypt(krb5_context context,
2038 struct key_data *key,
2039 void *data,
2040 size_t len,
2041 krb5_boolean encryptp,
2042 int usage,
2043 void *ivec)
2045 struct evp_schedule *ctx = key->schedule->data;
2046 EVP_CIPHER_CTX *c;
2047 c = encryptp ? &ctx->ectx : &ctx->dctx;
2048 if (ivec == NULL) {
2049 /* alloca ? */
2050 size_t len = EVP_CIPHER_CTX_iv_length(c);
2051 void *loiv = malloc(len);
2052 if (loiv == NULL) {
2053 krb5_clear_error_message(context);
2054 return ENOMEM;
2056 memset(loiv, 0, len);
2057 EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
2058 free(loiv);
2059 } else
2060 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2061 EVP_Cipher(c, data, data, len);
2062 return 0;
2065 #ifdef WEAK_ENCTYPES
2066 static krb5_error_code
2067 evp_des_encrypt_null_ivec(krb5_context context,
2068 struct key_data *key,
2069 void *data,
2070 size_t len,
2071 krb5_boolean encryptp,
2072 int usage,
2073 void *ignore_ivec)
2075 struct evp_schedule *ctx = key->schedule->data;
2076 EVP_CIPHER_CTX *c;
2077 DES_cblock ivec;
2078 memset(&ivec, 0, sizeof(ivec));
2079 c = encryptp ? &ctx->ectx : &ctx->dctx;
2080 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2081 EVP_Cipher(c, data, data, len);
2082 return 0;
2085 static krb5_error_code
2086 evp_des_encrypt_key_ivec(krb5_context context,
2087 struct key_data *key,
2088 void *data,
2089 size_t len,
2090 krb5_boolean encryptp,
2091 int usage,
2092 void *ignore_ivec)
2094 struct evp_schedule *ctx = key->schedule->data;
2095 EVP_CIPHER_CTX *c;
2096 DES_cblock ivec;
2097 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2098 c = encryptp ? &ctx->ectx : &ctx->dctx;
2099 EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2100 EVP_Cipher(c, data, data, len);
2101 return 0;
2104 static krb5_error_code
2105 DES_CFB64_encrypt_null_ivec(krb5_context context,
2106 struct key_data *key,
2107 void *data,
2108 size_t len,
2109 krb5_boolean encryptp,
2110 int usage,
2111 void *ignore_ivec)
2113 DES_cblock ivec;
2114 int num = 0;
2115 DES_key_schedule *s = key->schedule->data;
2116 memset(&ivec, 0, sizeof(ivec));
2118 DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
2119 return 0;
2122 static krb5_error_code
2123 DES_PCBC_encrypt_key_ivec(krb5_context context,
2124 struct key_data *key,
2125 void *data,
2126 size_t len,
2127 krb5_boolean encryptp,
2128 int usage,
2129 void *ignore_ivec)
2131 DES_cblock ivec;
2132 DES_key_schedule *s = key->schedule->data;
2133 memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2135 DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
2136 return 0;
2138 #endif
2141 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
2143 * warning: not for small children
2146 static krb5_error_code
2147 ARCFOUR_subencrypt(krb5_context context,
2148 struct key_data *key,
2149 void *data,
2150 size_t len,
2151 unsigned usage,
2152 void *ivec)
2154 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2155 Checksum k1_c, k2_c, k3_c, cksum;
2156 struct key_data ke;
2157 krb5_keyblock kb;
2158 unsigned char t[4];
2159 RC4_KEY rc4_key;
2160 unsigned char *cdata = data;
2161 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2162 krb5_error_code ret;
2164 t[0] = (usage >> 0) & 0xFF;
2165 t[1] = (usage >> 8) & 0xFF;
2166 t[2] = (usage >> 16) & 0xFF;
2167 t[3] = (usage >> 24) & 0xFF;
2169 k1_c.checksum.length = sizeof(k1_c_data);
2170 k1_c.checksum.data = k1_c_data;
2172 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2173 if (ret)
2174 krb5_abortx(context, "hmac failed");
2176 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2178 k2_c.checksum.length = sizeof(k2_c_data);
2179 k2_c.checksum.data = k2_c_data;
2181 ke.key = &kb;
2182 kb.keyvalue = k2_c.checksum;
2184 cksum.checksum.length = 16;
2185 cksum.checksum.data = data;
2187 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2188 if (ret)
2189 krb5_abortx(context, "hmac failed");
2191 ke.key = &kb;
2192 kb.keyvalue = k1_c.checksum;
2194 k3_c.checksum.length = sizeof(k3_c_data);
2195 k3_c.checksum.data = k3_c_data;
2197 ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
2198 if (ret)
2199 krb5_abortx(context, "hmac failed");
2201 RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
2202 RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
2203 memset (k1_c_data, 0, sizeof(k1_c_data));
2204 memset (k2_c_data, 0, sizeof(k2_c_data));
2205 memset (k3_c_data, 0, sizeof(k3_c_data));
2206 return 0;
2209 static krb5_error_code
2210 ARCFOUR_subdecrypt(krb5_context context,
2211 struct key_data *key,
2212 void *data,
2213 size_t len,
2214 unsigned usage,
2215 void *ivec)
2217 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2218 Checksum k1_c, k2_c, k3_c, cksum;
2219 struct key_data ke;
2220 krb5_keyblock kb;
2221 unsigned char t[4];
2222 RC4_KEY rc4_key;
2223 unsigned char *cdata = data;
2224 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2225 unsigned char cksum_data[16];
2226 krb5_error_code ret;
2228 t[0] = (usage >> 0) & 0xFF;
2229 t[1] = (usage >> 8) & 0xFF;
2230 t[2] = (usage >> 16) & 0xFF;
2231 t[3] = (usage >> 24) & 0xFF;
2233 k1_c.checksum.length = sizeof(k1_c_data);
2234 k1_c.checksum.data = k1_c_data;
2236 ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2237 if (ret)
2238 krb5_abortx(context, "hmac failed");
2240 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2242 k2_c.checksum.length = sizeof(k2_c_data);
2243 k2_c.checksum.data = k2_c_data;
2245 ke.key = &kb;
2246 kb.keyvalue = k1_c.checksum;
2248 k3_c.checksum.length = sizeof(k3_c_data);
2249 k3_c.checksum.data = k3_c_data;
2251 ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
2252 if (ret)
2253 krb5_abortx(context, "hmac failed");
2255 RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
2256 RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
2258 ke.key = &kb;
2259 kb.keyvalue = k2_c.checksum;
2261 cksum.checksum.length = 16;
2262 cksum.checksum.data = cksum_data;
2264 ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2265 if (ret)
2266 krb5_abortx(context, "hmac failed");
2268 memset (k1_c_data, 0, sizeof(k1_c_data));
2269 memset (k2_c_data, 0, sizeof(k2_c_data));
2270 memset (k3_c_data, 0, sizeof(k3_c_data));
2272 if (memcmp (cksum.checksum.data, data, 16) != 0) {
2273 krb5_clear_error_message (context);
2274 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
2275 } else {
2276 return 0;
2281 * convert the usage numbers used in
2282 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2283 * draft-brezak-win2k-krb-rc4-hmac-04.txt
2286 static krb5_error_code
2287 usage2arcfour (krb5_context context, unsigned *usage)
2289 switch (*usage) {
2290 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2291 case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
2292 *usage = 8;
2293 return 0;
2294 case KRB5_KU_USAGE_SEAL : /* 22 */
2295 *usage = 13;
2296 return 0;
2297 case KRB5_KU_USAGE_SIGN : /* 23 */
2298 *usage = 15;
2299 return 0;
2300 case KRB5_KU_USAGE_SEQ: /* 24 */
2301 *usage = 0;
2302 return 0;
2303 default :
2304 return 0;
2308 static krb5_error_code
2309 ARCFOUR_encrypt(krb5_context context,
2310 struct key_data *key,
2311 void *data,
2312 size_t len,
2313 krb5_boolean encryptp,
2314 int usage,
2315 void *ivec)
2317 krb5_error_code ret;
2318 unsigned keyusage = usage;
2320 if((ret = usage2arcfour (context, &keyusage)) != 0)
2321 return ret;
2323 if (encryptp)
2324 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
2325 else
2326 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
2334 static krb5_error_code
2335 AES_PRF(krb5_context context,
2336 krb5_crypto crypto,
2337 const krb5_data *in,
2338 krb5_data *out)
2340 struct checksum_type *ct = crypto->et->checksum;
2341 krb5_error_code ret;
2342 Checksum result;
2343 krb5_keyblock *derived;
2345 result.cksumtype = ct->type;
2346 ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2347 if (ret) {
2348 krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
2349 return ret;
2352 ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2353 if (ret) {
2354 krb5_data_free(&result.checksum);
2355 return ret;
2358 if (result.checksum.length < crypto->et->blocksize)
2359 krb5_abortx(context, "internal prf error");
2361 derived = NULL;
2362 ret = krb5_derive_key(context, crypto->key.key,
2363 crypto->et->type, "prf", 3, &derived);
2364 if (ret)
2365 krb5_abortx(context, "krb5_derive_key");
2367 ret = krb5_data_alloc(out, crypto->et->blocksize);
2368 if (ret)
2369 krb5_abortx(context, "malloc failed");
2372 const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
2373 EVP_CIPHER_CTX ctx;
2374 /* XXX blksz 1 for cts, so we can't use that */
2375 EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
2376 EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
2377 EVP_Cipher(&ctx, out->data, result.checksum.data, 16);
2378 EVP_CIPHER_CTX_cleanup(&ctx);
2381 krb5_data_free(&result.checksum);
2382 krb5_free_keyblock(context, derived);
2384 return ret;
2388 * these should currently be in reverse preference order.
2389 * (only relevant for !F_PSEUDO) */
2391 static struct encryption_type enctype_null = {
2392 ETYPE_NULL,
2393 "null",
2397 &keytype_null,
2398 &checksum_none,
2399 NULL,
2400 F_DISABLED,
2401 NULL_encrypt,
2403 NULL
2405 static struct encryption_type enctype_arcfour_hmac_md5 = {
2406 ETYPE_ARCFOUR_HMAC_MD5,
2407 "arcfour-hmac-md5",
2411 &keytype_arcfour,
2412 &checksum_hmac_md5,
2413 NULL,
2414 F_SPECIAL,
2415 ARCFOUR_encrypt,
2417 NULL
2419 #ifdef DES3_OLD_ENCTYPE
2420 static struct encryption_type enctype_des3_cbc_md5 = {
2421 ETYPE_DES3_CBC_MD5,
2422 "des3-cbc-md5",
2426 &keytype_des3,
2427 &checksum_rsa_md5,
2428 &checksum_rsa_md5_des3,
2430 evp_encrypt,
2432 NULL
2434 #endif
2435 static struct encryption_type enctype_des3_cbc_sha1 = {
2436 ETYPE_DES3_CBC_SHA1,
2437 "des3-cbc-sha1",
2441 &keytype_des3_derived,
2442 &checksum_sha1,
2443 &checksum_hmac_sha1_des3,
2444 F_DERIVED,
2445 evp_encrypt,
2447 NULL
2449 #ifdef DES3_OLD_ENCTYPE
2450 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2451 ETYPE_OLD_DES3_CBC_SHA1,
2452 "old-des3-cbc-sha1",
2456 &keytype_des3,
2457 &checksum_sha1,
2458 &checksum_hmac_sha1_des3,
2460 evp_encrypt,
2462 NULL
2464 #endif
2465 static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2466 ETYPE_AES128_CTS_HMAC_SHA1_96,
2467 "aes128-cts-hmac-sha1-96",
2471 &keytype_aes128,
2472 &checksum_sha1,
2473 &checksum_hmac_sha1_aes128,
2474 F_DERIVED,
2475 evp_encrypt,
2477 AES_PRF
2479 static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2480 ETYPE_AES256_CTS_HMAC_SHA1_96,
2481 "aes256-cts-hmac-sha1-96",
2485 &keytype_aes256,
2486 &checksum_sha1,
2487 &checksum_hmac_sha1_aes256,
2488 F_DERIVED,
2489 evp_encrypt,
2491 AES_PRF
2493 static struct encryption_type enctype_des3_cbc_none = {
2494 ETYPE_DES3_CBC_NONE,
2495 "des3-cbc-none",
2499 &keytype_des3_derived,
2500 &checksum_none,
2501 NULL,
2502 F_PSEUDO,
2503 evp_encrypt,
2505 NULL
2507 #ifdef WEAK_ENCTYPES
2508 static struct encryption_type enctype_des_cbc_crc = {
2509 ETYPE_DES_CBC_CRC,
2510 "des-cbc-crc",
2514 &keytype_des,
2515 &checksum_crc32,
2516 NULL,
2517 F_DISABLED,
2518 evp_des_encrypt_key_ivec,
2520 NULL
2522 static struct encryption_type enctype_des_cbc_md4 = {
2523 ETYPE_DES_CBC_MD4,
2524 "des-cbc-md4",
2528 &keytype_des,
2529 &checksum_rsa_md4,
2530 &checksum_rsa_md4_des,
2531 F_DISABLED,
2532 evp_des_encrypt_null_ivec,
2534 NULL
2536 static struct encryption_type enctype_des_cbc_md5 = {
2537 ETYPE_DES_CBC_MD5,
2538 "des-cbc-md5",
2542 &keytype_des,
2543 &checksum_rsa_md5,
2544 &checksum_rsa_md5_des,
2545 F_DISABLED,
2546 evp_des_encrypt_null_ivec,
2548 NULL
2550 static struct encryption_type enctype_des_cbc_none = {
2551 ETYPE_DES_CBC_NONE,
2552 "des-cbc-none",
2556 &keytype_des,
2557 &checksum_none,
2558 NULL,
2559 F_PSEUDO|F_DISABLED,
2560 evp_des_encrypt_null_ivec,
2562 NULL
2564 static struct encryption_type enctype_des_cfb64_none = {
2565 ETYPE_DES_CFB64_NONE,
2566 "des-cfb64-none",
2570 &keytype_des_old,
2571 &checksum_none,
2572 NULL,
2573 F_PSEUDO|F_DISABLED,
2574 DES_CFB64_encrypt_null_ivec,
2576 NULL
2578 static struct encryption_type enctype_des_pcbc_none = {
2579 ETYPE_DES_PCBC_NONE,
2580 "des-pcbc-none",
2584 &keytype_des_old,
2585 &checksum_none,
2586 NULL,
2587 F_PSEUDO|F_DISABLED,
2588 DES_PCBC_encrypt_key_ivec,
2590 NULL
2592 #endif /* WEAK_ENCTYPES */
2594 static struct encryption_type *etypes[] = {
2595 &enctype_aes256_cts_hmac_sha1,
2596 &enctype_aes128_cts_hmac_sha1,
2597 &enctype_des3_cbc_sha1,
2598 &enctype_des3_cbc_none, /* used by the gss-api mech */
2599 &enctype_arcfour_hmac_md5,
2600 #ifdef DES3_OLD_ENCTYPE
2601 &enctype_des3_cbc_md5,
2602 &enctype_old_des3_cbc_sha1,
2603 #endif
2604 #ifdef WEAK_ENCTYPES
2605 &enctype_des_cbc_crc,
2606 &enctype_des_cbc_md4,
2607 &enctype_des_cbc_md5,
2608 &enctype_des_cbc_none,
2609 &enctype_des_cfb64_none,
2610 &enctype_des_pcbc_none,
2611 #endif
2612 &enctype_null
2615 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2618 static struct encryption_type *
2619 _find_enctype(krb5_enctype type)
2621 int i;
2622 for(i = 0; i < num_etypes; i++)
2623 if(etypes[i]->type == type)
2624 return etypes[i];
2625 return NULL;
2629 krb5_error_code KRB5_LIB_FUNCTION
2630 krb5_enctype_to_string(krb5_context context,
2631 krb5_enctype etype,
2632 char **string)
2634 struct encryption_type *e;
2635 e = _find_enctype(etype);
2636 if(e == NULL) {
2637 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2638 N_("encryption type %d not supported", ""),
2639 etype);
2640 *string = NULL;
2641 return KRB5_PROG_ETYPE_NOSUPP;
2643 *string = strdup(e->name);
2644 if(*string == NULL) {
2645 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2646 return ENOMEM;
2648 return 0;
2651 krb5_error_code KRB5_LIB_FUNCTION
2652 krb5_string_to_enctype(krb5_context context,
2653 const char *string,
2654 krb5_enctype *etype)
2656 int i;
2657 for(i = 0; i < num_etypes; i++)
2658 if(strcasecmp(etypes[i]->name, string) == 0){
2659 *etype = etypes[i]->type;
2660 return 0;
2662 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2663 N_("encryption type %s not supported", ""),
2664 string);
2665 return KRB5_PROG_ETYPE_NOSUPP;
2668 krb5_error_code KRB5_LIB_FUNCTION
2669 krb5_enctype_to_keytype(krb5_context context,
2670 krb5_enctype etype,
2671 krb5_keytype *keytype)
2673 struct encryption_type *e = _find_enctype(etype);
2674 if(e == NULL) {
2675 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2676 N_("encryption type %d not supported", ""),
2677 etype);
2678 return KRB5_PROG_ETYPE_NOSUPP;
2680 *keytype = e->keytype->type; /* XXX */
2681 return 0;
2684 krb5_error_code KRB5_LIB_FUNCTION
2685 krb5_enctype_valid(krb5_context context,
2686 krb5_enctype etype)
2688 struct encryption_type *e = _find_enctype(etype);
2689 if(e == NULL) {
2690 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2691 N_("encryption type %d not supported", ""),
2692 etype);
2693 return KRB5_PROG_ETYPE_NOSUPP;
2695 if (e->flags & F_DISABLED) {
2696 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2697 N_("encryption type %s is disabled", ""),
2698 e->name);
2699 return KRB5_PROG_ETYPE_NOSUPP;
2701 return 0;
2705 * Return the coresponding encryption type for a checksum type.
2707 * @param context Kerberos context
2708 * @param ctype The checksum type to get the result enctype for
2709 * @param etype The returned encryption, when the matching etype is
2710 * not found, etype is set to ETYPE_NULL.
2712 * @return Return an error code for an failure or 0 on success.
2713 * @ingroup krb5_crypto
2717 krb5_error_code KRB5_LIB_FUNCTION
2718 krb5_cksumtype_to_enctype(krb5_context context,
2719 krb5_cksumtype ctype,
2720 krb5_enctype *etype)
2722 int i;
2724 *etype = ETYPE_NULL;
2726 for(i = 0; i < num_etypes; i++) {
2727 if(etypes[i]->keyed_checksum &&
2728 etypes[i]->keyed_checksum->type == ctype)
2730 *etype = etypes[i]->type;
2731 return 0;
2735 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2736 N_("checksum type %d not supported", ""),
2737 (int)ctype);
2738 return KRB5_PROG_SUMTYPE_NOSUPP;
2742 krb5_error_code KRB5_LIB_FUNCTION
2743 krb5_cksumtype_valid(krb5_context context,
2744 krb5_cksumtype ctype)
2746 struct checksum_type *c = _find_checksum(ctype);
2747 if (c == NULL) {
2748 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2749 N_("checksum type %d not supported", ""),
2750 ctype);
2751 return KRB5_PROG_SUMTYPE_NOSUPP;
2753 if (c->flags & F_DISABLED) {
2754 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2755 N_("checksum type %s is disabled", ""),
2756 c->name);
2757 return KRB5_PROG_SUMTYPE_NOSUPP;
2759 return 0;
2763 static krb5_boolean
2764 derived_crypto(krb5_context context,
2765 krb5_crypto crypto)
2767 return (crypto->et->flags & F_DERIVED) != 0;
2770 static krb5_boolean
2771 special_crypto(krb5_context context,
2772 krb5_crypto crypto)
2774 return (crypto->et->flags & F_SPECIAL) != 0;
2777 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2778 #define CHECKSUMTYPE(C) ((C)->type)
2780 static krb5_error_code
2781 encrypt_internal_derived(krb5_context context,
2782 krb5_crypto crypto,
2783 unsigned usage,
2784 const void *data,
2785 size_t len,
2786 krb5_data *result,
2787 void *ivec)
2789 size_t sz, block_sz, checksum_sz, total_sz;
2790 Checksum cksum;
2791 unsigned char *p, *q;
2792 krb5_error_code ret;
2793 struct key_data *dkey;
2794 const struct encryption_type *et = crypto->et;
2796 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2798 sz = et->confoundersize + len;
2799 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2800 total_sz = block_sz + checksum_sz;
2801 p = calloc(1, total_sz);
2802 if(p == NULL) {
2803 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2804 return ENOMEM;
2807 q = p;
2808 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2809 q += et->confoundersize;
2810 memcpy(q, data, len);
2812 ret = create_checksum(context,
2813 et->keyed_checksum,
2814 crypto,
2815 INTEGRITY_USAGE(usage),
2817 block_sz,
2818 &cksum);
2819 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2820 free_Checksum (&cksum);
2821 krb5_clear_error_message (context);
2822 ret = KRB5_CRYPTO_INTERNAL;
2824 if(ret)
2825 goto fail;
2826 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2827 free_Checksum (&cksum);
2828 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2829 if(ret)
2830 goto fail;
2831 ret = _key_schedule(context, dkey);
2832 if(ret)
2833 goto fail;
2834 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2835 if (ret)
2836 goto fail;
2837 result->data = p;
2838 result->length = total_sz;
2839 return 0;
2840 fail:
2841 memset(p, 0, total_sz);
2842 free(p);
2843 return ret;
2847 static krb5_error_code
2848 encrypt_internal(krb5_context context,
2849 krb5_crypto crypto,
2850 const void *data,
2851 size_t len,
2852 krb5_data *result,
2853 void *ivec)
2855 size_t sz, block_sz, checksum_sz;
2856 Checksum cksum;
2857 unsigned char *p, *q;
2858 krb5_error_code ret;
2859 const struct encryption_type *et = crypto->et;
2861 checksum_sz = CHECKSUMSIZE(et->checksum);
2863 sz = et->confoundersize + checksum_sz + len;
2864 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2865 p = calloc(1, block_sz);
2866 if(p == NULL) {
2867 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2868 return ENOMEM;
2871 q = p;
2872 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2873 q += et->confoundersize;
2874 memset(q, 0, checksum_sz);
2875 q += checksum_sz;
2876 memcpy(q, data, len);
2878 ret = create_checksum(context,
2879 et->checksum,
2880 crypto,
2883 block_sz,
2884 &cksum);
2885 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2886 krb5_clear_error_message (context);
2887 free_Checksum(&cksum);
2888 ret = KRB5_CRYPTO_INTERNAL;
2890 if(ret)
2891 goto fail;
2892 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2893 free_Checksum(&cksum);
2894 ret = _key_schedule(context, &crypto->key);
2895 if(ret)
2896 goto fail;
2897 ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
2898 if (ret) {
2899 memset(p, 0, block_sz);
2900 free(p);
2901 return ret;
2903 result->data = p;
2904 result->length = block_sz;
2905 return 0;
2906 fail:
2907 memset(p, 0, block_sz);
2908 free(p);
2909 return ret;
2912 static krb5_error_code
2913 encrypt_internal_special(krb5_context context,
2914 krb5_crypto crypto,
2915 int usage,
2916 const void *data,
2917 size_t len,
2918 krb5_data *result,
2919 void *ivec)
2921 struct encryption_type *et = crypto->et;
2922 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2923 size_t sz = len + cksum_sz + et->confoundersize;
2924 char *tmp, *p;
2925 krb5_error_code ret;
2927 tmp = malloc (sz);
2928 if (tmp == NULL) {
2929 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2930 return ENOMEM;
2932 p = tmp;
2933 memset (p, 0, cksum_sz);
2934 p += cksum_sz;
2935 krb5_generate_random_block(p, et->confoundersize);
2936 p += et->confoundersize;
2937 memcpy (p, data, len);
2938 ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
2939 if (ret) {
2940 memset(tmp, 0, sz);
2941 free(tmp);
2942 return ret;
2944 result->data = tmp;
2945 result->length = sz;
2946 return 0;
2949 static krb5_error_code
2950 decrypt_internal_derived(krb5_context context,
2951 krb5_crypto crypto,
2952 unsigned usage,
2953 void *data,
2954 size_t len,
2955 krb5_data *result,
2956 void *ivec)
2958 size_t checksum_sz;
2959 Checksum cksum;
2960 unsigned char *p;
2961 krb5_error_code ret;
2962 struct key_data *dkey;
2963 struct encryption_type *et = crypto->et;
2964 unsigned long l;
2966 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2967 if (len < checksum_sz + et->confoundersize) {
2968 krb5_set_error_message(context, KRB5_BAD_MSIZE,
2969 N_("Encrypted data shorter then "
2970 "checksum + confunder", ""));
2971 return KRB5_BAD_MSIZE;
2974 if (((len - checksum_sz) % et->padsize) != 0) {
2975 krb5_clear_error_message(context);
2976 return KRB5_BAD_MSIZE;
2979 p = malloc(len);
2980 if(len != 0 && p == NULL) {
2981 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2982 return ENOMEM;
2984 memcpy(p, data, len);
2986 len -= checksum_sz;
2988 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2989 if(ret) {
2990 free(p);
2991 return ret;
2993 ret = _key_schedule(context, dkey);
2994 if(ret) {
2995 free(p);
2996 return ret;
2998 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
2999 if (ret) {
3000 free(p);
3001 return ret;
3004 cksum.checksum.data = p + len;
3005 cksum.checksum.length = checksum_sz;
3006 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3008 ret = verify_checksum(context,
3009 crypto,
3010 INTEGRITY_USAGE(usage),
3012 len,
3013 &cksum);
3014 if(ret) {
3015 free(p);
3016 return ret;
3018 l = len - et->confoundersize;
3019 memmove(p, p + et->confoundersize, l);
3020 result->data = realloc(p, l);
3021 if(result->data == NULL && l != 0) {
3022 free(p);
3023 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3024 return ENOMEM;
3026 result->length = l;
3027 return 0;
3030 static krb5_error_code
3031 decrypt_internal(krb5_context context,
3032 krb5_crypto crypto,
3033 void *data,
3034 size_t len,
3035 krb5_data *result,
3036 void *ivec)
3038 krb5_error_code ret;
3039 unsigned char *p;
3040 Checksum cksum;
3041 size_t checksum_sz, l;
3042 struct encryption_type *et = crypto->et;
3044 if ((len % et->padsize) != 0) {
3045 krb5_clear_error_message(context);
3046 return KRB5_BAD_MSIZE;
3049 checksum_sz = CHECKSUMSIZE(et->checksum);
3050 p = malloc(len);
3051 if(len != 0 && p == NULL) {
3052 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3053 return ENOMEM;
3055 memcpy(p, data, len);
3057 ret = _key_schedule(context, &crypto->key);
3058 if(ret) {
3059 free(p);
3060 return ret;
3062 ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
3063 if (ret) {
3064 free(p);
3065 return ret;
3067 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
3068 if(ret) {
3069 free(p);
3070 return ret;
3072 memset(p + et->confoundersize, 0, checksum_sz);
3073 cksum.cksumtype = CHECKSUMTYPE(et->checksum);
3074 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
3075 free_Checksum(&cksum);
3076 if(ret) {
3077 free(p);
3078 return ret;
3080 l = len - et->confoundersize - checksum_sz;
3081 memmove(p, p + et->confoundersize + checksum_sz, l);
3082 result->data = realloc(p, l);
3083 if(result->data == NULL && l != 0) {
3084 free(p);
3085 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3086 return ENOMEM;
3088 result->length = l;
3089 return 0;
3092 static krb5_error_code
3093 decrypt_internal_special(krb5_context context,
3094 krb5_crypto crypto,
3095 int usage,
3096 void *data,
3097 size_t len,
3098 krb5_data *result,
3099 void *ivec)
3101 struct encryption_type *et = crypto->et;
3102 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3103 size_t sz = len - cksum_sz - et->confoundersize;
3104 unsigned char *p;
3105 krb5_error_code ret;
3107 if ((len % et->padsize) != 0) {
3108 krb5_clear_error_message(context);
3109 return KRB5_BAD_MSIZE;
3112 p = malloc (len);
3113 if (p == NULL) {
3114 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3115 return ENOMEM;
3117 memcpy(p, data, len);
3119 ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
3120 if (ret) {
3121 free(p);
3122 return ret;
3125 memmove (p, p + cksum_sz + et->confoundersize, sz);
3126 result->data = realloc(p, sz);
3127 if(result->data == NULL && sz != 0) {
3128 free(p);
3129 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3130 return ENOMEM;
3132 result->length = sz;
3133 return 0;
3136 static krb5_crypto_iov *
3137 find_iv(krb5_crypto_iov *data, int num_data, int type)
3139 int i;
3140 for (i = 0; i < num_data; i++)
3141 if (data[i].flags == type)
3142 return &data[i];
3143 return NULL;
3147 * Inline encrypt a kerberos message
3149 * @param context Kerberos context
3150 * @param crypto Kerberos crypto context
3151 * @param usage Key usage for this buffer
3152 * @param data array of buffers to process
3153 * @param num_data length of array
3154 * @param ivec initial cbc/cts vector
3156 * @return Return an error code or 0.
3157 * @ingroup krb5_crypto
3159 * Kerberos encrypted data look like this:
3161 * 1. KRB5_CRYPTO_TYPE_HEADER
3162 * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
3163 * any order, however the receiver have to aware of the
3164 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used headers and
3165 * trailers.
3166 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
3167 * 4. KRB5_CRYPTO_TYPE_TRAILER
3170 krb5_error_code KRB5_LIB_FUNCTION
3171 krb5_encrypt_iov_ivec(krb5_context context,
3172 krb5_crypto crypto,
3173 unsigned usage,
3174 krb5_crypto_iov *data,
3175 int num_data,
3176 void *ivec)
3178 size_t headersz, trailersz, len;
3179 int i;
3180 size_t sz, block_sz, pad_sz;
3181 Checksum cksum;
3182 unsigned char *p, *q;
3183 krb5_error_code ret;
3184 struct key_data *dkey;
3185 const struct encryption_type *et = crypto->et;
3186 krb5_crypto_iov *tiv, *piv, *hiv;
3188 if (num_data < 0) {
3189 krb5_clear_error_message(context);
3190 return KRB5_CRYPTO_INTERNAL;
3193 if(!derived_crypto(context, crypto)) {
3194 krb5_clear_error_message(context);
3195 return KRB5_CRYPTO_INTERNAL;
3198 headersz = et->confoundersize;
3199 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3201 for (len = 0, i = 0; i < num_data; i++) {
3202 if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
3203 data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
3204 len += data[i].data.length;
3208 sz = headersz + len;
3209 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3211 pad_sz = block_sz - sz;
3212 trailersz += pad_sz;
3214 /* header */
3216 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3217 if (hiv == NULL || hiv->data.length != headersz)
3218 return KRB5_BAD_MSIZE;
3220 krb5_generate_random_block(hiv->data.data, hiv->data.length);
3222 /* padding */
3224 piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
3225 /* its ok to have no TYPE_PADDING if there is no padding */
3226 if (piv == NULL && pad_sz != 0)
3227 return KRB5_BAD_MSIZE;
3228 if (piv) {
3229 if (piv->data.length < pad_sz)
3230 return KRB5_BAD_MSIZE;
3231 piv->data.length = pad_sz;
3235 /* trailer */
3237 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3238 if (tiv == NULL || tiv->data.length != trailersz)
3239 return KRB5_BAD_MSIZE;
3243 * XXX replace with EVP_Sign? at least make create_checksum an iov
3244 * function.
3245 * XXX CTS EVP is broken, can't handle multi buffers :(
3248 len = hiv->data.length;
3249 for (i = 0; i < num_data; i++) {
3250 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3251 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3252 continue;
3253 len += data[i].data.length;
3256 p = q = malloc(len);
3258 memcpy(q, hiv->data.data, hiv->data.length);
3259 q += hiv->data.length;
3260 for (i = 0; i < num_data; i++) {
3261 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3262 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3263 continue;
3264 memcpy(q, data[i].data.data, data[i].data.length);
3265 q += data[i].data.length;
3268 ret = create_checksum(context,
3269 et->keyed_checksum,
3270 crypto,
3271 INTEGRITY_USAGE(usage),
3273 len,
3274 &cksum);
3275 free(p);
3276 if(ret == 0 && cksum.checksum.length != trailersz) {
3277 free_Checksum (&cksum);
3278 krb5_clear_error_message (context);
3279 ret = KRB5_CRYPTO_INTERNAL;
3281 if(ret)
3282 return ret;
3284 /* save cksum at end */
3285 memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
3286 free_Checksum (&cksum);
3288 /* now encrypt data */
3290 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3291 if(ret)
3292 return ret;
3293 ret = _key_schedule(context, dkey);
3294 if(ret)
3295 return ret;
3297 /* XXX replace with EVP_Cipher */
3299 len = hiv->data.length;
3300 for (i = 0; i < num_data; i++) {
3301 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3302 data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3303 continue;
3304 len += data[i].data.length;
3307 p = q = malloc(len);
3308 if(p == NULL)
3309 return ENOMEM;
3311 memcpy(q, hiv->data.data, hiv->data.length);
3312 q += hiv->data.length;
3313 for (i = 0; i < num_data; i++) {
3314 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3315 data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3316 continue;
3317 memcpy(q, data[i].data.data, data[i].data.length);
3318 q += data[i].data.length;
3321 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3322 if(ret) {
3323 free(p);
3324 return ret;
3326 ret = _key_schedule(context, dkey);
3327 if(ret) {
3328 free(p);
3329 return ret;
3332 ret = (*et->encrypt)(context, dkey, p, len, 1, usage, ivec);
3333 if (ret) {
3334 free(p);
3335 return ret;
3338 /* now copy data back to buffers */
3339 q = p;
3340 memcpy(hiv->data.data, q, hiv->data.length);
3341 q += hiv->data.length;
3343 for (i = 0; i < num_data; i++) {
3344 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3345 data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
3346 continue;
3347 memcpy(data[i].data.data, q, data[i].data.length);
3348 q += data[i].data.length;
3350 free(p);
3352 return ret;
3356 * Inline decrypt a Kerberos message.
3358 * @param context Kerberos context
3359 * @param crypto Kerberos crypto context
3360 * @param usage Key usage for this buffer
3361 * @param data array of buffers to process
3362 * @param num_data length of array
3363 * @param ivec initial cbc/cts vector
3365 * @return Return an error code or 0.
3366 * @ingroup krb5_crypto
3368 * 1. KRB5_CRYPTO_TYPE_HEADER
3369 * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
3370 * any order, however the receiver have to aware of the
3371 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
3372 * protocol headers and trailers. The output data will be of same
3373 * size as the input data or shorter.
3376 krb5_error_code KRB5_LIB_FUNCTION
3377 krb5_decrypt_iov_ivec(krb5_context context,
3378 krb5_crypto crypto,
3379 unsigned usage,
3380 krb5_crypto_iov *data,
3381 unsigned int num_data,
3382 void *ivec)
3384 unsigned int i;
3385 size_t headersz, trailersz, len;
3386 size_t sz, block_sz, pad_sz;
3387 Checksum cksum;
3388 unsigned char *p, *q;
3389 krb5_error_code ret;
3390 struct key_data *dkey;
3391 struct encryption_type *et = crypto->et;
3392 krb5_crypto_iov *tiv, *hiv;
3394 if (num_data < 0) {
3395 krb5_clear_error_message(context);
3396 return KRB5_CRYPTO_INTERNAL;
3399 if(!derived_crypto(context, crypto)) {
3400 krb5_clear_error_message(context);
3401 return KRB5_CRYPTO_INTERNAL;
3404 headersz = et->confoundersize;
3405 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3407 for (len = 0, i = 0; i < num_data; i++)
3408 if (data[i].flags == KRB5_CRYPTO_TYPE_DATA)
3409 len += data[i].data.length;
3411 sz = headersz + len;
3412 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3414 pad_sz = block_sz - sz;
3415 trailersz += pad_sz;
3417 /* header */
3419 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3420 if (hiv == NULL || hiv->data.length < headersz)
3421 return KRB5_BAD_MSIZE;
3422 hiv->data.length = headersz;
3424 /* trailer */
3426 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3427 if (tiv == NULL || tiv->data.length < trailersz)
3428 return KRB5_BAD_MSIZE;
3429 tiv->data.length = trailersz;
3431 /* body */
3433 /* XXX replace with EVP_Cipher */
3435 for (len = 0, i = 0; i < num_data; i++) {
3436 if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
3437 data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3438 continue;
3439 len += data[i].data.length;
3442 p = q = malloc(len);
3443 if (p == NULL)
3444 return ENOMEM;
3446 memcpy(q, hiv->data.data, hiv->data.length);
3447 q += hiv->data.length;
3448 for (i = 0; i < num_data; i++) {
3449 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3450 continue;
3451 memcpy(q, data[i].data.data, data[i].data.length);
3452 q += data[i].data.length;
3455 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3456 if(ret) {
3457 free(p);
3458 return ret;
3460 ret = _key_schedule(context, dkey);
3461 if(ret) {
3462 free(p);
3463 return ret;
3466 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3467 if (ret) {
3468 free(p);
3469 return ret;
3472 /* XXX now copy data back to buffers */
3473 q = p;
3474 memcpy(hiv->data.data, q, hiv->data.length);
3475 q += hiv->data.length;
3476 len -= hiv->data.length;
3478 for (i = 0; i < num_data; i++) {
3479 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3480 continue;
3481 if (len < data[i].data.length)
3482 data[i].data.length = len;
3483 memcpy(data[i].data.data, q, data[i].data.length);
3484 q += data[i].data.length;
3485 len -= data[i].data.length;
3487 free(p);
3488 if (len)
3489 krb5_abortx(context, "data still in the buffer");
3491 len = hiv->data.length;
3492 for (i = 0; i < num_data; i++) {
3493 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3494 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3495 continue;
3496 len += data[i].data.length;
3499 p = q = malloc(len);
3501 memcpy(q, hiv->data.data, hiv->data.length);
3502 q += hiv->data.length;
3503 for (i = 0; i < num_data; i++) {
3504 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3505 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3506 continue;
3507 memcpy(q, data[i].data.data, data[i].data.length);
3508 q += data[i].data.length;
3511 cksum.checksum.data = tiv->data.data;
3512 cksum.checksum.length = tiv->data.length;
3513 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3515 ret = verify_checksum(context,
3516 crypto,
3517 INTEGRITY_USAGE(usage),
3519 len,
3520 &cksum);
3521 free(p);
3522 return ret;
3526 * Create a Kerberos message checksum.
3528 * @param context Kerberos context
3529 * @param crypto Kerberos crypto context
3530 * @param usage Key usage for this buffer
3531 * @param data array of buffers to process
3532 * @param num_data length of array
3533 * @param result output data
3535 * @return Return an error code or 0.
3536 * @ingroup krb5_crypto
3539 krb5_error_code KRB5_LIB_FUNCTION
3540 krb5_create_checksum_iov(krb5_context context,
3541 krb5_crypto crypto,
3542 unsigned usage,
3543 krb5_crypto_iov *data,
3544 unsigned int num_data,
3545 krb5_cksumtype *type)
3547 Checksum cksum;
3548 krb5_crypto_iov *civ;
3549 krb5_error_code ret;
3550 int i;
3551 size_t len;
3552 char *p, *q;
3554 if (num_data < 0) {
3555 krb5_clear_error_message(context);
3556 return KRB5_CRYPTO_INTERNAL;
3559 if(!derived_crypto(context, crypto)) {
3560 krb5_clear_error_message(context);
3561 return KRB5_CRYPTO_INTERNAL;
3564 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3565 if (civ == NULL)
3566 return KRB5_BAD_MSIZE;
3568 len = 0;
3569 for (i = 0; i < num_data; i++) {
3570 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3571 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3572 continue;
3573 len += data[i].data.length;
3576 p = q = malloc(len);
3578 for (i = 0; i < num_data; i++) {
3579 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3580 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3581 continue;
3582 memcpy(q, data[i].data.data, data[i].data.length);
3583 q += data[i].data.length;
3586 ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
3587 free(p);
3588 if (ret)
3589 return ret;
3591 if (type)
3592 *type = cksum.cksumtype;
3594 if (cksum.checksum.length > civ->data.length) {
3595 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3596 N_("Checksum larger then input buffer", ""));
3597 free_Checksum(&cksum);
3598 return KRB5_BAD_MSIZE;
3601 civ->data.length = cksum.checksum.length;
3602 memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
3603 free_Checksum(&cksum);
3605 return 0;
3609 size_t KRB5_LIB_FUNCTION
3610 krb5_crypto_length(krb5_context context,
3611 krb5_crypto crypto,
3612 int type)
3614 if (!derived_crypto(context, crypto))
3615 return (size_t)-1;
3616 switch(type) {
3617 case KRB5_CRYPTO_TYPE_EMPTY:
3618 return 0;
3619 case KRB5_CRYPTO_TYPE_HEADER:
3620 return crypto->et->blocksize;
3621 case KRB5_CRYPTO_TYPE_PADDING:
3622 if (crypto->et->padsize > 1)
3623 return crypto->et->padsize;
3624 return 0;
3625 case KRB5_CRYPTO_TYPE_TRAILER:
3626 return CHECKSUMSIZE(crypto->et->keyed_checksum);
3627 case KRB5_CRYPTO_TYPE_CHECKSUM:
3628 if (crypto->et->keyed_checksum)
3629 return CHECKSUMSIZE(crypto->et->keyed_checksum);
3630 return CHECKSUMSIZE(crypto->et->checksum);
3632 return (size_t)-1;
3635 krb5_error_code KRB5_LIB_FUNCTION
3636 krb5_encrypt_ivec(krb5_context context,
3637 krb5_crypto crypto,
3638 unsigned usage,
3639 const void *data,
3640 size_t len,
3641 krb5_data *result,
3642 void *ivec)
3644 if(derived_crypto(context, crypto))
3645 return encrypt_internal_derived(context, crypto, usage,
3646 data, len, result, ivec);
3647 else if (special_crypto(context, crypto))
3648 return encrypt_internal_special (context, crypto, usage,
3649 data, len, result, ivec);
3650 else
3651 return encrypt_internal(context, crypto, data, len, result, ivec);
3654 krb5_error_code KRB5_LIB_FUNCTION
3655 krb5_encrypt(krb5_context context,
3656 krb5_crypto crypto,
3657 unsigned usage,
3658 const void *data,
3659 size_t len,
3660 krb5_data *result)
3662 return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
3665 krb5_error_code KRB5_LIB_FUNCTION
3666 krb5_encrypt_EncryptedData(krb5_context context,
3667 krb5_crypto crypto,
3668 unsigned usage,
3669 void *data,
3670 size_t len,
3671 int kvno,
3672 EncryptedData *result)
3674 result->etype = CRYPTO_ETYPE(crypto);
3675 if(kvno){
3676 ALLOC(result->kvno, 1);
3677 *result->kvno = kvno;
3678 }else
3679 result->kvno = NULL;
3680 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
3683 krb5_error_code KRB5_LIB_FUNCTION
3684 krb5_decrypt_ivec(krb5_context context,
3685 krb5_crypto crypto,
3686 unsigned usage,
3687 void *data,
3688 size_t len,
3689 krb5_data *result,
3690 void *ivec)
3692 if(derived_crypto(context, crypto))
3693 return decrypt_internal_derived(context, crypto, usage,
3694 data, len, result, ivec);
3695 else if (special_crypto (context, crypto))
3696 return decrypt_internal_special(context, crypto, usage,
3697 data, len, result, ivec);
3698 else
3699 return decrypt_internal(context, crypto, data, len, result, ivec);
3702 krb5_error_code KRB5_LIB_FUNCTION
3703 krb5_decrypt(krb5_context context,
3704 krb5_crypto crypto,
3705 unsigned usage,
3706 void *data,
3707 size_t len,
3708 krb5_data *result)
3710 return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
3711 NULL);
3714 krb5_error_code KRB5_LIB_FUNCTION
3715 krb5_decrypt_EncryptedData(krb5_context context,
3716 krb5_crypto crypto,
3717 unsigned usage,
3718 const EncryptedData *e,
3719 krb5_data *result)
3721 return krb5_decrypt(context, crypto, usage,
3722 e->cipher.data, e->cipher.length, result);
3725 /************************************************************
3727 ************************************************************/
3729 #define ENTROPY_NEEDED 128
3731 static int
3732 seed_something(void)
3734 char buf[1024], seedfile[256];
3736 /* If there is a seed file, load it. But such a file cannot be trusted,
3737 so use 0 for the entropy estimate */
3738 if (RAND_file_name(seedfile, sizeof(seedfile))) {
3739 int fd;
3740 fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
3741 if (fd >= 0) {
3742 ssize_t ret;
3743 rk_cloexec(fd);
3744 ret = read(fd, buf, sizeof(buf));
3745 if (ret > 0)
3746 RAND_add(buf, ret, 0.0);
3747 close(fd);
3748 } else
3749 seedfile[0] = '\0';
3750 } else
3751 seedfile[0] = '\0';
3753 /* Calling RAND_status() will try to use /dev/urandom if it exists so
3754 we do not have to deal with it. */
3755 if (RAND_status() != 1) {
3756 krb5_context context;
3757 const char *p;
3759 /* Try using egd */
3760 if (!krb5_init_context(&context)) {
3761 p = krb5_config_get_string(context, NULL, "libdefaults",
3762 "egd_socket", NULL);
3763 if (p != NULL)
3764 RAND_egd_bytes(p, ENTROPY_NEEDED);
3765 krb5_free_context(context);
3769 if (RAND_status() == 1) {
3770 /* Update the seed file */
3771 if (seedfile[0])
3772 RAND_write_file(seedfile);
3774 return 0;
3775 } else
3776 return -1;
3779 void KRB5_LIB_FUNCTION
3780 krb5_generate_random_block(void *buf, size_t len)
3782 static int rng_initialized = 0;
3784 HEIMDAL_MUTEX_lock(&crypto_mutex);
3785 if (!rng_initialized) {
3786 if (seed_something())
3787 krb5_abortx(NULL, "Fatal: could not seed the "
3788 "random number generator");
3790 rng_initialized = 1;
3792 HEIMDAL_MUTEX_unlock(&crypto_mutex);
3793 if (RAND_bytes(buf, len) != 1)
3794 krb5_abortx(NULL, "Failed to generate random block");
3797 static krb5_error_code
3798 derive_key(krb5_context context,
3799 struct encryption_type *et,
3800 struct key_data *key,
3801 const void *constant,
3802 size_t len)
3804 unsigned char *k = NULL;
3805 unsigned int nblocks = 0, i;
3806 krb5_error_code ret = 0;
3807 struct key_type *kt = et->keytype;
3809 ret = _key_schedule(context, key);
3810 if(ret)
3811 return ret;
3812 if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
3813 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
3814 k = malloc(nblocks * et->blocksize);
3815 if(k == NULL) {
3816 ret = ENOMEM;
3817 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3818 goto out;
3820 ret = _krb5_n_fold(constant, len, k, et->blocksize);
3821 if (ret) {
3822 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3823 goto out;
3826 for(i = 0; i < nblocks; i++) {
3827 if(i > 0)
3828 memcpy(k + i * et->blocksize,
3829 k + (i - 1) * et->blocksize,
3830 et->blocksize);
3831 (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
3832 1, 0, NULL);
3834 } else {
3835 /* this case is probably broken, but won't be run anyway */
3836 void *c = malloc(len);
3837 size_t res_len = (kt->bits + 7) / 8;
3839 if(len != 0 && c == NULL) {
3840 ret = ENOMEM;
3841 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3842 goto out;
3844 memcpy(c, constant, len);
3845 (*et->encrypt)(context, key, c, len, 1, 0, NULL);
3846 k = malloc(res_len);
3847 if(res_len != 0 && k == NULL) {
3848 free(c);
3849 ret = ENOMEM;
3850 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3851 goto out;
3853 ret = _krb5_n_fold(c, len, k, res_len);
3854 free(c);
3855 if (ret) {
3856 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3857 goto out;
3861 /* XXX keytype dependent post-processing */
3862 switch(kt->type) {
3863 case KEYTYPE_DES3:
3864 DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
3865 break;
3866 case KEYTYPE_AES128:
3867 case KEYTYPE_AES256:
3868 memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
3869 break;
3870 default:
3871 ret = KRB5_CRYPTO_INTERNAL;
3872 krb5_set_error_message(context, ret,
3873 N_("derive_key() called with unknown keytype (%u)", ""),
3874 kt->type);
3875 break;
3877 out:
3878 if (key->schedule) {
3879 free_key_schedule(context, key, et);
3880 key->schedule = NULL;
3882 if (k) {
3883 memset(k, 0, nblocks * et->blocksize);
3884 free(k);
3886 return ret;
3889 static struct key_data *
3890 _new_derived_key(krb5_crypto crypto, unsigned usage)
3892 struct key_usage *d = crypto->key_usage;
3893 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
3894 if(d == NULL)
3895 return NULL;
3896 crypto->key_usage = d;
3897 d += crypto->num_key_usage++;
3898 memset(d, 0, sizeof(*d));
3899 d->usage = usage;
3900 return &d->key;
3903 krb5_error_code KRB5_LIB_FUNCTION
3904 krb5_derive_key(krb5_context context,
3905 const krb5_keyblock *key,
3906 krb5_enctype etype,
3907 const void *constant,
3908 size_t constant_len,
3909 krb5_keyblock **derived_key)
3911 krb5_error_code ret;
3912 struct encryption_type *et;
3913 struct key_data d;
3915 *derived_key = NULL;
3917 et = _find_enctype (etype);
3918 if (et == NULL) {
3919 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3920 N_("encryption type %d not supported", ""),
3921 etype);
3922 return KRB5_PROG_ETYPE_NOSUPP;
3925 ret = krb5_copy_keyblock(context, key, &d.key);
3926 if (ret)
3927 return ret;
3929 d.schedule = NULL;
3930 ret = derive_key(context, et, &d, constant, constant_len);
3931 if (ret == 0)
3932 ret = krb5_copy_keyblock(context, d.key, derived_key);
3933 free_key_data(context, &d, et);
3934 return ret;
3937 static krb5_error_code
3938 _get_derived_key(krb5_context context,
3939 krb5_crypto crypto,
3940 unsigned usage,
3941 struct key_data **key)
3943 int i;
3944 struct key_data *d;
3945 unsigned char constant[5];
3947 for(i = 0; i < crypto->num_key_usage; i++)
3948 if(crypto->key_usage[i].usage == usage) {
3949 *key = &crypto->key_usage[i].key;
3950 return 0;
3952 d = _new_derived_key(crypto, usage);
3953 if(d == NULL) {
3954 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3955 return ENOMEM;
3957 krb5_copy_keyblock(context, crypto->key.key, &d->key);
3958 _krb5_put_int(constant, usage, 5);
3959 derive_key(context, crypto->et, d, constant, sizeof(constant));
3960 *key = d;
3961 return 0;
3965 krb5_error_code KRB5_LIB_FUNCTION
3966 krb5_crypto_init(krb5_context context,
3967 const krb5_keyblock *key,
3968 krb5_enctype etype,
3969 krb5_crypto *crypto)
3971 krb5_error_code ret;
3972 ALLOC(*crypto, 1);
3973 if(*crypto == NULL) {
3974 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3975 return ENOMEM;
3977 if(etype == ETYPE_NULL)
3978 etype = key->keytype;
3979 (*crypto)->et = _find_enctype(etype);
3980 if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
3981 free(*crypto);
3982 *crypto = NULL;
3983 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
3984 N_("encryption type %d not supported", ""),
3985 etype);
3986 return KRB5_PROG_ETYPE_NOSUPP;
3988 if((*crypto)->et->keytype->size != key->keyvalue.length) {
3989 free(*crypto);
3990 *crypto = NULL;
3991 krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
3992 "encryption key has bad length");
3993 return KRB5_BAD_KEYSIZE;
3995 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
3996 if(ret) {
3997 free(*crypto);
3998 *crypto = NULL;
3999 return ret;
4001 (*crypto)->key.schedule = NULL;
4002 (*crypto)->num_key_usage = 0;
4003 (*crypto)->key_usage = NULL;
4004 return 0;
4007 static void
4008 free_key_schedule(krb5_context context,
4009 struct key_data *key,
4010 struct encryption_type *et)
4012 if (et->keytype->cleanup)
4013 (*et->keytype->cleanup)(context, key);
4014 memset(key->schedule->data, 0, key->schedule->length);
4015 krb5_free_data(context, key->schedule);
4018 static void
4019 free_key_data(krb5_context context, struct key_data *key,
4020 struct encryption_type *et)
4022 krb5_free_keyblock(context, key->key);
4023 if(key->schedule) {
4024 free_key_schedule(context, key, et);
4025 key->schedule = NULL;
4029 static void
4030 free_key_usage(krb5_context context, struct key_usage *ku,
4031 struct encryption_type *et)
4033 free_key_data(context, &ku->key, et);
4036 krb5_error_code KRB5_LIB_FUNCTION
4037 krb5_crypto_destroy(krb5_context context,
4038 krb5_crypto crypto)
4040 int i;
4042 for(i = 0; i < crypto->num_key_usage; i++)
4043 free_key_usage(context, &crypto->key_usage[i], crypto->et);
4044 free(crypto->key_usage);
4045 free_key_data(context, &crypto->key, crypto->et);
4046 free (crypto);
4047 return 0;
4050 krb5_error_code KRB5_LIB_FUNCTION
4051 krb5_crypto_getblocksize(krb5_context context,
4052 krb5_crypto crypto,
4053 size_t *blocksize)
4055 *blocksize = crypto->et->blocksize;
4056 return 0;
4059 krb5_error_code KRB5_LIB_FUNCTION
4060 krb5_crypto_getenctype(krb5_context context,
4061 krb5_crypto crypto,
4062 krb5_enctype *enctype)
4064 *enctype = crypto->et->type;
4065 return 0;
4068 krb5_error_code KRB5_LIB_FUNCTION
4069 krb5_crypto_getpadsize(krb5_context context,
4070 krb5_crypto crypto,
4071 size_t *padsize)
4073 *padsize = crypto->et->padsize;
4074 return 0;
4077 krb5_error_code KRB5_LIB_FUNCTION
4078 krb5_crypto_getconfoundersize(krb5_context context,
4079 krb5_crypto crypto,
4080 size_t *confoundersize)
4082 *confoundersize = crypto->et->confoundersize;
4083 return 0;
4088 * Disable encryption type
4090 * @param context Kerberos 5 context
4091 * @param enctype encryption type to disable
4093 * @return Return an error code or 0.
4095 * @ingroup krb5_crypto
4098 krb5_error_code KRB5_LIB_FUNCTION
4099 krb5_enctype_disable(krb5_context context,
4100 krb5_enctype enctype)
4102 struct encryption_type *et = _find_enctype(enctype);
4103 if(et == NULL) {
4104 if (context)
4105 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4106 N_("encryption type %d not supported", ""),
4107 enctype);
4108 return KRB5_PROG_ETYPE_NOSUPP;
4110 et->flags |= F_DISABLED;
4111 return 0;
4115 * Enable encryption type
4117 * @param context Kerberos 5 context
4118 * @param enctype encryption type to enable
4120 * @return Return an error code or 0.
4122 * @ingroup krb5_crypto
4125 krb5_error_code KRB5_LIB_FUNCTION
4126 krb5_enctype_enable(krb5_context context,
4127 krb5_enctype enctype)
4129 struct encryption_type *et = _find_enctype(enctype);
4130 if(et == NULL) {
4131 if (context)
4132 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4133 N_("encryption type %d not supported", ""),
4134 enctype);
4135 return KRB5_PROG_ETYPE_NOSUPP;
4137 et->flags &= ~F_DISABLED;
4138 return 0;
4142 krb5_error_code KRB5_LIB_FUNCTION
4143 krb5_string_to_key_derived(krb5_context context,
4144 const void *str,
4145 size_t len,
4146 krb5_enctype etype,
4147 krb5_keyblock *key)
4149 struct encryption_type *et = _find_enctype(etype);
4150 krb5_error_code ret;
4151 struct key_data kd;
4152 size_t keylen;
4153 u_char *tmp;
4155 if(et == NULL) {
4156 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4157 N_("encryption type %d not supported", ""),
4158 etype);
4159 return KRB5_PROG_ETYPE_NOSUPP;
4161 keylen = et->keytype->bits / 8;
4163 ALLOC(kd.key, 1);
4164 if(kd.key == NULL) {
4165 krb5_set_error_message (context, ENOMEM,
4166 N_("malloc: out of memory", ""));
4167 return ENOMEM;
4169 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
4170 if(ret) {
4171 free(kd.key);
4172 return ret;
4174 kd.key->keytype = etype;
4175 tmp = malloc (keylen);
4176 if(tmp == NULL) {
4177 krb5_free_keyblock(context, kd.key);
4178 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4179 return ENOMEM;
4181 ret = _krb5_n_fold(str, len, tmp, keylen);
4182 if (ret) {
4183 free(tmp);
4184 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4185 return ret;
4187 kd.schedule = NULL;
4188 DES3_random_to_key(context, kd.key, tmp, keylen);
4189 memset(tmp, 0, keylen);
4190 free(tmp);
4191 ret = derive_key(context,
4193 &kd,
4194 "kerberos", /* XXX well known constant */
4195 strlen("kerberos"));
4196 if (ret) {
4197 free_key_data(context, &kd, et);
4198 return ret;
4200 ret = krb5_copy_keyblock_contents(context, kd.key, key);
4201 free_key_data(context, &kd, et);
4202 return ret;
4205 static size_t
4206 wrapped_length (krb5_context context,
4207 krb5_crypto crypto,
4208 size_t data_len)
4210 struct encryption_type *et = crypto->et;
4211 size_t padsize = et->padsize;
4212 size_t checksumsize = CHECKSUMSIZE(et->checksum);
4213 size_t res;
4215 res = et->confoundersize + checksumsize + data_len;
4216 res = (res + padsize - 1) / padsize * padsize;
4217 return res;
4220 static size_t
4221 wrapped_length_dervied (krb5_context context,
4222 krb5_crypto crypto,
4223 size_t data_len)
4225 struct encryption_type *et = crypto->et;
4226 size_t padsize = et->padsize;
4227 size_t res;
4229 res = et->confoundersize + data_len;
4230 res = (res + padsize - 1) / padsize * padsize;
4231 if (et->keyed_checksum)
4232 res += et->keyed_checksum->checksumsize;
4233 else
4234 res += et->checksum->checksumsize;
4235 return res;
4239 * Return the size of an encrypted packet of length `data_len'
4242 size_t
4243 krb5_get_wrapped_length (krb5_context context,
4244 krb5_crypto crypto,
4245 size_t data_len)
4247 if (derived_crypto (context, crypto))
4248 return wrapped_length_dervied (context, crypto, data_len);
4249 else
4250 return wrapped_length (context, crypto, data_len);
4254 * Return the size of an encrypted packet of length `data_len'
4257 static size_t
4258 crypto_overhead (krb5_context context,
4259 krb5_crypto crypto)
4261 struct encryption_type *et = crypto->et;
4262 size_t res;
4264 res = CHECKSUMSIZE(et->checksum);
4265 res += et->confoundersize;
4266 if (et->padsize > 1)
4267 res += et->padsize;
4268 return res;
4271 static size_t
4272 crypto_overhead_dervied (krb5_context context,
4273 krb5_crypto crypto)
4275 struct encryption_type *et = crypto->et;
4276 size_t res;
4278 if (et->keyed_checksum)
4279 res = CHECKSUMSIZE(et->keyed_checksum);
4280 else
4281 res = CHECKSUMSIZE(et->checksum);
4282 res += et->confoundersize;
4283 if (et->padsize > 1)
4284 res += et->padsize;
4285 return res;
4288 size_t
4289 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
4291 if (derived_crypto (context, crypto))
4292 return crypto_overhead_dervied (context, crypto);
4293 else
4294 return crypto_overhead (context, crypto);
4297 krb5_error_code KRB5_LIB_FUNCTION
4298 krb5_random_to_key(krb5_context context,
4299 krb5_enctype type,
4300 const void *data,
4301 size_t size,
4302 krb5_keyblock *key)
4304 krb5_error_code ret;
4305 struct encryption_type *et = _find_enctype(type);
4306 if(et == NULL) {
4307 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4308 N_("encryption type %d not supported", ""),
4309 type);
4310 return KRB5_PROG_ETYPE_NOSUPP;
4312 if ((et->keytype->bits + 7) / 8 > size) {
4313 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4314 N_("encryption key %s needs %d bytes "
4315 "of random to make an encryption key "
4316 "out of it", ""),
4317 et->name, (int)et->keytype->size);
4318 return KRB5_PROG_ETYPE_NOSUPP;
4320 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
4321 if(ret)
4322 return ret;
4323 key->keytype = type;
4324 if (et->keytype->random_to_key)
4325 (*et->keytype->random_to_key)(context, key, data, size);
4326 else
4327 memcpy(key->keyvalue.data, data, et->keytype->size);
4329 return 0;
4332 krb5_error_code
4333 _krb5_pk_octetstring2key(krb5_context context,
4334 krb5_enctype type,
4335 const void *dhdata,
4336 size_t dhsize,
4337 const heim_octet_string *c_n,
4338 const heim_octet_string *k_n,
4339 krb5_keyblock *key)
4341 struct encryption_type *et = _find_enctype(type);
4342 krb5_error_code ret;
4343 size_t keylen, offset;
4344 void *keydata;
4345 unsigned char counter;
4346 unsigned char shaoutput[20];
4348 if(et == NULL) {
4349 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4350 N_("encryption type %d not supported", ""),
4351 type);
4352 return KRB5_PROG_ETYPE_NOSUPP;
4354 keylen = (et->keytype->bits + 7) / 8;
4356 keydata = malloc(keylen);
4357 if (keydata == NULL) {
4358 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4359 return ENOMEM;
4362 counter = 0;
4363 offset = 0;
4364 do {
4365 SHA_CTX m;
4367 SHA1_Init(&m);
4368 SHA1_Update(&m, &counter, 1);
4369 SHA1_Update(&m, dhdata, dhsize);
4370 if (c_n)
4371 SHA1_Update(&m, c_n->data, c_n->length);
4372 if (k_n)
4373 SHA1_Update(&m, k_n->data, k_n->length);
4374 SHA1_Final(shaoutput, &m);
4376 memcpy((unsigned char *)keydata + offset,
4377 shaoutput,
4378 min(keylen - offset, sizeof(shaoutput)));
4380 offset += sizeof(shaoutput);
4381 counter++;
4382 } while(offset < keylen);
4383 memset(shaoutput, 0, sizeof(shaoutput));
4385 ret = krb5_random_to_key(context, type, keydata, keylen, key);
4386 memset(keydata, 0, sizeof(keylen));
4387 free(keydata);
4388 return ret;
4391 static krb5_error_code
4392 encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
4394 KRB5PrincipalName pn;
4395 krb5_error_code ret;
4396 size_t size;
4398 pn.principalName = p->name;
4399 pn.realm = p->realm;
4401 ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
4402 &pn, &size, ret);
4403 if (ret) {
4404 krb5_data_zero(data);
4405 krb5_set_error_message(context, ret,
4406 N_("Failed to encode KRB5PrincipalName", ""));
4407 return ret;
4409 if (data->length != size)
4410 krb5_abortx(context, "asn1 compiler internal error");
4411 return 0;
4414 static krb5_error_code
4415 encode_otherinfo(krb5_context context,
4416 const AlgorithmIdentifier *ai,
4417 krb5_const_principal client,
4418 krb5_const_principal server,
4419 krb5_enctype enctype,
4420 const krb5_data *as_req,
4421 const krb5_data *pk_as_rep,
4422 const Ticket *ticket,
4423 krb5_data *other)
4425 PkinitSP80056AOtherInfo otherinfo;
4426 PkinitSuppPubInfo pubinfo;
4427 krb5_error_code ret;
4428 krb5_data pub;
4429 size_t size;
4431 krb5_data_zero(other);
4432 memset(&otherinfo, 0, sizeof(otherinfo));
4433 memset(&pubinfo, 0, sizeof(pubinfo));
4435 pubinfo.enctype = enctype;
4436 pubinfo.as_REQ = *as_req;
4437 pubinfo.pk_as_rep = *pk_as_rep;
4438 pubinfo.ticket = *ticket;
4439 ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
4440 &pubinfo, &size, ret);
4441 if (ret) {
4442 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4443 return ret;
4445 if (pub.length != size)
4446 krb5_abortx(context, "asn1 compiler internal error");
4448 ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
4449 if (ret) {
4450 free(pub.data);
4451 return ret;
4453 ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
4454 if (ret) {
4455 free(otherinfo.partyUInfo.data);
4456 free(pub.data);
4457 return ret;
4460 otherinfo.algorithmID = *ai;
4461 otherinfo.suppPubInfo = &pub;
4463 ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
4464 &otherinfo, &size, ret);
4465 free(otherinfo.partyUInfo.data);
4466 free(otherinfo.partyVInfo.data);
4467 free(pub.data);
4468 if (ret) {
4469 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4470 return ret;
4472 if (other->length != size)
4473 krb5_abortx(context, "asn1 compiler internal error");
4475 return 0;
4478 krb5_error_code
4479 _krb5_pk_kdf(krb5_context context,
4480 const struct AlgorithmIdentifier *ai,
4481 const void *dhdata,
4482 size_t dhsize,
4483 krb5_const_principal client,
4484 krb5_const_principal server,
4485 krb5_enctype enctype,
4486 const krb5_data *as_req,
4487 const krb5_data *pk_as_rep,
4488 const Ticket *ticket,
4489 krb5_keyblock *key)
4491 struct encryption_type *et;
4492 krb5_error_code ret;
4493 krb5_data other;
4494 size_t keylen, offset;
4495 uint32_t counter;
4496 unsigned char *keydata;
4497 unsigned char shaoutput[20];
4499 if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai->algorithm) != 0) {
4500 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4501 N_("KDF not supported", ""));
4502 return KRB5_PROG_ETYPE_NOSUPP;
4504 if (ai->parameters != NULL &&
4505 (ai->parameters->length != 2 ||
4506 memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
4508 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4509 N_("kdf params not NULL or the NULL-type",
4510 ""));
4511 return KRB5_PROG_ETYPE_NOSUPP;
4514 et = _find_enctype(enctype);
4515 if(et == NULL) {
4516 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4517 N_("encryption type %d not supported", ""),
4518 enctype);
4519 return KRB5_PROG_ETYPE_NOSUPP;
4521 keylen = (et->keytype->bits + 7) / 8;
4523 keydata = malloc(keylen);
4524 if (keydata == NULL) {
4525 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4526 return ENOMEM;
4529 ret = encode_otherinfo(context, ai, client, server,
4530 enctype, as_req, pk_as_rep, ticket, &other);
4531 if (ret) {
4532 free(keydata);
4533 return ret;
4536 offset = 0;
4537 counter = 1;
4538 do {
4539 unsigned char cdata[4];
4540 SHA_CTX m;
4542 SHA1_Init(&m);
4543 _krb5_put_int(cdata, counter, 4);
4544 SHA1_Update(&m, cdata, 4);
4545 SHA1_Update(&m, dhdata, dhsize);
4546 SHA1_Update(&m, other.data, other.length);
4547 SHA1_Final(shaoutput, &m);
4549 memcpy((unsigned char *)keydata + offset,
4550 shaoutput,
4551 min(keylen - offset, sizeof(shaoutput)));
4553 offset += sizeof(shaoutput);
4554 counter++;
4555 } while(offset < keylen);
4556 memset(shaoutput, 0, sizeof(shaoutput));
4558 free(other.data);
4560 ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
4561 memset(keydata, 0, sizeof(keylen));
4562 free(keydata);
4564 return ret;
4568 krb5_error_code KRB5_LIB_FUNCTION
4569 krb5_crypto_prf_length(krb5_context context,
4570 krb5_enctype type,
4571 size_t *length)
4573 struct encryption_type *et = _find_enctype(type);
4575 if(et == NULL || et->prf_length == 0) {
4576 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4577 N_("encryption type %d not supported", ""),
4578 type);
4579 return KRB5_PROG_ETYPE_NOSUPP;
4582 *length = et->prf_length;
4583 return 0;
4586 krb5_error_code KRB5_LIB_FUNCTION
4587 krb5_crypto_prf(krb5_context context,
4588 const krb5_crypto crypto,
4589 const krb5_data *input,
4590 krb5_data *output)
4592 struct encryption_type *et = crypto->et;
4594 krb5_data_zero(output);
4596 if(et->prf == NULL) {
4597 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4598 "kerberos prf for %s not supported",
4599 et->name);
4600 return KRB5_PROG_ETYPE_NOSUPP;
4603 return (*et->prf)(context, crypto, input, output);
4606 #ifndef HEIMDAL_SMALLER
4608 static struct key_type *keytypes[] = {
4609 &keytype_null,
4610 &keytype_des,
4611 &keytype_des3_derived,
4612 #ifdef DES3_OLD_ENCTYPE
4613 &keytype_des3,
4614 #endif
4615 &keytype_aes128,
4616 &keytype_aes256,
4617 &keytype_arcfour
4620 static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
4623 static struct key_type *
4624 _find_keytype(krb5_keytype type)
4626 int i;
4627 for(i = 0; i < num_keytypes; i++)
4628 if(keytypes[i]->type == type)
4629 return keytypes[i];
4630 return NULL;
4634 * First take the configured list of etypes for `keytype' if available,
4635 * else, do `krb5_keytype_to_enctypes'.
4638 krb5_error_code KRB5_LIB_FUNCTION
4639 krb5_keytype_to_enctypes_default (krb5_context context,
4640 krb5_keytype keytype,
4641 unsigned *len,
4642 krb5_enctype **val)
4643 __attribute__((deprecated))
4645 unsigned int i, n;
4646 krb5_enctype *ret;
4648 if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
4649 return krb5_keytype_to_enctypes (context, keytype, len, val);
4651 for (n = 0; context->etypes_des[n]; ++n)
4653 ret = malloc (n * sizeof(*ret));
4654 if (ret == NULL && n != 0) {
4655 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4656 return ENOMEM;
4658 for (i = 0; i < n; ++i)
4659 ret[i] = context->etypes_des[i];
4660 *len = n;
4661 *val = ret;
4662 return 0;
4665 krb5_error_code KRB5_LIB_FUNCTION
4666 krb5_keytype_to_string(krb5_context context,
4667 krb5_keytype keytype,
4668 char **string)
4669 __attribute__((deprecated))
4671 struct key_type *kt = _find_keytype(keytype);
4672 if(kt == NULL) {
4673 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4674 "key type %d not supported", keytype);
4675 return KRB5_PROG_KEYTYPE_NOSUPP;
4677 *string = strdup(kt->name);
4678 if(*string == NULL) {
4679 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4680 return ENOMEM;
4682 return 0;
4686 krb5_error_code KRB5_LIB_FUNCTION
4687 krb5_string_to_keytype(krb5_context context,
4688 const char *string,
4689 krb5_keytype *keytype)
4690 __attribute__((deprecated))
4692 char *end;
4693 int i;
4695 for(i = 0; i < num_keytypes; i++)
4696 if(strcasecmp(keytypes[i]->name, string) == 0){
4697 *keytype = keytypes[i]->type;
4698 return 0;
4701 /* check if the enctype is a number */
4702 *keytype = strtol(string, &end, 0);
4703 if(*end == '\0' && *keytype != 0) {
4704 if (krb5_enctype_valid(context, *keytype) == 0)
4705 return 0;
4708 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4709 "key type %s not supported", string);
4710 return KRB5_PROG_KEYTYPE_NOSUPP;
4713 krb5_error_code KRB5_LIB_FUNCTION
4714 krb5_keytype_to_enctypes (krb5_context context,
4715 krb5_keytype keytype,
4716 unsigned *len,
4717 krb5_enctype **val)
4718 __attribute__((deprecated))
4720 int i;
4721 unsigned n = 0;
4722 krb5_enctype *ret;
4724 for (i = num_etypes - 1; i >= 0; --i) {
4725 if (etypes[i]->keytype->type == keytype
4726 && !(etypes[i]->flags & F_PSEUDO)
4727 && krb5_enctype_valid(context, etypes[i]->type) == 0)
4728 ++n;
4730 if (n == 0) {
4731 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4732 "Keytype have no mapping");
4733 return KRB5_PROG_KEYTYPE_NOSUPP;
4736 ret = malloc(n * sizeof(*ret));
4737 if (ret == NULL && n != 0) {
4738 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
4739 return ENOMEM;
4741 n = 0;
4742 for (i = num_etypes - 1; i >= 0; --i) {
4743 if (etypes[i]->keytype->type == keytype
4744 && !(etypes[i]->flags & F_PSEUDO)
4745 && krb5_enctype_valid(context, etypes[i]->type) == 0)
4746 ret[n++] = etypes[i]->type;
4748 *len = n;
4749 *val = ret;
4750 return 0;
4753 /* if two enctypes have compatible keys */
4754 krb5_boolean KRB5_LIB_FUNCTION
4755 krb5_enctypes_compatible_keys(krb5_context context,
4756 krb5_enctype etype1,
4757 krb5_enctype etype2)
4758 __attribute__((deprecated))
4760 struct encryption_type *e1 = _find_enctype(etype1);
4761 struct encryption_type *e2 = _find_enctype(etype2);
4762 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
4765 #endif /* HEIMDAL_SMALLER */