Add a kg_encrypt_inplace() utility function to the krb5 GSS mech, and
authorGreg Hudson <ghudson@mit.edu>
Tue, 26 Oct 2010 17:18:22 +0000 (17:18 +0000)
committerGreg Hudson <ghudson@mit.edu>
Tue, 26 Oct 2010 17:18:22 +0000 (17:18 +0000)
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
src/lib/gssapi/krb5/k5seal.c
src/lib/gssapi/krb5/k5sealiov.c
src/lib/gssapi/krb5/k5unseal.c
src/lib/gssapi/krb5/k5unsealiov.c
src/lib/gssapi/krb5/util_crypt.c

index ce0265234fbd12e59da7af7b19c0ccb0fe8b5159..1cb1c10625fbb9f47eac3b2bdcd2147290678256 100644 (file)
@@ -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,
index 18c83dfad88332eb6c860de56b9f6fa0898326f0..46accf1ac8ee4dc76f98625433af51c76494928b 100644 (file)
@@ -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);
index c15e4e74434228b58ede18e945ed2d4a0e5639e4..d797ce930647e15116e3b764385a70193c05b30f 100644 (file)
@@ -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;
 
index 5fa52feb44695c807253570df4b81707cbdcf366..4e9ee7739e4cd59b6722ad95fe983d2ff4bd906c 100644 (file)
@@ -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);
index 2be7b82aedfb8676e57716c1dbd9f1952c3f4917..9c821a6fcdab70557c05ad834e55dd85171b728d 100644 (file)
@@ -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;
index 9699c265677200e0cc8f5879b4090cd46067c690..36c5ef3809725666f4f295076f83775a0c7b679b 100644 (file)
@@ -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;
 }