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
*);
55 * Converts etype to a user readable string and sets as a side effect
56 * the krb5_error_message containing this string. Returns
57 * KRB5_PROG_ETYPE_NOSUPP in not the conversion of the etype failed in
58 * which case the error code of the etype convesion is returned.
61 static krb5_error_code
62 unsupported_enctype(krb5_context context
, krb5_enctype etype
)
67 ret
= krb5_enctype_to_string(context
, etype
, &name
);
71 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
72 N_("Encryption type %s not supported", ""),
75 return KRB5_PROG_ETYPE_NOSUPP
;
82 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
83 krb5_enctype_keysize(krb5_context context
,
87 struct _krb5_encryption_type
*et
= _krb5_find_enctype(type
);
89 return unsupported_enctype (context
, type
);
91 *keysize
= et
->keytype
->size
;
95 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
96 krb5_enctype_keybits(krb5_context context
,
100 struct _krb5_encryption_type
*et
= _krb5_find_enctype(type
);
102 return unsupported_enctype (context
, type
);
104 *keybits
= et
->keytype
->bits
;
108 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
109 krb5_generate_random_keyblock(krb5_context context
,
114 struct _krb5_encryption_type
*et
= _krb5_find_enctype(type
);
116 return unsupported_enctype (context
, type
);
118 ret
= krb5_data_alloc(&key
->keyvalue
, et
->keytype
->size
);
122 if(et
->keytype
->random_key
)
123 (*et
->keytype
->random_key
)(context
, key
);
125 krb5_generate_random_block(key
->keyvalue
.data
,
126 key
->keyvalue
.length
);
130 static krb5_error_code
131 _key_schedule(krb5_context context
,
132 struct _krb5_key_data
*key
)
135 struct _krb5_encryption_type
*et
= _krb5_find_enctype(key
->key
->keytype
);
136 struct _krb5_key_type
*kt
;
139 return unsupported_enctype (context
,
145 if(kt
->schedule
== NULL
)
147 if (key
->schedule
!= NULL
)
149 ALLOC(key
->schedule
, 1);
150 if(key
->schedule
== NULL
) {
151 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
154 ret
= krb5_data_alloc(key
->schedule
, kt
->schedule_size
);
157 key
->schedule
= NULL
;
160 (*kt
->schedule
)(context
, kt
, key
);
164 /************************************************************
166 ************************************************************/
168 static krb5_error_code
169 SHA1_checksum(krb5_context context
,
170 struct _krb5_key_data
*key
,
176 if (EVP_Digest(data
, len
, C
->checksum
.data
, NULL
, EVP_sha1(), NULL
) != 1)
177 krb5_abortx(context
, "sha1 checksum failed");
181 /* HMAC according to RFC2104 */
183 _krb5_internal_hmac(krb5_context context
,
184 struct _krb5_checksum_type
*cm
,
188 struct _krb5_key_data
*keyblock
,
191 unsigned char *ipad
, *opad
;
196 ipad
= malloc(cm
->blocksize
+ len
);
199 opad
= malloc(cm
->blocksize
+ cm
->checksumsize
);
204 memset(ipad
, 0x36, cm
->blocksize
);
205 memset(opad
, 0x5c, cm
->blocksize
);
207 if(keyblock
->key
->keyvalue
.length
> cm
->blocksize
){
208 (*cm
->checksum
)(context
,
210 keyblock
->key
->keyvalue
.data
,
211 keyblock
->key
->keyvalue
.length
,
214 key
= result
->checksum
.data
;
215 key_len
= result
->checksum
.length
;
217 key
= keyblock
->key
->keyvalue
.data
;
218 key_len
= keyblock
->key
->keyvalue
.length
;
220 for(i
= 0; i
< key_len
; i
++){
224 memcpy(ipad
+ cm
->blocksize
, data
, len
);
225 (*cm
->checksum
)(context
, keyblock
, ipad
, cm
->blocksize
+ len
,
227 memcpy(opad
+ cm
->blocksize
, result
->checksum
.data
,
228 result
->checksum
.length
);
229 (*cm
->checksum
)(context
, keyblock
, opad
,
230 cm
->blocksize
+ cm
->checksumsize
, usage
, result
);
231 memset(ipad
, 0, cm
->blocksize
+ len
);
233 memset(opad
, 0, cm
->blocksize
+ cm
->checksumsize
);
239 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
240 krb5_hmac(krb5_context context
,
241 krb5_cksumtype cktype
,
248 struct _krb5_checksum_type
*c
= _krb5_find_checksum(cktype
);
249 struct _krb5_key_data kd
;
253 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
254 N_("checksum type %d not supported", ""),
256 return KRB5_PROG_SUMTYPE_NOSUPP
;
262 ret
= _krb5_internal_hmac(context
, c
, data
, len
, usage
, &kd
, result
);
265 krb5_free_data(context
, kd
.schedule
);
271 _krb5_SP_HMAC_SHA1_checksum(krb5_context context
,
272 struct _krb5_key_data
*key
,
278 struct _krb5_checksum_type
*c
= _krb5_find_checksum(CKSUMTYPE_SHA1
);
283 res
.checksum
.data
= sha1_data
;
284 res
.checksum
.length
= sizeof(sha1_data
);
286 ret
= _krb5_internal_hmac(context
, c
, data
, len
, usage
, key
, &res
);
288 krb5_abortx(context
, "hmac failed");
289 memcpy(result
->checksum
.data
, res
.checksum
.data
, result
->checksum
.length
);
293 struct _krb5_checksum_type _krb5_checksum_sha1
= {
303 struct _krb5_checksum_type
*
304 _krb5_find_checksum(krb5_cksumtype type
)
307 for(i
= 0; i
< _krb5_num_checksums
; i
++)
308 if(_krb5_checksum_types
[i
]->type
== type
)
309 return _krb5_checksum_types
[i
];
313 static krb5_error_code
314 get_checksum_key(krb5_context context
,
316 unsigned usage
, /* not krb5_key_usage */
317 struct _krb5_checksum_type
*ct
,
318 struct _krb5_key_data
**key
)
320 krb5_error_code ret
= 0;
322 if(ct
->flags
& F_DERIVED
)
323 ret
= _get_derived_key(context
, crypto
, usage
, key
);
324 else if(ct
->flags
& F_VARIANT
) {
327 *key
= _new_derived_key(crypto
, 0xff/* KRB5_KU_RFC1510_VARIANT */);
329 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
332 ret
= krb5_copy_keyblock(context
, crypto
->key
.key
, &(*key
)->key
);
335 for(i
= 0; i
< (*key
)->key
->keyvalue
.length
; i
++)
336 ((unsigned char*)(*key
)->key
->keyvalue
.data
)[i
] ^= 0xF0;
341 ret
= _key_schedule(context
, *key
);
345 static krb5_error_code
346 create_checksum (krb5_context context
,
347 struct _krb5_checksum_type
*ct
,
355 struct _krb5_key_data
*dkey
;
358 if (ct
->flags
& F_DISABLED
) {
359 krb5_clear_error_message (context
);
360 return KRB5_PROG_SUMTYPE_NOSUPP
;
362 keyed_checksum
= (ct
->flags
& F_KEYED
) != 0;
363 if(keyed_checksum
&& crypto
== NULL
) {
364 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
365 N_("Checksum type %s is keyed but no "
366 "crypto context (key) was passed in", ""),
368 return KRB5_PROG_SUMTYPE_NOSUPP
; /* XXX */
371 ret
= get_checksum_key(context
, crypto
, usage
, ct
, &dkey
);
376 result
->cksumtype
= ct
->type
;
377 ret
= krb5_data_alloc(&result
->checksum
, ct
->checksumsize
);
380 return (*ct
->checksum
)(context
, dkey
, data
, len
, usage
, result
);
384 arcfour_checksum_p(struct _krb5_checksum_type
*ct
, krb5_crypto crypto
)
386 return (ct
->type
== CKSUMTYPE_HMAC_MD5
) &&
387 (crypto
->key
.key
->keytype
== KEYTYPE_ARCFOUR
);
390 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
391 krb5_create_checksum(krb5_context context
,
393 krb5_key_usage usage
,
399 struct _krb5_checksum_type
*ct
= NULL
;
402 /* type 0 -> pick from crypto */
404 ct
= _krb5_find_checksum(type
);
406 ct
= crypto
->et
->keyed_checksum
;
408 ct
= crypto
->et
->checksum
;
412 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
413 N_("checksum type %d not supported", ""),
415 return KRB5_PROG_SUMTYPE_NOSUPP
;
418 if (arcfour_checksum_p(ct
, crypto
)) {
420 _krb5_usage2arcfour(context
, &keyusage
);
422 keyusage
= CHECKSUM_USAGE(usage
);
424 return create_checksum(context
, ct
, crypto
, keyusage
,
428 static krb5_error_code
429 verify_checksum(krb5_context context
,
431 unsigned usage
, /* not krb5_key_usage */
437 struct _krb5_key_data
*dkey
;
440 struct _krb5_checksum_type
*ct
;
442 ct
= _krb5_find_checksum(cksum
->cksumtype
);
443 if (ct
== NULL
|| (ct
->flags
& F_DISABLED
)) {
444 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
445 N_("checksum type %d not supported", ""),
447 return KRB5_PROG_SUMTYPE_NOSUPP
;
449 if(ct
->checksumsize
!= cksum
->checksum
.length
) {
450 krb5_clear_error_message (context
);
451 krb5_set_error_message(context
, KRB5KRB_AP_ERR_BAD_INTEGRITY
,
452 N_("Decrypt integrity check failed for checksum type %s, "
453 "length was %u, expected %u", ""),
454 ct
->name
, (unsigned)cksum
->checksum
.length
,
455 (unsigned)ct
->checksumsize
);
457 return KRB5KRB_AP_ERR_BAD_INTEGRITY
; /* XXX */
459 keyed_checksum
= (ct
->flags
& F_KEYED
) != 0;
461 struct _krb5_checksum_type
*kct
;
462 if (crypto
== NULL
) {
463 krb5_set_error_message(context
, KRB5_PROG_SUMTYPE_NOSUPP
,
464 N_("Checksum type %s is keyed but no "
465 "crypto context (key) was passed in", ""),
467 return KRB5_PROG_SUMTYPE_NOSUPP
; /* XXX */
469 kct
= crypto
->et
->keyed_checksum
;
470 if (kct
== NULL
|| kct
->type
!= ct
->type
) {
471 krb5_set_error_message(context
, KRB5_PROG_SUMTYPE_NOSUPP
,
472 N_("Checksum type %s is keyed, but "
473 "the key type %s passed didnt have that checksum "
474 "type as the keyed type", ""),
475 ct
->name
, crypto
->et
->name
);
476 return KRB5_PROG_SUMTYPE_NOSUPP
; /* XXX */
479 ret
= get_checksum_key(context
, crypto
, usage
, ct
, &dkey
);
486 * If checksum have a verify function, lets use that instead of
487 * calling ->checksum and then compare result.
491 ret
= (*ct
->verify
)(context
, dkey
, data
, len
, usage
, cksum
);
493 krb5_set_error_message(context
, ret
,
494 N_("Decrypt integrity check failed for checksum "
495 "type %s, key type %s", ""),
496 ct
->name
, (crypto
!= NULL
)? crypto
->et
->name
: "(none)");
500 ret
= krb5_data_alloc (&c
.checksum
, ct
->checksumsize
);
504 ret
= (*ct
->checksum
)(context
, dkey
, data
, len
, usage
, &c
);
506 krb5_data_free(&c
.checksum
);
510 if(krb5_data_ct_cmp(&c
.checksum
, &cksum
->checksum
) != 0) {
511 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
512 krb5_set_error_message(context
, ret
,
513 N_("Decrypt integrity check failed for checksum "
514 "type %s, key type %s", ""),
515 ct
->name
, crypto
? crypto
->et
->name
: "(unkeyed)");
519 krb5_data_free (&c
.checksum
);
523 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
524 krb5_verify_checksum(krb5_context context
,
526 krb5_key_usage usage
,
531 struct _krb5_checksum_type
*ct
;
534 ct
= _krb5_find_checksum(cksum
->cksumtype
);
536 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
537 N_("checksum type %d not supported", ""),
539 return KRB5_PROG_SUMTYPE_NOSUPP
;
542 if (arcfour_checksum_p(ct
, crypto
)) {
544 _krb5_usage2arcfour(context
, &keyusage
);
546 keyusage
= CHECKSUM_USAGE(usage
);
548 return verify_checksum(context
, crypto
, keyusage
,
552 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
553 krb5_crypto_get_checksum_type(krb5_context context
,
555 krb5_cksumtype
*type
)
557 struct _krb5_checksum_type
*ct
= NULL
;
559 if (crypto
!= NULL
) {
560 ct
= crypto
->et
->keyed_checksum
;
562 ct
= crypto
->et
->checksum
;
566 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
567 N_("checksum type not found", ""));
568 return KRB5_PROG_SUMTYPE_NOSUPP
;
577 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
578 krb5_checksumsize(krb5_context context
,
582 struct _krb5_checksum_type
*ct
= _krb5_find_checksum(type
);
584 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
585 N_("checksum type %d not supported", ""),
587 return KRB5_PROG_SUMTYPE_NOSUPP
;
589 *size
= ct
->checksumsize
;
593 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
594 krb5_checksum_is_keyed(krb5_context context
,
597 struct _krb5_checksum_type
*ct
= _krb5_find_checksum(type
);
600 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
601 N_("checksum type %d not supported", ""),
603 return KRB5_PROG_SUMTYPE_NOSUPP
;
605 return ct
->flags
& F_KEYED
;
608 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
609 krb5_checksum_is_collision_proof(krb5_context context
,
612 struct _krb5_checksum_type
*ct
= _krb5_find_checksum(type
);
615 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
616 N_("checksum type %d not supported", ""),
618 return KRB5_PROG_SUMTYPE_NOSUPP
;
620 return ct
->flags
& F_CPROOF
;
623 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
624 krb5_checksum_disable(krb5_context context
,
627 struct _krb5_checksum_type
*ct
= _krb5_find_checksum(type
);
630 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
631 N_("checksum type %d not supported", ""),
633 return KRB5_PROG_SUMTYPE_NOSUPP
;
635 ct
->flags
|= F_DISABLED
;
639 /************************************************************
641 ************************************************************/
643 struct _krb5_encryption_type
*
644 _krb5_find_enctype(krb5_enctype type
)
647 for(i
= 0; i
< _krb5_num_etypes
; i
++)
648 if(_krb5_etypes
[i
]->type
== type
)
649 return _krb5_etypes
[i
];
654 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
655 krb5_enctype_to_string(krb5_context context
,
659 struct _krb5_encryption_type
*e
;
660 e
= _krb5_find_enctype(etype
);
662 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
663 N_("encryption type %d not supported", ""),
666 return KRB5_PROG_ETYPE_NOSUPP
;
668 *string
= strdup(e
->name
);
669 if(*string
== NULL
) {
670 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
676 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
677 krb5_string_to_enctype(krb5_context context
,
682 for(i
= 0; i
< _krb5_num_etypes
; i
++)
683 if(strcasecmp(_krb5_etypes
[i
]->name
, string
) == 0){
684 *etype
= _krb5_etypes
[i
]->type
;
687 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
688 N_("encryption type %s not supported", ""),
690 return KRB5_PROG_ETYPE_NOSUPP
;
693 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
694 krb5_enctype_to_keytype(krb5_context context
,
696 krb5_keytype
*keytype
)
698 struct _krb5_encryption_type
*e
= _krb5_find_enctype(etype
);
700 return unsupported_enctype (context
, etype
);
702 *keytype
= e
->keytype
->type
; /* XXX */
707 * Check if a enctype is valid, return 0 if it is.
709 * @param context Kerberos context
710 * @param etype enctype to check if its valid or not
712 * @return Return an error code for an failure or 0 on success (enctype valid).
713 * @ingroup krb5_crypto
716 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
717 krb5_enctype_valid(krb5_context context
,
720 struct _krb5_encryption_type
*e
= _krb5_find_enctype(etype
);
721 if(e
&& (e
->flags
& F_DISABLED
) == 0)
724 return KRB5_PROG_ETYPE_NOSUPP
;
726 return unsupported_enctype (context
, etype
);
728 /* Must be (e->flags & F_DISABLED) */
729 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
730 N_("encryption type %s is disabled", ""),
732 return KRB5_PROG_ETYPE_NOSUPP
;
736 * Return the coresponding encryption type for a checksum type.
738 * @param context Kerberos context
739 * @param ctype The checksum type to get the result enctype for
740 * @param etype The returned encryption, when the matching etype is
741 * not found, etype is set to ETYPE_NULL.
743 * @return Return an error code for an failure or 0 on success.
744 * @ingroup krb5_crypto
748 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
749 krb5_cksumtype_to_enctype(krb5_context context
,
750 krb5_cksumtype ctype
,
757 for(i
= 0; i
< _krb5_num_etypes
; i
++) {
758 if(_krb5_etypes
[i
]->keyed_checksum
&&
759 _krb5_etypes
[i
]->keyed_checksum
->type
== ctype
)
761 *etype
= _krb5_etypes
[i
]->type
;
766 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
767 N_("checksum type %d not supported", ""),
769 return KRB5_PROG_SUMTYPE_NOSUPP
;
773 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
774 krb5_cksumtype_valid(krb5_context context
,
775 krb5_cksumtype ctype
)
777 struct _krb5_checksum_type
*c
= _krb5_find_checksum(ctype
);
779 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
780 N_("checksum type %d not supported", ""),
782 return KRB5_PROG_SUMTYPE_NOSUPP
;
784 if (c
->flags
& F_DISABLED
) {
785 krb5_set_error_message (context
, KRB5_PROG_SUMTYPE_NOSUPP
,
786 N_("checksum type %s is disabled", ""),
788 return KRB5_PROG_SUMTYPE_NOSUPP
;
795 derived_crypto(krb5_context context
,
798 return (crypto
->et
->flags
& F_DERIVED
) != 0;
802 special_crypto(krb5_context context
,
805 return (crypto
->et
->flags
& F_SPECIAL
) != 0;
808 #define CHECKSUMSIZE(C) ((C)->checksumsize)
809 #define CHECKSUMTYPE(C) ((C)->type)
811 static krb5_error_code
812 encrypt_internal_derived(krb5_context context
,
820 size_t sz
, block_sz
, checksum_sz
, total_sz
;
822 unsigned char *p
, *q
;
824 struct _krb5_key_data
*dkey
;
825 const struct _krb5_encryption_type
*et
= crypto
->et
;
827 checksum_sz
= CHECKSUMSIZE(et
->keyed_checksum
);
829 sz
= et
->confoundersize
+ len
;
830 block_sz
= (sz
+ et
->padsize
- 1) &~ (et
->padsize
- 1); /* pad */
831 total_sz
= block_sz
+ checksum_sz
;
832 p
= calloc(1, total_sz
);
834 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
839 krb5_generate_random_block(q
, et
->confoundersize
); /* XXX */
840 q
+= et
->confoundersize
;
841 memcpy(q
, data
, len
);
843 ret
= create_checksum(context
,
846 INTEGRITY_USAGE(usage
),
850 if(ret
== 0 && cksum
.checksum
.length
!= checksum_sz
) {
851 free_Checksum (&cksum
);
852 krb5_clear_error_message (context
);
853 ret
= KRB5_CRYPTO_INTERNAL
;
857 memcpy(p
+ block_sz
, cksum
.checksum
.data
, cksum
.checksum
.length
);
858 free_Checksum (&cksum
);
859 ret
= _get_derived_key(context
, crypto
, ENCRYPTION_USAGE(usage
), &dkey
);
862 ret
= _key_schedule(context
, dkey
);
865 ret
= (*et
->encrypt
)(context
, dkey
, p
, block_sz
, 1, usage
, ivec
);
869 result
->length
= total_sz
;
872 memset(p
, 0, total_sz
);
878 static krb5_error_code
879 encrypt_internal(krb5_context context
,
886 size_t sz
, block_sz
, checksum_sz
;
888 unsigned char *p
, *q
;
890 const struct _krb5_encryption_type
*et
= crypto
->et
;
892 checksum_sz
= CHECKSUMSIZE(et
->checksum
);
894 sz
= et
->confoundersize
+ checksum_sz
+ len
;
895 block_sz
= (sz
+ et
->padsize
- 1) &~ (et
->padsize
- 1); /* pad */
896 p
= calloc(1, block_sz
);
898 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
903 krb5_generate_random_block(q
, et
->confoundersize
); /* XXX */
904 q
+= et
->confoundersize
;
905 memset(q
, 0, checksum_sz
);
907 memcpy(q
, data
, len
);
909 ret
= create_checksum(context
,
916 if(ret
== 0 && cksum
.checksum
.length
!= checksum_sz
) {
917 krb5_clear_error_message (context
);
918 free_Checksum(&cksum
);
919 ret
= KRB5_CRYPTO_INTERNAL
;
923 memcpy(p
+ et
->confoundersize
, cksum
.checksum
.data
, cksum
.checksum
.length
);
924 free_Checksum(&cksum
);
925 ret
= _key_schedule(context
, &crypto
->key
);
928 ret
= (*et
->encrypt
)(context
, &crypto
->key
, p
, block_sz
, 1, 0, ivec
);
930 memset(p
, 0, block_sz
);
935 result
->length
= block_sz
;
938 memset(p
, 0, block_sz
);
943 static krb5_error_code
944 encrypt_internal_special(krb5_context context
,
952 struct _krb5_encryption_type
*et
= crypto
->et
;
953 size_t cksum_sz
= CHECKSUMSIZE(et
->checksum
);
954 size_t sz
= len
+ cksum_sz
+ et
->confoundersize
;
960 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
964 memset (p
, 0, cksum_sz
);
966 krb5_generate_random_block(p
, et
->confoundersize
);
967 p
+= et
->confoundersize
;
968 memcpy (p
, data
, len
);
969 ret
= (*et
->encrypt
)(context
, &crypto
->key
, tmp
, sz
, TRUE
, usage
, ivec
);
980 static krb5_error_code
981 decrypt_internal_derived(krb5_context context
,
993 struct _krb5_key_data
*dkey
;
994 struct _krb5_encryption_type
*et
= crypto
->et
;
997 checksum_sz
= CHECKSUMSIZE(et
->keyed_checksum
);
998 if (len
< checksum_sz
+ et
->confoundersize
) {
999 krb5_set_error_message(context
, KRB5_BAD_MSIZE
,
1000 N_("Encrypted data shorter then "
1001 "checksum + confunder", ""));
1002 return KRB5_BAD_MSIZE
;
1005 if (((len
- checksum_sz
) % et
->padsize
) != 0) {
1006 krb5_clear_error_message(context
);
1007 return KRB5_BAD_MSIZE
;
1011 if(len
!= 0 && p
== NULL
) {
1012 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1015 memcpy(p
, data
, len
);
1019 ret
= _get_derived_key(context
, crypto
, ENCRYPTION_USAGE(usage
), &dkey
);
1024 ret
= _key_schedule(context
, dkey
);
1029 ret
= (*et
->encrypt
)(context
, dkey
, p
, len
, 0, usage
, ivec
);
1035 cksum
.checksum
.data
= p
+ len
;
1036 cksum
.checksum
.length
= checksum_sz
;
1037 cksum
.cksumtype
= CHECKSUMTYPE(et
->keyed_checksum
);
1039 ret
= verify_checksum(context
,
1041 INTEGRITY_USAGE(usage
),
1049 l
= len
- et
->confoundersize
;
1050 memmove(p
, p
+ et
->confoundersize
, l
);
1051 result
->data
= realloc(p
, l
);
1052 if(result
->data
== NULL
&& l
!= 0) {
1054 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1061 static krb5_error_code
1062 decrypt_internal(krb5_context context
,
1069 krb5_error_code ret
;
1072 size_t checksum_sz
, l
;
1073 struct _krb5_encryption_type
*et
= crypto
->et
;
1075 if ((len
% et
->padsize
) != 0) {
1076 krb5_clear_error_message(context
);
1077 return KRB5_BAD_MSIZE
;
1079 checksum_sz
= CHECKSUMSIZE(et
->checksum
);
1080 if (len
< checksum_sz
+ et
->confoundersize
) {
1081 krb5_set_error_message(context
, KRB5_BAD_MSIZE
,
1082 N_("Encrypted data shorter then "
1083 "checksum + confunder", ""));
1084 return KRB5_BAD_MSIZE
;
1088 if(len
!= 0 && p
== NULL
) {
1089 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1092 memcpy(p
, data
, len
);
1094 ret
= _key_schedule(context
, &crypto
->key
);
1099 ret
= (*et
->encrypt
)(context
, &crypto
->key
, p
, len
, 0, 0, ivec
);
1104 ret
= krb5_data_copy(&cksum
.checksum
, p
+ et
->confoundersize
, checksum_sz
);
1109 memset(p
+ et
->confoundersize
, 0, checksum_sz
);
1110 cksum
.cksumtype
= CHECKSUMTYPE(et
->checksum
);
1111 ret
= verify_checksum(context
, NULL
, 0, p
, len
, &cksum
);
1112 free_Checksum(&cksum
);
1117 l
= len
- et
->confoundersize
- checksum_sz
;
1118 memmove(p
, p
+ et
->confoundersize
+ checksum_sz
, l
);
1119 result
->data
= realloc(p
, l
);
1120 if(result
->data
== NULL
&& l
!= 0) {
1122 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1129 static krb5_error_code
1130 decrypt_internal_special(krb5_context context
,
1138 struct _krb5_encryption_type
*et
= crypto
->et
;
1139 size_t cksum_sz
= CHECKSUMSIZE(et
->checksum
);
1140 size_t sz
= len
- cksum_sz
- et
->confoundersize
;
1142 krb5_error_code ret
;
1144 if ((len
% et
->padsize
) != 0) {
1145 krb5_clear_error_message(context
);
1146 return KRB5_BAD_MSIZE
;
1148 if (len
< cksum_sz
+ et
->confoundersize
) {
1149 krb5_set_error_message(context
, KRB5_BAD_MSIZE
,
1150 N_("Encrypted data shorter then "
1151 "checksum + confunder", ""));
1152 return KRB5_BAD_MSIZE
;
1157 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1160 memcpy(p
, data
, len
);
1162 ret
= (*et
->encrypt
)(context
, &crypto
->key
, p
, len
, FALSE
, usage
, ivec
);
1168 memmove (p
, p
+ cksum_sz
+ et
->confoundersize
, sz
);
1169 result
->data
= realloc(p
, sz
);
1170 if(result
->data
== NULL
&& sz
!= 0) {
1172 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1175 result
->length
= sz
;
1179 static krb5_crypto_iov
*
1180 find_iv(krb5_crypto_iov
*data
, size_t num_data
, unsigned type
)
1183 for (i
= 0; i
< num_data
; i
++)
1184 if (data
[i
].flags
== type
)
1190 * Inline encrypt a kerberos message
1192 * @param context Kerberos context
1193 * @param crypto Kerberos crypto context
1194 * @param usage Key usage for this buffer
1195 * @param data array of buffers to process
1196 * @param num_data length of array
1197 * @param ivec initial cbc/cts vector
1199 * @return Return an error code or 0.
1200 * @ingroup krb5_crypto
1202 * Kerberos encrypted data look like this:
1204 * 1. KRB5_CRYPTO_TYPE_HEADER
1205 * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
1206 * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
1207 * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
1208 * commonly used headers and trailers.
1209 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
1210 * 4. KRB5_CRYPTO_TYPE_TRAILER
1213 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1214 krb5_encrypt_iov_ivec(krb5_context context
,
1217 krb5_crypto_iov
*data
,
1221 size_t headersz
, trailersz
, len
;
1223 size_t sz
, block_sz
, pad_sz
;
1225 unsigned char *p
, *q
;
1226 krb5_error_code ret
;
1227 struct _krb5_key_data
*dkey
;
1228 const struct _krb5_encryption_type
*et
= crypto
->et
;
1229 krb5_crypto_iov
*tiv
, *piv
, *hiv
;
1232 krb5_clear_error_message(context
);
1233 return KRB5_CRYPTO_INTERNAL
;
1236 if(!derived_crypto(context
, crypto
)) {
1237 krb5_clear_error_message(context
);
1238 return KRB5_CRYPTO_INTERNAL
;
1241 headersz
= et
->confoundersize
;
1242 trailersz
= CHECKSUMSIZE(et
->keyed_checksum
);
1244 for (len
= 0, i
= 0; i
< num_data
; i
++) {
1245 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
1247 len
+= data
[i
].data
.length
;
1250 sz
= headersz
+ len
;
1251 block_sz
= (sz
+ et
->padsize
- 1) &~ (et
->padsize
- 1); /* pad */
1253 pad_sz
= block_sz
- sz
;
1257 hiv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_HEADER
);
1258 if (hiv
== NULL
|| hiv
->data
.length
!= headersz
)
1259 return KRB5_BAD_MSIZE
;
1261 krb5_generate_random_block(hiv
->data
.data
, hiv
->data
.length
);
1264 piv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_PADDING
);
1265 /* its ok to have no TYPE_PADDING if there is no padding */
1266 if (piv
== NULL
&& pad_sz
!= 0)
1267 return KRB5_BAD_MSIZE
;
1269 if (piv
->data
.length
< pad_sz
)
1270 return KRB5_BAD_MSIZE
;
1271 piv
->data
.length
= pad_sz
;
1273 memset(piv
->data
.data
, pad_sz
, pad_sz
);
1279 tiv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_TRAILER
);
1280 if (tiv
== NULL
|| tiv
->data
.length
!= trailersz
)
1281 return KRB5_BAD_MSIZE
;
1284 * XXX replace with EVP_Sign? at least make create_checksum an iov
1286 * XXX CTS EVP is broken, can't handle multi buffers :(
1290 for (i
= 0; i
< num_data
; i
++) {
1291 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
1293 len
+= data
[i
].data
.length
;
1296 p
= q
= malloc(len
);
1298 memcpy(q
, hiv
->data
.data
, hiv
->data
.length
);
1299 q
+= hiv
->data
.length
;
1300 for (i
= 0; i
< num_data
; i
++) {
1301 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
1302 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
1304 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
1305 q
+= data
[i
].data
.length
;
1308 memset(q
, 0, piv
->data
.length
);
1310 ret
= create_checksum(context
,
1313 INTEGRITY_USAGE(usage
),
1318 if(ret
== 0 && cksum
.checksum
.length
!= trailersz
) {
1319 free_Checksum (&cksum
);
1320 krb5_clear_error_message (context
);
1321 ret
= KRB5_CRYPTO_INTERNAL
;
1326 /* save cksum at end */
1327 memcpy(tiv
->data
.data
, cksum
.checksum
.data
, cksum
.checksum
.length
);
1328 free_Checksum (&cksum
);
1330 /* XXX replace with EVP_Cipher */
1331 p
= q
= malloc(block_sz
);
1335 memcpy(q
, hiv
->data
.data
, hiv
->data
.length
);
1336 q
+= hiv
->data
.length
;
1338 for (i
= 0; i
< num_data
; i
++) {
1339 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
1341 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
1342 q
+= data
[i
].data
.length
;
1345 memset(q
, 0, piv
->data
.length
);
1348 ret
= _get_derived_key(context
, crypto
, ENCRYPTION_USAGE(usage
), &dkey
);
1353 ret
= _key_schedule(context
, dkey
);
1359 ret
= (*et
->encrypt
)(context
, dkey
, p
, block_sz
, 1, usage
, ivec
);
1365 /* now copy data back to buffers */
1368 memcpy(hiv
->data
.data
, q
, hiv
->data
.length
);
1369 q
+= hiv
->data
.length
;
1371 for (i
= 0; i
< num_data
; i
++) {
1372 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
1374 memcpy(data
[i
].data
.data
, q
, data
[i
].data
.length
);
1375 q
+= data
[i
].data
.length
;
1378 memcpy(piv
->data
.data
, q
, pad_sz
);
1386 * Inline decrypt a Kerberos message.
1388 * @param context Kerberos context
1389 * @param crypto Kerberos crypto context
1390 * @param usage Key usage for this buffer
1391 * @param data array of buffers to process
1392 * @param num_data length of array
1393 * @param ivec initial cbc/cts vector
1395 * @return Return an error code or 0.
1396 * @ingroup krb5_crypto
1398 * 1. KRB5_CRYPTO_TYPE_HEADER
1399 * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
1400 * any order, however the receiver have to aware of the
1401 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
1402 * protocol headers and trailers. The output data will be of same
1403 * size as the input data or shorter.
1406 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1407 krb5_decrypt_iov_ivec(krb5_context context
,
1410 krb5_crypto_iov
*data
,
1411 unsigned int num_data
,
1415 size_t headersz
, trailersz
, len
;
1417 unsigned char *p
, *q
;
1418 krb5_error_code ret
;
1419 struct _krb5_key_data
*dkey
;
1420 struct _krb5_encryption_type
*et
= crypto
->et
;
1421 krb5_crypto_iov
*tiv
, *hiv
;
1423 if(!derived_crypto(context
, crypto
)) {
1424 krb5_clear_error_message(context
);
1425 return KRB5_CRYPTO_INTERNAL
;
1428 headersz
= et
->confoundersize
;
1430 hiv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_HEADER
);
1431 if (hiv
== NULL
|| hiv
->data
.length
!= headersz
)
1432 return KRB5_BAD_MSIZE
;
1435 trailersz
= CHECKSUMSIZE(et
->keyed_checksum
);
1437 tiv
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_TRAILER
);
1438 if (tiv
->data
.length
!= trailersz
)
1439 return KRB5_BAD_MSIZE
;
1441 /* Find length of data we will decrypt */
1444 for (i
= 0; i
< num_data
; i
++) {
1445 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
1447 len
+= data
[i
].data
.length
;
1450 if ((len
% et
->padsize
) != 0) {
1451 krb5_clear_error_message(context
);
1452 return KRB5_BAD_MSIZE
;
1455 /* XXX replace with EVP_Cipher */
1457 p
= q
= malloc(len
);
1461 memcpy(q
, hiv
->data
.data
, hiv
->data
.length
);
1462 q
+= hiv
->data
.length
;
1464 for (i
= 0; i
< num_data
; i
++) {
1465 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
1467 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
1468 q
+= data
[i
].data
.length
;
1471 ret
= _get_derived_key(context
, crypto
, ENCRYPTION_USAGE(usage
), &dkey
);
1476 ret
= _key_schedule(context
, dkey
);
1482 ret
= (*et
->encrypt
)(context
, dkey
, p
, len
, 0, usage
, ivec
);
1488 /* copy data back to buffers */
1489 memcpy(hiv
->data
.data
, p
, hiv
->data
.length
);
1490 q
= p
+ hiv
->data
.length
;
1491 for (i
= 0; i
< num_data
; i
++) {
1492 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
)
1494 memcpy(data
[i
].data
.data
, q
, data
[i
].data
.length
);
1495 q
+= data
[i
].data
.length
;
1500 /* check signature */
1501 for (i
= 0; i
< num_data
; i
++) {
1502 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
1504 len
+= data
[i
].data
.length
;
1507 p
= q
= malloc(len
);
1511 memcpy(q
, hiv
->data
.data
, hiv
->data
.length
);
1512 q
+= hiv
->data
.length
;
1513 for (i
= 0; i
< num_data
; i
++) {
1514 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
1515 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
1517 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
1518 q
+= data
[i
].data
.length
;
1521 cksum
.checksum
.data
= tiv
->data
.data
;
1522 cksum
.checksum
.length
= tiv
->data
.length
;
1523 cksum
.cksumtype
= CHECKSUMTYPE(et
->keyed_checksum
);
1525 ret
= verify_checksum(context
,
1527 INTEGRITY_USAGE(usage
),
1536 * Create a Kerberos message checksum.
1538 * @param context Kerberos context
1539 * @param crypto Kerberos crypto context
1540 * @param usage Key usage for this buffer
1541 * @param data array of buffers to process
1542 * @param num_data length of array
1543 * @param type output data
1545 * @return Return an error code or 0.
1546 * @ingroup krb5_crypto
1549 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1550 krb5_create_checksum_iov(krb5_context context
,
1553 krb5_crypto_iov
*data
,
1554 unsigned int num_data
,
1555 krb5_cksumtype
*type
)
1558 krb5_crypto_iov
*civ
;
1559 krb5_error_code ret
;
1564 if(!derived_crypto(context
, crypto
)) {
1565 krb5_clear_error_message(context
);
1566 return KRB5_CRYPTO_INTERNAL
;
1569 civ
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_CHECKSUM
);
1571 return KRB5_BAD_MSIZE
;
1574 for (i
= 0; i
< num_data
; i
++) {
1575 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
1576 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
1578 len
+= data
[i
].data
.length
;
1581 p
= q
= malloc(len
);
1583 for (i
= 0; i
< num_data
; i
++) {
1584 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
1585 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
1587 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
1588 q
+= data
[i
].data
.length
;
1591 ret
= krb5_create_checksum(context
, crypto
, usage
, 0, p
, len
, &cksum
);
1597 *type
= cksum
.cksumtype
;
1599 if (cksum
.checksum
.length
> civ
->data
.length
) {
1600 krb5_set_error_message(context
, KRB5_BAD_MSIZE
,
1601 N_("Checksum larger then input buffer", ""));
1602 free_Checksum(&cksum
);
1603 return KRB5_BAD_MSIZE
;
1606 civ
->data
.length
= cksum
.checksum
.length
;
1607 memcpy(civ
->data
.data
, cksum
.checksum
.data
, civ
->data
.length
);
1608 free_Checksum(&cksum
);
1614 * Verify a Kerberos message checksum.
1616 * @param context Kerberos context
1617 * @param crypto Kerberos crypto context
1618 * @param usage Key usage for this buffer
1619 * @param data array of buffers to process
1620 * @param num_data length of array
1621 * @param type return checksum type if not NULL
1623 * @return Return an error code or 0.
1624 * @ingroup krb5_crypto
1627 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1628 krb5_verify_checksum_iov(krb5_context context
,
1631 krb5_crypto_iov
*data
,
1632 unsigned int num_data
,
1633 krb5_cksumtype
*type
)
1635 struct _krb5_encryption_type
*et
= crypto
->et
;
1637 krb5_crypto_iov
*civ
;
1638 krb5_error_code ret
;
1643 if(!derived_crypto(context
, crypto
)) {
1644 krb5_clear_error_message(context
);
1645 return KRB5_CRYPTO_INTERNAL
;
1648 civ
= find_iv(data
, num_data
, KRB5_CRYPTO_TYPE_CHECKSUM
);
1650 return KRB5_BAD_MSIZE
;
1653 for (i
= 0; i
< num_data
; i
++) {
1654 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
1655 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
1657 len
+= data
[i
].data
.length
;
1660 p
= q
= malloc(len
);
1662 for (i
= 0; i
< num_data
; i
++) {
1663 if (data
[i
].flags
!= KRB5_CRYPTO_TYPE_DATA
&&
1664 data
[i
].flags
!= KRB5_CRYPTO_TYPE_SIGN_ONLY
)
1666 memcpy(q
, data
[i
].data
.data
, data
[i
].data
.length
);
1667 q
+= data
[i
].data
.length
;
1670 cksum
.cksumtype
= CHECKSUMTYPE(et
->keyed_checksum
);
1671 cksum
.checksum
.length
= civ
->data
.length
;
1672 cksum
.checksum
.data
= civ
->data
.data
;
1674 ret
= krb5_verify_checksum(context
, crypto
, usage
, p
, len
, &cksum
);
1677 if (ret
== 0 && type
)
1678 *type
= cksum
.cksumtype
;
1684 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1685 krb5_crypto_length(krb5_context context
,
1690 if (!derived_crypto(context
, crypto
)) {
1691 krb5_set_error_message(context
, EINVAL
, "not a derived crypto");
1696 case KRB5_CRYPTO_TYPE_EMPTY
:
1699 case KRB5_CRYPTO_TYPE_HEADER
:
1700 *len
= crypto
->et
->blocksize
;
1702 case KRB5_CRYPTO_TYPE_DATA
:
1703 case KRB5_CRYPTO_TYPE_SIGN_ONLY
:
1704 /* len must already been filled in */
1706 case KRB5_CRYPTO_TYPE_PADDING
:
1707 if (crypto
->et
->padsize
> 1)
1708 *len
= crypto
->et
->padsize
;
1712 case KRB5_CRYPTO_TYPE_TRAILER
:
1713 *len
= CHECKSUMSIZE(crypto
->et
->keyed_checksum
);
1715 case KRB5_CRYPTO_TYPE_CHECKSUM
:
1716 if (crypto
->et
->keyed_checksum
)
1717 *len
= CHECKSUMSIZE(crypto
->et
->keyed_checksum
);
1719 *len
= CHECKSUMSIZE(crypto
->et
->checksum
);
1722 krb5_set_error_message(context
, EINVAL
,
1723 "%d not a supported type", type
);
1728 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1729 krb5_crypto_length_iov(krb5_context context
,
1731 krb5_crypto_iov
*data
,
1732 unsigned int num_data
)
1734 krb5_error_code ret
;
1737 for (i
= 0; i
< num_data
; i
++) {
1738 ret
= krb5_crypto_length(context
, crypto
,
1740 &data
[i
].data
.length
);
1748 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1749 krb5_encrypt_ivec(krb5_context context
,
1757 if(derived_crypto(context
, crypto
))
1758 return encrypt_internal_derived(context
, crypto
, usage
,
1759 data
, len
, result
, ivec
);
1760 else if (special_crypto(context
, crypto
))
1761 return encrypt_internal_special (context
, crypto
, usage
,
1762 data
, len
, result
, ivec
);
1764 return encrypt_internal(context
, crypto
, data
, len
, result
, ivec
);
1767 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1768 krb5_encrypt(krb5_context context
,
1775 return krb5_encrypt_ivec(context
, crypto
, usage
, data
, len
, result
, NULL
);
1778 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1779 krb5_encrypt_EncryptedData(krb5_context context
,
1785 EncryptedData
*result
)
1787 result
->etype
= CRYPTO_ETYPE(crypto
);
1789 ALLOC(result
->kvno
, 1);
1790 *result
->kvno
= kvno
;
1792 result
->kvno
= NULL
;
1793 return krb5_encrypt(context
, crypto
, usage
, data
, len
, &result
->cipher
);
1796 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1797 krb5_decrypt_ivec(krb5_context context
,
1805 if(derived_crypto(context
, crypto
))
1806 return decrypt_internal_derived(context
, crypto
, usage
,
1807 data
, len
, result
, ivec
);
1808 else if (special_crypto (context
, crypto
))
1809 return decrypt_internal_special(context
, crypto
, usage
,
1810 data
, len
, result
, ivec
);
1812 return decrypt_internal(context
, crypto
, data
, len
, result
, ivec
);
1815 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1816 krb5_decrypt(krb5_context context
,
1823 return krb5_decrypt_ivec (context
, crypto
, usage
, data
, len
, result
,
1827 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1828 krb5_decrypt_EncryptedData(krb5_context context
,
1831 const EncryptedData
*e
,
1834 return krb5_decrypt(context
, crypto
, usage
,
1835 e
->cipher
.data
, e
->cipher
.length
, result
);
1838 /************************************************************
1840 ************************************************************/
1843 _krb5_derive_key(krb5_context context
,
1844 struct _krb5_encryption_type
*et
,
1845 struct _krb5_key_data
*key
,
1846 const void *constant
,
1849 unsigned char *k
= NULL
;
1850 unsigned int nblocks
= 0, i
;
1851 krb5_error_code ret
= 0;
1852 struct _krb5_key_type
*kt
= et
->keytype
;
1854 ret
= _key_schedule(context
, key
);
1857 if(et
->blocksize
* 8 < kt
->bits
|| len
!= et
->blocksize
) {
1858 nblocks
= (kt
->bits
+ et
->blocksize
* 8 - 1) / (et
->blocksize
* 8);
1859 k
= malloc(nblocks
* et
->blocksize
);
1862 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
1865 ret
= _krb5_n_fold(constant
, len
, k
, et
->blocksize
);
1867 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
1871 for(i
= 0; i
< nblocks
; i
++) {
1873 memcpy(k
+ i
* et
->blocksize
,
1874 k
+ (i
- 1) * et
->blocksize
,
1876 (*et
->encrypt
)(context
, key
, k
+ i
* et
->blocksize
, et
->blocksize
,
1880 /* this case is probably broken, but won't be run anyway */
1881 void *c
= malloc(len
);
1882 size_t res_len
= (kt
->bits
+ 7) / 8;
1884 if(len
!= 0 && c
== NULL
) {
1886 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
1889 memcpy(c
, constant
, len
);
1890 (*et
->encrypt
)(context
, key
, c
, len
, 1, 0, NULL
);
1891 k
= malloc(res_len
);
1892 if(res_len
!= 0 && k
== NULL
) {
1895 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
1898 ret
= _krb5_n_fold(c
, len
, k
, res_len
);
1901 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
1906 /* XXX keytype dependent post-processing */
1908 case KRB5_ENCTYPE_OLD_DES3_CBC_SHA1
:
1909 _krb5_DES3_random_to_key(context
, key
->key
, k
, nblocks
* et
->blocksize
);
1911 case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96
:
1912 case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96
:
1913 memcpy(key
->key
->keyvalue
.data
, k
, key
->key
->keyvalue
.length
);
1916 ret
= KRB5_CRYPTO_INTERNAL
;
1917 krb5_set_error_message(context
, ret
,
1918 N_("derive_key() called with unknown keytype (%u)", ""),
1923 if (key
->schedule
) {
1924 free_key_schedule(context
, key
, et
);
1925 key
->schedule
= NULL
;
1928 memset(k
, 0, nblocks
* et
->blocksize
);
1934 static struct _krb5_key_data
*
1935 _new_derived_key(krb5_crypto crypto
, unsigned usage
)
1937 struct _krb5_key_usage
*d
= crypto
->key_usage
;
1938 d
= realloc(d
, (crypto
->num_key_usage
+ 1) * sizeof(*d
));
1941 crypto
->key_usage
= d
;
1942 d
+= crypto
->num_key_usage
++;
1943 memset(d
, 0, sizeof(*d
));
1948 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1949 krb5_derive_key(krb5_context context
,
1950 const krb5_keyblock
*key
,
1952 const void *constant
,
1953 size_t constant_len
,
1954 krb5_keyblock
**derived_key
)
1956 krb5_error_code ret
;
1957 struct _krb5_encryption_type
*et
;
1958 struct _krb5_key_data d
;
1960 *derived_key
= NULL
;
1962 et
= _krb5_find_enctype (etype
);
1964 return unsupported_enctype (context
, etype
);
1967 ret
= krb5_copy_keyblock(context
, key
, &d
.key
);
1972 ret
= _krb5_derive_key(context
, et
, &d
, constant
, constant_len
);
1974 ret
= krb5_copy_keyblock(context
, d
.key
, derived_key
);
1975 _krb5_free_key_data(context
, &d
, et
);
1979 static krb5_error_code
1980 _get_derived_key(krb5_context context
,
1983 struct _krb5_key_data
**key
)
1986 struct _krb5_key_data
*d
;
1987 unsigned char constant
[5];
1989 for(i
= 0; i
< crypto
->num_key_usage
; i
++)
1990 if(crypto
->key_usage
[i
].usage
== usage
) {
1991 *key
= &crypto
->key_usage
[i
].key
;
1994 d
= _new_derived_key(crypto
, usage
);
1996 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
1999 krb5_copy_keyblock(context
, crypto
->key
.key
, &d
->key
);
2000 _krb5_put_int(constant
, usage
, 5);
2001 _krb5_derive_key(context
, crypto
->et
, d
, constant
, sizeof(constant
));
2007 * Create a crypto context used for all encryption and signature
2008 * operation. The encryption type to use is taken from the key, but
2009 * can be overridden with the enctype parameter. This can be useful
2010 * for encryptions types which is compatiable (DES for example).
2012 * To free the crypto context, use krb5_crypto_destroy().
2014 * @param context Kerberos context
2015 * @param key the key block information with all key data
2016 * @param etype the encryption type
2017 * @param crypto the resulting crypto context
2019 * @return Return an error code or 0.
2021 * @ingroup krb5_crypto
2024 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2025 krb5_crypto_init(krb5_context context
,
2026 const krb5_keyblock
*key
,
2028 krb5_crypto
*crypto
)
2030 krb5_error_code ret
;
2032 if(*crypto
== NULL
) {
2033 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
2036 if(etype
== (krb5_enctype
)ETYPE_NULL
)
2037 etype
= key
->keytype
;
2038 (*crypto
)->et
= _krb5_find_enctype(etype
);
2039 if((*crypto
)->et
== NULL
|| ((*crypto
)->et
->flags
& F_DISABLED
)) {
2042 return unsupported_enctype(context
, etype
);
2044 if((*crypto
)->et
->keytype
->size
!= key
->keyvalue
.length
) {
2047 krb5_set_error_message (context
, KRB5_BAD_KEYSIZE
,
2048 "encryption key has bad length");
2049 return KRB5_BAD_KEYSIZE
;
2051 ret
= krb5_copy_keyblock(context
, key
, &(*crypto
)->key
.key
);
2057 (*crypto
)->key
.schedule
= NULL
;
2058 (*crypto
)->num_key_usage
= 0;
2059 (*crypto
)->key_usage
= NULL
;
2064 free_key_schedule(krb5_context context
,
2065 struct _krb5_key_data
*key
,
2066 struct _krb5_encryption_type
*et
)
2068 if (et
->keytype
->cleanup
)
2069 (*et
->keytype
->cleanup
)(context
, key
);
2070 memset(key
->schedule
->data
, 0, key
->schedule
->length
);
2071 krb5_free_data(context
, key
->schedule
);
2075 _krb5_free_key_data(krb5_context context
, struct _krb5_key_data
*key
,
2076 struct _krb5_encryption_type
*et
)
2078 krb5_free_keyblock(context
, key
->key
);
2080 free_key_schedule(context
, key
, et
);
2081 key
->schedule
= NULL
;
2086 free_key_usage(krb5_context context
, struct _krb5_key_usage
*ku
,
2087 struct _krb5_encryption_type
*et
)
2089 _krb5_free_key_data(context
, &ku
->key
, et
);
2093 * Free a crypto context created by krb5_crypto_init().
2095 * @param context Kerberos context
2096 * @param crypto crypto context to free
2098 * @return Return an error code or 0.
2100 * @ingroup krb5_crypto
2103 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2104 krb5_crypto_destroy(krb5_context context
,
2109 for(i
= 0; i
< crypto
->num_key_usage
; i
++)
2110 free_key_usage(context
, &crypto
->key_usage
[i
], crypto
->et
);
2111 free(crypto
->key_usage
);
2112 _krb5_free_key_data(context
, &crypto
->key
, crypto
->et
);
2118 * Return the blocksize used algorithm referenced by the crypto context
2120 * @param context Kerberos context
2121 * @param crypto crypto context to query
2122 * @param blocksize the resulting blocksize
2124 * @return Return an error code or 0.
2126 * @ingroup krb5_crypto
2129 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2130 krb5_crypto_getblocksize(krb5_context context
,
2134 *blocksize
= crypto
->et
->blocksize
;
2139 * Return the encryption type used by the crypto context
2141 * @param context Kerberos context
2142 * @param crypto crypto context to query
2143 * @param enctype the resulting encryption type
2145 * @return Return an error code or 0.
2147 * @ingroup krb5_crypto
2150 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2151 krb5_crypto_getenctype(krb5_context context
,
2153 krb5_enctype
*enctype
)
2155 *enctype
= crypto
->et
->type
;
2160 * Return the padding size used by the crypto context
2162 * @param context Kerberos context
2163 * @param crypto crypto context to query
2164 * @param padsize the return padding size
2166 * @return Return an error code or 0.
2168 * @ingroup krb5_crypto
2171 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2172 krb5_crypto_getpadsize(krb5_context context
,
2176 *padsize
= crypto
->et
->padsize
;
2181 * Return the confounder size used by the crypto context
2183 * @param context Kerberos context
2184 * @param crypto crypto context to query
2185 * @param confoundersize the returned confounder size
2187 * @return Return an error code or 0.
2189 * @ingroup krb5_crypto
2192 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2193 krb5_crypto_getconfoundersize(krb5_context context
,
2195 size_t *confoundersize
)
2197 *confoundersize
= crypto
->et
->confoundersize
;
2203 * Disable encryption type
2205 * @param context Kerberos 5 context
2206 * @param enctype encryption type to disable
2208 * @return Return an error code or 0.
2210 * @ingroup krb5_crypto
2213 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2214 krb5_enctype_disable(krb5_context context
,
2215 krb5_enctype enctype
)
2217 struct _krb5_encryption_type
*et
= _krb5_find_enctype(enctype
);
2220 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
2221 N_("encryption type %d not supported", ""),
2223 return KRB5_PROG_ETYPE_NOSUPP
;
2225 et
->flags
|= F_DISABLED
;
2230 * Enable encryption type
2232 * @param context Kerberos 5 context
2233 * @param enctype encryption type to enable
2235 * @return Return an error code or 0.
2237 * @ingroup krb5_crypto
2240 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2241 krb5_enctype_enable(krb5_context context
,
2242 krb5_enctype enctype
)
2244 struct _krb5_encryption_type
*et
= _krb5_find_enctype(enctype
);
2247 krb5_set_error_message (context
, KRB5_PROG_ETYPE_NOSUPP
,
2248 N_("encryption type %d not supported", ""),
2250 return KRB5_PROG_ETYPE_NOSUPP
;
2252 et
->flags
&= ~F_DISABLED
;
2257 * Enable or disable all weak encryption types
2259 * @param context Kerberos 5 context
2260 * @param enable true to enable, false to disable
2262 * @return Return an error code or 0.
2264 * @ingroup krb5_crypto
2267 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2268 krb5_allow_weak_crypto(krb5_context context
,
2269 krb5_boolean enable
)
2273 for(i
= 0; i
< _krb5_num_etypes
; i
++)
2274 if(_krb5_etypes
[i
]->flags
& F_WEAK
) {
2276 _krb5_etypes
[i
]->flags
&= ~F_DISABLED
;
2278 _krb5_etypes
[i
]->flags
|= F_DISABLED
;
2284 * Returns is the encryption is strong or weak
2286 * @param context Kerberos 5 context
2287 * @param enctype encryption type to probe
2289 * @return Returns true if encryption type is weak or is not supported.
2291 * @ingroup krb5_crypto
2294 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2295 krb5_is_enctype_weak(krb5_context context
, krb5_enctype enctype
)
2297 struct _krb5_encryption_type
*et
= _krb5_find_enctype(enctype
);
2298 if(et
== NULL
|| (et
->flags
& F_WEAK
))
2304 wrapped_length (krb5_context context
,
2308 struct _krb5_encryption_type
*et
= crypto
->et
;
2309 size_t padsize
= et
->padsize
;
2310 size_t checksumsize
= CHECKSUMSIZE(et
->checksum
);
2313 res
= et
->confoundersize
+ checksumsize
+ data_len
;
2314 res
= (res
+ padsize
- 1) / padsize
* padsize
;
2319 wrapped_length_dervied (krb5_context context
,
2323 struct _krb5_encryption_type
*et
= crypto
->et
;
2324 size_t padsize
= et
->padsize
;
2327 res
= et
->confoundersize
+ data_len
;
2328 res
= (res
+ padsize
- 1) / padsize
* padsize
;
2329 if (et
->keyed_checksum
)
2330 res
+= et
->keyed_checksum
->checksumsize
;
2332 res
+= et
->checksum
->checksumsize
;
2337 * Return the size of an encrypted packet of length `data_len'
2340 KRB5_LIB_FUNCTION
size_t KRB5_LIB_CALL
2341 krb5_get_wrapped_length (krb5_context context
,
2345 if (derived_crypto (context
, crypto
))
2346 return wrapped_length_dervied (context
, crypto
, data_len
);
2348 return wrapped_length (context
, crypto
, data_len
);
2352 * Return the size of an encrypted packet of length `data_len'
2356 crypto_overhead (krb5_context context
,
2359 struct _krb5_encryption_type
*et
= crypto
->et
;
2362 res
= CHECKSUMSIZE(et
->checksum
);
2363 res
+= et
->confoundersize
;
2364 if (et
->padsize
> 1)
2370 crypto_overhead_dervied (krb5_context context
,
2373 struct _krb5_encryption_type
*et
= crypto
->et
;
2376 if (et
->keyed_checksum
)
2377 res
= CHECKSUMSIZE(et
->keyed_checksum
);
2379 res
= CHECKSUMSIZE(et
->checksum
);
2380 res
+= et
->confoundersize
;
2381 if (et
->padsize
> 1)
2386 KRB5_LIB_FUNCTION
size_t KRB5_LIB_CALL
2387 krb5_crypto_overhead (krb5_context context
, krb5_crypto crypto
)
2389 if (derived_crypto (context
, crypto
))
2390 return crypto_overhead_dervied (context
, crypto
);
2392 return crypto_overhead (context
, crypto
);
2396 * Converts the random bytestring to a protocol key according to
2397 * Kerberos crypto frame work. It may be assumed that all the bits of
2398 * the input string are equally random, even though the entropy
2399 * present in the random source may be limited.
2401 * @param context Kerberos 5 context
2402 * @param type the enctype resulting key will be of
2403 * @param data input random data to convert to a key
2404 * @param size size of input random data, at least krb5_enctype_keysize() long
2405 * @param key key, output key, free with krb5_free_keyblock_contents()
2407 * @return Return an error code or 0.
2409 * @ingroup krb5_crypto
2412 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2413 krb5_random_to_key(krb5_context context
,
2419 krb5_error_code ret
;
2420 struct _krb5_encryption_type
*et
= _krb5_find_enctype(type
);
2422 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
2423 N_("encryption type %d not supported", ""),
2425 return KRB5_PROG_ETYPE_NOSUPP
;
2427 if ((et
->keytype
->bits
+ 7) / 8 > size
) {
2428 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
2429 N_("encryption key %s needs %d bytes "
2430 "of random to make an encryption key "
2432 et
->name
, (int)et
->keytype
->size
);
2433 return KRB5_PROG_ETYPE_NOSUPP
;
2435 ret
= krb5_data_alloc(&key
->keyvalue
, et
->keytype
->size
);
2438 key
->keytype
= type
;
2439 if (et
->keytype
->random_to_key
)
2440 (*et
->keytype
->random_to_key
)(context
, key
, data
, size
);
2442 memcpy(key
->keyvalue
.data
, data
, et
->keytype
->size
);
2449 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2450 krb5_crypto_prf_length(krb5_context context
,
2454 struct _krb5_encryption_type
*et
= _krb5_find_enctype(type
);
2456 if(et
== NULL
|| et
->prf_length
== 0) {
2457 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
2458 N_("encryption type %d not supported", ""),
2460 return KRB5_PROG_ETYPE_NOSUPP
;
2463 *length
= et
->prf_length
;
2467 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2468 krb5_crypto_prf(krb5_context context
,
2469 const krb5_crypto crypto
,
2470 const krb5_data
*input
,
2473 struct _krb5_encryption_type
*et
= crypto
->et
;
2475 krb5_data_zero(output
);
2477 if(et
->prf
== NULL
) {
2478 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
2479 "kerberos prf for %s not supported",
2481 return KRB5_PROG_ETYPE_NOSUPP
;
2484 return (*et
->prf
)(context
, crypto
, input
, output
);
2487 static krb5_error_code
2488 krb5_crypto_prfplus(krb5_context context
,
2489 const krb5_crypto crypto
,
2490 const krb5_data
*input
,
2494 krb5_error_code ret
;
2496 unsigned char i
= 1;
2499 krb5_data_zero(&input2
);
2500 krb5_data_zero(output
);
2502 krb5_clear_error_message(context
);
2504 ret
= krb5_data_alloc(output
, length
);
2506 ret
= krb5_data_alloc(&input2
, input
->length
+ 1);
2509 krb5_clear_error_message(context
);
2511 memcpy(((unsigned char *)input2
.data
) + 1, input
->data
, input
->length
);
2518 ((unsigned char *)input2
.data
)[0] = i
++;
2520 ret
= krb5_crypto_prf(context
, crypto
, &input2
, &block
);
2524 if (block
.length
< length
) {
2525 memcpy(p
, block
.data
, block
.length
);
2526 length
-= block
.length
;
2528 memcpy(p
, block
.data
, length
);
2532 krb5_data_free(&block
);
2536 krb5_data_free(&input2
);
2538 krb5_data_free(output
);
2543 * The FX-CF2 key derivation function, used in FAST and preauth framework.
2545 * @param context Kerberos 5 context
2546 * @param crypto1 first key to combine
2547 * @param crypto2 second key to combine
2548 * @param pepper1 factor to combine with first key to garante uniqueness
2549 * @param pepper2 factor to combine with second key to garante uniqueness
2550 * @param enctype the encryption type of the resulting key
2551 * @param res allocated key, free with krb5_free_keyblock_contents()
2553 * @return Return an error code or 0.
2555 * @ingroup krb5_crypto
2558 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2559 krb5_crypto_fx_cf2(krb5_context context
,
2560 const krb5_crypto crypto1
,
2561 const krb5_crypto crypto2
,
2564 krb5_enctype enctype
,
2567 krb5_error_code ret
;
2571 memset(res
, 0, sizeof(*res
));
2573 ret
= krb5_enctype_keysize(context
, enctype
, &keysize
);
2577 ret
= krb5_data_alloc(&res
->keyvalue
, keysize
);
2580 ret
= krb5_crypto_prfplus(context
, crypto1
, pepper1
, keysize
, &os1
);
2583 ret
= krb5_crypto_prfplus(context
, crypto2
, pepper2
, keysize
, &os2
);
2587 res
->keytype
= enctype
;
2589 unsigned char *p1
= os1
.data
, *p2
= os2
.data
, *p3
= res
->keyvalue
.data
;
2590 for (i
= 0; i
< keysize
; i
++)
2591 p3
[i
] = p1
[i
] ^ p2
[i
];
2595 krb5_data_free(&res
->keyvalue
);
2596 krb5_data_free(&os1
);
2597 krb5_data_free(&os2
);
2604 #ifndef HEIMDAL_SMALLER
2607 * Deprecated: keytypes doesn't exists, they are really enctypes.
2609 * @ingroup krb5_deprecated
2612 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2613 krb5_keytype_to_enctypes (krb5_context context
,
2614 krb5_keytype keytype
,
2617 KRB5_DEPRECATED_FUNCTION("Use X instead")
2623 for (i
= _krb5_num_etypes
- 1; i
>= 0; --i
) {
2624 if (_krb5_etypes
[i
]->keytype
->type
== keytype
2625 && !(_krb5_etypes
[i
]->flags
& F_PSEUDO
)
2626 && krb5_enctype_valid(context
, _krb5_etypes
[i
]->type
) == 0)
2630 krb5_set_error_message(context
, KRB5_PROG_KEYTYPE_NOSUPP
,
2631 "Keytype have no mapping");
2632 return KRB5_PROG_KEYTYPE_NOSUPP
;
2635 ret
= malloc(n
* sizeof(*ret
));
2636 if (ret
== NULL
&& n
!= 0) {
2637 krb5_set_error_message(context
, ENOMEM
, "malloc: out of memory");
2641 for (i
= _krb5_num_etypes
- 1; i
>= 0; --i
) {
2642 if (_krb5_etypes
[i
]->keytype
->type
== keytype
2643 && !(_krb5_etypes
[i
]->flags
& F_PSEUDO
)
2644 && krb5_enctype_valid(context
, _krb5_etypes
[i
]->type
) == 0)
2645 ret
[n
++] = _krb5_etypes
[i
]->type
;
2653 * Deprecated: keytypes doesn't exists, they are really enctypes.
2655 * @ingroup krb5_deprecated
2658 /* if two enctypes have compatible keys */
2659 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2660 krb5_enctypes_compatible_keys(krb5_context context
,
2661 krb5_enctype etype1
,
2662 krb5_enctype etype2
)
2663 KRB5_DEPRECATED_FUNCTION("Use X instead")
2665 struct _krb5_encryption_type
*e1
= _krb5_find_enctype(etype1
);
2666 struct _krb5_encryption_type
*e2
= _krb5_find_enctype(etype2
);
2667 return e1
!= NULL
&& e2
!= NULL
&& e1
->keytype
== e2
->keytype
;
2670 #endif /* HEIMDAL_SMALLER */