From 9ab3afbf9569254cf67bf7363cb9a50f549a5cdf Mon Sep 17 00:00:00 2001 From: Sam Hartman Date: Thu, 4 Dec 2008 15:48:08 +0000 Subject: [PATCH] Merge r21120 from mskrb-integ Refactor code such that an AEAD provider does not need to implement the older, non-IOV SPIs. Instead, the older APIs will implement their behaviour on top of the AEAD SPIs, using the wrapper functions in aead.c. ticket: 6274 Status: open git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21278 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/crypto/aead.c | 145 ++++++++++++++++++++++++++++++-- src/lib/crypto/aead.h | 40 +++++++-- src/lib/crypto/crypto_length.c | 26 +----- src/lib/crypto/decrypt.c | 11 +++ src/lib/crypto/encrypt.c | 11 +++ src/lib/crypto/encrypt_length.c | 16 +++- 6 files changed, 210 insertions(+), 39 deletions(-) diff --git a/src/lib/crypto/aead.c b/src/lib/crypto/aead.c index 6d042e60d..547aee861 100644 --- a/src/lib/crypto/aead.c +++ b/src/lib/crypto/aead.c @@ -30,7 +30,7 @@ #include "dk.h" #include "aead.h" -krb5_crypto_iov * KRB5_CALLCONV +krb5_crypto_iov * krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data, krb5_cryptotype type) @@ -91,7 +91,7 @@ make_unkeyed_checksum_iov(const struct krb5_hash_provider *hash_provider, return ret; } -krb5_error_code KRB5_CALLCONV +krb5_error_code krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum_type, const krb5_keyblock *key, krb5_keyusage usage, @@ -152,7 +152,7 @@ cleanup: return ret; } -const struct krb5_cksumtypes * KRB5_CALLCONV +const struct krb5_cksumtypes * krb5int_c_find_checksum_type(krb5_cksumtype cksumtype) { size_t i; @@ -243,7 +243,7 @@ pad_to_boundary_p(const krb5_crypto_iov *data, return 1; } -krb5_boolean KRB5_CALLCONV +krb5_boolean krb5int_c_iov_get_block(unsigned char *block, size_t block_size, const krb5_crypto_iov *data, @@ -296,7 +296,7 @@ krb5int_c_iov_get_block(unsigned char *block, return (iov_state->iov_pos < num_data); } -krb5_boolean KRB5_CALLCONV +krb5_boolean krb5int_c_iov_put_block(const krb5_crypto_iov *data, size_t num_data, unsigned char *block, @@ -346,7 +346,7 @@ krb5int_c_iov_put_block(const krb5_crypto_iov *data, return (iov_state->iov_pos < num_data); } -krb5_error_code KRB5_CALLCONV +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, @@ -429,3 +429,136 @@ krb5int_c_iov_decrypt_stream(const struct krb5_aead_provider *aead, return ret; } +krb5_error_code +krb5int_padding_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t data_length, + unsigned int *pad_length) +{ + unsigned int padding; + krb5_error_code ret; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_PADDING, &padding); + if (ret != 0) + return ret; + + if (padding == 0 || (data_length % padding) == 0) + *pad_length = 0; + else + *pad_length = padding - (data_length % padding); + + return 0; +} + +krb5_error_code +krb5int_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, + const krb5_data *ivec, const krb5_data *input, + krb5_data *output) +{ + krb5_crypto_iov iov[4]; + krb5_error_code ret; + size_t header_len = 0; + size_t padding_len = 0; + size_t trailer_len = 0; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_HEADER, + &header_len); + if (ret != 0) + return ret; + + ret = krb5int_padding_length(aead, enc, hash, input->length, &padding_len); + if (ret != 0) + return ret; + + ret = aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, + &trailer_len); + if (ret != 0) + return ret; + + if (output->length < header_len + input->length + padding_len + trailer_len) + return KRB5_BAD_MSIZE; + + iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; + iov[0].data.data = output->data; + iov[0].data.length = header_len; + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data.data = iov[0].data.data + iov[0].data.length; + iov[1].data.length = input->length; + memcpy(iov[1].data.data, input->data, input->length); + + iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[2].data.data = iov[1].data.data + iov[1].data.length; + iov[2].data.length = padding_len; + + iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[3].data.data = iov[2].data.data + iov[2].data.length; + iov[3].data.length = trailer_len; + + ret = aead->encrypt_iov(aead, enc, hash, key, + usage, ivec, + iov, sizeof(iov)/sizeof(iov[0])); + + if (ret != 0) + zap(iov[1].data.data, iov[1].data.length); + + output->length = iov[0].data.length + iov[1].data.length + + iov[2].data.length + iov[3].data.length; + + return ret; +} + +krb5_error_code +krb5int_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, + const krb5_data *ivec, const krb5_data *input, + krb5_data *output) +{ + krb5_crypto_iov iov[2]; + krb5_error_code ret; + + iov[0].flags = KRB5_CRYPTO_TYPE_STREAM; + iov[0].data = *input; + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data.data = NULL; + iov[1].data.length = 0; + + ret = krb5int_c_iov_decrypt_stream(aead, enc, hash, key, + usage, ivec, + iov, sizeof(iov)/sizeof(iov[0])); + if (ret != 0) + return ret; + + if (output->length < iov[1].data.length) + return KRB5_BAD_MSIZE; + + memcpy(output->data, iov[1].data.data, iov[1].data.length); + output->length = iov[1].data.length; + + return ret; +} + +void +krb5int_encrypt_length_aead_compat(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t inputlen, size_t *length) +{ + size_t header_len = 0; + size_t padding_len = 0; + size_t trailer_len = 0; + + aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_HEADER, &header_len); + krb5int_padding_length(aead, enc, hash, inputlen, &padding_len); + aead->crypto_length(aead, enc, hash, KRB5_CRYPTO_TYPE_TRAILER, &trailer_len); + + *length = header_len + inputlen + padding_len + trailer_len; +} + diff --git a/src/lib/crypto/aead.h b/src/lib/crypto/aead.h index f183d1a05..057d6a7d4 100644 --- a/src/lib/crypto/aead.h +++ b/src/lib/crypto/aead.h @@ -28,12 +28,12 @@ /* AEAD helpers */ -krb5_crypto_iov * KRB5_CALLCONV +krb5_crypto_iov * krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data, krb5_cryptotype type); -krb5_error_code KRB5_CALLCONV +krb5_error_code krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum, const krb5_keyblock *key, krb5_keyusage usage, @@ -41,7 +41,7 @@ krb5int_c_make_checksum_iov(const struct krb5_cksumtypes *cksum, size_t num_data, krb5_data *cksum_data); -const struct krb5_cksumtypes * KRB5_CALLCONV +const struct krb5_cksumtypes * krb5int_c_find_checksum_type(krb5_cksumtype cksumtype); #define ENCRYPT_CONF_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_HEADER) @@ -68,21 +68,21 @@ struct iov_block_state { (_state)->include_sign_only = \ (_state)->pad_to_boundary = 0) -krb5_boolean KRB5_CALLCONV +krb5_boolean krb5int_c_iov_get_block(unsigned char *block, size_t block_size, const krb5_crypto_iov *data, size_t num_data, struct iov_block_state *iov_state); -krb5_boolean KRB5_CALLCONV +krb5_boolean krb5int_c_iov_put_block(const krb5_crypto_iov *data, size_t num_data, unsigned char *block, size_t block_size, struct iov_block_state *iov_state); -krb5_error_code KRB5_CALLCONV +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, @@ -92,3 +92,31 @@ krb5int_c_iov_decrypt_stream(const struct krb5_aead_provider *aead, krb5_crypto_iov *data, size_t num_data); +krb5_error_code +krb5int_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, + const krb5_data *ivec, const krb5_data *input, + krb5_data *output); + +krb5_error_code +krb5int_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, + const krb5_data *ivec, const krb5_data *input, + krb5_data *output); + +void +krb5int_encrypt_length_aead_compat(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t inputlen, size_t *length); + +krb5_error_code +krb5int_padding_length(const struct krb5_aead_provider *aead, + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t data_length, + unsigned int *pad_length); diff --git a/src/lib/crypto/crypto_length.c b/src/lib/crypto/crypto_length.c index 4a64b90f9..eb19b5990 100644 --- a/src/lib/crypto/crypto_length.c +++ b/src/lib/crypto/crypto_length.c @@ -73,28 +73,6 @@ krb5_c_crypto_length(krb5_context context, return ret; } -static krb5_error_code -k5_padding_length(const struct krb5_keytypes *ktp, - size_t data_length, - unsigned int *pad_length) -{ - unsigned int padding; - krb5_error_code ret; - - ret = ktp->aead->crypto_length(ktp->aead, ktp->enc, ktp->hash, - KRB5_CRYPTO_TYPE_PADDING, &padding); - if (ret != 0) - return ret; - - if (padding == 0 || (data_length % padding) == 0) - *pad_length = 0; - else - *pad_length = padding - (data_length % padding); - - return 0; -} - - krb5_error_code KRB5_CALLCONV krb5_c_padding_length(krb5_context context, krb5_enctype enctype, @@ -115,7 +93,7 @@ krb5_c_padding_length(krb5_context context, return KRB5_BAD_ENCTYPE; } - return k5_padding_length(ktp, data_length, pad_length); + return krb5int_padding_length(ktp->aead, ktp->enc, ktp->hash, data_length, pad_length); } krb5_error_code KRB5_CALLCONV @@ -177,7 +155,7 @@ krb5_c_crypto_length_iov(krb5_context context, if (ret != 0) return ret; - ret = k5_padding_length(ktp, data_length, &pad_length); + ret = krb5int_padding_length(ktp->aead, ktp->enc, ktp->hash, data_length, &pad_length); if (ret != 0) return ret; diff --git a/src/lib/crypto/decrypt.c b/src/lib/crypto/decrypt.c index 96861bda1..3c33c83c1 100644 --- a/src/lib/crypto/decrypt.c +++ b/src/lib/crypto/decrypt.c @@ -26,6 +26,7 @@ #include "k5-int.h" #include "etypes.h" +#include "aead.h" krb5_error_code KRB5_CALLCONV krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, @@ -50,6 +51,16 @@ krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, (krb5_enctypes_list[i].etype != input->enctype)) return(KRB5_BAD_ENCTYPE); + if (krb5_enctypes_list[i].decrypt == NULL) { + assert(krb5_enctypes_list[i].aead != NULL); + + return krb5int_decrypt_aead_compat(krb5_enctypes_list[i].aead, + krb5_enctypes_list[i].enc, + krb5_enctypes_list[i].hash, + key, usage, ivec, + &input->ciphertext, output); + } + return((*(krb5_enctypes_list[i].decrypt)) (krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash, key, usage, ivec, &input->ciphertext, output)); diff --git a/src/lib/crypto/encrypt.c b/src/lib/crypto/encrypt.c index c215dc429..414736675 100644 --- a/src/lib/crypto/encrypt.c +++ b/src/lib/crypto/encrypt.c @@ -26,6 +26,7 @@ #include "k5-int.h" #include "etypes.h" +#include "aead.h" krb5_error_code KRB5_CALLCONV krb5_c_encrypt(krb5_context context, const krb5_keyblock *key, @@ -46,6 +47,16 @@ krb5_c_encrypt(krb5_context context, const krb5_keyblock *key, output->kvno = 0; output->enctype = key->enctype; + if (krb5_enctypes_list[i].encrypt == NULL) { + assert(krb5_enctypes_list[i].aead != NULL); + + return krb5int_encrypt_aead_compat(krb5_enctypes_list[i].aead, + krb5_enctypes_list[i].enc, + krb5_enctypes_list[i].hash, + key, usage, ivec, + input, &output->ciphertext); + } + return((*(krb5_enctypes_list[i].encrypt)) (krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash, key, usage, ivec, input, &output->ciphertext)); diff --git a/src/lib/crypto/encrypt_length.c b/src/lib/crypto/encrypt_length.c index 71c25e735..fca1da248 100644 --- a/src/lib/crypto/encrypt_length.c +++ b/src/lib/crypto/encrypt_length.c @@ -26,6 +26,7 @@ #include "k5-int.h" #include "etypes.h" +#include "aead.h" krb5_error_code KRB5_CALLCONV krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype, @@ -41,9 +42,18 @@ krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype, if (i == krb5_enctypes_length) return(KRB5_BAD_ENCTYPE); - (*(krb5_enctypes_list[i].encrypt_len)) - (krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash, - inputlen, length); + if (krb5_enctypes_list[i].encrypt_len == NULL) { + assert(krb5_enctypes_list[i].aead != NULL); + + krb5int_encrypt_length_aead_compat(krb5_enctypes_list[i].aead, + krb5_enctypes_list[i].enc, + krb5_enctypes_list[i].hash, + inputlen, length); + } else { + (*(krb5_enctypes_list[i].encrypt_len)) + (krb5_enctypes_list[i].enc, krb5_enctypes_list[i].hash, + inputlen, length); + } return(0); } -- 2.26.2