From 52ae4d17e90b69577b845f388621c2f7011056cc Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sat, 28 Nov 2009 23:10:31 +0000 Subject: [PATCH] Create functional internal interfaces to allow GSSAPI to perform arcfour encryption of GSS tokens. This factors out derivation of the usage and encryption keys, and removes the need for the provider structures to be visible to all of krb5 via k5-int.h. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23378 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/k5-int.h | 40 +++--- src/lib/crypto/krb/arcfour/arcfour.c | 48 +++++++- src/lib/crypto/krb/arcfour/arcfour_aead.c | 46 +++++++ src/lib/crypto/krb/prf/des_prf.c | 2 +- src/lib/crypto/libk5crypto.exports | 3 +- src/lib/gssapi/krb5/gssapiP_krb5.h | 4 +- src/lib/gssapi/krb5/util_crypt.c | 142 +++------------------- src/lib/krb5/os/accessor.c | 5 +- 8 files changed, 143 insertions(+), 147 deletions(-) diff --git a/src/include/k5-int.h b/src/include/k5-int.h index ad7f53994..43d9d21fe 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -752,6 +752,18 @@ krb5int_hmac_iov_keyblock(const struct krb5_hash_provider *hash, krb5_error_code krb5int_pbkdf2_hmac_sha1(const krb5_data *, unsigned long, const krb5_data *, const krb5_data *); +/* These crypto functions are used by GSSAPI via the accessor. */ + +krb5_error_code +krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage, + const krb5_data *kd_data, const krb5_data *input, + krb5_data *output); + +krb5_error_code +krb5int_arcfour_gsscrypt_iov(const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *kd_data, + krb5_crypto_iov *data, size_t num_data); + /* * Attempt to zero memory in a way that compilers won't optimize out. * @@ -843,15 +855,6 @@ krb5_error_code krb5int_c_copy_keyblock_contents(krb5_context context, extern void krb5int_prng_cleanup(void); -/* - * These declarations are here, so both krb5 and k5crypto - * can get to them. - * krb5 needs to get to them so it can make them available to libgssapi. - */ -extern const struct krb5_enc_provider krb5int_enc_arcfour; -extern const struct krb5_hash_provider krb5int_hash_md5; - - #ifdef KRB5_OLD_CRYPTO /* old provider api */ @@ -2192,19 +2195,24 @@ void krb5int_free_srv_dns_data(struct srv_dns_entry *); /* To keep happy libraries which are (for now) accessing internal stuff */ /* Make sure to increment by one when changing the struct */ -#define KRB5INT_ACCESS_STRUCT_VERSION 15 +#define KRB5INT_ACCESS_STRUCT_VERSION 16 #ifndef ANAME_SZ struct ktext; /* from krb.h, for krb524 support */ #endif typedef struct _krb5int_access { /* crypto stuff */ - const struct krb5_hash_provider *md5_hash_provider; - const struct krb5_enc_provider *arcfour_enc_provider; - krb5_error_code (*hmac)(const struct krb5_hash_provider *hash, - const krb5_keyblock *key, - unsigned int icount, const krb5_data *input, - krb5_data *output); + krb5_error_code (*arcfour_gsscrypt)(const krb5_keyblock *keyblock, + krb5_keyusage usage, + const krb5_data *kd_data, + const krb5_data *input, + krb5_data *output); + krb5_error_code (*arcfour_gsscrypt_iov)(const krb5_keyblock *keyblock, + krb5_keyusage usage, + const krb5_data *kd_data, + krb5_crypto_iov *data, + size_t num_data); + krb5_error_code (*auth_con_get_subkey_enctype)(krb5_context, krb5_auth_context, krb5_enctype *); diff --git a/src/lib/crypto/krb/arcfour/arcfour.c b/src/lib/crypto/krb/arcfour/arcfour.c index a057da09f..b9cb5fc67 100644 --- a/src/lib/crypto/krb/arcfour/arcfour.c +++ b/src/lib/crypto/krb/arcfour/arcfour.c @@ -70,7 +70,7 @@ krb5int_arcfour_usage_key(const struct krb5_enc_provider *enc, return krb5int_hmac_keyblock(hash, session_keyblock, 1, &salt, &out_data); } -/* Derive an encryption key from a usage key and checksum. */ +/* Derive an encryption key from a usage key and (typically) checksum. */ krb5_error_code krb5int_arcfour_enc_key(const struct krb5_enc_provider *enc, const struct krb5_hash_provider *hash, @@ -264,3 +264,49 @@ cleanup: zapfree(comp_checksum.data, comp_checksum.length); return ret; } + +/* Encrypt or decrypt data for a GSSAPI token. */ +krb5_error_code +krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage, + const krb5_data *kd_data, const krb5_data *input, + krb5_data *output) +{ + const struct krb5_enc_provider *enc = &krb5int_enc_arcfour; + const struct krb5_hash_provider *hash = &krb5int_hash_md5; + krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; + krb5_key enc_key; + krb5_error_code ret; + + ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, + &usage_keyblock); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, + &enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive a usage key from the session key and usage. */ + ret = krb5int_arcfour_usage_key(enc, hash, keyblock, usage, + usage_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive the encryption key from the usage key and kd_data. */ + ret = krb5int_arcfour_enc_key(enc, hash, usage_keyblock, kd_data, + enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Encrypt or decrypt (encrypt works for both) the input. */ + ret = krb5_k_create_key(NULL, enc_keyblock, &enc_key); + if (ret != 0) + goto cleanup; + ret = (*enc->encrypt)(enc_key, 0, input, output); + krb5_k_free_key(NULL, enc_key); + +cleanup: + krb5int_c_free_keyblock(NULL, usage_keyblock); + krb5int_c_free_keyblock(NULL, enc_keyblock); + return ret; +} diff --git a/src/lib/crypto/krb/arcfour/arcfour_aead.c b/src/lib/crypto/krb/arcfour/arcfour_aead.c index a409484c5..c5e65ca42 100644 --- a/src/lib/crypto/krb/arcfour/arcfour_aead.c +++ b/src/lib/crypto/krb/arcfour/arcfour_aead.c @@ -29,6 +29,7 @@ #include "k5-int.h" #include "arcfour.h" #include "arcfour-int.h" +#include "hash_provider/hash_provider.h" #include "aead.h" /* AEAD */ @@ -265,3 +266,48 @@ const struct krb5_aead_provider krb5int_aead_arcfour = { krb5int_arcfour_encrypt_iov, krb5int_arcfour_decrypt_iov }; + +krb5_error_code +krb5int_arcfour_gsscrypt_iov(const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *kd_data, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = &krb5int_enc_arcfour; + const struct krb5_hash_provider *hash = &krb5int_hash_md5; + krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; + krb5_key enc_key; + krb5_error_code ret; + + ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, + &usage_keyblock); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, + &enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive a usage key from the session key and usage. */ + ret = krb5int_arcfour_usage_key(enc, hash, keyblock, usage, + usage_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive the encryption key from the usage key and kd_data. */ + ret = krb5int_arcfour_enc_key(enc, hash, usage_keyblock, kd_data, + enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Encrypt or decrypt (encrypt_iov works for both) the input. */ + ret = krb5_k_create_key(NULL, enc_keyblock, &enc_key); + if (ret != 0) + goto cleanup; + ret = (*enc->encrypt_iov)(enc_key, 0, data, num_data); + krb5_k_free_key(NULL, enc_key); + +cleanup: + krb5int_c_free_keyblock(NULL, usage_keyblock); + krb5int_c_free_keyblock(NULL, enc_keyblock); + return ret; +} diff --git a/src/lib/crypto/krb/prf/des_prf.c b/src/lib/crypto/krb/prf/des_prf.c index 6d5baf60b..9b4e1355a 100644 --- a/src/lib/crypto/krb/prf/des_prf.c +++ b/src/lib/crypto/krb/prf/des_prf.c @@ -31,7 +31,7 @@ */ #include "prf_int.h" -//#include /* XXX is this ok? */ +#include "hash_provider/hash_provider.h" krb5_error_code krb5int_des_prf (const struct krb5_enc_provider *enc, diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports index f108cca89..9b1955756 100644 --- a/src/lib/crypto/libk5crypto.exports +++ b/src/lib/crypto/libk5crypto.exports @@ -65,7 +65,6 @@ krb5int_c_free_keyblock_contents krb5int_c_free_keyblock krb5int_c_init_keyblock krb5int_hash_md5 -krb5int_hmac_keyblock krb5int_enc_arcfour krb5int_hmac mit_des_fixup_key_parity @@ -96,3 +95,5 @@ krb5int_MD5Update krb5int_MD5Final krb5int_aes_decrypt krb5int_enc_des3 +krb5int_arcfour_gsscrypt +krb5int_arcfour_gsscrypt_iov diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index 13413b972..0127e8ccb 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -299,14 +299,14 @@ krb5_error_code kg_encrypt_iov (krb5_context context, int iov_count); krb5_error_code -kg_arcfour_docrypt (const krb5_keyblock *longterm_key , int ms_usage, +kg_arcfour_docrypt (const krb5_keyblock *keyblock, int usage, const unsigned char *kd_data, size_t kd_data_len, const unsigned char *input_buf, size_t input_len, unsigned char *output_buf); krb5_error_code kg_arcfour_docrypt_iov (krb5_context context, - const krb5_keyblock *longterm_key , int ms_usage, + const krb5_keyblock *keyblock, int usage, const unsigned char *kd_data, size_t kd_data_len, gss_iov_buffer_desc *iov, int iov_count); diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c index e0970865b..7478c7f12 100644 --- a/src/lib/gssapi/krb5/util_crypt.c +++ b/src/lib/gssapi/krb5/util_crypt.c @@ -282,73 +282,21 @@ kg_decrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv, } krb5_error_code -kg_arcfour_docrypt(const krb5_keyblock *longterm_key , int ms_usage, +kg_arcfour_docrypt(const krb5_keyblock *keyblock, int usage, const unsigned char *kd_data, size_t kd_data_len, const unsigned char *input_buf, size_t input_len, unsigned char *output_buf) { krb5_error_code code; - krb5_data input, output; + krb5_data kd = make_data((char *) kd_data, kd_data_len); + krb5_data input = make_data((char *) input_buf, input_len); + krb5_data output = make_data(output_buf, input_len); krb5int_access kaccess; - krb5_key key; - krb5_keyblock seq_enc_key, usage_key; - unsigned char t[14]; - size_t i = 0; - int exportable = (longterm_key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP); - - usage_key.length = longterm_key->length; - usage_key.contents = malloc(usage_key.length); - if (usage_key.contents == NULL) - return (ENOMEM); - seq_enc_key.length = longterm_key->length; - seq_enc_key.contents = malloc(seq_enc_key.length); - if (seq_enc_key.contents == NULL) { - free ((void *) usage_key.contents); - return (ENOMEM); - } - code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); - if (code) - goto cleanup_arcfour; - if (exportable) { - memcpy(t, kg_arcfour_l40, sizeof(kg_arcfour_l40)); - i += sizeof(kg_arcfour_l40); - } - store_32_le(ms_usage, &t[i]); - i += 4; - input.data = (void *) &t; - input.length = i; - output.data = (void *) usage_key.contents; - output.length = usage_key.length; - code = (*kaccess.hmac)(kaccess.md5_hash_provider, longterm_key, 1, - &input, &output); - if (code) - goto cleanup_arcfour; - if (exportable) - memset(usage_key.contents + 7, 0xab, 9); - - input.data = ( void *) kd_data; - input.length = kd_data_len; - output.data = (void *) seq_enc_key.contents; - code = (*kaccess.hmac)(kaccess.md5_hash_provider, &usage_key, 1, - &input, &output); - if (code) - goto cleanup_arcfour; - input.data = ( void * ) input_buf; - input.length = input_len; - output.data = (void * ) output_buf; - output.length = input_len; - code = krb5_k_create_key(NULL, &seq_enc_key, &key); + code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION); if (code) - goto cleanup_arcfour; - code = (*kaccess.arcfour_enc_provider->encrypt)(key, 0, &input, &output); - krb5_k_free_key(NULL, key); -cleanup_arcfour: - memset (seq_enc_key.contents, 0, seq_enc_key.length); - memset (usage_key.contents, 0, usage_key.length); - free (usage_key.contents); - free (seq_enc_key.contents); - return (code); + return code; + return (*kaccess.arcfour_gsscrypt)(keyblock, usage, &kd, &input, &output); } /* AEAD */ @@ -626,81 +574,29 @@ kg_decrypt_iov(krb5_context context, int proto, int dce_style, size_t ec, } krb5_error_code -kg_arcfour_docrypt_iov(krb5_context context, - const krb5_keyblock *longterm_key, int ms_usage, - const unsigned char *kd_data, size_t kd_data_len, - gss_iov_buffer_desc *iov, int iov_count) +kg_arcfour_docrypt_iov(krb5_context context, const krb5_keyblock *keyblock, + int usage, const unsigned char *kd_data, + size_t kd_data_len, gss_iov_buffer_desc *iov, + int iov_count) { krb5_error_code code; - krb5_data input, output; + krb5_data kd = make_data((char *) kd_data, kd_data_len); krb5int_access kaccess; - krb5_key key; - krb5_keyblock seq_enc_key, usage_key; - unsigned char t[14]; - size_t i = 0; - int exportable = (longterm_key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP); krb5_crypto_iov *kiov = NULL; size_t kiov_count = 0; - usage_key.length = longterm_key->length; - usage_key.contents = malloc(usage_key.length); - if (usage_key.contents == NULL) - return (ENOMEM); - seq_enc_key.length = longterm_key->length; - seq_enc_key.contents = malloc(seq_enc_key.length); - if (seq_enc_key.contents == NULL) { - free ((void *) usage_key.contents); - return (ENOMEM); - } code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); if (code) - goto cleanup_arcfour; - - if (exportable) { - memcpy(t, kg_arcfour_l40, sizeof(kg_arcfour_l40)); - i += sizeof(kg_arcfour_l40); - } - store_32_le(ms_usage, &t[i]); - i += 4; - input.data = (void *) &t; - input.length = i; - output.data = (void *) usage_key.contents; - output.length = usage_key.length; - code = (*kaccess.hmac)(kaccess.md5_hash_provider, longterm_key, 1, - &input, &output); - if (code) - goto cleanup_arcfour; - if (exportable) - memset(usage_key.contents + 7, 0xab, 9); - - input.data = ( void *) kd_data; - input.length = kd_data_len; - output.data = (void *) seq_enc_key.contents; - code = (*kaccess.hmac)(kaccess.md5_hash_provider, &usage_key, 1, - &input, &output); - if (code) - goto cleanup_arcfour; - + return code; code = kg_translate_iov(context, 0 /* proto */, 0 /* dce_style */, - 0 /* ec */, 0 /* rrc */, longterm_key->enctype, + 0 /* ec */, 0 /* rrc */, keyblock->enctype, iov, iov_count, &kiov, &kiov_count); if (code) - goto cleanup_arcfour; - - code = krb5_k_create_key(context, &seq_enc_key, &key); - if (code) - goto cleanup_arcfour; - code = (*kaccess.arcfour_enc_provider->encrypt_iov)(key, 0, kiov, - kiov_count); - krb5_k_free_key(context, key); -cleanup_arcfour: - memset (seq_enc_key.contents, 0, seq_enc_key.length); - memset (usage_key.contents, 0, usage_key.length); - free (usage_key.contents); - free (seq_enc_key.contents); - if (kiov != NULL) - free(kiov); - return (code); + return code; + code = (*kaccess.arcfour_gsscrypt_iov)(keyblock, usage, &kd, + kiov, kiov_count); + free(kiov); + return code; } krb5_cryptotype diff --git a/src/lib/krb5/os/accessor.c b/src/lib/krb5/os/accessor.c index 20fb30d20..4561c6cf4 100644 --- a/src/lib/krb5/os/accessor.c +++ b/src/lib/krb5/os/accessor.c @@ -52,11 +52,10 @@ krb5int_accessor(krb5int_access *internals, krb5_int32 version) #define S(FIELD, VAL) internals_temp.FIELD = VAL krb5int_access internals_temp; #endif + S (arcfour_gsscrypt, krb5int_arcfour_gsscrypt), + S (arcfour_gsscrypt_iov, krb5int_arcfour_gsscrypt_iov), S (free_addrlist, krb5int_free_addrlist), - S (hmac, krb5int_hmac_keyblock), S (auth_con_get_subkey_enctype, krb5_auth_con_get_subkey_enctype), - S (md5_hash_provider, &krb5int_hash_md5), - S (arcfour_enc_provider, &krb5int_enc_arcfour), S (sendto_udp, &krb5int_sendto), S (add_host_to_list, krb5int_add_host_to_list), -- 2.26.2