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 struct _krb5_key_usage {
38 struct _krb5_key_data key;
42 #ifndef HEIMDAL_SMALLER
43 #define DES3_OLD_ENCTYPE 1
46 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
47 unsigned, struct _krb5_key_data**);
48 static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
50 static void free_key_schedule(krb5_context,
51 struct _krb5_key_data *,
52 struct _krb5_encryption_type *);
54 /************************************************************
56 ************************************************************/
58 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
59 krb5_enctype_keysize(krb5_context context,
63 struct _krb5_encryption_type *et = _krb5_find_enctype(type);
65 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
66 N_("encryption type %d not supported", ""),
68 return KRB5_PROG_ETYPE_NOSUPP;
70 *keysize = et->keytype->size;
74 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
75 krb5_enctype_keybits(krb5_context context,
79 struct _krb5_encryption_type *et = _krb5_find_enctype(type);
81 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
82 "encryption type %d not supported",
84 return KRB5_PROG_ETYPE_NOSUPP;
86 *keybits = et->keytype->bits;
90 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
91 krb5_generate_random_keyblock(krb5_context context,
96 struct _krb5_encryption_type *et = _krb5_find_enctype(type);
98 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
99 N_("encryption type %d not supported", ""),
101 return KRB5_PROG_ETYPE_NOSUPP;
103 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
107 if(et->keytype->random_key)
108 (*et->keytype->random_key)(context, key);
110 krb5_generate_random_block(key->keyvalue.data,
111 key->keyvalue.length);
115 static krb5_error_code
116 _key_schedule(krb5_context context,
117 struct _krb5_key_data *key)
120 struct _krb5_encryption_type *et = _krb5_find_enctype(key->key->keytype);
121 struct _krb5_key_type *kt;
124 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
125 N_("encryption type %d not supported", ""),
127 return KRB5_PROG_ETYPE_NOSUPP;
132 if(kt->schedule == NULL)
134 if (key->schedule != NULL)
136 ALLOC(key->schedule, 1);
137 if(key->schedule == NULL) {
138 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
141 ret = krb5_data_alloc(key->schedule, kt->schedule_size);
144 key->schedule = NULL;
147 (*kt->schedule)(context, kt, key);
151 /************************************************************
153 ************************************************************/
155 static krb5_error_code
156 SHA1_checksum(krb5_context context,
157 struct _krb5_key_data *key,
163 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
164 krb5_abortx(context, "sha1 checksum failed");
168 /* HMAC according to RFC2104 */
170 _krb5_internal_hmac(krb5_context context,
171 struct _krb5_checksum_type *cm,
175 struct _krb5_key_data *keyblock,
178 unsigned char *ipad, *opad;
183 ipad = malloc(cm->blocksize + len);
186 opad = malloc(cm->blocksize + cm->checksumsize);
191 memset(ipad, 0x36, cm->blocksize);
192 memset(opad, 0x5c, cm->blocksize);
194 if(keyblock->key->keyvalue.length > cm->blocksize){
195 (*cm->checksum)(context,
197 keyblock->key->keyvalue.data,
198 keyblock->key->keyvalue.length,
201 key = result->checksum.data;
202 key_len = result->checksum.length;
204 key = keyblock->key->keyvalue.data;
205 key_len = keyblock->key->keyvalue.length;
207 for(i = 0; i < key_len; i++){
211 memcpy(ipad + cm->blocksize, data, len);
212 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
214 memcpy(opad + cm->blocksize, result->checksum.data,
215 result->checksum.length);
216 (*cm->checksum)(context, keyblock, opad,
217 cm->blocksize + cm->checksumsize, usage, result);
218 memset(ipad, 0, cm->blocksize + len);
220 memset(opad, 0, cm->blocksize + cm->checksumsize);
226 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
227 krb5_hmac(krb5_context context,
228 krb5_cksumtype cktype,
235 struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
236 struct _krb5_key_data kd;
240 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
241 N_("checksum type %d not supported", ""),
243 return KRB5_PROG_SUMTYPE_NOSUPP;
249 ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result);
252 krb5_free_data(context, kd.schedule);
258 _krb5_SP_HMAC_SHA1_checksum(krb5_context context,
259 struct _krb5_key_data *key,
265 struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
270 res.checksum.data = sha1_data;
271 res.checksum.length = sizeof(sha1_data);
273 ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res);
275 krb5_abortx(context, "hmac failed");
276 memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
280 struct _krb5_checksum_type _krb5_checksum_sha1 = {
290 struct _krb5_checksum_type *
291 _krb5_find_checksum(krb5_cksumtype type)
294 for(i = 0; i < _krb5_num_checksums; i++)
295 if(_krb5_checksum_types[i]->type == type)
296 return _krb5_checksum_types[i];
300 static krb5_error_code
301 get_checksum_key(krb5_context context,
303 unsigned usage, /* not krb5_key_usage */
304 struct _krb5_checksum_type *ct,
305 struct _krb5_key_data **key)
307 krb5_error_code ret = 0;
308 struct _krb5_checksum_type *kct = NULL;
310 if (crypto == NULL) {
311 krb5_set_error_message(context, KRB5_BAD_ENCTYPE,
312 N_("Checksum type %s is keyed but no "
313 "crypto context (key) was passed in", ""),
315 return KRB5_BAD_ENCTYPE;
317 kct = crypto->et->keyed_checksum;
318 if (kct == NULL || kct->type != ct->type) {
319 krb5_set_error_message(context, KRB5_BAD_ENCTYPE,
320 N_("Checksum type %s is keyed, but "
321 "the key type %s passed didnt have that checksum "
322 "type as the keyed type", ""),
323 ct->name, crypto->et->name);
324 return KRB5_BAD_ENCTYPE;
327 if(ct->flags & F_DERIVED)
328 ret = _get_derived_key(context, crypto, usage, key);
329 else if(ct->flags & F_VARIANT) {
332 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
334 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
337 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
340 for(i = 0; i < (*key)->key->keyvalue.length; i++)
341 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
346 ret = _key_schedule(context, *key);
350 static krb5_error_code
351 create_checksum (krb5_context context,
352 struct _krb5_checksum_type *ct,
360 struct _krb5_key_data *dkey;
362 if (ct->flags & F_DISABLED) {
363 krb5_clear_error_message (context);
364 return KRB5_PROG_SUMTYPE_NOSUPP;
366 if (ct->flags & F_KEYED) {
367 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
372 result->cksumtype = ct->type;
373 ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
376 return (*ct->checksum)(context, dkey, data, len, usage, result);
380 arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
382 return (ct->type == CKSUMTYPE_HMAC_MD5) &&
383 (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
386 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
387 krb5_create_checksum(krb5_context context,
389 krb5_key_usage usage,
395 struct _krb5_checksum_type *ct = NULL;
398 /* type 0 -> pick from crypto */
400 ct = _krb5_find_checksum(type);
402 ct = crypto->et->keyed_checksum;
404 ct = crypto->et->checksum;
408 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
409 N_("checksum type %d not supported", ""),
411 return KRB5_PROG_SUMTYPE_NOSUPP;
414 if (arcfour_checksum_p(ct, crypto)) {
416 _krb5_usage2arcfour(context, &keyusage);
418 keyusage = CHECKSUM_USAGE(usage);
420 return create_checksum(context, ct, crypto, keyusage,
424 static krb5_error_code
425 verify_checksum(krb5_context context,
427 unsigned usage, /* not krb5_key_usage */
433 struct _krb5_key_data *dkey;
435 struct _krb5_checksum_type *ct;
437 ct = _krb5_find_checksum(cksum->cksumtype);
438 if (ct == NULL || (ct->flags & F_DISABLED)) {
439 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
440 N_("checksum type %d not supported", ""),
442 return KRB5_PROG_SUMTYPE_NOSUPP;
444 if(ct->checksumsize != cksum->checksum.length) {
445 krb5_clear_error_message (context);
446 krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
447 N_("Decrypt integrity check failed for checksum type %s, "
448 "length was %u, expected %u", ""),
449 ct->name, (unsigned)cksum->checksum.length,
450 (unsigned)ct->checksumsize);
452 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
454 if (ct->flags & F_KEYED) {
455 ret = get_checksum_key(context, crypto, usage, ct, &dkey);
462 * If checksum have a verify function, lets use that instead of
463 * calling ->checksum and then compare result.
467 ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
469 krb5_set_error_message(context, ret,
470 N_("Decrypt integrity check failed for checksum "
471 "type %s, key type %s", ""),
472 ct->name, (crypto != NULL)? crypto->et->name : "(none)");
476 ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
480 ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
482 krb5_data_free(&c.checksum);
486 if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
487 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
488 krb5_set_error_message(context, ret,
489 N_("Decrypt integrity check failed for checksum "
490 "type %s, key type %s", ""),
491 ct->name, crypto ? crypto->et->name : "(unkeyed)");
495 krb5_data_free (&c.checksum);
499 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
500 krb5_verify_checksum(krb5_context context,
502 krb5_key_usage usage,
507 struct _krb5_checksum_type *ct;
510 ct = _krb5_find_checksum(cksum->cksumtype);
512 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
513 N_("checksum type %d not supported", ""),
515 return KRB5_PROG_SUMTYPE_NOSUPP;
518 if (arcfour_checksum_p(ct, crypto)) {
520 _krb5_usage2arcfour(context, &keyusage);
522 keyusage = CHECKSUM_USAGE(usage);
524 return verify_checksum(context, crypto, keyusage,
528 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
529 krb5_crypto_get_checksum_type(krb5_context context,
531 krb5_cksumtype *type)
533 struct _krb5_checksum_type *ct = NULL;
535 if (crypto != NULL) {
536 ct = crypto->et->keyed_checksum;
538 ct = crypto->et->checksum;
542 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
543 N_("checksum type not found", ""));
544 return KRB5_PROG_SUMTYPE_NOSUPP;
553 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
554 krb5_checksumsize(krb5_context context,
558 struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
560 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
561 N_("checksum type %d not supported", ""),
563 return KRB5_PROG_SUMTYPE_NOSUPP;
565 *size = ct->checksumsize;
569 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
570 krb5_checksum_is_keyed(krb5_context context,
573 struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
576 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
577 N_("checksum type %d not supported", ""),
579 return KRB5_PROG_SUMTYPE_NOSUPP;
581 return ct->flags & F_KEYED;
584 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
585 krb5_checksum_is_collision_proof(krb5_context context,
588 struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
591 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
592 N_("checksum type %d not supported", ""),
594 return KRB5_PROG_SUMTYPE_NOSUPP;
596 return ct->flags & F_CPROOF;
599 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
600 krb5_checksum_disable(krb5_context context,
603 struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
606 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
607 N_("checksum type %d not supported", ""),
609 return KRB5_PROG_SUMTYPE_NOSUPP;
611 ct->flags |= F_DISABLED;
615 /************************************************************
617 ************************************************************/
619 struct _krb5_encryption_type *
620 _krb5_find_enctype(krb5_enctype type)
623 for(i = 0; i < _krb5_num_etypes; i++)
624 if(_krb5_etypes[i]->type == type)
625 return _krb5_etypes[i];
630 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
631 krb5_enctype_to_string(krb5_context context,
635 struct _krb5_encryption_type *e;
636 e = _krb5_find_enctype(etype);
638 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
639 N_("encryption type %d not supported", ""),
642 return KRB5_PROG_ETYPE_NOSUPP;
644 *string = strdup(e->name);
645 if(*string == NULL) {
646 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
652 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
653 krb5_string_to_enctype(krb5_context context,
658 for(i = 0; i < _krb5_num_etypes; i++)
659 if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
660 *etype = _krb5_etypes[i]->type;
663 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
664 N_("encryption type %s not supported", ""),
666 return KRB5_PROG_ETYPE_NOSUPP;
669 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
670 krb5_enctype_to_keytype(krb5_context context,
672 krb5_keytype *keytype)
674 struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
676 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
677 N_("encryption type %d not supported", ""),
679 return KRB5_PROG_ETYPE_NOSUPP;
681 *keytype = e->keytype->type; /* XXX */
686 * Check if a enctype is valid, return 0 if it is.
688 * @param context Kerberos context
689 * @param etype enctype to check if its valid or not
691 * @return Return an error code for an failure or 0 on success (enctype valid).
692 * @ingroup krb5_crypto
695 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
696 krb5_enctype_valid(krb5_context context,
699 struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
700 if(e && (e->flags & F_DISABLED) == 0)
703 return KRB5_PROG_ETYPE_NOSUPP;
705 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
706 N_("encryption type %d not supported", ""),
708 return KRB5_PROG_ETYPE_NOSUPP;
710 /* Must be (e->flags & F_DISABLED) */
711 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
712 N_("encryption type %s is disabled", ""),
714 return KRB5_PROG_ETYPE_NOSUPP;
718 * Return the coresponding encryption type for a checksum type.
720 * @param context Kerberos context
721 * @param ctype The checksum type to get the result enctype for
722 * @param etype The returned encryption, when the matching etype is
723 * not found, etype is set to ETYPE_NULL.
725 * @return Return an error code for an failure or 0 on success.
726 * @ingroup krb5_crypto
730 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
731 krb5_cksumtype_to_enctype(krb5_context context,
732 krb5_cksumtype ctype,
739 for(i = 0; i < _krb5_num_etypes; i++) {
740 if(_krb5_etypes[i]->keyed_checksum &&
741 _krb5_etypes[i]->keyed_checksum->type == ctype)
743 *etype = _krb5_etypes[i]->type;
748 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
749 N_("checksum type %d not supported", ""),
751 return KRB5_PROG_SUMTYPE_NOSUPP;
755 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
756 krb5_cksumtype_valid(krb5_context context,
757 krb5_cksumtype ctype)
759 struct _krb5_checksum_type *c = _krb5_find_checksum(ctype);
761 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
762 N_("checksum type %d not supported", ""),
764 return KRB5_PROG_SUMTYPE_NOSUPP;
766 if (c->flags & F_DISABLED) {
767 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
768 N_("checksum type %s is disabled", ""),
770 return KRB5_PROG_SUMTYPE_NOSUPP;
777 derived_crypto(krb5_context context,
780 return (crypto->et->flags & F_DERIVED) != 0;
784 special_crypto(krb5_context context,
787 return (crypto->et->flags & F_SPECIAL) != 0;
790 #define CHECKSUMSIZE(C) ((C)->checksumsize)
791 #define CHECKSUMTYPE(C) ((C)->type)
793 static krb5_error_code
794 encrypt_internal_derived(krb5_context context,
802 size_t sz, block_sz, checksum_sz, total_sz;
804 unsigned char *p, *q;
806 struct _krb5_key_data *dkey;
807 const struct _krb5_encryption_type *et = crypto->et;
809 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
811 sz = et->confoundersize + len;
812 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
813 total_sz = block_sz + checksum_sz;
814 p = calloc(1, total_sz);
816 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
821 krb5_generate_random_block(q, et->confoundersize); /* XXX */
822 q += et->confoundersize;
823 memcpy(q, data, len);
825 ret = create_checksum(context,
828 INTEGRITY_USAGE(usage),
832 if(ret == 0 && cksum.checksum.length != checksum_sz) {
833 free_Checksum (&cksum);
834 krb5_clear_error_message (context);
835 ret = KRB5_CRYPTO_INTERNAL;
839 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
840 free_Checksum (&cksum);
841 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
844 ret = _key_schedule(context, dkey);
847 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
851 result->length = total_sz;
854 memset(p, 0, total_sz);
860 static krb5_error_code
861 encrypt_internal(krb5_context context,
868 size_t sz, block_sz, checksum_sz;
870 unsigned char *p, *q;
872 const struct _krb5_encryption_type *et = crypto->et;
874 checksum_sz = CHECKSUMSIZE(et->checksum);
876 sz = et->confoundersize + checksum_sz + len;
877 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
878 p = calloc(1, block_sz);
880 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
885 krb5_generate_random_block(q, et->confoundersize); /* XXX */
886 q += et->confoundersize;
887 memset(q, 0, checksum_sz);
889 memcpy(q, data, len);
891 ret = create_checksum(context,
898 if(ret == 0 && cksum.checksum.length != checksum_sz) {
899 krb5_clear_error_message (context);
900 free_Checksum(&cksum);
901 ret = KRB5_CRYPTO_INTERNAL;
905 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
906 free_Checksum(&cksum);
907 ret = _key_schedule(context, &crypto->key);
910 ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
912 memset(p, 0, block_sz);
917 result->length = block_sz;
920 memset(p, 0, block_sz);
925 static krb5_error_code
926 encrypt_internal_special(krb5_context context,
934 struct _krb5_encryption_type *et = crypto->et;
935 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
936 size_t sz = len + cksum_sz + et->confoundersize;
942 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
946 memset (p, 0, cksum_sz);
948 krb5_generate_random_block(p, et->confoundersize);
949 p += et->confoundersize;
950 memcpy (p, data, len);
951 ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
962 static krb5_error_code
963 decrypt_internal_derived(krb5_context context,
975 struct _krb5_key_data *dkey;
976 struct _krb5_encryption_type *et = crypto->et;
979 checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
980 if (len < checksum_sz + et->confoundersize) {
981 krb5_set_error_message(context, KRB5_BAD_MSIZE,
982 N_("Encrypted data shorter then "
983 "checksum + confunder", ""));
984 return KRB5_BAD_MSIZE;
987 if (((len - checksum_sz) % et->padsize) != 0) {
988 krb5_clear_error_message(context);
989 return KRB5_BAD_MSIZE;
993 if(len != 0 && p == NULL) {
994 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
997 memcpy(p, data, len);
1001 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1006 ret = _key_schedule(context, dkey);
1011 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1017 cksum.checksum.data = p + len;
1018 cksum.checksum.length = checksum_sz;
1019 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1021 ret = verify_checksum(context,
1023 INTEGRITY_USAGE(usage),
1031 l = len - et->confoundersize;
1032 memmove(p, p + et->confoundersize, l);
1033 result->data = realloc(p, l);
1034 if(result->data == NULL && l != 0) {
1036 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1043 static krb5_error_code
1044 decrypt_internal(krb5_context context,
1051 krb5_error_code ret;
1054 size_t checksum_sz, l;
1055 struct _krb5_encryption_type *et = crypto->et;
1057 if ((len % et->padsize) != 0) {
1058 krb5_clear_error_message(context);
1059 return KRB5_BAD_MSIZE;
1061 checksum_sz = CHECKSUMSIZE(et->checksum);
1062 if (len < checksum_sz + et->confoundersize) {
1063 krb5_set_error_message(context, KRB5_BAD_MSIZE,
1064 N_("Encrypted data shorter then "
1065 "checksum + confunder", ""));
1066 return KRB5_BAD_MSIZE;
1070 if(len != 0 && p == NULL) {
1071 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1074 memcpy(p, data, len);
1076 ret = _key_schedule(context, &crypto->key);
1081 ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
1086 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1091 memset(p + et->confoundersize, 0, checksum_sz);
1092 cksum.cksumtype = CHECKSUMTYPE(et->checksum);
1093 ret = verify_checksum(context, NULL, 0, p, len, &cksum);
1094 free_Checksum(&cksum);
1099 l = len - et->confoundersize - checksum_sz;
1100 memmove(p, p + et->confoundersize + checksum_sz, l);
1101 result->data = realloc(p, l);
1102 if(result->data == NULL && l != 0) {
1104 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1111 static krb5_error_code
1112 decrypt_internal_special(krb5_context context,
1120 struct _krb5_encryption_type *et = crypto->et;
1121 size_t cksum_sz = CHECKSUMSIZE(et->checksum);
1122 size_t sz = len - cksum_sz - et->confoundersize;
1124 krb5_error_code ret;
1126 if ((len % et->padsize) != 0) {
1127 krb5_clear_error_message(context);
1128 return KRB5_BAD_MSIZE;
1130 if (len < cksum_sz + et->confoundersize) {
1131 krb5_set_error_message(context, KRB5_BAD_MSIZE,
1132 N_("Encrypted data shorter then "
1133 "checksum + confunder", ""));
1134 return KRB5_BAD_MSIZE;
1139 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1142 memcpy(p, data, len);
1144 ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
1150 memmove (p, p + cksum_sz + et->confoundersize, sz);
1151 result->data = realloc(p, sz);
1152 if(result->data == NULL && sz != 0) {
1154 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1157 result->length = sz;
1161 static krb5_crypto_iov *
1162 find_iv(krb5_crypto_iov *data, size_t num_data, unsigned type)
1165 for (i = 0; i < num_data; i++)
1166 if (data[i].flags == type)
1172 * Inline encrypt a kerberos message
1174 * @param context Kerberos context
1175 * @param crypto Kerberos crypto context
1176 * @param usage Key usage for this buffer
1177 * @param data array of buffers to process
1178 * @param num_data length of array
1179 * @param ivec initial cbc/cts vector
1181 * @return Return an error code or 0.
1182 * @ingroup krb5_crypto
1184 * Kerberos encrypted data look like this:
1186 * 1. KRB5_CRYPTO_TYPE_HEADER
1187 * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
1188 * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
1189 * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
1190 * commonly used headers and trailers.
1191 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
1192 * 4. KRB5_CRYPTO_TYPE_TRAILER
1195 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1196 krb5_encrypt_iov_ivec(krb5_context context,
1199 krb5_crypto_iov *data,
1203 size_t headersz, trailersz, len;
1205 size_t sz, block_sz, pad_sz;
1207 unsigned char *p, *q;
1208 krb5_error_code ret;
1209 struct _krb5_key_data *dkey;
1210 const struct _krb5_encryption_type *et = crypto->et;
1211 krb5_crypto_iov *tiv, *piv, *hiv;
1214 krb5_clear_error_message(context);
1215 return KRB5_CRYPTO_INTERNAL;
1218 if(!derived_crypto(context, crypto)) {
1219 krb5_clear_error_message(context);
1220 return KRB5_CRYPTO_INTERNAL;
1223 headersz = et->confoundersize;
1224 trailersz = CHECKSUMSIZE(et->keyed_checksum);
1226 for (len = 0, i = 0; i < num_data; i++) {
1227 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1229 len += data[i].data.length;
1232 sz = headersz + len;
1233 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1235 pad_sz = block_sz - sz;
1239 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1240 if (hiv == NULL || hiv->data.length != headersz)
1241 return KRB5_BAD_MSIZE;
1243 krb5_generate_random_block(hiv->data.data, hiv->data.length);
1246 piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1247 /* its ok to have no TYPE_PADDING if there is no padding */
1248 if (piv == NULL && pad_sz != 0)
1249 return KRB5_BAD_MSIZE;
1251 if (piv->data.length < pad_sz)
1252 return KRB5_BAD_MSIZE;
1253 piv->data.length = pad_sz;
1255 memset(piv->data.data, pad_sz, pad_sz);
1261 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1262 if (tiv == NULL || tiv->data.length != trailersz)
1263 return KRB5_BAD_MSIZE;
1266 * XXX replace with EVP_Sign? at least make create_checksum an iov
1268 * XXX CTS EVP is broken, can't handle multi buffers :(
1272 for (i = 0; i < num_data; i++) {
1273 if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1275 len += data[i].data.length;
1278 p = q = malloc(len);
1280 memcpy(q, hiv->data.data, hiv->data.length);
1281 q += hiv->data.length;
1282 for (i = 0; i < num_data; i++) {
1283 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1284 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1286 memcpy(q, data[i].data.data, data[i].data.length);
1287 q += data[i].data.length;
1290 memset(q, 0, piv->data.length);
1292 ret = create_checksum(context,
1295 INTEGRITY_USAGE(usage),
1300 if(ret == 0 && cksum.checksum.length != trailersz) {
1301 free_Checksum (&cksum);
1302 krb5_clear_error_message (context);
1303 ret = KRB5_CRYPTO_INTERNAL;
1308 /* save cksum at end */
1309 memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
1310 free_Checksum (&cksum);
1312 /* XXX replace with EVP_Cipher */
1313 p = q = malloc(block_sz);
1317 memcpy(q, hiv->data.data, hiv->data.length);
1318 q += hiv->data.length;
1320 for (i = 0; i < num_data; i++) {
1321 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1323 memcpy(q, data[i].data.data, data[i].data.length);
1324 q += data[i].data.length;
1327 memset(q, 0, piv->data.length);
1330 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1335 ret = _key_schedule(context, dkey);
1341 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
1347 /* now copy data back to buffers */
1350 memcpy(hiv->data.data, q, hiv->data.length);
1351 q += hiv->data.length;
1353 for (i = 0; i < num_data; i++) {
1354 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1356 memcpy(data[i].data.data, q, data[i].data.length);
1357 q += data[i].data.length;
1360 memcpy(piv->data.data, q, pad_sz);
1368 * Inline decrypt a Kerberos message.
1370 * @param context Kerberos context
1371 * @param crypto Kerberos crypto context
1372 * @param usage Key usage for this buffer
1373 * @param data array of buffers to process
1374 * @param num_data length of array
1375 * @param ivec initial cbc/cts vector
1377 * @return Return an error code or 0.
1378 * @ingroup krb5_crypto
1380 * 1. KRB5_CRYPTO_TYPE_HEADER
1381 * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
1382 * any order, however the receiver have to aware of the
1383 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
1384 * protocol headers and trailers. The output data will be of same
1385 * size as the input data or shorter.
1388 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1389 krb5_decrypt_iov_ivec(krb5_context context,
1392 krb5_crypto_iov *data,
1393 unsigned int num_data,
1397 size_t headersz, trailersz, len;
1399 unsigned char *p, *q;
1400 krb5_error_code ret;
1401 struct _krb5_key_data *dkey;
1402 struct _krb5_encryption_type *et = crypto->et;
1403 krb5_crypto_iov *tiv, *hiv;
1405 if(!derived_crypto(context, crypto)) {
1406 krb5_clear_error_message(context);
1407 return KRB5_CRYPTO_INTERNAL;
1410 headersz = et->confoundersize;
1412 hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1413 if (hiv == NULL || hiv->data.length != headersz)
1414 return KRB5_BAD_MSIZE;
1417 trailersz = CHECKSUMSIZE(et->keyed_checksum);
1419 tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1420 if (tiv->data.length != trailersz)
1421 return KRB5_BAD_MSIZE;
1423 /* Find length of data we will decrypt */
1426 for (i = 0; i < num_data; i++) {
1427 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1429 len += data[i].data.length;
1432 if ((len % et->padsize) != 0) {
1433 krb5_clear_error_message(context);
1434 return KRB5_BAD_MSIZE;
1437 /* XXX replace with EVP_Cipher */
1439 p = q = malloc(len);
1443 memcpy(q, hiv->data.data, hiv->data.length);
1444 q += hiv->data.length;
1446 for (i = 0; i < num_data; i++) {
1447 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1449 memcpy(q, data[i].data.data, data[i].data.length);
1450 q += data[i].data.length;
1453 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1458 ret = _key_schedule(context, dkey);
1464 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1470 /* copy data back to buffers */
1471 memcpy(hiv->data.data, p, hiv->data.length);
1472 q = p + hiv->data.length;
1473 for (i = 0; i < num_data; i++) {
1474 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1476 memcpy(data[i].data.data, q, data[i].data.length);
1477 q += data[i].data.length;
1482 /* check signature */
1483 for (i = 0; i < num_data; i++) {
1484 if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1486 len += data[i].data.length;
1489 p = q = malloc(len);
1493 memcpy(q, hiv->data.data, hiv->data.length);
1494 q += hiv->data.length;
1495 for (i = 0; i < num_data; i++) {
1496 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1497 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1499 memcpy(q, data[i].data.data, data[i].data.length);
1500 q += data[i].data.length;
1503 cksum.checksum.data = tiv->data.data;
1504 cksum.checksum.length = tiv->data.length;
1505 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1507 ret = verify_checksum(context,
1509 INTEGRITY_USAGE(usage),
1518 * Create a Kerberos message checksum.
1520 * @param context Kerberos context
1521 * @param crypto Kerberos crypto context
1522 * @param usage Key usage for this buffer
1523 * @param data array of buffers to process
1524 * @param num_data length of array
1525 * @param type output data
1527 * @return Return an error code or 0.
1528 * @ingroup krb5_crypto
1531 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1532 krb5_create_checksum_iov(krb5_context context,
1535 krb5_crypto_iov *data,
1536 unsigned int num_data,
1537 krb5_cksumtype *type)
1540 krb5_crypto_iov *civ;
1541 krb5_error_code ret;
1546 if(!derived_crypto(context, crypto)) {
1547 krb5_clear_error_message(context);
1548 return KRB5_CRYPTO_INTERNAL;
1551 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1553 return KRB5_BAD_MSIZE;
1556 for (i = 0; i < num_data; i++) {
1557 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1558 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1560 len += data[i].data.length;
1563 p = q = malloc(len);
1565 for (i = 0; i < num_data; i++) {
1566 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1567 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1569 memcpy(q, data[i].data.data, data[i].data.length);
1570 q += data[i].data.length;
1573 ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
1579 *type = cksum.cksumtype;
1581 if (cksum.checksum.length > civ->data.length) {
1582 krb5_set_error_message(context, KRB5_BAD_MSIZE,
1583 N_("Checksum larger then input buffer", ""));
1584 free_Checksum(&cksum);
1585 return KRB5_BAD_MSIZE;
1588 civ->data.length = cksum.checksum.length;
1589 memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
1590 free_Checksum(&cksum);
1596 * Verify a Kerberos message checksum.
1598 * @param context Kerberos context
1599 * @param crypto Kerberos crypto context
1600 * @param usage Key usage for this buffer
1601 * @param data array of buffers to process
1602 * @param num_data length of array
1603 * @param type return checksum type if not NULL
1605 * @return Return an error code or 0.
1606 * @ingroup krb5_crypto
1609 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1610 krb5_verify_checksum_iov(krb5_context context,
1613 krb5_crypto_iov *data,
1614 unsigned int num_data,
1615 krb5_cksumtype *type)
1617 struct _krb5_encryption_type *et = crypto->et;
1619 krb5_crypto_iov *civ;
1620 krb5_error_code ret;
1625 if(!derived_crypto(context, crypto)) {
1626 krb5_clear_error_message(context);
1627 return KRB5_CRYPTO_INTERNAL;
1630 civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1632 return KRB5_BAD_MSIZE;
1635 for (i = 0; i < num_data; i++) {
1636 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1637 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1639 len += data[i].data.length;
1642 p = q = malloc(len);
1644 for (i = 0; i < num_data; i++) {
1645 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1646 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1648 memcpy(q, data[i].data.data, data[i].data.length);
1649 q += data[i].data.length;
1652 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1653 cksum.checksum.length = civ->data.length;
1654 cksum.checksum.data = civ->data.data;
1656 ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
1659 if (ret == 0 && type)
1660 *type = cksum.cksumtype;
1666 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1667 krb5_crypto_length(krb5_context context,
1672 if (!derived_crypto(context, crypto)) {
1673 krb5_set_error_message(context, EINVAL, "not a derived crypto");
1678 case KRB5_CRYPTO_TYPE_EMPTY:
1681 case KRB5_CRYPTO_TYPE_HEADER:
1682 *len = crypto->et->blocksize;
1684 case KRB5_CRYPTO_TYPE_DATA:
1685 case KRB5_CRYPTO_TYPE_SIGN_ONLY:
1686 /* len must already been filled in */
1688 case KRB5_CRYPTO_TYPE_PADDING:
1689 if (crypto->et->padsize > 1)
1690 *len = crypto->et->padsize;
1694 case KRB5_CRYPTO_TYPE_TRAILER:
1695 *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1697 case KRB5_CRYPTO_TYPE_CHECKSUM:
1698 if (crypto->et->keyed_checksum)
1699 *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1701 *len = CHECKSUMSIZE(crypto->et->checksum);
1704 krb5_set_error_message(context, EINVAL,
1705 "%d not a supported type", type);
1710 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1711 krb5_crypto_length_iov(krb5_context context,
1713 krb5_crypto_iov *data,
1714 unsigned int num_data)
1716 krb5_error_code ret;
1719 for (i = 0; i < num_data; i++) {
1720 ret = krb5_crypto_length(context, crypto,
1722 &data[i].data.length);
1730 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1731 krb5_encrypt_ivec(krb5_context context,
1739 if(derived_crypto(context, crypto))
1740 return encrypt_internal_derived(context, crypto, usage,
1741 data, len, result, ivec);
1742 else if (special_crypto(context, crypto))
1743 return encrypt_internal_special (context, crypto, usage,
1744 data, len, result, ivec);
1746 return encrypt_internal(context, crypto, data, len, result, ivec);
1749 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1750 krb5_encrypt(krb5_context context,
1757 return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
1760 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1761 krb5_encrypt_EncryptedData(krb5_context context,
1767 EncryptedData *result)
1769 result->etype = CRYPTO_ETYPE(crypto);
1771 ALLOC(result->kvno, 1);
1772 *result->kvno = kvno;
1774 result->kvno = NULL;
1775 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
1778 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1779 krb5_decrypt_ivec(krb5_context context,
1787 if(derived_crypto(context, crypto))
1788 return decrypt_internal_derived(context, crypto, usage,
1789 data, len, result, ivec);
1790 else if (special_crypto (context, crypto))
1791 return decrypt_internal_special(context, crypto, usage,
1792 data, len, result, ivec);
1794 return decrypt_internal(context, crypto, data, len, result, ivec);
1797 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1798 krb5_decrypt(krb5_context context,
1805 return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
1809 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1810 krb5_decrypt_EncryptedData(krb5_context context,
1813 const EncryptedData *e,
1816 return krb5_decrypt(context, crypto, usage,
1817 e->cipher.data, e->cipher.length, result);
1820 /************************************************************
1822 ************************************************************/
1825 _krb5_derive_key(krb5_context context,
1826 struct _krb5_encryption_type *et,
1827 struct _krb5_key_data *key,
1828 const void *constant,
1831 unsigned char *k = NULL;
1832 unsigned int nblocks = 0, i;
1833 krb5_error_code ret = 0;
1834 struct _krb5_key_type *kt = et->keytype;
1836 ret = _key_schedule(context, key);
1839 if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
1840 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
1841 k = malloc(nblocks * et->blocksize);
1844 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1847 ret = _krb5_n_fold(constant, len, k, et->blocksize);
1849 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1853 for(i = 0; i < nblocks; i++) {
1855 memcpy(k + i * et->blocksize,
1856 k + (i - 1) * et->blocksize,
1858 ret = (*et->encrypt)(context, key, k + i * et->blocksize,
1859 et->blocksize, 1, 0, NULL);
1861 krb5_set_error_message(context, ret, N_("encrypt failed", ""));
1866 /* this case is probably broken, but won't be run anyway */
1867 void *c = malloc(len);
1868 size_t res_len = (kt->bits + 7) / 8;
1870 if(len != 0 && c == NULL) {
1872 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1875 memcpy(c, constant, len);
1876 ret = (*et->encrypt)(context, key, c, len, 1, 0, NULL);
1879 krb5_set_error_message(context, ret, N_("encrypt failed", ""));
1882 k = malloc(res_len);
1883 if(res_len != 0 && k == NULL) {
1886 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1889 ret = _krb5_n_fold(c, len, k, res_len);
1892 krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1897 /* XXX keytype dependent post-processing */
1899 case KRB5_ENCTYPE_OLD_DES3_CBC_SHA1:
1900 _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
1902 case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96:
1903 case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96:
1904 memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
1907 ret = KRB5_CRYPTO_INTERNAL;
1908 krb5_set_error_message(context, ret,
1909 N_("derive_key() called with unknown keytype (%u)", ""),
1914 if (key->schedule) {
1915 free_key_schedule(context, key, et);
1916 key->schedule = NULL;
1919 memset(k, 0, nblocks * et->blocksize);
1925 static struct _krb5_key_data *
1926 _new_derived_key(krb5_crypto crypto, unsigned usage)
1928 struct _krb5_key_usage *d = crypto->key_usage;
1929 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
1932 crypto->key_usage = d;
1933 d += crypto->num_key_usage++;
1934 memset(d, 0, sizeof(*d));
1939 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1940 krb5_derive_key(krb5_context context,
1941 const krb5_keyblock *key,
1943 const void *constant,
1944 size_t constant_len,
1945 krb5_keyblock **derived_key)
1947 krb5_error_code ret;
1948 struct _krb5_encryption_type *et;
1949 struct _krb5_key_data d;
1951 *derived_key = NULL;
1953 et = _krb5_find_enctype (etype);
1955 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1956 N_("encryption type %d not supported", ""),
1958 return KRB5_PROG_ETYPE_NOSUPP;
1961 ret = krb5_copy_keyblock(context, key, &d.key);
1966 ret = _krb5_derive_key(context, et, &d, constant, constant_len);
1968 ret = krb5_copy_keyblock(context, d.key, derived_key);
1969 _krb5_free_key_data(context, &d, et);
1973 static krb5_error_code
1974 _get_derived_key(krb5_context context,
1977 struct _krb5_key_data **key)
1980 struct _krb5_key_data *d;
1981 unsigned char constant[5];
1983 for(i = 0; i < crypto->num_key_usage; i++)
1984 if(crypto->key_usage[i].usage == usage) {
1985 *key = &crypto->key_usage[i].key;
1988 d = _new_derived_key(crypto, usage);
1990 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1993 krb5_copy_keyblock(context, crypto->key.key, &d->key);
1994 _krb5_put_int(constant, usage, 5);
1995 _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
2001 * Create a crypto context used for all encryption and signature
2002 * operation. The encryption type to use is taken from the key, but
2003 * can be overridden with the enctype parameter. This can be useful
2004 * for encryptions types which is compatiable (DES for example).
2006 * To free the crypto context, use krb5_crypto_destroy().
2008 * @param context Kerberos context
2009 * @param key the key block information with all key data
2010 * @param etype the encryption type
2011 * @param crypto the resulting crypto context
2013 * @return Return an error code or 0.
2015 * @ingroup krb5_crypto
2018 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2019 krb5_crypto_init(krb5_context context,
2020 const krb5_keyblock *key,
2022 krb5_crypto *crypto)
2024 krb5_error_code ret;
2026 if(*crypto == NULL) {
2027 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2030 if(etype == ETYPE_NULL)
2031 etype = key->keytype;
2032 (*crypto)->et = _krb5_find_enctype(etype);
2033 if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
2036 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2037 N_("encryption type %d not supported", ""),
2039 return KRB5_PROG_ETYPE_NOSUPP;
2041 if((*crypto)->et->keytype->size != key->keyvalue.length) {
2044 krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
2045 "encryption key has bad length");
2046 return KRB5_BAD_KEYSIZE;
2048 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2054 (*crypto)->key.schedule = NULL;
2055 (*crypto)->num_key_usage = 0;
2056 (*crypto)->key_usage = NULL;
2061 free_key_schedule(krb5_context context,
2062 struct _krb5_key_data *key,
2063 struct _krb5_encryption_type *et)
2065 if (et->keytype->cleanup)
2066 (*et->keytype->cleanup)(context, key);
2067 memset(key->schedule->data, 0, key->schedule->length);
2068 krb5_free_data(context, key->schedule);
2072 _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
2073 struct _krb5_encryption_type *et)
2075 krb5_free_keyblock(context, key->key);
2077 free_key_schedule(context, key, et);
2078 key->schedule = NULL;
2083 free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
2084 struct _krb5_encryption_type *et)
2086 _krb5_free_key_data(context, &ku->key, et);
2090 * Free a crypto context created by krb5_crypto_init().
2092 * @param context Kerberos context
2093 * @param crypto crypto context to free
2095 * @return Return an error code or 0.
2097 * @ingroup krb5_crypto
2100 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2101 krb5_crypto_destroy(krb5_context context,
2106 for(i = 0; i < crypto->num_key_usage; i++)
2107 free_key_usage(context, &crypto->key_usage[i], crypto->et);
2108 free(crypto->key_usage);
2109 _krb5_free_key_data(context, &crypto->key, crypto->et);
2115 * Return the blocksize used algorithm referenced by the crypto context
2117 * @param context Kerberos context
2118 * @param crypto crypto context to query
2119 * @param blocksize the resulting blocksize
2121 * @return Return an error code or 0.
2123 * @ingroup krb5_crypto
2126 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2127 krb5_crypto_getblocksize(krb5_context context,
2131 *blocksize = crypto->et->blocksize;
2136 * Return the encryption type used by the crypto context
2138 * @param context Kerberos context
2139 * @param crypto crypto context to query
2140 * @param enctype the resulting encryption type
2142 * @return Return an error code or 0.
2144 * @ingroup krb5_crypto
2147 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2148 krb5_crypto_getenctype(krb5_context context,
2150 krb5_enctype *enctype)
2152 *enctype = crypto->et->type;
2157 * Return the padding size used by the crypto context
2159 * @param context Kerberos context
2160 * @param crypto crypto context to query
2161 * @param padsize the return padding size
2163 * @return Return an error code or 0.
2165 * @ingroup krb5_crypto
2168 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2169 krb5_crypto_getpadsize(krb5_context context,
2173 *padsize = crypto->et->padsize;
2178 * Return the confounder size used by the crypto context
2180 * @param context Kerberos context
2181 * @param crypto crypto context to query
2182 * @param confoundersize the returned confounder size
2184 * @return Return an error code or 0.
2186 * @ingroup krb5_crypto
2189 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2190 krb5_crypto_getconfoundersize(krb5_context context,
2192 size_t *confoundersize)
2194 *confoundersize = crypto->et->confoundersize;
2200 * Disable encryption type
2202 * @param context Kerberos 5 context
2203 * @param enctype encryption type to disable
2205 * @return Return an error code or 0.
2207 * @ingroup krb5_crypto
2210 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2211 krb5_enctype_disable(krb5_context context,
2212 krb5_enctype enctype)
2214 struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2217 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2218 N_("encryption type %d not supported", ""),
2220 return KRB5_PROG_ETYPE_NOSUPP;
2222 et->flags |= F_DISABLED;
2227 * Enable encryption type
2229 * @param context Kerberos 5 context
2230 * @param enctype encryption type to enable
2232 * @return Return an error code or 0.
2234 * @ingroup krb5_crypto
2237 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2238 krb5_enctype_enable(krb5_context context,
2239 krb5_enctype enctype)
2241 struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2244 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2245 N_("encryption type %d not supported", ""),
2247 return KRB5_PROG_ETYPE_NOSUPP;
2249 et->flags &= ~F_DISABLED;
2254 * Enable or disable all weak encryption types
2256 * @param context Kerberos 5 context
2257 * @param enable true to enable, false to disable
2259 * @return Return an error code or 0.
2261 * @ingroup krb5_crypto
2264 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2265 krb5_allow_weak_crypto(krb5_context context,
2266 krb5_boolean enable)
2270 for(i = 0; i < _krb5_num_etypes; i++)
2271 if(_krb5_etypes[i]->flags & F_WEAK) {
2273 _krb5_etypes[i]->flags &= ~F_DISABLED;
2275 _krb5_etypes[i]->flags |= F_DISABLED;
2281 wrapped_length (krb5_context context,
2285 struct _krb5_encryption_type *et = crypto->et;
2286 size_t padsize = et->padsize;
2287 size_t checksumsize = CHECKSUMSIZE(et->checksum);
2290 res = et->confoundersize + checksumsize + data_len;
2291 res = (res + padsize - 1) / padsize * padsize;
2296 wrapped_length_dervied (krb5_context context,
2300 struct _krb5_encryption_type *et = crypto->et;
2301 size_t padsize = et->padsize;
2304 res = et->confoundersize + data_len;
2305 res = (res + padsize - 1) / padsize * padsize;
2306 if (et->keyed_checksum)
2307 res += et->keyed_checksum->checksumsize;
2309 res += et->checksum->checksumsize;
2314 * Return the size of an encrypted packet of length `data_len'
2317 KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
2318 krb5_get_wrapped_length (krb5_context context,
2322 if (derived_crypto (context, crypto))
2323 return wrapped_length_dervied (context, crypto, data_len);
2325 return wrapped_length (context, crypto, data_len);
2329 * Return the size of an encrypted packet of length `data_len'
2333 crypto_overhead (krb5_context context,
2336 struct _krb5_encryption_type *et = crypto->et;
2339 res = CHECKSUMSIZE(et->checksum);
2340 res += et->confoundersize;
2341 if (et->padsize > 1)
2347 crypto_overhead_dervied (krb5_context context,
2350 struct _krb5_encryption_type *et = crypto->et;
2353 if (et->keyed_checksum)
2354 res = CHECKSUMSIZE(et->keyed_checksum);
2356 res = CHECKSUMSIZE(et->checksum);
2357 res += et->confoundersize;
2358 if (et->padsize > 1)
2363 KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
2364 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
2366 if (derived_crypto (context, crypto))
2367 return crypto_overhead_dervied (context, crypto);
2369 return crypto_overhead (context, crypto);
2373 * Converts the random bytestring to a protocol key according to
2374 * Kerberos crypto frame work. It may be assumed that all the bits of
2375 * the input string are equally random, even though the entropy
2376 * present in the random source may be limited.
2378 * @param context Kerberos 5 context
2379 * @param type the enctype resulting key will be of
2380 * @param data input random data to convert to a key
2381 * @param size size of input random data, at least krb5_enctype_keysize() long
2382 * @param key key, output key, free with krb5_free_keyblock_contents()
2384 * @return Return an error code or 0.
2386 * @ingroup krb5_crypto
2389 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2390 krb5_random_to_key(krb5_context context,
2396 krb5_error_code ret;
2397 struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2399 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2400 N_("encryption type %d not supported", ""),
2402 return KRB5_PROG_ETYPE_NOSUPP;
2404 if ((et->keytype->bits + 7) / 8 > size) {
2405 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2406 N_("encryption key %s needs %d bytes "
2407 "of random to make an encryption key "
2409 et->name, (int)et->keytype->size);
2410 return KRB5_PROG_ETYPE_NOSUPP;
2412 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
2415 key->keytype = type;
2416 if (et->keytype->random_to_key)
2417 (*et->keytype->random_to_key)(context, key, data, size);
2419 memcpy(key->keyvalue.data, data, et->keytype->size);
2426 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2427 krb5_crypto_prf_length(krb5_context context,
2431 struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2433 if(et == NULL || et->prf_length == 0) {
2434 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2435 N_("encryption type %d not supported", ""),
2437 return KRB5_PROG_ETYPE_NOSUPP;
2440 *length = et->prf_length;
2444 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2445 krb5_crypto_prf(krb5_context context,
2446 const krb5_crypto crypto,
2447 const krb5_data *input,
2450 struct _krb5_encryption_type *et = crypto->et;
2452 krb5_data_zero(output);
2454 if(et->prf == NULL) {
2455 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2456 "kerberos prf for %s not supported",
2458 return KRB5_PROG_ETYPE_NOSUPP;
2461 return (*et->prf)(context, crypto, input, output);
2464 static krb5_error_code
2465 krb5_crypto_prfplus(krb5_context context,
2466 const krb5_crypto crypto,
2467 const krb5_data *input,
2471 krb5_error_code ret;
2473 unsigned char i = 1;
2476 krb5_data_zero(&input2);
2477 krb5_data_zero(output);
2479 krb5_clear_error_message(context);
2481 ret = krb5_data_alloc(output, length);
2483 ret = krb5_data_alloc(&input2, input->length + 1);
2486 krb5_clear_error_message(context);
2488 memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
2495 ((unsigned char *)input2.data)[0] = i++;
2497 ret = krb5_crypto_prf(context, crypto, &input2, &block);
2501 if (block.length < length) {
2502 memcpy(p, block.data, block.length);
2503 length -= block.length;
2505 memcpy(p, block.data, length);
2509 krb5_data_free(&block);
2513 krb5_data_free(&input2);
2515 krb5_data_free(output);
2520 * The FX-CF2 key derivation function, used in FAST and preauth framework.
2522 * @param context Kerberos 5 context
2523 * @param crypto1 first key to combine
2524 * @param crypto2 second key to combine
2525 * @param pepper1 factor to combine with first key to garante uniqueness
2526 * @param pepper2 factor to combine with second key to garante uniqueness
2527 * @param enctype the encryption type of the resulting key
2528 * @param res allocated key, free with krb5_free_keyblock_contents()
2530 * @return Return an error code or 0.
2532 * @ingroup krb5_crypto
2535 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2536 krb5_crypto_fx_cf2(krb5_context context,
2537 const krb5_crypto crypto1,
2538 const krb5_crypto crypto2,
2541 krb5_enctype enctype,
2544 krb5_error_code ret;
2548 memset(res, 0, sizeof(*res));
2550 ret = krb5_enctype_keysize(context, enctype, &keysize);
2554 ret = krb5_data_alloc(&res->keyvalue, keysize);
2557 ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
2560 ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
2564 res->keytype = enctype;
2566 unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
2567 for (i = 0; i < keysize; i++)
2568 p3[i] = p1[i] ^ p2[i];
2572 krb5_data_free(&res->keyvalue);
2573 krb5_data_free(&os1);
2574 krb5_data_free(&os2);
2581 #ifndef HEIMDAL_SMALLER
2584 * Deprecated: keytypes doesn't exists, they are really enctypes.
2586 * @ingroup krb5_deprecated
2589 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2590 krb5_keytype_to_enctypes (krb5_context context,
2591 krb5_keytype keytype,
2594 KRB5_DEPRECATED_FUNCTION("Use X instead")
2600 for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2601 if (_krb5_etypes[i]->keytype->type == keytype
2602 && !(_krb5_etypes[i]->flags & F_PSEUDO)
2603 && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2607 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
2608 "Keytype have no mapping");
2609 return KRB5_PROG_KEYTYPE_NOSUPP;
2612 ret = malloc(n * sizeof(*ret));
2613 if (ret == NULL && n != 0) {
2614 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
2618 for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2619 if (_krb5_etypes[i]->keytype->type == keytype
2620 && !(_krb5_etypes[i]->flags & F_PSEUDO)
2621 && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2622 ret[n++] = _krb5_etypes[i]->type;
2630 * Deprecated: keytypes doesn't exists, they are really enctypes.
2632 * @ingroup krb5_deprecated
2635 /* if two enctypes have compatible keys */
2636 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2637 krb5_enctypes_compatible_keys(krb5_context context,
2638 krb5_enctype etype1,
2639 krb5_enctype etype2)
2640 KRB5_DEPRECATED_FUNCTION("Use X instead")
2642 struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
2643 struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
2644 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2647 #endif /* HEIMDAL_SMALLER */