diff --git a/lib/krb5/crypto-aes-sha1.c b/lib/krb5/crypto-aes-sha1.c index 30df0ee86b..d07ad0e8b1 100644 --- a/lib/krb5/crypto-aes-sha1.c +++ b/lib/krb5/crypto-aes-sha1.c @@ -92,6 +92,7 @@ AES_SHA1_PRF(krb5_context context, krb5_data *out) { struct _krb5_checksum_type *ct = crypto->et->checksum; + struct krb5_crypto_iov iov[1]; krb5_error_code ret; Checksum result; krb5_keyblock *derived; @@ -103,7 +104,9 @@ AES_SHA1_PRF(krb5_context context, return ret; } - ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); + iov[0].data = *in; + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + ret = (*ct->checksum)(context, 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 4630ce0715..c7d8dc10dc 100644 --- a/lib/krb5/crypto-aes-sha2.c +++ b/lib/krb5/crypto-aes-sha2.c @@ -59,9 +59,9 @@ _krb5_aes_sha2_md_for_enctype(krb5_context context, static krb5_error_code SP_HMAC_SHA2_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, - unsigned usage, + unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *result) { krb5_error_code ret; @@ -73,8 +73,9 @@ SP_HMAC_SHA2_checksum(krb5_context context, if (ret) return ret; - HMAC(md, key->key->keyvalue.data, key->key->keyvalue.length, - data, len, hmac, &hmaclen); + ret = _krb5_evp_hmac_iov(context, key, iov, niov, hmac, &hmaclen, md, NULL); + if (ret) + return ret; heim_assert(result->checksum.length <= hmaclen, "SHA2 internal error"); diff --git a/lib/krb5/crypto-arcfour.c b/lib/krb5/crypto-arcfour.c index c491561c69..dfc5d2f363 100644 --- a/lib/krb5/crypto-arcfour.c +++ b/lib/krb5/crypto-arcfour.c @@ -58,9 +58,9 @@ static struct _krb5_key_type keytype_arcfour = { krb5_error_code _krb5_HMAC_MD5_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *result) { EVP_MD_CTX *m; @@ -73,6 +73,7 @@ _krb5_HMAC_MD5_checksum(krb5_context context, unsigned char tmp[16]; unsigned char ksign_c_data[16]; krb5_error_code ret; + int i; m = EVP_MD_CTX_create(); if (m == NULL) @@ -93,7 +94,10 @@ _krb5_HMAC_MD5_checksum(krb5_context context, t[2] = (usage >> 16) & 0xFF; t[3] = (usage >> 24) & 0xFF; EVP_DigestUpdate(m, t, 4); - EVP_DigestUpdate(m, data, len); + for (i = 0; i < niov; i++) { + if (_krb5_crypto_iov_should_sign(&iov[i])) + EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length); + } EVP_DigestFinal_ex (m, tmp, NULL); EVP_MD_CTX_destroy(m); diff --git a/lib/krb5/crypto-des-common.c b/lib/krb5/crypto-des-common.c index 95f6389d1e..c85bd24335 100644 --- a/lib/krb5/crypto-des-common.c +++ b/lib/krb5/crypto-des-common.c @@ -57,13 +57,14 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_des_checksum(krb5_context context, const EVP_MD *evp_md, struct _krb5_key_data *key, - const void *data, - size_t len, + const struct krb5_crypto_iov *iov, + int niov, Checksum *cksum) { struct _krb5_evp_schedule *ctx = key->schedule->data; EVP_MD_CTX *m; DES_cblock ivec; + int i; unsigned char *p = cksum->checksum.data; krb5_generate_random_block(p, 8); @@ -74,7 +75,10 @@ _krb5_des_checksum(krb5_context context, EVP_DigestInit_ex(m, evp_md, NULL); EVP_DigestUpdate(m, p, 8); - EVP_DigestUpdate(m, data, len); + for (i = 0; i < niov; i++) { + if (_krb5_crypto_iov_should_sign(&iov[i])) + EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length); + } EVP_DigestFinal_ex (m, p + 8, NULL); EVP_MD_CTX_destroy(m); memset_s(&ivec, sizeof(ivec), 0, sizeof(ivec)); @@ -126,13 +130,14 @@ _krb5_des_verify(krb5_context context, static krb5_error_code RSA_MD5_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *C) { - if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1) + if (_krb5_evp_digest_iov(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 8ea145b56d..017ce106fc 100644 --- a/lib/krb5/crypto-des.c +++ b/lib/krb5/crypto-des.c @@ -99,15 +99,22 @@ static struct _krb5_key_type keytype_des = { static krb5_error_code CRC32_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *C) { - uint32_t crc; + uint32_t crc = 0; unsigned char *r = C->checksum.data; + int i; + _krb5_crc_init_table (); - crc = _krb5_crc_update (data, len, 0); + + for (i = 0; i < niov; i++) { + if (_krb5_crypto_iov_should_sign(&iov[i])) + crc = _krb5_crc_update(iov[i].data.data, iov[i].data.length, crc); + } + r[0] = crc & 0xff; r[1] = (crc >> 8) & 0xff; r[2] = (crc >> 16) & 0xff; @@ -118,12 +125,12 @@ CRC32_checksum(krb5_context context, static krb5_error_code RSA_MD4_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *C) { - if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1) + if (_krb5_evp_digest_iov(iov, niov, C->checksum.data, NULL, EVP_md4(), NULL) != 1) krb5_abortx(context, "md4 checksum failed"); return 0; } @@ -131,12 +138,12 @@ RSA_MD4_checksum(krb5_context context, static krb5_error_code RSA_MD4_DES_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *cksum) { - return _krb5_des_checksum(context, EVP_md4(), key, data, len, cksum); + return _krb5_des_checksum(context, EVP_md4(), key, iov, niov, cksum); } static krb5_error_code @@ -153,12 +160,12 @@ RSA_MD4_DES_verify(krb5_context context, static krb5_error_code RSA_MD5_DES_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *C) { - return _krb5_des_checksum(context, EVP_md5(), key, data, len, C); + return _krb5_des_checksum(context, EVP_md5(), key, iov, niov, C); } static krb5_error_code diff --git a/lib/krb5/crypto-des3.c b/lib/krb5/crypto-des3.c index ed3e7c960e..36174ff7fb 100644 --- a/lib/krb5/crypto-des3.c +++ b/lib/krb5/crypto-des3.c @@ -59,6 +59,7 @@ DES3_prf(krb5_context context, krb5_data *out) { struct _krb5_checksum_type *ct = crypto->et->checksum; + struct krb5_crypto_iov iov[1]; krb5_error_code ret; Checksum result; krb5_keyblock *derived; @@ -70,7 +71,9 @@ DES3_prf(krb5_context context, return ret; } - ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); + iov[0].data = *in; + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + ret = (*ct->checksum)(context, NULL, 0, iov, 1, &result); if (ret) { krb5_data_free(&result.checksum); return ret; @@ -140,12 +143,12 @@ static struct _krb5_key_type keytype_des3_derived = { static krb5_error_code RSA_MD5_DES3_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *C) { - return _krb5_des_checksum(context, EVP_md5(), key, data, len, C); + return _krb5_des_checksum(context, EVP_md5(), key, iov, niov, C); } static krb5_error_code diff --git a/lib/krb5/crypto-null.c b/lib/krb5/crypto-null.c index 96b7799470..8aca50239d 100644 --- a/lib/krb5/crypto-null.c +++ b/lib/krb5/crypto-null.c @@ -54,9 +54,9 @@ static struct _krb5_key_type keytype_null = { static krb5_error_code NONE_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *C) { return 0; diff --git a/lib/krb5/crypto.c b/lib/krb5/crypto.c index 8afcc0eb2c..04ace41511 100644 --- a/lib/krb5/crypto.c +++ b/lib/krb5/crypto.c @@ -166,48 +166,62 @@ _key_schedule(krb5_context context, static krb5_error_code SHA1_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *C) { - if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1) + if (_krb5_evp_digest_iov(iov, niov, C->checksum.data, + NULL, EVP_sha1(), NULL) != 1) krb5_abortx(context, "sha1 checksum failed"); + return 0; } /* HMAC according to RFC2104 */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -_krb5_internal_hmac(krb5_context context, - struct _krb5_checksum_type *cm, - const void *data, - size_t len, - unsigned usage, - struct _krb5_key_data *keyblock, - Checksum *result) +_krb5_internal_hmac_iov(krb5_context context, + struct _krb5_checksum_type *cm, + unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, + struct _krb5_key_data *keyblock, + Checksum *result) { unsigned char *ipad, *opad; unsigned char *key; + struct krb5_crypto_iov *working; size_t key_len; size_t i; - ipad = malloc(cm->blocksize + len); + ipad = malloc(cm->blocksize); if (ipad == NULL) return ENOMEM; + opad = malloc(cm->blocksize + cm->checksumsize); if (opad == NULL) { free(ipad); return ENOMEM; } + + working = calloc(niov + 1, sizeof(struct krb5_crypto_iov)); + if (working == NULL) { + free(ipad); + free(opad); + return ENOMEM; + } + memset(ipad, 0x36, cm->blocksize); memset(opad, 0x5c, cm->blocksize); if(keyblock->key->keyvalue.length > cm->blocksize){ + working[0].data = keyblock->key->keyvalue; + working[0].flags = KRB5_CRYPTO_TYPE_DATA; (*cm->checksum)(context, keyblock, - keyblock->key->keyvalue.data, - keyblock->key->keyvalue.length, usage, + working, + 1, result); key = result->checksum.data; key_len = result->checksum.length; @@ -219,21 +233,48 @@ _krb5_internal_hmac(krb5_context context, ipad[i] ^= key[i]; opad[i] ^= key[i]; } - memcpy(ipad + cm->blocksize, data, len); - (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, - usage, result); + + working[0].data.data = ipad; + working[0].data.length = cm->blocksize; + working[0].flags = KRB5_CRYPTO_TYPE_DATA; + for (i = 0; i < niov; i++) + working[i + 1] = iov[i]; + + (*cm->checksum)(context, keyblock, usage, working, niov + 1, result); memcpy(opad + cm->blocksize, result->checksum.data, result->checksum.length); - (*cm->checksum)(context, keyblock, opad, - cm->blocksize + cm->checksumsize, usage, result); - memset(ipad, 0, cm->blocksize + len); + + 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); + memset(ipad, 0, cm->blocksize); free(ipad); memset(opad, 0, cm->blocksize + cm->checksumsize); free(opad); + free(working); return 0; } +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_internal_hmac(krb5_context context, + struct _krb5_checksum_type *cm, + const void *data, + size_t len, + unsigned usage, + struct _krb5_key_data *keyblock, + Checksum *result) +{ + struct krb5_crypto_iov iov[1]; + + 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, + keyblock, result); +} + KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_hmac(krb5_context context, krb5_cksumtype cktype, @@ -268,9 +309,9 @@ krb5_hmac(krb5_context context, krb5_error_code _krb5_SP_HMAC_SHA1_checksum(krb5_context context, struct _krb5_key_data *key, - const void *data, - size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, Checksum *result) { struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1); @@ -281,7 +322,7 @@ _krb5_SP_HMAC_SHA1_checksum(krb5_context context, res.checksum.data = sha1_data; res.checksum.length = sizeof(sha1_data); - ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res); + ret = _krb5_internal_hmac_iov(context, c, usage, iov, niov, key, &res); if (ret) krb5_abortx(context, "hmac failed"); memcpy(result->checksum.data, res.checksum.data, result->checksum.length); @@ -367,6 +408,7 @@ create_checksum (krb5_context context, { krb5_error_code ret; struct _krb5_key_data *dkey; + struct krb5_crypto_iov iov[1]; if (ct->flags & F_DISABLED) { krb5_clear_error_message (context); @@ -382,7 +424,11 @@ create_checksum (krb5_context context, ret = krb5_data_alloc(&result->checksum, ct->checksumsize); if (ret) return (ret); - return (*ct->checksum)(context, dkey, data, len, usage, result); + + iov[0].data.data = data; + iov[0].data.length = len; + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + return (*ct->checksum)(context, dkey, usage, iov, 1, result); } static int @@ -442,6 +488,7 @@ verify_checksum(krb5_context context, struct _krb5_key_data *dkey; Checksum c; struct _krb5_checksum_type *ct; + struct krb5_crypto_iov iov[1]; ct = _krb5_find_checksum(cksum->cksumtype); if (ct == NULL || (ct->flags & F_DISABLED)) { @@ -472,6 +519,10 @@ verify_checksum(krb5_context context, * calling ->checksum and then compare result. */ + iov[0].data.data = data; + iov[0].data.length = len; + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + if(ct->verify) { ret = (*ct->verify)(context, dkey, data, len, usage, cksum); if (ret) @@ -486,7 +537,7 @@ verify_checksum(krb5_context context, if (ret) return ret; - ret = (*ct->checksum)(context, dkey, data, len, usage, &c); + ret = (*ct->checksum)(context, dkey, usage, iov, 1, &c); if (ret) { krb5_data_free(&c.checksum); return ret; diff --git a/lib/krb5/crypto.h b/lib/krb5/crypto.h index 62f48395a1..f1ed1a5a33 100644 --- a/lib/krb5/crypto.h +++ b/lib/krb5/crypto.h @@ -98,8 +98,8 @@ struct _krb5_checksum_type { unsigned flags; krb5_error_code (*checksum)(krb5_context context, struct _krb5_key_data *key, - const void *buf, size_t len, unsigned usage, + const struct krb5_crypto_iov *iov, int niov, Checksum *csum); krb5_error_code (*verify)(krb5_context context, struct _krb5_key_data *key, diff --git a/lib/krb5/pac.c b/lib/krb5/pac.c index 8ad510998b..1788b59bd5 100644 --- a/lib/krb5/pac.c +++ b/lib/krb5/pac.c @@ -88,6 +88,7 @@ HMAC_MD5_any_checksum(krb5_context context, Checksum *result) { struct _krb5_key_data local_key; + struct krb5_crypto_iov iov; krb5_error_code ret; memset(&local_key, 0, sizeof(local_key)); @@ -103,7 +104,11 @@ HMAC_MD5_any_checksum(krb5_context context, } result->cksumtype = CKSUMTYPE_HMAC_MD5; - ret = _krb5_HMAC_MD5_checksum(context, &local_key, data, len, usage, result); + iov.data.data = (void *)data; + iov.data.length = len; + iov.flags = KRB5_CRYPTO_TYPE_DATA; + + ret = _krb5_HMAC_MD5_checksum(context, &local_key, usage, &iov, 1, result); if (ret) krb5_data_free(&result->checksum);