From c079477480c839bd983afd082ac7a7ec51e906ca Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Tue, 26 Oct 2010 17:18:22 +0000 Subject: [PATCH] Add a kg_encrypt_inplace() utility function to the krb5 GSS mech, and use it where we do in-place encryption of checksums in the non-CFX seal tokens with raw DES enctypes. Avoids a harmless but incorrect in-place memcpy(). ticket: 6770 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24485 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/gssapi/krb5/gssapiP_krb5.h | 6 ++ src/lib/gssapi/krb5/k5seal.c | 9 +- src/lib/gssapi/krb5/k5sealiov.c | 9 +- src/lib/gssapi/krb5/k5unseal.c | 10 +- src/lib/gssapi/krb5/k5unsealiov.c | 9 +- src/lib/gssapi/krb5/util_crypt.c | 166 ++++++++++++++--------------- 6 files changed, 108 insertions(+), 101 deletions(-) diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index ce0265234..1cb1c1062 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -305,6 +305,12 @@ krb5_error_code kg_encrypt (krb5_context context, krb5_pointer out, unsigned int length); +/* Encrypt length bytes at ptr in place, with the given key and usage. If + * iv is not NULL, use it as the cipher state. */ +krb5_error_code kg_encrypt_inplace(krb5_context context, krb5_key key, + int usage, krb5_pointer iv, + krb5_pointer ptr, unsigned int length); + krb5_error_code kg_encrypt_iov (krb5_context context, int proto, int dce_style, size_t ec, size_t rrc, diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c index 18c83dfad..46accf1ac 100644 --- a/src/lib/gssapi/krb5/k5seal.c +++ b/src/lib/gssapi/krb5/k5seal.c @@ -211,10 +211,11 @@ make_seal_token_v1 (krb5_context context, case SGN_ALG_DES_MAC_MD5: case 3: - if ((code = kg_encrypt(context, seq, KG_USAGE_SEAL, - (g_OID_equal(oid, gss_mech_krb5_old) ? - seq->keyblock.contents : NULL), - md5cksum.contents, md5cksum.contents, 16))) { + code = kg_encrypt_inplace(context, seq, KG_USAGE_SEAL, + (g_OID_equal(oid, gss_mech_krb5_old) ? + seq->keyblock.contents : NULL), + md5cksum.contents, 16); + if (code) { krb5_free_checksum_contents(context, &md5cksum); xfree (plain); xfree(t); diff --git a/src/lib/gssapi/krb5/k5sealiov.c b/src/lib/gssapi/krb5/k5sealiov.c index c15e4e744..d797ce930 100644 --- a/src/lib/gssapi/krb5/k5sealiov.c +++ b/src/lib/gssapi/krb5/k5sealiov.c @@ -192,10 +192,11 @@ make_seal_token_v1_iov(krb5_context context, switch (ctx->signalg) { case SGN_ALG_DES_MAC_MD5: case SGN_ALG_3: - code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL, - (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? - ctx->seq->keyblock.contents : NULL), - md5cksum.contents, md5cksum.contents, 16); + code = kg_encrypt_inplace(context, ctx->seq, KG_USAGE_SEAL, + (g_OID_equal(ctx->mech_used, + gss_mech_krb5_old) ? + ctx->seq->keyblock.contents : NULL), + md5cksum.contents, 16); if (code != 0) goto cleanup; diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c index 5fa52feb4..4e9ee7739 100644 --- a/src/lib/gssapi/krb5/k5unseal.c +++ b/src/lib/gssapi/krb5/k5unseal.c @@ -298,10 +298,12 @@ kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer, return(GSS_S_FAILURE); } - if ((code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL, - (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? - ctx->seq->keyblock.contents : NULL), - md5cksum.contents, md5cksum.contents, 16))) { + code = kg_encrypt_inplace(context, ctx->seq, KG_USAGE_SEAL, + (g_OID_equal(ctx->mech_used, + gss_mech_krb5_old) ? + ctx->seq->keyblock.contents : NULL), + md5cksum.contents, 16); + if (code) { krb5_free_checksum_contents(context, &md5cksum); if (toktype == KG_TOK_SEAL_MSG) xfree(token.value); diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c index 2be7b82ae..9c821a6fc 100644 --- a/src/lib/gssapi/krb5/k5unsealiov.c +++ b/src/lib/gssapi/krb5/k5unsealiov.c @@ -228,10 +228,11 @@ kg_unseal_v1_iov(krb5_context context, switch (signalg) { case SGN_ALG_DES_MAC_MD5: case SGN_ALG_3: - code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL, - (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? - ctx->seq->keyblock.contents : NULL), - md5cksum.contents, md5cksum.contents, 16); + code = kg_encrypt_inplace(context, ctx->seq, KG_USAGE_SEAL, + (g_OID_equal(ctx->mech_used, + gss_mech_krb5_old) ? + ctx->seq->keyblock.contents : NULL), + md5cksum.contents, 16); if (code != 0) { retval = GSS_S_FAILURE; goto cleanup; diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c index 9699c2656..36c5ef380 100644 --- a/src/lib/gssapi/krb5/util_crypt.c +++ b/src/lib/gssapi/krb5/util_crypt.c @@ -206,29 +206,48 @@ kg_make_confounder(krb5_context context, krb5_enctype enctype, return(krb5_c_random_make_octets(context, &lrandom)); } +/* Set *data_out to a krb5_data structure containing iv, or to NULL if iv is + * NULL. */ +static krb5_error_code +iv_to_state(krb5_context context, krb5_key key, krb5_pointer iv, + krb5_data **data_out) +{ + krb5_error_code code; + krb5_data *data; + size_t blocksize; + + *data_out = NULL; + if (iv == NULL) + return 0; + + code = krb5_c_block_size(context, key->keyblock.enctype, &blocksize); + if (code) + return code; + + data = k5alloc(sizeof(*data), &code); + if (data == NULL) + return code; + code = alloc_data(data, blocksize); + if (code) { + free(data); + return code; + } + memcpy(data->data, iv, blocksize); + *data_out = data; + return 0; +} + krb5_error_code kg_encrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv, krb5_const_pointer in, krb5_pointer out, unsigned int length) { krb5_error_code code; - size_t blocksize; - krb5_data ivd, *pivd, inputd; + krb5_data *state, inputd; krb5_enc_data outputd; - if (iv) { - code = krb5_c_block_size(context, key->keyblock.enctype, &blocksize); - if (code) - return(code); - - ivd.length = blocksize; - ivd.data = malloc(ivd.length); - if (ivd.data == NULL) - return ENOMEM; - memcpy(ivd.data, iv, ivd.length); - pivd = &ivd; - } else { - pivd = NULL; - } + code = iv_to_state(context, key, iv, &state); + if (code) + return code; inputd.length = length; inputd.data = (char *)in; @@ -236,9 +255,27 @@ kg_encrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv, outputd.ciphertext.length = length; outputd.ciphertext.data = out; - code = krb5_k_encrypt(context, key, usage, pivd, &inputd, &outputd); - if (pivd != NULL) - free(pivd->data); + code = krb5_k_encrypt(context, key, usage, state, &inputd, &outputd); + krb5_free_data(context, state); + return code; +} + +krb5_error_code +kg_encrypt_inplace(krb5_context context, krb5_key key, int usage, + krb5_pointer iv, krb5_pointer ptr, unsigned int length) +{ + krb5_error_code code; + krb5_crypto_iov iov; + krb5_data *state; + + code = iv_to_state(context, key, iv, &state); + if (code) + return code; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data((void *)ptr, length); + code = krb5_k_encrypt_iov(context, key, usage, state, &iov, 1); + krb5_free_data(context, state); return code; } @@ -249,24 +286,12 @@ kg_decrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv, krb5_const_pointer in, krb5_pointer out, unsigned int length) { krb5_error_code code; - size_t blocksize; - krb5_data ivd, *pivd, outputd; + krb5_data *state, outputd; krb5_enc_data inputd; - if (iv) { - code = krb5_c_block_size(context, key->keyblock.enctype, &blocksize); - if (code) - return(code); - - ivd.length = blocksize; - ivd.data = malloc(ivd.length); - if (ivd.data == NULL) - return ENOMEM; - memcpy(ivd.data, iv, ivd.length); - pivd = &ivd; - } else { - pivd = NULL; - } + code = iv_to_state(context, key, iv, &state); + if (code) + return code; inputd.enctype = ENCTYPE_UNKNOWN; inputd.ciphertext.length = length; @@ -275,9 +300,8 @@ kg_decrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv, outputd.length = length; outputd.data = out; - code = krb5_k_decrypt(context, key, usage, pivd, &inputd, &outputd); - if (pivd != NULL) - free(pivd->data); + code = krb5_k_decrypt(context, key, usage, state, &inputd, &outputd); + krb5_free_data(context, state); return code; } @@ -499,37 +523,23 @@ kg_encrypt_iov(krb5_context context, int proto, int dce_style, size_t ec, gss_iov_buffer_desc *iov, int iov_count) { krb5_error_code code; - size_t blocksize; - krb5_data ivd, *pivd; - size_t kiov_count; + krb5_data *state; + size_t kiov_len; krb5_crypto_iov *kiov; - if (iv) { - code = krb5_c_block_size(context, key->keyblock.enctype, &blocksize); - if (code) - return(code); - - ivd.length = blocksize; - ivd.data = malloc(ivd.length); - if (ivd.data == NULL) - return ENOMEM; - memcpy(ivd.data, iv, ivd.length); - pivd = &ivd; - } else { - pivd = NULL; - } + code = iv_to_state(context, key, iv, &state); + if (code) + return code; code = kg_translate_iov(context, proto, dce_style, ec, rrc, key->keyblock.enctype, iov, iov_count, - &kiov, &kiov_count); + &kiov, &kiov_len); if (code == 0) { - code = krb5_k_encrypt_iov(context, key, usage, pivd, kiov, kiov_count); + code = krb5_k_encrypt_iov(context, key, usage, state, kiov, kiov_len); free(kiov); } - if (pivd != NULL) - free(pivd->data); - + krb5_free_data(context, state); return code; } @@ -541,37 +551,23 @@ kg_decrypt_iov(krb5_context context, int proto, int dce_style, size_t ec, gss_iov_buffer_desc *iov, int iov_count) { krb5_error_code code; - size_t blocksize; - krb5_data ivd, *pivd; - size_t kiov_count; + krb5_data *state; + size_t kiov_len; krb5_crypto_iov *kiov; - if (iv) { - code = krb5_c_block_size(context, key->keyblock.enctype, &blocksize); - if (code) - return(code); - - ivd.length = blocksize; - ivd.data = malloc(ivd.length); - if (ivd.data == NULL) - return ENOMEM; - memcpy(ivd.data, iv, ivd.length); - pivd = &ivd; - } else { - pivd = NULL; - } + code = iv_to_state(context, key, iv, &state); + if (code) + return code; code = kg_translate_iov(context, proto, dce_style, ec, rrc, key->keyblock.enctype, iov, iov_count, - &kiov, &kiov_count); + &kiov, &kiov_len); if (code == 0) { - code = krb5_k_decrypt_iov(context, key, usage, pivd, kiov, kiov_count); + code = krb5_k_decrypt_iov(context, key, usage, state, kiov, kiov_len); free(kiov); } - if (pivd != NULL) - free(pivd->data); - + krb5_free_data(context, state); return code; } @@ -585,17 +581,17 @@ kg_arcfour_docrypt_iov(krb5_context context, const krb5_keyblock *keyblock, krb5_data kd = make_data((char *) kd_data, kd_data_len); krb5int_access kaccess; krb5_crypto_iov *kiov = NULL; - size_t kiov_count = 0; + size_t kiov_len = 0; code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); if (code) return code; code = kg_translate_iov(context, 0 /* proto */, 0 /* dce_style */, 0 /* ec */, 0 /* rrc */, keyblock->enctype, - iov, iov_count, &kiov, &kiov_count); + iov, iov_count, &kiov, &kiov_len); if (code) return code; - code = (*kaccess.arcfour_gsscrypt)(keyblock, usage, &kd, kiov, kiov_count); + code = (*kaccess.arcfour_gsscrypt)(keyblock, usage, &kd, kiov, kiov_len); free(kiov); return code; } -- 2.26.2