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>
39 #define __attribute__(X)
41 #ifndef HEIMDAL_SMALLER
42 #define WEAK_ENCTYPES 1
43 #define DES3_OLD_ENCTYPE 1
47 #ifdef HAVE_OPENSSL /* XXX forward decl for hcrypto glue */
48 const EVP_CIPHER
* _krb5_EVP_hcrypto_aes_128_cts(void);
49 const EVP_CIPHER
* _krb5_EVP_hcrypto_aes_256_cts(void);
50 #define EVP_hcrypto_aes_128_cts _krb5_EVP_hcrypto_aes_128_cts
51 #define EVP_hcrypto_aes_256_cts _krb5_EVP_hcrypto_aes_256_cts
64 struct krb5_crypto_data
{
65 struct encryption_type
*et
;
68 struct key_usage
*key_usage
;
71 #define CRYPTO_ETYPE(C) ((C)->et->type)
73 /* bits for `flags' below */
74 #define F_KEYED 1 /* checksum is keyed */
75 #define F_CPROOF 2 /* checksum is collision proof */
76 #define F_DERIVED 4 /* uses derived keys */
77 #define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
78 #define F_PSEUDO 16 /* not a real protocol type */
79 #define F_SPECIAL 32 /* backwards */
80 #define F_DISABLED 64 /* enctype/checksum disabled */
85 krb5_error_code (*string_to_key
)(krb5_context
, krb5_enctype
, krb5_data
,
86 krb5_salt
, krb5_data
, krb5_keyblock
*);
90 krb5_keytype type
; /* XXX */
95 void (*random_key
)(krb5_context
, krb5_keyblock
*);
96 void (*schedule
)(krb5_context
, struct key_type
*, struct key_data
*);
97 struct salt_type
*string_to_key
;
98 void (*random_to_key
)(krb5_context
, krb5_keyblock
*, const void*, size_t);
99 void (*cleanup
)(krb5_context
, struct key_data
*);
100 const EVP_CIPHER
*(*evp
)(void);
103 struct checksum_type
{
109 krb5_enctype (*checksum
)(krb5_context context
,
110 struct key_data
*key
,
111 const void *buf
, size_t len
,
114 krb5_error_code (*verify
)(krb5_context context
,
115 struct key_data
*key
,
116 const void *buf
, size_t len
,
121 struct encryption_type
{
126 size_t confoundersize
;
127 struct key_type
*keytype
;
128 struct checksum_type
*checksum
;
129 struct checksum_type
*keyed_checksum
;
131 krb5_error_code (*encrypt
)(krb5_context context
,
132 struct key_data
*key
,
133 void *data
, size_t len
,
134 krb5_boolean encryptp
,
138 krb5_error_code (*prf
)(krb5_context
,
139 krb5_crypto
, const krb5_data
*, krb5_data
*);
142 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
143 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
144 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
146 static struct checksum_type
*_find_checksum(krb5_cksumtype type
);
147 static struct encryption_type
*_find_enctype(krb5_enctype type
);
148 static struct key_type
*_find_keytype(krb5_keytype 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 krb5_error_code
usage2arcfour (krb5_context
, unsigned *);
168 static void xor (DES_cblock
*, const unsigned char *);
170 /************************************************************
172 ************************************************************/
174 struct evp_schedule
{
180 static HEIMDAL_MUTEX crypto_mutex
= HEIMDAL_MUTEX_INITIALIZER
;
183 krb5_DES_random_key(krb5_context context
,
186 DES_cblock
*k
= key
->keyvalue
.data
;
188 krb5_generate_random_block(k
, sizeof(DES_cblock
));
189 DES_set_odd_parity(k
);
190 } while(DES_is_weak_key(k
));
195 krb5_DES_schedule_old(krb5_context context
,
197 struct key_data
*key
)
199 DES_set_key_unchecked(key
->key
->keyvalue
.data
, key
->schedule
->data
);
201 #endif /* WEAK_ENCTYPES */
204 #ifdef ENABLE_AFS_STRING_TO_KEY
206 /* This defines the Andrew string_to_key function. It accepts a password
207 * string as input and converts it via a one-way encryption algorithm to a DES
208 * encryption key. It is compatible with the original Andrew authentication
209 * service password database.
213 * Short passwords, i.e 8 characters or less.
216 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw
,
220 char password
[8+1]; /* crypt is limited to 8 chars anyway */
223 for(i
= 0; i
< 8; i
++) {
224 char c
= ((i
< pw
.length
) ? ((char*)pw
.data
)[i
] : 0) ^
226 tolower(((unsigned char*)cell
.data
)[i
]) : 0);
227 password
[i
] = c
? c
: 'X';
231 memcpy(key
, crypt(password
, "p1") + 2, sizeof(DES_cblock
));
233 /* parity is inserted into the LSB so left shift each byte up one
234 bit. This allows ascii characters with a zero MSB to retain as
235 much significance as possible. */
236 for (i
= 0; i
< sizeof(DES_cblock
); i
++)
237 ((unsigned char*)key
)[i
] <<= 1;
238 DES_set_odd_parity (key
);
242 * Long passwords, i.e 9 characters or more.
245 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw
,
249 DES_key_schedule schedule
;
255 memcpy(password
, pw
.data
, min(pw
.length
, sizeof(password
)));
256 if(pw
.length
< sizeof(password
)) {
257 int len
= min(cell
.length
, sizeof(password
) - pw
.length
);
260 memcpy(password
+ pw
.length
, cell
.data
, len
);
261 for (i
= pw
.length
; i
< pw
.length
+ len
; ++i
)
262 password
[i
] = tolower((unsigned char)password
[i
]);
264 passlen
= min(sizeof(password
), pw
.length
+ cell
.length
);
265 memcpy(&ivec
, "kerberos", 8);
266 memcpy(&temp_key
, "kerberos", 8);
267 DES_set_odd_parity (&temp_key
);
268 DES_set_key_unchecked (&temp_key
, &schedule
);
269 DES_cbc_cksum ((void*)password
, &ivec
, passlen
, &schedule
, &ivec
);
271 memcpy(&temp_key
, &ivec
, 8);
272 DES_set_odd_parity (&temp_key
);
273 DES_set_key_unchecked (&temp_key
, &schedule
);
274 DES_cbc_cksum ((void*)password
, key
, passlen
, &schedule
, &ivec
);
275 memset(&schedule
, 0, sizeof(schedule
));
276 memset(&temp_key
, 0, sizeof(temp_key
));
277 memset(&ivec
, 0, sizeof(ivec
));
278 memset(password
, 0, sizeof(password
));
280 DES_set_odd_parity (key
);
283 static krb5_error_code
284 DES_AFS3_string_to_key(krb5_context context
,
285 krb5_enctype enctype
,
292 if(password
.length
> 8)
293 krb5_DES_AFS3_Transarc_string_to_key(password
, salt
.saltvalue
, &tmp
);
295 krb5_DES_AFS3_CMU_string_to_key(password
, salt
.saltvalue
, &tmp
);
296 key
->keytype
= enctype
;
297 krb5_data_copy(&key
->keyvalue
, tmp
, sizeof(tmp
));
298 memset(&key
, 0, sizeof(key
));
301 #endif /* ENABLE_AFS_STRING_TO_KEY */
304 DES_string_to_key_int(unsigned char *data
, size_t length
, DES_cblock
*key
)
306 DES_key_schedule schedule
;
311 unsigned char swap
[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
312 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
315 p
= (unsigned char*)key
;
316 for (i
= 0; i
< length
; i
++) {
317 unsigned char tmp
= data
[i
];
321 *--p
^= (swap
[tmp
& 0xf] << 4) | swap
[(tmp
& 0xf0) >> 4];
325 DES_set_odd_parity(key
);
326 if(DES_is_weak_key(key
))
328 DES_set_key_unchecked(key
, &schedule
);
329 DES_cbc_cksum((void*)data
, key
, length
, &schedule
, key
);
330 memset(&schedule
, 0, sizeof(schedule
));
331 DES_set_odd_parity(key
);
332 if(DES_is_weak_key(key
))
336 static krb5_error_code
337 krb5_DES_string_to_key(krb5_context context
,
338 krb5_enctype enctype
,
348 #ifdef ENABLE_AFS_STRING_TO_KEY
349 if (opaque
.length
== 1) {
351 _krb5_get_int(opaque
.data
, &v
, 1);
353 return DES_AFS3_string_to_key(context
, enctype
, password
,
358 len
= password
.length
+ salt
.saltvalue
.length
;
360 if(len
> 0 && s
== NULL
) {
361 krb5_set_error_message (context
, ENOMEM
, "malloc: out of memory");
364 memcpy(s
, password
.data
, password
.length
);
365 memcpy(s
+ password
.length
, salt
.saltvalue
.data
, salt
.saltvalue
.length
);
366 DES_string_to_key_int(s
, len
, &tmp
);
367 key
->keytype
= enctype
;
368 krb5_data_copy(&key
->keyvalue
, tmp
, sizeof(tmp
));
369 memset(&tmp
, 0, sizeof(tmp
));
376 krb5_DES_random_to_key(krb5_context context
,
381 DES_cblock
*k
= key
->keyvalue
.data
;
382 memcpy(k
, data
, key
->keyvalue
.length
);
383 DES_set_odd_parity(k
);
384 if(DES_is_weak_key(k
))
385 xor(k
, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
393 DES3_random_key(krb5_context context
,
396 DES_cblock
*k
= key
->keyvalue
.data
;
398 krb5_generate_random_block(k
, 3 * sizeof(DES_cblock
));
399 DES_set_odd_parity(&k
[0]);
400 DES_set_odd_parity(&k
[1]);
401 DES_set_odd_parity(&k
[2]);
402 } while(DES_is_weak_key(&k
[0]) ||
403 DES_is_weak_key(&k
[1]) ||
404 DES_is_weak_key(&k
[2]));
408 * A = A xor B. A & B are 8 bytes.
412 xor (DES_cblock
*key
, const unsigned char *b
)
414 unsigned char *a
= (unsigned char*)key
;
425 #ifdef DES3_OLD_ENCTYPE
426 static krb5_error_code
427 DES3_string_to_key(krb5_context context
,
428 krb5_enctype enctype
,
436 unsigned char tmp
[24];
440 len
= password
.length
+ salt
.saltvalue
.length
;
442 if(len
!= 0 && str
== NULL
) {
443 krb5_set_error_message (context
, ENOMEM
, "malloc: out of memory");
446 memcpy(str
, password
.data
, password
.length
);
447 memcpy(str
+ password
.length
, salt
.saltvalue
.data
, salt
.saltvalue
.length
);
450 DES_key_schedule s
[3];
453 ret
= _krb5_n_fold(str
, len
, tmp
, 24);
457 krb5_set_error_message (context
, ret
, "malloc: out of memory");
461 for(i
= 0; i
< 3; i
++){
462 memcpy(keys
+ i
, tmp
+ i
* 8, sizeof(keys
[i
]));
463 DES_set_odd_parity(keys
+ i
);
464 if(DES_is_weak_key(keys
+ i
))
465 xor(keys
+ i
, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
466 DES_set_key_unchecked(keys
+ i
, &s
[i
]);
468 memset(&ivec
, 0, sizeof(ivec
));
469 DES_ede3_cbc_encrypt(tmp
,
471 &s
[0], &s
[1], &s
[2], &ivec
, DES_ENCRYPT
);
472 memset(s
, 0, sizeof(s
));
473 memset(&ivec
, 0, sizeof(ivec
));
474 for(i
= 0; i
< 3; i
++){
475 memcpy(keys
+ i
, tmp
+ i
* 8, sizeof(keys
[i
]));
476 DES_set_odd_parity(keys
+ i
);
477 if(DES_is_weak_key(keys
+ i
))
478 xor(keys
+ i
, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
480 memset(tmp
, 0, sizeof(tmp
));
482 key
->keytype
= enctype
;
483 krb5_data_copy(&key
->keyvalue
, keys
, sizeof(keys
));
484 memset(keys
, 0, sizeof(keys
));
491 static krb5_error_code
492 DES3_string_to_key_derived(krb5_context context
,
493 krb5_enctype enctype
,
500 size_t len
= password
.length
+ salt
.saltvalue
.length
;
504 if(len
!= 0 && s
== NULL
) {
505 krb5_set_error_message (context
, ENOMEM
, "malloc: out of memory");
508 memcpy(s
, password
.data
, password
.length
);
509 memcpy(s
+ password
.length
, salt
.saltvalue
.data
, salt
.saltvalue
.length
);
510 ret
= krb5_string_to_key_derived(context
,
521 DES3_random_to_key(krb5_context context
,
526 unsigned char *x
= key
->keyvalue
.data
;
527 const u_char
*q
= data
;
531 memset(x
, 0, sizeof(x
));
532 for (i
= 0; i
< 3; ++i
) {
534 for (j
= 0; j
< 7; ++j
) {
535 unsigned char b
= q
[7 * i
+ j
];
540 for (j
= 6; j
>= 0; --j
) {
541 foo
|= q
[7 * i
+ j
] & 1;
546 k
= key
->keyvalue
.data
;
547 for (i
= 0; i
< 3; i
++) {
548 DES_set_odd_parity(&k
[i
]);
549 if(DES_is_weak_key(&k
[i
]))
550 xor(&k
[i
], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
559 ARCFOUR_schedule(krb5_context context
,
563 RC4_set_key (kd
->schedule
->data
,
564 kd
->key
->keyvalue
.length
, kd
->key
->keyvalue
.data
);
567 static krb5_error_code
568 ARCFOUR_string_to_key(krb5_context context
,
569 krb5_enctype enctype
,
580 m
= EVP_MD_CTX_create();
583 krb5_set_error_message(context
, ret
, "Malloc: out of memory");
587 EVP_DigestInit_ex(m
, EVP_md4(), NULL
);
589 ret
= wind_utf8ucs2_length(password
.data
, &len
);
591 krb5_set_error_message (context
, ret
, "Password not an UCS2 string");
595 s
= malloc (len
* sizeof(s
[0]));
596 if (len
!= 0 && s
== NULL
) {
597 krb5_set_error_message (context
, ENOMEM
, "malloc: out of memory");
602 ret
= wind_utf8ucs2(password
.data
, s
, &len
);
604 krb5_set_error_message (context
, ret
, "Password not an UCS2 string");
609 for (i
= 0; i
< len
; i
++) {
612 EVP_DigestUpdate (m
, &p
, 1);
613 p
= (s
[i
] >> 8) & 0xff;
614 EVP_DigestUpdate (m
, &p
, 1);
617 key
->keytype
= enctype
;
618 ret
= krb5_data_alloc (&key
->keyvalue
, 16);
620 krb5_set_error_message (context
, ENOMEM
, "malloc: out of memory");
623 EVP_DigestFinal_ex (m
, key
->keyvalue
.data
, NULL
);
626 EVP_MD_CTX_destroy(m
);
637 int _krb5_AES_string_to_default_iterator
= 4096;
639 static krb5_error_code
640 AES_string_to_key(krb5_context context
,
641 krb5_enctype enctype
,
649 struct encryption_type
*et
;
652 if (opaque
.length
== 0)
653 iter
= _krb5_AES_string_to_default_iterator
;
654 else if (opaque
.length
== 4) {
656 _krb5_get_int(opaque
.data
, &v
, 4);
657 iter
= ((uint32_t)v
);
659 return KRB5_PROG_KEYTYPE_NOSUPP
; /* XXX */
661 et
= _find_enctype(enctype
);
663 return KRB5_PROG_KEYTYPE_NOSUPP
;
668 krb5_set_error_message (context
, ENOMEM
, "malloc: out of memory");
671 kd
.key
->keytype
= enctype
;
672 ret
= krb5_data_alloc(&kd
.key
->keyvalue
, et
->keytype
->size
);
674 krb5_set_error_message (context
, ret
, "malloc: out of memory");
678 ret
= PKCS5_PBKDF2_HMAC_SHA1(password
.data
, password
.length
,
679 salt
.saltvalue
.data
, salt
.saltvalue
.length
,
681 et
->keytype
->size
, kd
.key
->keyvalue
.data
);
683 free_key_data(context
, &kd
, et
);
684 krb5_set_error_message(context
, KRB5_PROG_KEYTYPE_NOSUPP
,
685 "Error calculating s2k");
686 return KRB5_PROG_KEYTYPE_NOSUPP
;
689 ret
= derive_key(context
, et
, &kd
, "kerberos", strlen("kerberos"));
691 ret
= krb5_copy_keyblock_contents(context
, kd
.key
, key
);
692 free_key_data(context
, &kd
, et
);
698 evp_schedule(krb5_context context
, struct key_type
*kt
, struct key_data
*kd
)
700 struct evp_schedule
*key
= kd
->schedule
->data
;
701 const EVP_CIPHER
*c
= (*kt
->evp
)();
703 EVP_CIPHER_CTX_init(&key
->ectx
);
704 EVP_CIPHER_CTX_init(&key
->dctx
);
706 EVP_CipherInit_ex(&key
->ectx
, c
, NULL
, kd
->key
->keyvalue
.data
, NULL
, 1);
707 EVP_CipherInit_ex(&key
->dctx
, c
, NULL
, kd
->key
->keyvalue
.data
, NULL
, 0);
711 evp_cleanup(krb5_context context
, struct key_data
*kd
)
713 struct evp_schedule
*key
= kd
->schedule
->data
;
714 EVP_CIPHER_CTX_cleanup(&key
->ectx
);
715 EVP_CIPHER_CTX_cleanup(&key
->dctx
);
722 static struct salt_type des_salt
[] = {
726 krb5_DES_string_to_key
728 #ifdef ENABLE_AFS_STRING_TO_KEY
732 DES_AFS3_string_to_key
738 #ifdef DES3_OLD_ENCTYPE
739 static struct salt_type des3_salt
[] = {
749 static struct salt_type des3_salt_derived
[] = {
753 DES3_string_to_key_derived
758 static struct salt_type AES_salt
[] = {
767 static struct salt_type arcfour_salt
[] = {
771 ARCFOUR_string_to_key
780 static struct key_type keytype_null
= {
792 static struct key_type keytype_des_old
= {
797 sizeof(DES_key_schedule
),
799 krb5_DES_schedule_old
,
801 krb5_DES_random_to_key
803 #endif /* WEAK_ENCTYPES */
805 static struct key_type keytype_des
= {
810 sizeof(struct evp_schedule
),
814 krb5_DES_random_to_key
,
819 #ifdef DES3_OLD_ENCTYPE
820 static struct key_type keytype_des3
= {
825 sizeof(struct evp_schedule
),
835 static struct key_type keytype_des3_derived
= {
840 sizeof(struct evp_schedule
),
849 static struct key_type keytype_aes128
= {
854 sizeof(struct evp_schedule
),
860 EVP_hcrypto_aes_128_cts
863 static struct key_type keytype_aes256
= {
868 sizeof(struct evp_schedule
),
874 EVP_hcrypto_aes_256_cts
877 static struct key_type keytype_arcfour
= {
888 static struct key_type
*keytypes
[] = {
891 &keytype_des3_derived
,
892 #ifdef DES3_OLD_ENCTYPE
900 static int num_keytypes
= sizeof(keytypes
) / sizeof(keytypes
[0]);
902 static struct key_type
*
903 _find_keytype(krb5_keytype type
)
906 for(i
= 0; i
< num_keytypes
; i
++)
907 if(keytypes
[i
]->type
== type
)
913 krb5_error_code KRB5_LIB_FUNCTION
914 krb5_salttype_to_string (krb5_context context
,
919 struct encryption_type
*e
;
920 struct salt_type
*st
;
922 e
= _find_enctype (etype
);
924 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
925 "encryption type %d not supported",
927 return KRB5_PROG_ETYPE_NOSUPP
;
929 for (st
= e
->keytype
->string_to_key
; st
&& st
->type
; st
++) {
930 if (st
->type
== stype
) {
931 *string
= strdup (st
->name
);
932 if (*string
== NULL
) {
933 krb5_set_error_message (context
, ENOMEM
,
934 "malloc: out of memory");
940 krb5_set_error_message (context
, HEIM_ERR_SALTTYPE_NOSUPP
,
941 "salttype %d not supported", stype
);
942 return HEIM_ERR_SALTTYPE_NOSUPP
;
945 krb5_error_code KRB5_LIB_FUNCTION
946 krb5_string_to_salttype (krb5_context context
,
949 krb5_salttype
*salttype
)
951 struct encryption_type
*e
;
952 struct salt_type
*st
;
954 e
= _find_enctype (etype
);
956 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
957 "encryption type %d not supported",
959 return KRB5_PROG_ETYPE_NOSUPP
;
961 for (st
= e
->keytype
->string_to_key
; st
&& st
->type
; st
++) {
962 if (strcasecmp (st
->name
, string
) == 0) {
963 *salttype
= st
->type
;
967 krb5_set_error_message(context
, HEIM_ERR_SALTTYPE_NOSUPP
,
968 "salttype %s not supported", string
);
969 return HEIM_ERR_SALTTYPE_NOSUPP
;
972 krb5_error_code KRB5_LIB_FUNCTION
973 krb5_get_pw_salt(krb5_context context
,
974 krb5_const_principal principal
,
982 salt
->salttype
= KRB5_PW_SALT
;
983 len
= strlen(principal
->realm
);
984 for (i
= 0; i
< principal
->name
.name_string
.len
; ++i
)
985 len
+= strlen(principal
->name
.name_string
.val
[i
]);
986 ret
= krb5_data_alloc (&salt
->saltvalue
, len
);
989 p
= salt
->saltvalue
.data
;
990 memcpy (p
, principal
->realm
, strlen(principal
->realm
));
991 p
+= strlen(principal
->realm
);
992 for (i
= 0; i
< principal
->name
.name_string
.len
; ++i
) {
994 principal
->name
.name_string
.val
[i
],
995 strlen(principal
->name
.name_string
.val
[i
]));
996 p
+= strlen(principal
->name
.name_string
.val
[i
]);
1001 krb5_error_code KRB5_LIB_FUNCTION
1002 krb5_free_salt(krb5_context context
,
1005 krb5_data_free(&salt
.saltvalue
);
1009 krb5_error_code KRB5_LIB_FUNCTION
1010 krb5_string_to_key_data (krb5_context context
,
1011 krb5_enctype enctype
,
1013 krb5_principal principal
,
1016 krb5_error_code ret
;
1019 ret
= krb5_get_pw_salt(context
, principal
, &salt
);
1022 ret
= krb5_string_to_key_data_salt(context
, enctype
, password
, salt
, key
);
1023 krb5_free_salt(context
, salt
);
1027 krb5_error_code KRB5_LIB_FUNCTION
1028 krb5_string_to_key (krb5_context context
,
1029 krb5_enctype enctype
,
1030 const char *password
,
1031 krb5_principal principal
,
1035 pw
.data
= rk_UNCONST(password
);
1036 pw
.length
= strlen(password
);
1037 return krb5_string_to_key_data(context
, enctype
, pw
, principal
, key
);
1040 krb5_error_code KRB5_LIB_FUNCTION
1041 krb5_string_to_key_data_salt (krb5_context context
,
1042 krb5_enctype enctype
,
1048 krb5_data_zero(&opaque
);
1049 return krb5_string_to_key_data_salt_opaque(context
, enctype
, password
,
1054 * Do a string -> key for encryption type `enctype' operation on
1055 * `password' (with salt `salt' and the enctype specific data string
1056 * `opaque'), returning the resulting key in `key'
1059 krb5_error_code KRB5_LIB_FUNCTION
1060 krb5_string_to_key_data_salt_opaque (krb5_context context
,
1061 krb5_enctype enctype
,
1067 struct encryption_type
*et
=_find_enctype(enctype
);
1068 struct salt_type
*st
;
1070 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
1071 "encryption type %d not supported",
1073 return KRB5_PROG_ETYPE_NOSUPP
;
1075 for(st
= et
->keytype
->string_to_key
; st
&& st
->type
; st
++)
1076 if(st
->type
== salt
.salttype
)
1077 return (*st
->string_to_key
)(context
, enctype
, password
,
1079 krb5_set_error_message(context
, HEIM_ERR_SALTTYPE_NOSUPP
,
1080 "salt type %d not supported",
1082 return HEIM_ERR_SALTTYPE_NOSUPP
;
1086 * Do a string -> key for encryption type `enctype' operation on the
1087 * string `password' (with salt `salt'), returning the resulting key
1091 krb5_error_code KRB5_LIB_FUNCTION
1092 krb5_string_to_key_salt (krb5_context context
,
1093 krb5_enctype enctype
,
1094 const char *password
,
1099 pw
.data
= rk_UNCONST(password
);
1100 pw
.length
= strlen(password
);
1101 return krb5_string_to_key_data_salt(context
, enctype
, pw
, salt
, key
);
1104 krb5_error_code KRB5_LIB_FUNCTION
1105 krb5_string_to_key_salt_opaque (krb5_context context
,
1106 krb5_enctype enctype
,
1107 const char *password
,
1113 pw
.data
= rk_UNCONST(password
);
1114 pw
.length
= strlen(password
);
1115 return krb5_string_to_key_data_salt_opaque(context
, enctype
,
1116 pw
, salt
, opaque
, key
);
1119 krb5_error_code KRB5_LIB_FUNCTION
1120 krb5_enctype_keysize(krb5_context context
,
1124 struct encryption_type
*et
= _find_enctype(type
);
1126 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
1127 "encryption type %d not supported",
1129 return KRB5_PROG_ETYPE_NOSUPP
;
1131 *keysize
= et
->keytype
->size
;
1135 krb5_error_code KRB5_LIB_FUNCTION
1136 krb5_enctype_keybits(krb5_context context
,
1140 struct encryption_type
*et
= _find_enctype(type
);
1142 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
1143 "encryption type %d not supported",
1145 return KRB5_PROG_ETYPE_NOSUPP
;
1147 *keybits
= et
->keytype
->bits
;
1151 krb5_error_code KRB5_LIB_FUNCTION
1152 krb5_generate_random_keyblock(krb5_context context
,
1156 krb5_error_code ret
;
1157 struct encryption_type
*et
= _find_enctype(type
);
1159 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
1160 "encryption type %d not supported",
1162 return KRB5_PROG_ETYPE_NOSUPP
;
1164 ret
= krb5_data_alloc(&key
->keyvalue
, et
->keytype
->size
);
1167 key
->keytype
= type
;
1168 if(et
->keytype
->random_key
)
1169 (*et
->keytype
->random_key
)(context
, key
);
1171 krb5_generate_random_block(key
->keyvalue
.data
,
1172 key
->keyvalue
.length
);
1176 static krb5_error_code
1177 _key_schedule(krb5_context context
,
1178 struct key_data
*key
)
1180 krb5_error_code ret
;
1181 struct encryption_type
*et
= _find_enctype(key
->key
->keytype
);
1182 struct key_type
*kt
= et
->keytype
;
1184 if(kt
->schedule
== NULL
)
1186 if (key
->schedule
!= NULL
)
1188 ALLOC(key
->schedule
, 1);
1189 if(key
->schedule
== NULL
) {
1190 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
1193 ret
= krb5_data_alloc(key
->schedule
, kt
->schedule_size
);
1195 free(key
->schedule
);
1196 key
->schedule
= NULL
;
1199 (*kt
->schedule
)(context
, kt
, key
);
1203 /************************************************************
1205 ************************************************************/
1207 static krb5_error_code
1208 NONE_checksum(krb5_context context
,
1209 struct key_data
*key
,
1218 static krb5_error_code
1219 CRC32_checksum(krb5_context context
,
1220 struct key_data
*key
,
1227 unsigned char *r
= C
->checksum
.data
;
1228 _krb5_crc_init_table ();
1229 crc
= _krb5_crc_update (data
, len
, 0);
1231 r
[1] = (crc
>> 8) & 0xff;
1232 r
[2] = (crc
>> 16) & 0xff;
1233 r
[3] = (crc
>> 24) & 0xff;
1237 static krb5_error_code
1238 RSA_MD4_checksum(krb5_context context
,
1239 struct key_data
*key
,
1245 if (EVP_Digest(data
, len
, C
->checksum
.data
, NULL
, EVP_md4(), NULL
) != 1)
1246 krb5_abortx(context
, "md4 checksum failed");
1250 static krb5_error_code
1251 des_checksum(krb5_context context
,
1252 const EVP_MD
*evp_md
,
1253 struct key_data
*key
,
1258 struct evp_schedule
*ctx
= key
->schedule
->data
;
1261 unsigned char *p
= cksum
->checksum
.data
;
1263 krb5_generate_random_block(p
, 8);
1265 m
= EVP_MD_CTX_create();
1267 krb5_set_error_message(context
, ENOMEM
, "Malloc: out of memory");
1271 EVP_DigestInit_ex(m
, evp_md
, NULL
);
1272 EVP_DigestUpdate(m
, p
, 8);
1273 EVP_DigestUpdate(m
, data
, len
);
1274 EVP_DigestFinal_ex (m
, p
+ 8, NULL
);
1275 EVP_MD_CTX_destroy(m
);
1276 memset (&ivec
, 0, sizeof(ivec
));
1277 EVP_CipherInit_ex(&ctx
->ectx
, NULL
, NULL
, NULL
, (void *)&ivec
, -1);
1278 EVP_Cipher(&ctx
->ectx
, p
, p
, 24);
1283 static krb5_error_code
1284 des_verify(krb5_context context
,
1285 const EVP_MD
*evp_md
,
1286 struct key_data
*key
,
1291 struct evp_schedule
*ctx
= key
->schedule
->data
;
1293 unsigned char tmp
[24];
1294 unsigned char res
[16];
1296 krb5_error_code ret
= 0;
1298 m
= EVP_MD_CTX_create();
1300 krb5_set_error_message(context
, ENOMEM
, "Malloc: out of memory");
1304 memset(&ivec
, 0, sizeof(ivec
));
1305 EVP_CipherInit_ex(&ctx
->dctx
, NULL
, NULL
, NULL
, (void *)&ivec
, -1);
1306 EVP_Cipher(&ctx
->dctx
, tmp
, C
->checksum
.data
, 24);
1308 EVP_DigestInit_ex(m
, evp_md
, NULL
);
1309 EVP_DigestUpdate(m
, tmp
, 8); /* confounder */
1310 EVP_DigestUpdate(m
, data
, len
);
1311 EVP_DigestFinal_ex (m
, res
, NULL
);
1312 EVP_MD_CTX_destroy(m
);
1313 if(memcmp(res
, tmp
+ 8, sizeof(res
)) != 0) {
1314 krb5_clear_error_string (context
);
1315 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
1317 memset(tmp
, 0, sizeof(tmp
));
1318 memset(res
, 0, sizeof(res
));
1322 static krb5_error_code
1323 RSA_MD4_DES_checksum(krb5_context context
,
1324 struct key_data
*key
,
1330 return des_checksum(context
, EVP_md4(), key
, data
, len
, cksum
);
1333 static krb5_error_code
1334 RSA_MD4_DES_verify(krb5_context context
,
1335 struct key_data
*key
,
1341 return des_verify(context
, EVP_md5(), key
, data
, len
, C
);
1344 static krb5_error_code
1345 RSA_MD5_checksum(krb5_context context
,
1346 struct key_data
*key
,
1352 if (EVP_Digest(data
, len
, C
->checksum
.data
, NULL
, EVP_md5(), NULL
) != 1)
1353 krb5_abortx(context
, "md5 checksum failed");
1357 static krb5_error_code
1358 RSA_MD5_DES_checksum(krb5_context context
,
1359 struct key_data
*key
,
1365 return des_checksum(context
, EVP_md5(), key
, data
, len
, C
);
1368 static krb5_error_code
1369 RSA_MD5_DES_verify(krb5_context context
,
1370 struct key_data
*key
,
1376 return des_verify(context
, EVP_md5(), key
, data
, len
, C
);
1379 static krb5_error_code
1380 RSA_MD5_DES3_checksum(krb5_context context
,
1381 struct key_data
*key
,
1387 return des_checksum(context
, EVP_md5(), key
, data
, len
, C
);
1390 static krb5_error_code
1391 RSA_MD5_DES3_verify(krb5_context context
,
1392 struct key_data
*key
,
1398 return des_verify(context
, EVP_md5(), key
, data
, len
, C
);
1401 static krb5_error_code
1402 SHA1_checksum(krb5_context context
,
1403 struct key_data
*key
,
1409 if (EVP_Digest(data
, len
, C
->checksum
.data
, NULL
, EVP_sha1(), NULL
) != 1)
1410 krb5_abortx(context
, "sha1 checksum failed");
1414 /* HMAC according to RFC2104 */
1415 static krb5_error_code
1416 hmac(krb5_context context
,
1417 struct checksum_type
*cm
,
1421 struct key_data
*keyblock
,
1424 unsigned char *ipad
, *opad
;
1429 ipad
= malloc(cm
->blocksize
+ len
);
1432 opad
= malloc(cm
->blocksize
+ cm
->checksumsize
);
1437 memset(ipad
, 0x36, cm
->blocksize
);
1438 memset(opad
, 0x5c, cm
->blocksize
);
1440 if(keyblock
->key
->keyvalue
.length
> cm
->blocksize
){
1441 (*cm
->checksum
)(context
,
1443 keyblock
->key
->keyvalue
.data
,
1444 keyblock
->key
->keyvalue
.length
,
1447 key
= result
->checksum
.data
;
1448 key_len
= result
->checksum
.length
;
1450 key
= keyblock
->key
->keyvalue
.data
;
1451 key_len
= keyblock
->key
->keyvalue
.length
;
1453 for(i
= 0; i
< key_len
; i
++){
1457 memcpy(ipad
+ cm
->blocksize
, data
, len
);
1458 (*cm
->checksum
)(context
, keyblock
, ipad
, cm
->blocksize
+ len
,
1460 memcpy(opad
+ cm
->blocksize
, result
->checksum
.data
,
1461 result
->checksum
.length
);
1462 (*cm
->checksum
)(context
, keyblock
, opad
,
1463 cm
->blocksize
+ cm
->checksumsize
, usage
, result
);
1464 memset(ipad
, 0, cm
->blocksize
+ len
);
1466 memset(opad
, 0, cm
->blocksize
+ cm
->checksumsize
);
1472 krb5_error_code KRB5_LIB_FUNCTION
1473 krb5_hmac(krb5_context context
,
1474 krb5_cksumtype cktype
,
1481 struct checksum_type
*c
= _find_checksum(cktype
);
1483 krb5_error_code ret
;
1486 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1487 "checksum type %d not supported",
1489 return KRB5_PROG_SUMTYPE_NOSUPP
;
1495 ret
= hmac(context
, c
, data
, len
, usage
, &kd
, result
);
1498 krb5_free_data(context
, kd
.schedule
);
1503 static krb5_error_code
1504 SP_HMAC_SHA1_checksum(krb5_context context
,
1505 struct key_data
*key
,
1511 struct checksum_type
*c
= _find_checksum(CKSUMTYPE_SHA1
);
1514 krb5_error_code ret
;
1516 res
.checksum
.data
= sha1_data
;
1517 res
.checksum
.length
= sizeof(sha1_data
);
1519 ret
= hmac(context
, c
, data
, len
, usage
, key
, &res
);
1521 krb5_abortx(context
, "hmac failed");
1522 memcpy(result
->checksum
.data
, res
.checksum
.data
, result
->checksum
.length
);
1527 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1530 static krb5_error_code
1531 HMAC_MD5_checksum(krb5_context context
,
1532 struct key_data
*key
,
1539 struct checksum_type
*c
= _find_checksum (CKSUMTYPE_RSA_MD5
);
1540 const char signature
[] = "signaturekey";
1542 struct key_data ksign
;
1545 unsigned char tmp
[16];
1546 unsigned char ksign_c_data
[16];
1547 krb5_error_code ret
;
1549 m
= EVP_MD_CTX_create();
1551 krb5_set_error_message(context
, ENOMEM
, "Malloc: out of memory");
1554 ksign_c
.checksum
.length
= sizeof(ksign_c_data
);
1555 ksign_c
.checksum
.data
= ksign_c_data
;
1556 ret
= hmac(context
, c
, signature
, sizeof(signature
), 0, key
, &ksign_c
);
1558 EVP_MD_CTX_destroy(m
);
1562 kb
.keyvalue
= ksign_c
.checksum
;
1563 EVP_DigestInit_ex(m
, EVP_md5(), NULL
);
1564 t
[0] = (usage
>> 0) & 0xFF;
1565 t
[1] = (usage
>> 8) & 0xFF;
1566 t
[2] = (usage
>> 16) & 0xFF;
1567 t
[3] = (usage
>> 24) & 0xFF;
1568 EVP_DigestUpdate(m
, t
, 4);
1569 EVP_DigestUpdate(m
, data
, len
);
1570 EVP_DigestFinal_ex (m
, tmp
, NULL
);
1571 EVP_MD_CTX_destroy(m
);
1573 ret
= hmac(context
, c
, tmp
, sizeof(tmp
), 0, &ksign
, result
);
1579 static struct checksum_type checksum_none
= {
1588 static struct checksum_type checksum_crc32
= {
1597 static struct checksum_type checksum_rsa_md4
= {
1606 static struct checksum_type checksum_rsa_md4_des
= {
1607 CKSUMTYPE_RSA_MD4_DES
,
1611 F_KEYED
| F_CPROOF
| F_VARIANT
,
1612 RSA_MD4_DES_checksum
,
1615 static struct checksum_type checksum_rsa_md5
= {
1624 static struct checksum_type checksum_rsa_md5_des
= {
1625 CKSUMTYPE_RSA_MD5_DES
,
1629 F_KEYED
| F_CPROOF
| F_VARIANT
,
1630 RSA_MD5_DES_checksum
,
1633 #ifdef DES3_OLD_ENCTYPE
1634 static struct checksum_type checksum_rsa_md5_des3
= {
1635 CKSUMTYPE_RSA_MD5_DES3
,
1639 F_KEYED
| F_CPROOF
| F_VARIANT
,
1640 RSA_MD5_DES3_checksum
,
1644 static struct checksum_type checksum_sha1
= {
1653 static struct checksum_type checksum_hmac_sha1_des3
= {
1654 CKSUMTYPE_HMAC_SHA1_DES3
,
1658 F_KEYED
| F_CPROOF
| F_DERIVED
,
1659 SP_HMAC_SHA1_checksum
,
1663 static struct checksum_type checksum_hmac_sha1_aes128
= {
1664 CKSUMTYPE_HMAC_SHA1_96_AES_128
,
1665 "hmac-sha1-96-aes128",
1668 F_KEYED
| F_CPROOF
| F_DERIVED
,
1669 SP_HMAC_SHA1_checksum
,
1673 static struct checksum_type checksum_hmac_sha1_aes256
= {
1674 CKSUMTYPE_HMAC_SHA1_96_AES_256
,
1675 "hmac-sha1-96-aes256",
1678 F_KEYED
| F_CPROOF
| F_DERIVED
,
1679 SP_HMAC_SHA1_checksum
,
1683 static struct checksum_type checksum_hmac_md5
= {
1693 static struct checksum_type
*checksum_types
[] = {
1697 &checksum_rsa_md4_des
,
1699 &checksum_rsa_md5_des
,
1700 #ifdef DES3_OLD_ENCTYPE
1701 &checksum_rsa_md5_des3
,
1704 &checksum_hmac_sha1_des3
,
1705 &checksum_hmac_sha1_aes128
,
1706 &checksum_hmac_sha1_aes256
,
1710 static int num_checksums
= sizeof(checksum_types
) / sizeof(checksum_types
[0]);
1712 static struct checksum_type
*
1713 _find_checksum(krb5_cksumtype type
)
1716 for(i
= 0; i
< num_checksums
; i
++)
1717 if(checksum_types
[i
]->type
== type
)
1718 return checksum_types
[i
];
1722 static krb5_error_code
1723 get_checksum_key(krb5_context context
,
1725 unsigned usage
, /* not krb5_key_usage */
1726 struct checksum_type
*ct
,
1727 struct key_data
**key
)
1729 krb5_error_code ret
= 0;
1731 if(ct
->flags
& F_DERIVED
)
1732 ret
= _get_derived_key(context
, crypto
, usage
, key
);
1733 else if(ct
->flags
& F_VARIANT
) {
1736 *key
= _new_derived_key(crypto
, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1738 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
1741 ret
= krb5_copy_keyblock(context
, crypto
->key
.key
, &(*key
)->key
);
1744 for(i
= 0; i
< (*key
)->key
->keyvalue
.length
; i
++)
1745 ((unsigned char*)(*key
)->key
->keyvalue
.data
)[i
] ^= 0xF0;
1747 *key
= &crypto
->key
;
1750 ret
= _key_schedule(context
, *key
);
1754 static krb5_error_code
1755 create_checksum (krb5_context context
,
1756 struct checksum_type
*ct
,
1763 krb5_error_code ret
;
1764 struct key_data
*dkey
;
1767 if (ct
->flags
& F_DISABLED
) {
1768 krb5_clear_error_string (context
);
1769 return KRB5_PROG_SUMTYPE_NOSUPP
;
1771 keyed_checksum
= (ct
->flags
& F_KEYED
) != 0;
1772 if(keyed_checksum
&& crypto
== NULL
) {
1773 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1774 "Checksum type %s is keyed "
1775 "but no crypto context (key) was passed in",
1777 return KRB5_PROG_SUMTYPE_NOSUPP
; /* XXX */
1779 if(keyed_checksum
) {
1780 ret
= get_checksum_key(context
, crypto
, usage
, ct
, &dkey
);
1785 result
->cksumtype
= ct
->type
;
1786 ret
= krb5_data_alloc(&result
->checksum
, ct
->checksumsize
);
1789 return (*ct
->checksum
)(context
, dkey
, data
, len
, usage
, result
);
1793 arcfour_checksum_p(struct checksum_type
*ct
, krb5_crypto crypto
)
1795 return (ct
->type
== CKSUMTYPE_HMAC_MD5
) &&
1796 (crypto
->key
.key
->keytype
== KEYTYPE_ARCFOUR
);
1799 krb5_error_code KRB5_LIB_FUNCTION
1800 krb5_create_checksum(krb5_context context
,
1802 krb5_key_usage usage
,
1808 struct checksum_type
*ct
= NULL
;
1811 /* type 0 -> pick from crypto */
1813 ct
= _find_checksum(type
);
1814 } else if (crypto
) {
1815 ct
= crypto
->et
->keyed_checksum
;
1817 ct
= crypto
->et
->checksum
;
1821 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1822 "checksum type %d not supported",
1824 return KRB5_PROG_SUMTYPE_NOSUPP
;
1827 if (arcfour_checksum_p(ct
, crypto
)) {
1829 usage2arcfour(context
, &keyusage
);
1831 keyusage
= CHECKSUM_USAGE(usage
);
1833 return create_checksum(context
, ct
, crypto
, keyusage
,
1837 static krb5_error_code
1838 verify_checksum(krb5_context context
,
1840 unsigned usage
, /* not krb5_key_usage */
1845 krb5_error_code ret
;
1846 struct key_data
*dkey
;
1849 struct checksum_type
*ct
;
1851 ct
= _find_checksum(cksum
->cksumtype
);
1852 if (ct
== NULL
|| (ct
->flags
& F_DISABLED
)) {
1853 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1854 "checksum type %d not supported",
1856 return KRB5_PROG_SUMTYPE_NOSUPP
;
1858 if(ct
->checksumsize
!= cksum
->checksum
.length
) {
1859 krb5_clear_error_string (context
);
1860 return KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* XXX */
1862 keyed_checksum
= (ct
->flags
& F_KEYED
) != 0;
1863 if(keyed_checksum
&& crypto
== NULL
) {
1864 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1865 "Checksum type %s is keyed "
1866 "but no crypto context (key) was passed in",
1868 return KRB5_PROG_SUMTYPE_NOSUPP
; /* XXX */
1870 if(keyed_checksum
) {
1871 ret
= get_checksum_key(context
, crypto
, usage
, ct
, &dkey
);
1877 return (*ct
->verify
)(context
, dkey
, data
, len
, usage
, cksum
);
1879 ret
= krb5_data_alloc (&c
.checksum
, ct
->checksumsize
);
1883 ret
= (*ct
->checksum
)(context
, dkey
, data
, len
, usage
, &c
);
1885 krb5_data_free(&c
.checksum
);
1889 if(c
.checksum
.length
!= cksum
->checksum
.length
||
1890 memcmp(c
.checksum
.data
, cksum
->checksum
.data
, c
.checksum
.length
)) {
1891 krb5_clear_error_string (context
);
1892 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
1896 krb5_data_free (&c
.checksum
);
1900 krb5_error_code KRB5_LIB_FUNCTION
1901 krb5_verify_checksum(krb5_context context
,
1903 krb5_key_usage usage
,
1908 struct checksum_type
*ct
;
1911 ct
= _find_checksum(cksum
->cksumtype
);
1913 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1914 "checksum type %d not supported",
1916 return KRB5_PROG_SUMTYPE_NOSUPP
;
1919 if (arcfour_checksum_p(ct
, crypto
)) {
1921 usage2arcfour(context
, &keyusage
);
1923 keyusage
= CHECKSUM_USAGE(usage
);
1925 return verify_checksum(context
, crypto
, keyusage
,
1929 krb5_error_code KRB5_LIB_FUNCTION
1930 krb5_crypto_get_checksum_type(krb5_context context
,
1932 krb5_cksumtype
*type
)
1934 struct checksum_type
*ct
= NULL
;
1936 if (crypto
!= NULL
) {
1937 ct
= crypto
->et
->keyed_checksum
;
1939 ct
= crypto
->et
->checksum
;
1943 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1944 "checksum type not found");
1945 return KRB5_PROG_SUMTYPE_NOSUPP
;
1954 krb5_error_code KRB5_LIB_FUNCTION
1955 krb5_checksumsize(krb5_context context
,
1956 krb5_cksumtype type
,
1959 struct checksum_type
*ct
= _find_checksum(type
);
1961 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1962 "checksum type %d not supported",
1964 return KRB5_PROG_SUMTYPE_NOSUPP
;
1966 *size
= ct
->checksumsize
;
1970 krb5_boolean KRB5_LIB_FUNCTION
1971 krb5_checksum_is_keyed(krb5_context context
,
1972 krb5_cksumtype type
)
1974 struct checksum_type
*ct
= _find_checksum(type
);
1977 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1978 "checksum type %d not supported",
1980 return KRB5_PROG_SUMTYPE_NOSUPP
;
1982 return ct
->flags
& F_KEYED
;
1985 krb5_boolean KRB5_LIB_FUNCTION
1986 krb5_checksum_is_collision_proof(krb5_context context
,
1987 krb5_cksumtype type
)
1989 struct checksum_type
*ct
= _find_checksum(type
);
1992 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
1993 "checksum type %d not supported",
1995 return KRB5_PROG_SUMTYPE_NOSUPP
;
1997 return ct
->flags
& F_CPROOF
;
2000 krb5_error_code KRB5_LIB_FUNCTION
2001 krb5_checksum_disable(krb5_context context
,
2002 krb5_cksumtype type
)
2004 struct checksum_type
*ct
= _find_checksum(type
);
2007 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
2008 "checksum type %d not supported",
2010 return KRB5_PROG_SUMTYPE_NOSUPP
;
2012 ct
->flags
|= F_DISABLED
;
2016 /************************************************************
2018 ************************************************************/
2020 static krb5_error_code
2021 NULL_encrypt(krb5_context context
,
2022 struct key_data
*key
,
2025 krb5_boolean encryptp
,
2032 static krb5_error_code
2033 evp_encrypt(krb5_context context
,
2034 struct key_data
*key
,
2037 krb5_boolean encryptp
,
2041 struct evp_schedule
*ctx
= key
->schedule
->data
;
2043 c
= encryptp
? &ctx
->ectx
: &ctx
->dctx
;
2046 size_t len
= EVP_CIPHER_CTX_iv_length(c
);
2047 void *loiv
= malloc(len
);
2049 krb5_clear_error_string(context
);
2052 memset(loiv
, 0, len
);
2053 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, loiv
, -1);
2056 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, ivec
, -1);
2057 EVP_Cipher(c
, data
, data
, len
);
2061 #ifdef WEAK_ENCTYPES
2062 static krb5_error_code
2063 evp_des_encrypt_null_ivec(krb5_context context
,
2064 struct key_data
*key
,
2067 krb5_boolean encryptp
,
2071 struct evp_schedule
*ctx
= key
->schedule
->data
;
2074 memset(&ivec
, 0, sizeof(ivec
));
2075 c
= encryptp
? &ctx
->ectx
: &ctx
->dctx
;
2076 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, (void *)&ivec
, -1);
2077 EVP_Cipher(c
, data
, data
, len
);
2081 static krb5_error_code
2082 evp_des_encrypt_key_ivec(krb5_context context
,
2083 struct key_data
*key
,
2086 krb5_boolean encryptp
,
2090 struct evp_schedule
*ctx
= key
->schedule
->data
;
2093 memcpy(&ivec
, key
->key
->keyvalue
.data
, sizeof(ivec
));
2094 c
= encryptp
? &ctx
->ectx
: &ctx
->dctx
;
2095 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, (void *)&ivec
, -1);
2096 EVP_Cipher(c
, data
, data
, len
);
2100 static krb5_error_code
2101 DES_CFB64_encrypt_null_ivec(krb5_context context
,
2102 struct key_data
*key
,
2105 krb5_boolean encryptp
,
2111 DES_key_schedule
*s
= key
->schedule
->data
;
2112 memset(&ivec
, 0, sizeof(ivec
));
2114 DES_cfb64_encrypt(data
, data
, len
, s
, &ivec
, &num
, encryptp
);
2118 static krb5_error_code
2119 DES_PCBC_encrypt_key_ivec(krb5_context context
,
2120 struct key_data
*key
,
2123 krb5_boolean encryptp
,
2128 DES_key_schedule
*s
= key
->schedule
->data
;
2129 memcpy(&ivec
, key
->key
->keyvalue
.data
, sizeof(ivec
));
2131 DES_pcbc_encrypt(data
, data
, len
, s
, &ivec
, encryptp
);
2137 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
2139 * warning: not for small children
2142 static krb5_error_code
2143 ARCFOUR_subencrypt(krb5_context context
,
2144 struct key_data
*key
,
2150 struct checksum_type
*c
= _find_checksum (CKSUMTYPE_RSA_MD5
);
2151 Checksum k1_c
, k2_c
, k3_c
, cksum
;
2156 unsigned char *cdata
= data
;
2157 unsigned char k1_c_data
[16], k2_c_data
[16], k3_c_data
[16];
2158 krb5_error_code ret
;
2160 t
[0] = (usage
>> 0) & 0xFF;
2161 t
[1] = (usage
>> 8) & 0xFF;
2162 t
[2] = (usage
>> 16) & 0xFF;
2163 t
[3] = (usage
>> 24) & 0xFF;
2165 k1_c
.checksum
.length
= sizeof(k1_c_data
);
2166 k1_c
.checksum
.data
= k1_c_data
;
2168 ret
= hmac(NULL
, c
, t
, sizeof(t
), 0, key
, &k1_c
);
2170 krb5_abortx(context
, "hmac failed");
2172 memcpy (k2_c_data
, k1_c_data
, sizeof(k1_c_data
));
2174 k2_c
.checksum
.length
= sizeof(k2_c_data
);
2175 k2_c
.checksum
.data
= k2_c_data
;
2178 kb
.keyvalue
= k2_c
.checksum
;
2180 cksum
.checksum
.length
= 16;
2181 cksum
.checksum
.data
= data
;
2183 ret
= hmac(NULL
, c
, cdata
+ 16, len
- 16, 0, &ke
, &cksum
);
2185 krb5_abortx(context
, "hmac failed");
2188 kb
.keyvalue
= k1_c
.checksum
;
2190 k3_c
.checksum
.length
= sizeof(k3_c_data
);
2191 k3_c
.checksum
.data
= k3_c_data
;
2193 ret
= hmac(NULL
, c
, data
, 16, 0, &ke
, &k3_c
);
2195 krb5_abortx(context
, "hmac failed");
2197 RC4_set_key (&rc4_key
, k3_c
.checksum
.length
, k3_c
.checksum
.data
);
2198 RC4 (&rc4_key
, len
- 16, cdata
+ 16, cdata
+ 16);
2199 memset (k1_c_data
, 0, sizeof(k1_c_data
));
2200 memset (k2_c_data
, 0, sizeof(k2_c_data
));
2201 memset (k3_c_data
, 0, sizeof(k3_c_data
));
2205 static krb5_error_code
2206 ARCFOUR_subdecrypt(krb5_context context
,
2207 struct key_data
*key
,
2213 struct checksum_type
*c
= _find_checksum (CKSUMTYPE_RSA_MD5
);
2214 Checksum k1_c
, k2_c
, k3_c
, cksum
;
2219 unsigned char *cdata
= data
;
2220 unsigned char k1_c_data
[16], k2_c_data
[16], k3_c_data
[16];
2221 unsigned char cksum_data
[16];
2222 krb5_error_code ret
;
2224 t
[0] = (usage
>> 0) & 0xFF;
2225 t
[1] = (usage
>> 8) & 0xFF;
2226 t
[2] = (usage
>> 16) & 0xFF;
2227 t
[3] = (usage
>> 24) & 0xFF;
2229 k1_c
.checksum
.length
= sizeof(k1_c_data
);
2230 k1_c
.checksum
.data
= k1_c_data
;
2232 ret
= hmac(NULL
, c
, t
, sizeof(t
), 0, key
, &k1_c
);
2234 krb5_abortx(context
, "hmac failed");
2236 memcpy (k2_c_data
, k1_c_data
, sizeof(k1_c_data
));
2238 k2_c
.checksum
.length
= sizeof(k2_c_data
);
2239 k2_c
.checksum
.data
= k2_c_data
;
2242 kb
.keyvalue
= k1_c
.checksum
;
2244 k3_c
.checksum
.length
= sizeof(k3_c_data
);
2245 k3_c
.checksum
.data
= k3_c_data
;
2247 ret
= hmac(NULL
, c
, cdata
, 16, 0, &ke
, &k3_c
);
2249 krb5_abortx(context
, "hmac failed");
2251 RC4_set_key (&rc4_key
, k3_c
.checksum
.length
, k3_c
.checksum
.data
);
2252 RC4 (&rc4_key
, len
- 16, cdata
+ 16, cdata
+ 16);
2255 kb
.keyvalue
= k2_c
.checksum
;
2257 cksum
.checksum
.length
= 16;
2258 cksum
.checksum
.data
= cksum_data
;
2260 ret
= hmac(NULL
, c
, cdata
+ 16, len
- 16, 0, &ke
, &cksum
);
2262 krb5_abortx(context
, "hmac failed");
2264 memset (k1_c_data
, 0, sizeof(k1_c_data
));
2265 memset (k2_c_data
, 0, sizeof(k2_c_data
));
2266 memset (k3_c_data
, 0, sizeof(k3_c_data
));
2268 if (memcmp (cksum
.checksum
.data
, data
, 16) != 0) {
2269 krb5_clear_error_string (context
);
2270 return KRB5KRB_AP_ERR_BAD_INTEGRITY
;
2277 * convert the usage numbers used in
2278 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2279 * draft-brezak-win2k-krb-rc4-hmac-04.txt
2282 static krb5_error_code
2283 usage2arcfour (krb5_context context
, unsigned *usage
)
2286 case KRB5_KU_AS_REP_ENC_PART
: /* 3 */
2287 case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY
: /* 9 */
2290 case KRB5_KU_USAGE_SEAL
: /* 22 */
2293 case KRB5_KU_USAGE_SIGN
: /* 23 */
2296 case KRB5_KU_USAGE_SEQ
: /* 24 */
2304 static krb5_error_code
2305 ARCFOUR_encrypt(krb5_context context
,
2306 struct key_data
*key
,
2309 krb5_boolean encryptp
,
2313 krb5_error_code ret
;
2314 unsigned keyusage
= usage
;
2316 if((ret
= usage2arcfour (context
, &keyusage
)) != 0)
2320 return ARCFOUR_subencrypt (context
, key
, data
, len
, keyusage
, ivec
);
2322 return ARCFOUR_subdecrypt (context
, key
, data
, len
, keyusage
, ivec
);
2330 static krb5_error_code
2331 AES_PRF(krb5_context context
,
2333 const krb5_data
*in
,
2336 struct checksum_type
*ct
= crypto
->et
->checksum
;
2337 krb5_error_code ret
;
2339 krb5_keyblock
*derived
;
2341 result
.cksumtype
= ct
->type
;
2342 ret
= krb5_data_alloc(&result
.checksum
, ct
->checksumsize
);
2344 krb5_set_error_message(context
, ret
, "out memory");
2348 ret
= (*ct
->checksum
)(context
, NULL
, in
->data
, in
->length
, 0, &result
);
2350 krb5_data_free(&result
.checksum
);
2354 if (result
.checksum
.length
< crypto
->et
->blocksize
)
2355 krb5_abortx(context
, "internal prf error");
2358 ret
= krb5_derive_key(context
, crypto
->key
.key
,
2359 crypto
->et
->type
, "prf", 3, &derived
);
2361 krb5_abortx(context
, "krb5_derive_key");
2363 ret
= krb5_data_alloc(out
, crypto
->et
->blocksize
);
2365 krb5_abortx(context
, "malloc failed");
2368 const EVP_CIPHER
*c
= (*crypto
->et
->keytype
->evp
)();
2370 /* XXX blksz 1 for cts, so we can't use that */
2371 EVP_CIPHER_CTX_init(&ctx
); /* ivec all zero */
2372 EVP_CipherInit_ex(&ctx
, c
, NULL
, derived
->keyvalue
.data
, NULL
, 1);
2373 EVP_Cipher(&ctx
, out
->data
, result
.checksum
.data
, 16);
2374 EVP_CIPHER_CTX_cleanup(&ctx
);
2377 krb5_data_free(&result
.checksum
);
2378 krb5_free_keyblock(context
, derived
);
2384 * these should currently be in reverse preference order.
2385 * (only relevant for !F_PSEUDO) */
2387 static struct encryption_type enctype_null
= {
2401 static struct encryption_type enctype_arcfour_hmac_md5
= {
2402 ETYPE_ARCFOUR_HMAC_MD5
,
2415 #ifdef DES3_OLD_ENCTYPE
2416 static struct encryption_type enctype_des3_cbc_md5
= {
2424 &checksum_rsa_md5_des3
,
2431 static struct encryption_type enctype_des3_cbc_sha1
= {
2432 ETYPE_DES3_CBC_SHA1
,
2437 &keytype_des3_derived
,
2439 &checksum_hmac_sha1_des3
,
2445 #ifdef DES3_OLD_ENCTYPE
2446 static struct encryption_type enctype_old_des3_cbc_sha1
= {
2447 ETYPE_OLD_DES3_CBC_SHA1
,
2448 "old-des3-cbc-sha1",
2454 &checksum_hmac_sha1_des3
,
2461 static struct encryption_type enctype_aes128_cts_hmac_sha1
= {
2462 ETYPE_AES128_CTS_HMAC_SHA1_96
,
2463 "aes128-cts-hmac-sha1-96",
2469 &checksum_hmac_sha1_aes128
,
2475 static struct encryption_type enctype_aes256_cts_hmac_sha1
= {
2476 ETYPE_AES256_CTS_HMAC_SHA1_96
,
2477 "aes256-cts-hmac-sha1-96",
2483 &checksum_hmac_sha1_aes256
,
2489 static struct encryption_type enctype_des3_cbc_none
= {
2490 ETYPE_DES3_CBC_NONE
,
2495 &keytype_des3_derived
,
2503 #ifdef WEAK_ENCTYPES
2504 static struct encryption_type enctype_des_cbc_crc
= {
2514 evp_des_encrypt_key_ivec
,
2518 static struct encryption_type enctype_des_cbc_md4
= {
2526 &checksum_rsa_md4_des
,
2528 evp_des_encrypt_null_ivec
,
2532 static struct encryption_type enctype_des_cbc_md5
= {
2540 &checksum_rsa_md5_des
,
2542 evp_des_encrypt_null_ivec
,
2546 static struct encryption_type enctype_des_cbc_none
= {
2555 F_PSEUDO
|F_DISABLED
,
2556 evp_des_encrypt_null_ivec
,
2560 static struct encryption_type enctype_des_cfb64_none
= {
2561 ETYPE_DES_CFB64_NONE
,
2569 F_PSEUDO
|F_DISABLED
,
2570 DES_CFB64_encrypt_null_ivec
,
2574 static struct encryption_type enctype_des_pcbc_none
= {
2575 ETYPE_DES_PCBC_NONE
,
2583 F_PSEUDO
|F_DISABLED
,
2584 DES_PCBC_encrypt_key_ivec
,
2588 #endif /* WEAK_ENCTYPES */
2590 static struct encryption_type
*etypes
[] = {
2591 &enctype_aes256_cts_hmac_sha1
,
2592 &enctype_aes128_cts_hmac_sha1
,
2593 &enctype_des3_cbc_sha1
,
2594 &enctype_des3_cbc_none
, /* used by the gss-api mech */
2595 &enctype_arcfour_hmac_md5
,
2596 #ifdef DES3_OLD_ENCTYPE
2597 &enctype_des3_cbc_md5
,
2598 &enctype_old_des3_cbc_sha1
,
2600 #ifdef WEAK_ENCTYPES
2601 &enctype_des_cbc_crc
,
2602 &enctype_des_cbc_md4
,
2603 &enctype_des_cbc_md5
,
2604 &enctype_des_cbc_none
,
2605 &enctype_des_cfb64_none
,
2606 &enctype_des_pcbc_none
,
2611 static unsigned num_etypes
= sizeof(etypes
) / sizeof(etypes
[0]);
2614 static struct encryption_type
*
2615 _find_enctype(krb5_enctype type
)
2618 for(i
= 0; i
< num_etypes
; i
++)
2619 if(etypes
[i
]->type
== type
)
2625 krb5_error_code KRB5_LIB_FUNCTION
2626 krb5_enctype_to_string(krb5_context context
,
2630 struct encryption_type
*e
;
2631 e
= _find_enctype(etype
);
2633 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
2634 "encryption type %d not supported",
2637 return KRB5_PROG_ETYPE_NOSUPP
;
2639 *string
= strdup(e
->name
);
2640 if(*string
== NULL
) {
2641 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
2647 krb5_error_code KRB5_LIB_FUNCTION
2648 krb5_string_to_enctype(krb5_context context
,
2650 krb5_enctype
*etype
)
2653 for(i
= 0; i
< num_etypes
; i
++)
2654 if(strcasecmp(etypes
[i
]->name
, string
) == 0){
2655 *etype
= etypes
[i
]->type
;
2658 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
2659 "encryption type %s not supported",
2661 return KRB5_PROG_ETYPE_NOSUPP
;
2664 krb5_error_code KRB5_LIB_FUNCTION
2665 krb5_enctype_to_keytype(krb5_context context
,
2667 krb5_keytype
*keytype
)
2669 struct encryption_type
*e
= _find_enctype(etype
);
2671 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
2672 "encryption type %d not supported",
2674 return KRB5_PROG_ETYPE_NOSUPP
;
2676 *keytype
= e
->keytype
->type
; /* XXX */
2680 krb5_error_code KRB5_LIB_FUNCTION
2681 krb5_keytype_to_enctypes (krb5_context context
,
2682 krb5_keytype keytype
,
2690 for (i
= num_etypes
- 1; i
>= 0; --i
) {
2691 if (etypes
[i
]->keytype
->type
== keytype
2692 && !(etypes
[i
]->flags
& F_PSEUDO
))
2695 ret
= malloc(n
* sizeof(*ret
));
2696 if (ret
== NULL
&& n
!= 0) {
2697 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
2701 for (i
= num_etypes
- 1; i
>= 0; --i
) {
2702 if (etypes
[i
]->keytype
->type
== keytype
2703 && !(etypes
[i
]->flags
& F_PSEUDO
))
2704 ret
[n
++] = etypes
[i
]->type
;
2711 krb5_error_code KRB5_LIB_FUNCTION
2712 krb5_enctype_valid(krb5_context context
,
2715 struct encryption_type
*e
= _find_enctype(etype
);
2717 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
2718 "encryption type %d not supported",
2720 return KRB5_PROG_ETYPE_NOSUPP
;
2722 if (e
->flags
& F_DISABLED
) {
2723 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
2724 "encryption type %s is disabled",
2726 return KRB5_PROG_ETYPE_NOSUPP
;
2731 krb5_error_code KRB5_LIB_FUNCTION
2732 krb5_cksumtype_valid(krb5_context context
,
2733 krb5_cksumtype ctype
)
2735 struct checksum_type
*c
= _find_checksum(ctype
);
2737 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
2738 "checksum type %d not supported",
2740 return KRB5_PROG_SUMTYPE_NOSUPP
;
2742 if (c
->flags
& F_DISABLED
) {
2743 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
2744 "checksum type %s is disabled",
2746 return KRB5_PROG_SUMTYPE_NOSUPP
;
2752 /* if two enctypes have compatible keys */
2753 krb5_boolean KRB5_LIB_FUNCTION
2754 krb5_enctypes_compatible_keys(krb5_context context
,
2755 krb5_enctype etype1
,
2756 krb5_enctype etype2
)
2758 struct encryption_type
*e1
= _find_enctype(etype1
);
2759 struct encryption_type
*e2
= _find_enctype(etype2
);
2760 return e1
!= NULL
&& e2
!= NULL
&& e1
->keytype
== e2
->keytype
;
2764 derived_crypto(krb5_context context
,
2767 return (crypto
->et
->flags
& F_DERIVED
) != 0;
2771 special_crypto(krb5_context context
,
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
,
2789 size_t sz
, block_sz
, checksum_sz
, total_sz
;
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
);
2803 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
2808 krb5_generate_random_block(q
, et
->confoundersize
); /* XXX */
2809 q
+= et
->confoundersize
;
2810 memcpy(q
, data
, len
);
2812 ret
= create_checksum(context
,
2815 INTEGRITY_USAGE(usage
),
2819 if(ret
== 0 && cksum
.checksum
.length
!= checksum_sz
) {
2820 free_Checksum (&cksum
);
2821 krb5_clear_error_string (context
);
2822 ret
= KRB5_CRYPTO_INTERNAL
;
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
);
2831 ret
= _key_schedule(context
, dkey
);
2834 ret
= (*et
->encrypt
)(context
, dkey
, p
, block_sz
, 1, usage
, ivec
);
2838 result
->length
= total_sz
;
2841 memset(p
, 0, total_sz
);
2847 static krb5_error_code
2848 encrypt_internal(krb5_context context
,
2855 size_t sz
, block_sz
, checksum_sz
;
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
);
2867 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
2872 krb5_generate_random_block(q
, et
->confoundersize
); /* XXX */
2873 q
+= et
->confoundersize
;
2874 memset(q
, 0, checksum_sz
);
2876 memcpy(q
, data
, len
);
2878 ret
= create_checksum(context
,
2885 if(ret
== 0 && cksum
.checksum
.length
!= checksum_sz
) {
2886 krb5_clear_error_string (context
);
2887 free_Checksum(&cksum
);
2888 ret
= KRB5_CRYPTO_INTERNAL
;
2892 memcpy(p
+ et
->confoundersize
, cksum
.checksum
.data
, cksum
.checksum
.length
);
2893 free_Checksum(&cksum
);
2894 ret
= _key_schedule(context
, &crypto
->key
);
2897 ret
= (*et
->encrypt
)(context
, &crypto
->key
, p
, block_sz
, 1, 0, ivec
);
2899 memset(p
, 0, block_sz
);
2904 result
->length
= block_sz
;
2907 memset(p
, 0, block_sz
);
2912 static krb5_error_code
2913 encrypt_internal_special(krb5_context context
,
2921 struct encryption_type
*et
= crypto
->et
;
2922 size_t cksum_sz
= CHECKSUMSIZE(et
->checksum
);
2923 size_t sz
= len
+ cksum_sz
+ et
->confoundersize
;
2925 krb5_error_code ret
;
2929 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
2933 memset (p
, 0, 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
);
2945 result
->length
= sz
;
2949 static krb5_error_code
2950 decrypt_internal_derived(krb5_context context
,
2961 krb5_error_code ret
;
2962 struct key_data
*dkey
;
2963 struct encryption_type
*et
= crypto
->et
;
2966 checksum_sz
= CHECKSUMSIZE(et
->keyed_checksum
);
2967 if (len
< checksum_sz
+ et
->confoundersize
) {
2968 krb5_set_error_message(context
, KRB5_BAD_MSIZE
,
2969 "Encrypted data shorter then "
2970 "checksum + confunder");
2971 return KRB5_BAD_MSIZE
;
2974 if (((len
- checksum_sz
) % et
->padsize
) != 0) {
2975 krb5_clear_error_string(context
);
2976 return KRB5_BAD_MSIZE
;
2980 if(len
!= 0 && p
== NULL
) {
2981 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
2984 memcpy(p
, data
, len
);
2988 ret
= _get_derived_key(context
, crypto
, ENCRYPTION_USAGE(usage
), &dkey
);
2993 ret
= _key_schedule(context
, dkey
);
2998 ret
= (*et
->encrypt
)(context
, dkey
, p
, len
, 0, usage
, ivec
);
3004 cksum
.checksum
.data
= p
+ len
;
3005 cksum
.checksum
.length
= checksum_sz
;
3006 cksum
.cksumtype
= CHECKSUMTYPE(et
->keyed_checksum
);
3008 ret
= verify_checksum(context
,
3010 INTEGRITY_USAGE(usage
),
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) {
3023 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3030 static krb5_error_code
3031 decrypt_internal(krb5_context context
,
3038 krb5_error_code ret
;
3041 size_t checksum_sz
, l
;
3042 struct encryption_type
*et
= crypto
->et
;
3044 if ((len
% et
->padsize
) != 0) {
3045 krb5_clear_error_string(context
);
3046 return KRB5_BAD_MSIZE
;
3049 checksum_sz
= CHECKSUMSIZE(et
->checksum
);
3051 if(len
!= 0 && p
== NULL
) {
3052 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3055 memcpy(p
, data
, len
);
3057 ret
= _key_schedule(context
, &crypto
->key
);
3062 ret
= (*et
->encrypt
)(context
, &crypto
->key
, p
, len
, 0, 0, ivec
);
3067 ret
= krb5_data_copy(&cksum
.checksum
, p
+ et
->confoundersize
, checksum_sz
);
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
);
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) {
3085 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3092 static krb5_error_code
3093 decrypt_internal_special(krb5_context context
,
3101 struct encryption_type
*et
= crypto
->et
;
3102 size_t cksum_sz
= CHECKSUMSIZE(et
->checksum
);
3103 size_t sz
= len
- cksum_sz
- et
->confoundersize
;
3105 krb5_error_code ret
;
3107 if ((len
% et
->padsize
) != 0) {
3108 krb5_clear_error_string(context
);
3109 return KRB5_BAD_MSIZE
;
3114 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3117 memcpy(p
, data
, len
);
3119 ret
= (*et
->encrypt
)(context
, &crypto
->key
, p
, len
, FALSE
, usage
, ivec
);
3125 memmove (p
, p
+ cksum_sz
+ et
->confoundersize
, sz
);
3126 result
->data
= realloc(p
, sz
);
3127 if(result
->data
== NULL
&& sz
!= 0) {
3129 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3132 result
->length
= sz
;
3137 * Inline encrypt a kerberos message
3139 * @param context Kerberos context
3140 * @param crypto Kerberos crypto context
3141 * @param usage Key usage for this buffer
3142 * @param data array of buffers to process
3143 * @param num_data length of array
3144 * @param ivec initial cbc/cts vector
3146 * @return Return an error code or 0.
3147 * @ingroup krb5_crypto
3149 * Kerberos encrypted data look like this:
3151 * 1. KRB5_CRYPTO_TYPE_HEADER
3152 * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
3153 * any order, however the receiver have to aware of the
3154 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used headers and
3156 * 3. KRB5_CRYPTO_TYPE_TRAILER
3159 static krb5_crypto_iov
*
3160 find_iv(krb5_crypto_iov
*data
, int num_data
, int type
)
3163 for (i
= 0; i
< num_data
; i
++)
3164 if (data
[i
].flags
== type
)
3169 krb5_error_code KRB5_LIB_FUNCTION
3170 krb5_encrypt_iov_ivec(krb5_context context
,
3173 krb5_crypto_iov
*data
,
3177 size_t headersz
, trailersz
, len
;
3178 size_t i
, sz
, block_sz
, pad_sz
;
3180 unsigned char *p
, *q
;
3181 krb5_error_code ret
;
3182 struct key_data
*dkey
;
3183 const struct encryption_type
*et
= crypto
->et
;
3184 krb5_crypto_iov
*tiv
, *piv
, *hiv
;
3186 if(!derived_crypto(context
, crypto
)) {
3187 krb5_clear_error_string(context
);
3188 return KRB5_CRYPTO_INTERNAL
;
3191 headersz
= et
->confoundersize
;
3192 trailersz
= CHECKSUMSIZE(et
->keyed_checksum
);
3194 for (len
= 0, i
= 0; i
< num_data
; i
++) {
3195 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_HEADER
&&
3196 data
[i
].flags
== KRB5_CRYPTO_TYPE_DATA
) {
3197 len
+= data
[i
].data
.length
;
3201 sz
= headersz
+ len
;
3202 block_sz
= (sz
+ et
->padsize
- 1) &~ (et
->padsize
- 1); /* pad */
3204 pad_sz
= block_sz
- sz
;
3205 trailersz
+= pad_sz
;
3209 hiv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_HEADER
);
3210 if (hiv
== NULL
|| hiv
->data
.length
!= headersz
)
3211 return KRB5_BAD_MSIZE
;
3213 krb5_generate_random_block(hiv
->data
.data
, hiv
->data
.length
);
3217 piv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_PADDING
);
3218 /* its ok to have no TYPE_PADDING if there is no padding */
3219 if (piv
== NULL
&& pad_sz
!= 0)
3220 return KRB5_BAD_MSIZE
;
3222 if (piv
->data
.length
< pad_sz
)
3223 return KRB5_BAD_MSIZE
;
3224 piv
->data
.length
= pad_sz
;
3230 tiv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_TRAILER
);
3231 if (tiv
== NULL
|| tiv
->data
.length
!= trailersz
)
3232 return KRB5_BAD_MSIZE
;
3236 * XXX replace with EVP_Sign? at least make create_checksum an iov
3238 * XXX CTS EVP is broken, can't handle multi buffers :(
3241 len
= hiv
->data
.length
;
3242 for (i
= 0; i
< num_data
; i
++) {
3243 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
3244 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
3246 len
+= data
[i
].data
.length
;
3249 p
= q
= malloc(len
);
3251 memcpy(q
, hiv
->data
.data
, hiv
->data
.length
);
3252 q
+= hiv
->data
.length
;
3253 for (i
= 0; i
< num_data
; i
++) {
3254 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
3255 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
3257 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
3258 q
+= data
[i
].data
.length
;
3261 ret
= create_checksum(context
,
3264 INTEGRITY_USAGE(usage
),
3269 if(ret
== 0 && cksum
.checksum
.length
!= trailersz
) {
3270 free_Checksum (&cksum
);
3271 krb5_clear_error_string (context
);
3272 ret
= KRB5_CRYPTO_INTERNAL
;
3277 /* save cksum at end */
3278 memcpy(tiv
->data
.data
, cksum
.checksum
.data
, cksum
.checksum
.length
);
3279 free_Checksum (&cksum
);
3281 /* now encrypt data */
3283 ret
= _get_derived_key(context
, crypto
, ENCRYPTION_USAGE(usage
), &dkey
);
3286 ret
= _key_schedule(context
, dkey
);
3290 /* XXX replace with EVP_Cipher */
3292 len
= hiv
->data
.length
;
3293 for (i
= 0; i
< num_data
; i
++) {
3294 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
3295 data
[i
].flags
!= KRB5_CRYPTO_TYPE_PADDING
)
3297 len
+= data
[i
].data
.length
;
3300 p
= q
= malloc(len
);
3304 memcpy(q
, hiv
->data
.data
, hiv
->data
.length
);
3305 q
+= hiv
->data
.length
;
3306 for (i
= 0; i
< num_data
; i
++) {
3307 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
3308 data
[i
].flags
!= KRB5_CRYPTO_TYPE_PADDING
)
3310 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
3311 q
+= data
[i
].data
.length
;
3314 ret
= _get_derived_key(context
, crypto
, ENCRYPTION_USAGE(usage
), &dkey
);
3319 ret
= _key_schedule(context
, dkey
);
3325 ret
= (*et
->encrypt
)(context
, dkey
, p
, len
, 1, usage
, ivec
);
3331 /* now copy data back to buffers */
3333 memcpy(hiv
->data
.data
, q
, hiv
->data
.length
);
3334 q
+= hiv
->data
.length
;
3336 for (i
= 0; i
< num_data
; i
++) {
3337 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
3338 data
[i
].flags
!= KRB5_CRYPTO_TYPE_PADDING
)
3340 memcpy(data
[i
].data
.data
, q
, data
[i
].data
.length
);
3341 q
+= data
[i
].data
.length
;
3348 krb5_error_code KRB5_LIB_FUNCTION
3349 krb5_decrypt_iov_ivec(krb5_context context
,
3352 krb5_crypto_iov
*data
,
3356 size_t headersz
, trailersz
, len
;
3357 size_t i
, sz
, block_sz
, pad_sz
;
3359 unsigned char *p
, *q
;
3360 krb5_error_code ret
;
3361 struct key_data
*dkey
;
3362 struct encryption_type
*et
= crypto
->et
;
3363 krb5_crypto_iov
*tiv
, *hiv
;
3365 if(!derived_crypto(context
, crypto
)) {
3366 krb5_clear_error_string(context
);
3367 return KRB5_CRYPTO_INTERNAL
;
3370 headersz
= et
->confoundersize
;
3371 trailersz
= CHECKSUMSIZE(et
->keyed_checksum
);
3373 for (len
= 0, i
= 0; i
< num_data
; i
++)
3374 if (data
[i
].flags
== KRB5_CRYPTO_TYPE_DATA
)
3375 len
+= data
[i
].data
.length
;
3377 sz
= headersz
+ len
;
3378 block_sz
= (sz
+ et
->padsize
- 1) &~ (et
->padsize
- 1); /* pad */
3380 pad_sz
= block_sz
- sz
;
3381 trailersz
+= pad_sz
;
3385 hiv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_HEADER
);
3386 if (hiv
== NULL
|| hiv
->data
.length
< headersz
)
3387 return KRB5_BAD_MSIZE
;
3388 hiv
->data
.length
= headersz
;
3392 tiv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_TRAILER
);
3393 if (tiv
== NULL
|| tiv
->data
.length
< trailersz
)
3394 return KRB5_BAD_MSIZE
;
3395 tiv
->data
.length
= trailersz
;
3399 /* XXX replace with EVP_Cipher */
3401 for (len
= 0, i
= 0; i
< num_data
; i
++) {
3402 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_HEADER
&&
3403 data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
3405 len
+= data
[i
].data
.length
;
3408 p
= q
= malloc(len
);
3412 memcpy(q
, hiv
->data
.data
, hiv
->data
.length
);
3413 q
+= hiv
->data
.length
;
3414 for (i
= 0; i
< num_data
; i
++) {
3415 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
3417 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
3418 q
+= data
[i
].data
.length
;
3421 ret
= _get_derived_key(context
, crypto
, ENCRYPTION_USAGE(usage
), &dkey
);
3426 ret
= _key_schedule(context
, dkey
);
3432 ret
= (*et
->encrypt
)(context
, dkey
, p
, len
, 0, usage
, ivec
);
3438 /* XXX now copy data back to buffers */
3440 memcpy(hiv
->data
.data
, q
, hiv
->data
.length
);
3441 q
+= hiv
->data
.length
;
3442 len
-= hiv
->data
.length
;
3444 for (i
= 0; i
< num_data
; i
++) {
3445 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
3447 if (len
< data
[i
].data
.length
)
3448 data
[i
].data
.length
= len
;
3449 memcpy(data
[i
].data
.data
, q
, data
[i
].data
.length
);
3450 q
+= data
[i
].data
.length
;
3451 len
-= data
[i
].data
.length
;
3455 krb5_abortx(context
, "data still in the buffer");
3457 len
= hiv
->data
.length
;
3458 for (i
= 0; i
< num_data
; i
++) {
3459 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
3460 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
3462 len
+= data
[i
].data
.length
;
3465 p
= q
= malloc(len
);
3467 memcpy(q
, hiv
->data
.data
, hiv
->data
.length
);
3468 q
+= hiv
->data
.length
;
3469 for (i
= 0; i
< num_data
; i
++) {
3470 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
3471 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
3473 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
3474 q
+= data
[i
].data
.length
;
3477 cksum
.checksum
.data
= tiv
->data
.data
;
3478 cksum
.checksum
.length
= tiv
->data
.length
;
3479 cksum
.cksumtype
= CHECKSUMTYPE(et
->keyed_checksum
);
3481 ret
= verify_checksum(context
,
3483 INTEGRITY_USAGE(usage
),
3495 size_t KRB5_LIB_FUNCTION
3496 krb5_crypto_length(krb5_context context
,
3500 if (!derived_crypto(context
, crypto
))
3503 case KRB5_CRYPTO_TYPE_EMPTY
:
3505 case KRB5_CRYPTO_TYPE_HEADER
:
3506 return crypto
->et
->blocksize
;
3507 case KRB5_CRYPTO_TYPE_PADDING
:
3508 if (crypto
->et
->padsize
> 1)
3509 return crypto
->et
->padsize
;
3511 case KRB5_CRYPTO_TYPE_TRAILER
:
3512 return CHECKSUMSIZE(crypto
->et
->keyed_checksum
);
3517 krb5_error_code KRB5_LIB_FUNCTION
3518 krb5_encrypt_ivec(krb5_context context
,
3526 if(derived_crypto(context
, crypto
))
3527 return encrypt_internal_derived(context
, crypto
, usage
,
3528 data
, len
, result
, ivec
);
3529 else if (special_crypto(context
, crypto
))
3530 return encrypt_internal_special (context
, crypto
, usage
,
3531 data
, len
, result
, ivec
);
3533 return encrypt_internal(context
, crypto
, data
, len
, result
, ivec
);
3536 krb5_error_code KRB5_LIB_FUNCTION
3537 krb5_encrypt(krb5_context context
,
3544 return krb5_encrypt_ivec(context
, crypto
, usage
, data
, len
, result
, NULL
);
3547 krb5_error_code KRB5_LIB_FUNCTION
3548 krb5_encrypt_EncryptedData(krb5_context context
,
3554 EncryptedData
*result
)
3556 result
->etype
= CRYPTO_ETYPE(crypto
);
3558 ALLOC(result
->kvno
, 1);
3559 *result
->kvno
= kvno
;
3561 result
->kvno
= NULL
;
3562 return krb5_encrypt(context
, crypto
, usage
, data
, len
, &result
->cipher
);
3565 krb5_error_code KRB5_LIB_FUNCTION
3566 krb5_decrypt_ivec(krb5_context context
,
3574 if(derived_crypto(context
, crypto
))
3575 return decrypt_internal_derived(context
, crypto
, usage
,
3576 data
, len
, result
, ivec
);
3577 else if (special_crypto (context
, crypto
))
3578 return decrypt_internal_special(context
, crypto
, usage
,
3579 data
, len
, result
, ivec
);
3581 return decrypt_internal(context
, crypto
, data
, len
, result
, ivec
);
3584 krb5_error_code KRB5_LIB_FUNCTION
3585 krb5_decrypt(krb5_context context
,
3592 return krb5_decrypt_ivec (context
, crypto
, usage
, data
, len
, result
,
3596 krb5_error_code KRB5_LIB_FUNCTION
3597 krb5_decrypt_EncryptedData(krb5_context context
,
3600 const EncryptedData
*e
,
3603 return krb5_decrypt(context
, crypto
, usage
,
3604 e
->cipher
.data
, e
->cipher
.length
, result
);
3607 /************************************************************
3609 ************************************************************/
3611 #define ENTROPY_NEEDED 128
3614 seed_something(void)
3616 char buf
[1024], seedfile
[256];
3618 /* If there is a seed file, load it. But such a file cannot be trusted,
3619 so use 0 for the entropy estimate */
3620 if (RAND_file_name(seedfile
, sizeof(seedfile
))) {
3622 fd
= open(seedfile
, O_RDONLY
| O_BINARY
| O_CLOEXEC
);
3626 ret
= read(fd
, buf
, sizeof(buf
));
3628 RAND_add(buf
, ret
, 0.0);
3635 /* Calling RAND_status() will try to use /dev/urandom if it exists so
3636 we do not have to deal with it. */
3637 if (RAND_status() != 1) {
3638 krb5_context context
;
3642 if (!krb5_init_context(&context
)) {
3643 p
= krb5_config_get_string(context
, NULL
, "libdefaults",
3644 "egd_socket", NULL
);
3646 RAND_egd_bytes(p
, ENTROPY_NEEDED
);
3647 krb5_free_context(context
);
3651 if (RAND_status() == 1) {
3652 /* Update the seed file */
3654 RAND_write_file(seedfile
);
3661 void KRB5_LIB_FUNCTION
3662 krb5_generate_random_block(void *buf
, size_t len
)
3664 static int rng_initialized
= 0;
3666 HEIMDAL_MUTEX_lock(&crypto_mutex
);
3667 if (!rng_initialized
) {
3668 if (seed_something())
3669 krb5_abortx(NULL
, "Fatal: could not seed the "
3670 "random number generator");
3672 rng_initialized
= 1;
3674 HEIMDAL_MUTEX_unlock(&crypto_mutex
);
3675 if (RAND_bytes(buf
, len
) != 1)
3676 krb5_abortx(NULL
, "Failed to generate random block");
3680 DES3_postproc(krb5_context context
,
3681 unsigned char *k
, size_t len
, struct key_data
*key
)
3683 DES3_random_to_key(context
, key
->key
, k
, len
);
3685 if (key
->schedule
) {
3686 krb5_free_data(context
, key
->schedule
);
3687 key
->schedule
= NULL
;
3691 static krb5_error_code
3692 derive_key(krb5_context context
,
3693 struct encryption_type
*et
,
3694 struct key_data
*key
,
3695 const void *constant
,
3699 unsigned int nblocks
= 0, i
;
3700 krb5_error_code ret
= 0;
3701 struct key_type
*kt
= et
->keytype
;
3703 ret
= _key_schedule(context
, key
);
3706 if(et
->blocksize
* 8 < kt
->bits
|| len
!= et
->blocksize
) {
3707 nblocks
= (kt
->bits
+ et
->blocksize
* 8 - 1) / (et
->blocksize
* 8);
3708 k
= malloc(nblocks
* et
->blocksize
);
3710 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3713 ret
= _krb5_n_fold(constant
, len
, k
, et
->blocksize
);
3716 krb5_set_error_message(context
, ret
, "malloc: out of memory");
3719 for(i
= 0; i
< nblocks
; i
++) {
3721 memcpy(k
+ i
* et
->blocksize
,
3722 k
+ (i
- 1) * et
->blocksize
,
3724 (*et
->encrypt
)(context
, key
, k
+ i
* et
->blocksize
, et
->blocksize
,
3728 /* this case is probably broken, but won't be run anyway */
3729 void *c
= malloc(len
);
3730 size_t res_len
= (kt
->bits
+ 7) / 8;
3732 if(len
!= 0 && c
== NULL
) {
3733 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3736 memcpy(c
, constant
, len
);
3737 (*et
->encrypt
)(context
, key
, c
, len
, 1, 0, NULL
);
3738 k
= malloc(res_len
);
3739 if(res_len
!= 0 && k
== NULL
) {
3741 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3744 ret
= _krb5_n_fold(c
, len
, k
, res_len
);
3747 krb5_set_error_message(context
, ret
, "malloc: out of memory");
3753 /* XXX keytype dependent post-processing */
3756 DES3_postproc(context
, k
, nblocks
* et
->blocksize
, key
);
3758 case KEYTYPE_AES128
:
3759 case KEYTYPE_AES256
:
3760 memcpy(key
->key
->keyvalue
.data
, k
, key
->key
->keyvalue
.length
);
3763 ret
= KRB5_CRYPTO_INTERNAL
;
3764 krb5_set_error_message(context
, ret
,
3765 "derive_key() called with unknown keytype (%u)",
3769 if (key
->schedule
) {
3770 krb5_free_data(context
, key
->schedule
);
3771 key
->schedule
= NULL
;
3773 memset(k
, 0, nblocks
* et
->blocksize
);
3778 static struct key_data
*
3779 _new_derived_key(krb5_crypto crypto
, unsigned usage
)
3781 struct key_usage
*d
= crypto
->key_usage
;
3782 d
= realloc(d
, (crypto
->num_key_usage
+ 1) * sizeof(*d
));
3785 crypto
->key_usage
= d
;
3786 d
+= crypto
->num_key_usage
++;
3787 memset(d
, 0, sizeof(*d
));
3792 krb5_error_code KRB5_LIB_FUNCTION
3793 krb5_derive_key(krb5_context context
,
3794 const krb5_keyblock
*key
,
3796 const void *constant
,
3797 size_t constant_len
,
3798 krb5_keyblock
**derived_key
)
3800 krb5_error_code ret
;
3801 struct encryption_type
*et
;
3804 *derived_key
= NULL
;
3806 et
= _find_enctype (etype
);
3808 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
3809 "encryption type %d not supported",
3811 return KRB5_PROG_ETYPE_NOSUPP
;
3814 ret
= krb5_copy_keyblock(context
, key
, &d
.key
);
3819 ret
= derive_key(context
, et
, &d
, constant
, constant_len
);
3821 ret
= krb5_copy_keyblock(context
, d
.key
, derived_key
);
3822 free_key_data(context
, &d
, et
);
3826 static krb5_error_code
3827 _get_derived_key(krb5_context context
,
3830 struct key_data
**key
)
3834 unsigned char constant
[5];
3836 for(i
= 0; i
< crypto
->num_key_usage
; i
++)
3837 if(crypto
->key_usage
[i
].usage
== usage
) {
3838 *key
= &crypto
->key_usage
[i
].key
;
3841 d
= _new_derived_key(crypto
, usage
);
3843 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3846 krb5_copy_keyblock(context
, crypto
->key
.key
, &d
->key
);
3847 _krb5_put_int(constant
, usage
, 5);
3848 derive_key(context
, crypto
->et
, d
, constant
, sizeof(constant
));
3854 krb5_error_code KRB5_LIB_FUNCTION
3855 krb5_crypto_init(krb5_context context
,
3856 const krb5_keyblock
*key
,
3858 krb5_crypto
*crypto
)
3860 krb5_error_code ret
;
3862 if(*crypto
== NULL
) {
3863 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
3866 if(etype
== ETYPE_NULL
)
3867 etype
= key
->keytype
;
3868 (*crypto
)->et
= _find_enctype(etype
);
3869 if((*crypto
)->et
== NULL
|| ((*crypto
)->et
->flags
& F_DISABLED
)) {
3872 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
3873 "encryption type %d not supported",
3875 return KRB5_PROG_ETYPE_NOSUPP
;
3877 if((*crypto
)->et
->keytype
->size
!= key
->keyvalue
.length
) {
3880 krb5_set_error_message (context
, KRB5_BAD_KEYSIZE
,
3881 "encryption key has bad length");
3882 return KRB5_BAD_KEYSIZE
;
3884 ret
= krb5_copy_keyblock(context
, key
, &(*crypto
)->key
.key
);
3890 (*crypto
)->key
.schedule
= NULL
;
3891 (*crypto
)->num_key_usage
= 0;
3892 (*crypto
)->key_usage
= NULL
;
3897 free_key_data(krb5_context context
, struct key_data
*key
,
3898 struct encryption_type
*et
)
3900 krb5_free_keyblock(context
, key
->key
);
3902 if (et
->keytype
->cleanup
)
3903 (*et
->keytype
->cleanup
)(context
, key
);
3904 memset(key
->schedule
->data
, 0, key
->schedule
->length
);
3905 krb5_free_data(context
, key
->schedule
);
3910 free_key_usage(krb5_context context
, struct key_usage
*ku
,
3911 struct encryption_type
*et
)
3913 free_key_data(context
, &ku
->key
, et
);
3916 krb5_error_code KRB5_LIB_FUNCTION
3917 krb5_crypto_destroy(krb5_context context
,
3922 for(i
= 0; i
< crypto
->num_key_usage
; i
++)
3923 free_key_usage(context
, &crypto
->key_usage
[i
], crypto
->et
);
3924 free(crypto
->key_usage
);
3925 free_key_data(context
, &crypto
->key
, crypto
->et
);
3930 krb5_error_code KRB5_LIB_FUNCTION
3931 krb5_crypto_getblocksize(krb5_context context
,
3935 *blocksize
= crypto
->et
->blocksize
;
3939 krb5_error_code KRB5_LIB_FUNCTION
3940 krb5_crypto_getenctype(krb5_context context
,
3942 krb5_enctype
*enctype
)
3944 *enctype
= crypto
->et
->type
;
3948 krb5_error_code KRB5_LIB_FUNCTION
3949 krb5_crypto_getpadsize(krb5_context context
,
3953 *padsize
= crypto
->et
->padsize
;
3957 krb5_error_code KRB5_LIB_FUNCTION
3958 krb5_crypto_getconfoundersize(krb5_context context
,
3960 size_t *confoundersize
)
3962 *confoundersize
= crypto
->et
->confoundersize
;
3968 * Disable encryption type
3970 * @param context Kerberos 5 context
3971 * @param enctype encryption type to disable
3973 * @return Return an error code or 0.
3975 * @ingroup krb5_crypto
3978 krb5_error_code KRB5_LIB_FUNCTION
3979 krb5_enctype_disable(krb5_context context
,
3980 krb5_enctype enctype
)
3982 struct encryption_type
*et
= _find_enctype(enctype
);
3985 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
3986 "encryption type %d not supported",
3988 return KRB5_PROG_ETYPE_NOSUPP
;
3990 et
->flags
|= F_DISABLED
;
3995 * Enable encryption type
3997 * @param context Kerberos 5 context
3998 * @param enctype encryption type to enable
4000 * @return Return an error code or 0.
4002 * @ingroup krb5_crypto
4005 krb5_error_code KRB5_LIB_FUNCTION
4006 krb5_enctype_enable(krb5_context context
,
4007 krb5_enctype enctype
)
4009 struct encryption_type
*et
= _find_enctype(enctype
);
4012 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
4013 "encryption type %d not supported",
4015 return KRB5_PROG_ETYPE_NOSUPP
;
4017 et
->flags
&= ~F_DISABLED
;
4022 krb5_error_code KRB5_LIB_FUNCTION
4023 krb5_string_to_key_derived(krb5_context context
,
4029 struct encryption_type
*et
= _find_enctype(etype
);
4030 krb5_error_code ret
;
4036 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
4037 "encryption type %d not supported",
4039 return KRB5_PROG_ETYPE_NOSUPP
;
4041 keylen
= et
->keytype
->bits
/ 8;
4044 if(kd
.key
== NULL
) {
4045 krb5_set_error_message (context
, ENOMEM
,
4046 "malloc: out of memory");
4049 ret
= krb5_data_alloc(&kd
.key
->keyvalue
, et
->keytype
->size
);
4054 kd
.key
->keytype
= etype
;
4055 tmp
= malloc (keylen
);
4057 krb5_free_keyblock(context
, kd
.key
);
4058 krb5_set_error_message (context
, ENOMEM
, "malloc: out of memory");
4061 ret
= _krb5_n_fold(str
, len
, tmp
, keylen
);
4064 krb5_set_error_message (context
, ENOMEM
, "malloc: out of memory");
4068 DES3_postproc (context
, tmp
, keylen
, &kd
); /* XXX */
4069 memset(tmp
, 0, keylen
);
4071 ret
= derive_key(context
,
4074 "kerberos", /* XXX well known constant */
4075 strlen("kerberos"));
4077 free_key_data(context
, &kd
, et
);
4080 ret
= krb5_copy_keyblock_contents(context
, kd
.key
, key
);
4081 free_key_data(context
, &kd
, et
);
4086 wrapped_length (krb5_context context
,
4090 struct encryption_type
*et
= crypto
->et
;
4091 size_t padsize
= et
->padsize
;
4092 size_t checksumsize
= CHECKSUMSIZE(et
->checksum
);
4095 res
= et
->confoundersize
+ checksumsize
+ data_len
;
4096 res
= (res
+ padsize
- 1) / padsize
* padsize
;
4101 wrapped_length_dervied (krb5_context context
,
4105 struct encryption_type
*et
= crypto
->et
;
4106 size_t padsize
= et
->padsize
;
4109 res
= et
->confoundersize
+ data_len
;
4110 res
= (res
+ padsize
- 1) / padsize
* padsize
;
4111 if (et
->keyed_checksum
)
4112 res
+= et
->keyed_checksum
->checksumsize
;
4114 res
+= et
->checksum
->checksumsize
;
4119 * Return the size of an encrypted packet of length `data_len'
4123 krb5_get_wrapped_length (krb5_context context
,
4127 if (derived_crypto (context
, crypto
))
4128 return wrapped_length_dervied (context
, crypto
, data_len
);
4130 return wrapped_length (context
, crypto
, data_len
);
4134 * Return the size of an encrypted packet of length `data_len'
4138 crypto_overhead (krb5_context context
,
4141 struct encryption_type
*et
= crypto
->et
;
4144 res
= CHECKSUMSIZE(et
->checksum
);
4145 res
+= et
->confoundersize
;
4146 if (et
->padsize
> 1)
4152 crypto_overhead_dervied (krb5_context context
,
4155 struct encryption_type
*et
= crypto
->et
;
4158 if (et
->keyed_checksum
)
4159 res
= CHECKSUMSIZE(et
->keyed_checksum
);
4161 res
= CHECKSUMSIZE(et
->checksum
);
4162 res
+= et
->confoundersize
;
4163 if (et
->padsize
> 1)
4169 krb5_crypto_overhead (krb5_context context
, krb5_crypto crypto
)
4171 if (derived_crypto (context
, crypto
))
4172 return crypto_overhead_dervied (context
, crypto
);
4174 return crypto_overhead (context
, crypto
);
4177 krb5_error_code KRB5_LIB_FUNCTION
4178 krb5_random_to_key(krb5_context context
,
4184 krb5_error_code ret
;
4185 struct encryption_type
*et
= _find_enctype(type
);
4187 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
4188 "encryption type %d not supported",
4190 return KRB5_PROG_ETYPE_NOSUPP
;
4192 if ((et
->keytype
->bits
+ 7) / 8 > size
) {
4193 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
4194 "encryption key %s needs %d bytes "
4195 "of random to make an encryption key out of it",
4196 et
->name
, (int)et
->keytype
->size
);
4197 return KRB5_PROG_ETYPE_NOSUPP
;
4199 ret
= krb5_data_alloc(&key
->keyvalue
, et
->keytype
->size
);
4202 key
->keytype
= type
;
4203 if (et
->keytype
->random_to_key
)
4204 (*et
->keytype
->random_to_key
)(context
, key
, data
, size
);
4206 memcpy(key
->keyvalue
.data
, data
, et
->keytype
->size
);
4212 _krb5_pk_octetstring2key(krb5_context context
,
4216 const heim_octet_string
*c_n
,
4217 const heim_octet_string
*k_n
,
4220 struct encryption_type
*et
= _find_enctype(type
);
4221 krb5_error_code ret
;
4222 size_t keylen
, offset
;
4224 unsigned char counter
;
4225 unsigned char shaoutput
[20];
4228 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
4229 "encryption type %d not supported",
4231 return KRB5_PROG_ETYPE_NOSUPP
;
4233 keylen
= (et
->keytype
->bits
+ 7) / 8;
4235 keydata
= malloc(keylen
);
4236 if (keydata
== NULL
) {
4237 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
4247 SHA1_Update(&m
, &counter
, 1);
4248 SHA1_Update(&m
, dhdata
, dhsize
);
4250 SHA1_Update(&m
, c_n
->data
, c_n
->length
);
4252 SHA1_Update(&m
, k_n
->data
, k_n
->length
);
4253 SHA1_Final(shaoutput
, &m
);
4255 memcpy((unsigned char *)keydata
+ offset
,
4257 min(keylen
- offset
, sizeof(shaoutput
)));
4259 offset
+= sizeof(shaoutput
);
4261 } while(offset
< keylen
);
4262 memset(shaoutput
, 0, sizeof(shaoutput
));
4264 ret
= krb5_random_to_key(context
, type
, keydata
, keylen
, key
);
4265 memset(keydata
, 0, sizeof(keylen
));
4270 static krb5_error_code
4271 encode_uvinfo(krb5_context context
, krb5_const_principal p
, krb5_data
*data
)
4273 KRB5PrincipalName pn
;
4274 krb5_error_code ret
;
4277 pn
.principalName
= p
->name
;
4278 pn
.realm
= p
->realm
;
4280 ASN1_MALLOC_ENCODE(KRB5PrincipalName
, data
->data
, data
->length
,
4283 krb5_data_zero(data
);
4284 krb5_set_error_message(context
, ret
,
4285 "Failed to encode KRB5PrincipalName");
4288 if (data
->length
!= size
)
4289 krb5_abortx(context
, "asn1 compiler internal error");
4293 static krb5_error_code
4294 encode_otherinfo(krb5_context context
,
4295 const AlgorithmIdentifier
*ai
,
4296 krb5_const_principal client
,
4297 krb5_const_principal server
,
4298 krb5_enctype enctype
,
4299 const krb5_data
*as_req
,
4300 const krb5_data
*pk_as_rep
,
4301 const Ticket
*ticket
,
4304 PkinitSP80056AOtherInfo otherinfo
;
4305 PkinitSuppPubInfo pubinfo
;
4306 krb5_error_code ret
;
4310 krb5_data_zero(other
);
4311 memset(&otherinfo
, 0, sizeof(otherinfo
));
4312 memset(&pubinfo
, 0, sizeof(pubinfo
));
4314 pubinfo
.enctype
= enctype
;
4315 pubinfo
.as_REQ
= *as_req
;
4316 pubinfo
.pk_as_rep
= *pk_as_rep
;
4317 pubinfo
.ticket
= *ticket
;
4318 ASN1_MALLOC_ENCODE(PkinitSuppPubInfo
, pub
.data
, pub
.length
,
4319 &pubinfo
, &size
, ret
);
4321 krb5_set_error_message(context
, ret
, "out of memory");
4324 if (pub
.length
!= size
)
4325 krb5_abortx(context
, "asn1 compiler internal error");
4327 ret
= encode_uvinfo(context
, client
, &otherinfo
.partyUInfo
);
4332 ret
= encode_uvinfo(context
, server
, &otherinfo
.partyVInfo
);
4334 free(otherinfo
.partyUInfo
.data
);
4339 otherinfo
.algorithmID
= *ai
;
4340 otherinfo
.suppPubInfo
= &pub
;
4342 ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo
, other
->data
, other
->length
,
4343 &otherinfo
, &size
, ret
);
4344 free(otherinfo
.partyUInfo
.data
);
4345 free(otherinfo
.partyVInfo
.data
);
4348 krb5_set_error_message(context
, ret
, "out of memory");
4351 if (other
->length
!= size
)
4352 krb5_abortx(context
, "asn1 compiler internal error");
4358 _krb5_pk_kdf(krb5_context context
,
4359 const struct AlgorithmIdentifier
*ai
,
4362 krb5_const_principal client
,
4363 krb5_const_principal server
,
4364 krb5_enctype enctype
,
4365 const krb5_data
*as_req
,
4366 const krb5_data
*pk_as_rep
,
4367 const Ticket
*ticket
,
4370 struct encryption_type
*et
;
4371 krb5_error_code ret
;
4373 size_t keylen
, offset
;
4375 unsigned char *keydata
;
4376 unsigned char shaoutput
[20];
4378 if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai
->algorithm
) != 0) {
4379 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
4380 "kdf not supported");
4381 return KRB5_PROG_ETYPE_NOSUPP
;
4383 if (ai
->parameters
!= NULL
&&
4384 (ai
->parameters
->length
!= 2 ||
4385 memcmp(ai
->parameters
->data
, "\x05\x00", 2) != 0))
4387 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
4388 "kdf params not NULL or the NULL-type");
4389 return KRB5_PROG_ETYPE_NOSUPP
;
4392 et
= _find_enctype(enctype
);
4394 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
4395 "encryption type %d not supported",
4397 return KRB5_PROG_ETYPE_NOSUPP
;
4399 keylen
= (et
->keytype
->bits
+ 7) / 8;
4401 keydata
= malloc(keylen
);
4402 if (keydata
== NULL
) {
4403 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
4407 ret
= encode_otherinfo(context
, ai
, client
, server
,
4408 enctype
, as_req
, pk_as_rep
, ticket
, &other
);
4417 unsigned char cdata
[4];
4421 _krb5_put_int(cdata
, counter
, 4);
4422 SHA1_Update(&m
, cdata
, 4);
4423 SHA1_Update(&m
, dhdata
, dhsize
);
4424 SHA1_Update(&m
, other
.data
, other
.length
);
4425 SHA1_Final(shaoutput
, &m
);
4427 memcpy((unsigned char *)keydata
+ offset
,
4429 min(keylen
- offset
, sizeof(shaoutput
)));
4431 offset
+= sizeof(shaoutput
);
4433 } while(offset
< keylen
);
4434 memset(shaoutput
, 0, sizeof(shaoutput
));
4438 ret
= krb5_random_to_key(context
, enctype
, keydata
, keylen
, key
);
4439 memset(keydata
, 0, sizeof(keylen
));
4446 krb5_error_code KRB5_LIB_FUNCTION
4447 krb5_crypto_prf_length(krb5_context context
,
4451 struct encryption_type
*et
= _find_enctype(type
);
4453 if(et
== NULL
|| et
->prf_length
== 0) {
4454 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
4455 "encryption type %d not supported",
4457 return KRB5_PROG_ETYPE_NOSUPP
;
4460 *length
= et
->prf_length
;
4464 krb5_error_code KRB5_LIB_FUNCTION
4465 krb5_crypto_prf(krb5_context context
,
4466 const krb5_crypto crypto
,
4467 const krb5_data
*input
,
4470 struct encryption_type
*et
= crypto
->et
;
4472 krb5_data_zero(output
);
4474 if(et
->prf
== NULL
) {
4475 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
4476 "kerberos prf for %s not supported",
4478 return KRB5_PROG_ETYPE_NOSUPP
;
4481 return (*et
->prf
)(context
, crypto
, input
, output
);
4484 #ifndef HEIMDAL_SMALLER
4487 * First take the configured list of etypes for `keytype' if available,
4488 * else, do `krb5_keytype_to_enctypes'.
4491 krb5_error_code KRB5_LIB_FUNCTION
4492 krb5_keytype_to_enctypes_default (krb5_context context
,
4493 krb5_keytype keytype
,
4496 __attribute__((deprecated
))
4501 if (keytype
!= KEYTYPE_DES
|| context
->etypes_des
== NULL
)
4502 return krb5_keytype_to_enctypes (context
, keytype
, len
, val
);
4504 for (n
= 0; context
->etypes_des
[n
]; ++n
)
4506 ret
= malloc (n
* sizeof(*ret
));
4507 if (ret
== NULL
&& n
!= 0) {
4508 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
4511 for (i
= 0; i
< n
; ++i
)
4512 ret
[i
] = context
->etypes_des
[i
];
4518 krb5_error_code KRB5_LIB_FUNCTION
4519 krb5_keytype_to_string(krb5_context context
,
4520 krb5_keytype keytype
,
4522 __attribute__((deprecated
))
4524 struct key_type
*kt
= _find_keytype(keytype
);
4526 krb5_set_error_message(context
, KRB5_PROG_KEYTYPE_NOSUPP
,
4527 "key type %d not supported", keytype
);
4528 return KRB5_PROG_KEYTYPE_NOSUPP
;
4530 *string
= strdup(kt
->name
);
4531 if(*string
== NULL
) {
4532 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
4539 krb5_error_code KRB5_LIB_FUNCTION
4540 krb5_string_to_keytype(krb5_context context
,
4542 krb5_keytype
*keytype
)
4543 __attribute__((deprecated
))
4548 for(i
= 0; i
< num_keytypes
; i
++)
4549 if(strcasecmp(keytypes
[i
]->name
, string
) == 0){
4550 *keytype
= keytypes
[i
]->type
;
4554 /* check if the enctype is a number */
4555 *keytype
= strtol(string
, &end
, 0);
4556 if(*end
== '\0' && *keytype
!= 0) {
4557 if (krb5_enctype_valid(context
, *keytype
) == 0)
4561 krb5_set_error_message(context
, KRB5_PROG_KEYTYPE_NOSUPP
,
4562 "key type %s not supported", string
);
4563 return KRB5_PROG_KEYTYPE_NOSUPP
;