Create functional internal interfaces to allow GSSAPI to perform
authorGreg Hudson <ghudson@mit.edu>
Sat, 28 Nov 2009 23:10:31 +0000 (23:10 +0000)
committerGreg Hudson <ghudson@mit.edu>
Sat, 28 Nov 2009 23:10:31 +0000 (23:10 +0000)
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
src/lib/crypto/krb/arcfour/arcfour.c
src/lib/crypto/krb/arcfour/arcfour_aead.c
src/lib/crypto/krb/prf/des_prf.c
src/lib/crypto/libk5crypto.exports
src/lib/gssapi/krb5/gssapiP_krb5.h
src/lib/gssapi/krb5/util_crypt.c
src/lib/krb5/os/accessor.c

index ad7f53994358b9ad8cb4604f8746196c4296dc45..43d9d21fe5753320ced988a6b9fcdb64cc9a9467 100644 (file)
@@ -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 *);
index a057da09f84953d157c01b0c9ee7dd5c1461b517..b9cb5fc671a68f88ff4b2d633ca92fea5e7f52b0 100644 (file)
@@ -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;
+}
index a409484c591dd37c364a4572499ae389eff14c72..c5e65ca429a7e4e9f75c67be314b6a1b231093bb 100644 (file)
@@ -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;
+}
index 6d5baf60ba3c40147506728351b940205764018b..9b4e1355a3887a053c3180d240ea3bd09ac91363 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 #include "prf_int.h"
-//#include <hash_provider/hash_provider.h>              /* XXX is this ok? */
+#include "hash_provider/hash_provider.h"
 
 krb5_error_code
 krb5int_des_prf (const struct krb5_enc_provider *enc,
index f108cca89526a910552953453582612386e719b0..9b19557568f50aeb86c243100ccf39d709e4791e 100644 (file)
@@ -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
index 13413b972e4f7f8c812771fd4f26fdab2f74fd71..0127e8ccb2fadd0b0389d2cc5199795b2f5a07a3 100644 (file)
@@ -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);
index e0970865b80f100d09cd0932f4d9a2a8dea9a631..7478c7f12529139ffe03a444dc092d162d6758f0 100644 (file)
@@ -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
index 20fb30d2094c350f9aa12d97cfe66f0e054bff68..4561c6cf4dc53ac98e48a056fe57f609326173d1 100644 (file)
@@ -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),