From d664af0a321b3dceec9d97d3483d9bc3de9ed51d Mon Sep 17 00:00:00 2001 From: zzz Date: Fri, 13 Jun 2025 08:51:34 -0400 Subject: [PATCH] Patches to BouncyCastle 1.80 source files to minimize dependencies --- .../crypto/CryptoServicesRegistrar.java | 529 +----------------- .../crypto/digests/KeccakDigest.java | 5 +- .../crypto/digests/SHA512Digest.java | 3 +- .../crypto/digests/SHAKEDigest.java | 2 +- .../crypto/params/ParametersWithContext.java | 6 +- .../src/org/bouncycastle/package-info.java | 6 + .../pqc/crypto/mlkem/MLKEMEngine.java | 9 +- .../pqc/crypto/mlkem/MLKEMExtractor.java | 3 - .../pqc/crypto/mlkem/MLKEMGenerator.java | 2 - .../pqc/crypto/mlkem/MLKEMIndCpa.java | 6 +- .../crypto/mlkem/MLKEMKeyPairGenerator.java | 2 - .../mlkem/MLKEMPrivateKeyParameters.java | 30 +- .../mlkem/MLKEMPublicKeyParameters.java | 14 +- .../pqc/crypto/mlkem/PolyVec.java | 2 +- .../pqc/crypto/mlkem/package-info.java | 6 + .../util/SecretWithEncapsulationImpl.java | 11 +- .../src/org/bouncycastle/util/Memoable.java | 1 - .../java/src/org/bouncycastle/util/Util.java | 52 ++ 18 files changed, 117 insertions(+), 572 deletions(-) create mode 100644 router/java/src/org/bouncycastle/package-info.java create mode 100644 router/java/src/org/bouncycastle/pqc/crypto/mlkem/package-info.java create mode 100644 router/java/src/org/bouncycastle/util/Util.java diff --git a/router/java/src/org/bouncycastle/crypto/CryptoServicesRegistrar.java b/router/java/src/org/bouncycastle/crypto/CryptoServicesRegistrar.java index 90d3c85348..2589bc21f5 100644 --- a/router/java/src/org/bouncycastle/crypto/CryptoServicesRegistrar.java +++ b/router/java/src/org/bouncycastle/crypto/CryptoServicesRegistrar.java @@ -1,541 +1,20 @@ package org.bouncycastle.crypto; -import java.math.BigInteger; -import java.security.AccessController; -import java.security.Permission; -import java.security.PrivilegedAction; import java.security.SecureRandom; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; -import java.util.logging.Logger; -import org.bouncycastle.asn1.x9.X9ECParameters; -import org.bouncycastle.crypto.params.DHParameters; -import org.bouncycastle.crypto.params.DHValidationParameters; -import org.bouncycastle.crypto.params.DSAParameters; -import org.bouncycastle.crypto.params.DSAValidationParameters; -import org.bouncycastle.util.Properties; -import org.bouncycastle.util.Strings; -import org.bouncycastle.util.encoders.Hex; +public class CryptoServicesRegistrar { -/** - * Basic registrar class for providing defaults for cryptography services in this module. - */ -public final class CryptoServicesRegistrar -{ - private static final Logger LOG = Logger.getLogger(CryptoServicesRegistrar.class.getName()); + public static void checkConstraints(CryptoServiceProperties csp) {} - private static final Permission CanSetDefaultProperty = new CryptoServicesPermission(CryptoServicesPermission.GLOBAL_CONFIG); - private static final Permission CanSetThreadProperty = new CryptoServicesPermission(CryptoServicesPermission.THREAD_LOCAL_CONFIG); - private static final Permission CanSetDefaultRandom = new CryptoServicesPermission(CryptoServicesPermission.DEFAULT_RANDOM); - private static final Permission CanSetConstraints = new CryptoServicesPermission(CryptoServicesPermission.CONSTRAINTS); - - private static final ThreadLocal> threadProperties = new ThreadLocal>(); - private static final Map globalProperties = Collections.synchronizedMap(new HashMap()); - private static final SecureRandomProvider defaultRandomProviderImpl = new ThreadLocalSecureRandomProvider(); - - private static final CryptoServicesConstraints noConstraintsImpl = new CryptoServicesConstraints() - { - public void check(CryptoServiceProperties service) - { - // anything goes. - } - }; - - private static final AtomicReference defaultSecureRandomProvider = new AtomicReference(); - private static final boolean preconfiguredConstraints; - private static final AtomicReference servicesConstraints = new AtomicReference(); - - static - { - // default domain parameters for DSA and Diffie-Hellman - - DSAParameters def512Params = new DSAParameters( - new BigInteger("fca682ce8e12caba26efccf7110e526db078b05edecbcd1eb4a208f3ae1617ae01f35b91a47e6df63413c5e12ed0899bcd132acd50d99151bdc43ee737592e17", 16), - new BigInteger("962eddcc369cba8ebb260ee6b6a126d9346e38c5", 16), - new BigInteger("678471b27a9cf44ee91a49c5147db1a9aaf244f05a434d6486931d2d14271b9e35030b71fd73da179069b32e2935630e1c2062354d0da20a6c416e50be794ca4", 16), - new DSAValidationParameters(Hex.decodeStrict("b869c82b35d70e1b1ff91b28e37a62ecdc34409b"), 123)); - - DSAParameters def768Params = new DSAParameters( - new BigInteger("e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5" + - "d890141922d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a" + - "22219d470bce7d777d4a21fbe9c270b57f607002f3cef8393694cf45" + - "ee3688c11a8c56ab127a3daf", 16), - new BigInteger("9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511", 16), - new BigInteger("30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7" + - "a31d23c4dbbcbe06174544401a5b2c020965d8c2bd2171d366844577" + - "1f74ba084d2029d83c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a" + - "7064f316933a346d3f529252", 16), - new DSAValidationParameters(Hex.decodeStrict("77d0f8c4dad15eb8c4f2f8d6726cefd96d5bb399"), 263)); - - DSAParameters def1024Params = new DSAParameters( - new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80" + - "b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b" + - "801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c6" + - "1bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675" + - "f3ae2b61d72aeff22203199dd14801c7", 16), - new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16), - new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b" + - "3d0782675159578ebad4594fe67107108180b449167123e84c281613" + - "b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f" + - "0bfa213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06" + - "928b665e807b552564014c3bfecf492a", 16), - new DSAValidationParameters(Hex.decodeStrict("8d5155894229d5e689ee01e6018a237e2cae64cd"), 92)); - - DSAParameters def2048Params = new DSAParameters( - new BigInteger("95475cf5d93e596c3fcd1d902add02f427f5f3c7210313bb45fb4d5b" + - "b2e5fe1cbd678cd4bbdd84c9836be1f31c0777725aeb6c2fc38b85f4" + - "8076fa76bcd8146cc89a6fb2f706dd719898c2083dc8d896f84062e2" + - "c9c94d137b054a8d8096adb8d51952398eeca852a0af12df83e475aa" + - "65d4ec0c38a9560d5661186ff98b9fc9eb60eee8b030376b236bc73b" + - "e3acdbd74fd61c1d2475fa3077b8f080467881ff7e1ca56fee066d79" + - "506ade51edbb5443a563927dbc4ba520086746175c8885925ebc64c6" + - "147906773496990cb714ec667304e261faee33b3cbdf008e0c3fa906" + - "50d97d3909c9275bf4ac86ffcb3d03e6dfc8ada5934242dd6d3bcca2" + - "a406cb0b", 16), - new BigInteger("f8183668ba5fc5bb06b5981e6d8b795d30b8978d43ca0ec572e37e09939a9773", 16), - new BigInteger("42debb9da5b3d88cc956e08787ec3f3a09bba5f48b889a74aaf53174" + - "aa0fbe7e3c5b8fcd7a53bef563b0e98560328960a9517f4014d3325f" + - "c7962bf1e049370d76d1314a76137e792f3f0db859d095e4a5b93202" + - "4f079ecf2ef09c797452b0770e1350782ed57ddf794979dcef23cb96" + - "f183061965c4ebc93c9c71c56b925955a75f94cccf1449ac43d586d0" + - "beee43251b0b2287349d68de0d144403f13e802f4146d882e057af19" + - "b6f6275c6676c8fa0e3ca2713a3257fd1b27d0639f695e347d8d1cf9" + - "ac819a26ca9b04cb0eb9b7b035988d15bbac65212a55239cfc7e58fa" + - "e38d7250ab9991ffbc97134025fe8ce04c4399ad96569be91a546f49" + - "78693c7a", 16), - new DSAValidationParameters(Hex.decodeStrict("b0b4417601b59cbc9d8ac8f935cadaec4f5fbb2f23785609ae466748d9b5a536"), 497)); - - localSetGlobalProperty(Property.DSA_DEFAULT_PARAMS, def512Params, def768Params, def1024Params, def2048Params); - localSetGlobalProperty(Property.DH_DEFAULT_PARAMS, toDH(def512Params), toDH(def768Params), toDH(def1024Params), toDH(def2048Params)); - - servicesConstraints.set(getDefaultConstraints()); - preconfiguredConstraints = (servicesConstraints.get() != noConstraintsImpl); - } - - private CryptoServicesRegistrar() - { - - } + private static final SecureRandom sr = new SecureRandom(); /** * Return the default source of randomness. * * @return the default SecureRandom */ - public static SecureRandom getSecureRandom() - { - defaultSecureRandomProvider.compareAndSet(null, defaultRandomProviderImpl); - - return defaultSecureRandomProvider.get().get(); - } - - /** - * Return either the passed-in SecureRandom, or if it is null, then the default source of randomness. - * - * @param secureRandom the SecureRandom to use if it is not null. - * @return the SecureRandom parameter if it is not null, or else the default SecureRandom - */ public static SecureRandom getSecureRandom(SecureRandom secureRandom) { - return null == secureRandom ? getSecureRandom() : secureRandom; - } - - /** - * Set a default secure random to be used where none is otherwise provided. - * - * @param secureRandom the SecureRandom to use as the default. - */ - public static void setSecureRandom(final SecureRandom secureRandom) - { - checkPermission(CanSetDefaultRandom); - - if (secureRandom == null) - { - defaultSecureRandomProvider.set(defaultRandomProviderImpl); - } - else - { - defaultSecureRandomProvider.set(new SecureRandomProvider() - { - public SecureRandom get() - { - return secureRandom; - } - }); - } - } - - /** - * Set a default secure random provider to be used where none is otherwise provided. - * - * @param secureRandomProvider a provider SecureRandom to use when a default SecureRandom is requested. - */ - public static void setSecureRandomProvider(SecureRandomProvider secureRandomProvider) - { - checkPermission(CanSetDefaultRandom); - - defaultSecureRandomProvider.set(secureRandomProvider); - } - - /** - * Return the current algorithm/services constraints. - * - * @return the algorithm/services constraints. - */ - public static CryptoServicesConstraints getServicesConstraints() - { - return servicesConstraints.get(); - } - - /** - * Check a service to make sure it meets the current constraints. - * - * @param cryptoService the service to be checked. - * @throws CryptoServiceConstraintsException if the service violates the current constraints. - */ - public static void checkConstraints(CryptoServiceProperties cryptoService) - { - servicesConstraints.get().check(cryptoService); - } - - /** - * Set the current algorithm constraints. - */ - public static void setServicesConstraints(CryptoServicesConstraints constraints) - { - checkPermission(CanSetConstraints); - - CryptoServicesConstraints newConstraints = (constraints == null) ? noConstraintsImpl : constraints; - - if (preconfiguredConstraints) - { - if (Properties.isOverrideSet("org.bouncycastle.constraints.allow_override")) - { - servicesConstraints.set(newConstraints); - } - else - { - LOG.warning("attempt to override pre-configured constraints ignored"); - } - } - else - { - // TODO: should this only be allowed once? - servicesConstraints.set(newConstraints); - } - } - - /** - * Return the default value for a particular property if one exists. The look up is done on the thread's local - * configuration first and then on the global configuration in no local configuration exists. - * - * @param property the property to look up. - * @param the type to be returned - * @return null if the property is not set, the default value otherwise, - */ - public static T getProperty(Property property) - { - Object[] values = lookupProperty(property); - - if (values != null) - { - return (T)values[0]; - } - - return null; - } - - private static Object[] lookupProperty(Property property) - { - Map properties = threadProperties.get(); - Object[] values; - - if (properties == null || !properties.containsKey(property.name)) - { - values = globalProperties.get(property.name); - } - else - { - values = properties.get(property.name); - } - return values; - } - - /** - * Return an array representing the current values for a sized property such as DH_DEFAULT_PARAMS or - * DSA_DEFAULT_PARAMS. - * - * @param property the name of the property to look up. - * @param the base type of the array to be returned. - * @return null if the property is not set, an array of the current values otherwise. - */ - public static T[] getSizedProperty(Property property) - { - Object[] values = lookupProperty(property); - - if (values == null) - { - return null; - } - - return (T[])values.clone(); - } - - /** - * Return the value for a specific size for a sized property such as DH_DEFAULT_PARAMS or - * DSA_DEFAULT_PARAMS. - * - * @param property the name of the property to look up. - * @param size the size (in bits) of the defining value in the property type. - * @param the type of the value to be returned. - * @return the current value for the size, null if there is no value set, - */ - public static T getSizedProperty(Property property, int size) - { - Object[] values = lookupProperty(property); - - if (values == null) - { - return null; - } - - if (property.type.isAssignableFrom(DHParameters.class)) - { - for (int i = 0; i != values.length; i++) - { - DHParameters params = (DHParameters)values[i]; - - if (params.getP().bitLength() == size) - { - return (T)params; - } - } - } - else if (property.type.isAssignableFrom(DSAParameters.class)) - { - for (int i = 0; i != values.length; i++) - { - DSAParameters params = (DSAParameters)values[i]; - - if (params.getP().bitLength() == size) - { - return (T)params; - } - } - } - - return null; - } - - /** - * Set the value of the the passed in property on the current thread only. More than - * one value can be passed in for a sized property. If more than one value is provided the - * first value in the argument list becomes the default value. - * - * @param property the name of the property to set. - * @param propertyValue the values to assign to the property. - * @param the base type of the property value. - */ - public static void setThreadProperty(Property property, T... propertyValue) - { - checkPermission(CanSetThreadProperty); - - if (!property.type.isAssignableFrom(propertyValue[0].getClass())) - { - throw new IllegalArgumentException("Bad property value passed"); - } - - localSetThread(property, propertyValue.clone()); - } - - /** - * Set the value of the the passed in property globally in the JVM. More than - * one value can be passed in for a sized property. If more than one value is provided the - * first value in the argument list becomes the default value. - * - * @param property the name of the property to set. - * @param propertyValue the values to assign to the property. - * @param the base type of the property value. - */ - public static void setGlobalProperty(Property property, T... propertyValue) - { - checkPermission(CanSetDefaultProperty); - - localSetGlobalProperty(property, propertyValue.clone()); - } - - private static void localSetThread(Property property, T[] propertyValue) - { - Map properties = threadProperties.get(); - - if (properties == null) - { - properties = new HashMap(); - threadProperties.set(properties); - } - - properties.put(property.name, propertyValue); - } - - private static void localSetGlobalProperty(Property property, T... propertyValue) - { - if (!property.type.isAssignableFrom(propertyValue[0].getClass())) - { - throw new IllegalArgumentException("Bad property value passed"); - } - - // set the property for the current thread as well to avoid mass confusion - localSetThread(property, propertyValue); - - globalProperties.put(property.name, propertyValue); - } - - /** - * Clear the global value for the passed in property. - * - * @param property the property to be cleared. - * @param the base type of the property value - * @return an array of T if a value was previously set, null otherwise. - */ - public static T[] clearGlobalProperty(Property property) - { - checkPermission(CanSetDefaultProperty); - - // clear the property for the current thread as well to avoid confusion - localClearThreadProperty(property); - - return (T[])globalProperties.remove(property.name); - } - - /** - * Clear the thread local value for the passed in property. - * - * @param property the property to be cleared. - * @param the base type of the property value - * @return an array of T if a value was previously set, null otherwise. - */ - public static T[] clearThreadProperty(Property property) - { - checkPermission(CanSetThreadProperty); - - return (T[])localClearThreadProperty(property); - } - - private static Object[] localClearThreadProperty(Property property) - { - Map properties = threadProperties.get(); - - if (properties == null) - { - properties = new HashMap(); - threadProperties.set(properties); - } - - return properties.remove(property.name); - } - - private static void checkPermission(final Permission permission) - { - final SecurityManager securityManager = System.getSecurityManager(); - - if (securityManager != null) - { - AccessController.doPrivileged(new PrivilegedAction() - { - public Object run() - { - securityManager.checkPermission(permission); - - return null; - } - }); - } - } - - private static DHParameters toDH(DSAParameters dsaParams) - { - int pSize = dsaParams.getP().bitLength(); - int m = chooseLowerBound(pSize); - return new DHParameters(dsaParams.getP(), dsaParams.getG(), dsaParams.getQ(), m, 0, null, - new DHValidationParameters(dsaParams.getValidationParameters().getSeed(), dsaParams.getValidationParameters().getCounter())); - } - - // based on lower limit of at least 2^{2 * bits_of_security} - private static int chooseLowerBound(int pSize) - { - int m = 160; - if (pSize > 1024) - { - if (pSize <= 2048) - { - m = 224; - } - else if (pSize <= 3072) - { - m = 256; - } - else if (pSize <= 7680) - { - m = 384; - } - else - { - m = 512; - } - } - return m; - } - - private static CryptoServicesConstraints getDefaultConstraints() - { - // TODO: return one based on system/security properties if set. - - return noConstraintsImpl; - } - - /** - * Available properties that can be set. - */ - public static final class Property - { - /** - * The parameters to be used for processing implicitlyCA X9.62 parameters - */ - public static final Property EC_IMPLICITLY_CA = new Property("ecImplicitlyCA", X9ECParameters.class); - /** - * The default parameters for a particular size of Diffie-Hellman key.This is a sized property. - */ - public static final Property DH_DEFAULT_PARAMS = new Property("dhDefaultParams", DHParameters.class); - /** - * The default parameters for a particular size of DSA key. This is a sized property. - */ - public static final Property DSA_DEFAULT_PARAMS = new Property("dsaDefaultParams", DSAParameters.class); - private final String name; - private final Class type; - - private Property(String name, Class type) - { - this.name = name; - this.type = type; - } - } - - private static class ThreadLocalSecureRandomProvider - implements SecureRandomProvider - { - final ThreadLocal defaultRandoms = new ThreadLocal(); - - public SecureRandom get() - { - if (defaultRandoms.get() == null) - { - defaultRandoms.set(new SecureRandom()); - } - - return defaultRandoms.get(); - } + return null == secureRandom ? sr : secureRandom; } } diff --git a/router/java/src/org/bouncycastle/crypto/digests/KeccakDigest.java b/router/java/src/org/bouncycastle/crypto/digests/KeccakDigest.java index f53552e550..933f14f697 100644 --- a/router/java/src/org/bouncycastle/crypto/digests/KeccakDigest.java +++ b/router/java/src/org/bouncycastle/crypto/digests/KeccakDigest.java @@ -1,10 +1,11 @@ package org.bouncycastle.crypto.digests; +import java.util.Arrays; + import org.bouncycastle.crypto.CryptoServiceProperties; import org.bouncycastle.crypto.CryptoServicePurpose; import org.bouncycastle.crypto.CryptoServicesRegistrar; import org.bouncycastle.crypto.ExtendedDigest; -import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Pack; /** @@ -438,6 +439,6 @@ public class KeccakDigest protected CryptoServiceProperties cryptoServiceProperties() { - return Utils.getDefaultProperties(this, getDigestSize() * 8, purpose); + return null; } } diff --git a/router/java/src/org/bouncycastle/crypto/digests/SHA512Digest.java b/router/java/src/org/bouncycastle/crypto/digests/SHA512Digest.java index 0fab188b98..85753972ae 100644 --- a/router/java/src/org/bouncycastle/crypto/digests/SHA512Digest.java +++ b/router/java/src/org/bouncycastle/crypto/digests/SHA512Digest.java @@ -143,7 +143,8 @@ public class SHA512Digest protected CryptoServiceProperties cryptoServiceProperties() { - return Utils.getDefaultProperties(this, 256, purpose); + return null; + //return Utils.getDefaultProperties(this, 256, purpose); } } diff --git a/router/java/src/org/bouncycastle/crypto/digests/SHAKEDigest.java b/router/java/src/org/bouncycastle/crypto/digests/SHAKEDigest.java index 4b30c0e150..998f1286ab 100644 --- a/router/java/src/org/bouncycastle/crypto/digests/SHAKEDigest.java +++ b/router/java/src/org/bouncycastle/crypto/digests/SHAKEDigest.java @@ -145,6 +145,6 @@ public class SHAKEDigest protected CryptoServiceProperties cryptoServiceProperties() { - return Utils.getDefaultProperties(this, purpose); + return null; } } diff --git a/router/java/src/org/bouncycastle/crypto/params/ParametersWithContext.java b/router/java/src/org/bouncycastle/crypto/params/ParametersWithContext.java index 0f6a3c8524..e8778cbe20 100644 --- a/router/java/src/org/bouncycastle/crypto/params/ParametersWithContext.java +++ b/router/java/src/org/bouncycastle/crypto/params/ParametersWithContext.java @@ -1,7 +1,7 @@ package org.bouncycastle.crypto.params; import org.bouncycastle.crypto.CipherParameters; -import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Util; public class ParametersWithContext implements CipherParameters @@ -19,7 +19,7 @@ public class ParametersWithContext } this.parameters = parameters; - this.context = Arrays.clone(context); + this.context = Util.clone(context); } public void copyContextTo(byte[] buf, int off, int len) @@ -34,7 +34,7 @@ public class ParametersWithContext public byte[] getContext() { - return Arrays.clone(context); + return Util.clone(context); } public int getContextLength() diff --git a/router/java/src/org/bouncycastle/package-info.java b/router/java/src/org/bouncycastle/package-info.java new file mode 100644 index 0000000000..ad1c9ca40e --- /dev/null +++ b/router/java/src/org/bouncycastle/package-info.java @@ -0,0 +1,6 @@ +/** + * This is a small portion of bouncycastle 1.80 for MLKEM, modified to reduce dependencies. + * + * @since 0.9.67 + */ +package org.bouncycastle; diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMEngine.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMEngine.java index b41116e7a2..6c5b49f36a 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMEngine.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMEngine.java @@ -1,8 +1,9 @@ package org.bouncycastle.pqc.crypto.mlkem; import java.security.SecureRandom; +import java.util.Arrays; -import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Util; class MLKEMEngine { @@ -219,7 +220,7 @@ class MLKEMEngine s, hashedPublicKey, z, - Arrays.concatenate(d, z) + Util.concatenate(d, z) }; } @@ -274,7 +275,7 @@ class MLKEMEngine byte[] cmp = indCpa.encrypt(publicKey, Arrays.copyOfRange(buf, 0, KyberSymBytes), Arrays.copyOfRange(kr, KyberSymBytes, kr.length)); - boolean fail = !(Arrays.constantTimeAreEqual(cipherText, cmp)); + boolean fail = !(Util.constantTimeAreEqual(cipherText, cmp)); cmov(kr, implicit_rejection, KyberSymBytes, fail); @@ -294,7 +295,7 @@ class MLKEMEngine PolyVec polyVec = new PolyVec(this); byte[] seed = indCpa.unpackPublicKey(polyVec, publicKeyInput); byte[] ek = indCpa.packPublicKey(polyVec, seed); - if (!Arrays.areEqual(ek, publicKeyInput)) + if (!Arrays.equals(ek, publicKeyInput)) { throw new IllegalArgumentException("Input validation: Modulus check failed for ml-kem encapsulation"); } diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMExtractor.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMExtractor.java index 6f19f835e6..e36c3c6ae3 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMExtractor.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMExtractor.java @@ -1,9 +1,6 @@ package org.bouncycastle.pqc.crypto.mlkem; -import org.bouncycastle.crypto.EncapsulatedSecretExtractor; - public class MLKEMExtractor - implements EncapsulatedSecretExtractor { private final MLKEMPrivateKeyParameters privateKey; private final MLKEMEngine engine; diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMGenerator.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMGenerator.java index 61c693724d..cfeb318009 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMGenerator.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMGenerator.java @@ -2,13 +2,11 @@ package org.bouncycastle.pqc.crypto.mlkem; import java.security.SecureRandom; -import org.bouncycastle.crypto.EncapsulatedSecretGenerator; import org.bouncycastle.crypto.SecretWithEncapsulation; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.pqc.crypto.util.SecretWithEncapsulationImpl; public class MLKEMGenerator - implements EncapsulatedSecretGenerator { // the source of randomness private final SecureRandom sr; diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMIndCpa.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMIndCpa.java index c5d7527c33..3e30319137 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMIndCpa.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMIndCpa.java @@ -1,6 +1,8 @@ package org.bouncycastle.pqc.crypto.mlkem; -import org.bouncycastle.util.Arrays; +import java.util.Arrays; + +import org.bouncycastle.util.Util; class MLKEMIndCpa { @@ -51,7 +53,7 @@ class MLKEMIndCpa // (p, sigma) <- G(d || k) byte[] buf = new byte[64]; - symmetric.hash_g(buf, Arrays.append(d, (byte)kyberK)); + symmetric.hash_g(buf, Util.append(d, (byte)kyberK)); byte[] publicSeed = new byte[32]; // p in docs byte[] noiseSeed = new byte[32]; // sigma in docs diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMKeyPairGenerator.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMKeyPairGenerator.java index 22c1d686db..9f1d6d9dc2 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMKeyPairGenerator.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMKeyPairGenerator.java @@ -3,11 +3,9 @@ package org.bouncycastle.pqc.crypto.mlkem; import java.security.SecureRandom; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; -import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; import org.bouncycastle.crypto.KeyGenerationParameters; public class MLKEMKeyPairGenerator - implements AsymmetricCipherKeyPairGenerator { private MLKEMParameters mlkemParams; diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMPrivateKeyParameters.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMPrivateKeyParameters.java index b59198a6f1..43d19653ba 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMPrivateKeyParameters.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMPrivateKeyParameters.java @@ -1,6 +1,8 @@ package org.bouncycastle.pqc.crypto.mlkem; -import org.bouncycastle.util.Arrays; +import java.util.Arrays; + +import org.bouncycastle.util.Util; public class MLKEMPrivateKeyParameters extends MLKEMKeyParameters @@ -21,12 +23,12 @@ public class MLKEMPrivateKeyParameters { super(true, params); - this.s = Arrays.clone(s); - this.hpk = Arrays.clone(hpk); - this.nonce = Arrays.clone(nonce); - this.t = Arrays.clone(t); - this.rho = Arrays.clone(rho); - this.seed = Arrays.clone(seed); + this.s = Util.clone(s); + this.hpk = Util.clone(hpk); + this.nonce = Util.clone(nonce); + this.t = Util.clone(t); + this.rho = Util.clone(rho); + this.seed = Util.clone(seed); } public MLKEMPrivateKeyParameters(MLKEMParameters params, byte[] encoding) @@ -64,17 +66,17 @@ public class MLKEMPrivateKeyParameters public byte[] getEncoded() { - return Arrays.concatenate(new byte[][]{ s, t, rho, hpk, nonce }); + return Util.concatenate(new byte[][]{ s, t, rho, hpk, nonce }); } public byte[] getHPK() { - return Arrays.clone(hpk); + return Util.clone(hpk); } public byte[] getNonce() { - return Arrays.clone(nonce); + return Util.clone(nonce); } public byte[] getPublicKey() @@ -89,21 +91,21 @@ public class MLKEMPrivateKeyParameters public byte[] getRho() { - return Arrays.clone(rho); + return Util.clone(rho); } public byte[] getS() { - return Arrays.clone(s); + return Util.clone(s); } public byte[] getT() { - return Arrays.clone(t); + return Util.clone(t); } public byte[] getSeed() { - return Arrays.clone(seed); + return Util.clone(seed); } } diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMPublicKeyParameters.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMPublicKeyParameters.java index 5f2676d730..e2cc7afe2b 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMPublicKeyParameters.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/MLKEMPublicKeyParameters.java @@ -1,13 +1,15 @@ package org.bouncycastle.pqc.crypto.mlkem; -import org.bouncycastle.util.Arrays; +import java.util.Arrays; + +import org.bouncycastle.util.Util; public class MLKEMPublicKeyParameters extends MLKEMKeyParameters { static byte[] getEncoded(byte[] t, byte[] rho) { - return Arrays.concatenate(t, rho); + return Util.concatenate(t, rho); } final byte[] t; @@ -16,8 +18,8 @@ public class MLKEMPublicKeyParameters public MLKEMPublicKeyParameters(MLKEMParameters params, byte[] t, byte[] rho) { super(false, params); - this.t = Arrays.clone(t); - this.rho = Arrays.clone(rho); + this.t = Util.clone(t); + this.rho = Util.clone(rho); } public MLKEMPublicKeyParameters(MLKEMParameters params, byte[] encoding) @@ -34,11 +36,11 @@ public class MLKEMPublicKeyParameters public byte[] getRho() { - return Arrays.clone(rho); + return Util.clone(rho); } public byte[] getT() { - return Arrays.clone(t); + return Util.clone(t); } } diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/PolyVec.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/PolyVec.java index d6613e904f..d802840dd9 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/PolyVec.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/PolyVec.java @@ -1,6 +1,6 @@ package org.bouncycastle.pqc.crypto.mlkem; -import org.bouncycastle.util.Arrays; +import java.util.Arrays; class PolyVec { diff --git a/router/java/src/org/bouncycastle/pqc/crypto/mlkem/package-info.java b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/package-info.java new file mode 100644 index 0000000000..3bcbfa374f --- /dev/null +++ b/router/java/src/org/bouncycastle/pqc/crypto/mlkem/package-info.java @@ -0,0 +1,6 @@ +/** + * This is a small portion of bouncycastle 1.80 for MLKEM, modified to reduce dependencies. + * MLDSA and common classes are in i2p.jar (core). + * @since 0.9.67 + */ +package org.bouncycastle.pqc.crypto.mlkem; diff --git a/router/java/src/org/bouncycastle/pqc/crypto/util/SecretWithEncapsulationImpl.java b/router/java/src/org/bouncycastle/pqc/crypto/util/SecretWithEncapsulationImpl.java index ab60d77409..9e07bd654d 100644 --- a/router/java/src/org/bouncycastle/pqc/crypto/util/SecretWithEncapsulationImpl.java +++ b/router/java/src/org/bouncycastle/pqc/crypto/util/SecretWithEncapsulationImpl.java @@ -1,11 +1,12 @@ package org.bouncycastle.pqc.crypto.util; +import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import javax.security.auth.DestroyFailedException; import org.bouncycastle.crypto.SecretWithEncapsulation; -import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Util; public class SecretWithEncapsulationImpl implements SecretWithEncapsulation @@ -23,7 +24,7 @@ public class SecretWithEncapsulationImpl public byte[] getSecret() { - byte[] clone = Arrays.clone(sessionKey); + byte[] clone = Util.clone(sessionKey); checkDestroyed(); @@ -32,7 +33,7 @@ public class SecretWithEncapsulationImpl public byte[] getEncapsulation() { - byte[] clone = Arrays.clone(cipher_text); + byte[] clone = Util.clone(cipher_text); checkDestroyed(); @@ -44,8 +45,8 @@ public class SecretWithEncapsulationImpl { if (!hasBeenDestroyed.getAndSet(true)) { - Arrays.clear(sessionKey); - Arrays.clear(cipher_text); + Arrays.fill(sessionKey, (byte) 0); + Arrays.fill(cipher_text, (byte) 0); } } diff --git a/router/java/src/org/bouncycastle/util/Memoable.java b/router/java/src/org/bouncycastle/util/Memoable.java index a6eede90c1..3ee7a0cce1 100644 --- a/router/java/src/org/bouncycastle/util/Memoable.java +++ b/router/java/src/org/bouncycastle/util/Memoable.java @@ -21,7 +21,6 @@ public interface Memoable * * @param other an object originally {@link #copy() copied} from an object of the same type as this instance. * @throws ClassCastException if the provided object is not of the correct type. - * @throws MemoableResetException if the other parameter is in some other way invalid. */ void reset(Memoable other); } diff --git a/router/java/src/org/bouncycastle/util/Util.java b/router/java/src/org/bouncycastle/util/Util.java new file mode 100644 index 0000000000..20873b3e79 --- /dev/null +++ b/router/java/src/org/bouncycastle/util/Util.java @@ -0,0 +1,52 @@ +package org.bouncycastle.util; + +import java.util.Arrays; + +import net.i2p.data.DataHelper; + +public class Util +{ + public static byte[] clone(byte[] a) + { + return Arrays.copyOf(a, a.length); + } + + public static byte[] concatenate(byte[][] arrays) + { + int size = 0; + for (int i = 0; i != arrays.length; i++) + { + size += arrays[i].length; + } + + byte[] rv = new byte[size]; + + int offSet = 0; + for (int i = 0; i != arrays.length; i++) + { + System.arraycopy(arrays[i], 0, rv, offSet, arrays[i].length); + offSet += arrays[i].length; + } + + return rv; + } + + public static byte[] concatenate(byte[] a, byte[] b) + { + byte[] rv = Arrays.copyOf(a, a.length + b.length); + System.arraycopy(b, 0, rv, a.length, b.length); + return rv; + } + + public static byte[] append(byte[] a, byte b) + { + byte[] rv = Arrays.copyOf(a, a.length + 1); + rv[a.length] = b; + return rv; + } + + public static boolean constantTimeAreEqual(byte[] a, byte[] b) + { + return a.length == b.length && DataHelper.eqCT(a, 0, b, 0, a.length); + } +}