diff --git a/lib/krb5/crypto-aes-sha1.c b/lib/krb5/crypto-aes-sha1.c index d07ad0e8b..bc7f0fc39 100644 --- a/lib/krb5/crypto-aes-sha1.c +++ b/lib/krb5/crypto-aes-sha1.c @@ -106,7 +106,7 @@ AES_SHA1_PRF(krb5_context context, iov[0].data = *in; iov[0].flags = KRB5_CRYPTO_TYPE_DATA; - ret = (*ct->checksum)(context, NULL, 0, iov, 1, &result); + ret = (*ct->checksum)(context, crypto, NULL, 0, iov, 1, &result); if (ret) { krb5_data_free(&result.checksum); return ret; diff --git a/lib/krb5/crypto-aes-sha2.c b/lib/krb5/crypto-aes-sha2.c index c7d8dc10d..78bbf025f 100644 --- a/lib/krb5/crypto-aes-sha2.c +++ b/lib/krb5/crypto-aes-sha2.c @@ -58,6 +58,7 @@ _krb5_aes_sha2_md_for_enctype(krb5_context context, static krb5_error_code SP_HMAC_SHA2_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, diff --git a/lib/krb5/crypto-arcfour.c b/lib/krb5/crypto-arcfour.c index dfc5d2f36..2a5d295a2 100644 --- a/lib/krb5/crypto-arcfour.c +++ b/lib/krb5/crypto-arcfour.c @@ -57,6 +57,7 @@ static struct _krb5_key_type keytype_arcfour = { krb5_error_code _krb5_HMAC_MD5_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, @@ -75,17 +76,22 @@ _krb5_HMAC_MD5_checksum(krb5_context context, krb5_error_code ret; int i; - m = EVP_MD_CTX_create(); - if (m == NULL) - return krb5_enomem(context); + if (crypto != NULL) { + if (crypto->mdctx == NULL) + crypto->mdctx = EVP_MD_CTX_create(); + if (crypto->mdctx == NULL) + return krb5_enomem(context); + m = crypto->mdctx; + } else + m = EVP_MD_CTX_create(); + ksign_c.checksum.length = sizeof(ksign_c_data); ksign_c.checksum.data = ksign_c_data; - ret = _krb5_internal_hmac(context, c, signature, sizeof(signature), + ret = _krb5_internal_hmac(context, crypto, c, signature, sizeof(signature), 0, key, &ksign_c); - if (ret) { - EVP_MD_CTX_destroy(m); - return ret; - } + if (ret) + goto out; + ksign.key = &kb; kb.keyvalue = ksign_c.checksum; EVP_DigestInit_ex(m, EVP_md5(), NULL); @@ -99,12 +105,13 @@ _krb5_HMAC_MD5_checksum(krb5_context context, EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length); } EVP_DigestFinal_ex (m, tmp, NULL); - EVP_MD_CTX_destroy(m); - ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); - if (ret) - return ret; - return 0; + ret = _krb5_internal_hmac(context, crypto, c, tmp, sizeof(tmp), 0, &ksign, result); +out: + if (crypto == NULL) + EVP_MD_CTX_destroy(m); + + return ret; } struct _krb5_checksum_type _krb5_checksum_hmac_md5 = { @@ -153,7 +160,7 @@ ARCFOUR_subencrypt(krb5_context context, k1_c.checksum.length = sizeof(k1_c_data); k1_c.checksum.data = k1_c_data; - ret = _krb5_internal_hmac(context, c, t, sizeof(t), 0, key, &k1_c); + ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c); if (ret) krb5_abortx(context, "hmac failed"); @@ -168,7 +175,7 @@ ARCFOUR_subencrypt(krb5_context context, cksum.checksum.length = 16; cksum.checksum.data = data; - ret = _krb5_internal_hmac(context, c, cdata + 16, len - 16, 0, &ke, &cksum); + ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); if (ret) krb5_abortx(context, "hmac failed"); @@ -178,7 +185,7 @@ ARCFOUR_subencrypt(krb5_context context, k3_c.checksum.length = sizeof(k3_c_data); k3_c.checksum.data = k3_c_data; - ret = _krb5_internal_hmac(context, c, data, 16, 0, &ke, &k3_c); + ret = _krb5_internal_hmac(context, NULL, c, data, 16, 0, &ke, &k3_c); if (ret) krb5_abortx(context, "hmac failed"); @@ -225,7 +232,7 @@ ARCFOUR_subdecrypt(krb5_context context, k1_c.checksum.length = sizeof(k1_c_data); k1_c.checksum.data = k1_c_data; - ret = _krb5_internal_hmac(context, c, t, sizeof(t), 0, key, &k1_c); + ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c); if (ret) krb5_abortx(context, "hmac failed"); @@ -240,7 +247,7 @@ ARCFOUR_subdecrypt(krb5_context context, k3_c.checksum.length = sizeof(k3_c_data); k3_c.checksum.data = k3_c_data; - ret = _krb5_internal_hmac(context, c, cdata, 16, 0, &ke, &k3_c); + ret = _krb5_internal_hmac(context, NULL, c, cdata, 16, 0, &ke, &k3_c); if (ret) krb5_abortx(context, "hmac failed"); @@ -255,7 +262,7 @@ ARCFOUR_subdecrypt(krb5_context context, cksum.checksum.length = 16; cksum.checksum.data = cksum_data; - ret = _krb5_internal_hmac(context, c, cdata + 16, len - 16, 0, &ke, &cksum); + ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); if (ret) krb5_abortx(context, "hmac failed"); @@ -336,7 +343,7 @@ ARCFOUR_prf(krb5_context context, res.checksum.data = out->data; res.checksum.length = out->length; - ret = _krb5_internal_hmac(context, c, in->data, in->length, 0, &crypto->key, &res); + ret = _krb5_internal_hmac(context, crypto, c, in->data, in->length, 0, &crypto->key, &res); if (ret) krb5_data_free(out); return 0; diff --git a/lib/krb5/crypto-des-common.c b/lib/krb5/crypto-des-common.c index b6d765066..a8344ae5b 100644 --- a/lib/krb5/crypto-des-common.c +++ b/lib/krb5/crypto-des-common.c @@ -133,13 +133,15 @@ _krb5_des_verify(krb5_context context, static krb5_error_code RSA_MD5_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, int niov, Checksum *C) { - if (_krb5_evp_digest_iov(iov, niov, C->checksum.data, NULL, EVP_md5(), NULL) != 1) + if (_krb5_evp_digest_iov(crypto, iov, niov, C->checksum.data, + NULL, EVP_md5(), NULL) != 1) krb5_abortx(context, "md5 checksum failed"); return 0; diff --git a/lib/krb5/crypto-des.c b/lib/krb5/crypto-des.c index 152c01550..fbb7c347b 100644 --- a/lib/krb5/crypto-des.c +++ b/lib/krb5/crypto-des.c @@ -98,6 +98,7 @@ static struct _krb5_key_type keytype_des = { static krb5_error_code CRC32_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, @@ -124,19 +125,22 @@ CRC32_checksum(krb5_context context, static krb5_error_code RSA_MD4_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, int niov, Checksum *C) { - if (_krb5_evp_digest_iov(iov, niov, C->checksum.data, NULL, EVP_md4(), NULL) != 1) + if (_krb5_evp_digest_iov(crypto, iov, niov, C->checksum.data, + NULL, EVP_md4(), NULL) != 1) krb5_abortx(context, "md4 checksum failed"); return 0; } static krb5_error_code RSA_MD4_DES_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, @@ -148,6 +152,7 @@ RSA_MD4_DES_checksum(krb5_context context, static krb5_error_code RSA_MD4_DES_verify(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, @@ -159,6 +164,7 @@ RSA_MD4_DES_verify(krb5_context context, static krb5_error_code RSA_MD5_DES_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, @@ -170,6 +176,7 @@ RSA_MD5_DES_checksum(krb5_context context, static krb5_error_code RSA_MD5_DES_verify(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, diff --git a/lib/krb5/crypto-des3.c b/lib/krb5/crypto-des3.c index 98faed853..9b8853db9 100644 --- a/lib/krb5/crypto-des3.c +++ b/lib/krb5/crypto-des3.c @@ -73,7 +73,7 @@ DES3_prf(krb5_context context, iov[0].data = *in; iov[0].flags = KRB5_CRYPTO_TYPE_DATA; - ret = (*ct->checksum)(context, NULL, 0, iov, 1, &result); + ret = (*ct->checksum)(context, crypto, NULL, 0, iov, 1, &result); if (ret) { krb5_data_free(&result.checksum); return ret; @@ -142,6 +142,7 @@ static struct _krb5_key_type keytype_des3_derived = { #ifdef DES3_OLD_ENCTYPE static krb5_error_code RSA_MD5_DES3_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, @@ -153,6 +154,7 @@ RSA_MD5_DES3_checksum(krb5_context context, static krb5_error_code RSA_MD5_DES3_verify(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, diff --git a/lib/krb5/crypto-evp.c b/lib/krb5/crypto-evp.c index 387e5672f..594614910 100644 --- a/lib/krb5/crypto-evp.c +++ b/lib/krb5/crypto-evp.c @@ -57,7 +57,8 @@ _krb5_evp_cleanup(krb5_context context, struct _krb5_key_data *kd) } int -_krb5_evp_digest_iov(const struct krb5_crypto_iov *iov, +_krb5_evp_digest_iov(krb5_crypto crypto, + const struct krb5_crypto_iov *iov, int niov, void *hash, unsigned int *hsize, @@ -68,9 +69,14 @@ _krb5_evp_digest_iov(const struct krb5_crypto_iov *iov, int ret, i; krb5_data current = {0,0}; - ctx = EVP_MD_CTX_create(); - if (ctx == NULL) - return 0; + if (crypto != NULL) { + if (crypto->mdctx == NULL) + crypto->mdctx = EVP_MD_CTX_create(); + if (crypto->mdctx == NULL) + return 0; + ctx = crypto->mdctx; + } else + ctx = EVP_MD_CTX_create(); ret = EVP_DigestInit_ex(ctx, md, engine); if (ret != 1) @@ -100,7 +106,9 @@ _krb5_evp_digest_iov(const struct krb5_crypto_iov *iov, ret = EVP_DigestFinal_ex(ctx, hash, hsize); out: - EVP_MD_CTX_destroy(ctx); + if (crypto == NULL) + EVP_MD_CTX_destroy(ctx); + return ret; } diff --git a/lib/krb5/crypto-null.c b/lib/krb5/crypto-null.c index 8aca50239..4e5934282 100644 --- a/lib/krb5/crypto-null.c +++ b/lib/krb5/crypto-null.c @@ -53,6 +53,7 @@ static struct _krb5_key_type keytype_null = { static krb5_error_code NONE_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, diff --git a/lib/krb5/crypto.c b/lib/krb5/crypto.c index 1ed9fac83..4df2a12a4 100644 --- a/lib/krb5/crypto.c +++ b/lib/krb5/crypto.c @@ -168,14 +168,17 @@ _key_schedule(krb5_context context, static krb5_error_code SHA1_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, int niov, Checksum *C) { - if (_krb5_evp_digest_iov(iov, niov, C->checksum.data, - NULL, EVP_sha1(), NULL) != 1) + if (_krb5_evp_digest_iov(crypto, + iov, niov, + C->checksum.data, NULL, + EVP_sha1(), NULL) != 1) krb5_abortx(context, "sha1 checksum failed"); return 0; @@ -184,6 +187,7 @@ SHA1_checksum(krb5_context context, /* HMAC according to RFC2104 */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_internal_hmac_iov(krb5_context context, + krb5_crypto crypto, struct _krb5_checksum_type *cm, unsigned usage, const struct krb5_crypto_iov *iov, @@ -221,6 +225,7 @@ _krb5_internal_hmac_iov(krb5_context context, working[0].data = keyblock->key->keyvalue; working[0].flags = KRB5_CRYPTO_TYPE_DATA; (*cm->checksum)(context, + crypto, keyblock, usage, working, @@ -243,14 +248,14 @@ _krb5_internal_hmac_iov(krb5_context context, for (i = 0; i < niov; i++) working[i + 1] = iov[i]; - (*cm->checksum)(context, keyblock, usage, working, niov + 1, result); + (*cm->checksum)(context, crypto, keyblock, usage, working, niov + 1, result); memcpy(opad + cm->blocksize, result->checksum.data, result->checksum.length); working[0].data.data = opad; working[0].data.length = cm->blocksize + cm->checksumsize; working[0].flags = KRB5_CRYPTO_TYPE_DATA; - (*cm->checksum)(context, keyblock, usage, working, 1, result); + (*cm->checksum)(context, crypto, keyblock, usage, working, 1, result); memset(ipad, 0, cm->blocksize); free(ipad); memset(opad, 0, cm->blocksize + cm->checksumsize); @@ -262,6 +267,7 @@ _krb5_internal_hmac_iov(krb5_context context, KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_internal_hmac(krb5_context context, + krb5_crypto crypto, struct _krb5_checksum_type *cm, const void *data, size_t len, @@ -274,7 +280,7 @@ _krb5_internal_hmac(krb5_context context, iov[0].data.data = (void *) data; iov[0].data.length = len; iov[0].flags = KRB5_CRYPTO_TYPE_DATA; - return _krb5_internal_hmac_iov(context, cm, usage, iov, 1, + return _krb5_internal_hmac_iov(context, crypto, cm, usage, iov, 1, keyblock, result); } @@ -302,7 +308,7 @@ krb5_hmac(krb5_context context, kd.key = key; kd.schedule = NULL; - ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result); + ret = _krb5_internal_hmac(context, NULL, c, data, len, usage, &kd, result); if (kd.schedule) krb5_free_data(context, kd.schedule); @@ -312,6 +318,7 @@ krb5_hmac(krb5_context context, krb5_error_code _krb5_SP_HMAC_SHA1_checksum(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, @@ -425,7 +432,7 @@ create_checksum_iov(krb5_context context, result->cksumtype = ct->type; - return (*ct->checksum)(context, dkey, usage, iov, niov, result); + return (*ct->checksum)(context, crypto, dkey, usage, iov, niov, result); } static krb5_error_code @@ -539,7 +546,7 @@ verify_checksum_iov(krb5_context context, */ if(ct->verify) { - ret = (*ct->verify)(context, dkey, usage, iov, niov, cksum); + ret = (*ct->verify)(context, crypto, dkey, usage, iov, niov, cksum); if (ret) krb5_set_error_message(context, ret, N_("Decrypt integrity check failed for checksum " @@ -552,7 +559,7 @@ verify_checksum_iov(krb5_context context, if (ret) return ret; - ret = (*ct->checksum)(context, dkey, usage, iov, niov, &c); + ret = (*ct->checksum)(context, crypto, dkey, usage, iov, niov, &c); if (ret) { krb5_data_free(&c.checksum); return ret; @@ -2515,6 +2522,10 @@ krb5_crypto_destroy(krb5_context context, free_key_usage(context, &crypto->key_usage[i], crypto->et); free(crypto->key_usage); _krb5_free_key_data(context, &crypto->key, crypto->et); + + if (crypto->mdctx) + EVP_MD_CTX_destroy(crypto->mdctx); + free (crypto); return 0; } diff --git a/lib/krb5/crypto.h b/lib/krb5/crypto.h index 1480e5ea4..908443b3a 100644 --- a/lib/krb5/crypto.h +++ b/lib/krb5/crypto.h @@ -42,13 +42,6 @@ struct _krb5_key_data { struct _krb5_key_usage; -struct krb5_crypto_data { - struct _krb5_encryption_type *et; - struct _krb5_key_data key; - int num_key_usage; - struct _krb5_key_usage *key_usage; -}; - #define CRYPTO_ETYPE(C) ((C)->et->type) /* bits for `flags' below */ @@ -97,11 +90,13 @@ struct _krb5_checksum_type { size_t checksumsize; unsigned flags; krb5_error_code (*checksum)(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, int niov, Checksum *csum); krb5_error_code (*verify)(krb5_context context, + krb5_crypto crypto, struct _krb5_key_data *key, unsigned usage, const struct krb5_crypto_iov *iov, int niov, @@ -200,9 +195,18 @@ _krb5_crypto_iov_should_sign(const struct krb5_crypto_iov *iov) struct _krb5_evp_schedule { /* * Normally we'd say EVP_CIPHER_CTX here, but! this header gets - * included in lib/krb5/pkinit-ec.ck + * included in lib/krb5/pkinit-ec.c */ EVP_CIPHER_CTX ectx; EVP_CIPHER_CTX dctx; }; + +struct krb5_crypto_data { + struct _krb5_encryption_type *et; + struct _krb5_key_data key; + EVP_MD_CTX *mdctx; + int num_key_usage; + struct _krb5_key_usage *key_usage; +}; + #endif diff --git a/lib/krb5/pac.c b/lib/krb5/pac.c index 1788b59bd..853a84b70 100644 --- a/lib/krb5/pac.c +++ b/lib/krb5/pac.c @@ -108,7 +108,8 @@ HMAC_MD5_any_checksum(krb5_context context, iov.data.length = len; iov.flags = KRB5_CRYPTO_TYPE_DATA; - ret = _krb5_HMAC_MD5_checksum(context, &local_key, usage, &iov, 1, result); + ret = _krb5_HMAC_MD5_checksum(context, NULL, &local_key, usage, &iov, 1, + result); if (ret) krb5_data_free(&result->checksum); diff --git a/lib/krb5/test_rfc3961.c b/lib/krb5/test_rfc3961.c index 3f85e0333..f1255948f 100644 --- a/lib/krb5/test_rfc3961.c +++ b/lib/krb5/test_rfc3961.c @@ -85,6 +85,7 @@ time_hmac_evp(krb5_context context, size_t size, int iterations) struct _krb5_key_data kd; krb5_error_code ret; krb5_keyblock key; + krb5_crypto crypto; char sha1_data[20]; Checksum result; char *buf; @@ -110,9 +111,14 @@ time_hmac_evp(krb5_context context, size_t size, int iterations) kd.key = &key; kd.schedule = NULL; + ret = krb5_crypto_init(context, &key, ETYPE_AES128_CTS_HMAC_SHA1_96, + &crypto); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_init"); + for (i = 0; i < iterations; i++) { - ret = _krb5_SP_HMAC_SHA1_checksum(context, &kd, 0, - &iov, 1, &result); + ret = _krb5_SP_HMAC_SHA1_checksum(context, crypto, &kd, 0, + &iov, 1, &result); if (ret) krb5_err(context, 1, ret, "hmac: %d", i); } @@ -413,7 +419,7 @@ test_rfc2202(krb5_context context) iov.flags = KRB5_CRYPTO_TYPE_DATA; kd.key = &keyblock; kd.schedule = NULL; - code = _krb5_SP_HMAC_SHA1_checksum(context, &kd, 0, + code = _krb5_SP_HMAC_SHA1_checksum(context, NULL, &kd, 0, &iov, 1, &result); if (code != 0)