diff options
author | Greg Hudson <ghudson@mit.edu> | 2009-10-19 20:04:21 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2009-10-19 20:04:21 +0000 |
commit | e6b93b7dd43bb765900b2db71641479b597844da (patch) | |
tree | 2b6da09e37da6ca699a8cb43c87e8a4218132254 /src/lib/crypto | |
parent | 04a5d19e61bedbb1da4db52334c00f7a54a9d5a8 (diff) | |
download | krb5-e6b93b7dd43bb765900b2db71641479b597844da.tar.gz krb5-e6b93b7dd43bb765900b2db71641479b597844da.tar.xz krb5-e6b93b7dd43bb765900b2db71641479b597844da.zip |
Implement new APIs to allow improved crypto performance
Merge branches/enc-perf to trunk. Adds the krb5_key opaque type, the
krb5_k_* APIs to use them, and caching of derived keys when krb5_k_*
functions are used. Updates the krb5 auth context and GSS id-rec to
use krb5_keys.
ticket: 6576
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22944 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/crypto')
68 files changed, 1281 insertions, 655 deletions
diff --git a/src/lib/crypto/builtin/aes/aes_s2k.c b/src/lib/crypto/builtin/aes/aes_s2k.c index 36045edc0d..76d73c6357 100644 --- a/src/lib/crypto/builtin/aes/aes_s2k.c +++ b/src/lib/crypto/builtin/aes/aes_s2k.c @@ -44,6 +44,7 @@ krb5int_aes_string_to_key(const struct krb5_enc_provider *enc, unsigned long iter_count; krb5_data out; static const krb5_data usage = { KV5M_DATA, 8, "kerberos" }; + krb5_key tempkey = NULL; krb5_error_code err; if (params) { @@ -66,25 +67,25 @@ krb5int_aes_string_to_key(const struct krb5_enc_provider *enc, if (iter_count >= MAX_ITERATION_COUNT) return KRB5_ERR_BAD_S2K_PARAMS; - /* - * Dense key space, no parity bits or anything, so take a shortcut - * and use the key contents buffer for the generated bytes. - */ + /* Use the output keyblock contents for temporary space. */ out.data = (char *) key->contents; out.length = key->length; if (out.length != 16 && out.length != 32) return KRB5_CRYPTO_INTERNAL; err = krb5int_pbkdf2_hmac_sha1 (&out, iter_count, string, salt); - if (err) { - memset(out.data, 0, out.length); - return err; - } + if (err) + goto cleanup; - err = krb5_derive_key (enc, key, key, &usage); - if (err) { - memset(out.data, 0, out.length); - return err; - } - return 0; + err = krb5_k_create_key (NULL, key, &tempkey); + if (err) + goto cleanup; + + err = krb5_derive_keyblock (enc, tempkey, key, &usage); + +cleanup: + if (err) + memset (out.data, 0, out.length); + krb5_k_free_key (NULL, tempkey); + return err; } diff --git a/src/lib/crypto/builtin/arcfour/arcfour.c b/src/lib/crypto/builtin/arcfour/arcfour.c index e5cdfdc8c2..150a7aa067 100644 --- a/src/lib/crypto/builtin/arcfour/arcfour.c +++ b/src/lib/crypto/builtin/arcfour/arcfour.c @@ -64,11 +64,12 @@ case 7: /* tgs-req authenticator */ krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_keyblock k1, k2, k3; + krb5_key k3key = NULL; krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder; krb5_keyusage ms_usage; size_t keylength, keybytes, blocksize, hashsize; @@ -83,7 +84,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, d1.data=malloc(d1.length); if (d1.data == NULL) return (ENOMEM); - k1 = *key; + k1 = key->keyblock; k1.length=d1.length; k1.contents= (void *) d1.data; @@ -93,7 +94,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, free(d1.data); return (ENOMEM); } - k2 = *key; + k2 = key->keyblock; k2.length=d2.length; k2.contents=(void *) d2.data; @@ -104,7 +105,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, free(d2.data); return (ENOMEM); } - k3 = *key; + k3 = key->keyblock; k3.length=d3.length; k3.contents= (void *) d3.data; @@ -140,7 +141,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, /* begin the encryption, computer K1 */ ms_usage=krb5int_arcfour_translate_usage(usage); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { strncpy(salt.data, krb5int_arcfour_l40, salt.length); store_32_le(ms_usage, salt.data+10); } else { @@ -151,7 +152,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) + if (key->keyblock.enctype==ENCTYPE_ARCFOUR_HMAC_EXP) memset(k1.contents+7, 0xab, 9); ret=krb5_c_random_make_octets(/* XXX */ 0, &confounder); @@ -159,11 +160,19 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, if (ret) goto cleanup; - krb5_hmac(hash, &k2, 1, &plaintext, &checksum); + ret = krb5int_hmac_keyblock(hash, &k2, 1, &plaintext, &checksum); + if (ret) + goto cleanup; + + ret = krb5int_hmac_keyblock(hash, &k1, 1, &checksum, &d3); + if (ret) + goto cleanup; - krb5_hmac(hash, &k1, 1, &checksum, &d3); + ret = krb5_k_create_key(NULL, &k3, &k3key); + if (ret) + goto cleanup; - ret=(*(enc->encrypt))(&k3, ivec, &plaintext, &ciphertext); + ret=(*(enc->encrypt))(k3key, ivec, &plaintext, &ciphertext); cleanup: memset(d1.data, 0, d1.length); @@ -184,11 +193,12 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, krb5_error_code krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_keyblock k1,k2,k3; + krb5_key k3key; krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum; krb5_keyusage ms_usage; size_t keybytes, keylength, hashsize, blocksize; @@ -203,7 +213,7 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, d1.data=malloc(d1.length); if (d1.data == NULL) return (ENOMEM); - k1 = *key; + k1 = key->keyblock; k1.length=d1.length; k1.contents= (void *) d1.data; @@ -213,7 +223,7 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, free(d1.data); return (ENOMEM); } - k2 = *key; + k2 = key->keyblock; k2.length=d2.length; k2.contents= (void *) d2.data; @@ -224,7 +234,7 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, free(d2.data); return (ENOMEM); } - k3 = *key; + k3 = key->keyblock; k3.length=d3.length; k3.contents= (void *) d3.data; @@ -257,7 +267,7 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, /* We may have to try two ms_usage values; see below. */ do { /* compute the salt */ - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { strncpy(salt.data, krb5int_arcfour_l40, salt.length); store_32_le(ms_usage, salt.data + 10); } else { @@ -270,18 +280,22 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) memset(k1.contents + 7, 0xab, 9); - ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + ret = krb5int_hmac_keyblock(hash, &k1, 1, &checksum, &d3); if (ret) goto cleanup; - ret = (*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext); + ret = krb5_k_create_key(NULL, &k3, &k3key); + if (ret) + goto cleanup; + ret = (*(enc->decrypt))(k3key, ivec, &ciphertext, &plaintext); + krb5_k_free_key(NULL, k3key); if (ret) goto cleanup; - ret = krb5_hmac(hash, &k2, 1, &plaintext, &d1); + ret = krb5int_hmac_keyblock(hash, &k2, 1, &plaintext, &d1); if (ret) goto cleanup; diff --git a/src/lib/crypto/builtin/arcfour/arcfour.h b/src/lib/crypto/builtin/arcfour/arcfour.h index e8ff203ca1..1a2876437d 100644 --- a/src/lib/crypto/builtin/arcfour/arcfour.h +++ b/src/lib/crypto/builtin/arcfour/arcfour.h @@ -10,7 +10,7 @@ krb5_arcfour_encrypt_length(const struct krb5_enc_provider *, extern krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *, const struct krb5_hash_provider *, - const krb5_keyblock *, + krb5_key, krb5_keyusage, const krb5_data *, const krb5_data *, @@ -19,7 +19,7 @@ krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *, extern krb5_error_code krb5_arcfour_decrypt(const struct krb5_enc_provider *, const struct krb5_hash_provider *, - const krb5_keyblock *, + krb5_key, krb5_keyusage, const krb5_data *, const krb5_data *, diff --git a/src/lib/crypto/builtin/arcfour/arcfour_aead.c b/src/lib/crypto/builtin/arcfour/arcfour_aead.c index cff7d66d65..4896afaaf4 100644 --- a/src/lib/crypto/builtin/arcfour/arcfour_aead.c +++ b/src/lib/crypto/builtin/arcfour/arcfour_aead.c @@ -82,7 +82,7 @@ static krb5_error_code krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -91,6 +91,7 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, krb5_error_code ret; krb5_crypto_iov *header, *trailer; krb5_keyblock k1, k2, k3; + krb5_key k3key = NULL; krb5_data d1, d2, d3; krb5_data checksum, confounder, header_data; krb5_keyusage ms_usage; @@ -126,15 +127,15 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, data[i].data.length = 0; } - ret = alloc_derived_key(enc, &k1, &d1, key); + ret = alloc_derived_key(enc, &k1, &d1, &key->keyblock); if (ret != 0) goto cleanup; - ret = alloc_derived_key(enc, &k2, &d2, key); + ret = alloc_derived_key(enc, &k2, &d2, &key->keyblock); if (ret != 0) goto cleanup; - ret = alloc_derived_key(enc, &k3, &d3, key); + ret = alloc_derived_key(enc, &k3, &d3, &key->keyblock); if (ret != 0) goto cleanup; @@ -144,7 +145,7 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, ms_usage = krb5int_arcfour_translate_usage(usage); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { strncpy(salt.data, krb5int_arcfour_l40, salt.length); store_32_le(ms_usage, salt.data + 10); } else { @@ -157,7 +158,7 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) memset(k1.contents + 7, 0xAB, 9); header->data.length = hash->hashsize + CONFOUNDERLENGTH; @@ -176,15 +177,19 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, header->data.length -= hash->hashsize; header->data.data += hash->hashsize; - ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum); + ret = krb5int_hmac_iov_keyblock(hash, &k2, data, num_data, &checksum); if (ret != 0) goto cleanup; - ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + ret = krb5int_hmac_keyblock(hash, &k1, 1, &checksum, &d3); if (ret != 0) goto cleanup; - ret = enc->encrypt_iov(&k3, ivec, data, num_data); + ret = krb5_k_create_key(NULL, &k3, &k3key); + if (ret != 0) + goto cleanup; + + ret = enc->encrypt_iov(k3key, ivec, data, num_data); if (ret != 0) goto cleanup; @@ -204,6 +209,7 @@ cleanup: free(d3.data); } + krb5_k_free_key(NULL, k3key); return ret; } @@ -211,7 +217,7 @@ static krb5_error_code krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -220,6 +226,7 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, krb5_error_code ret; krb5_crypto_iov *header, *trailer; krb5_keyblock k1, k2, k3; + krb5_key k3key = NULL; krb5_data d1, d2, d3; krb5_data checksum, header_data; krb5_keyusage ms_usage; @@ -240,15 +247,15 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, if (trailer != NULL && trailer->data.length != 0) return KRB5_BAD_MSIZE; - ret = alloc_derived_key(enc, &k1, &d1, key); + ret = alloc_derived_key(enc, &k1, &d1, &key->keyblock); if (ret != 0) goto cleanup; - ret = alloc_derived_key(enc, &k2, &d2, key); + ret = alloc_derived_key(enc, &k2, &d2, &key->keyblock); if (ret != 0) goto cleanup; - ret = alloc_derived_key(enc, &k3, &d3, key); + ret = alloc_derived_key(enc, &k3, &d3, &key->keyblock); if (ret != 0) goto cleanup; @@ -258,7 +265,7 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, ms_usage = krb5int_arcfour_translate_usage(usage); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { strncpy(salt.data, krb5int_arcfour_l40, salt.length); store_32_le(ms_usage, (unsigned char *)salt.data + 10); } else { @@ -271,7 +278,7 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) memset(k1.contents + 7, 0xAB, 9); checksum.data = header->data.data; @@ -281,15 +288,19 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, header->data.length -= hash->hashsize; header->data.data += hash->hashsize; - ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + ret = krb5int_hmac_keyblock(hash, &k1, 1, &checksum, &d3); + if (ret != 0) + goto cleanup; + + ret = krb5_k_create_key(NULL, &k3, &k3key); if (ret != 0) goto cleanup; - ret = enc->decrypt_iov(&k3, ivec, data, num_data); + ret = enc->decrypt_iov(k3key, ivec, data, num_data); if (ret != 0) goto cleanup; - ret = krb5int_hmac_iov(hash, &k2, data, num_data, &d1); + ret = krb5int_hmac_iov_keyblock(hash, &k2, data, num_data, &d1); if (ret != 0) goto cleanup; @@ -314,6 +325,7 @@ cleanup: free(d3.data); } + krb5_k_free_key(NULL, k3key); return ret; } diff --git a/src/lib/crypto/builtin/enc_provider/aes.c b/src/lib/crypto/builtin/enc_provider/aes.c index 934bc63a2c..52fb2259d8 100644 --- a/src/lib/crypto/builtin/enc_provider/aes.c +++ b/src/lib/crypto/builtin/enc_provider/aes.c @@ -86,7 +86,7 @@ static void xorblock(char *out, const char *in) } krb5_error_code -krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec, +krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { aes_ctx ctx; @@ -95,7 +95,8 @@ krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec, /* CHECK_SIZES; */ - if (aes_enc_key(key->contents, key->length, &ctx) != aes_good) + if (aes_enc_key(key->keyblock.contents, key->keyblock.length, + &ctx) != aes_good) abort(); if (ivec) @@ -140,7 +141,7 @@ krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec, } krb5_error_code -krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec, +krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { aes_ctx ctx; @@ -149,7 +150,8 @@ krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec, CHECK_SIZES; - if (aes_dec_key(key->contents, key->length, &ctx) != aes_good) + if (aes_dec_key(key->keyblock.contents, key->keyblock.length, + &ctx) != aes_good) abort(); if (ivec) @@ -200,7 +202,7 @@ krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -krb5int_aes_encrypt_iov(const krb5_keyblock *key, +krb5int_aes_encrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -210,7 +212,8 @@ krb5int_aes_encrypt_iov(const krb5_keyblock *key, int nblocks = 0, blockno; size_t input_length, i; - if (aes_enc_key(key->contents, key->length, &ctx) != aes_good) + if (aes_enc_key(key->keyblock.contents, key->keyblock.length, &ctx) + != aes_good) abort(); if (ivec != NULL) @@ -280,7 +283,7 @@ krb5int_aes_encrypt_iov(const krb5_keyblock *key, } static krb5_error_code -krb5int_aes_decrypt_iov(const krb5_keyblock *key, +krb5int_aes_decrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -293,7 +296,8 @@ krb5int_aes_decrypt_iov(const krb5_keyblock *key, CHECK_SIZES; - if (aes_dec_key(key->contents, key->length, &ctx) != aes_good) + if (aes_dec_key(key->keyblock.contents, key->keyblock.length, + &ctx) != aes_good) abort(); if (ivec != NULL) diff --git a/src/lib/crypto/builtin/enc_provider/des.c b/src/lib/crypto/builtin/enc_provider/des.c index 433032dd31..d73a1d2901 100644 --- a/src/lib/crypto/builtin/enc_provider/des.c +++ b/src/lib/crypto/builtin/enc_provider/des.c @@ -32,14 +32,14 @@ static krb5_error_code -k5_des_docrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des_docrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output, int enc) { mit_des_key_schedule schedule; - /* key->enctype was checked by the caller */ + /* key->keyblock.enctype was checked by the caller */ - if (key->length != 8) + if (key->keyblock.length != 8) return(KRB5_BAD_KEYSIZE); if ((input->length%8) != 0) return(KRB5_BAD_MSIZE); @@ -48,7 +48,7 @@ k5_des_docrypt(const krb5_keyblock *key, const krb5_data *ivec, if (input->length != output->length) return(KRB5_BAD_MSIZE); - switch (mit_des_key_sched(key->contents, schedule)) { + switch (mit_des_key_sched(key->keyblock.contents, schedule)) { case -1: return(KRB5DES_BAD_KEYPAR); case -2: @@ -71,30 +71,30 @@ k5_des_docrypt(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des_encrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { return(k5_des_docrypt(key, ivec, input, output, 1)); } static krb5_error_code -k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des_decrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { return(k5_des_docrypt(key, ivec, input, output, 0)); } static krb5_error_code -k5_des_docrypt_iov(const krb5_keyblock *key, const krb5_data *ivec, +k5_des_docrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data, int enc) { mit_des_key_schedule schedule; size_t input_length = 0; unsigned int i; - /* key->enctype was checked by the caller */ + /* key->keyblock.enctype was checked by the caller */ - if (key->length != 8) + if (key->keyblock.length != 8) return(KRB5_BAD_KEYSIZE); for (i = 0; i < num_data; i++) { @@ -109,7 +109,7 @@ k5_des_docrypt_iov(const krb5_keyblock *key, const krb5_data *ivec, if (ivec && (ivec->length != 8)) return(KRB5_BAD_MSIZE); - switch (mit_des_key_sched(key->contents, schedule)) { + switch (mit_des_key_sched(key->keyblock.contents, schedule)) { case -1: return(KRB5DES_BAD_KEYPAR); case -2: @@ -128,7 +128,7 @@ k5_des_docrypt_iov(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des_encrypt_iov(const krb5_keyblock *key, +k5_des_encrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -137,7 +137,7 @@ k5_des_encrypt_iov(const krb5_keyblock *key, } static krb5_error_code -k5_des_decrypt_iov(const krb5_keyblock *key, +k5_des_decrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) diff --git a/src/lib/crypto/builtin/enc_provider/des3.c b/src/lib/crypto/builtin/enc_provider/des3.c index 7dba292ae0..eae504b8c3 100644 --- a/src/lib/crypto/builtin/enc_provider/des3.c +++ b/src/lib/crypto/builtin/enc_provider/des3.c @@ -30,13 +30,13 @@ #include <rand2key.h> static krb5_error_code -validate_and_schedule(const krb5_keyblock *key, const krb5_data *ivec, +validate_and_schedule(krb5_key key, const krb5_data *ivec, const krb5_data *input, const krb5_data *output, mit_des3_key_schedule *schedule) { - /* key->enctype was checked by the caller */ + /* key->keyblock.enctype was checked by the caller */ - if (key->length != 24) + if (key->keyblock.length != 24) return(KRB5_BAD_KEYSIZE); if ((input->length%8) != 0) return(KRB5_BAD_MSIZE); @@ -45,7 +45,7 @@ validate_and_schedule(const krb5_keyblock *key, const krb5_data *ivec, if (input->length != output->length) return(KRB5_BAD_MSIZE); - switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents, + switch (mit_des3_key_sched(*(mit_des3_cblock *)key->keyblock.contents, *schedule)) { case -1: return(KRB5DES_BAD_KEYPAR); @@ -56,7 +56,7 @@ validate_and_schedule(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -validate_and_schedule_iov(const krb5_keyblock *key, const krb5_data *ivec, +validate_and_schedule_iov(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data, size_t num_data, mit_des3_key_schedule *schedule) { @@ -69,14 +69,14 @@ validate_and_schedule_iov(const krb5_keyblock *key, const krb5_data *ivec, input_length += iov->data.length; } - if (key->length != 24) + if (key->keyblock.length != 24) return(KRB5_BAD_KEYSIZE); if ((input_length%8) != 0) return(KRB5_BAD_MSIZE); if (ivec && (ivec->length != 8)) return(KRB5_BAD_MSIZE); - switch (mit_des3_key_sched(*(mit_des3_cblock *)key->contents, + switch (mit_des3_key_sched(*(mit_des3_cblock *)key->keyblock.contents, *schedule)) { case -1: return(KRB5DES_BAD_KEYPAR); @@ -87,7 +87,7 @@ validate_and_schedule_iov(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des3_encrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { mit_des3_key_schedule schedule; @@ -109,7 +109,7 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des3_decrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { mit_des3_key_schedule schedule; @@ -131,7 +131,7 @@ k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des3_encrypt_iov(const krb5_keyblock *key, +k5_des3_encrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -154,7 +154,7 @@ k5_des3_encrypt_iov(const krb5_keyblock *key, } static krb5_error_code -k5_des3_decrypt_iov(const krb5_keyblock *key, +k5_des3_decrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) diff --git a/src/lib/crypto/builtin/enc_provider/rc4.c b/src/lib/crypto/builtin/enc_provider/rc4.c index df2c914f88..47c131da4d 100644 --- a/src/lib/crypto/builtin/enc_provider/rc4.c +++ b/src/lib/crypto/builtin/enc_provider/rc4.c @@ -29,7 +29,7 @@ static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest, /* Interface layer to kerb5 crypto layer */ static krb5_error_code -k5_arcfour_docrypt(const krb5_keyblock *, const krb5_data *, +k5_arcfour_docrypt(krb5_key, const krb5_data *, const krb5_data *, krb5_data *); static const unsigned char arcfour_weakkey1[] = {0x00, 0x00, 0xfd}; @@ -113,14 +113,14 @@ k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key, /* The workhorse of the arcfour system, this impliments the cipher */ static krb5_error_code -k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state, +k5_arcfour_docrypt(krb5_key key, const krb5_data *state, const krb5_data *input, krb5_data *output) { ArcfourContext *arcfour_ctx; ArcFourCipherState *cipher_state; int ret; - if (key->length != 16) + if (key->keyblock.length != 16) return(KRB5_BAD_KEYSIZE); if (state && (state->length != sizeof (ArcFourCipherState))) return(KRB5_BAD_MSIZE); @@ -131,7 +131,8 @@ k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state, cipher_state = (ArcFourCipherState *) state->data; arcfour_ctx=&cipher_state->ctx; if (cipher_state->initialized == 0) { - if ((ret=k5_arcfour_init(arcfour_ctx, key->contents, key->length))) { + if ((ret=k5_arcfour_init(arcfour_ctx, key->keyblock.contents, + key->keyblock.length))) { return ret; } cipher_state->initialized = 1; @@ -142,7 +143,8 @@ k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state, arcfour_ctx=malloc(sizeof (ArcfourContext)); if (arcfour_ctx == NULL) return ENOMEM; - if ((ret=k5_arcfour_init(arcfour_ctx, key->contents, key->length))) { + if ((ret=k5_arcfour_init(arcfour_ctx, key->keyblock.contents, + key->keyblock.length))) { free(arcfour_ctx); return (ret); } @@ -157,7 +159,7 @@ k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state, /* In-place encryption */ static krb5_error_code -k5_arcfour_docrypt_iov(const krb5_keyblock *key, +k5_arcfour_docrypt_iov(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, size_t num_data) @@ -167,7 +169,7 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key, krb5_error_code ret; size_t i; - if (key->length != 16) + if (key->keyblock.length != 16) return KRB5_BAD_KEYSIZE; if (state != NULL && (state->length != sizeof(ArcFourCipherState))) return KRB5_BAD_MSIZE; @@ -176,7 +178,8 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key, cipher_state = (ArcFourCipherState *)state->data; arcfour_ctx = &cipher_state->ctx; if (cipher_state->initialized == 0) { - ret = k5_arcfour_init(arcfour_ctx, key->contents, key->length); + ret = k5_arcfour_init(arcfour_ctx, key->keyblock.contents, + key->keyblock.length); if (ret != 0) return ret; @@ -187,7 +190,8 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key, if (arcfour_ctx == NULL) return ENOMEM; - ret = k5_arcfour_init(arcfour_ctx, key->contents, key->length); + ret = k5_arcfour_init(arcfour_ctx, key->keyblock.contents, + key->keyblock.length); if (ret != 0) { free(arcfour_ctx); return ret; diff --git a/src/lib/crypto/builtin/hmac.c b/src/lib/crypto/builtin/hmac.c index 3bff3cf957..6726a08262 100644 --- a/src/lib/crypto/builtin/hmac.c +++ b/src/lib/crypto/builtin/hmac.c @@ -28,6 +28,17 @@ #include "aead.h" /* + * Because our built-in HMAC implementation doesn't need to invoke any + * encryption or keyed hash functions, it is simplest to define it in + * terms of keyblocks, and then supply a simple wrapper for the + * "normal" krb5_key-using interfaces. The keyblock interfaces are + * useful for the built-in arcfour code which constructs a lot of + * intermediate HMAC keys. For other back ends, it should not be + * necessary to supply the _keyblock versions of the hmac functions if + * the back end code doesn't make use of them. + */ + +/* * the HMAC transform looks like: * * H(K XOR opad, H(K XOR ipad, text)) @@ -40,8 +51,9 @@ */ krb5_error_code -krb5_hmac(const struct krb5_hash_provider *hash, const krb5_keyblock *key, - unsigned int icount, const krb5_data *input, krb5_data *output) +krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *key, unsigned int icount, + const krb5_data *input, krb5_data *output) { size_t hashsize, blocksize; unsigned char *xorkey, *ihash; @@ -127,8 +139,10 @@ cleanup: } krb5_error_code -krb5int_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key, - const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +krb5int_hmac_iov_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) { krb5_data *sign_data; size_t num_sign_data; @@ -156,10 +170,25 @@ krb5int_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key } /* caller must store checksum in iov as it may be TYPE_TRAILER or TYPE_CHECKSUM */ - ret = krb5_hmac(hash, key, num_sign_data, sign_data, output); + ret = krb5int_hmac_keyblock(hash, key, num_sign_data, sign_data, output); free(sign_data); return ret; } +krb5_error_code +krb5_hmac(const struct krb5_hash_provider *hash, krb5_key key, + unsigned int icount, const krb5_data *input, krb5_data *output) +{ + return krb5int_hmac_keyblock(hash, &key->keyblock, icount, input, output); +} + +krb5_error_code +krb5int_hmac_iov(const struct krb5_hash_provider *hash, krb5_key key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + return krb5int_hmac_iov_keyblock(hash, &key->keyblock, data, num_data, + output); +} diff --git a/src/lib/crypto/builtin/pbkdf2.c b/src/lib/crypto/builtin/pbkdf2.c index d897e9a718..9201e23b09 100644 --- a/src/lib/crypto/builtin/pbkdf2.c +++ b/src/lib/crypto/builtin/pbkdf2.c @@ -25,19 +25,36 @@ * * * Implementation of PBKDF2 from RFC 2898. - * Not currently used; likely to be used when we get around to AES support. */ #include <ctype.h> #include "k5-int.h" #include "hash_provider.h" +/* + * RFC 2898 specifies PBKDF2 in terms of an underlying pseudo-random + * function with two arguments (password and salt||blockindex). Right + * now we only use PBKDF2 with the hmac-sha1 PRF, also specified in + * RFC 2898, which invokes HMAC with the password as the key and the + * second argument as the text. (HMAC accepts any key size up to the + * block size; the password is pre-hashed with unkeyed SHA1 if it is + * longer than the block size.) + * + * For efficiency, it is better to generate the key from the password + * once at the beginning, so we specify prf_func in terms of a + * krb5_key first argument. That might not be convenient for a PRF + * which uses the password in some other way, so this might need to be + * adjusted in the future. + */ + +typedef krb5_error_code (*prf_func)(krb5_key pass, krb5_data *salt, + krb5_data *out); + /* Not exported, for now. */ static krb5_error_code -krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, - krb5_data *), - size_t hlen, const krb5_data *pass, const krb5_data *salt, - unsigned long count, const krb5_data *output); +krb5int_pbkdf2 (prf_func prf, size_t hlen, krb5_key pass, + const krb5_data *salt, unsigned long count, + const krb5_data *output); static int debug_hmac = 0; @@ -61,35 +78,21 @@ static void printd (const char *descr, krb5_data *d) { } printf("\n"); } -static void printk(const char *descr, krb5_keyblock *k) { - krb5_data d; - d.data = (char *) k->contents; - d.length = k->length; - printd(descr, &d); -} static krb5_error_code -F(char *output, char *u_tmp1, char *u_tmp2, - krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, krb5_data *), - size_t hlen, - const krb5_data *pass, const krb5_data *salt, - unsigned long count, int i) +F(char *output, char *u_tmp1, char *u_tmp2, prf_func prf, size_t hlen, + krb5_key pass, const krb5_data *salt, unsigned long count, int i) { unsigned char ibytes[4]; size_t tlen; unsigned int j, k; - krb5_keyblock pdata; krb5_data sdata; krb5_data out; krb5_error_code err; - pdata.contents = pass->data; - pdata.length = pass->length; - #if 0 printf("F(i=%d, count=%lu, pass=%d:%s)\n", i, count, pass->length, pass->data); - printk("F password", &pdata); #endif /* Compute U_1. */ @@ -112,7 +115,7 @@ F(char *output, char *u_tmp1, char *u_tmp2, #if 0 printf("F: computing hmac #1 (U_1) with %s\n", pdata.contents); #endif - err = (*prf)(&pdata, &sdata, &out); + err = (*prf)(pass, &sdata, &out); if (err) return err; #if 0 @@ -127,7 +130,7 @@ F(char *output, char *u_tmp1, char *u_tmp2, printf("F: computing hmac #%d (U_%d)\n", j, j); #endif memcpy(u_tmp2, u_tmp1, hlen); - err = (*prf)(&pdata, &sdata, &out); + err = (*prf)(pass, &sdata, &out); if (err) return err; #if 0 @@ -147,11 +150,9 @@ F(char *output, char *u_tmp1, char *u_tmp2, } static krb5_error_code -krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, - krb5_data *), - size_t hlen, - const krb5_data *pass, const krb5_data *salt, - unsigned long count, const krb5_data *output) +krb5int_pbkdf2 (prf_func prf, size_t hlen, krb5_key pass, + const krb5_data *salt, unsigned long count, + const krb5_data *output) { int l, r, i; char *utmp1, *utmp2; @@ -209,57 +210,55 @@ krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, return 0; } -static krb5_error_code hmac1(const struct krb5_hash_provider *h, - krb5_keyblock *key, krb5_data *in, krb5_data *out) +/* + * Implements the hmac-sha1 PRF. pass has been pre-hashed (if + * necessary) and converted to a key already; salt has had the block + * index appended to the original salt. + */ +static krb5_error_code +hmac_sha1(krb5_key pass, krb5_data *salt, krb5_data *out) { - char tmp[40]; - size_t blocksize, hashsize; + const struct krb5_hash_provider *h = &krb5int_hash_sha1; krb5_error_code err; - krb5_keyblock k; - k = *key; - key = &k; if (debug_hmac) - printk(" test key", key); - blocksize = h->blocksize; - hashsize = h->hashsize; - if (hashsize > sizeof(tmp)) - abort(); - if (key->length > blocksize) { - krb5_data d, d2; - d.data = (char *) key->contents; - d.length = key->length; - d2.data = tmp; - d2.length = hashsize; - err = h->hash (1, &d, &d2); - if (err) - return err; - key->length = d2.length; - key->contents = (krb5_octet *) d2.data; - if (debug_hmac) - printk(" pre-hashed key", key); - } - if (debug_hmac) - printd(" hmac input", in); - err = krb5_hmac(h, key, 1, in, out); + printd(" hmac input", salt); + err = krb5_hmac(h, pass, 1, salt, out); if (err == 0 && debug_hmac) printd(" hmac output", out); return err; } -static krb5_error_code -foo(krb5_keyblock *pass, krb5_data *salt, krb5_data *out) -{ - krb5_error_code err; - - memset(out->data, 0, out->length); - err = hmac1 (&krb5int_hash_sha1, pass, salt, out); - return err; -} - krb5_error_code krb5int_pbkdf2_hmac_sha1 (const krb5_data *out, unsigned long count, const krb5_data *pass, const krb5_data *salt) { - return krb5int_pbkdf2 (foo, 20, pass, salt, count, out); + const struct krb5_hash_provider *h = &krb5int_hash_sha1; + krb5_keyblock keyblock; + krb5_key key; + char tmp[40]; + krb5_data d; + krb5_error_code err; + + assert(h->hashsize <= sizeof(tmp)); + if (pass->length > h->blocksize) { + d.data = tmp; + d.length = h->hashsize; + err = h->hash (1, pass, &d); + if (err) + return err; + keyblock.length = d.length; + keyblock.contents = (krb5_octet *) d.data; + } else { + keyblock.length = pass->length; + keyblock.contents = (krb5_octet *) pass->data; + } + + err = krb5_k_create_key(NULL, &keyblock, &key); + if (err) + return err; + + err = krb5int_pbkdf2(hmac_sha1, 20, key, salt, count, out); + krb5_k_free_key(NULL, key); + return err; } diff --git a/src/lib/crypto/crypto_tests/Makefile.in b/src/lib/crypto/crypto_tests/Makefile.in index ab6ebfa4c6..7b240d5783 100644 --- a/src/lib/crypto/crypto_tests/Makefile.in +++ b/src/lib/crypto/crypto_tests/Makefile.in @@ -33,6 +33,7 @@ EXTRADEPSRCS=\ $(srcdir)/t_shs3.c \ $(srcdir)/t_shs.c \ $(srcdir)/t_verify.c \ + $(srcdir)/t_kperf.c \ $(srcdir)/ytest.c ##DOSBUILDTOP = ..\..\.. @@ -149,6 +150,9 @@ t_shs: t_shs.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) t_shs3: t_shs3.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) $(CC_LINK) -o t_shs3 t_shs3.o $(SUPPORT_LIB) $(CRYPTO_DEPLIB) +t_kperf: t_kperf.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) + $(CC_LINK) -o t_kperf t_kperf.o $(SUPPORT_LIB) $(CRYPTO_DEPLIB) + ytest: ytest.o shs.o $(SUPPORT_DEPLIB) $(CRYPTO_DEPLIB) $(CC_LINK) -o ytest ytest.o $(SUPPORT_LIB) $(CRYPTO_DEPLIB) diff --git a/src/lib/crypto/crypto_tests/aes-test.c b/src/lib/crypto/crypto_tests/aes-test.c index c05fd26e3c..8999bd7578 100644 --- a/src/lib/crypto/crypto_tests/aes-test.c +++ b/src/lib/crypto/crypto_tests/aes-test.c @@ -50,7 +50,11 @@ static void init() } static void enc() { - krb5int_aes_encrypt(&enc_key, &ivec, &in, &out); + krb5_key key; + + krb5_k_create_key(NULL, &enc_key, &key); + krb5int_aes_encrypt(key, &ivec, &in, &out); + krb5_k_free_key(NULL, key); } static void hexdump(const char *label, const char *cp, int len) diff --git a/src/lib/crypto/crypto_tests/t_cksum.c b/src/lib/crypto/crypto_tests/t_cksum.c index 98187f7f16..2b53651197 100644 --- a/src/lib/crypto/crypto_tests/t_cksum.c +++ b/src/lib/crypto/crypto_tests/t_cksum.c @@ -75,6 +75,7 @@ main(argc, argv) krb5_boolean valid; size_t length; krb5_keyblock keyblock; + krb5_key key; krb5_error_code kret=0; krb5_data plaintext, newstyle_checksum; @@ -89,6 +90,8 @@ main(argc, argv) keyblock.length = sizeof(testkey); keyblock.contents = testkey; + krb5_k_create_key(NULL, &keyblock, &key); + length = khp.hashsize; newstyle_checksum.length = length; @@ -102,13 +105,13 @@ main(argc, argv) plaintext.length = strlen(argv[msgindex]); plaintext.data = argv[msgindex]; - if ((kret = (*(khp.hash))(&keyblock, 0, 0, &plaintext, &newstyle_checksum))) { + if ((kret = (*(khp.hash))(key, 0, 0, &plaintext, &newstyle_checksum))) { printf("krb5_calculate_checksum choked with %d\n", kret); break; } print_checksum("correct", MD, argv[msgindex], &newstyle_checksum); - if ((kret = (*(khp.verify))(&keyblock, 0, 0, &plaintext, &newstyle_checksum, + if ((kret = (*(khp.verify))(key, 0, 0, &plaintext, &newstyle_checksum, &valid))) { printf("verify on new checksum choked with %d\n", kret); break; @@ -120,7 +123,7 @@ main(argc, argv) printf("Verify succeeded for \"%s\"\n", argv[msgindex]); newstyle_checksum.data[0]++; - if ((kret = (*(khp.verify))(&keyblock, 0, 0, &plaintext, &newstyle_checksum, + if ((kret = (*(khp.verify))(key, 0, 0, &plaintext, &newstyle_checksum, &valid))) { printf("verify on new checksum choked with %d\n", kret); break; diff --git a/src/lib/crypto/crypto_tests/t_cts.c b/src/lib/crypto/crypto_tests/t_cts.c index aef813273f..fab5b27071 100644 --- a/src/lib/crypto/crypto_tests/t_cts.c +++ b/src/lib/crypto/crypto_tests/t_cts.c @@ -114,15 +114,12 @@ static void test_cts() "I would like the General Gau's Chicken, please, and wonton soup."; static const unsigned char aeskey[16] = "chicken teriyaki"; static const int lengths[] = { 17, 31, 32, 47, 48, 64 }; - extern krb5_error_code krb5int_aes_encrypt(const krb5_keyblock *, - const krb5_data *, - const krb5_data *, - krb5_data *); int i; char outbuf[64], encivbuf[16], decivbuf[16], outbuf2[64]; krb5_data in, out, enciv, deciv, out2; - krb5_keyblock key; + krb5_keyblock keyblock; + krb5_key key; krb5_error_code err; in.data = input; @@ -131,11 +128,17 @@ static void test_cts() enciv.length = deciv.length = 16; enciv.data = encivbuf; deciv.data = decivbuf; - key.contents = aeskey; - key.length = 16; + keyblock.contents = aeskey; + keyblock.length = 16; + + err = krb5_k_create_key(NULL, &keyblock, &key); + if (err) { + printf("error %ld from krb5_k_create_key\n", (long)err); + exit(1); + } memset(enciv.data, 0, 16); - printk("AES 128-bit key", &key); + printk("AES 128-bit key", &keyblock); for (i = 0; i < sizeof(lengths)/sizeof(lengths[0]); i++) { memset(enciv.data, 0, 16); memset(deciv.data, 0, 16); @@ -143,7 +146,7 @@ static void test_cts() printf("\n"); in.length = out.length = lengths[i]; printd("IV", &enciv); - err = krb5int_aes_encrypt(&key, &enciv, &in, &out); + err = krb5int_aes_encrypt(key, &enciv, &in, &out); if (err) { printf("error %ld from krb5int_aes_encrypt\n", (long)err); exit(1); @@ -152,7 +155,7 @@ static void test_cts() printd("Output", &out); printd("Next IV", &enciv); out2.length = out.length; - err = krb5int_aes_decrypt(&key, &deciv, &out, &out2); + err = krb5int_aes_decrypt(key, &deciv, &out, &out2); if (err) { printf("error %ld from krb5int_aes_decrypt\n", (long)err); exit(1); diff --git a/src/lib/crypto/crypto_tests/t_encrypt.c b/src/lib/crypto/crypto_tests/t_encrypt.c index 739c6d3e0b..aac31fb21f 100644 --- a/src/lib/crypto/crypto_tests/t_encrypt.c +++ b/src/lib/crypto/crypto_tests/t_encrypt.c @@ -78,12 +78,14 @@ int main () { krb5_context context = 0; - krb5_data in, in2, out, out2, check, check2, state; + krb5_data in, in2, out, out2, check, check2, state, signdata; krb5_crypto_iov iov[5]; - int i; + int i, j, pos; + unsigned int dummy; size_t len; krb5_enc_data enc_out, enc_out2; - krb5_keyblock *key; + krb5_keyblock *keyblock; + krb5_key key; memset(iov, 0, sizeof(iov)); @@ -94,6 +96,8 @@ main () test ("Seeding random number generator", krb5_c_random_seed (context, &in)); + + /* Set up output buffers. */ out.data = malloc(2048); out2.data = malloc(2048); check.data = malloc(2048); @@ -107,39 +111,67 @@ main () out2.length = 2048; check.length = 2048; check2.length = 2048; + for (i = 0; interesting_enctypes[i]; i++) { krb5_enctype enctype = interesting_enctypes [i]; + printf ("Testing enctype %d\n", enctype); test ("Initializing a keyblock", - krb5_init_keyblock (context, enctype, 0, &key)); - test ("Generating random key", - krb5_c_make_random_key (context, enctype, key)); + krb5_init_keyblock (context, enctype, 0, &keyblock)); + test ("Generating random keyblock", + krb5_c_make_random_key (context, enctype, keyblock)); + test ("Creating opaque key from keyblock", + krb5_k_create_key (context, keyblock, &key)); + enc_out.ciphertext = out; enc_out2.ciphertext = out2; /* We use an intermediate `len' because size_t may be different size than `int' */ - krb5_c_encrypt_length (context, key->enctype, in.length, &len); + krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len); enc_out.ciphertext.length = len; - test ("Encrypting", - krb5_c_encrypt (context, key, 7, 0, &in, &enc_out)); + + /* Encrypt, decrypt, and see if we got the plaintext back again. */ + test ("Encrypting (c)", + krb5_c_encrypt (context, keyblock, 7, 0, &in, &enc_out)); test ("Decrypting", - krb5_c_decrypt (context, key, 7, 0, &enc_out, &check)); + krb5_c_decrypt (context, keyblock, 7, 0, &enc_out, &check)); test ("Comparing", compare_results (&in, &check)); - if ( krb5_c_crypto_length(context, key->enctype, KRB5_CRYPTO_TYPE_HEADER, &len) == 0 ){ - /* We support iov/aead*/ - int j, pos; - krb5_data signdata; - signdata.magic = KV5M_DATA; - signdata.data = (char *) "This should be signed"; - signdata.length = strlen(signdata.data); + + /* Try again with the opaque-key-using variants. */ + memset(out.data, 0, out.length); + test ("Encrypting (k)", + krb5_k_encrypt (context, key, 7, 0, &in, &enc_out)); + test ("Decrypting", + krb5_k_decrypt (context, key, 7, 0, &enc_out, &check)); + test ("Comparing", compare_results (&in, &check)); + + /* Check if this enctype supports IOV encryption. */ + if ( krb5_c_crypto_length(context, keyblock->enctype, + KRB5_CRYPTO_TYPE_HEADER, &dummy) == 0 ){ + /* Set up iovecs for stream decryption. */ + memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length); iov[0].flags= KRB5_CRYPTO_TYPE_STREAM; + iov[0].data.data = out2.data; + iov[0].data.length = enc_out.ciphertext.length; iov[1].flags = KRB5_CRYPTO_TYPE_DATA; - iov[0].data = enc_out.ciphertext; - iov[1].data = out; - test("IOV stream decrypting", - krb5_c_decrypt_iov( context, key, 7, 0, iov, 2)); + + /* Decrypt the encrypted data from above and check it. */ + test("IOV stream decrypting (c)", + krb5_c_decrypt_iov( context, keyblock, 7, 0, iov, 2)); test("Comparing results", compare_results(&in, &iov[1].data)); + + /* Try again with the opaque-key-using variant. */ + memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length); + test("IOV stream decrypting (k)", + krb5_k_decrypt_iov( context, key, 7, 0, iov, 2)); + test("Comparing results", + compare_results(&in, &iov[1].data)); + + /* Set up iovecs for AEAD encryption. */ + signdata.magic = KV5M_DATA; + signdata.data = (char *) "This should be signed"; + signdata.length = strlen(signdata.data); iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; iov[1].flags = KRB5_CRYPTO_TYPE_DATA; iov[1].data = in; /*We'll need to copy memory before encrypt*/ @@ -147,8 +179,10 @@ main () iov[2].data = signdata; iov[3].flags = KRB5_CRYPTO_TYPE_PADDING; iov[4].flags = KRB5_CRYPTO_TYPE_TRAILER; + + /* "Allocate" data for the iovec buffers from the "out" buffer. */ test("Setting up iov lengths", - krb5_c_crypto_length_iov(context, key->enctype, iov, 5)); + krb5_c_crypto_length_iov(context, keyblock->enctype, iov, 5)); for (j=0,pos=0; j <= 4; j++ ){ if (iov[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) continue; @@ -157,56 +191,70 @@ main () } assert (iov[1].data.length == in.length); memcpy(iov[1].data.data, in.data, in.length); - test("iov encrypting", - krb5_c_encrypt_iov(context, key, 7, 0, iov, 5)); + + /* Encrypt and decrypt in place, and check the result. */ + test("iov encrypting (c)", + krb5_c_encrypt_iov(context, keyblock, 7, 0, iov, 5)); assert(iov[1].data.length == in.length); test("iov decrypting", - krb5_c_decrypt_iov(context, key, 7, 0, iov, 5)); + krb5_c_decrypt_iov(context, keyblock, 7, 0, iov, 5)); test("Comparing results", compare_results(&in, &iov[1].data)); + /* Try again with opaque-key-using variants. */ + test("iov encrypting (k)", + krb5_k_encrypt_iov(context, key, 7, 0, iov, 5)); + assert(iov[1].data.length == in.length); + test("iov decrypting", + krb5_k_decrypt_iov(context, key, 7, 0, iov, 5)); + test("Comparing results", + compare_results(&in, &iov[1].data)); } + enc_out.ciphertext.length = out.length; check.length = 2048; + test ("init_state", - krb5_c_init_state (context, key, 7, &state)); + krb5_c_init_state (context, keyblock, 7, &state)); test ("Encrypting with state", - krb5_c_encrypt (context, key, 7, &state, &in, &enc_out)); + krb5_c_encrypt (context, keyblock, 7, &state, &in, &enc_out)); test ("Encrypting again with state", - krb5_c_encrypt (context, key, 7, &state, &in2, &enc_out2)); + krb5_c_encrypt (context, keyblock, 7, &state, &in2, &enc_out2)); test ("free_state", - krb5_c_free_state (context, key, &state)); + krb5_c_free_state (context, keyblock, &state)); test ("init_state", - krb5_c_init_state (context, key, 7, &state)); + krb5_c_init_state (context, keyblock, 7, &state)); test ("Decrypting with state", - krb5_c_decrypt (context, key, 7, &state, &enc_out, &check)); + krb5_c_decrypt (context, keyblock, 7, &state, &enc_out, &check)); test ("Decrypting again with state", - krb5_c_decrypt (context, key, 7, &state, &enc_out2, &check2)); + krb5_c_decrypt (context, keyblock, 7, &state, &enc_out2, &check2)); test ("free_state", - krb5_c_free_state (context, key, &state)); + krb5_c_free_state (context, keyblock, &state)); test ("Comparing", compare_results (&in, &check)); test ("Comparing", compare_results (&in2, &check2)); - krb5_free_keyblock (context, key); + + krb5_free_keyblock (context, keyblock); + krb5_k_free_key (context, key); } /* Test the RC4 decrypt fallback from key usage 9 to 8. */ test ("Initializing an RC4 keyblock", - krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &key)); + krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &keyblock)); test ("Generating random RC4 key", - krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, key)); + krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, keyblock)); enc_out.ciphertext = out; - krb5_c_encrypt_length (context, key->enctype, in.length, &len); + krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len); enc_out.ciphertext.length = len; check.length = 2048; test ("Encrypting with RC4 key usage 8", - krb5_c_encrypt (context, key, 8, 0, &in, &enc_out)); + krb5_c_encrypt (context, keyblock, 8, 0, &in, &enc_out)); test ("Decrypting with RC4 key usage 9", - krb5_c_decrypt (context, key, 9, 0, &enc_out, &check)); + krb5_c_decrypt (context, keyblock, 9, 0, &enc_out, &check)); test ("Comparing", compare_results (&in, &check)); - krb5_free_keyblock (context, key); + krb5_free_keyblock (context, keyblock); free(out.data); free(out2.data); free(check.data); diff --git a/src/lib/crypto/crypto_tests/t_hmac.c b/src/lib/crypto/crypto_tests/t_hmac.c index bf629c359f..30830d6173 100644 --- a/src/lib/crypto/crypto_tests/t_hmac.c +++ b/src/lib/crypto/crypto_tests/t_hmac.c @@ -98,6 +98,7 @@ static krb5_error_code hmac1(const struct krb5_hash_provider *h, char tmp[40]; size_t blocksize, hashsize; krb5_error_code err; + krb5_key k; printk(" test key", key); blocksize = h->blocksize; @@ -120,7 +121,9 @@ static krb5_error_code hmac1(const struct krb5_hash_provider *h, printk(" pre-hashed key", key); } printd(" hmac input", in); - err = krb5_hmac(h, key, 1, in, out); + krb5_k_create_key(NULL, key, &k); + err = krb5_hmac(h, k, 1, in, out); + krb5_k_free_key(NULL, k); if (err == 0) printd(" hmac output", out); return err; diff --git a/src/lib/crypto/crypto_tests/t_kperf.c b/src/lib/crypto/crypto_tests/t_kperf.c new file mode 100644 index 0000000000..f56aa3cd15 --- /dev/null +++ b/src/lib/crypto/crypto_tests/t_kperf.c @@ -0,0 +1,119 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * lib/crypto/crypto_tests/t_kperf.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This file contains a harness to measure the performance improvement + * of using the the krb5_k functions (which cache derived keys) over + * the equivalent krb5_c functions which do not. Sample usages: + * + * ./t_kperf ce aes128-cts 10 100000 + * ./t_kperf kv aes256-cts 1024 10000 + * + * The first usage encrypts ('e') a hundred thousand ten-byte blobs + * with aes128-cts, using the non-caching APIs ('c'). The second + * usage verifies ('v') ten thousand checksums over 1K blobs with the + * first available keyed checksum type for aes256-cts, using the + * caching APIs ('k'). Run commands under "time" to measure how much + * time is used by the operations. + */ + +#include "k5-int.h" + +int +main(int argc, char **argv) +{ + krb5_keyblock kblock; + krb5_key key; + krb5_enctype enctype; + krb5_cksumtype cktype, *cktypelist; + int blocksize, num_blocks, intf, op, i; + unsigned int count; + size_t outlen, cklen; + krb5_data block; + krb5_enc_data outblock; + krb5_checksum sum; + krb5_boolean val; + + if (argc != 5) { + fprintf(stderr, "Usage: t_kperf {c|k}{e|d|m|v} type size nblocks\n"); + exit(1); + } + intf = argv[1][0]; + assert(intf == 'c' || intf =='k'); + op = argv[1][1]; + assert(krb5_string_to_enctype(argv[2], &enctype) == 0); + blocksize = atoi(argv[3]); + num_blocks = atoi(argv[4]); + + /* Pick the first available keyed checksum type. */ + krb5_c_keyed_checksum_types(NULL, enctype, &count, &cktypelist); + assert(count > 0); + cktype = cktypelist[0]; + + block.data = "notrandom"; + block.length = 9; + krb5_c_random_seed(NULL, &block); + + krb5_c_make_random_key(NULL, enctype, &kblock); + krb5_k_create_key(NULL, &kblock, &key); + + block.length = blocksize; + block.data = calloc(1, blocksize); + + krb5_c_encrypt_length(NULL, enctype, blocksize, &outlen); + outblock.enctype = enctype; + outblock.ciphertext.length = outlen; + outblock.ciphertext.data = calloc(1, outlen); + + krb5_c_checksum_length(NULL, cktype, &cklen); + sum.checksum_type = cktype; + sum.length = cklen; + sum.contents = calloc(1, cklen); + + for (i = 0; i < num_blocks; i++) { + if (intf == 'c') { + if (op == 'e') + krb5_c_encrypt(NULL, &kblock, 0, NULL, &block, &outblock); + else if (op == 'd') + krb5_c_decrypt(NULL, &kblock, 0, NULL, &outblock, &block); + else if (op == 'm') + krb5_c_make_checksum(NULL, cktype, &kblock, 0, &block, &sum); + else if (op == 'v') + krb5_c_verify_checksum(NULL, &kblock, 0, &block, &sum, &val); + } else { + if (op == 'e') + krb5_k_encrypt(NULL, key, 0, NULL, &block, &outblock); + else if (op == 'd') + krb5_k_decrypt(NULL, key, 0, NULL, &outblock, &block); + else if (op == 'm') + krb5_k_make_checksum(NULL, cktype, key, 0, &block, &sum); + else if (op == 'v') + krb5_k_verify_checksum(NULL, key, 0, &block, &sum, &val); + } + } + return 0; +} diff --git a/src/lib/crypto/krb/Makefile.in b/src/lib/crypto/krb/Makefile.in index e64ef8f310..fe96eba852 100644 --- a/src/lib/crypto/krb/Makefile.in +++ b/src/lib/crypto/krb/Makefile.in @@ -44,6 +44,7 @@ STLIBOBJS=\ enctype_compare.o \ enctype_to_string.o \ etypes.o \ + key.o \ keyblocks.o \ keyed_cksum.o \ keyed_checksum_types.o \ @@ -86,6 +87,7 @@ OBJS=\ $(OUTPRE)enctype_compare.$(OBJEXT) \ $(OUTPRE)enctype_to_string.$(OBJEXT) \ $(OUTPRE)etypes.$(OBJEXT) \ + $(OUTPRE)key.$(OBJECT) \ $(OUTPRE)keyblocks.$(OBJEXT) \ $(OUTPRE)keyed_cksum.$(OBJEXT) \ $(OUTPRE)keyed_checksum_types.$(OBJEXT) \ @@ -127,6 +129,7 @@ SRCS=\ $(srcdir)/enctype_compare.c \ $(srcdir)/enctype_to_string.c \ $(srcdir)/etypes.c \ + $(srcdir)/key.c \ $(srcdir)/keyblocks.c \ $(srcdir)/keyed_cksum.c \ $(srcdir)/keyed_checksum_types.c\ diff --git a/src/lib/crypto/krb/aead.c b/src/lib/crypto/krb/aead.c index ac5e7e87c7..3b11da5dc2 100644 --- a/src/lib/crypto/krb/aead.c +++ b/src/lib/crypto/krb/aead.c @@ -93,7 +93,7 @@ make_unkeyed_checksum_iov(const struct krb5_hash_provider *hash_provider, krb5_error_code krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum_type, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_crypto_iov *data, size_t num_data, @@ -107,7 +107,7 @@ krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum_type, if (cksum_type->keyed_etype) { e1 = find_enctype(cksum_type->keyed_etype); - e2 = find_enctype(key->enctype); + e2 = find_enctype(key->keyblock.enctype); if (e1 == NULL || e2 == NULL || e1->enc != e2->enc) { ret = KRB5_BAD_ENCTYPE; goto cleanup; @@ -338,7 +338,7 @@ krb5_error_code krb5int_c_iov_decrypt_stream(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage keyusage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -451,7 +451,7 @@ krb5_error_code krb5int_c_encrypt_aead_compat(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { @@ -513,7 +513,7 @@ krb5_error_code krb5int_c_decrypt_aead_compat(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { diff --git a/src/lib/crypto/krb/aead.h b/src/lib/crypto/krb/aead.h index 2c99eb868c..cc43875e25 100644 --- a/src/lib/crypto/krb/aead.h +++ b/src/lib/crypto/krb/aead.h @@ -36,7 +36,7 @@ krb5int_c_locate_iov(krb5_crypto_iov *data, krb5_error_code krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_crypto_iov *data, size_t num_data, @@ -87,7 +87,7 @@ krb5_error_code krb5int_c_iov_decrypt_stream(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage keyusage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -97,7 +97,7 @@ krb5_error_code krb5int_c_decrypt_aead_compat(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); @@ -105,7 +105,7 @@ krb5_error_code krb5int_c_encrypt_aead_compat(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); diff --git a/src/lib/crypto/krb/combine_keys.c b/src/lib/crypto/krb/combine_keys.c index 8c3ea1936e..acfb99bbdb 100644 --- a/src/lib/crypto/krb/combine_keys.c +++ b/src/lib/crypto/krb/combine_keys.c @@ -79,7 +79,8 @@ krb5int_c_combine_keys(krb5_context context, krb5_keyblock *key1, size_t keybytes, keylength; const struct krb5_enc_provider *enc; krb5_data input, randbits; - krb5_keyblock tkey; + krb5_keyblock tkeyblock; + krb5_key tkey = NULL; krb5_error_code ret; const struct krb5_keytypes *ktp; krb5_boolean myalloc = FALSE; @@ -152,10 +153,14 @@ krb5int_c_combine_keys(krb5_context context, krb5_keyblock *key1, randbits.length = keybytes; randbits.data = (char *) rnd; - tkey.length = keylength; - tkey.contents = output; + tkeyblock.length = keylength; + tkeyblock.contents = output; - ret = (*enc->make_key)(&randbits, &tkey); + ret = (*enc->make_key)(&randbits, &tkeyblock); + if (ret) + goto cleanup; + + ret = krb5_k_create_key(NULL, &tkeyblock, &tkey); if (ret) goto cleanup; @@ -185,7 +190,7 @@ krb5int_c_combine_keys(krb5_context context, krb5_keyblock *key1, myalloc = TRUE; } - ret = krb5_derive_key(enc, &tkey, outkey, &input); + ret = krb5_derive_keyblock(enc, tkey, outkey, &input); if (ret) { if (myalloc) { free(outkey->contents); @@ -200,6 +205,7 @@ cleanup: zapfree(rnd, keybytes); zapfree(combined, keybytes * 2); zapfree(output, keylength); + krb5_k_free_key(NULL, tkey); return ret; } @@ -215,6 +221,7 @@ dr(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, unsigned char *inblockdata = NULL, *outblockdata = NULL; krb5_data inblock, outblock; krb5_error_code ret; + krb5_key key = NULL; blocksize = enc->block_size; keybytes = enc->keybytes; @@ -226,6 +233,9 @@ dr(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, outblockdata = k5alloc(blocksize, &ret); if (ret) goto cleanup; + ret = krb5_k_create_key(NULL, inkey, &key); + if (ret) + goto cleanup; inblock.data = (char *) inblockdata; inblock.length = blocksize; @@ -246,7 +256,7 @@ dr(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, n = 0; while (n < keybytes) { - ret = (*enc->encrypt)(inkey, 0, &inblock, &outblock); + ret = (*enc->encrypt)(key, 0, &inblock, &outblock); if (ret) goto cleanup; @@ -263,6 +273,7 @@ dr(const struct krb5_enc_provider *enc, const krb5_keyblock *inkey, cleanup: zapfree(inblockdata, blocksize); zapfree(outblockdata, blocksize); + krb5_k_free_key(NULL, key); return ret; } diff --git a/src/lib/crypto/krb/decrypt.c b/src/lib/crypto/krb/decrypt.c index 29b6ef75ca..36c3bf0ab8 100644 --- a/src/lib/crypto/krb/decrypt.c +++ b/src/lib/crypto/krb/decrypt.c @@ -29,13 +29,13 @@ #include "aead.h" krb5_error_code KRB5_CALLCONV -krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, +krb5_k_decrypt(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_enc_data *input, krb5_data *output) { const struct krb5_keytypes *ktp; - ktp = find_enctype(key->enctype); + ktp = find_enctype(key->keyblock.enctype); if (ktp == NULL) return KRB5_BAD_ENCTYPE; @@ -53,3 +53,19 @@ krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, return (*ktp->decrypt)(ktp->enc, ktp->hash, key, usage, ivec, &input->ciphertext, output); } + +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *ivec, + const krb5_enc_data *input, krb5_data *output) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_decrypt(context, key, usage, ivec, input, output); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/decrypt_iov.c b/src/lib/crypto/krb/decrypt_iov.c index c2f2c0b61c..fcc9973776 100644 --- a/src/lib/crypto/krb/decrypt_iov.c +++ b/src/lib/crypto/krb/decrypt_iov.c @@ -29,8 +29,8 @@ #include "aead.h" krb5_error_code KRB5_CALLCONV -krb5_c_decrypt_iov(krb5_context context, - const krb5_keyblock *key, +krb5_k_decrypt_iov(krb5_context context, + krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, krb5_crypto_iov *data, @@ -38,7 +38,7 @@ krb5_c_decrypt_iov(krb5_context context, { const struct krb5_keytypes *ktp; - ktp = find_enctype(key->enctype); + ktp = find_enctype(key->keyblock.enctype); if (ktp == NULL || ktp->aead == NULL) return KRB5_BAD_ENCTYPE; @@ -53,3 +53,22 @@ krb5_c_decrypt_iov(krb5_context context, usage, cipher_state, data, num_data); } +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt_iov(krb5_context context, + const krb5_keyblock *keyblock, + krb5_keyusage usage, + const krb5_data *cipher_state, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_decrypt_iov(context, key, usage, cipher_state, data, + num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/dk/checksum.c b/src/lib/crypto/krb/dk/checksum.c index fb5622a735..31e7de90ef 100644 --- a/src/lib/crypto/krb/dk/checksum.c +++ b/src/lib/crypto/krb/dk/checksum.c @@ -33,19 +33,17 @@ krb5_error_code krb5_dk_make_checksum(const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *input, krb5_data *output) { const struct krb5_keytypes *ktp; const struct krb5_enc_provider *enc; - size_t keylength; krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data datain; - unsigned char *kcdata; - krb5_keyblock kc; + krb5_key kc; - ktp = find_enctype(key->enctype); + ktp = find_enctype(key->keyblock.enctype); if (ktp == NULL) return KRB5_BAD_ENCTYPE; enc = ktp->enc; @@ -55,15 +53,6 @@ krb5_dk_make_checksum(const struct krb5_hash_provider *hash, * output->length will be tested in krb5_hmac. */ - /* Allocate and set to-be-derived keys. */ - keylength = enc->keylength; - kcdata = malloc(keylength); - if (kcdata == NULL) - return ENOMEM; - - kc.contents = kcdata; - kc.length = keylength; - /* Derive the key. */ datain.data = (char *) constantdata; @@ -75,37 +64,34 @@ krb5_dk_make_checksum(const struct krb5_hash_provider *hash, ret = krb5_derive_key(enc, key, &kc, &datain); if (ret) - goto cleanup; + return ret; /* hash the data */ datain = *input; - ret = krb5_hmac(hash, &kc, 1, &datain, output); + ret = krb5_hmac(hash, kc, 1, &datain, output); if (ret) memset(output->data, 0, output->length); -cleanup: - zapfree(kcdata, keylength); + krb5_k_free_key(NULL, kc); return ret; } krb5_error_code krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_crypto_iov *data, size_t num_data, krb5_data *output) { const struct krb5_keytypes *ktp; const struct krb5_enc_provider *enc; - size_t keylength; krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data datain; - unsigned char *kcdata; - krb5_keyblock kc; + krb5_key kc; - ktp = find_enctype(key->enctype); + ktp = find_enctype(key->keyblock.enctype); if (ktp == NULL) return KRB5_BAD_ENCTYPE; enc = ktp->enc; @@ -115,16 +101,6 @@ krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash, * output->length will be tested in krb5_hmac. */ - /* Allocate and set to-be-derived keys. */ - - keylength = enc->keylength; - kcdata = malloc(keylength); - if (kcdata == NULL) - return ENOMEM; - - kc.contents = kcdata; - kc.length = keylength; - /* Derive the key. */ datain.data = (char *) constantdata; @@ -136,17 +112,14 @@ krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash, ret = krb5_derive_key(enc, key, &kc, &datain); if (ret) - goto cleanup; + return ret; /* Hash the data. */ - ret = krb5int_hmac_iov(hash, &kc, data, num_data, output); + ret = krb5int_hmac_iov(hash, kc, data, num_data, output); if (ret) memset(output->data, 0, output->length); -cleanup: - zapfree(kcdata, keylength); - - return(ret); + krb5_k_free_key(NULL, kc); + return ret; } - diff --git a/src/lib/crypto/krb/dk/derive.c b/src/lib/crypto/krb/dk/derive.c index 8c8214c125..c2638e804e 100644 --- a/src/lib/crypto/krb/dk/derive.c +++ b/src/lib/crypto/krb/dk/derive.c @@ -27,10 +27,67 @@ #include "k5-int.h" #include "dk.h" +static krb5_key +find_cached_dkey(struct derived_key *list, const krb5_data *constant) +{ + for (; list; list = list->next) { + if (data_eq(list->constant, *constant)) { + krb5_k_reference_key(NULL, list->dkey); + return list->dkey; + } + } + return NULL; +} + +static krb5_error_code +add_cached_dkey(krb5_key key, const krb5_data *constant, + const krb5_keyblock *dkeyblock, krb5_key *cached_dkey) +{ + krb5_key dkey; + krb5_error_code ret; + struct derived_key *dkent = NULL; + char *data = NULL; + + /* Allocate fields for the new entry. */ + dkent = malloc(sizeof(*dkent)); + if (dkent == NULL) + goto cleanup; + data = malloc(constant->length); + if (data == NULL) + goto cleanup; + ret = krb5_k_create_key(NULL, dkeyblock, &dkey); + if (ret != 0) + goto cleanup; + + /* Add the new entry to the list. */ + memcpy(data, constant->data, constant->length); + dkent->dkey = dkey; + dkent->constant.data = data; + dkent->constant.length = constant->length; + dkent->next = key->derived; + key->derived = dkent; + + /* Return a "copy" of the cached key. */ + krb5_k_reference_key(NULL, dkey); + *cached_dkey = dkey; + return 0; + +cleanup: + free(dkent); + free(data); + return ENOMEM; +} + +/* + * Compute a derived key into the keyblock outkey. This variation on + * krb5_derive_key does not cache the result, as it is only used + * directly in situations which are not expected to be repeated with + * the same inkey and constant. + */ krb5_error_code -krb5_derive_key(const struct krb5_enc_provider *enc, - const krb5_keyblock *inkey, krb5_keyblock *outkey, - const krb5_data *in_constant) +krb5_derive_keyblock(const struct krb5_enc_provider *enc, + krb5_key inkey, krb5_keyblock *outkey, + const krb5_data *in_constant) { size_t blocksize, keybytes, n; unsigned char *inblockdata = NULL, *outblockdata = NULL, *rawkey = NULL; @@ -40,7 +97,8 @@ krb5_derive_key(const struct krb5_enc_provider *enc, blocksize = enc->block_size; keybytes = enc->keybytes; - if (inkey->length != enc->keylength || outkey->length != enc->keylength) + if (inkey->keyblock.length != enc->keylength || + outkey->length != enc->keylength) return KRB5_CRYPTO_INTERNAL; /* Allocate and set up buffers. */ @@ -103,10 +161,48 @@ cleanup: return ret; } +krb5_error_code +krb5_derive_key(const struct krb5_enc_provider *enc, + krb5_key inkey, krb5_key *outkey, + const krb5_data *in_constant) +{ + krb5_keyblock keyblock; + krb5_error_code ret; + krb5_key dkey; + + *outkey = NULL; + + /* Check for a cached result. */ + dkey = find_cached_dkey(inkey->derived, in_constant); + if (dkey != NULL) { + *outkey = dkey; + return 0; + } + + /* Derive into a temporary keyblock. */ + keyblock.length = enc->keylength; + keyblock.contents = malloc(keyblock.length); + if (keyblock.contents == NULL) + return ENOMEM; + ret = krb5_derive_keyblock(enc, inkey, &keyblock, in_constant); + if (ret) + goto cleanup; + + /* Cache the derived key. */ + ret = add_cached_dkey(inkey, in_constant, &keyblock, &dkey); + if (ret != 0) + goto cleanup; + + *outkey = dkey; + +cleanup: + zapfree(keyblock.contents, keyblock.length); + return ret; +} krb5_error_code krb5_derive_random(const struct krb5_enc_provider *enc, - const krb5_keyblock *inkey, krb5_data *outrnd, + krb5_key inkey, krb5_data *outrnd, const krb5_data *in_constant) { size_t blocksize, keybytes, n; @@ -117,7 +213,7 @@ krb5_derive_random(const struct krb5_enc_provider *enc, blocksize = enc->block_size; keybytes = enc->keybytes; - if (inkey->length != enc->keylength || outrnd->length != keybytes) + if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes) return KRB5_CRYPTO_INTERNAL; /* Allocate and set up buffers. */ diff --git a/src/lib/crypto/krb/dk/dk.h b/src/lib/crypto/krb/dk/dk.h index 9ddeb408c8..6566ce8d5a 100644 --- a/src/lib/crypto/krb/dk/dk.h +++ b/src/lib/crypto/krb/dk/dk.h @@ -32,7 +32,7 @@ void krb5_dk_encrypt_length(const struct krb5_enc_provider *enc, krb5_error_code krb5_dk_encrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); @@ -42,7 +42,7 @@ void krb5int_aes_encrypt_length(const struct krb5_enc_provider *enc, krb5_error_code krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, @@ -50,13 +50,13 @@ krb5_error_code krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, krb5_error_code krb5_dk_decrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *arg_output); krb5_error_code krb5int_aes_dk_decrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, @@ -68,26 +68,31 @@ krb5_error_code krb5int_dk_string_to_key(const struct krb5_enc_provider *enc, const krb5_data *params, krb5_keyblock *key); +krb5_error_code krb5_derive_keyblock(const struct krb5_enc_provider *enc, + krb5_key inkey, + krb5_keyblock *outkey, + const krb5_data *in_constant); + krb5_error_code krb5_derive_key(const struct krb5_enc_provider *enc, - const krb5_keyblock *inkey, - krb5_keyblock *outkey, + krb5_key inkey, + krb5_key *outkey, const krb5_data *in_constant); krb5_error_code krb5_dk_make_checksum(const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *input, krb5_data *output); krb5_error_code krb5int_dk_make_checksum_iov(const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_crypto_iov *data, size_t num_data, krb5_data *output); krb5_error_code krb5_derive_random(const struct krb5_enc_provider *enc, - const krb5_keyblock *inkey, krb5_data *outrnd, + krb5_key inkey, krb5_data *outrnd, const krb5_data *in_constant); /* AEAD */ diff --git a/src/lib/crypto/krb/dk/dk_aead.c b/src/lib/crypto/krb/dk/dk_aead.c index 13eb007cdb..5c9c1ad5c7 100644 --- a/src/lib/crypto/krb/dk/dk_aead.c +++ b/src/lib/crypto/krb/dk/dk_aead.c @@ -61,7 +61,7 @@ static krb5_error_code krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -71,7 +71,7 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, unsigned char constantdata[K5CLENGTH]; krb5_data d1, d2; krb5_crypto_iov *header, *trailer, *padding; - krb5_keyblock ke, ki; + krb5_key ke = NULL, ki = NULL; size_t i; unsigned int blocksize = 0; unsigned int plainlen = 0; @@ -79,9 +79,6 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, unsigned int padsize = 0; unsigned char *cksum = NULL; - ke.contents = ki.contents = NULL; - ke.length = ki.length = 0; - /* E(Confounder | Plaintext | Pad) | Checksum */ ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, @@ -126,14 +123,6 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, padding->data.length = padsize; } - ke.length = enc->keylength; - ke.contents = k5alloc(ke.length, &ret); - if (ret != 0) - goto cleanup; - ki.length = enc->keylength; - ki.contents = k5alloc(ki.length, &ret); - if (ret != 0) - goto cleanup; cksum = k5alloc(hash->hashsize, &ret); if (ret != 0) goto cleanup; @@ -169,14 +158,14 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, d2.length = hash->hashsize; d2.data = (char *)cksum; - ret = krb5int_hmac_iov(hash, &ki, data, num_data, &d2); + ret = krb5int_hmac_iov(hash, ki, data, num_data, &d2); if (ret != 0) goto cleanup; /* Encrypt the plaintext (header | data | padding) */ assert(enc->encrypt_iov != NULL); - ret = (*enc->encrypt_iov)(&ke, ivec, data, num_data); /* updates ivec */ + ret = (*enc->encrypt_iov)(ke, ivec, data, num_data); /* updates ivec */ if (ret != 0) goto cleanup; @@ -187,8 +176,8 @@ krb5int_dk_encrypt_iov(const struct krb5_aead_provider *aead, trailer->data.length = hmacsize; cleanup: - zapfree(ke.contents, ke.length); - zapfree(ki.contents, ki.length); + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); free(cksum); return ret; } @@ -197,7 +186,7 @@ static krb5_error_code krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -207,7 +196,7 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, unsigned char constantdata[K5CLENGTH]; krb5_data d1; krb5_crypto_iov *header, *trailer; - krb5_keyblock ke, ki; + krb5_key ke = NULL, ki = NULL; size_t i; unsigned int blocksize = 0; /* enc block size, not confounder len */ unsigned int cipherlen = 0; @@ -220,9 +209,6 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, usage, ivec, data, num_data); } - ke.contents = ki.contents = NULL; - ke.length = ki.length = 0; - /* E(Confounder | Plaintext | Pad) | Checksum */ ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, @@ -262,14 +248,6 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, if (trailer == NULL || trailer->data.length != hmacsize) return KRB5_BAD_MSIZE; - ke.length = enc->keylength; - ke.contents = k5alloc(ke.length, &ret); - if (ret != 0) - goto cleanup; - ki.length = enc->keylength; - ki.contents = k5alloc(ki.length, &ret); - if (ret != 0) - goto cleanup; cksum = k5alloc(hash->hashsize, &ret); if (ret != 0) goto cleanup; @@ -296,7 +274,7 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, /* Decrypt the plaintext (header | data | padding). */ assert(enc->decrypt_iov != NULL); - ret = (*enc->decrypt_iov)(&ke, ivec, data, num_data); /* updates ivec */ + ret = (*enc->decrypt_iov)(ke, ivec, data, num_data); /* updates ivec */ if (ret != 0) goto cleanup; @@ -304,7 +282,7 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, d1.length = hash->hashsize; /* non-truncated length */ d1.data = (char *)cksum; - ret = krb5int_hmac_iov(hash, &ki, data, num_data, &d1); + ret = krb5int_hmac_iov(hash, ki, data, num_data, &d1); if (ret != 0) goto cleanup; @@ -315,10 +293,9 @@ krb5int_dk_decrypt_iov(const struct krb5_aead_provider *aead, } cleanup: - zapfree(ke.contents, ke.length); - zapfree(ki.contents, ki.length); + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); free(cksum); - return ret; } diff --git a/src/lib/crypto/krb/dk/dk_decrypt.c b/src/lib/crypto/krb/dk/dk_decrypt.c index 1c0358a2d3..abb7a39b06 100644 --- a/src/lib/crypto/krb/dk/dk_decrypt.c +++ b/src/lib/crypto/krb/dk/dk_decrypt.c @@ -32,7 +32,7 @@ static krb5_error_code krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, @@ -43,7 +43,7 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, krb5_error_code krb5_dk_decrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { @@ -54,7 +54,7 @@ krb5_dk_decrypt(const struct krb5_enc_provider *enc, krb5_error_code krb5int_aes_dk_decrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { @@ -65,22 +65,20 @@ krb5int_aes_dk_decrypt(const struct krb5_enc_provider *enc, static krb5_error_code krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output, size_t hmacsize, int ivec_mode) { krb5_error_code ret; - size_t hashsize, blocksize, keylength, enclen, plainlen; - unsigned char *plaindata = NULL, *kedata = NULL, *kidata = NULL; - unsigned char *cksum = NULL, *cn; - krb5_keyblock ke, ki; + size_t hashsize, blocksize, enclen, plainlen; + unsigned char *plaindata = NULL, *cksum = NULL, *cn; + krb5_key ke = NULL, ki = NULL; krb5_data d1, d2; unsigned char constantdata[K5CLENGTH]; hashsize = hash->hashsize; blocksize = enc->block_size; - keylength = enc->keylength; if (hmacsize == 0) hmacsize = hashsize; @@ -90,12 +88,6 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, enclen = input->length - hmacsize; /* Allocate and set up ciphertext and to-be-derived keys. */ - kedata = k5alloc(keylength, &ret); - if (ret != 0) - goto cleanup; - kidata = k5alloc(keylength, &ret); - if (ret != 0) - goto cleanup; plaindata = k5alloc(enclen, &ret); if (ret != 0) goto cleanup; @@ -103,11 +95,6 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, if (ret != 0) goto cleanup; - ke.contents = kedata; - ke.length = keylength; - ki.contents = kidata; - ki.length = keylength; - /* Derive the keys. */ d1.data = (char *) constantdata; @@ -135,7 +122,7 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, d2.length = enclen; d2.data = (char *) plaindata; - ret = (*enc->decrypt)(&ke, ivec, &d1, &d2); + ret = (*enc->decrypt)(ke, ivec, &d1, &d2); if (ret != 0) goto cleanup; @@ -155,7 +142,7 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, d1.length = hashsize; d1.data = (char *) cksum; - ret = krb5_hmac(hash, &ki, 1, &d2, &d1); + ret = krb5_hmac(hash, ki, 1, &d2, &d1); if (ret != 0) goto cleanup; @@ -183,8 +170,8 @@ krb5_dk_decrypt_maybe_trunc_hmac(const struct krb5_enc_provider *enc, memcpy(ivec->data, cn, blocksize); cleanup: - zapfree(kedata, keylength); - zapfree(kidata, keylength); + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); zapfree(plaindata, enclen); zapfree(cksum, hashsize); return ret; diff --git a/src/lib/crypto/krb/dk/dk_encrypt.c b/src/lib/crypto/krb/dk/dk_encrypt.c index b06079c636..bb045fa6b0 100644 --- a/src/lib/crypto/krb/dk/dk_encrypt.c +++ b/src/lib/crypto/krb/dk/dk_encrypt.c @@ -53,20 +53,19 @@ krb5_dk_encrypt_length(const struct krb5_enc_provider *enc, krb5_error_code krb5_dk_encrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { - size_t blocksize, keylength, plainlen, enclen; + size_t blocksize, plainlen, enclen; krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data d1, d2; - unsigned char *plaintext = NULL, *kedata = NULL, *kidata = NULL; + unsigned char *plaintext = NULL; char *cn; - krb5_keyblock ke, ki; + krb5_key ke = NULL, ki = NULL; blocksize = enc->block_size; - keylength = enc->keylength; plainlen = krb5_roundup(blocksize + input->length, blocksize); krb5_dk_encrypt_length(enc, hash, input->length, &enclen); @@ -78,20 +77,9 @@ krb5_dk_encrypt(const struct krb5_enc_provider *enc, /* Allocate and set up plaintext and to-be-derived keys. */ - kedata = k5alloc(keylength, &ret); - if (ret != 0) - goto cleanup; - kidata = k5alloc(keylength, &ret); - if (ret != 0) - goto cleanup; - plaintext = k5alloc(plainlen, &ret); - if (ret != 0) - goto cleanup; - - ke.contents = kedata; - ke.length = keylength; - ki.contents = kidata; - ki.length = keylength; + plaintext = malloc(plainlen); + if (plaintext == NULL) + return ENOMEM; /* Derive the keys. */ @@ -134,7 +122,7 @@ krb5_dk_encrypt(const struct krb5_enc_provider *enc, d2.length = plainlen; d2.data = output->data; - ret = (*enc->encrypt)(&ke, ivec, &d1, &d2); + ret = (*enc->encrypt)(ke, ivec, &d1, &d2); if (ret != 0) goto cleanup; @@ -150,7 +138,7 @@ krb5_dk_encrypt(const struct krb5_enc_provider *enc, output->length = enclen; - ret = krb5_hmac(hash, &ki, 1, &d1, &d2); + ret = krb5_hmac(hash, ki, 1, &d1, &d2); if (ret != 0) { memset(d2.data, 0, d2.length); goto cleanup; @@ -161,8 +149,8 @@ krb5_dk_encrypt(const struct krb5_enc_provider *enc, memcpy(ivec->data, cn, blocksize); cleanup: - zapfree(kedata, keylength); - zapfree(kidata, keylength); + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); zapfree(plaintext, plainlen); return ret; } @@ -186,7 +174,7 @@ krb5int_aes_encrypt_length(const struct krb5_enc_provider *enc, static krb5_error_code trunc_hmac (const struct krb5_hash_provider *hash, - const krb5_keyblock *ki, unsigned int num, + krb5_key ki, unsigned int num, const krb5_data *input, const krb5_data *output) { size_t hashsize; @@ -211,23 +199,22 @@ trunc_hmac (const struct krb5_hash_provider *hash, krb5_error_code krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { - size_t blocksize, keybytes, keylength, plainlen, enclen; + size_t blocksize, keybytes, plainlen, enclen; krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data d1, d2; - unsigned char *plaintext = NULL, *kedata = NULL, *kidata = NULL; + unsigned char *plaintext = NULL; char *cn; - krb5_keyblock ke, ki; + krb5_key ke = NULL, ki = NULL; /* allocate and set up plaintext and to-be-derived keys */ blocksize = enc->block_size; keybytes = enc->keybytes; - keylength = enc->keylength; plainlen = blocksize+input->length; krb5int_aes_encrypt_length(enc, hash, input->length, &enclen); @@ -237,20 +224,9 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, if (output->length < enclen) return KRB5_BAD_MSIZE; - kedata = k5alloc(keylength, &ret); - if (ret != 0) - goto cleanup; - kidata = k5alloc(keylength, &ret); - if (ret != 0) - goto cleanup; - plaintext = k5alloc(plainlen, &ret); - if (ret != 0) - goto cleanup; - - ke.contents = kedata; - ke.length = keylength; - ki.contents = kidata; - ki.length = keylength; + plaintext = malloc(plainlen); + if (plaintext == NULL) + return ENOMEM; /* Derive the keys. */ @@ -294,7 +270,7 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, d2.length = plainlen; d2.data = output->data; - ret = (*enc->encrypt)(&ke, ivec, &d1, &d2); + ret = (*enc->encrypt)(ke, ivec, &d1, &d2); if (ret != 0) goto cleanup; @@ -311,7 +287,7 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, if (d2.length != 96 / 8) abort(); - ret = trunc_hmac(hash, &ki, 1, &d1, &d2); + ret = trunc_hmac(hash, ki, 1, &d1, &d2); if (ret != 0) { memset(d2.data, 0, d2.length); goto cleanup; @@ -324,8 +300,8 @@ krb5int_aes_dk_encrypt(const struct krb5_enc_provider *enc, memcpy(ivec->data, cn, blocksize); cleanup: - zapfree(kedata, keylength); - zapfree(kidata, keylength); + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); zapfree(plaintext, plainlen); return ret; } diff --git a/src/lib/crypto/krb/dk/stringtokey.c b/src/lib/crypto/krb/dk/stringtokey.c index 3265657583..48b053ad9c 100644 --- a/src/lib/crypto/krb/dk/stringtokey.c +++ b/src/lib/crypto/krb/dk/stringtokey.c @@ -32,15 +32,16 @@ static const unsigned char kerberos[] = "kerberos"; krb5_error_code krb5int_dk_string_to_key(const struct krb5_enc_provider *enc, const krb5_data *string, const krb5_data *salt, - const krb5_data *parms, krb5_keyblock *key) + const krb5_data *parms, krb5_keyblock *keyblock) { krb5_error_code ret; size_t keybytes, keylength, concatlen; unsigned char *concat = NULL, *foldstring = NULL, *foldkeydata = NULL; krb5_data indata; - krb5_keyblock foldkey; + krb5_keyblock foldkeyblock; + krb5_key foldkey = NULL; - /* key->length is checked by krb5_derive_key. */ + /* keyblock->length is checked by krb5_derive_key. */ keybytes = enc->keybytes; keylength = enc->keylength; @@ -67,10 +68,14 @@ krb5int_dk_string_to_key(const struct krb5_enc_provider *enc, indata.length = keybytes; indata.data = (char *) foldstring; - foldkey.length = keylength; - foldkey.contents = foldkeydata; + foldkeyblock.length = keylength; + foldkeyblock.contents = foldkeydata; - ret = (*enc->make_key)(&indata, &foldkey); + ret = (*enc->make_key)(&indata, &foldkeyblock); + if (ret != 0) + goto cleanup; + + ret = krb5_k_create_key(NULL, &foldkeyblock, &foldkey); if (ret != 0) goto cleanup; @@ -79,13 +84,14 @@ krb5int_dk_string_to_key(const struct krb5_enc_provider *enc, indata.length = kerberos_len; indata.data = (char *) kerberos; - ret = krb5_derive_key(enc, &foldkey, key, &indata); + ret = krb5_derive_keyblock(enc, foldkey, keyblock, &indata); if (ret != 0) - memset(key->contents, 0, key->length); + memset(keyblock->contents, 0, keyblock->length); cleanup: zapfree(concat, concatlen); zapfree(foldstring, keybytes); zapfree(foldkeydata, keylength); + krb5_k_free_key(NULL, foldkey); return ret; } diff --git a/src/lib/crypto/krb/encrypt.c b/src/lib/crypto/krb/encrypt.c index 741485a314..3c39838cf5 100644 --- a/src/lib/crypto/krb/encrypt.c +++ b/src/lib/crypto/krb/encrypt.c @@ -29,19 +29,19 @@ #include "aead.h" krb5_error_code KRB5_CALLCONV -krb5_c_encrypt(krb5_context context, const krb5_keyblock *key, +krb5_k_encrypt(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_enc_data *output) { const struct krb5_keytypes *ktp; - ktp = find_enctype(key->enctype); + ktp = find_enctype(key->keyblock.enctype); if (ktp == NULL) return KRB5_BAD_ENCTYPE; output->magic = KV5M_ENC_DATA; output->kvno = 0; - output->enctype = key->enctype; + output->enctype = key->keyblock.enctype; if (ktp->encrypt == NULL) { assert(ktp->aead != NULL); @@ -54,3 +54,19 @@ krb5_c_encrypt(krb5_context context, const krb5_keyblock *key, return (*ktp->encrypt)(ktp->enc, ktp->hash, key, usage, ivec, input, &output->ciphertext); } + +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *ivec, + const krb5_data *input, krb5_enc_data *output) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_encrypt(context, key, usage, ivec, input, output); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/encrypt_iov.c b/src/lib/crypto/krb/encrypt_iov.c index 21242bca2c..b7b2f58145 100644 --- a/src/lib/crypto/krb/encrypt_iov.c +++ b/src/lib/crypto/krb/encrypt_iov.c @@ -28,8 +28,8 @@ #include "etypes.h" krb5_error_code KRB5_CALLCONV -krb5_c_encrypt_iov(krb5_context context, - const krb5_keyblock *key, +krb5_k_encrypt_iov(krb5_context context, + krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, krb5_crypto_iov *data, @@ -37,7 +37,7 @@ krb5_c_encrypt_iov(krb5_context context, { const struct krb5_keytypes *ktp; - ktp = find_enctype(key->enctype); + ktp = find_enctype(key->keyblock.enctype); if (ktp == NULL || ktp->aead == NULL) return KRB5_BAD_ENCTYPE; @@ -45,3 +45,22 @@ krb5_c_encrypt_iov(krb5_context context, key, usage, cipher_state, data, num_data); } +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt_iov(krb5_context context, + const krb5_keyblock *keyblock, + krb5_keyusage usage, + const krb5_data *cipher_state, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_encrypt_iov(context, key, usage, cipher_state, data, + num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/etypes.h b/src/lib/crypto/krb/etypes.h index 8d83b4200f..edaa00caea 100644 --- a/src/lib/crypto/krb/etypes.h +++ b/src/lib/crypto/krb/etypes.h @@ -33,7 +33,7 @@ typedef void (*krb5_encrypt_length_func)(const struct krb5_enc_provider *enc, typedef krb5_error_code (*krb5_crypt_func)(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage keyusage, const krb5_data *ivec, const krb5_data *input, @@ -48,7 +48,7 @@ typedef krb5_error_code (*krb5_str2key_func)(const struct typedef krb5_error_code (*krb5_prf_func)(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, const krb5_data *in, krb5_data *out); struct krb5_keytypes { diff --git a/src/lib/crypto/krb/key.c b/src/lib/crypto/krb/key.c new file mode 100644 index 0000000000..4ea72b478f --- /dev/null +++ b/src/lib/crypto/krb/key.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Functions for manipulating krb5_key structures + */ + +#include "k5-int.h" + +/* + * The krb5_key data type wraps an exposed keyblock in an opaque data + * structure, to allow for internal optimizations such as caching of + * derived keys. + */ + +/* Create a krb5_key from the enctype and key data in a keyblock. */ +krb5_error_code KRB5_CALLCONV +krb5_k_create_key(krb5_context context, const krb5_keyblock *key_data, + krb5_key *out) +{ + krb5_key key = NULL; + krb5_error_code code; + + *out = NULL; + + key = malloc(sizeof(*key)); + if (key == NULL) + return ENOMEM; + code = krb5int_c_copy_keyblock_contents(context, key_data, &key->keyblock); + if (code) + goto cleanup; + + key->refcount = 1; + key->derived = NULL; + *out = key; + return 0; + +cleanup: + free(key); + return code; +} + +void KRB5_CALLCONV +krb5_k_reference_key(krb5_context context, krb5_key key) +{ + key->refcount++; +} + +/* Free the memory used by a krb5_key. */ +void KRB5_CALLCONV +krb5_k_free_key(krb5_context context, krb5_key key) +{ + struct derived_key *dk; + + if (key == NULL || --key->refcount > 0) + return; + + /* Free the derived key cache. */ + while ((dk = key->derived) != NULL) { + key->derived = dk->next; + krb5_k_free_key(context, dk->dkey); + free(dk); + } + krb5int_c_free_keyblock_contents(context, &key->keyblock); +} + +/* Retrieve a copy of the keyblock from a krb5_key. */ +krb5_error_code KRB5_CALLCONV +krb5_k_key_keyblock(krb5_context context, krb5_key key, + krb5_keyblock **key_data) +{ + return krb5int_c_copy_keyblock(context, &key->keyblock, key_data); +} + +/* Retrieve the enctype of a krb5_key. */ +krb5_enctype KRB5_CALLCONV +krb5_k_key_enctype(krb5_context context, krb5_key key) +{ + return key->keyblock.enctype; +} diff --git a/src/lib/crypto/krb/keyblocks.c b/src/lib/crypto/krb/keyblocks.c index ee88f9a8a9..51e31d3015 100644 --- a/src/lib/crypto/krb/keyblocks.c +++ b/src/lib/crypto/krb/keyblocks.c @@ -62,7 +62,6 @@ krb5int_c_init_keyblock(krb5_context context, krb5_enctype enctype, return 0; } - void krb5int_c_free_keyblock(krb5_context context, register krb5_keyblock *val) { @@ -78,3 +77,38 @@ krb5int_c_free_keyblock_contents(krb5_context context, krb5_keyblock *key) key->contents = NULL; } } + +krb5_error_code +krb5int_c_copy_keyblock(krb5_context context, const krb5_keyblock *from, + krb5_keyblock **to) +{ + krb5_keyblock *new_key; + krb5_error_code code; + + *to = NULL; + new_key = malloc(sizeof(*new_key)); + if (!new_key) + return ENOMEM; + code = krb5int_c_copy_keyblock_contents(context, from, new_key); + if (code) { + free(new_key); + return code; + } + *to = new_key; + return 0; +} + +krb5_error_code +krb5int_c_copy_keyblock_contents(krb5_context context, + const krb5_keyblock *from, krb5_keyblock *to) +{ + *to = *from; + if (to->length) { + to->contents = malloc(to->length); + if (!to->contents) + return ENOMEM; + memcpy(to->contents, from->contents, to->length); + } else + to->contents = 0; + return 0; +} diff --git a/src/lib/crypto/krb/keyhash_provider/descbc.c b/src/lib/crypto/krb/keyhash_provider/descbc.c index bf68e324ce..b08e30b7c6 100644 --- a/src/lib/crypto/krb/keyhash_provider/descbc.c +++ b/src/lib/crypto/krb/keyhash_provider/descbc.c @@ -29,12 +29,12 @@ #include "keyhash_provider.h" static krb5_error_code -k5_descbc_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, +k5_descbc_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { mit_des_key_schedule schedule; - if (key->length != 8) + if (key->keyblock.length != 8) return(KRB5_BAD_KEYSIZE); if ((input->length%8) != 0) return(KRB5_BAD_MSIZE); @@ -43,7 +43,7 @@ k5_descbc_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *i if (output->length != 8) return(KRB5_CRYPTO_INTERNAL); - switch (mit_des_key_sched(key->contents, schedule)) { + switch (mit_des_key_sched(key->keyblock.contents, schedule)) { case -1: return(KRB5DES_BAD_KEYPAR); case -2: diff --git a/src/lib/crypto/krb/keyhash_provider/hmac_md5.c b/src/lib/crypto/krb/keyhash_provider/hmac_md5.c index 34ce67169e..61c6d8c21d 100644 --- a/src/lib/crypto/krb/keyhash_provider/hmac_md5.c +++ b/src/lib/crypto/krb/keyhash_provider/hmac_md5.c @@ -36,24 +36,23 @@ #include "../aead.h" static krb5_error_code -k5_hmac_md5_hash (const krb5_keyblock *key, krb5_keyusage usage, +k5_hmac_md5_hash (krb5_key key, krb5_keyusage usage, const krb5_data *iv, const krb5_data *input, krb5_data *output) { krb5_keyusage ms_usage; krb5_error_code ret; - krb5_keyblock ks; + krb5_keyblock keyblock; + krb5_key ks = NULL; krb5_data ds, ks_constant, md5tmp; krb5_MD5_CTX ctx; char t[4]; - ds.length = key->length; - ks.length = key->length; + ds.length = key->keyblock.length; ds.data = malloc(ds.length); if (ds.data == NULL) return ENOMEM; - ks.contents = (void *) ds.data; ks_constant.data = "signaturekey"; ks_constant.length = strlen(ks_constant.data)+1; /* Including null*/ @@ -63,6 +62,12 @@ k5_hmac_md5_hash (const krb5_keyblock *key, krb5_keyusage usage, if (ret) goto cleanup; + keyblock.length = key->keyblock.length; + keyblock.contents = (void *) ds.data; + ret = krb5_k_create_key(NULL, &keyblock, &ks); + if (ret) + goto cleanup; + krb5_MD5Init (&ctx); ms_usage = krb5int_arcfour_translate_usage (usage); store_32_le(ms_usage, t); @@ -72,36 +77,36 @@ k5_hmac_md5_hash (const krb5_keyblock *key, krb5_keyusage usage, krb5_MD5Final(&ctx); md5tmp.data = (void *) ctx.digest; md5tmp.length = 16; - ret = krb5_hmac ( &krb5int_hash_md5, &ks, 1, &md5tmp, + + ret = krb5_hmac ( &krb5int_hash_md5, ks, 1, &md5tmp, output); cleanup: memset(&ctx, 0, sizeof(ctx)); - memset (ks.contents, 0, ks.length); - free (ks.contents); + zapfree(ds.data, ds.length); + krb5_k_free_key(NULL, ks); return ret; } static krb5_error_code -k5_hmac_md5_hash_iov (const krb5_keyblock *key, krb5_keyusage usage, +k5_hmac_md5_hash_iov (krb5_key key, krb5_keyusage usage, const krb5_data *iv, const krb5_crypto_iov *data, size_t num_data, krb5_data *output) { krb5_keyusage ms_usage; krb5_error_code ret; - krb5_keyblock ks; + krb5_keyblock keyblock; + krb5_key ks = NULL; krb5_data ds, ks_constant, md5tmp; krb5_MD5_CTX ctx; char t[4]; size_t i; - ds.length = key->length; - ks.length = key->length; + ds.length = key->keyblock.length; ds.data = malloc(ds.length); if (ds.data == NULL) return ENOMEM; - ks.contents = (void *) ds.data; ks_constant.data = "signaturekey"; ks_constant.length = strlen(ks_constant.data)+1; /* Including null*/ @@ -111,6 +116,12 @@ k5_hmac_md5_hash_iov (const krb5_keyblock *key, krb5_keyusage usage, if (ret) goto cleanup; + keyblock.length = key->keyblock.length; + keyblock.contents = (void *) ds.data; + ret = krb5_k_create_key(NULL, &keyblock, &ks); + if (ret) + goto cleanup; + krb5_MD5Init (&ctx); ms_usage = krb5int_arcfour_translate_usage (usage); store_32_le(ms_usage, t); @@ -125,13 +136,13 @@ k5_hmac_md5_hash_iov (const krb5_keyblock *key, krb5_keyusage usage, krb5_MD5Final(&ctx); md5tmp.data = (void *) ctx.digest; md5tmp.length = 16; - ret = krb5_hmac ( &krb5int_hash_md5, &ks, 1, &md5tmp, + ret = krb5_hmac ( &krb5int_hash_md5, ks, 1, &md5tmp, output); cleanup: memset(&ctx, 0, sizeof(ctx)); - memset (ks.contents, 0, ks.length); - free (ks.contents); + zapfree(keyblock.contents, keyblock.length); + krb5_k_free_key(NULL, ks); return ret; } diff --git a/src/lib/crypto/krb/keyhash_provider/k5_md4des.c b/src/lib/crypto/krb/keyhash_provider/k5_md4des.c index 49700a89d4..1514dccc67 100644 --- a/src/lib/crypto/krb/keyhash_provider/k5_md4des.c +++ b/src/lib/crypto/krb/keyhash_provider/k5_md4des.c @@ -39,7 +39,7 @@ extern struct krb5_enc_provider krb5int_enc_des; static krb5_error_code -k5_md4des_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, +k5_md4des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_error_code ret; @@ -77,7 +77,7 @@ k5_md4des_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *i } static krb5_error_code -k5_md4des_verify(const krb5_keyblock *key, krb5_keyusage usage, +k5_md4des_verify(krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, const krb5_data *hash, krb5_boolean *valid) @@ -89,7 +89,7 @@ k5_md4des_verify(const krb5_keyblock *key, krb5_keyusage usage, struct krb5_enc_provider *enc = &krb5int_enc_des; krb5_data output, iv; - if (key->length != 8) + if (key->keyblock.length != 8) return(KRB5_BAD_KEYSIZE); if (hash->length != (CONFLENGTH+RSA_MD4_CKSUM_LENGTH)) { #ifdef KRB5_MD4DES_BETA5_COMPAT @@ -104,11 +104,11 @@ k5_md4des_verify(const krb5_keyblock *key, krb5_keyusage usage, } if (compathash) { - iv.data = malloc(key->length); + iv.data = malloc(key->keyblock.length); if (!iv.data) return ENOMEM; - iv.length = key->length; - if (key->contents) - memcpy(iv.data, key->contents, key->length); + iv.length = key->keyblock.length; + if (key->keyblock.contents) + memcpy(iv.data, key->keyblock.contents, key->keyblock.length); } /* decrypt it */ diff --git a/src/lib/crypto/krb/keyhash_provider/k5_md5des.c b/src/lib/crypto/krb/keyhash_provider/k5_md5des.c index 24d6317060..e7a84e2a85 100644 --- a/src/lib/crypto/krb/keyhash_provider/k5_md5des.c +++ b/src/lib/crypto/krb/keyhash_provider/k5_md5des.c @@ -39,7 +39,7 @@ extern struct krb5_enc_provider krb5int_enc_des; static krb5_error_code -k5_md5des_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, +k5_md5des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_error_code ret; @@ -78,7 +78,7 @@ k5_md5des_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *i } static krb5_error_code -k5_md5des_verify(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, +k5_md5des_verify(krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, const krb5_data *hash, krb5_boolean *valid) { @@ -89,7 +89,7 @@ k5_md5des_verify(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data struct krb5_enc_provider *enc = &krb5int_enc_des; krb5_data output, iv; - if (key->length != 8) + if (key->keyblock.length != 8) return(KRB5_BAD_KEYSIZE); if (hash->length != (CONFLENGTH+RSA_MD5_CKSUM_LENGTH)) { @@ -104,11 +104,11 @@ k5_md5des_verify(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data } if (compathash) { - iv.data = malloc(key->length); + iv.data = malloc(key->keyblock.length); if (!iv.data) return ENOMEM; - iv.length = key->length; - if (key->contents) - memcpy(iv.data, key->contents, key->length); + iv.length = key->keyblock.length; + if (key->keyblock.contents) + memcpy(iv.data, key->keyblock.contents, key->keyblock.length); } /* decrypt it */ diff --git a/src/lib/crypto/krb/keyhash_provider/md5_hmac.c b/src/lib/crypto/krb/keyhash_provider/md5_hmac.c index d05b97f00d..589c3475ed 100644 --- a/src/lib/crypto/krb/keyhash_provider/md5_hmac.c +++ b/src/lib/crypto/krb/keyhash_provider/md5_hmac.c @@ -33,7 +33,7 @@ #include "hash_provider.h" static krb5_error_code -k5_md5_hmac_hash (const krb5_keyblock *key, krb5_keyusage usage, +k5_md5_hmac_hash (krb5_key key, krb5_keyusage usage, const krb5_data *iv, const krb5_data *input, krb5_data *output) { diff --git a/src/lib/crypto/krb/make_checksum.c b/src/lib/crypto/krb/make_checksum.c index ca4ca58056..dd34df3770 100644 --- a/src/lib/crypto/krb/make_checksum.c +++ b/src/lib/crypto/krb/make_checksum.c @@ -30,8 +30,8 @@ #include "dk.h" krb5_error_code KRB5_CALLCONV -krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, - const krb5_keyblock *key, krb5_keyusage usage, +krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype, + krb5_key key, krb5_keyusage usage, const krb5_data *input, krb5_checksum *cksum) { unsigned int i; @@ -68,7 +68,7 @@ krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, /* check if key is compatible */ if (ctp->keyed_etype) { ktp1 = find_enctype(ctp->keyed_etype); - ktp2 = find_enctype(key->enctype); + ktp2 = find_enctype(key->keyblock.enctype); if (ktp1 == NULL || ktp2 == NULL || ktp1->enc != ktp2->enc) { ret = KRB5_BAD_ENCTYPE; goto cleanup; @@ -115,3 +115,21 @@ cleanup: return ret; } + +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, + const krb5_keyblock *keyblock, krb5_keyusage usage, + const krb5_data *input, krb5_checksum *cksum) +{ + krb5_key key = NULL; + krb5_error_code ret; + + if (keyblock != NULL) { + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + } + ret = krb5_k_make_checksum(context, cksumtype, key, usage, input, cksum); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/make_checksum_iov.c b/src/lib/crypto/krb/make_checksum_iov.c index a16b849c05..32c9a4cb4f 100644 --- a/src/lib/crypto/krb/make_checksum_iov.c +++ b/src/lib/crypto/krb/make_checksum_iov.c @@ -29,9 +29,9 @@ #include "aead.h" krb5_error_code KRB5_CALLCONV -krb5_c_make_checksum_iov(krb5_context context, +krb5_k_make_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, krb5_crypto_iov *data, size_t num_data) @@ -81,3 +81,23 @@ krb5_c_make_checksum_iov(krb5_context context, return(ret); } + +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum_iov(krb5_context context, + krb5_cksumtype cksumtype, + const krb5_keyblock *keyblock, + krb5_keyusage usage, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_make_checksum_iov(context, cksumtype, key, usage, + data, num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/old/old.h b/src/lib/crypto/krb/old/old.h index 94ee6421e8..6cfb0c97ad 100644 --- a/src/lib/crypto/krb/old/old.h +++ b/src/lib/crypto/krb/old/old.h @@ -34,14 +34,14 @@ void krb5_old_encrypt_length krb5_error_code krb5_old_encrypt (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); krb5_error_code krb5_old_decrypt (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *arg_output); diff --git a/src/lib/crypto/krb/old/old_decrypt.c b/src/lib/crypto/krb/old/old_decrypt.c index cfbbd7272a..dd9ad19cb3 100644 --- a/src/lib/crypto/krb/old/old_decrypt.c +++ b/src/lib/crypto/krb/old/old_decrypt.c @@ -30,7 +30,7 @@ krb5_error_code krb5_old_decrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, @@ -87,9 +87,9 @@ krb5_old_decrypt(const struct krb5_enc_provider *enc, cn = NULL; /* XXX this is gross, but I don't have much choice */ - if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) { - crcivec.length = key->length; - crcivec.data = (char *) key->contents; + if ((key->keyblock.enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) { + crcivec.length = key->keyblock.length; + crcivec.data = (char *) key->keyblock.contents; ivec = &crcivec; } diff --git a/src/lib/crypto/krb/old/old_encrypt.c b/src/lib/crypto/krb/old/old_encrypt.c index 98bd109e0e..1121dc935e 100644 --- a/src/lib/crypto/krb/old/old_encrypt.c +++ b/src/lib/crypto/krb/old/old_encrypt.c @@ -44,7 +44,7 @@ krb5_old_encrypt_length(const struct krb5_enc_provider *enc, krb5_error_code krb5_old_encrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, @@ -87,9 +87,9 @@ krb5_old_encrypt(const struct krb5_enc_provider *enc, /* encrypt it */ /* XXX this is gross, but I don't have much choice */ - if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) { - crcivec.length = key->length; - crcivec.data = (char *) key->contents; + if ((key->keyblock.enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) { + crcivec.length = key->keyblock.length; + crcivec.data = (char *) key->keyblock.contents; ivec = &crcivec; real_ivec = 0; } else diff --git a/src/lib/crypto/krb/prf.c b/src/lib/crypto/krb/prf.c index d2c633e757..12ec22b65b 100644 --- a/src/lib/crypto/krb/prf.c +++ b/src/lib/crypto/krb/prf.c @@ -50,15 +50,17 @@ krb5_c_prf_length(krb5_context context, krb5_enctype enctype, size_t *len) } krb5_error_code KRB5_CALLCONV -krb5_c_prf(krb5_context context, const krb5_keyblock *key, +krb5_c_prf(krb5_context context, const krb5_keyblock *keyblock, krb5_data *input, krb5_data *output) { const struct krb5_keytypes *ktp; + krb5_key key; + krb5_error_code ret; assert(input && output); assert(output->data); - ktp = find_enctype(key->enctype); + ktp = find_enctype(keyblock->enctype); if (ktp == NULL) return KRB5_BAD_ENCTYPE; if (ktp->prf == NULL) @@ -67,5 +69,10 @@ krb5_c_prf(krb5_context context, const krb5_keyblock *key, output->magic = KV5M_DATA; if (ktp->prf_length != output->length) return KRB5_CRYPTO_INTERNAL; - return (*ktp->prf)(ktp->enc, ktp->hash, key, input, output); + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = (*ktp->prf)(ktp->enc, ktp->hash, key, input, output); + krb5_k_free_key(context, key); + return ret; } diff --git a/src/lib/crypto/krb/prf/des_prf.c b/src/lib/crypto/krb/prf/des_prf.c index 869f2e0bf6..dd9907bda4 100644 --- a/src/lib/crypto/krb/prf/des_prf.c +++ b/src/lib/crypto/krb/prf/des_prf.c @@ -35,8 +35,7 @@ krb5_error_code krb5int_des_prf (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, - const krb5_data *in, krb5_data *out) + krb5_key key, const krb5_data *in, krb5_data *out) { krb5_data tmp; krb5_error_code ret = 0; diff --git a/src/lib/crypto/krb/prf/dk_prf.c b/src/lib/crypto/krb/prf/dk_prf.c index cc3e2d9341..cc203875cb 100644 --- a/src/lib/crypto/krb/prf/dk_prf.c +++ b/src/lib/crypto/krb/prf/dk_prf.c @@ -35,12 +35,11 @@ krb5_error_code krb5int_dk_prf (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, - const krb5_data *in, krb5_data *out) + krb5_key key, const krb5_data *in, krb5_data *out) { krb5_data tmp; krb5_data prfconst; - krb5_keyblock *kp = NULL; + krb5_key kp = NULL; krb5_error_code ret = 0; prfconst.data = (char *) "prf"; @@ -51,14 +50,10 @@ krb5int_dk_prf (const struct krb5_enc_provider *enc, return ENOMEM; hash->hash(1, in, &tmp); tmp.length = (tmp.length/enc->block_size)*enc->block_size; /*truncate to block size*/ - ret = krb5int_c_init_keyblock(0, key->enctype, - key->length, &kp); - if (ret == 0) - ret = krb5_derive_key(enc, key, kp, &prfconst); + ret = krb5_derive_key(enc, key, &kp, &prfconst); if (ret == 0) - ret = enc->encrypt(kp, NULL, &tmp, out); - if (kp) - krb5int_c_free_keyblock(0, kp); + ret = enc->encrypt(kp, NULL, &tmp, out); + krb5_k_free_key(NULL, kp); free (tmp.data); return ret; } diff --git a/src/lib/crypto/krb/prf/prf_int.h b/src/lib/crypto/krb/prf/prf_int.h index 180ce027d9..97bbf049d0 100644 --- a/src/lib/crypto/krb/prf/prf_int.h +++ b/src/lib/crypto/krb/prf/prf_int.h @@ -32,19 +32,17 @@ krb5_error_code krb5int_arcfour_prf(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, - const krb5_data *in, krb5_data *out); + krb5_key key, const krb5_data *in, krb5_data *out); krb5_error_code krb5int_des_prf (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, - const krb5_data *in, krb5_data *out); + krb5_key key, const krb5_data *in, krb5_data *out); krb5_error_code krb5int_dk_prf(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, const krb5_data *in, krb5_data *out); + krb5_key key, const krb5_data *in, krb5_data *out); #endif /*PRF_INTERNAL_DEFS*/ diff --git a/src/lib/crypto/krb/prf/rc4_prf.c b/src/lib/crypto/krb/prf/rc4_prf.c index 2b1b73f914..3affaa5398 100644 --- a/src/lib/crypto/krb/prf/rc4_prf.c +++ b/src/lib/crypto/krb/prf/rc4_prf.c @@ -32,8 +32,7 @@ krb5_error_code krb5int_arcfour_prf(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, - const krb5_data *in, krb5_data *out) + krb5_key key, const krb5_data *in, krb5_data *out) { assert(out->length == 20); return krb5_hmac(&krb5int_hash_sha1, key, 1, in, out); diff --git a/src/lib/crypto/krb/raw/raw.h b/src/lib/crypto/krb/raw/raw.h index f4b7d5f0b7..84ae730238 100644 --- a/src/lib/crypto/krb/raw/raw.h +++ b/src/lib/crypto/krb/raw/raw.h @@ -34,14 +34,14 @@ void krb5_raw_encrypt_length krb5_error_code krb5_raw_encrypt (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output); krb5_error_code krb5_raw_decrypt (const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *arg_output); diff --git a/src/lib/crypto/krb/raw/raw_aead.c b/src/lib/crypto/krb/raw/raw_aead.c index f52fe000d1..68070d1daa 100644 --- a/src/lib/crypto/krb/raw/raw_aead.c +++ b/src/lib/crypto/krb/raw/raw_aead.c @@ -54,7 +54,7 @@ static krb5_error_code krb5int_raw_encrypt_iov(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -104,7 +104,7 @@ static krb5_error_code krb5int_raw_decrypt_iov(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, diff --git a/src/lib/crypto/krb/raw/raw_decrypt.c b/src/lib/crypto/krb/raw/raw_decrypt.c index 767da1f9fa..dd62806e4e 100644 --- a/src/lib/crypto/krb/raw/raw_decrypt.c +++ b/src/lib/crypto/krb/raw/raw_decrypt.c @@ -30,7 +30,7 @@ krb5_error_code krb5_raw_decrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { diff --git a/src/lib/crypto/krb/raw/raw_encrypt.c b/src/lib/crypto/krb/raw/raw_encrypt.c index 68b819c016..462239ee59 100644 --- a/src/lib/crypto/krb/raw/raw_encrypt.c +++ b/src/lib/crypto/krb/raw/raw_encrypt.c @@ -42,7 +42,7 @@ krb5_raw_encrypt_length(const struct krb5_enc_provider *enc, krb5_error_code krb5_raw_encrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { diff --git a/src/lib/crypto/krb/verify_checksum.c b/src/lib/crypto/krb/verify_checksum.c index 4466c7dadf..82f4fb11f1 100644 --- a/src/lib/crypto/krb/verify_checksum.c +++ b/src/lib/crypto/krb/verify_checksum.c @@ -28,7 +28,7 @@ #include "cksumtypes.h" krb5_error_code KRB5_CALLCONV -krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, +krb5_k_verify_checksum(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *data, const krb5_checksum *cksum, krb5_boolean *valid) { @@ -79,7 +79,7 @@ krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, computed.length = hashsize; - ret = krb5_c_make_checksum(context, cksum->checksum_type, key, usage, + ret = krb5_k_make_checksum(context, cksum->checksum_type, key, usage, data, &computed); if (ret) return ret; @@ -89,3 +89,21 @@ krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, free(computed.contents); return 0; } + +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *data, + const krb5_checksum *cksum, krb5_boolean *valid) +{ + krb5_key key = NULL; + krb5_error_code ret; + + if (keyblock != NULL) { + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + } + ret = krb5_k_verify_checksum(context, key, usage, data, cksum, valid); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/verify_checksum_iov.c b/src/lib/crypto/krb/verify_checksum_iov.c index 341c89684f..f322dc386c 100644 --- a/src/lib/crypto/krb/verify_checksum_iov.c +++ b/src/lib/crypto/krb/verify_checksum_iov.c @@ -29,9 +29,9 @@ #include "aead.h" krb5_error_code KRB5_CALLCONV -krb5_c_verify_checksum_iov(krb5_context context, +krb5_k_verify_checksum_iov(krb5_context context, krb5_cksumtype checksum_type, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_crypto_iov *data, size_t num_data, @@ -94,3 +94,24 @@ krb5_c_verify_checksum_iov(krb5_context context, free(computed.data); return 0; } + +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum_iov(krb5_context context, + krb5_cksumtype checksum_type, + const krb5_keyblock *keyblock, + krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_boolean *valid) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_verify_checksum_iov(context, checksum_type, key, usage, data, + num_data, valid); + krb5_k_free_key(context, key); + return ret; +} diff --git a/src/lib/crypto/krb/yarrow/ycipher.c b/src/lib/crypto/krb/yarrow/ycipher.c index 2af410440d..84cadd13fb 100644 --- a/src/lib/crypto/krb/yarrow/ycipher.c +++ b/src/lib/crypto/krb/yarrow/ycipher.c @@ -42,27 +42,28 @@ krb5int_yarrow_cipher_init const struct krb5_enc_provider *enc = &yarrow_enc_provider; krb5_error_code ret; krb5_data randombits; + krb5_keyblock keyblock; + keybytes = enc->keybytes; keylength = enc->keylength; assert (keybytes == CIPHER_KEY_SIZE); - if (ctx->key.contents) { - memset (ctx->key.contents, 0, ctx->key.length); - free (ctx->key.contents); - } - ctx->key.contents = (void *) malloc (keylength); - ctx->key.length = keylength; - if (ctx->key.contents == NULL) + krb5_k_free_key(NULL, ctx->key); + ctx->key = NULL; + keyblock.contents = malloc(keylength); + keyblock.length = keylength; + if (keyblock.contents == NULL) return (YARROW_NOMEM); randombits.data = (char *) key; randombits.length = keybytes; - ret = enc->make_key (&randombits, &ctx->key); - if (ret) { - memset (ctx->key.contents, 0, ctx->key.length); - free(ctx->key.contents); - ctx->key.contents = NULL; - return (YARROW_FAIL); - } - return (YARROW_OK); + ret = enc->make_key(&randombits, &keyblock); + if (ret != 0) + goto cleanup; + ret = krb5_k_create_key(NULL, &keyblock, &ctx->key); +cleanup: + free(keyblock.contents); + if (ret) + return YARROW_FAIL; + return YARROW_OK; } int krb5int_yarrow_cipher_encrypt_block @@ -76,7 +77,7 @@ int krb5int_yarrow_cipher_encrypt_block ind.length = CIPHER_BLOCK_SIZE; outd.data = (char *) out; outd.length = CIPHER_BLOCK_SIZE; - ret = enc->encrypt (&ctx->key, 0, &ind, &outd); + ret = enc->encrypt(ctx->key, 0, &ind, &outd); if (ret) return YARROW_FAIL; return YARROW_OK; @@ -87,10 +88,6 @@ krb5int_yarrow_cipher_final (CIPHER_CTX *ctx) { - if (ctx->key.contents) { - memset (ctx->key.contents, 0, ctx->key.length); - free (ctx->key.contents); - } - ctx->key.contents = 0; - ctx->key.length = 0; + krb5_k_free_key(NULL, ctx->key); + ctx->key = NULL; } diff --git a/src/lib/crypto/krb/yarrow/ycipher.h b/src/lib/crypto/krb/yarrow/ycipher.h index 96999c0dbb..ad0d307fcb 100644 --- a/src/lib/crypto/krb/yarrow/ycipher.h +++ b/src/lib/crypto/krb/yarrow/ycipher.h @@ -7,7 +7,7 @@ typedef struct { - krb5_keyblock key; + krb5_key key; } CIPHER_CTX; /* We need to choose a cipher. To do this, choose an enc_provider. diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports index 4ea46fa193..953497e176 100644 --- a/src/lib/crypto/libk5crypto.exports +++ b/src/lib/crypto/libk5crypto.exports @@ -72,6 +72,18 @@ krb5_finish_random_key krb5_free_cksumtypes krb5_hmac krb5_init_random_key +krb5_k_create_key +krb5_k_decrypt +krb5_k_decrypt_iov +krb5_k_encrypt +krb5_k_encrypt_iov +krb5_k_free_key +krb5_k_key_enctype +krb5_k_key_keyblock +krb5_k_make_checksum +krb5_k_make_checksum_iov +krb5_k_verify_checksum +krb5_k_verify_checksum_iov krb5_nfold krb5_old_decrypt krb5_old_encrypt @@ -100,6 +112,8 @@ krb5int_aes_string_to_key krb5int_arcfour_string_to_key krb5int_arcfour_translate_usage krb5int_c_combine_keys +krb5int_c_copy_keyblock +krb5int_c_copy_keyblock_contents krb5int_c_free_keyblock krb5int_c_free_keyblock_contents krb5int_c_init_keyblock @@ -122,6 +136,7 @@ krb5int_hash_crc32 krb5int_hash_md4 krb5int_hash_md5 krb5int_hash_sha1 +krb5int_hmac_keyblock krb5int_keyhash_descbc krb5int_keyhash_hmac_md5 krb5int_keyhash_md4des diff --git a/src/lib/crypto/openssl/aes/aes_s2k.c b/src/lib/crypto/openssl/aes/aes_s2k.c index 1383be11a2..db6553e25a 100644 --- a/src/lib/crypto/openssl/aes/aes_s2k.c +++ b/src/lib/crypto/openssl/aes/aes_s2k.c @@ -44,6 +44,7 @@ krb5int_aes_string_to_key(const struct krb5_enc_provider *enc, unsigned long iter_count; krb5_data out; static const krb5_data usage = { KV5M_DATA, 8, "kerberos" }; + krb5_key tempkey = NULL; krb5_error_code err; if (params) { @@ -66,25 +67,25 @@ krb5int_aes_string_to_key(const struct krb5_enc_provider *enc, if (iter_count >= MAX_ITERATION_COUNT) return KRB5_ERR_BAD_S2K_PARAMS; - /* - * Dense key space, no parity bits or anything, so take a shortcut - * and use the key contents buffer for the generated bytes. - */ + /* Use the output keyblock contents for temporary space. */ out.data = (char *) key->contents; out.length = key->length; if (out.length != 16 && out.length != 32) return KRB5_CRYPTO_INTERNAL; err = krb5int_pbkdf2_hmac_sha1 (&out, iter_count, string, salt); - if (err) { - memset(out.data, 0, out.length); - return err; - } + if (err) + goto cleanup; - err = krb5_derive_key (enc, key, key, &usage); - if (err) { - memset(out.data, 0, out.length); - return err; - } - return 0; + err = krb5_k_create_key (NULL, key, &tempkey); + if (err) + goto cleanup; + + err = krb5_derive_keyblock (enc, tempkey, key, &usage); + +cleanup: + if (err) + memset (out.data, 0, out.length); + krb5_k_free_key (NULL, tempkey); + return err; } diff --git a/src/lib/crypto/openssl/arcfour/arcfour.c b/src/lib/crypto/openssl/arcfour/arcfour.c index 687f276b01..2c89b99b82 100644 --- a/src/lib/crypto/openssl/arcfour/arcfour.c +++ b/src/lib/crypto/openssl/arcfour/arcfour.c @@ -65,11 +65,12 @@ case 7: /* tgs-req authenticator */ krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_keyblock k1, k2, k3; + krb5_key k3key = NULL; krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder; krb5_keyusage ms_usage; size_t keylength, keybytes, blocksize, hashsize; @@ -84,7 +85,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, d1.data=malloc(d1.length); if (d1.data == NULL) return (ENOMEM); - k1 = *key; + k1 = key->keyblock; k1.length=d1.length; k1.contents= (void *) d1.data; @@ -94,7 +95,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, free(d1.data); return (ENOMEM); } - k2 = *key; + k2 = key->keyblock; k2.length=d2.length; k2.contents=(void *) d2.data; @@ -105,7 +106,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, free(d2.data); return (ENOMEM); } - k3 = *key; + k3 = key->keyblock; k3.length=d3.length; k3.contents= (void *) d3.data; @@ -141,7 +142,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, /* begin the encryption, computer K1 */ ms_usage=krb5int_arcfour_translate_usage(usage); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { strncpy(salt.data, krb5int_arcfour_l40, salt.length); store_32_le(ms_usage, salt.data+10); } else { @@ -152,7 +153,7 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) + if (key->keyblock.enctype==ENCTYPE_ARCFOUR_HMAC_EXP) memset(k1.contents+7, 0xab, 9); ret=krb5_c_random_make_octets(/* XXX */ 0, &confounder); @@ -160,11 +161,19 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, if (ret) goto cleanup; - krb5_hmac(hash, &k2, 1, &plaintext, &checksum); + ret = krb5int_hmac_keyblock(hash, &k2, 1, &plaintext, &checksum); + if (ret) + goto cleanup; + + ret = krb5int_hmac_keyblock(hash, &k1, 1, &checksum, &d3); + if (ret) + goto cleanup; - krb5_hmac(hash, &k1, 1, &checksum, &d3); + ret = krb5_k_create_key(NULL, &k3, &k3key); + if (ret) + goto cleanup; - ret=(*(enc->encrypt))(&k3, ivec, &plaintext, &ciphertext); + ret=(*(enc->encrypt))(k3key, ivec, &plaintext, &ciphertext); cleanup: memset(d1.data, 0, d1.length); @@ -185,11 +194,12 @@ krb5_arcfour_encrypt(const struct krb5_enc_provider *enc, krb5_error_code krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage usage, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_keyblock k1,k2,k3; + krb5_key k3key; krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum; krb5_keyusage ms_usage; size_t keybytes, keylength, hashsize, blocksize; @@ -204,7 +214,7 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, d1.data=malloc(d1.length); if (d1.data == NULL) return (ENOMEM); - k1 = *key; + k1 = key->keyblock; k1.length=d1.length; k1.contents= (void *) d1.data; @@ -214,7 +224,7 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, free(d1.data); return (ENOMEM); } - k2 = *key; + k2 = key->keyblock; k2.length=d2.length; k2.contents= (void *) d2.data; @@ -225,7 +235,7 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, free(d2.data); return (ENOMEM); } - k3 = *key; + k3 = key->keyblock; k3.length=d3.length; k3.contents= (void *) d3.data; @@ -258,7 +268,7 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, /* We may have to try two ms_usage values; see below. */ do { /* compute the salt */ - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { strncpy(salt.data, krb5int_arcfour_l40, salt.length); store_32_le(ms_usage, salt.data + 10); } else { @@ -271,18 +281,22 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) memset(k1.contents + 7, 0xab, 9); - ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + ret = krb5int_hmac_keyblock(hash, &k1, 1, &checksum, &d3); if (ret) goto cleanup; - ret = (*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext); + ret = krb5_k_create_key(NULL, &k3, &k3key); + if (ret) + goto cleanup; + ret = (*(enc->decrypt))(k3key, ivec, &ciphertext, &plaintext); + krb5_k_free_key(NULL, k3key); if (ret) goto cleanup; - ret = krb5_hmac(hash, &k2, 1, &plaintext, &d1); + ret = krb5int_hmac_keyblock(hash, &k2, 1, &plaintext, &d1); if (ret) goto cleanup; diff --git a/src/lib/crypto/openssl/arcfour/arcfour.h b/src/lib/crypto/openssl/arcfour/arcfour.h index be408febc6..1a2876437d 100644 --- a/src/lib/crypto/openssl/arcfour/arcfour.h +++ b/src/lib/crypto/openssl/arcfour/arcfour.h @@ -10,7 +10,7 @@ krb5_arcfour_encrypt_length(const struct krb5_enc_provider *, extern krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *, const struct krb5_hash_provider *, - const krb5_keyblock *, + krb5_key, krb5_keyusage, const krb5_data *, const krb5_data *, @@ -19,7 +19,7 @@ krb5_error_code krb5_arcfour_encrypt(const struct krb5_enc_provider *, extern krb5_error_code krb5_arcfour_decrypt(const struct krb5_enc_provider *, const struct krb5_hash_provider *, - const krb5_keyblock *, + krb5_key, krb5_keyusage, const krb5_data *, const krb5_data *, @@ -34,10 +34,5 @@ extern krb5_error_code krb5int_arcfour_string_to_key( extern const struct krb5_enc_provider krb5int_enc_arcfour; extern const struct krb5_aead_provider krb5int_aead_arcfour; - krb5_error_code krb5int_arcfour_prf( - const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - const krb5_keyblock *key, - const krb5_data *in, krb5_data *out); #endif /* ARCFOUR_H */ diff --git a/src/lib/crypto/openssl/arcfour/arcfour_aead.c b/src/lib/crypto/openssl/arcfour/arcfour_aead.c index cff7d66d65..4896afaaf4 100644 --- a/src/lib/crypto/openssl/arcfour/arcfour_aead.c +++ b/src/lib/crypto/openssl/arcfour/arcfour_aead.c @@ -82,7 +82,7 @@ static krb5_error_code krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -91,6 +91,7 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, krb5_error_code ret; krb5_crypto_iov *header, *trailer; krb5_keyblock k1, k2, k3; + krb5_key k3key = NULL; krb5_data d1, d2, d3; krb5_data checksum, confounder, header_data; krb5_keyusage ms_usage; @@ -126,15 +127,15 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, data[i].data.length = 0; } - ret = alloc_derived_key(enc, &k1, &d1, key); + ret = alloc_derived_key(enc, &k1, &d1, &key->keyblock); if (ret != 0) goto cleanup; - ret = alloc_derived_key(enc, &k2, &d2, key); + ret = alloc_derived_key(enc, &k2, &d2, &key->keyblock); if (ret != 0) goto cleanup; - ret = alloc_derived_key(enc, &k3, &d3, key); + ret = alloc_derived_key(enc, &k3, &d3, &key->keyblock); if (ret != 0) goto cleanup; @@ -144,7 +145,7 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, ms_usage = krb5int_arcfour_translate_usage(usage); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { strncpy(salt.data, krb5int_arcfour_l40, salt.length); store_32_le(ms_usage, salt.data + 10); } else { @@ -157,7 +158,7 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) memset(k1.contents + 7, 0xAB, 9); header->data.length = hash->hashsize + CONFOUNDERLENGTH; @@ -176,15 +177,19 @@ krb5int_arcfour_encrypt_iov(const struct krb5_aead_provider *aead, header->data.length -= hash->hashsize; header->data.data += hash->hashsize; - ret = krb5int_hmac_iov(hash, &k2, data, num_data, &checksum); + ret = krb5int_hmac_iov_keyblock(hash, &k2, data, num_data, &checksum); if (ret != 0) goto cleanup; - ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + ret = krb5int_hmac_keyblock(hash, &k1, 1, &checksum, &d3); if (ret != 0) goto cleanup; - ret = enc->encrypt_iov(&k3, ivec, data, num_data); + ret = krb5_k_create_key(NULL, &k3, &k3key); + if (ret != 0) + goto cleanup; + + ret = enc->encrypt_iov(k3key, ivec, data, num_data); if (ret != 0) goto cleanup; @@ -204,6 +209,7 @@ cleanup: free(d3.data); } + krb5_k_free_key(NULL, k3key); return ret; } @@ -211,7 +217,7 @@ static krb5_error_code krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, - const krb5_keyblock *key, + krb5_key key, krb5_keyusage usage, const krb5_data *ivec, krb5_crypto_iov *data, @@ -220,6 +226,7 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, krb5_error_code ret; krb5_crypto_iov *header, *trailer; krb5_keyblock k1, k2, k3; + krb5_key k3key = NULL; krb5_data d1, d2, d3; krb5_data checksum, header_data; krb5_keyusage ms_usage; @@ -240,15 +247,15 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, if (trailer != NULL && trailer->data.length != 0) return KRB5_BAD_MSIZE; - ret = alloc_derived_key(enc, &k1, &d1, key); + ret = alloc_derived_key(enc, &k1, &d1, &key->keyblock); if (ret != 0) goto cleanup; - ret = alloc_derived_key(enc, &k2, &d2, key); + ret = alloc_derived_key(enc, &k2, &d2, &key->keyblock); if (ret != 0) goto cleanup; - ret = alloc_derived_key(enc, &k3, &d3, key); + ret = alloc_derived_key(enc, &k3, &d3, &key->keyblock); if (ret != 0) goto cleanup; @@ -258,7 +265,7 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, ms_usage = krb5int_arcfour_translate_usage(usage); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { strncpy(salt.data, krb5int_arcfour_l40, salt.length); store_32_le(ms_usage, (unsigned char *)salt.data + 10); } else { @@ -271,7 +278,7 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) memset(k1.contents + 7, 0xAB, 9); checksum.data = header->data.data; @@ -281,15 +288,19 @@ krb5int_arcfour_decrypt_iov(const struct krb5_aead_provider *aead, header->data.length -= hash->hashsize; header->data.data += hash->hashsize; - ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + ret = krb5int_hmac_keyblock(hash, &k1, 1, &checksum, &d3); + if (ret != 0) + goto cleanup; + + ret = krb5_k_create_key(NULL, &k3, &k3key); if (ret != 0) goto cleanup; - ret = enc->decrypt_iov(&k3, ivec, data, num_data); + ret = enc->decrypt_iov(k3key, ivec, data, num_data); if (ret != 0) goto cleanup; - ret = krb5int_hmac_iov(hash, &k2, data, num_data, &d1); + ret = krb5int_hmac_iov_keyblock(hash, &k2, data, num_data, &d1); if (ret != 0) goto cleanup; @@ -314,6 +325,7 @@ cleanup: free(d3.data); } + krb5_k_free_key(NULL, k3key); return ret; } diff --git a/src/lib/crypto/openssl/enc_provider/aes.c b/src/lib/crypto/openssl/enc_provider/aes.c index 81d3063003..76f81d41e1 100644 --- a/src/lib/crypto/openssl/enc_provider/aes.c +++ b/src/lib/crypto/openssl/enc_provider/aes.c @@ -36,22 +36,22 @@ /* proto's */ static krb5_error_code -cts_enc(const krb5_keyblock *key, const krb5_data *ivec, +cts_enc(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output); static krb5_error_code -cbc_enc(const krb5_keyblock *key, const krb5_data *ivec, +cbc_enc(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output); static krb5_error_code -cts_decr(const krb5_keyblock *key, const krb5_data *ivec, +cts_decr(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output); static krb5_error_code -cbc_decr(const krb5_keyblock *key, const krb5_data *ivec, +cbc_decr(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output); static krb5_error_code -cts_encr_iov(const krb5_keyblock *key, const krb5_data *ivec, +cts_encr_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data, size_t dlen); static krb5_error_code -cts_decr_iov(const krb5_keyblock *key, const krb5_data *ivec, +cts_decr_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data, size_t dlen); #define NUM_BITS 8 @@ -69,7 +69,7 @@ map_mode(unsigned int len) } static krb5_error_code -cbc_enc(const krb5_keyblock *key, const krb5_data *ivec, +cbc_enc(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0, tmp_len = 0; @@ -77,7 +77,7 @@ cbc_enc(const krb5_keyblock *key, const krb5_data *ivec, unsigned char *tmp_buf = NULL; EVP_CIPHER_CTX ciph_ctx; - key_buf = OPENSSL_malloc(key->length); + key_buf = OPENSSL_malloc(key->keyblock.length); if (!key_buf) return ENOMEM; @@ -87,11 +87,11 @@ cbc_enc(const krb5_keyblock *key, const krb5_data *ivec, OPENSSL_free(key_buf); return ENOMEM; } - memcpy(key_buf, key->contents, key->length); + memcpy(key_buf, key->keyblock.contents, key->keyblock.length); EVP_CIPHER_CTX_init(&ciph_ctx); - ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->length), + ret = EVP_EncryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length), NULL, key_buf, (ivec) ? (unsigned char*)ivec->data : NULL); if (ret == 1){ @@ -112,7 +112,7 @@ cbc_enc(const krb5_keyblock *key, const krb5_data *ivec, ret = KRB5_CRYPTO_INTERNAL; } - memset(key_buf, 0, key->length); + memset(key_buf, 0, key->keyblock.length); memset(tmp_buf, 0, input->length); OPENSSL_free(key_buf); OPENSSL_free(tmp_buf); @@ -121,7 +121,7 @@ cbc_enc(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -cbc_decr(const krb5_keyblock *key, const krb5_data *ivec, +cbc_decr(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0, tmp_len = 0; @@ -129,7 +129,7 @@ cbc_decr(const krb5_keyblock *key, const krb5_data *ivec, unsigned char *tmp_buf = NULL; EVP_CIPHER_CTX ciph_ctx; - key_buf = OPENSSL_malloc(key->length); + key_buf = OPENSSL_malloc(key->keyblock.length); if (!key_buf) return ENOMEM; @@ -139,11 +139,11 @@ cbc_decr(const krb5_keyblock *key, const krb5_data *ivec, OPENSSL_free(key_buf); return ENOMEM; } - memcpy(key_buf, key->contents, key->length); + memcpy(key_buf, key->keyblock.contents, key->keyblock.length); EVP_CIPHER_CTX_init(&ciph_ctx); - ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->length), + ret = EVP_DecryptInit_ex(&ciph_ctx, map_mode(key->keyblock.length), NULL, key_buf, (ivec) ? (unsigned char*)ivec->data : NULL); if (ret == 1) { EVP_CIPHER_CTX_set_padding(&ciph_ctx,0); @@ -164,7 +164,7 @@ cbc_decr(const krb5_keyblock *key, const krb5_data *ivec, ret = KRB5_CRYPTO_INTERNAL; } - memset(key_buf, 0, key->length); + memset(key_buf, 0, key->keyblock.length); memset(tmp_buf, 0, input->length); OPENSSL_free(key_buf); OPENSSL_free(tmp_buf); @@ -173,7 +173,7 @@ cbc_decr(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -cts_enc(const krb5_keyblock *key, const krb5_data *ivec, +cts_enc(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0, tmp_len = 0; @@ -194,7 +194,8 @@ cts_enc(const krb5_keyblock *key, const krb5_data *ivec, return ENOMEM; tmp_len = input->length; - AES_set_encrypt_key(key->contents, NUM_BITS * key->length, &enck); + AES_set_encrypt_key(key->keyblock.contents, + NUM_BITS * key->keyblock.length, &enck); size = CRYPTO_cts128_encrypt((unsigned char *)input->data, tmp_buf, input->length, &enck, @@ -217,7 +218,7 @@ cts_enc(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -cts_decr(const krb5_keyblock *key, const krb5_data *ivec, +cts_decr(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0, tmp_len = 0; @@ -238,7 +239,8 @@ cts_decr(const krb5_keyblock *key, const krb5_data *ivec, return ENOMEM; tmp_len = input->length; - AES_set_decrypt_key(key->contents, NUM_BITS * key->length, &deck); + AES_set_decrypt_key(key->keyblock.contents, + NUM_BITS * key->keyblock.length, &deck); size = CRYPTO_cts128_decrypt((unsigned char *)input->data, tmp_buf, input->length, &deck, @@ -261,7 +263,7 @@ cts_decr(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -cts_encr_iov(const krb5_keyblock *key, +cts_encr_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data, size_t dlen) @@ -313,7 +315,8 @@ cts_encr_iov(const krb5_keyblock *key, if (tlen > dlen) break; } - AES_set_encrypt_key(key->contents, NUM_BITS * key->length, &enck); + AES_set_encrypt_key(key->keyblock.contents, + NUM_BITS * key->keyblock.length, &enck); size = CRYPTO_cts128_encrypt((unsigned char *)dbuf, oblock, dlen, &enck, iv_cts, (cbc128_f)AES_cbc_encrypt); @@ -336,7 +339,7 @@ cts_encr_iov(const krb5_keyblock *key, } static krb5_error_code -cts_decr_iov(const krb5_keyblock *key, +cts_decr_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data, size_t dlen) @@ -373,7 +376,8 @@ cts_decr_iov(const krb5_keyblock *key, memset(oblock, 0, oblock_len); memset(dbuf, 0, dlen); - AES_set_decrypt_key(key->contents, NUM_BITS * key->length, &deck); + AES_set_decrypt_key(key->keyblock.contents, + NUM_BITS * key->keyblock.length, &deck); tlen = 0; for (;;) { @@ -411,7 +415,7 @@ cts_decr_iov(const krb5_keyblock *key, } krb5_error_code -krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec, +krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0; @@ -426,7 +430,7 @@ krb5int_aes_encrypt(const krb5_keyblock *key, const krb5_data *ivec, } krb5_error_code -krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec, +krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0; @@ -445,7 +449,7 @@ krb5int_aes_decrypt(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -krb5int_aes_encrypt_iov(const krb5_keyblock *key, +krb5int_aes_encrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -470,7 +474,7 @@ krb5int_aes_encrypt_iov(const krb5_keyblock *key, } static krb5_error_code -krb5int_aes_decrypt_iov(const krb5_keyblock *key, +krb5int_aes_decrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) diff --git a/src/lib/crypto/openssl/enc_provider/des.c b/src/lib/crypto/openssl/enc_provider/des.c index 4965c6e6fa..a4208eefcb 100644 --- a/src/lib/crypto/openssl/enc_provider/des.c +++ b/src/lib/crypto/openssl/enc_provider/des.c @@ -11,11 +11,11 @@ #define DES_KEY_BYTES 7 static krb5_error_code -validate(const krb5_keyblock *key, const krb5_data *ivec, +validate(krb5_key key, const krb5_data *ivec, const krb5_data *input, const krb5_data *output) { - /* key->enctype was checked by the caller */ - if (key->length != KRB5_MIT_DES_KEYSIZE) + /* key->keyblock.enctype was checked by the caller */ + if (key->keyblock.length != KRB5_MIT_DES_KEYSIZE) return(KRB5_BAD_KEYSIZE); if ((input->length%8) != 0) return(KRB5_BAD_MSIZE); @@ -28,7 +28,7 @@ validate(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -validate_iov(const krb5_keyblock *key, const krb5_data *ivec, +validate_iov(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data, size_t num_data) { size_t i, input_length; @@ -39,7 +39,7 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec, input_length += iov->data.length; } - if (key->length != KRB5_MIT_DES3_KEYSIZE) + if (key->keyblock.length != KRB5_MIT_DES3_KEYSIZE) return(KRB5_BAD_KEYSIZE); if ((input_length%DES_BLOCK_SIZE) != 0) return(KRB5_BAD_MSIZE); @@ -50,7 +50,7 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des_encrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0, tmp_len = 0; @@ -63,8 +63,8 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec, if (ret) return ret; - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; tmp_buf_len = output->length*2; tmp_buf=OPENSSL_malloc(tmp_buf_len); @@ -103,10 +103,10 @@ k5_des_encrypt(const krb5_keyblock *key, const krb5_data *ivec, static krb5_error_code -k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des_decrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { - /* key->enctype was checked by the caller */ + /* key->keyblock.enctype was checked by the caller */ int ret = 0, tmp_len = 0; unsigned char *keybuf = NULL; unsigned char *tmp_buf; @@ -116,8 +116,8 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec, if (ret) return ret; - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; tmp_buf=OPENSSL_malloc(output->length); if (!tmp_buf) @@ -152,7 +152,7 @@ k5_des_decrypt(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des_encrypt_iov(const krb5_keyblock *key, +k5_des_encrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -176,8 +176,8 @@ k5_des_encrypt_iov(const krb5_keyblock *key, IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; ret = validate_iov(key, ivec, data, num_data); if (ret) @@ -229,7 +229,7 @@ k5_des_encrypt_iov(const krb5_keyblock *key, } static krb5_error_code -k5_des_decrypt_iov(const krb5_keyblock *key, +k5_des_decrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -254,8 +254,8 @@ k5_des_decrypt_iov(const krb5_keyblock *key, IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; ret = validate_iov(key, ivec, data, num_data); if (ret) diff --git a/src/lib/crypto/openssl/enc_provider/des3.c b/src/lib/crypto/openssl/enc_provider/des3.c index 1dec8e27e2..e20e42e23d 100644 --- a/src/lib/crypto/openssl/enc_provider/des3.c +++ b/src/lib/crypto/openssl/enc_provider/des3.c @@ -11,12 +11,12 @@ #define DES_BLOCK_SIZE 8 static krb5_error_code -validate(const krb5_keyblock *key, const krb5_data *ivec, +validate(krb5_key key, const krb5_data *ivec, const krb5_data *input, const krb5_data *output) { - /* key->enctype was checked by the caller */ + /* key->keyblock.enctype was checked by the caller */ - if (key->length != KRB5_MIT_DES3_KEYSIZE) + if (key->keyblock.length != KRB5_MIT_DES3_KEYSIZE) return(KRB5_BAD_KEYSIZE); if ((input->length%DES_BLOCK_SIZE) != 0) return(KRB5_BAD_MSIZE); @@ -29,7 +29,7 @@ validate(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -validate_iov(const krb5_keyblock *key, const krb5_data *ivec, +validate_iov(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data, size_t num_data) { size_t i, input_length; @@ -40,7 +40,7 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec, input_length += iov->data.length; } - if (key->length != KRB5_MIT_DES3_KEYSIZE) + if (key->keyblock.length != KRB5_MIT_DES3_KEYSIZE) return(KRB5_BAD_KEYSIZE); if ((input_length%DES_BLOCK_SIZE) != 0) return(KRB5_BAD_MSIZE); @@ -51,7 +51,7 @@ validate_iov(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des3_encrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0, tmp_len = 0; @@ -64,8 +64,8 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, if (ret) return ret; - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; tmp_buf_len = output->length * 2; tmp_buf = OPENSSL_malloc(tmp_buf_len); @@ -104,7 +104,7 @@ k5_des3_encrypt(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec, +k5_des3_decrypt(krb5_key key, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { int ret = 0, tmp_len = 0; @@ -117,8 +117,8 @@ k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec, if (ret) return ret; - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; tmp_buf_len = output->length; tmp_buf=OPENSSL_malloc(tmp_buf_len); @@ -156,7 +156,7 @@ k5_des3_decrypt(const krb5_keyblock *key, const krb5_data *ivec, } static krb5_error_code -k5_des3_encrypt_iov(const krb5_keyblock *key, +k5_des3_encrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -185,8 +185,8 @@ k5_des3_encrypt_iov(const krb5_keyblock *key, IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; memset(oblock, 0, oblock_len); @@ -236,7 +236,7 @@ k5_des3_encrypt_iov(const krb5_keyblock *key, } static krb5_error_code -k5_des3_decrypt_iov(const krb5_keyblock *key, +k5_des3_decrypt_iov(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) @@ -265,8 +265,8 @@ k5_des3_decrypt_iov(const krb5_keyblock *key, IOV_BLOCK_STATE_INIT(&input_pos); IOV_BLOCK_STATE_INIT(&output_pos); - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; memset(oblock, 0, oblock_len); diff --git a/src/lib/crypto/openssl/enc_provider/rc4.c b/src/lib/crypto/openssl/enc_provider/rc4.c index ae2f58f406..fd1c7238d6 100644 --- a/src/lib/crypto/openssl/enc_provider/rc4.c +++ b/src/lib/crypto/openssl/enc_provider/rc4.c @@ -15,7 +15,7 @@ /* prototypes */ static krb5_error_code -k5_arcfour_docrypt(const krb5_keyblock *, const krb5_data *, +k5_arcfour_docrypt(krb5_key, const krb5_data *, const krb5_data *, krb5_data *); static krb5_error_code k5_arcfour_free_state ( krb5_data *state); @@ -29,7 +29,7 @@ k5_arcfour_init_state (const krb5_keyblock *key, /* In-place rc4 crypto */ static krb5_error_code -k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state, +k5_arcfour_docrypt(krb5_key key, const krb5_data *state, const krb5_data *input, krb5_data *output) { int ret = 0, tmp_len = 0; @@ -37,14 +37,14 @@ k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state, unsigned char *tmp_buf = NULL; EVP_CIPHER_CTX ciph_ctx; - if (key->length != RC4_KEY_SIZE) + if (key->keyblock.length != RC4_KEY_SIZE) return(KRB5_BAD_KEYSIZE); if (input->length != output->length) return(KRB5_BAD_MSIZE); - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; EVP_CIPHER_CTX_init(&ciph_ctx); @@ -72,7 +72,7 @@ k5_arcfour_docrypt(const krb5_keyblock *key, const krb5_data *state, /* In-place IOV crypto */ static krb5_error_code -k5_arcfour_docrypt_iov(const krb5_keyblock *key, +k5_arcfour_docrypt_iov(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, size_t num_data) @@ -84,8 +84,8 @@ k5_arcfour_docrypt_iov(const krb5_keyblock *key, krb5_crypto_iov *iov = NULL; EVP_CIPHER_CTX ciph_ctx; - keybuf=key->contents; - keybuf[key->length] = '\0'; + keybuf=key->keyblock.contents; + keybuf[key->keyblock.length] = '\0'; EVP_CIPHER_CTX_init(&ciph_ctx); diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c index e0c8dec796..658bc28f10 100644 --- a/src/lib/crypto/openssl/hmac.c +++ b/src/lib/crypto/openssl/hmac.c @@ -32,8 +32,9 @@ map_digest(const struct krb5_hash_provider *hash) } krb5_error_code -krb5_hmac(const struct krb5_hash_provider *hash, const krb5_keyblock *key, - unsigned int icount, const krb5_data *input, krb5_data *output) +krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *key, unsigned int icount, + const krb5_data *input, krb5_data *output) { unsigned int i = 0, md_len = 0; unsigned char md[EVP_MAX_MD_SIZE]; @@ -72,8 +73,10 @@ krb5_hmac(const struct krb5_hash_provider *hash, const krb5_keyblock *key, } krb5_error_code -krb5int_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key, - const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +krb5int_hmac_iov_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) { krb5_data *sign_data; size_t num_sign_data; @@ -101,10 +104,25 @@ krb5int_hmac_iov(const struct krb5_hash_provider *hash, const krb5_keyblock *key } /* caller must store checksum in iov as it may be TYPE_TRAILER or TYPE_CHECKSUM */ - ret = krb5_hmac(hash, key, num_sign_data, sign_data, output); + ret = krb5int_hmac_keyblock(hash, key, num_sign_data, sign_data, output); free(sign_data); return ret; } +krb5_error_code +krb5_hmac(const struct krb5_hash_provider *hash, krb5_key key, + unsigned int icount, const krb5_data *input, krb5_data *output) +{ + return krb5int_hmac_keyblock(hash, &key->keyblock, icount, input, output); +} + +krb5_error_code +krb5int_hmac_iov(const struct krb5_hash_provider *hash, krb5_key key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + return krb5int_hmac_iov_keyblock(hash, &key->keyblock, data, num_data, + output); +} |