From afe7f4ed4edc646facb4f156b04fcc428a4baa9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 16:04:56 +0300 Subject: [PATCH 01/23] Added multiples classes implementing the TLS injection mechanism in BC --- .../tls/injection/InjectableAlgorithms.java | 69 +++++++ .../tls/injection/InjectableKEMs.java | 118 ++++++++++++ .../tls/injection/InjectableSigAlgs.java | 173 +++++++++++++++++ .../tls/injection/InjectionPoint.java | 146 +++++++++++++++ .../tls/injection/kems/InjectedKEM.java | 48 +++++ .../bouncycastle/tls/injection/kems/KEM.java | 43 +++++ .../tls/injection/kems/KemFactory.java | 5 + .../injection/kems/TlsAgreementForKEM.java | 101 ++++++++++ .../tls/injection/sigalgs/Asn1Bridge.java | 60 ++++++ .../sigalgs/CipherParametersToEncodedKey.java | 7 + .../sigalgs/InjectedSigAlgorithm.java | 93 +++++++++ .../sigalgs/InjectedSigVerifiers.java | 154 +++++++++++++++ .../injection/sigalgs/InjectedSigners.java | 61 ++++++ .../injection/sigalgs/MyMessageSigner.java | 63 +++++++ .../tls/injection/sigalgs/MyStreamSigner.java | 40 ++++ .../injection/sigalgs/MyTls13Verifier.java | 71 +++++++ .../tls/injection/sigalgs/MyTlsSigner.java | 34 ++++ .../sigalgs/PrivateKeyToCipherParameters.java | 10 + .../sigalgs/PublicKeyToCipherParameters.java | 10 + .../sigalgs/PublicKeyToEncodedKey.java | 7 + .../tls/injection/sigalgs/SigAlgAPI.java | 97 ++++++++++ .../SignatureAndHashAlgorithmFactory.java | 14 ++ .../tls/injection/sigalgs/SignerFunction.java | 7 + .../injection/sigalgs/VerifierFunction.java | 7 + .../signaturespi/DirectSignatureSpi.java | 177 ++++++++++++++++++ .../signaturespi/UniversalSignatureSpi.java | 108 +++++++++++ 26 files changed, 1723 insertions(+) create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java new file mode 100644 index 0000000000..d942eee064 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java @@ -0,0 +1,69 @@ +package org.bouncycastle.tls.injection; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.tls.injection.kems.KemFactory; +import org.bouncycastle.tls.injection.sigalgs.SigAlgAPI; + +public class InjectableAlgorithms { + + ///// KEMs + private final InjectableKEMs kems; + private final InjectableSigAlgs sigAlgs; + + + public InjectableAlgorithms() { + this(new InjectableKEMs(), new InjectableSigAlgs()); + } + + private InjectableAlgorithms(InjectableKEMs kems, InjectableSigAlgs sigAlgs) { + this.kems = kems; + this.sigAlgs = sigAlgs; + } + + private InjectableAlgorithms(InjectableAlgorithms origin) { // clone constructor + this.kems = new InjectableKEMs(origin.kems); + this.sigAlgs = new InjectableSigAlgs(origin.sigAlgs); + } + + + public InjectableAlgorithms withKEM(int kemCodePoint, + String standardName, KemFactory kemFactory, InjectableKEMs.Ordering ordering) { + return new InjectableAlgorithms( + this.kems.withKEM(kemCodePoint, standardName, kemFactory, ordering), + new InjectableSigAlgs(this.sigAlgs) + ); + } + + public InjectableAlgorithms withoutKEM(int kemCodePoint) { + return new InjectableAlgorithms( + this.kems.withoutKEM(kemCodePoint), + this.sigAlgs + ); + } + + public InjectableAlgorithms withoutDefaultKEMs() { + return new InjectableAlgorithms( + this.kems.withoutDefaultKEMs(), + this.sigAlgs + ); + } + + public InjectableAlgorithms withSigAlg(String name, + ASN1ObjectIdentifier oid, + int signatureSchemeCodePoint, + SigAlgAPI api) { + InjectableAlgorithms clone = new InjectableAlgorithms(this); + clone.sigAlgs().add(name, oid, signatureSchemeCodePoint, api); + return clone; + } + + public InjectableKEMs kems() { + return this.kems; + } + + public InjectableSigAlgs sigAlgs() { + return this.sigAlgs; + } + + +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java new file mode 100644 index 0000000000..f3a3cd4bad --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java @@ -0,0 +1,118 @@ +package org.bouncycastle.tls.injection; + +import org.bouncycastle.tls.injection.kems.InjectedKEM; +import org.bouncycastle.tls.injection.kems.KemFactory; + +import java.util.*; + +public class InjectableKEMs { + public enum Ordering { BEFORE, AFTER }; + + ///// KEMs + private final List kemsBefore; + private final boolean useDefaultKems; + private final List kemsAfter; + private final Map code2kem; + + public InjectableKEMs() { + this.kemsBefore = new LinkedList<>(); + this.useDefaultKems = true; + this.kemsAfter = new LinkedList<>(); + this.code2kem = new HashMap<>(); + + } + + InjectableKEMs(InjectableKEMs origin) { // clone constructor + this(origin, origin.useDefaultKems); + } + private InjectableKEMs(InjectableKEMs origin, boolean useDefaultKems) { // clone constructor + this.kemsBefore = new LinkedList<>(origin.kemsBefore); + this.useDefaultKems = useDefaultKems; + this.kemsAfter = new LinkedList<>(origin.kemsAfter); + this.code2kem = new HashMap<>(origin.code2kem); + } + + public InjectableKEMs withKEM(int kemCodePoint, + String standardName, KemFactory kemFactory, Ordering ordering) { + if (code2kem.containsKey(kemCodePoint)) + throw new RuntimeException("KEM code point "+kemCodePoint+" already exists."); + + InjectedKEM kem = new InjectedKEM(kemCodePoint, standardName, kemFactory); + + InjectableKEMs clone = new InjectableKEMs(this); + clone.code2kem.put(kemCodePoint, kem); + if (ordering == Ordering.BEFORE) + clone.kemsBefore.add(kemCodePoint); + else + clone.kemsAfter.add(kemCodePoint); + return clone; + } + + public InjectableKEMs withoutKEM(int kemCodePoint) { + if (!code2kem.containsKey(kemCodePoint)) + throw new RuntimeException("KEM code point "+kemCodePoint+" does not exist."); + + InjectableKEMs clone = new InjectableKEMs(this); + clone.code2kem.remove(kemCodePoint); + + int i = clone.kemsBefore.indexOf(kemCodePoint); + if (i>=0) + clone.kemsBefore.remove(i); + + i = clone.kemsAfter.indexOf(kemCodePoint); + if (i>=0) + clone.kemsAfter.remove(i); + return clone; + } + + public InjectableKEMs withoutDefaultKEMs() { + return new InjectableKEMs(this, false); + } + + public boolean contain(int codePoint) { + return code2kem.containsKey(codePoint); + } + + public InjectedKEM kemByCodePoint(int codePoint) { + return code2kem.get(codePoint); + } + + public Collection kemsByOrdering(Ordering ordering) { + if (ordering == Ordering.BEFORE) + return kemsBefore.stream().map(code2kem::get).toList(); + else + return kemsAfter.stream().map(code2kem::get).toList(); + } + + public Collection asCodePointCollection(Ordering ordering) { + if (ordering == Ordering.BEFORE) + return new LinkedList<>(kemsBefore); + else + return new LinkedList<>(kemsAfter); + } + + public Collection asCodePointCollection() { + List result = new LinkedList<>(kemsBefore); + result.addAll(kemsAfter); + return result; + } + + public boolean defaultKemsNeeded() { + return useDefaultKems; + } + + public InjectedKEM firstKEM() { + + + Collection kems = kemsByOrdering(InjectableKEMs.Ordering.BEFORE); + if (!kems.isEmpty()) + return kems.iterator().next(); + + kems = kemsByOrdering(InjectableKEMs.Ordering.AFTER); + if (!kems.isEmpty()) + return kems.iterator().next(); + + throw new IllegalStateException("No KEM injected"); + } + +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java new file mode 100644 index 0000000000..f768a92c3c --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java @@ -0,0 +1,173 @@ +package org.bouncycastle.tls.injection; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.tls.SignatureAndHashAlgorithm; +import org.bouncycastle.tls.crypto.TlsSigner; +import org.bouncycastle.tls.crypto.TlsVerifier; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.injection.sigalgs.*; + +import java.io.IOException; +import java.security.*; +import java.util.*; + +public class InjectableSigAlgs { + + private final List orderedSigs; + private final Map code2sig; + private final Map oid2sig; + private final InjectedSigners signers; + private final InjectedSigVerifiers verifiers; + + public InjectableSigAlgs() { + this.orderedSigs = new LinkedList<>(); + this.code2sig = new HashMap<>(); + this.oid2sig = new HashMap<>(); + this.signers = new InjectedSigners(); + this.verifiers = new InjectedSigVerifiers(); + } + + InjectableSigAlgs(InjectableSigAlgs origin) { // clone constructor + this.orderedSigs = new LinkedList<>(origin.orderedSigs); + this.code2sig = new HashMap<>(origin.code2sig); + this.oid2sig = new HashMap<>(origin.oid2sig); + this.signers = new InjectedSigners(origin.signers); + this.verifiers = new InjectedSigVerifiers(origin.verifiers); + } + + public void add(String name, + ASN1ObjectIdentifier oid, + int signatureSchemeCodePoint, + SigAlgAPI api) { + InjectedSigAlgorithm newAlg = new InjectedSigAlgorithm(name, oid, signatureSchemeCodePoint, api); + orderedSigs.add(newAlg); + code2sig.put(signatureSchemeCodePoint, newAlg); + oid2sig.put(oid.toString(), newAlg); + signers.add(name, api::sign); + verifiers.add(signatureSchemeCodePoint, api::verifySignature, api::internalEncoding); + } + + public boolean contain(int codePoint) { + return code2sig.containsKey(codePoint); + } + + public boolean contain(SignatureAndHashAlgorithm signatureAndHashAlgorithm) { + int codePoint = SignatureAndHashAlgorithmFactory.codePointFromSignatureAndHashAlgorithm(signatureAndHashAlgorithm); + return code2sig.containsKey(codePoint); + } + + public boolean contain(ASN1ObjectIdentifier oid) { + for (InjectedSigAlgorithm sigAlgorithm : orderedSigs) { + if (oid.equals(sigAlgorithm.oid())) + return true; + } + return false; + } + + public Collection asSigAndHashCollection() { + return orderedSigs.stream().map(InjectedSigAlgorithm::signatureAndHashAlgorithm).toList(); + } + + public Collection asCodePointCollection() { + return orderedSigs.stream().map(InjectedSigAlgorithm::codePoint).toList(); + } + + public Collection asSigAlgCollection() { + return orderedSigs; + } + + public Iterable names() { + return signers.getNames(); + } + + ///// for BC TLS + + public Asn1Bridge asn1Bridge() { + return new Asn1Bridge() { + @Override + public boolean isSupportedParameter(AsymmetricKeyParameter bcKey) { + for (InjectedSigAlgorithm sigAlg : orderedSigs) { + if (sigAlg.isSupportedParameter(bcKey)) + return true; + } + return false; + } + + @Override + public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo asnPrivateKey) throws IOException { + AlgorithmIdentifier algId = asnPrivateKey.getPrivateKeyAlgorithm(); + ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + String algKey = algOID.toString(); + return oid2sig.get(algKey).createPrivateKeyParameter(asnPrivateKey); + } + + @Override + public PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter bcPrivateKey, ASN1Set attributes) throws IOException { + for (InjectedSigAlgorithm sigAlg : orderedSigs) { + if (sigAlg.isSupportedParameter(bcPrivateKey)) + return sigAlg.createPrivateKeyInfo(bcPrivateKey, attributes); + } + throw new RuntimeException("Unsupported private key params were given"); + } + + @Override + public AsymmetricKeyParameter createPublicKeyParameter(SubjectPublicKeyInfo ansPublicKey, Object defaultParams) throws IOException { + AlgorithmIdentifier algId = ansPublicKey.getAlgorithm(); + ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + String algKey = algOID.toString(); + return oid2sig.get(algKey).createPublicKeyParameter(ansPublicKey, defaultParams); + } + + @Override + public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter bcPublicKey) throws IOException { + for (InjectedSigAlgorithm sigAlg : orderedSigs) { + if (sigAlg.isSupportedParameter(bcPublicKey)) + return sigAlg.createSubjectPublicKeyInfo(bcPublicKey); + } + throw new RuntimeException("Unsupported public key params were given"); + } + }; + } + + ; + + public MyTls13Verifier tls13VerifierFor(PublicKey key) throws InvalidKeyException { + SignatureSpi spi = signatureSpiFor(key); + + + return new MyTls13Verifier(key, spi); + } + + public TlsVerifier tlsVerifierFor(JcaTlsCrypto crypto, PublicKey publicKey, int sigSchemeCodePoint) { + return verifiers.tlsVerifier(crypto, publicKey, sigSchemeCodePoint); + } + + public TlsSigner tlsSignerFor(JcaTlsCrypto crypto, PrivateKey privateKey) { + return signers.tlsSigner(crypto, privateKey); + } + + public SignatureSpi signatureSpiFor(Key publicOrPrivateKey) throws InvalidKeyException { + SignatureSpi result = null; + for (InjectedSigAlgorithm sigAlg : orderedSigs) { + try { + result = sigAlg.signatureSpi(publicOrPrivateKey); + } catch (Exception e) { + // SignatureSpi could not been created with this factory, continue with the next one + } + if (result != null) + break; + } + + if (result == null) { + throw new InvalidKeyException("No known SignatureSpi for the passed public key of type " + publicOrPrivateKey.getClass().getName()); + } + + return result; + } + +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java new file mode 100644 index 0000000000..fd29c65bc9 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java @@ -0,0 +1,146 @@ +package org.bouncycastle.tls.injection; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; +import org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider; +import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; +import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgorithm; + +import java.util.Stack; + +public class InjectionPoint { + private final Stack injectionStack; + + + // Bill Pugh Singleton Implementation, see https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/ + private static class BillPughSingleton { + private static final InjectionPoint INSTANCE = new InjectionPoint(); + } + + // private = do not allow to call the constructor directly; force using _new + private InjectionPoint() { + this.injectionStack = new Stack<>(); + } + + public static InjectionPoint _new() { + return BillPughSingleton.INSTANCE; + } + + /** + * Injects (pushes) the given algorithms into BouncyCastle TLS implementation. + * + * @param newAlgorithms the algorithms to inject + * @throws IllegalStateException if another set of InjectableAlgorithms has already been injected (pushed). + * In this case, use pushAfter() to be able to push the new algorithms instead of the previous. + * Alternatively, use pop() to withdraw all previously injected algorithms and push() the new set of algorithms. + */ + public synchronized void push(InjectableAlgorithms newAlgorithms) throws IllegalStateException { + if (!injectionStack.isEmpty()) + throw new IllegalStateException("Some other algorithms have been already injected (pushed)."); + + injectionStack.push(newAlgorithms); + } + + /** + * Injects (pushes) the current InjectableAlgorithms into BouncyCastle TLS implementation + * by replacing (staging into the stack) the previously injected algorithms. + * + * @param newAlgorithms the algorithms to inject + * @param previous the previously injected algorithms (works as a "token" that allows us to "overwrite" them) + * @throws IllegalStateException if the previously injected algorithms do not match the " previous" argument. + * In this case, use pop() to withdraw all previously injected algorithms and push() the new set of algorithms. + */ + public synchronized void pushAfter(InjectableAlgorithms newAlgorithms, InjectableAlgorithms previous) throws IllegalStateException { + if (injectionStack.isEmpty()) + throw new IllegalStateException("No previously injected (pushed) algorithms found."); + if (!injectionStack.peek().equals(previous)) + throw new IllegalStateException("The previously injected (pushed) algorithms do not match the previous argument."); + injectionStack.push(newAlgorithms); + } + + /** + * Withdraws (pops) the current set of algorithms and restores the previously injected algorithms (if any). + * + * @throws IllegalStateException if no InjectableAlgorithms have been pushed + */ + public synchronized void pop() throws IllegalStateException { + if (injectionStack.isEmpty()) + throw new IllegalStateException("No previously injected (pushed) algorithms found."); + injectionStack.pop(); + } + + + ///// for BC TLS + + private static InjectableKEMs dummyKems = new InjectableKEMs(); + private static InjectableSigAlgs dummySigAlgs = new InjectableSigAlgs(); + + public static InjectableKEMs kems() { + InjectableAlgorithms algs = BillPughSingleton.INSTANCE.injectionStack.peek(); + if (algs == null) + return dummyKems; + return algs.kems(); + } + + public static InjectableSigAlgs sigAlgs() { + InjectableAlgorithms algs = BillPughSingleton.INSTANCE.injectionStack.peek(); + if (algs == null) + return dummySigAlgs; + return algs.sigAlgs(); + } + + public synchronized static void configureProvider(ConfigurableProvider provider) { + + // TODO: call not only from BouncyCastlePQCProvider, but also from JSSE? + InjectableAlgorithms algs = BillPughSingleton.INSTANCE.injectionStack.peek(); + for (InjectedSigAlgorithm alg : sigAlgs().asSigAlgCollection()) { + + new Registrar(alg.oid(), alg.name(), alg.converter()).configure(provider); + } + } + + private static class Registrar extends AsymmetricAlgorithmProvider { + private final ASN1ObjectIdentifier oid; + private final String name; + private final AsymmetricKeyInfoConverter converter; + + public Registrar(ASN1ObjectIdentifier oid, String name, AsymmetricKeyInfoConverter converter) { + super(); + this.oid = oid; + this.name = name; + this.converter = converter; + } + + @Override + public void configure(ConfigurableProvider provider) { + try { + provider.addAlgorithm("Alg.Alias.Signature." + this.oid, this.name); + provider.addAlgorithm("Alg.Alias.Signature.OID." + this.oid, this.name); + } catch (IllegalStateException e) { + // ignore, if duplicate (needed for injected RSA) + } + + // remove previous values in order to avoid the duplicate key exception + if (provider instanceof java.security.Provider) { + java.security.Provider p = (java.security.Provider) provider; + p.remove("Signature." + this.name); + p.remove("Alg.Alias.Signature." + this.oid); + p.remove("Alg.Alias.Signature.OID." + this.oid); + } + // = provider.addSignatureAlgorithm(provider, "SPHINCSPLUS", PREFIX + "SignatureSpi$Direct", BCObjectIdentifiers.sphincsPlus); + provider.addAlgorithm("Signature." + this.name, "org.bouncycastle.tls.injection.signaturespi.DirectSignatureSpi"); + provider.addAlgorithm("Alg.Alias.Signature." + this.oid, this.name); + provider.addAlgorithm("Alg.Alias.Signature.OID." + this.oid, this.name); + + + try { + registerOid(provider, this.oid, this.name, converter); + registerOidAlgorithmParameters(provider, this.oid, this.name); + } catch (IllegalStateException e) { + // ignore, if duplicate (needed for injected RSA) + } + provider.addKeyInfoConverter(this.oid, converter); + } + } + +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java new file mode 100644 index 0000000000..9db48029c0 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java @@ -0,0 +1,48 @@ +package org.bouncycastle.tls.injection.kems; + +import org.bouncycastle.tls.crypto.TlsAgreement; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; + +/** + * The class for storing information of an injected key encapsulation mechanism (KEM ~ named group ~ curve). + * (For the needs of Post-Quantum Cryptography, DH/ECC groups/curves have been replaced by KEMs.) + * #tls-injection + * + * @author Sergejs Kozlovics + */ +public class InjectedKEM { + + public interface TlsAgreementFactory { + TlsAgreement create(JcaTlsCrypto crypto, boolean isServer); + } + + private final int codePoint; + private final String standardName; + private final TlsAgreementFactory tlsAgreementFactory; + + public InjectedKEM(int kemCodePoint, + String standardName, KemFactory kemFactory) { + this(kemCodePoint, + standardName, + (crypto, isServer) -> new TlsAgreementForKEM(crypto, isServer, kemFactory.create())); + + } + + public InjectedKEM(int codePoint, String standardName, TlsAgreementFactory tlsAgreementFactory) { + this.codePoint = codePoint; + this.standardName = standardName; + this.tlsAgreementFactory = tlsAgreementFactory; + } + + public int codePoint() { + return this.codePoint; + } + + public String standardName() { + return this.standardName; + } + + public TlsAgreement tlsAgreement(JcaTlsCrypto crypto, boolean isServer) { + return this.tlsAgreementFactory.create(crypto, isServer); + } +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java new file mode 100644 index 0000000000..bfdc72e31b --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java @@ -0,0 +1,43 @@ +package org.bouncycastle.tls.injection.kems; + +import org.openquantumsafe.Pair; + +/** + * A KEM (key encapsulation mechanism) is a set of functions that can be used to obtain + * a symmetric encryption key from asymmetric keys. + * The term KEM is a generalisation of Diffie-Hellman key exchange. + *

+ * The three KEM functions actually define a half-KEM: keyGen() and decapsulate() are called at one side (e.g., the client), + * while encapsulate() is called at the other side (e.g., the server). + *

+ * This interface defines the three functions that are present in any KEM. + * All keys/secrets/ciphertexts are byte[]-encoded. + * #pqc-tls #injection + * + * @author Sergejs Kozlovics + */ +public interface KEM { + /** + * Generates a new key pair (pk, sk). + * + * @return a public key pk and its corresponding private key (=secret key) sk + */ + Pair keyGen() throws Exception; + + /** + * Generates a secret (=symmetric key K) and encapsulates it to be sent to the partner. + * + * @param partnerPublicKey partner's public key received during the TLS handshake + * @return a generated symmetric key K and a ciphertext ct (=K encrypted with partner's public Key) + */ + Pair encapsulate(byte[] partnerPublicKey) throws Exception; + + /** + * Decapsulates the ciphertext (=secret K encrypted with our public key) received from the partner. + * + * @param secretKey our secret key to use to decrypt the ciphertext + * @param ciphertext the ciphertext + * @return the shared secret K + */ + byte[] decapsulate(byte[] secretKey, byte[] ciphertext) throws Exception; +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java new file mode 100644 index 0000000000..b9bd7ddf3c --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java @@ -0,0 +1,5 @@ +package org.bouncycastle.tls.injection.kems; + +public interface KemFactory { + KEM create(); +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java new file mode 100644 index 0000000000..9f76f8e296 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java @@ -0,0 +1,101 @@ +package org.bouncycastle.tls.injection.kems; + +import org.bouncycastle.tls.crypto.TlsAgreement; +import org.bouncycastle.tls.crypto.TlsSecret; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.crypto.impl.jcajce.JceTlsSecret; +import org.openquantumsafe.Pair; + +import java.io.IOException; + + +/** + * #pqc-tls #injection + * Wraps a Half-KEM and represents it as a BouncyCastle TlsAgreement. + * In the Half-KEM, keyGen() is invoked at the client side, encapsulate() at the server side, + * and decapsulate() at the client side. + * + * @author Sergejs Kozlovics + */ +public class TlsAgreementForKEM implements TlsAgreement { + private JcaTlsCrypto crypto; + private boolean isServer; + private KEM kem; // delegate + + + // writable object state (=assignable "coordinates"): + private byte[] peerEncapsulated; + protected byte[] clientSecretKey; + protected byte[] serverSecret; + + public TlsAgreementForKEM(JcaTlsCrypto crypto, boolean isServer, KEM kem) { + this.crypto = crypto; + this.isServer = isServer; + this.kem = kem; + this.peerEncapsulated = null; + this.clientSecretKey = null; + this.serverSecret = null; + } + + public byte[] generateEphemeral() throws IOException { + + Pair p; + + try { + p = kem.keyGen(); + } catch (Exception e) { + throw new RuntimeException(e); + } + byte[] pk = p.getLeft(); + byte[] sk = p.getRight(); + + if (isServer) { + // Half-KEM Step2: client <--- peerEncapsulated ciphertext <--- server + if (this.peerEncapsulated == null) + throw new IOException("receivePeerValue must be called before generateEphemeral for KEMs"); + + Pair p2; + + try { + p = kem.encapsulate(this.peerEncapsulated); // peerEncapsulated === client public key + } catch (Exception e) { + throw new RuntimeException(e); + } + this.serverSecret = p.getLeft(); // server secret + return p.getRight(); + } else { + // Half-KEM Step1: client ---> generated pk ---> server + this.clientSecretKey = sk; + return pk; + } + } + + public void receivePeerValue(byte[] peerEncapsulated) throws IOException { + this.peerEncapsulated = peerEncapsulated; + } + + public TlsSecret calculateSecret() throws IOException { + + if (isServer) { + if (this.serverSecret == null) + throw new IOException("Server-side secret has not been generated: generateEphemeral must be called before calculateSecret"); + return new JceTlsSecret(this.crypto, this.serverSecret); + } else { + if (this.clientSecretKey == null) + throw new IOException("Client-side key pair has not been generated: generateEphemeral must be called before calculateSecret"); + if (this.peerEncapsulated == null) + throw new IOException("receivePeerValue must be called before calculateSecret for KEMs"); + + try { + // Half-KEM Step3: decapsulate at the client + byte[] receivedSecret = kem.decapsulate(this.clientSecretKey, this.peerEncapsulated); + return new JceTlsSecret(this.crypto, receivedSecret); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + } + + +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java new file mode 100644 index 0000000000..e8d2623651 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java @@ -0,0 +1,60 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; + +import java.io.IOException; + +public interface Asn1Bridge { + /** + * Checks whether the given BC key (public or private) can be converted to ASN.1. + * + * @param bcKey an internal BC representation of a public or a private key + * that has to be converted to ASN.1 + * @return returns true, iff bcKey is of known type and can be converted to ASN.1 + * (i.e., a PrivateKeyInfo or SubjectPublicKeyInfo instance) + */ + boolean isSupportedParameter(AsymmetricKeyParameter bcKey); + + /** + * Converts the given private key from ASN.1 to the internal BC representation. + * + * @param asnPrivateKey private key in the ASN.1 notation + * @return internal BC representation of the private key + * @throws IOException + */ + AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo asnPrivateKey) throws IOException; + + + /** + * Converts the given private key from the internal BC representation to the ASN.1 notation. + * + * @param bcPrivateKey internal BC representation of a private key + * @param attributes ASN.1 attributes to be embedded into the ASN.1 representation + * @return ASN.1 representation of the private key + * @throws IOException + */ + PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter bcPrivateKey, ASN1Set attributes) throws IOException; + + + /** + * Converts the given public key from ASN.1 to the internal BC representation. + * + * @param ansPublicKey public key in the ASN.1 notation + * @param defaultParams some default parameters (currently, null is passed) + * @return internal BC representation of the public key + * @throws IOException + */ + AsymmetricKeyParameter createPublicKeyParameter(SubjectPublicKeyInfo ansPublicKey, Object defaultParams) throws IOException; + + /** + * Converts the given public key from the internal BC representation to the ASN.1 notation. + * + * @param bcPublicKey internal BC representation of a public key + * @return ASN.1 representation of the public key + * @throws IOException + */ + SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter bcPublicKey) throws IOException; +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java new file mode 100644 index 0000000000..38772971a8 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java @@ -0,0 +1,7 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.crypto.CipherParameters; + +public interface CipherParametersToEncodedKey { + byte[] encodedKey(CipherParameters params); +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java new file mode 100644 index 0000000000..0a8f0d02c0 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java @@ -0,0 +1,93 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; +import org.bouncycastle.tls.SignatureAndHashAlgorithm; + +import java.io.IOException; +import java.security.Key; +import java.security.PublicKey; +import java.security.SignatureSpi; + +/** + * A class representing injected signature algorithms. #pqc-tls #injection + * + * @author Sergejs Kozlovics + */ +public class InjectedSigAlgorithm { + private final String name; + private final ASN1ObjectIdentifier oid; + private final int signatureSchemeCodePoint; + private final SignatureAndHashAlgorithm signatureAndHashAlgorithm; + // ^^^ Just splits the code point (a 2-byte integer) into two separate bytes: + // HighestByte(signatureSchemeCodePoint), LowestByte(signatureSchemeCodePoint). + // Actually, the highest (the second) byte does not necessarily correspond to the hash algorithm, + // but we still use the BC SignatureAndHashAlgorithm class since it is needed internally + // in many places within BC code. + + private final SigAlgAPI api; + + + public InjectedSigAlgorithm(String name, + ASN1ObjectIdentifier oid, + int signatureSchemeCodePoint, + SigAlgAPI api) { + this.name = name; + this.oid = oid; + this.signatureSchemeCodePoint = signatureSchemeCodePoint; + this.signatureAndHashAlgorithm = SignatureAndHashAlgorithmFactory.newFromCodePoint(signatureSchemeCodePoint); + this.api = api; + } + + public String name() { + return this.name; + } + + public ASN1ObjectIdentifier oid() { + return this.oid; + } + + public int codePoint() { + return this.signatureSchemeCodePoint; + } + + public SignatureAndHashAlgorithm signatureAndHashAlgorithm() { + return this.signatureAndHashAlgorithm; + } + + public boolean isSupportedParameter(AsymmetricKeyParameter param) { + return this.api.isSupportedParameter(param); + } + + public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo keyInfo) throws IOException { + return this.api.createPrivateKeyParameter(keyInfo); + } + + public PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter param, ASN1Set attributes) throws IOException { + return this.api.createPrivateKeyInfo(param, attributes); + } + + public AsymmetricKeyParameter createPublicKeyParameter(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException { + return this.api.createPublicKeyParameter(keyInfo, defaultParams); + } + + public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException { + return this.api.createSubjectPublicKeyInfo(publicKey); + } + + public AsymmetricKeyInfoConverter converter() { + return this.api; + } + + public byte[] internalEncodingFor(PublicKey key) { + return this.api.internalEncoding(key); + } + + public SignatureSpi signatureSpi(Key key) { + return this.api.signatureSpi(key); + } +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java new file mode 100644 index 0000000000..2ab41a5d6a --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java @@ -0,0 +1,154 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.tls.DigitallySigned; +import org.bouncycastle.tls.crypto.TlsStreamVerifier; +import org.bouncycastle.tls.crypto.TlsVerifier; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.PublicKey; +import java.util.HashMap; +import java.util.Map; + +/** + * The class holds signature verifiers (e.g., for PQC) + * and is able to build a TlsVerifier for the given public key. + *

+ * #tls-injection + * + * @author Sergejs Kozlovics + */ +public class InjectedSigVerifiers { + + public interface VerifySignatureFunction { + boolean verifySignature(byte[] data, byte[] key, DigitallySigned signature); + } + + private final Map verifiers; // code point -> verifier fn + private final Map converters; // code point -> encoder fn + + public InjectedSigVerifiers() { + this.verifiers = new HashMap<>(); + this.converters = new HashMap<>(); + } + + public InjectedSigVerifiers(InjectedSigVerifiers origin) { // clone + this.verifiers = new HashMap<>(origin.verifiers); + this.converters = new HashMap<>(origin.converters); + } + + public void add(int sigSchemeCodePoint, VerifySignatureFunction fn, PublicKeyToEncodedKey fn2) { + verifiers.put(sigSchemeCodePoint, fn); + converters.put(sigSchemeCodePoint, fn2); + } + + public boolean contain(int sigSchemeCodePoint) { + return verifiers.containsKey(sigSchemeCodePoint); + } + + public TlsVerifier tlsVerifier(JcaTlsCrypto crypto, PublicKey publicKey, int sigSchemeCodePoint) { + VerifySignatureFunction fn = verifiers.get(sigSchemeCodePoint); + PublicKeyToEncodedKey fn2 = converters.get(sigSchemeCodePoint); + + return new MyTlsVerifier(crypto, publicKey, sigSchemeCodePoint, fn, fn2); + } + + // implementing TlsVerifier via VerifySignatureFunction + private class MyTlsVerifier + implements TlsVerifier { + private final JcaTlsCrypto crypto; + private final PublicKey publicKey; + private final int signatureScheme; + private final VerifySignatureFunction fn; + private final PublicKeyToEncodedKey fn2; + + public MyTlsVerifier(JcaTlsCrypto crypto, PublicKey publicKey, int signatureSchemeCodePoint, VerifySignatureFunction fn, PublicKeyToEncodedKey fn2) { + if (null == crypto) { + throw new NullPointerException("crypto"); + } + if (null == publicKey) { + throw new NullPointerException("publicKey"); + } + if (!contain(signatureSchemeCodePoint)) { + throw new IllegalArgumentException("signatureSchemeCodePoint"); + } + + this.crypto = crypto; + this.publicKey = publicKey; + this.signatureScheme = signatureSchemeCodePoint; + this.fn = fn; + this.fn2 = fn2; + } + + public boolean verifyRawSignature(DigitallySigned signature, byte[] hash) throws IOException { + byte[] encoded = fn2.encodedKey(publicKey); + boolean b = fn.verifySignature(hash, encoded, signature); + return b; + } + + private class MyStreamVerifier implements TlsStreamVerifier { + + private final PublicKey publicKey; + private final DigitallySigned signature; + private final ByteArrayOutputStream stream; + private final int signatureScheme; + + public MyStreamVerifier(PublicKey publicKey, DigitallySigned signature, int signatureScheme) { + this.publicKey = publicKey; + this.signature = signature; + this.stream = new ByteArrayOutputStream(); + this.signatureScheme = signatureScheme; + } + + @Override + public OutputStream getOutputStream() throws IOException { + return this.stream; + } + + @Override + public boolean isVerified() throws IOException { + + byte[] data = this.stream.toByteArray(); + byte[] key = publicKey.getEncoded(); + + int from = 0; + int priorTo = key.length; + + + /* if liboqs +JNI+DLL is used: // TODO + if (this.signatureScheme==SignatureScheme.oqs_rainbowIclassic) { + from = 24; + Signature verifier = new Signature("Rainbow-I-Classic"); + key = Arrays.copyOfRange(key, from, priorTo); + + boolean b = verifier.verify(data, signature.getSignature(), key); + verifier.dispose_sig(); + return b; + } + else*/ + /* for signatureScheme==SignatureScheme.oqs_sphincsshake256128frobust: + from = 26; // see der.md + + SPHINCSPlusSigner signer = new SPHINCSPlusSigner(); + byte[] pubKey = Arrays.copyOfRange(key, from, priorTo); + SPHINCSPlusPublicKeyParameters params = new SPHINCSPlusPublicKeyParameters(SPHINCSPlusParameters.shake256_128f, pubKey); + signer.init(false, params); + boolean b = signer.verifySignature(data, signature.getSignature()); + return b; + + */ + + // the main functionality of MyTlsVerifier: + return fn.verifySignature(data, key, signature); + } + } + + public TlsStreamVerifier getStreamVerifier(DigitallySigned signature) throws IOException { + return new MyStreamVerifier(this.publicKey, signature, this.signatureScheme); + + } + } + +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java new file mode 100644 index 0000000000..5f7e1bd6d6 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java @@ -0,0 +1,61 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.tls.crypto.TlsSigner; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; + +import java.io.IOException; +import java.security.PrivateKey; +import java.util.HashMap; +import java.util.Map; + +/** + * This class holds a set of signers (e.g., for PQC) + * and can build a TlsSigner for the given private key. + * #tls-injection + * + * @author Sergejs Kozlovics + */ +public class InjectedSigners { + + private final Map injectedSigners; + + public InjectedSigners() { + this.injectedSigners = new HashMap<>(); + } + + public InjectedSigners(InjectedSigners origin) { // clone + this.injectedSigners = new HashMap<>(origin.injectedSigners); + } + + public void add(String algorithmName, SignerFunction fn) { + injectedSigners.put(algorithmName, fn); + } + + public boolean contain(String name) { + return injectedSigners.containsKey(name); + } + + public Iterable getNames() { + return injectedSigners.keySet(); + } + + public TlsSigner tlsSigner(JcaTlsCrypto crypto, PrivateKey privateKey) { + String algorithm = privateKey.getAlgorithm(); + + Object fn = injectedSigners.get(algorithm); + if (fn == null) + throw new RuntimeException("Algorithm " + algorithm + " not found among signers."); + + byte[] sk = privateKey.getEncoded(); + PrivateKeyInfo info = PrivateKeyInfo.getInstance(sk); + + byte[] sk2; + try { + sk2 = info.getPrivateKey().getEncoded(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return new MyTlsSigner(crypto, sk2, (SignerFunction) fn); + } +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java new file mode 100644 index 0000000000..0a9686b23e --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java @@ -0,0 +1,63 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import lv.lumii.pqc.InjectablePQC; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.pqc.crypto.MessageSigner; +import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusPrivateKeyParameters; +import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusPublicKeyParameters; +import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusSigner; +import org.bouncycastle.tls.DigitallySigned; +import org.bouncycastle.tls.SignatureAndHashAlgorithm; +import org.bouncycastle.tls.crypto.TlsSigner; +import org.bouncycastle.tls.crypto.TlsStreamSigner; +import org.bouncycastle.util.Pack; + +import java.io.IOException; +import java.util.Arrays; + +public class MyMessageSigner implements MessageSigner { + + private SignatureAndHashAlgorithm algorithm; + private SignerFunction fnSign; + private VerifierFunction fnVerify; + private CipherParametersToEncodedKey paramsToPublicKey, paramsToPrivateKey; + + // the following fields are initialized by BC by invoking init(): + private CipherParameters params; + + public MyMessageSigner(int signatureSchemeCodePoint, + SignerFunction fnSign, VerifierFunction fnVerify, + CipherParametersToEncodedKey paramsToPublicKey, + CipherParametersToEncodedKey paramsToPrivateKey) { + this.algorithm = new SignatureAndHashAlgorithm((short) (signatureSchemeCodePoint >> 8), (short) (signatureSchemeCodePoint & 0xFF)); + this.fnSign = fnSign; + this.fnVerify = fnVerify; + this.paramsToPublicKey = paramsToPublicKey; + this.paramsToPrivateKey = paramsToPrivateKey; + } + + @Override + public void init(boolean forSigning, CipherParameters param) { + this.params = param; + } + + + @Override + public byte[] generateSignature(byte[] message) { + byte[] sk = this.paramsToPrivateKey.encodedKey(params); //skParams.getEncoded(); + + byte[] bcSignature = new byte[0]; + try { + bcSignature = fnSign.sign(null, message, sk); // TODO: do we need to pass crypto instead of null? + } catch (Exception e) { + throw new RuntimeException(e); + } + return bcSignature; + } + + @Override + public boolean verifySignature(byte[] message, byte[] signature) { + byte[] pk = this.paramsToPublicKey.encodedKey(params); + return fnVerify.verify(message, pk, new DigitallySigned(algorithm, signature)); + } +} \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java new file mode 100644 index 0000000000..eb585ebe3d --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java @@ -0,0 +1,40 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.tls.crypto.TlsStreamSigner; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class MyStreamSigner implements TlsStreamSigner { + + private JcaTlsCrypto crypto; + + private SignerFunction fn; + private byte[] key; + private ByteArrayOutputStream os = new ByteArrayOutputStream(); + + public MyStreamSigner(JcaTlsCrypto crypto, byte[] key, SignerFunction fn) { + this.crypto = crypto; + this.fn = fn; + this.key = key; + } + + @Override + public OutputStream getOutputStream() throws IOException { + return os; + } + + @Override + public byte[] getSignature() throws IOException { + byte[] data = os.toByteArray(); + byte[] signature = new byte[0]; + try { + signature = fn.sign(this.crypto, data, key); + } catch (Exception e) { + throw new IOException(e); + } + return signature; + } +} \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java new file mode 100644 index 0000000000..98cbd27259 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java @@ -0,0 +1,71 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.tls.crypto.Tls13Verifier; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.security.*; + +public class MyTls13Verifier + implements Tls13Verifier +{ + private final PublicKey publicKey; + private final SignatureSpi verifier; + + private ByteArrayOutputStream os = new ByteArrayOutputStream(); + + public MyTls13Verifier(PublicKey publicKey, SignatureSpi verifier) + { + this.publicKey = publicKey; + this.verifier = verifier; + } + + private Method findDirectOrInheritedMethod(Class c, String methodName, Class... args) { + Method m = null; + while (c!=null) { + for (Method mm : c.getDeclaredMethods()) { + // this is an optimization: we don't check all arg types, just their number + // (for SignatureSpi-s that's sufficient) + if (mm.getName().equals(methodName) && (args.length == mm.getParameterTypes().length)) + m = mm; + } + if (m!=null) + break; + c = c.getSuperclass(); + } + m.setAccessible(true); + return m; + } + + public final OutputStream getOutputStream() throws IOException + { + return os; + } + + public final boolean verifySignature(byte[] signature) throws IOException + { + try + { + Class c = verifier.getClass(); + + Method m = this.findDirectOrInheritedMethod(c, "engineInitVerify", PublicKey.class); + m.invoke(verifier, publicKey); + + m = this.findDirectOrInheritedMethod(c, "engineUpdate", byte[].class, int.class, int.class); + byte[] data = os.toByteArray(); + m.invoke(verifier, data, 0, data.length); + + m = this.findDirectOrInheritedMethod(c, "engineVerify", byte[].class); + Object result = m.invoke(verifier, signature); + + return (boolean) result; + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java new file mode 100644 index 0000000000..e5c33b0431 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java @@ -0,0 +1,34 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.tls.SignatureAndHashAlgorithm; +import org.bouncycastle.tls.crypto.TlsSigner; +import org.bouncycastle.tls.crypto.TlsStreamSigner; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; + +import java.io.IOException; + +public class MyTlsSigner implements TlsSigner +{ + private JcaTlsCrypto crypto; + private SignerFunction fn; + private byte[] key; + + public MyTlsSigner(JcaTlsCrypto crypto, byte[] key, SignerFunction fn) { + this.crypto = crypto; + this.fn = fn; + this.key = key; + } + + public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm, byte[] hash) + throws IOException { + try { + return this.fn.sign(this.crypto, hash, key); + } catch (Exception e) { + throw new IOException(e); + } + } + + public TlsStreamSigner getStreamSigner(SignatureAndHashAlgorithm algorithm) throws IOException { + return new MyStreamSigner(this.crypto, key, this.fn); + } +} \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java new file mode 100644 index 0000000000..c873cfa2e4 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java @@ -0,0 +1,10 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.crypto.CipherParameters; + +import java.security.InvalidKeyException; +import java.security.PrivateKey; + +public interface PrivateKeyToCipherParameters { + CipherParameters parameters(PrivateKey privateKey) throws InvalidKeyException; +} \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java new file mode 100644 index 0000000000..cd25b1a2a7 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java @@ -0,0 +1,10 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.crypto.CipherParameters; + +import java.security.InvalidKeyException; +import java.security.PublicKey; + +public interface PublicKeyToCipherParameters { + CipherParameters parameters(PublicKey publicKey) throws InvalidKeyException; +} \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java new file mode 100644 index 0000000000..33d5f76e6e --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java @@ -0,0 +1,7 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import java.security.PublicKey; + +public interface PublicKeyToEncodedKey { + byte[] encodedKey(PublicKey key); +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java new file mode 100644 index 0000000000..12b86f5cf2 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java @@ -0,0 +1,97 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; +import org.bouncycastle.tls.DigitallySigned; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; + +import java.io.IOException; +import java.security.Key; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SignatureSpi; + +public interface SigAlgAPI extends AsymmetricKeyInfoConverter, Asn1Bridge { + + ///// BC <-> ASN.1 converters ///// + + /** + * Checks whether the given BC key (public or private) can be converted to ASN.1. + * + * @param bcKey an internal BC representation of a public or a private key + * that has to be converted to ASN.1 + * @return returns true, iff bcKey is of known type and can be converted to ASN.1 + * (i.e., a PrivateKeyInfo or SubjectPublicKeyInfo instance) + */ + boolean isSupportedParameter(AsymmetricKeyParameter bcKey); + + /** + * Converts the given private key from ASN.1 to the internal BC representation. + * + * @param asnPrivateKey private key in the ASN.1 notation + * @return internal BC representation of the private key + * @throws IOException + */ + AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo asnPrivateKey) throws IOException; + + + /** + * Converts the given private key from the internal BC representation to the ASN.1 notation. + * + * @param bcPrivateKey internal BC representation of a private key + * @param attributes ASN.1 attributes to be embedded into the ASN.1 representation + * @return ASN.1 representation of the private key + * @throws IOException + */ + PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter bcPrivateKey, ASN1Set attributes) throws IOException; + + + /** + * Converts the given public key from ASN.1 to the internal BC representation. + * + * @param ansPublicKey public key in the ASN.1 notation + * @param defaultParams some default parameters (currently, null is passed) + * @return internal BC representation of the public key + * @throws IOException + */ + AsymmetricKeyParameter createPublicKeyParameter(SubjectPublicKeyInfo ansPublicKey, Object defaultParams) throws IOException; + + /** + * Converts the given public key from the internal BC representation to the ASN.1 notation. + * + * @param bcPublicKey internal BC representation of a public key + * @return ASN.1 representation of the public key + * @throws IOException + */ + SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter bcPublicKey) throws IOException; + + + ///// AsymmetricKeyInfoConverter ///// + PrivateKey generatePrivate(PrivateKeyInfo keyInfo) + throws IOException; + + PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) + throws IOException; + + ///// Encodings ///// + byte[] internalEncoding(PublicKey key); + + ///// sign & verify ///// + byte[] sign(JcaTlsCrypto crypto, byte[] message, byte[] privateKey) + throws IOException, Exception; + + boolean verifySignature(byte[] message, byte[] publicKey, DigitallySigned signature); + + ///// SPI ///// + + /** + * Constructs a Java Service Provider Interface (SPI) driver for the current signature algorithm. + * This driver will be used by the DirectSignatureSpi of the TLS injection mechanism. + * @param key a public or a private key + * @return a SignatureSpi instance (we suggest using our UniversalSignatureSpi class for that) + */ + SignatureSpi signatureSpi(Key key); +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java new file mode 100644 index 0000000000..3419f6bf7a --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java @@ -0,0 +1,14 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.tls.SignatureAndHashAlgorithm; + +public class SignatureAndHashAlgorithmFactory { + public static SignatureAndHashAlgorithm newFromCodePoint(int signatureSchemeCodePoint) { + return new SignatureAndHashAlgorithm((short) (signatureSchemeCodePoint >> 8), (short) (signatureSchemeCodePoint & 0xFF)); + } + + public static int codePointFromSignatureAndHashAlgorithm(SignatureAndHashAlgorithm sigAndHashAlgorithm) { + int codePoint = (sigAndHashAlgorithm.getHash() << 8) | sigAndHashAlgorithm.getSignature(); + return codePoint; + } +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java new file mode 100644 index 0000000000..92bc53a43c --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java @@ -0,0 +1,7 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; + +public interface SignerFunction { + byte[] sign(JcaTlsCrypto crypto, byte[] data, byte[] key) throws Exception; +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java new file mode 100644 index 0000000000..60a18de1fe --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java @@ -0,0 +1,7 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import org.bouncycastle.tls.DigitallySigned; + +public interface VerifierFunction { + boolean verify(byte[] message, byte[] publicKey, DigitallySigned signature); +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java new file mode 100644 index 0000000000..3a72cebcb8 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java @@ -0,0 +1,177 @@ +package org.bouncycastle.tls.injection.signaturespi; + + +import org.bouncycastle.tls.injection.InjectionPoint; + +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.*; + +/** + * The DirectSignatureSpi class acts as a proxy for all injected SignatureSpi-s. + * DirectSignatureSpi can be registered in JCA/JCE providers, since it has the no-arg constructor. + * See, for example, the InjectedSigAlgorithms class, which registers the full class name + * "org.bouncycastle.tls.injection.signaturespi.DirectSignatureSpi" when configuring a provider. + * + * Internally, DirectSignatureSpi tries all injected SignatureSpi factories until + * some factory returns a valid SignatureSpi. Then this SignatureSpi is used as a delegate + * to which SignatureSpi method invocations are forwarded (via Java reflection due to protected method declarations). + * + * #pqc-tls #injection + * + * @author Sergejs Kozlovics + */ +public class DirectSignatureSpi extends java.security.SignatureSpi +{ + + + private java.security.SignatureSpi delegate = null; // will be initialized in engineInitVerify + + public DirectSignatureSpi() + { + } + + private Method findDirectOrInheritedMethod(Class c, String methodName, Class... args) { + Method m = null; + while (c!=null) { + for (Method mm : c.getDeclaredMethods()) { + // this is an optimization: we don't check all arg types, just their number + // (for SignatureSpi-s that's sufficient) + if (mm.getName().equals(methodName) && (args.length == mm.getParameterTypes().length)) + m = mm; + } + if (m!=null) + break; + c = c.getSuperclass(); + } + return m; + } + + @Override + protected void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException + { + + delegate = InjectionPoint.sigAlgs().signatureSpiFor(publicKey); + + Class c = delegate.getClass(); // searching for the method in the class or in base classes + Method m = findDirectOrInheritedMethod(c, "engineInitVerify", PublicKey.class); + if (m==null) + throw new RuntimeException("Method engineInitVerify not found"); + + try { + m.setAccessible(true); + m.invoke(delegate, publicKey); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { + delegate = InjectionPoint.sigAlgs().signatureSpiFor(privateKey); + + Class c = delegate.getClass(); // searching for the method in the class or in base classes + Method m = findDirectOrInheritedMethod(c, "engineInitSign", PrivateKey.class); + if (m==null) + throw new RuntimeException("Method engineInitSign not found"); + + try { + m.setAccessible(true); + m.invoke(delegate, privateKey); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + protected void engineUpdate(byte b) throws SignatureException { + Class c = delegate.getClass(); // searching for the method in the class or in base classes + Method m = findDirectOrInheritedMethod(c, "engineUpdate", Byte.TYPE); + if (m==null) + throw new RuntimeException("Method engineUpdate(1) not found"); + + try { + m.setAccessible(true); + m.invoke(delegate, b); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { + Class c = delegate.getClass(); // searching for the method in the class or in base classes + Method m = findDirectOrInheritedMethod(c, "engineUpdate", Array.class, Integer.TYPE, Integer.TYPE); + if (m==null) + throw new RuntimeException("Method engineUpdate(3) not found"); + try { + m.setAccessible(true); + m.invoke(delegate, b, off, len); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + protected byte[] engineSign() throws SignatureException { + Class c = delegate.getClass(); // searching for the method in the class or in base classes + Method m = findDirectOrInheritedMethod(c, "engineSign"); + if (m==null) + throw new RuntimeException("Method engineSign not found"); + + try { + m.setAccessible(true); + return (byte[])m.invoke(delegate); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + Class c = delegate.getClass(); // searching for the method in the class or in base classes + Method m = findDirectOrInheritedMethod(c, "engineVerify", Array.class); + if (m==null) + throw new RuntimeException("Method engineVerify not found"); + + try { + m.setAccessible(true); + return (boolean) m.invoke(delegate, sigBytes); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + protected void engineSetParameter(String param, Object value) throws InvalidParameterException { + Class c = delegate.getClass(); // searching for the method in the class or in base classes + Method m = findDirectOrInheritedMethod(c, "engineSetParameter", String.class, Object.class); + if (m==null) + throw new RuntimeException("Method engineSetParameter not found"); + + try { + m.setAccessible(true); + m.invoke(delegate, param, value); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + @Override + protected Object engineGetParameter(String param) throws InvalidParameterException { + Class c = delegate.getClass(); // searching for the method in the class or in base classes + Method m = findDirectOrInheritedMethod(c, "engineGetParameter", String.class); + if (m==null) + throw new RuntimeException("Method engineGetParameter not found"); + + try { + m.setAccessible(true); + return m.invoke(delegate, param); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java new file mode 100644 index 0000000000..d8b8a91bce --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java @@ -0,0 +1,108 @@ +package org.bouncycastle.tls.injection.signaturespi; + +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.params.ParametersWithRandom; +import org.bouncycastle.pqc.crypto.MessageSigner; +import org.bouncycastle.tls.injection.sigalgs.PrivateKeyToCipherParameters; +import org.bouncycastle.tls.injection.sigalgs.PublicKeyToCipherParameters; + +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; + +public class UniversalSignatureSpi + extends java.security.SignatureSpi { + private final Digest digest; + private final MessageSigner signer; + + + private PublicKeyToCipherParameters pkToParams; + private PrivateKeyToCipherParameters skToParams; + + public UniversalSignatureSpi(Digest digest, MessageSigner signer, + PublicKeyToCipherParameters pkToParams, + PrivateKeyToCipherParameters skToParams) { + this.digest = digest; + this.signer = signer; + this.pkToParams = pkToParams; + this.skToParams = skToParams; + } + + protected void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException { + CipherParameters params = this.pkToParams.parameters(publicKey); + signer.init(false, params); + } + + protected void engineInitSign(PrivateKey privateKey, SecureRandom random) + throws InvalidKeyException { + this.appRandom = random; + engineInitSign(privateKey); + } + + protected void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException { + CipherParameters params = this.skToParams.parameters(privateKey); + signer.init(false, params); + + + if (appRandom != null) { + signer.init(true, new ParametersWithRandom(params, appRandom)); + } else { + signer.init(true, params); + } + } + + protected void engineUpdate(byte b) + throws SignatureException { + digest.update(b); + } + + protected void engineUpdate(byte[] b, int off, int len) + throws SignatureException { + digest.update(b, off, len); + } + + protected byte[] engineSign() + throws SignatureException { + byte[] hash = new byte[digest.getDigestSize()]; + digest.doFinal(hash, 0); + try { + byte[] sig = signer.generateSignature(hash); + + return sig; + } catch (Exception e) { + throw new SignatureException(e.toString()); + } + } + + protected boolean engineVerify(byte[] sigBytes) + throws SignatureException { + byte[] hash = new byte[digest.getDigestSize()]; + digest.doFinal(hash, 0); + + boolean result = signer.verifySignature(hash, sigBytes); + return result; + } + + protected void engineSetParameter(AlgorithmParameterSpec params) { + // TODO + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } + + /** + * @deprecated replaced with #engineSetParameter(java.security.spec.AlgorithmParameterSpec) + */ + protected void engineSetParameter(String param, Object value) { + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } + + /** + * @deprecated + */ + protected Object engineGetParameter(String param) { + throw new UnsupportedOperationException("engineSetParameter unsupported"); + } + +} + From 33abb91ab9ac1017f964e1d463725886d528aca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 16:21:37 +0300 Subject: [PATCH 02/23] Added code that makes injected KEMs visible to TLS --- .../bouncycastle/tls/AbstractTlsClient.java | 52 ++++++++++++++----- .../java/org/bouncycastle/tls/NamedGroup.java | 12 +++++ .../bouncycastle/tls/TlsClientProtocol.java | 2 + .../bouncycastle/tls/TlsServerProtocol.java | 12 ++++- .../tls/crypto/impl/bc/BcTlsCrypto.java | 5 ++ 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/tls/AbstractTlsClient.java b/tls/src/main/java/org/bouncycastle/tls/AbstractTlsClient.java index 446eec9898..823990108f 100644 --- a/tls/src/main/java/org/bouncycastle/tls/AbstractTlsClient.java +++ b/tls/src/main/java/org/bouncycastle/tls/AbstractTlsClient.java @@ -5,6 +5,9 @@ import java.util.Vector; import org.bouncycastle.tls.crypto.TlsCrypto; +import org.bouncycastle.tls.injection.InjectableKEMs; +import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.kems.InjectedKEM; import org.bouncycastle.util.Integers; /** @@ -155,23 +158,37 @@ protected Vector getSupportedGroups(Vector namedGroupRoles) TlsCrypto crypto = getCrypto(); Vector supportedGroups = new Vector(); - if (namedGroupRoles.contains(Integers.valueOf(NamedGroupRole.ecdh))) - { - TlsUtils.addIfSupported(supportedGroups, crypto, - new int[]{ NamedGroup.x25519, NamedGroup.x448 }); + // #tls-injection + // Adding injected KEMs before: + for (InjectedKEM kem : InjectionPoint.kems().kemsByOrdering(InjectableKEMs.Ordering.BEFORE)) { + supportedGroups.add(kem.codePoint()); } - if (namedGroupRoles.contains(Integers.valueOf(NamedGroupRole.ecdh)) || - namedGroupRoles.contains(Integers.valueOf(NamedGroupRole.ecdsa))) - { - TlsUtils.addIfSupported(supportedGroups, crypto, - new int[]{ NamedGroup.secp256r1, NamedGroup.secp384r1 }); + // #tls-injection + // Skipping the default KEMS, if they are not needed: + if (InjectionPoint.kems().defaultKemsNeeded()) { + + if (namedGroupRoles.contains(Integers.valueOf(NamedGroupRole.ecdh))) { + TlsUtils.addIfSupported(supportedGroups, crypto, + new int[]{NamedGroup.x25519, NamedGroup.x448}); + } + + if (namedGroupRoles.contains(Integers.valueOf(NamedGroupRole.ecdh)) || + namedGroupRoles.contains(Integers.valueOf(NamedGroupRole.ecdsa))) { + TlsUtils.addIfSupported(supportedGroups, crypto, + new int[]{NamedGroup.secp256r1, NamedGroup.secp384r1}); + } + + if (namedGroupRoles.contains(Integers.valueOf(NamedGroupRole.dh))) { + TlsUtils.addIfSupported(supportedGroups, crypto, + new int[]{NamedGroup.ffdhe2048, NamedGroup.ffdhe3072, NamedGroup.ffdhe4096}); + } } - if (namedGroupRoles.contains(Integers.valueOf(NamedGroupRole.dh))) - { - TlsUtils.addIfSupported(supportedGroups, crypto, - new int[]{ NamedGroup.ffdhe2048, NamedGroup.ffdhe3072, NamedGroup.ffdhe4096 }); + // #tls-injection + // Adding injected KEMs after: + for (InjectedKEM kem : InjectionPoint.kems().kemsByOrdering(InjectableKEMs.Ordering.AFTER)) { + supportedGroups.add(kem.codePoint()); } return supportedGroups; @@ -415,6 +432,15 @@ public Vector getEarlyKeyShareGroups() * preferred groups. */ + // #tls-injection + // Adding the first injected KEM (if there exists one): + try { + return TlsUtils.vectorOfOne(InjectionPoint.kems().firstKEM().codePoint()); + } + catch (IllegalStateException e) { + // KEM not found, continue with default algorithms + } + if (null == supportedGroups || supportedGroups.isEmpty()) { return null; diff --git a/tls/src/main/java/org/bouncycastle/tls/NamedGroup.java b/tls/src/main/java/org/bouncycastle/tls/NamedGroup.java index a8aaeb14a9..4cf7cb6d7d 100644 --- a/tls/src/main/java/org/bouncycastle/tls/NamedGroup.java +++ b/tls/src/main/java/org/bouncycastle/tls/NamedGroup.java @@ -1,5 +1,8 @@ package org.bouncycastle.tls; + +import org.bouncycastle.tls.injection.InjectionPoint; + /** * RFC 7919 */ @@ -119,6 +122,8 @@ public static boolean canBeNegotiated(int namedGroup, ProtocolVersion version) { if (TlsUtils.isTLSv13(version)) { + if (InjectionPoint.kems().contain(namedGroup)) + return true; // #tls-injection if ((namedGroup >= sect163k1 && namedGroup <= secp256k1) || (namedGroup >= brainpoolP256r1 && namedGroup <= brainpoolP512r1) || (namedGroup >= GC256A && namedGroup <= GC512C) @@ -344,6 +349,13 @@ public static String getStandardName(int namedGroup) return finiteFieldName; } + // #tls-injection + String injectedKEMName = InjectionPoint.kems().kemByCodePoint(namedGroup).standardName(); + if (null != injectedKEMName) + { + return injectedKEMName; + } + return null; } diff --git a/tls/src/main/java/org/bouncycastle/tls/TlsClientProtocol.java b/tls/src/main/java/org/bouncycastle/tls/TlsClientProtocol.java index 6dbe98bb7f..cab8ee3450 100644 --- a/tls/src/main/java/org/bouncycastle/tls/TlsClientProtocol.java +++ b/tls/src/main/java/org/bouncycastle/tls/TlsClientProtocol.java @@ -1053,6 +1053,8 @@ protected void process13ServerHello(ServerHello serverHello, boolean afterHelloR throw new TlsFatalAlert(AlertDescription.illegal_parameter); } + + // #tls-injection (everything remains the same here, if KemAgreement is used as TlsAgreement for KEMs) agreement.receivePeerValue(keyShareEntry.getKeyExchange()); sharedSecret = agreement.calculateSecret(); } diff --git a/tls/src/main/java/org/bouncycastle/tls/TlsServerProtocol.java b/tls/src/main/java/org/bouncycastle/tls/TlsServerProtocol.java index a788067b64..2a2f20b829 100644 --- a/tls/src/main/java/org/bouncycastle/tls/TlsServerProtocol.java +++ b/tls/src/main/java/org/bouncycastle/tls/TlsServerProtocol.java @@ -13,6 +13,8 @@ import org.bouncycastle.tls.crypto.TlsDHConfig; import org.bouncycastle.tls.crypto.TlsECConfig; import org.bouncycastle.tls.crypto.TlsSecret; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; public class TlsServerProtocol @@ -405,16 +407,24 @@ else if (NamedGroup.refersToASpecificFiniteField(namedGroup)) { agreement = crypto.createDHDomain(new TlsDHConfig(namedGroup, true)).createDH(); } + else if (InjectionPoint.kems().contain(namedGroup)) { + // #tls-injection + assert crypto instanceof JcaTlsCrypto; + agreement = InjectionPoint.kems().kemByCodePoint(namedGroup).tlsAgreement((JcaTlsCrypto) crypto, true); + } else { throw new TlsFatalAlert(AlertDescription.internal_error); } + // #tls-injection moved the following line here (due to the requirements of KemAgreement implementing TlsAgreement for KEMs): + agreement.receivePeerValue(clientShare.getKeyExchange()); byte[] key_exchange = agreement.generateEphemeral(); KeyShareEntry serverShare = new KeyShareEntry(namedGroup, key_exchange); TlsExtensionsUtils.addKeyShareServerHello(serverHelloExtensions, serverShare); - agreement.receivePeerValue(clientShare.getKeyExchange()); + // #pqc-tls #injection moved the following line from here (due to the requirements of KemAgreement implementing TlsAgreement for KEMs): + // agreement.receivePeerValue(clientShare.getKeyExchange()); sharedSecret = agreement.calculateSecret(); } diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/bc/BcTlsCrypto.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/bc/BcTlsCrypto.java index 56b4c1fc83..66ec7a3dd9 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/bc/BcTlsCrypto.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/bc/BcTlsCrypto.java @@ -65,6 +65,7 @@ import org.bouncycastle.tls.crypto.impl.TlsBlockCipher; import org.bouncycastle.tls.crypto.impl.TlsImplUtils; import org.bouncycastle.tls.crypto.impl.TlsNullCipher; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; /** @@ -377,6 +378,10 @@ public boolean hasMacAlgorithm(int macAlgorithm) public boolean hasNamedGroup(int namedGroup) { + // #tls-injection + if (InjectionPoint.kems().contain(namedGroup)) { + return true; + } return NamedGroup.refersToASpecificGroup(namedGroup); } From 006ee2987a2a23ecf426e6b6afe3d2c5f18c58e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 16:40:31 +0300 Subject: [PATCH 03/23] Re-implemented NamedGroupInfo to support injected KEMs --- .../jsse/provider/NamedGroupInfo.java | 93 ++++++++++++++++--- 1 file changed, 81 insertions(+), 12 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/jsse/provider/NamedGroupInfo.java b/tls/src/main/java/org/bouncycastle/jsse/provider/NamedGroupInfo.java index 4fa2b71542..60d869e4dc 100644 --- a/tls/src/main/java/org/bouncycastle/jsse/provider/NamedGroupInfo.java +++ b/tls/src/main/java/org/bouncycastle/jsse/provider/NamedGroupInfo.java @@ -19,6 +19,8 @@ import org.bouncycastle.tls.ProtocolVersion; import org.bouncycastle.tls.TlsUtils; import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.injection.InjectableKEMs; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Integers; @@ -336,7 +338,24 @@ private static int[] createCandidatesFromProperty(Map i String[] names = PropertyUtils.getStringArraySystemProperty(propertyName); if (null == names) { - return CANDIDATES_DEFAULT; + // #tls-injection + // return a concatenation of CANDIDATES_DEFAULT and injected KEMs code points + + int[] candidates = CANDIDATES_DEFAULT; + if (!InjectionPoint.kems().defaultKemsNeeded()) + candidates = new int[] {}; + + int[] before = InjectionPoint.kems().asCodePointCollection(InjectableKEMs.Ordering.BEFORE).stream().mapToInt(Integer::intValue).toArray(); + int[] after = InjectionPoint.kems().asCodePointCollection(InjectableKEMs.Ordering.AFTER).stream().mapToInt(Integer::intValue).toArray(); + + int resultLength = before.length + candidates.length + after.length; + int[] result = new int[resultLength]; + + System.arraycopy(before, 0, result, 0, before.length); + System.arraycopy(candidates, 0, result, before.length, candidates.length); + System.arraycopy(after, 0, result, before.length+candidates.length, after.length); + + return result; } return createCandidates(index, names, propertyName); @@ -396,6 +415,12 @@ private static Map createIndex(boolean isFipsContext, J addNamedGroup(isFipsContext, crypto, disableChar2, disableFFDHE, ng, all); } + // #tls-injection + for (int codePoint : InjectionPoint.kems().asCodePointCollection()) { + NamedGroupInfo ngInfo = new NamedGroupInfo(codePoint, InjectionPoint.kems().kemByCodePoint(codePoint).standardName(), null, true); + ng.put(codePoint, ngInfo); + } + return ng; } @@ -462,41 +487,85 @@ private static boolean hasAnyECDSA(Map local) } return false; } - - private final All all; + + //private final All all; + // for injection, we cannot use final enum All; we need some dynamic + // data structure for storing the corresponding sig scheme info + // #tls-injection + + private final int namedGroup; + private final String name; + private final String text; + private final String jcaAlgorithm; + private final String jcaGroup; + private final boolean char2; + private final boolean supportedPost13; + private final boolean supportedPre13; + private final int bitsECDH; + private final int bitsFFDHE; private final AlgorithmParameters algorithmParameters; private final boolean enabled; NamedGroupInfo(All all, AlgorithmParameters algorithmParameters, boolean enabled) { - this.all = all; + //this.all = all; + // #tls-injection + this.namedGroup = all.namedGroup; + this.name = all.name; + this.text = all.text; + this.jcaAlgorithm = all.jcaAlgorithm; + this.jcaGroup = all.jcaGroup; + this.char2 = all.char2; + this.supportedPost13 = all.supportedPost13; + this.supportedPre13 = all.supportedPre13; + this.bitsECDH = all.bitsECDH; + this.bitsFFDHE = all.bitsFFDHE; + + this.algorithmParameters = algorithmParameters; + this.enabled = enabled; + } + + NamedGroupInfo(int kemCodePoint, String name, AlgorithmParameters algorithmParameters, boolean enabled) + { + // #tls-injection + this.namedGroup = kemCodePoint; + this.name = name; + this.text = name; + this.jcaAlgorithm = name; + this.jcaGroup = name; + this.char2 = false; // not a curve + this.supportedPost13 = true; + this.supportedPre13 = true; + this.bitsECDH = 0; // not a curve + this.bitsFFDHE = 0; // not a curve + this.algorithmParameters = algorithmParameters; this.enabled = enabled; } int getBitsECDH() { - return all.bitsECDH; + return this.bitsECDH; } int getBitsFFDHE() { - return all.bitsFFDHE; + return this.bitsFFDHE; } String getJcaAlgorithm() { - return all.jcaAlgorithm; + return this.jcaAlgorithm; } String getJcaGroup() { - return all.jcaGroup; + return this.jcaGroup; } int getNamedGroup() { - return all.namedGroup; + return this.namedGroup; } boolean isActive(BCAlgorithmConstraints algorithmConstraints, boolean post13Active, boolean pre13Active) @@ -513,18 +582,18 @@ boolean isEnabled() boolean isSupportedPost13() { - return all.supportedPost13; + return this.supportedPost13; } boolean isSupportedPre13() { - return all.supportedPre13; + return this.supportedPre13; } @Override public String toString() { - return all.text; + return this.text; } private boolean isPermittedBy(BCAlgorithmConstraints algorithmConstraints) From 04d11e6814257d8059953abac739fad7409c0a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Thu, 26 Oct 2023 00:34:42 +0300 Subject: [PATCH 04/23] Re-implemented SignatureSchemeInfo to support injected Sig Algs --- .../jsse/provider/SignatureSchemeInfo.java | 140 ++++++++++++++---- 1 file changed, 109 insertions(+), 31 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java b/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java index 09fc9bbb0d..6dae2b9f40 100644 --- a/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java +++ b/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java @@ -1,14 +1,7 @@ package org.bouncycastle.jsse.provider; import java.security.AlgorithmParameters; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.Vector; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Logger; @@ -20,6 +13,9 @@ import org.bouncycastle.tls.SignatureScheme; import org.bouncycastle.tls.TlsUtils; import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.injection.InjectableKEMs; +import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgorithm; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Integers; @@ -455,7 +451,17 @@ private static int[] createCandidatesFromProperty(Map result = new LinkedList<>(); + + result.addAll(InjectionPoint.sigAlgs().asCodePointCollection()); + + for (int codePoint : CANDIDATES_DEFAULT) + result.add(codePoint); + + return result.stream().mapToInt(Integer::intValue).toArray(); } return createCandidates(index, names, propertyName); @@ -503,12 +509,20 @@ private static int[] createCandidates(Map index, S private static int[] createCandidatesDefault() { All[] values = All.values(); - int[] result = new int[values.length]; + + + Vector result = new Vector(); for (int i = 0; i < values.length; ++i) { - result[i] = values[i].signatureScheme; + result.add(values[i].signatureScheme); } - return result; + + // #tls-injection + for (int codePoint : InjectionPoint.sigAlgs().asCodePointCollection()) { + result.add(codePoint); + } + + return result.stream().mapToInt(Integer::intValue).toArray(); } private static Map createIndex(boolean isFipsContext, JcaTlsCrypto crypto, @@ -519,6 +533,13 @@ private static Map createIndex(boolean isFipsConte { addSignatureScheme(isFipsContext, crypto, ng, ss, all); } + + // #tls-injection + for (InjectedSigAlgorithm sigAlg : InjectionPoint.sigAlgs().asSigAlgCollection()) { + SignatureSchemeInfo ssinfo = new SignatureSchemeInfo(sigAlg.codePoint(), sigAlg.name(), null); + ss.put(sigAlg.codePoint(), ssinfo); + } + return ss; } @@ -532,6 +553,13 @@ private static int getSignatureSchemeByName(String name) } } + // #tls-injection + for (InjectedSigAlgorithm sigAlg : InjectionPoint.sigAlgs().asSigAlgCollection()) { + if (sigAlg.name().equalsIgnoreCase(name)) { + return sigAlg.codePoint(); + } + } + return -1; } @@ -554,50 +582,100 @@ private static boolean isECDSA(int signatureScheme) } } - private final All all; + //private final All all; + // for injection, we cannot use final enum All; we need some dynamic + // data structure for storing the corresponding sig scheme info + // #pqc-tls #injection + private final int signatureScheme; + private final String name; + private final String text; + private final String jcaSignatureAlgorithm; + private final String jcaSignatureAlgorithmBC; + private final String keyAlgorithm; + private final String keyType13; + private final AlgorithmParameters algorithmParameters; private final NamedGroupInfo namedGroupInfo; private final boolean enabled; private final boolean disabled13; + private final boolean supportedPre13; + private final boolean supportedPost13; + private final boolean supportedCerts13; + + SignatureSchemeInfo(All all, AlgorithmParameters algorithmParameters, NamedGroupInfo namedGroupInfo, boolean enabled, boolean disabled13) { - this.all = all; + //this.all = all; + //#pqc-tls #injection: + this.signatureScheme = all.signatureScheme; + this.name = all.name; + this.text = all.text; + this.jcaSignatureAlgorithm = all.jcaSignatureAlgorithm; + this.jcaSignatureAlgorithmBC = all.jcaSignatureAlgorithmBC; + this.keyAlgorithm = all.keyAlgorithm; + this.keyType13 = all.keyType13; + this.algorithmParameters = algorithmParameters; this.namedGroupInfo = namedGroupInfo; this.enabled = enabled; this.disabled13 = disabled13; + + this.supportedPre13 = all.supportedPre13; + this.supportedPost13 = all.supportedPost13; + this.supportedCerts13 = all.supportedCerts13; } + // #tls-injection + SignatureSchemeInfo(int signatureSchemeCodePoint, String name, AlgorithmParameters algorithmParameters) { + this.signatureScheme = signatureSchemeCodePoint; + this.name = name; + this.text = name; + this.jcaSignatureAlgorithm = name; + this.jcaSignatureAlgorithmBC = name; + this.keyAlgorithm = name; + this.keyType13 = name; + + this.algorithmParameters = algorithmParameters; + this.namedGroupInfo = null; + this.enabled = true; + this.disabled13 = false; + + this.supportedPre13 = false; + this.supportedPost13 = true; + this.supportedCerts13 = true; + } + + short getHashAlgorithm() { - return SignatureScheme.getHashAlgorithm(all.signatureScheme); + return SignatureScheme.getHashAlgorithm(this.signatureScheme); } String getJcaSignatureAlgorithm() { - return all.jcaSignatureAlgorithm; + return this.jcaSignatureAlgorithm; } String getJcaSignatureAlgorithmBC() { - return all.jcaSignatureAlgorithmBC; + return this.jcaSignatureAlgorithmBC; } String getKeyType() { - return all.keyAlgorithm; + return this.keyAlgorithm; } String getKeyType13() { - return all.keyType13; + return this.keyType13; } String getName() { - return all.name; + return this.name; } NamedGroupInfo getNamedGroupInfo() @@ -607,17 +685,17 @@ NamedGroupInfo getNamedGroupInfo() short getSignatureAlgorithm() { - return SignatureScheme.getSignatureAlgorithm(all.signatureScheme); + return SignatureScheme.getSignatureAlgorithm(this.signatureScheme); } SignatureAndHashAlgorithm getSignatureAndHashAlgorithm() { - return getSignatureAndHashAlgorithm(all.signatureScheme); + return getSignatureAndHashAlgorithm(this.signatureScheme); } int getSignatureScheme() { - return all.signatureScheme; + return this.signatureScheme; } boolean isActive(BCAlgorithmConstraints algorithmConstraints, boolean post13Active, boolean pre13Active, @@ -643,23 +721,23 @@ boolean isEnabled() boolean isSupportedPost13() { - return !disabled13 && all.supportedPost13; + return !disabled13 && this.supportedPost13; } boolean isSupportedPre13() { - return all.supportedPre13; + return this.supportedPre13; } boolean isSupportedCerts13() { - return !disabled13 && all.supportedCerts13; + return !disabled13 && this.supportedCerts13; } @Override public String toString() { - return all.text; + return this.text; } private boolean isNamedGroupOK(boolean post13Allowed, boolean pre13Allowed, NamedGroupInfo.PerConnection namedGroupInfos) @@ -673,15 +751,15 @@ private boolean isNamedGroupOK(boolean post13Allowed, boolean pre13Allowed, Name } return (post13Allowed || pre13Allowed) - && (!isECDSA(all.signatureScheme) || NamedGroupInfo.hasAnyECDSALocal(namedGroupInfos)); + && (!isECDSA(this.signatureScheme) || NamedGroupInfo.hasAnyECDSALocal(namedGroupInfos)); } private boolean isPermittedBy(BCAlgorithmConstraints algorithmConstraints) { Set primitives = JsseUtils.SIGNATURE_CRYPTO_PRIMITIVES_BC; - return algorithmConstraints.permits(primitives, all.name, null) - && algorithmConstraints.permits(primitives, all.keyAlgorithm, null) - && algorithmConstraints.permits(primitives, all.jcaSignatureAlgorithm, algorithmParameters); + return algorithmConstraints.permits(primitives, this.name, null) + && algorithmConstraints.permits(primitives, this.keyAlgorithm, null) + && algorithmConstraints.permits(primitives, this.jcaSignatureAlgorithm, algorithmParameters); } } From 2c97329bbd2c177a07f01a42456c0ec052b52aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 17:00:23 +0300 Subject: [PATCH 05/23] added injected KEMs to the TLS supported groups extension --- .../bouncycastle/tls/TlsExtensionsUtils.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tls/src/main/java/org/bouncycastle/tls/TlsExtensionsUtils.java b/tls/src/main/java/org/bouncycastle/tls/TlsExtensionsUtils.java index a44904459e..51fde50341 100644 --- a/tls/src/main/java/org/bouncycastle/tls/TlsExtensionsUtils.java +++ b/tls/src/main/java/org/bouncycastle/tls/TlsExtensionsUtils.java @@ -11,6 +11,8 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.tls.injection.InjectableKEMs; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Integers; @@ -1442,7 +1444,22 @@ public static int[] readSupportedGroupsExtension(byte[] extensionData) throws IO TlsProtocol.assertEmpty(buf); - return namedGroups; + // #tls-injection + // adding injected KEMs... + + int[] before = InjectionPoint.kems().asCodePointCollection(InjectableKEMs.Ordering.BEFORE).stream().mapToInt(Integer::intValue).toArray(); + if (!InjectionPoint.kems().defaultKemsNeeded()) + namedGroups = new int[] {}; + int[] after = InjectionPoint.kems().asCodePointCollection(InjectableKEMs.Ordering.AFTER).stream().mapToInt(Integer::intValue).toArray(); + + int resultLength = before.length + namedGroups.length + after.length; + int[] result = new int[resultLength]; + + System.arraycopy(before, 0, result, 0, before.length); + System.arraycopy(namedGroups, 0, result, before.length, namedGroups.length); + System.arraycopy(after, 0, result, before.length+namedGroups.length, after.length); + + return result; } public static short[] readSupportedPointFormatsExtension(byte[] extensionData) throws IOException From 77b40de51ee348571611ddd5ca53eeeb18de236a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 22:34:32 +0300 Subject: [PATCH 06/23] adding injected KEMs and signature algorithms to the list of supported by TLS --- .../jsse/provider/ProvTlsClient.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/jsse/provider/ProvTlsClient.java b/tls/src/main/java/org/bouncycastle/jsse/provider/ProvTlsClient.java index 3a8f5ebe7d..3bdfce2ad6 100644 --- a/tls/src/main/java/org/bouncycastle/jsse/provider/ProvTlsClient.java +++ b/tls/src/main/java/org/bouncycastle/jsse/provider/ProvTlsClient.java @@ -44,6 +44,8 @@ import org.bouncycastle.tls.TlsUtils; import org.bouncycastle.tls.TrustedAuthority; import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.injection.InjectableKEMs; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.IPAddress; import org.bouncycastle.util.encoders.Hex; @@ -163,7 +165,15 @@ protected Vector getSupportedGroups(@SuppressWarnings("rawtypes") Vecto // @SuppressWarnings("unchecked") // Vector namedGroupRoles = namedGroupRolesRaw; - return NamedGroupInfo.getSupportedGroupsLocalClient(jsseSecurityParameters.namedGroups); + Vector defaultGroups = NamedGroupInfo.getSupportedGroupsLocalClient(jsseSecurityParameters.namedGroups); + + + // #tls-injection + Vector result = new Vector<>(); + result.addAll(InjectionPoint.kems().asCodePointCollection(InjectableKEMs.Ordering.BEFORE)); + result.addAll(NamedGroupInfo.getSupportedGroupsLocalClient(jsseSecurityParameters.namedGroups)); + result.addAll(InjectionPoint.kems().asCodePointCollection(InjectableKEMs.Ordering.AFTER)); + return result; } @Override @@ -217,7 +227,14 @@ protected int[] getSupportedCipherSuites() @Override protected Vector getSupportedSignatureAlgorithms() { - return jsseSecurityParameters.signatureSchemes.getLocalSignatureAndHashAlgorithms(); + Vector result = jsseSecurityParameters.signatureSchemes.getLocalSignatureAndHashAlgorithms(); + if (result == null) + result = new Vector<>(); + // #tls-injection + // adding injected sig algorithms (to TLS client hello) + result.addAll(0, InjectionPoint.sigAlgs().asSigAndHashCollection()); + + return result; } @Override From d9c4416163f8ff88796d6ebdf4bc7640f66e595f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 22:43:44 +0300 Subject: [PATCH 07/23] using KEM as a TlsAgreement --- .../java/org/bouncycastle/tls/TlsUtils.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/tls/src/main/java/org/bouncycastle/tls/TlsUtils.java b/tls/src/main/java/org/bouncycastle/tls/TlsUtils.java index 5a02e05e65..616c6af51e 100644 --- a/tls/src/main/java/org/bouncycastle/tls/TlsUtils.java +++ b/tls/src/main/java/org/bouncycastle/tls/TlsUtils.java @@ -44,6 +44,9 @@ import org.bouncycastle.tls.crypto.TlsStreamSigner; import org.bouncycastle.tls.crypto.TlsStreamVerifier; import org.bouncycastle.tls.crypto.TlsVerifier; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgorithm; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Integers; import org.bouncycastle.util.Shorts; @@ -119,6 +122,11 @@ private static Hashtable createCertSigAlgOIDs() addCertSigAlgOID(h, RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512, SignatureAndHashAlgorithm.gostr34102012_512); + // adding injected algorithms #tls-injection + for (InjectedSigAlgorithm alg : InjectionPoint.sigAlgs().asSigAlgCollection()) { + addCertSigAlgOID(h, alg.oid(), alg.signatureAndHashAlgorithm()); + } + // TODO[RFC 8998] // addCertSigAlgOID(h, GMObjectIdentifiers.sm2sign_with_sm3, HashAlgorithm.sm3, SignatureAlgorithm.sm2); @@ -151,6 +159,12 @@ private static Vector createDefaultSupportedSigAlgs() result.addElement(SignatureAndHashAlgorithm.getInstance(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa)); result.addElement(SignatureAndHashAlgorithm.getInstance(HashAlgorithm.sha1, SignatureAlgorithm.rsa)); result.addElement(SignatureAndHashAlgorithm.getInstance(HashAlgorithm.sha1, SignatureAlgorithm.dsa)); + + // adding injected signature+hash algorithms #tls-injection + for (InjectedSigAlgorithm alg: InjectionPoint.sigAlgs().asSigAlgCollection()) { + result.addElement(alg.signatureAndHashAlgorithm()); + } + return result; } @@ -1236,6 +1250,9 @@ public static Vector getSupportedSignatureAlgorithms(TlsContext context, Vector { addIfSupported(result, crypto, (SignatureAndHashAlgorithm)candidates.elementAt(i)); } + + // adding injected sig algorithms (to TLS client hello) #pqc-tls #injection + result.addAll(0, InjectionPoint.sigAlgs().asSigAndHashCollection()); return result; } @@ -5371,10 +5388,16 @@ else if (NamedGroup.refersToASpecificFiniteField(supportedGroup)) agreement = crypto.createDHDomain(new TlsDHConfig(supportedGroup, true)).createDH(); } } + else { + // #tls-injection + assert (crypto instanceof JcaTlsCrypto); + agreement = InjectionPoint.kems().kemByCodePoint(supportedGroup).tlsAgreement((JcaTlsCrypto)crypto, false); // assume we are a client + } if (null != agreement) { - byte[] key_exchange = agreement.generateEphemeral(); + // #pqc-tls #injection (everything remains the same here, if KemAgreement is used as TlsAgreement for KEMs) + byte[] key_exchange = agreement.generateEphemeral(); // key_exchange = ephemeral public key for KEMs KeyShareEntry clientShare = new KeyShareEntry(supportedGroup, key_exchange); clientShares.addElement(clientShare); From fa0b30b9d163bcd335c2c30156c4748c20ce039f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 22:45:57 +0300 Subject: [PATCH 08/23] adding injected KEMs and signature algorithms to JcaTlsCrypto --- .../tls/crypto/impl/jcajce/JcaTlsCrypto.java | 177 +++++++----------- 1 file changed, 72 insertions(+), 105 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java index 56000a8c40..9f73bf6a79 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java @@ -1,73 +1,26 @@ package org.bouncycastle.tls.crypto.impl.jcajce; -import java.io.IOException; -import java.math.BigInteger; -import java.security.AlgorithmParameters; -import java.security.GeneralSecurityException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.Signature; -import java.security.spec.AlgorithmParameterSpec; -import java.util.Hashtable; -import java.util.Vector; - -import javax.crypto.Cipher; -import javax.crypto.KeyAgreement; - import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; -import org.bouncycastle.tls.AlertDescription; -import org.bouncycastle.tls.CertificateType; -import org.bouncycastle.tls.DigitallySigned; -import org.bouncycastle.tls.EncryptionAlgorithm; -import org.bouncycastle.tls.HashAlgorithm; -import org.bouncycastle.tls.MACAlgorithm; -import org.bouncycastle.tls.NamedGroup; -import org.bouncycastle.tls.ProtocolVersion; -import org.bouncycastle.tls.SignatureAlgorithm; -import org.bouncycastle.tls.SignatureAndHashAlgorithm; -import org.bouncycastle.tls.SignatureScheme; -import org.bouncycastle.tls.TlsDHUtils; -import org.bouncycastle.tls.TlsFatalAlert; -import org.bouncycastle.tls.TlsUtils; -import org.bouncycastle.tls.crypto.CryptoHashAlgorithm; -import org.bouncycastle.tls.crypto.CryptoSignatureAlgorithm; -import org.bouncycastle.tls.crypto.SRP6Group; -import org.bouncycastle.tls.crypto.Tls13Verifier; -import org.bouncycastle.tls.crypto.TlsCertificate; -import org.bouncycastle.tls.crypto.TlsCipher; -import org.bouncycastle.tls.crypto.TlsCryptoException; -import org.bouncycastle.tls.crypto.TlsCryptoParameters; -import org.bouncycastle.tls.crypto.TlsCryptoUtils; -import org.bouncycastle.tls.crypto.TlsDHConfig; -import org.bouncycastle.tls.crypto.TlsDHDomain; -import org.bouncycastle.tls.crypto.TlsECConfig; -import org.bouncycastle.tls.crypto.TlsECDomain; -import org.bouncycastle.tls.crypto.TlsHMAC; -import org.bouncycastle.tls.crypto.TlsHash; -import org.bouncycastle.tls.crypto.TlsNonceGenerator; -import org.bouncycastle.tls.crypto.TlsSRP6Client; -import org.bouncycastle.tls.crypto.TlsSRP6Server; -import org.bouncycastle.tls.crypto.TlsSRP6VerifierGenerator; -import org.bouncycastle.tls.crypto.TlsSRPConfig; -import org.bouncycastle.tls.crypto.TlsSecret; -import org.bouncycastle.tls.crypto.TlsStreamSigner; -import org.bouncycastle.tls.crypto.TlsStreamVerifier; -import org.bouncycastle.tls.crypto.impl.AbstractTlsCrypto; -import org.bouncycastle.tls.crypto.impl.TlsAEADCipher; -import org.bouncycastle.tls.crypto.impl.TlsAEADCipherImpl; -import org.bouncycastle.tls.crypto.impl.TlsBlockCipher; -import org.bouncycastle.tls.crypto.impl.TlsBlockCipherImpl; -import org.bouncycastle.tls.crypto.impl.TlsImplUtils; -import org.bouncycastle.tls.crypto.impl.TlsNullCipher; +import org.bouncycastle.tls.*; +import org.bouncycastle.tls.crypto.*; +import org.bouncycastle.tls.crypto.impl.*; import org.bouncycastle.tls.crypto.impl.jcajce.srp.SRP6Client; import org.bouncycastle.tls.crypto.impl.jcajce.srp.SRP6Server; import org.bouncycastle.tls.crypto.impl.jcajce.srp.SRP6VerifierGenerator; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Integers; +import javax.crypto.Cipher; +import javax.crypto.KeyAgreement; +import java.io.IOException; +import java.math.BigInteger; +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Hashtable; +import java.util.Vector; + /** * Class for providing cryptographic services for TLS based on implementations in the JCA/JCE. *

@@ -409,21 +362,24 @@ String getHMACAlgorithmName(int cryptoHashAlgorithm) } } - public AlgorithmParameters getNamedGroupAlgorithmParameters(int namedGroup) throws GeneralSecurityException - { - if (NamedGroup.refersToAnXDHCurve(namedGroup)) - { - switch (namedGroup) - { - /* - * TODO Return AlgorithmParameters to check against disabled algorithms - * - * NOTE: The JDK doesn't even support AlgorithmParameters for XDH, so SunJSSE also winds - * up using null AlgorithmParameters when checking algorithm constraints. - */ - case NamedGroup.x25519: - case NamedGroup.x448: - return null; + public AlgorithmParameters getNamedGroupAlgorithmParameters(int namedGroup) throws GeneralSecurityException { + // #tls-injection + // for injected KEMs (~NamedGroups), return null + if (InjectionPoint.kems().contain(namedGroup)) + return null; // KEM is supported, no specific parameters (e.g., there are no disabled algorithms) + + + if (NamedGroup.refersToAnXDHCurve(namedGroup)) { + switch (namedGroup) { + /* + * TODO Return AlgorithmParameters to check against disabled algorithms + * + * NOTE: The JDK doesn't even support AlgorithmParameters for XDH, so SunJSSE also winds + * up using null AlgorithmParameters when checking algorithm constraints. + */ + case NamedGroup.x25519: + case NamedGroup.x448: + return null; } } else if (NamedGroup.refersToAnECDSACurve(namedGroup)) @@ -622,8 +578,11 @@ public boolean hasMacAlgorithm(int macAlgorithm) } } - public boolean hasNamedGroup(int namedGroup) - { + public boolean hasNamedGroup(int namedGroup) { + // #tls-injection + if (InjectionPoint.kems().contain(namedGroup)) { + return true; + } final Integer key = Integers.valueOf(namedGroup); synchronized (supportedNamedGroups) { @@ -723,8 +682,10 @@ public boolean hasSignatureAlgorithm(short signatureAlgorithm) } } - public boolean hasSignatureAndHashAlgorithm(SignatureAndHashAlgorithm sigAndHashAlgorithm) - { + public boolean hasSignatureAndHashAlgorithm(SignatureAndHashAlgorithm sigAndHashAlgorithm) { + if (InjectionPoint.sigAlgs().contain(sigAndHashAlgorithm)) + return true; // #tls-injection + short signature = sigAndHashAlgorithm.getSignature(); switch (sigAndHashAlgorithm.getHash()) @@ -739,28 +700,27 @@ public boolean hasSignatureAndHashAlgorithm(SignatureAndHashAlgorithm sigAndHash } } - public boolean hasSignatureScheme(int signatureScheme) - { - switch (signatureScheme) - { - case SignatureScheme.sm2sig_sm3: - return false; - default: - { - short signature = SignatureScheme.getSignatureAlgorithm(signatureScheme); - - switch(SignatureScheme.getCryptoHashAlgorithm(signatureScheme)) - { - case CryptoHashAlgorithm.md5: - return SignatureAlgorithm.rsa == signature && hasSignatureAlgorithm(signature); - case CryptoHashAlgorithm.sha224: - // Somewhat overkill, but simpler for now. It's also consistent with SunJSSE behaviour. - return !JcaUtils.isSunMSCAPIProviderActive() && hasSignatureAlgorithm(signature); - default: - return hasSignatureAlgorithm(signature); + public boolean hasSignatureScheme(int signatureScheme) { + if (InjectionPoint.sigAlgs().contain(signatureScheme)) + return true; // #tls-injection + + switch (signatureScheme) { + case SignatureScheme.sm2sig_sm3: + return false; + default: { + short signature = SignatureScheme.getSignatureAlgorithm(signatureScheme); + + switch (SignatureScheme.getCryptoHashAlgorithm(signatureScheme)) { + case CryptoHashAlgorithm.md5: + return SignatureAlgorithm.rsa == signature && hasSignatureAlgorithm(signature); + case CryptoHashAlgorithm.sha224: + // Somewhat overkill, but simpler for now. It's also consistent with SunJSSE behaviour. + return !JcaUtils.isSunMSCAPIProviderActive() && hasSignatureAlgorithm(signature); + default: + return hasSignatureAlgorithm(signature); + } } } - } } public boolean hasSRPAuthentication() @@ -989,6 +949,14 @@ protected Tls13Verifier createTls13Verifier(String algorithmName, AlgorithmParam helper = new ProviderJcaJceHelper(dummyVerifier.getProvider()); } + // #tls-injection + // try injected verifier... + try { + return InjectionPoint.sigAlgs().tls13VerifierFor(publicKey); + } catch (Exception e) { + // e.g., not injected, continue as usual + } + Signature verifier = helper.createSignature(algorithmName); if (null != parameter) { @@ -1097,12 +1065,11 @@ protected Boolean isSupportedEncryptionAlgorithm(int encryptionAlgorithm) return null; } - protected Boolean isSupportedNamedGroup(int namedGroup) - { - try - { - if (NamedGroup.refersToAnXDHCurve(namedGroup)) - { + protected Boolean isSupportedNamedGroup(int namedGroup) { + try { + if (InjectionPoint.kems().contain(namedGroup)) { + return true; // #tls-injection + } else if (NamedGroup.refersToAnXDHCurve(namedGroup)) { /* * NOTE: We don't check for AlgorithmParameters support because even the SunEC * provider doesn't support them. We skip checking KeyFactory and KeyPairGenerator From c43337423bd8e8cf6e942cbd008151775648fa36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 23:04:15 +0300 Subject: [PATCH 09/23] Added code that makes signature algorithms (injected via InjectionPoint) visible to TLS --- .../crypto/util/PrivateKeyFactory.java | 6 ++++ .../crypto/util/PrivateKeyInfoFactory.java | 6 ++++ .../crypto/util/PublicKeyFactory.java | 7 +++++ .../util/SubjectPublicKeyInfoFactory.java | 6 ++++ .../pqc/crypto/util/PrivateKeyFactory.java | 19 +++++------- .../crypto/util/PrivateKeyInfoFactory.java | 20 ++++++------- .../pqc/crypto/util/PublicKeyFactory.java | 18 +++++++----- .../util/SubjectPublicKeyInfoFactory.java | 7 +++++ .../jsse/provider/ProvX509KeyManager.java | 21 +++++++++++--- .../JcaDefaultTlsCredentialedSigner.java | 8 +++++ .../crypto/impl/jcajce/JcaTlsCertificate.java | 29 +++++++++++++++---- 11 files changed, 107 insertions(+), 40 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java index a8b13deebe..0778635110 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java @@ -47,6 +47,7 @@ import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; import org.bouncycastle.crypto.params.X25519PrivateKeyParameters; import org.bouncycastle.crypto.params.X448PrivateKeyParameters; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; /** @@ -107,6 +108,11 @@ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm(); ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + // #tls-injection + if (InjectionPoint.sigAlgs().contain(algOID)) { + return InjectionPoint.sigAlgs().asn1Bridge().createPrivateKeyParameter(keyInfo); + } + if (algOID.equals(PKCSObjectIdentifiers.rsaEncryption) || algOID.equals(PKCSObjectIdentifiers.id_RSASSA_PSS) || algOID.equals(X509ObjectIdentifiers.id_ea_rsa)) diff --git a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java index cd4bf4d36c..63b5077dcf 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java @@ -41,6 +41,7 @@ import org.bouncycastle.crypto.params.X448PrivateKeyParameters; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.FixedPointCombMultiplier; +import org.bouncycastle.tls.injection.InjectionPoint; /** * Factory to create ASN.1 private key info objects from lightweight private keys. @@ -87,6 +88,11 @@ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter private public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey, ASN1Set attributes) throws IOException { + // #tls-injection + if (InjectionPoint.sigAlgs().asn1Bridge().isSupportedParameter(privateKey)) { + return InjectionPoint.sigAlgs().asn1Bridge().createPrivateKeyInfo(privateKey, attributes); + } + if (privateKey instanceof RSAKeyParameters) { RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters)privateKey; diff --git a/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java index 7da525ff0a..a7b80d63b4 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java @@ -63,6 +63,7 @@ import org.bouncycastle.crypto.params.X448PublicKeyParameters; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; /** @@ -163,6 +164,12 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Obj } AlgorithmIdentifier algID = keyInfo.getAlgorithm(); + ASN1ObjectIdentifier algOID = algID.getAlgorithm(); + + // #tls-injection + if (InjectionPoint.sigAlgs().contain((algOID))) { + return InjectionPoint.sigAlgs().asn1Bridge().createPublicKeyParameter(keyInfo, defaultParams); + } SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters.get(algID.getAlgorithm()); if (null == converter) diff --git a/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java index 40e4c39b1d..39e9b16dfc 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java @@ -36,6 +36,7 @@ import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.X25519PublicKeyParameters; import org.bouncycastle.crypto.params.X448PublicKeyParameters; +import org.bouncycastle.tls.injection.InjectionPoint; /** * Factory to create ASN.1 subject public key info objects from lightweight public keys. @@ -68,6 +69,11 @@ private SubjectPublicKeyInfoFactory() public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException { + // #tls-injection: + if (InjectionPoint.sigAlgs().asn1Bridge().isSupportedParameter(publicKey)) { + return InjectionPoint.sigAlgs().asn1Bridge().createSubjectPublicKeyInfo(publicKey); + } + if (publicKey instanceof RSAKeyParameters) { RSAKeyParameters pub = (RSAKeyParameters)publicKey; diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java index 5442f6c2ce..5ab9897b35 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java @@ -17,17 +17,7 @@ import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; -import org.bouncycastle.pqc.asn1.CMCEPrivateKey; -import org.bouncycastle.pqc.asn1.FalconPrivateKey; -import org.bouncycastle.pqc.asn1.McElieceCCA2PrivateKey; -import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers; -import org.bouncycastle.pqc.asn1.SPHINCS256KeyParams; -import org.bouncycastle.pqc.asn1.SPHINCSPLUSPrivateKey; -import org.bouncycastle.pqc.asn1.SPHINCSPLUSPublicKey; -import org.bouncycastle.pqc.asn1.XMSSKeyParams; -import org.bouncycastle.pqc.asn1.XMSSMTKeyParams; -import org.bouncycastle.pqc.asn1.XMSSMTPrivateKey; -import org.bouncycastle.pqc.asn1.XMSSPrivateKey; +import org.bouncycastle.pqc.asn1.*; import org.bouncycastle.pqc.crypto.bike.BIKEParameters; import org.bouncycastle.pqc.crypto.bike.BIKEPrivateKeyParameters; import org.bouncycastle.pqc.crypto.cmce.CMCEParameters; @@ -70,7 +60,9 @@ import org.bouncycastle.pqc.crypto.xmss.XMSSUtil; import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PrivateKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPrivateKeyParameters; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Integers; import org.bouncycastle.util.Pack; /** @@ -131,6 +123,11 @@ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm(); ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + // #tls-injection: + if (InjectionPoint.sigAlgs().contain((algOID))) { + return InjectionPoint.sigAlgs().asn1Bridge().createPrivateKeyParameter(keyInfo); + } + if (algOID.on(PQCObjectIdentifiers.qTESLA)) { ASN1OctetString qTESLAPriv = ASN1OctetString.getInstance(keyInfo.parsePrivateKey()); diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java index 1c97591500..e8fc3d383e 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java @@ -3,24 +3,16 @@ import java.io.IOException; import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; -import org.bouncycastle.pqc.asn1.CMCEPrivateKey; -import org.bouncycastle.pqc.asn1.CMCEPublicKey; -import org.bouncycastle.pqc.asn1.FalconPrivateKey; -import org.bouncycastle.pqc.asn1.FalconPublicKey; -import org.bouncycastle.pqc.asn1.McElieceCCA2PrivateKey; -import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers; -import org.bouncycastle.pqc.asn1.SPHINCS256KeyParams; -import org.bouncycastle.pqc.asn1.XMSSKeyParams; -import org.bouncycastle.pqc.asn1.XMSSMTKeyParams; -import org.bouncycastle.pqc.asn1.XMSSMTPrivateKey; -import org.bouncycastle.pqc.asn1.XMSSPrivateKey; +import org.bouncycastle.pqc.asn1.*; import org.bouncycastle.pqc.crypto.bike.BIKEPrivateKeyParameters; import org.bouncycastle.pqc.crypto.cmce.CMCEPrivateKeyParameters; import org.bouncycastle.pqc.crypto.crystals.dilithium.DilithiumPrivateKeyParameters; @@ -48,6 +40,7 @@ import org.bouncycastle.pqc.crypto.xmss.XMSSUtil; import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PrivateKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPrivateKeyParameters; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Pack; /** @@ -81,6 +74,11 @@ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter private */ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey, ASN1Set attributes) throws IOException { + // #tls-injection: + if (InjectionPoint.sigAlgs().asn1Bridge().isSupportedParameter(privateKey)) { + return InjectionPoint.sigAlgs().asn1Bridge().createPrivateKeyInfo(privateKey, attributes); + } + if (privateKey instanceof QTESLAPrivateKeyParameters) { QTESLAPrivateKeyParameters keyParams = (QTESLAPrivateKeyParameters)privateKey; diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java index c783dc1235..5c4ed5620d 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java @@ -17,14 +17,7 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; -import org.bouncycastle.pqc.asn1.CMCEPublicKey; -import org.bouncycastle.pqc.asn1.KyberPublicKey; -import org.bouncycastle.pqc.asn1.McElieceCCA2PublicKey; -import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers; -import org.bouncycastle.pqc.asn1.SPHINCS256KeyParams; -import org.bouncycastle.pqc.asn1.XMSSKeyParams; -import org.bouncycastle.pqc.asn1.XMSSMTKeyParams; -import org.bouncycastle.pqc.asn1.XMSSPublicKey; +import org.bouncycastle.pqc.asn1.*; import org.bouncycastle.pqc.crypto.bike.BIKEParameters; import org.bouncycastle.pqc.crypto.bike.BIKEPublicKeyParameters; import org.bouncycastle.pqc.crypto.cmce.CMCEParameters; @@ -63,7 +56,9 @@ import org.bouncycastle.pqc.crypto.xmss.XMSSPublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPublicKeyParameters; +import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Integers; import org.bouncycastle.util.Pack; /** @@ -294,6 +289,13 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Obj } AlgorithmIdentifier algId = keyInfo.getAlgorithm(); + ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + + // #tls-injection: + if (InjectionPoint.sigAlgs().contain((algOID))) { + return InjectionPoint.sigAlgs().asn1Bridge().createPublicKeyParameter(keyInfo, defaultParams); + } + SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters.get(algId.getAlgorithm()); if (converter != null) diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java index 834c9dee39..1e01df3486 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java @@ -39,6 +39,8 @@ import org.bouncycastle.pqc.crypto.xmss.XMSSPublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPublicKeyParameters; +import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.util.Arrays; /** * Factory to create ASN.1 subject public key info objects from lightweight public keys. @@ -60,6 +62,11 @@ private SubjectPublicKeyInfoFactory() public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException { + // #tls-injection: + if (InjectionPoint.sigAlgs().asn1Bridge().isSupportedParameter(publicKey)) { + return InjectionPoint.sigAlgs().asn1Bridge().createSubjectPublicKeyInfo(publicKey); + } + if (publicKey instanceof QTESLAPublicKeyParameters) { QTESLAPublicKeyParameters keyParams = (QTESLAPublicKeyParameters)publicKey; diff --git a/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java b/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java index 269dfff1f1..bdf8e8a4ad 100644 --- a/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java +++ b/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java @@ -41,10 +41,9 @@ import org.bouncycastle.jsse.BCX509ExtendedKeyManager; import org.bouncycastle.jsse.BCX509Key; import org.bouncycastle.jsse.java.security.BCAlgorithmConstraints; -import org.bouncycastle.tls.KeyExchangeAlgorithm; -import org.bouncycastle.tls.NamedGroup; -import org.bouncycastle.tls.ProtocolVersion; -import org.bouncycastle.tls.TlsUtils; +import org.bouncycastle.tls.*; +import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.sigalgs.InjectedSigners; class ProvX509KeyManager extends BCX509ExtendedKeyManager @@ -173,6 +172,13 @@ private static Map createFiltersClient() addFilter(filters, DSAPublicKey.class, "DSA"); addFilter(filters, ECPublicKey.class, "EC"); + // #tls-injection + // adding filters for injected signers (e.g., PQC signers) + for (String name: InjectionPoint.sigAlgs().names()) { + if (!filters.containsKey(name)) + addFilter(filters, name); + } + return Collections.unmodifiableMap(filters); } @@ -201,6 +207,13 @@ private static Map createFiltersServer() KeyExchangeAlgorithm.SRP_RSA); addFilterLegacyServer(filters, ProvAlgorithmChecker.KU_KEY_ENCIPHERMENT, "RSA", KeyExchangeAlgorithm.RSA); + // #tls-injection + // adding filters for injected signers (e.g., PQC signers) #pqc-tls #injection + for (String name: InjectionPoint.sigAlgs().names()) { + if (!filters.containsKey(name)) + addFilter(filters, name); + } + return Collections.unmodifiableMap(filters); } diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java index abb8dd177c..684fb10a65 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java @@ -12,6 +12,8 @@ import org.bouncycastle.tls.SignatureScheme; import org.bouncycastle.tls.crypto.TlsCryptoParameters; import org.bouncycastle.tls.crypto.TlsSigner; +import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.sigalgs.InjectedSigners; // #tls-injection /** * Credentialed class for generating signatures based on the use of primitives from the JCA. @@ -36,6 +38,12 @@ private static TlsSigner makeSigner(JcaTlsCrypto crypto, PrivateKey privateKey, TlsSigner signer; + + if (InjectionPoint.sigAlgs().contain(signatureAndHashAlgorithm)) { // #tls-injection + signer = InjectionPoint.sigAlgs().tlsSignerFor(crypto, privateKey); + return signer; + } + // TODO We probably want better distinction b/w the rsa_pss_pss and rsa_pss_rsae cases here if (privateKey instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(algorithm) diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java index dedd63c8fb..7128ecd078 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java @@ -1,9 +1,12 @@ package org.bouncycastle.tls.crypto.impl.jcajce; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.math.BigInteger; import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; import java.security.PublicKey; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; @@ -23,12 +26,7 @@ import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.jcajce.util.JcaJceHelper; -import org.bouncycastle.tls.AlertDescription; -import org.bouncycastle.tls.HashAlgorithm; -import org.bouncycastle.tls.SignatureAlgorithm; -import org.bouncycastle.tls.SignatureScheme; -import org.bouncycastle.tls.TlsFatalAlert; -import org.bouncycastle.tls.TlsUtils; +import org.bouncycastle.tls.*; import org.bouncycastle.tls.crypto.Tls13Verifier; import org.bouncycastle.tls.crypto.TlsCertificate; import org.bouncycastle.tls.crypto.TlsCertificateRole; @@ -37,6 +35,9 @@ import org.bouncycastle.tls.crypto.TlsVerifier; import org.bouncycastle.tls.crypto.impl.LegacyTls13Verifier; import org.bouncycastle.tls.crypto.impl.RSAUtil; +import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.sigalgs.InjectedSigVerifiers; +import org.bouncycastle.tls.injection.sigalgs.SignatureAndHashAlgorithmFactory; /** * Implementation class for a single X.509 certificate based on the JCA. @@ -137,6 +138,10 @@ public TlsEncryptor createEncryptor(int tlsCertificateRole) throws IOException public TlsVerifier createVerifier(short signatureAlgorithm) throws IOException { + if (InjectionPoint.sigAlgs().contain(signatureAlgorithm)) { + // #tls-injection + return InjectionPoint.sigAlgs().tlsVerifierFor(crypto, getPublicKey(), signatureAlgorithm); + } switch (signatureAlgorithm) { case SignatureAlgorithm.ed25519: @@ -270,6 +275,18 @@ public Tls13Verifier createVerifier(int signatureScheme) throws IOException // case SignatureScheme.sm2sig_sm3: default: + // #tls-injection + if (InjectionPoint.sigAlgs().contain(signatureScheme)) { + + try { + return InjectionPoint.sigAlgs().tls13VerifierFor(getPublicKey()); + } catch (InvalidKeyException e) { + throw new TlsFatalAlert(AlertDescription.certificate_unknown); + } + + + } + throw new TlsFatalAlert(AlertDescription.certificate_unknown); } } From 7450b06fbdc5b8be6f3c9e275d773b0b058e5eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Wed, 25 Oct 2023 23:06:44 +0300 Subject: [PATCH 10/23] Adding support for injected algorithms (via InjectionPoint) to the BC PQC provider. PQC algorithms now can be loaded without reflection (useful when compiling with GraalVM native-image). --- .../provider/BouncyCastlePQCProvider.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java b/prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java index ecaa8b2ed7..837842d8d3 100644 --- a/prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java +++ b/prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/BouncyCastlePQCProvider.java @@ -17,6 +17,7 @@ import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; import org.bouncycastle.jcajce.provider.util.AlgorithmProvider; import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; +import org.bouncycastle.tls.injection.InjectionPoint; public class BouncyCastlePQCProvider extends Provider @@ -43,6 +44,19 @@ public class BouncyCastlePQCProvider "Dilithium", "NTRUPrime", "BIKE", "HQC", "Rainbow" }; + /** + * #tls-injection + * ALGORITHM_MAPPING_CLASSES contains real classes corresponding to the names given in ALGORITHMS. + * We rely on ALGORITHM_MAPPING_CLASSES when we are unable to load classes by names via reflection + * (important, since we cannot rely fully on reflection in NativeImage from GraalVM). + * #pqc-tls + */ + private static final Class[] ALGORITHM_MAPPING_CLASSES = { + SPHINCS.Mappings.class, LMS.Mappings.class, NH.Mappings.class, XMSS.Mappings.class, SPHINCSPlus.Mappings.class, + CMCE.Mappings.class, Frodo.Mappings.class, SABER.Mappings.class, Picnic.Mappings.class, NTRU.Mappings.class, Falcon.Mappings.class, Kyber.Mappings.class, + Dilithium.Mappings.class, NTRUPrime.Mappings.class, BIKE.Mappings.class, HQC.Mappings.class, Rainbow.Mappings.class + }; + /** * Construct a new provider. This should only be required when * using runtime registration of the provider using the @@ -71,13 +85,20 @@ private void loadAlgorithms(String packageName, String[] names) { for (int i = 0; i != names.length; i++) { - Class clazz = loadClass(BouncyCastlePQCProvider.class, packageName + names[i] + "$Mappings"); + Class clazz; + if (i Date: Fri, 27 Oct 2023 14:03:24 +0300 Subject: [PATCH 11/23] moved TLS injection mechanism from BC tls folder to core --- .../tls/injection/InjectableAlgorithms.java | 0 .../org/bouncycastle/tls/injection/InjectableKEMs.java | 0 .../bouncycastle/tls/injection/InjectableSigAlgs.java | 0 .../org/bouncycastle/tls/injection/InjectionPoint.java | 0 .../bouncycastle/tls/injection/kems/InjectedKEM.java | 0 .../java/org/bouncycastle/tls/injection/kems/KEM.java | 0 .../bouncycastle/tls/injection/kems/KemFactory.java | 0 .../tls/injection/kems/TlsAgreementForKEM.java | 0 .../bouncycastle/tls/injection/sigalgs/Asn1Bridge.java | 0 .../sigalgs/CipherParametersToEncodedKey.java | 0 .../tls/injection/sigalgs/InjectedSigAlgorithm.java | 0 .../tls/injection/sigalgs/InjectedSigVerifiers.java | 0 .../tls/injection/sigalgs/InjectedSigners.java | 0 .../tls/injection/sigalgs/MyMessageSigner.java | 10 ---------- .../tls/injection/sigalgs/MyStreamSigner.java | 0 .../tls/injection/sigalgs/MyTls13Verifier.java | 0 .../tls/injection/sigalgs/MyTlsSigner.java | 0 .../sigalgs/PrivateKeyToCipherParameters.java | 0 .../injection/sigalgs/PublicKeyToCipherParameters.java | 0 .../tls/injection/sigalgs/PublicKeyToEncodedKey.java | 0 .../bouncycastle/tls/injection/sigalgs/SigAlgAPI.java | 0 .../sigalgs/SignatureAndHashAlgorithmFactory.java | 0 .../tls/injection/sigalgs/SignerFunction.java | 0 .../tls/injection/sigalgs/VerifierFunction.java | 0 .../tls/injection/signaturespi/DirectSignatureSpi.java | 0 .../injection/signaturespi/UniversalSignatureSpi.java | 0 26 files changed, 10 deletions(-) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java (81%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java (100%) rename {tls => core}/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java (100%) diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java b/core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java rename to core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java b/core/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java rename to core/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java b/core/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java rename to core/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java b/core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java rename to core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java b/core/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java rename to core/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java b/core/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java rename to core/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java b/core/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java rename to core/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java b/core/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java rename to core/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java similarity index 81% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java index 0a9686b23e..ef7b4a2ae3 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java +++ b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java @@ -1,19 +1,9 @@ package org.bouncycastle.tls.injection.sigalgs; -import lv.lumii.pqc.InjectablePQC; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.pqc.crypto.MessageSigner; -import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusPrivateKeyParameters; -import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusPublicKeyParameters; -import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusSigner; import org.bouncycastle.tls.DigitallySigned; import org.bouncycastle.tls.SignatureAndHashAlgorithm; -import org.bouncycastle.tls.crypto.TlsSigner; -import org.bouncycastle.tls.crypto.TlsStreamSigner; -import org.bouncycastle.util.Pack; - -import java.io.IOException; -import java.util.Arrays; public class MyMessageSigner implements MessageSigner { diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java b/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java rename to core/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java b/core/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java rename to core/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java b/core/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java similarity index 100% rename from tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java rename to core/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java From e2d73ddf26f40cd014cedfb2ba4f182cd715835e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Fri, 27 Oct 2023 14:06:34 +0300 Subject: [PATCH 12/23] some changes in imports --- .../bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java | 1 - .../org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java | 1 - .../bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java | 2 -- .../org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java | 1 - .../pqc/crypto/util/SubjectPublicKeyInfoFactory.java | 1 - .../org/bouncycastle/jsse/provider/ProvX509KeyManager.java | 1 - .../org/bouncycastle/jsse/provider/SignatureSchemeInfo.java | 1 - .../crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java | 1 - .../tls/crypto/impl/jcajce/JcaTlsCertificate.java | 4 ---- 9 files changed, 13 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java index 39e9b16dfc..edb049958c 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java @@ -8,7 +8,6 @@ import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java index 5ab9897b35..b3f535e504 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java @@ -62,7 +62,6 @@ import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPrivateKeyParameters; import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; -import org.bouncycastle.util.Integers; import org.bouncycastle.util.Pack; /** diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java index e8fc3d383e..164fe6e81a 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java @@ -3,9 +3,7 @@ import java.io.IOException; import org.bouncycastle.asn1.ASN1EncodableVector; -import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Set; -import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java index 5c4ed5620d..e5c1f88062 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java @@ -58,7 +58,6 @@ import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPublicKeyParameters; import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.util.Arrays; -import org.bouncycastle.util.Integers; import org.bouncycastle.util.Pack; /** diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java index 1e01df3486..f6308ab912 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java @@ -40,7 +40,6 @@ import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPublicKeyParameters; import org.bouncycastle.tls.injection.InjectionPoint; -import org.bouncycastle.util.Arrays; /** * Factory to create ASN.1 subject public key info objects from lightweight public keys. diff --git a/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java b/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java index bdf8e8a4ad..5d9df9f442 100644 --- a/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java +++ b/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java @@ -43,7 +43,6 @@ import org.bouncycastle.jsse.java.security.BCAlgorithmConstraints; import org.bouncycastle.tls.*; import org.bouncycastle.tls.injection.InjectionPoint; -import org.bouncycastle.tls.injection.sigalgs.InjectedSigners; class ProvX509KeyManager extends BCX509ExtendedKeyManager diff --git a/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java b/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java index 6dae2b9f40..f4b478bd9b 100644 --- a/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java +++ b/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java @@ -13,7 +13,6 @@ import org.bouncycastle.tls.SignatureScheme; import org.bouncycastle.tls.TlsUtils; import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; -import org.bouncycastle.tls.injection.InjectableKEMs; import org.bouncycastle.tls.injection.InjectionPoint; import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgorithm; import org.bouncycastle.util.Arrays; diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java index 684fb10a65..4d34e646b8 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaDefaultTlsCredentialedSigner.java @@ -13,7 +13,6 @@ import org.bouncycastle.tls.crypto.TlsCryptoParameters; import org.bouncycastle.tls.crypto.TlsSigner; import org.bouncycastle.tls.injection.InjectionPoint; -import org.bouncycastle.tls.injection.sigalgs.InjectedSigners; // #tls-injection /** * Credentialed class for generating signatures based on the use of primitives from the JCA. diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java index 7128ecd078..836edc32b9 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java @@ -1,9 +1,7 @@ package org.bouncycastle.tls.crypto.impl.jcajce; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.math.BigInteger; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; @@ -36,8 +34,6 @@ import org.bouncycastle.tls.crypto.impl.LegacyTls13Verifier; import org.bouncycastle.tls.crypto.impl.RSAUtil; import org.bouncycastle.tls.injection.InjectionPoint; -import org.bouncycastle.tls.injection.sigalgs.InjectedSigVerifiers; -import org.bouncycastle.tls.injection.sigalgs.SignatureAndHashAlgorithmFactory; /** * Implementation class for a single X.509 certificate based on the JCA. From 4861e5e17294905b6ab9979ee086082086f6f78f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Fri, 27 Oct 2023 23:12:18 +0300 Subject: [PATCH 13/23] changed arg ordering --- .../org/bouncycastle/tls/injection/InjectableAlgorithms.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java b/core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java index d942eee064..e16bc9a2da 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java +++ b/core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java @@ -26,8 +26,8 @@ private InjectableAlgorithms(InjectableAlgorithms origin) { // clone constructor } - public InjectableAlgorithms withKEM(int kemCodePoint, - String standardName, KemFactory kemFactory, InjectableKEMs.Ordering ordering) { + public InjectableAlgorithms withKEM(String standardName, int kemCodePoint, + KemFactory kemFactory, InjectableKEMs.Ordering ordering) { return new InjectableAlgorithms( this.kems.withKEM(kemCodePoint, standardName, kemFactory, ordering), new InjectableSigAlgs(this.sigAlgs) From 8fdce665747679cfc5f65932180739461eadf047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergejs=20Kozlovi=C4=8Ds?= Date: Thu, 23 Nov 2023 13:27:36 +0200 Subject: [PATCH 14/23] More secure pop() method for InjectionPoint. Better logic for inserting KEMs before others in InjectableKEMs. --- .../java/org/bouncycastle/tls/injection/InjectableKEMs.java | 2 +- .../java/org/bouncycastle/tls/injection/InjectionPoint.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java b/core/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java index f3a3cd4bad..47ad2137f0 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java +++ b/core/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java @@ -42,7 +42,7 @@ public InjectableKEMs withKEM(int kemCodePoint, InjectableKEMs clone = new InjectableKEMs(this); clone.code2kem.put(kemCodePoint, kem); if (ordering == Ordering.BEFORE) - clone.kemsBefore.add(kemCodePoint); + clone.kemsBefore.add(0,kemCodePoint); // adding BEFORE all else clone.kemsAfter.add(kemCodePoint); return clone; diff --git a/core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java b/core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java index fd29c65bc9..8ef73618a5 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java +++ b/core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java @@ -60,12 +60,14 @@ public synchronized void pushAfter(InjectableAlgorithms newAlgorithms, Injectabl /** * Withdraws (pops) the current set of algorithms and restores the previously injected algorithms (if any). - * + * @param current the currently used injected algorithms (act as a key to withdraw) * @throws IllegalStateException if no InjectableAlgorithms have been pushed */ - public synchronized void pop() throws IllegalStateException { + public synchronized void pop(InjectableAlgorithms current) throws IllegalStateException { if (injectionStack.isEmpty()) throw new IllegalStateException("No previously injected (pushed) algorithms found."); + if (!injectionStack.peek().equals(current)) + throw new IllegalStateException("The currently used injected (pushed) algorithms do not match the current argument."); injectionStack.pop(); } From dc6a80129eae1c56adea45013b58b5de24356d7d Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Fri, 19 Apr 2024 21:58:19 +0300 Subject: [PATCH 15/23] moved the main TLS Injection Mechanism out from the core package, leaving only Asn1Bridge and Asn1BridgeForInjectedSigAlgs there; no dependency on the tls package --- .../crypto/util/PrivateKeyFactory.java | 72 ++-- .../crypto/util/PrivateKeyInfoFactory.java | 79 +++-- .../crypto/util/PublicKeyFactory.java | 171 ++++++---- .../util/SubjectPublicKeyInfoFactory.java | 48 +-- .../pqc/crypto/util/PrivateKeyFactory.java | 99 +++--- .../crypto/util/PrivateKeyInfoFactory.java | 89 ++--- .../pqc/crypto/util/PublicKeyFactory.java | 229 +++++++------ .../util/SubjectPublicKeyInfoFactory.java | 61 ++-- .../injection/{sigalgs => }/Asn1Bridge.java | 26 +- .../Asn1BridgeForInjectedSigAlgs.java | 149 +++++++++ .../tls/injection/InjectableSigAlgs.java | 173 ---------- .../tls/injection/InjectableAlgorithms.java | 5 +- .../tls/injection/InjectableKEMs.java | 0 .../tls/injection/InjectableSigAlgs.java | 312 ++++++++++++++++++ .../tls/injection/InjectionPoint.java | 123 +++++-- .../tls/injection/kems/InjectedKEM.java | 0 .../bouncycastle/tls/injection/kems/KEM.java | 2 +- .../tls/injection/kems/KemFactory.java | 0 .../injection/kems/TlsAgreementForKEM.java | 2 +- .../sigalgs/CipherParametersToEncodedKey.java | 0 .../sigalgs/InjectedSigAlgorithm.java | 85 +++-- .../sigalgs/InjectedSigAlgsProvider.java | 193 +++++++++++ .../sigalgs/InjectedSigVerifiers.java | 0 .../injection/sigalgs/InjectedSigners.java | 18 +- .../injection/sigalgs/MyMessageSigner.java | 0 .../tls/injection/sigalgs/MyStreamSigner.java | 0 .../injection/sigalgs/MyTls13Verifier.java | 14 + .../tls/injection/sigalgs/MyTlsSigner.java | 0 .../sigalgs/PrivateKeyToCipherParameters.java | 0 .../sigalgs/PublicKeyToCipherParameters.java | 0 .../sigalgs/PublicKeyToEncodedKey.java | 0 .../tls/injection/sigalgs/SigAlgAPI.java | 11 +- .../SignatureAndHashAlgorithmFactory.java | 0 .../tls/injection/sigalgs/SignerFunction.java | 0 .../injection/sigalgs/VerifierFunction.java | 0 .../signaturespi/DirectSignatureSpi.java | 4 +- .../signaturespi/UniversalKeyFactorySpi.java | 120 +++++++ .../UniversalKeyPairGeneratorSpi.java | 72 ++++ .../signaturespi/UniversalSignatureSpi.java | 0 39 files changed, 1544 insertions(+), 613 deletions(-) rename core/src/main/java/org/bouncycastle/tls/injection/{sigalgs => }/Asn1Bridge.java (67%) create mode 100644 core/src/main/java/org/bouncycastle/tls/injection/Asn1BridgeForInjectedSigAlgs.java delete mode 100644 core/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java (91%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java (100%) create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java (60%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java (98%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java (99%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java (56%) create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgsProvider.java rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java (65%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java (82%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java (91%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java (100%) rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java (98%) create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyFactorySpi.java create mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyPairGeneratorSpi.java rename {core => tls}/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java (100%) diff --git a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java index f53611c0c1..641e7505f9 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyFactory.java @@ -47,10 +47,9 @@ import org.bouncycastle.internal.asn1.oiw.ElGamalParameter; import org.bouncycastle.internal.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.internal.asn1.rosstandart.RosstandartObjectIdentifiers; +import org.bouncycastle.tls.injection.Asn1BridgeForInjectedSigAlgs; import org.bouncycastle.util.Arrays; -import org.bouncycastle.tls.injection.InjectionPoint; - /** * Factory for creating private key objects from PKCS8 PrivateKeyInfo objects. */ @@ -64,7 +63,7 @@ public class PrivateKeyFactory * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) - throws IOException + throws IOException { if (privateKeyInfoData == null) { @@ -86,7 +85,7 @@ public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(InputStream inStr) - throws IOException + throws IOException { return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); } @@ -99,7 +98,7 @@ public static AsymmetricKeyParameter createKey(InputStream inStr) * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) - throws IOException + throws IOException { if (keyInfo == null) { @@ -110,27 +109,28 @@ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) ASN1ObjectIdentifier algOID = algId.getAlgorithm(); // #tls-injection - if (InjectionPoint.sigAlgs().contain(algOID)) { - return InjectionPoint.sigAlgs().asn1Bridge().createPrivateKeyParameter(keyInfo); + if (Asn1BridgeForInjectedSigAlgs.theInstance().isSupportedAlgorithm(algOID)) + { + return Asn1BridgeForInjectedSigAlgs.theInstance().createPrivateKeyParameter(keyInfo); } if (algOID.equals(PKCSObjectIdentifiers.rsaEncryption) - || algOID.equals(PKCSObjectIdentifiers.id_RSASSA_PSS) - || algOID.equals(X509ObjectIdentifiers.id_ea_rsa)) + || algOID.equals(PKCSObjectIdentifiers.id_RSASSA_PSS) + || algOID.equals(X509ObjectIdentifiers.id_ea_rsa)) { RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey()); return new RSAPrivateCrtKeyParameters(keyStructure.getModulus(), - keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(), - keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(), - keyStructure.getExponent2(), keyStructure.getCoefficient()); + keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(), + keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(), + keyStructure.getExponent2(), keyStructure.getCoefficient()); } // TODO? // else if (algOID.equals(X9ObjectIdentifiers.dhpublicnumber)) else if (algOID.equals(PKCSObjectIdentifiers.dhKeyAgreement)) { DHParameter params = DHParameter.getInstance(algId.getParameters()); - ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); + ASN1Integer derX = (ASN1Integer) keyInfo.parsePrivateKey(); BigInteger lVal = params.getL(); int l = lVal == null ? 0 : lVal.intValue(); @@ -141,14 +141,14 @@ else if (algOID.equals(PKCSObjectIdentifiers.dhKeyAgreement)) else if (algOID.equals(OIWObjectIdentifiers.elGamalAlgorithm)) { ElGamalParameter params = ElGamalParameter.getInstance(algId.getParameters()); - ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); + ASN1Integer derX = (ASN1Integer) keyInfo.parsePrivateKey(); return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters( - params.getP(), params.getG())); + params.getP(), params.getG())); } else if (algOID.equals(X9ObjectIdentifiers.id_dsa)) { - ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey(); + ASN1Integer derX = (ASN1Integer) keyInfo.parsePrivateKey(); ASN1Encodable algParameters = algId.getParameters(); DSAParameters parameters = null; @@ -169,7 +169,7 @@ else if (algOID.equals(X9ObjectIdentifiers.id_ecPublicKey)) if (params.isNamedCurve()) { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) params.getParameters(); x9 = CustomNamedCurves.getByOID(oid); if (x9 == null) @@ -182,7 +182,7 @@ else if (algOID.equals(X9ObjectIdentifiers.id_ecPublicKey)) { x9 = X9ECParameters.getInstance(params.getParameters()); dParams = new ECDomainParameters( - x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); + x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); } ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey()); @@ -219,9 +219,9 @@ else if (algOID.equals(EdECObjectIdentifiers.id_Ed448)) return new Ed448PrivateKeyParameters(getRawKey(keyInfo)); } else if ( - algOID.equals(CryptoProObjectIdentifiers.gostR3410_2001) || - algOID.equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512) || - algOID.equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256)) + algOID.equals(CryptoProObjectIdentifiers.gostR3410_2001) || + algOID.equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512) || + algOID.equals(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256)) { ASN1Encodable algParameters = algId.getParameters(); GOST3410PublicKeyAlgParameters gostParams = GOST3410PublicKeyAlgParameters.getInstance(algParameters); @@ -233,11 +233,11 @@ else if ( X9ECParameters ecP = ECGOST3410NamedCurves.getByOIDX9(gostParams.getPublicKeyParamSet()); ecSpec = new ECGOST3410Parameters( - new ECNamedDomainParameters( - gostParams.getPublicKeyParamSet(), ecP), - gostParams.getPublicKeyParamSet(), - gostParams.getDigestParamSet(), - gostParams.getEncryptionParamSet()); + new ECNamedDomainParameters( + gostParams.getPublicKeyParamSet(), ecP), + gostParams.getPublicKeyParamSet(), + gostParams.getDigestParamSet(), + gostParams.getEncryptionParamSet()); int privateKeyLength = keyInfo.getPrivateKeyLength(); @@ -269,8 +269,8 @@ else if ( X9ECParameters ecP = ECNamedCurveTable.getByOID(oid); ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(oid, ecP), - gostParams.getPublicKeyParamSet(), gostParams.getDigestParamSet(), - gostParams.getEncryptionParamSet()); + gostParams.getPublicKeyParamSet(), gostParams.getDigestParamSet(), + gostParams.getEncryptionParamSet()); } else if (params.isImplicitlyCA()) { @@ -280,8 +280,8 @@ else if (params.isImplicitlyCA()) { X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); ecSpec = new ECGOST3410Parameters(new ECNamedDomainParameters(algOID, ecP), - gostParams.getPublicKeyParamSet(), gostParams.getDigestParamSet(), - gostParams.getEncryptionParamSet()); + gostParams.getPublicKeyParamSet(), gostParams.getDigestParamSet(), + gostParams.getEncryptionParamSet()); } ASN1Encodable privKey = keyInfo.parsePrivateKey(); @@ -301,12 +301,12 @@ else if (params.isImplicitlyCA()) } return new ECPrivateKeyParameters( - d, - new ECGOST3410Parameters( - ecSpec, - gostParams.getPublicKeyParamSet(), - gostParams.getDigestParamSet(), - gostParams.getEncryptionParamSet())); + d, + new ECGOST3410Parameters( + ecSpec, + gostParams.getPublicKeyParamSet(), + gostParams.getDigestParamSet(), + gostParams.getEncryptionParamSet())); } else diff --git a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java index 7f729883e2..21fe06f9bd 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java @@ -41,7 +41,7 @@ import org.bouncycastle.internal.asn1.rosstandart.RosstandartObjectIdentifiers; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.FixedPointCombMultiplier; -import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.Asn1BridgeForInjectedSigAlgs; /** * Factory to create ASN.1 private key info objects from lightweight private keys. @@ -72,7 +72,7 @@ private PrivateKeyInfoFactory() * @throws java.io.IOException on an error encoding the key */ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey) - throws IOException + throws IOException { return createPrivateKeyInfo(privateKey, null); } @@ -85,34 +85,37 @@ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter private * @return the appropriate PrivateKeyInfo * @throws java.io.IOException on an error encoding the key */ - public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey, ASN1Set attributes) - throws IOException + public static PrivateKeyInfo createPrivateKeyInfo( + AsymmetricKeyParameter privateKey, + ASN1Set attributes) + throws IOException { // #tls-injection - if (InjectionPoint.sigAlgs().asn1Bridge().isSupportedParameter(privateKey)) { - return InjectionPoint.sigAlgs().asn1Bridge().createPrivateKeyInfo(privateKey, attributes); + if (Asn1BridgeForInjectedSigAlgs.theInstance().isSupportedParameter(privateKey)) + { + return Asn1BridgeForInjectedSigAlgs.theInstance().createPrivateKeyInfo(privateKey, attributes); } if (privateKey instanceof RSAKeyParameters) { - RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters)privateKey; + RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters) privateKey; return new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), - new RSAPrivateKey(priv.getModulus(), priv.getPublicExponent(), priv.getExponent(), priv.getP(), priv.getQ(), priv.getDP(), priv.getDQ(), priv.getQInv()), - attributes); + new RSAPrivateKey(priv.getModulus(), priv.getPublicExponent(), priv.getExponent(), priv.getP(), priv.getQ(), priv.getDP(), priv.getDQ(), priv.getQInv()), + attributes); } else if (privateKey instanceof DSAPrivateKeyParameters) { - DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)privateKey; + DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters) privateKey; DSAParameters params = priv.getParameters(); return new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, - new DSAParameter(params.getP(), params.getQ(), params.getG())), new ASN1Integer(priv.getX()), - attributes); + new DSAParameter(params.getP(), params.getQ(), params.getG())), new ASN1Integer(priv.getX()), + attributes); } else if (privateKey instanceof ECPrivateKeyParameters) { - ECPrivateKeyParameters priv = (ECPrivateKeyParameters)privateKey; + ECPrivateKeyParameters priv = (ECPrivateKeyParameters) privateKey; ECDomainParameters domainParams = priv.getParameters(); ASN1Encodable params; int orderBitLength; @@ -125,9 +128,9 @@ else if (privateKey instanceof ECPrivateKeyParameters) else if (domainParams instanceof ECGOST3410Parameters) { GOST3410PublicKeyAlgParameters gostParams = new GOST3410PublicKeyAlgParameters( - ((ECGOST3410Parameters)domainParams).getPublicKeyParamSet(), - ((ECGOST3410Parameters)domainParams).getDigestParamSet(), - ((ECGOST3410Parameters)domainParams).getEncryptionParamSet()); + ((ECGOST3410Parameters) domainParams).getPublicKeyParamSet(), + ((ECGOST3410Parameters) domainParams).getDigestParamSet(), + ((ECGOST3410Parameters) domainParams).getEncryptionParamSet()); int size; @@ -143,8 +146,8 @@ else if (domainParams instanceof ECGOST3410Parameters) boolean is512 = priv.getD().bitLength() > 256; identifier = (is512) ? - RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512 : - RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256; + RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512 : + RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256; size = (is512) ? 64 : 32; } byte[] encKey = new byte[size]; @@ -155,17 +158,17 @@ else if (domainParams instanceof ECGOST3410Parameters) } else if (domainParams instanceof ECNamedDomainParameters) { - params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName()); + params = new X962Parameters(((ECNamedDomainParameters) domainParams).getName()); orderBitLength = domainParams.getN().bitLength(); } else { X9ECParameters ecP = new X9ECParameters( - domainParams.getCurve(), - new X9ECPoint(domainParams.getG(), false), - domainParams.getN(), - domainParams.getH(), - domainParams.getSeed()); + domainParams.getCurve(), + new X9ECPoint(domainParams.getG(), false), + domainParams.getN(), + domainParams.getH(), + domainParams.getSeed()); params = new X962Parameters(ecP); orderBitLength = domainParams.getN().bitLength(); @@ -177,37 +180,37 @@ else if (domainParams instanceof ECNamedDomainParameters) DERBitString publicKey = new DERBitString(q.getEncoded(false)); return new PrivateKeyInfo( - new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), - new ECPrivateKey(orderBitLength, priv.getD(), publicKey, params), - attributes); + new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), + new ECPrivateKey(orderBitLength, priv.getD(), publicKey, params), + attributes); } else if (privateKey instanceof X448PrivateKeyParameters) { - X448PrivateKeyParameters key = (X448PrivateKeyParameters)privateKey; + X448PrivateKeyParameters key = (X448PrivateKeyParameters) privateKey; return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X448), - new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded()); + new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded()); } else if (privateKey instanceof X25519PrivateKeyParameters) { - X25519PrivateKeyParameters key = (X25519PrivateKeyParameters)privateKey; + X25519PrivateKeyParameters key = (X25519PrivateKeyParameters) privateKey; return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X25519), - new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded()); + new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded()); } else if (privateKey instanceof Ed448PrivateKeyParameters) { - Ed448PrivateKeyParameters key = (Ed448PrivateKeyParameters)privateKey; + Ed448PrivateKeyParameters key = (Ed448PrivateKeyParameters) privateKey; return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed448), - new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded()); + new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded()); } else if (privateKey instanceof Ed25519PrivateKeyParameters) { - Ed25519PrivateKeyParameters key = (Ed25519PrivateKeyParameters)privateKey; + Ed25519PrivateKeyParameters key = (Ed25519PrivateKeyParameters) privateKey; return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), - new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded()); + new DEROctetString(key.getEncoded()), attributes, key.generatePublicKey().getEncoded()); } else { @@ -216,7 +219,11 @@ else if (privateKey instanceof Ed25519PrivateKeyParameters) } - private static void extractBytes(byte[] encKey, int size, int offSet, BigInteger bI) + private static void extractBytes( + byte[] encKey, + int size, + int offSet, + BigInteger bI) { byte[] val = bI.toByteArray(); if (val.length < size) diff --git a/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java index 06837b2055..a74155f205 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/PublicKeyFactory.java @@ -63,7 +63,7 @@ import org.bouncycastle.internal.asn1.rosstandart.RosstandartObjectIdentifiers; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; -import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.Asn1BridgeForInjectedSigAlgs; import org.bouncycastle.util.Arrays; /** @@ -104,7 +104,7 @@ public class PublicKeyFactory * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(byte[] keyInfoData) - throws IOException + throws IOException { if (keyInfoData == null) { @@ -125,7 +125,7 @@ public static AsymmetricKeyParameter createKey(byte[] keyInfoData) * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(InputStream inStr) - throws IOException + throws IOException { return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); } @@ -138,7 +138,7 @@ public static AsymmetricKeyParameter createKey(InputStream inStr) * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) - throws IOException + throws IOException { if (keyInfo == null) { @@ -155,8 +155,10 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) * @return the appropriate key parameter * @throws IOException on an error decoding the key */ - public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + public static AsymmetricKeyParameter createKey( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { if (keyInfo == null) { @@ -167,11 +169,12 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Obj ASN1ObjectIdentifier algOID = algID.getAlgorithm(); // #tls-injection - if (InjectionPoint.sigAlgs().contain((algOID))) { - return InjectionPoint.sigAlgs().asn1Bridge().createPublicKeyParameter(keyInfo, defaultParams); + if (Asn1BridgeForInjectedSigAlgs.theInstance().isSupportedAlgorithm((algOID))) + { + return Asn1BridgeForInjectedSigAlgs.theInstance().createPublicKeyParameter(keyInfo, defaultParams); } - SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters.get(algID.getAlgorithm()); + SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter) converters.get(algID.getAlgorithm()); if (null == converter) { throw new IOException("algorithm identifier in public key not recognised: " + algID.getAlgorithm()); @@ -182,15 +185,19 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Obj private static abstract class SubjectPublicKeyInfoConverter { - abstract AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException; + abstract AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException; } private static class RSAConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey()); @@ -199,10 +206,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class DHPublicNumberConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey()); @@ -237,13 +246,15 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class DHAgreementConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { DHParameter params = DHParameter.getInstance(keyInfo.getAlgorithm().getParameters()); - ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); + ASN1Integer derY = (ASN1Integer) keyInfo.parsePublicKey(); BigInteger lVal = params.getL(); int l = lVal == null ? 0 : lVal.intValue(); @@ -254,26 +265,30 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class ElGamalConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { ElGamalParameter params = ElGamalParameter.getInstance(keyInfo.getAlgorithm().getParameters()); - ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); + ASN1Integer derY = (ASN1Integer) keyInfo.parsePublicKey(); return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters( - params.getP(), params.getG())); + params.getP(), params.getG())); } } private static class DSAConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { - ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey(); + ASN1Integer derY = (ASN1Integer) keyInfo.parsePublicKey(); ASN1Encodable de = keyInfo.getAlgorithm().getParameters(); DSAParameters parameters = null; @@ -288,16 +303,18 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class ECConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) { X962Parameters params = X962Parameters.getInstance(keyInfo.getAlgorithm().getParameters()); ECDomainParameters dParams; if (params.isNamedCurve()) { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) params.getParameters(); X9ECParameters x9 = CustomNamedCurves.getByOID(oid); if (x9 == null) @@ -308,7 +325,7 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } else if (params.isImplicitlyCA()) { - dParams = (ECDomainParameters)defaultParams; + dParams = (ECDomainParameters) defaultParams; } else { @@ -324,7 +341,7 @@ else if (params.isImplicitlyCA()) // extra octet string - the old extra embedded octet string // if (data[0] == 0x04 && data[1] == data.length - 2 - && (data[2] == 0x02 || data[2] == 0x03)) + && (data[2] == 0x02 || data[2] == 0x03)) { int qLength = new X9IntegerConverter().getByteLength(dParams.getCurve()); @@ -332,9 +349,8 @@ else if (params.isImplicitlyCA()) { try { - key = (ASN1OctetString)ASN1Primitive.fromByteArray(data); - } - catch (IOException ex) + key = (ASN1OctetString) ASN1Primitive.fromByteArray(data); + } catch (IOException ex) { throw new IllegalArgumentException("error recovering public key"); } @@ -348,9 +364,11 @@ else if (params.isImplicitlyCA()) } private static class GOST3410_2001Converter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) { AlgorithmIdentifier algID = keyInfo.getAlgorithm(); // ASN1ObjectIdentifier algOid = algID.getAlgorithm(); @@ -358,17 +376,16 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje ASN1ObjectIdentifier publicKeyParamSet = gostParams.getPublicKeyParamSet(); ECGOST3410Parameters ecDomainParameters = new ECGOST3410Parameters( - new ECNamedDomainParameters(publicKeyParamSet, ECGOST3410NamedCurves.getByOIDX9(publicKeyParamSet)), - publicKeyParamSet, - gostParams.getDigestParamSet(), - gostParams.getEncryptionParamSet()); + new ECNamedDomainParameters(publicKeyParamSet, ECGOST3410NamedCurves.getByOIDX9(publicKeyParamSet)), + publicKeyParamSet, + gostParams.getDigestParamSet(), + gostParams.getEncryptionParamSet()); ASN1OctetString key; try { - key = (ASN1OctetString)keyInfo.parsePublicKey(); - } - catch (IOException ex) + key = (ASN1OctetString) keyInfo.parsePublicKey(); + } catch (IOException ex) { throw new IllegalArgumentException("error recovering GOST3410_2001 public key"); } @@ -397,9 +414,11 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class GOST3410_2012Converter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) { AlgorithmIdentifier algID = keyInfo.getAlgorithm(); ASN1ObjectIdentifier algOid = algID.getAlgorithm(); @@ -407,17 +426,16 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje ASN1ObjectIdentifier publicKeyParamSet = gostParams.getPublicKeyParamSet(); ECGOST3410Parameters ecDomainParameters = new ECGOST3410Parameters( - new ECNamedDomainParameters(publicKeyParamSet, ECGOST3410NamedCurves.getByOIDX9(publicKeyParamSet)), - publicKeyParamSet, - gostParams.getDigestParamSet(), - gostParams.getEncryptionParamSet()); + new ECNamedDomainParameters(publicKeyParamSet, ECGOST3410NamedCurves.getByOIDX9(publicKeyParamSet)), + publicKeyParamSet, + gostParams.getDigestParamSet(), + gostParams.getEncryptionParamSet()); ASN1OctetString key; try { - key = (ASN1OctetString)keyInfo.parsePublicKey(); - } - catch (IOException ex) + key = (ASN1OctetString) keyInfo.parsePublicKey(); + } catch (IOException ex) { throw new IllegalArgumentException("error recovering GOST3410_2012 public key"); } @@ -450,10 +468,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class DSTUConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { AlgorithmIdentifier algID = keyInfo.getAlgorithm(); ASN1ObjectIdentifier algOid = algID.getAlgorithm(); @@ -462,9 +482,8 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje ASN1OctetString key; try { - key = (ASN1OctetString)keyInfo.parsePublicKey(); - } - catch (IOException ex) + key = (ASN1OctetString) keyInfo.parsePublicKey(); + } catch (IOException ex) { throw new IllegalArgumentException("error recovering DSTU public key"); } @@ -520,42 +539,52 @@ private void reverseBytes(byte[] bytes) } private static class X25519Converter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) { return new X25519PublicKeyParameters(getRawKey(keyInfo, defaultParams)); } } private static class X448Converter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) { return new X448PublicKeyParameters(getRawKey(keyInfo, defaultParams)); } } private static class Ed25519Converter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) { return new Ed25519PublicKeyParameters(getRawKey(keyInfo, defaultParams)); } } private static class Ed448Converter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) { return new Ed448PublicKeyParameters(getRawKey(keyInfo, defaultParams)); } } - private static byte[] getRawKey(SubjectPublicKeyInfo keyInfo, Object defaultParams) + private static byte[] getRawKey( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) { /* * TODO[RFC 8422] diff --git a/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java index bf35a8484e..c970516b66 100644 --- a/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java @@ -36,7 +36,7 @@ import org.bouncycastle.internal.asn1.edec.EdECObjectIdentifiers; import org.bouncycastle.internal.asn1.rosstandart.RosstandartObjectIdentifiers; -import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.Asn1BridgeForInjectedSigAlgs; /** * Factory to create ASN.1 subject public key info objects from lightweight public keys. @@ -67,22 +67,23 @@ private SubjectPublicKeyInfoFactory() * @throws java.io.IOException on an error encoding the key */ public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) - throws IOException + throws IOException { // #tls-injection: - if (InjectionPoint.sigAlgs().asn1Bridge().isSupportedParameter(publicKey)) { - return InjectionPoint.sigAlgs().asn1Bridge().createSubjectPublicKeyInfo(publicKey); + if (Asn1BridgeForInjectedSigAlgs.theInstance().isSupportedParameter(publicKey)) + { + return Asn1BridgeForInjectedSigAlgs.theInstance().createSubjectPublicKeyInfo(publicKey); } if (publicKey instanceof RSAKeyParameters) { - RSAKeyParameters pub = (RSAKeyParameters)publicKey; + RSAKeyParameters pub = (RSAKeyParameters) publicKey; return new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPublicKey(pub.getModulus(), pub.getExponent())); } else if (publicKey instanceof DSAPublicKeyParameters) { - DSAPublicKeyParameters pub = (DSAPublicKeyParameters)publicKey; + DSAPublicKeyParameters pub = (DSAPublicKeyParameters) publicKey; DSAParameter params = null; DSAParameters dsaParams = pub.getParameters(); @@ -95,7 +96,7 @@ else if (publicKey instanceof DSAPublicKeyParameters) } else if (publicKey instanceof ECPublicKeyParameters) { - ECPublicKeyParameters pub = (ECPublicKeyParameters)publicKey; + ECPublicKeyParameters pub = (ECPublicKeyParameters) publicKey; ECDomainParameters domainParams = pub.getParameters(); ASN1Encodable params; @@ -105,7 +106,7 @@ else if (publicKey instanceof ECPublicKeyParameters) } else if (domainParams instanceof ECGOST3410Parameters) { - ECGOST3410Parameters gostParams = (ECGOST3410Parameters)domainParams; + ECGOST3410Parameters gostParams = (ECGOST3410Parameters) domainParams; BigInteger bX = pub.getQ().getAffineXCoord().toBigInteger(); BigInteger bY = pub.getQ().getAffineYCoord().toBigInteger(); @@ -147,25 +148,24 @@ else if (domainParams instanceof ECGOST3410Parameters) try { return new SubjectPublicKeyInfo(new AlgorithmIdentifier(algIdentifier, params), new DEROctetString(encKey)); - } - catch (IOException e) + } catch (IOException e) { return null; } } else if (domainParams instanceof ECNamedDomainParameters) { - params = new X962Parameters(((ECNamedDomainParameters)domainParams).getName()); + params = new X962Parameters(((ECNamedDomainParameters) domainParams).getName()); } else { X9ECParameters ecP = new X9ECParameters( - domainParams.getCurve(), - // TODO Support point compression - new X9ECPoint(domainParams.getG(), false), - domainParams.getN(), - domainParams.getH(), - domainParams.getSeed()); + domainParams.getCurve(), + // TODO Support point compression + new X9ECPoint(domainParams.getG(), false), + domainParams.getN(), + domainParams.getH(), + domainParams.getSeed()); params = new X962Parameters(ecP); } @@ -177,25 +177,25 @@ else if (domainParams instanceof ECNamedDomainParameters) } else if (publicKey instanceof X448PublicKeyParameters) { - X448PublicKeyParameters key = (X448PublicKeyParameters)publicKey; + X448PublicKeyParameters key = (X448PublicKeyParameters) publicKey; return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X448), key.getEncoded()); } else if (publicKey instanceof X25519PublicKeyParameters) { - X25519PublicKeyParameters key = (X25519PublicKeyParameters)publicKey; + X25519PublicKeyParameters key = (X25519PublicKeyParameters) publicKey; return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X25519), key.getEncoded()); } else if (publicKey instanceof Ed448PublicKeyParameters) { - Ed448PublicKeyParameters key = (Ed448PublicKeyParameters)publicKey; + Ed448PublicKeyParameters key = (Ed448PublicKeyParameters) publicKey; return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed448), key.getEncoded()); } else if (publicKey instanceof Ed25519PublicKeyParameters) { - Ed25519PublicKeyParameters key = (Ed25519PublicKeyParameters)publicKey; + Ed25519PublicKeyParameters key = (Ed25519PublicKeyParameters) publicKey; return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), key.getEncoded()); } @@ -205,7 +205,11 @@ else if (publicKey instanceof Ed25519PublicKeyParameters) } } - private static void extractBytes(byte[] encKey, int size, int offSet, BigInteger bI) + private static void extractBytes( + byte[] encKey, + int size, + int offSet, + BigInteger bI) { byte[] val = bI.toByteArray(); if (val.length < size) diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java index b3f535e504..7e9568a3ee 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java @@ -60,7 +60,7 @@ import org.bouncycastle.pqc.crypto.xmss.XMSSUtil; import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PrivateKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPrivateKeyParameters; -import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.Asn1BridgeForInjectedSigAlgs; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Pack; @@ -77,7 +77,7 @@ public class PrivateKeyFactory * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) - throws IOException + throws IOException { if (privateKeyInfoData == null) { @@ -99,7 +99,7 @@ public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(InputStream inStr) - throws IOException + throws IOException { return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); } @@ -112,7 +112,7 @@ public static AsymmetricKeyParameter createKey(InputStream inStr) * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) - throws IOException + throws IOException { if (keyInfo == null) { @@ -123,8 +123,9 @@ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) ASN1ObjectIdentifier algOID = algId.getAlgorithm(); // #tls-injection: - if (InjectionPoint.sigAlgs().contain((algOID))) { - return InjectionPoint.sigAlgs().asn1Bridge().createPrivateKeyParameter(keyInfo); + if (Asn1BridgeForInjectedSigAlgs.theInstance().isSupportedAlgorithm(algOID)) + { + return Asn1BridgeForInjectedSigAlgs.theInstance().createPrivateKeyParameter(keyInfo); } if (algOID.on(PQCObjectIdentifiers.qTESLA)) @@ -136,7 +137,7 @@ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) else if (algOID.equals(PQCObjectIdentifiers.sphincs256)) { return new SPHINCSPrivateKeyParameters(ASN1OctetString.getInstance(keyInfo.parsePrivateKey()).getOctets(), - Utils.sphincs256LookupTreeAlgName(SPHINCS256KeyParams.getInstance(algId.getParameters()))); + Utils.sphincs256LookupTreeAlgName(SPHINCS256KeyParams.getInstance(algId.getParameters()))); } else if (algOID.equals(PQCObjectIdentifiers.newHope)) { @@ -178,7 +179,7 @@ else if (algOID.on(BCObjectIdentifiers.sphincsPlus) || algOID.on(BCObjectIdentif SPHINCSPLUSPrivateKey spKey = SPHINCSPLUSPrivateKey.getInstance(obj); SPHINCSPLUSPublicKey publicKey = spKey.getPublicKey(); return new SPHINCSPlusPrivateKeyParameters(spParams, spKey.getSkseed(), spKey.getSkprf(), - publicKey.getPkseed(), publicKey.getPkroot()); + publicKey.getPkseed(), publicKey.getPkroot()); } else { @@ -234,10 +235,10 @@ else if (algOID.on(BCObjectIdentifiers.pqc_kem_ntrulprime)) NTRULPRimeParameters spParams = Utils.ntrulprimeParamsLookup(algOID); return new NTRULPRimePrivateKeyParameters(spParams, - ASN1OctetString.getInstance(keyEnc.getObjectAt(0)).getOctets(), - ASN1OctetString.getInstance(keyEnc.getObjectAt(1)).getOctets(), - ASN1OctetString.getInstance(keyEnc.getObjectAt(2)).getOctets(), - ASN1OctetString.getInstance(keyEnc.getObjectAt(3)).getOctets()); + ASN1OctetString.getInstance(keyEnc.getObjectAt(0)).getOctets(), + ASN1OctetString.getInstance(keyEnc.getObjectAt(1)).getOctets(), + ASN1OctetString.getInstance(keyEnc.getObjectAt(2)).getOctets(), + ASN1OctetString.getInstance(keyEnc.getObjectAt(3)).getOctets()); } else if (algOID.on(BCObjectIdentifiers.pqc_kem_sntruprime)) { @@ -246,14 +247,14 @@ else if (algOID.on(BCObjectIdentifiers.pqc_kem_sntruprime)) SNTRUPrimeParameters spParams = Utils.sntruprimeParamsLookup(algOID); return new SNTRUPrimePrivateKeyParameters(spParams, - ASN1OctetString.getInstance(keyEnc.getObjectAt(0)).getOctets(), - ASN1OctetString.getInstance(keyEnc.getObjectAt(1)).getOctets(), - ASN1OctetString.getInstance(keyEnc.getObjectAt(2)).getOctets(), - ASN1OctetString.getInstance(keyEnc.getObjectAt(3)).getOctets(), - ASN1OctetString.getInstance(keyEnc.getObjectAt(4)).getOctets()); + ASN1OctetString.getInstance(keyEnc.getObjectAt(0)).getOctets(), + ASN1OctetString.getInstance(keyEnc.getObjectAt(1)).getOctets(), + ASN1OctetString.getInstance(keyEnc.getObjectAt(2)).getOctets(), + ASN1OctetString.getInstance(keyEnc.getObjectAt(3)).getOctets(), + ASN1OctetString.getInstance(keyEnc.getObjectAt(4)).getOctets()); } else if (algOID.equals(BCObjectIdentifiers.dilithium2) - || algOID.equals(BCObjectIdentifiers.dilithium3) || algOID.equals(BCObjectIdentifiers.dilithium5)) + || algOID.equals(BCObjectIdentifiers.dilithium3) || algOID.equals(BCObjectIdentifiers.dilithium5)) { ASN1Encodable keyObj = keyInfo.parsePrivateKey(); DilithiumParameters spParams = Utils.dilithiumParamsLookup(algOID); @@ -273,24 +274,24 @@ else if (algOID.equals(BCObjectIdentifiers.dilithium2) DilithiumPublicKeyParameters pubParams = PublicKeyFactory.DilithiumConverter.getPublicKeyParams(spParams, keyInfo.getPublicKeyData()); return new DilithiumPrivateKeyParameters(spParams, - ASN1BitString.getInstance(keyEnc.getObjectAt(1)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(2)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(3)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(4)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(5)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(6)).getOctets(), - pubParams.getT1()); // encT1 + ASN1BitString.getInstance(keyEnc.getObjectAt(1)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(2)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(3)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(4)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(5)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(6)).getOctets(), + pubParams.getT1()); // encT1 } else { return new DilithiumPrivateKeyParameters(spParams, - ASN1BitString.getInstance(keyEnc.getObjectAt(1)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(2)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(3)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(4)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(5)).getOctets(), - ASN1BitString.getInstance(keyEnc.getObjectAt(6)).getOctets(), - null); + ASN1BitString.getInstance(keyEnc.getObjectAt(1)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(2)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(3)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(4)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(5)).getOctets(), + ASN1BitString.getInstance(keyEnc.getObjectAt(6)).getOctets(), + null); } } else if (keyObj instanceof DEROctetString) @@ -349,12 +350,12 @@ else if (algOID.equals(PQCObjectIdentifiers.xmss)) try { XMSSPrivateKeyParameters.Builder keyBuilder = new XMSSPrivateKeyParameters - .Builder(new XMSSParameters(keyParams.getHeight(), Utils.getDigest(treeDigest))) - .withIndex(xmssPrivateKey.getIndex()) - .withSecretKeySeed(xmssPrivateKey.getSecretKeySeed()) - .withSecretKeyPRF(xmssPrivateKey.getSecretKeyPRF()) - .withPublicSeed(xmssPrivateKey.getPublicSeed()) - .withRoot(xmssPrivateKey.getRoot()); + .Builder(new XMSSParameters(keyParams.getHeight(), Utils.getDigest(treeDigest))) + .withIndex(xmssPrivateKey.getIndex()) + .withSecretKeySeed(xmssPrivateKey.getSecretKeySeed()) + .withSecretKeyPRF(xmssPrivateKey.getSecretKeyPRF()) + .withPublicSeed(xmssPrivateKey.getPublicSeed()) + .withRoot(xmssPrivateKey.getRoot()); if (xmssPrivateKey.getVersion() != 0) { @@ -363,13 +364,12 @@ else if (algOID.equals(PQCObjectIdentifiers.xmss)) if (xmssPrivateKey.getBdsState() != null) { - BDS bds = (BDS)XMSSUtil.deserialize(xmssPrivateKey.getBdsState(), BDS.class); + BDS bds = (BDS) XMSSUtil.deserialize(xmssPrivateKey.getBdsState(), BDS.class); keyBuilder.withBDSState(bds.withWOTSDigest(treeDigest)); } return keyBuilder.build(); - } - catch (ClassNotFoundException e) + } catch (ClassNotFoundException e) { throw new IOException("ClassNotFoundException processing BDS state: " + e.getMessage()); } @@ -384,12 +384,12 @@ else if (algOID.equals(PQCObjectIdentifiers.xmss_mt)) XMSSMTPrivateKey xmssMtPrivateKey = XMSSMTPrivateKey.getInstance(keyInfo.parsePrivateKey()); XMSSMTPrivateKeyParameters.Builder keyBuilder = new XMSSMTPrivateKeyParameters - .Builder(new XMSSMTParameters(keyParams.getHeight(), keyParams.getLayers(), Utils.getDigest(treeDigest))) - .withIndex(xmssMtPrivateKey.getIndex()) - .withSecretKeySeed(xmssMtPrivateKey.getSecretKeySeed()) - .withSecretKeyPRF(xmssMtPrivateKey.getSecretKeyPRF()) - .withPublicSeed(xmssMtPrivateKey.getPublicSeed()) - .withRoot(xmssMtPrivateKey.getRoot()); + .Builder(new XMSSMTParameters(keyParams.getHeight(), keyParams.getLayers(), Utils.getDigest(treeDigest))) + .withIndex(xmssMtPrivateKey.getIndex()) + .withSecretKeySeed(xmssMtPrivateKey.getSecretKeySeed()) + .withSecretKeyPRF(xmssMtPrivateKey.getSecretKeyPRF()) + .withPublicSeed(xmssMtPrivateKey.getPublicSeed()) + .withRoot(xmssMtPrivateKey.getRoot()); if (xmssMtPrivateKey.getVersion() != 0) { @@ -398,13 +398,12 @@ else if (algOID.equals(PQCObjectIdentifiers.xmss_mt)) if (xmssMtPrivateKey.getBdsState() != null) { - BDSStateMap bdsState = (BDSStateMap)XMSSUtil.deserialize(xmssMtPrivateKey.getBdsState(), BDSStateMap.class); + BDSStateMap bdsState = (BDSStateMap) XMSSUtil.deserialize(xmssMtPrivateKey.getBdsState(), BDSStateMap.class); keyBuilder.withBDSState(bdsState.withWOTSDigest(treeDigest)); } return keyBuilder.build(); - } - catch (ClassNotFoundException e) + } catch (ClassNotFoundException e) { throw new IOException("ClassNotFoundException processing BDS state: " + e.getMessage()); } diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java index 164fe6e81a..f637be5ece 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyInfoFactory.java @@ -38,7 +38,7 @@ import org.bouncycastle.pqc.crypto.xmss.XMSSUtil; import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PrivateKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPrivateKeyParameters; -import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.Asn1BridgeForInjectedSigAlgs; import org.bouncycastle.util.Pack; /** @@ -70,16 +70,19 @@ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter private * @return the appropriate PrivateKeyInfo * @throws java.io.IOException on an error encoding the key */ - public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey, ASN1Set attributes) throws IOException + public static PrivateKeyInfo createPrivateKeyInfo( + AsymmetricKeyParameter privateKey, + ASN1Set attributes) throws IOException { // #tls-injection: - if (InjectionPoint.sigAlgs().asn1Bridge().isSupportedParameter(privateKey)) { - return InjectionPoint.sigAlgs().asn1Bridge().createPrivateKeyInfo(privateKey, attributes); + if (Asn1BridgeForInjectedSigAlgs.theInstance().isSupportedParameter(privateKey)) + { + return Asn1BridgeForInjectedSigAlgs.theInstance().createPrivateKeyInfo(privateKey, attributes); } if (privateKey instanceof QTESLAPrivateKeyParameters) { - QTESLAPrivateKeyParameters keyParams = (QTESLAPrivateKeyParameters)privateKey; + QTESLAPrivateKeyParameters keyParams = (QTESLAPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = Utils.qTeslaLookupAlgID(keyParams.getSecurityCategory()); @@ -87,15 +90,15 @@ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter private } else if (privateKey instanceof SPHINCSPrivateKeyParameters) { - SPHINCSPrivateKeyParameters params = (SPHINCSPrivateKeyParameters)privateKey; + SPHINCSPrivateKeyParameters params = (SPHINCSPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.sphincs256, - new SPHINCS256KeyParams(Utils.sphincs256LookupTreeAlgID(params.getTreeDigest()))); + new SPHINCS256KeyParams(Utils.sphincs256LookupTreeAlgID(params.getTreeDigest()))); return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(params.getKeyData())); } else if (privateKey instanceof NHPrivateKeyParameters) { - NHPrivateKeyParameters params = (NHPrivateKeyParameters)privateKey; + NHPrivateKeyParameters params = (NHPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.newHope); @@ -111,7 +114,7 @@ else if (privateKey instanceof NHPrivateKeyParameters) } else if (privateKey instanceof LMSPrivateKeyParameters) { - LMSPrivateKeyParameters params = (LMSPrivateKeyParameters)privateKey; + LMSPrivateKeyParameters params = (LMSPrivateKeyParameters) privateKey; byte[] encoding = Composer.compose().u32str(1).bytes(params).build(); byte[] pubEncoding = Composer.compose().u32str(1).bytes(params.getPublicKey()).build(); @@ -121,7 +124,7 @@ else if (privateKey instanceof LMSPrivateKeyParameters) } else if (privateKey instanceof HSSPrivateKeyParameters) { - HSSPrivateKeyParameters params = (HSSPrivateKeyParameters)privateKey; + HSSPrivateKeyParameters params = (HSSPrivateKeyParameters) privateKey; byte[] encoding = Composer.compose().u32str(params.getL()).bytes(params).build(); byte[] pubEncoding = Composer.compose().u32str(params.getL()).bytes(params.getPublicKey().getLMSPublicKey()).build(); @@ -131,7 +134,7 @@ else if (privateKey instanceof HSSPrivateKeyParameters) } else if (privateKey instanceof SPHINCSPlusPrivateKeyParameters) { - SPHINCSPlusPrivateKeyParameters params = (SPHINCSPlusPrivateKeyParameters)privateKey; + SPHINCSPlusPrivateKeyParameters params = (SPHINCSPlusPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.sphincsPlusOidLookup(params.getParameters())); @@ -139,7 +142,7 @@ else if (privateKey instanceof SPHINCSPlusPrivateKeyParameters) } else if (privateKey instanceof PicnicPrivateKeyParameters) { - PicnicPrivateKeyParameters params = (PicnicPrivateKeyParameters)privateKey; + PicnicPrivateKeyParameters params = (PicnicPrivateKeyParameters) privateKey; byte[] encoding = params.getEncoded(); @@ -148,7 +151,7 @@ else if (privateKey instanceof PicnicPrivateKeyParameters) } else if (privateKey instanceof CMCEPrivateKeyParameters) { - CMCEPrivateKeyParameters params = (CMCEPrivateKeyParameters)privateKey; + CMCEPrivateKeyParameters params = (CMCEPrivateKeyParameters) privateKey; //todo either make CMCEPrivateKey split the parameters from the private key or // (current) Make CMCEPrivateKey take parts of the private key splitted in the params @@ -161,25 +164,25 @@ else if (privateKey instanceof CMCEPrivateKeyParameters) } else if (privateKey instanceof XMSSPrivateKeyParameters) { - XMSSPrivateKeyParameters keyParams = (XMSSPrivateKeyParameters)privateKey; + XMSSPrivateKeyParameters keyParams = (XMSSPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.xmss, - new XMSSKeyParams(keyParams.getParameters().getHeight(), - Utils.xmssLookupTreeAlgID(keyParams.getTreeDigest()))); + new XMSSKeyParams(keyParams.getParameters().getHeight(), + Utils.xmssLookupTreeAlgID(keyParams.getTreeDigest()))); return new PrivateKeyInfo(algorithmIdentifier, xmssCreateKeyStructure(keyParams), attributes); } else if (privateKey instanceof XMSSMTPrivateKeyParameters) { - XMSSMTPrivateKeyParameters keyParams = (XMSSMTPrivateKeyParameters)privateKey; + XMSSMTPrivateKeyParameters keyParams = (XMSSMTPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.xmss_mt, - new XMSSMTKeyParams(keyParams.getParameters().getHeight(), keyParams.getParameters().getLayers(), - Utils.xmssLookupTreeAlgID(keyParams.getTreeDigest()))); + new XMSSMTKeyParams(keyParams.getParameters().getHeight(), keyParams.getParameters().getLayers(), + Utils.xmssLookupTreeAlgID(keyParams.getTreeDigest()))); return new PrivateKeyInfo(algorithmIdentifier, xmssmtCreateKeyStructure(keyParams), attributes); } else if (privateKey instanceof McElieceCCA2PrivateKeyParameters) { - McElieceCCA2PrivateKeyParameters priv = (McElieceCCA2PrivateKeyParameters)privateKey; + McElieceCCA2PrivateKeyParameters priv = (McElieceCCA2PrivateKeyParameters) privateKey; McElieceCCA2PrivateKey mcEliecePriv = new McElieceCCA2PrivateKey(priv.getN(), priv.getK(), priv.getField(), priv.getGoppaPoly(), priv.getP(), Utils.getAlgorithmIdentifier(priv.getDigest())); AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.mcElieceCca2); @@ -187,7 +190,7 @@ else if (privateKey instanceof McElieceCCA2PrivateKeyParameters) } else if (privateKey instanceof FrodoPrivateKeyParameters) { - FrodoPrivateKeyParameters params = (FrodoPrivateKeyParameters)privateKey; + FrodoPrivateKeyParameters params = (FrodoPrivateKeyParameters) privateKey; byte[] encoding = params.getEncoded(); @@ -197,7 +200,7 @@ else if (privateKey instanceof FrodoPrivateKeyParameters) } else if (privateKey instanceof SABERPrivateKeyParameters) { - SABERPrivateKeyParameters params = (SABERPrivateKeyParameters)privateKey; + SABERPrivateKeyParameters params = (SABERPrivateKeyParameters) privateKey; byte[] encoding = params.getEncoded(); @@ -207,7 +210,7 @@ else if (privateKey instanceof SABERPrivateKeyParameters) } else if (privateKey instanceof NTRUPrivateKeyParameters) { - NTRUPrivateKeyParameters params = (NTRUPrivateKeyParameters)privateKey; + NTRUPrivateKeyParameters params = (NTRUPrivateKeyParameters) privateKey; byte[] encoding = params.getEncoded(); @@ -217,7 +220,7 @@ else if (privateKey instanceof NTRUPrivateKeyParameters) } else if (privateKey instanceof FalconPrivateKeyParameters) { - FalconPrivateKeyParameters params = (FalconPrivateKeyParameters)privateKey; + FalconPrivateKeyParameters params = (FalconPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.falconOidLookup(params.getParameters())); @@ -228,15 +231,15 @@ else if (privateKey instanceof FalconPrivateKeyParameters) } else if (privateKey instanceof KyberPrivateKeyParameters) { - KyberPrivateKeyParameters params = (KyberPrivateKeyParameters)privateKey; - + KyberPrivateKeyParameters params = (KyberPrivateKeyParameters) privateKey; + AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.kyberOidLookup(params.getParameters())); return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(params.getEncoded()), attributes); } else if (privateKey instanceof NTRULPRimePrivateKeyParameters) { - NTRULPRimePrivateKeyParameters params = (NTRULPRimePrivateKeyParameters)privateKey; + NTRULPRimePrivateKeyParameters params = (NTRULPRimePrivateKeyParameters) privateKey; ASN1EncodableVector v = new ASN1EncodableVector(); @@ -251,7 +254,7 @@ else if (privateKey instanceof NTRULPRimePrivateKeyParameters) } else if (privateKey instanceof SNTRUPrimePrivateKeyParameters) { - SNTRUPrimePrivateKeyParameters params = (SNTRUPrimePrivateKeyParameters)privateKey; + SNTRUPrimePrivateKeyParameters params = (SNTRUPrimePrivateKeyParameters) privateKey; ASN1EncodableVector v = new ASN1EncodableVector(); @@ -267,7 +270,7 @@ else if (privateKey instanceof SNTRUPrimePrivateKeyParameters) } else if (privateKey instanceof DilithiumPrivateKeyParameters) { - DilithiumPrivateKeyParameters params = (DilithiumPrivateKeyParameters)privateKey; + DilithiumPrivateKeyParameters params = (DilithiumPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.dilithiumOidLookup(params.getParameters())); @@ -277,21 +280,21 @@ else if (privateKey instanceof DilithiumPrivateKeyParameters) } else if (privateKey instanceof BIKEPrivateKeyParameters) { - BIKEPrivateKeyParameters params = (BIKEPrivateKeyParameters)privateKey; + BIKEPrivateKeyParameters params = (BIKEPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.bikeOidLookup(params.getParameters())); byte[] encoding = params.getEncoded(); return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(encoding), attributes); } else if (privateKey instanceof HQCPrivateKeyParameters) { - HQCPrivateKeyParameters params = (HQCPrivateKeyParameters)privateKey; + HQCPrivateKeyParameters params = (HQCPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.hqcOidLookup(params.getParameters())); byte[] encoding = params.getEncoded(); return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(encoding), attributes); } else if (privateKey instanceof RainbowPrivateKeyParameters) { - RainbowPrivateKeyParameters params = (RainbowPrivateKeyParameters)privateKey; + RainbowPrivateKeyParameters params = (RainbowPrivateKeyParameters) privateKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.rainbowOidLookup(params.getParameters())); byte[] encoding = params.getEncoded(); return new PrivateKeyInfo(algorithmIdentifier, new DEROctetString(encoding), attributes); @@ -303,7 +306,7 @@ else if (privateKey instanceof RainbowPrivateKeyParameters) } private static XMSSPrivateKey xmssCreateKeyStructure(XMSSPrivateKeyParameters keyParams) - throws IOException + throws IOException { byte[] keyData = keyParams.getEncoded(); @@ -316,7 +319,7 @@ private static XMSSPrivateKey xmssCreateKeyStructure(XMSSPrivateKeyParameters ke int rootSize = n; int position = 0; - int index = (int)XMSSUtil.bytesToXBigEndian(keyData, position, indexSize); + int index = (int) XMSSUtil.bytesToXBigEndian(keyData, position, indexSize); if (!XMSSUtil.isIndexValid(totalHeight, index)) { throw new IllegalArgumentException("index out of bounds"); @@ -330,14 +333,13 @@ private static XMSSPrivateKey xmssCreateKeyStructure(XMSSPrivateKeyParameters ke position += publicSeedSize; byte[] root = XMSSUtil.extractBytesAtOffset(keyData, position, rootSize); position += rootSize; - /* import BDS state */ + /* import BDS state */ byte[] bdsStateBinary = XMSSUtil.extractBytesAtOffset(keyData, position, keyData.length - position); BDS bds = null; try { - bds = (BDS)XMSSUtil.deserialize(bdsStateBinary, BDS.class); - } - catch (ClassNotFoundException e) + bds = (BDS) XMSSUtil.deserialize(bdsStateBinary, BDS.class); + } catch (ClassNotFoundException e) { throw new IOException("cannot parse BDS: " + e.getMessage()); } @@ -353,7 +355,7 @@ private static XMSSPrivateKey xmssCreateKeyStructure(XMSSPrivateKeyParameters ke } private static XMSSMTPrivateKey xmssmtCreateKeyStructure(XMSSMTPrivateKeyParameters keyParams) - throws IOException + throws IOException { byte[] keyData = keyParams.getEncoded(); @@ -366,7 +368,7 @@ private static XMSSMTPrivateKey xmssmtCreateKeyStructure(XMSSMTPrivateKeyParamet int rootSize = n; int position = 0; - int index = (int)XMSSUtil.bytesToXBigEndian(keyData, position, indexSize); + int index = (int) XMSSUtil.bytesToXBigEndian(keyData, position, indexSize); if (!XMSSUtil.isIndexValid(totalHeight, index)) { throw new IllegalArgumentException("index out of bounds"); @@ -380,14 +382,13 @@ private static XMSSMTPrivateKey xmssmtCreateKeyStructure(XMSSMTPrivateKeyParamet position += publicSeedSize; byte[] root = XMSSUtil.extractBytesAtOffset(keyData, position, rootSize); position += rootSize; - /* import BDS state */ + /* import BDS state */ byte[] bdsStateBinary = XMSSUtil.extractBytesAtOffset(keyData, position, keyData.length - position); BDSStateMap bds = null; try { - bds = (BDSStateMap)XMSSUtil.deserialize(bdsStateBinary, BDSStateMap.class); - } - catch (ClassNotFoundException e) + bds = (BDSStateMap) XMSSUtil.deserialize(bdsStateBinary, BDSStateMap.class); + } catch (ClassNotFoundException e) { throw new IOException("cannot parse BDSStateMap: " + e.getMessage()); } diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java index 5e4a744764..5b3fc3eb30 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/PublicKeyFactory.java @@ -63,7 +63,7 @@ import org.bouncycastle.pqc.crypto.xmss.XMSSPublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPublicKeyParameters; -import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.Asn1BridgeForInjectedSigAlgs; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Pack; @@ -139,7 +139,7 @@ public class PublicKeyFactory converters.put(BCObjectIdentifiers.sphincsPlus_shake_256s, new SPHINCSPlusConverter()); converters.put(BCObjectIdentifiers.sphincsPlus_shake_256f, new SPHINCSPlusConverter()); converters.put(new ASN1ObjectIdentifier("1.3.9999.6.4.10"), new SPHINCSPlusConverter()); - + converters.put(BCObjectIdentifiers.mceliece348864_r3, new CMCEConverter()); converters.put(BCObjectIdentifiers.mceliece348864f_r3, new CMCEConverter()); converters.put(BCObjectIdentifiers.mceliece460896_r3, new CMCEConverter()); @@ -240,7 +240,7 @@ public class PublicKeyFactory * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(byte[] keyInfoData) - throws IOException + throws IOException { if (keyInfoData == null) { @@ -261,7 +261,7 @@ public static AsymmetricKeyParameter createKey(byte[] keyInfoData) * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(InputStream inStr) - throws IOException + throws IOException { return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); } @@ -274,7 +274,7 @@ public static AsymmetricKeyParameter createKey(InputStream inStr) * @throws IOException on an error decoding the key */ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) - throws IOException + throws IOException { if (keyInfo == null) { @@ -291,8 +291,10 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) * @return the appropriate key parameter * @throws IOException on an error decoding the key */ - public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + public static AsymmetricKeyParameter createKey( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { if (keyInfo == null) { @@ -303,11 +305,12 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Obj ASN1ObjectIdentifier algOID = algId.getAlgorithm(); // #tls-injection: - if (InjectionPoint.sigAlgs().contain((algOID))) { - return InjectionPoint.sigAlgs().asn1Bridge().createPublicKeyParameter(keyInfo, defaultParams); + if (Asn1BridgeForInjectedSigAlgs.theInstance().isSupportedAlgorithm(algOID)) + { + return Asn1BridgeForInjectedSigAlgs.theInstance().createPublicKeyParameter(keyInfo, defaultParams); } - SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters.get(algId.getAlgorithm()); + SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter) converters.get(algId.getAlgorithm()); if (converter != null) { @@ -321,46 +324,56 @@ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Obj private static abstract class SubjectPublicKeyInfoConverter { - abstract AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException; + abstract AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException; } private static class QTeslaConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { return new QTESLAPublicKeyParameters(Utils.qTeslaLookupSecurityCategory(keyInfo.getAlgorithm()), keyInfo.getPublicKeyData().getOctets()); } } private static class SPHINCSConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { return new SPHINCSPublicKeyParameters(keyInfo.getPublicKeyData().getBytes(), - Utils.sphincs256LookupTreeAlgName(SPHINCS256KeyParams.getInstance(keyInfo.getAlgorithm().getParameters()))); + Utils.sphincs256LookupTreeAlgName(SPHINCS256KeyParams.getInstance(keyInfo.getAlgorithm().getParameters()))); } } private static class NHConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { return new NHPublicKeyParameters(keyInfo.getPublicKeyData().getBytes()); } } private static class XMSSConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { XMSSKeyParams keyParams = XMSSKeyParams.getInstance(keyInfo.getAlgorithm().getParameters()); @@ -370,26 +383,28 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje XMSSPublicKey xmssPublicKey = XMSSPublicKey.getInstance(keyInfo.parsePublicKey()); return new XMSSPublicKeyParameters - .Builder(new XMSSParameters(keyParams.getHeight(), Utils.getDigest(treeDigest))) - .withPublicSeed(xmssPublicKey.getPublicSeed()) - .withRoot(xmssPublicKey.getRoot()).build(); + .Builder(new XMSSParameters(keyParams.getHeight(), Utils.getDigest(treeDigest))) + .withPublicSeed(xmssPublicKey.getPublicSeed()) + .withRoot(xmssPublicKey.getRoot()).build(); } else { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); return new XMSSPublicKeyParameters - .Builder(XMSSParameters.lookupByOID(Pack.bigEndianToInt(keyEnc, 0))) - .withPublicKey(keyEnc).build(); + .Builder(XMSSParameters.lookupByOID(Pack.bigEndianToInt(keyEnc, 0))) + .withPublicKey(keyEnc).build(); } } } private static class XMSSMTConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { XMSSMTKeyParams keyParams = XMSSMTKeyParams.getInstance(keyInfo.getAlgorithm().getParameters()); @@ -400,26 +415,28 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje XMSSPublicKey xmssMtPublicKey = XMSSPublicKey.getInstance(keyInfo.parsePublicKey()); return new XMSSMTPublicKeyParameters - .Builder(new XMSSMTParameters(keyParams.getHeight(), keyParams.getLayers(), Utils.getDigest(treeDigest))) - .withPublicSeed(xmssMtPublicKey.getPublicSeed()) - .withRoot(xmssMtPublicKey.getRoot()).build(); + .Builder(new XMSSMTParameters(keyParams.getHeight(), keyParams.getLayers(), Utils.getDigest(treeDigest))) + .withPublicSeed(xmssMtPublicKey.getPublicSeed()) + .withRoot(xmssMtPublicKey.getRoot()).build(); } else { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); return new XMSSMTPublicKeyParameters - .Builder(XMSSMTParameters.lookupByOID(Pack.bigEndianToInt(keyEnc, 0))) - .withPublicKey(keyEnc).build(); + .Builder(XMSSMTParameters.lookupByOID(Pack.bigEndianToInt(keyEnc, 0))) + .withPublicKey(keyEnc).build(); } } } private static class LMSConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); @@ -440,10 +457,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class SPHINCSPlusConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { try { @@ -452,8 +471,7 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje SPHINCSPlusParameters spParams = Utils.sphincsPlusParamsLookup(keyInfo.getAlgorithm().getAlgorithm()); return new SPHINCSPlusPublicKeyParameters(spParams, Arrays.copyOfRange(keyEnc, 4, keyEnc.length)); - } - catch (Exception e) + } catch (Exception e) { byte[] keyEnc = keyInfo.getPublicKeyData().getOctets(); @@ -465,10 +483,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class CMCEConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { try { @@ -477,9 +497,8 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje CMCEParameters spParams = Utils.mcElieceParamsLookup(keyInfo.getAlgorithm().getAlgorithm()); return new CMCEPublicKeyParameters(spParams, keyEnc); - } - catch (Exception e) - { + } catch (Exception e) + { byte[] keyEnc = keyInfo.getPublicKeyData().getOctets(); CMCEParameters spParams = Utils.mcElieceParamsLookup(keyInfo.getAlgorithm().getAlgorithm()); @@ -492,7 +511,9 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje private static class SABERConverter extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) throws IOException { byte[] keyEnc = ASN1OctetString.getInstance( @@ -505,10 +526,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class McElieceCCA2Converter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { McElieceCCA2PublicKey mKey = McElieceCCA2PublicKey.getInstance(keyInfo.parsePublicKey()); @@ -519,7 +542,9 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje private static class FrodoConverter extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) throws IOException { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); @@ -533,7 +558,9 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje private static class PicnicConverter extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) throws IOException { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); @@ -545,10 +572,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class NtruConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); @@ -559,10 +588,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class FalconConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { byte[] keyEnc = keyInfo.getPublicKeyData().getOctets(); // FalconPublicKey falconPublicKey = FalconPublicKey.getInstance(keyInfo.parsePublicKey()); @@ -575,10 +606,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class KyberConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { KyberParameters kyberParameters = Utils.kyberParamsLookup(keyInfo.getAlgorithm().getAlgorithm()); @@ -588,8 +621,7 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje KyberPublicKey kyberKey = KyberPublicKey.getInstance(obj); return new KyberPublicKeyParameters(kyberParameters, kyberKey.getT(), kyberKey.getRho()); - } - catch (Exception e) + } catch (Exception e) { // we're a raw encoding return new KyberPublicKeyParameters(kyberParameters, keyInfo.getPublicKeyData().getOctets()); @@ -598,10 +630,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class NTRULPrimeConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); @@ -612,10 +646,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class SNTRUPrimeConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); @@ -624,19 +660,23 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje return new SNTRUPrimePublicKeyParameters(ntruLPRimeParams, keyEnc); } } - + static class DilithiumConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { DilithiumParameters dilithiumParams = Utils.dilithiumParamsLookup(keyInfo.getAlgorithm().getAlgorithm()); return getPublicKeyParams(dilithiumParams, keyInfo.getPublicKeyData()); } - static DilithiumPublicKeyParameters getPublicKeyParams(DilithiumParameters dilithiumParams, ASN1BitString publicKeyData) + static DilithiumPublicKeyParameters getPublicKeyParams( + DilithiumParameters dilithiumParams, + ASN1BitString publicKeyData) { try { @@ -646,8 +686,8 @@ static DilithiumPublicKeyParameters getPublicKeyParams(DilithiumParameters dilit ASN1Sequence keySeq = ASN1Sequence.getInstance(obj); return new DilithiumPublicKeyParameters(dilithiumParams, - ASN1OctetString.getInstance(keySeq.getObjectAt(0)).getOctets(), - ASN1OctetString.getInstance(keySeq.getObjectAt(1)).getOctets()); + ASN1OctetString.getInstance(keySeq.getObjectAt(0)).getOctets(), + ASN1OctetString.getInstance(keySeq.getObjectAt(1)).getOctets()); } else { @@ -655,8 +695,7 @@ static DilithiumPublicKeyParameters getPublicKeyParams(DilithiumParameters dilit return new DilithiumPublicKeyParameters(dilithiumParams, encKey); } - } - catch (Exception e) + } catch (Exception e) { // we're a raw encoding return new DilithiumPublicKeyParameters(dilithiumParams, publicKeyData.getOctets()); @@ -667,7 +706,9 @@ static DilithiumPublicKeyParameters getPublicKeyParams(DilithiumParameters dilit private static class BIKEConverter extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) throws IOException { try @@ -677,8 +718,7 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje BIKEParameters bikeParams = Utils.bikeParamsLookup(keyInfo.getAlgorithm().getAlgorithm()); return new BIKEPublicKeyParameters(bikeParams, keyEnc); - } - catch (Exception e) + } catch (Exception e) { byte[] keyEnc = keyInfo.getPublicKeyData().getOctets(); @@ -692,7 +732,9 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje private static class HQCConverter extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) throws IOException { try @@ -702,8 +744,7 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje HQCParameters hqcParams = Utils.hqcParamsLookup(keyInfo.getAlgorithm().getAlgorithm()); return new HQCPublicKeyParameters(hqcParams, keyEnc); - } - catch (Exception e) + } catch (Exception e) { // raw encoding byte[] keyEnc = keyInfo.getPublicKeyData().getOctets(); @@ -716,10 +757,12 @@ AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Obje } private static class RainbowConverter - extends SubjectPublicKeyInfoConverter + extends SubjectPublicKeyInfoConverter { - AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) - throws IOException + AsymmetricKeyParameter getPublicKeyParameters( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) + throws IOException { byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePublicKey()).getOctets(); diff --git a/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java b/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java index 108222a7f3..ba5c687775 100644 --- a/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java +++ b/core/src/main/java/org/bouncycastle/pqc/crypto/util/SubjectPublicKeyInfoFactory.java @@ -39,7 +39,7 @@ import org.bouncycastle.pqc.crypto.xmss.XMSSPublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.mceliece.McElieceCCA2PublicKeyParameters; import org.bouncycastle.pqc.legacy.crypto.qtesla.QTESLAPublicKeyParameters; -import org.bouncycastle.tls.injection.InjectionPoint; +import org.bouncycastle.tls.injection.Asn1BridgeForInjectedSigAlgs; /** * Factory to create ASN.1 subject public key info objects from lightweight public keys. @@ -59,38 +59,39 @@ private SubjectPublicKeyInfoFactory() * @throws java.io.IOException on an error encoding the key */ public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) - throws IOException + throws IOException { // #tls-injection: - if (InjectionPoint.sigAlgs().asn1Bridge().isSupportedParameter(publicKey)) { - return InjectionPoint.sigAlgs().asn1Bridge().createSubjectPublicKeyInfo(publicKey); + if (Asn1BridgeForInjectedSigAlgs.theInstance().isSupportedParameter(publicKey)) + { + return Asn1BridgeForInjectedSigAlgs.theInstance().createSubjectPublicKeyInfo(publicKey); } if (publicKey instanceof QTESLAPublicKeyParameters) { - QTESLAPublicKeyParameters keyParams = (QTESLAPublicKeyParameters)publicKey; + QTESLAPublicKeyParameters keyParams = (QTESLAPublicKeyParameters) publicKey; AlgorithmIdentifier algorithmIdentifier = Utils.qTeslaLookupAlgID(keyParams.getSecurityCategory()); return new SubjectPublicKeyInfo(algorithmIdentifier, keyParams.getPublicData()); } else if (publicKey instanceof SPHINCSPublicKeyParameters) { - SPHINCSPublicKeyParameters params = (SPHINCSPublicKeyParameters)publicKey; + SPHINCSPublicKeyParameters params = (SPHINCSPublicKeyParameters) publicKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.sphincs256, - new SPHINCS256KeyParams(Utils.sphincs256LookupTreeAlgID(params.getTreeDigest()))); + new SPHINCS256KeyParams(Utils.sphincs256LookupTreeAlgID(params.getTreeDigest()))); return new SubjectPublicKeyInfo(algorithmIdentifier, params.getKeyData()); } else if (publicKey instanceof NHPublicKeyParameters) { - NHPublicKeyParameters params = (NHPublicKeyParameters)publicKey; + NHPublicKeyParameters params = (NHPublicKeyParameters) publicKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.newHope); return new SubjectPublicKeyInfo(algorithmIdentifier, params.getPubData()); } else if (publicKey instanceof LMSPublicKeyParameters) { - LMSPublicKeyParameters params = (LMSPublicKeyParameters)publicKey; + LMSPublicKeyParameters params = (LMSPublicKeyParameters) publicKey; byte[] encoding = Composer.compose().u32str(1).bytes(params).build(); @@ -99,7 +100,7 @@ else if (publicKey instanceof LMSPublicKeyParameters) } else if (publicKey instanceof HSSPublicKeyParameters) { - HSSPublicKeyParameters params = (HSSPublicKeyParameters)publicKey; + HSSPublicKeyParameters params = (HSSPublicKeyParameters) publicKey; byte[] encoding = Composer.compose().u32str(params.getL()).bytes(params.getLMSPublicKey()).build(); @@ -108,7 +109,7 @@ else if (publicKey instanceof HSSPublicKeyParameters) } else if (publicKey instanceof SPHINCSPlusPublicKeyParameters) { - SPHINCSPlusPublicKeyParameters params = (SPHINCSPlusPublicKeyParameters)publicKey; + SPHINCSPlusPublicKeyParameters params = (SPHINCSPlusPublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); @@ -117,7 +118,7 @@ else if (publicKey instanceof SPHINCSPlusPublicKeyParameters) } else if (publicKey instanceof CMCEPublicKeyParameters) { - CMCEPublicKeyParameters params = (CMCEPublicKeyParameters)publicKey; + CMCEPublicKeyParameters params = (CMCEPublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); @@ -127,7 +128,7 @@ else if (publicKey instanceof CMCEPublicKeyParameters) } else if (publicKey instanceof XMSSPublicKeyParameters) { - XMSSPublicKeyParameters keyParams = (XMSSPublicKeyParameters)publicKey; + XMSSPublicKeyParameters keyParams = (XMSSPublicKeyParameters) publicKey; byte[] publicSeed = keyParams.getPublicSeed(); byte[] root = keyParams.getRoot(); @@ -141,14 +142,14 @@ else if (publicKey instanceof XMSSPublicKeyParameters) else { AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.xmss, - new XMSSKeyParams(keyParams.getParameters().getHeight(), Utils.xmssLookupTreeAlgID(keyParams.getTreeDigest()))); + new XMSSKeyParams(keyParams.getParameters().getHeight(), Utils.xmssLookupTreeAlgID(keyParams.getTreeDigest()))); return new SubjectPublicKeyInfo(algorithmIdentifier, new XMSSPublicKey(publicSeed, root)); } } else if (publicKey instanceof XMSSMTPublicKeyParameters) { - XMSSMTPublicKeyParameters keyParams = (XMSSMTPublicKeyParameters)publicKey; + XMSSMTPublicKeyParameters keyParams = (XMSSMTPublicKeyParameters) publicKey; byte[] publicSeed = keyParams.getPublicSeed(); byte[] root = keyParams.getRoot(); @@ -162,13 +163,13 @@ else if (publicKey instanceof XMSSMTPublicKeyParameters) else { AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.xmss_mt, new XMSSMTKeyParams(keyParams.getParameters().getHeight(), keyParams.getParameters().getLayers(), - Utils.xmssLookupTreeAlgID(keyParams.getTreeDigest()))); + Utils.xmssLookupTreeAlgID(keyParams.getTreeDigest()))); return new SubjectPublicKeyInfo(algorithmIdentifier, new XMSSMTPublicKey(keyParams.getPublicSeed(), keyParams.getRoot())); } } else if (publicKey instanceof McElieceCCA2PublicKeyParameters) { - McElieceCCA2PublicKeyParameters pub = (McElieceCCA2PublicKeyParameters)publicKey; + McElieceCCA2PublicKeyParameters pub = (McElieceCCA2PublicKeyParameters) publicKey; McElieceCCA2PublicKey mcEliecePub = new McElieceCCA2PublicKey(pub.getN(), pub.getT(), pub.getG(), Utils.getAlgorithmIdentifier(pub.getDigest())); AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PQCObjectIdentifiers.mcElieceCca2); @@ -176,7 +177,7 @@ else if (publicKey instanceof McElieceCCA2PublicKeyParameters) } else if (publicKey instanceof FrodoPublicKeyParameters) { - FrodoPublicKeyParameters params = (FrodoPublicKeyParameters)publicKey; + FrodoPublicKeyParameters params = (FrodoPublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); @@ -186,17 +187,17 @@ else if (publicKey instanceof FrodoPublicKeyParameters) } else if (publicKey instanceof SABERPublicKeyParameters) { - SABERPublicKeyParameters params = (SABERPublicKeyParameters)publicKey; + SABERPublicKeyParameters params = (SABERPublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.saberOidLookup(params.getParameters())); - + return new SubjectPublicKeyInfo(algorithmIdentifier, new DERSequence(new DEROctetString(encoding))); } else if (publicKey instanceof PicnicPublicKeyParameters) { - PicnicPublicKeyParameters params = (PicnicPublicKeyParameters)publicKey; + PicnicPublicKeyParameters params = (PicnicPublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); @@ -205,7 +206,7 @@ else if (publicKey instanceof PicnicPublicKeyParameters) } else if (publicKey instanceof NTRUPublicKeyParameters) { - NTRUPublicKeyParameters params = (NTRUPublicKeyParameters)publicKey; + NTRUPublicKeyParameters params = (NTRUPublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); @@ -214,20 +215,20 @@ else if (publicKey instanceof NTRUPublicKeyParameters) } else if (publicKey instanceof FalconPublicKeyParameters) { - FalconPublicKeyParameters params = (FalconPublicKeyParameters)publicKey; + FalconPublicKeyParameters params = (FalconPublicKeyParameters) publicKey; byte[] encoding = params.getH(); AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.falconOidLookup(params.getParameters())); byte[] keyEnc = new byte[encoding.length + 1]; - keyEnc[0] = (byte)(0x00 + params.getParameters().getLogN()); + keyEnc[0] = (byte) (0x00 + params.getParameters().getLogN()); System.arraycopy(encoding, 0, keyEnc, 1, encoding.length); return new SubjectPublicKeyInfo(algorithmIdentifier, keyEnc); } else if (publicKey instanceof KyberPublicKeyParameters) { - KyberPublicKeyParameters params = (KyberPublicKeyParameters)publicKey; + KyberPublicKeyParameters params = (KyberPublicKeyParameters) publicKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.kyberOidLookup(params.getParameters())); @@ -235,7 +236,7 @@ else if (publicKey instanceof KyberPublicKeyParameters) } else if (publicKey instanceof NTRULPRimePublicKeyParameters) { - NTRULPRimePublicKeyParameters params = (NTRULPRimePublicKeyParameters)publicKey; + NTRULPRimePublicKeyParameters params = (NTRULPRimePublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.ntrulprimeOidLookup(params.getParameters())); @@ -244,7 +245,7 @@ else if (publicKey instanceof NTRULPRimePublicKeyParameters) } else if (publicKey instanceof SNTRUPrimePublicKeyParameters) { - SNTRUPrimePublicKeyParameters params = (SNTRUPrimePublicKeyParameters)publicKey; + SNTRUPrimePublicKeyParameters params = (SNTRUPrimePublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.sntruprimeOidLookup(params.getParameters())); @@ -253,7 +254,7 @@ else if (publicKey instanceof SNTRUPrimePublicKeyParameters) } else if (publicKey instanceof DilithiumPublicKeyParameters) { - DilithiumPublicKeyParameters params = (DilithiumPublicKeyParameters)publicKey; + DilithiumPublicKeyParameters params = (DilithiumPublicKeyParameters) publicKey; AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(Utils.dilithiumOidLookup(params.getParameters())); @@ -271,7 +272,7 @@ else if (publicKey instanceof BIKEPublicKeyParameters) } else if (publicKey instanceof HQCPublicKeyParameters) { - HQCPublicKeyParameters params = (HQCPublicKeyParameters)publicKey; + HQCPublicKeyParameters params = (HQCPublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); @@ -281,7 +282,7 @@ else if (publicKey instanceof HQCPublicKeyParameters) } else if (publicKey instanceof RainbowPublicKeyParameters) { - RainbowPublicKeyParameters params = (RainbowPublicKeyParameters)publicKey; + RainbowPublicKeyParameters params = (RainbowPublicKeyParameters) publicKey; byte[] encoding = params.getEncoded(); diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java b/core/src/main/java/org/bouncycastle/tls/injection/Asn1Bridge.java similarity index 67% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java rename to core/src/main/java/org/bouncycastle/tls/injection/Asn1Bridge.java index e8d2623651..c113e7f88f 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/Asn1Bridge.java +++ b/core/src/main/java/org/bouncycastle/tls/injection/Asn1Bridge.java @@ -1,5 +1,6 @@ -package org.bouncycastle.tls.injection.sigalgs; +package org.bouncycastle.tls.injection; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; @@ -7,7 +8,30 @@ import java.io.IOException; +/** + * #tls-injection + * + * The Asn1Bridge interface defines the bridge between ASN.1 notation for public/private keys and their internal + * representation inside the BC AsymmetricKeyParameter class. + * + * This interface is implemented by the Asn1BridgeForInjectedSigAlgs class (in the BC core package), + * which represents signature algorithms injected into TLS Injection Mechanism (in the BC tls package; + * however there is no compile-time dependency on "tls" from the "core" package). + * + * The Asn1BridgeForInjectedSigAlgs is consulted inside the BC core package in order to add the ability to + * work with public and private keys corresponding to the injected (perhaps, non-standard) signature algorithms. + * + * + */ public interface Asn1Bridge { + + /** + * Checks whether the signature algorithm with the given object identified (OID) has been injected. + * @param oid the ASN object identifier of the algorithm in question + * @return returns true, iff the algorithm with the given oid has been injected + */ + boolean isSupportedAlgorithm(ASN1ObjectIdentifier oid); + /** * Checks whether the given BC key (public or private) can be converted to ASN.1. * diff --git a/core/src/main/java/org/bouncycastle/tls/injection/Asn1BridgeForInjectedSigAlgs.java b/core/src/main/java/org/bouncycastle/tls/injection/Asn1BridgeForInjectedSigAlgs.java new file mode 100644 index 0000000000..61bd431e7e --- /dev/null +++ b/core/src/main/java/org/bouncycastle/tls/injection/Asn1BridgeForInjectedSigAlgs.java @@ -0,0 +1,149 @@ +package org.bouncycastle.tls.injection; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; + +import java.io.IOException; +import java.lang.reflect.Method; + +/** + * Represents signature algorithms injected into TLS Injection Mechanism in the BC "tls" package. + * However, there is no compile-time dependency on "tls" from our ("core") package. + *

+ * Asn1BridgeForInjectedSigAlgs tries to contact the TLS Injection Mechanism's InjectionPoint class dynamically + * to obtain the corresponding Asn1Bridge implementation representing all the injected signature algorithms. + * If InjectionPoint is not available, the default Asn1Bridge implementation + * (which doesn't support any of the signature algorithms) is used. + * The default Asn1Bridge implementation can be replaced via the replaceWith() call. + */ +public class Asn1BridgeForInjectedSigAlgs + implements Asn1Bridge +{ + + // Bill Pugh Singleton Implementation, see https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/ + private static class BillPughSingleton + { + private static Asn1Bridge INSTANCE = new Asn1BridgeForInjectedSigAlgs(); + // ^^^ not final, since we allow to replace the instance via replaceWith + } + + + private Asn1Bridge delegate = null; + + // private = do not allow to call the constructor directly; force using theInstance() + private Asn1BridgeForInjectedSigAlgs() + { + // Here we try to reach the InjectionPoint class in the dependent "tls" package. If it is present, + // we use that class as an implementation for Asn1Bridge. + try + { + Class c = Class.forName("org.bouncycastle.tls.injection.InjectionPoint"); + Method m1 = c.getMethod("theInstance"); + Object o = m1.invoke(c); + + Method m2 = c.getMethod("asn1Bridge"); + Object bridge = m2.invoke(o); + assert bridge instanceof Asn1Bridge; + this.delegate = (Asn1Bridge) bridge; + } catch (Exception e) + { + // keeping the default implementation + } + } + + public synchronized static Asn1Bridge theInstance() + { + return Asn1BridgeForInjectedSigAlgs.BillPughSingleton.INSTANCE; + } + + public synchronized static void replaceWith(Asn1Bridge newInstance) + { + Asn1BridgeForInjectedSigAlgs.BillPughSingleton.INSTANCE = newInstance; + } + + @Override + public boolean isSupportedAlgorithm(ASN1ObjectIdentifier oid) + { + if (delegate != null) + { + return delegate.isSupportedAlgorithm(oid); + } + else + { + return false; + } + } + + + @Override + public boolean isSupportedParameter(AsymmetricKeyParameter bcKey) + { + if (delegate != null) + { + return delegate.isSupportedParameter(bcKey); + } + else + { + return false; + } + } + + @Override + public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo asnPrivateKey) throws IOException + { + if (delegate != null) + { + return delegate.createPrivateKeyParameter(asnPrivateKey); + } + else + { + throw new IOException("No injected signature algorithms to choose from."); + } + } + + @Override + public PrivateKeyInfo createPrivateKeyInfo( + AsymmetricKeyParameter bcPrivateKey, + ASN1Set attributes) throws IOException + { + if (delegate != null) + { + return delegate.createPrivateKeyInfo(bcPrivateKey, attributes); + } + else + { + throw new IOException("No injected signature algorithms to choose from."); + } + } + + @Override + public AsymmetricKeyParameter createPublicKeyParameter( + SubjectPublicKeyInfo ansPublicKey, + Object defaultParams) throws IOException + { + if (delegate != null) + { + return delegate.createPublicKeyParameter(ansPublicKey, defaultParams); + } + else + { + throw new IOException("No injected signature algorithms to choose from."); + } + } + + @Override + public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter bcPublicKey) throws IOException + { + if (delegate != null) + { + return delegate.createSubjectPublicKeyInfo(bcPublicKey); + } + else + { + throw new IOException("No injected signature algorithms to choose from."); + } + } +} diff --git a/core/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java b/core/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java deleted file mode 100644 index f768a92c3c..0000000000 --- a/core/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.bouncycastle.tls.injection; - -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Set; -import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.crypto.params.AsymmetricKeyParameter; -import org.bouncycastle.tls.SignatureAndHashAlgorithm; -import org.bouncycastle.tls.crypto.TlsSigner; -import org.bouncycastle.tls.crypto.TlsVerifier; -import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; -import org.bouncycastle.tls.injection.sigalgs.*; - -import java.io.IOException; -import java.security.*; -import java.util.*; - -public class InjectableSigAlgs { - - private final List orderedSigs; - private final Map code2sig; - private final Map oid2sig; - private final InjectedSigners signers; - private final InjectedSigVerifiers verifiers; - - public InjectableSigAlgs() { - this.orderedSigs = new LinkedList<>(); - this.code2sig = new HashMap<>(); - this.oid2sig = new HashMap<>(); - this.signers = new InjectedSigners(); - this.verifiers = new InjectedSigVerifiers(); - } - - InjectableSigAlgs(InjectableSigAlgs origin) { // clone constructor - this.orderedSigs = new LinkedList<>(origin.orderedSigs); - this.code2sig = new HashMap<>(origin.code2sig); - this.oid2sig = new HashMap<>(origin.oid2sig); - this.signers = new InjectedSigners(origin.signers); - this.verifiers = new InjectedSigVerifiers(origin.verifiers); - } - - public void add(String name, - ASN1ObjectIdentifier oid, - int signatureSchemeCodePoint, - SigAlgAPI api) { - InjectedSigAlgorithm newAlg = new InjectedSigAlgorithm(name, oid, signatureSchemeCodePoint, api); - orderedSigs.add(newAlg); - code2sig.put(signatureSchemeCodePoint, newAlg); - oid2sig.put(oid.toString(), newAlg); - signers.add(name, api::sign); - verifiers.add(signatureSchemeCodePoint, api::verifySignature, api::internalEncoding); - } - - public boolean contain(int codePoint) { - return code2sig.containsKey(codePoint); - } - - public boolean contain(SignatureAndHashAlgorithm signatureAndHashAlgorithm) { - int codePoint = SignatureAndHashAlgorithmFactory.codePointFromSignatureAndHashAlgorithm(signatureAndHashAlgorithm); - return code2sig.containsKey(codePoint); - } - - public boolean contain(ASN1ObjectIdentifier oid) { - for (InjectedSigAlgorithm sigAlgorithm : orderedSigs) { - if (oid.equals(sigAlgorithm.oid())) - return true; - } - return false; - } - - public Collection asSigAndHashCollection() { - return orderedSigs.stream().map(InjectedSigAlgorithm::signatureAndHashAlgorithm).toList(); - } - - public Collection asCodePointCollection() { - return orderedSigs.stream().map(InjectedSigAlgorithm::codePoint).toList(); - } - - public Collection asSigAlgCollection() { - return orderedSigs; - } - - public Iterable names() { - return signers.getNames(); - } - - ///// for BC TLS - - public Asn1Bridge asn1Bridge() { - return new Asn1Bridge() { - @Override - public boolean isSupportedParameter(AsymmetricKeyParameter bcKey) { - for (InjectedSigAlgorithm sigAlg : orderedSigs) { - if (sigAlg.isSupportedParameter(bcKey)) - return true; - } - return false; - } - - @Override - public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo asnPrivateKey) throws IOException { - AlgorithmIdentifier algId = asnPrivateKey.getPrivateKeyAlgorithm(); - ASN1ObjectIdentifier algOID = algId.getAlgorithm(); - String algKey = algOID.toString(); - return oid2sig.get(algKey).createPrivateKeyParameter(asnPrivateKey); - } - - @Override - public PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter bcPrivateKey, ASN1Set attributes) throws IOException { - for (InjectedSigAlgorithm sigAlg : orderedSigs) { - if (sigAlg.isSupportedParameter(bcPrivateKey)) - return sigAlg.createPrivateKeyInfo(bcPrivateKey, attributes); - } - throw new RuntimeException("Unsupported private key params were given"); - } - - @Override - public AsymmetricKeyParameter createPublicKeyParameter(SubjectPublicKeyInfo ansPublicKey, Object defaultParams) throws IOException { - AlgorithmIdentifier algId = ansPublicKey.getAlgorithm(); - ASN1ObjectIdentifier algOID = algId.getAlgorithm(); - String algKey = algOID.toString(); - return oid2sig.get(algKey).createPublicKeyParameter(ansPublicKey, defaultParams); - } - - @Override - public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter bcPublicKey) throws IOException { - for (InjectedSigAlgorithm sigAlg : orderedSigs) { - if (sigAlg.isSupportedParameter(bcPublicKey)) - return sigAlg.createSubjectPublicKeyInfo(bcPublicKey); - } - throw new RuntimeException("Unsupported public key params were given"); - } - }; - } - - ; - - public MyTls13Verifier tls13VerifierFor(PublicKey key) throws InvalidKeyException { - SignatureSpi spi = signatureSpiFor(key); - - - return new MyTls13Verifier(key, spi); - } - - public TlsVerifier tlsVerifierFor(JcaTlsCrypto crypto, PublicKey publicKey, int sigSchemeCodePoint) { - return verifiers.tlsVerifier(crypto, publicKey, sigSchemeCodePoint); - } - - public TlsSigner tlsSignerFor(JcaTlsCrypto crypto, PrivateKey privateKey) { - return signers.tlsSigner(crypto, privateKey); - } - - public SignatureSpi signatureSpiFor(Key publicOrPrivateKey) throws InvalidKeyException { - SignatureSpi result = null; - for (InjectedSigAlgorithm sigAlg : orderedSigs) { - try { - result = sigAlg.signatureSpi(publicOrPrivateKey); - } catch (Exception e) { - // SignatureSpi could not been created with this factory, continue with the next one - } - if (result != null) - break; - } - - if (result == null) { - throw new InvalidKeyException("No known SignatureSpi for the passed public key of type " + publicOrPrivateKey.getClass().getName()); - } - - return result; - } - -} diff --git a/core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java similarity index 91% rename from core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java rename to tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java index e16bc9a2da..63ee09a27e 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java @@ -4,6 +4,8 @@ import org.bouncycastle.tls.injection.kems.KemFactory; import org.bouncycastle.tls.injection.sigalgs.SigAlgAPI; +import java.util.Collection; + public class InjectableAlgorithms { ///// KEMs @@ -49,11 +51,12 @@ public InjectableAlgorithms withoutDefaultKEMs() { } public InjectableAlgorithms withSigAlg(String name, + Collection aliases, ASN1ObjectIdentifier oid, int signatureSchemeCodePoint, SigAlgAPI api) { InjectableAlgorithms clone = new InjectableAlgorithms(this); - clone.sigAlgs().add(name, oid, signatureSchemeCodePoint, api); + clone.sigAlgs().add(name, aliases, oid, signatureSchemeCodePoint, api); return clone; } diff --git a/core/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java rename to tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java new file mode 100644 index 0000000000..16ae6f5013 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java @@ -0,0 +1,312 @@ +package org.bouncycastle.tls.injection; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.tls.SignatureAndHashAlgorithm; +import org.bouncycastle.tls.crypto.TlsSigner; +import org.bouncycastle.tls.crypto.TlsVerifier; +import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.injection.sigalgs.*; + +import java.io.IOException; +import java.security.*; +import java.util.*; + +public class InjectableSigAlgs +{ + + private final List orderedSigs; + private final Map code2sig; + private final Map oid2sig; + private final InjectedSigners signers; + private final InjectedSigVerifiers verifiers; + + public InjectableSigAlgs() + { + this.orderedSigs = new LinkedList<>(); + this.code2sig = new HashMap<>(); + this.oid2sig = new HashMap<>(); + this.signers = new InjectedSigners(); + this.verifiers = new InjectedSigVerifiers(); + } + + InjectableSigAlgs(InjectableSigAlgs origin) + { // clone constructor + this.orderedSigs = new LinkedList<>(origin.orderedSigs); + this.code2sig = new HashMap<>(origin.code2sig); + this.oid2sig = new HashMap<>(origin.oid2sig); + this.signers = new InjectedSigners(origin.signers); + this.verifiers = new InjectedSigVerifiers(origin.verifiers); + } + + public void add( + String algorithmFullName, + Collection aliases, + ASN1ObjectIdentifier oid, + int signatureSchemeCodePoint, + SigAlgAPI api) + { + InjectedSigAlgorithm newAlg = new InjectedSigAlgorithm(algorithmFullName, aliases, oid, signatureSchemeCodePoint, api); + orderedSigs.add(newAlg); + code2sig.put(signatureSchemeCodePoint, newAlg); + oid2sig.put(oid.toString(), newAlg); + signers.add(algorithmFullName, api::sign); + verifiers.add(signatureSchemeCodePoint, api::verifySignature, api::internalEncodingFor); + } + + public boolean contain(int codePoint) + { + return code2sig.containsKey(codePoint); + } + + public boolean contain(SignatureAndHashAlgorithm signatureAndHashAlgorithm) + { + int codePoint = SignatureAndHashAlgorithmFactory.codePointFromSignatureAndHashAlgorithm(signatureAndHashAlgorithm); + return code2sig.containsKey(codePoint); + } + + public boolean contain(ASN1ObjectIdentifier oid) + { + for (InjectedSigAlgorithm sigAlgorithm : orderedSigs) + { + if (oid.equals(sigAlgorithm.oid())) + { + return true; + } + } + return false; + } + + public Collection asSigAndHashCollection() + { + return orderedSigs.stream().map(InjectedSigAlgorithm::signatureAndHashAlgorithm).toList(); + } + + public Collection asCodePointCollection() + { + return orderedSigs.stream().map(InjectedSigAlgorithm::codePoint).toList(); + } + + public Collection asSigAlgCollection() + { + return orderedSigs; + } + + public Iterable names() + { + return signers.getNames(); + } + + ///// for BC TLS + + public boolean isSupportedPublicKey(Key someKey) + { + for (InjectedSigAlgorithm sigAlg : orderedSigs) + if (sigAlg.isSupportedPublicKey(someKey)) + { + return true; + } + + return false; + } + + public boolean isSupportedPrivateKey(Key someKey) + { + for (InjectedSigAlgorithm sigAlg : orderedSigs) + if (sigAlg.isSupportedPrivateKey(someKey)) + { + return true; + } + + return false; + } + + public byte[] internalEncodingFor(PublicKey publicKey) + { + for (InjectedSigAlgorithm sigAlg : orderedSigs) + if (sigAlg.isSupportedPublicKey(publicKey)) + { + return sigAlg.internalEncodingFor(publicKey); + } + throw new RuntimeException("Public key is not supported."); + } + + public byte[] internalEncodingFor(PrivateKey privateKey) + { + for (InjectedSigAlgorithm sigAlg : orderedSigs) + if (sigAlg.isSupportedPrivateKey(privateKey)) + { + return sigAlg.internalEncodingFor(privateKey); + } + throw new RuntimeException("Private key is not supported."); + } + + public PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) + throws IOException + { + ASN1ObjectIdentifier algOid = keyInfo.getAlgorithm().getAlgorithm(); + for (InjectedSigAlgorithm sigAlg : orderedSigs) + if (sigAlg.oid().equals(algOid)) + { + return sigAlg.converter().generatePublic(keyInfo); + } + + throw new RuntimeException("Public key generation for the algorithm " + algOid + " is not supported."); + } + + public PrivateKey generatePrivate(PrivateKeyInfo keyInfo) + throws IOException + { + ASN1ObjectIdentifier algOid = keyInfo.getPrivateKeyAlgorithm().getAlgorithm(); + for (InjectedSigAlgorithm sigAlg : orderedSigs) + if (sigAlg.oid().equals(algOid)) + { + return sigAlg.converter().generatePrivate(keyInfo); + } + + throw new RuntimeException("Private key generation for the algorithm " + algOid + " is not supported."); + } + + + + public Asn1Bridge asn1Bridge() + { + return new Asn1Bridge() + { + @Override + public boolean isSupportedParameter(AsymmetricKeyParameter bcKey) + { + for (InjectedSigAlgorithm sigAlg : orderedSigs) + { + if (sigAlg.isSupportedParameter(bcKey)) + { + return true; + } + } + return false; + } + + @Override + public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo asnPrivateKey) throws IOException + { + AlgorithmIdentifier algId = asnPrivateKey.getPrivateKeyAlgorithm(); + ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + String algKey = algOID.toString(); + return oid2sig.get(algKey).createPrivateKeyParameter(asnPrivateKey); + } + + @Override + public PrivateKeyInfo createPrivateKeyInfo( + AsymmetricKeyParameter bcPrivateKey, + ASN1Set attributes) throws IOException + { + for (InjectedSigAlgorithm sigAlg : orderedSigs) + { + if (sigAlg.isSupportedParameter(bcPrivateKey)) + { + return sigAlg.createPrivateKeyInfo(bcPrivateKey, attributes); + } + } + throw new RuntimeException("Unsupported private key params were given"); + } + + @Override + public AsymmetricKeyParameter createPublicKeyParameter( + SubjectPublicKeyInfo ansPublicKey, + Object defaultParams) throws IOException + { + AlgorithmIdentifier algId = ansPublicKey.getAlgorithm(); + ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + String algKey = algOID.toString(); + return oid2sig.get(algKey).createPublicKeyParameter(ansPublicKey, defaultParams); + } + + @Override + public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter bcPublicKey) throws IOException + { + for (InjectedSigAlgorithm sigAlg : orderedSigs) + { + if (sigAlg.isSupportedParameter(bcPublicKey)) + { + return sigAlg.createSubjectPublicKeyInfo(bcPublicKey); + } + } + throw new RuntimeException("Unsupported public key params were given"); + } + }; + } + + ; + + public MyTls13Verifier tls13VerifierFor(PublicKey key) throws InvalidKeyException + { + SignatureSpi spi = signatureSpiFor(key); + + + return new MyTls13Verifier(key, spi); + } + + public TlsVerifier tlsVerifierFor( + JcaTlsCrypto crypto, + PublicKey publicKey, + int sigSchemeCodePoint) + { + return verifiers.tlsVerifier(crypto, publicKey, sigSchemeCodePoint); + } + + public TlsSigner tlsSignerFor( + JcaTlsCrypto crypto, + PrivateKey privateKey) + { + for (InjectedSigAlgorithm sigAlg : orderedSigs) + { + SignatureSpi result = null; + try + { + result = sigAlg.signatureSpi(privateKey); + } catch (Exception e) + { + // SignatureSpi could not been created with this factory, continue with the next one + } + if (result != null) + { + // found some sigAlg that can handle our privateKey; + // use sigAlg.name() to obtain the signer + return signers.tlsSigner(crypto, privateKey, sigAlg.name()); + } + } + throw new RuntimeException("Private key with algorithm " + privateKey.getAlgorithm() + " is not supported" + + "(perhaps, with these particular parameters)."); + } + + public SignatureSpi signatureSpiFor(Key publicOrPrivateKey) throws InvalidKeyException + { + SignatureSpi result = null; + for (InjectedSigAlgorithm sigAlg : orderedSigs) + { + try + { + result = sigAlg.signatureSpi(publicOrPrivateKey); + } catch (Exception e) + { + // SignatureSpi could not been created with this factory, continue with the next one + } + if (result != null) + { + break; + } + } + + if (result == null) + { + throw new InvalidKeyException("No known SignatureSpi for the passed public key of type " + publicOrPrivateKey.getClass().getName()); + } + + return result; + } + +} diff --git a/core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java similarity index 60% rename from core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java rename to tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java index 8ef73618a5..0a1a44e706 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java @@ -4,25 +4,33 @@ import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; import org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider; import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; +import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider; import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgorithm; +import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgsProvider; +import java.security.Security; +import java.util.Collection; import java.util.Stack; -public class InjectionPoint { +public class InjectionPoint +{ private final Stack injectionStack; // Bill Pugh Singleton Implementation, see https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/ - private static class BillPughSingleton { + private static class BillPughSingleton + { private static final InjectionPoint INSTANCE = new InjectionPoint(); } // private = do not allow to call the constructor directly; force using _new - private InjectionPoint() { + private InjectionPoint() + { this.injectionStack = new Stack<>(); } - public static InjectionPoint _new() { + public static InjectionPoint theInstance() + { return BillPughSingleton.INSTANCE; } @@ -34,11 +42,23 @@ public static InjectionPoint _new() { * In this case, use pushAfter() to be able to push the new algorithms instead of the previous. * Alternatively, use pop() to withdraw all previously injected algorithms and push() the new set of algorithms. */ - public synchronized void push(InjectableAlgorithms newAlgorithms) throws IllegalStateException { + public synchronized void push(InjectableAlgorithms newAlgorithms) throws IllegalStateException + { if (!injectionStack.isEmpty()) + { throw new IllegalStateException("Some other algorithms have been already injected (pushed)."); + } injectionStack.push(newAlgorithms); + + // Inserting forcefully (to the second place) the BC TLS provider + // and (to the first place) our provider for injected signature algorithms: + + BouncyCastleJsseProvider jsseProvider = new BouncyCastleJsseProvider(); + Security.insertProviderAt(jsseProvider, 1); + + InjectedSigAlgsProvider injProvider = new InjectedSigAlgsProvider(); + Security.insertProviderAt(injProvider, 1); } /** @@ -50,24 +70,37 @@ public synchronized void push(InjectableAlgorithms newAlgorithms) throws Illegal * @throws IllegalStateException if the previously injected algorithms do not match the " previous" argument. * In this case, use pop() to withdraw all previously injected algorithms and push() the new set of algorithms. */ - public synchronized void pushAfter(InjectableAlgorithms newAlgorithms, InjectableAlgorithms previous) throws IllegalStateException { + public synchronized void pushAfter( + InjectableAlgorithms newAlgorithms, + InjectableAlgorithms previous) throws IllegalStateException + { if (injectionStack.isEmpty()) + { throw new IllegalStateException("No previously injected (pushed) algorithms found."); + } if (!injectionStack.peek().equals(previous)) + { throw new IllegalStateException("The previously injected (pushed) algorithms do not match the previous argument."); + } injectionStack.push(newAlgorithms); } /** * Withdraws (pops) the current set of algorithms and restores the previously injected algorithms (if any). + * * @param current the currently used injected algorithms (act as a key to withdraw) * @throws IllegalStateException if no InjectableAlgorithms have been pushed */ - public synchronized void pop(InjectableAlgorithms current) throws IllegalStateException { + public synchronized void pop(InjectableAlgorithms current) throws IllegalStateException + { if (injectionStack.isEmpty()) + { throw new IllegalStateException("No previously injected (pushed) algorithms found."); + } if (!injectionStack.peek().equals(current)) + { throw new IllegalStateException("The currently used injected (pushed) algorithms do not match the current argument."); + } injectionStack.pop(); } @@ -77,68 +110,118 @@ public synchronized void pop(InjectableAlgorithms current) throws IllegalStateEx private static InjectableKEMs dummyKems = new InjectableKEMs(); private static InjectableSigAlgs dummySigAlgs = new InjectableSigAlgs(); - public static InjectableKEMs kems() { + public static InjectableKEMs kems() + { InjectableAlgorithms algs = BillPughSingleton.INSTANCE.injectionStack.peek(); if (algs == null) + { return dummyKems; + } return algs.kems(); } - public static InjectableSigAlgs sigAlgs() { + public static InjectableSigAlgs sigAlgs() + { InjectableAlgorithms algs = BillPughSingleton.INSTANCE.injectionStack.peek(); if (algs == null) + { return dummySigAlgs; + } return algs.sigAlgs(); } - public synchronized static void configureProvider(ConfigurableProvider provider) { + public synchronized static void configureProvider(ConfigurableProvider provider) + { // TODO: call not only from BouncyCastlePQCProvider, but also from JSSE? InjectableAlgorithms algs = BillPughSingleton.INSTANCE.injectionStack.peek(); - for (InjectedSigAlgorithm alg : sigAlgs().asSigAlgCollection()) { + for (InjectedSigAlgorithm alg : sigAlgs().asSigAlgCollection()) + { - new Registrar(alg.oid(), alg.name(), alg.converter()).configure(provider); + new SigAlgRegistrar(alg.oid(), alg.name(), alg.aliases(), alg.converter()).configure(provider); } } - private static class Registrar extends AsymmetricAlgorithmProvider { + private static class SigAlgRegistrar + extends AsymmetricAlgorithmProvider + { private final ASN1ObjectIdentifier oid; private final String name; + private final Collection aliases; private final AsymmetricKeyInfoConverter converter; - public Registrar(ASN1ObjectIdentifier oid, String name, AsymmetricKeyInfoConverter converter) { + public SigAlgRegistrar( + ASN1ObjectIdentifier oid, + String name, + Collection aliases, + AsymmetricKeyInfoConverter converter) + { super(); this.oid = oid; this.name = name; + this.aliases = aliases; this.converter = converter; } @Override - public void configure(ConfigurableProvider provider) { - try { + public void configure(ConfigurableProvider provider) + { + try + { provider.addAlgorithm("Alg.Alias.Signature." + this.oid, this.name); provider.addAlgorithm("Alg.Alias.Signature.OID." + this.oid, this.name); - } catch (IllegalStateException e) { + } catch (IllegalStateException e) + { // ignore, if duplicate (needed for injected RSA) } // remove previous values in order to avoid the duplicate key exception - if (provider instanceof java.security.Provider) { + if (provider instanceof java.security.Provider) + { java.security.Provider p = (java.security.Provider) provider; p.remove("Signature." + this.name); + for (String alias : this.aliases) + { + p.remove("Signature." + alias); + p.remove("Alg.Alias.Signature." + alias); + } p.remove("Alg.Alias.Signature." + this.oid); p.remove("Alg.Alias.Signature.OID." + this.oid); + + p.remove("Alg.Alias.KeyFactory."+this.oid); + p.remove("Alg.Alias.KeyFactory.OID."+this.oid); + + p.remove("Alg.Alias.KeyPairGenerator."+this.oid); + p.remove("Alg.Alias.KeyPairGenerator.OID."+this.oid); } // = provider.addSignatureAlgorithm(provider, "SPHINCSPLUS", PREFIX + "SignatureSpi$Direct", BCObjectIdentifiers.sphincsPlus); provider.addAlgorithm("Signature." + this.name, "org.bouncycastle.tls.injection.signaturespi.DirectSignatureSpi"); provider.addAlgorithm("Alg.Alias.Signature." + this.oid, this.name); provider.addAlgorithm("Alg.Alias.Signature.OID." + this.oid, this.name); + // TO FIX: (NEEDED TO READ THE KEY FILE) OR CREATE SOME UniversalKeyFactorySpi + //provider.addAlgorithm("KeyFactory."+this.name, "org.bouncycastle.pqc.jcajce.provider.sphincsplus.SPHINCSPlusKeyFactorySpi"); + provider.addAlgorithm("KeyFactory."+this.name, "org.bouncycastle.tls.injection.signaturespi.UniversalKeyFactorySpi"); + provider.addAlgorithm("Alg.Alias.KeyFactory."+this.oid, this.name); + provider.addAlgorithm("Alg.Alias.KeyFactory.OID."+this.oid, this.name); + + provider.addAlgorithm("KeyPairGenerator."+this.name, "org.bouncycastle.tls.injection.signaturespi.UniversalKeyPairGeneratorSpi"); + provider.addAlgorithm("Alg.Alias.KeyPairGenerator."+this.oid, this.name); + provider.addAlgorithm("Alg.Alias.KeyPairGenerator.OID."+this.oid, this.name); + + /*for (String alias : this.aliases) { + provider.addAlgorithm("Alg.Alias.Signature." + alias, this.name); + provider.addAlgorithm("Alg.Alias.KeyFactory." + alias, this.name); + provider.addAlgorithm("Alg.Alias.KeyPairGenerator." + alias, this.name); + }*/ + - try { + try + { registerOid(provider, this.oid, this.name, converter); registerOidAlgorithmParameters(provider, this.oid, this.name); - } catch (IllegalStateException e) { + } catch (IllegalStateException e) + { // ignore, if duplicate (needed for injected RSA) } provider.addKeyInfoConverter(this.oid, converter); diff --git a/core/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java rename to tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java similarity index 98% rename from core/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java rename to tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java index bfdc72e31b..36ab71f568 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java @@ -12,7 +12,7 @@ *

* This interface defines the three functions that are present in any KEM. * All keys/secrets/ciphertexts are byte[]-encoded. - * #pqc-tls #injection + * #tls-injection * * @author Sergejs Kozlovics */ diff --git a/core/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java rename to tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java similarity index 99% rename from core/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java rename to tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java index 9f76f8e296..8ac58cff08 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java @@ -10,7 +10,7 @@ /** - * #pqc-tls #injection + * #tls-injection * Wraps a Half-KEM and represents it as a BouncyCastle TlsAgreement. * In the Half-KEM, keyGen() is invoked at the client side, encapsulate() at the server side, * and decapsulate() at the client side. diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java similarity index 56% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java index 0a8f0d02c0..8e7d1a1e5c 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java @@ -10,16 +10,20 @@ import java.io.IOException; import java.security.Key; +import java.security.PrivateKey; import java.security.PublicKey; import java.security.SignatureSpi; +import java.util.Collection; /** - * A class representing injected signature algorithms. #pqc-tls #injection + * A class representing injected signature algorithms. #tls-injection * * @author Sergejs Kozlovics */ -public class InjectedSigAlgorithm { - private final String name; +public class InjectedSigAlgorithm +{ + private final String algorithmFullName; + private final Collection aliases; private final ASN1ObjectIdentifier oid; private final int signatureSchemeCodePoint; private final SignatureAndHashAlgorithm signatureAndHashAlgorithm; @@ -32,62 +36,99 @@ public class InjectedSigAlgorithm { private final SigAlgAPI api; - public InjectedSigAlgorithm(String name, - ASN1ObjectIdentifier oid, - int signatureSchemeCodePoint, - SigAlgAPI api) { - this.name = name; + public InjectedSigAlgorithm( + String algorithmFullName, + Collection aliases, + ASN1ObjectIdentifier oid, + int signatureSchemeCodePoint, + SigAlgAPI api) + { + this.algorithmFullName = algorithmFullName; + this.aliases = aliases; this.oid = oid; this.signatureSchemeCodePoint = signatureSchemeCodePoint; this.signatureAndHashAlgorithm = SignatureAndHashAlgorithmFactory.newFromCodePoint(signatureSchemeCodePoint); this.api = api; } - public String name() { - return this.name; + public String name() + { + return this.algorithmFullName; } - public ASN1ObjectIdentifier oid() { + public Collection aliases() + { + return this.aliases; + } + + public ASN1ObjectIdentifier oid() + { return this.oid; } - public int codePoint() { + public int codePoint() + { return this.signatureSchemeCodePoint; } - public SignatureAndHashAlgorithm signatureAndHashAlgorithm() { + public SignatureAndHashAlgorithm signatureAndHashAlgorithm() + { return this.signatureAndHashAlgorithm; } - public boolean isSupportedParameter(AsymmetricKeyParameter param) { + public boolean isSupportedParameter(AsymmetricKeyParameter param) + { return this.api.isSupportedParameter(param); } - public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo keyInfo) throws IOException { + public boolean isSupportedPublicKey(Key someKey) { + return this.api.isSupportedPublicKey(someKey); + } + public boolean isSupportedPrivateKey(Key someKey) { + return this.api.isSupportedPrivateKey(someKey); + } + + public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo keyInfo) throws IOException + { return this.api.createPrivateKeyParameter(keyInfo); } - public PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter param, ASN1Set attributes) throws IOException { + public PrivateKeyInfo createPrivateKeyInfo( + AsymmetricKeyParameter param, + ASN1Set attributes) throws IOException + { return this.api.createPrivateKeyInfo(param, attributes); } - public AsymmetricKeyParameter createPublicKeyParameter(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException { + public AsymmetricKeyParameter createPublicKeyParameter( + SubjectPublicKeyInfo keyInfo, + Object defaultParams) throws IOException + { return this.api.createPublicKeyParameter(keyInfo, defaultParams); } - public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException { + public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException + { return this.api.createSubjectPublicKeyInfo(publicKey); } - public AsymmetricKeyInfoConverter converter() { + public AsymmetricKeyInfoConverter converter() + { return this.api; } - public byte[] internalEncodingFor(PublicKey key) { - return this.api.internalEncoding(key); + public byte[] internalEncodingFor(PublicKey key) + { + return this.api.internalEncodingFor(key); + } + + public byte[] internalEncodingFor(PrivateKey key) + { + return this.api.internalEncodingFor(key); } - public SignatureSpi signatureSpi(Key key) { + public SignatureSpi signatureSpi(Key key) + { return this.api.signatureSpi(key); } } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgsProvider.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgsProvider.java new file mode 100644 index 0000000000..e9b67d9b5f --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgsProvider.java @@ -0,0 +1,193 @@ +package org.bouncycastle.tls.injection.sigalgs; + +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivateKey; +import java.security.PrivilegedAction; +import java.security.Provider; +import java.security.PublicKey; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; +import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; +import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; +import org.bouncycastle.tls.injection.InjectionPoint; + +public class InjectedSigAlgsProvider + extends Provider + implements ConfigurableProvider +{ + private static String info = "TLS Injection Mechanism (TLS-IM) Provider for Injected Signature Algorithms"; + + public static String PROVIDER_NAME = "TLS-IM"; + + public static final ProviderConfiguration CONFIGURATION = null; + + + private static final Map keyInfoConverters = new HashMap(); + public InjectedSigAlgsProvider() + { + super(PROVIDER_NAME, 1.0, info); + + AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + InjectionPoint.configureProvider(InjectedSigAlgsProvider.this); + return null; + } + }); + } + + + public void setParameter(String parameterName, Object parameter) + { + synchronized (CONFIGURATION) + { + //((BouncyCastleProviderConfiguration)CONFIGURATION).setParameter(parameterName, parameter); + } + } + + public boolean hasAlgorithm(String type, String name) + { + return containsKey(type + "." + name) || containsKey("Alg.Alias." + type + "." + name); + } + + public void addAlgorithm(String key, String value) + { + if (containsKey(key)) + { + throw new IllegalStateException("duplicate provider key (" + key + ") found"); + } + + put(key, value); + } + + public void addAlgorithm(String key, String value, Map attributes) + { + addAlgorithm(key, value); + addAttributes(key, attributes); + } + + public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className) + { + if (!containsKey(type + "." + className)) + { + throw new IllegalStateException("primary key (" + type + "." + className + ") not found"); + } + + addAlgorithm(type + "." + oid, className); + addAlgorithm(type + ".OID." + oid, className); + } + + public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className, Map attributes) + { + addAlgorithm(type, oid, className); + addAttributes(type + "." + oid, attributes); + addAttributes(type + ".OID." + oid, attributes); + } + + public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter) + { + synchronized (keyInfoConverters) + { + keyInfoConverters.put(oid, keyInfoConverter); + } + } + + public AsymmetricKeyInfoConverter getKeyInfoConverter(ASN1ObjectIdentifier oid) + { + return (AsymmetricKeyInfoConverter)keyInfoConverters.get(oid); + } + + public void addAttributes(String key, Map attributeMap) + { + for (Iterator it = attributeMap.keySet().iterator(); it.hasNext();) + { + String attributeName = (String)it.next(); + String attributeKey = key + " " + attributeName; + if (containsKey(attributeKey)) + { + throw new IllegalStateException("duplicate provider attribute key (" + attributeKey + ") found"); + } + + put(attributeKey, attributeMap.get(attributeName)); + } + } + + private static AsymmetricKeyInfoConverter getAsymmetricKeyInfoConverter(ASN1ObjectIdentifier algorithm) + { + synchronized (keyInfoConverters) + { + return (AsymmetricKeyInfoConverter)keyInfoConverters.get(algorithm); + } + } + + public static PublicKey getPublicKey(SubjectPublicKeyInfo publicKeyInfo) + throws IOException + { + AsymmetricKeyInfoConverter converter = getAsymmetricKeyInfoConverter(publicKeyInfo.getAlgorithm().getAlgorithm()); + + if (converter == null) + { + return null; + } + + return converter.generatePublic(publicKeyInfo); + } + + public static PrivateKey getPrivateKey(PrivateKeyInfo privateKeyInfo) + throws IOException + { + AsymmetricKeyInfoConverter converter = getAsymmetricKeyInfoConverter(privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm()); + + if (converter == null) + { + return null; + } + + return converter.generatePrivate(privateKeyInfo); + } + + static Class loadClass(Class sourceClass, final String className) + { + try + { + ClassLoader loader = sourceClass.getClassLoader(); + if (loader != null) + { + return loader.loadClass(className); + } + else + { + return (Class)AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + try + { + return Class.forName(className); + } + catch (Exception e) + { + // ignore - maybe log? + } + + return null; + } + }); + } + } + catch (ClassNotFoundException e) + { + // ignore - maybe log? + } + + return null; + } +} diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java similarity index 65% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java index 5f7e1bd6d6..9d47a846fd 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java @@ -28,24 +28,26 @@ public InjectedSigners(InjectedSigners origin) { // clone this.injectedSigners = new HashMap<>(origin.injectedSigners); } - public void add(String algorithmName, SignerFunction fn) { - injectedSigners.put(algorithmName, fn); + public void add(String algorithmFullName, SignerFunction fn) { + injectedSigners.put(algorithmFullName, fn); } - public boolean contain(String name) { - return injectedSigners.containsKey(name); + public boolean contain(String algorithmFullName) { + return injectedSigners.containsKey(algorithmFullName); } public Iterable getNames() { return injectedSigners.keySet(); } - public TlsSigner tlsSigner(JcaTlsCrypto crypto, PrivateKey privateKey) { - String algorithm = privateKey.getAlgorithm(); + public TlsSigner tlsSigner(JcaTlsCrypto crypto, PrivateKey privateKey, String algorithmFullName) { + // privateKey.getAlgorithm() returns some generinc name, e.g., "DSA" or "SPHINCS+" + // however, we assume that the full algorithm name (with params) has been registered with the signer function; + // thus, we require algorithmFullName to be passed as an argument - Object fn = injectedSigners.get(algorithm); + Object fn = injectedSigners.get(algorithmFullName); if (fn == null) - throw new RuntimeException("Algorithm " + algorithm + " not found among signers."); + throw new RuntimeException("Algorithm " + algorithmFullName + " not found among signers."); byte[] sk = privateKey.getEncoded(); PrivateKeyInfo info = PrivateKeyInfo.getInstance(sk); diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java similarity index 82% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java index 98cbd27259..698ac0cb5a 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java @@ -68,4 +68,18 @@ public final boolean verifySignature(byte[] signature) throws IOException } } + public static boolean isPresentInCallStack() { + Exception e = new Exception(); + + StackTraceElement[] stack = e.getStackTrace(); + + // ignore the top of the stack since it will always be MyTls13Verifier + for (int i=1; i< stack.length; i++) { + StackTraceElement call = stack[i]; + if (call.getClassName().equals(MyTls13Verifier.class.getName())) + return true; + } + return false; + } + } diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java similarity index 91% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java index 12b86f5cf2..476c00c78f 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java @@ -7,6 +7,7 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; import org.bouncycastle.tls.DigitallySigned; import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; +import org.bouncycastle.tls.injection.Asn1Bridge; import java.io.IOException; import java.security.Key; @@ -14,7 +15,9 @@ import java.security.PublicKey; import java.security.SignatureSpi; -public interface SigAlgAPI extends AsymmetricKeyInfoConverter, Asn1Bridge { +public interface SigAlgAPI extends AsymmetricKeyInfoConverter, + Asn1Bridge +{ ///// BC <-> ASN.1 converters ///// @@ -28,6 +31,9 @@ public interface SigAlgAPI extends AsymmetricKeyInfoConverter, Asn1Bridge { */ boolean isSupportedParameter(AsymmetricKeyParameter bcKey); + boolean isSupportedPublicKey(Key key); + boolean isSupportedPrivateKey(Key key); + /** * Converts the given private key from ASN.1 to the internal BC representation. * @@ -77,7 +83,8 @@ PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) throws IOException; ///// Encodings ///// - byte[] internalEncoding(PublicKey key); + byte[] internalEncodingFor(PublicKey key); + byte[] internalEncodingFor(PrivateKey key); ///// sign & verify ///// byte[] sign(JcaTlsCrypto crypto, byte[] message, byte[] privateKey) diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java diff --git a/core/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java similarity index 98% rename from core/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java rename to tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java index 3a72cebcb8..f2ace5c99a 100644 --- a/core/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/DirectSignatureSpi.java @@ -18,7 +18,7 @@ * some factory returns a valid SignatureSpi. Then this SignatureSpi is used as a delegate * to which SignatureSpi method invocations are forwarded (via Java reflection due to protected method declarations). * - * #pqc-tls #injection + * #tls-injection * * @author Sergejs Kozlovics */ @@ -28,7 +28,7 @@ public class DirectSignatureSpi extends java.security.SignatureSpi private java.security.SignatureSpi delegate = null; // will be initialized in engineInitVerify - public DirectSignatureSpi() + public DirectSignatureSpi() // must be no-arg constructor, full class name is used within the provider { } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyFactorySpi.java b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyFactorySpi.java new file mode 100644 index 0000000000..31df686418 --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyFactorySpi.java @@ -0,0 +1,120 @@ +package org.bouncycastle.tls.injection.signaturespi; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactorySpi; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; +import org.bouncycastle.tls.injection.InjectionPoint; + +public class UniversalKeyFactorySpi + extends KeyFactorySpi + implements AsymmetricKeyInfoConverter +{ + public UniversalKeyFactorySpi() { // must be no-arg constructor, full class name is used within the provider + } + + public PrivateKey engineGeneratePrivate(KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof PKCS8EncodedKeySpec) + { + // get the DER-encoded Key according to PKCS#8 from the spec + byte[] encKey = ((PKCS8EncodedKeySpec)keySpec).getEncoded(); + + try + { + return generatePrivate(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(encKey))); + } + catch (Exception e) + { + throw new InvalidKeySpecException(e.toString()); + } + } + + throw new InvalidKeySpecException("Unsupported key specification: " + + keySpec.getClass() + "."); + } + + public PublicKey engineGeneratePublic(KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof X509EncodedKeySpec) + { + // get the DER-encoded Key according to X.509 from the spec + byte[] encKey = ((X509EncodedKeySpec)keySpec).getEncoded(); + + // decode the SubjectPublicKeyInfo data structure to the pki object + try + { + return generatePublic(SubjectPublicKeyInfo.getInstance(encKey)); + } + catch (Exception e) + { + throw new InvalidKeySpecException(e.toString()); + } + } + + throw new InvalidKeySpecException("Unknown key specification: " + keySpec + "."); + } + + public final KeySpec engineGetKeySpec(Key someKey, Class keySpec) + throws InvalidKeySpecException + { + if (InjectionPoint.sigAlgs().isSupportedPrivateKey(someKey)) + { + if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)) + { + return new PKCS8EncodedKeySpec(someKey.getEncoded()); + } + } + else if (InjectionPoint.sigAlgs().isSupportedPublicKey(someKey)) + { + if (X509EncodedKeySpec.class.isAssignableFrom(keySpec)) + { + return new X509EncodedKeySpec(someKey.getEncoded()); + } + } + else + { + throw new InvalidKeySpecException("Unsupported key type: " + + someKey.getClass() + "."); + } + + throw new InvalidKeySpecException("Unknown key specification: " + + keySpec + "."); + } + + public final Key engineTranslateKey(Key someKey) + throws InvalidKeyException + { + if (InjectionPoint.sigAlgs().isSupportedPublicKey(someKey) || InjectionPoint.sigAlgs().isSupportedPrivateKey(someKey)) + { + return someKey; + } + + throw new InvalidKeyException("Unsupported key type: "+someKey.getClass()+"."); + } + + public PrivateKey generatePrivate(PrivateKeyInfo keyInfo) + throws IOException + { + return InjectionPoint.sigAlgs().generatePrivate(keyInfo); + } + + public PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) + throws IOException + { + return InjectionPoint.sigAlgs().generatePublic(keyInfo); + } +} diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyPairGeneratorSpi.java b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyPairGeneratorSpi.java new file mode 100644 index 0000000000..0333db012f --- /dev/null +++ b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyPairGeneratorSpi.java @@ -0,0 +1,72 @@ +package org.bouncycastle.tls.injection.signaturespi; + + +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.util.HashMap; +import java.util.Map; + +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.CryptoServicesRegistrar; +import org.bouncycastle.crypto.engines.RSAEngine; +import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusKeyGenerationParameters; +import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusKeyPairGenerator; +import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusParameters; +import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusPrivateKeyParameters; +import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusPublicKeyParameters; +import org.bouncycastle.pqc.jcajce.provider.util.SpecUtil; +import org.bouncycastle.pqc.jcajce.spec.SPHINCSPlusParameterSpec; +import org.bouncycastle.util.Strings; + +public class UniversalKeyPairGeneratorSpi + extends java.security.KeyPairGenerator +{ + + SecureRandom random = CryptoServicesRegistrar.getSecureRandom(); + boolean initialised = false; + + RSAEngine engine; + + public UniversalKeyPairGeneratorSpi() + { + super("TLS INJECTION MECHANISM SIGNATURE ALGORITHMS"); + this.engine = new RSAEngine(); + } + + public void initialize( + int strength, + SecureRandom random) + { + throw new IllegalArgumentException("use AlgorithmParameterSpec"); + } + + public void initialize( + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException + { + int x=5; + } + + public KeyPair generateKeyPair() + { + if (!initialised) + { + //param = new SPHINCSPlusKeyGenerationParameters(random, SPHINCSPlusParameters.sha2_256s); + + //engine.init(param); + initialised = true; + } + + /*engine. + AsymmetricCipherKeyPair pair = engine.generateKeyPair(); + SPHINCSPlusPublicKeyParameters pub = (SPHINCSPlusPublicKeyParameters)pair.getPublic(); + SPHINCSPlusPrivateKeyParameters priv = (SPHINCSPlusPrivateKeyParameters)pair.getPrivate(); + + return new KeyPair(new BCSPHINCSPlusPublicKey(pub), new BCSPHINCSPlusPrivateKey(priv));*/ + return null; + } + +} diff --git a/core/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java similarity index 100% rename from core/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java rename to tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalSignatureSpi.java From 48792c78bfe156efc73c7f97b81dc4030720f27b Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Fri, 19 Apr 2024 22:11:16 +0300 Subject: [PATCH 16/23] refactored TLS Injection Mechanism; moved it to the tls package --- .../crypto/impl/jcajce/JcaTlsCertificate.java | 13 +++ .../tls/crypto/impl/jcajce/JcaTlsCrypto.java | 16 +-- .../tls/injection/InjectableAlgorithms.java | 46 +++++--- .../tls/injection/InjectableKEMs.java | 89 ++++++++++++---- .../tls/injection/InjectableSigAlgs.java | 79 ++------------ .../tls/injection/InjectionPoint.java | 100 ++++++++++++++++-- .../tls/injection/kems/InjectedKEM.java | 34 ++++-- .../bouncycastle/tls/injection/kems/KEM.java | 9 +- .../tls/injection/kems/KemFactory.java | 3 +- .../injection/kems/TlsAgreementForKEM.java | 59 ++++++++--- .../sigalgs/CipherParametersToEncodedKey.java | 3 +- .../sigalgs/InjectedSigAlgorithm.java | 7 +- .../sigalgs/InjectedSigAlgsProvider.java | 57 ++++++---- .../sigalgs/InjectedSigVerifiers.java | 78 ++++++++++---- .../injection/sigalgs/InjectedSigners.java | 34 ++++-- .../injection/sigalgs/MyMessageSigner.java | 34 ++++-- .../tls/injection/sigalgs/MyStreamSigner.java | 22 ++-- .../injection/sigalgs/MyTls13Verifier.java | 35 ++++-- .../tls/injection/sigalgs/MyTlsSigner.java | 25 +++-- .../sigalgs/PrivateKeyToCipherParameters.java | 3 +- .../sigalgs/PublicKeyToCipherParameters.java | 3 +- .../sigalgs/PublicKeyToEncodedKey.java | 3 +- .../tls/injection/sigalgs/SigAlgAPI.java | 26 +++-- .../SignatureAndHashAlgorithmFactory.java | 9 +- .../tls/injection/sigalgs/SignerFunction.java | 8 +- .../injection/sigalgs/VerifierFunction.java | 8 +- 26 files changed, 550 insertions(+), 253 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java index 836edc32b9..2d005b1d66 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java @@ -192,6 +192,18 @@ public Tls13Verifier createVerifier(int signatureScheme) throws IOException { validateKeyUsageBit(KU_DIGITAL_SIGNATURE); + // #tls-injection + if (InjectionPoint.sigAlgs().contain(signatureScheme)) { + + try { + return InjectionPoint.sigAlgs().tls13VerifierFor(getPublicKey()); + } catch (InvalidKeyException e) { + throw new TlsFatalAlert(AlertDescription.certificate_unknown); + } + + + } + switch (signatureScheme) { case SignatureScheme.ecdsa_brainpoolP256r1tls13_sha256: @@ -258,6 +270,7 @@ public Tls13Verifier createVerifier(int signatureScheme) throws IOException int cryptoHashAlgorithm = SignatureScheme.getCryptoHashAlgorithm(signatureScheme); String digestName = crypto.getDigestName(cryptoHashAlgorithm); String sigName = org.bouncycastle.tls.crypto.impl.jcajce.RSAUtil.getDigestSigAlgName(digestName) + //+"WITHRSA";//+ + "WITHRSAANDMGF1"; // NOTE: We explicitly set them even though they should be the defaults, because providers vary diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java index 7993ca353f..8de4bed3fb 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java @@ -1054,14 +1054,6 @@ protected Tls13Verifier createTls13Verifier(String algorithmName, AlgorithmParam { try { - JcaJceHelper helper = getHelper(); - if (null != parameter) - { - Signature dummyVerifier = helper.createSignature(algorithmName); - dummyVerifier.initVerify(publicKey); - helper = new ProviderJcaJceHelper(dummyVerifier.getProvider()); - } - // #tls-injection // try injected verifier... try { @@ -1070,6 +1062,14 @@ protected Tls13Verifier createTls13Verifier(String algorithmName, AlgorithmParam // e.g., not injected, continue as usual } + JcaJceHelper helper = getHelper(); + if (null != parameter) + { + Signature dummyVerifier = helper.createSignature(algorithmName); + dummyVerifier.initVerify(publicKey); + helper = new ProviderJcaJceHelper(dummyVerifier.getProvider()); + } + Signature verifier = helper.createSignature(algorithmName); if (null != parameter) { diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java index 63ee09a27e..154f574de4 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableAlgorithms.java @@ -6,65 +6,81 @@ import java.util.Collection; -public class InjectableAlgorithms { +public class InjectableAlgorithms +{ ///// KEMs private final InjectableKEMs kems; private final InjectableSigAlgs sigAlgs; - public InjectableAlgorithms() { + public InjectableAlgorithms() + { this(new InjectableKEMs(), new InjectableSigAlgs()); } - private InjectableAlgorithms(InjectableKEMs kems, InjectableSigAlgs sigAlgs) { + private InjectableAlgorithms( + InjectableKEMs kems, + InjectableSigAlgs sigAlgs) + { this.kems = kems; this.sigAlgs = sigAlgs; } - private InjectableAlgorithms(InjectableAlgorithms origin) { // clone constructor + private InjectableAlgorithms(InjectableAlgorithms origin) + { // clone constructor this.kems = new InjectableKEMs(origin.kems); this.sigAlgs = new InjectableSigAlgs(origin.sigAlgs); } - public InjectableAlgorithms withKEM(String standardName, int kemCodePoint, - KemFactory kemFactory, InjectableKEMs.Ordering ordering) { + public InjectableAlgorithms withKEM( + String standardName, + int kemCodePoint, + KemFactory kemFactory, + InjectableKEMs.Ordering ordering) + { return new InjectableAlgorithms( this.kems.withKEM(kemCodePoint, standardName, kemFactory, ordering), new InjectableSigAlgs(this.sigAlgs) ); } - public InjectableAlgorithms withoutKEM(int kemCodePoint) { + public InjectableAlgorithms withoutKEM(int kemCodePoint) + { return new InjectableAlgorithms( this.kems.withoutKEM(kemCodePoint), this.sigAlgs ); } - public InjectableAlgorithms withoutDefaultKEMs() { + public InjectableAlgorithms withoutDefaultKEMs() + { return new InjectableAlgorithms( this.kems.withoutDefaultKEMs(), this.sigAlgs ); } - public InjectableAlgorithms withSigAlg(String name, - Collection aliases, - ASN1ObjectIdentifier oid, - int signatureSchemeCodePoint, - SigAlgAPI api) { + public InjectableAlgorithms withSigAlg( + String name, + Collection aliases, + ASN1ObjectIdentifier oid, + int signatureSchemeCodePoint, + SigAlgAPI api) + { InjectableAlgorithms clone = new InjectableAlgorithms(this); clone.sigAlgs().add(name, aliases, oid, signatureSchemeCodePoint, api); return clone; } - public InjectableKEMs kems() { + public InjectableKEMs kems() + { return this.kems; } - public InjectableSigAlgs sigAlgs() { + public InjectableSigAlgs sigAlgs() + { return this.sigAlgs; } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java index 47ad2137f0..c1dba62068 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableKEMs.java @@ -5,8 +5,12 @@ import java.util.*; -public class InjectableKEMs { - public enum Ordering { BEFORE, AFTER }; +public class InjectableKEMs +{ + public enum Ordering + {BEFORE, AFTER} + + ; ///// KEMs private final List kemsBefore; @@ -14,7 +18,8 @@ public enum Ordering { BEFORE, AFTER }; private final List kemsAfter; private final Map code2kem; - public InjectableKEMs() { + public InjectableKEMs() + { this.kemsBefore = new LinkedList<>(); this.useDefaultKems = true; this.kemsAfter = new LinkedList<>(); @@ -22,95 +27,137 @@ public InjectableKEMs() { } - InjectableKEMs(InjectableKEMs origin) { // clone constructor + InjectableKEMs(InjectableKEMs origin) + { // clone constructor this(origin, origin.useDefaultKems); } - private InjectableKEMs(InjectableKEMs origin, boolean useDefaultKems) { // clone constructor + + private InjectableKEMs( + InjectableKEMs origin, + boolean useDefaultKems) + { // clone constructor this.kemsBefore = new LinkedList<>(origin.kemsBefore); this.useDefaultKems = useDefaultKems; this.kemsAfter = new LinkedList<>(origin.kemsAfter); this.code2kem = new HashMap<>(origin.code2kem); } - public InjectableKEMs withKEM(int kemCodePoint, - String standardName, KemFactory kemFactory, Ordering ordering) { + public InjectableKEMs withKEM( + int kemCodePoint, + String standardName, + KemFactory kemFactory, + Ordering ordering) + { if (code2kem.containsKey(kemCodePoint)) - throw new RuntimeException("KEM code point "+kemCodePoint+" already exists."); + { + throw new RuntimeException("KEM code point " + kemCodePoint + " already exists."); + } InjectedKEM kem = new InjectedKEM(kemCodePoint, standardName, kemFactory); InjectableKEMs clone = new InjectableKEMs(this); clone.code2kem.put(kemCodePoint, kem); if (ordering == Ordering.BEFORE) - clone.kemsBefore.add(0,kemCodePoint); // adding BEFORE all + { + clone.kemsBefore.add(0, kemCodePoint); // adding BEFORE all + } else + { clone.kemsAfter.add(kemCodePoint); + } return clone; } - public InjectableKEMs withoutKEM(int kemCodePoint) { + public InjectableKEMs withoutKEM(int kemCodePoint) + { if (!code2kem.containsKey(kemCodePoint)) - throw new RuntimeException("KEM code point "+kemCodePoint+" does not exist."); + { + throw new RuntimeException("KEM code point " + kemCodePoint + " does not exist."); + } InjectableKEMs clone = new InjectableKEMs(this); clone.code2kem.remove(kemCodePoint); int i = clone.kemsBefore.indexOf(kemCodePoint); - if (i>=0) + if (i >= 0) + { clone.kemsBefore.remove(i); + } i = clone.kemsAfter.indexOf(kemCodePoint); - if (i>=0) + if (i >= 0) + { clone.kemsAfter.remove(i); + } return clone; } - public InjectableKEMs withoutDefaultKEMs() { + public InjectableKEMs withoutDefaultKEMs() + { return new InjectableKEMs(this, false); } - public boolean contain(int codePoint) { + public boolean contain(int codePoint) + { return code2kem.containsKey(codePoint); } - public InjectedKEM kemByCodePoint(int codePoint) { + public InjectedKEM kemByCodePoint(int codePoint) + { return code2kem.get(codePoint); } - public Collection kemsByOrdering(Ordering ordering) { + public Collection kemsByOrdering(Ordering ordering) + { if (ordering == Ordering.BEFORE) + { return kemsBefore.stream().map(code2kem::get).toList(); + } else + { return kemsAfter.stream().map(code2kem::get).toList(); + } } - public Collection asCodePointCollection(Ordering ordering) { + public Collection asCodePointCollection(Ordering ordering) + { if (ordering == Ordering.BEFORE) + { return new LinkedList<>(kemsBefore); + } else + { return new LinkedList<>(kemsAfter); + } } - public Collection asCodePointCollection() { + public Collection asCodePointCollection() + { List result = new LinkedList<>(kemsBefore); result.addAll(kemsAfter); return result; } - public boolean defaultKemsNeeded() { + public boolean defaultKemsNeeded() + { return useDefaultKems; } - public InjectedKEM firstKEM() { + public InjectedKEM firstKEM() + { Collection kems = kemsByOrdering(InjectableKEMs.Ordering.BEFORE); if (!kems.isEmpty()) + { return kems.iterator().next(); + } kems = kemsByOrdering(InjectableKEMs.Ordering.AFTER); if (!kems.isEmpty()) + { return kems.iterator().next(); + } throw new IllegalStateException("No KEM injected"); } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java index 16ae6f5013..e5cbe2601d 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectableSigAlgs.java @@ -1,11 +1,8 @@ package org.bouncycastle.tls.injection; import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Set; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.tls.SignatureAndHashAlgorithm; import org.bouncycastle.tls.crypto.TlsSigner; import org.bouncycastle.tls.crypto.TlsVerifier; @@ -101,6 +98,12 @@ public Iterable names() return signers.getNames(); } + public InjectedSigAlgorithm byOid(ASN1ObjectIdentifier oid) + { + String algKey = oid.toString(); + return oid2sig.get(algKey); + } + ///// for BC TLS public boolean isSupportedPublicKey(Key someKey) @@ -172,76 +175,6 @@ public PrivateKey generatePrivate(PrivateKeyInfo keyInfo) } - - public Asn1Bridge asn1Bridge() - { - return new Asn1Bridge() - { - @Override - public boolean isSupportedParameter(AsymmetricKeyParameter bcKey) - { - for (InjectedSigAlgorithm sigAlg : orderedSigs) - { - if (sigAlg.isSupportedParameter(bcKey)) - { - return true; - } - } - return false; - } - - @Override - public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo asnPrivateKey) throws IOException - { - AlgorithmIdentifier algId = asnPrivateKey.getPrivateKeyAlgorithm(); - ASN1ObjectIdentifier algOID = algId.getAlgorithm(); - String algKey = algOID.toString(); - return oid2sig.get(algKey).createPrivateKeyParameter(asnPrivateKey); - } - - @Override - public PrivateKeyInfo createPrivateKeyInfo( - AsymmetricKeyParameter bcPrivateKey, - ASN1Set attributes) throws IOException - { - for (InjectedSigAlgorithm sigAlg : orderedSigs) - { - if (sigAlg.isSupportedParameter(bcPrivateKey)) - { - return sigAlg.createPrivateKeyInfo(bcPrivateKey, attributes); - } - } - throw new RuntimeException("Unsupported private key params were given"); - } - - @Override - public AsymmetricKeyParameter createPublicKeyParameter( - SubjectPublicKeyInfo ansPublicKey, - Object defaultParams) throws IOException - { - AlgorithmIdentifier algId = ansPublicKey.getAlgorithm(); - ASN1ObjectIdentifier algOID = algId.getAlgorithm(); - String algKey = algOID.toString(); - return oid2sig.get(algKey).createPublicKeyParameter(ansPublicKey, defaultParams); - } - - @Override - public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter bcPublicKey) throws IOException - { - for (InjectedSigAlgorithm sigAlg : orderedSigs) - { - if (sigAlg.isSupportedParameter(bcPublicKey)) - { - return sigAlg.createSubjectPublicKeyInfo(bcPublicKey); - } - } - throw new RuntimeException("Unsupported public key params were given"); - } - }; - } - - ; - public MyTls13Verifier tls13VerifierFor(PublicKey key) throws InvalidKeyException { SignatureSpi spi = signatureSpiFor(key); diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java index 0a1a44e706..1152888f1a 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java @@ -1,6 +1,11 @@ package org.bouncycastle.tls.injection; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; import org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider; import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; @@ -8,6 +13,7 @@ import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgorithm; import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgsProvider; +import java.io.IOException; import java.security.Security; import java.util.Collection; import java.util.Stack; @@ -188,11 +194,11 @@ public void configure(ConfigurableProvider provider) p.remove("Alg.Alias.Signature." + this.oid); p.remove("Alg.Alias.Signature.OID." + this.oid); - p.remove("Alg.Alias.KeyFactory."+this.oid); - p.remove("Alg.Alias.KeyFactory.OID."+this.oid); + p.remove("Alg.Alias.KeyFactory." + this.oid); + p.remove("Alg.Alias.KeyFactory.OID." + this.oid); - p.remove("Alg.Alias.KeyPairGenerator."+this.oid); - p.remove("Alg.Alias.KeyPairGenerator.OID."+this.oid); + p.remove("Alg.Alias.KeyPairGenerator." + this.oid); + p.remove("Alg.Alias.KeyPairGenerator.OID." + this.oid); } // = provider.addSignatureAlgorithm(provider, "SPHINCSPLUS", PREFIX + "SignatureSpi$Direct", BCObjectIdentifiers.sphincsPlus); provider.addAlgorithm("Signature." + this.name, "org.bouncycastle.tls.injection.signaturespi.DirectSignatureSpi"); @@ -201,13 +207,13 @@ public void configure(ConfigurableProvider provider) // TO FIX: (NEEDED TO READ THE KEY FILE) OR CREATE SOME UniversalKeyFactorySpi //provider.addAlgorithm("KeyFactory."+this.name, "org.bouncycastle.pqc.jcajce.provider.sphincsplus.SPHINCSPlusKeyFactorySpi"); - provider.addAlgorithm("KeyFactory."+this.name, "org.bouncycastle.tls.injection.signaturespi.UniversalKeyFactorySpi"); - provider.addAlgorithm("Alg.Alias.KeyFactory."+this.oid, this.name); - provider.addAlgorithm("Alg.Alias.KeyFactory.OID."+this.oid, this.name); + provider.addAlgorithm("KeyFactory." + this.name, "org.bouncycastle.tls.injection.signaturespi.UniversalKeyFactorySpi"); + provider.addAlgorithm("Alg.Alias.KeyFactory." + this.oid, this.name); + provider.addAlgorithm("Alg.Alias.KeyFactory.OID." + this.oid, this.name); - provider.addAlgorithm("KeyPairGenerator."+this.name, "org.bouncycastle.tls.injection.signaturespi.UniversalKeyPairGeneratorSpi"); - provider.addAlgorithm("Alg.Alias.KeyPairGenerator."+this.oid, this.name); - provider.addAlgorithm("Alg.Alias.KeyPairGenerator.OID."+this.oid, this.name); + provider.addAlgorithm("KeyPairGenerator." + this.name, "org.bouncycastle.tls.injection.signaturespi.UniversalKeyPairGeneratorSpi"); + provider.addAlgorithm("Alg.Alias.KeyPairGenerator." + this.oid, this.name); + provider.addAlgorithm("Alg.Alias.KeyPairGenerator.OID." + this.oid, this.name); /*for (String alias : this.aliases) { provider.addAlgorithm("Alg.Alias.Signature." + alias, this.name); @@ -228,4 +234,78 @@ public void configure(ConfigurableProvider provider) } } + public Asn1Bridge asn1Bridge() + { + return new Asn1Bridge() + { + @Override + public boolean isSupportedAlgorithm(ASN1ObjectIdentifier oid) + { + return sigAlgs().contain(oid); + } + + @Override + public boolean isSupportedParameter(AsymmetricKeyParameter bcKey) + { + for (InjectedSigAlgorithm sigAlg : sigAlgs().asSigAlgCollection()) + { + if (sigAlg.isSupportedParameter(bcKey)) + { + return true; + } + } + return false; + } + + @Override + public AsymmetricKeyParameter createPrivateKeyParameter(PrivateKeyInfo asnPrivateKey) throws IOException + { + AlgorithmIdentifier algId = asnPrivateKey.getPrivateKeyAlgorithm(); + ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + return sigAlgs().byOid(algOID).createPrivateKeyParameter(asnPrivateKey); + } + + @Override + public PrivateKeyInfo createPrivateKeyInfo( + AsymmetricKeyParameter bcPrivateKey, + ASN1Set attributes) throws IOException + { + for (InjectedSigAlgorithm sigAlg : sigAlgs().asSigAlgCollection()) + { + if (sigAlg.isSupportedParameter(bcPrivateKey)) + { + return sigAlg.createPrivateKeyInfo(bcPrivateKey, attributes); + } + } + throw new RuntimeException("Unsupported private key params were given"); + } + + @Override + public AsymmetricKeyParameter createPublicKeyParameter( + SubjectPublicKeyInfo ansPublicKey, + Object defaultParams) throws IOException + { + AlgorithmIdentifier algId = ansPublicKey.getAlgorithm(); + ASN1ObjectIdentifier algOID = algId.getAlgorithm(); + String algKey = algOID.toString(); + return sigAlgs().byOid(algOID).createPublicKeyParameter(ansPublicKey, defaultParams); + } + + @Override + public SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter bcPublicKey) throws IOException + { + for (InjectedSigAlgorithm sigAlg : sigAlgs().asSigAlgCollection()) + { + if (sigAlg.isSupportedParameter(bcPublicKey)) + { + return sigAlg.createSubjectPublicKeyInfo(bcPublicKey); + } + } + throw new RuntimeException("Unsupported public key params were given"); + } + }; + } + + ; + } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java index 9db48029c0..5ad65acbd1 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/InjectedKEM.java @@ -10,39 +10,55 @@ * * @author Sergejs Kozlovics */ -public class InjectedKEM { +public class InjectedKEM +{ - public interface TlsAgreementFactory { - TlsAgreement create(JcaTlsCrypto crypto, boolean isServer); + public interface TlsAgreementFactory + { + TlsAgreement create( + JcaTlsCrypto crypto, + boolean isServer); } private final int codePoint; private final String standardName; private final TlsAgreementFactory tlsAgreementFactory; - public InjectedKEM(int kemCodePoint, - String standardName, KemFactory kemFactory) { + public InjectedKEM( + int kemCodePoint, + String standardName, + KemFactory kemFactory) + { this(kemCodePoint, standardName, (crypto, isServer) -> new TlsAgreementForKEM(crypto, isServer, kemFactory.create())); } - public InjectedKEM(int codePoint, String standardName, TlsAgreementFactory tlsAgreementFactory) { + public InjectedKEM( + int codePoint, + String standardName, + TlsAgreementFactory tlsAgreementFactory) + { this.codePoint = codePoint; this.standardName = standardName; this.tlsAgreementFactory = tlsAgreementFactory; } - public int codePoint() { + public int codePoint() + { return this.codePoint; } - public String standardName() { + public String standardName() + { return this.standardName; } - public TlsAgreement tlsAgreement(JcaTlsCrypto crypto, boolean isServer) { + public TlsAgreement tlsAgreement( + JcaTlsCrypto crypto, + boolean isServer) + { return this.tlsAgreementFactory.create(crypto, isServer); } } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java index 36ab71f568..f0184f7ed1 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KEM.java @@ -6,6 +6,8 @@ * A KEM (key encapsulation mechanism) is a set of functions that can be used to obtain * a symmetric encryption key from asymmetric keys. * The term KEM is a generalisation of Diffie-Hellman key exchange. + * The KEM abstraction can also be used to obtain quantumly exchanged keys via QKD + * (a KEM then needs to exchange only key IDs) *

* The three KEM functions actually define a half-KEM: keyGen() and decapsulate() are called at one side (e.g., the client), * while encapsulate() is called at the other side (e.g., the server). @@ -16,7 +18,8 @@ * * @author Sergejs Kozlovics */ -public interface KEM { +public interface KEM +{ /** * Generates a new key pair (pk, sk). * @@ -39,5 +42,7 @@ public interface KEM { * @param ciphertext the ciphertext * @return the shared secret K */ - byte[] decapsulate(byte[] secretKey, byte[] ciphertext) throws Exception; + byte[] decapsulate( + byte[] secretKey, + byte[] ciphertext) throws Exception; } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java index b9bd7ddf3c..9f9174a3c4 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/KemFactory.java @@ -1,5 +1,6 @@ package org.bouncycastle.tls.injection.kems; -public interface KemFactory { +public interface KemFactory +{ KEM create(); } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java index 8ac58cff08..d3f642d60f 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java @@ -17,7 +17,9 @@ * * @author Sergejs Kozlovics */ -public class TlsAgreementForKEM implements TlsAgreement { +public class TlsAgreementForKEM + implements TlsAgreement +{ private JcaTlsCrypto crypto; private boolean isServer; private KEM kem; // delegate @@ -28,7 +30,11 @@ public class TlsAgreementForKEM implements TlsAgreement { protected byte[] clientSecretKey; protected byte[] serverSecret; - public TlsAgreementForKEM(JcaTlsCrypto crypto, boolean isServer, KEM kem) { + public TlsAgreementForKEM( + JcaTlsCrypto crypto, + boolean isServer, + KEM kem) + { this.crypto = crypto; this.isServer = isServer; this.kem = kem; @@ -37,60 +43,83 @@ public TlsAgreementForKEM(JcaTlsCrypto crypto, boolean isServer, KEM kem) { this.serverSecret = null; } - public byte[] generateEphemeral() throws IOException { + public byte[] generateEphemeral() throws IOException + { Pair p; - try { + try + { p = kem.keyGen(); - } catch (Exception e) { + } catch (Exception e) + { throw new RuntimeException(e); } byte[] pk = p.getLeft(); byte[] sk = p.getRight(); - if (isServer) { + if (isServer) + { // Half-KEM Step2: client <--- peerEncapsulated ciphertext <--- server if (this.peerEncapsulated == null) + { throw new IOException("receivePeerValue must be called before generateEphemeral for KEMs"); + } Pair p2; - try { + try + { p = kem.encapsulate(this.peerEncapsulated); // peerEncapsulated === client public key - } catch (Exception e) { + } catch (Exception e) + { throw new RuntimeException(e); } this.serverSecret = p.getLeft(); // server secret return p.getRight(); - } else { + } + else + { // Half-KEM Step1: client ---> generated pk ---> server this.clientSecretKey = sk; return pk; } } - public void receivePeerValue(byte[] peerEncapsulated) throws IOException { + public void receivePeerValue(byte[] peerEncapsulated) throws IOException + { this.peerEncapsulated = peerEncapsulated; } - public TlsSecret calculateSecret() throws IOException { + public TlsSecret calculateSecret() throws IOException + { - if (isServer) { + if (isServer) + { if (this.serverSecret == null) + { throw new IOException("Server-side secret has not been generated: generateEphemeral must be called before calculateSecret"); + } return new JceTlsSecret(this.crypto, this.serverSecret); - } else { + } + else + { if (this.clientSecretKey == null) + { throw new IOException("Client-side key pair has not been generated: generateEphemeral must be called before calculateSecret"); + } if (this.peerEncapsulated == null) + { throw new IOException("receivePeerValue must be called before calculateSecret for KEMs"); + } - try { + try + { // Half-KEM Step3: decapsulate at the client byte[] receivedSecret = kem.decapsulate(this.clientSecretKey, this.peerEncapsulated); return new JceTlsSecret(this.crypto, receivedSecret); - } catch (Exception e) { + } catch (Exception e) + { throw new RuntimeException(e); } } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java index 38772971a8..14de679e90 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java @@ -2,6 +2,7 @@ import org.bouncycastle.crypto.CipherParameters; -public interface CipherParametersToEncodedKey { +public interface CipherParametersToEncodedKey +{ byte[] encodedKey(CipherParameters params); } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java index 8e7d1a1e5c..fcb0fd6a7c 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgorithm.java @@ -81,10 +81,13 @@ public boolean isSupportedParameter(AsymmetricKeyParameter param) return this.api.isSupportedParameter(param); } - public boolean isSupportedPublicKey(Key someKey) { + public boolean isSupportedPublicKey(Key someKey) + { return this.api.isSupportedPublicKey(someKey); } - public boolean isSupportedPrivateKey(Key someKey) { + + public boolean isSupportedPrivateKey(Key someKey) + { return this.api.isSupportedPrivateKey(someKey); } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgsProvider.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgsProvider.java index e9b67d9b5f..34f928cdb9 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgsProvider.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigAlgsProvider.java @@ -30,6 +30,7 @@ public class InjectedSigAlgsProvider private static final Map keyInfoConverters = new HashMap(); + public InjectedSigAlgsProvider() { super(PROVIDER_NAME, 1.0, info); @@ -45,7 +46,9 @@ public Object run() } - public void setParameter(String parameterName, Object parameter) + public void setParameter( + String parameterName, + Object parameter) { synchronized (CONFIGURATION) { @@ -53,12 +56,16 @@ public void setParameter(String parameterName, Object parameter) } } - public boolean hasAlgorithm(String type, String name) + public boolean hasAlgorithm( + String type, + String name) { return containsKey(type + "." + name) || containsKey("Alg.Alias." + type + "." + name); } - public void addAlgorithm(String key, String value) + public void addAlgorithm( + String key, + String value) { if (containsKey(key)) { @@ -68,13 +75,19 @@ public void addAlgorithm(String key, String value) put(key, value); } - public void addAlgorithm(String key, String value, Map attributes) + public void addAlgorithm( + String key, + String value, + Map attributes) { addAlgorithm(key, value); addAttributes(key, attributes); } - public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className) + public void addAlgorithm( + String type, + ASN1ObjectIdentifier oid, + String className) { if (!containsKey(type + "." + className)) { @@ -85,14 +98,20 @@ public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String classNam addAlgorithm(type + ".OID." + oid, className); } - public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className, Map attributes) + public void addAlgorithm( + String type, + ASN1ObjectIdentifier oid, + String className, + Map attributes) { addAlgorithm(type, oid, className); addAttributes(type + "." + oid, attributes); addAttributes(type + ".OID." + oid, attributes); } - public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter) + public void addKeyInfoConverter( + ASN1ObjectIdentifier oid, + AsymmetricKeyInfoConverter keyInfoConverter) { synchronized (keyInfoConverters) { @@ -102,14 +121,16 @@ public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConve public AsymmetricKeyInfoConverter getKeyInfoConverter(ASN1ObjectIdentifier oid) { - return (AsymmetricKeyInfoConverter)keyInfoConverters.get(oid); + return (AsymmetricKeyInfoConverter) keyInfoConverters.get(oid); } - public void addAttributes(String key, Map attributeMap) + public void addAttributes( + String key, + Map attributeMap) { - for (Iterator it = attributeMap.keySet().iterator(); it.hasNext();) + for (Iterator it = attributeMap.keySet().iterator(); it.hasNext(); ) { - String attributeName = (String)it.next(); + String attributeName = (String) it.next(); String attributeKey = key + " " + attributeName; if (containsKey(attributeKey)) { @@ -124,7 +145,7 @@ private static AsymmetricKeyInfoConverter getAsymmetricKeyInfoConverter(ASN1Obje { synchronized (keyInfoConverters) { - return (AsymmetricKeyInfoConverter)keyInfoConverters.get(algorithm); + return (AsymmetricKeyInfoConverter) keyInfoConverters.get(algorithm); } } @@ -154,7 +175,9 @@ public static PrivateKey getPrivateKey(PrivateKeyInfo privateKeyInfo) return converter.generatePrivate(privateKeyInfo); } - static Class loadClass(Class sourceClass, final String className) + static Class loadClass( + Class sourceClass, + final String className) { try { @@ -165,15 +188,14 @@ static Class loadClass(Class sourceClass, final String className) } else { - return (Class)AccessController.doPrivileged(new PrivilegedAction() + return (Class) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { return Class.forName(className); - } - catch (Exception e) + } catch (Exception e) { // ignore - maybe log? } @@ -182,8 +204,7 @@ public Object run() } }); } - } - catch (ClassNotFoundException e) + } catch (ClassNotFoundException e) { // ignore - maybe log? } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java index 2ab41a5d6a..88f4a1250c 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java @@ -20,35 +20,51 @@ * * @author Sergejs Kozlovics */ -public class InjectedSigVerifiers { - - public interface VerifySignatureFunction { - boolean verifySignature(byte[] data, byte[] key, DigitallySigned signature); +public class InjectedSigVerifiers +{ + + public interface VerifySignatureFunction + { + boolean verifySignature( + byte[] data, + byte[] key, + DigitallySigned signature); } private final Map verifiers; // code point -> verifier fn private final Map converters; // code point -> encoder fn - public InjectedSigVerifiers() { + public InjectedSigVerifiers() + { this.verifiers = new HashMap<>(); this.converters = new HashMap<>(); } - public InjectedSigVerifiers(InjectedSigVerifiers origin) { // clone + public InjectedSigVerifiers(InjectedSigVerifiers origin) + { // clone this.verifiers = new HashMap<>(origin.verifiers); this.converters = new HashMap<>(origin.converters); } - public void add(int sigSchemeCodePoint, VerifySignatureFunction fn, PublicKeyToEncodedKey fn2) { + public void add( + int sigSchemeCodePoint, + VerifySignatureFunction fn, + PublicKeyToEncodedKey fn2) + { verifiers.put(sigSchemeCodePoint, fn); converters.put(sigSchemeCodePoint, fn2); } - public boolean contain(int sigSchemeCodePoint) { + public boolean contain(int sigSchemeCodePoint) + { return verifiers.containsKey(sigSchemeCodePoint); } - public TlsVerifier tlsVerifier(JcaTlsCrypto crypto, PublicKey publicKey, int sigSchemeCodePoint) { + public TlsVerifier tlsVerifier( + JcaTlsCrypto crypto, + PublicKey publicKey, + int sigSchemeCodePoint) + { VerifySignatureFunction fn = verifiers.get(sigSchemeCodePoint); PublicKeyToEncodedKey fn2 = converters.get(sigSchemeCodePoint); @@ -57,21 +73,31 @@ public TlsVerifier tlsVerifier(JcaTlsCrypto crypto, PublicKey publicKey, int sig // implementing TlsVerifier via VerifySignatureFunction private class MyTlsVerifier - implements TlsVerifier { + implements TlsVerifier + { private final JcaTlsCrypto crypto; private final PublicKey publicKey; private final int signatureScheme; private final VerifySignatureFunction fn; private final PublicKeyToEncodedKey fn2; - public MyTlsVerifier(JcaTlsCrypto crypto, PublicKey publicKey, int signatureSchemeCodePoint, VerifySignatureFunction fn, PublicKeyToEncodedKey fn2) { - if (null == crypto) { + public MyTlsVerifier( + JcaTlsCrypto crypto, + PublicKey publicKey, + int signatureSchemeCodePoint, + VerifySignatureFunction fn, + PublicKeyToEncodedKey fn2) + { + if (null == crypto) + { throw new NullPointerException("crypto"); } - if (null == publicKey) { + if (null == publicKey) + { throw new NullPointerException("publicKey"); } - if (!contain(signatureSchemeCodePoint)) { + if (!contain(signatureSchemeCodePoint)) + { throw new IllegalArgumentException("signatureSchemeCodePoint"); } @@ -82,20 +108,29 @@ public MyTlsVerifier(JcaTlsCrypto crypto, PublicKey publicKey, int signatureSche this.fn2 = fn2; } - public boolean verifyRawSignature(DigitallySigned signature, byte[] hash) throws IOException { + public boolean verifyRawSignature( + DigitallySigned signature, + byte[] hash) throws IOException + { byte[] encoded = fn2.encodedKey(publicKey); boolean b = fn.verifySignature(hash, encoded, signature); return b; } - private class MyStreamVerifier implements TlsStreamVerifier { + private class MyStreamVerifier + implements TlsStreamVerifier + { private final PublicKey publicKey; private final DigitallySigned signature; private final ByteArrayOutputStream stream; private final int signatureScheme; - public MyStreamVerifier(PublicKey publicKey, DigitallySigned signature, int signatureScheme) { + public MyStreamVerifier( + PublicKey publicKey, + DigitallySigned signature, + int signatureScheme) + { this.publicKey = publicKey; this.signature = signature; this.stream = new ByteArrayOutputStream(); @@ -103,12 +138,14 @@ public MyStreamVerifier(PublicKey publicKey, DigitallySigned signature, int sign } @Override - public OutputStream getOutputStream() throws IOException { + public OutputStream getOutputStream() throws IOException + { return this.stream; } @Override - public boolean isVerified() throws IOException { + public boolean isVerified() throws IOException + { byte[] data = this.stream.toByteArray(); byte[] key = publicKey.getEncoded(); @@ -145,7 +182,8 @@ public boolean isVerified() throws IOException { } } - public TlsStreamVerifier getStreamVerifier(DigitallySigned signature) throws IOException { + public TlsStreamVerifier getStreamVerifier(DigitallySigned signature) throws IOException + { return new MyStreamVerifier(this.publicKey, signature, this.signatureScheme); } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java index 9d47a846fd..3fb6934ffe 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java @@ -16,46 +16,62 @@ * * @author Sergejs Kozlovics */ -public class InjectedSigners { +public class InjectedSigners +{ private final Map injectedSigners; - public InjectedSigners() { + public InjectedSigners() + { this.injectedSigners = new HashMap<>(); } - public InjectedSigners(InjectedSigners origin) { // clone + public InjectedSigners(InjectedSigners origin) + { // clone this.injectedSigners = new HashMap<>(origin.injectedSigners); } - public void add(String algorithmFullName, SignerFunction fn) { + public void add( + String algorithmFullName, + SignerFunction fn) + { injectedSigners.put(algorithmFullName, fn); } - public boolean contain(String algorithmFullName) { + public boolean contain(String algorithmFullName) + { return injectedSigners.containsKey(algorithmFullName); } - public Iterable getNames() { + public Iterable getNames() + { return injectedSigners.keySet(); } - public TlsSigner tlsSigner(JcaTlsCrypto crypto, PrivateKey privateKey, String algorithmFullName) { + public TlsSigner tlsSigner( + JcaTlsCrypto crypto, + PrivateKey privateKey, + String algorithmFullName) + { // privateKey.getAlgorithm() returns some generinc name, e.g., "DSA" or "SPHINCS+" // however, we assume that the full algorithm name (with params) has been registered with the signer function; // thus, we require algorithmFullName to be passed as an argument Object fn = injectedSigners.get(algorithmFullName); if (fn == null) + { throw new RuntimeException("Algorithm " + algorithmFullName + " not found among signers."); + } byte[] sk = privateKey.getEncoded(); PrivateKeyInfo info = PrivateKeyInfo.getInstance(sk); byte[] sk2; - try { + try + { sk2 = info.getPrivateKey().getEncoded(); - } catch (IOException e) { + } catch (IOException e) + { throw new RuntimeException(e); } return new MyTlsSigner(crypto, sk2, (SignerFunction) fn); diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java index ef7b4a2ae3..8ed112498b 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java @@ -5,7 +5,9 @@ import org.bouncycastle.tls.DigitallySigned; import org.bouncycastle.tls.SignatureAndHashAlgorithm; -public class MyMessageSigner implements MessageSigner { +public class MyMessageSigner + implements MessageSigner +{ private SignatureAndHashAlgorithm algorithm; private SignerFunction fnSign; @@ -15,10 +17,13 @@ public class MyMessageSigner implements MessageSigner { // the following fields are initialized by BC by invoking init(): private CipherParameters params; - public MyMessageSigner(int signatureSchemeCodePoint, - SignerFunction fnSign, VerifierFunction fnVerify, - CipherParametersToEncodedKey paramsToPublicKey, - CipherParametersToEncodedKey paramsToPrivateKey) { + public MyMessageSigner( + int signatureSchemeCodePoint, + SignerFunction fnSign, + VerifierFunction fnVerify, + CipherParametersToEncodedKey paramsToPublicKey, + CipherParametersToEncodedKey paramsToPrivateKey) + { this.algorithm = new SignatureAndHashAlgorithm((short) (signatureSchemeCodePoint >> 8), (short) (signatureSchemeCodePoint & 0xFF)); this.fnSign = fnSign; this.fnVerify = fnVerify; @@ -27,26 +32,35 @@ public MyMessageSigner(int signatureSchemeCodePoint, } @Override - public void init(boolean forSigning, CipherParameters param) { + public void init( + boolean forSigning, + CipherParameters param) + { this.params = param; } @Override - public byte[] generateSignature(byte[] message) { + public byte[] generateSignature(byte[] message) + { byte[] sk = this.paramsToPrivateKey.encodedKey(params); //skParams.getEncoded(); byte[] bcSignature = new byte[0]; - try { + try + { bcSignature = fnSign.sign(null, message, sk); // TODO: do we need to pass crypto instead of null? - } catch (Exception e) { + } catch (Exception e) + { throw new RuntimeException(e); } return bcSignature; } @Override - public boolean verifySignature(byte[] message, byte[] signature) { + public boolean verifySignature( + byte[] message, + byte[] signature) + { byte[] pk = this.paramsToPublicKey.encodedKey(params); return fnVerify.verify(message, pk, new DigitallySigned(algorithm, signature)); } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java index eb585ebe3d..e154ff5cd9 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyStreamSigner.java @@ -7,7 +7,9 @@ import java.io.IOException; import java.io.OutputStream; -public class MyStreamSigner implements TlsStreamSigner { +public class MyStreamSigner + implements TlsStreamSigner +{ private JcaTlsCrypto crypto; @@ -15,24 +17,32 @@ public class MyStreamSigner implements TlsStreamSigner { private byte[] key; private ByteArrayOutputStream os = new ByteArrayOutputStream(); - public MyStreamSigner(JcaTlsCrypto crypto, byte[] key, SignerFunction fn) { + public MyStreamSigner( + JcaTlsCrypto crypto, + byte[] key, + SignerFunction fn) + { this.crypto = crypto; this.fn = fn; this.key = key; } @Override - public OutputStream getOutputStream() throws IOException { + public OutputStream getOutputStream() throws IOException + { return os; } @Override - public byte[] getSignature() throws IOException { + public byte[] getSignature() throws IOException + { byte[] data = os.toByteArray(); byte[] signature = new byte[0]; - try { + try + { signature = fn.sign(this.crypto, data, key); - } catch (Exception e) { + } catch (Exception e) + { throw new IOException(e); } return signature; diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java index 698ac0cb5a..70a426bda5 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTls13Verifier.java @@ -16,23 +16,35 @@ public class MyTls13Verifier private ByteArrayOutputStream os = new ByteArrayOutputStream(); - public MyTls13Verifier(PublicKey publicKey, SignatureSpi verifier) + public MyTls13Verifier( + PublicKey publicKey, + SignatureSpi verifier) { this.publicKey = publicKey; this.verifier = verifier; } - private Method findDirectOrInheritedMethod(Class c, String methodName, Class... args) { + private Method findDirectOrInheritedMethod( + Class c, + String methodName, + Class... args) + { Method m = null; - while (c!=null) { - for (Method mm : c.getDeclaredMethods()) { + while (c != null) + { + for (Method mm : c.getDeclaredMethods()) + { // this is an optimization: we don't check all arg types, just their number // (for SignatureSpi-s that's sufficient) if (mm.getName().equals(methodName) && (args.length == mm.getParameterTypes().length)) + { m = mm; + } } - if (m!=null) + if (m != null) + { break; + } c = c.getSuperclass(); } m.setAccessible(true); @@ -61,23 +73,26 @@ public final boolean verifySignature(byte[] signature) throws IOException Object result = m.invoke(verifier, signature); return (boolean) result; - } - catch (Exception e) + } catch (Exception e) { throw new RuntimeException(e); } } - public static boolean isPresentInCallStack() { - Exception e = new Exception(); + public static boolean isPresentInCallStack() + { + Exception e = new Exception(); StackTraceElement[] stack = e.getStackTrace(); // ignore the top of the stack since it will always be MyTls13Verifier - for (int i=1; i< stack.length; i++) { + for (int i = 1; i < stack.length; i++) + { StackTraceElement call = stack[i]; if (call.getClassName().equals(MyTls13Verifier.class.getName())) + { return true; + } } return false; } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java index e5c33b0431..cf8466b1db 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyTlsSigner.java @@ -7,28 +7,39 @@ import java.io.IOException; -public class MyTlsSigner implements TlsSigner +public class MyTlsSigner + implements TlsSigner { private JcaTlsCrypto crypto; private SignerFunction fn; private byte[] key; - public MyTlsSigner(JcaTlsCrypto crypto, byte[] key, SignerFunction fn) { + public MyTlsSigner( + JcaTlsCrypto crypto, + byte[] key, + SignerFunction fn) + { this.crypto = crypto; this.fn = fn; this.key = key; } - public byte[] generateRawSignature(SignatureAndHashAlgorithm algorithm, byte[] hash) - throws IOException { - try { + public byte[] generateRawSignature( + SignatureAndHashAlgorithm algorithm, + byte[] hash) + throws IOException + { + try + { return this.fn.sign(this.crypto, hash, key); - } catch (Exception e) { + } catch (Exception e) + { throw new IOException(e); } } - public TlsStreamSigner getStreamSigner(SignatureAndHashAlgorithm algorithm) throws IOException { + public TlsStreamSigner getStreamSigner(SignatureAndHashAlgorithm algorithm) throws IOException + { return new MyStreamSigner(this.crypto, key, this.fn); } } \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java index c873cfa2e4..2800deca15 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PrivateKeyToCipherParameters.java @@ -5,6 +5,7 @@ import java.security.InvalidKeyException; import java.security.PrivateKey; -public interface PrivateKeyToCipherParameters { +public interface PrivateKeyToCipherParameters +{ CipherParameters parameters(PrivateKey privateKey) throws InvalidKeyException; } \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java index cd25b1a2a7..facc400034 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToCipherParameters.java @@ -5,6 +5,7 @@ import java.security.InvalidKeyException; import java.security.PublicKey; -public interface PublicKeyToCipherParameters { +public interface PublicKeyToCipherParameters +{ CipherParameters parameters(PublicKey publicKey) throws InvalidKeyException; } \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java index 33d5f76e6e..a30028a3af 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java @@ -2,6 +2,7 @@ import java.security.PublicKey; -public interface PublicKeyToEncodedKey { +public interface PublicKeyToEncodedKey +{ byte[] encodedKey(PublicKey key); } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java index 476c00c78f..bce8df9455 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SigAlgAPI.java @@ -15,8 +15,9 @@ import java.security.PublicKey; import java.security.SignatureSpi; -public interface SigAlgAPI extends AsymmetricKeyInfoConverter, - Asn1Bridge +public interface SigAlgAPI + extends AsymmetricKeyInfoConverter, + Asn1Bridge { ///// BC <-> ASN.1 converters ///// @@ -32,6 +33,7 @@ public interface SigAlgAPI extends AsymmetricKeyInfoConverter, boolean isSupportedParameter(AsymmetricKeyParameter bcKey); boolean isSupportedPublicKey(Key key); + boolean isSupportedPrivateKey(Key key); /** @@ -52,7 +54,9 @@ public interface SigAlgAPI extends AsymmetricKeyInfoConverter, * @return ASN.1 representation of the private key * @throws IOException */ - PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter bcPrivateKey, ASN1Set attributes) throws IOException; + PrivateKeyInfo createPrivateKeyInfo( + AsymmetricKeyParameter bcPrivateKey, + ASN1Set attributes) throws IOException; /** @@ -63,7 +67,9 @@ public interface SigAlgAPI extends AsymmetricKeyInfoConverter, * @return internal BC representation of the public key * @throws IOException */ - AsymmetricKeyParameter createPublicKeyParameter(SubjectPublicKeyInfo ansPublicKey, Object defaultParams) throws IOException; + AsymmetricKeyParameter createPublicKeyParameter( + SubjectPublicKeyInfo ansPublicKey, + Object defaultParams) throws IOException; /** * Converts the given public key from the internal BC representation to the ASN.1 notation. @@ -84,19 +90,27 @@ PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) ///// Encodings ///// byte[] internalEncodingFor(PublicKey key); + byte[] internalEncodingFor(PrivateKey key); ///// sign & verify ///// - byte[] sign(JcaTlsCrypto crypto, byte[] message, byte[] privateKey) + byte[] sign( + JcaTlsCrypto crypto, + byte[] message, + byte[] privateKey) throws IOException, Exception; - boolean verifySignature(byte[] message, byte[] publicKey, DigitallySigned signature); + boolean verifySignature( + byte[] message, + byte[] publicKey, + DigitallySigned signature); ///// SPI ///// /** * Constructs a Java Service Provider Interface (SPI) driver for the current signature algorithm. * This driver will be used by the DirectSignatureSpi of the TLS injection mechanism. + * * @param key a public or a private key * @return a SignatureSpi instance (we suggest using our UniversalSignatureSpi class for that) */ diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java index 3419f6bf7a..f086b1cb2e 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignatureAndHashAlgorithmFactory.java @@ -2,12 +2,15 @@ import org.bouncycastle.tls.SignatureAndHashAlgorithm; -public class SignatureAndHashAlgorithmFactory { - public static SignatureAndHashAlgorithm newFromCodePoint(int signatureSchemeCodePoint) { +public class SignatureAndHashAlgorithmFactory +{ + public static SignatureAndHashAlgorithm newFromCodePoint(int signatureSchemeCodePoint) + { return new SignatureAndHashAlgorithm((short) (signatureSchemeCodePoint >> 8), (short) (signatureSchemeCodePoint & 0xFF)); } - public static int codePointFromSignatureAndHashAlgorithm(SignatureAndHashAlgorithm sigAndHashAlgorithm) { + public static int codePointFromSignatureAndHashAlgorithm(SignatureAndHashAlgorithm sigAndHashAlgorithm) + { int codePoint = (sigAndHashAlgorithm.getHash() << 8) | sigAndHashAlgorithm.getSignature(); return codePoint; } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java index 92bc53a43c..2b43fa8f7c 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/SignerFunction.java @@ -2,6 +2,10 @@ import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto; -public interface SignerFunction { - byte[] sign(JcaTlsCrypto crypto, byte[] data, byte[] key) throws Exception; +public interface SignerFunction +{ + byte[] sign( + JcaTlsCrypto crypto, + byte[] data, + byte[] key) throws Exception; } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java index 60a18de1fe..984c349812 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/VerifierFunction.java @@ -2,6 +2,10 @@ import org.bouncycastle.tls.DigitallySigned; -public interface VerifierFunction { - boolean verify(byte[] message, byte[] publicKey, DigitallySigned signature); +public interface VerifierFunction +{ + boolean verify( + byte[] message, + byte[] publicKey, + DigitallySigned signature); } From 45dd268a4f01ccda7b46650c46e61d6f14fd163e Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Fri, 19 Apr 2024 22:11:36 +0300 Subject: [PATCH 17/23] fixed comments --- .../org/bouncycastle/jsse/provider/ProvX509KeyManager.java | 2 +- .../org/bouncycastle/jsse/provider/SignatureSchemeInfo.java | 4 ++-- tls/src/main/java/org/bouncycastle/tls/TlsUtils.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java b/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java index 5d9df9f442..14700b0bdd 100644 --- a/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java +++ b/tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java @@ -207,7 +207,7 @@ private static Map createFiltersServer() addFilterLegacyServer(filters, ProvAlgorithmChecker.KU_KEY_ENCIPHERMENT, "RSA", KeyExchangeAlgorithm.RSA); // #tls-injection - // adding filters for injected signers (e.g., PQC signers) #pqc-tls #injection + // adding filters for injected signers (e.g., PQC signers) for (String name: InjectionPoint.sigAlgs().names()) { if (!filters.containsKey(name)) addFilter(filters, name); diff --git a/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java b/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java index 4efb593e7b..5e6792bc1b 100644 --- a/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java +++ b/tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java @@ -584,7 +584,7 @@ private static boolean isECDSA(int signatureScheme) //private final All all; // for injection, we cannot use final enum All; we need some dynamic // data structure for storing the corresponding sig scheme info - // #pqc-tls #injection + // #tls-injection private final int signatureScheme; private final String name; private final String text; @@ -607,7 +607,7 @@ private static boolean isECDSA(int signatureScheme) boolean enabled, boolean disabled13) { //this.all = all; - //#pqc-tls #injection: + //#tls-injection: this.signatureScheme = all.signatureScheme; this.name = all.name; this.text = all.text; diff --git a/tls/src/main/java/org/bouncycastle/tls/TlsUtils.java b/tls/src/main/java/org/bouncycastle/tls/TlsUtils.java index 0ff8b5ea08..e7322c2da2 100644 --- a/tls/src/main/java/org/bouncycastle/tls/TlsUtils.java +++ b/tls/src/main/java/org/bouncycastle/tls/TlsUtils.java @@ -5383,7 +5383,7 @@ else if (NamedGroup.refersToASpecificKem(supportedGroup)) if (null != agreement) { - // #pqc-tls #injection (everything remains the same here, if KemAgreement is used as TlsAgreement for KEMs) + // #tls-injection (everything remains the same here, if KemAgreement is used as TlsAgreement for KEMs) byte[] key_exchange = agreement.generateEphemeral(); // key_exchange = ephemeral public key for KEMs KeyShareEntry clientShare = new KeyShareEntry(supportedGroup, key_exchange); From ee644dfaa7d517361b98af840aa506e2ea4c1664 Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Fri, 19 Apr 2024 22:18:03 +0300 Subject: [PATCH 18/23] Removed UniversalKeyPairGenerator, since it is not used by the TLS Injection Mechanism. Besides, UniversalKeyPairGenerator is difficult to implement. --- .../tls/injection/InjectionPoint.java | 13 ++-- .../UniversalKeyPairGeneratorSpi.java | 72 ------------------- 2 files changed, 5 insertions(+), 80 deletions(-) delete mode 100644 tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyPairGeneratorSpi.java diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java index 1152888f1a..a4321953ff 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java @@ -205,21 +205,18 @@ public void configure(ConfigurableProvider provider) provider.addAlgorithm("Alg.Alias.Signature." + this.oid, this.name); provider.addAlgorithm("Alg.Alias.Signature.OID." + this.oid, this.name); - // TO FIX: (NEEDED TO READ THE KEY FILE) OR CREATE SOME UniversalKeyFactorySpi - //provider.addAlgorithm("KeyFactory."+this.name, "org.bouncycastle.pqc.jcajce.provider.sphincsplus.SPHINCSPlusKeyFactorySpi"); provider.addAlgorithm("KeyFactory." + this.name, "org.bouncycastle.tls.injection.signaturespi.UniversalKeyFactorySpi"); provider.addAlgorithm("Alg.Alias.KeyFactory." + this.oid, this.name); provider.addAlgorithm("Alg.Alias.KeyFactory.OID." + this.oid, this.name); + /* Maybe, in the future, we'll implement a universal KeyPairGenerator. + We need to check parameters carefully during the initialization + in order to find out whether the parameters correspond to one of the injected algorithms... + provider.addAlgorithm("KeyPairGenerator." + this.name, "org.bouncycastle.tls.injection.signaturespi.UniversalKeyPairGeneratorSpi"); provider.addAlgorithm("Alg.Alias.KeyPairGenerator." + this.oid, this.name); provider.addAlgorithm("Alg.Alias.KeyPairGenerator.OID." + this.oid, this.name); - - /*for (String alias : this.aliases) { - provider.addAlgorithm("Alg.Alias.Signature." + alias, this.name); - provider.addAlgorithm("Alg.Alias.KeyFactory." + alias, this.name); - provider.addAlgorithm("Alg.Alias.KeyPairGenerator." + alias, this.name); - }*/ + */ try diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyPairGeneratorSpi.java b/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyPairGeneratorSpi.java deleted file mode 100644 index 0333db012f..0000000000 --- a/tls/src/main/java/org/bouncycastle/tls/injection/signaturespi/UniversalKeyPairGeneratorSpi.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.bouncycastle.tls.injection.signaturespi; - - -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyPair; -import java.security.SecureRandom; -import java.security.spec.AlgorithmParameterSpec; -import java.util.HashMap; -import java.util.Map; - -import org.bouncycastle.crypto.AsymmetricCipherKeyPair; -import org.bouncycastle.crypto.CryptoServicesRegistrar; -import org.bouncycastle.crypto.engines.RSAEngine; -import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusKeyGenerationParameters; -import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusKeyPairGenerator; -import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusParameters; -import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusPrivateKeyParameters; -import org.bouncycastle.pqc.crypto.sphincsplus.SPHINCSPlusPublicKeyParameters; -import org.bouncycastle.pqc.jcajce.provider.util.SpecUtil; -import org.bouncycastle.pqc.jcajce.spec.SPHINCSPlusParameterSpec; -import org.bouncycastle.util.Strings; - -public class UniversalKeyPairGeneratorSpi - extends java.security.KeyPairGenerator -{ - - SecureRandom random = CryptoServicesRegistrar.getSecureRandom(); - boolean initialised = false; - - RSAEngine engine; - - public UniversalKeyPairGeneratorSpi() - { - super("TLS INJECTION MECHANISM SIGNATURE ALGORITHMS"); - this.engine = new RSAEngine(); - } - - public void initialize( - int strength, - SecureRandom random) - { - throw new IllegalArgumentException("use AlgorithmParameterSpec"); - } - - public void initialize( - AlgorithmParameterSpec params, - SecureRandom random) - throws InvalidAlgorithmParameterException - { - int x=5; - } - - public KeyPair generateKeyPair() - { - if (!initialised) - { - //param = new SPHINCSPlusKeyGenerationParameters(random, SPHINCSPlusParameters.sha2_256s); - - //engine.init(param); - initialised = true; - } - - /*engine. - AsymmetricCipherKeyPair pair = engine.generateKeyPair(); - SPHINCSPlusPublicKeyParameters pub = (SPHINCSPlusPublicKeyParameters)pair.getPublic(); - SPHINCSPlusPrivateKeyParameters priv = (SPHINCSPlusPrivateKeyParameters)pair.getPrivate(); - - return new KeyPair(new BCSPHINCSPlusPublicKey(pub), new BCSPHINCSPlusPrivateKey(priv));*/ - return null; - } - -} From 57af27a58c1b7d44cda7a2e06a28c67a6d716c57 Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Mon, 3 Jun 2024 15:32:04 +0300 Subject: [PATCH 19/23] renamed variables "*EncodedKey" to "*ByteKey"; add "RSASSA-PSS" as a fallback algorithm for the BC adapter (since WITHRSAANDMGF1 sometimes is not found) --- .../tls/crypto/impl/jcajce/JcaTlsCertificate.java | 10 ++++++++-- .../tls/crypto/impl/jcajce/JcaTlsCrypto.java | 9 ++++++++- .../crypto/impl/jcajce/JcaTlsRSAPSSSigner.java | 9 ++++++++- ...codedKey.java => CipherParametersByteKey.java} | 4 ++-- .../injection/sigalgs/InjectedSigVerifiers.java | 12 ++++++------ .../tls/injection/sigalgs/InjectedSigners.java | 15 ++++----------- .../tls/injection/sigalgs/MyMessageSigner.java | 13 +++++++------ ...yToEncodedKey.java => PublicKeyToByteKey.java} | 4 ++-- 8 files changed, 45 insertions(+), 31 deletions(-) rename tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/{CipherParametersToEncodedKey.java => CipherParametersByteKey.java} (52%) rename tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/{PublicKeyToEncodedKey.java => PublicKeyToByteKey.java} (52%) diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java index 2d005b1d66..bf8cff609b 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCertificate.java @@ -270,14 +270,20 @@ public Tls13Verifier createVerifier(int signatureScheme) throws IOException int cryptoHashAlgorithm = SignatureScheme.getCryptoHashAlgorithm(signatureScheme); String digestName = crypto.getDigestName(cryptoHashAlgorithm); String sigName = org.bouncycastle.tls.crypto.impl.jcajce.RSAUtil.getDigestSigAlgName(digestName) - //+"WITHRSA";//+ + "WITHRSAANDMGF1"; // NOTE: We explicitly set them even though they should be the defaults, because providers vary AlgorithmParameterSpec pssSpec = org.bouncycastle.tls.crypto.impl.jcajce.RSAUtil .getPSSParameterSpec(cryptoHashAlgorithm, digestName, crypto.getHelper()); - return crypto.createTls13Verifier(sigName, pssSpec, getPubKeyRSA()); + try { + return crypto.createTls13Verifier(sigName, pssSpec, getPubKeyRSA()); + } + catch(Exception e) { + // #tls-injection fix: using the sig alg name of the SunRsaSign provider + sigName = "RSASSA-PSS"; + return crypto.createTls13Verifier(sigName, pssSpec, getPubKeyRSA()); + } } // TODO[RFC 8998] diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java index 8de4bed3fb..ec9f09b5f8 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java @@ -492,7 +492,14 @@ public AlgorithmParameters getSignatureSchemeAlgorithmParameters(int signatureSc AlgorithmParameterSpec pssSpec = RSAUtil.getPSSParameterSpec(cryptoHashAlgorithm, digestName, getHelper()); - Signature signer = getHelper().createSignature(sigName); + Signature signer; + try { + signer = getHelper().createSignature(sigName); + } + catch(Exception e) { + signer = Signature.getInstance("RSASSA-PSS", "SunRsaSign"); + // #tls-injection fix: using the sig alg name of the SunRsaSign provider + } // NOTE: We explicitly set them even though they should be the defaults, because providers vary signer.setParameter(pssSpec); diff --git a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsRSAPSSSigner.java b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsRSAPSSSigner.java index 815431fc02..97e09426cb 100644 --- a/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsRSAPSSSigner.java +++ b/tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsRSAPSSSigner.java @@ -85,6 +85,13 @@ public TlsStreamSigner getStreamSigner(SignatureAndHashAlgorithm algorithm) thro AlgorithmParameterSpec pssSpec = RSAUtil.getPSSParameterSpec(cryptoHashAlgorithm, digestName, crypto.getHelper()); - return crypto.createStreamSigner(sigName, pssSpec, privateKey, true); + try { + return crypto.createStreamSigner(sigName, pssSpec, privateKey, true); + } + catch(Exception e) { + // #tls-injection fix: using the sig alg name of the SunRsaSign provider + sigName = "RSASSA-PSS"; + return crypto.createStreamSigner(sigName, pssSpec, privateKey, true); + } } } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersByteKey.java similarity index 52% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersByteKey.java index 14de679e90..e0ece96470 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersToEncodedKey.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/CipherParametersByteKey.java @@ -2,7 +2,7 @@ import org.bouncycastle.crypto.CipherParameters; -public interface CipherParametersToEncodedKey +public interface CipherParametersByteKey { - byte[] encodedKey(CipherParameters params); + byte[] byteKey(CipherParameters params); } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java index 88f4a1250c..26c0726ba7 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigVerifiers.java @@ -32,7 +32,7 @@ boolean verifySignature( } private final Map verifiers; // code point -> verifier fn - private final Map converters; // code point -> encoder fn + private final Map converters; // code point -> encoder fn public InjectedSigVerifiers() { @@ -49,7 +49,7 @@ public InjectedSigVerifiers(InjectedSigVerifiers origin) public void add( int sigSchemeCodePoint, VerifySignatureFunction fn, - PublicKeyToEncodedKey fn2) + PublicKeyToByteKey fn2) { verifiers.put(sigSchemeCodePoint, fn); converters.put(sigSchemeCodePoint, fn2); @@ -66,7 +66,7 @@ public TlsVerifier tlsVerifier( int sigSchemeCodePoint) { VerifySignatureFunction fn = verifiers.get(sigSchemeCodePoint); - PublicKeyToEncodedKey fn2 = converters.get(sigSchemeCodePoint); + PublicKeyToByteKey fn2 = converters.get(sigSchemeCodePoint); return new MyTlsVerifier(crypto, publicKey, sigSchemeCodePoint, fn, fn2); } @@ -79,14 +79,14 @@ private class MyTlsVerifier private final PublicKey publicKey; private final int signatureScheme; private final VerifySignatureFunction fn; - private final PublicKeyToEncodedKey fn2; + private final PublicKeyToByteKey fn2; public MyTlsVerifier( JcaTlsCrypto crypto, PublicKey publicKey, int signatureSchemeCodePoint, VerifySignatureFunction fn, - PublicKeyToEncodedKey fn2) + PublicKeyToByteKey fn2) { if (null == crypto) { @@ -112,7 +112,7 @@ public boolean verifyRawSignature( DigitallySigned signature, byte[] hash) throws IOException { - byte[] encoded = fn2.encodedKey(publicKey); + byte[] encoded = fn2.byteKey(publicKey); boolean b = fn.verifySignature(hash, encoded, signature); return b; } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java index 3fb6934ffe..c3a2d7bccf 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/InjectedSigners.java @@ -63,17 +63,10 @@ public TlsSigner tlsSigner( throw new RuntimeException("Algorithm " + algorithmFullName + " not found among signers."); } - byte[] sk = privateKey.getEncoded(); - PrivateKeyInfo info = PrivateKeyInfo.getInstance(sk); + byte[] skEncoded = privateKey.getEncoded(); + PrivateKeyInfo info = PrivateKeyInfo.getInstance(skEncoded); - byte[] sk2; - try - { - sk2 = info.getPrivateKey().getEncoded(); - } catch (IOException e) - { - throw new RuntimeException(e); - } - return new MyTlsSigner(crypto, sk2, (SignerFunction) fn); + byte[] skBytes = info.getPrivateKey().getOctets(); + return new MyTlsSigner(crypto, skBytes, (SignerFunction) fn); } } diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java index 8ed112498b..9bcbbdc1ab 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/MyMessageSigner.java @@ -12,7 +12,7 @@ public class MyMessageSigner private SignatureAndHashAlgorithm algorithm; private SignerFunction fnSign; private VerifierFunction fnVerify; - private CipherParametersToEncodedKey paramsToPublicKey, paramsToPrivateKey; + private CipherParametersByteKey paramsToPublicKey, paramsToPrivateKey; // the following fields are initialized by BC by invoking init(): private CipherParameters params; @@ -21,8 +21,8 @@ public MyMessageSigner( int signatureSchemeCodePoint, SignerFunction fnSign, VerifierFunction fnVerify, - CipherParametersToEncodedKey paramsToPublicKey, - CipherParametersToEncodedKey paramsToPrivateKey) + CipherParametersByteKey paramsToPublicKey, + CipherParametersByteKey paramsToPrivateKey) { this.algorithm = new SignatureAndHashAlgorithm((short) (signatureSchemeCodePoint >> 8), (short) (signatureSchemeCodePoint & 0xFF)); this.fnSign = fnSign; @@ -43,7 +43,7 @@ public void init( @Override public byte[] generateSignature(byte[] message) { - byte[] sk = this.paramsToPrivateKey.encodedKey(params); //skParams.getEncoded(); + byte[] sk = this.paramsToPrivateKey.byteKey(params); //skParams.getEncoded(); byte[] bcSignature = new byte[0]; try @@ -61,7 +61,8 @@ public boolean verifySignature( byte[] message, byte[] signature) { - byte[] pk = this.paramsToPublicKey.encodedKey(params); - return fnVerify.verify(message, pk, new DigitallySigned(algorithm, signature)); + byte[] pk = this.paramsToPublicKey.byteKey(params); + boolean isValid = fnVerify.verify(message, pk, new DigitallySigned(algorithm, signature)); + return isValid; } } \ No newline at end of file diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToByteKey.java similarity index 52% rename from tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java rename to tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToByteKey.java index a30028a3af..a4da7a0123 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToEncodedKey.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/sigalgs/PublicKeyToByteKey.java @@ -2,7 +2,7 @@ import java.security.PublicKey; -public interface PublicKeyToEncodedKey +public interface PublicKeyToByteKey { - byte[] encodedKey(PublicKey key); + byte[] byteKey(PublicKey key); } From 9a2e253928005163febe122a81a72020b4cd3386 Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Fri, 14 Jun 2024 23:16:43 +0300 Subject: [PATCH 20/23] added .clone() for the shared key, since BC may alter it --- .../bouncycastle/tls/injection/kems/TlsAgreementForKEM.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java index d3f642d60f..66ca7feed4 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java @@ -100,7 +100,7 @@ public TlsSecret calculateSecret() throws IOException { throw new IOException("Server-side secret has not been generated: generateEphemeral must be called before calculateSecret"); } - return new JceTlsSecret(this.crypto, this.serverSecret); + return new JceTlsSecret(this.crypto, this.serverSecret.clone()); // added .clone() since BC may alter the key } else { @@ -117,7 +117,7 @@ public TlsSecret calculateSecret() throws IOException { // Half-KEM Step3: decapsulate at the client byte[] receivedSecret = kem.decapsulate(this.clientSecretKey, this.peerEncapsulated); - return new JceTlsSecret(this.crypto, receivedSecret); + return new JceTlsSecret(this.crypto, receivedSecret.clone()); // added .clone() since BC may alter the key } catch (Exception e) { throw new RuntimeException(e); From 8449c717611cf5dc1e29a75e64b5319b5d6e0ccb Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Sat, 15 Jun 2024 01:31:36 +0300 Subject: [PATCH 21/23] added isEmpty() to InjectionPoint --- .../org/bouncycastle/tls/injection/InjectionPoint.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java index a4321953ff..ea52b1796e 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java @@ -40,6 +40,14 @@ public static InjectionPoint theInstance() return BillPughSingleton.INSTANCE; } + /** + * Checks whether the stack of injected algorithms is empty. + * @return true, iff no InjectableAlgorithms have been pushed (or all have been popped out) + */ + public synchronized boolean isEmpty() { + return injectionStack.isEmpty(); + } + /** * Injects (pushes) the given algorithms into BouncyCastle TLS implementation. * From afb1a442326544c9c6a0f0ed2019509df0b9079c Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Sat, 15 Jun 2024 01:32:28 +0300 Subject: [PATCH 22/23] fixed a bug when KEM keyGen() was unnecessarily invoked at the server side --- .../injection/kems/TlsAgreementForKEM.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java index 66ca7feed4..a067b40b46 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/kems/TlsAgreementForKEM.java @@ -46,17 +46,7 @@ public TlsAgreementForKEM( public byte[] generateEphemeral() throws IOException { - Pair p; - try - { - p = kem.keyGen(); - } catch (Exception e) - { - throw new RuntimeException(e); - } - byte[] pk = p.getLeft(); - byte[] sk = p.getRight(); if (isServer) { @@ -66,7 +56,7 @@ public byte[] generateEphemeral() throws IOException throw new IOException("receivePeerValue must be called before generateEphemeral for KEMs"); } - Pair p2; + Pair p; try { @@ -81,6 +71,17 @@ public byte[] generateEphemeral() throws IOException else { // Half-KEM Step1: client ---> generated pk ---> server + Pair p; + + try + { + p = kem.keyGen(); + } catch (Exception e) + { + throw new RuntimeException(e); + } + byte[] pk = p.getLeft(); + byte[] sk = p.getRight(); this.clientSecretKey = sk; return pk; } From ac2006b569457b413d1522b68c7e362e151099e6 Mon Sep 17 00:00:00 2001 From: Sergejs Kozlovics Date: Tue, 18 Jun 2024 17:23:55 +0300 Subject: [PATCH 23/23] adding the BC provider in InjectionPoint.push --- .../org/bouncycastle/tls/injection/InjectionPoint.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java index ea52b1796e..c0a41f3995 100644 --- a/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java +++ b/tls/src/main/java/org/bouncycastle/tls/injection/InjectionPoint.java @@ -9,11 +9,13 @@ import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; import org.bouncycastle.jcajce.provider.util.AsymmetricAlgorithmProvider; import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider; import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgorithm; import org.bouncycastle.tls.injection.sigalgs.InjectedSigAlgsProvider; import java.io.IOException; +import java.security.Provider; import java.security.Security; import java.util.Collection; import java.util.Stack; @@ -67,12 +69,15 @@ public synchronized void push(InjectableAlgorithms newAlgorithms) throws Illegal // Inserting forcefully (to the second place) the BC TLS provider // and (to the first place) our provider for injected signature algorithms: - BouncyCastleJsseProvider jsseProvider = new BouncyCastleJsseProvider(); Security.insertProviderAt(jsseProvider, 1); InjectedSigAlgsProvider injProvider = new InjectedSigAlgsProvider(); Security.insertProviderAt(injProvider, 1); + + // adding the BC provider as the last (since we want to prioritize Java built-in algorithms): + BouncyCastleProvider jceProvider = new BouncyCastleProvider(); + Security.addProvider(jceProvider); } /**