diff options
author | Pete Bentley <prb@google.com> | 2023-01-09 15:21:28 +0000 |
---|---|---|
committer | Pete Bentley <prb@google.com> | 2023-01-09 17:48:21 +0000 |
commit | 4fae1c6cb82e4b3e7d51e38ce0e3d7a4f22a0939 (patch) | |
tree | 65260259418173beabcb7083eda429d52ee967b6 /bcprov/src/main/java/org/bouncycastle/jcajce | |
parent | df7def18766fefe820438604d92fc5142a9a6a49 (diff) | |
download | bouncycastle-4fae1c6cb82e4b3e7d51e38ce0e3d7a4f22a0939.tar.gz |
Bouncy Castle: Add support for PBES2 encrypted KeyStores.
Adds a private sub-Provider to BouncyCastleProvider which allows BC's
PKCS12 implementation to conintue using its own implementations of some
Macs and Ciphers which support PBES2.
These implementions are not exposed to apps and are only used
from BC internals.
Bug: 230750823
Test: atest
CtsLibcoreTestCases:tests.targets.security.KeyStorePkcs7FormatTest
Change-Id: Ic505d0259d16cdc66f9776e818efa20ed97aa32b
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/jcajce')
9 files changed, 87 insertions, 13 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java index 9818f864..831b497e 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java @@ -54,4 +54,11 @@ public interface ConfigurableProvider AsymmetricKeyInfoConverter getKeyInfoConverter(ASN1ObjectIdentifier oid); void addAttributes(String key, Map<String, String> attributeMap); + + // BEGIN Android-added: Allow algorithms to be added privately. + // See BouncyCastleProvider for details. + void addPrivateAlgorithm(String key, String value); + + void addPrivateAlgorithm(String type, ASN1ObjectIdentifier oid, String className); + // END Android-added: Allow algorithms to be added privately. } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA224.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA224.java index 5c6b699d..dd25b0c4 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA224.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA224.java @@ -76,6 +76,8 @@ public class SHA224 addHMACAlias(provider, "SHA224", PKCSObjectIdentifiers.id_hmacWithSHA224); */ // END Android-removed: Unsupported algorithms + // Android-added: Private implementation needed to support PBKDF2 with PKCS#12 + provider.addPrivateAlgorithm("Mac", NISTObjectIdentifiers.id_sha224, PREFIX + "$HashMac"); } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA256.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA256.java index 48f99b4d..ae4c82fd 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA256.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA256.java @@ -101,6 +101,8 @@ public class SHA256 addHMACAlias(provider, "SHA256", NISTObjectIdentifiers.id_sha256); */ // END Android-removed: Unsupported algorithms + // Android-added: Private implementation needed to support PBKDF2 with PKCS#12 + provider.addPrivateAlgorithm("Mac", NISTObjectIdentifiers.id_sha256, PREFIX + "$HashMac"); } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA384.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA384.java index 8f083748..b5f269ee 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA384.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA384.java @@ -95,6 +95,8 @@ public class SHA384 addHMACAlias(provider, "SHA384", PKCSObjectIdentifiers.id_hmacWithSHA384); */ // END Android-removed: Unsupported algorithms + // Android-added: Private implementation needed to support PBKDF2 with PKCS#12 + provider.addPrivateAlgorithm("Mac", NISTObjectIdentifiers.id_sha384, PREFIX + "$HashMac"); } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA512.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA512.java index e227620e..335d0d60 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA512.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA512.java @@ -193,6 +193,8 @@ public class SHA512 addHMACAlgorithm(provider, "SHA512/256", PREFIX + "$HashMacT256", PREFIX + "$KeyGeneratorT256"); */ // END Android-removed: Unsupported algorithms + // Android-added: Private implementation needed to support PBKDF2 with PKCS#12 + provider.addPrivateAlgorithm("Mac", NISTObjectIdentifiers.id_sha512, PREFIX + "$HashMac"); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java index 4c3e480d..263c63d2 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java @@ -116,9 +116,12 @@ public class PKCS12KeyStoreSpi { static final String PKCS12_MAX_IT_COUNT_PROPERTY = "org.bouncycastle.pkcs12.max_it_count"; - // Android-changed: Use default provider for JCA algorithms instead of BC + // Android-changed: Use default provider for most JCA algorithms instead of BC. + // For the case where we need BC implementations, the BCJcaJceHelper will also search + // the list of private implementations help by BouncyCastleProvider. // Was: private final JcaJceHelper helper = new BCJcaJceHelper(); private final JcaJceHelper helper = new DefaultJcaJceHelper(); + private final JcaJceHelper selfHelper = new BCJcaJceHelper(); private static final int SALT_SIZE = 20; private static final int MIN_ITERATIONS = 50 * 1024; @@ -727,7 +730,9 @@ public class PKCS12KeyStoreSpi PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters()); AlgorithmIdentifier encScheme = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme()); - SecretKeyFactory keyFact = helper.createSecretKeyFactory(alg.getKeyDerivationFunc().getAlgorithm().getId()); + // Android-Changed: SecretKeyFactory must be from BC due to instanceof logic. + // SecretKeyFactory keyFact = helper.createSecretKeyFactory(alg.getKeyDerivationFunc().getAlgorithm().getId()); + SecretKeyFactory keyFact = selfHelper.createSecretKeyFactory(alg.getKeyDerivationFunc().getAlgorithm().getId()); SecretKey key; if (func.isDefaultPrf()) @@ -739,7 +744,9 @@ public class PKCS12KeyStoreSpi key = keyFact.generateSecret(new PBKDF2KeySpec(password, func.getSalt(), validateIterationCount(func.getIterationCount()), keySizeProvider.getKeySize(encScheme), func.getPrf())); } - Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId()); + // Android-Changed: Cipher must be from BC due to use of internal PKCS12Key tyoe. + // Cipher cipher = Cipher.getInstance(alg.getEncryptionScheme().getAlgorithm().getId()); + Cipher cipher = selfHelper.createCipher(alg.getEncryptionScheme().getAlgorithm().getId()); ASN1Encodable encParams = alg.getEncryptionScheme().getParameters(); if (encParams instanceof ASN1OctetString) @@ -1781,7 +1788,9 @@ public class PKCS12KeyStoreSpi { PBEParameterSpec defParams = new PBEParameterSpec(salt, itCount); - Mac mac = helper.createMac(oid.getId()); + // Android-Changed: Mac must be from BC due to use of internal PKCS12Key tyoe. + // Mac mac = helper.createMac(oid.getId()); + Mac mac = selfHelper.createMac(oid.getId()); mac.init(new PKCS12Key(password, wrongPkcs12Zero), defParams); mac.update(data); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java index e7d3ec24..d25ed90c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java @@ -1088,6 +1088,11 @@ public final class AES // addGMacAlgorithm(provider, "AES", PREFIX + "$AESGMAC", PREFIX + "$KeyGen128"); // addPoly1305Algorithm(provider, "AES", PREFIX + "$Poly1305", PREFIX + "$Poly1305KeyGen"); // END Android-removed: Unsupported algorithms + + // Android-added: Private implementations needed to support PBKDF2 with PKCS#12 + provider.addPrivateAlgorithm("Cipher", NISTObjectIdentifiers.id_aes128_CBC, PREFIX + "$CBC"); + provider.addPrivateAlgorithm("Cipher", NISTObjectIdentifiers.id_aes192_CBC, PREFIX + "$CBC"); + provider.addPrivateAlgorithm("Cipher", NISTObjectIdentifiers.id_aes256_CBC, PREFIX + "$CBC"); } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java index 1af79b80..e384134b 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java @@ -40,14 +40,14 @@ public class PBEPBKDF2 static { - // BEGIN Android-removed: Unsupported algorithm - /* - prfCodes.put(CryptoProObjectIdentifiers.gostR3411Hmac, Integers.valueOf(PBE.GOST3411)); prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA1, Integers.valueOf(PBE.SHA1)); prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA256, Integers.valueOf(PBE.SHA256)); prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA224, Integers.valueOf(PBE.SHA224)); prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA384, Integers.valueOf(PBE.SHA384)); prfCodes.put(PKCSObjectIdentifiers.id_hmacWithSHA512, Integers.valueOf(PBE.SHA512)); + // BEGIN Android-removed: Unsupported algorithms + /* + prfCodes.put(CryptoProObjectIdentifiers.gostR3411Hmac, Integers.valueOf(PBE.GOST3411)); prfCodes.put(NISTObjectIdentifiers.id_hmacWithSHA3_256, Integers.valueOf(PBE.SHA3_256)); prfCodes.put(NISTObjectIdentifiers.id_hmacWithSHA3_224, Integers.valueOf(PBE.SHA3_224)); prfCodes.put(NISTObjectIdentifiers.id_hmacWithSHA3_384, Integers.valueOf(PBE.SHA3_384)); @@ -62,8 +62,6 @@ public class PBEPBKDF2 } - // BEGIN Android-removed: Unsupported algorithms - /* public static class AlgParams extends BaseAlgorithmParameters { @@ -146,8 +144,6 @@ public class PBEPBKDF2 return "PBKDF2 Parameters"; } } - */ - // END Android-removed: Unsupported algorithms public static class BasePBKDF2 extends BaseSecretKeyFactory @@ -273,8 +269,6 @@ public class PBEPBKDF2 } } - // BEGIN Android-removed: Unsupported algorithms - /* public static class PBKDF2withUTF8 extends BasePBKDF2 { @@ -284,6 +278,8 @@ public class PBEPBKDF2 } } + // BEGIN Android-removed: Unsupported algorithms + /* public static class PBKDF2withSHA224 extends BasePBKDF2 { @@ -614,6 +610,9 @@ public class PBEPBKDF2 provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA512AndAES_256", PREFIX + "$PBEWithHmacSHA512AndAES_256"); provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1And8BIT", PREFIX + "$PBKDF2WithHmacSHA18BIT"); // END Android-added: Android versions of algorithms. + // Android-added: Private implementations needed to support PBKDF2 with PKCS#12 + provider.addPrivateAlgorithm("SecretKeyFactory.PBKDF2", PREFIX + "$PBKDF2withUTF8"); + provider.addPrivateAlgorithm("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.5.12", "PBKDF2"); } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java index 6c384585..9a41d31c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java @@ -1,8 +1,13 @@ package org.bouncycastle.jcajce.util; +import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.Security; +import javax.crypto.Cipher; +import javax.crypto.Mac; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKeyFactory; import org.bouncycastle.jce.provider.BouncyCastleProvider; /** @@ -38,4 +43,45 @@ public class BCJcaJceHelper { super(getBouncyCastleProvider()); } + + // BEGIN Android-added: Look up algorithms in private provider if not found in main Provider. + // + // If code is using a BCJcajceHelper to ensure it gets its implementation from BC, then + // also search in the privately provided algorithms if not found in the main set. + @Override + public Cipher createCipher(String algorithm) + throws NoSuchAlgorithmException, NoSuchPaddingException { + try { + return super.createCipher(algorithm); + } catch (NoSuchAlgorithmException e) { + return Cipher.getInstance(algorithm, getPrivateProvider()); + } + } + + @Override + public SecretKeyFactory createSecretKeyFactory(String algorithm) + throws NoSuchAlgorithmException { + try { + return super.createSecretKeyFactory(algorithm); + } catch (NoSuchAlgorithmException e) { + return SecretKeyFactory.getInstance(algorithm, getPrivateProvider()); + } + } + + @Override + public Mac createMac(String algorithm) throws NoSuchAlgorithmException { + try { + return super.createMac(algorithm); + } catch (NoSuchAlgorithmException e) { + return Mac.getInstance(algorithm, getPrivateProvider()); + } + } + + private Provider getPrivateProvider() { + if (provider instanceof BouncyCastleProvider) { + return ((BouncyCastleProvider) provider).getPrivateProvider(); + } + throw new IllegalStateException(); // XXX + } + // END Android-added: Look up algorithms in private provider if not found in main Provider. } |