diff options
Diffstat (limited to 'security/nss/lib/pkcs12')
-rw-r--r-- | security/nss/lib/pkcs12/p12d.c | 46 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12e.c | 23 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12local.c | 67 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12local.h | 11 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12plcy.c | 3 |
5 files changed, 136 insertions, 14 deletions
diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index d0b647615..57333ac37 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/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/security/nss/lib/pkcs12/p12e.c b/security/nss/lib/pkcs12/p12e.c index cce1ff7c0..4a21d8955 100644 --- a/security/nss/lib/pkcs12/p12e.c +++ b/security/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/security/nss/lib/pkcs12/p12local.c b/security/nss/lib/pkcs12/p12local.c index d7f0d9e9a..a94c08be1 100644 --- a/security/nss/lib/pkcs12/p12local.c +++ b/security/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/security/nss/lib/pkcs12/p12local.h b/security/nss/lib/pkcs12/p12local.h index f07122a28..06a56d13b 100644 --- a/security/nss/lib/pkcs12/p12local.h +++ b/security/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/security/nss/lib/pkcs12/p12plcy.c b/security/nss/lib/pkcs12/p12plcy.c index fef288c3e..97970abc4 100644 --- a/security/nss/lib/pkcs12/p12plcy.c +++ b/security/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 } }; |