summaryrefslogtreecommitdiff
path: root/nss/lib/pkcs12
diff options
context:
space:
mode:
Diffstat (limited to 'nss/lib/pkcs12')
-rw-r--r--nss/lib/pkcs12/p12d.c46
-rw-r--r--nss/lib/pkcs12/p12e.c23
-rw-r--r--nss/lib/pkcs12/p12local.c67
-rw-r--r--nss/lib/pkcs12/p12local.h11
-rw-r--r--nss/lib/pkcs12/p12plcy.c3
5 files changed, 136 insertions, 14 deletions
diff --git a/nss/lib/pkcs12/p12d.c b/nss/lib/pkcs12/p12d.c
index d0b6476..57333ac 100644
--- a/nss/lib/pkcs12/p12d.c
+++ b/nss/lib/pkcs12/p12d.c
@@ -177,6 +177,8 @@ sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg;
PK11SlotInfo *slot;
PK11SymKey *bulkKey;
+ SECItem pwitem = { 0 };
+ SECOidTag algorithm;
if (!p12dcx) {
return NULL;
@@ -189,8 +191,11 @@ sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
slot = PK11_GetInternalKeySlot();
}
- bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem,
- PR_FALSE, p12dcx->wincx);
+ algorithm = SECOID_GetAlgorithmTag(algid);
+ if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, p12dcx->pwitem))
+ return NULL;
+
+ bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE, p12dcx->wincx);
/* some tokens can't generate PBE keys on their own, generate the
* key in the internal slot, and let the Import code deal with it,
* (if the slot can't generate PBEs, then we need to use the internal
@@ -198,8 +203,7 @@ sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
if (!bulkKey && !PK11_IsInternal(slot)) {
PK11_FreeSlot(slot);
slot = PK11_GetInternalKeySlot();
- bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem,
- PR_FALSE, p12dcx->wincx);
+ bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE, p12dcx->wincx);
}
PK11_FreeSlot(slot);
@@ -208,6 +212,10 @@ sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
PK11_SetSymKeyUserData(bulkKey, p12dcx->pwitem, NULL);
}
+ if (pwitem.data) {
+ SECITEM_ZfreeItem(&pwitem, PR_FALSE);
+ }
+
return bulkKey;
}
@@ -1335,11 +1343,23 @@ sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx)
case SEC_OID_MD2:
integrityMech = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN;
break;
+ case SEC_OID_SHA224:
+ integrityMech = CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN;
+ break;
+ case SEC_OID_SHA256:
+ integrityMech = CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN;
+ break;
+ case SEC_OID_SHA384:
+ integrityMech = CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN;
+ break;
+ case SEC_OID_SHA512:
+ integrityMech = CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN;
+ break;
default:
goto loser;
}
- symKey = PK11_KeyGen(NULL, integrityMech, params, 20, NULL);
+ symKey = PK11_KeyGen(NULL, integrityMech, params, 0, NULL);
PK11_DestroyPBEParams(params);
params = NULL;
if (!symKey)
@@ -2440,13 +2460,25 @@ sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECKEYPublicKey *pubKey,
nickName, publicValue, PR_TRUE, PR_TRUE,
keyUsage, wincx);
break;
- case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
+ case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: {
+ SECItem pwitem = { 0 };
+ SECAlgorithmID *algid =
+ &key->safeBagContent.pkcs8ShroudedKeyBag->algorithm;
+ SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
+
+ if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm,
+ key->pwitem))
+ return SECFailure;
rv = PK11_ImportEncryptedPrivateKeyInfo(key->slot,
key->safeBagContent.pkcs8ShroudedKeyBag,
- key->pwitem, nickName, publicValue,
+ &pwitem, nickName, publicValue,
PR_TRUE, PR_TRUE, keyType, keyUsage,
wincx);
+ if (pwitem.data) {
+ SECITEM_ZfreeItem(&pwitem, PR_FALSE);
+ }
break;
+ }
default:
key->error = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION;
key->problem = PR_TRUE;
diff --git a/nss/lib/pkcs12/p12e.c b/nss/lib/pkcs12/p12e.c
index cce1ff7..4a21d89 100644
--- a/nss/lib/pkcs12/p12e.c
+++ b/nss/lib/pkcs12/p12e.c
@@ -10,6 +10,7 @@
#include "seccomon.h"
#include "secport.h"
#include "cert.h"
+#include "secpkcs5.h"
#include "secpkcs7.h"
#include "secasn1.h"
#include "secerr.h"
@@ -378,17 +379,25 @@ SEC_PKCS12CreatePasswordPrivSafe(SEC_PKCS12ExportContext *p12ctxt,
safeInfo->itemCount = 0;
/* create the encrypted safe */
- safeInfo->cinfo = SEC_PKCS7CreateEncryptedData(privAlg, 0, p12ctxt->pwfn,
- p12ctxt->pwfnarg);
+ if (!SEC_PKCS5IsAlgorithmPBEAlgTag(privAlg) &&
+ PK11_AlgtagToMechanism(privAlg) == CKM_AES_CBC) {
+ safeInfo->cinfo = SEC_PKCS7CreateEncryptedDataWithPBEV2(SEC_OID_PKCS5_PBES2,
+ privAlg,
+ SEC_OID_UNKNOWN,
+ 0,
+ p12ctxt->pwfn,
+ p12ctxt->pwfnarg);
+ } else {
+ safeInfo->cinfo = SEC_PKCS7CreateEncryptedData(privAlg, 0, p12ctxt->pwfn,
+ p12ctxt->pwfnarg);
+ }
if (!safeInfo->cinfo) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
safeInfo->arena = p12ctxt->arena;
- /* convert the password to unicode */
- if (!sec_pkcs12_convert_item_to_unicode(NULL, &uniPwitem, pwitem,
- PR_TRUE, PR_TRUE, PR_TRUE)) {
+ if (!sec_pkcs12_encode_password(NULL, &uniPwitem, privAlg, pwitem)) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
@@ -1203,8 +1212,8 @@ SEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *sa
SECKEYEncryptedPrivateKeyInfo *epki = NULL;
PK11SlotInfo *slot = NULL;
- if (!sec_pkcs12_convert_item_to_unicode(p12ctxt->arena, &uniPwitem,
- pwitem, PR_TRUE, PR_TRUE, PR_TRUE)) {
+ if (!sec_pkcs12_encode_password(p12ctxt->arena, &uniPwitem, algorithm,
+ pwitem)) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
diff --git a/nss/lib/pkcs12/p12local.c b/nss/lib/pkcs12/p12local.c
index d7f0d9e..a94c08b 100644
--- a/nss/lib/pkcs12/p12local.c
+++ b/nss/lib/pkcs12/p12local.c
@@ -949,6 +949,73 @@ sec_pkcs12_convert_item_to_unicode(PLArenaPool *arena, SECItem *dest,
return PR_TRUE;
}
+PRBool
+sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm)
+{
+ switch (algorithm) {
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
+ case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
+ /* those are actually PKCS #5 v1.5 PBEs, but we
+ * historically treat them in the same way as PKCS #12
+ * PBEs */
+ case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
+ case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
+ case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
+ return PR_TRUE;
+ default:
+ return PR_FALSE;
+ }
+}
+
+/* this function decodes a password from Unicode if necessary,
+ * according to the PBE algorithm.
+ *
+ * we assume that the pwitem is already encoded in Unicode by the
+ * caller. if the encryption scheme is not the one defined in PKCS
+ * #12, decode the pwitem back into UTF-8. */
+PRBool
+sec_pkcs12_decode_password(PLArenaPool *arena,
+ SECItem *result,
+ SECOidTag algorithm,
+ const SECItem *pwitem)
+{
+ if (!sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm))
+ return sec_pkcs12_convert_item_to_unicode(arena, result,
+ (SECItem *)pwitem,
+ PR_TRUE, PR_FALSE, PR_FALSE);
+
+ return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess;
+}
+
+/* this function encodes a password into Unicode if necessary,
+ * according to the PBE algorithm.
+ *
+ * we assume that the pwitem holds a raw password. if the encryption
+ * scheme is the one defined in PKCS #12, encode the password into
+ * BMPString. */
+PRBool
+sec_pkcs12_encode_password(PLArenaPool *arena,
+ SECItem *result,
+ SECOidTag algorithm,
+ const SECItem *pwitem)
+{
+ if (sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm))
+ return sec_pkcs12_convert_item_to_unicode(arena, result,
+ (SECItem *)pwitem,
+ PR_TRUE, PR_TRUE, PR_TRUE);
+
+ return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess;
+}
+
/* pkcs 12 templates */
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser =
sec_pkcs12_choose_shroud_type;
diff --git a/nss/lib/pkcs12/p12local.h b/nss/lib/pkcs12/p12local.h
index f07122a..06a56d1 100644
--- a/nss/lib/pkcs12/p12local.h
+++ b/nss/lib/pkcs12/p12local.h
@@ -55,4 +55,15 @@ sec_PKCS12ConvertOldSafeToNew(PLArenaPool *arena, PK11SlotInfo *slot,
void *wincx, SEC_PKCS12SafeContents *safe,
SEC_PKCS12Baggage *baggage);
+extern PRBool sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm);
+
+extern PRBool sec_pkcs12_decode_password(PLArenaPool *arena,
+ SECItem *result,
+ SECOidTag algorithm,
+ const SECItem *pwitem);
+extern PRBool sec_pkcs12_encode_password(PLArenaPool *arena,
+ SECItem *result,
+ SECOidTag algorithm,
+ const SECItem *pwitem);
+
#endif
diff --git a/nss/lib/pkcs12/p12plcy.c b/nss/lib/pkcs12/p12plcy.c
index fef288c..97970ab 100644
--- a/nss/lib/pkcs12/p12plcy.c
+++ b/nss/lib/pkcs12/p12plcy.c
@@ -24,6 +24,9 @@ static pkcs12SuiteMap pkcs12SuiteMaps[] = {
{ SEC_OID_RC2_CBC, 128, PKCS12_RC2_CBC_128, PR_FALSE, PR_FALSE },
{ SEC_OID_DES_CBC, 64, PKCS12_DES_56, PR_FALSE, PR_FALSE },
{ SEC_OID_DES_EDE3_CBC, 192, PKCS12_DES_EDE3_168, PR_FALSE, PR_FALSE },
+ { SEC_OID_AES_128_CBC, 128, PKCS12_AES_CBC_128, PR_FALSE, PR_FALSE },
+ { SEC_OID_AES_192_CBC, 192, PKCS12_AES_CBC_192, PR_FALSE, PR_FALSE },
+ { SEC_OID_AES_256_CBC, 256, PKCS12_AES_CBC_256, PR_FALSE, PR_FALSE },
{ SEC_OID_UNKNOWN, 0, PKCS12_NULL, PR_FALSE, PR_FALSE },
{ SEC_OID_UNKNOWN, 0, 0L, PR_FALSE, PR_FALSE }
};