diff --git a/base/src/main/java/org/mozilla/jss/pkcs12/PFX.java b/base/src/main/java/org/mozilla/jss/pkcs12/PFX.java index 8b44bb39c..1f2bcc333 100644 --- a/base/src/main/java/org/mozilla/jss/pkcs12/PFX.java +++ b/base/src/main/java/org/mozilla/jss/pkcs12/PFX.java @@ -11,7 +11,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; + import java.security.DigestException; +import java.security.NoSuchAlgorithmException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; @@ -28,10 +30,12 @@ import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.JSSSecureRandom; import org.mozilla.jss.crypto.PBEAlgorithm; +import org.mozilla.jss.crypto.DigestAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkcs7.ContentInfo; import org.mozilla.jss.pkcs7.DigestInfo; import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.Attribute; import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; @@ -211,11 +215,14 @@ public PFX( AuthenticatedSafes authSafes ) { */ public void computeMacData(Password password, byte[] salt, int iterationCount) - throws NotInitializedException, DigestException, + throws NotInitializedException, DigestException,NoSuchAlgorithmException, TokenException, CharConversionException { + + //Make this alg the default mac alg. + AlgorithmIdentifier algID = new AlgorithmIdentifier(DigestAlgorithm.SHA256.toOID()); macData = new MacData( password, salt, iterationCount, - ASN1Util.encode(authSafes) ); + ASN1Util.encode(authSafes), algID ); } diff --git a/native/src/main/native/org/mozilla/jss/pkcs11/PK11Store.c b/native/src/main/native/org/mozilla/jss/pkcs11/PK11Store.c index b8cc6fcfe..f20b02c5e 100644 --- a/native/src/main/native/org/mozilla/jss/pkcs11/PK11Store.c +++ b/native/src/main/native/org/mozilla/jss/pkcs11/PK11Store.c @@ -794,28 +794,22 @@ Java_org_mozilla_jss_pkcs11_PK11Store_getEncryptedPrivateKeyInfo( goto finish; } - // export the epki - epki = PK11_ExportEncryptedPrivKeyInfo( - slot, algTag, pwItem, privk, iterations, NULL /*wincx*/); - if (epki == NULL) { - //try our own version for the new AES KWP algs. - - epki = JSS_ExportEncryptedPrivKeyInfoV2( + // Call our JSS version of the newer V2 version of PK11_ExportEncryptedPrivateKeyInfoV2 + epki = JSS_ExportEncryptedPrivKeyInfoV2( slot, - algTag, /* PBE algorithm to encrypt the key with */ - SEC_OID_UNKNOWN, /* Encryption algorithm to Encrypt the key with */ - SEC_OID_UNKNOWN, /* Hash algorithm for PRF */ - pwItem, /* password for PBE encryption */ - privk, /* encrypt this private key */ - iterations, /* interations for PBE alg */ - NULL); - - if(epki == NULL) { - JSS_throwMsgPrErr( + algTag, /* PBE algorithm to encrypt the key with */ + SEC_OID_UNKNOWN, /* Encryption algorithm to Encrypt the key with */ + SEC_OID_HMAC_SHA256, /* Hash algorithm for PRF, make this upgraded to SHA256, we can make configurable in future. */ + pwItem, /* password for PBE encryption */ + privk, /* encrypt this private key */ + iterations, /* interations for PBE alg */ + NULL); + + if(epki == NULL) { + JSS_throwMsgPrErr( env, TOKEN_EXCEPTION, "Failed to export EncryptedPrivateKeyInfo"); goto finish; } - } // DER-encode the epki if (SEC_ASN1EncodeItem(NULL, &epkiItem, epki, diff --git a/native/src/main/native/org/mozilla/jss/util/jssutil.c b/native/src/main/native/org/mozilla/jss/util/jssutil.c index 3988ac883..b3f943e5a 100644 --- a/native/src/main/native/org/mozilla/jss/util/jssutil.c +++ b/native/src/main/native/org/mozilla/jss/util/jssutil.c @@ -945,7 +945,9 @@ JSS_ExportEncryptedPrivKeyInfoV2( SECKEYEncryptedPrivateKeyInfo *epki = NULL; PLArenaPool *arena = NULL; SECAlgorithmID *algid; - SECOidTag pbeAlgTag = SEC_OID_UNKNOWN; + // Make this alg set to what the routine sec_pkcs5CreateAlgorithmID sets it to. + // From here we can't get to this lower level routine, using PK11_CreatePBEV2AlgorithmID. + SECOidTag pbeAlgTag = SEC_OID_PKCS5_PBKDF2; SECItem *crypto_param = NULL; PK11SymKey *key = NULL; PK11SymKey *finalKey = NULL; @@ -955,7 +957,6 @@ JSS_ExportEncryptedPrivKeyInfoV2( CK_MECHANISM_TYPE pbeMechType; CK_MECHANISM_TYPE cryptoMechType; CK_MECHANISM cryptoMech; - SECItem *iv = NULL; if (!pwitem || !pk) { PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -964,6 +965,7 @@ JSS_ExportEncryptedPrivKeyInfoV2( algid = PK11_CreatePBEV2AlgorithmID(pbeAlg, encAlg, prfAlg, 0,iteration , NULL); + if (algid == NULL) { return NULL; } @@ -986,6 +988,7 @@ JSS_ExportEncryptedPrivKeyInfoV2( * pbe key gen, generate the key in the private key slot so we don't have * to move it later */ pbeMechType = PK11_AlgtagToMechanism(pbeAlgTag); + if (slot != pk->pkcs11Slot) { if (PK11_DoesMechanism(pk->pkcs11Slot, pbeMechType)) { slot = pk->pkcs11Slot; @@ -1000,12 +1003,14 @@ JSS_ExportEncryptedPrivKeyInfoV2( } cryptoMechType = PK11_GetPBECryptoMechanism(algid, &crypto_param, pwitem); + if (cryptoMechType == CKM_INVALID_MECHANISM) { rv = SECFailure; goto loser; } cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMechType); + cryptoMech.pParameter = crypto_param ? crypto_param->data : NULL; cryptoMech.ulParameterLen = crypto_param ? crypto_param->len : 0; @@ -1050,15 +1055,42 @@ JSS_ExportEncryptedPrivKeyInfoV2( * pkcs8/pkcs5. */ - /* Allocate a large buffer to make sure we can fit the wrapped key */ - encBufLen = 16384; + encBufLen = 0; + + epki->encryptedData.data = NULL; + epki->encryptedData.len = 0; // Just get the len we need + + // Modify behavior for KWP since NULL is not returned for crypto_param + // from PK11_GetPBECryptoMechanism. It returns some default 8 byte iv, which is incorrect. + int isKeyWrapKWP = 0; + if(cryptoMech.mechanism == CKM_AES_KEY_WRAP_KWP) { + isKeyWrapKWP = 1; + } + + //First call to get get the size. + crv = PK11_WrapPrivKey(pk->pkcs11Slot, finalKey, + pk, cryptoMech.mechanism, + isKeyWrapKWP ? NULL : crypto_param, &epki->encryptedData, NULL); + if (crv != CKR_OK) { + rv = SECFailure; + goto loser; + } + + // If KWP increase buffer size by 8 + // The size value from the first PK11_WrapPrivKey does not account for AES_BLOCK_SIZE + + if(isKeyWrapKWP) { + epki->encryptedData.len += 8; + } + + encBufLen = epki->encryptedData.len; epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen); + if (!epki->encryptedData.data) { rv = SECFailure; goto loser; } - epki->encryptedData.len = (unsigned int)encBufLen; if (!epki->encryptedData.len) { rv = SECFailure; @@ -1066,10 +1098,9 @@ JSS_ExportEncryptedPrivKeyInfoV2( } crv = PK11_WrapPrivKey(pk->pkcs11Slot, finalKey, - pk, cryptoMechType, - iv, &epki->encryptedData, NULL); + pk, cryptoMech.mechanism, + isKeyWrapKWP ? NULL : crypto_param, &epki->encryptedData, NULL); - /* crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, &cryptoMech, key->objectID, pk->pkcs11ID, NULL, &encBufLen); */ if (crv != CKR_OK) { rv = SECFailure; goto loser;