aboutsummaryrefslogtreecommitdiff
path: root/crypto/apr_crypto_nss.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/apr_crypto_nss.c')
-rw-r--r--crypto/apr_crypto_nss.c421
1 files changed, 324 insertions, 97 deletions
diff --git a/crypto/apr_crypto_nss.c b/crypto/apr_crypto_nss.c
index b345953de73d..47d164094614 100644
--- a/crypto/apr_crypto_nss.c
+++ b/crypto/apr_crypto_nss.c
@@ -50,7 +50,6 @@ struct apr_crypto_t {
apr_pool_t *pool;
const apr_crypto_driver_t *provider;
apu_err_t *result;
- apr_array_header_t *keys;
apr_crypto_config_t *config;
apr_hash_t *types;
apr_hash_t *modes;
@@ -68,6 +67,7 @@ struct apr_crypto_key_t {
SECOidTag cipherOid;
PK11SymKey *symKey;
int ivSize;
+ int keyLength;
};
struct apr_crypto_block_t {
@@ -76,16 +76,24 @@ struct apr_crypto_block_t {
const apr_crypto_t *f;
PK11Context *ctx;
apr_crypto_key_t *key;
+ SECItem *secParam;
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.
@@ -107,6 +115,8 @@ static apr_status_t crypto_shutdown(void)
if (NSS_IsInitialized()) {
SECStatus s = NSS_Shutdown();
if (s != SECSuccess) {
+ fprintf(stderr, "NSS failed to shutdown, possible leak: %d: %s",
+ PR_GetError(), PR_ErrorToName(s));
return APR_EINIT;
}
}
@@ -197,9 +207,6 @@ static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
return APR_EREINIT;
}
- apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
- apr_pool_cleanup_null);
-
if (keyPrefix || certPrefix || secmod) {
s = NSS_Initialize(dir, certPrefix, keyPrefix, secmod, flags);
}
@@ -211,15 +218,20 @@ static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
}
if (s != SECSuccess) {
if (result) {
+ /* Note: all memory must be owned by the caller, in case we're unloaded */
apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t));
err->rc = PR_GetError();
- err->msg = PR_ErrorToName(s);
- err->reason = "Error during 'nss' initialisation";
+ err->msg = apr_pstrdup(pool, PR_ErrorToName(s));
+ err->reason = apr_pstrdup(pool, "Error during 'nss' initialisation");
*result = err;
}
+
return APR_ECRYPT;
}
+ apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper,
+ apr_pool_cleanup_null);
+
return APR_SUCCESS;
}
@@ -233,6 +245,11 @@ static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
static apr_status_t crypto_block_cleanup(apr_crypto_block_t *block)
{
+ if (block->secParam) {
+ SECITEM_FreeItem(block->secParam, PR_TRUE);
+ block->secParam = NULL;
+ }
+
if (block->ctx) {
PK11_DestroyContext(block->ctx, PR_TRUE);
block->ctx = NULL;
@@ -248,6 +265,15 @@ static apr_status_t crypto_block_cleanup_helper(void *data)
return crypto_block_cleanup(block);
}
+static apr_status_t crypto_key_cleanup(void *data)
+{
+ apr_crypto_key_t *key = data;
+ if (key->symKey) {
+ PK11_FreeSymKey(key->symKey);
+ key->symKey = NULL;
+ }
+ return APR_SUCCESS;
+}
/**
* @brief Clean encryption / decryption context.
* @note After cleanup, a context is free to be reused if necessary.
@@ -256,15 +282,6 @@ static apr_status_t crypto_block_cleanup_helper(void *data)
*/
static apr_status_t crypto_cleanup(apr_crypto_t *f)
{
- apr_crypto_key_t *key;
- if (f->keys) {
- while ((key = apr_array_pop(f->keys))) {
- if (key->symKey) {
- PK11_FreeSymKey(key->symKey);
- key->symKey = NULL;
- }
- }
- }
return APR_SUCCESS;
}
@@ -308,23 +325,22 @@ static apr_status_t crypto_make(apr_crypto_t **ff,
if (!f->result) {
return APR_ENOMEM;
}
- f->keys = apr_array_make(pool, 10, sizeof(apr_crypto_key_t));
f->types = apr_hash_make(pool);
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);
@@ -335,7 +351,7 @@ static apr_status_t crypto_make(apr_crypto_t **ff,
/**
* @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
@@ -350,7 +366,7 @@ static apr_status_t crypto_get_block_key_types(apr_hash_t **types,
/**
* @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
@@ -363,57 +379,13 @@ static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes,
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) {
@@ -426,6 +398,7 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
return APR_ENOCIPHER;
/* No OID for CKM_DES3_ECB; */
}
+ key->keyLength = 24;
break;
case (APR_KEY_AES_128):
if (APR_MODE_CBC == mode) {
@@ -434,6 +407,7 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
else {
key->cipherOid = SEC_OID_AES_128_ECB;
}
+ key->keyLength = 16;
break;
case (APR_KEY_AES_192):
if (APR_MODE_CBC == mode) {
@@ -442,6 +416,7 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
else {
key->cipherOid = SEC_OID_AES_192_ECB;
}
+ key->keyLength = 24;
break;
case (APR_KEY_AES_256):
if (APR_MODE_CBC == mode) {
@@ -450,6 +425,7 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
else {
key->cipherOid = SEC_OID_AES_256_ECB;
}
+ key->keyLength = 32;
break;
default:
/* unknown key type, give up */
@@ -464,13 +440,266 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
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_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ apr_pool_cleanup_register(p, key, crypto_key_cleanup,
+ apr_pool_cleanup_null);
+ }
+
+ 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_pcalloc(p, sizeof *key);
+ if (!key) {
+ return APR_ENOMEM;
+ }
+ apr_pool_cleanup_register(p, key, crypto_key_cleanup,
+ apr_pool_cleanup_null);
+ }
+
+ 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;
@@ -478,9 +707,9 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
saltItem.len = saltLen;
/* generate the key */
- /* pbeAlg and cipherAlg are the same. NSS decides the keylength. */
+ /* pbeAlg and cipherAlg are the same. */
algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid,
- SEC_OID_HMAC_SHA1, 0, iterations, &saltItem);
+ SEC_OID_HMAC_SHA1, key->keyLength, iterations, &saltItem);
if (algid) {
slot = PK11_GetBestSlot(key->cipherMech, wincx);
if (slot) {
@@ -501,7 +730,6 @@ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize,
}
}
- key->ivSize = PK11_GetIVLength(key->cipherMech);
if (ivSize) {
*ivSize = key->ivSize;
}
@@ -530,7 +758,6 @@ static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
apr_size_t *blockSize, apr_pool_t *p)
{
PRErrorCode perr;
- SECItem * secParam;
SECItem ivItem;
unsigned char * usedIv;
apr_crypto_block_t *block = *ctx;
@@ -569,14 +796,14 @@ static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
}
ivItem.data = usedIv;
ivItem.len = key->ivSize;
- secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
+ block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
}
else {
- secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
+ block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
}
- block->blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
+ block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_ENCRYPT,
- key->symKey, secParam);
+ key->symKey, block->secParam);
/* did an error occur? */
perr = PORT_GetError();
@@ -587,7 +814,7 @@ static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
}
if (blockSize) {
- *blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
+ *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
}
return APR_SUCCESS;
@@ -711,7 +938,6 @@ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
const apr_crypto_key_t *key, apr_pool_t *p)
{
PRErrorCode perr;
- SECItem * secParam;
apr_crypto_block_t *block = *ctx;
if (!block) {
*ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
@@ -733,14 +959,14 @@ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
}
ivItem.data = (unsigned char*) iv;
ivItem.len = key->ivSize;
- secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
+ block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
}
else {
- secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
+ block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
}
- block->blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
+ block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_DECRYPT,
- key->symKey, secParam);
+ key->symKey, block->secParam);
/* did an error occur? */
perr = PORT_GetError();
@@ -751,7 +977,7 @@ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
}
if (blockSize) {
- *blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
+ *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam);
}
return APR_SUCCESS;
@@ -864,7 +1090,8 @@ APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_nss_driver = {
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