2 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
34 #include "krb5_locl.h"
36 #include <pkinit_asn1.h>
38 #undef KRB5_DEPRECATED
39 #define KRB5_DEPRECATED
41 #define WEAK_ENCTYPES 1
43 #ifndef HEIMDAL_SMALLER
44 #define DES3_OLD_ENCTYPE 1
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
65 struct krb5_crypto_data {
66 struct encryption_type *et;
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 */
86 krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
87 krb5_salt, krb5_data, krb5_keyblock*);
91 krb5_keytype type; /* XXX */
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 {
110 krb5_enctype (*checksum)(krb5_context context,
111 struct key_data *key,
112 const void *buf, size_t len,
115 krb5_error_code (*verify)(krb5_context context,
116 struct key_data *key,
117 const void *buf, size_t len,
122 struct encryption_type {
127 size_t confoundersize;
128 struct key_type *keytype;
129 struct checksum_type *checksum;
130 struct checksum_type *keyed_checksum;
132 krb5_error_code (*encrypt)(krb5_context context,
133 struct key_data *key,
134 void *data, size_t len,
135 krb5_boolean encryptp,
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,
157 static krb5_error_code hmac(krb5_context context,
158 struct checksum_type *cm,
162 struct key_data *keyblock,
164 static void free_key_data(krb5_context,
166 struct encryption_type *);
167 static void free_key_schedule(krb5_context,
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 {
183 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
187 krb5_DES_random_key(krb5_context context,
190 DES_cblock *k = key->keyvalue.data;
192 krb5_generate_random_block(k, sizeof(DES_cblock));
193 DES_set_odd_parity(k);
194 } while(DES_is_weak_key(k));
198 krb5_DES_schedule_old(krb5_context context,
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.
217 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
221 char password[8+1]; /* crypt is limited to 8 chars anyway */
224 for(i = 0; i < 8; i++) {
225 char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
227 tolower(((unsigned char*)cell.data)[i]) : 0);
228 password[i] = c ? c : 'X';
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.
246 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
250 DES_key_schedule schedule;
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);
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,
293 if(password.length > 8)
294 krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
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));
302 #endif /* ENABLE_AFS_STRING_TO_KEY */
305 DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
307 DES_key_schedule schedule;
312 unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
313 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
316 p = (unsigned char*)key;
317 for (i = 0; i < length; i++) {
318 unsigned char tmp = data[i];
322 *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
326 DES_set_odd_parity(key);
327 if(DES_is_weak_key(key))
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))
337 static krb5_error_code
338 krb5_DES_string_to_key(krb5_context context,
339 krb5_enctype enctype,
349 #ifdef ENABLE_AFS_STRING_TO_KEY
350 if (opaque.length == 1) {
352 _krb5_get_int(opaque.data, &v, 1);
354 return DES_AFS3_string_to_key(context, enctype, password,
359 len = password.length + salt.saltvalue.length;
361 if(len > 0 && s == NULL) {
362 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
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));
377 krb5_DES_random_to_key(krb5_context context,
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");
395 DES3_random_key(krb5_context context,
398 DES_cblock *k = key->keyvalue.data;
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.
414 xor (DES_cblock *key, const unsigned char *b)
416 unsigned char *a = (unsigned char*)key;
427 #ifdef DES3_OLD_ENCTYPE
428 static krb5_error_code
429 DES3_string_to_key(krb5_context context,
430 krb5_enctype enctype,
438 unsigned char tmp[24];
442 len = password.length + salt.saltvalue.length;
444 if(len != 0 && str == NULL) {
445 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
448 memcpy(str, password.data, password.length);
449 memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
452 DES_key_schedule s[3];
455 ret = _krb5_n_fold(str, len, tmp, 24);
459 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
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,
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));
493 static krb5_error_code
494 DES3_string_to_key_derived(krb5_context context,
495 krb5_enctype enctype,
502 size_t len = password.length + salt.saltvalue.length;
506 if(len != 0 && s == NULL) {
507 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
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,
523 DES3_random_to_key(krb5_context context,
528 unsigned char *x = key->keyvalue.data;
529 const u_char *q = data;
533 memset(x, 0, sizeof(x));
534 for (i = 0; i < 3; ++i) {
536 for (j = 0; j < 7; ++j) {
537 unsigned char b = q[7 * i + j];
542 for (j = 6; j >= 0; --j) {
543 foo |= q[7 * i + j] & 1;
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");
561 ARCFOUR_schedule(krb5_context context,
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,
582 m = EVP_MD_CTX_create();
585 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
589 EVP_DigestInit_ex(m, EVP_md4(), NULL);
591 ret = wind_utf8ucs2_length(password.data, &len);
593 krb5_set_error_message (context, ret,
594 N_("Password not an UCS2 string", ""));
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", ""));
606 ret = wind_utf8ucs2(password.data, s, &len);
608 krb5_set_error_message (context, ret,
609 N_("Password not an UCS2 string", ""));
614 for (i = 0; i < len; i++) {
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);
625 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
628 EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
631 EVP_MD_CTX_destroy(m);
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,
654 struct encryption_type *et;
657 if (opaque.length == 0)
658 iter = _krb5_AES_string_to_default_iterator;
659 else if (opaque.length == 4) {
661 _krb5_get_int(opaque.data, &v, 4);
662 iter = ((uint32_t)v);
664 return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
666 et = _find_enctype(enctype);
668 return KRB5_PROG_KEYTYPE_NOSUPP;
673 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
676 kd.key->keytype = enctype;
677 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
679 krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
683 ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
684 salt.saltvalue.data, salt.saltvalue.length,
686 et->keytype->size, kd.key->keyvalue.data);
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"));
696 ret = krb5_copy_keyblock_contents(context, kd.key, key);
697 free_key_data(context, &kd, et);
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);
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);
728 static struct salt_type des_salt[] = {
732 krb5_DES_string_to_key
734 #ifdef ENABLE_AFS_STRING_TO_KEY
738 DES_AFS3_string_to_key
745 #ifdef DES3_OLD_ENCTYPE
746 static struct salt_type des3_salt[] = {
756 static struct salt_type des3_salt_derived[] = {
760 DES3_string_to_key_derived
765 static struct salt_type AES_salt[] = {
774 static struct salt_type arcfour_salt[] = {
778 ARCFOUR_string_to_key
787 static struct key_type keytype_null = {
799 static struct key_type keytype_des_old = {
804 sizeof(DES_key_schedule),
806 krb5_DES_schedule_old,
808 krb5_DES_random_to_key
811 static struct key_type keytype_des = {
816 sizeof(struct evp_schedule),
820 krb5_DES_random_to_key,
824 #endif /* WEAK_ENCTYPES */
826 #ifdef DES3_OLD_ENCTYPE
827 static struct key_type keytype_des3 = {
832 sizeof(struct evp_schedule),
842 static struct key_type keytype_des3_derived = {
847 sizeof(struct evp_schedule),
856 static struct key_type keytype_aes128 = {
861 sizeof(struct evp_schedule),
867 EVP_hcrypto_aes_128_cts
870 static struct key_type keytype_aes256 = {
875 sizeof(struct evp_schedule),
881 EVP_hcrypto_aes_256_cts
884 static struct key_type keytype_arcfour = {
895 krb5_error_code KRB5_LIB_FUNCTION
896 krb5_salttype_to_string (krb5_context context,
901 struct encryption_type *e;
902 struct salt_type *st;
904 e = _find_enctype (etype);
906 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
907 "encryption type %d not supported",
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", ""));
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,
931 krb5_salttype *salttype)
933 struct encryption_type *e;
934 struct salt_type *st;
936 e = _find_enctype (etype);
938 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
939 N_("encryption type %d not supported", ""),
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;
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,
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);
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) {
976 principal->name.name_string.val[i],
977 strlen(principal->name.name_string.val[i]));
978 p += strlen(principal->name.name_string.val[i]);
983 krb5_error_code KRB5_LIB_FUNCTION
984 krb5_free_salt(krb5_context context,
987 krb5_data_free(&salt.saltvalue);
991 krb5_error_code KRB5_LIB_FUNCTION
992 krb5_string_to_key_data (krb5_context context,
993 krb5_enctype enctype,
995 krb5_principal principal,
1001 ret = krb5_get_pw_salt(context, principal, &salt);
1004 ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
1005 krb5_free_salt(context, salt);
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,
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,
1030 krb5_data_zero(&opaque);
1031 return krb5_string_to_key_data_salt_opaque(context, enctype, password,
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,
1049 struct encryption_type *et =_find_enctype(enctype);
1050 struct salt_type *st;
1052 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1053 N_("encryption type %d not supported", ""),
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,
1061 krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
1062 N_("salt type %d not supported", ""),
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
1073 krb5_error_code KRB5_LIB_FUNCTION
1074 krb5_string_to_key_salt (krb5_context context,
1075 krb5_enctype enctype,
1076 const char *password,
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,
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,
1106 struct encryption_type *et = _find_enctype(type);
1108 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1109 N_("encryption type %d not supported", ""),
1111 return KRB5_PROG_ETYPE_NOSUPP;
1113 *keysize = et->keytype->size;
1117 krb5_error_code KRB5_LIB_FUNCTION
1118 krb5_enctype_keybits(krb5_context context,
1122 struct encryption_type *et = _find_enctype(type);
1124 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1125 "encryption type %d not supported",
1127 return KRB5_PROG_ETYPE_NOSUPP;
1129 *keybits = et->keytype->bits;
1133 krb5_error_code KRB5_LIB_FUNCTION
1134 krb5_generate_random_keyblock(krb5_context context,
1138 krb5_error_code ret;
1139 struct encryption_type *et = _find_enctype(type);
1141 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1142 N_("encryption type %d not supported", ""),
1144 return KRB5_PROG_ETYPE_NOSUPP;
1146 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
1149 key->keytype = type;
1150 if(et->keytype->random_key)
1151 (*et->keytype->random_key)(context, key);
1153 krb5_generate_random_block(key->keyvalue.data,
1154 key->keyvalue.length);
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;
1167 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
1168 N_("encryption type %d not supported", ""),
1170 return KRB5_PROG_ETYPE_NOSUPP;
1175 if(kt->schedule == NULL)
1177 if (key->schedule != NULL)
1179 ALLOC(key->schedule, 1);
1180 if(key->schedule == NULL) {
1181 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1184 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
1186 free(key->schedule);
1187 key->schedule = NULL;
1190 (*kt->schedule)(context, kt, key);
1194 /************************************************************
1196 ************************************************************/
1198 static krb5_error_code
1199 NONE_checksum(krb5_context context,
1200 struct key_data *key,
1209 static krb5_error_code
1210 CRC32_checksum(krb5_context context,
1211 struct key_data *key,
1218 unsigned char *r = C->checksum.data;
1219 _krb5_crc_init_table ();
1220 crc = _krb5_crc_update (data, len, 0);
1222 r[1] = (crc >> 8) & 0xff;
1223 r[2] = (crc >> 16) & 0xff;
1224 r[3] = (crc >> 24) & 0xff;
1228 static krb5_error_code
1229 RSA_MD4_checksum(krb5_context context,
1230 struct key_data *key,
1236 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
1237 krb5_abortx(context, "md4 checksum failed");
1241 static krb5_error_code
1242 des_checksum(krb5_context context,
1243 const EVP_MD *evp_md,
1244 struct key_data *key,
1249 struct evp_schedule *ctx = key->schedule->data;
1252 unsigned char *p = cksum->checksum.data;
1254 krb5_generate_random_block(p, 8);
1256 m = EVP_MD_CTX_create();
1258 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
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);
1274 static krb5_error_code
1275 des_verify(krb5_context context,
1276 const EVP_MD *evp_md,
1277 struct key_data *key,
1282 struct evp_schedule *ctx = key->schedule->data;
1284 unsigned char tmp[24];
1285 unsigned char res[16];
1287 krb5_error_code ret = 0;
1289 m = EVP_MD_CTX_create();
1291 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
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));
1313 static krb5_error_code
1314 RSA_MD4_DES_checksum(krb5_context context,
1315 struct key_data *key,
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,
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,
1343 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
1344 krb5_abortx(context, "md5 checksum failed");
1348 static krb5_error_code
1349 RSA_MD5_DES_checksum(krb5_context context,
1350 struct key_data *key,
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,
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,
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,
1390 return des_verify(context, EVP_md5(), key, data, len, C);
1394 static krb5_error_code
1395 SHA1_checksum(krb5_context context,
1396 struct key_data *key,
1402 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
1403 krb5_abortx(context, "sha1 checksum failed");
1407 /* HMAC according to RFC2104 */
1408 static krb5_error_code
1409 hmac(krb5_context context,
1410 struct checksum_type *cm,
1414 struct key_data *keyblock,
1417 unsigned char *ipad, *opad;
1422 ipad = malloc(cm->blocksize + len);
1425 opad = malloc(cm->blocksize + cm->checksumsize);
1430 memset(ipad, 0x36, cm->blocksize);
1431 memset(opad, 0x5c, cm->blocksize);
1433 if(keyblock->key->keyvalue.length > cm->blocksize){
1434 (*cm->checksum)(context,
1436 keyblock->key->keyvalue.data,
1437 keyblock->key->keyvalue.length,
1440 key = result->checksum.data;
1441 key_len = result->checksum.length;
1443 key = keyblock->key->keyvalue.data;
1444 key_len = keyblock->key->keyvalue.length;
1446 for(i = 0; i < key_len; i++){
1450 memcpy(ipad + cm->blocksize, data, len);
1451 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
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);
1459 memset(opad, 0, cm->blocksize + cm->checksumsize);
1465 krb5_error_code KRB5_LIB_FUNCTION
1466 krb5_hmac(krb5_context context,
1467 krb5_cksumtype cktype,
1474 struct checksum_type *c = _find_checksum(cktype);
1476 krb5_error_code ret;
1479 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1480 N_("checksum type %d not supported", ""),
1482 return KRB5_PROG_SUMTYPE_NOSUPP;
1488 ret = hmac(context, c, data, len, usage, &kd, result);
1491 krb5_free_data(context, kd.schedule);
1496 static krb5_error_code
1497 SP_HMAC_SHA1_checksum(krb5_context context,
1498 struct key_data *key,
1504 struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
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);
1514 krb5_abortx(context, "hmac failed");
1515 memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
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,
1532 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1533 const char signature[] = "signaturekey";
1535 struct key_data ksign;
1538 unsigned char tmp[16];
1539 unsigned char ksign_c_data[16];
1540 krb5_error_code ret;
1542 m = EVP_MD_CTX_create();
1544 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
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);
1551 EVP_MD_CTX_destroy(m);
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);
1572 static struct checksum_type checksum_none = {
1581 static struct checksum_type checksum_crc32 = {
1590 static struct checksum_type checksum_rsa_md4 = {
1599 static struct checksum_type checksum_rsa_md4_des = {
1600 CKSUMTYPE_RSA_MD4_DES,
1604 F_KEYED | F_CPROOF | F_VARIANT,
1605 RSA_MD4_DES_checksum,
1608 static struct checksum_type checksum_rsa_md5 = {
1617 static struct checksum_type checksum_rsa_md5_des = {
1618 CKSUMTYPE_RSA_MD5_DES,
1622 F_KEYED | F_CPROOF | F_VARIANT,
1623 RSA_MD5_DES_checksum,
1626 #ifdef DES3_OLD_ENCTYPE
1627 static struct checksum_type checksum_rsa_md5_des3 = {
1628 CKSUMTYPE_RSA_MD5_DES3,
1632 F_KEYED | F_CPROOF | F_VARIANT,
1633 RSA_MD5_DES3_checksum,
1637 static struct checksum_type checksum_sha1 = {
1646 static struct checksum_type checksum_hmac_sha1_des3 = {
1647 CKSUMTYPE_HMAC_SHA1_DES3,
1651 F_KEYED | F_CPROOF | F_DERIVED,
1652 SP_HMAC_SHA1_checksum,
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,
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,
1676 static struct checksum_type checksum_hmac_md5 = {
1686 static struct checksum_type *checksum_types[] = {
1690 &checksum_rsa_md4_des,
1692 &checksum_rsa_md5_des,
1693 #ifdef DES3_OLD_ENCTYPE
1694 &checksum_rsa_md5_des3,
1697 &checksum_hmac_sha1_des3,
1698 &checksum_hmac_sha1_aes128,
1699 &checksum_hmac_sha1_aes256,
1703 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1705 static struct checksum_type *
1706 _find_checksum(krb5_cksumtype type)
1709 for(i = 0; i < num_checksums; i++)
1710 if(checksum_types[i]->type == type)
1711 return checksum_types[i];
1715 static krb5_error_code
1716 get_checksum_key(krb5_context context,
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) {
1729 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1731 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1734 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1737 for(i = 0; i < (*key)->key->keyvalue.length; i++)
1738 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1740 *key = &crypto->key;
1743 ret = _key_schedule(context, *key);
1747 static krb5_error_code
1748 create_checksum (krb5_context context,
1749 struct checksum_type *ct,
1756 krb5_error_code ret;
1757 struct key_data *dkey;
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", ""),
1770 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1772 if(keyed_checksum) {
1773 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1778 result->cksumtype = ct->type;
1779 ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1782 return (*ct->checksum)(context, dkey, data, len, usage, result);
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,
1795 krb5_key_usage usage,
1801 struct checksum_type *ct = NULL;
1804 /* type 0 -> pick from crypto */
1806 ct = _find_checksum(type);
1807 } else if (crypto) {
1808 ct = crypto->et->keyed_checksum;
1810 ct = crypto->et->checksum;
1814 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1815 N_("checksum type %d not supported", ""),
1817 return KRB5_PROG_SUMTYPE_NOSUPP;
1820 if (arcfour_checksum_p(ct, crypto)) {
1822 usage2arcfour(context, &keyusage);
1824 keyusage = CHECKSUM_USAGE(usage);
1826 return create_checksum(context, ct, crypto, keyusage,
1830 static krb5_error_code
1831 verify_checksum(krb5_context context,
1833 unsigned usage, /* not krb5_key_usage */
1838 krb5_error_code ret;
1839 struct key_data *dkey;
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", ""),
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", ""),
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);
1881 return (*ct->verify)(context, dkey, data, len, usage, cksum);
1883 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1887 ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
1889 krb5_data_free(&c.checksum);
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;
1900 krb5_data_free (&c.checksum);
1904 krb5_error_code KRB5_LIB_FUNCTION
1905 krb5_verify_checksum(krb5_context context,
1907 krb5_key_usage usage,
1912 struct checksum_type *ct;
1915 ct = _find_checksum(cksum->cksumtype);
1917 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1918 N_("checksum type %d not supported", ""),
1920 return KRB5_PROG_SUMTYPE_NOSUPP;
1923 if (arcfour_checksum_p(ct, crypto)) {
1925 usage2arcfour(context, &keyusage);
1927 keyusage = CHECKSUM_USAGE(usage);
1929 return verify_checksum(context, crypto, keyusage,
1933 krb5_error_code KRB5_LIB_FUNCTION
1934 krb5_crypto_get_checksum_type(krb5_context context,
1936 krb5_cksumtype *type)
1938 struct checksum_type *ct = NULL;
1940 if (crypto != NULL) {
1941 ct = crypto->et->keyed_checksum;
1943 ct = crypto->et->checksum;
1947 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1948 N_("checksum type not found", ""));
1949 return KRB5_PROG_SUMTYPE_NOSUPP;
1958 krb5_error_code KRB5_LIB_FUNCTION
1959 krb5_checksumsize(krb5_context context,
1960 krb5_cksumtype type,
1963 struct checksum_type *ct = _find_checksum(type);
1965 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1966 N_("checksum type %d not supported", ""),
1968 return KRB5_PROG_SUMTYPE_NOSUPP;
1970 *size = ct->checksumsize;
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);
1981 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1982 N_("checksum type %d not supported", ""),
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);
1996 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1997 N_("checksum type %d not supported", ""),
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);
2011 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2012 N_("checksum type %d not supported", ""),
2014 return KRB5_PROG_SUMTYPE_NOSUPP;
2016 ct->flags |= F_DISABLED;
2020 /************************************************************
2022 ************************************************************/
2024 static krb5_error_code
2025 NULL_encrypt(krb5_context context,
2026 struct key_data *key,
2029 krb5_boolean encryptp,
2036 static krb5_error_code
2037 evp_encrypt(krb5_context context,
2038 struct key_data *key,
2041 krb5_boolean encryptp,
2045 struct evp_schedule *ctx = key->schedule->data;
2047 c = encryptp ? &ctx->ectx : &ctx->dctx;
2050 size_t len = EVP_CIPHER_CTX_iv_length(c);
2051 void *loiv = malloc(len);
2053 krb5_clear_error_message(context);
2056 memset(loiv, 0, len);
2057 EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
2060 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2061 EVP_Cipher(c, data, data, len);
2065 #ifdef WEAK_ENCTYPES
2066 static krb5_error_code
2067 evp_des_encrypt_null_ivec(krb5_context context,
2068 struct key_data *key,
2071 krb5_boolean encryptp,
2075 struct evp_schedule *ctx = key->schedule->data;
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);
2085 static krb5_error_code
2086 evp_des_encrypt_key_ivec(krb5_context context,
2087 struct key_data *key,
2090 krb5_boolean encryptp,
2094 struct evp_schedule *ctx = key->schedule->data;
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);
2104 static krb5_error_code
2105 DES_CFB64_encrypt_null_ivec(krb5_context context,
2106 struct key_data *key,
2109 krb5_boolean encryptp,
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);
2122 static krb5_error_code
2123 DES_PCBC_encrypt_key_ivec(krb5_context context,
2124 struct key_data *key,
2127 krb5_boolean encryptp,
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);
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,
2154 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2155 Checksum k1_c, k2_c, k3_c, cksum;
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);
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;
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);
2189 krb5_abortx(context, "hmac failed");
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);
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));
2209 static krb5_error_code
2210 ARCFOUR_subdecrypt(krb5_context context,
2211 struct key_data *key,
2217 struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2218 Checksum k1_c, k2_c, k3_c, cksum;
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);
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;
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);
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);
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);
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;
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)
2290 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2291 case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
2294 case KRB5_KU_USAGE_SEAL : /* 22 */
2297 case KRB5_KU_USAGE_SIGN : /* 23 */
2300 case KRB5_KU_USAGE_SEQ: /* 24 */
2308 static krb5_error_code
2309 ARCFOUR_encrypt(krb5_context context,
2310 struct key_data *key,
2313 krb5_boolean encryptp,
2317 krb5_error_code ret;
2318 unsigned keyusage = usage;
2320 if((ret = usage2arcfour (context, &keyusage)) != 0)
2324 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
2326 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
2334 static krb5_error_code
2335 AES_PRF(krb5_context context,
2337 const krb5_data *in,
2340 struct checksum_type *ct = crypto->et->checksum;
2341 krb5_error_code ret;
2343 krb5_keyblock *derived;
2345 result.cksumtype = ct->type;
2346 ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2348 krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
2352 ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2354 krb5_data_free(&result.checksum);
2358 if (result.checksum.length < crypto->et->blocksize)
2359 krb5_abortx(context, "internal prf error");
2362 ret = krb5_derive_key(context, crypto->key.key,
2363 crypto->et->type, "prf", 3, &derived);
2365 krb5_abortx(context, "krb5_derive_key");
2367 ret = krb5_data_alloc(out, crypto->et->blocksize);
2369 krb5_abortx(context, "malloc failed");
2372 const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
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,
2378 crypto->et->blocksize);
2379 EVP_CIPHER_CTX_cleanup(&ctx);
2382 krb5_data_free(&result.checksum);
2383 krb5_free_keyblock(context, derived);
2389 * these should currently be in reverse preference order.
2390 * (only relevant for !F_PSEUDO) */
2392 static struct encryption_type enctype_null = {
2406 static struct encryption_type enctype_arcfour_hmac_md5 = {
2407 ETYPE_ARCFOUR_HMAC_MD5,
2420 #ifdef DES3_OLD_ENCTYPE
2421 static struct encryption_type enctype_des3_cbc_md5 = {
2429 &checksum_rsa_md5_des3,
2436 static struct encryption_type enctype_des3_cbc_sha1 = {
2437 ETYPE_DES3_CBC_SHA1,
2442 &keytype_des3_derived,
2444 &checksum_hmac_sha1_des3,
2450 #ifdef DES3_OLD_ENCTYPE
2451 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2452 ETYPE_OLD_DES3_CBC_SHA1,
2453 "old-des3-cbc-sha1",
2459 &checksum_hmac_sha1_des3,
2466 static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2467 ETYPE_AES128_CTS_HMAC_SHA1_96,
2468 "aes128-cts-hmac-sha1-96",
2474 &checksum_hmac_sha1_aes128,
2480 static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2481 ETYPE_AES256_CTS_HMAC_SHA1_96,
2482 "aes256-cts-hmac-sha1-96",
2488 &checksum_hmac_sha1_aes256,
2494 static struct encryption_type enctype_des3_cbc_none = {
2495 ETYPE_DES3_CBC_NONE,
2500 &keytype_des3_derived,
2508 #ifdef WEAK_ENCTYPES
2509 static struct encryption_type enctype_des_cbc_crc = {
2519 evp_des_encrypt_key_ivec,
2523 static struct encryption_type enctype_des_cbc_md4 = {
2531 &checksum_rsa_md4_des,
2533 evp_des_encrypt_null_ivec,
2537 static struct encryption_type enctype_des_cbc_md5 = {
2545 &checksum_rsa_md5_des,
2547 evp_des_encrypt_null_ivec,
2551 static struct encryption_type enctype_des_cbc_none = {
2560 F_PSEUDO|F_DISABLED,
2561 evp_des_encrypt_null_ivec,
2565 static struct encryption_type enctype_des_cfb64_none = {
2566 ETYPE_DES_CFB64_NONE,
2574 F_PSEUDO|F_DISABLED,
2575 DES_CFB64_encrypt_null_ivec,
2579 static struct encryption_type enctype_des_pcbc_none = {
2580 ETYPE_DES_PCBC_NONE,
2588 F_PSEUDO|F_DISABLED,
2589 DES_PCBC_encrypt_key_ivec,
2593 #endif /* WEAK_ENCTYPES */
2595 static struct encryption_type *etypes[] = {
2596 &enctype_aes256_cts_hmac_sha1,
2597 &enctype_aes128_cts_hmac_sha1,
2598 &enctype_des3_cbc_sha1,
2599 &enctype_des3_cbc_none, /* used by the gss-api mech */
2600 &enctype_arcfour_hmac_md5,
2601 #ifdef DES3_OLD_ENCTYPE
2602 &enctype_des3_cbc_md5,
2603 &enctype_old_des3_cbc_sha1,
2605 #ifdef WEAK_ENCTYPES
2606 &enctype_des_cbc_crc,
2607 &enctype_des_cbc_md4,
2608 &enctype_des_cbc_md5,
2609 &enctype_des_cbc_none,
2610 &enctype_des_cfb64_none,
2611 &enctype_des_pcbc_none,
2616 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2619 static struct encryption_type *
2620 _find_enctype(krb5_enctype type)
2623 for(i = 0; i < num_etypes; i++)
2624 if(etypes[i]->type == type)
2630 krb5_error_code KRB5_LIB_FUNCTION
2631 krb5_enctype_to_string(krb5_context context,
2635 struct encryption_type *e;
2636 e = _find_enctype(etype);
2638 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2639 N_("encryption type %d not supported", ""),
2642 return KRB5_PROG_ETYPE_NOSUPP;
2644 *string = strdup(e->name);
2645 if(*string == NULL) {
2646 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2652 krb5_error_code KRB5_LIB_FUNCTION
2653 krb5_string_to_enctype(krb5_context context,
2655 krb5_enctype *etype)
2658 for(i = 0; i < num_etypes; i++)
2659 if(strcasecmp(etypes[i]->name, string) == 0){
2660 *etype = etypes[i]->type;
2663 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2664 N_("encryption type %s not supported", ""),
2666 return KRB5_PROG_ETYPE_NOSUPP;
2669 krb5_error_code KRB5_LIB_FUNCTION
2670 krb5_enctype_to_keytype(krb5_context context,
2672 krb5_keytype *keytype)
2674 struct encryption_type *e = _find_enctype(etype);
2676 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2677 N_("encryption type %d not supported", ""),
2679 return KRB5_PROG_ETYPE_NOSUPP;
2681 *keytype = e->keytype->type; /* XXX */
2685 krb5_error_code KRB5_LIB_FUNCTION
2686 krb5_enctype_valid(krb5_context context,
2689 struct encryption_type *e = _find_enctype(etype);
2691 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2692 N_("encryption type %d not supported", ""),
2694 return KRB5_PROG_ETYPE_NOSUPP;
2696 if (e->flags & F_DISABLED) {
2697 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2698 N_("encryption type %s is disabled", ""),
2700 return KRB5_PROG_ETYPE_NOSUPP;
2706 * Return the coresponding encryption type for a checksum type.
2708 * @param context Kerberos context
2709 * @param ctype The checksum type to get the result enctype for
2710 * @param etype The returned encryption, when the matching etype is
2711 * not found, etype is set to ETYPE_NULL.
2713 * @return Return an error code for an failure or 0 on success.
2714 * @ingroup krb5_crypto
2718 krb5_error_code KRB5_LIB_FUNCTION
2719 krb5_cksumtype_to_enctype(krb5_context context,
2720 krb5_cksumtype ctype,
2721 krb5_enctype *etype)
2725 *etype = ETYPE_NULL;
2727 for(i = 0; i < num_etypes; i++) {
2728 if(etypes[i]->keyed_checksum &&
2729 etypes[i]->keyed_checksum->type == ctype)
2731 *etype = etypes[i]->type;
2736 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2737 N_("checksum type %d not supported", ""),
2739 return KRB5_PROG_SUMTYPE_NOSUPP;
2743 krb5_error_code KRB5_LIB_FUNCTION
2744 krb5_cksumtype_valid(krb5_context context,
2745 krb5_cksumtype ctype)
2747 struct checksum_type *c = _find_checksum(ctype);
2749 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2750 N_("checksum type %d not supported", ""),
2752 return KRB5_PROG_SUMTYPE_NOSUPP;
2754 if (c->flags & F_DISABLED) {
2755 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2756 N_("checksum type %s is disabled", ""),
2758 return KRB5_PROG_SUMTYPE_NOSUPP;
2765 derived_crypto(krb5_context context,
2768 return (crypto->et->flags & F_DERIVED) != 0;
2772 special_crypto(krb5_context context,
2775 return (crypto->et->flags & F_SPECIAL) != 0;
2778 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2779 #define CHECKSUMTYPE(C) ((C)->type)
2781 static krb5_error_code
2782 encrypt_internal_derived(krb5_context context,
2790 size_t sz, block_sz, checksum_sz, total_sz;
2792 unsigned char *p, *q;
2793 krb5_error_code ret;
2794 struct key_data *dkey;
2795 const struct encryption_type *et = crypto->et;
2797 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2799 sz = et->confoundersize + len;
2800 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2801 total_sz = block_sz + checksum_sz;
2802 p = calloc(1, total_sz);
2804 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2809 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2810 q += et->confoundersize;
2811 memcpy(q, data, len);
2813 ret = create_checksum(context,
2816 INTEGRITY_USAGE(usage),
2820 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2821 free_Checksum (&cksum);
2822 krb5_clear_error_message (context);
2823 ret = KRB5_CRYPTO_INTERNAL;
2827 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2828 free_Checksum (&cksum);
2829 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2832 ret = _key_schedule(context, dkey);
2835 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2839 result->length = total_sz;
2842 memset(p, 0, total_sz);
2848 static krb5_error_code
2849 encrypt_internal(krb5_context context,
2856 size_t sz, block_sz, checksum_sz;
2858 unsigned char *p, *q;
2859 krb5_error_code ret;
2860 const struct encryption_type *et = crypto->et;
2862 checksum_sz = CHECKSUMSIZE(et->checksum);
2864 sz = et->confoundersize + checksum_sz + len;
2865 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2866 p = calloc(1, block_sz);
2868 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2873 krb5_generate_random_block(q, et->confoundersize); /* XXX */
2874 q += et->confoundersize;
2875 memset(q, 0, checksum_sz);
2877 memcpy(q, data, len);
2879 ret = create_checksum(context,
2886 if(ret == 0 && cksum.checksum.length != checksum_sz) {
2887 krb5_clear_error_message (context);
2888 free_Checksum(&cksum);
2889 ret = KRB5_CRYPTO_INTERNAL;
2893 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2894 free_Checksum(&cksum);
2895 ret = _key_schedule(context, &crypto->key);
2898 ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
2900 memset(p, 0, block_sz);
2905 result->length = block_sz;
2908 memset(p, 0, block_sz);
2913 static krb5_error_code
2914 encrypt_internal_special(krb5_context context,
2922 struct encryption_type *et = crypto->et;
2923 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2924 size_t sz = len + cksum_sz + et->confoundersize;
2926 krb5_error_code ret;
2930 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2934 memset (p, 0, cksum_sz);
2936 krb5_generate_random_block(p, et->confoundersize);
2937 p += et->confoundersize;
2938 memcpy (p, data, len);
2939 ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
2946 result->length = sz;
2950 static krb5_error_code
2951 decrypt_internal_derived(krb5_context context,
2962 krb5_error_code ret;
2963 struct key_data *dkey;
2964 struct encryption_type *et = crypto->et;
2967 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2968 if (len < checksum_sz + et->confoundersize) {
2969 krb5_set_error_message(context, KRB5_BAD_MSIZE,
2970 N_("Encrypted data shorter then "
2971 "checksum + confunder", ""));
2972 return KRB5_BAD_MSIZE;
2975 if (((len - checksum_sz) % et->padsize) != 0) {
2976 krb5_clear_error_message(context);
2977 return KRB5_BAD_MSIZE;
2981 if(len != 0 && p == NULL) {
2982 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2985 memcpy(p, data, len);
2989 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2994 ret = _key_schedule(context, dkey);
2999 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3005 cksum.checksum.data = p + len;
3006 cksum.checksum.length = checksum_sz;
3007 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3009 ret = verify_checksum(context,
3011 INTEGRITY_USAGE(usage),
3019 l = len - et->confoundersize;
3020 memmove(p, p + et->confoundersize, l);
3021 result->data = realloc(p, l);
3022 if(result->data == NULL && l != 0) {
3024 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3031 static krb5_error_code
3032 decrypt_internal(krb5_context context,
3039 krb5_error_code ret;
3042 size_t checksum_sz, l;
3043 struct encryption_type *et = crypto->et;
3045 if ((len % et->padsize) != 0) {
3046 krb5_clear_error_message(context);
3047 return KRB5_BAD_MSIZE;
3050 checksum_sz = CHECKSUMSIZE(et->checksum);
3052 if(len != 0 && p == NULL) {
3053 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3056 memcpy(p, data, len);
3058 ret = _key_schedule(context, &crypto->key);
3063 ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
3068 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
3073 memset(p + et->confoundersize, 0, checksum_sz);
3074 cksum.cksumtype = CHECKSUMTYPE(et->checksum);
3075 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
3076 free_Checksum(&cksum);
3081 l = len - et->confoundersize - checksum_sz;
3082 memmove(p, p + et->confoundersize + checksum_sz, l);
3083 result->data = realloc(p, l);
3084 if(result->data == NULL && l != 0) {
3086 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3093 static krb5_error_code
3094 decrypt_internal_special(krb5_context context,
3102 struct encryption_type *et = crypto->et;
3103 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3104 size_t sz = len - cksum_sz - et->confoundersize;
3106 krb5_error_code ret;
3108 if ((len % et->padsize) != 0) {
3109 krb5_clear_error_message(context);
3110 return KRB5_BAD_MSIZE;
3115 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3118 memcpy(p, data, len);
3120 ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
3126 memmove (p, p + cksum_sz + et->confoundersize, sz);
3127 result->data = realloc(p, sz);
3128 if(result->data == NULL && sz != 0) {
3130 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3133 result->length = sz;
3137 static krb5_crypto_iov *
3138 find_iv(krb5_crypto_iov *data, int num_data, int type)
3141 for (i = 0; i < num_data; i++)
3142 if (data[i].flags == type)
3148 * Inline encrypt a kerberos message
3150 * @param context Kerberos context
3151 * @param crypto Kerberos crypto context
3152 * @param usage Key usage for this buffer
3153 * @param data array of buffers to process
3154 * @param num_data length of array
3155 * @param ivec initial cbc/cts vector
3157 * @return Return an error code or 0.
3158 * @ingroup krb5_crypto
3160 * Kerberos encrypted data look like this:
3162 * 1. KRB5_CRYPTO_TYPE_HEADER
3163 * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...]
3164 * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
3165 * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
3166 * commonly used headers and trailers.
3167 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
3168 * 4. KRB5_CRYPTO_TYPE_TRAILER
3171 krb5_error_code KRB5_LIB_FUNCTION
3172 krb5_encrypt_iov_ivec(krb5_context context,
3175 krb5_crypto_iov *data,
3179 size_t headersz, trailersz, len;
3181 size_t sz, block_sz, pad_sz;
3183 unsigned char *p, *q;
3184 krb5_error_code ret;
3185 struct key_data *dkey;
3186 const struct encryption_type *et = crypto->et;
3187 krb5_crypto_iov *tiv, *piv, *hiv, *div;
3190 krb5_clear_error_message(context);
3191 return KRB5_CRYPTO_INTERNAL;
3194 if(!derived_crypto(context, crypto)) {
3195 krb5_clear_error_message(context);
3196 return KRB5_CRYPTO_INTERNAL;
3199 headersz = et->confoundersize;
3200 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3202 div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA);
3204 return KRB5_CRYPTO_INTERNAL;
3206 len = div->data.length;
3208 sz = headersz + len;
3209 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3211 pad_sz = block_sz - sz;
3215 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3216 if (hiv == NULL || hiv->data.length != headersz)
3217 return KRB5_BAD_MSIZE;
3219 krb5_generate_random_block(hiv->data.data, hiv->data.length);
3223 piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
3224 /* its ok to have no TYPE_PADDING if there is no padding */
3225 if (piv == NULL && pad_sz != 0)
3226 return KRB5_BAD_MSIZE;
3228 if (piv->data.length < pad_sz)
3229 return KRB5_BAD_MSIZE;
3230 piv->data.length = pad_sz;
3236 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3237 if (tiv == NULL || tiv->data.length != trailersz)
3238 return KRB5_BAD_MSIZE;
3242 * XXX replace with EVP_Sign? at least make create_checksum an iov
3244 * XXX CTS EVP is broken, can't handle multi buffers :(
3247 len = hiv->data.length;
3248 for (i = 0; i < num_data; i++) {
3249 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3250 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3252 len += data[i].data.length;
3255 p = q = malloc(len);
3257 memcpy(q, hiv->data.data, hiv->data.length);
3258 q += hiv->data.length;
3259 for (i = 0; i < num_data; i++) {
3260 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3261 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3263 memcpy(q, data[i].data.data, data[i].data.length);
3264 q += data[i].data.length;
3267 ret = create_checksum(context,
3270 INTEGRITY_USAGE(usage),
3275 if(ret == 0 && cksum.checksum.length != trailersz) {
3276 free_Checksum (&cksum);
3277 krb5_clear_error_message (context);
3278 ret = KRB5_CRYPTO_INTERNAL;
3283 /* save cksum at end */
3284 memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
3285 free_Checksum (&cksum);
3287 /* now encrypt data */
3289 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3292 ret = _key_schedule(context, dkey);
3296 /* XXX replace with EVP_Cipher */
3298 len = hiv->data.length + div->data.length;
3300 len += piv->data.length;
3302 p = q = malloc(len);
3306 memcpy(q, hiv->data.data, hiv->data.length);
3307 q += hiv->data.length;
3308 memcpy(q, div->data.data, div->data.length);
3309 q += div->data.length;
3310 memset(q, 0, pad_sz);
3312 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3317 ret = _key_schedule(context, dkey);
3323 ret = (*et->encrypt)(context, dkey, p, len, 1, usage, ivec);
3329 /* now copy data back to buffers */
3332 memcpy(hiv->data.data, q, hiv->data.length);
3333 q += hiv->data.length;
3335 memcpy(div->data.data, q, div->data.length);
3336 q += div->data.length;
3339 memcpy(piv->data.data, q, pad_sz);
3346 * Inline decrypt a Kerberos message.
3348 * @param context Kerberos context
3349 * @param crypto Kerberos crypto context
3350 * @param usage Key usage for this buffer
3351 * @param data array of buffers to process
3352 * @param num_data length of array
3353 * @param ivec initial cbc/cts vector
3355 * @return Return an error code or 0.
3356 * @ingroup krb5_crypto
3358 * 1. KRB5_CRYPTO_TYPE_HEADER
3359 * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
3360 * any order, however the receiver have to aware of the
3361 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
3362 * protocol headers and trailers. The output data will be of same
3363 * size as the input data or shorter.
3366 krb5_error_code KRB5_LIB_FUNCTION
3367 krb5_decrypt_iov_ivec(krb5_context context,
3370 krb5_crypto_iov *data,
3371 unsigned int num_data,
3375 size_t headersz, trailersz, len;
3376 size_t sz, block_sz, pad_sz;
3378 unsigned char *p, *q;
3379 krb5_error_code ret;
3380 struct key_data *dkey;
3381 struct encryption_type *et = crypto->et;
3382 krb5_crypto_iov *tiv, *hiv, *div;
3385 krb5_clear_error_message(context);
3386 return KRB5_CRYPTO_INTERNAL;
3389 if(!derived_crypto(context, crypto)) {
3390 krb5_clear_error_message(context);
3391 return KRB5_CRYPTO_INTERNAL;
3394 headersz = et->confoundersize;
3395 trailersz = CHECKSUMSIZE(et->keyed_checksum);
3397 for (len = 0, i = 0; i < num_data; i++) {
3398 if (data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
3400 return KRB5_CRYPTO_INTERNAL;
3401 len += data[i].data.length;
3405 sz = headersz + len;
3406 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3408 pad_sz = block_sz - sz;
3409 trailersz += pad_sz;
3413 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3414 if (hiv == NULL || hiv->data.length < headersz)
3415 return KRB5_BAD_MSIZE;
3416 hiv->data.length = headersz;
3420 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3421 if (tiv == NULL || tiv->data.length < trailersz)
3422 return KRB5_BAD_MSIZE;
3423 tiv->data.length = trailersz;
3425 div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA);
3427 return KRB5_CRYPTO_INTERNAL;
3429 /* XXX replace with EVP_Cipher */
3431 for (len = 0, i = 0; i < num_data; i++) {
3432 if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
3433 data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3435 len += data[i].data.length;
3438 p = q = malloc(len);
3442 memcpy(q, hiv->data.data, hiv->data.length);
3443 q += hiv->data.length;
3444 memcpy(q, div->data.data, div->data.length);
3446 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3451 ret = _key_schedule(context, dkey);
3457 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3463 /* copy data back to buffers */
3464 memcpy(hiv->data.data, p, hiv->data.length);
3465 memcpy(div->data.data, p + hiv->data.length, len - hiv->data.length);
3468 /* check signature */
3470 len = hiv->data.length;
3471 for (i = 0; i < num_data; i++) {
3472 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3473 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3475 len += data[i].data.length;
3478 p = q = malloc(len);
3480 memcpy(q, hiv->data.data, hiv->data.length);
3481 q += hiv->data.length;
3482 for (i = 0; i < num_data; i++) {
3483 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3484 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3486 memcpy(q, data[i].data.data, data[i].data.length);
3487 q += data[i].data.length;
3490 cksum.checksum.data = tiv->data.data;
3491 cksum.checksum.length = tiv->data.length;
3492 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
3494 ret = verify_checksum(context,
3496 INTEGRITY_USAGE(usage),
3505 * Create a Kerberos message checksum.
3507 * @param context Kerberos context
3508 * @param crypto Kerberos crypto context
3509 * @param usage Key usage for this buffer
3510 * @param data array of buffers to process
3511 * @param num_data length of array
3512 * @param type output data
3514 * @return Return an error code or 0.
3515 * @ingroup krb5_crypto
3518 krb5_error_code KRB5_LIB_FUNCTION
3519 krb5_create_checksum_iov(krb5_context context,
3522 krb5_crypto_iov *data,
3523 unsigned int num_data,
3524 krb5_cksumtype *type)
3527 krb5_crypto_iov *civ;
3528 krb5_error_code ret;
3534 krb5_clear_error_message(context);
3535 return KRB5_CRYPTO_INTERNAL;
3538 if(!derived_crypto(context, crypto)) {
3539 krb5_clear_error_message(context);
3540 return KRB5_CRYPTO_INTERNAL;
3543 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
3545 return KRB5_BAD_MSIZE;
3548 for (i = 0; i < num_data; i++) {
3549 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3550 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3552 len += data[i].data.length;
3555 p = q = malloc(len);
3557 for (i = 0; i < num_data; i++) {
3558 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3559 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3561 memcpy(q, data[i].data.data, data[i].data.length);
3562 q += data[i].data.length;
3565 ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
3571 *type = cksum.cksumtype;
3573 if (cksum.checksum.length > civ->data.length) {
3574 krb5_set_error_message(context, KRB5_BAD_MSIZE,
3575 N_("Checksum larger then input buffer", ""));
3576 free_Checksum(&cksum);
3577 return KRB5_BAD_MSIZE;
3580 civ->data.length = cksum.checksum.length;
3581 memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
3582 free_Checksum(&cksum);
3588 size_t KRB5_LIB_FUNCTION
3589 krb5_crypto_length(krb5_context context,
3593 if (!derived_crypto(context, crypto))
3596 case KRB5_CRYPTO_TYPE_EMPTY:
3598 case KRB5_CRYPTO_TYPE_HEADER:
3599 return crypto->et->blocksize;
3600 case KRB5_CRYPTO_TYPE_PADDING:
3601 if (crypto->et->padsize > 1)
3602 return crypto->et->padsize;
3604 case KRB5_CRYPTO_TYPE_TRAILER:
3605 return CHECKSUMSIZE(crypto->et->keyed_checksum);
3606 case KRB5_CRYPTO_TYPE_CHECKSUM:
3607 if (crypto->et->keyed_checksum)
3608 return CHECKSUMSIZE(crypto->et->keyed_checksum);
3609 return CHECKSUMSIZE(crypto->et->checksum);
3614 krb5_error_code KRB5_LIB_FUNCTION
3615 krb5_encrypt_ivec(krb5_context context,
3623 if(derived_crypto(context, crypto))
3624 return encrypt_internal_derived(context, crypto, usage,
3625 data, len, result, ivec);
3626 else if (special_crypto(context, crypto))
3627 return encrypt_internal_special (context, crypto, usage,
3628 data, len, result, ivec);
3630 return encrypt_internal(context, crypto, data, len, result, ivec);
3633 krb5_error_code KRB5_LIB_FUNCTION
3634 krb5_encrypt(krb5_context context,
3641 return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
3644 krb5_error_code KRB5_LIB_FUNCTION
3645 krb5_encrypt_EncryptedData(krb5_context context,
3651 EncryptedData *result)
3653 result->etype = CRYPTO_ETYPE(crypto);
3655 ALLOC(result->kvno, 1);
3656 *result->kvno = kvno;
3658 result->kvno = NULL;
3659 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
3662 krb5_error_code KRB5_LIB_FUNCTION
3663 krb5_decrypt_ivec(krb5_context context,
3671 if(derived_crypto(context, crypto))
3672 return decrypt_internal_derived(context, crypto, usage,
3673 data, len, result, ivec);
3674 else if (special_crypto (context, crypto))
3675 return decrypt_internal_special(context, crypto, usage,
3676 data, len, result, ivec);
3678 return decrypt_internal(context, crypto, data, len, result, ivec);
3681 krb5_error_code KRB5_LIB_FUNCTION
3682 krb5_decrypt(krb5_context context,
3689 return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
3693 krb5_error_code KRB5_LIB_FUNCTION
3694 krb5_decrypt_EncryptedData(krb5_context context,
3697 const EncryptedData *e,
3700 return krb5_decrypt(context, crypto, usage,
3701 e->cipher.data, e->cipher.length, result);
3704 /************************************************************
3706 ************************************************************/
3708 #define ENTROPY_NEEDED 128
3711 seed_something(void)
3713 char buf[1024], seedfile[256];
3715 /* If there is a seed file, load it. But such a file cannot be trusted,
3716 so use 0 for the entropy estimate */
3717 if (RAND_file_name(seedfile, sizeof(seedfile))) {
3719 fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
3723 ret = read(fd, buf, sizeof(buf));
3725 RAND_add(buf, ret, 0.0);
3732 /* Calling RAND_status() will try to use /dev/urandom if it exists so
3733 we do not have to deal with it. */
3734 if (RAND_status() != 1) {
3735 krb5_context context;
3739 if (!krb5_init_context(&context)) {
3740 p = krb5_config_get_string(context, NULL, "libdefaults",
3741 "egd_socket", NULL);
3743 RAND_egd_bytes(p, ENTROPY_NEEDED);
3744 krb5_free_context(context);
3748 if (RAND_status() == 1) {
3749 /* Update the seed file */
3751 RAND_write_file(seedfile);
3758 void KRB5_LIB_FUNCTION
3759 krb5_generate_random_block(void *buf, size_t len)
3761 static int rng_initialized = 0;
3763 HEIMDAL_MUTEX_lock(&crypto_mutex);
3764 if (!rng_initialized) {
3765 if (seed_something())
3766 krb5_abortx(NULL, "Fatal: could not seed the "
3767 "random number generator");
3769 rng_initialized = 1;
3771 HEIMDAL_MUTEX_unlock(&crypto_mutex);
3772 if (RAND_bytes(buf, len) != 1)
3773 krb5_abortx(NULL, "Failed to generate random block");
3776 static krb5_error_code
3777 derive_key(krb5_context context,
3778 struct encryption_type *et,
3779 struct key_data *key,
3780 const void *constant,
3783 unsigned char *k = NULL;
3784 unsigned int nblocks = 0, i;
3785 krb5_error_code ret = 0;
3786 struct key_type *kt = et->keytype;
3788 ret = _key_schedule(context, key);
3791 if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
3792 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
3793 k = malloc(nblocks * et->blocksize);
3796 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3799 ret = _krb5_n_fold(constant, len, k, et->blocksize);
3801 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3805 for(i = 0; i < nblocks; i++) {
3807 memcpy(k + i * et->blocksize,
3808 k + (i - 1) * et->blocksize,
3810 (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
3814 /* this case is probably broken, but won't be run anyway */
3815 void *c = malloc(len);
3816 size_t res_len = (kt->bits + 7) / 8;
3818 if(len != 0 && c == NULL) {
3820 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3823 memcpy(c, constant, len);
3824 (*et->encrypt)(context, key, c, len, 1, 0, NULL);
3825 k = malloc(res_len);
3826 if(res_len != 0 && k == NULL) {
3829 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3832 ret = _krb5_n_fold(c, len, k, res_len);
3835 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
3840 /* XXX keytype dependent post-processing */
3843 DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
3845 case KEYTYPE_AES128:
3846 case KEYTYPE_AES256:
3847 memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
3850 ret = KRB5_CRYPTO_INTERNAL;
3851 krb5_set_error_message(context, ret,
3852 N_("derive_key() called with unknown keytype (%u)", ""),
3857 if (key->schedule) {
3858 free_key_schedule(context, key, et);
3859 key->schedule = NULL;
3862 memset(k, 0, nblocks * et->blocksize);
3868 static struct key_data *
3869 _new_derived_key(krb5_crypto crypto, unsigned usage)
3871 struct key_usage *d = crypto->key_usage;
3872 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
3875 crypto->key_usage = d;
3876 d += crypto->num_key_usage++;
3877 memset(d, 0, sizeof(*d));
3882 krb5_error_code KRB5_LIB_FUNCTION
3883 krb5_derive_key(krb5_context context,
3884 const krb5_keyblock *key,
3886 const void *constant,
3887 size_t constant_len,
3888 krb5_keyblock **derived_key)
3890 krb5_error_code ret;
3891 struct encryption_type *et;
3894 *derived_key = NULL;
3896 et = _find_enctype (etype);
3898 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3899 N_("encryption type %d not supported", ""),
3901 return KRB5_PROG_ETYPE_NOSUPP;
3904 ret = krb5_copy_keyblock(context, key, &d.key);
3909 ret = derive_key(context, et, &d, constant, constant_len);
3911 ret = krb5_copy_keyblock(context, d.key, derived_key);
3912 free_key_data(context, &d, et);
3916 static krb5_error_code
3917 _get_derived_key(krb5_context context,
3920 struct key_data **key)
3924 unsigned char constant[5];
3926 for(i = 0; i < crypto->num_key_usage; i++)
3927 if(crypto->key_usage[i].usage == usage) {
3928 *key = &crypto->key_usage[i].key;
3931 d = _new_derived_key(crypto, usage);
3933 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3936 krb5_copy_keyblock(context, crypto->key.key, &d->key);
3937 _krb5_put_int(constant, usage, 5);
3938 derive_key(context, crypto->et, d, constant, sizeof(constant));
3944 krb5_error_code KRB5_LIB_FUNCTION
3945 krb5_crypto_init(krb5_context context,
3946 const krb5_keyblock *key,
3948 krb5_crypto *crypto)
3950 krb5_error_code ret;
3952 if(*crypto == NULL) {
3953 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3956 if(etype == ETYPE_NULL)
3957 etype = key->keytype;
3958 (*crypto)->et = _find_enctype(etype);
3959 if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
3962 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
3963 N_("encryption type %d not supported", ""),
3965 return KRB5_PROG_ETYPE_NOSUPP;
3967 if((*crypto)->et->keytype->size != key->keyvalue.length) {
3970 krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
3971 "encryption key has bad length");
3972 return KRB5_BAD_KEYSIZE;
3974 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
3980 (*crypto)->key.schedule = NULL;
3981 (*crypto)->num_key_usage = 0;
3982 (*crypto)->key_usage = NULL;
3987 free_key_schedule(krb5_context context,
3988 struct key_data *key,
3989 struct encryption_type *et)
3991 if (et->keytype->cleanup)
3992 (*et->keytype->cleanup)(context, key);
3993 memset(key->schedule->data, 0, key->schedule->length);
3994 krb5_free_data(context, key->schedule);
3998 free_key_data(krb5_context context, struct key_data *key,
3999 struct encryption_type *et)
4001 krb5_free_keyblock(context, key->key);
4003 free_key_schedule(context, key, et);
4004 key->schedule = NULL;
4009 free_key_usage(krb5_context context, struct key_usage *ku,
4010 struct encryption_type *et)
4012 free_key_data(context, &ku->key, et);
4015 krb5_error_code KRB5_LIB_FUNCTION
4016 krb5_crypto_destroy(krb5_context context,
4021 for(i = 0; i < crypto->num_key_usage; i++)
4022 free_key_usage(context, &crypto->key_usage[i], crypto->et);
4023 free(crypto->key_usage);
4024 free_key_data(context, &crypto->key, crypto->et);
4029 krb5_error_code KRB5_LIB_FUNCTION
4030 krb5_crypto_getblocksize(krb5_context context,
4034 *blocksize = crypto->et->blocksize;
4038 krb5_error_code KRB5_LIB_FUNCTION
4039 krb5_crypto_getenctype(krb5_context context,
4041 krb5_enctype *enctype)
4043 *enctype = crypto->et->type;
4047 krb5_error_code KRB5_LIB_FUNCTION
4048 krb5_crypto_getpadsize(krb5_context context,
4052 *padsize = crypto->et->padsize;
4056 krb5_error_code KRB5_LIB_FUNCTION
4057 krb5_crypto_getconfoundersize(krb5_context context,
4059 size_t *confoundersize)
4061 *confoundersize = crypto->et->confoundersize;
4067 * Disable encryption type
4069 * @param context Kerberos 5 context
4070 * @param enctype encryption type to disable
4072 * @return Return an error code or 0.
4074 * @ingroup krb5_crypto
4077 krb5_error_code KRB5_LIB_FUNCTION
4078 krb5_enctype_disable(krb5_context context,
4079 krb5_enctype enctype)
4081 struct encryption_type *et = _find_enctype(enctype);
4084 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4085 N_("encryption type %d not supported", ""),
4087 return KRB5_PROG_ETYPE_NOSUPP;
4089 et->flags |= F_DISABLED;
4094 * Enable encryption type
4096 * @param context Kerberos 5 context
4097 * @param enctype encryption type to enable
4099 * @return Return an error code or 0.
4101 * @ingroup krb5_crypto
4104 krb5_error_code KRB5_LIB_FUNCTION
4105 krb5_enctype_enable(krb5_context context,
4106 krb5_enctype enctype)
4108 struct encryption_type *et = _find_enctype(enctype);
4111 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4112 N_("encryption type %d not supported", ""),
4114 return KRB5_PROG_ETYPE_NOSUPP;
4116 et->flags &= ~F_DISABLED;
4121 krb5_error_code KRB5_LIB_FUNCTION
4122 krb5_string_to_key_derived(krb5_context context,
4128 struct encryption_type *et = _find_enctype(etype);
4129 krb5_error_code ret;
4135 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
4136 N_("encryption type %d not supported", ""),
4138 return KRB5_PROG_ETYPE_NOSUPP;
4140 keylen = et->keytype->bits / 8;
4143 if(kd.key == NULL) {
4144 krb5_set_error_message (context, ENOMEM,
4145 N_("malloc: out of memory", ""));
4148 ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
4153 kd.key->keytype = etype;
4154 tmp = malloc (keylen);
4156 krb5_free_keyblock(context, kd.key);
4157 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4160 ret = _krb5_n_fold(str, len, tmp, keylen);
4163 krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
4167 DES3_random_to_key(context, kd.key, tmp, keylen);
4168 memset(tmp, 0, keylen);
4170 ret = derive_key(context,
4173 "kerberos", /* XXX well known constant */
4174 strlen("kerberos"));
4176 free_key_data(context, &kd, et);
4179 ret = krb5_copy_keyblock_contents(context, kd.key, key);
4180 free_key_data(context, &kd, et);
4185 wrapped_length (krb5_context context,
4189 struct encryption_type *et = crypto->et;
4190 size_t padsize = et->padsize;
4191 size_t checksumsize = CHECKSUMSIZE(et->checksum);
4194 res = et->confoundersize + checksumsize + data_len;
4195 res = (res + padsize - 1) / padsize * padsize;
4200 wrapped_length_dervied (krb5_context context,
4204 struct encryption_type *et = crypto->et;
4205 size_t padsize = et->padsize;
4208 res = et->confoundersize + data_len;
4209 res = (res + padsize - 1) / padsize * padsize;
4210 if (et->keyed_checksum)
4211 res += et->keyed_checksum->checksumsize;
4213 res += et->checksum->checksumsize;
4218 * Return the size of an encrypted packet of length `data_len'
4222 krb5_get_wrapped_length (krb5_context context,
4226 if (derived_crypto (context, crypto))
4227 return wrapped_length_dervied (context, crypto, data_len);
4229 return wrapped_length (context, crypto, data_len);
4233 * Return the size of an encrypted packet of length `data_len'
4237 crypto_overhead (krb5_context context,
4240 struct encryption_type *et = crypto->et;
4243 res = CHECKSUMSIZE(et->checksum);
4244 res += et->confoundersize;
4245 if (et->padsize > 1)
4251 crypto_overhead_dervied (krb5_context context,
4254 struct encryption_type *et = crypto->et;
4257 if (et->keyed_checksum)
4258 res = CHECKSUMSIZE(et->keyed_checksum);
4260 res = CHECKSUMSIZE(et->checksum);
4261 res += et->confoundersize;
4262 if (et->padsize > 1)
4268 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
4270 if (derived_crypto (context, crypto))
4271 return crypto_overhead_dervied (context, crypto);
4273 return crypto_overhead (context, crypto);
4276 krb5_error_code KRB5_LIB_FUNCTION
4277 krb5_random_to_key(krb5_context context,
4283 krb5_error_code ret;
4284 struct encryption_type *et = _find_enctype(type);
4286 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4287 N_("encryption type %d not supported", ""),
4289 return KRB5_PROG_ETYPE_NOSUPP;
4291 if ((et->keytype->bits + 7) / 8 > size) {
4292 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4293 N_("encryption key %s needs %d bytes "
4294 "of random to make an encryption key "
4296 et->name, (int)et->keytype->size);
4297 return KRB5_PROG_ETYPE_NOSUPP;
4299 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
4302 key->keytype = type;
4303 if (et->keytype->random_to_key)
4304 (*et->keytype->random_to_key)(context, key, data, size);
4306 memcpy(key->keyvalue.data, data, et->keytype->size);
4312 _krb5_pk_octetstring2key(krb5_context context,
4316 const heim_octet_string *c_n,
4317 const heim_octet_string *k_n,
4320 struct encryption_type *et = _find_enctype(type);
4321 krb5_error_code ret;
4322 size_t keylen, offset;
4324 unsigned char counter;
4325 unsigned char shaoutput[20];
4328 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4329 N_("encryption type %d not supported", ""),
4331 return KRB5_PROG_ETYPE_NOSUPP;
4333 keylen = (et->keytype->bits + 7) / 8;
4335 keydata = malloc(keylen);
4336 if (keydata == NULL) {
4337 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4347 SHA1_Update(&m, &counter, 1);
4348 SHA1_Update(&m, dhdata, dhsize);
4350 SHA1_Update(&m, c_n->data, c_n->length);
4352 SHA1_Update(&m, k_n->data, k_n->length);
4353 SHA1_Final(shaoutput, &m);
4355 memcpy((unsigned char *)keydata + offset,
4357 min(keylen - offset, sizeof(shaoutput)));
4359 offset += sizeof(shaoutput);
4361 } while(offset < keylen);
4362 memset(shaoutput, 0, sizeof(shaoutput));
4364 ret = krb5_random_to_key(context, type, keydata, keylen, key);
4365 memset(keydata, 0, sizeof(keylen));
4370 static krb5_error_code
4371 encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
4373 KRB5PrincipalName pn;
4374 krb5_error_code ret;
4377 pn.principalName = p->name;
4378 pn.realm = p->realm;
4380 ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
4383 krb5_data_zero(data);
4384 krb5_set_error_message(context, ret,
4385 N_("Failed to encode KRB5PrincipalName", ""));
4388 if (data->length != size)
4389 krb5_abortx(context, "asn1 compiler internal error");
4393 static krb5_error_code
4394 encode_otherinfo(krb5_context context,
4395 const AlgorithmIdentifier *ai,
4396 krb5_const_principal client,
4397 krb5_const_principal server,
4398 krb5_enctype enctype,
4399 const krb5_data *as_req,
4400 const krb5_data *pk_as_rep,
4401 const Ticket *ticket,
4404 PkinitSP80056AOtherInfo otherinfo;
4405 PkinitSuppPubInfo pubinfo;
4406 krb5_error_code ret;
4410 krb5_data_zero(other);
4411 memset(&otherinfo, 0, sizeof(otherinfo));
4412 memset(&pubinfo, 0, sizeof(pubinfo));
4414 pubinfo.enctype = enctype;
4415 pubinfo.as_REQ = *as_req;
4416 pubinfo.pk_as_rep = *pk_as_rep;
4417 pubinfo.ticket = *ticket;
4418 ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
4419 &pubinfo, &size, ret);
4421 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4424 if (pub.length != size)
4425 krb5_abortx(context, "asn1 compiler internal error");
4427 ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
4432 ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
4434 free(otherinfo.partyUInfo.data);
4439 otherinfo.algorithmID = *ai;
4440 otherinfo.suppPubInfo = &pub;
4442 ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
4443 &otherinfo, &size, ret);
4444 free(otherinfo.partyUInfo.data);
4445 free(otherinfo.partyVInfo.data);
4448 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
4451 if (other->length != size)
4452 krb5_abortx(context, "asn1 compiler internal error");
4458 _krb5_pk_kdf(krb5_context context,
4459 const struct AlgorithmIdentifier *ai,
4462 krb5_const_principal client,
4463 krb5_const_principal server,
4464 krb5_enctype enctype,
4465 const krb5_data *as_req,
4466 const krb5_data *pk_as_rep,
4467 const Ticket *ticket,
4470 struct encryption_type *et;
4471 krb5_error_code ret;
4473 size_t keylen, offset;
4475 unsigned char *keydata;
4476 unsigned char shaoutput[20];
4478 if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai->algorithm) != 0) {
4479 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4480 N_("KDF not supported", ""));
4481 return KRB5_PROG_ETYPE_NOSUPP;
4483 if (ai->parameters != NULL &&
4484 (ai->parameters->length != 2 ||
4485 memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
4487 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4488 N_("kdf params not NULL or the NULL-type",
4490 return KRB5_PROG_ETYPE_NOSUPP;
4493 et = _find_enctype(enctype);
4495 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4496 N_("encryption type %d not supported", ""),
4498 return KRB5_PROG_ETYPE_NOSUPP;
4500 keylen = (et->keytype->bits + 7) / 8;
4502 keydata = malloc(keylen);
4503 if (keydata == NULL) {
4504 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
4508 ret = encode_otherinfo(context, ai, client, server,
4509 enctype, as_req, pk_as_rep, ticket, &other);
4518 unsigned char cdata[4];
4522 _krb5_put_int(cdata, counter, 4);
4523 SHA1_Update(&m, cdata, 4);
4524 SHA1_Update(&m, dhdata, dhsize);
4525 SHA1_Update(&m, other.data, other.length);
4526 SHA1_Final(shaoutput, &m);
4528 memcpy((unsigned char *)keydata + offset,
4530 min(keylen - offset, sizeof(shaoutput)));
4532 offset += sizeof(shaoutput);
4534 } while(offset < keylen);
4535 memset(shaoutput, 0, sizeof(shaoutput));
4539 ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
4540 memset(keydata, 0, sizeof(keylen));
4547 krb5_error_code KRB5_LIB_FUNCTION
4548 krb5_crypto_prf_length(krb5_context context,
4552 struct encryption_type *et = _find_enctype(type);
4554 if(et == NULL || et->prf_length == 0) {
4555 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4556 N_("encryption type %d not supported", ""),
4558 return KRB5_PROG_ETYPE_NOSUPP;
4561 *length = et->prf_length;
4565 krb5_error_code KRB5_LIB_FUNCTION
4566 krb5_crypto_prf(krb5_context context,
4567 const krb5_crypto crypto,
4568 const krb5_data *input,
4571 struct encryption_type *et = crypto->et;
4573 krb5_data_zero(output);
4575 if(et->prf == NULL) {
4576 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
4577 "kerberos prf for %s not supported",
4579 return KRB5_PROG_ETYPE_NOSUPP;
4582 return (*et->prf)(context, crypto, input, output);
4585 #ifndef HEIMDAL_SMALLER
4587 krb5_error_code KRB5_LIB_FUNCTION
4588 krb5_keytype_to_enctypes (krb5_context context,
4589 krb5_keytype keytype,
4598 for (i = num_etypes - 1; i >= 0; --i) {
4599 if (etypes[i]->keytype->type == keytype
4600 && !(etypes[i]->flags & F_PSEUDO)
4601 && krb5_enctype_valid(context, etypes[i]->type) == 0)
4605 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
4606 "Keytype have no mapping");
4607 return KRB5_PROG_KEYTYPE_NOSUPP;
4610 ret = malloc(n * sizeof(*ret));
4611 if (ret == NULL && n != 0) {
4612 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
4616 for (i = num_etypes - 1; i >= 0; --i) {
4617 if (etypes[i]->keytype->type == keytype
4618 && !(etypes[i]->flags & F_PSEUDO)
4619 && krb5_enctype_valid(context, etypes[i]->type) == 0)
4620 ret[n++] = etypes[i]->type;
4627 /* if two enctypes have compatible keys */
4628 krb5_boolean KRB5_LIB_FUNCTION
4629 krb5_enctypes_compatible_keys(krb5_context context,
4630 krb5_enctype etype1,
4631 krb5_enctype etype2)
4634 struct encryption_type *e1 = _find_enctype(etype1);
4635 struct encryption_type *e2 = _find_enctype(etype2);
4636 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
4639 #endif /* HEIMDAL_SMALLER */