diff options
Diffstat (limited to 'security/nss/lib/pk11wrap/pk11pbe.c')
-rw-r--r-- | security/nss/lib/pk11wrap/pk11pbe.c | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/security/nss/lib/pk11wrap/pk11pbe.c b/security/nss/lib/pk11wrap/pk11pbe.c index 7837bfe9c7..bea9333f62 100644 --- a/security/nss/lib/pk11wrap/pk11pbe.c +++ b/security/nss/lib/pk11wrap/pk11pbe.c @@ -4,6 +4,7 @@ #include "plarena.h" +#include "blapit.h" #include "seccomon.h" #include "secitem.h" #include "secport.h" @@ -301,17 +302,49 @@ SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen) return SEC_OID_UNKNOWN; } +static PRBool +sec_pkcs5_is_algorithm_v2_aes_algorithm(SECOidTag algorithm) +{ + switch (algorithm) { + case SEC_OID_AES_128_CBC: + case SEC_OID_AES_192_CBC: + case SEC_OID_AES_256_CBC: + return PR_TRUE; + default: + return PR_FALSE; + } +} + +static int +sec_pkcs5v2_aes_key_length(SECOidTag algorithm) +{ + switch (algorithm) { + /* The key length for the AES-CBC-Pad algorithms are + * determined from the undelying cipher algorithm. */ + case SEC_OID_AES_128_CBC: + return AES_128_KEY_LENGTH; + case SEC_OID_AES_192_CBC: + return AES_192_KEY_LENGTH; + case SEC_OID_AES_256_CBC: + return AES_256_KEY_LENGTH; + default: + break; + } + return 0; +} + /* * get the key length in bytes from a PKCS5 PBE */ -int -sec_pkcs5v2_key_length(SECAlgorithmID *algid) +static int +sec_pkcs5v2_key_length(SECAlgorithmID *algid, SECAlgorithmID *cipherAlgId) { SECOidTag algorithm; PLArenaPool *arena = NULL; SEC_PKCS5PBEParameter p5_param; SECStatus rv; int length = -1; + SECOidTag cipherAlg = SEC_OID_UNKNOWN; algorithm = SECOID_GetAlgorithmTag(algid); /* sanity check, they should all be PBKDF2 here */ @@ -330,8 +363,20 @@ sec_pkcs5v2_key_length(SECAlgorithmID *algid) goto loser; } - if (p5_param.keyLength.data != NULL) { + if (cipherAlgId) + cipherAlg = SECOID_GetAlgorithmTag(cipherAlgId); + + if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlg)) { + length = sec_pkcs5v2_aes_key_length(cipherAlg); + } else if (p5_param.keyLength.data != NULL) { length = DER_GetInteger(&p5_param.keyLength); + } else { + CK_MECHANISM_TYPE cipherMech; + cipherMech = PK11_AlgtagToMechanism(cipherAlg); + if (cipherMech == CKM_INVALID_MECHANISM) { + goto loser; + } + length = PK11_GetMaxKeyLength(cipherMech); } loser: @@ -375,14 +420,15 @@ SEC_PKCS5GetKeyLength(SECAlgorithmID *algid) case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: return 16; case SEC_OID_PKCS5_PBKDF2: - return sec_pkcs5v2_key_length(algid); + return sec_pkcs5v2_key_length(algid, NULL); case SEC_OID_PKCS5_PBES2: case SEC_OID_PKCS5_PBMAC1: { sec_pkcs5V2Parameter *pbeV2_param; int length = -1; pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); if (pbeV2_param != NULL) { - length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId); + length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId, + &pbeV2_param->cipherAlgId); sec_pkcs5_v2_destroy_v2_param(pbeV2_param); } return length; @@ -614,6 +660,8 @@ sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm); if (hashAlg != SEC_OID_UNKNOWN) { keyLength = HASH_ResultLenByOidTag(hashAlg); + } else if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlgorithm)) { + keyLength = sec_pkcs5v2_aes_key_length(cipherAlgorithm); } else { CK_MECHANISM_TYPE cryptoMech; cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm); |