You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by mi...@apache.org on 2016/07/10 15:32:13 UTC

svn commit: r1752097 - in /apr/apr-util/branches/1.6.x: ./ CHANGES crypto/apr_crypto.c crypto/apr_crypto_commoncrypto.c crypto/apr_crypto_nss.c crypto/apr_crypto_openssl.c include/apr_crypto.h include/private/apr_crypto_internal.h test/testcrypto.c

Author: minfrin
Date: Sun Jul 10 15:32:12 2016
New Revision: 1752097

URL: http://svn.apache.org/viewvc?rev=1752097&view=rev
Log:
Backport r1752008.
apr_crypto: Add apr_crypto_key() function which supports keys
generated from a passphrase or a raw secret provided by the caller.
Deprecate apr_crypto_passphrase().

Modified:
    apr/apr-util/branches/1.6.x/   (props changed)
    apr/apr-util/branches/1.6.x/CHANGES
    apr/apr-util/branches/1.6.x/crypto/apr_crypto.c
    apr/apr-util/branches/1.6.x/crypto/apr_crypto_commoncrypto.c
    apr/apr-util/branches/1.6.x/crypto/apr_crypto_nss.c
    apr/apr-util/branches/1.6.x/crypto/apr_crypto_openssl.c
    apr/apr-util/branches/1.6.x/include/apr_crypto.h
    apr/apr-util/branches/1.6.x/include/private/apr_crypto_internal.h
    apr/apr-util/branches/1.6.x/test/testcrypto.c

Propchange: apr/apr-util/branches/1.6.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sun Jul 10 15:32:12 2016
@@ -1,4 +1,4 @@
-/apr/apr/trunk:781403,781409,784519,784592,789965,794508,917837-917838,982408-982409,998533,1086937,1127053,1127648,1128838,1129433,1133587,1207704,1210524,1211987,1214516,1308087,1308131,1308318,1327636,1340286,1346865,1357761,1357772,1357780,1357966,1357968,1357979,1358295,1358480,1361811,1362241,1362248,1362252,1362255,1363076,1369681,1370626,1371811,1371817,1371919,1371923,1382174,1389154,1389169,1390461,1390477,1402870,1402897,1402903,1402907,1406088,1422413,1425356,1426442,1426448,1438960,1449308,1449314,1460185,1460243-1460244,1462219,1462224,1484271,1493715,1495887,1495889,1496407,1516261,1523479,1529554,1531009,1541054,1543399,1544846,1618843,1619438,1625247,1626561,1648830,1711657,1722547,1728958,1728963,1747941,1751567,1751806,1751898
+/apr/apr/trunk:781403,781409,784519,784592,789965,794508,917837-917838,982408-982409,998533,1086937,1127053,1127648,1128838,1129433,1133587,1207704,1210524,1211987,1214516,1308087,1308131,1308318,1327636,1340286,1346865,1357761,1357772,1357780,1357966,1357968,1357979,1358295,1358480,1361811,1362241,1362248,1362252,1362255,1363076,1369681,1370626,1371811,1371817,1371919,1371923,1382174,1389154,1389169,1390461,1390477,1402870,1402897,1402903,1402907,1406088,1422413,1425356,1426442,1426448,1438960,1449308,1449314,1460185,1460243-1460244,1462219,1462224,1484271,1493715,1495887,1495889,1496407,1516261,1523479,1529554,1531009,1541054,1543399,1544846,1618843,1619438,1625247,1626561,1648830,1711657,1722547,1728958,1728963,1747941,1751567,1751806,1751898,1752008
 /apr/apr-util/branches/1.3.x:896410,1154885
 /apr/apr-util/branches/1.4.x:1126217,1211211,1211219,1211223,1211330
 /apr/apr-util/trunk:731033-731034,731225,731236,731291,731293,731379,743986,744009,745771,747612,747623,747630,1626561

Modified: apr/apr-util/branches/1.6.x/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/CHANGES?rev=1752097&r1=1752096&r2=1752097&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/CHANGES [utf-8] (original)
+++ apr/apr-util/branches/1.6.x/CHANGES [utf-8] Sun Jul 10 15:32:12 2016
@@ -1,6 +1,10 @@
                                                      -*- coding: utf-8 -*-
 Changes with APR-util 1.6.0
 
+  *) apr_crypto: Add apr_crypto_key() function which supports keys
+     generated from a passphrase or a raw secret provided by the caller.
+     Deprecate apr_crypto_passphrase(). [Graham Leggett]
+
   *) apr_crypto_nss: Ensure the SECItem returned by PK11_ParamFromIV
      is properly freed. [Graham Leggett]
 

Modified: apr/apr-util/branches/1.6.x/crypto/apr_crypto.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/crypto/apr_crypto.c?rev=1752097&r1=1752096&r2=1752097&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/crypto/apr_crypto.c (original)
+++ apr/apr-util/branches/1.6.x/crypto/apr_crypto.c Sun Jul 10 15:32:12 2016
@@ -295,7 +295,8 @@ APU_DECLARE(apr_status_t) apr_crypto_mak
 
 /**
  * @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t, which in turn begins with an
+ * integer.
  *
  * @param types - hashtable of key types keyed to constants.
  * @param f - encryption context
@@ -309,7 +310,8 @@ APU_DECLARE(apr_status_t) apr_crypto_get
 
 /**
  * @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t, which in turn begins with an
+ * integer.
  *
  * @param modes - hashtable of key modes keyed to constants.
  * @param f - encryption context
@@ -322,6 +324,28 @@ APU_DECLARE(apr_status_t) apr_crypto_get
 }
 
 /**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_key(apr_crypto_key_t **key,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+    return f->provider->key(key, rec, f, p);
+}
+
+/**
  * @brief Create a key from the given passphrase. By default, the PBKDF2
  *        algorithm is used to generate the key from the passphrase. It is expected
  *        that the same pass phrase will generate the same key, regardless of the

Modified: apr/apr-util/branches/1.6.x/crypto/apr_crypto_commoncrypto.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/crypto/apr_crypto_commoncrypto.c?rev=1752097&r1=1752096&r2=1752097&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/crypto/apr_crypto_commoncrypto.c (original)
+++ apr/apr-util/branches/1.6.x/crypto/apr_crypto_commoncrypto.c Sun Jul 10 15:32:12 2016
@@ -69,13 +69,17 @@ struct apr_crypto_block_t
     CCCryptorRef ref;
 };
 
-static int key_3des_192 = APR_KEY_3DES_192;
-static int key_aes_128 = APR_KEY_AES_128;
-static int key_aes_192 = APR_KEY_AES_192;
-static int key_aes_256 = APR_KEY_AES_256;
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
 
-static int mode_ecb = APR_MODE_ECB;
-static int mode_cbc = APR_MODE_CBC;
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
 
 /**
  * Fetch the most recent error from this driver.
@@ -211,17 +215,17 @@ static apr_status_t crypto_make(apr_cryp
     if (!f->types) {
         return APR_ENOMEM;
     }
-    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_3des_192));
-    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128));
-    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192));
-    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256));
+    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
 
     f->modes = apr_hash_make(pool);
     if (!f->modes) {
         return APR_ENOMEM;
     }
-    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb));
-    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc));
+    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
 
     apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
             apr_pool_cleanup_null);
@@ -232,7 +236,7 @@ static apr_status_t crypto_make(apr_cryp
 
 /**
  * @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t.
  *
  * @param types - hashtable of key types keyed to constants.
  * @param f - encryption context
@@ -247,7 +251,7 @@ static apr_status_t crypto_get_block_key
 
 /**
  * @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t.
  *
  * @param modes - hashtable of key modes keyed to constants.
  * @param f - encryption context
@@ -260,52 +264,13 @@ static apr_status_t crypto_get_block_key
     return APR_SUCCESS;
 }
 
-/**
- * @brief Create a key from the given passphrase. By default, the PBKDF2
- *        algorithm is used to generate the key from the passphrase. It is expected
- *        that the same pass phrase will generate the same key, regardless of the
- *        backend crypto platform used. The key is cleaned up when the context
- *        is cleaned, and may be reused with multiple encryption or decryption
- *        operations.
- * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
- *       *key is not NULL, *key must point at a previously created structure.
- * @param key The key returned, see note.
- * @param ivSize The size of the initialisation vector will be returned, based
- *               on whether an IV is relevant for this type of crypto.
- * @param pass The passphrase to use.
- * @param passLen The passphrase length in bytes
- * @param salt The salt to use.
- * @param saltLen The salt length in bytes
- * @param type 3DES_192, AES_128, AES_192, AES_256.
- * @param mode Electronic Code Book / Cipher Block Chaining.
- * @param doPad Pad if necessary.
- * @param iterations Iteration count
- * @param f The context to use.
- * @param p The pool to use.
- * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
- *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
- *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
- *         not known. APR_EPADDING if padding was requested but is not supported.
- *         APR_ENOTIMPL if not implemented.
+/*
+ * Work out which mechanism to use.
  */
-static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
-        const char *pass, apr_size_t passLen, const unsigned char * salt,
-        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
-        const apr_crypto_block_key_mode_e mode, const int doPad,
-        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad, apr_pool_t *p)
 {
-    apr_crypto_key_t *key = *k;
-
-    if (!key) {
-        *k = key = apr_array_push(f->keys);
-    }
-    if (!key) {
-        return APR_ENOMEM;
-    }
-
-    key->f = f;
-    key->provider = f->provider;
-
     /* handle padding */
     key->options = doPad ? kCCOptionPKCS7Padding : 0;
 
@@ -391,12 +356,145 @@ static apr_status_t crypto_passphrase(ap
     }
 
     /* make space for the key */
-    key->key = apr_pcalloc(p, key->keyLen);
+    key->key = apr_palloc(p, key->keyLen);
     if (!key->key) {
         return APR_ENOMEM;
     }
     apr_crypto_clear(p, key->key, key->keyLen);
 
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_status_t rv;
+    apr_crypto_key_t *key = *k;
+
+    if (!key) {
+        *k = key = apr_array_push(f->keys);
+    }
+    if (!key) {
+        return APR_ENOMEM;
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    switch (rec->ktype) {
+
+    case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+        /* generate the key */
+        if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2,
+                rec->k.passphrase.pass, rec->k.passphrase.passLen,
+                rec->k.passphrase.salt, rec->k.passphrase.saltLen,
+                kCCPRFHmacAlgSHA1, rec->k.passphrase.iterations, key->key,
+                key->keyLen)) == kCCParamError) {
+            return APR_ENOKEY;
+        }
+
+        break;
+    }
+
+    case APR_CRYPTO_KTYPE_SECRET: {
+
+        /* sanity check - key correct size? */
+        if (rec->k.secret.secretLen != key->keyLen) {
+            return APR_EKEYLENGTH;
+        }
+
+        /* copy the key */
+        memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
+
+        break;
+    }
+
+    default: {
+
+        return APR_ENOKEY;
+
+    }
+    }
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ *        algorithm is used to generate the key from the passphrase. It is expected
+ *        that the same pass phrase will generate the same key, regardless of the
+ *        backend crypto platform used. The key is cleaned up when the context
+ *        is cleaned, and may be reused with multiple encryption or decryption
+ *        operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ *               on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+        const char *pass, apr_size_t passLen, const unsigned char * salt,
+        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad,
+        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_status_t rv;
+    apr_crypto_key_t *key = *k;
+
+    if (!key) {
+        *k = key = apr_array_push(f->keys);
+    }
+    if (!key) {
+        return APR_ENOMEM;
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, type, mode, doPad, p);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
     /* generate the key */
     if ((f->result->rc = CCKeyDerivationPBKDF(kCCPBKDF2, pass, passLen, salt,
             saltLen, kCCPRFHmacAlgSHA1, iterations, key->key, key->keyLen))
@@ -808,7 +906,7 @@ APR_MODULE_DECLARE_DATA const apr_crypto
         crypto_block_encrypt_init, crypto_block_encrypt,
         crypto_block_encrypt_finish, crypto_block_decrypt_init,
         crypto_block_decrypt, crypto_block_decrypt_finish, crypto_block_cleanup,
-        crypto_cleanup, crypto_shutdown, crypto_error
+        crypto_cleanup, crypto_shutdown, crypto_error, crypto_key
 };
 
 #endif

Modified: apr/apr-util/branches/1.6.x/crypto/apr_crypto_nss.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/crypto/apr_crypto_nss.c?rev=1752097&r1=1752096&r2=1752097&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/crypto/apr_crypto_nss.c (original)
+++ apr/apr-util/branches/1.6.x/crypto/apr_crypto_nss.c Sun Jul 10 15:32:12 2016
@@ -81,13 +81,20 @@ struct apr_crypto_block_t {
     int blockSize;
 };
 
-static int key_3des_192 = APR_KEY_3DES_192;
-static int key_aes_128 = APR_KEY_AES_128;
-static int key_aes_192 = APR_KEY_AES_192;
-static int key_aes_256 = APR_KEY_AES_256;
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
 
-static int mode_ecb = APR_MODE_ECB;
-static int mode_cbc = APR_MODE_CBC;
+/* sufficient space to wrap a key */
+#define BUFFER_SIZE 128
 
 /**
  * Fetch the most recent error from this driver.
@@ -219,10 +226,6 @@ static apr_status_t crypto_init(apr_pool
             err->reason = apr_pstrdup(pool, "Error during 'nss' initialisation");
             *result = err;
         }
-        s = NSS_Shutdown();
-        if (s != SECSuccess) {
-            return APR_ECRYPT;
-        }
 
         return APR_ECRYPT;
     }
@@ -329,17 +332,17 @@ static apr_status_t crypto_make(apr_cryp
     if (!f->types) {
         return APR_ENOMEM;
     }
-    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_3des_192));
-    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128));
-    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192));
-    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256));
+    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
 
     f->modes = apr_hash_make(pool);
     if (!f->modes) {
         return APR_ENOMEM;
     }
-    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb));
-    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc));
+    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
 
     apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
             apr_pool_cleanup_null);
@@ -350,7 +353,7 @@ static apr_status_t crypto_make(apr_cryp
 
 /**
  * @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t.
  *
  * @param types - hashtable of key types keyed to constants.
  * @param f - encryption context
@@ -365,7 +368,7 @@ static apr_status_t crypto_get_block_key
 
 /**
  * @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t.
  *
  * @param modes - hashtable of key modes keyed to constants.
  * @param f - encryption context
@@ -378,57 +381,13 @@ static apr_status_t crypto_get_block_key
     return APR_SUCCESS;
 }
 
-/**
- * @brief Create a key from the given passphrase. By default, the PBKDF2
- *        algorithm is used to generate the key from the passphrase. It is expected
- *        that the same pass phrase will generate the same key, regardless of the
- *        backend crypto platform used. The key is cleaned up when the context
- *        is cleaned, and may be reused with multiple encryption or decryption
- *        operations.
- * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
- *       *key is not NULL, *key must point at a previously created structure.
- * @param key The key returned, see note.
- * @param ivSize The size of the initialisation vector will be returned, based
- *               on whether an IV is relevant for this type of crypto.
- * @param pass The passphrase to use.
- * @param passLen The passphrase length in bytes
- * @param salt The salt to use.
- * @param saltLen The salt length in bytes
- * @param type 3DES_192, AES_128, AES_192, AES_256.
- * @param mode Electronic Code Book / Cipher Block Chaining.
- * @param doPad Pad if necessary.
- * @param iterations Iteration count
- * @param f The context to use.
- * @param p The pool to use.
- * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
- *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
- *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
- *         not known. APR_EPADDING if padding was requested but is not supported.
- *         APR_ENOTIMPL if not implemented.
+/*
+ * Work out which mechanism to use.
  */
-static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
-        const char *pass, apr_size_t passLen, const unsigned char * salt,
-        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
-        const apr_crypto_block_key_mode_e mode, const int doPad,
-        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad)
 {
-    apr_status_t rv = APR_SUCCESS;
-    PK11SlotInfo * slot;
-    SECItem passItem;
-    SECItem saltItem;
-    SECAlgorithmID *algid;
-    void *wincx = NULL; /* what is wincx? */
-    apr_crypto_key_t *key = *k;
-
-    if (!key) {
-        *k = key = apr_array_push(f->keys);
-    }
-    if (!key) {
-        return APR_ENOMEM;
-    }
-
-    key->f = f;
-    key->provider = f->provider;
 
     /* decide on what cipher mechanism we will be using */
     switch (type) {
@@ -483,13 +442,262 @@ static apr_status_t crypto_passphrase(ap
     if (doPad) {
         CK_MECHANISM_TYPE paddedMech;
         paddedMech = PK11_GetPadMechanism(key->cipherMech);
-        if (CKM_INVALID_MECHANISM == paddedMech || key->cipherMech
-                == paddedMech) {
+        if (CKM_INVALID_MECHANISM == paddedMech
+                || key->cipherMech == paddedMech) {
             return APR_EPADDING;
         }
         key->cipherMech = paddedMech;
     }
 
+    key->ivSize = PK11_GetIVLength(key->cipherMech);
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_status_t rv = APR_SUCCESS;
+    PK11SlotInfo *slot, *tslot;
+    PK11SymKey *tkey;
+    SECItem secretItem;
+    SECItem wrappedItem;
+    SECItem *secParam;
+    PK11Context *ctx;
+    SECStatus s;
+    SECItem passItem;
+    SECItem saltItem;
+    SECAlgorithmID *algid;
+    void *wincx = NULL; /* what is wincx? */
+    apr_crypto_key_t *key;
+    int blockSize;
+    int remainder;
+
+    key = *k;
+    if (!key) {
+        *k = key = apr_array_push(f->keys);
+    }
+    if (!key) {
+        return APR_ENOMEM;
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    switch (rec->ktype) {
+
+    case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+        /* Turn the raw passphrase and salt into SECItems */
+        passItem.data = (unsigned char*) rec->k.passphrase.pass;
+        passItem.len = rec->k.passphrase.passLen;
+        saltItem.data = (unsigned char*) rec->k.passphrase.salt;
+        saltItem.len = rec->k.passphrase.saltLen;
+
+        /* generate the key */
+        /* pbeAlg and cipherAlg are the same. */
+        algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
+                SEC_OID_HMAC_SHA1, key->keyLength,
+                rec->k.passphrase.iterations, &saltItem);
+        if (algid) {
+            slot = PK11_GetBestSlot(key->cipherMech, wincx);
+            if (slot) {
+                key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE,
+                        wincx);
+                PK11_FreeSlot(slot);
+            }
+            SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+        }
+
+        break;
+    }
+
+    case APR_CRYPTO_KTYPE_SECRET: {
+
+        /*
+         * NSS is by default in FIPS mode, which disallows the use of unencrypted
+         * symmetrical keys. As per http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
+         * we do the following:
+         *
+         * 1. Generate a (temporary) symmetric key in NSS.
+         * 2. Use that symmetric key to encrypt your symmetric key as data.
+         * 3. Unwrap your wrapped symmetric key, using the symmetric key
+         * you generated in Step 1 as the unwrapping key.
+         *
+         * http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947
+         */
+
+        /* generate the key */
+        slot = PK11_GetBestSlot(key->cipherMech, NULL);
+        if (slot) {
+            unsigned char data[BUFFER_SIZE];
+
+            /* sanity check - key correct size? */
+            if (rec->k.secret.secretLen != key->keyLength) {
+                PK11_FreeSlot(slot);
+                return APR_EKEYLENGTH;
+            }
+
+            tslot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
+            if (tslot) {
+
+                /* generate a temporary wrapping key */
+                tkey = PK11_KeyGen(tslot, CKM_AES_ECB, 0, PK11_GetBestKeyLength(tslot, CKM_AES_ECB), 0);
+
+                /* prepare the key to wrap */
+                secretItem.data = (unsigned char *) rec->k.secret.secret;
+                secretItem.len = rec->k.secret.secretLen;
+
+                /* ensure our key matches the blocksize */
+                secParam = PK11_GenerateNewParam(CKM_AES_ECB, tkey);
+                blockSize = PK11_GetBlockSize(CKM_AES_ECB, secParam);
+                remainder = rec->k.secret.secretLen % blockSize;
+                if (remainder) {
+                    secretItem.data =
+                            apr_pcalloc(p, rec->k.secret.secretLen + remainder);
+                    apr_crypto_clear(p, secretItem.data,
+                            rec->k.secret.secretLen);
+                    memcpy(secretItem.data, rec->k.secret.secret,
+                            rec->k.secret.secretLen);
+                    secretItem.len += remainder;
+                }
+
+                /* prepare a space for the wrapped key */
+                wrappedItem.data = data;
+
+                /* wrap the key */
+                ctx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, tkey,
+                        secParam);
+                if (ctx) {
+                    s = PK11_CipherOp(ctx, wrappedItem.data,
+                            (int *) (&wrappedItem.len), BUFFER_SIZE,
+                            secretItem.data, secretItem.len);
+                    if (s == SECSuccess) {
+
+                        /* unwrap the key again */
+                        key->symKey = PK11_UnwrapSymKeyWithFlags(tkey,
+                                CKM_AES_ECB, NULL, &wrappedItem,
+                                key->cipherMech, CKA_ENCRYPT,
+                                rec->k.secret.secretLen, 0);
+
+                    }
+
+                    PK11_DestroyContext(ctx, PR_TRUE);
+                }
+
+                /* clean up */
+                SECITEM_FreeItem(secParam, PR_TRUE);
+                PK11_FreeSymKey(tkey);
+                PK11_FreeSlot(tslot);
+
+            }
+
+            PK11_FreeSlot(slot);
+        }
+
+        break;
+    }
+
+    default: {
+
+        return APR_ENOKEY;
+
+    }
+    }
+
+    /* sanity check? */
+    if (!key->symKey) {
+        PRErrorCode perr = PORT_GetError();
+        if (perr) {
+            f->result->rc = perr;
+            f->result->msg = PR_ErrorToName(perr);
+            rv = APR_ENOKEY;
+        }
+    }
+
+    return rv;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ *        algorithm is used to generate the key from the passphrase. It is expected
+ *        that the same pass phrase will generate the same key, regardless of the
+ *        backend crypto platform used. The key is cleaned up when the context
+ *        is cleaned, and may be reused with multiple encryption or decryption
+ *        operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ *               on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+        const char *pass, apr_size_t passLen, const unsigned char * salt,
+        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad,
+        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_status_t rv = APR_SUCCESS;
+    PK11SlotInfo * slot;
+    SECItem passItem;
+    SECItem saltItem;
+    SECAlgorithmID *algid;
+    void *wincx = NULL; /* what is wincx? */
+    apr_crypto_key_t *key = *k;
+
+    if (!key) {
+        *k = key = apr_array_push(f->keys);
+    }
+    if (!key) {
+        return APR_ENOMEM;
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, type, mode, doPad);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
     /* Turn the raw passphrase and salt into SECItems */
     passItem.data = (unsigned char*) pass;
     passItem.len = passLen;
@@ -520,7 +728,6 @@ static apr_status_t crypto_passphrase(ap
         }
     }
 
-    key->ivSize = PK11_GetIVLength(key->cipherMech);
     if (ivSize) {
         *ivSize = key->ivSize;
     }
@@ -881,7 +1088,8 @@ APU_MODULE_DECLARE_DATA const apr_crypto
     crypto_block_encrypt_init, crypto_block_encrypt,
     crypto_block_encrypt_finish, crypto_block_decrypt_init,
     crypto_block_decrypt, crypto_block_decrypt_finish,
-    crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error
+    crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
+    crypto_key
 };
 
 #endif

Modified: apr/apr-util/branches/1.6.x/crypto/apr_crypto_openssl.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/crypto/apr_crypto_openssl.c?rev=1752097&r1=1752096&r2=1752097&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/crypto/apr_crypto_openssl.c (original)
+++ apr/apr-util/branches/1.6.x/crypto/apr_crypto_openssl.c Sun Jul 10 15:32:12 2016
@@ -71,13 +71,20 @@ struct apr_crypto_block_t {
     int doPad;
 };
 
-static int key_3des_192 = APR_KEY_3DES_192;
-static int key_aes_128 = APR_KEY_AES_128;
-static int key_aes_192 = APR_KEY_AES_192;
-static int key_aes_256 = APR_KEY_AES_256;
+static struct apr_crypto_block_key_type_t key_types[] =
+{
+{ APR_KEY_3DES_192, 24, 8, 8 },
+{ APR_KEY_AES_128, 16, 16, 16 },
+{ APR_KEY_AES_192, 24, 16, 16 },
+{ APR_KEY_AES_256, 32, 16, 16 } };
+
+static struct apr_crypto_block_key_mode_t key_modes[] =
+{
+{ APR_MODE_ECB },
+{ APR_MODE_CBC } };
 
-static int mode_ecb = APR_MODE_ECB;
-static int mode_cbc = APR_MODE_CBC;
+/* sufficient space to wrap a key */
+#define BUFFER_SIZE 128
 
 /**
  * Fetch the most recent error from this driver.
@@ -293,17 +300,17 @@ static apr_status_t crypto_make(apr_cryp
     if (!f->types) {
         return APR_ENOMEM;
     }
-    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_3des_192));
-    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128));
-    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192));
-    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256));
+    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0]));
+    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1]));
+    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2]));
+    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3]));
 
     f->modes = apr_hash_make(pool);
     if (!f->modes) {
         return APR_ENOMEM;
     }
-    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb));
-    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc));
+    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0]));
+    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1]));
 
     apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
             apr_pool_cleanup_null);
@@ -326,7 +333,7 @@ static apr_status_t crypto_make(apr_cryp
 
 /**
  * @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t.
  *
  * @param types - hashtable of key types keyed to constants.
  * @param f - encryption context
@@ -341,7 +348,7 @@ static apr_status_t crypto_get_block_key
 
 /**
  * @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t.
  *
  * @param modes - hashtable of key modes keyed to constants.
  * @param f - encryption context
@@ -354,52 +361,13 @@ static apr_status_t crypto_get_block_key
     return APR_SUCCESS;
 }
 
-/**
- * @brief Create a key from the given passphrase. By default, the PBKDF2
- *        algorithm is used to generate the key from the passphrase. It is expected
- *        that the same pass phrase will generate the same key, regardless of the
- *        backend crypto platform used. The key is cleaned up when the context
- *        is cleaned, and may be reused with multiple encryption or decryption
- *        operations.
- * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
- *       *key is not NULL, *key must point at a previously created structure.
- * @param key The key returned, see note.
- * @param ivSize The size of the initialisation vector will be returned, based
- *               on whether an IV is relevant for this type of crypto.
- * @param pass The passphrase to use.
- * @param passLen The passphrase length in bytes
- * @param salt The salt to use.
- * @param saltLen The salt length in bytes
- * @param type 3DES_192, AES_128, AES_192, AES_256.
- * @param mode Electronic Code Book / Cipher Block Chaining.
- * @param doPad Pad if necessary.
- * @param iterations Iteration count
- * @param f The context to use.
- * @param p The pool to use.
- * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
- *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
- *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
- *         not known. APR_EPADDING if padding was requested but is not supported.
- *         APR_ENOTIMPL if not implemented.
+/*
+ * Work out which mechanism to use.
  */
-static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
-        const char *pass, apr_size_t passLen, const unsigned char * salt,
-        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
-        const apr_crypto_block_key_mode_e mode, const int doPad,
-        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key,
+        const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad, apr_pool_t *p)
 {
-    apr_crypto_key_t *key = *k;
-
-    if (!key) {
-        *k = key = apr_array_push(f->keys);
-    }
-    if (!key) {
-        return APR_ENOMEM;
-    }
-
-    key->f = f;
-    key->provider = f->provider;
-
     /* determine the cipher to be used */
     switch (type) {
 
@@ -461,6 +429,148 @@ static apr_status_t crypto_passphrase(ap
     }
     apr_crypto_clear(p, key->key, key->keyLen);
 
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_key(apr_crypto_key_t **k,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_crypto_key_t *key = *k;
+    apr_status_t rv;
+
+    if (!key) {
+        *k = key = apr_array_push(f->keys);
+    }
+    if (!key) {
+        return APR_ENOMEM;
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
+    switch (rec->ktype) {
+
+    case APR_CRYPTO_KTYPE_PASSPHRASE: {
+
+        /* generate the key */
+        if (PKCS5_PBKDF2_HMAC_SHA1(rec->k.passphrase.pass,
+                rec->k.passphrase.passLen,
+                (unsigned char *) rec->k.passphrase.salt,
+                rec->k.passphrase.saltLen, rec->k.passphrase.iterations,
+                key->keyLen, key->key) == 0) {
+            return APR_ENOKEY;
+        }
+
+        break;
+    }
+
+    case APR_CRYPTO_KTYPE_SECRET: {
+
+        /* sanity check - key correct size? */
+        if (rec->k.secret.secretLen != key->keyLen) {
+            return APR_EKEYLENGTH;
+        }
+
+        /* copy the key */
+        memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
+
+        break;
+    }
+
+    default: {
+
+        return APR_ENOKEY;
+
+    }
+    }
+
+    key->doPad = rec->pad;
+
+    /* note: openssl incorrectly returns non zero IV size values for ECB
+     * algorithms, so work around this by ignoring the IV size.
+     */
+    if (APR_MODE_ECB != rec->mode) {
+        key->ivSize = EVP_CIPHER_iv_length(key->cipher);
+    }
+
+    return APR_SUCCESS;
+}
+
+/**
+ * @brief Create a key from the given passphrase. By default, the PBKDF2
+ *        algorithm is used to generate the key from the passphrase. It is expected
+ *        that the same pass phrase will generate the same key, regardless of the
+ *        backend crypto platform used. The key is cleaned up when the context
+ *        is cleaned, and may be reused with multiple encryption or decryption
+ *        operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param ivSize The size of the initialisation vector will be returned, based
+ *               on whether an IV is relevant for this type of crypto.
+ * @param pass The passphrase to use.
+ * @param passLen The passphrase length in bytes
+ * @param salt The salt to use.
+ * @param saltLen The salt length in bytes
+ * @param type 3DES_192, AES_128, AES_192, AES_256.
+ * @param mode Electronic Code Book / Cipher Block Chaining.
+ * @param doPad Pad if necessary.
+ * @param iterations Iteration count
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
+        const char *pass, apr_size_t passLen, const unsigned char * salt,
+        apr_size_t saltLen, const apr_crypto_block_key_type_e type,
+        const apr_crypto_block_key_mode_e mode, const int doPad,
+        const int iterations, const apr_crypto_t *f, apr_pool_t *p)
+{
+    apr_crypto_key_t *key = *k;
+    apr_status_t rv;
+
+    if (!key) {
+        *k = key = apr_array_push(f->keys);
+    }
+    if (!key) {
+        return APR_ENOMEM;
+    }
+
+    key->f = f;
+    key->provider = f->provider;
+
+    /* decide on what cipher mechanism we will be using */
+    rv = crypto_cipher_mechanism(key, type, mode, doPad, p);
+    if (APR_SUCCESS != rv) {
+        return rv;
+    }
+
     /* generate the key */
     if (PKCS5_PBKDF2_HMAC_SHA1(pass, passLen, (unsigned char *) salt, saltLen,
             iterations, key->keyLen, key->key) == 0) {
@@ -849,7 +959,8 @@ APU_MODULE_DECLARE_DATA const apr_crypto
     crypto_block_encrypt_init, crypto_block_encrypt,
     crypto_block_encrypt_finish, crypto_block_decrypt_init,
     crypto_block_decrypt, crypto_block_decrypt_finish,
-    crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error
+    crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error,
+    crypto_key
 };
 
 #endif

Modified: apr/apr-util/branches/1.6.x/include/apr_crypto.h
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/include/apr_crypto.h?rev=1752097&r1=1752096&r2=1752097&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/include/apr_crypto.h (original)
+++ apr/apr-util/branches/1.6.x/include/apr_crypto.h Sun Jul 10 15:32:12 2016
@@ -127,6 +127,48 @@ typedef struct apr_crypto_config_t apr_c
 typedef struct apr_crypto_key_t apr_crypto_key_t;
 typedef struct apr_crypto_block_t apr_crypto_block_t;
 
+typedef struct apr_crypto_block_key_type_t {
+    apr_crypto_block_key_type_e type;
+    int keysize;
+    int blocksize;
+    int ivsize;
+} apr_crypto_block_key_type_t;
+
+typedef struct apr_crypto_block_key_mode_t {
+    apr_crypto_block_key_mode_e mode;
+} apr_crypto_block_key_mode_t;
+
+typedef struct apr_crypto_passphrase_t {
+    const char *pass;
+    apr_size_t passLen;
+    const unsigned char * salt;
+    apr_size_t saltLen;
+    int iterations;
+} apr_crypto_passphrase_t;
+
+typedef struct apr_crypto_secret_t {
+    const unsigned char *secret;
+    apr_size_t secretLen;
+} apr_crypto_secret_t;
+
+typedef enum {
+    /** Key is derived from a passphrase */
+    APR_CRYPTO_KTYPE_PASSPHRASE     = 1,
+    /** Key is derived from a raw key */
+    APR_CRYPTO_KTYPE_SECRET     = 2,
+} apr_crypto_key_type;
+
+typedef struct apr_crypto_key_rec_t {
+    apr_crypto_key_type ktype;
+    apr_crypto_block_key_type_e type;
+    apr_crypto_block_key_mode_e mode;
+    int pad;
+    union {
+        apr_crypto_passphrase_t passphrase;
+        apr_crypto_secret_t secret;
+    } k;
+} apr_crypto_key_rec_t;
+
 /**
  * @brief Perform once-only initialisation. Call once only.
  *
@@ -209,7 +251,8 @@ APU_DECLARE(apr_status_t) apr_crypto_mak
 
 /**
  * @brief Get a hash table of key types, keyed by the name of the type against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_type_t, which in turn begins with an
+ * integer.
  *
  * @param types - hashtable of key types keyed to constants.
  * @param f - encryption context
@@ -220,7 +263,8 @@ APU_DECLARE(apr_status_t) apr_crypto_get
 
 /**
  * @brief Get a hash table of key modes, keyed by the name of the mode against
- * an integer pointer constant.
+ * a pointer to apr_crypto_block_key_mode_t, which in turn begins with an
+ * integer.
  *
  * @param modes - hashtable of key modes keyed to constants.
  * @param f - encryption context
@@ -230,6 +274,25 @@ APU_DECLARE(apr_status_t) apr_crypto_get
         const apr_crypto_t *f);
 
 /**
+ * @brief Create a key from the provided secret or passphrase. The key is cleaned
+ *        up when the context is cleaned, and may be reused with multiple encryption
+ *        or decryption operations.
+ * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+ *       *key is not NULL, *key must point at a previously created structure.
+ * @param key The key returned, see note.
+ * @param rec The key record, from which the key will be derived.
+ * @param f The context to use.
+ * @param p The pool to use.
+ * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+ *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+ *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+ *         not known. APR_EPADDING if padding was requested but is not supported.
+ *         APR_ENOTIMPL if not implemented.
+ */
+APR_DECLARE(apr_status_t) apr_crypto_key(apr_crypto_key_t **key,
+        const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p);
+
+/**
  * @brief Create a key from the given passphrase. By default, the PBKDF2
  *        algorithm is used to generate the key from the passphrase. It is expected
  *        that the same pass phrase will generate the same key, regardless of the
@@ -256,6 +319,7 @@ APU_DECLARE(apr_status_t) apr_crypto_get
  *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
  *         not known. APR_EPADDING if padding was requested but is not supported.
  *         APR_ENOTIMPL if not implemented.
+ * @deprecated Replaced by apr_crypto_key().
  */
 APU_DECLARE(apr_status_t) apr_crypto_passphrase(apr_crypto_key_t **key,
         apr_size_t *ivSize, const char *pass, apr_size_t passLen,

Modified: apr/apr-util/branches/1.6.x/include/private/apr_crypto_internal.h
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/include/private/apr_crypto_internal.h?rev=1752097&r1=1752096&r2=1752097&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/include/private/apr_crypto_internal.h (original)
+++ apr/apr-util/branches/1.6.x/include/private/apr_crypto_internal.h Sun Jul 10 15:32:12 2016
@@ -59,7 +59,7 @@ struct apr_crypto_driver_t {
 
     /**
      * @brief Get a hash table of key types, keyed by the name of the type against
-     * an integer pointer constant.
+     * a pointer to apr_crypto_block_key_type_t.
      *
      * @param types - hashtable of key types keyed to constants.
      * @param f - encryption context
@@ -70,7 +70,7 @@ struct apr_crypto_driver_t {
 
     /**
      * @brief Get a hash table of key modes, keyed by the name of the mode against
-     * an integer pointer constant.
+     * a pointer to apr_crypto_block_key_mode_t.
      *
      * @param modes - hashtable of key modes keyed to constants.
      * @param f - encryption context
@@ -267,6 +267,25 @@ struct apr_crypto_driver_t {
      */
     apr_status_t (*error)(const apu_err_t **result, const apr_crypto_t *f);
 
+    /**
+     * @brief Create a key from the provided secret or passphrase. The key is cleaned
+     *        up when the context is cleaned, and may be reused with multiple encryption
+     *        or decryption operations.
+     * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
+     *       *key is not NULL, *key must point at a previously created structure.
+     * @param key The key returned, see note.
+     * @param rec The key record, from which the key will be derived.
+     * @param f The context to use.
+     * @param p The pool to use.
+     * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend
+     *         error occurred while generating the key. APR_ENOCIPHER if the type or mode
+     *         is not supported by the particular backend. APR_EKEYTYPE if the key type is
+     *         not known. APR_EPADDING if padding was requested but is not supported.
+     *         APR_ENOTIMPL if not implemented.
+     */
+    apr_status_t (*key)(apr_crypto_key_t **key, const apr_crypto_key_rec_t *rec,
+            const apr_crypto_t *f, apr_pool_t *p);
+
 };
 
 #endif

Modified: apr/apr-util/branches/1.6.x/test/testcrypto.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.6.x/test/testcrypto.c?rev=1752097&r1=1752096&r2=1752097&view=diff
==============================================================================
--- apr/apr-util/branches/1.6.x/test/testcrypto.c (original)
+++ apr/apr-util/branches/1.6.x/test/testcrypto.c Sun Jul 10 15:32:12 2016
@@ -42,24 +42,24 @@ static const apr_crypto_driver_t *get_dr
     rv = apr_crypto_get_driver(&driver, name, params, &result, pool);
     if (APR_ENOTIMPL == rv) {
         ABTS_NOT_IMPL(tc,
-                apr_psprintf(pool, "\nCrypto driver '%s' not implemented, skipping", (char *)name));
+                apr_psprintf(pool, "Crypto driver '%s' not implemented", (char *)name));
         return NULL;
     }
     if (APR_EDSOOPEN == rv) {
         ABTS_NOT_IMPL(tc,
-                apr_psprintf(pool, "\nCrypto driver '%s' DSO could not be opened, skipping", (char *)name));
+                apr_psprintf(pool, "Crypto driver '%s' DSO could not be opened", (char *)name));
         return NULL;
     }
     if (APR_SUCCESS != rv && result) {
         char err[1024];
         apr_strerror(rv, err, sizeof(err) - 1);
-        fprintf(stderr, "\nget_driver error %d: %s: '%s' native error %d: %s (%s)\n",
+        fprintf(stderr, "get_driver error %d: %s: '%s' native error %d: %s (%s),",
                 rv, err, name, result->rc, result->reason ? result->reason : "",
                 result->msg ? result->msg : "");
     }
-    ABTS_ASSERT(tc, apr_psprintf(pool, "\nfailed to apr_crypto_get_driver for '%s' with %d",
+    ABTS_ASSERT(tc, apr_psprintf(pool, "failed to apr_crypto_get_driver for '%s' with %d",
                 name, rv), rv == APR_SUCCESS);
-    ABTS_ASSERT(tc, "\napr_crypto_get_driver returned NULL", driver != NULL);
+    ABTS_ASSERT(tc, "apr_crypto_get_driver returned NULL", driver != NULL);
     if (!driver || rv) {
         return NULL;
     }
@@ -73,7 +73,7 @@ static const apr_crypto_driver_t *get_ns
 {
 
     /* initialise NSS */
-    return get_driver(tc, pool, "nss", "dir=data");
+    return get_driver(tc, pool, "nss", "");
 
 }
 
@@ -111,6 +111,59 @@ static apr_crypto_t *make(abts_case *tc,
 
 }
 
+static const apr_crypto_key_t *keysecret(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+        apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
+        int doPad, apr_size_t secretLen, const char *description)
+{
+    apr_crypto_key_t *key = NULL;
+    const apu_err_t *result = NULL;
+    apr_crypto_key_rec_t *rec = apr_pcalloc(pool, sizeof(apr_crypto_key_rec_t));
+    apr_status_t rv;
+
+    if (!f) {
+        return NULL;
+    }
+
+    rec->ktype = APR_CRYPTO_KTYPE_SECRET;
+    rec->type = type;
+    rec->mode = mode;
+    rec->pad = doPad;
+    rec->k.secret.secret = apr_pcalloc(pool, secretLen);
+    rec->k.secret.secretLen = secretLen;
+
+    /* init the passphrase */
+    rv = apr_crypto_key(&key, rec, f, pool);
+    if (APR_ENOCIPHER == rv) {
+        apr_crypto_error(&result, f);
+        ABTS_NOT_IMPL(tc,
+                apr_psprintf(pool, "skipped: %s %s key return APR_ENOCIPHER: error %d: %s (%s)\n", description, apr_crypto_driver_name(driver), result->rc, result->reason ? result->reason : "", result->msg ? result->msg : ""));
+        return NULL;
+    }
+    else {
+        if (APR_SUCCESS != rv) {
+            apr_crypto_error(&result, f);
+            fprintf(stderr, "key: %s %s apr error %d / native error %d: %s (%s)\n",
+                    description, apr_crypto_driver_name(driver), rv, result->rc,
+                    result->reason ? result->reason : "",
+                    result->msg ? result->msg : "");
+        }
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYLENGTH", rv != APR_EKEYLENGTH);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_ENOKEY", rv != APR_ENOKEY);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EPADDING",
+                rv != APR_EPADDING);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYTYPE",
+                rv != APR_EKEYTYPE);
+        ABTS_ASSERT(tc, "failed to apr_crypto_key", rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, "apr_crypto_key returned NULL context", key != NULL);
+    }
+    if (rv) {
+        return NULL;
+    }
+    return key;
+
+}
+
 static const apr_crypto_key_t *passphrase(abts_case *tc, apr_pool_t *pool,
         const apr_crypto_driver_t *driver, const apr_crypto_t *f,
         apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
@@ -142,8 +195,8 @@ static const apr_crypto_key_t *passphras
     else {
         if (APR_SUCCESS != rv) {
             apr_crypto_error(&result, f);
-            fprintf(stderr, "passphrase: %s %s native error %d: %s (%s)\n",
-                    description, apr_crypto_driver_name(driver), result->rc,
+            fprintf(stderr, "passphrase: %s %s apr error %d / native error %d: %s (%s)\n",
+                    description, apr_crypto_driver_name(driver), rv, result->rc,
                     result->reason ? result->reason : "",
                     result->msg ? result->msg : "");
         }
@@ -160,6 +213,64 @@ static const apr_crypto_key_t *passphras
 
 }
 
+static const apr_crypto_key_t *keypassphrase(abts_case *tc, apr_pool_t *pool,
+        const apr_crypto_driver_t *driver, const apr_crypto_t *f,
+        apr_crypto_block_key_type_e type, apr_crypto_block_key_mode_e mode,
+        int doPad, const char *description)
+{
+
+    apr_crypto_key_t *key = NULL;
+    const apu_err_t *result = NULL;
+    const char *pass = "secret";
+    const char *salt = "salt";
+    apr_crypto_key_rec_t *rec = apr_pcalloc(pool, sizeof(apr_crypto_key_rec_t));
+    apr_status_t rv;
+
+    if (!f) {
+        return NULL;
+    }
+
+    rec->ktype = APR_CRYPTO_KTYPE_PASSPHRASE;
+    rec->type = type;
+    rec->mode = mode;
+    rec->pad = doPad;
+    rec->k.passphrase.pass = pass;
+    rec->k.passphrase.passLen = strlen(pass);
+    rec->k.passphrase.salt = (unsigned char *)salt;
+    rec->k.passphrase.saltLen = strlen(salt);
+    rec->k.passphrase.iterations = 4096;
+
+    /* init the passphrase */
+    rv = apr_crypto_key(&key, rec, f, pool);
+    if (APR_ENOCIPHER == rv) {
+        apr_crypto_error(&result, f);
+        ABTS_NOT_IMPL(tc, apr_psprintf(pool,
+                        "skipped: %s %s key passphrase return APR_ENOCIPHER: error %d: %s (%s)\n",
+                        description, apr_crypto_driver_name(driver), result->rc,
+                        result->reason ? result->reason : "", result->msg ? result->msg : ""));
+        return NULL;
+    }
+    else {
+        if (APR_SUCCESS != rv) {
+            apr_crypto_error(&result, f);
+            fprintf(stderr, "key passphrase: %s %s apr error %d / native error %d: %s (%s)\n",
+                    description, apr_crypto_driver_name(driver), rv, result->rc,
+                    result->reason ? result->reason : "",
+                    result->msg ? result->msg : "");
+        }
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_ENOKEY", rv != APR_ENOKEY);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EPADDING", rv != APR_EPADDING);
+        ABTS_ASSERT(tc, "apr_crypto_key returned APR_EKEYTYPE", rv != APR_EKEYTYPE);
+        ABTS_ASSERT(tc, "failed to apr_crypto_key", rv == APR_SUCCESS);
+        ABTS_ASSERT(tc, "apr_crypto_key returned NULL context", key != NULL);
+    }
+    if (rv) {
+        return NULL;
+    }
+    return key;
+
+}
+
 static unsigned char *encrypt_block(abts_case *tc, apr_pool_t *pool,
         const apr_crypto_driver_t *driver, const apr_crypto_t *f,
         const apr_crypto_key_t *key, const unsigned char *in,
@@ -349,7 +460,8 @@ static void crypto_block_cross(abts_case
         const apr_crypto_driver_t **drivers,
         const apr_crypto_block_key_type_e type,
         const apr_crypto_block_key_mode_e mode, int doPad,
-        const unsigned char *in, apr_size_t inlen, const char *description)
+        const unsigned char *in, apr_size_t inlen, apr_size_t secretLen,
+        const char *description)
 {
     const apr_crypto_driver_t *driver1 = drivers[0];
     const apr_crypto_driver_t *driver2 = drivers[1];
@@ -357,6 +469,10 @@ static void crypto_block_cross(abts_case
     apr_crypto_t *f2 = NULL;
     const apr_crypto_key_t *key1 = NULL;
     const apr_crypto_key_t *key2 = NULL;
+    const apr_crypto_key_t *key3 = NULL;
+    const apr_crypto_key_t *key4 = NULL;
+    const apr_crypto_key_t *key5 = NULL;
+    const apr_crypto_key_t *key6 = NULL;
 
     unsigned char *cipherText = NULL;
     apr_size_t cipherTextLen = 0;
@@ -378,7 +494,51 @@ static void crypto_block_cross(abts_case
 
     if (cipherText && plainText) {
         if (memcmp(in, plainText, inlen)) {
-            fprintf(stderr, "cross mismatch: %s %s/%s\n", description,
+            fprintf(stderr, "passphrase cross mismatch: %s %s/%s\n", description,
+                    apr_crypto_driver_name(driver1), apr_crypto_driver_name(
+                            driver2));
+        }
+        ABTS_STR_EQUAL(tc, (char *)in, (char *)plainText);
+    }
+
+    key3 = keysecret(tc, pool, driver1, f1, type, mode, doPad, secretLen, description);
+    key4 = keysecret(tc, pool, driver2, f2, type, mode, doPad, secretLen, description);
+
+    iv = NULL;
+    blockSize = 0;
+    cipherText = NULL;
+    plainText = NULL;
+    cipherText = encrypt_block(tc, pool, driver1, f1, key3, in, inlen,
+            &cipherText, &cipherTextLen, &iv, &blockSize, description);
+    plainText = decrypt_block(tc, pool, driver2, f2, key4, cipherText,
+            cipherTextLen, &plainText, &plainTextLen, iv, &blockSize,
+            description);
+
+    if (cipherText && plainText) {
+        if (memcmp(in, plainText, inlen)) {
+            fprintf(stderr, "key secret cross mismatch: %s %s/%s\n", description,
+                    apr_crypto_driver_name(driver1), apr_crypto_driver_name(
+                            driver2));
+        }
+        ABTS_STR_EQUAL(tc, (char *)in, (char *)plainText);
+    }
+
+    key5 = keypassphrase(tc, pool, driver1, f1, type, mode, doPad, description);
+    key6 = keypassphrase(tc, pool, driver2, f2, type, mode, doPad, description);
+
+    iv = NULL;
+    blockSize = 0;
+    cipherText = NULL;
+    plainText = NULL;
+    cipherText = encrypt_block(tc, pool, driver1, f1, key5, in, inlen,
+            &cipherText, &cipherTextLen, &iv, &blockSize, description);
+    plainText = decrypt_block(tc, pool, driver2, f2, key6, cipherText,
+            cipherTextLen, &plainText, &plainTextLen, iv, &blockSize,
+            description);
+
+    if (cipherText && plainText) {
+        if (memcmp(in, plainText, inlen)) {
+            fprintf(stderr, "key passphrase cross mismatch: %s %s/%s\n", description,
                     apr_crypto_driver_name(driver1), apr_crypto_driver_name(
                             driver2));
         }
@@ -405,6 +565,63 @@ static void test_crypto_init(abts_case *
 }
 
 /**
+ * Simple test of OpenSSL key.
+ */
+static void test_crypto_key_openssl(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f = NULL;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_openssl_driver(tc, pool);
+
+    f = make(tc, pool, driver);
+    keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+            "KEY_AES_256/MODE_CBC");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of NSS key.
+ */
+static void test_crypto_key_nss(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f = NULL;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_nss_driver(tc, pool);
+
+    f = make(tc, pool, driver);
+    keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+            "KEY_AES_256/MODE_CBC");
+    apr_pool_destroy(pool);
+
+}
+
+/**
+ * Simple test of CommonCrypto key.
+ */
+static void test_crypto_key_commoncrypto(abts_case *tc, void *data)
+{
+    apr_pool_t *pool = NULL;
+    const apr_crypto_driver_t *driver;
+    apr_crypto_t *f = NULL;
+
+    apr_pool_create(&pool, NULL);
+    driver = get_commoncrypto_driver(tc, pool);
+
+    f = make(tc, pool, driver);
+    keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32,
+            "KEY_AES_256/MODE_CBC");
+    apr_pool_destroy(pool);
+
+}
+
+/**
  * Simple test of OpenSSL block crypt.
  */
 static void test_crypto_block_openssl(abts_case *tc, void *data)
@@ -419,21 +636,21 @@ static void test_crypto_block_openssl(ab
     drivers[0] = get_openssl_driver(tc, pool);
     drivers[1] = get_openssl_driver(tc, pool);
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0,
-            in, inlen, "KEY_3DES_192/MODE_ECB");
+            in, inlen, 24, "KEY_3DES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
     apr_pool_destroy(pool);
 
 }
@@ -453,21 +670,21 @@ static void test_crypto_block_nss(abts_c
     drivers[0] = get_nss_driver(tc, pool);
     drivers[1] = get_nss_driver(tc, pool);
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
     /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
     /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, "KEY_3DES_192/MODE_ECB"); */
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
     apr_pool_destroy(pool);
 
 }
@@ -487,21 +704,21 @@ static void test_crypto_block_commoncryp
     drivers[0] = get_commoncrypto_driver(tc, pool);
     drivers[1] = get_commoncrypto_driver(tc, pool);
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0,
-            in, inlen, "KEY_3DES_192/MODE_ECB");
+            in, inlen, 24, "KEY_3DES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
     apr_pool_destroy(pool);
 
 }
@@ -522,22 +739,22 @@ static void test_crypto_block_nss_openss
     drivers[1] = get_openssl_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
 
     /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
-    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
     apr_pool_destroy(pool);
 
 }
@@ -557,23 +774,23 @@ static void test_crypto_block_openssl_ns
     drivers[0] = get_openssl_driver(tc, pool);
     drivers[1] = get_nss_driver(tc, pool);
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
 
     /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
-    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 0, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
     apr_pool_destroy(pool);
 
 }
@@ -595,21 +812,21 @@ static void test_crypto_block_openssl_co
     drivers[1] = get_commoncrypto_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_3DES_192/MODE_CBC");
+            inlen, 24, "KEY_3DES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_3DES_192/MODE_ECB");
+            inlen, 24, "KEY_3DES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
     apr_pool_destroy(pool);
 
 }
@@ -631,21 +848,21 @@ static void test_crypto_block_commoncryp
     drivers[1] = get_openssl_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_3DES_192/MODE_CBC");
+            inlen, 24, "KEY_3DES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_3DES_192/MODE_ECB");
+            inlen, 24, "KEY_3DES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 0, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 0, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
     apr_pool_destroy(pool);
 
 }
@@ -666,21 +883,21 @@ static void test_crypto_block_openssl_pa
     drivers[1] = get_openssl_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1,
-            in, inlen, "KEY_3DES_192/MODE_ECB");
+            in, inlen, 24, "KEY_3DES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
 
     apr_pool_destroy(pool);
 
@@ -703,27 +920,27 @@ static void test_crypto_block_nss_pad(ab
     drivers[1] = get_nss_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
     /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
-    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
 
     /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
-    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, "KEY_AES_256/MODE_ECB");*/
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
 
     /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
-    /*crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 1, in, inlen, "KEY_AES_192/MODE_ECB");*/
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_192, MODE_ECB, 1, in, inlen, 24, "KEY_AES_192/MODE_ECB");*/
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
 
     /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
-    /*crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 1, in, inlen, "KEY_AES_128/MODE_ECB");*/
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_128, MODE_ECB, 1, in, inlen, 16, "KEY_AES_128/MODE_ECB");*/
 
     apr_pool_destroy(pool);
 
@@ -745,21 +962,21 @@ static void test_crypto_block_commoncryp
     drivers[1] = get_commoncrypto_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1,
-            in, inlen, "KEY_3DES_192/MODE_ECB");
+            in, inlen, 24, "KEY_3DES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
 
     apr_pool_destroy(pool);
 
@@ -781,30 +998,30 @@ static void test_crypto_block_nss_openss
     drivers[1] = get_openssl_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
 
     /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
-    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
 
     /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
-    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, "KEY_AES_256/MODE_ECB");*/
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
 
     /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
     /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_192/MODE_ECB");*/
+            inlen, 24, "KEY_AES_192/MODE_ECB");*/
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
 
     /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
     /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_128/MODE_ECB");*/
+            inlen, 16, "KEY_AES_128/MODE_ECB");*/
 
     apr_pool_destroy(pool);
 
@@ -825,30 +1042,30 @@ static void test_crypto_block_openssl_ns
     drivers[0] = get_openssl_driver(tc, pool);
     drivers[1] = get_nss_driver(tc, pool);
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1,
-            in, inlen, "KEY_3DES_192/MODE_CBC");
+            in, inlen, 24, "KEY_3DES_192/MODE_CBC");
 
     /* KEY_3DES_192 / MODE_ECB doesn't work on NSS */
-    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, "KEY_3DES_192/MODE_ECB"); */
+    /* crypto_block_cross(tc, pool, drivers, KEY_3DES_192, MODE_ECB, 1, in, inlen, 24, "KEY_3DES_192/MODE_ECB"); */
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
 
     /* KEY_AES_256 / MODE_ECB doesn't support padding on NSS */
-    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, "KEY_AES_256/MODE_ECB");*/
+    /*crypto_block_cross(tc, pool, drivers, KEY_AES_256, MODE_ECB, 1, in, inlen, 32, "KEY_AES_256/MODE_ECB");*/
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in, inlen,
-            "KEY_AES_192/MODE_CBC");
+            24, "KEY_AES_192/MODE_CBC");
 
     /* KEY_AES_192 / MODE_ECB doesn't support padding on NSS */
     /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in, inlen,
-            "KEY_AES_192/MODE_ECB");*/
+            24, "KEY_AES_192/MODE_ECB");*/
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in, inlen,
-            "KEY_AES_128/MODE_CBC");
+            16, "KEY_AES_128/MODE_CBC");
 
     /* KEY_AES_128 / MODE_ECB doesn't support padding on NSS */
     /*crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in, inlen,
-            "KEY_AES_128/MODE_ECB");*/
+            16, "KEY_AES_128/MODE_ECB");*/
 
     apr_pool_destroy(pool);
 
@@ -872,21 +1089,21 @@ static void test_crypto_block_commoncryp
     drivers[1] = get_openssl_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1, in,
-            inlen, "KEY_3DES_192/MODE_CBC");
+            inlen, 24, "KEY_3DES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1, in,
-            inlen, "KEY_3DES_192/MODE_ECB");
+            inlen, 24, "KEY_3DES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
 
     apr_pool_destroy(pool);
 
@@ -910,21 +1127,21 @@ static void test_crypto_block_openssl_co
     drivers[1] = get_commoncrypto_driver(tc, pool);
 
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_CBC, 1, in,
-            inlen, "KEY_3DES_192/MODE_CBC");
+            inlen, 24, "KEY_3DES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_3DES_192, APR_MODE_ECB, 1, in,
-            inlen, "KEY_3DES_192/MODE_ECB");
+            inlen, 24, "KEY_3DES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_256/MODE_CBC");
+            inlen, 32, "KEY_AES_256/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_256, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_256/MODE_ECB");
+            inlen, 32, "KEY_AES_256/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_192/MODE_CBC");
+            inlen, 24, "KEY_AES_192/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_192, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_192/MODE_ECB");
+            inlen, 24, "KEY_AES_192/MODE_ECB");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_CBC, 1, in,
-            inlen, "KEY_AES_128/MODE_CBC");
+            inlen, 16, "KEY_AES_128/MODE_CBC");
     crypto_block_cross(tc, pool, drivers, APR_KEY_AES_128, APR_MODE_ECB, 1, in,
-            inlen, "KEY_AES_128/MODE_ECB");
+            inlen, 16, "KEY_AES_128/MODE_ECB");
 
     apr_pool_destroy(pool);
 
@@ -1165,6 +1382,15 @@ abts_suite *testcrypto(abts_suite *suite
     /* test simple init and shutdown */
     abts_run_test(suite, test_crypto_init, NULL);
 
+    /* test key parsing - openssl */
+    abts_run_test(suite, test_crypto_key_openssl, NULL);
+
+    /* test key parsing - nss */
+    abts_run_test(suite, test_crypto_key_nss, NULL);
+
+    /* test key parsing - commoncrypto */
+    abts_run_test(suite, test_crypto_key_commoncrypto, NULL);
+
     /* test a simple encrypt / decrypt operation - openssl */
     abts_run_test(suite, test_crypto_block_openssl, NULL);