diff options
author | Sergio Giro <sgiro@google.com> | 2017-01-19 21:40:17 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-01-19 21:40:17 +0000 |
commit | fbf7512c8942075f80cba53e708c13682f04ea29 (patch) | |
tree | 8ebc72ead6f9a80938fdba92e217da96ee451037 | |
parent | e54ca62fe13a7f6a52a89e409edcf4b6547072be (diff) | |
parent | 07a37e800ceaa1470036078af8d69981604e0945 (diff) | |
download | bouncycastle-fbf7512c8942075f80cba53e708c13682f04ea29.tar.gz |
Merge "bouncycastle: upgrade to version 1.56" am: ae9dc88d85 am: ed012da722
am: 07a37e800c
Change-Id: Ie6a51b57d83037f0f7f1acecedc16da1c1bd6820
162 files changed, 3732 insertions, 1516 deletions
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReqBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReqBuilder.java index b0cfb9ef..3f3c954a 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReqBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/OCSPReqBuilder.java @@ -75,9 +75,9 @@ public class OCSPReqBuilder } /** - * Set the requestor name to the passed in X500Principal + * Set the requestor name to the passed in X500Name * - * @param requestorName a X500Principal representing the requestor name. + * @param requestorName an X500Name representing the requestor name. */ public OCSPReqBuilder setRequestorName( X500Name requestorName) @@ -176,7 +176,7 @@ public class OCSPReqBuilder * Generate an unsigned request * * @return the OCSPReq - * @throws org.bouncycastle.ocsp.OCSPException + * @throws org.bouncycastle.cert.ocsp.OCSPException */ public OCSPReq build() throws OCSPException diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/RespID.java b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/RespID.java index a0fd765a..4cd19ef9 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/RespID.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/ocsp/RespID.java @@ -48,7 +48,7 @@ public class RespID { if (!digCalc.getAlgorithmIdentifier().equals(HASH_SHA1)) { - throw new IllegalArgumentException("only SHA-1 can be used with RespID"); + throw new IllegalArgumentException("only SHA-1 can be used with RespID - found: " + digCalc.getAlgorithmIdentifier().getAlgorithm()); } OutputStream digOut = digCalc.getOutputStream(); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAbsentContent.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAbsentContent.java index f256e2a2..242d64bb 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSAbsentContent.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSAbsentContent.java @@ -17,7 +17,7 @@ public class CMSAbsentContent public CMSAbsentContent() { - this(new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId())); + this(CMSObjectIdentifiers.data); } public CMSAbsentContent( diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java index e8ebc83e..780d4660 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java @@ -41,7 +41,7 @@ public class DefaultCMSSignatureEncryptionAlgorithmFinder public AlgorithmIdentifier findEncryptionAlgorithm(AlgorithmIdentifier signatureAlgorithm) { - // RFC3370 section 3.2 + // RFC3370 section 3.2 with RFC 5754 update if (RSA_PKCS1d5.contains(signatureAlgorithm.getAlgorithm())) { return new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE); diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java index ddfd2ebd..fb268b29 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultSignedAttributeTableGenerator.java @@ -51,8 +51,8 @@ public class DefaultSignedAttributeTableGenerator /** * Create a standard attribute table from the passed in parameters - this will - * normally include contentType, signingTime, and messageDigest. If the constructor - * using an AttributeTable was used, entries in it for contentType, signingTime, and + * normally include contentType, signingTime, messageDigest, and CMS algorithm protection. + * If the constructor using an AttributeTable was used, entries in it for contentType, signingTime, and * messageDigest will override the generated ones. * * @param parameters source parameters for table generation. diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java index 7322fdcc..932c2762 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/PasswordRecipient.java @@ -1,5 +1,7 @@ package org.bouncycastle.cms; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; public interface PasswordRecipient @@ -8,6 +10,34 @@ public interface PasswordRecipient public static final int PKCS5_SCHEME2 = 0; public static final int PKCS5_SCHEME2_UTF8 = 1; + static final class PRF + { + public static final PRF HMacSHA1 = new PRF("HMacSHA1", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA1, DERNull.INSTANCE)); + public static final PRF HMacSHA224 = new PRF("HMacSHA224", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA224, DERNull.INSTANCE)); + public static final PRF HMacSHA256 = new PRF("HMacSHA256", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA256, DERNull.INSTANCE)); + public static final PRF HMacSHA384 = new PRF("HMacSHA384", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA384, DERNull.INSTANCE)); + public static final PRF HMacSHA512 = new PRF("HMacSHA512", new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA512, DERNull.INSTANCE)); + + private final String hmac; + final AlgorithmIdentifier prfAlgID; + + private PRF(String hmac, AlgorithmIdentifier prfAlgID) + { + this.hmac = hmac; + this.prfAlgID = prfAlgID; + } + + public String getName() + { + return hmac; + } + + public AlgorithmIdentifier getAlgorithmID() + { + return prfAlgID; + } + } + byte[] calculateDerivedKey(int schemeID, AlgorithmIdentifier derivationAlgorithm, int keySize) throws CMSException; diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGeneratorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGeneratorBuilder.java index 7a47a2f8..ccb6e2cf 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGeneratorBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInfoGeneratorBuilder.java @@ -29,10 +29,11 @@ public class SignerInfoGeneratorBuilder this(digestProvider, new DefaultCMSSignatureEncryptionAlgorithmFinder()); } - /** - * Base constructor. + /** + * Base constructor with a particular finder for signature algorithms. * - * @param digestProvider a provider of digest calculators for the algorithms required in the signature and attribute calculations. + * @param digestProvider a provider of digest calculators for the algorithms required in the signature and attribute calculations. + * @param sigEncAlgFinder finder for algorithm IDs to store for the signature encryption/signature algorithm field. */ public SignerInfoGeneratorBuilder(DigestCalculatorProvider digestProvider, CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcaSignerInfoGeneratorBuilder.java b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcaSignerInfoGeneratorBuilder.java index 4a0e7ca4..17a2f093 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcaSignerInfoGeneratorBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/JcaSignerInfoGeneratorBuilder.java @@ -6,6 +6,8 @@ import java.security.cert.X509Certificate; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import org.bouncycastle.cms.CMSAttributeTableGenerator; +import org.bouncycastle.cms.CMSSignatureEncryptionAlgorithmFinder; +import org.bouncycastle.cms.DefaultCMSSignatureEncryptionAlgorithmFinder; import org.bouncycastle.cms.SignerInfoGenerator; import org.bouncycastle.cms.SignerInfoGeneratorBuilder; import org.bouncycastle.operator.ContentSigner; @@ -16,9 +18,25 @@ public class JcaSignerInfoGeneratorBuilder { private SignerInfoGeneratorBuilder builder; + /** + * Base constructor. + * + * @param digestProvider a provider of digest calculators for the algorithms required in the signature and attribute calculations. + */ public JcaSignerInfoGeneratorBuilder(DigestCalculatorProvider digestProvider) { - builder = new SignerInfoGeneratorBuilder(digestProvider); + this(digestProvider, new DefaultCMSSignatureEncryptionAlgorithmFinder()); + } + + /** + * Base constructor with a particular finder for signature algorithms. + * + * @param digestProvider a provider of digest calculators for the algorithms required in the signature and attribute calculations. + * @param sigEncAlgFinder finder for algorithm IDs to store for the signature encryption/signature algorithm field. + */ + public JcaSignerInfoGeneratorBuilder(DigestCalculatorProvider digestProvider, CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder) + { + builder = new SignerInfoGeneratorBuilder(digestProvider, sigEncAlgFinder); } /** diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java index dc2c431b..57920181 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java @@ -6,6 +6,8 @@ import java.util.Map; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERNull; // BEGIN android-removed +// import org.bouncycastle.asn1.bc.BCObjectIdentifiers; +// import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers; // import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; // END android-removed import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; @@ -51,6 +53,14 @@ public class DefaultDigestAlgorithmIdentifierFinder digestOids.put(X9ObjectIdentifiers.ecdsa_with_SHA512, NISTObjectIdentifiers.id_sha512); digestOids.put(X9ObjectIdentifiers.id_dsa_with_sha1, OIWObjectIdentifiers.idSHA1); + // BEGIN android-removed + // digestOids.put(BSIObjectIdentifiers.ecdsa_plain_SHA1, OIWObjectIdentifiers.idSHA1); + // digestOids.put(BSIObjectIdentifiers.ecdsa_plain_SHA224, NISTObjectIdentifiers.id_sha224); + // digestOids.put(BSIObjectIdentifiers.ecdsa_plain_SHA256, NISTObjectIdentifiers.id_sha256); + // digestOids.put(BSIObjectIdentifiers.ecdsa_plain_SHA384, NISTObjectIdentifiers.id_sha384); + // digestOids.put(BSIObjectIdentifiers.ecdsa_plain_SHA512, NISTObjectIdentifiers.id_sha512); + // END android-removed + digestOids.put(NISTObjectIdentifiers.dsa_with_sha224, NISTObjectIdentifiers.id_sha224); digestOids.put(NISTObjectIdentifiers.dsa_with_sha256, NISTObjectIdentifiers.id_sha256); digestOids.put(NISTObjectIdentifiers.dsa_with_sha384, NISTObjectIdentifiers.id_sha384); @@ -63,8 +73,31 @@ public class DefaultDigestAlgorithmIdentifierFinder // // digestOids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, CryptoProObjectIdentifiers.gostR3411); // digestOids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, CryptoProObjectIdentifiers.gostR3411); + // digestOids.put(NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_224, NISTObjectIdentifiers.id_sha3_224); + // digestOids.put(NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_256, NISTObjectIdentifiers.id_sha3_256); + // digestOids.put(NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_384, NISTObjectIdentifiers.id_sha3_384); + // digestOids.put(NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_512, NISTObjectIdentifiers.id_sha3_512); + // digestOids.put(NISTObjectIdentifiers.id_dsa_with_sha3_224, NISTObjectIdentifiers.id_sha3_224); + // digestOids.put(NISTObjectIdentifiers.id_dsa_with_sha3_256, NISTObjectIdentifiers.id_sha3_256); + // digestOids.put(NISTObjectIdentifiers.id_dsa_with_sha3_384, NISTObjectIdentifiers.id_sha3_384); + // digestOids.put(NISTObjectIdentifiers.id_dsa_with_sha3_512, NISTObjectIdentifiers.id_sha3_512); + // digestOids.put(NISTObjectIdentifiers.id_ecdsa_with_sha3_224, NISTObjectIdentifiers.id_sha3_224); + // digestOids.put(NISTObjectIdentifiers.id_ecdsa_with_sha3_256, NISTObjectIdentifiers.id_sha3_256); + // digestOids.put(NISTObjectIdentifiers.id_ecdsa_with_sha3_384, NISTObjectIdentifiers.id_sha3_384); + // digestOids.put(NISTObjectIdentifiers.id_ecdsa_with_sha3_512, NISTObjectIdentifiers.id_sha3_512); + // + // digestOids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128, TeleTrusTObjectIdentifiers.ripemd128); + // digestOids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160, TeleTrusTObjectIdentifiers.ripemd160); + // digestOids.put(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256, TeleTrusTObjectIdentifiers.ripemd256); + // + // digestOids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94, CryptoProObjectIdentifiers.gostR3411); + // digestOids.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001, CryptoProObjectIdentifiers.gostR3411); + // + // digestOids.put(BCObjectIdentifiers.sphincs256_with_SHA3_512, NISTObjectIdentifiers.id_sha3_512); + // digestOids.put(BCObjectIdentifiers.sphincs256_with_SHA512, NISTObjectIdentifiers.id_sha512); // END android-removed + digestNameToOids.put("SHA-1", OIWObjectIdentifiers.idSHA1); digestNameToOids.put("SHA-224", NISTObjectIdentifiers.id_sha224); digestNameToOids.put("SHA-256", NISTObjectIdentifiers.id_sha256); diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java index f6a54821..77f358a0 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java @@ -10,6 +10,7 @@ import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERNull; // BEGIN android-removed +// import org.bouncycastle.asn1.bc.BCObjectIdentifiers; // import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers; // import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; // import org.bouncycastle.asn1.eac.EACObjectIdentifiers; @@ -84,6 +85,7 @@ public class DefaultSignatureAlgorithmIdentifierFinder algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256); algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384); algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512); + // BEGIN android-removed // algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); // algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); @@ -101,7 +103,10 @@ public class DefaultSignatureAlgorithmIdentifierFinder // algorithms.put("SHA256WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_256); // algorithms.put("SHA384WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_384); // algorithms.put("SHA512WITHCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_512); + // algorithms.put("SHA3-512WITHSPHINCS256", BCObjectIdentifiers.sphincs256_with_SHA3_512); + // algorithms.put("SHA512WITHSPHINCS256", BCObjectIdentifiers.sphincs256_with_SHA512); // END android-removed + // // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. // The parameters field SHALL be NULL for RSA based signature algorithms. @@ -125,6 +130,14 @@ public class DefaultSignatureAlgorithmIdentifierFinder // noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001); // END android-removed + // BEGIN android-removed + // + // SPHINCS-256 + // + // noParams.add(BCObjectIdentifiers.sphincs256_with_SHA512); + // noParams.add(BCObjectIdentifiers.sphincs256_with_SHA3_512); + // END android-removed + // // PKCS 1.5 encrypted algorithms // diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java b/bcpkix/src/main/java/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java index 805dc479..74c0aa29 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java @@ -28,6 +28,9 @@ import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.digests.SHA224Digest; import org.bouncycastle.crypto.digests.SHA256Digest; import org.bouncycastle.crypto.digests.SHA384Digest; +// BEGIN android-removed +// import org.bouncycastle.crypto.digests.SHA3Digest; +// END android-removed import org.bouncycastle.crypto.digests.SHA512Digest; import org.bouncycastle.operator.OperatorCreationException; @@ -75,14 +78,42 @@ public class BcDefaultDigestProvider return new SHA512Digest(); } }); - table.put(PKCSObjectIdentifiers.md5, new BcDigestProvider() - { - public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) - { - return new MD5Digest(); - } - }); // BEGIN android-removed + // table.put(NISTObjectIdentifiers.id_sha3_224, new BcDigestProvider() + // { + // public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + // { + // return new SHA3Digest(224); + // } + // }); + // table.put(NISTObjectIdentifiers.id_sha3_256, new BcDigestProvider() + // { + // public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + // { + // return new SHA3Digest(256); + // } + // }); + // table.put(NISTObjectIdentifiers.id_sha3_384, new BcDigestProvider() + // { + // public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + // { + // return new SHA3Digest(384); + // } + // }); + // table.put(NISTObjectIdentifiers.id_sha3_512, new BcDigestProvider() + // { + // public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + // { + // return new SHA3Digest(512); + // } + // }); + // table.put(PKCSObjectIdentifiers.md5, new BcDigestProvider() + // { + // public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + // { + // return new MD5Digest(); + // } + // }); // table.put(PKCSObjectIdentifiers.md4, new BcDigestProvider() // { // public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java index 31af916f..55831943 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java @@ -59,6 +59,7 @@ public class JcaContentSignerBuilder try { final Signature sig = helper.createSignature(sigAlgId); + final AlgorithmIdentifier signatureAlgId = sigAlgId; if (random != null) { @@ -75,7 +76,7 @@ public class JcaContentSignerBuilder public AlgorithmIdentifier getAlgorithmIdentifier() { - return sigAlgId; + return signatureAlgId; } public OutputStream getOutputStream() diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java index 19d46ec9..532d3b51 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java @@ -383,7 +383,7 @@ class OperatorHelper String name = MessageDigestUtils.getDigestName(oid); int dIndex = name.indexOf('-'); - if (dIndex > 0) + if (dIndex > 0 && !name.startsWith("SHA3")) { return name.substring(0, dIndex) + name.substring(dIndex + 1); } @@ -394,7 +394,6 @@ class OperatorHelper public X509Certificate convertCertificate(X509CertificateHolder certHolder) throws CertificateException { - try { CertificateFactory certFact = helper.createCertificateFactory("X.509"); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java index fca4e01a..c67e42f3 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ApplicationSpecific.java @@ -21,7 +21,7 @@ public abstract class ASN1ApplicationSpecific { this.isConstructed = isConstructed; this.tag = tag; - this.octets = octets; + this.octets = Arrays.clone(octets); } /** @@ -93,7 +93,7 @@ public abstract class ASN1ApplicationSpecific */ public byte[] getContents() { - return octets; + return Arrays.clone(octets); } /** @@ -115,7 +115,7 @@ public abstract class ASN1ApplicationSpecific public ASN1Primitive getObject() throws IOException { - return new ASN1InputStream(getContents()).readObject(); + return ASN1Primitive.fromByteArray(getContents()); } /** @@ -141,7 +141,7 @@ public abstract class ASN1ApplicationSpecific tmp[0] |= BERTags.CONSTRUCTED; } - return new ASN1InputStream(tmp).readObject(); + return ASN1Primitive.fromByteArray(tmp); } int encodedLength() diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java index 195b924f..ca192f31 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Enumerated.java @@ -99,7 +99,18 @@ public class ASN1Enumerated public ASN1Enumerated( byte[] bytes) { - this.bytes = bytes; + if (bytes.length > 1) + { + if (bytes[0] == 0 && (bytes[1] & 0x80) == 0) + { + throw new IllegalArgumentException("malformed enumerated"); + } + if (bytes[0] == (byte)0xff && (bytes[1] & 0x80) != 0) + { + throw new IllegalArgumentException("malformed enumerated"); + } + } + this.bytes = Arrays.clone(bytes); } public BigInteger getValue() @@ -148,7 +159,7 @@ public class ASN1Enumerated { if (enc.length > 1) { - return new ASN1Enumerated(Arrays.clone(enc)); + return new ASN1Enumerated(enc); } if (enc.length == 0) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Exception.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Exception.java index dc0ee203..2696add7 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Exception.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Exception.java @@ -2,22 +2,41 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * Exception thrown in cases of corrupted or unexpected data in a stream. + */ public class ASN1Exception extends IOException { private Throwable cause; + /** + * Base constructor + * + * @param message a message concerning the exception. + */ ASN1Exception(String message) { super(message); } + /** + * Constructor when this exception is due to another one. + * + * @param message a message concerning the exception. + * @param cause the exception that caused this exception to be thrown. + */ ASN1Exception(String message, Throwable cause) { super(message); this.cause = cause; } + /** + * Return the underlying cause of this exception, if any. + * + * @return the exception causing this one, null if there isn't one. + */ public Throwable getCause() { return cause; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Generator.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Generator.java index 50cb7054..3817d82c 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Generator.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Generator.java @@ -2,14 +2,27 @@ package org.bouncycastle.asn1; import java.io.OutputStream; +/** + * Basic class for streaming generators. + */ public abstract class ASN1Generator { protected OutputStream _out; - + + /** + * Base constructor. + * + * @param out the end output stream that object encodings are written to. + */ public ASN1Generator(OutputStream out) { _out = out; } - + + /** + * Return the actual stream object encodings are written to. + * + * @return the stream that is directly encoded to. + */ public abstract OutputStream getRawOutputStream(); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java index c3c3f9cf..ab6d2020 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Integer.java @@ -89,6 +89,17 @@ public class ASN1Integer ASN1Integer(byte[] bytes, boolean clone) { + if (bytes.length > 1) + { + if (bytes[0] == 0 && (bytes[1] & 0x80) == 0) + { + throw new IllegalArgumentException("malformed integer"); + } + if (bytes[0] == (byte)0xff && (bytes[1] & 0x80) != 0) + { + throw new IllegalArgumentException("malformed integer"); + } + } this.bytes = (clone) ? Arrays.clone(bytes) : bytes; } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java index ac65d96f..50b8a491 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ObjectIdentifier.java @@ -3,8 +3,8 @@ package org.bouncycastle.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; -import java.util.HashMap; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.bouncycastle.util.Arrays; @@ -20,9 +20,10 @@ public class ASN1ObjectIdentifier /** * return an OID from the passed in object + * * @param obj an ASN1ObjectIdentifier or an object that can be converted into one. - * @throws IllegalArgumentException if the object cannot be converted. * @return an ASN1ObjectIdentifier instance, or null. + * @throws IllegalArgumentException if the object cannot be converted. */ public static ASN1ObjectIdentifier getInstance( Object obj) @@ -59,9 +60,9 @@ public class ASN1ObjectIdentifier * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. + * @return an ASN1ObjectIdentifier instance, or null. * @throws IllegalArgumentException if the tagged object cannot * be converted. - * @return an ASN1ObjectIdentifier instance, or null. */ public static ASN1ObjectIdentifier getInstance( ASN1TaggedObject obj, @@ -190,12 +191,12 @@ public class ASN1ObjectIdentifier // END android-changed } - /** - * Create an OID that creates a branch under the current one. - * - * @param branchID node numbers for the new branch. - * @return the OID for the new created branch. - */ + /** + * Create an OID that creates a branch under the current one. + * + * @param branchID node numbers for the new branch. + * @return the OID for the new created branch. + */ ASN1ObjectIdentifier(ASN1ObjectIdentifier oid, String branchID) { if (!isValidBranchID(branchID, 0)) @@ -428,32 +429,29 @@ public class ASN1ObjectIdentifier * The pool is also used by the ASN.1 parsers to limit the number of duplicated OID * objects in circulation. * </p> + * * @return a reference to the identifier in the pool. */ public ASN1ObjectIdentifier intern() { - synchronized (pool) + final OidHandle hdl = new OidHandle(getBody()); + ASN1ObjectIdentifier oid = pool.get(hdl); + if (oid == null) { - OidHandle hdl = new OidHandle(getBody()); - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)pool.get(hdl); - - if (oid != null) - { - return oid; - } - else + oid = pool.putIfAbsent(hdl, this); + if (oid == null) { - pool.put(hdl, this); - return this; + oid = this; } } + return oid; } - private static final Map pool = new HashMap(); + private static final ConcurrentMap<OidHandle, ASN1ObjectIdentifier> pool = new ConcurrentHashMap<OidHandle, ASN1ObjectIdentifier>(); private static class OidHandle { - private int key; + private final int key; private final byte[] enc; OidHandle(byte[] enc) @@ -480,17 +478,12 @@ public class ASN1ObjectIdentifier static ASN1ObjectIdentifier fromOctetString(byte[] enc) { - OidHandle hdl = new OidHandle(enc); - - synchronized (pool) + final OidHandle hdl = new OidHandle(enc); + ASN1ObjectIdentifier oid = pool.get(hdl); + if (oid == null) { - ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)pool.get(hdl); - if (oid != null) - { - return oid; - } + return new ASN1ObjectIdentifier(enc); } - - return new ASN1ObjectIdentifier(enc); + return oid; } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java index a3fa4a41..07811d71 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1OctetString.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.InputStream; import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; /** @@ -248,6 +249,6 @@ public abstract class ASN1OctetString public String toString() { - return "#"+new String(Hex.encode(string)); + return "#"+ Strings.fromByteArray(Hex.encode(string)); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ParsingException.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ParsingException.java index 995b5e93..509c213c 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ParsingException.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1ParsingException.java @@ -1,21 +1,40 @@ package org.bouncycastle.asn1; +/** + * Exception thrown when correctly encoded, but unexpected data is found in a stream while building an object. + */ public class ASN1ParsingException extends IllegalStateException { private Throwable cause; + /** + * Base constructor + * + * @param message a message concerning the exception. + */ public ASN1ParsingException(String message) { super(message); } + /** + * Constructor when this exception is due to another one. + * + * @param message a message concerning the exception. + * @param cause the exception that caused this exception to be thrown. + */ public ASN1ParsingException(String message, Throwable cause) { super(message); this.cause = cause; } + /** + * Return the underlying cause of this exception, if any. + * + * @return the exception causing this one, null if there isn't one. + */ public Throwable getCause() { return cause; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java index 778bea74..808f478e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1TaggedObject.java @@ -143,6 +143,11 @@ public abstract class ASN1TaggedObject return code; } + /** + * Return the tag number associated with this object. + * + * @return the tag number. + */ public int getTagNo() { return tagNo; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java b/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java index b8df94af..55e695c7 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java @@ -3,9 +3,19 @@ package org.bouncycastle.asn1; import java.io.IOException; import java.io.OutputStream; +/** + * A generator for indefinite-length OCTET STRINGs + */ public class BEROctetStringGenerator extends BERGenerator { + /** + * Use the passed in stream as the target for the generator, writing out the header tag + * for a constructed OCTET STRING. + * + * @param out target stream + * @throws IOException if the target stream cannot be written to. + */ public BEROctetStringGenerator(OutputStream out) throws IOException { @@ -14,6 +24,15 @@ public class BEROctetStringGenerator writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING); } + /** + * Use the passed in stream as the target for the generator, writing out the header tag + * for a tagged constructed OCTET STRING (possibly implicit). + * + * @param out target stream + * @param tagNo the tag number to introduce + * @param isExplicit true if this is an explicitly tagged object, false otherwise. + * @throws IOException if the target stream cannot be written to. + */ public BEROctetStringGenerator( OutputStream out, int tagNo, @@ -24,12 +43,23 @@ public class BEROctetStringGenerator writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING); } - + + /** + * Return a stream representing the content target for this OCTET STRING + * + * @return an OutputStream which chunks data in blocks of 1000 (CER limit). + */ public OutputStream getOctetOutputStream() { return getOctetOutputStream(new byte[1000]); // limit for CER encoding. } + /** + * Return a stream representing the content target for this OCTET STRING + * + * @param buf the buffer to use for chunking the data. + * @return an OutputStream which chunks data in blocks of buf length. + */ public OutputStream getOctetOutputStream( byte[] buf) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetStringParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetStringParser.java index 1c7132e5..77a3049d 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetStringParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BEROctetStringParser.java @@ -5,6 +5,9 @@ import java.io.InputStream; import org.bouncycastle.util.io.Streams; +/** + * A parser for indefinite-length OCTET STRINGs. + */ public class BEROctetStringParser implements ASN1OctetStringParser { @@ -16,17 +19,33 @@ public class BEROctetStringParser _parser = parser; } + /** + * Return an InputStream representing the contents of the OCTET STRING. + * + * @return an InputStream with its source as the OCTET STRING content. + */ public InputStream getOctetStream() { return new ConstructedOctetStream(_parser); } + /** + * Return an in-memory, encodable, representation of the OCTET STRING. + * + * @return a BEROctetString. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { return new BEROctetString(Streams.readAll(getOctetStream())); } + /** + * Return an BEROctetString representing this parser and its contents. + * + * @return an BEROctetString + */ public ASN1Primitive toASN1Primitive() { try diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java b/bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java index 7117d4fb..f6459b2e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BEROutputStream.java @@ -3,15 +3,29 @@ package org.bouncycastle.asn1; import java.io.IOException; import java.io.OutputStream; +/** + * A class which writes indefinite and definite length objects, + */ public class BEROutputStream extends DEROutputStream { + /** + * Base constructor. + * + * @param os target output stream. + */ public BEROutputStream( OutputStream os) { super(os); } + /** + * Write out an ASN.1 object. + * + * @param obj the object to be encoded. + * @throws IOException if there is an issue on encoding or output of the object. + */ public void writeObject( Object obj) throws IOException diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/BERTaggedObject.java b/bcprov/src/main/java/org/bouncycastle/asn1/BERTaggedObject.java index 1af0a433..37599fbe 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/BERTaggedObject.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/BERTaggedObject.java @@ -127,7 +127,7 @@ public class BERTaggedObject } else { - throw new RuntimeException("not implemented: " + obj.getClass().getName()); + throw new ASN1Exception("not implemented: " + obj.getClass().getName()); } while (e.hasMoreElements()) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java index d74bc00e..c789d7cd 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERBitString.java @@ -26,6 +26,17 @@ public class DERBitString { return new DERBitString(((DLBitString)obj).data, ((DLBitString)obj).padBits); } + if (obj instanceof byte[]) + { + try + { + return (DERBitString)fromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); + } + } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERSequenceParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERSequenceParser.java index 376c1fd8..5503feb8 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERSequenceParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERSequenceParser.java @@ -2,6 +2,9 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * Parser class for DER SEQUENCEs. + */ public class DERSequenceParser implements ASN1SequenceParser { @@ -12,18 +15,35 @@ public class DERSequenceParser this._parser = parser; } + /** + * Return the next object in the SEQUENCE. + * + * @return next object in SEQUENCE. + * @throws IOException if there is an issue loading the object. + */ public ASN1Encodable readObject() throws IOException { return _parser.readObject(); } + /** + * Return an in memory, encodable, representation of the SEQUENCE. + * + * @return a DERSequence. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { return new DERSequence(_parser.readVector()); } + /** + * Return a DERSequence representing this parser and its contents. + * + * @return a DERSequence. + */ public ASN1Primitive toASN1Primitive() { try diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java index ac58eacf..1a72a0b1 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERSet.java @@ -4,7 +4,7 @@ import java.io.IOException; import java.util.Enumeration; /** - * A DER encoded set object + * A DER encoded SET object */ public class DERSet extends ASN1Set diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERSetParser.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERSetParser.java index 17702fa4..d16cb157 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERSetParser.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERSetParser.java @@ -2,6 +2,9 @@ package org.bouncycastle.asn1; import java.io.IOException; +/** + * Parser class for DER SETs. + */ public class DERSetParser implements ASN1SetParser { @@ -12,18 +15,35 @@ public class DERSetParser this._parser = parser; } + /** + * Return the next object in the SET. + * + * @return next object in SET. + * @throws IOException if there is an issue loading the object. + */ public ASN1Encodable readObject() throws IOException { return _parser.readObject(); } + /** + * Return an in memory, encodable, representation of the SET. + * + * @return a DERSet. + * @throws IOException if there is an issue loading the data. + */ public ASN1Primitive getLoadedObject() throws IOException { return new DERSet(_parser.readVector(), false); } + /** + * Return a DERSet representing this parser and its contents. + * + * @return a DERSet + */ public ASN1Primitive toASN1Primitive() { try diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java index 30744c69..c5c29137 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERT61String.java @@ -13,7 +13,7 @@ public class DERT61String extends ASN1Primitive implements ASN1String { - private final byte[] string; + private byte[] string; /** * return a T61 string from the passed in object. @@ -79,7 +79,7 @@ public class DERT61String public DERT61String( byte[] string) { - this.string = string; + this.string = Arrays.clone(string); } /** @@ -90,7 +90,7 @@ public class DERT61String public DERT61String( String string) { - this(Strings.toByteArray(string)); + this.string = Strings.toByteArray(string); } /** diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java index 85390990..6b70faab 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DERUniversalString.java @@ -79,7 +79,7 @@ public class DERUniversalString public DERUniversalString( byte[] string) { - this.string = string; + this.string = Arrays.clone(string); } public String getString() @@ -94,7 +94,7 @@ public class DERUniversalString } catch (IOException e) { - throw new RuntimeException("internal error encoding BitString"); + throw new ASN1ParsingException("internal error encoding BitString"); } byte[] string = bOut.toByteArray(); @@ -115,7 +115,7 @@ public class DERUniversalString public byte[] getOctets() { - return string; + return Arrays.clone(string); } boolean isConstructed() diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java b/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java index c81f0ab9..f6cb49bd 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/DLBitString.java @@ -26,6 +26,17 @@ public class DLBitString { return (DERBitString)obj; } + if (obj instanceof byte[]) + { + try + { + return (ASN1BitString)fromByteArray((byte[])obj); + } + catch (Exception e) + { + throw new IllegalArgumentException("encoding error in getInstance: " + e.toString()); + } + } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java index 5b95b79e..a4f3f3b2 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java @@ -66,4 +66,29 @@ public interface BCObjectIdentifiers public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = bc_pbe_sha256_pkcs12.branch("1.22"); /** 1.3.6.1.4.1.22554.1.1.2.2.42 */ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = bc_pbe_sha256_pkcs12.branch("1.42"); + + /** + * signature(2) algorithms + */ + public static final ASN1ObjectIdentifier bc_sig = bc.branch("2"); + + // BEGIN android-removed + // /** + // * Sphincs-256 + // */ + // public static final ASN1ObjectIdentifier sphincs256 = bc_sig.branch("1"); + // public static final ASN1ObjectIdentifier sphincs256_with_BLAKE512 = sphincs256.branch("1"); + // public static final ASN1ObjectIdentifier sphincs256_with_SHA512 = sphincs256.branch("2"); + // public static final ASN1ObjectIdentifier sphincs256_with_SHA3_512 = sphincs256.branch("3"); + + // /** + // * key_exchange(3) algorithms + // */ + // public static final ASN1ObjectIdentifier bc_exch = bc.branch("3"); + + // /** + // * NewHope + // */ + // public static final ASN1ObjectIdentifier newHope = bc_exch.branch("1"); + // END android-removed } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java index 19077e4c..ba7e5187 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTNamedCurves.java @@ -17,38 +17,42 @@ public class NISTNamedCurves static final Hashtable objIds = new Hashtable(); static final Hashtable names = new Hashtable(); - static void defineCurveAlias(String name, ASN1ObjectIdentifier oid) + static void defineCurve(String name, ASN1ObjectIdentifier oid) { - objIds.put(name.toUpperCase(), oid); + objIds.put(name, oid); names.put(oid, name); } static { - defineCurveAlias("B-163", SECObjectIdentifiers.sect163r2); - defineCurveAlias("B-233", SECObjectIdentifiers.sect233r1); - defineCurveAlias("B-283", SECObjectIdentifiers.sect283r1); - defineCurveAlias("B-409", SECObjectIdentifiers.sect409r1); - defineCurveAlias("B-571", SECObjectIdentifiers.sect571r1); - - defineCurveAlias("K-163", SECObjectIdentifiers.sect163k1); - defineCurveAlias("K-233", SECObjectIdentifiers.sect233k1); - defineCurveAlias("K-283", SECObjectIdentifiers.sect283k1); - defineCurveAlias("K-409", SECObjectIdentifiers.sect409k1); - defineCurveAlias("K-571", SECObjectIdentifiers.sect571k1); - - defineCurveAlias("P-192", SECObjectIdentifiers.secp192r1); - defineCurveAlias("P-224", SECObjectIdentifiers.secp224r1); - defineCurveAlias("P-256", SECObjectIdentifiers.secp256r1); - defineCurveAlias("P-384", SECObjectIdentifiers.secp384r1); - defineCurveAlias("P-521", SECObjectIdentifiers.secp521r1); + defineCurve("B-571", SECObjectIdentifiers.sect571r1); + defineCurve("B-409", SECObjectIdentifiers.sect409r1); + defineCurve("B-283", SECObjectIdentifiers.sect283r1); + defineCurve("B-233", SECObjectIdentifiers.sect233r1); + defineCurve("B-163", SECObjectIdentifiers.sect163r2); + defineCurve("K-571", SECObjectIdentifiers.sect571k1); + defineCurve("K-409", SECObjectIdentifiers.sect409k1); + defineCurve("K-283", SECObjectIdentifiers.sect283k1); + defineCurve("K-233", SECObjectIdentifiers.sect233k1); + defineCurve("K-163", SECObjectIdentifiers.sect163k1); + defineCurve("P-521", SECObjectIdentifiers.secp521r1); + defineCurve("P-384", SECObjectIdentifiers.secp384r1); + defineCurve("P-256", SECObjectIdentifiers.secp256r1); + defineCurve("P-224", SECObjectIdentifiers.secp224r1); + defineCurve("P-192", SECObjectIdentifiers.secp192r1); } public static X9ECParameters getByName( String name) { - ASN1ObjectIdentifier oid = getOID(name); - return oid == null ? null : getByOID(oid); + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toUpperCase(name)); + + if (oid != null) + { + return getByOID(oid); + } + + return null; } /** @@ -90,6 +94,6 @@ public class NISTNamedCurves */ public static Enumeration getNames() { - return names.elements(); + return objIds.keys(); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java index 0de40f20..49c0e6d7 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java @@ -40,9 +40,17 @@ public interface NISTObjectIdentifiers /** 2.16.840.1.101.3.4.2.10 */ static final ASN1ObjectIdentifier id_sha3_512 = hashAlgs.branch("10"); /** 2.16.840.1.101.3.4.2.11 */ - static final ASN1ObjectIdentifier id_shake128 = hashAlgs.branch("11"); + static final ASN1ObjectIdentifier id_shake128 = hashAlgs.branch("11"); /** 2.16.840.1.101.3.4.2.12 */ - static final ASN1ObjectIdentifier id_shake256 = hashAlgs.branch("12"); + static final ASN1ObjectIdentifier id_shake256 = hashAlgs.branch("12"); + /** 2.16.840.1.101.3.4.2.13 */ + static final ASN1ObjectIdentifier id_hmacWithSHA3_224 = hashAlgs.branch("13"); + /** 2.16.840.1.101.3.4.2.14 */ + static final ASN1ObjectIdentifier id_hmacWithSHA3_256 = hashAlgs.branch("14"); + /** 2.16.840.1.101.3.4.2.15 */ + static final ASN1ObjectIdentifier id_hmacWithSHA3_384 = hashAlgs.branch("15"); + /** 2.16.840.1.101.3.4.2.16 */ + static final ASN1ObjectIdentifier id_hmacWithSHA3_512 = hashAlgs.branch("16"); /** 2.16.840.1.101.3.4.1 */ static final ASN1ObjectIdentifier aes = nistAlgorithm.branch("1"); @@ -61,7 +69,9 @@ public interface NISTObjectIdentifiers static final ASN1ObjectIdentifier id_aes128_GCM = aes.branch("6"); /** 2.16.840.1.101.3.4.1.7 */ static final ASN1ObjectIdentifier id_aes128_CCM = aes.branch("7"); - + /** 2.16.840.1.101.3.4.1.28 */ + static final ASN1ObjectIdentifier id_aes128_wrap_pad = aes.branch("8"); + /** 2.16.840.1.101.3.4.1.21 */ static final ASN1ObjectIdentifier id_aes192_ECB = aes.branch("21"); /** 2.16.840.1.101.3.4.1.22 */ @@ -76,7 +86,9 @@ public interface NISTObjectIdentifiers static final ASN1ObjectIdentifier id_aes192_GCM = aes.branch("26"); /** 2.16.840.1.101.3.4.1.27 */ static final ASN1ObjectIdentifier id_aes192_CCM = aes.branch("27"); - + /** 2.16.840.1.101.3.4.1.28 */ + static final ASN1ObjectIdentifier id_aes192_wrap_pad = aes.branch("28"); + /** 2.16.840.1.101.3.4.1.41 */ static final ASN1ObjectIdentifier id_aes256_ECB = aes.branch("41"); /** 2.16.840.1.101.3.4.1.42 */ @@ -91,19 +103,51 @@ public interface NISTObjectIdentifiers static final ASN1ObjectIdentifier id_aes256_GCM = aes.branch("46"); /** 2.16.840.1.101.3.4.1.47 */ static final ASN1ObjectIdentifier id_aes256_CCM = aes.branch("47"); + /** 2.16.840.1.101.3.4.1.48 */ + static final ASN1ObjectIdentifier id_aes256_wrap_pad = aes.branch("48"); // // signatures // /** 2.16.840.1.101.3.4.3 */ - static final ASN1ObjectIdentifier id_dsa_with_sha2 = nistAlgorithm.branch("3"); + static final ASN1ObjectIdentifier sigAlgs = nistAlgorithm.branch("3"); + + static final ASN1ObjectIdentifier id_dsa_with_sha2 = sigAlgs; /** 2.16.840.1.101.3.4.3.1 */ - static final ASN1ObjectIdentifier dsa_with_sha224 = id_dsa_with_sha2.branch("1"); + static final ASN1ObjectIdentifier dsa_with_sha224 = sigAlgs.branch("1"); /** 2.16.840.1.101.3.4.3.2 */ - static final ASN1ObjectIdentifier dsa_with_sha256 = id_dsa_with_sha2.branch("2"); + static final ASN1ObjectIdentifier dsa_with_sha256 = sigAlgs.branch("2"); /** 2.16.840.1.101.3.4.3.3 */ - static final ASN1ObjectIdentifier dsa_with_sha384 = id_dsa_with_sha2.branch("3"); + static final ASN1ObjectIdentifier dsa_with_sha384 = sigAlgs.branch("3"); /** 2.16.840.1.101.3.4.3.4 */ - static final ASN1ObjectIdentifier dsa_with_sha512 = id_dsa_with_sha2.branch("4"); + static final ASN1ObjectIdentifier dsa_with_sha512 = sigAlgs.branch("4"); + /** 2.16.840.1.101.3.4.3.5 */ + static final ASN1ObjectIdentifier id_dsa_with_sha3_224 = sigAlgs.branch("5"); + /** 2.16.840.1.101.3.4.3.6 */ + static final ASN1ObjectIdentifier id_dsa_with_sha3_256 = sigAlgs.branch("6"); + /** 2.16.840.1.101.3.4.3.7 */ + static final ASN1ObjectIdentifier id_dsa_with_sha3_384 = sigAlgs.branch("7"); + /** 2.16.840.1.101.3.4.3.8 */ + static final ASN1ObjectIdentifier id_dsa_with_sha3_512 = sigAlgs.branch("8"); + + // ECDSA with SHA-3 + /** 2.16.840.1.101.3.4.3.9 */ + static final ASN1ObjectIdentifier id_ecdsa_with_sha3_224 = sigAlgs.branch("9"); + /** 2.16.840.1.101.3.4.3.10 */ + static final ASN1ObjectIdentifier id_ecdsa_with_sha3_256 = sigAlgs.branch("10"); + /** 2.16.840.1.101.3.4.3.11 */ + static final ASN1ObjectIdentifier id_ecdsa_with_sha3_384 = sigAlgs.branch("11"); + /** 2.16.840.1.101.3.4.3.12 */ + static final ASN1ObjectIdentifier id_ecdsa_with_sha3_512 = sigAlgs.branch("12"); + + // RSA PKCS #1 v1.5 Signature with SHA-3 family. + /** 2.16.840.1.101.3.4.3.9 */ + static final ASN1ObjectIdentifier id_rsassa_pkcs1_v1_5_with_sha3_224 = sigAlgs.branch("13"); + /** 2.16.840.1.101.3.4.3.10 */ + static final ASN1ObjectIdentifier id_rsassa_pkcs1_v1_5_with_sha3_256 = sigAlgs.branch("14"); + /** 2.16.840.1.101.3.4.3.11 */ + static final ASN1ObjectIdentifier id_rsassa_pkcs1_v1_5_with_sha3_384 = sigAlgs.branch("15"); + /** 2.16.840.1.101.3.4.3.12 */ + static final ASN1ObjectIdentifier id_rsassa_pkcs1_v1_5_with_sha3_512 = sigAlgs.branch("16"); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java index af530ae5..0b1db325 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/ocsp/CertStatus.java @@ -13,7 +13,7 @@ public class CertStatus implements ASN1Choice { private int tagNo; - private ASN1Encodable value; + private ASN1Encodable value; /** * create a CertStatus object with a tag of zero. @@ -39,7 +39,7 @@ public class CertStatus this.value = value; } - public CertStatus( + private CertStatus( ASN1TaggedObject choice) { this.tagNo = choice.getTagNo(); @@ -54,6 +54,9 @@ public class CertStatus break; case 2: value = DERNull.INSTANCE; + break; + default: + throw new IllegalArgumentException("Unknown tag encountered: " + choice.getTagNo()); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java index 747277c3..49b2652c 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CRLBag.java @@ -6,6 +6,7 @@ import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; @@ -22,7 +23,7 @@ public class CRLBag ASN1Sequence seq) { this.crlId = (ASN1ObjectIdentifier)seq.getObjectAt(0); - this.crlValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject(); + this.crlValue = ((ASN1TaggedObject)seq.getObjectAt(1)).getObject(); } public static CRLBag getInstance(Object o) diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java index fb418aeb..dca0719c 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java @@ -6,6 +6,7 @@ import org.bouncycastle.asn1.ASN1Object; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.x500.X500Name; @@ -116,7 +117,7 @@ public class CertificationRequestInfo // if (seq.size() > 3) { - DERTaggedObject tagobj = (DERTaggedObject)seq.getObjectAt(3); + ASN1TaggedObject tagobj = (ASN1TaggedObject)seq.getObjectAt(3); attributes = ASN1Set.getInstance(tagobj, false); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java index 1d8f582c..63fa2e4e 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/MacData.java @@ -11,6 +11,7 @@ import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.DigestInfo; +import org.bouncycastle.util.Arrays; public class MacData extends ASN1Object @@ -41,7 +42,7 @@ public class MacData { this.digInfo = DigestInfo.getInstance(seq.getObjectAt(0)); - this.salt = ((ASN1OctetString)seq.getObjectAt(1)).getOctets(); + this.salt = Arrays.clone(((ASN1OctetString)seq.getObjectAt(1)).getOctets()); if (seq.size() == 3) { @@ -59,7 +60,7 @@ public class MacData int iterationCount) { this.digInfo = digInfo; - this.salt = salt; + this.salt = Arrays.clone(salt); this.iterationCount = BigInteger.valueOf(iterationCount); } @@ -70,7 +71,7 @@ public class MacData public byte[] getSalt() { - return salt; + return Arrays.clone(salt); } public BigInteger getIterationCount() diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java index 5dbddc3c..6e50f552 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java @@ -41,6 +41,10 @@ public interface PKCSObjectIdentifiers static final ASN1ObjectIdentifier sha512WithRSAEncryption = pkcs_1.branch("13"); /** PKCS#1: 1.2.840.113549.1.1.14 */ static final ASN1ObjectIdentifier sha224WithRSAEncryption = pkcs_1.branch("14"); + /** PKCS#1: 1.2.840.113549.1.1.15 */ + ASN1ObjectIdentifier sha512_224WithRSAEncryption = pkcs_1.branch("15"); + /** PKCS#1: 1.2.840.113549.1.1.16 */ + ASN1ObjectIdentifier sha512_256WithRSAEncryption = pkcs_1.branch("16"); // // pkcs-3 OBJECT IDENTIFIER ::= { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java index 1cdaf129..1d2c78cb 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/SECNamedCurves.java @@ -987,7 +987,7 @@ public class SECNamedCurves static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder) { - objIds.put(name.toLowerCase(), oid); + objIds.put(name, oid); names.put(oid, name); curves.put(oid, holder); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java index 2be7efec..c38eac74 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java @@ -3,9 +3,11 @@ package org.bouncycastle.asn1.teletrust; import org.bouncycastle.asn1.ASN1ObjectIdentifier; /** + * Object identifiers based on the TeleTrust branch. + * <pre> * TeleTrusT: * { iso(1) identifier-organization(3) teleTrust(36) algorithm(3) - * + * </pre> */ public interface TeleTrusTObjectIdentifiers { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java b/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java index 1330d256..59c961f2 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/util/ASN1Dump.java @@ -38,6 +38,9 @@ import org.bouncycastle.asn1.DERVisibleString; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; +/** + * Utility class for dumping ASN.1 objects as (hopefully) human friendly strings. + */ public class ASN1Dump { private static final String TAB = " "; @@ -319,7 +322,7 @@ public class ASN1Dump return buf.toString(); } - return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl; + return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + Strings.fromByteArray(Hex.encode(app.getContents())) + ")" + nl; } /** @@ -376,7 +379,7 @@ public class ASN1Dump if (bytes.length - i > SAMPLE_SIZE) { buf.append(indent); - buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE))); + buf.append(Strings.fromByteArray(Hex.encode(bytes, i, SAMPLE_SIZE))); buf.append(TAB); buf.append(calculateAscString(bytes, i, SAMPLE_SIZE)); buf.append(nl); @@ -384,7 +387,7 @@ public class ASN1Dump else { buf.append(indent); - buf.append(new String(Hex.encode(bytes, i, bytes.length - i))); + buf.append(Strings.fromByteArray(Hex.encode(bytes, i, bytes.length - i))); for (int j = bytes.length - i; j != SAMPLE_SIZE; j++) { buf.append(" "); diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java index 34b43856..2ef24d36 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/BCStyle.java @@ -78,59 +78,50 @@ public class BCStyle /** * businessCategory - DirectoryString(SIZE(1..128) */ - public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier( - "2.5.4.15").intern(); + public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier("2.5.4.15").intern(); /** * postalCode - DirectoryString(SIZE(1..40) */ - public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier( - "2.5.4.17").intern(); + public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier("2.5.4.17").intern(); /** * dnQualifier - DirectoryString(SIZE(1..64) */ - public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier( - "2.5.4.46").intern(); + public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier("2.5.4.46").intern(); /** * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64) */ - public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier( - "2.5.4.65").intern(); + public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier("2.5.4.65").intern(); /** * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z */ - public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.1").intern(); + public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.9.1").intern(); /** * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128) */ - public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.2").intern(); + public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.9.2").intern(); /** * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f" */ - public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.3").intern(); + public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.9.3").intern(); /** * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166 * codes only */ - public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.4").intern(); + public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.9.4").intern(); /** * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166 * codes only */ - public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier( - "1.3.6.1.5.5.7.9.5").intern(); + public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.9.5").intern(); /** diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java index 48e5640d..1a4c8dd2 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/DistributionPoint.java @@ -66,6 +66,9 @@ public class DistributionPoint break; case 2: cRLIssuer = GeneralNames.getInstance(t, false); + break; + default: + throw new IllegalArgumentException("Unknown tag encountered in structure: " + t.getTagNo()); } } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extension.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extension.java index 456e3d32..b8c0473a 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extension.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extension.java @@ -174,6 +174,11 @@ public class Extension */ public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55").intern(); + /** + * Expired Certificates on CRL extension + */ + public static final ASN1ObjectIdentifier expiredCertsOnCRL = new ASN1ObjectIdentifier("2.5.29.60").intern(); + private ASN1ObjectIdentifier extnId; private boolean critical; private ASN1OctetString value; diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraints.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraints.java index 0a923a85..88cfe3a9 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraints.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/NameConstraints.java @@ -37,12 +37,14 @@ public class NameConstraints ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement()); switch (o.getTagNo()) { - case 0: - permitted = createArray(ASN1Sequence.getInstance(o, false)); - break; - case 1: - excluded = createArray(ASN1Sequence.getInstance(o, false)); - break; + case 0: + permitted = createArray(ASN1Sequence.getInstance(o, false)); + break; + case 1: + excluded = createArray(ASN1Sequence.getInstance(o, false)); + break; + default: + throw new IllegalArgumentException("Unknown tag encountered: " + o.getTagNo()); } } } @@ -62,15 +64,8 @@ public class NameConstraints GeneralSubtree[] permitted, GeneralSubtree[] excluded) { - if (permitted != null) - { - this.permitted = permitted; - } - - if (excluded != null) - { - this.excluded = excluded; - } + this.permitted = cloneSubtree(permitted); + this.excluded = cloneSubtree(excluded); } private GeneralSubtree[] createArray(ASN1Sequence subtree) @@ -87,12 +82,12 @@ public class NameConstraints public GeneralSubtree[] getPermittedSubtrees() { - return permitted; + return cloneSubtree(permitted); } public GeneralSubtree[] getExcludedSubtrees() { - return excluded; + return cloneSubtree(excluded); } /* @@ -115,4 +110,18 @@ public class NameConstraints return new DERSequence(v); } + + private static GeneralSubtree[] cloneSubtree(GeneralSubtree[] subtrees) + { + if (subtrees != null) + { + GeneralSubtree[] rv = new GeneralSubtree[subtrees.length]; + + System.arraycopy(subtrees, 0, rv, 0, rv.length); + + return rv; + } + + return null; + } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java index 5f0cd079..52e35a15 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java @@ -5,6 +5,7 @@ import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1TaggedObject; import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.util.Arrays; /** * The SubjectKeyIdentifier object. @@ -47,22 +48,22 @@ public class SubjectKeyIdentifier public SubjectKeyIdentifier( byte[] keyid) { - this.keyidentifier = keyid; + this.keyidentifier = Arrays.clone(keyid); } protected SubjectKeyIdentifier( ASN1OctetString keyid) { - this.keyidentifier = keyid.getOctets(); + this(keyid.getOctets()); } public byte[] getKeyIdentifier() { - return keyidentifier; + return Arrays.clone(keyidentifier); } public ASN1Primitive toASN1Primitive() { - return new DEROctetString(keyidentifier); + return new DEROctetString(getKeyIdentifier()); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java index 23f99d0a..c7682f1a 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertList.java @@ -199,13 +199,13 @@ public class TBSCertList } if (seqPos < seq.size() - && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject)) + && !(seq.getObjectAt(seqPos) instanceof ASN1TaggedObject)) { revokedCertificates = ASN1Sequence.getInstance(seq.getObjectAt(seqPos++)); } if (seqPos < seq.size() - && seq.getObjectAt(seqPos) instanceof DERTaggedObject) + && seq.getObjectAt(seqPos) instanceof ASN1TaggedObject) { crlExtensions = Extensions.getInstance(ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(seqPos), true)); } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java index dc419649..f7f60050 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/TBSCertificate.java @@ -77,7 +77,7 @@ public class TBSCertificate // // some certficates don't include a version number - we assume v1 // - if (seq.getObjectAt(0) instanceof DERTaggedObject) + if (seq.getObjectAt(0) instanceof ASN1TaggedObject) { version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true); } @@ -109,7 +109,7 @@ public class TBSCertificate for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--) { - DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras); + ASN1TaggedObject extra = (ASN1TaggedObject)seq.getObjectAt(seqStart + 6 + extras); switch (extra.getTagNo()) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ValidationParams.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ValidationParams.java index 34ad746a..855974d2 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/ValidationParams.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/ValidationParams.java @@ -12,10 +12,13 @@ import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSequence; /** + * Diffie-Hellman domain validation parameters. + * <pre> * ValidationParams ::= SEQUENCE { * seed BIT STRING, * pgenCounter INTEGER * } + * </pre> */ public class ValidationParams extends ASN1Object diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java index 84574a3a..022c0183 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962NamedCurves.java @@ -11,7 +11,7 @@ import org.bouncycastle.util.encoders.Hex; /** - * table of the current named curves defined in X.962 EC-DSA. + * Table of the current named curves defined in X.962 EC-DSA. */ public class X962NamedCurves { @@ -546,7 +546,7 @@ public class X962NamedCurves static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder) { - objIds.put(name.toLowerCase(), oid); + objIds.put(name, oid); names.put(oid, name); curves.put(oid, holder); } @@ -581,8 +581,14 @@ public class X962NamedCurves public static X9ECParameters getByName( String name) { - ASN1ObjectIdentifier oid = getOID(name); - return oid == null ? null : getByOID(oid); + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name)); + + if (oid != null) + { + return getByOID(oid); + } + + return null; } /** @@ -595,7 +601,13 @@ public class X962NamedCurves ASN1ObjectIdentifier oid) { X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid); - return holder == null ? null : holder.getParameters(); + + if (holder != null) + { + return holder.getParameters(); + } + + return null; } /** @@ -625,6 +637,6 @@ public class X962NamedCurves */ public static Enumeration getNames() { - return names.elements(); + return objIds.keys(); } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java index a06aa85f..2f26c66d 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X962Parameters.java @@ -37,7 +37,7 @@ public class X962Parameters { return new X962Parameters(ASN1Primitive.fromByteArray((byte[])obj)); } - catch (IOException e) + catch (Exception e) { throw new IllegalArgumentException("unable to parse encoded data: " + e.getMessage()); } @@ -107,6 +107,6 @@ public class X962Parameters */ public ASN1Primitive toASN1Primitive() { - return (ASN1Primitive)params; + return params; } } diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java index 57b0fda4..95fdc672 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ECPoint.java @@ -53,7 +53,7 @@ public class X9ECPoint return Arrays.clone(encoding.getOctets()); } - public ECPoint getPoint() + public synchronized ECPoint getPoint() { if (p == null) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java index 16a803cc..2851bcae 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9IntegerConverter.java @@ -5,20 +5,43 @@ import java.math.BigInteger; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECFieldElement; +/** + * A class which converts integers to byte arrays, allowing padding and calculations + * to be done according the the filed size of the curve or field element involved. + */ public class X9IntegerConverter { + /** + * Return the curve's field size in bytes. + * + * @param c the curve of interest. + * @return the field size in bytes (rounded up). + */ public int getByteLength( ECCurve c) { return (c.getFieldSize() + 7) / 8; } + /** + * Return the field element's field size in bytes. + * + * @param fe the field element of interest. + * @return the field size in bytes (rounded up). + */ public int getByteLength( ECFieldElement fe) { return (fe.getFieldSize() + 7) / 8; } + /** + * Convert an integer to a byte array, ensuring it is exactly qLength long. + * + * @param s the integer to be converted. + * @param qLength the length + * @return the resulting byte array. + */ public byte[] integerToBytes( BigInteger s, int qLength) diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java index d2e2a09f..4dd80d0a 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/DHBasicAgreement.java @@ -20,6 +20,8 @@ import org.bouncycastle.crypto.params.ParametersWithRandom; public class DHBasicAgreement implements BasicAgreement { + private static final BigInteger ONE = BigInteger.valueOf(1); + private DHPrivateKeyParameters key; private DHParameters dhParams; @@ -66,6 +68,12 @@ public class DHBasicAgreement throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters."); } - return pub.getY().modPow(key.getX(), dhParams.getP()); + BigInteger result = pub.getY().modPow(key.getX(), dhParams.getP()); + if (result.compareTo(ONE) == 0) + { + throw new IllegalStateException("Shared key can't be 1"); + } + + return result; } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java index 5aa2f2bb..45ff0d36 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java @@ -59,6 +59,11 @@ public class ECDHBasicAgreement // Explicitly construct a public key using the private key's curve. ECPoint pubPoint = myCurve.createPoint(peerPoint.getXCoord().toBigInteger(), peerPoint.getYCoord().toBigInteger()); + ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey; + if (!pub.getParameters().equals(key.getParameters())) + { + throw new IllegalStateException("ECDH public key has wrong domain parameters"); + } ECPoint P = pubPoint.multiply(key.getD()).normalize(); // END android-changed diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java index ff9cedf0..417c4bad 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/MD5Digest.java @@ -2,12 +2,14 @@ package org.bouncycastle.crypto.digests; import org.bouncycastle.util.Memoable; +import org.bouncycastle.util.Pack; /** * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347. */ public class MD5Digest extends GeneralDigest + implements EncodableDigest { private static final int DIGEST_LENGTH = 16; @@ -24,6 +26,22 @@ public class MD5Digest reset(); } + public MD5Digest(byte[] encodedState) + { + super(encodedState); + + H1 = Pack.bigEndianToInt(encodedState, 16); + H2 = Pack.bigEndianToInt(encodedState, 20); + H3 = Pack.bigEndianToInt(encodedState, 24); + H4 = Pack.bigEndianToInt(encodedState, 28); + + xOff = Pack.bigEndianToInt(encodedState, 32); + for (int i = 0; i != xOff; i++) + { + X[i] = Pack.bigEndianToInt(encodedState, 36 + (i * 4)); + } + } + /** * Copy constructor. This will copy the state of the provided * message digest. @@ -320,4 +338,24 @@ public class MD5Digest copyIn(d); } + + public byte[] getEncodedState() + { + byte[] state = new byte[36 + xOff * 4]; + + super.populateState(state); + + Pack.intToBigEndian(H1, state, 16); + Pack.intToBigEndian(H2, state, 20); + Pack.intToBigEndian(H3, state, 24); + Pack.intToBigEndian(H4, state, 28); + Pack.intToBigEndian(xOff, state, 32); + + for (int i = 0; i != xOff; i++) + { + Pack.intToBigEndian(X[i], state, 36 + (i * 4)); + } + + return state; + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java index 450dda46..b81e7c0a 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA1Digest.java @@ -39,6 +39,11 @@ public class SHA1Digest copyIn(t); } + /** + * State constructor - create a digest initialised with the state of a previous one. + * + * @param encodedState the encoded state from the originating digest. + */ public SHA1Digest(byte[] encodedState) { super(encodedState); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java index 4f2b2842..c0fbd456 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA224Digest.java @@ -63,6 +63,11 @@ public class SHA224Digest xOff = t.xOff; } + /** + * State constructor - create a digest initialised with the state of a previous one. + * + * @param encodedState the encoded state from the originating digest. + */ public SHA224Digest(byte[] encodedState) { super(encodedState); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java index 600d2343..c6e3d283 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA256Digest.java @@ -63,6 +63,11 @@ public class SHA256Digest xOff = t.xOff; } + /** + * State constructor - create a digest initialised with the state of a previous one. + * + * @param encodedState the encoded state from the originating digest. + */ public SHA256Digest(byte[] encodedState) { super(encodedState); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java index fc9fa1e7..0c814b11 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA384Digest.java @@ -36,6 +36,11 @@ public class SHA384Digest super(t); } + /** + * State constructor - create a digest initialised with the state of a previous one. + * + * @param encodedState the encoded state from the originating digest. + */ public SHA384Digest(byte[] encodedState) { restoreState(encodedState); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java index 644bafad..dea3d88e 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/digests/SHA512Digest.java @@ -36,6 +36,11 @@ public class SHA512Digest super(t); } + /** + * State constructor - create a digest initialised with the state of a previous one. + * + * @param encodedState the encoded state from the originating digest. + */ public SHA512Digest(byte[] encodedState) { restoreState(encodedState); diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java index 4dbfbffd..b5505f43 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/OAEPEncoding.java @@ -4,12 +4,17 @@ import java.security.SecureRandom; import org.bouncycastle.crypto.AsymmetricBlockCipher; import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.InvalidCipherTextException; // BEGIN android-changed import org.bouncycastle.crypto.digests.AndroidDigestFactory; // END android-changed import org.bouncycastle.crypto.params.ParametersWithRandom; +// BEGIN android-removed +// import org.bouncycastle.crypto.util.DigestFactory; +// END android-remnoved +import org.bouncycastle.util.Arrays; /** * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2. @@ -28,6 +33,7 @@ public class OAEPEncoding AsymmetricBlockCipher cipher) { // BEGIN android-changed + // Was: this(cipher, DigestFactory.createSHA1(), null); this(cipher, AndroidDigestFactory.getSHA1(), null); // END android-changed } @@ -142,6 +148,11 @@ public class OAEPEncoding int inLen) throws InvalidCipherTextException { + if (inLen > getInputBlockSize()) + { + throw new DataLengthException("input data too long"); + } + byte[] block = new byte[getInputBlockSize() + 1 + 2 * defHash.length]; // @@ -210,28 +221,17 @@ public class OAEPEncoding throws InvalidCipherTextException { byte[] data = engine.processBlock(in, inOff, inLen); - byte[] block; + byte[] block = new byte[engine.getOutputBlockSize()]; // // as we may have zeros in our leading bytes for the block we produced // on encryption, we need to make sure our decrypted block comes back // the same size. // - if (data.length < engine.getOutputBlockSize()) - { - block = new byte[engine.getOutputBlockSize()]; - System.arraycopy(data, 0, block, block.length - data.length, data.length); - } - else - { - block = data; - } + System.arraycopy(data, 0, block, block.length - data.length, data.length); - if (block.length < (2 * defHash.length) + 1) - { - throw new InvalidCipherTextException("data too short"); - } + boolean shortData = (block.length < (2 * defHash.length) + 1); // // unmask the seed. @@ -268,31 +268,29 @@ public class OAEPEncoding } } - if (defHashWrong) - { - throw new InvalidCipherTextException("data hash wrong"); - } - // // find the data block // - int start; + int start = block.length; - for (start = 2 * defHash.length; start != block.length; start++) + for (int index = 2 * defHash.length; index != block.length; index++) { - if (block[start] != 0) + if (block[index] != 0 & start == block.length) { - break; + start = index; } } - if (start >= (block.length - 1) || block[start] != 1) - { - throw new InvalidCipherTextException("data start wrong " + start); - } + boolean dataStartWrong = (start > (block.length - 1) | block[start] != 1); start++; + if (defHashWrong | shortData | dataStartWrong) + { + Arrays.fill(block, (byte)0); + throw new InvalidCipherTextException("data wrong"); + } + // // extract the data block // diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java index 71ca7f7d..b36ae58c 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java @@ -9,6 +9,7 @@ import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.ParametersWithRandom; +import org.bouncycastle.util.Arrays; /** * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this @@ -34,33 +35,35 @@ public class PKCS1Encoding private static final int HEADER_LENGTH = 10; - private SecureRandom random; - private AsymmetricBlockCipher engine; - private boolean forEncryption; - private boolean forPrivateKey; - private boolean useStrictLength; - private int pLen = -1; - private byte[] fallback = null; + private SecureRandom random; + private AsymmetricBlockCipher engine; + private boolean forEncryption; + private boolean forPrivateKey; + private boolean useStrictLength; + private int pLen = -1; + private byte[] fallback = null; + private byte[] blockBuffer; /** * Basic constructor. + * * @param cipher */ public PKCS1Encoding( - AsymmetricBlockCipher cipher) + AsymmetricBlockCipher cipher) { this.engine = cipher; this.useStrictLength = useStrict(); - } + } /** * Constructor for decryption with a fixed plaintext length. - * + * * @param cipher The cipher to use for cryptographic operation. - * @param pLen Length of the expected plaintext. + * @param pLen Length of the expected plaintext. */ public PKCS1Encoding( - AsymmetricBlockCipher cipher, + AsymmetricBlockCipher cipher, int pLen) { this.engine = cipher; @@ -68,27 +71,24 @@ public class PKCS1Encoding this.pLen = pLen; } - /** - * Constructor for decryption with a fixed plaintext length and a fallback - * value that is returned, if the padding is incorrect. - * - * @param cipher - * The cipher to use for cryptographic operation. - * @param fallback - * The fallback value, we don't do an arraycopy here. - */ - public PKCS1Encoding( - AsymmetricBlockCipher cipher, + /** + * Constructor for decryption with a fixed plaintext length and a fallback + * value that is returned, if the padding is incorrect. + * + * @param cipher The cipher to use for cryptographic operation. + * @param fallback The fallback value, we don't do an arraycopy here. + */ + public PKCS1Encoding( + AsymmetricBlockCipher cipher, byte[] fallback) { - this.engine = cipher; - this.useStrictLength = useStrict(); - this.fallback = fallback; - this.pLen = fallback.length; + this.engine = cipher; + this.useStrictLength = useStrict(); + this.fallback = fallback; + this.pLen = fallback.length; } - - + // // for J2ME compatibility // @@ -124,14 +124,14 @@ public class PKCS1Encoding } public void init( - boolean forEncryption, - CipherParameters param) + boolean forEncryption, + CipherParameters param) { - AsymmetricKeyParameter kParam; + AsymmetricKeyParameter kParam; if (param instanceof ParametersWithRandom) { - ParametersWithRandom rParam = (ParametersWithRandom)param; + ParametersWithRandom rParam = (ParametersWithRandom)param; this.random = rParam.getRandom(); kParam = (AsymmetricKeyParameter)rParam.getParameters(); @@ -149,11 +149,17 @@ public class PKCS1Encoding this.forPrivateKey = kParam.isPrivate(); this.forEncryption = forEncryption; + this.blockBuffer = new byte[engine.getOutputBlockSize()]; + + if (pLen > 0 && fallback == null && random == null) + { + throw new IllegalArgumentException("encoder requires random"); + } } public int getInputBlockSize() { - int baseBlockSize = engine.getInputBlockSize(); + int baseBlockSize = engine.getInputBlockSize(); if (forEncryption) { @@ -167,7 +173,7 @@ public class PKCS1Encoding public int getOutputBlockSize() { - int baseBlockSize = engine.getOutputBlockSize(); + int baseBlockSize = engine.getOutputBlockSize(); if (forEncryption) { @@ -180,9 +186,9 @@ public class PKCS1Encoding } public byte[] processBlock( - byte[] in, - int inOff, - int inLen) + byte[] in, + int inOff, + int inLen) throws InvalidCipherTextException { if (forEncryption) @@ -196,17 +202,17 @@ public class PKCS1Encoding } private byte[] encodeBlock( - byte[] in, - int inOff, - int inLen) + byte[] in, + int inOff, + int inLen) throws InvalidCipherTextException { if (inLen > getInputBlockSize()) { throw new IllegalArgumentException("input data too large"); } - - byte[] block = new byte[engine.getInputBlockSize()]; + + byte[] block = new byte[engine.getInputBlockSize()]; if (forPrivateKey) { @@ -241,62 +247,63 @@ public class PKCS1Encoding return engine.processBlock(block, 0, block.length); } - + /** * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext * for encryption. - * + * * @param encoded The Plaintext. - * @param pLen Expected length of the plaintext. + * @param pLen Expected length of the plaintext. * @return Either 0, if the encoding is correct, or -1, if it is incorrect. */ - private static int checkPkcs1Encoding(byte[] encoded, int pLen) { - int correct = 0; - /* + private static int checkPkcs1Encoding(byte[] encoded, int pLen) + { + int correct = 0; + /* * Check if the first two bytes are 0 2 */ - correct |= (encoded[0] ^ 2); + correct |= (encoded[0] ^ 2); /* * Now the padding check, check for no 0 byte in the padding */ - int plen = encoded.length - ( - pLen /* Lenght of the PMS */ - + 1 /* Final 0-byte before PMS */ - ); - - for (int i = 1; i < plen; i++) { - int tmp = encoded[i]; - tmp |= tmp >> 1; - tmp |= tmp >> 2; - tmp |= tmp >> 4; - correct |= (tmp & 1) - 1; - } + int plen = encoded.length - ( + pLen /* Lenght of the PMS */ + + 1 /* Final 0-byte before PMS */ + ); + + for (int i = 1; i < plen; i++) + { + int tmp = encoded[i]; + tmp |= tmp >> 1; + tmp |= tmp >> 2; + tmp |= tmp >> 4; + correct |= (tmp & 1) - 1; + } /* * Make sure the padding ends with a 0 byte. */ - correct |= encoded[encoded.length - (pLen +1)]; + correct |= encoded[encoded.length - (pLen + 1)]; /* * Return 0 or 1, depending on the result. */ - correct |= correct >> 1; - correct |= correct >> 2; - correct |= correct >> 4; - return ~((correct & 1) - 1); - } - + correct |= correct >> 1; + correct |= correct >> 2; + correct |= correct >> 4; + return ~((correct & 1) - 1); + } + /** * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct. - * - * @param in The encrypted block. + * + * @param in The encrypted block. * @param inOff Offset in the encrypted block. * @param inLen Length of the encrypted block. - * //@param pLen Length of the desired output. + * //@param pLen Length of the desired output. * @return The plaintext without padding, or a random value if the padding was incorrect. - * * @throws InvalidCipherTextException */ private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen) @@ -308,7 +315,7 @@ public class PKCS1Encoding } byte[] block = engine.processBlock(in, inOff, inLen); - byte[] random = null; + byte[] random; if (this.fallback == null) { random = new byte[this.pLen]; @@ -319,30 +326,12 @@ public class PKCS1Encoding random = fallback; } - /* - * TODO: This is a potential dangerous side channel. However, you can - * fix this by changing the RSA engine in a way, that it will always - * return blocks of the same length and prepend them with 0 bytes if - * needed. - */ - if (block.length < getOutputBlockSize()) - { - throw new InvalidCipherTextException("block truncated"); - } - - /* - * TODO: Potential side channel. Fix it by making the engine always - * return blocks of the correct length. - */ - if (useStrictLength && block.length != engine.getOutputBlockSize()) - { - throw new InvalidCipherTextException("block incorrect size"); - } + byte[] data = (useStrictLength & (block.length != engine.getOutputBlockSize())) ? blockBuffer : block; /* * Check the padding. */ - int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen); + int correct = PKCS1Encoding.checkPkcs1Encoding(data, this.pLen); /* * Now, to a constant time constant memory copy of the decrypted value @@ -351,52 +340,55 @@ public class PKCS1Encoding byte[] result = new byte[this.pLen]; for (int i = 0; i < this.pLen; i++) { - result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct)); + result[i] = (byte)((data[i + (data.length - pLen)] & (~correct)) | (random[i] & correct)); } + Arrays.fill(data, (byte)0); + return result; } /** - * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format. + * @throws InvalidCipherTextException if the decrypted block is not in PKCS1 format. */ private byte[] decodeBlock( - byte[] in, - int inOff, - int inLen) + byte[] in, + int inOff, + int inLen) throws InvalidCipherTextException { /* * If the length of the expected plaintext is known, we use a constant-time decryption. * If the decryption fails, we return a random value. */ - if (this.pLen != -1) + if (this.pLen != -1) { - return this.decodeBlockOrRandom(in, inOff, inLen); - } - + return this.decodeBlockOrRandom(in, inOff, inLen); + } + byte[] block = engine.processBlock(in, inOff, inLen); + boolean incorrectLength = (useStrictLength & (block.length != engine.getOutputBlockSize())); + byte[] data; if (block.length < getOutputBlockSize()) { - throw new InvalidCipherTextException("block truncated"); + data = blockBuffer; + } + else + { + data = block; } - byte type = block[0]; + byte type = data[0]; + boolean badType; if (forPrivateKey) { - if (type != 2) - { - throw new InvalidCipherTextException("unknown block type"); - } + badType = (type != 2); } else { - if (type != 1) - { - throw new InvalidCipherTextException("unknown block type"); - } + badType = (type != 1); } // BEGIN android-added if ((type == 1 && forPrivateKey) || (type == 2 && !forPrivateKey)) @@ -405,41 +397,55 @@ public class PKCS1Encoding } // END android-added - if (useStrictLength && block.length != engine.getOutputBlockSize()) - { - throw new InvalidCipherTextException("block incorrect size"); - } - // // find and extract the message block. // - int start; - - for (start = 1; start != block.length; start++) - { - byte pad = block[start]; - - if (pad == 0) - { - break; - } - if (type == 1 && pad != (byte)0xff) - { - throw new InvalidCipherTextException("block padding incorrect"); - } - } + int start = findStart(type, data); start++; // data should start at the next byte - if (start > block.length || start < HEADER_LENGTH) + if (badType | start < HEADER_LENGTH) + { + Arrays.fill(data, (byte)0); + throw new InvalidCipherTextException("block incorrect"); + } + + // if we get this far, it's likely to be a genuine encoding error + if (incorrectLength) { - throw new InvalidCipherTextException("no data in block"); + Arrays.fill(data, (byte)0); + throw new InvalidCipherTextException("block incorrect size"); } - byte[] result = new byte[block.length - start]; + byte[] result = new byte[data.length - start]; - System.arraycopy(block, start, result, 0, result.length); + System.arraycopy(data, start, result, 0, result.length); return result; } + + private int findStart(byte type, byte[] block) + throws InvalidCipherTextException + { + int start = -1; + boolean padErr = false; + + for (int i = 1; i != block.length; i++) + { + byte pad = block[i]; + + if (pad == 0 & start < 0) + { + start = i; + } + padErr |= (type == 1 & start < 0 & pad != (byte)0xff); + } + + if (padErr) + { + return -1; + } + + return start; + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java index 924dff35..021b0f7d 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java @@ -5,6 +5,7 @@ import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Pack; /** @@ -415,6 +416,8 @@ private static final int[] Tinv0 = private int C0, C1, C2, C3; private boolean forEncryption; + private byte[] s; + private static final int BLOCK_SIZE = 16; /** @@ -440,6 +443,14 @@ private static final int[] Tinv0 = { WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption); this.forEncryption = forEncryption; + if (forEncryption) + { + s = Arrays.clone(S); + } + else + { + s = Arrays.clone(Si); + } return; } @@ -578,10 +589,10 @@ private static final int[] Tinv0 = // the final round's table is a simple function of S so we don't use a whole other four tables for it - this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0]; - this.C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1]; - this.C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2]; - this.C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3]; + this.C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((s[(r2>>16)&255]&255)<<16) ^ (s[(r3>>24)&255]<<24) ^ KW[r][0]; + this.C1 = (s[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (s[(r0>>24)&255]<<24) ^ KW[r][1]; + this.C2 = (s[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2]; + this.C3 = (s[r3&255]&255) ^ ((s[(r0>>8)&255]&255)<<8) ^ ((s[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3]; } private void decryptBlock(int[][] KW) @@ -610,9 +621,9 @@ private static final int[] Tinv0 = // the final round's table is a simple function of Si so we don't use a whole other four tables for it - this.C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0]; - this.C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1]; - this.C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2]; - this.C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3]; + this.C0 = (Si[r0&255]&255) ^ ((s[(r3>>8)&255]&255)<<8) ^ ((s[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0]; + this.C1 = (s[r1&255]&255) ^ ((s[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (s[(r2>>24)&255]<<24) ^ KW[0][1]; + this.C2 = (s[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (s[(r3>>24)&255]<<24) ^ KW[0][2]; + this.C3 = (Si[r3&255]&255) ^ ((s[(r2>>8)&255]&255)<<8) ^ ((s[(r1>>16)&255]&255)<<16) ^ (s[(r0>>24)&255]<<24) ^ KW[0][3]; } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java index 11e1bce8..abb8ba8c 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESFastEngine.java @@ -26,9 +26,11 @@ import org.bouncycastle.util.Pack; * the contents of the first * * The slowest version uses no static tables at all and computes the values in each round + * </p> * <p> - * This file contains the fast version with 8Kbytes of static tables for round precomputation - * + * This file contains the fast version with 8Kbytes of static tables for round precomputation. + * </p> + * @deprecated unfortunately this class is has a few side channel issues. In an environment where encryption/decryption may be closely observed it should not be used. */ public class AESFastEngine implements BlockCipher diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java index ba75c8d7..7274bf94 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/DESedeWrapEngine.java @@ -13,6 +13,9 @@ import org.bouncycastle.crypto.modes.CBCBlockCipher; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; import org.bouncycastle.crypto.params.ParametersWithRandom; +// BEGIN android-removed +// import org.bouncycastle.crypto.util.DigestFactory; +// END android-removed import org.bouncycastle.util.Arrays; /** diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java index 61b4bea9..cec79e03 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/DSAParametersGenerator.java @@ -4,12 +4,13 @@ import java.math.BigInteger; import java.security.SecureRandom; import org.bouncycastle.crypto.Digest; -// BEGIN android-changed -import org.bouncycastle.crypto.digests.AndroidDigestFactory; -// END android-changed import org.bouncycastle.crypto.params.DSAParameterGenerationParameters; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.DSAValidationParameters; +// BEGIN android-changed +// Was: import org.bouncycastle.crypto.util.DigestFactory; +import org.bouncycastle.crypto.digests.AndroidDigestFactory; +// END android-added import org.bouncycastle.util.Arrays; import org.bouncycastle.util.BigIntegers; import org.bouncycastle.util.encoders.Hex; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java index 79ec0f24..e6ec53a0 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java @@ -5,9 +5,11 @@ import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.PBEParametersGenerator; // BEGIN android-changed import org.bouncycastle.crypto.digests.AndroidDigestFactory; -// END android-changed import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; +// BEGIN android-removed +// import org.bouncycastle.crypto.util.DigestFactory; +// END android-removed /** * Generator for PBE derived keys and ivs as usd by OpenSSL. diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java index 9a2239e2..3089f8cc 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java @@ -10,6 +10,9 @@ import org.bouncycastle.crypto.digests.AndroidDigestFactory; import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; +// BEGIN android-removed +// import org.bouncycastle.crypto.util.DigestFactory; +// END android-removed import org.bouncycastle.util.Arrays; /** diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java index ed89ef7d..54e54cec 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java @@ -38,6 +38,7 @@ public class GCMBlockCipher // These fields are set by init and not modified by processing private boolean forEncryption; private int macSize; + private byte[] lastKey; private byte[] nonce; private byte[] initialAssociatedText; private byte[] H; @@ -48,6 +49,7 @@ public class GCMBlockCipher private byte[] macBlock; private byte[] S, S_at, S_atPre; private byte[] counter; + private int blocksRemaining; private int bufOff; private long totalLength; private byte[] atBlock; @@ -99,12 +101,13 @@ public class GCMBlockCipher this.macBlock = null; KeyParameter keyParam; + byte[] newNonce = null; if (params instanceof AEADParameters) { AEADParameters param = (AEADParameters)params; - nonce = param.getNonce(); + newNonce = param.getNonce(); initialAssociatedText = param.getAssociatedText(); int macSizeBits = param.getMacSize(); @@ -120,7 +123,7 @@ public class GCMBlockCipher { ParametersWithIV param = (ParametersWithIV)params; - nonce = param.getIV(); + newNonce = param.getIV(); initialAssociatedText = null; macSize = 16; keyParam = (KeyParameter)param.getParameters(); @@ -133,11 +136,32 @@ public class GCMBlockCipher int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize); this.bufBlock = new byte[bufLength]; - if (nonce == null || nonce.length < 1) + if (newNonce == null || newNonce.length < 1) { throw new IllegalArgumentException("IV must be at least 1 byte"); } + if (forEncryption) + { + if (nonce != null && Arrays.areEqual(nonce, newNonce)) + { + if (keyParam == null) + { + throw new IllegalArgumentException("cannot reuse nonce for GCM encryption"); + } + if (lastKey != null && Arrays.areEqual(lastKey, keyParam.getKey())) + { + throw new IllegalArgumentException("cannot reuse nonce for GCM encryption"); + } + } + } + + nonce = newNonce; + if (keyParam != null) + { + lastKey = keyParam.getKey(); + } + // TODO Restrict macSize to 16 if nonce length not 12? // Cipher always used in forward mode @@ -181,6 +205,7 @@ public class GCMBlockCipher this.atLength = 0; this.atLengthPre = 0; this.counter = Arrays.clone(J0); + this.blocksRemaining = -2; // page 8, len(P) <= 2^39 - 256, 1 block used by tag but done on J0 this.bufOff = 0; this.totalLength = 0; @@ -192,6 +217,10 @@ public class GCMBlockCipher public byte[] getMac() { + if (macBlock == null) + { + return new byte[macSize]; + } return Arrays.clone(macBlock); } @@ -481,6 +510,8 @@ public class GCMBlockCipher { cipher.reset(); + // note: we do not reset the nonce. + S = new byte[BLOCK_SIZE]; S_at = new byte[BLOCK_SIZE]; S_atPre = new byte[BLOCK_SIZE]; @@ -489,6 +520,7 @@ public class GCMBlockCipher atLength = 0; atLengthPre = 0; counter = Arrays.clone(J0); + blocksRemaining = -2; bufOff = 0; totalLength = 0; @@ -555,6 +587,12 @@ public class GCMBlockCipher private byte[] getNextCounterBlock() { + if (blocksRemaining == 0) + { + throw new IllegalStateException("Attempt to process too many blocks"); + } + blocksRemaining--; + int c = 1; c += counter[15] & 0xFF; counter[15] = (byte)c; c >>>= 8; c += counter[14] & 0xFF; counter[14] = (byte)c; c >>>= 8; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHPublicKeyParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHPublicKeyParameters.java index ed531603..ba392ab1 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHPublicKeyParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHPublicKeyParameters.java @@ -5,6 +5,9 @@ import java.math.BigInteger; public class DHPublicKeyParameters extends DHKeyParameters { + private static final BigInteger ONE = BigInteger.valueOf(1); + private static final BigInteger TWO = BigInteger.valueOf(2); + private BigInteger y; public DHPublicKeyParameters( @@ -13,9 +16,37 @@ public class DHPublicKeyParameters { super(false, params); - this.y = y; + this.y = validate(y, params); } + private BigInteger validate(BigInteger y, DHParameters dhParams) + { + if (y == null) + { + throw new NullPointerException("y value cannot be null"); + } + + // TLS check + if (y.compareTo(TWO) < 0 || y.compareTo(dhParams.getP().subtract(TWO)) > 0) + { + throw new IllegalArgumentException("invalid DH public key"); + } + + if (dhParams.getQ() != null) + { + if (ONE.equals(y.modPow(dhParams.getQ(), dhParams.getP()))) + { + return y; + } + + throw new IllegalArgumentException("Y value does not appear to be in correct group"); + } + else + { + return y; // we can't validate without Q. + } + } + public BigInteger getY() { return y; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java index c0066568..5786ee36 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java @@ -5,6 +5,9 @@ import java.math.BigInteger; public class DSAPublicKeyParameters extends DSAKeyParameters { + private static final BigInteger ONE = BigInteger.valueOf(1); + private static final BigInteger TWO = BigInteger.valueOf(2); + private BigInteger y; public DSAPublicKeyParameters( @@ -13,9 +16,27 @@ public class DSAPublicKeyParameters { super(false, params); - this.y = y; + this.y = validate(y, params); } + private BigInteger validate(BigInteger y, DSAParameters params) + { + if (params != null) + { + if (TWO.compareTo(y) <= 0 && params.getP().subtract(TWO).compareTo(y) >= 0 + && ONE.equals(y.modPow(params.getQ(), params.getP()))) + { + return y; + } + + throw new IllegalArgumentException("y value does not appear to be in correct group"); + } + else + { + return y; // we can't validate without params, fortunately we can't use the key either... + } + } + public BigInteger getY() { return y; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java index 9cc6e727..c97f2e76 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECDomainParameters.java @@ -71,4 +71,34 @@ public class ECDomainParameters { return Arrays.clone(seed); } + + public boolean equals( + Object obj) + { + if (this == obj) + { + return true; + } + + if ((obj instanceof ECDomainParameters)) + { + ECDomainParameters other = (ECDomainParameters)obj; + + return this.curve.equals(other.curve) && this.G.equals(other.G) && this.n.equals(other.n) && this.h.equals(other.h); + } + + return false; + } + + public int hashCode() + { + int hc = curve.hashCode(); + hc *= 37; + hc ^= G.hashCode(); + hc *= 37; + hc ^= n.hashCode(); + hc *= 37; + hc ^= h.hashCode(); + return hc; + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java index b6b3fb6d..036bf4ae 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ECPublicKeyParameters.java @@ -5,14 +5,37 @@ import org.bouncycastle.math.ec.ECPoint; public class ECPublicKeyParameters extends ECKeyParameters { - ECPoint Q; + private final ECPoint Q; public ECPublicKeyParameters( ECPoint Q, ECDomainParameters params) { super(false, params); - this.Q = Q.normalize(); + + this.Q = validate(Q); + } + + private ECPoint validate(ECPoint q) + { + if (q == null) + { + throw new IllegalArgumentException("point has null value"); + } + + if (q.isInfinity()) + { + throw new IllegalArgumentException("point at infinity"); + } + + q = q.normalize(); + + if (!q.isValid()) + { + throw new IllegalArgumentException("point not on curve"); + } + + return q; } public ECPoint getQ() diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/RSAKeyParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/RSAKeyParameters.java index 4a2d9354..c357843e 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/params/RSAKeyParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/RSAKeyParameters.java @@ -5,6 +5,8 @@ import java.math.BigInteger; public class RSAKeyParameters extends AsymmetricKeyParameter { + private static final BigInteger ONE = BigInteger.valueOf(1); + private BigInteger modulus; private BigInteger exponent; @@ -15,10 +17,40 @@ public class RSAKeyParameters { super(isPrivate); - this.modulus = modulus; + if (!isPrivate) + { + if ((exponent.intValue() & 1) == 0) + { + throw new IllegalArgumentException("RSA publicExponent is even"); + } + } + + this.modulus = validate(modulus); this.exponent = exponent; } + private BigInteger validate(BigInteger modulus) + { + if ((modulus.intValue() & 1) == 0) + { + throw new IllegalArgumentException("RSA modulus is even"); + } + + // the value is the product of the 132 smallest primes from 3 to 751 + if (!modulus.gcd(new BigInteger("145188775577763990151158743208307020242261438098488931355057091965" + + "931517706595657435907891265414916764399268423699130577757433083166" + + "651158914570105971074227669275788291575622090199821297575654322355" + + "049043101306108213104080801056529374892690144291505781966373045481" + + "8359472391642885328171302299245556663073719855")).equals(ONE)) + { + throw new IllegalArgumentException("RSA modulus has a small prime factor"); + } + + // TODO: add additional primePower/Composite test - expensive!! + + return modulus; + } + public BigInteger getModulus() { return modulus; diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java index 44f838b2..920611bc 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java @@ -95,7 +95,8 @@ public class DSASigner BigInteger k = kCalculator.nextK(); - BigInteger r = params.getG().modPow(k, params.getP()).mod(q); + // the randomizer is to conceal timing information related to k and x. + BigInteger r = params.getG().modPow(k.add(getRandomizer(q, random)), params.getP()).mod(q); k = k.modInverse(q).multiply(m.add(x.multiply(r))); @@ -163,4 +164,12 @@ public class DSASigner { return !needed ? null : (provided != null) ? provided : new SecureRandom(); } + + private BigInteger getRandomizer(BigInteger q, SecureRandom provided) + { + // Calculate a random multiple of q to add to k. Note that g^q = 1 (mod p), so adding multiple of q to k does not change r. + int randomBits = 7; + + return new BigInteger(randomBits, provided != null ? provided : new SecureRandom()).add(BigInteger.valueOf(128)).multiply(q); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateType.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateType.java new file mode 100644 index 00000000..5dc503eb --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/CertificateType.java @@ -0,0 +1,15 @@ +package org.bouncycastle.crypto.tls; + +/** + * RFC 6091 + */ +public class CertificateType +{ + public static final short X509 = 0; + public static final short OpenPGP = 1; + + /* + * RFC 7250 + */ + public static final short RawPublicKey = 2; +} diff --git a/bcprov/src/main/java/org/bouncycastle/iana/AEADAlgorithm.java b/bcprov/src/main/java/org/bouncycastle/iana/AEADAlgorithm.java new file mode 100644 index 00000000..c289b6a3 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/iana/AEADAlgorithm.java @@ -0,0 +1,57 @@ +package org.bouncycastle.iana; + +/** + * RFC 5116 + */ +public class AEADAlgorithm +{ + public static final int AEAD_AES_128_GCM = 1; + public static final int AEAD_AES_256_GCM = 2; + public static final int AEAD_AES_128_CCM = 3; + public static final int AEAD_AES_256_CCM = 4; + + /* + * RFC 5282 + */ + public static final int AEAD_AES_128_GCM_8 = 5; + public static final int AEAD_AES_256_GCM_8 = 6; + public static final int AEAD_AES_128_GCM_12 = 7; + public static final int AEAD_AES_256_GCM_12 = 8; + public static final int AEAD_AES_128_CCM_SHORT = 9; + public static final int AEAD_AES_256_CCM_SHORT = 10; + public static final int AEAD_AES_128_CCM_SHORT_8 = 11; + public static final int AEAD_AES_256_CCM_SHORT_8 = 12; + public static final int AEAD_AES_128_CCM_SHORT_12 = 13; + public static final int AEAD_AES_256_CCM_SHORT_12 = 14; + + /* + * RFC 5297 + */ + public static final int AEAD_AES_SIV_CMAC_256 = 15; + public static final int AEAD_AES_SIV_CMAC_384 = 16; + public static final int AEAD_AES_SIV_CMAC_512 = 17; + + /* + * RFC 6655 + */ + public static final int AEAD_AES_128_CCM_8 = 18; + public static final int AEAD_AES_256_CCM_8 = 19; + + /* + * RFC 7253 + */ + public static final int AEAD_AES_128_OCB_TAGLEN128 = 20; + public static final int AEAD_AES_128_OCB_TAGLEN96 = 21; + public static final int AEAD_AES_128_OCB_TAGLEN64 = 22; + public static final int AEAD_AES_192_OCB_TAGLEN128 = 23; + public static final int AEAD_AES_192_OCB_TAGLEN96 = 24; + public static final int AEAD_AES_192_OCB_TAGLEN64 = 25; + public static final int AEAD_AES_256_OCB_TAGLEN128 = 26; + public static final int AEAD_AES_256_OCB_TAGLEN96 = 27; + public static final int AEAD_AES_256_OCB_TAGLEN64 = 28; + + /* + * RFC 7539 + */ + public static final int AEAD_CHACHA20_POLY1305 = 29; +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12Key.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12Key.java index db63ecdb..856b3e5b 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12Key.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12Key.java @@ -29,6 +29,11 @@ public class PKCS12Key */ public PKCS12Key(char[] password, boolean useWrongZeroLengthConversion) { + if (password == null) + { + password = new char[0]; + } + this.password = new char[password.length]; this.useWrongZeroLengthConversion = useWrongZeroLengthConversion; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java index 889d957d..da326f47 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java @@ -41,14 +41,14 @@ public class DH // BEGIN android-removed // provider.addAlgorithm("Cipher.IES", PREFIX + "IESCipher$IES"); - // provider.addAlgorithm("Cipher.IESwithAES", PREFIX + "IESCipher$IESwithAES"); - // provider.addAlgorithm("Cipher.IESWITHAES", PREFIX + "IESCipher$IESwithAES"); - // provider.addAlgorithm("Cipher.IESWITHDESEDE", PREFIX + "IESCipher$IESwithDESede"); + // provider.addAlgorithm("Cipher.IESwithAES-CBC", PREFIX + "IESCipher$IESwithAES"); + // provider.addAlgorithm("Cipher.IESWITHAES-CBC", PREFIX + "IESCipher$IESwithAES"); + // provider.addAlgorithm("Cipher.IESWITHDESEDE-CBC", PREFIX + "IESCipher$IESwithDESede"); // // provider.addAlgorithm("Cipher.DHIES", PREFIX + "IESCipher$IES"); - // provider.addAlgorithm("Cipher.DHIESwithAES", PREFIX + "IESCipher$IESwithAES"); - // provider.addAlgorithm("Cipher.DHIESWITHAES", PREFIX + "IESCipher$IESwithAES"); - // provider.addAlgorithm("Cipher.DHIESWITHDESEDE", PREFIX + "IESCipher$IESwithDESede"); + // provider.addAlgorithm("Cipher.DHIESwithAES-CBC", PREFIX + "IESCipher$IESwithAES"); + // provider.addAlgorithm("Cipher.DHIESWITHAES-CBC", PREFIX + "IESCipher$IESwithAES"); + // provider.addAlgorithm("Cipher.DHIESWITHDESEDE-CBC", PREFIX + "IESCipher$IESwithDESede"); // // provider.addAlgorithm("Cipher.OLDDHIES", PREFIX + "IESCipher$OldIES"); // provider.addAlgorithm("Cipher.OLDDHIESwithAES", PREFIX + "IESCipher$OldIESwithAES"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java index 7c402f3d..92581f47 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DSA.java @@ -41,6 +41,17 @@ public class DSA // provider.addAlgorithm("Signature.SHA256WITHDETDSA", PREFIX + "DSASigner$detDSA256"); // provider.addAlgorithm("Signature.SHA384WITHDETDSA", PREFIX + "DSASigner$detDSA384"); // provider.addAlgorithm("Signature.SHA512WITHDETDSA", PREFIX + "DSASigner$detDSA512"); + + // provider.addAlgorithm("Signature.DDSA", PREFIX + "DSASigner$detDSA"); + // provider.addAlgorithm("Signature.SHA1WITHDDSA", PREFIX + "DSASigner$detDSA"); + // provider.addAlgorithm("Signature.SHA224WITHDDSA", PREFIX + "DSASigner$detDSA224"); + // provider.addAlgorithm("Signature.SHA256WITHDDSA", PREFIX + "DSASigner$detDSA256"); + // provider.addAlgorithm("Signature.SHA384WITHDDSA", PREFIX + "DSASigner$detDSA384"); + // provider.addAlgorithm("Signature.SHA512WITHDDSA", PREFIX + "DSASigner$detDSA512"); + // provider.addAlgorithm("Signature.SHA3-224WITHDDSA", PREFIX + "DSASigner$detDSASha3_224"); + // provider.addAlgorithm("Signature.SHA3-256WITHDDSA", PREFIX + "DSASigner$detDSASha3_256"); + // provider.addAlgorithm("Signature.SHA3-384WITHDDSA", PREFIX + "DSASigner$detDSASha3_384"); + // provider.addAlgorithm("Signature.SHA3-512WITHDDSA", PREFIX + "DSASigner$detDSASha3_512"); // END android-removed addSignatureAlgorithm(provider, "SHA224", "DSA", PREFIX + "DSASigner$dsa224", NISTObjectIdentifiers.dsa_with_sha224); @@ -53,6 +64,14 @@ public class DSA // BEGIN android-added provider.addAlgorithm("Alg.Alias.Signature.DSA", "SHA1withDSA"); // END android-added + + // BEGIN android-removed + // addSignatureAlgorithm(provider, "SHA3-224", "DSA", PREFIX + "DSASigner$dsaSha3_224", NISTObjectIdentifiers.id_dsa_with_sha3_224); + // addSignatureAlgorithm(provider, "SHA3-256", "DSA", PREFIX + "DSASigner$dsaSha3_256", NISTObjectIdentifiers.id_dsa_with_sha3_256); + // addSignatureAlgorithm(provider, "SHA3-384", "DSA", PREFIX + "DSASigner$dsaSha3_384", NISTObjectIdentifiers.id_dsa_with_sha3_384); + // addSignatureAlgorithm(provider, "SHA3-512", "DSA", PREFIX + "DSASigner$dsaSha3_512", NISTObjectIdentifiers.id_dsa_with_sha3_512); + // END android-removed + // BEGIN android-changed provider.addAlgorithm("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA"); provider.addAlgorithm("Alg.Alias.Signature.SHA1withDSA", "SHA1withDSA"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java index 99a27bf8..17e805be 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java @@ -3,6 +3,7 @@ package org.bouncycastle.jcajce.provider.asymmetric; // BEGIN android-removed // import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers; // import org.bouncycastle.asn1.eac.EACObjectIdentifiers; +// import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; // import org.bouncycastle.asn1.sec.SECObjectIdentifiers; // import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; // END android-removed @@ -160,24 +161,13 @@ public class EC // provider.addAlgorithm("KeyPairGenerator.ECIES", PREFIX + "KeyPairGeneratorSpi$ECDH"); // // provider.addAlgorithm("Cipher.ECIES", PREFIX + "IESCipher$ECIES"); - // provider.addAlgorithm("Cipher.ECIESwithAES", PREFIX + "IESCipher$ECIESwithAES"); - // provider.addAlgorithm("Cipher.ECIESWITHAES", PREFIX + "IESCipher$ECIESwithAES"); - // provider.addAlgorithm("Cipher.ECIESwithDESEDE", PREFIX + "IESCipher$ECIESwithDESede"); - // provider.addAlgorithm("Cipher.ECIESWITHDESEDE", PREFIX + "IESCipher$ECIESwithDESede"); + // // provider.addAlgorithm("Cipher.ECIESwithAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC"); // provider.addAlgorithm("Cipher.ECIESWITHAES-CBC", PREFIX + "IESCipher$ECIESwithAESCBC"); // provider.addAlgorithm("Cipher.ECIESwithDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC"); // provider.addAlgorithm("Cipher.ECIESWITHDESEDE-CBC", PREFIX + "IESCipher$ECIESwithDESedeCBC"); // - // provider.addAlgorithm("Cipher.OldECIES", PREFIX + "IESCipher$OldECIES"); - // provider.addAlgorithm("Cipher.OldECIESwithAES", PREFIX + "IESCipher$OldECIESwithAES"); - // provider.addAlgorithm("Cipher.OldECIESWITHAES", PREFIX + "IESCipher$OldECIESwithAES"); - // provider.addAlgorithm("Cipher.OldECIESwithDESEDE", PREFIX + "IESCipher$OldECIESwithDESede"); - // provider.addAlgorithm("Cipher.OldECIESWITHDESEDE", PREFIX + "IESCipher$OldECIESwithDESede"); - // provider.addAlgorithm("Cipher.OldECIESwithAES-CBC", PREFIX + "IESCipher$OldECIESwithAESCBC"); - // provider.addAlgorithm("Cipher.OldECIESWITHAES-CBC", PREFIX + "IESCipher$OldECIESwithAESCBC"); - // provider.addAlgorithm("Cipher.OldECIESwithDESEDE-CBC", PREFIX + "IESCipher$OldECIESwithDESedeCBC"); - // provider.addAlgorithm("Cipher.OldECIESWITHDESEDE-CBC", PREFIX + "IESCipher$OldECIESwithDESedeCBC"); + // provider.addAlgorithm("Signature.ECDSA", PREFIX + "SignatureSpi$ecDSA"); // END android-removed // BEGIN android-changed @@ -201,7 +191,11 @@ public class EC // provider.addAlgorithm("Signature.SHA256WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSA256"); // provider.addAlgorithm("Signature.SHA384WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSA384"); // provider.addAlgorithm("Signature.SHA512WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSA512"); - // + // provider.addAlgorithm("Signature.SHA3-224WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSASha3_224"); + // provider.addAlgorithm("Signature.SHA3-256WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSASha3_256"); + // provider.addAlgorithm("Signature.SHA3-384WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSASha3_384"); + // provider.addAlgorithm("Signature.SHA3-512WITHECDDSA", PREFIX + "SignatureSpi$ecDetDSASha3_512"); + // provider.addAlgorithm("Alg.Alias.Signature.DETECDSA", "ECDDSA"); // provider.addAlgorithm("Alg.Alias.Signature.SHA1WITHDETECDSA", "SHA1WITHECDDSA"); // provider.addAlgorithm("Alg.Alias.Signature.SHA224WITHDETECDSA", "SHA224WITHECDDSA"); @@ -215,6 +209,11 @@ public class EC addSignatureAlgorithm(provider, "SHA384", "ECDSA", PREFIX + "SignatureSpi$ecDSA384", X9ObjectIdentifiers.ecdsa_with_SHA384); addSignatureAlgorithm(provider, "SHA512", "ECDSA", PREFIX + "SignatureSpi$ecDSA512", X9ObjectIdentifiers.ecdsa_with_SHA512); // BEGIN android-removed + // addSignatureAlgorithm(provider, "SHA3-224", "ECDSA", PREFIX + "SignatureSpi$ecDSASha3_224", NISTObjectIdentifiers.id_ecdsa_with_sha3_224); + // addSignatureAlgorithm(provider, "SHA3-256", "ECDSA", PREFIX + "SignatureSpi$ecDSASha3_256", NISTObjectIdentifiers.id_ecdsa_with_sha3_256); + // addSignatureAlgorithm(provider, "SHA3-384", "ECDSA", PREFIX + "SignatureSpi$ecDSASha3_384", NISTObjectIdentifiers.id_ecdsa_with_sha3_384); + // addSignatureAlgorithm(provider, "SHA3-512", "ECDSA", PREFIX + "SignatureSpi$ecDSASha3_512", NISTObjectIdentifiers.id_ecdsa_with_sha3_512); + // // addSignatureAlgorithm(provider, "RIPEMD160", "ECDSA", PREFIX + "SignatureSpi$ecDSARipeMD160",TeleTrusTObjectIdentifiers.ecSignWithRipemd160); // // provider.addAlgorithm("Signature.SHA1WITHECNR", PREFIX + "SignatureSpi$ecNR"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java index 5098c33d..20899c91 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/RSA.java @@ -1,6 +1,7 @@ package org.bouncycastle.jcajce.provider.asymmetric; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; // BEGIN android-removed @@ -108,6 +109,11 @@ public class RSA // addPSSSignature(provider, "SHA512(224)", PREFIX + "PSSSignatureSpi$SHA512_224withRSA"); // addPSSSignature(provider, "SHA512(256)", PREFIX + "PSSSignatureSpi$SHA512_256withRSA"); // + // addPSSSignature(provider, "SHA3-224", PREFIX + "PSSSignatureSpi$SHA3_224withRSA"); + // addPSSSignature(provider, "SHA3-256", PREFIX + "PSSSignatureSpi$SHA3_256withRSA"); + // addPSSSignature(provider, "SHA3-384", PREFIX + "PSSSignatureSpi$SHA3_384withRSA"); + // addPSSSignature(provider, "SHA3-512", PREFIX + "PSSSignatureSpi$SHA3_512withRSA"); + // // if (provider.hasAlgorithm("MessageDigest", "MD2")) // { // addDigestSignature(provider, "MD2", PREFIX + "DigestSignatureSpi$MD2", PKCSObjectIdentifiers.md2WithRSAEncryption); @@ -152,11 +158,15 @@ public class RSA addDigestSignature(provider, "SHA256", PREFIX + "DigestSignatureSpi$SHA256", PKCSObjectIdentifiers.sha256WithRSAEncryption); addDigestSignature(provider, "SHA384", PREFIX + "DigestSignatureSpi$SHA384", PKCSObjectIdentifiers.sha384WithRSAEncryption); addDigestSignature(provider, "SHA512", PREFIX + "DigestSignatureSpi$SHA512", PKCSObjectIdentifiers.sha512WithRSAEncryption); - // BEGIN android-removed - // addDigestSignature(provider, "SHA512(224)", PREFIX + "DigestSignatureSpi$SHA512_224", null); - // addDigestSignature(provider, "SHA512(256)", PREFIX + "DigestSignatureSpi$SHA512_256", null); - + // addDigestSignature(provider, "SHA512(224)", PREFIX + "DigestSignatureSpi$SHA512_224", PKCSObjectIdentifiers.sha512_224WithRSAEncryption); + // addDigestSignature(provider, "SHA512(256)", PREFIX + "DigestSignatureSpi$SHA512_256", PKCSObjectIdentifiers.sha512_256WithRSAEncryption); + // + // addDigestSignature(provider, "SHA3-224", PREFIX + "DigestSignatureSpi$SHA3_224", NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_224); + // addDigestSignature(provider, "SHA3-256", PREFIX + "DigestSignatureSpi$SHA3_256", NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_256); + // addDigestSignature(provider, "SHA3-384", PREFIX + "DigestSignatureSpi$SHA3_384", NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_384); + // addDigestSignature(provider, "SHA3-512", PREFIX + "DigestSignatureSpi$SHA3_512", NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_512); + // // addISO9796Signature(provider, "SHA224", PREFIX + "ISOSignatureSpi$SHA224WithRSAEncryption"); // addISO9796Signature(provider, "SHA256", PREFIX + "ISOSignatureSpi$SHA256WithRSAEncryption"); // addISO9796Signature(provider, "SHA384", PREFIX + "ISOSignatureSpi$SHA384WithRSAEncryption"); @@ -173,38 +183,24 @@ public class RSA // // if (provider.hasAlgorithm("MessageDigest", "RIPEMD128")) // { - // addDigestSignature(provider, "RIPEMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); - // addDigestSignature(provider, "RMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", null); - // provider.addAlgorithm("Alg.Alias.Signature.RIPEMD128withRSA/X9.31", "RIPEMD128WITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.RIPEMD128WithRSA/X9.31", "RIPEMD128WITHRSA/X9.31"); - // provider.addAlgorithm("Signature.RIPEMD128WITHRSA/X9.31", PREFIX + "X931SignatureSpi$RIPEMD128WithRSAEncryption"); + // addDigestSignature(provider, "RIPEMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128); + // addDigestSignature(provider, "RMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", null); + // + // addX931Signature(provider, "RMD128", PREFIX + "X931SignatureSpi$RIPEMD128WithRSAEncryption"); + // addX931Signature(provider, "RIPEMD128", PREFIX + "X931SignatureSpi$RIPEMD128WithRSAEncryption"); // } - // + // // if (provider.hasAlgorithm("MessageDigest", "RIPEMD160")) // { - // addDigestSignature(provider, "RIPEMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); - // addDigestSignature(provider, "RMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", null); - // provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/ISO9796-2", "RIPEMD160withRSA/ISO9796-2"); - // provider.addAlgorithm("Signature.RIPEMD160withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$RIPEMD160WithRSAEncryption"); - // provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160withRSA/X9.31", "RIPEMD160WITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/X9.31", "RIPEMD160WITHRSA/X9.31"); - // provider.addAlgorithm("Signature.RIPEMD160WITHRSA/X9.31", PREFIX + "X931SignatureSpi$RIPEMD160WithRSAEncryption"); - // } - // - // if (provider.hasAlgorithm("MessageDigest", "RIPEMD256")) - // { - // addDigestSignature(provider, "RIPEMD256", PREFIX + "DigestSignatureSpi$RIPEMD256", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256); - // addDigestSignature(provider, "RMD256", PREFIX + "DigestSignatureSpi$RIPEMD256", null); - // } - // - // if (provider.hasAlgorithm("MessageDigest", "WHIRLPOOL")) - // { - // provider.addAlgorithm("Alg.Alias.Signature.WhirlpoolWithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.WHIRLPOOLwithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31"); - // provider.addAlgorithm("Alg.Alias.Signature.WHIRLPOOLWithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31"); - // provider.addAlgorithm("Signature.WHIRLPOOLWITHRSA/X9.31", PREFIX + "X931SignatureSpi$WhirlpoolWithRSAEncryption"); + // addDigestSignature(provider, "RIPEMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160); + // addDigestSignature(provider, "RMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", null); + // provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/ISO9796-2", "RIPEMD160withRSA/ISO9796-2"); + // provider.addAlgorithm("Signature.RIPEMD160withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$RIPEMD160WithRSAEncryption"); + // + // addX931Signature(provider, "RMD160", PREFIX + "X931SignatureSpi$RIPEMD160WithRSAEncryption"); + // addX931Signature(provider, "RIPEMD160", PREFIX + "X931SignatureSpi$RIPEMD160WithRSAEncryption"); // } - // END android-removed + // END android-removed } private void addDigestSignature( diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java index ef743095..1462a38b 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/BCDHPublicKey.java @@ -16,10 +16,12 @@ import org.bouncycastle.asn1.pkcs.DHParameter; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.asn1.x9.DHDomainParameters; import org.bouncycastle.asn1.x9.DomainParameters; +import org.bouncycastle.asn1.x9.ValidationParams; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DHPublicKeyParameters; +import org.bouncycastle.crypto.params.DHValidationParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; public class BCDHPublicKey @@ -29,6 +31,7 @@ public class BCDHPublicKey private BigInteger y; + private transient DHPublicKeyParameters dhPublicKey; private transient DHParameterSpec dhSpec; private transient SubjectPublicKeyInfo info; @@ -37,6 +40,7 @@ public class BCDHPublicKey { this.y = spec.getY(); this.dhSpec = new DHParameterSpec(spec.getP(), spec.getG()); + this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(spec.getP(), spec.getG())); } BCDHPublicKey( @@ -44,6 +48,7 @@ public class BCDHPublicKey { this.y = key.getY(); this.dhSpec = key.getParams(); + this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(dhSpec.getP(), dhSpec.getG())); } BCDHPublicKey( @@ -51,6 +56,7 @@ public class BCDHPublicKey { this.y = params.getY(); this.dhSpec = new DHParameterSpec(params.getParameters().getP(), params.getParameters().getG(), params.getParameters().getL()); + this.dhPublicKey = params; } BCDHPublicKey( @@ -59,6 +65,7 @@ public class BCDHPublicKey { this.y = y; this.dhSpec = dhSpec; + this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(dhSpec.getP(), dhSpec.getG())); } public BCDHPublicKey( @@ -94,12 +101,23 @@ public class BCDHPublicKey { this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); } + this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(dhSpec.getP(), dhSpec.getG())); } else if (id.equals(X9ObjectIdentifiers.dhpublicnumber)) { DomainParameters params = DomainParameters.getInstance(seq); this.dhSpec = new DHParameterSpec(params.getP(), params.getG()); + ValidationParams validationParams = params.getValidationParams(); + if (validationParams != null) + { + this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(params.getP(), params.getG(), params.getQ(), params.getJ(), + new DHValidationParameters(validationParams.getSeed(), validationParams.getPgenCounter().intValue()))); + } + else + { + this.dhPublicKey = new DHPublicKeyParameters(y, new DHParameters(params.getP(), params.getG(), params.getQ(), params.getJ(), null)); + } } else { @@ -137,6 +155,11 @@ public class BCDHPublicKey return y; } + public DHPublicKeyParameters engineGetKeyParameters() + { + return dhPublicKey; + } + private boolean isPKCSParam(ASN1Sequence seq) { if (seq.size() == 2) diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java index 3de8ffe5..f5e8d0ef 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyAgreementSpi.java @@ -18,8 +18,8 @@ import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.crypto.DerivationFunction; // BEGIN android-removed // import org.bouncycastle.crypto.agreement.kdf.DHKEKGenerator; +// import org.bouncycastle.crypto.util.DigestFactory; // END android-removed -import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi; import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec; @@ -31,10 +31,15 @@ import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec; public class KeyAgreementSpi extends BaseAgreementSpi { + private static final BigInteger ONE = BigInteger.valueOf(1); + private static final BigInteger TWO = BigInteger.valueOf(2); + private BigInteger x; private BigInteger p; private BigInteger g; + private BigInteger result; + public KeyAgreementSpi() { super("Diffie-Hellman", null); @@ -101,14 +106,22 @@ public class KeyAgreementSpi throw new InvalidKeyException("DHPublicKey not for this KeyAgreement!"); } - if (lastPhase) + BigInteger peerY = ((DHPublicKey)key).getY(); + if (peerY == null || peerY.compareTo(TWO) < 0 + || peerY.compareTo(p.subtract(ONE)) >= 0) { - result = ((DHPublicKey)key).getY().modPow(x, p); - return null; + throw new InvalidKeyException("Invalid DH PublicKey"); } - else + + result = peerY.modPow(x, p); + if (result.compareTo(ONE) == 0) + { + throw new InvalidKeyException("Shared key can't be 1"); + } + + if (lastPhase) { - result = ((DHPublicKey)key).getY().modPow(x, p); + return null; } return new BCDHPublicKey(result, pubKey.getParams()); @@ -216,13 +229,18 @@ public class KeyAgreementSpi this.x = this.result = privKey.getX(); } + protected byte[] calcSecret() + { + return bigIntToBytes(result); + } + // BEGIN android-removed // public static class DHwithRFC2631KDF - // extends KeyAgreementSpi + // extends KeyAgreementSpi // { - // public DHwithRFC2631KDF() + // public DHwithRFC2631KDF() // { - // super("DHwithRFC2631KDF", new DHKEKGenerator(new SHA1Digest())); + // super("DHwithRFC2631KDF", new DHKEKGenerator(DigestFactory.createSHA1())); // } // } // END android-removed diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyFactorySpi.java index 9565bd2d..32e9b496 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyFactorySpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyFactorySpi.java @@ -19,6 +19,7 @@ import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi; +import org.bouncycastle.jcajce.provider.asymmetric.util.ExtendedInvalidKeySpecException; public class KeyFactorySpi extends BaseKeyFactorySpi @@ -82,7 +83,14 @@ public class KeyFactorySpi { if (keySpec instanceof DHPublicKeySpec) { - return new BCDHPublicKey((DHPublicKeySpec)keySpec); + try + { + return new BCDHPublicKey((DHPublicKeySpec)keySpec); + } + catch (IllegalArgumentException e) + { + throw new ExtendedInvalidKeySpecException(e.getMessage(), e); + } } return super.engineGeneratePublic(keySpec); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java index 48da0203..793f7299 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/KeyPairGeneratorSpi.java @@ -42,6 +42,7 @@ public class KeyPairGeneratorSpi { this.strength = strength; this.random = random; + this.initialised = false; } public void initialize( @@ -113,7 +114,6 @@ public class KeyPairGeneratorSpi DHPublicKeyParameters pub = (DHPublicKeyParameters)pair.getPublic(); DHPrivateKeyParameters priv = (DHPrivateKeyParameters)pair.getPrivate(); - return new KeyPair(new BCDHPublicKey(pub), - new BCDHPrivateKey(priv)); + return new KeyPair(new BCDHPublicKey(pub), new BCDHPrivateKey(priv)); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java index 3a7b3121..13223cb6 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/BCDSAPublicKey.java @@ -24,15 +24,19 @@ public class BCDSAPublicKey implements DSAPublicKey { private static final long serialVersionUID = 1752452449903495175L; + private static BigInteger ZERO = BigInteger.valueOf(0); private BigInteger y; - private transient DSAParams dsaSpec; + + private transient DSAPublicKeyParameters lwKeyParams; + private transient DSAParams dsaSpec; BCDSAPublicKey( DSAPublicKeySpec spec) { this.y = spec.getY(); this.dsaSpec = new DSAParameterSpec(spec.getP(), spec.getQ(), spec.getG()); + this.lwKeyParams = new DSAPublicKeyParameters(y, DSAUtil.toDSAParameters(dsaSpec)); } BCDSAPublicKey( @@ -40,27 +44,27 @@ public class BCDSAPublicKey { this.y = key.getY(); this.dsaSpec = key.getParams(); + this.lwKeyParams = new DSAPublicKeyParameters(y, DSAUtil.toDSAParameters(dsaSpec)); } BCDSAPublicKey( DSAPublicKeyParameters params) { this.y = params.getY(); - this.dsaSpec = new DSAParameterSpec(params.getParameters().getP(), params.getParameters().getQ(), params.getParameters().getG()); - } - - BCDSAPublicKey( - BigInteger y, - DSAParameterSpec dsaSpec) - { - this.y = y; - this.dsaSpec = dsaSpec; + if (params != null) + { + this.dsaSpec = new DSAParameterSpec(params.getParameters().getP(), params.getParameters().getQ(), params.getParameters().getG()); + } + else + { + this.dsaSpec = null; + } + this.lwKeyParams = params; } public BCDSAPublicKey( SubjectPublicKeyInfo info) { - ASN1Integer derY; try @@ -80,6 +84,12 @@ public class BCDSAPublicKey this.dsaSpec = new DSAParameterSpec(params.getP(), params.getQ(), params.getG()); } + else + { + this.dsaSpec = null; + } + + this.lwKeyParams = new DSAPublicKeyParameters(y, DSAUtil.toDSAParameters(dsaSpec)); } private boolean isNotNull(ASN1Encodable parameters) @@ -97,6 +107,11 @@ public class BCDSAPublicKey return "X.509"; } + DSAPublicKeyParameters engineGetKeyParameters() + { + return lwKeyParams; + } + public byte[] getEncoded() { if (dsaSpec == null) @@ -130,8 +145,15 @@ public class BCDSAPublicKey public int hashCode() { - return this.getY().hashCode() ^ this.getParams().getG().hashCode() + if (dsaSpec != null) + { + return this.getY().hashCode() ^ this.getParams().getG().hashCode() ^ this.getParams().getP().hashCode() ^ this.getParams().getQ().hashCode(); + } + else + { + return this.getY().hashCode(); + } } public boolean equals( @@ -143,11 +165,19 @@ public class BCDSAPublicKey } DSAPublicKey other = (DSAPublicKey)o; - - return this.getY().equals(other.getY()) - && this.getParams().getG().equals(other.getParams().getG()) - && this.getParams().getP().equals(other.getParams().getP()) - && this.getParams().getQ().equals(other.getParams().getQ()); + + if (this.dsaSpec != null) + { + return this.getY().equals(other.getY()) + && other.getParams() != null + && this.getParams().getG().equals(other.getParams().getG()) + && this.getParams().getP().equals(other.getParams().getP()) + && this.getParams().getQ().equals(other.getParams().getQ()); + } + else + { + return this.getY().equals(other.getY()) && other.getParams() == null; + } } private void readObject( @@ -156,7 +186,16 @@ public class BCDSAPublicKey { in.defaultReadObject(); - this.dsaSpec = new DSAParameterSpec((BigInteger)in.readObject(), (BigInteger)in.readObject(), (BigInteger)in.readObject()); + BigInteger p = (BigInteger)in.readObject(); + if (p.equals(ZERO)) + { + this.dsaSpec = null; + } + else + { + this.dsaSpec = new DSAParameterSpec(p, (BigInteger)in.readObject(), (BigInteger)in.readObject()); + } + this.lwKeyParams = new DSAPublicKeyParameters(y, DSAUtil.toDSAParameters(dsaSpec)); } private void writeObject( @@ -165,8 +204,15 @@ public class BCDSAPublicKey { out.defaultWriteObject(); - out.writeObject(dsaSpec.getP()); - out.writeObject(dsaSpec.getQ()); - out.writeObject(dsaSpec.getG()); + if (dsaSpec == null) + { + out.writeObject(ZERO); + } + else + { + out.writeObject(dsaSpec.getP()); + out.writeObject(dsaSpec.getQ()); + out.writeObject(dsaSpec.getG()); + } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java index fead55dd..6374419f 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java @@ -8,7 +8,6 @@ import java.security.PublicKey; import java.security.SecureRandom; import java.security.SignatureException; import java.security.SignatureSpi; -import java.security.interfaces.DSAKey; import java.security.spec.AlgorithmParameterSpec; import org.bouncycastle.asn1.ASN1Encoding; @@ -17,7 +16,6 @@ import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DSA; @@ -39,8 +37,12 @@ import org.bouncycastle.crypto.params.DSAParameters; // END android-added import org.bouncycastle.crypto.params.ParametersWithRandom; // BEGIN android-removed +// import org.bouncycastle.crypto.digests.SHA1Digest; +// import org.bouncycastle.crypto.params.ParametersWithRandom; // import org.bouncycastle.crypto.signers.HMacDSAKCalculator; +// import org.bouncycastle.crypto.util.DigestFactory; // END android-removed +import org.bouncycastle.util.Arrays; public class DSASigner extends SignatureSpi @@ -62,34 +64,7 @@ public class DSASigner PublicKey publicKey) throws InvalidKeyException { - CipherParameters param; - - if (publicKey instanceof DSAKey) - { - param = DSAUtil.generatePublicKeyParameter(publicKey); - } - else - { - try - { - byte[] bytes = publicKey.getEncoded(); - - publicKey = new BCDSAPublicKey(SubjectPublicKeyInfo.getInstance(bytes)); - - if (publicKey instanceof DSAKey) - { - param = DSAUtil.generatePublicKeyParameter(publicKey); - } - else - { - throw new InvalidKeyException("can't recognise key type in DSA based signer"); - } - } - catch (Exception e) - { - throw new InvalidKeyException("can't recognise key type in DSA based signer"); - } - } + CipherParameters param = DSAUtil.generatePublicKeyParameter(publicKey); digest.reset(); signer.init(false, param); @@ -243,6 +218,15 @@ public class DSASigner throws IOException { ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding); + if (s.size() != 2) + { + throw new IOException("malformed signature"); + } + if (!Arrays.areEqual(encoding, s.getEncoded(ASN1Encoding.DER))) + { + throw new IOException("malformed signature"); + } + return new BigInteger[]{ ((ASN1Integer)s.getObjectAt(0)).getValue(), ((ASN1Integer)s.getObjectAt(1)).getValue() @@ -266,10 +250,9 @@ public class DSASigner // { // public detDSA() // { - // super(new SHA1Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA1Digest()))); + // super(DigestFactory.createSHA1(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA1()))); // } // } - // END android-removed static public class dsa224 extends DSASigner @@ -288,10 +271,9 @@ public class DSASigner // { // public detDSA224() // { - // super(new SHA224Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA224Digest()))); + // super(DigestFactory.createSHA224(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA224()))); // } // } - // END android-removed static public class dsa256 extends DSASigner @@ -303,14 +285,13 @@ public class DSASigner // END android-changed } } - // BEGIN android-removed // static public class detDSA256 // extends DSASigner // { // public detDSA256() // { - // super(new SHA256Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA256Digest()))); + // super(DigestFactory.createSHA256(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA256()))); // } // } // @@ -319,7 +300,7 @@ public class DSASigner // { // public dsa384() // { - // super(new SHA384Digest(), new org.bouncycastle.crypto.signers.DSASigner()); + // super(DigestFactory.createSHA384(), new org.bouncycastle.crypto.signers.DSASigner()); // } // } // @@ -328,7 +309,7 @@ public class DSASigner // { // public detDSA384() // { - // super(new SHA384Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA384Digest()))); + // super(DigestFactory.createSHA384(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA384()))); // } // } // @@ -337,7 +318,7 @@ public class DSASigner // { // public dsa512() // { - // super(new SHA512Digest(), new org.bouncycastle.crypto.signers.DSASigner()); + // super(DigestFactory.createSHA512(), new org.bouncycastle.crypto.signers.DSASigner()); // } // } // @@ -346,7 +327,79 @@ public class DSASigner // { // public detDSA512() // { - // super(new SHA512Digest(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(new SHA512Digest()))); + // super(DigestFactory.createSHA512(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA512()))); + // } + // } + // + // static public class dsaSha3_224 + // extends DSASigner + // { + // public dsaSha3_224() + // { + // super(DigestFactory.createSHA3_224(), new org.bouncycastle.crypto.signers.DSASigner()); + // } + // } + // + // static public class detDSASha3_224 + // extends DSASigner + // { + // public detDSASha3_224() + // { + // super(DigestFactory.createSHA3_224(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_224()))); + // } + // } + // + // static public class dsaSha3_256 + // extends DSASigner + // { + // public dsaSha3_256() + // { + // super(DigestFactory.createSHA3_256(), new org.bouncycastle.crypto.signers.DSASigner()); + // } + // } + // + // static public class detDSASha3_256 + // extends DSASigner + // { + // public detDSASha3_256() + // { + // super(DigestFactory.createSHA3_256(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_256()))); + // } + // } + // + // static public class dsaSha3_384 + // extends DSASigner + // { + // public dsaSha3_384() + // { + // super(DigestFactory.createSHA3_384(), new org.bouncycastle.crypto.signers.DSASigner()); + // } + // } + // + // static public class detDSASha3_384 + // extends DSASigner + // { + // public detDSASha3_384() + // { + // super(DigestFactory.createSHA3_384(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_384()))); + // } + // } + // + // static public class dsaSha3_512 + // extends DSASigner + // { + // public dsaSha3_512() + // { + // super(DigestFactory.createSHA3_512(), new org.bouncycastle.crypto.signers.DSASigner()); + // } + // } + // + // static public class detDSASha3_512 + // extends DSASigner + // { + // public detDSASha3_512() + // { + // super(DigestFactory.createSHA3_512(), new org.bouncycastle.crypto.signers.DSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_512()))); // } // } // END android-removed diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java index c7e2aa91..10bac464 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSAUtil.java @@ -3,11 +3,14 @@ package org.bouncycastle.jcajce.provider.asymmetric.dsa; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAParameterSpec; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.DSAParameters; @@ -43,19 +46,42 @@ public class DSAUtil return false; } + static DSAParameters toDSAParameters(DSAParams spec) + { + if (spec != null) + { + return new DSAParameters(spec.getP(), spec.getQ(), spec.getG()); + } + + return null; + } + static public AsymmetricKeyParameter generatePublicKeyParameter( PublicKey key) throws InvalidKeyException { - if (key instanceof DSAPublicKey) + if (key instanceof BCDSAPublicKey) { - DSAPublicKey k = (DSAPublicKey)key; + return ((BCDSAPublicKey)key).engineGetKeyParameters(); + } - return new DSAPublicKeyParameters(k.getY(), - new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG())); + if (key instanceof DSAPublicKey) + { + return new BCDSAPublicKey((DSAPublicKey)key).engineGetKeyParameters(); } - throw new InvalidKeyException("can't identify DSA public key: " + key.getClass().getName()); + try + { + byte[] bytes = key.getEncoded(); + + BCDSAPublicKey bckey = new BCDSAPublicKey(SubjectPublicKeyInfo.getInstance(bytes)); + + return bckey.engineGetKeyParameters(); + } + catch (Exception e) + { + throw new InvalidKeyException("can't identify DSA public key: " + key.getClass().getName()); + } } static public AsymmetricKeyParameter generatePrivateKeyParameter( diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java index a36f3dd7..7816320d 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyFactorySpi.java @@ -109,7 +109,20 @@ public class KeyFactorySpi { if (keySpec instanceof DSAPublicKeySpec) { - return new BCDSAPublicKey((DSAPublicKeySpec)keySpec); + try + { + return new BCDSAPublicKey((DSAPublicKeySpec)keySpec); + } + catch (final Exception e) + { + throw new InvalidKeySpecException("invalid KeySpec: " + e.getMessage()) + { + public Throwable getCause() + { + return e; + } + }; + } } return super.engineGeneratePublic(keySpec); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java index d2c2c712..bacbb6c2 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/KeyPairGeneratorSpi.java @@ -6,18 +6,26 @@ import java.security.KeyPair; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.DSAParameterSpec; +import java.util.Hashtable; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.digests.SHA256Digest; import org.bouncycastle.crypto.generators.DSAKeyPairGenerator; import org.bouncycastle.crypto.generators.DSAParametersGenerator; import org.bouncycastle.crypto.params.DSAKeyGenerationParameters; +import org.bouncycastle.crypto.params.DSAParameterGenerationParameters; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.crypto.params.DSAPrivateKeyParameters; import org.bouncycastle.crypto.params.DSAPublicKeyParameters; +import org.bouncycastle.util.Integers; +import org.bouncycastle.util.Properties; public class KeyPairGeneratorSpi extends java.security.KeyPairGenerator { + private static Hashtable params = new Hashtable(); + private static Object lock = new Object(); + DSAKeyGenerationParameters param; DSAKeyPairGenerator engine = new DSAKeyPairGenerator(); int strength = 1024; @@ -41,6 +49,7 @@ public class KeyPairGeneratorSpi this.strength = strength; this.random = random; + this.initialised = false; } public void initialize( @@ -64,10 +73,65 @@ public class KeyPairGeneratorSpi { if (!initialised) { - DSAParametersGenerator pGen = new DSAParametersGenerator(); + Integer paramStrength = Integers.valueOf(strength); + + if (params.containsKey(paramStrength)) + { + param = (DSAKeyGenerationParameters)params.get(paramStrength); + } + else + { + synchronized (lock) + { + // we do the check again in case we were blocked by a generator for + // our key size. + if (params.containsKey(paramStrength)) + { + param = (DSAKeyGenerationParameters)params.get(paramStrength); + } + else + { + DSAParametersGenerator pGen; + DSAParameterGenerationParameters dsaParams; + + // Typical combination of keysize and size of q. + // keysize = 1024, q's size = 160 + // keysize = 2048, q's size = 224 + // keysize = 2048, q's size = 256 + // keysize = 3072, q's size = 256 + // For simplicity if keysize is greater than 1024 then we choose q's size to be 256. + // For legacy keysize that is less than 1024-bit, we just use the 186-2 style parameters + if (strength == 1024) + { + pGen = new DSAParametersGenerator(); + if (Properties.isOverrideSet("org.bouncycastle.dsa.FIPS186-2for1024bits")) + { + pGen.init(strength, certainty, random); + } + else + { + dsaParams = new DSAParameterGenerationParameters(1024, 160, certainty, random); + pGen.init(dsaParams); + } + } + else if (strength > 1024) + { + dsaParams = new DSAParameterGenerationParameters(strength, 256, certainty, random); + pGen = new DSAParametersGenerator(new SHA256Digest()); + pGen.init(dsaParams); + } + else + { + pGen = new DSAParametersGenerator(); + pGen.init(strength, certainty, random); + } + param = new DSAKeyGenerationParameters(random, pGen.generateParameters()); + + params.put(paramStrength, param); + } + } + } - pGen.init(strength, certainty, random); - param = new DSAKeyGenerationParameters(random, pGen.generateParameters()); engine.init(param); initialised = true; } @@ -76,7 +140,6 @@ public class KeyPairGeneratorSpi DSAPublicKeyParameters pub = (DSAPublicKeyParameters)pair.getPublic(); DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)pair.getPrivate(); - return new KeyPair(new BCDSAPublicKey(pub), - new BCDSAPrivateKey(priv)); + return new KeyPair(new BCDSAPublicKey(pub), new BCDSAPrivateKey(priv)); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java index 6af71e80..9f56a55a 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/AlgorithmParametersSpi.java @@ -14,6 +14,7 @@ import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; public class AlgorithmParametersSpi @@ -45,7 +46,14 @@ public class AlgorithmParametersSpi } else if (algorithmParameterSpec instanceof ECParameterSpec) { - curveName = null; + if (algorithmParameterSpec instanceof ECNamedCurveSpec) + { + curveName = ((ECNamedCurveSpec)algorithmParameterSpec).getName(); + } + else + { + curveName = null; + } ecParameterSpec = (ECParameterSpec)algorithmParameterSpec; } else @@ -73,7 +81,13 @@ public class AlgorithmParametersSpi if (params.isNamedCurve()) { - curveName = ECNamedCurveTable.getName(ASN1ObjectIdentifier.getInstance(params.getParameters())); + ASN1ObjectIdentifier curveId = ASN1ObjectIdentifier.getInstance(params.getParameters()); + + curveName = ECNamedCurveTable.getName(curveId); + if (curveName == null) + { + curveName = curveId.getId(); + } } ecParameterSpec = EC5Util.convertToSpec(params, curve); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java index e69942a2..815bcac0 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java @@ -17,12 +17,10 @@ import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DERBitString; -import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X962Parameters; -import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; @@ -33,7 +31,6 @@ import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; import org.bouncycastle.jce.interfaces.ECPointEncoder; import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.util.Strings; @@ -181,7 +178,14 @@ public class BCECPrivateKey this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec); } - publicKey = getPublicKeyDetails(pubKey); + try + { + publicKey = getPublicKeyDetails(pubKey); + } + catch (Exception e) + { + publicKey = null; // not all curves are encodable + } } public BCECPrivateKey( @@ -253,38 +257,16 @@ public class BCECPrivateKey */ public byte[] getEncoded() { - X962Parameters params; - int orderBitLength; + X962Parameters params = ECUtils.getDomainParametersFromName(ecSpec, withCompression); - if (ecSpec instanceof ECNamedCurveSpec) - { - ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); - if (curveOid == null) // guess it's the OID - { - curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()); - } - - params = new X962Parameters(curveOid); - orderBitLength = ECUtil.getOrderBitLength(ecSpec.getOrder(), this.getS()); - } - else if (ecSpec == null) + int orderBitLength; + if (ecSpec == null) { - params = new X962Parameters(DERNull.INSTANCE); - orderBitLength = ECUtil.getOrderBitLength(null, this.getS()); + orderBitLength = ECUtil.getOrderBitLength(configuration, null, this.getS()); } else { - ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); - - X9ECParameters ecP = new X9ECParameters( - curve, - EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), - ecSpec.getOrder(), - BigInteger.valueOf(ecSpec.getCofactor()), - ecSpec.getCurve().getSeed()); - - params = new X962Parameters(ecP); - orderBitLength = ECUtil.getOrderBitLength(ecSpec.getOrder(), this.getS()); + orderBitLength = ECUtil.getOrderBitLength(configuration, ecSpec.getOrder(), this.getS()); } PrivateKeyInfo info; @@ -420,9 +402,10 @@ public class BCECPrivateKey byte[] enc = (byte[])in.readObject(); + this.configuration = BouncyCastleProvider.CONFIGURATION; + populateFromPrivKeyInfo(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(enc))); - this.configuration = BouncyCastleProvider.CONFIGURATION; this.attrCarrier = new PKCS12BagAttributeCarrierImpl(); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java index c3f0dd02..443c5f63 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java @@ -3,7 +3,6 @@ package org.bouncycastle.jcajce.provider.asymmetric.ec; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.math.BigInteger; import java.security.interfaces.ECPublicKey; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; @@ -11,16 +10,13 @@ import java.security.spec.ECPublicKeySpec; import java.security.spec.EllipticCurve; import org.bouncycastle.asn1.ASN1Encodable; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DERBitString; -import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X962Parameters; -import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.asn1.x9.X9ECPoint; import org.bouncycastle.asn1.x9.X9IntegerConverter; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; @@ -32,7 +28,6 @@ import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil; import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; import org.bouncycastle.jce.interfaces.ECPointEncoder; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.util.Strings; @@ -44,7 +39,7 @@ public class BCECPublicKey private String algorithm = "EC"; private boolean withCompression; - private transient org.bouncycastle.math.ec.ECPoint q; + private transient ECPublicKeyParameters ecPublicKey; private transient ECParameterSpec ecSpec; private transient ProviderConfiguration configuration; @@ -53,7 +48,7 @@ public class BCECPublicKey BCECPublicKey key) { this.algorithm = algorithm; - this.q = key.q; + this.ecPublicKey = key.ecPublicKey; this.ecSpec = key.ecSpec; this.withCompression = key.withCompression; this.configuration = key.configuration; @@ -66,7 +61,7 @@ public class BCECPublicKey { this.algorithm = algorithm; this.ecSpec = spec.getParams(); - this.q = EC5Util.convertPoint(ecSpec, spec.getW(), false); + this.ecPublicKey = new ECPublicKeyParameters(EC5Util.convertPoint(ecSpec, spec.getW(), false), EC5Util.getDomainParameters(configuration, spec.getParams())); this.configuration = configuration; } @@ -76,7 +71,6 @@ public class BCECPublicKey ProviderConfiguration configuration) { this.algorithm = algorithm; - this.q = spec.getQ(); if (spec.getParams() != null) // can be null if implictlyCa { @@ -84,17 +78,15 @@ public class BCECPublicKey EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed()); // this may seem a little long-winded but it's how we pick up the custom curve. - this.q = EC5Util.convertCurve(ellipticCurve).createPoint(spec.getQ().getAffineXCoord().toBigInteger(), spec.getQ().getAffineYCoord().toBigInteger()); + this.ecPublicKey = new ECPublicKeyParameters( + spec.getQ(), ECUtil.getDomainParameters(configuration, spec.getParams())); this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams()); } else { - if (q.getCurve() == null) - { - org.bouncycastle.jce.spec.ECParameterSpec s = configuration.getEcImplicitlyCa(); + org.bouncycastle.jce.spec.ECParameterSpec s = configuration.getEcImplicitlyCa(); - q = s.getCurve().createPoint(q.getXCoord().toBigInteger(), q.getYCoord().toBigInteger(), false); - } + this.ecPublicKey = new ECPublicKeyParameters(s.getCurve().createPoint(spec.getQ().getAffineXCoord().toBigInteger(), spec.getQ().getAffineYCoord().toBigInteger()), EC5Util.getDomainParameters(configuration, (ECParameterSpec)null)); this.ecSpec = null; } @@ -110,7 +102,7 @@ public class BCECPublicKey ECDomainParameters dp = params.getParameters(); this.algorithm = algorithm; - this.q = params.getQ(); + this.ecPublicKey = params; if (spec == null) { @@ -149,8 +141,7 @@ public class BCECPublicKey this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec); } - this.q = EC5Util.convertCurve(ecSpec.getCurve()).createPoint(params.getQ().getAffineXCoord().toBigInteger(), params.getQ().getAffineYCoord().toBigInteger()); - + this.ecPublicKey = params; this.configuration = configuration; } @@ -163,7 +154,7 @@ public class BCECPublicKey ProviderConfiguration configuration) { this.algorithm = algorithm; - this.q = params.getQ(); + this.ecPublicKey = params; this.ecSpec = null; this.configuration = configuration; } @@ -174,7 +165,7 @@ public class BCECPublicKey { this.algorithm = key.getAlgorithm(); this.ecSpec = key.getParams(); - this.q = EC5Util.convertPoint(this.ecSpec, key.getW(), false); + this.ecPublicKey = new ECPublicKeyParameters(EC5Util.convertPoint(this.ecSpec, key.getW(), false), EC5Util.getDomainParameters(configuration, key.getParams())); } BCECPublicKey( @@ -200,7 +191,7 @@ public class BCECPublicKey private void populateFromPubKeyInfo(SubjectPublicKeyInfo info) { - X962Parameters params = new X962Parameters((ASN1Primitive)info.getAlgorithm().getParameters()); + X962Parameters params = X962Parameters.getInstance(info.getAlgorithm().getParameters()); ECCurve curve = EC5Util.getCurve(configuration, params); ecSpec = EC5Util.convertToSpec(params, curve); @@ -231,7 +222,7 @@ public class BCECPublicKey X9ECPoint derQ = new X9ECPoint(curve, key); - this.q = derQ.getPoint(); + this.ecPublicKey = new ECPublicKeyParameters(derQ.getPoint(), ECUtil.getDomainParameters(configuration, params)); } public String getAlgorithm() @@ -246,72 +237,15 @@ public class BCECPublicKey public byte[] getEncoded() { - ASN1Encodable params; - SubjectPublicKeyInfo info; - - if (ecSpec instanceof ECNamedCurveSpec) - { - ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); - if (curveOid == null) - { - curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()); - } - params = new X962Parameters(curveOid); - } - else if (ecSpec == null) - { - params = new X962Parameters(DERNull.INSTANCE); - } - else - { - ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); - - X9ECParameters ecP = new X9ECParameters( - curve, - EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), - ecSpec.getOrder(), - BigInteger.valueOf(ecSpec.getCofactor()), - ecSpec.getCurve().getSeed()); - - params = new X962Parameters(ecP); - } - - ECCurve curve = this.engineGetQ().getCurve(); - ASN1OctetString p; + ASN1Encodable params = ECUtils.getDomainParametersFromName(ecSpec, withCompression); + ASN1OctetString p = ASN1OctetString.getInstance(new X9ECPoint(ecPublicKey.getQ(), withCompression).toASN1Primitive()); // stored curve is null if ImplicitlyCa - if (ecSpec == null) - { - p = (ASN1OctetString) - new X9ECPoint(curve.createPoint(this.getQ().getXCoord().toBigInteger(), this.getQ().getYCoord().toBigInteger(), withCompression)).toASN1Primitive(); - } - else - { - p = (ASN1OctetString) - new X9ECPoint(curve.createPoint(this.getQ().getAffineXCoord().toBigInteger(), this.getQ().getAffineYCoord().toBigInteger(), withCompression)).toASN1Primitive(); - } - - info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets()); + SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params), p.getOctets()); return KeyUtil.getEncodedSubjectPublicKeyInfo(info); } - private void extractBytes(byte[] encKey, int offSet, BigInteger bI) - { - byte[] val = bI.toByteArray(); - if (val.length < 32) - { - byte[] tmp = new byte[32]; - System.arraycopy(val, 0, tmp, tmp.length - val.length, val.length); - val = tmp; - } - - for (int i = 0; i != 32; i++) - { - encKey[offSet + i] = val[val.length - 1 - i]; - } - } - public ECParameterSpec getParams() { return ecSpec; @@ -329,11 +263,15 @@ public class BCECPublicKey public ECPoint getW() { + org.bouncycastle.math.ec.ECPoint q = ecPublicKey.getQ(); + return new ECPoint(q.getAffineXCoord().toBigInteger(), q.getAffineYCoord().toBigInteger()); } public org.bouncycastle.math.ec.ECPoint getQ() { + org.bouncycastle.math.ec.ECPoint q = ecPublicKey.getQ(); + if (ecSpec == null) { return q.getDetachedPoint(); @@ -342,9 +280,9 @@ public class BCECPublicKey return q; } - public org.bouncycastle.math.ec.ECPoint engineGetQ() + ECPublicKeyParameters engineGetKeyParameters() { - return q; + return ecPublicKey; } org.bouncycastle.jce.spec.ECParameterSpec engineGetSpec() @@ -361,10 +299,11 @@ public class BCECPublicKey { StringBuffer buf = new StringBuffer(); String nl = Strings.lineSeparator(); + org.bouncycastle.math.ec.ECPoint q = ecPublicKey.getQ(); buf.append("EC Public Key").append(nl); - buf.append(" X: ").append(this.q.getAffineXCoord().toBigInteger().toString(16)).append(nl); - buf.append(" Y: ").append(this.q.getAffineYCoord().toBigInteger().toString(16)).append(nl); + buf.append(" X: ").append(q.getAffineXCoord().toBigInteger().toString(16)).append(nl); + buf.append(" Y: ").append(q.getAffineYCoord().toBigInteger().toString(16)).append(nl); return buf.toString(); @@ -384,12 +323,12 @@ public class BCECPublicKey BCECPublicKey other = (BCECPublicKey)o; - return engineGetQ().equals(other.engineGetQ()) && (engineGetSpec().equals(other.engineGetSpec())); + return ecPublicKey.getQ().equals(other.ecPublicKey.getQ()) && (engineGetSpec().equals(other.engineGetSpec())); } public int hashCode() { - return engineGetQ().hashCode() ^ engineGetSpec().hashCode(); + return ecPublicKey.getQ().hashCode() ^ engineGetSpec().hashCode(); } private void readObject( @@ -400,9 +339,9 @@ public class BCECPublicKey byte[] enc = (byte[])in.readObject(); - populateFromPubKeyInfo(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(enc))); - this.configuration = BouncyCastleProvider.CONFIGURATION; + + populateFromPubKeyInfo(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(enc))); } private void writeObject( diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java index dc92e0e4..8a5c834c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtils.java @@ -1,13 +1,30 @@ package org.bouncycastle.jcajce.provider.asymmetric.ec; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.PublicKey; import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.params.AsymmetricKeyParameter; +import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.math.ec.ECCurve; class ECUtils { + static AsymmetricKeyParameter generatePublicKeyParameter( + PublicKey key) + throws InvalidKeyException + { + return (key instanceof BCECPublicKey) ? ((BCECPublicKey)key).engineGetKeyParameters() : ECUtil.generatePublicKeyParameter(key); + } + static X9ECParameters getDomainParametersFromGenSpec(ECGenParameterSpec genSpec) { return getDomainParametersFromName(genSpec.getName()); @@ -42,4 +59,38 @@ class ECUtils } return domainParameters; } + + static X962Parameters getDomainParametersFromName(ECParameterSpec ecSpec, boolean withCompression) + { + X962Parameters params; + + if (ecSpec instanceof ECNamedCurveSpec) + { + ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveSpec)ecSpec).getName()); + if (curveOid == null) + { + curveOid = new ASN1ObjectIdentifier(((ECNamedCurveSpec)ecSpec).getName()); + } + params = new X962Parameters(curveOid); + } + else if (ecSpec == null) + { + params = new X962Parameters(DERNull.INSTANCE); + } + else + { + ECCurve curve = EC5Util.convertCurve(ecSpec.getCurve()); + + X9ECParameters ecP = new X9ECParameters( + curve, + EC5Util.convertPoint(curve, ecSpec.getGenerator(), withCompression), + ecSpec.getOrder(), + BigInteger.valueOf(ecSpec.getCofactor()), + ecSpec.getCurve().getSeed()); + + params = new X962Parameters(ecP); + } + + return params; + } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java index 004e2873..5d8e6b18 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java @@ -18,13 +18,6 @@ import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; // import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement; // import org.bouncycastle.crypto.agreement.ECMQVBasicAgreement; // import org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator; -// END android-removed -import org.bouncycastle.crypto.digests.SHA1Digest; -import org.bouncycastle.crypto.digests.SHA224Digest; -import org.bouncycastle.crypto.digests.SHA256Digest; -import org.bouncycastle.crypto.digests.SHA384Digest; -import org.bouncycastle.crypto.digests.SHA512Digest; -// BEGIN android-removed // import org.bouncycastle.crypto.generators.KDF2BytesGenerator; // END android-removed import org.bouncycastle.crypto.params.ECDomainParameters; @@ -33,6 +26,7 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters; // BEGIN android-removed // import org.bouncycastle.crypto.params.MQVPrivateParameters; // import org.bouncycastle.crypto.params.MQVPublicParameters; +// import org.bouncycastle.crypto.util.DigestFactory; // END android-removed import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; @@ -66,6 +60,7 @@ public class KeyAgreementSpi // BEGIN android-removed // private MQVParameterSpec mqvParameters; // END android-removed + private BigInteger result; protected KeyAgreementSpi( String kaAlgorithm, @@ -106,9 +101,9 @@ public class KeyAgreementSpi // if (!(key instanceof MQVPublicKey)) // { // ECPublicKeyParameters staticKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter((PublicKey)key); + // ECUtils.generatePublicKeyParameter((PublicKey)key); // ECPublicKeyParameters ephemKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter(mqvParameters.getOtherPartyEphemeralKey()); + // ECUtils.generatePublicKeyParameter(mqvParameters.getOtherPartyEphemeralKey()); // // pubKey = new MQVPublicParameters(staticKey, ephemKey); // } @@ -116,13 +111,11 @@ public class KeyAgreementSpi // { // MQVPublicKey mqvPubKey = (MQVPublicKey)key; // ECPublicKeyParameters staticKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter(mqvPubKey.getStaticKey()); + // ECUtils.generatePublicKeyParameter(mqvPubKey.getStaticKey()); // ECPublicKeyParameters ephemKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter(mqvPubKey.getEphemeralKey()); + // ECUtils.generatePublicKeyParameter(mqvPubKey.getEphemeralKey()); // // pubKey = new MQVPublicParameters(staticKey, ephemKey); - // - // // TODO Validate that all the keys are using the same parameters? // } // } // else @@ -134,21 +127,27 @@ public class KeyAgreementSpi + getSimpleName(ECPublicKey.class) + " for doPhase"); } - pubKey = ECUtil.generatePublicKeyParameter((PublicKey)key); - - // TODO Validate that all the keys are using the same parameters? + pubKey = ECUtils.generatePublicKeyParameter((PublicKey)key); } - // BEGIN android-added - try { - // END android-added - result = agreement.calculateAgreement(pubKey); - // BEGIN android-added + try + { + result = agreement.calculateAgreement(pubKey); + // BEGIN android-changed + // Was: + // } catch (final Exception e) { + // throw new InvalidKeyException("calculation failed: " + e.getMessage()) + // { + // public Throwable getCause() + // { + // return e; + // } + // }; + // } + // END android-changed } catch (IllegalStateException e) { - throw new InvalidKeyException("Invalid public key"); + throw new InvalidKeyException("Invalid public key"); } - // END android-added - return null; } @@ -170,7 +169,7 @@ public class KeyAgreementSpi protected void engineInit( Key key, - SecureRandom random) + SecureRandom random) throws InvalidKeyException { initFromKey(key, null); @@ -204,7 +203,7 @@ public class KeyAgreementSpi // if (mqvPrivKey.getEphemeralPublicKey() != null) // { // ephemPubKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey()); + // ECUtils.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey()); // } // } // else @@ -220,7 +219,7 @@ public class KeyAgreementSpi // if (mqvParameterSpec.getEphemeralPublicKey() != null) // { // ephemPubKey = (ECPublicKeyParameters) - // ECUtil.generatePublicKeyParameter(mqvParameterSpec.getEphemeralPublicKey()); + // ECUtils.generatePublicKeyParameter(mqvParameterSpec.getEphemeralPublicKey()); // } // mqvParameters = mqvParameterSpec; // ukmParameters = mqvParameterSpec.getUserKeyingMaterial(); @@ -256,6 +255,12 @@ public class KeyAgreementSpi return fullName.substring(fullName.lastIndexOf('.') + 1); } + + protected byte[] calcSecret() + { + return bigIntToBytes(result); + } + public static class DH extends KeyAgreementSpi { @@ -274,7 +279,7 @@ public class KeyAgreementSpi // super("ECDHC", new ECDHCBasicAgreement(), null); // } // } - // + // public static class MQV // extends KeyAgreementSpi // { @@ -283,229 +288,230 @@ public class KeyAgreementSpi // super("ECMQV", new ECMQVBasicAgreement(), null); // } // } - // + // public static class DHwithSHA1KDF // extends KeyAgreementSpi // { // public DHwithSHA1KDF() // { - // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest())); + // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1())); // } // } - // + // public static class DHwithSHA1KDFAndSharedInfo // extends KeyAgreementSpi // { // public DHwithSHA1KDFAndSharedInfo() // { - // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest())); + // super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1())); // } // } - // + // public static class CDHwithSHA1KDFAndSharedInfo // extends KeyAgreementSpi // { // public CDHwithSHA1KDFAndSharedInfo() // { - // super("ECCDHwithSHA1KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest())); + // super("ECCDHwithSHA1KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1())); // } // } - // + // public static class DHwithSHA224KDFAndSharedInfo // extends KeyAgreementSpi // { // public DHwithSHA224KDFAndSharedInfo() // { - // super("ECDHwithSHA224KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA224Digest())); + // super("ECDHwithSHA224KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224())); // } // } - // + // public static class CDHwithSHA224KDFAndSharedInfo // extends KeyAgreementSpi // { // public CDHwithSHA224KDFAndSharedInfo() // { - // super("ECCDHwithSHA224KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA224Digest())); + // super("ECCDHwithSHA224KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224())); // } // } - // + // public static class DHwithSHA256KDFAndSharedInfo // extends KeyAgreementSpi // { // public DHwithSHA256KDFAndSharedInfo() // { - // super("ECDHwithSHA256KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA256Digest())); + // super("ECDHwithSHA256KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256())); // } // } - // + // public static class CDHwithSHA256KDFAndSharedInfo // extends KeyAgreementSpi // { // public CDHwithSHA256KDFAndSharedInfo() // { - // super("ECCDHwithSHA256KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA256Digest())); + // super("ECCDHwithSHA256KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256())); // } // } - // + // public static class DHwithSHA384KDFAndSharedInfo // extends KeyAgreementSpi // { // public DHwithSHA384KDFAndSharedInfo() // { - // super("ECDHwithSHA384KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA384Digest())); + // super("ECDHwithSHA384KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384())); // } // } - // + // public static class CDHwithSHA384KDFAndSharedInfo // extends KeyAgreementSpi // { // public CDHwithSHA384KDFAndSharedInfo() // { - // super("ECCDHwithSHA384KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA384Digest())); + // super("ECCDHwithSHA384KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384())); // } // } - // + // public static class DHwithSHA512KDFAndSharedInfo // extends KeyAgreementSpi // { // public DHwithSHA512KDFAndSharedInfo() // { - // super("ECDHwithSHA512KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(new SHA512Digest())); + // super("ECDHwithSHA512KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512())); // } // } - // + // public static class CDHwithSHA512KDFAndSharedInfo // extends KeyAgreementSpi // { // public CDHwithSHA512KDFAndSharedInfo() // { - // super("ECCDHwithSHA512KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(new SHA512Digest())); + // super("ECCDHwithSHA512KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512())); // } // } - // + // public static class MQVwithSHA1KDFAndSharedInfo // extends KeyAgreementSpi // { // public MQVwithSHA1KDFAndSharedInfo() // { - // super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA1Digest())); + // super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1())); // } // } - // + // public static class MQVwithSHA224KDFAndSharedInfo // extends KeyAgreementSpi // { // public MQVwithSHA224KDFAndSharedInfo() // { - // super("ECMQVwithSHA224KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA224Digest())); + // super("ECMQVwithSHA224KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224())); // } // } - // + // public static class MQVwithSHA256KDFAndSharedInfo // extends KeyAgreementSpi // { // public MQVwithSHA256KDFAndSharedInfo() // { - // super("ECMQVwithSHA256KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA256Digest())); + // super("ECMQVwithSHA256KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256())); // } // } - // + // public static class MQVwithSHA384KDFAndSharedInfo // extends KeyAgreementSpi // { // public MQVwithSHA384KDFAndSharedInfo() // { - // super("ECMQVwithSHA384KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA384Digest())); + // super("ECMQVwithSHA384KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384())); // } // } - // + // public static class MQVwithSHA512KDFAndSharedInfo // extends KeyAgreementSpi // { // public MQVwithSHA512KDFAndSharedInfo() // { - // super("ECMQVwithSHA512KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(new SHA512Digest())); + // super("ECMQVwithSHA512KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512())); // } // } - // + // public static class DHwithSHA1CKDF // extends KeyAgreementSpi // { // public DHwithSHA1CKDF() // { - // super("ECDHwithSHA1CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(new SHA1Digest())); + // super("ECDHwithSHA1CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA1())); // } // } - // + // public static class DHwithSHA256CKDF // extends KeyAgreementSpi // { // public DHwithSHA256CKDF() // { - // super("ECDHwithSHA256CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(new SHA256Digest())); + // super("ECDHwithSHA256CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA256())); // } // } - // + // public static class DHwithSHA384CKDF // extends KeyAgreementSpi // { // public DHwithSHA384CKDF() // { - // super("ECDHwithSHA384CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(new SHA384Digest())); + // super("ECDHwithSHA384CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA384())); // } // } - // + // public static class DHwithSHA512CKDF // extends KeyAgreementSpi // { // public DHwithSHA512CKDF() // { - // super("ECDHwithSHA512CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(new SHA512Digest())); + // super("ECDHwithSHA512CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA512())); // } // } - // + // public static class MQVwithSHA1CKDF // extends KeyAgreementSpi // { // public MQVwithSHA1CKDF() // { - // super("ECMQVwithSHA1CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA1Digest())); + // super("ECMQVwithSHA1CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA1())); // } // } - // + // public static class MQVwithSHA224CKDF // extends KeyAgreementSpi // { // public MQVwithSHA224CKDF() // { - // super("ECMQVwithSHA224CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA224Digest())); + // super("ECMQVwithSHA224CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA224())); // } // } - // + // public static class MQVwithSHA256CKDF // extends KeyAgreementSpi // { // public MQVwithSHA256CKDF() // { - // super("ECMQVwithSHA256CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA256Digest())); + // super("ECMQVwithSHA256CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA256())); // } // } - // + // public static class MQVwithSHA384CKDF // extends KeyAgreementSpi // { // public MQVwithSHA384CKDF() // { - // super("ECMQVwithSHA384CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA384Digest())); + // super("ECMQVwithSHA384CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA384())); // } // } - // + // public static class MQVwithSHA512CKDF // extends KeyAgreementSpi // { // public MQVwithSHA512CKDF() // { - // super("ECMQVwithSHA512CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(new SHA512Digest())); + // super("ECMQVwithSHA512CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA512())); // } // } + // END android-removed } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java index 5769bacc..a749f114 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java @@ -141,13 +141,20 @@ public class KeyFactorySpi KeySpec keySpec) throws InvalidKeySpecException { - if (keySpec instanceof ECPublicKeySpec) + try { - return new BCECPublicKey(algorithm, (ECPublicKeySpec)keySpec, configuration); + if (keySpec instanceof ECPublicKeySpec) + { + return new BCECPublicKey(algorithm, (ECPublicKeySpec)keySpec, configuration); + } + else if (keySpec instanceof java.security.spec.ECPublicKeySpec) + { + return new BCECPublicKey(algorithm, (java.security.spec.ECPublicKeySpec)keySpec, configuration); + } } - else if (keySpec instanceof java.security.spec.ECPublicKeySpec) + catch (Exception e) { - return new BCECPublicKey(algorithm, (java.security.spec.ECPublicKeySpec)keySpec, configuration); + throw new InvalidKeySpecException("invalid KeySpec: " + e.getMessage(), e); } return super.engineGeneratePublic(keySpec); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java index 9a9c46be..5f8a901e 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java @@ -8,6 +8,7 @@ import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.util.Hashtable; +import java.util.Map; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x9.ECNamedCurveTable; @@ -194,7 +195,7 @@ public abstract class KeyPairGeneratorSpi protected ECKeyGenerationParameters createKeyGenParamsBC(ECParameterSpec p, SecureRandom r) { - return new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), r); + return new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH()), r); } protected ECKeyGenerationParameters createKeyGenParamsJCE(java.security.spec.ECParameterSpec p, SecureRandom r) @@ -221,7 +222,14 @@ public abstract class KeyPairGeneratorSpi p = ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(curveName)); if (p == null) { - throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName); + Map extraCurves = configuration.getAdditionalECParameters(); + + p = (X9ECParameters)extraCurves.get(new ASN1ObjectIdentifier(curveName)); + + if (p == null) + { + throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName); + } } } catch (IllegalArgumentException ex) diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java index 26811d18..46aeec7e 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java @@ -21,21 +21,18 @@ import org.bouncycastle.crypto.digests.AndroidDigestFactory; // END android-added // BEGIN android-removed // import org.bouncycastle.crypto.digests.RIPEMD160Digest; -// import org.bouncycastle.crypto.digests.SHA1Digest; -// import org.bouncycastle.crypto.digests.SHA224Digest; -// import org.bouncycastle.crypto.digests.SHA256Digest; -// import org.bouncycastle.crypto.digests.SHA384Digest; -// import org.bouncycastle.crypto.digests.SHA512Digest; // END android-removed import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.crypto.signers.ECDSASigner; // BEGIN android-removed // import org.bouncycastle.crypto.signers.ECNRSigner; // import org.bouncycastle.crypto.signers.HMacDSAKCalculator; +// import org.bouncycastle.crypto.util.DigestFactory; // END android-removed import org.bouncycastle.jcajce.provider.asymmetric.util.DSABase; import org.bouncycastle.jcajce.provider.asymmetric.util.DSAEncoder; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; +import org.bouncycastle.util.Arrays; public class SignatureSpi extends DSABase @@ -48,7 +45,7 @@ public class SignatureSpi protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { - CipherParameters param = ECUtil.generatePublicKeyParameter(publicKey); + CipherParameters param = ECUtils.generatePublicKeyParameter(publicKey); digest.reset(); signer.init(false, param); @@ -89,7 +86,7 @@ public class SignatureSpi // { // public ecDetDSA() // { - // super(new SHA1Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA1Digest())), new StdDSAEncoder()); + // super(DigestFactory.createSHA1(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA1())), new StdDSAEncoder()); // } // } // END android-removed @@ -120,7 +117,7 @@ public class SignatureSpi // { // public ecDetDSA224() // { - // super(new SHA224Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA224Digest())), new StdDSAEncoder()); + // super(DigestFactory.createSHA224(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA224())), new StdDSAEncoder()); // } // } // END android-removed @@ -142,7 +139,7 @@ public class SignatureSpi // { // public ecDetDSA256() // { - // super(new SHA256Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest())), new StdDSAEncoder()); + // super(DigestFactory.createSHA256(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA256())), new StdDSAEncoder()); // } // } // END android-removed @@ -164,11 +161,10 @@ public class SignatureSpi // { // public ecDetDSA384() // { - // super(new SHA384Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA384Digest())), new StdDSAEncoder()); + // super(DigestFactory.createSHA384(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA384())), new StdDSAEncoder()); // } // } // END android-removed - static public class ecDSA512 extends SignatureSpi { @@ -186,10 +182,82 @@ public class SignatureSpi // { // public ecDetDSA512() // { - // super(new SHA512Digest(), new ECDSASigner(new HMacDSAKCalculator(new SHA512Digest())), new StdDSAEncoder()); + // super(DigestFactory.createSHA512(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA512())), new StdDSAEncoder()); // } // } - // + + // static public class ecDSASha3_224 + // extends SignatureSpi + // { + // public ecDSASha3_224() + // { + // super(DigestFactory.createSHA3_224(), new ECDSASigner(), new StdDSAEncoder()); + // } + // } + + // static public class ecDetDSASha3_224 + // extends SignatureSpi + // { + // public ecDetDSASha3_224() + // { + // super(DigestFactory.createSHA3_224(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_224())), new StdDSAEncoder()); + // } + // } + + // static public class ecDSASha3_256 + // extends SignatureSpi + // { + // public ecDSASha3_256() + // { + // super(DigestFactory.createSHA3_256(), new ECDSASigner(), new StdDSAEncoder()); + // } + // } + + // static public class ecDetDSASha3_256 + // extends SignatureSpi + // { + // public ecDetDSASha3_256() + // { + // super(DigestFactory.createSHA3_256(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_256())), new StdDSAEncoder()); + // } + // } + + // static public class ecDSASha3_384 + // extends SignatureSpi + // { + // public ecDSASha3_384() + // { + // super(DigestFactory.createSHA3_384(), new ECDSASigner(), new StdDSAEncoder()); + // } + // } + + // static public class ecDetDSASha3_384 + // extends SignatureSpi + // { + // public ecDetDSASha3_384() + // { + // super(DigestFactory.createSHA3_384(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_384())), new StdDSAEncoder()); + // } + // } + + // static public class ecDSASha3_512 + // extends SignatureSpi + // { + // public ecDSASha3_512() + // { + // super(DigestFactory.createSHA3_512(), new ECDSASigner(), new StdDSAEncoder()); + // } + // } + + // static public class ecDetDSASha3_512 + // extends SignatureSpi + // { + // public ecDetDSASha3_512() + // { + // super(DigestFactory.createSHA3_512(), new ECDSASigner(new HMacDSAKCalculator(DigestFactory.createSHA3_512())), new StdDSAEncoder()); + // } + // } + // static public class ecDSARipeMD160 // extends SignatureSpi // { @@ -198,97 +266,97 @@ public class SignatureSpi // super(new RIPEMD160Digest(), new ECDSASigner(), new StdDSAEncoder()); // } // } - // + // static public class ecNR // extends SignatureSpi // { // public ecNR() // { - // super(new SHA1Digest(), new ECNRSigner(), new StdDSAEncoder()); + // super(DigestFactory.createSHA1(), new ECNRSigner(), new StdDSAEncoder()); // } // } - // + // static public class ecNR224 // extends SignatureSpi // { // public ecNR224() // { - // super(new SHA224Digest(), new ECNRSigner(), new StdDSAEncoder()); + // super(DigestFactory.createSHA224(), new ECNRSigner(), new StdDSAEncoder()); // } // } - // + // static public class ecNR256 // extends SignatureSpi // { // public ecNR256() // { - // super(new SHA256Digest(), new ECNRSigner(), new StdDSAEncoder()); + // super(DigestFactory.createSHA256(), new ECNRSigner(), new StdDSAEncoder()); // } // } - // + // static public class ecNR384 // extends SignatureSpi // { // public ecNR384() // { - // super(new SHA384Digest(), new ECNRSigner(), new StdDSAEncoder()); + // super(DigestFactory.createSHA384(), new ECNRSigner(), new StdDSAEncoder()); // } // } - // + // static public class ecNR512 // extends SignatureSpi // { // public ecNR512() // { - // super(new SHA512Digest(), new ECNRSigner(), new StdDSAEncoder()); + // super(DigestFactory.createSHA512(), new ECNRSigner(), new StdDSAEncoder()); // } // } - // + // static public class ecCVCDSA // extends SignatureSpi // { // public ecCVCDSA() // { - // super(new SHA1Digest(), new ECDSASigner(), new PlainDSAEncoder()); + // super(DigestFactory.createSHA1(), new ECDSASigner(), new PlainDSAEncoder()); // } // } - // + // static public class ecCVCDSA224 // extends SignatureSpi // { // public ecCVCDSA224() // { - // super(new SHA224Digest(), new ECDSASigner(), new PlainDSAEncoder()); + // super(DigestFactory.createSHA224(), new ECDSASigner(), new PlainDSAEncoder()); // } // } - // + // static public class ecCVCDSA256 // extends SignatureSpi // { // public ecCVCDSA256() // { - // super(new SHA256Digest(), new ECDSASigner(), new PlainDSAEncoder()); + // super(DigestFactory.createSHA256(), new ECDSASigner(), new PlainDSAEncoder()); // } // } - // + // static public class ecCVCDSA384 // extends SignatureSpi // { // public ecCVCDSA384() // { - // super(new SHA384Digest(), new ECDSASigner(), new PlainDSAEncoder()); + // super(DigestFactory.createSHA384(), new ECDSASigner(), new PlainDSAEncoder()); // } // } - // + // static public class ecCVCDSA512 // extends SignatureSpi // { // public ecCVCDSA512() // { - // super(new SHA512Digest(), new ECDSASigner(), new PlainDSAEncoder()); + // super(DigestFactory.createSHA512(), new ECDSASigner(), new PlainDSAEncoder()); // } // } - // + // static public class ecPlainDSARP160 // extends SignatureSpi // { @@ -320,6 +388,15 @@ public class SignatureSpi throws IOException { ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding); + if (s.size() != 2) + { + throw new IOException("malformed signature"); + } + if (!Arrays.areEqual(encoding, s.getEncoded(ASN1Encoding.DER))) + { + throw new IOException("malformed signature"); + } + BigInteger[] sig = new BigInteger[2]; sig[0] = ASN1Integer.getInstance(s.getObjectAt(0)).getValue(); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java index de5a9aa5..e60c36ae 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/AlgorithmParametersSpi.java @@ -19,6 +19,7 @@ import org.bouncycastle.asn1.pkcs.RSAESOAEPparams; import org.bouncycastle.asn1.pkcs.RSASSAPSSparams; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.jcajce.provider.util.DigestFactory; +import org.bouncycastle.jcajce.util.MessageDigestUtils; public abstract class AlgorithmParametersSpi extends java.security.AlgorithmParametersSpi @@ -118,10 +119,15 @@ public abstract class AlgorithmParametersSpi { RSAESOAEPparams oaepP = RSAESOAEPparams.getInstance(params); + if (!oaepP.getMaskGenAlgorithm().getAlgorithm().equals(PKCSObjectIdentifiers.id_mgf1)) + { + throw new IOException("unknown mask generation function: " + oaepP.getMaskGenAlgorithm().getAlgorithm()); + } + currentSpec = new OAEPParameterSpec( - oaepP.getHashAlgorithm().getAlgorithm().getId(), - oaepP.getMaskGenAlgorithm().getAlgorithm().getId(), - new MGF1ParameterSpec(AlgorithmIdentifier.getInstance(oaepP.getMaskGenAlgorithm().getParameters()).getAlgorithm().getId()), + MessageDigestUtils.getDigestName(oaepP.getHashAlgorithm().getAlgorithm()), + OAEPParameterSpec.DEFAULT.getMGFAlgorithm(), + new MGF1ParameterSpec(MessageDigestUtils.getDigestName(AlgorithmIdentifier.getInstance(oaepP.getMaskGenAlgorithm().getParameters()).getAlgorithm())), new PSource.PSpecified(ASN1OctetString.getInstance(oaepP.getPSourceAlgorithm().getParameters()).getOctets())); } catch (ClassCastException e) @@ -133,7 +139,7 @@ public abstract class AlgorithmParametersSpi throw new IOException("Not a valid OAEP Parameter encoding."); } } - + protected void engineInit( byte[] params, String format) @@ -225,10 +231,15 @@ public abstract class AlgorithmParametersSpi { RSASSAPSSparams pssP = RSASSAPSSparams.getInstance(params); + if (!pssP.getMaskGenAlgorithm().getAlgorithm().equals(PKCSObjectIdentifiers.id_mgf1)) + { + throw new IOException("unknown mask generation function: " + pssP.getMaskGenAlgorithm().getAlgorithm()); + } + currentSpec = new PSSParameterSpec( - pssP.getHashAlgorithm().getAlgorithm().getId(), - pssP.getMaskGenAlgorithm().getAlgorithm().getId(), - new MGF1ParameterSpec(AlgorithmIdentifier.getInstance(pssP.getMaskGenAlgorithm().getParameters()).getAlgorithm().getId()), + MessageDigestUtils.getDigestName(pssP.getHashAlgorithm().getAlgorithm()), + PSSParameterSpec.DEFAULT.getMGFAlgorithm(), + new MGF1ParameterSpec(MessageDigestUtils.getDigestName(AlgorithmIdentifier.getInstance(pssP.getMaskGenAlgorithm().getParameters()).getAlgorithm())), pssP.getSaltLength().intValue(), pssP.getTrailerField().intValue()); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java index 81e50132..c98b764c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java @@ -34,6 +34,7 @@ import org.bouncycastle.crypto.encodings.PKCS1Encoding; import org.bouncycastle.crypto.engines.RSABlindedEngine; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.jcajce.provider.asymmetric.util.BaseCipherSpi; +import org.bouncycastle.jcajce.provider.util.BadBlockException; import org.bouncycastle.jcajce.provider.util.DigestFactory; import org.bouncycastle.jcajce.util.BCJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; @@ -236,9 +237,27 @@ public class CipherSpi { initFromSpec(new OAEPParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, PSource.PSpecified.DEFAULT)); } + // BEGIN android-removed + // else if (pad.equals("OAEPWITHSHA3-224ANDMGF1PADDING")) + // { + // initFromSpec(new OAEPParameterSpec("SHA3-224", "MGF1", new MGF1ParameterSpec("SHA3-224"), PSource.PSpecified.DEFAULT)); + // } + // else if (pad.equals("OAEPWITHSHA3-256ANDMGF1PADDING")) + // { + // initFromSpec(new OAEPParameterSpec("SHA3-256", "MGF1", new MGF1ParameterSpec("SHA3-256"), PSource.PSpecified.DEFAULT)); + // } + // else if (pad.equals("OAEPWITHSHA3-384ANDMGF1PADDING")) + // { + // initFromSpec(new OAEPParameterSpec("SHA3-384", "MGF1", new MGF1ParameterSpec("SHA3-384"), PSource.PSpecified.DEFAULT)); + // } + // else if (pad.equals("OAEPWITHSHA3-512ANDMGF1PADDING")) + // { + // initFromSpec(new OAEPParameterSpec("SHA3-512", "MGF1", new MGF1ParameterSpec("SHA3-512"), PSource.PSpecified.DEFAULT)); + // } + // END android-removed else { - throw new NoSuchPaddingException(padding + " unavailable with RSA."); + throw new NoSuchPaddingException(padding + " unavailable with RSA."); } } @@ -308,7 +327,7 @@ public class CipherSpi { throw new InvalidAlgorithmParameterException("no match on MGF digest algorithm: "+ mgfParams.getDigestAlgorithm()); } - + cipher = new OAEPEncoding(new RSABlindedEngine(), digest, mgfDigest, ((PSource.PSpecified)spec.getPSource()).getValue()); } } @@ -466,18 +485,7 @@ public class CipherSpi } } - try - { - byte[] bytes = bOut.toByteArray(); - - bOut.reset(); - - return cipher.processBlock(bytes, 0, bytes.length); - } - catch (InvalidCipherTextException e) - { - throw new BadPaddingException(e.getMessage()); - } + return getOutput(); } protected int engineDoFinal( @@ -508,29 +516,37 @@ public class CipherSpi } } - byte[] out; + byte[] out = getOutput(); + for (int i = 0; i != out.length; i++) + { + output[outputOffset + i] = out[i]; + } + + return out.length; + } + + private byte[] getOutput() + throws BadPaddingException + { try { byte[] bytes = bOut.toByteArray(); - out = cipher.processBlock(bytes, 0, bytes.length); + return cipher.processBlock(bytes, 0, bytes.length); } catch (InvalidCipherTextException e) { - throw new BadPaddingException(e.getMessage()); + throw new BadBlockException("unable to decrypt block", e); } - finally + catch (ArrayIndexOutOfBoundsException e) { - bOut.reset(); + throw new BadBlockException("unable to decrypt block", e); } - - for (int i = 0; i != out.length; i++) + finally { - output[outputOffset + i] = out[i]; + bOut.reset(); } - - return out.length; } /** diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java index 9616a99b..1e4d854b 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java @@ -31,20 +31,16 @@ import org.bouncycastle.crypto.digests.AndroidDigestFactory; // BEGIN android-removed // import org.bouncycastle.crypto.digests.MD2Digest; // import org.bouncycastle.crypto.digests.MD4Digest; -// import org.bouncycastle.crypto.digests.MD5Digest; // import org.bouncycastle.crypto.digests.NullDigest; // import org.bouncycastle.crypto.digests.RIPEMD128Digest; // import org.bouncycastle.crypto.digests.RIPEMD160Digest; // import org.bouncycastle.crypto.digests.RIPEMD256Digest; -// import org.bouncycastle.crypto.digests.SHA1Digest; -// import org.bouncycastle.crypto.digests.SHA224Digest; -// import org.bouncycastle.crypto.digests.SHA256Digest; -// import org.bouncycastle.crypto.digests.SHA384Digest; -// import org.bouncycastle.crypto.digests.SHA512Digest; -// import org.bouncycastle.crypto.digests.SHA512tDigest; // END android-removed import org.bouncycastle.crypto.encodings.PKCS1Encoding; import org.bouncycastle.crypto.engines.RSABlindedEngine; +// BEGIN android-removed +// import org.bouncycastle.crypto.util.DigestFactory; +// END android-removed import org.bouncycastle.util.Arrays; public class DigestSignatureSpi @@ -318,7 +314,7 @@ public class DigestSignatureSpi // { // public SHA512_224() // { - // super(NISTObjectIdentifiers.id_sha512_224, new SHA512tDigest(224), new PKCS1Encoding(new RSABlindedEngine())); + // super(NISTObjectIdentifiers.id_sha512_224, DigestFactory.createSHA512_224(), new PKCS1Encoding(new RSABlindedEngine())); // } // } @@ -327,7 +323,43 @@ public class DigestSignatureSpi // { // public SHA512_256() // { - // super(NISTObjectIdentifiers.id_sha512_256, new SHA512tDigest(256), new PKCS1Encoding(new RSABlindedEngine())); + // super(NISTObjectIdentifiers.id_sha512_256, DigestFactory.createSHA512_256(), new PKCS1Encoding(new RSABlindedEngine())); + // } + // } + + // static public class SHA3_224 + // extends DigestSignatureSpi + // { + // public SHA3_224() + // { + // super(NISTObjectIdentifiers.id_sha3_224, DigestFactory.createSHA3_224(), new PKCS1Encoding(new RSABlindedEngine())); + // } + // } + + // static public class SHA3_256 + // extends DigestSignatureSpi + // { + // public SHA3_256() + // { + // super(NISTObjectIdentifiers.id_sha3_256, DigestFactory.createSHA3_256(), new PKCS1Encoding(new RSABlindedEngine())); + // } + // } + + // static public class SHA3_384 + // extends DigestSignatureSpi + // { + // public SHA3_384() + // { + // super(NISTObjectIdentifiers.id_sha3_384, DigestFactory.createSHA3_384(), new PKCS1Encoding(new RSABlindedEngine())); + // } + // } + + // static public class SHA3_512 + // extends DigestSignatureSpi + // { + // public SHA3_512() + // { + // super(NISTObjectIdentifiers.id_sha3_512, DigestFactory.createSHA3_512(), new PKCS1Encoding(new RSABlindedEngine())); // } // } @@ -339,7 +371,7 @@ public class DigestSignatureSpi // super(PKCSObjectIdentifiers.md2, new MD2Digest(), new PKCS1Encoding(new RSABlindedEngine())); // } // } - // + // static public class MD4 // extends DigestSignatureSpi // { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java index 16e73481..2994e739 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAgreementSpi.java @@ -1,6 +1,5 @@ package org.bouncycastle.jcajce.provider.asymmetric.util; -import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Hashtable; @@ -145,7 +144,6 @@ public abstract class BaseAgreementSpi private final String kaAlgorithm; private final DerivationFunction kdf; - protected BigInteger result; protected byte[] ukmParameters; public BaseAgreementSpi(String kaAlgorithm, DerivationFunction kdf) @@ -186,7 +184,7 @@ public abstract class BaseAgreementSpi { if (algDetails.indexOf('[') > 0) { - return (Integer.parseInt(algDetails.substring(algDetails.indexOf('[') + 1, algDetails.indexOf(']'))) + 7) / 8; + return Integer.parseInt(algDetails.substring(algDetails.indexOf('[') + 1, algDetails.indexOf(']'))); } String algKey = Strings.toUpperCase(algDetails); @@ -229,7 +227,7 @@ public abstract class BaseAgreementSpi "KDF can only be used when algorithm is known"); } - return bigIntToBytes(result); + return calcSecret(); } protected int engineGenerateSecret( @@ -253,7 +251,7 @@ public abstract class BaseAgreementSpi String algorithm) throws NoSuchAlgorithmException { - byte[] secret = bigIntToBytes(result); + byte[] secret = calcSecret(); String algKey = Strings.toUpperCase(algorithm); String oidAlgorithm = algorithm; @@ -311,13 +309,15 @@ public abstract class BaseAgreementSpi } } - if (des.containsKey(oidAlgorithm)) + String algName = getAlgorithm(algorithm); + + if (des.containsKey(algName)) { DESParameters.setOddParity(secret); } - return new SecretKeySpec(secret, getAlgorithm(algorithm)); + return new SecretKeySpec(secret, algName); } - protected abstract byte[] bigIntToBytes(BigInteger result); + protected abstract byte[] calcSecret(); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java index 5842b9e1..602ca74c 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java @@ -156,9 +156,15 @@ public abstract class BaseCipherSpi { throw new InvalidKeyException(e.getMessage()); } - catch (BadPaddingException e) + catch (final BadPaddingException e) { - throw new InvalidKeyException(e.getMessage()); + throw new InvalidKeyException("unable to unwrap") + { + public synchronized Throwable getCause() + { + return e; + } + }; } catch (IllegalBlockSizeException e2) { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java index cb34f447..17c4d3fb 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseKeyFactorySpi.java @@ -28,12 +28,12 @@ public abstract class BaseKeyFactorySpi } catch (Exception e) { - throw new InvalidKeySpecException("encoded key spec not recognised"); + throw new InvalidKeySpecException("encoded key spec not recognized: " + e.getMessage()); } } else { - throw new InvalidKeySpecException("key spec not recognised"); + throw new InvalidKeySpecException("key spec not recognized"); } } @@ -49,12 +49,12 @@ public abstract class BaseKeyFactorySpi } catch (Exception e) { - throw new InvalidKeySpecException("encoded key spec not recognised"); + throw new InvalidKeySpecException("encoded key spec not recognized: " + e.getMessage()); } } else { - throw new InvalidKeySpecException("key spec not recognised"); + throw new InvalidKeySpecException("key spec not recognized"); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DHUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DHUtil.java index 52c84ec0..07f8cfd2 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DHUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DHUtil.java @@ -11,6 +11,7 @@ import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DHPrivateKeyParameters; import org.bouncycastle.crypto.params.DHPublicKeyParameters; +import org.bouncycastle.jcajce.provider.asymmetric.dh.BCDHPublicKey; /** * utility class for converting jce/jca DH objects @@ -22,6 +23,10 @@ public class DHUtil PublicKey key) throws InvalidKeyException { + if (key instanceof BCDHPublicKey) + { + return ((BCDHPublicKey)key).engineGetKeyParameters(); + } if (key instanceof DHPublicKey) { DHPublicKey k = (DHPublicKey)key; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java index 0f25888a..3b8a0a6a 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java @@ -10,13 +10,16 @@ import java.security.spec.EllipticCurve; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; +import java.util.Set; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.ec.CustomNamedCurves; +import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECAlgorithms; @@ -43,6 +46,15 @@ public class EC5Util customCurves.put(curveParams.getCurve(), CustomNamedCurves.getByName(name).getCurve()); } } + + // BEGIN android-removed + // X9ECParameters c25519 = CustomNamedCurves.getByName("Curve25519"); + + // customCurves.put(new ECCurve.Fp( + // c25519.getCurve().getField().getCharacteristic(), + // c25519.getCurve().getA().toBigInteger(), + // c25519.getCurve().getB().toBigInteger()), c25519.getCurve()); + // END android-removed } public static ECCurve getCurve( @@ -50,28 +62,66 @@ public class EC5Util X962Parameters params) { ECCurve curve; + Set acceptableCurves = configuration.getAcceptableNamedCurves(); if (params.isNamedCurve()) { ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters()); - X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); - curve = ecP.getCurve(); + if (acceptableCurves.isEmpty() || acceptableCurves.contains(oid)) + { + X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); + + if (ecP == null) + { + ecP = (X9ECParameters)configuration.getAdditionalECParameters().get(oid); + } + + curve = ecP.getCurve(); + } + else + { + throw new IllegalStateException("named curve not acceptable"); + } } else if (params.isImplicitlyCA()) { curve = configuration.getEcImplicitlyCa().getCurve(); } - else + else if (acceptableCurves.isEmpty()) { X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); curve = ecP.getCurve(); } + else + { + throw new IllegalStateException("encoded parameters not acceptable"); + } return curve; } + public static ECDomainParameters getDomainParameters( + ProviderConfiguration configuration, + java.security.spec.ECParameterSpec params) + { + ECDomainParameters domainParameters; + + if (params == null) + { + org.bouncycastle.jce.spec.ECParameterSpec iSpec = configuration.getEcImplicitlyCa(); + + domainParameters = new ECDomainParameters(iSpec.getCurve(), iSpec.getG(), iSpec.getN(), iSpec.getH(), iSpec.getSeed()); + } + else + { + domainParameters = ECUtil.getDomainParameters(configuration, convertSpec(params, false)); + } + + return domainParameters; + } + public static ECParameterSpec convertToSpec( X962Parameters params, ECCurve curve) { @@ -82,6 +132,14 @@ public class EC5Util { ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); + if (ecP == null) + { + Map additionalECParameters = BouncyCastleProvider.CONFIGURATION.getAdditionalECParameters(); + if (!additionalECParameters.isEmpty()) + { + ecP = (X9ECParameters)additionalECParameters.get(oid); + } + } ellipticCurve = EC5Util.convertCurve(curve, ecP.getSeed()); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java index 561259ad..6fd4a0dd 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java @@ -5,6 +5,7 @@ import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Enumeration; +import java.util.Map; import org.bouncycastle.asn1.ASN1ObjectIdentifier; // BEGIN android-removed @@ -20,16 +21,19 @@ import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.ECNamedCurveTable; import org.bouncycastle.asn1.x9.X962NamedCurves; +import org.bouncycastle.asn1.x9.X962Parameters; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECNamedDomainParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; -import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; +import org.bouncycastle.jcajce.provider.config.ProviderConfiguration; import org.bouncycastle.jce.interfaces.ECPrivateKey; import org.bouncycastle.jce.interfaces.ECPublicKey; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec; /** @@ -108,6 +112,67 @@ public class ECUtil return res; } + public static ECDomainParameters getDomainParameters( + ProviderConfiguration configuration, + org.bouncycastle.jce.spec.ECParameterSpec params) + { + ECDomainParameters domainParameters; + + if (params instanceof ECNamedCurveParameterSpec) + { + ECNamedCurveParameterSpec nParams = (ECNamedCurveParameterSpec)params; + ASN1ObjectIdentifier nameOid = ECUtil.getNamedCurveOid(nParams.getName()); + + domainParameters = new ECNamedDomainParameters(nameOid, nParams.getCurve(), nParams.getG(), nParams.getN(), nParams.getH(), nParams.getSeed()); + } + else if (params == null) + { + org.bouncycastle.jce.spec.ECParameterSpec iSpec = configuration.getEcImplicitlyCa(); + + domainParameters = new ECDomainParameters(iSpec.getCurve(), iSpec.getG(), iSpec.getN(), iSpec.getH(), iSpec.getSeed()); + } + else + { + domainParameters = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH(), params.getSeed()); + } + + return domainParameters; + } + + public static ECDomainParameters getDomainParameters( + ProviderConfiguration configuration, + X962Parameters params) + { + ECDomainParameters domainParameters; + + if (params.isNamedCurve()) + { + ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters()); + X9ECParameters ecP = ECUtil.getNamedCurveByOid(oid); + if (ecP == null) + { + Map extraCurves = configuration.getAdditionalECParameters(); + + ecP = (X9ECParameters)extraCurves.get(oid); + } + domainParameters = new ECNamedDomainParameters(oid, ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed()); + } + else if (params.isImplicitlyCA()) + { + org.bouncycastle.jce.spec.ECParameterSpec iSpec = configuration.getEcImplicitlyCa(); + + domainParameters = new ECDomainParameters(iSpec.getCurve(), iSpec.getG(), iSpec.getN(), iSpec.getH(), iSpec.getSeed()); + } + else + { + X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); + + domainParameters = new ECDomainParameters(ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed()); + } + + return domainParameters; + } + public static AsymmetricKeyParameter generatePublicKeyParameter( PublicKey key) throws InvalidKeyException @@ -117,20 +182,9 @@ public class ECUtil ECPublicKey k = (ECPublicKey)key; ECParameterSpec s = k.getParameters(); - if (s == null) - { - s = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa(); - - return new ECPublicKeyParameters( - ((BCECPublicKey)k).engineGetQ(), - new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); - } - else - { - return new ECPublicKeyParameters( + return new ECPublicKeyParameters( k.getQ(), new ECDomainParameters(s.getCurve(), s.getG(), s.getN(), s.getH(), s.getSeed())); - } } else if (key instanceof java.security.interfaces.ECPublicKey) { @@ -222,11 +276,11 @@ public class ECUtil throw new InvalidKeyException("can't identify EC private key."); } - public static int getOrderBitLength(BigInteger order, BigInteger privateValue) + public static int getOrderBitLength(ProviderConfiguration configuration, BigInteger order, BigInteger privateValue) { if (order == null) // implicitly CA { - ECParameterSpec implicitCA = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa(); + ECParameterSpec implicitCA = configuration.getEcImplicitlyCa(); if (implicitCA == null) { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java index 2203ce79..f00ee7bd 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java @@ -1,5 +1,7 @@ package org.bouncycastle.jcajce.provider.asymmetric.x509; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; @@ -26,6 +28,7 @@ import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.CertificateList; import org.bouncycastle.jcajce.util.BCJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; +import org.bouncycastle.util.io.Streams; /** * class for dealing with X509 certificates. @@ -200,7 +203,31 @@ public class CertificateFactory } } - PushbackInputStream pis = new PushbackInputStream(in); + InputStream pis; + + if (in.markSupported()) + { + pis = in; + } + else + { + // BEGIN android-changed + // Was: pis = new ByteArrayInputStream(Streams.readAll(in)); + // Reason: we want {@code in.available()} to return the number of available bytes if + // there is trailing data (otherwise it breaks + // libcore.java.security.cert.X509CertificateTest#test_Provider + // ). Which is not possible if we read the whole stream at this point. + pis = new PushbackInputStream(in); + // END android-changed + } + + // BEGIN android-changed + // Was: pis.mark(1); + if (in.markSupported()) { + pis.mark(1); + } + // END android-changed + int tag = pis.read(); if (tag == -1) @@ -208,7 +235,16 @@ public class CertificateFactory return null; } - pis.unread(tag); + // BEGIN android-changdd + // Was: pis.reset + if (in.markSupported()) { + pis.reset(); + } + else + { + ((PushbackInputStream) pis).unread(tag); + } + // END android-changed if (tag != 0x30) // assume ascii PEM encoded. { @@ -234,9 +270,19 @@ public class CertificateFactory throws CertificateException { java.security.cert.Certificate cert; + // BEGIN android-removed + // BufferedInputStream in = new BufferedInputStream(inStream); + // Reason: we want {@code in.available()} to return the number of available bytes if + // there is trailing data (otherwise it breaks + // libcore.java.security.cert.X509CertificateTest#test_Provider + // ). Which is not possible if we read the whole stream at this point. + // END android-removed List certs = new ArrayList(); + // BEGIN android-changed + // Was: while ((cert = engineGenerateCertificate(in)) != null) while ((cert = engineGenerateCertificate(inStream)) != null) + // END android-changed { certs.add(cert); } @@ -249,18 +295,18 @@ public class CertificateFactory * it with the data read from the input stream inStream. */ public CRL engineGenerateCRL( - InputStream inStream) + InputStream in) throws CRLException { if (currentCrlStream == null) { - currentCrlStream = inStream; + currentCrlStream = in; sCrlData = null; sCrlDataObjectCount = 0; } - else if (currentCrlStream != inStream) // reset if input stream has changed + else if (currentCrlStream != in) // reset if input stream has changed { - currentCrlStream = inStream; + currentCrlStream = in; sCrlData = null; sCrlDataObjectCount = 0; } @@ -281,7 +327,18 @@ public class CertificateFactory } } - PushbackInputStream pis = new PushbackInputStream(inStream); + InputStream pis; + + if (in.markSupported()) + { + pis = in; + } + else + { + pis = new ByteArrayInputStream(Streams.readAll(in)); + } + + pis.mark(1); int tag = pis.read(); if (tag == -1) @@ -289,8 +346,7 @@ public class CertificateFactory return null; } - pis.unread(tag); - + pis.reset(); if (tag != 0x30) // assume ascii PEM encoded. { return readPEMCRL(pis); @@ -325,8 +381,9 @@ public class CertificateFactory { CRL crl; List crls = new ArrayList(); + BufferedInputStream in = new BufferedInputStream(inStream); - while ((crl = engineGenerateCRL(inStream)) != null) + while ((crl = engineGenerateCRL(in)) != null) { crls.add(crl); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java index 8116f294..3efd2d69 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PEMUtil.java @@ -43,6 +43,22 @@ class PEMUtil return null; } + // make sure we parse to end of line. + if (c == '\r') + { + // a '\n' may follow + in.mark(1); + if (((c = in.read()) == '\n')) + { + in.mark(1); + } + + if (c > 0) + { + in.reset(); + } + } + return l.toString(); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java index 8242b117..51213d42 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java @@ -68,11 +68,7 @@ import org.bouncycastle.util.Integers; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; -// BEGIN ANDROID-CHANGED -// Was: class X509CertificateObject -// Changed to public so that it can be accessed from X509V3CertificateGenerator -public class X509CertificateObject -// END ANDROID-CHANGED +class X509CertificateObject extends X509Certificate implements PKCS12BagAttributeCarrier { diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java index 61b05452..d94dd16f 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java @@ -16,24 +16,17 @@ import org.bouncycastle.asn1.ASN1Null; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERNull; -// BEGIN android-removed -// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; -// END android-removed -import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; -import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.RSASSAPSSparams; -// BEGIN android-removed -// import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; -// END android-removed import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import org.bouncycastle.jcajce.util.MessageDigestUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; class X509SignatureUtil { private static final ASN1Null derNull = DERNull.INSTANCE; - + static void setSignatureParameters( Signature signature, ASN1Encodable params) @@ -123,51 +116,14 @@ class X509SignatureUtil private static String getDigestAlgName( ASN1ObjectIdentifier digestAlgOID) { - if (PKCSObjectIdentifiers.md5.equals(digestAlgOID)) - { - return "MD5"; - } - else if (OIWObjectIdentifiers.idSHA1.equals(digestAlgOID)) - { - return "SHA1"; - } - else if (NISTObjectIdentifiers.id_sha224.equals(digestAlgOID)) - { - return "SHA224"; - } - else if (NISTObjectIdentifiers.id_sha256.equals(digestAlgOID)) - { - return "SHA256"; - } - else if (NISTObjectIdentifiers.id_sha384.equals(digestAlgOID)) - { - return "SHA384"; - } - else if (NISTObjectIdentifiers.id_sha512.equals(digestAlgOID)) - { - return "SHA512"; - } - // BEGIN android-removed - // else if (TeleTrusTObjectIdentifiers.ripemd128.equals(digestAlgOID)) - // { - // return "RIPEMD128"; - // } - // else if (TeleTrusTObjectIdentifiers.ripemd160.equals(digestAlgOID)) - // { - // return "RIPEMD160"; - // } - // else if (TeleTrusTObjectIdentifiers.ripemd256.equals(digestAlgOID)) - // { - // return "RIPEMD256"; - // } - // else if (CryptoProObjectIdentifiers.gostR3411.equals(digestAlgOID)) - // { - // return "GOST3411"; - // } - // END android-removed - else + String name = MessageDigestUtils.getDigestName(digestAlgOID); + + int dIndex = name.indexOf('-'); + if (dIndex > 0 && !name.startsWith("SHA3")) { - return digestAlgOID.getId(); + return name.substring(0, dIndex) + name.substring(dIndex + 1); } + + return MessageDigestUtils.getDigestName(digestAlgOID); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java index 5fb3ffc9..0865b576 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ConfigurableProvider.java @@ -29,6 +29,16 @@ public interface ConfigurableProvider */ static final String DH_DEFAULT_PARAMS = "DhDefaultParams"; + /** + * A set of OBJECT IDENTIFIERs representing acceptable named curves for imported keys. + */ + static final String ACCEPTABLE_EC_CURVES = "acceptableEcCurves"; + + /** + * A set of OBJECT IDENTIFIERs to EC Curves providing local curve name mapping. + */ + static final String ADDITIONAL_EC_PARAMETERS = "additionalEcParameters"; + void setParameter(String parameterName, Object parameter); void addAlgorithm(String key, String value); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java index 2d99ed9b..e293d9f7 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfiguration.java @@ -1,5 +1,8 @@ package org.bouncycastle.jcajce.provider.config; +import java.util.Map; +import java.util.Set; + import javax.crypto.spec.DHParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec; @@ -9,4 +12,8 @@ public interface ProviderConfiguration ECParameterSpec getEcImplicitlyCa(); DHParameterSpec getDHDefaultParameters(int keySize); + + Set getAcceptableNamedCurves(); + + Map getAdditionalECParameters(); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfigurationPermission.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfigurationPermission.java index b21afc54..8d937877 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfigurationPermission.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/ProviderConfigurationPermission.java @@ -27,18 +27,23 @@ import org.bouncycastle.util.Strings; public class ProviderConfigurationPermission extends BasicPermission { - private static final int THREAD_LOCAL_EC_IMPLICITLY_CA = 0x01; - private static final int EC_IMPLICITLY_CA = 0x02; - private static final int THREAD_LOCAL_DH_DEFAULT_PARAMS = 0x04; - private static final int DH_DEFAULT_PARAMS = 0x08; + private static final int THREAD_LOCAL_EC_IMPLICITLY_CA = 0x01; + private static final int EC_IMPLICITLY_CA = 0x02; + private static final int THREAD_LOCAL_DH_DEFAULT_PARAMS = 0x04; + private static final int DH_DEFAULT_PARAMS = 0x08; + private static final int ACCEPTABLE_EC_CURVES = 0x10; + private static final int ADDITIONAL_EC_PARAMETERS = 0x20; - private static final int ALL = THREAD_LOCAL_EC_IMPLICITLY_CA | EC_IMPLICITLY_CA | THREAD_LOCAL_DH_DEFAULT_PARAMS | DH_DEFAULT_PARAMS; + private static final int ALL = + THREAD_LOCAL_EC_IMPLICITLY_CA | EC_IMPLICITLY_CA | THREAD_LOCAL_DH_DEFAULT_PARAMS | DH_DEFAULT_PARAMS | + ACCEPTABLE_EC_CURVES | ADDITIONAL_EC_PARAMETERS; private static final String THREAD_LOCAL_EC_IMPLICITLY_CA_STR = "threadlocalecimplicitlyca"; private static final String EC_IMPLICITLY_CA_STR = "ecimplicitlyca"; private static final String THREAD_LOCAL_DH_DEFAULT_PARAMS_STR = "threadlocaldhdefaultparams"; private static final String DH_DEFAULT_PARAMS_STR = "dhdefaultparams"; - + private static final String ACCEPTABLE_EC_CURVES_STR = "acceptableeccurves"; + private static final String ADDITIONAL_EC_PARAMETERS_STR = "additionalecparameters"; private static final String ALL_STR = "all"; private final String actions; @@ -84,6 +89,14 @@ public class ProviderConfigurationPermission { mask |= DH_DEFAULT_PARAMS; } + else if (s.equals(ACCEPTABLE_EC_CURVES_STR)) + { + mask |= ACCEPTABLE_EC_CURVES; + } + else if (s.equals(ADDITIONAL_EC_PARAMETERS_STR)) + { + mask |= ADDITIONAL_EC_PARAMETERS; + } else if (s.equals(ALL_STR)) { mask |= ALL; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java index 9c99e0b5..35e03189 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA1.java @@ -1,16 +1,9 @@ package org.bouncycastle.jcajce.provider.digest; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; - -import javax.crypto.SecretKey; -import javax.crypto.spec.PBEKeySpec; - import org.bouncycastle.asn1.iana.IANAObjectIdentifiers; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.crypto.CipherKeyGenerator; -import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.digests.SHA1Digest; // BEGIN ANDROID-ADDED import org.bouncycastle.crypto.digests.SHA224Digest; @@ -20,11 +13,8 @@ import org.bouncycastle.crypto.digests.SHA512Digest; // END ANDROID-ADDED import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; -import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator; import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac; -import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory; -import org.bouncycastle.jcajce.provider.symmetric.util.PBE; import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory; public class SHA1 @@ -86,44 +76,6 @@ public class SHA1 } } - // BEGIN ANDROID-ADDED - public static class SHA224Mac - extends BaseMac - { - public SHA224Mac() - { - super(new HMac(new SHA224Digest())); - } - } - - public static class SHA256Mac - extends BaseMac - { - public SHA256Mac() - { - super(new HMac(new SHA256Digest())); - } - } - - public static class SHA384Mac - extends BaseMac - { - public SHA384Mac() - { - super(new HMac(new SHA384Digest())); - } - } - - public static class SHA512Mac - extends BaseMac - { - public SHA512Mac() - { - super(new HMac(new SHA512Digest())); - } - } - // END ANDROID-ADDED - /** * PBEWithHmacSHA */ @@ -136,267 +88,6 @@ public class SHA1 } } - // BEGIN ANDROID-CHANGED - // Was: public static class BasePBKDF2WithHmacSHA1 - private static class BasePBKDF2WithHmacSHA_Variant - // END ANDROID-CHANGED - extends BaseSecretKeyFactory - { - private int scheme; - // BEGIN ANDROID-ADDED - private int digest; - private int keySizeInBits; - private int ivSizeInBits; - // END ANDROID-ADDED - - // BEGIN ANDROID-CHANGED - // Was: public BasePBKDF2WithHmacSHA1(String name, int scheme) - private BasePBKDF2WithHmacSHA_Variant( - String name, int scheme, int digest, int keySizeInBits, int ivSizeInBits) - // END ANDROID-CHANGED - { - super(name, PKCSObjectIdentifiers.id_PBKDF2); - - this.scheme = scheme; - // BEGIN ANDROID-ADDED - this.digest = digest; - this.keySizeInBits = keySizeInBits; - this.ivSizeInBits = ivSizeInBits; - // END ANDROID-ADDED - } - - // BEGIN android-added - private BasePBKDF2WithHmacSHA_Variant(String name, int scheme, int digest) { - this(name, scheme, digest, 0, 0); - } - // END android-added - - protected SecretKey engineGenerateSecret( - KeySpec keySpec) - throws InvalidKeySpecException - { - if (keySpec instanceof PBEKeySpec) - { - PBEKeySpec pbeSpec = (PBEKeySpec)keySpec; - - // BEGIN ANDROID-ADDED - // Allow to specify a key using only the password. The key will be generated later - // when other parameters are known. - if (pbeSpec.getSalt() == null - && pbeSpec.getIterationCount() == 0 - && pbeSpec.getKeyLength() == 0 - && pbeSpec.getPassword().length > 0 - && keySizeInBits != 0) { - return new BCPBEKey( - this.algName, this.algOid, scheme, digest, keySizeInBits, ivSizeInBits, - pbeSpec, - // cipherParameters, to be generated when the PBE parameters are known. - null); - } - // END ANDROID-ADDED - - if (pbeSpec.getSalt() == null) - { - throw new InvalidKeySpecException("missing required salt"); - } - - if (pbeSpec.getIterationCount() <= 0) - { - throw new InvalidKeySpecException("positive iteration count required: " - + pbeSpec.getIterationCount()); - } - - if (pbeSpec.getKeyLength() <= 0) - { - throw new InvalidKeySpecException("positive key length required: " - + pbeSpec.getKeyLength()); - } - - if (pbeSpec.getPassword().length == 0) - { - throw new IllegalArgumentException("password empty"); - } - - // BEGIN android-removed - // int digest = SHA1; - // END android-removed - int keySize = pbeSpec.getKeyLength(); - int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version. - CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize); - - return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param); - } - - throw new InvalidKeySpecException("Invalid KeySpec"); - } - } - - // BEGIN android-added - public static class BasePBKDF2WithHmacSHA1 extends BasePBKDF2WithHmacSHA_Variant { - public BasePBKDF2WithHmacSHA1(String name, int scheme) - { - super(name, scheme, SHA1); - } - } - // END android-added - - public static class PBKDF2WithHmacSHA1UTF8 - extends BasePBKDF2WithHmacSHA1 - { - public PBKDF2WithHmacSHA1UTF8() - { - super("PBKDF2WithHmacSHA1", PKCS5S2_UTF8); - } - } - - public static class PBKDF2WithHmacSHA18BIT - extends BasePBKDF2WithHmacSHA1 - { - public PBKDF2WithHmacSHA18BIT() - { - super("PBKDF2WithHmacSHA1And8bit", PKCS5S2); - } - } - - // BEGIN ANDROID-ADDED - public static class BasePBKDF2WithHmacSHA224 extends BasePBKDF2WithHmacSHA_Variant { - public BasePBKDF2WithHmacSHA224(String name, int scheme) - { - super(name, scheme, SHA224); - } - } - - public static class PBKDF2WithHmacSHA224UTF8 - extends BasePBKDF2WithHmacSHA224 - { - public PBKDF2WithHmacSHA224UTF8() - { - super("PBKDF2WithHmacSHA224", PKCS5S2_UTF8); - } - } - - public static class BasePBKDF2WithHmacSHA256 extends BasePBKDF2WithHmacSHA_Variant { - public BasePBKDF2WithHmacSHA256(String name, int scheme) - { - super(name, scheme, SHA256); - } - } - - public static class PBKDF2WithHmacSHA256UTF8 - extends BasePBKDF2WithHmacSHA256 - { - public PBKDF2WithHmacSHA256UTF8() - { - super("PBKDF2WithHmacSHA256", PKCS5S2_UTF8); - } - } - - - public static class BasePBKDF2WithHmacSHA384 extends BasePBKDF2WithHmacSHA_Variant { - public BasePBKDF2WithHmacSHA384(String name, int scheme) - { - super(name, scheme, SHA384); - } - } - - public static class PBKDF2WithHmacSHA384UTF8 - extends BasePBKDF2WithHmacSHA384 - { - public PBKDF2WithHmacSHA384UTF8() - { - super("PBKDF2WithHmacSHA384", PKCS5S2_UTF8); - } - } - - public static class BasePBKDF2WithHmacSHA512 extends BasePBKDF2WithHmacSHA_Variant { - public BasePBKDF2WithHmacSHA512(String name, int scheme) - { - super(name, scheme, SHA512); - } - } - - public static class PBKDF2WithHmacSHA512UTF8 - extends BasePBKDF2WithHmacSHA512 - { - public PBKDF2WithHmacSHA512UTF8() - { - super("PBKDF2WithHmacSHA512", PKCS5S2_UTF8); - } - } - - public static class PBEWithHmacSHA1AndAES_128 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA1AndAES_128() { - super("PBEWithHmacSHA1AndAES_128", PKCS5S2_UTF8, SHA1, 128, 128); - } - } - - public static class PBEWithHmacSHA224AndAES_128 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA224AndAES_128() { - super("PBEWithHmacSHA224AndAES_128", PKCS5S2_UTF8, SHA224, 128, 128); - } - } - - public static class PBEWithHmacSHA256AndAES_128 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA256AndAES_128() { - super("PBEWithHmacSHA256AndAES_128", PKCS5S2_UTF8, SHA256, 128, 128); - } - } - - public static class PBEWithHmacSHA384AndAES_128 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA384AndAES_128() { - super("PBEWithHmacSHA384AndAES_128", PKCS5S2_UTF8, SHA384, 128, 128); - } - } - - public static class PBEWithHmacSHA512AndAES_128 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA512AndAES_128() { - super("PBEWithHmacSHA512AndAES_128", PKCS5S2_UTF8, SHA512, 128, 128); - } - } - - - public static class PBEWithHmacSHA1AndAES_256 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA1AndAES_256() { - super("PBEWithHmacSHA1AndAES_256", PKCS5S2_UTF8, SHA1, 256, 128); - } - } - - public static class PBEWithHmacSHA224AndAES_256 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA224AndAES_256() { - super("PBEWithHmacSHA224AndAES_256", PKCS5S2_UTF8, SHA224, 256, 128); - } - } - - public static class PBEWithHmacSHA256AndAES_256 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA256AndAES_256() { - super("PBEWithHmacSHA256AndAES_256", PKCS5S2_UTF8, SHA256, 256, 128); - } - } - - public static class PBEWithHmacSHA384AndAES_256 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA384AndAES_256() { - super("PBEWithHmacSHA384AndAES_256", PKCS5S2_UTF8, SHA384, 256, 128); - } - } - - public static class PBEWithHmacSHA512AndAES_256 - extends BasePBKDF2WithHmacSHA_Variant { - public PBEWithHmacSHA512AndAES_256() { - super("PBEWithHmacSHA512AndAES_256", PKCS5S2_UTF8, SHA512, 256, 128); - } - } - // END ANDROID-ADDED - - public static class Mappings extends DigestAlgorithmProvider { @@ -419,38 +110,11 @@ public class SHA1 provider.addAlgorithm("Mac.PBEWITHHMACSHA", PREFIX + "$SHA1Mac"); provider.addAlgorithm("Mac.PBEWITHHMACSHA1", PREFIX + "$SHA1Mac"); - // BEGIN android-added - provider.addAlgorithm("Mac.PBEWITHHMACSHA224", PREFIX + "$SHA224Mac"); - provider.addAlgorithm("Mac.PBEWITHHMACSHA256", PREFIX + "$SHA256Mac"); - provider.addAlgorithm("Mac.PBEWITHHMACSHA384", PREFIX + "$SHA384Mac"); - provider.addAlgorithm("Mac.PBEWITHHMACSHA512", PREFIX + "$SHA512Mac"); - // END android-added provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBEWITHHMACSHA", "PBEWITHHMACSHA1"); provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + OIWObjectIdentifiers.idSHA1, "PBEWITHHMACSHA1"); provider.addAlgorithm("Alg.Alias.Mac." + OIWObjectIdentifiers.idSHA1, "PBEWITHHMACSHA"); provider.addAlgorithm("SecretKeyFactory.PBEWITHHMACSHA1", PREFIX + "$PBEWithMacKeyFactory"); - provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1", PREFIX + "$PBKDF2WithHmacSHA1UTF8"); - // BEGIN android-added - provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA224", PREFIX + "$PBKDF2WithHmacSHA224UTF8"); - provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA256", PREFIX + "$PBKDF2WithHmacSHA256UTF8"); - provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA384", PREFIX + "$PBKDF2WithHmacSHA384UTF8"); - provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA512", PREFIX + "$PBKDF2WithHmacSHA512UTF8"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA1AndAES_128", PREFIX + "$PBEWithHmacSHA1AndAES_128"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA224AndAES_128", PREFIX + "$PBEWithHmacSHA224AndAES_128"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA256AndAES_128", PREFIX + "$PBEWithHmacSHA256AndAES_128"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA384AndAES_128", PREFIX + "$PBEWithHmacSHA384AndAES_128"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA512AndAES_128", PREFIX + "$PBEWithHmacSHA512AndAES_128"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA1AndAES_256", PREFIX + "$PBEWithHmacSHA1AndAES_256"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA224AndAES_256", PREFIX + "$PBEWithHmacSHA224AndAES_256"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA256AndAES_256", PREFIX + "$PBEWithHmacSHA256AndAES_256"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA384AndAES_256", PREFIX + "$PBEWithHmacSHA384AndAES_256"); - provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA512AndAES_256", PREFIX + "$PBEWithHmacSHA512AndAES_256"); - // END android-added - provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WithHmacSHA1AndUTF8", "PBKDF2WithHmacSHA1"); - provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1And8BIT", PREFIX + "$PBKDF2WithHmacSHA18BIT"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2withASCII", "PBKDF2WithHmacSHA1And8BIT"); - provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2with8BIT", "PBKDF2WithHmacSHA1And8BIT"); - } + } } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA224.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA224.java index ba06a0fb..ac83fc23 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA224.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA224.java @@ -68,6 +68,8 @@ public class SHA224 provider.addAlgorithm("Alg.Alias.MessageDigest.SHA224", "SHA-224"); provider.addAlgorithm("Alg.Alias.MessageDigest." + NISTObjectIdentifiers.id_sha224, "SHA-224"); + provider.addAlgorithm("Mac.PBEWITHHMACSHA224", PREFIX + "$HashMac"); + addHMACAlgorithm(provider, "SHA224", PREFIX + "$HashMac", PREFIX + "$KeyGenerator"); addHMACAlias(provider, "SHA224", PKCSObjectIdentifiers.id_hmacWithSHA224); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA256.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA256.java index 4504f306..e129db4d 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA256.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA256.java @@ -92,6 +92,8 @@ public class SHA256 // provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + NISTObjectIdentifiers.id_sha256, "PBEWITHHMACSHA256"); // END android-removed + provider.addAlgorithm("Mac.PBEWITHHMACSHA256", PREFIX + "$HashMac"); + addHMACAlgorithm(provider, "SHA256", PREFIX + "$HashMac", PREFIX + "$KeyGenerator"); addHMACAlias(provider, "SHA256", PKCSObjectIdentifiers.id_hmacWithSHA256); addHMACAlias(provider, "SHA256", NISTObjectIdentifiers.id_sha256); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA384.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA384.java index e5635798..f2fb6d32 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA384.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA384.java @@ -88,6 +88,8 @@ public class SHA384 // provider.addAlgorithm("Mac.OLDHMACSHA384", PREFIX + "$OldSHA384"); // END android-removed + provider.addAlgorithm("Mac.PBEWITHHMACSHA384", PREFIX + "$HashMac"); + addHMACAlgorithm(provider, "SHA384", PREFIX + "$HashMac", PREFIX + "$KeyGenerator"); addHMACAlias(provider, "SHA384", PKCSObjectIdentifiers.id_hmacWithSHA384); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA512.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA512.java index 903eec1b..9433a817 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA512.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/digest/SHA512.java @@ -180,6 +180,8 @@ public class SHA512 // provider.addAlgorithm("Mac.OLDHMACSHA512", PREFIX + "$OldSHA512"); // END android-removed + provider.addAlgorithm("Mac.PBEWITHHMACSHA512", PREFIX + "$HashMac"); + addHMACAlgorithm(provider, "SHA512", PREFIX + "$HashMac", PREFIX + "$KeyGenerator"); addHMACAlias(provider, "SHA512", PKCSObjectIdentifiers.id_hmacWithSHA512); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java index ed0fadce..106f75b2 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java @@ -90,7 +90,10 @@ import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; import org.bouncycastle.crypto.Digest; -import org.bouncycastle.crypto.digests.SHA1Digest; +// BEGIN android-changed +// Was: import org.bouncycastle.crypto.digests.SHA1Digest +import org.bouncycastle.crypto.digests.AndroidDigestFactory; +// END android-changed import org.bouncycastle.jcajce.PKCS12Key; import org.bouncycastle.jcajce.PKCS12StoreParameter; // BEGIN android-removed @@ -230,7 +233,7 @@ public class PKCS12KeyStoreSpi private static byte[] getDigest(SubjectPublicKeyInfo spki) { - Digest digest = new SHA1Digest(); + Digest digest = AndroidDigestFactory.getSHA1(); byte[] resBuf = new byte[digest.getDigestSize()]; byte[] bytes = spki.getPublicKeyData().getBytes(); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java index 0328ac8b..ed7342d8 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/AES.java @@ -26,7 +26,11 @@ import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.CipherKeyGenerator; -import org.bouncycastle.crypto.engines.AESFastEngine; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.Mac; +import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.engines.AESWrapEngine; // BEGIN android-removed // import org.bouncycastle.crypto.engines.RFC3211WrapEngine; @@ -51,11 +55,13 @@ import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher; import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator; // BEGIN android-removed // import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac; +// import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory; // END android-removed import org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher; import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider; import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters; import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory; +import org.bouncycastle.jcajce.spec.AEADParameterSpec; public final class AES { @@ -74,7 +80,7 @@ public final class AES { public BlockCipher get() { - return new AESFastEngine(); + return new AESEngine(); } }); } @@ -85,7 +91,7 @@ public final class AES { public CBC() { - super(new CBCBlockCipher(new AESFastEngine()), 128); + super(new CBCBlockCipher(new AESEngine()), 128); } } @@ -94,7 +100,7 @@ public final class AES { public CFB() { - super(new BufferedBlockCipher(new CFBBlockCipher(new AESFastEngine(), 128)), 128); + super(new BufferedBlockCipher(new CFBBlockCipher(new AESEngine(), 128)), 128); } } @@ -103,7 +109,7 @@ public final class AES { public OFB() { - super(new BufferedBlockCipher(new OFBBlockCipher(new AESFastEngine(), 128)), 128); + super(new BufferedBlockCipher(new OFBBlockCipher(new AESEngine(), 128)), 128); } } @@ -112,7 +118,7 @@ public final class AES { public GCM() { - super(new GCMBlockCipher(new AESFastEngine())); + super(new GCMBlockCipher(new AESEngine())); // BEGIN android-added try { engineSetMode("GCM"); @@ -131,37 +137,111 @@ public final class AES // { // public CCM() // { - // super(new CCMBlockCipher(new AESFastEngine()), false, 16); + // super(new CCMBlockCipher(new AESEngine()), false, 16); // } // } - // + // public static class AESCMAC // extends BaseMac // { // public AESCMAC() // { - // super(new CMac(new AESFastEngine())); + // super(new CMac(new AESEngine())); // } // } - // + // public static class AESGMAC // extends BaseMac // { // public AESGMAC() // { - // super(new GMac(new GCMBlockCipher(new AESFastEngine()))); + // super(new GMac(new GCMBlockCipher(new AESEngine()))); // } // } - // + + // public static class AESCCMMAC + // extends BaseMac + // { + // public AESCCMMAC() + // { + // super(new CCMMac()); + // } + + // private static class CCMMac + // implements Mac + // { + // private final CCMBlockCipher ccm = new CCMBlockCipher(new AESEngine()); + + // private int macLength = 8; + + // public void init(CipherParameters params) + // throws IllegalArgumentException + // { + // ccm.init(true, params); + + // this.macLength = ccm.getMac().length; + // } + + // public String getAlgorithmName() + // { + // return ccm.getAlgorithmName() + "Mac"; + // } + + // public int getMacSize() + // { + // return macLength; + // } + + // public void update(byte in) + // throws IllegalStateException + // { + // ccm.processAADByte(in); + // } + + // public void update(byte[] in, int inOff, int len) + // throws DataLengthException, IllegalStateException + // { + // ccm.processAADBytes(in, inOff, len); + // } + + // public int doFinal(byte[] out, int outOff) + // throws DataLengthException, IllegalStateException + // { + // try + // { + // return ccm.doFinal(out, 0); + // } + // catch (InvalidCipherTextException e) + // { + // throw new IllegalStateException("exception on doFinal(): " + e.toString()); + // } + // } + + // public void reset() + // { + // ccm.reset(); + // } + // } + // } + + // static public class KeyFactory + // extends BaseSecretKeyFactory + // { + // public KeyFactory() + // { + // super("AES", null); + // } + // } + // public static class Poly1305 // extends BaseMac // { // public Poly1305() // { - // super(new org.bouncycastle.crypto.macs.Poly1305(new AESFastEngine())); + // super(new org.bouncycastle.crypto.macs.Poly1305(new AESEngine())); // } // } - // + // public static class Poly1305KeyGen // extends BaseKeyGenerator // { @@ -187,16 +267,16 @@ public final class AES // { // public RFC3211Wrap() // { - // super(new RFC3211WrapEngine(new AESFastEngine()), 16); + // super(new RFC3211WrapEngine(new AESEngine()), 16); // } // } - // + // public static class RFC5649Wrap // extends BaseWrapCipher // { // public RFC5649Wrap() // { - // super(new RFC5649WrapEngine(new AESFastEngine())); + // super(new RFC5649WrapEngine(new AESEngine())); // } // } // END android-removed @@ -209,7 +289,7 @@ public final class AES { public PBEWithAESCBC() { - super(new CBCBlockCipher(new AESFastEngine())); + super(new CBCBlockCipher(new AESEngine())); } } @@ -221,7 +301,7 @@ public final class AES { public PBEWithSHA1AESCBC128() { - super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA1, 128, 16); + super(new CBCBlockCipher(new AESEngine()), PKCS12, SHA1, 128, 16); } } @@ -230,7 +310,7 @@ public final class AES { public PBEWithSHA1AESCBC192() { - super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA1, 192, 16); + super(new CBCBlockCipher(new AESEngine()), PKCS12, SHA1, 192, 16); } } @@ -239,7 +319,7 @@ public final class AES { public PBEWithSHA1AESCBC256() { - super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA1, 256, 16); + super(new CBCBlockCipher(new AESEngine()), PKCS12, SHA1, 256, 16); } } @@ -251,7 +331,7 @@ public final class AES { public PBEWithSHA256AESCBC128() { - super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA256, 128, 16); + super(new CBCBlockCipher(new AESEngine()), PKCS12, SHA256, 128, 16); } } @@ -260,7 +340,7 @@ public final class AES { public PBEWithSHA256AESCBC192() { - super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA256, 192, 16); + super(new CBCBlockCipher(new AESEngine()), PKCS12, SHA256, 192, 16); } } @@ -269,7 +349,7 @@ public final class AES { public PBEWithSHA256AESCBC256() { - super(new CBCBlockCipher(new AESFastEngine()), PKCS12, SHA256, 256, 16); + super(new CBCBlockCipher(new AESEngine()), PKCS12, SHA256, 256, 16); } } @@ -425,7 +505,7 @@ public final class AES super("PBEWithMD5And256BitAES-CBC-OpenSSL", null, true, OPENSSL, MD5, 256, 128); } } - + // BEGIN android-removed // public static class AlgParamGen // extends BaseAlgorithmParameterGenerator @@ -437,20 +517,20 @@ public final class AES // { // throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation."); // } - // + // protected AlgorithmParameters engineGenerateParameters() // { // byte[] iv = new byte[16]; - // + // if (random == null) // { // random = new SecureRandom(); // } - // + // random.nextBytes(iv); - // + // AlgorithmParameters params; - // + // try // { // params = createParametersInstance("AES"); @@ -460,11 +540,11 @@ public final class AES // { // throw new RuntimeException(e.getMessage()); // } - // + // return params; // } // } - // + // public static class AlgParamGenCCM // extends BaseAlgorithmParameterGenerator // { @@ -473,22 +553,23 @@ public final class AES // SecureRandom random) // throws InvalidAlgorithmParameterException // { + // // TODO: add support for GCMParameterSpec as a template. // throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation."); // } - // + // protected AlgorithmParameters engineGenerateParameters() // { // byte[] iv = new byte[12]; - // + // if (random == null) // { // random = new SecureRandom(); // } - // + // random.nextBytes(iv); - // + // AlgorithmParameters params; - // + // try // { // params = createParametersInstance("CCM"); @@ -498,11 +579,11 @@ public final class AES // { // throw new RuntimeException(e.getMessage()); // } - // + // return params; // } // } - // + // public static class AlgParamGenGCM // extends BaseAlgorithmParameterGenerator // { @@ -511,32 +592,33 @@ public final class AES // SecureRandom random) // throws InvalidAlgorithmParameterException // { + // // TODO: add support for GCMParameterSpec as a template. // throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation."); // } - // + // protected AlgorithmParameters engineGenerateParameters() // { // byte[] nonce = new byte[12]; - // + // if (random == null) // { // random = new SecureRandom(); // } - // + // random.nextBytes(nonce); - // + // AlgorithmParameters params; - // + // try // { // params = createParametersInstance("GCM"); - // params.init(new GCMParameters(nonce, 12).getEncoded()); + // params.init(new GCMParameters(nonce, 16).getEncoded()); // } // catch (Exception e) // { // throw new RuntimeException(e.getMessage()); // } - // + // return params; // } // } @@ -563,6 +645,10 @@ public final class AES { gcmParams = GcmSpecUtil.extractGcmParameters(paramSpec); } + else if (paramSpec instanceof AEADParameterSpec) + { + gcmParams = new GCMParameters(((AEADParameterSpec)paramSpec).getNonce(), ((AEADParameterSpec)paramSpec).getMacSizeInBits() / 8); + } else { throw new InvalidParameterSpecException("AlgorithmParameterSpec class not recognized: " + paramSpec.getClass().getName()); @@ -617,7 +703,11 @@ public final class AES { return GcmSpecUtil.extractGcmSpec(gcmParams.toASN1Primitive()); } - return new IvParameterSpec(gcmParams.getNonce()); + return new AEADParameterSpec(gcmParams.getNonce(), gcmParams.getIcvLen() * 8); + } + if (paramSpec == AEADParameterSpec.class) + { + return new AEADParameterSpec(gcmParams.getNonce(), gcmParams.getIcvLen() * 8); } if (paramSpec == IvParameterSpec.class) { @@ -633,7 +723,7 @@ public final class AES // extends BaseAlgorithmParameters // { // private CCMParameters ccmParams; - // + // protected void engineInit(AlgorithmParameterSpec paramSpec) // throws InvalidParameterSpecException // { @@ -641,18 +731,22 @@ public final class AES // { // ccmParams = CCMParameters.getInstance(GcmSpecUtil.extractGcmParameters(paramSpec)); // } + // else if (paramSpec instanceof AEADParameterSpec) + // { + // ccmParams = new CCMParameters(((AEADParameterSpec)paramSpec).getNonce(), ((AEADParameterSpec)paramSpec).getMacSizeInBits() / 8); + // } // else // { // throw new InvalidParameterSpecException("AlgorithmParameterSpec class not recognized: " + paramSpec.getClass().getName()); // } // } - // + // protected void engineInit(byte[] params) // throws IOException // { // ccmParams = CCMParameters.getInstance(params); // } - // + // protected void engineInit(byte[] params, String format) // throws IOException // { @@ -660,16 +754,16 @@ public final class AES // { // throw new IOException("unknown format specified"); // } - // + // ccmParams = CCMParameters.getInstance(params); // } - // + // protected byte[] engineGetEncoded() // throws IOException // { // return ccmParams.getEncoded(); // } - // + // protected byte[] engineGetEncoded(String format) // throws IOException // { @@ -677,15 +771,15 @@ public final class AES // { // throw new IOException("unknown format specified"); // } - // + // return ccmParams.getEncoded(); // } - // + // protected String engineToString() // { // return "CCM"; // } - // + // protected AlgorithmParameterSpec localEngineGetParameterSpec(Class paramSpec) // throws InvalidParameterSpecException // { @@ -695,13 +789,17 @@ public final class AES // { // return GcmSpecUtil.extractGcmSpec(ccmParams.toASN1Primitive()); // } - // return new IvParameterSpec(ccmParams.getNonce()); + // return new AEADParameterSpec(ccmParams.getNonce(), ccmParams.getIcvLen() * 8); + // } + // if (paramSpec == AEADParameterSpec.class) + // { + // return new AEADParameterSpec(ccmParams.getNonce(), ccmParams.getIcvLen() * 8); // } // if (paramSpec == IvParameterSpec.class) // { // return new IvParameterSpec(ccmParams.getNonce()); // } - // + // throw new InvalidParameterSpecException("AlgorithmParameterSpec not recognized: " + paramSpec.getName()); // } // } @@ -832,10 +930,15 @@ public final class AES // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_CCM, PREFIX + "$KeyGen128"); // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_CCM, PREFIX + "$KeyGen192"); // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_CCM, PREFIX + "$KeyGen256"); - // + // provider.addAlgorithm("Mac.AESCMAC", PREFIX + "$AESCMAC"); + + // provider.addAlgorithm("Mac.AESCCMMAC", PREFIX + "$AESCCMMAC"); + // provider.addAlgorithm("Alg.Alias.Mac." + NISTObjectIdentifiers.id_aes128_CCM.getId(), "AESCCMMAC"); + // provider.addAlgorithm("Alg.Alias.Mac." + NISTObjectIdentifiers.id_aes192_CCM.getId(), "AESCCMMAC"); + // provider.addAlgorithm("Alg.Alias.Mac." + NISTObjectIdentifiers.id_aes256_CCM.getId(), "AESCCMMAC"); // END android-removed - + provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc, "PBEWITHSHAAND128BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc, "PBEWITHSHAAND192BITAES-CBC-BC"); provider.addAlgorithm("Alg.Alias.Cipher", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc, "PBEWITHSHAAND256BITAES-CBC-BC"); @@ -878,7 +981,12 @@ public final class AES provider.addAlgorithm("Cipher.PBEWITHMD5AND128BITAES-CBC-OPENSSL", PREFIX + "$PBEWithAESCBC"); provider.addAlgorithm("Cipher.PBEWITHMD5AND192BITAES-CBC-OPENSSL", PREFIX + "$PBEWithAESCBC"); provider.addAlgorithm("Cipher.PBEWITHMD5AND256BITAES-CBC-OPENSSL", PREFIX + "$PBEWithAESCBC"); - + + // BEGIN android-removed + // provider.addAlgorithm("SecretKeyFactory.AES", PREFIX + "$KeyFactory"); + // provider.addAlgorithm("SecretKeyFactory", NISTObjectIdentifiers.aes, PREFIX + "$KeyFactory"); + // END android-removed + provider.addAlgorithm("SecretKeyFactory.PBEWITHMD5AND128BITAES-CBC-OPENSSL", PREFIX + "$PBEWithMD5And128BitAESCBCOpenSSL"); provider.addAlgorithm("SecretKeyFactory.PBEWITHMD5AND192BITAES-CBC-OPENSSL", PREFIX + "$PBEWithMD5And192BitAESCBCOpenSSL"); provider.addAlgorithm("SecretKeyFactory.PBEWITHMD5AND256BITAES-CBC-OPENSSL", PREFIX + "$PBEWithMD5And256BitAESCBCOpenSSL"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java index 64d8972a..c89fe348 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java @@ -18,6 +18,7 @@ import javax.crypto.spec.DESedeKeySpec; // END android-removed import javax.crypto.spec.SecretKeySpec; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.crypto.KeyGenerationParameters; import org.bouncycastle.crypto.engines.DESedeEngine; @@ -433,16 +434,18 @@ public final class DESede provider.addAlgorithm("SecretKeyFactory.DESEDE", PREFIX + "$KeyFactory"); // BEGIN android-removed + // provider.addAlgorithm("SecretKeyFactory", OIWObjectIdentifiers.desEDE, PREFIX + "$KeyFactory"); + // provider.addAlgorithm("Mac.DESEDECMAC", PREFIX + "$CMAC"); // provider.addAlgorithm("Mac.DESEDEMAC", PREFIX + "$CBCMAC"); // provider.addAlgorithm("Alg.Alias.Mac.DESEDE", "DESEDEMAC"); - // + // provider.addAlgorithm("Mac.DESEDEMAC/CFB8", PREFIX + "$DESedeCFB8"); // provider.addAlgorithm("Alg.Alias.Mac.DESEDE/CFB8", "DESEDEMAC/CFB8"); - // + // provider.addAlgorithm("Mac.DESEDEMAC64", PREFIX + "$DESede64"); // provider.addAlgorithm("Alg.Alias.Mac.DESEDE64", "DESEDEMAC64"); - // + // provider.addAlgorithm("Mac.DESEDEMAC64WITHISO7816-4PADDING", PREFIX + "$DESede64with7816d4"); // provider.addAlgorithm("Alg.Alias.Mac.DESEDE64WITHISO7816-4PADDING", "DESEDEMAC64WITHISO7816-4PADDING"); // provider.addAlgorithm("Alg.Alias.Mac.DESEDEISO9797ALG1MACWITHISO7816-4PADDING", "DESEDEMAC64WITHISO7816-4PADDING"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java new file mode 100644 index 00000000..b19a4d43 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/PBEPBKDF2.java @@ -0,0 +1,553 @@ +package org.bouncycastle.jcajce.provider.symmetric; + +import java.io.IOException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +import java.security.spec.KeySpec; + +import javax.crypto.SecretKey; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; + +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +// BEGIN android-removed +// import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +// END android-removed +import org.bouncycastle.asn1.pkcs.PBKDF2Params; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; +import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseAlgorithmParameters; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory; +import org.bouncycastle.jcajce.provider.symmetric.util.PBE; +import org.bouncycastle.jcajce.provider.util.AlgorithmProvider; +import org.bouncycastle.jcajce.spec.PBKDF2KeySpec; + +public class PBEPBKDF2 +{ + private PBEPBKDF2() + { + + } + + // BEGIN android-removed + // public static class AlgParams + // extends BaseAlgorithmParameters + // { + // PBKDF2Params params; + // + // protected byte[] engineGetEncoded() + // { + // try + // { + // return params.getEncoded(ASN1Encoding.DER); + // } + // catch (IOException e) + // { + // throw new RuntimeException("Oooops! " + e.toString()); + // } + // } + + // protected byte[] engineGetEncoded( + // String format) + // { + // if (this.isASN1FormatString(format)) + // { + // return engineGetEncoded(); + // } + // + // return null; + // } + // + // protected AlgorithmParameterSpec localEngineGetParameterSpec( + // Class paramSpec) + // throws InvalidParameterSpecException + // { + // if (paramSpec == PBEParameterSpec.class) + // { + // return new PBEParameterSpec(params.getSalt(), + // params.getIterationCount().intValue()); + // } + // + // throw new InvalidParameterSpecException("unknown parameter spec passed to PBKDF2 PBE parameters object."); + // } + // + // protected void engineInit( + // AlgorithmParameterSpec paramSpec) + // throws InvalidParameterSpecException + // { + // if (!(paramSpec instanceof PBEParameterSpec)) + // { + // throw new InvalidParameterSpecException("PBEParameterSpec required to initialise a PBKDF2 PBE parameters algorithm parameters object"); + // } + // + // PBEParameterSpec pbeSpec = (PBEParameterSpec)paramSpec; + // + // this.params = new PBKDF2Params(pbeSpec.getSalt(), + // pbeSpec.getIterationCount()); + // } + // + // protected void engineInit( + // byte[] params) + // throws IOException + // { + // this.params = PBKDF2Params.getInstance(ASN1Primitive.fromByteArray(params)); + // } + // + // protected void engineInit( + // byte[] params, + // String format) + // throws IOException + // { + // if (this.isASN1FormatString(format)) + // { + // engineInit(params); + // return; + // } + // + // throw new IOException("Unknown parameters format in PBKDF2 parameters object"); + // } + // + // protected String engineToString() + // { + // return "PBKDF2 Parameters"; + // } + // } + // END android-removed + + public static class BasePBKDF2 + extends BaseSecretKeyFactory + { + private int scheme; + // BEGIN ANDROID-ADDED + private int keySizeInBits; + private int ivSizeInBits; + // END ANDROID-ADDED + private int defaultDigest; + + public BasePBKDF2(String name, int scheme) + { + this(name, scheme, SHA1); + } + + // BEGIN ANDROID-CHANGED + // Was: public BasePBKDF2(String name, int scheme, int defaultDigest) + private BasePBKDF2( + String name, int scheme, int digest, int keySizeInBits, int ivSizeInBits) + // END ANDROID-CHANGED + { + super(name, PKCSObjectIdentifiers.id_PBKDF2); + + this.scheme = scheme; + // BEGIN ANDROID-ADDED + this.keySizeInBits = keySizeInBits; + this.ivSizeInBits = ivSizeInBits; + // END ANDROID-ADDED + this.defaultDigest = digest; + } + + // BEGIN android-added + private BasePBKDF2(String name, int scheme, int digest) { + this(name, scheme, digest, 0, 0); + } + // END android-added + + protected SecretKey engineGenerateSecret( + KeySpec keySpec) + throws InvalidKeySpecException + { + if (keySpec instanceof PBEKeySpec) + { + PBEKeySpec pbeSpec = (PBEKeySpec)keySpec; + + // BEGIN ANDROID-ADDED + // Allow to specify a key using only the password. The key will be generated later + // when other parameters are known. + if (pbeSpec.getSalt() == null + && pbeSpec.getIterationCount() == 0 + && pbeSpec.getKeyLength() == 0 + && pbeSpec.getPassword().length > 0 + && keySizeInBits != 0) { + return new BCPBEKey( + this.algName, this.algOid, scheme, defaultDigest, keySizeInBits, + ivSizeInBits, pbeSpec, + // cipherParameters, to be generated when the PBE parameters are known. + null); + } + // END ANDROID-ADDED + + if (pbeSpec.getSalt() == null) + { + throw new InvalidKeySpecException("missing required salt"); + } + + if (pbeSpec.getIterationCount() <= 0) + { + throw new InvalidKeySpecException("positive iteration count required: " + + pbeSpec.getIterationCount()); + } + + if (pbeSpec.getKeyLength() <= 0) + { + throw new InvalidKeySpecException("positive key length required: " + + pbeSpec.getKeyLength()); + } + + if (pbeSpec.getPassword().length == 0) + { + throw new IllegalArgumentException("password empty"); + } + + if (pbeSpec instanceof PBKDF2KeySpec) + { + PBKDF2KeySpec spec = (PBKDF2KeySpec)pbeSpec; + + int digest = getDigestCode(spec.getPrf().getAlgorithm()); + int keySize = pbeSpec.getKeyLength(); + int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version. + CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize); + + return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param); + } + else + { + int digest = defaultDigest; + int keySize = pbeSpec.getKeyLength(); + int ivSize = -1; // JDK 1,2 and earlier does not understand simplified version. + CipherParameters param = PBE.Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize); + + return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param); + } + } + + throw new InvalidKeySpecException("Invalid KeySpec"); + } + + + private int getDigestCode(ASN1ObjectIdentifier algorithm) + throws InvalidKeySpecException + { + // BEGIN android-removed + // if (algorithm.equals(CryptoProObjectIdentifiers.gostR3411Hmac)) + // { + // return GOST3411; + // } + // else + // END android-removed + if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA1)) + { + return SHA1; + } + else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA256)) + { + return SHA256; + } + else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA224)) + { + return SHA224; + } + else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA384)) + { + return SHA384; + } + else if (algorithm.equals(PKCSObjectIdentifiers.id_hmacWithSHA512)) + { + return SHA512; + } + + throw new InvalidKeySpecException("Invalid KeySpec: unknown PRF algorithm " + algorithm); + } + } + + // BEGIN android-removed + // public static class PBKDF2withUTF8 + // extends BasePBKDF2 + // { + // public PBKDF2withUTF8() + // { + // super("PBKDF2", PKCS5S2_UTF8); + // } + // } + // + // public static class PBKDF2withSHA224 + // extends BasePBKDF2 + // { + // public PBKDF2withSHA224() + // { + // super("PBKDF2", PKCS5S2_UTF8, SHA224); + // } + // } + // + // public static class PBKDF2withSHA256 + // extends BasePBKDF2 + // { + // public PBKDF2withSHA256() + // { + // super("PBKDF2", PKCS5S2_UTF8, SHA256); + // } + // } + // + // public static class PBKDF2withSHA384 + // extends BasePBKDF2 + // { + // public PBKDF2withSHA384() + // { + // super("PBKDF2", PKCS5S2_UTF8, SHA384); + // } + // } + // + // public static class PBKDF2withSHA512 + // extends BasePBKDF2 + // { + // public PBKDF2withSHA512() + // { + // super("PBKDF2", PKCS5S2_UTF8, SHA512); + // } + // } + // + // public static class PBKDF2with8BIT + // extends BasePBKDF2 + // { + // public PBKDF2with8BIT() + // { + // super("PBKDF2", PKCS5S2); + // } + // } + + // BEGIN android-added + public static class BasePBKDF2WithHmacSHA1 extends BasePBKDF2 { + public BasePBKDF2WithHmacSHA1(String name, int scheme) + { + super(name, scheme, SHA1); + } + } + + public static class PBKDF2WithHmacSHA1UTF8 + extends BasePBKDF2WithHmacSHA1 + { + public PBKDF2WithHmacSHA1UTF8() + { + super("PBKDF2WithHmacSHA1", PKCS5S2_UTF8); + } + } + + public static class PBKDF2WithHmacSHA18BIT + extends BasePBKDF2WithHmacSHA1 + { + public PBKDF2WithHmacSHA18BIT() + { + super("PBKDF2WithHmacSHA1And8bit", PKCS5S2); + } + } + + public static class BasePBKDF2WithHmacSHA224 extends BasePBKDF2 { + public BasePBKDF2WithHmacSHA224(String name, int scheme) + { + super(name, scheme, SHA224); + } + } + + public static class PBKDF2WithHmacSHA224UTF8 + extends BasePBKDF2WithHmacSHA224 + { + public PBKDF2WithHmacSHA224UTF8() + { + super("PBKDF2WithHmacSHA224", PKCS5S2_UTF8); + } + } + + public static class BasePBKDF2WithHmacSHA256 extends BasePBKDF2 { + public BasePBKDF2WithHmacSHA256(String name, int scheme) + { + super(name, scheme, SHA256); + } + } + + public static class PBKDF2WithHmacSHA256UTF8 + extends BasePBKDF2WithHmacSHA256 + { + public PBKDF2WithHmacSHA256UTF8() + { + super("PBKDF2WithHmacSHA256", PKCS5S2_UTF8); + } + } + + + public static class BasePBKDF2WithHmacSHA384 extends BasePBKDF2 { + public BasePBKDF2WithHmacSHA384(String name, int scheme) + { + super(name, scheme, SHA384); + } + } + + public static class PBKDF2WithHmacSHA384UTF8 + extends BasePBKDF2WithHmacSHA384 + { + public PBKDF2WithHmacSHA384UTF8() + { + super("PBKDF2WithHmacSHA384", PKCS5S2_UTF8); + } + } + + public static class BasePBKDF2WithHmacSHA512 extends BasePBKDF2 { + public BasePBKDF2WithHmacSHA512(String name, int scheme) + { + super(name, scheme, SHA512); + } + } + + public static class PBKDF2WithHmacSHA512UTF8 + extends BasePBKDF2WithHmacSHA512 + { + public PBKDF2WithHmacSHA512UTF8() + { + super("PBKDF2WithHmacSHA512", PKCS5S2_UTF8); + } + } + + public static class PBEWithHmacSHA1AndAES_128 + extends BasePBKDF2 { + public PBEWithHmacSHA1AndAES_128() { + super("PBEWithHmacSHA1AndAES_128", PKCS5S2_UTF8, SHA1, 128, 128); + } + } + + public static class PBEWithHmacSHA224AndAES_128 + extends BasePBKDF2 { + public PBEWithHmacSHA224AndAES_128() { + super("PBEWithHmacSHA224AndAES_128", PKCS5S2_UTF8, SHA224, 128, 128); + } + } + + public static class PBEWithHmacSHA256AndAES_128 + extends BasePBKDF2 { + public PBEWithHmacSHA256AndAES_128() { + super("PBEWithHmacSHA256AndAES_128", PKCS5S2_UTF8, SHA256, 128, 128); + } + } + + public static class PBEWithHmacSHA384AndAES_128 + extends BasePBKDF2 { + public PBEWithHmacSHA384AndAES_128() { + super("PBEWithHmacSHA384AndAES_128", PKCS5S2_UTF8, SHA384, 128, 128); + } + } + + public static class PBEWithHmacSHA512AndAES_128 + extends BasePBKDF2 { + public PBEWithHmacSHA512AndAES_128() { + super("PBEWithHmacSHA512AndAES_128", PKCS5S2_UTF8, SHA512, 128, 128); + } + } + + + public static class PBEWithHmacSHA1AndAES_256 + extends BasePBKDF2 { + public PBEWithHmacSHA1AndAES_256() { + super("PBEWithHmacSHA1AndAES_256", PKCS5S2_UTF8, SHA1, 256, 128); + } + } + + public static class PBEWithHmacSHA224AndAES_256 + extends BasePBKDF2 { + public PBEWithHmacSHA224AndAES_256() { + super("PBEWithHmacSHA224AndAES_256", PKCS5S2_UTF8, SHA224, 256, 128); + } + } + + public static class PBEWithHmacSHA256AndAES_256 + extends BasePBKDF2 { + public PBEWithHmacSHA256AndAES_256() { + super("PBEWithHmacSHA256AndAES_256", PKCS5S2_UTF8, SHA256, 256, 128); + } + } + + public static class PBEWithHmacSHA384AndAES_256 + extends BasePBKDF2 { + public PBEWithHmacSHA384AndAES_256() { + super("PBEWithHmacSHA384AndAES_256", PKCS5S2_UTF8, SHA384, 256, 128); + } + } + + public static class PBEWithHmacSHA512AndAES_256 + extends BasePBKDF2 { + public PBEWithHmacSHA512AndAES_256() { + super("PBEWithHmacSHA512AndAES_256", PKCS5S2_UTF8, SHA512, 256, 128); + } + } + // END android-added + + public static class Mappings + extends AlgorithmProvider + { + private static final String PREFIX = PBEPBKDF2.class.getName(); + + public Mappings() + { + } + + public void configure(ConfigurableProvider provider) + { + // BEGIN android-comment + // Context: many of these services used to be in + // com.android.org.bouncycastle.jcajce.provider.digest,SHA1, duplicated with respect to here. This + // class (PBEPBKDF2) wasn't present in Android until the upgrade to 1.56. Android added + // some other of these services in SHA1 (for fixed key sizes). Then the duplicate + // algorithms were removed upstream from SHA1 in + // b5634e3155e7fd8688599d3eef8e4f3c8a1db078 + // . As a result, when adapting BouncyCastle 1.56 from upstream, the Android code that + // had been added to SHA1 was moved here, and the rest of the services provided by this + // class were commented. + // BEGIN android-removed + // provider.addAlgorithm("AlgorithmParameters.PBKDF2", PREFIX + "$AlgParams"); + // provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2"); + // provider.addAlgorithm("SecretKeyFactory.PBKDF2", PREFIX + "$PBKDF2withUTF8"); + // provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WITHHMACSHA1", "PBKDF2"); + // END android-removed + // BEGIN android-changed + // Was: provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WITHHMACSHA1ANDUTF8", "PBKDF2"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WithHmacSHA1AndUTF8", "PBKDF2WithHmacSHA1"); + // END android-changed + // BEGin android-removed + // provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.id_PBKDF2, "PBKDF2"); + // provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHASCII", PREFIX + "$PBKDF2with8BIT"); + // END android-removed + // BEGIN android-changed + // Was: + // provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WITH8BIT", "PBKDF2WITHASCII"); + // provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2WITHHMACSHA1AND8BIT", "PBKDF2WITHASCII"); + provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2with8BIT", "PBKDF2WithHmacSHA1And8BIT"); + // END android-changed + // BEGIN android-added + provider.addAlgorithm("Alg.Alias.SecretKeyFactory.PBKDF2withASCII", "PBKDF2WithHmacSHA1And8BIT"); + // BEGIN android-removed + // provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA224", PREFIX + "$PBKDF2withSHA224"); + // provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA256", PREFIX + "$PBKDF2withSHA256"); + // provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA384", PREFIX + "$PBKDF2withSHA384"); + // provider.addAlgorithm("SecretKeyFactory.PBKDF2WITHHMACSHA512", PREFIX + "$PBKDF2withSHA512"); + // END android-removed + // BEGIN android-added + provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1", PREFIX + "$PBKDF2WithHmacSHA1UTF8"); + provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA224", PREFIX + "$PBKDF2WithHmacSHA224UTF8"); + provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA256", PREFIX + "$PBKDF2WithHmacSHA256UTF8"); + provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA384", PREFIX + "$PBKDF2WithHmacSHA384UTF8"); + provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA512", PREFIX + "$PBKDF2WithHmacSHA512UTF8"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA1AndAES_128", PREFIX + "$PBEWithHmacSHA1AndAES_128"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA224AndAES_128", PREFIX + "$PBEWithHmacSHA224AndAES_128"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA256AndAES_128", PREFIX + "$PBEWithHmacSHA256AndAES_128"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA384AndAES_128", PREFIX + "$PBEWithHmacSHA384AndAES_128"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA512AndAES_128", PREFIX + "$PBEWithHmacSHA512AndAES_128"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA1AndAES_256", PREFIX + "$PBEWithHmacSHA1AndAES_256"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA224AndAES_256", PREFIX + "$PBEWithHmacSHA224AndAES_256"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA256AndAES_256", PREFIX + "$PBEWithHmacSHA256AndAES_256"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA384AndAES_256", PREFIX + "$PBEWithHmacSHA384AndAES_256"); + provider.addAlgorithm("SecretKeyFactory.PBEWithHmacSHA512AndAES_256", PREFIX + "$PBEWithHmacSHA512AndAES_256"); + provider.addAlgorithm("SecretKeyFactory.PBKDF2WithHmacSHA1And8BIT", PREFIX + "$PBKDF2WithHmacSHA18BIT"); + // END android-added + } + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java index 343fa0c7..7bc1e713 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java @@ -215,7 +215,7 @@ public final class RC2 // extends BaseAlgorithmParameterGenerator // { // RC2ParameterSpec spec = null; - // + // protected void engineInit( // AlgorithmParameterSpec genParamSpec, // SecureRandom random) @@ -226,25 +226,25 @@ public final class RC2 // spec = (RC2ParameterSpec)genParamSpec; // return; // } - // + // throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for RC2 parameter generation."); // } - // + // protected AlgorithmParameters engineGenerateParameters() // { // AlgorithmParameters params; - // + // if (spec == null) // { // byte[] iv = new byte[8]; - // + // if (random == null) // { // random = new SecureRandom(); // } - // + // random.nextBytes(iv); - // + // try // { // params = createParametersInstance("RC2"); @@ -267,11 +267,11 @@ public final class RC2 // throw new RuntimeException(e.getMessage()); // } // } - // + // return params; // } // } - // + // public static class KeyGenerator // extends BaseKeyGenerator // { @@ -280,7 +280,7 @@ public final class RC2 // super("RC2", 128, new CipherKeyGenerator()); // } // } - // + // public static class AlgParams // extends BaseAlgorithmParameters // { @@ -302,7 +302,7 @@ public final class RC2 // 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, // 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab // }; - // + // private static final short[] ekb = { // 0x5d, 0xbe, 0x9b, 0x8b, 0x11, 0x99, 0x6e, 0x4d, 0x59, 0xf3, 0x85, 0xa6, 0x3f, 0xb7, 0x83, 0xc5, // 0xe4, 0x73, 0x6b, 0x3a, 0x68, 0x5a, 0xc0, 0x47, 0xa0, 0x64, 0x34, 0x0c, 0xf1, 0xd0, 0x52, 0xa5, @@ -321,15 +321,15 @@ public final class RC2 // 0xbd, 0x22, 0xbf, 0x9f, 0x7e, 0xa9, 0x51, 0x4b, 0x4c, 0xfb, 0x02, 0xd3, 0x70, 0x86, 0x31, 0xe7, // 0x3b, 0x05, 0x03, 0x54, 0x60, 0x48, 0x65, 0x18, 0xd2, 0xcd, 0x5f, 0x32, 0x88, 0x0e, 0x35, 0xfd // }; - // + // private byte[] iv; // private int parameterVersion = 58; - // + // protected byte[] engineGetEncoded() // { // return Arrays.clone(iv); // } - // + // protected byte[] engineGetEncoded( // String format) // throws IOException @@ -345,20 +345,20 @@ public final class RC2 // return new RC2CBCParameter(parameterVersion, engineGetEncoded()).getEncoded(); // } // } - // + // if (format.equals("RAW")) // { // return engineGetEncoded(); // } - // + // return null; // } - // + // protected AlgorithmParameterSpec localEngineGetParameterSpec( // Class paramSpec) // throws InvalidParameterSpecException // { - // if (paramSpec == RC2ParameterSpec.class) + // if (paramSpec == RC2ParameterSpec.class || paramSpec == AlgorithmParameterSpec.class) // { // if (parameterVersion != -1) // { @@ -372,15 +372,15 @@ public final class RC2 // } // } // } - // - // if (paramSpec == IvParameterSpec.class) + + // if (paramSpec == IvParameterSpec.class || paramSpec == AlgorithmParameterSpec.class) // { // return new IvParameterSpec(iv); // } - // + // throw new InvalidParameterSpecException("unknown parameter spec passed to RC2 parameters object."); // } - // + // protected void engineInit( // AlgorithmParameterSpec paramSpec) // throws InvalidParameterSpecException @@ -403,7 +403,7 @@ public final class RC2 // parameterVersion = effKeyBits; // } // } - // + // this.iv = ((RC2ParameterSpec)paramSpec).getIV(); // } // else @@ -411,14 +411,14 @@ public final class RC2 // throw new InvalidParameterSpecException("IvParameterSpec or RC2ParameterSpec required to initialise a RC2 parameters algorithm parameters object"); // } // } - // + // protected void engineInit( // byte[] params) // throws IOException // { // this.iv = Arrays.clone(params); // } - // + // protected void engineInit( // byte[] params, // String format) @@ -427,26 +427,26 @@ public final class RC2 // if (this.isASN1FormatString(format)) // { // RC2CBCParameter p = RC2CBCParameter.getInstance(ASN1Primitive.fromByteArray(params)); - // + // if (p.getRC2ParameterVersion() != null) // { // parameterVersion = p.getRC2ParameterVersion().intValue(); // } - // + // iv = p.getIV(); - // + // return; // } - // + // if (format.equals("RAW")) // { // engineInit(params); // return; // } - // + // throw new IOException("Unknown parameters format in IV parameters object"); // } - // + // protected String engineToString() // { // return "RC2 Parameters"; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java index fd99c41e..59b715ad 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java @@ -78,6 +78,7 @@ import org.bouncycastle.crypto.params.RC2Parameters; // END android-removed import org.bouncycastle.jcajce.PKCS12Key; import org.bouncycastle.jcajce.PKCS12KeyWithParameters; +import org.bouncycastle.jcajce.spec.AEADParameterSpec; // BEGIN android-removed // import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec; // import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec; @@ -177,9 +178,9 @@ public class BaseBlockCipher protected BaseBlockCipher( AEADBlockCipher engine) { - baseEngine = engine.getUnderlyingCipher(); - ivLength = baseEngine.getBlockSize(); - cipher = new AEADGenericBlockCipher(engine); + this.baseEngine = engine.getUnderlyingCipher(); + this.ivLength = baseEngine.getBlockSize(); + this.cipher = new AEADGenericBlockCipher(engine); } protected BaseBlockCipher( @@ -256,6 +257,18 @@ public class BaseBlockCipher return null; } } + else if (aeadParams != null) + { + try + { + engineParams = createParametersInstance("GCM"); + engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize() / 8).getEncoded()); + } + catch (Exception e) + { + throw new RuntimeException(e.toString()); + } + } else if (ivParam != null) { String name = cipher.getUnderlyingCipher().getAlgorithmName(); @@ -275,18 +288,6 @@ public class BaseBlockCipher throw new RuntimeException(e.toString()); } } - else if (aeadParams != null) - { - try - { - engineParams = createParametersInstance("GCM"); - engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize() / 8).getEncoded()); - } - catch (Exception e) - { - throw new RuntimeException(e.toString()); - } - } } return engineParams; @@ -515,7 +516,7 @@ public class BaseBlockCipher // if (!(key instanceof SecretKey)) { - throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption."); + throw new InvalidKeyException("Key for algorithm " + ((key != null) ? key.getAlgorithm() : null) + " not suitable for symmetric enryption."); } // @@ -553,34 +554,29 @@ public class BaseBlockCipher if (k instanceof PBEKey && pbeSpec == null) { - // BEGIN android-added - if (((PBEKey)k).getSalt() == null) { - throw new InvalidAlgorithmParameterException("Parameters for the algorithm are null " - + "and the PBEKey has null salt"); + PBEKey pbeKey = (PBEKey)k; + if (pbeKey.getSalt() == null) + { + throw new InvalidAlgorithmParameterException("PBEKey requires parameters to specify salt"); } - // END android-added - pbeSpec = new PBEParameterSpec(((PBEKey)k).getSalt(), ((PBEKey)k).getIterationCount()); + pbeSpec = new PBEParameterSpec(pbeKey.getSalt(), pbeKey.getIterationCount()); } if (pbeSpec == null && !(k instanceof PBEKey)) { throw new InvalidKeyException("Algorithm requires a PBE key"); } + if (key instanceof BCPBEKey) { - // BEGIN android-changed - // Was: - // if (((BCPBEKey)key).getParam() != null) - // Change taken from: - // https://github.com/bcgit/bc-java/commit/fcba5c782188d772148ba168beae368d06646ee2 - // PKCS#12 sets an IV, if we get a key that doesn't have ParametersWithIV we need to forget about the fact - // it's a BCPBEKey - if (((BCPBEKey)key).getParam() != null && ((BCPBEKey)key).getParam() instanceof ParametersWithIV) - // END android-changed + // PKCS#12 sets an IV, if we get a key that doesn't have ParametersWithIV we need to reject it. If the + // key has no parameters it means it's an old-school JCE PBE Key - we use getEncoded() on it. + CipherParameters pbeKeyParam = ((BCPBEKey)key).getParam(); + if (pbeKeyParam instanceof ParametersWithIV) { - param = ((BCPBEKey)key).getParam(); + param = pbeKeyParam; } - else + else if (pbeKeyParam == null) { // BEGIN android-changed // Was: param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); @@ -590,6 +586,10 @@ public class BaseBlockCipher // END android-changed throw new IllegalStateException("Unreachable code"); } + else + { + throw new InvalidKeyException("Algorithm requires a PBE key suitable for PKCS12"); + } } else { @@ -696,7 +696,27 @@ public class BaseBlockCipher // } // END android-removed - if (params instanceof IvParameterSpec) + if (params instanceof AEADParameterSpec) + { + if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher)) + { + throw new InvalidAlgorithmParameterException("AEADParameterSpec can only be used with AEAD modes."); + } + + AEADParameterSpec aeadSpec = (AEADParameterSpec)params; + + KeyParameter keyParam; + if (param instanceof ParametersWithIV) + { + keyParam = (KeyParameter)((ParametersWithIV)param).getParameters(); + } + else + { + keyParam = (KeyParameter)param; + } + param = aeadParams = new AEADParameters(keyParam, aeadSpec.getMacSizeInBits(), aeadSpec.getNonce(), aeadSpec.getAssociatedData()); + } + else if (params instanceof IvParameterSpec) { if (ivLength != 0) { @@ -878,6 +898,8 @@ public class BaseBlockCipher } } + + if (random != null && padded) { param = new ParametersWithRandom(param, random); @@ -898,16 +920,17 @@ public class BaseBlockCipher default: throw new InvalidParameterException("unknown opmode " + opmode + " passed"); } + + if (cipher instanceof AEADGenericBlockCipher && aeadParams == null) + { + AEADBlockCipher aeadCipher = ((AEADGenericBlockCipher)cipher).cipher; + + aeadParams = new AEADParameters((KeyParameter)ivParam.getParameters(), aeadCipher.getMac().length * 8, ivParam.getIV()); + } } catch (final Exception e) { - throw new InvalidKeyException(e.getMessage()) - { - public Throwable getCause() - { - return e; - } - }; + throw new InvalidKeyOrParametersException(e.getMessage(), e); } } @@ -1393,4 +1416,21 @@ public class BaseBlockCipher } } } + + private static class InvalidKeyOrParametersException + extends InvalidKeyException + { + private final Throwable cause; + + InvalidKeyOrParametersException(String msg, Throwable cause) + { + super(msg); + this.cause = cause; + } + + public Throwable getCause() + { + return cause; + } + } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java index f6076170..51c29d96 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java @@ -1,5 +1,6 @@ package org.bouncycastle.jcajce.provider.symmetric.util; +import java.lang.reflect.Method; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; @@ -13,15 +14,19 @@ import javax.crypto.SecretKey; import javax.crypto.interfaces.PBEKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.RC2ParameterSpec; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Mac; +import org.bouncycastle.crypto.params.AEADParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; // BEGIN android-removed +// import org.bouncycastle.crypto.params.RC2Parameters; // import org.bouncycastle.crypto.params.SkeinParameters; // END android-removed import org.bouncycastle.jcajce.PKCS12Key; +import org.bouncycastle.jcajce.spec.AEADParameterSpec; // BEGIN android-removed // import org.bouncycastle.jcajce.spec.SkeinParameterSpec; // END android-removed @@ -29,6 +34,8 @@ import org.bouncycastle.jcajce.PKCS12Key; public class BaseMac extends MacSpi implements PBE { + private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec"); + private Mac macEngine; private int scheme = PKCS12; @@ -129,26 +136,77 @@ public class BaseMac throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set."); } } + else + { + if (params instanceof PBEParameterSpec) + { + throw new InvalidAlgorithmParameterException("inappropriate parameter type: " + params.getClass().getName()); + } + param = new KeyParameter(key.getEncoded()); + } + + KeyParameter keyParam; + if (param instanceof ParametersWithIV) + { + keyParam = (KeyParameter)((ParametersWithIV)param).getParameters(); + } + else + { + keyParam = (KeyParameter)param; + } + + if (params instanceof AEADParameterSpec) + { + AEADParameterSpec aeadSpec = (AEADParameterSpec)params; + + param = new AEADParameters(keyParam, aeadSpec.getMacSizeInBits(), aeadSpec.getNonce(), aeadSpec.getAssociatedData()); + } else if (params instanceof IvParameterSpec) { - param = new ParametersWithIV(new KeyParameter(key.getEncoded()), ((IvParameterSpec)params).getIV()); + param = new ParametersWithIV(keyParam, ((IvParameterSpec)params).getIV()); } // BEGIN android-removed + // else if (params instanceof RC2ParameterSpec) + // { + // param = new ParametersWithIV(new RC2Parameters(keyParam.getKey(), ((RC2ParameterSpec)params).getEffectiveKeyBits()), ((RC2ParameterSpec)params).getIV()); + // } + // else if (params instanceof SkeinParameterSpec) // { - // param = new SkeinParameters.Builder(copyMap(((SkeinParameterSpec)params).getParameters())).setKey(key.getEncoded()).build(); + // param = new SkeinParameters.Builder(copyMap(((SkeinParameterSpec)params).getParameters())).setKey(keyParam.getKey()).build(); // } // END android-removed else if (params == null) { param = new KeyParameter(key.getEncoded()); } - else + else if (gcmSpecClass != null && gcmSpecClass.isAssignableFrom(params.getClass())) { - throw new InvalidAlgorithmParameterException("unknown parameter type."); + try + { + Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]); + Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]); + + param = new AEADParameters(keyParam, ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0])); + } + catch (Exception e) + { + throw new InvalidAlgorithmParameterException("Cannot process GCMParameterSpec."); + } + } + else if (!(params instanceof PBEParameterSpec)) + { + throw new InvalidAlgorithmParameterException("unknown parameter type: " + params.getClass().getName()); } - macEngine.init(param); + try + { + macEngine.init(param); + } + catch (Exception e) + { + throw new InvalidAlgorithmParameterException("cannot initialize MAC: " + e.getMessage()); + } } protected int engineGetMacLength() @@ -197,4 +255,18 @@ public class BaseMac return newTable; } + + private static Class lookup(String className) + { + try + { + Class def = BaseBlockCipher.class.getClassLoader().loadClass(className); + + return def; + } + catch (Exception e) + { + return null; + } + } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseSecretKeyFactory.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseSecretKeyFactory.java index 31896cd2..9e798428 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseSecretKeyFactory.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseSecretKeyFactory.java @@ -32,7 +32,7 @@ public class BaseSecretKeyFactory { if (keySpec instanceof SecretKeySpec) { - return (SecretKey)keySpec; + return new SecretKeySpec(((SecretKeySpec)keySpec).getEncoded(), algName); } throw new InvalidKeySpecException("Invalid KeySpec"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java index ece0d146..e2c86766 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java @@ -102,7 +102,7 @@ public abstract class BaseWrapCipher protected int engineGetKeySize( Key key) { - return key.getEncoded().length; + return key.getEncoded().length * 8; } protected int engineGetOutputSize( diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/IvAlgorithmParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/IvAlgorithmParameters.java index b5a95526..84da1003 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/IvAlgorithmParameters.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/IvAlgorithmParameters.java @@ -43,7 +43,7 @@ public class IvAlgorithmParameters Class paramSpec) throws InvalidParameterSpecException { - if (paramSpec == IvParameterSpec.class) + if (paramSpec == IvParameterSpec.class || paramSpec == AlgorithmParameterSpec.class) { return new IvParameterSpec(iv); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java index be131f4e..2e4f96b5 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java @@ -13,18 +13,15 @@ import javax.crypto.spec.PBEParameterSpec; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.PBEParametersGenerator; +// BEGIN android-added +import org.bouncycastle.crypto.digests.AndroidDigestFactory; +// END android-added // BEGIN android-removed // import org.bouncycastle.crypto.digests.GOST3411Digest; // import org.bouncycastle.crypto.digests.MD2Digest; -// import org.bouncycastle.crypto.digests.MD5Digest; // import org.bouncycastle.crypto.digests.RIPEMD160Digest; -// import org.bouncycastle.crypto.digests.SHA1Digest; -// import org.bouncycastle.crypto.digests.SHA256Digest; // import org.bouncycastle.crypto.digests.TigerDigest; // END android-removed -// BEGIN android-added -import org.bouncycastle.crypto.digests.AndroidDigestFactory; -// END android-added import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator; import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator; @@ -32,6 +29,9 @@ import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; import org.bouncycastle.crypto.params.DESParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; +// BEGIN android-removed +// import org.bouncycastle.crypto.util.DigestFactory; +// END android-removed public interface PBE { @@ -49,6 +49,9 @@ public interface PBE // static final int MD2 = 5; // static final int GOST3411 = 6; // END android-removed + static final int SHA224 = 7; + static final int SHA384 = 8; + static final int SHA512 = 9; static final int PKCS5S1 = 0; static final int PKCS5S2 = 1; @@ -56,11 +59,6 @@ public interface PBE static final int OPENSSL = 3; static final int PKCS5S1_UTF8 = 4; static final int PKCS5S2_UTF8 = 5; - // BEGIN android-added - static final int SHA224 = 6; - static final int SHA384 = 7; - static final int SHA512 = 8; - // END android-added /** @@ -111,6 +109,7 @@ public interface PBE generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getMD5()); // END android-changed break; + case SHA1: // BEGIN android-changed generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA1()); @@ -142,11 +141,6 @@ public interface PBE generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA512()); break; // END android-added - // BEGIN android-removed - // case GOST3411: - // generator = new PKCS5S2ParametersGenerator(new GOST3411Digest()); - // break; - // END android-removed default: throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption."); } @@ -195,12 +189,6 @@ public interface PBE case SHA512: generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA512()); break; - // END android-added - // BEGIN android-removed - // case GOST3411: - // generator = new PKCS12ParametersGenerator(new GOST3411Digest()); - // break; - // END android-removed default: throw new IllegalStateException("unknown digest scheme for PBE encryption."); } @@ -284,11 +272,6 @@ public interface PBE } } - for (int i = 0; i != key.length; i++) - { - key[i] = 0; - } - return param; } @@ -358,11 +341,6 @@ public interface PBE } } - for (int i = 0; i != key.length; i++) - { - key[i] = 0; - } - return param; } @@ -388,11 +366,6 @@ public interface PBE generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount()); param = generator.generateDerivedMacParameters(pbeKey.getKeySize()); - - for (int i = 0; i != key.length; i++) - { - key[i] = 0; - } return param; } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/BadBlockException.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/BadBlockException.java new file mode 100644 index 00000000..e2a8d63d --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/BadBlockException.java @@ -0,0 +1,21 @@ +package org.bouncycastle.jcajce.provider.util; + +import javax.crypto.BadPaddingException; + +public class BadBlockException + extends BadPaddingException +{ + private final Throwable cause; + + public BadBlockException(String msg, Throwable cause) + { + super(msg); + + this.cause = cause; + } + + public Throwable getCause() + { + return cause; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/DigestFactory.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/DigestFactory.java index ce8bb363..9869b1c6 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/DigestFactory.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/DigestFactory.java @@ -10,15 +10,6 @@ import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.crypto.Digest; -// BEGIN android-removed -// import org.bouncycastle.crypto.digests.MD5Digest; -// import org.bouncycastle.crypto.digests.SHA1Digest; -// import org.bouncycastle.crypto.digests.SHA224Digest; -// import org.bouncycastle.crypto.digests.SHA256Digest; -// import org.bouncycastle.crypto.digests.SHA384Digest; -// import org.bouncycastle.crypto.digests.SHA512Digest; -// import org.bouncycastle.crypto.digests.SHA512tDigest; -// END android-removed // BEGIN android-added import org.bouncycastle.crypto.digests.AndroidDigestFactory; // END android-added @@ -35,6 +26,10 @@ public class DigestFactory // BEGIN android-removed // private static Set sha512_224 = new HashSet(); // private static Set sha512_256 = new HashSet(); + // private static Set sha3_224 = new HashSet(); + // private static Set sha3_256 = new HashSet(); + // private static Set sha3_384 = new HashSet(); + // private static Set sha3_512 = new HashSet(); // END android-removed private static Map oids = new HashMap(); @@ -72,8 +67,21 @@ public class DigestFactory // sha512_256.add("SHA512(256)"); // sha512_256.add("SHA-512(256)"); // sha512_256.add(NISTObjectIdentifiers.id_sha512_256.getId()); + + // sha3_224.add("SHA3-224"); + // sha3_224.add(NISTObjectIdentifiers.id_sha3_224.getId()); + + // sha3_256.add("SHA3-256"); + // sha3_256.add(NISTObjectIdentifiers.id_sha3_256.getId()); + + // sha3_384.add("SHA3-384"); + // sha3_384.add(NISTObjectIdentifiers.id_sha3_384.getId()); + + // sha3_512.add("SHA3-512"); + // sha3_512.add(NISTObjectIdentifiers.id_sha3_512.getId()); // END android-removed + oids.put("MD5", PKCSObjectIdentifiers.md5); oids.put(PKCSObjectIdentifiers.md5.getId(), PKCSObjectIdentifiers.md5); @@ -104,6 +112,18 @@ public class DigestFactory oids.put("SHA512(256)", NISTObjectIdentifiers.id_sha512_256); oids.put("SHA-512(256)", NISTObjectIdentifiers.id_sha512_256); oids.put(NISTObjectIdentifiers.id_sha512_256.getId(), NISTObjectIdentifiers.id_sha512_256); + + oids.put("SHA3-224", NISTObjectIdentifiers.id_sha3_224); + oids.put(NISTObjectIdentifiers.id_sha3_224.getId(), NISTObjectIdentifiers.id_sha3_224); + + oids.put("SHA3-256", NISTObjectIdentifiers.id_sha3_256); + oids.put(NISTObjectIdentifiers.id_sha3_256.getId(), NISTObjectIdentifiers.id_sha3_256); + + oids.put("SHA3-384", NISTObjectIdentifiers.id_sha3_384); + oids.put(NISTObjectIdentifiers.id_sha3_384.getId(), NISTObjectIdentifiers.id_sha3_384); + + oids.put("SHA3-512", NISTObjectIdentifiers.id_sha3_512); + oids.put(NISTObjectIdentifiers.id_sha3_512.getId(), NISTObjectIdentifiers.id_sha3_512); } public static Digest getDigest( @@ -141,8 +161,7 @@ public class DigestFactory return AndroidDigestFactory.getSHA384(); // END android-changed } - if (sha512.contains(digestName)) - { + if (sha512.contains(digestName)) { // BEGIN android-changed return AndroidDigestFactory.getSHA512(); // END android-changed @@ -150,13 +169,29 @@ public class DigestFactory // BEGIN android-removed // if (sha512_224.contains(digestName)) // { - // return new SHA512tDigest(224); + // return org.bouncycastle.crypto.util.DigestFactory.createSHA512_224(); // } // if (sha512_256.contains(digestName)) // { - // return new SHA512tDigest(256); + // return org.bouncycastle.crypto.util.DigestFactory.createSHA512_256(); + // } + // + // if (sha3_224.contains(digestName)) + // { + // return org.bouncycastle.crypto.util.DigestFactory.createSHA3_224(); + // } + // if (sha3_256.contains(digestName)) + // { + // return org.bouncycastle.crypto.util.DigestFactory.createSHA3_256(); + // } + // if (sha3_384.contains(digestName)) + // { + // return org.bouncycastle.crypto.util.DigestFactory.createSHA3_384(); + // } + // if (sha3_512.contains(digestName)) + // { + // return org.bouncycastle.crypto.util.DigestFactory.createSHA3_512(); // } - // END android-removed return null; } @@ -173,6 +208,10 @@ public class DigestFactory // BEGIN android-removed // || (sha512_224.contains(digest1) && sha512_224.contains(digest2)) // || (sha512_256.contains(digest1) && sha512_256.contains(digest2)) + // || (sha3_224.contains(digest1) && sha3_224.contains(digest2)) + // || (sha3_256.contains(digest1) && sha3_256.contains(digest2)) + // || (sha3_384.contains(digest1) && sha3_384.contains(digest2)) + // || (sha3_512.contains(digest1) && sha3_512.contains(digest2)) // END android-removed || (md5.contains(digest1) && md5.contains(digest2)); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/AEADParameterSpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/AEADParameterSpec.java new file mode 100644 index 00000000..b5d9657a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/AEADParameterSpec.java @@ -0,0 +1,73 @@ +package org.bouncycastle.jcajce.spec; + +import javax.crypto.spec.IvParameterSpec; + +import org.bouncycastle.util.Arrays; + +/** + * ParameterSpec for AEAD modes which allows associated data to be added via an algorithm parameter spec.In normal + * circumstances you would only want to use this if you had to work with the pre-JDK1.7 Cipher class as associated + * data is ignored for the purposes of returning a Cipher's parameters. + */ +public class AEADParameterSpec + extends IvParameterSpec +{ + private final byte[] associatedData; + private final int macSizeInBits; + + /** + * Base constructor. + * + * @param nonce nonce/iv to be used + * @param macSizeInBits macSize in bits + */ + public AEADParameterSpec(byte[] nonce, int macSizeInBits) + { + this(nonce, macSizeInBits, null); + } + + /** + * Base constructor with prepended associated data. + * + * @param nonce nonce/iv to be used + * @param macSizeInBits macSize in bits + * @param associatedData associated data to be prepended to the cipher stream. + */ + public AEADParameterSpec(byte[] nonce, int macSizeInBits, byte[] associatedData) + { + super(nonce); + + this.macSizeInBits = macSizeInBits; + this.associatedData = Arrays.clone(associatedData); + } + + /** + * Return the size of the MAC associated with this parameter spec. + * + * @return the MAC size in bits. + */ + public int getMacSizeInBits() + { + return macSizeInBits; + } + + /** + * Return the associated data associated with this parameter spec. + * + * @return the associated data, null if there isn't any. + */ + public byte[] getAssociatedData() + { + return Arrays.clone(associatedData); + } + + /** + * Return the nonce (same as IV) associated with this parameter spec. + * + * @return the nonce/IV. + */ + public byte[] getNonce() + { + return getIV(); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java index df0c1454..e053fb93 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/spec/PBKDF2KeySpec.java @@ -2,6 +2,8 @@ package org.bouncycastle.jcajce.spec; import javax.crypto.spec.PBEKeySpec; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; /** @@ -10,6 +12,8 @@ import org.bouncycastle.asn1.x509.AlgorithmIdentifier; public class PBKDF2KeySpec extends PBEKeySpec { + private static final AlgorithmIdentifier defaultPRF = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA1, DERNull.INSTANCE); + private AlgorithmIdentifier prf; /** @@ -28,6 +32,21 @@ public class PBKDF2KeySpec this.prf = prf; } + /** + * Return true if this spec is for the default PRF (HmacSHA1), false otherwise. + * + * @return true if this spec uses the default PRF, false otherwise. + */ + public boolean isDefaultPrf() + { + return defaultPRF.equals(prf); + } + + /** + * Return an AlgorithmIdentifier representing the PRF. + * + * @return the PRF's AlgorithmIdentifier. + */ public AlgorithmIdentifier getPrf() { return prf; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java index 4a1a92a5..025327f6 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/AlgorithmParametersUtils.java @@ -1,6 +1,3 @@ -/***************************************************************/ -/****** DO NOT EDIT THIS CLASS bc-java SOURCE FILE ******/ -/***************************************************************/ package org.bouncycastle.jcajce.util; import java.io.IOException; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java index 40087612..25897cf5 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java @@ -11,15 +11,23 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; public class BCJcaJceHelper extends ProviderJcaJceHelper { + private static volatile Provider bcProvider; + private static Provider getBouncyCastleProvider() { if (Security.getProvider("BC") != null) { return Security.getProvider("BC"); } + else if (bcProvider != null) + { + return bcProvider; + } else { - return new BouncyCastleProvider(); + bcProvider = new BouncyCastleProvider(); + + return bcProvider; } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java index 27ca55ae..426efc09 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java @@ -6,6 +6,7 @@ import java.security.KeyFactory; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.security.Signature; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -96,4 +97,10 @@ public class DefaultJcaJceHelper { return CertificateFactory.getInstance(algorithm); } + + public SecureRandom createSecureRandom(String algorithm) + throws NoSuchAlgorithmException + { + return SecureRandom.getInstance(algorithm); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java index 7a78193e..aa151cce 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java @@ -7,6 +7,7 @@ import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.SecureRandom; import java.security.Signature; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -59,4 +60,7 @@ public interface JcaJceHelper CertificateFactory createCertificateFactory(String algorithm) throws NoSuchProviderException, CertificateException; + + SecureRandom createSecureRandom(String algorithm) + throws NoSuchAlgorithmException, NoSuchProviderException; } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java index 80ce603f..1125a4ba 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/MessageDigestUtils.java @@ -41,6 +41,10 @@ public class MessageDigestUtils // digestOidMap.put(CryptoProObjectIdentifiers.gostR3411, "GOST3411"); // digestOidMap.put(GNUObjectIdentifiers.Tiger_192, "Tiger"); // digestOidMap.put(ISOIECObjectIdentifiers.whirlpool, "Whirlpool"); + // digestOidMap.put(NISTObjectIdentifiers.id_sha3_224, "SHA3-224"); + // digestOidMap.put(NISTObjectIdentifiers.id_sha3_256, "SHA3-256"); + // digestOidMap.put(NISTObjectIdentifiers.id_sha3_384, "SHA3-384"); + // digestOidMap.put(NISTObjectIdentifiers.id_sha3_512, "SHA3-512"); // END android-removed } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java index 280539d5..bc5da9a9 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java @@ -7,6 +7,7 @@ import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.SecureRandom; import java.security.Signature; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -103,4 +104,10 @@ public class NamedJcaJceHelper { return CertificateFactory.getInstance(algorithm, providerName); } + + public SecureRandom createSecureRandom(String algorithm) + throws NoSuchAlgorithmException, NoSuchProviderException + { + return SecureRandom.getInstance(algorithm, providerName); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java index fb4b9a73..f07b0a85 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java @@ -7,6 +7,7 @@ import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Provider; +import java.security.SecureRandom; import java.security.Signature; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -103,4 +104,10 @@ public class ProviderJcaJceHelper { return CertificateFactory.getInstance(algorithm, provider); } + + public SecureRandom createSecureRandom(String algorithm) + throws NoSuchAlgorithmException + { + return SecureRandom.getInstance(algorithm, provider); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java index e5463aa0..6a7c9e62 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java @@ -44,7 +44,7 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; public final class BouncyCastleProvider extends Provider implements ConfigurableProvider { - private static String info = "BouncyCastle Security Provider v1.54"; + private static String info = "BouncyCastle Security Provider v1.56"; public static final String PROVIDER_NAME = "BC"; @@ -60,14 +60,14 @@ public final class BouncyCastleProvider extends Provider private static final String[] SYMMETRIC_GENERIC = { // BEGIN android-changed - // Was: "PBEPBKDF2", "PBEPKCS12" + // Was: "PBEPBKDF2", "TLSKDF" "PBEPBKDF2", "PBEPKCS12", "PBES2AlgorithmParameters" }; private static final String[] SYMMETRIC_MACS = { // BEGIN android-removed - // "SipHash" + // "SipHash", "Poly1305" // END android-removed }; @@ -132,9 +132,19 @@ public final class BouncyCastleProvider extends Provider private static final String KEYSTORE_PACKAGE = "org.bouncycastle.jcajce.provider.keystore."; private static final String[] KEYSTORES = { - "BC", "PKCS12" + "BC", "BCFKS", "PKCS12" }; + // BEGIN android-removed + // /* + // * Configurable secure random + // */ + // private static final String SECURE_RANDOM_PACKAGE = "org.bouncycastle.jcajce.provider.drbg."; + // private static final String[] SECURE_RANDOMS = + // { + // "DRBG" + // }; + /** * Construct a new provider. This should only be required when * using runtime registration of the provider using the @@ -142,7 +152,7 @@ public final class BouncyCastleProvider extends Provider */ public BouncyCastleProvider() { - super(PROVIDER_NAME, 1.54, info); + super(PROVIDER_NAME, 1.56, info); AccessController.doPrivileged(new PrivilegedAction() { @@ -171,6 +181,8 @@ public final class BouncyCastleProvider extends Provider loadAlgorithms(KEYSTORE_PACKAGE, KEYSTORES); // BEGIN android-removed + // loadAlgorithms(SECURE_RANDOM_PACKAGE, SECURE_RANDOMS); + // // // // // X509Store // // @@ -287,13 +299,24 @@ public final class BouncyCastleProvider extends Provider public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter) { - keyInfoConverters.put(oid, keyInfoConverter); + synchronized (keyInfoConverters) + { + keyInfoConverters.put(oid, keyInfoConverter); + } + } + + private static AsymmetricKeyInfoConverter getAsymmetricKeyInfoConverter(ASN1ObjectIdentifier algorithm) + { + synchronized (keyInfoConverters) + { + return (AsymmetricKeyInfoConverter)keyInfoConverters.get(algorithm); + } } public static PublicKey getPublicKey(SubjectPublicKeyInfo publicKeyInfo) throws IOException { - AsymmetricKeyInfoConverter converter = (AsymmetricKeyInfoConverter)keyInfoConverters.get(publicKeyInfo.getAlgorithm().getAlgorithm()); + AsymmetricKeyInfoConverter converter = getAsymmetricKeyInfoConverter(publicKeyInfo.getAlgorithm().getAlgorithm()); if (converter == null) { @@ -306,7 +329,7 @@ public final class BouncyCastleProvider extends Provider public static PrivateKey getPrivateKey(PrivateKeyInfo privateKeyInfo) throws IOException { - AsymmetricKeyInfoConverter converter = (AsymmetricKeyInfoConverter)keyInfoConverters.get(privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm()); + AsymmetricKeyInfoConverter converter = getAsymmetricKeyInfoConverter(privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm()); if (converter == null) { diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java index cda05e83..f89b9fd7 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProviderConfiguration.java @@ -1,6 +1,11 @@ package org.bouncycastle.jce.provider; import java.security.Permission; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import javax.crypto.spec.DHParameterSpec; @@ -21,12 +26,18 @@ class BouncyCastleProviderConfiguration BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.THREAD_LOCAL_DH_DEFAULT_PARAMS); private static Permission BC_DH_PERMISSION = new ProviderConfigurationPermission( BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.DH_DEFAULT_PARAMS); + private static Permission BC_EC_CURVE_PERMISSION = new ProviderConfigurationPermission( + BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.ACCEPTABLE_EC_CURVES); + private static Permission BC_ADDITIONAL_EC_CURVE_PERMISSION = new ProviderConfigurationPermission( + BouncyCastleProvider.PROVIDER_NAME, ConfigurableProvider.ADDITIONAL_EC_PARAMETERS); private ThreadLocal ecThreadSpec = new ThreadLocal(); private ThreadLocal dhThreadSpec = new ThreadLocal(); private volatile ECParameterSpec ecImplicitCaParams; private volatile Object dhDefaultParams; + private volatile Set acceptableNamedCurves = new HashSet(); + private volatile Map additionalECParameters = new HashMap(); void setParameter(String parameterName, Object parameter) { @@ -118,6 +129,24 @@ class BouncyCastleProviderConfiguration throw new IllegalArgumentException("not a valid DHParameterSpec or DHParameterSpec[]"); } } + else if (parameterName.equals(ConfigurableProvider.ACCEPTABLE_EC_CURVES)) + { + if (securityManager != null) + { + securityManager.checkPermission(BC_EC_CURVE_PERMISSION); + } + + this.acceptableNamedCurves = (Set)parameter; + } + else if (parameterName.equals(ConfigurableProvider.ADDITIONAL_EC_PARAMETERS)) + { + if (securityManager != null) + { + securityManager.checkPermission(BC_ADDITIONAL_EC_CURVE_PERMISSION); + } + + this.additionalECParameters = (Map)parameter; + } } public ECParameterSpec getEcImplicitlyCa() @@ -164,4 +193,14 @@ class BouncyCastleProviderConfiguration return null; } + + public Set getAcceptableNamedCurves() + { + return Collections.unmodifiableSet(acceptableNamedCurves); + } + + public Map getAdditionalECParameters() + { + return Collections.unmodifiableMap(additionalECParameters); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java index b6885ace..b8308207 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java @@ -53,6 +53,7 @@ import org.bouncycastle.util.encoders.Hex; * CRL Number * Delta CRL Indicator (critical) * Issuing Distribution Point (critical) + * @deprecated Do not use this class directly - either use org.bouncycastle.cert (bcpkix) or CertificateFactory. */ public class X509CRLObject extends X509CRL diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CertificateObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CertificateObject.java index 09703f4c..4a0166b2 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CertificateObject.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CertificateObject.java @@ -69,6 +69,9 @@ import org.bouncycastle.util.Integers; import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; +/** + * @deprecated Do not use this class directly - either use org.bouncycastle.cert (bcpkix) or CertificateFactory. + */ public class X509CertificateObject extends X509Certificate implements PKCS12BagAttributeCarrier diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java index 339689ea..301b5aee 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java @@ -440,7 +440,7 @@ public abstract class WNafUtil * 1) additions do not use the curve's A, B coefficients. * 2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ... */ - if (ECAlgorithms.isFpCurve(c) && c.getFieldSize() >= 64) + if (!twiceP.isInfinity() && ECAlgorithms.isFpCurve(c) && c.getFieldSize() >= 64) { switch (c.getCoordinateSystem()) { diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java index 5a066d81..1e04f4b9 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP256R1Field.java @@ -112,9 +112,10 @@ public class SecP256R1Field long t4 = xx12 + xx13; long t5 = xx13 + xx14; long t6 = xx14 + xx15; + long t7 = t5 - t0; long cc = 0; - cc += (xx[0] & M) + t0 - t3 - t5; + cc += (xx[0] & M) - t3 - t7; z[0] = (int)cc; cc >>= 32; cc += (xx[1] & M) + t1 - t4 - t6; @@ -123,7 +124,7 @@ public class SecP256R1Field cc += (xx[2] & M) + t2 - t5; z[2] = (int)cc; cc >>= 32; - cc += (xx[3] & M) + (t3 << 1) + xx13 - xx15 - t0; + cc += (xx[3] & M) + (t3 << 1) + t7 - t6; z[3] = (int)cc; cc >>= 32; cc += (xx[4] & M) + (t4 << 1) + xx14 - t1; @@ -132,7 +133,7 @@ public class SecP256R1Field cc += (xx[5] & M) + (t5 << 1) - t2; z[5] = (int)cc; cc >>= 32; - cc += (xx[6] & M) + (t6 << 1) + t5 - t0; + cc += (xx[6] & M) + (t6 << 1) + t7; z[6] = (int)cc; cc >>= 32; cc += (xx[7] & M) + (xx15 << 1) + xx08 - t2 - t4; diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java index fcbb8727..164a7957 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/custom/sec/SecP384R1Field.java @@ -107,9 +107,10 @@ public class SecP384R1Field long t4 = xx17 + xx21; long t5 = xx21 - xx23; long t6 = xx22 - xx23; + long t7 = t0 + t5; long cc = 0; - cc += (xx[0] & M) + t0 + t5; + cc += (xx[0] & M) + t7; z[0] = (int)cc; cc >>= 32; cc += (xx[1] & M) + xx23 - t0 + t1; @@ -118,10 +119,10 @@ public class SecP384R1Field cc += (xx[2] & M) - xx21 - t1 + t2; z[2] = (int)cc; cc >>= 32; - cc += (xx[3] & M) + t0 - t2 + t3 + t5; + cc += (xx[3] & M) - t2 + t3 + t7; z[3] = (int)cc; cc >>= 32; - cc += (xx[4] & M) + xx16 + xx21 + t0 + t1 - t3 + t5; + cc += (xx[4] & M) + xx16 + xx21 + t1 - t3 + t7; z[4] = (int)cc; cc >>= 32; cc += (xx[5] & M) - xx16 + t1 + t2 + t4; diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java index 421883e0..12db01bc 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java +++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat192.java @@ -715,8 +715,8 @@ public abstract class Nat192 } long x_3 = x[3] & M; - long zz_5 = zz[5] & M; - long zz_6 = zz[6] & M; + long zz_5 = (zz[5] & M) + (zz_4 >>> 32); zz_4 &= M; + long zz_6 = (zz[6] & M) + (zz_5 >>> 32); zz_5 &= M; { zz_3 += x_3 * x_0; w = (int)zz_3; @@ -730,8 +730,8 @@ public abstract class Nat192 } long x_4 = x[4] & M; - long zz_7 = zz[7] & M; - long zz_8 = zz[8] & M; + long zz_7 = (zz[7] & M) + (zz_6 >>> 32); zz_6 &= M; + long zz_8 = (zz[8] & M) + (zz_7 >>> 32); zz_7 &= M; { zz_4 += x_4 * x_0; w = (int)zz_4; @@ -747,8 +747,8 @@ public abstract class Nat192 } long x_5 = x[5] & M; - long zz_9 = zz[9] & M; - long zz_10 = zz[10] & M; + long zz_9 = (zz[9] & M) + (zz_8 >>> 32); zz_8 &= M; + long zz_10 = (zz[10] & M) + (zz_9 >>> 32); zz_9 &= M; { zz_5 += x_5 * x_0; w = (int)zz_5; @@ -776,7 +776,7 @@ public abstract class Nat192 w = (int)zz_10; zz[10] = (w << 1) | c; c = w >>> 31; - w = zz[11] + (int)(zz_10 >> 32); + w = zz[11] + (int)(zz_10 >>> 32); zz[11] = (w << 1) | c; } @@ -831,8 +831,8 @@ public abstract class Nat192 } long x_3 = x[xOff + 3] & M; - long zz_5 = zz[zzOff + 5] & M; - long zz_6 = zz[zzOff + 6] & M; + long zz_5 = (zz[zzOff + 5] & M) + (zz_4 >>> 32); zz_4 &= M; + long zz_6 = (zz[zzOff + 6] & M) + (zz_5 >>> 32); zz_5 &= M; { zz_3 += x_3 * x_0; w = (int)zz_3; @@ -846,8 +846,8 @@ public abstract class Nat192 } long x_4 = x[xOff + 4] & M; - long zz_7 = zz[zzOff + 7] & M; - long zz_8 = zz[zzOff + 8] & M; + long zz_7 = (zz[zzOff + 7] & M) + (zz_6 >>> 32); zz_6 &= M; + long zz_8 = (zz[zzOff + 8] & M) + (zz_7 >>> 32); zz_7 &= M; { zz_4 += x_4 * x_0; w = (int)zz_4; @@ -863,8 +863,8 @@ public abstract class Nat192 } long x_5 = x[xOff + 5] & M; - long zz_9 = zz[zzOff + 9] & M; - long zz_10 = zz[zzOff + 10] & M; + long zz_9 = (zz[zzOff + 9] & M) + (zz_8 >>> 32); zz_8 &= M; + long zz_10 = (zz[zzOff + 10] & M) + (zz_9 >>> 32); zz_9 &= M; { zz_5 += x_5 * x_0; w = (int)zz_5; @@ -892,7 +892,7 @@ public abstract class Nat192 w = (int)zz_10; zz[zzOff + 10] = (w << 1) | c; c = w >>> 31; - w = zz[zzOff + 11] + (int)(zz_10 >> 32); + w = zz[zzOff + 11] + (int)(zz_10 >>> 32); zz[zzOff + 11] = (w << 1) | c; } diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java index bbe81caa..9ff107c1 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java +++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat224.java @@ -793,8 +793,8 @@ public abstract class Nat224 } long x_3 = x[3] & M; - long zz_5 = zz[5] & M; - long zz_6 = zz[6] & M; + long zz_5 = (zz[5] & M) + (zz_4 >>> 32); zz_4 &= M; + long zz_6 = (zz[6] & M) + (zz_5 >>> 32); zz_5 &= M; { zz_3 += x_3 * x_0; w = (int)zz_3; @@ -808,8 +808,8 @@ public abstract class Nat224 } long x_4 = x[4] & M; - long zz_7 = zz[7] & M; - long zz_8 = zz[8] & M; + long zz_7 = (zz[7] & M) + (zz_6 >>> 32); zz_6 &= M; + long zz_8 = (zz[8] & M) + (zz_7 >>> 32); zz_7 &= M; { zz_4 += x_4 * x_0; w = (int)zz_4; @@ -825,8 +825,8 @@ public abstract class Nat224 } long x_5 = x[5] & M; - long zz_9 = zz[9] & M; - long zz_10 = zz[10] & M; + long zz_9 = (zz[9] & M) + (zz_8 >>> 32); zz_8 &= M; + long zz_10 = (zz[10] & M) + (zz_9 >>> 32); zz_9 &= M; { zz_5 += x_5 * x_0; w = (int)zz_5; @@ -844,8 +844,8 @@ public abstract class Nat224 } long x_6 = x[6] & M; - long zz_11 = zz[11] & M; - long zz_12 = zz[12] & M; + long zz_11 = (zz[11] & M) + (zz_10 >>> 32); zz_10 &= M; + long zz_12 = (zz[12] & M) + (zz_11 >>> 32); zz_11 &= M; { zz_6 += x_6 * x_0; w = (int)zz_6; @@ -877,7 +877,7 @@ public abstract class Nat224 w = (int)zz_12; zz[12] = (w << 1) | c; c = w >>> 31; - w = zz[13] + (int)(zz_12 >> 32); + w = zz[13] + (int)(zz_12 >>> 32); zz[13] = (w << 1) | c; } @@ -932,8 +932,8 @@ public abstract class Nat224 } long x_3 = x[xOff + 3] & M; - long zz_5 = zz[zzOff + 5] & M; - long zz_6 = zz[zzOff + 6] & M; + long zz_5 = (zz[zzOff + 5] & M) + (zz_4 >>> 32); zz_4 &= M; + long zz_6 = (zz[zzOff + 6] & M) + (zz_5 >>> 32); zz_5 &= M; { zz_3 += x_3 * x_0; w = (int)zz_3; @@ -947,8 +947,8 @@ public abstract class Nat224 } long x_4 = x[xOff + 4] & M; - long zz_7 = zz[zzOff + 7] & M; - long zz_8 = zz[zzOff + 8] & M; + long zz_7 = (zz[zzOff + 7] & M) + (zz_6 >>> 32); zz_6 &= M; + long zz_8 = (zz[zzOff + 8] & M) + (zz_7 >>> 32); zz_7 &= M; { zz_4 += x_4 * x_0; w = (int)zz_4; @@ -964,8 +964,8 @@ public abstract class Nat224 } long x_5 = x[xOff + 5] & M; - long zz_9 = zz[zzOff + 9] & M; - long zz_10 = zz[zzOff + 10] & M; + long zz_9 = (zz[zzOff + 9] & M) + (zz_8 >>> 32); zz_8 &= M; + long zz_10 = (zz[zzOff + 10] & M) + (zz_9 >>> 32); zz_9 &= M; { zz_5 += x_5 * x_0; w = (int)zz_5; @@ -983,8 +983,8 @@ public abstract class Nat224 } long x_6 = x[xOff + 6] & M; - long zz_11 = zz[zzOff + 11] & M; - long zz_12 = zz[zzOff + 12] & M; + long zz_11 = (zz[zzOff + 11] & M) + (zz_10 >>> 32); zz_10 &= M; + long zz_12 = (zz[zzOff + 12] & M) + (zz_11 >>> 32); zz_11 &= M; { zz_6 += x_6 * x_0; w = (int)zz_6; @@ -1016,7 +1016,7 @@ public abstract class Nat224 w = (int)zz_12; zz[zzOff + 12] = (w << 1) | c; c = w >>> 31; - w = zz[zzOff + 13] + (int)(zz_12 >> 32); + w = zz[zzOff + 13] + (int)(zz_12 >>> 32); zz[zzOff + 13] = (w << 1) | c; } diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java index db1daac0..726bae35 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java +++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat256.java @@ -926,8 +926,8 @@ public abstract class Nat256 } long x_3 = x[3] & M; - long zz_5 = zz[5] & M; - long zz_6 = zz[6] & M; + long zz_5 = (zz[5] & M) + (zz_4 >>> 32); zz_4 &= M; + long zz_6 = (zz[6] & M) + (zz_5 >>> 32); zz_5 &= M; { zz_3 += x_3 * x_0; w = (int)zz_3; @@ -941,8 +941,8 @@ public abstract class Nat256 } long x_4 = x[4] & M; - long zz_7 = zz[7] & M; - long zz_8 = zz[8] & M; + long zz_7 = (zz[7] & M) + (zz_6 >>> 32); zz_6 &= M; + long zz_8 = (zz[8] & M) + (zz_7 >>> 32); zz_7 &= M; { zz_4 += x_4 * x_0; w = (int)zz_4; @@ -958,8 +958,8 @@ public abstract class Nat256 } long x_5 = x[5] & M; - long zz_9 = zz[9] & M; - long zz_10 = zz[10] & M; + long zz_9 = (zz[9] & M) + (zz_8 >>> 32); zz_8 &= M; + long zz_10 = (zz[10] & M) + (zz_9 >>> 32); zz_9 &= M; { zz_5 += x_5 * x_0; w = (int)zz_5; @@ -977,8 +977,8 @@ public abstract class Nat256 } long x_6 = x[6] & M; - long zz_11 = zz[11] & M; - long zz_12 = zz[12] & M; + long zz_11 = (zz[11] & M) + (zz_10 >>> 32); zz_10 &= M; + long zz_12 = (zz[12] & M) + (zz_11 >>> 32); zz_11 &= M; { zz_6 += x_6 * x_0; w = (int)zz_6; @@ -998,8 +998,8 @@ public abstract class Nat256 } long x_7 = x[7] & M; - long zz_13 = zz[13] & M; - long zz_14 = zz[14] & M; + long zz_13 = (zz[13] & M) + (zz_12 >>> 32); zz_12 &= M; + long zz_14 = (zz[14] & M) + (zz_13 >>> 32); zz_13 &= M; { zz_7 += x_7 * x_0; w = (int)zz_7; @@ -1035,7 +1035,7 @@ public abstract class Nat256 w = (int)zz_14; zz[14] = (w << 1) | c; c = w >>> 31; - w = zz[15] + (int)(zz_14 >> 32); + w = zz[15] + (int)(zz_14 >>> 32); zz[15] = (w << 1) | c; } @@ -1090,8 +1090,8 @@ public abstract class Nat256 } long x_3 = x[xOff + 3] & M; - long zz_5 = zz[zzOff + 5] & M; - long zz_6 = zz[zzOff + 6] & M; + long zz_5 = (zz[zzOff + 5] & M) + (zz_4 >>> 32); zz_4 &= M; + long zz_6 = (zz[zzOff + 6] & M) + (zz_5 >>> 32); zz_5 &= M; { zz_3 += x_3 * x_0; w = (int)zz_3; @@ -1105,8 +1105,8 @@ public abstract class Nat256 } long x_4 = x[xOff + 4] & M; - long zz_7 = zz[zzOff + 7] & M; - long zz_8 = zz[zzOff + 8] & M; + long zz_7 = (zz[zzOff + 7] & M) + (zz_6 >>> 32); zz_6 &= M; + long zz_8 = (zz[zzOff + 8] & M) + (zz_7 >>> 32); zz_7 &= M; { zz_4 += x_4 * x_0; w = (int)zz_4; @@ -1122,8 +1122,8 @@ public abstract class Nat256 } long x_5 = x[xOff + 5] & M; - long zz_9 = zz[zzOff + 9] & M; - long zz_10 = zz[zzOff + 10] & M; + long zz_9 = (zz[zzOff + 9] & M) + (zz_8 >>> 32); zz_8 &= M; + long zz_10 = (zz[zzOff + 10] & M) + (zz_9 >>> 32); zz_9 &= M; { zz_5 += x_5 * x_0; w = (int)zz_5; @@ -1141,8 +1141,8 @@ public abstract class Nat256 } long x_6 = x[xOff + 6] & M; - long zz_11 = zz[zzOff + 11] & M; - long zz_12 = zz[zzOff + 12] & M; + long zz_11 = (zz[zzOff + 11] & M) + (zz_10 >>> 32); zz_10 &= M; + long zz_12 = (zz[zzOff + 12] & M) + (zz_11 >>> 32); zz_11 &= M; { zz_6 += x_6 * x_0; w = (int)zz_6; @@ -1162,8 +1162,8 @@ public abstract class Nat256 } long x_7 = x[xOff + 7] & M; - long zz_13 = zz[zzOff + 13] & M; - long zz_14 = zz[zzOff + 14] & M; + long zz_13 = (zz[zzOff + 13] & M) + (zz_12 >>> 32); zz_12 &= M; + long zz_14 = (zz[zzOff + 14] & M) + (zz_13 >>> 32); zz_13 &= M; { zz_7 += x_7 * x_0; w = (int)zz_7; @@ -1199,7 +1199,7 @@ public abstract class Nat256 w = (int)zz_14; zz[zzOff + 14] = (w << 1) | c; c = w >>> 31; - w = zz[zzOff + 15] + (int)(zz_14 >> 32); + w = zz[zzOff + 15] + (int)(zz_14 >>> 32); zz[zzOff + 15] = (w << 1) | c; } diff --git a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java index 99325a9f..ae609280 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java @@ -103,6 +103,36 @@ public final class Arrays return true; } + public static boolean areEqual( + short[] a, + short[] b) + { + if (a == b) + { + return true; + } + + if (a == null || b == null) + { + return false; + } + + if (a.length != b.length) + { + return false; + } + + for (int i = 0; i != a.length; i++) + { + if (a[i] != b[i]) + { + return false; + } + } + + return true; + } + /** * A constant time equals comparison - does not terminate early if * test will fail. @@ -232,6 +262,44 @@ public final class Arrays return true; } + public static int compareUnsigned(byte[] a, byte[] b) + { + if (a == b) + { + return 0; + } + if (a == null) + { + return -1; + } + if (b == null) + { + return 1; + } + int minLen = Math.min(a.length, b.length); + for (int i = 0; i < minLen; ++i) + { + int aVal = a[i] & 0xFF, bVal = b[i] & 0xFF; + if (aVal < bVal) + { + return -1; + } + if (aVal > bVal) + { + return 1; + } + } + if (a.length < b.length) + { + return -1; + } + if (a.length > b.length) + { + return 1; + } + return 0; + } + public static boolean contains(short[] a, short n) { for (int i = 0; i < a.length; ++i) @@ -954,6 +1022,26 @@ public final class Arrays } } + public static byte[] concatenate(byte[][] arrays) + { + int size = 0; + for (int i = 0; i != arrays.length; i++) + { + size += arrays[i].length; + } + + byte[] rv = new byte[size]; + + int offSet = 0; + for (int i = 0; i != arrays.length; i++) + { + System.arraycopy(arrays[i], 0, rv, offSet, arrays[i].length); + offSet += arrays[i].length; + } + + return rv; + } + public static int[] concatenate(int[] a, int[] b) { if (a == null) diff --git a/bcprov/src/main/java/org/bouncycastle/util/Pack.java b/bcprov/src/main/java/org/bouncycastle/util/Pack.java index 94ba17b1..82b02ea5 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Pack.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Pack.java @@ -5,6 +5,13 @@ package org.bouncycastle.util; */ public abstract class Pack { + public static short bigEndianToShort(byte[] bs, int off) + { + int n = (bs[ off] & 0xff) << 8; + n |= (bs[++off] & 0xff); + return (short)n; + } + public static int bigEndianToInt(byte[] bs, int off) { int n = bs[ off] << 24; @@ -99,6 +106,13 @@ public abstract class Pack } } + public static short littleEndianToShort(byte[] bs, int off) + { + int n = bs[ off] & 0xff; + n |= (bs[++off] & 0xff) << 8; + return (short)n; + } + public static int littleEndianToInt(byte[] bs, int off) { int n = bs[ off] & 0xff; @@ -126,6 +140,30 @@ public abstract class Pack } } + public static int[] littleEndianToInt(byte[] bs, int off, int count) + { + int[] ns = new int[count]; + for (int i = 0; i < ns.length; ++i) + { + ns[i] = littleEndianToInt(bs, off); + off += 4; + } + return ns; + } + + public static byte[] shortToLittleEndian(short n) + { + byte[] bs = new byte[2]; + shortToLittleEndian(n, bs, 0); + return bs; + } + + public static void shortToLittleEndian(short n, byte[] bs, int off) + { + bs[ off] = (byte)(n ); + bs[++off] = (byte)(n >>> 8); + } + public static byte[] intToLittleEndian(int n) { byte[] bs = new byte[4]; diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java b/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java index f39e026e..adb158f9 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java +++ b/bcprov/src/main/java/org/bouncycastle/util/io/Streams.java @@ -142,4 +142,10 @@ public final class Streams } return total; } + + public static void writeBufTo(ByteArrayOutputStream buf, OutputStream output) + throws IOException + { + buf.writeTo(output); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java b/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java index 01f4469f..5833d17e 100644 --- a/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/x509/X509V1CertificateGenerator.java @@ -1,5 +1,6 @@ package org.bouncycastle.x509; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.GeneralSecurityException; @@ -11,7 +12,6 @@ import java.security.PublicKey; import java.security.SecureRandom; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Iterator; @@ -19,19 +19,21 @@ import java.util.Iterator; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.TBSCertificate; import org.bouncycastle.asn1.x509.Time; import org.bouncycastle.asn1.x509.V1TBSCertificateGenerator; import org.bouncycastle.asn1.x509.X509Name; +import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory; +import org.bouncycastle.jcajce.util.BCJcaJceHelper; +import org.bouncycastle.jcajce.util.JcaJceHelper; import org.bouncycastle.jce.X509Principal; -import org.bouncycastle.jce.provider.X509CertificateObject; /** * class to produce an X.509 Version 1 certificate. @@ -39,6 +41,9 @@ import org.bouncycastle.jce.provider.X509CertificateObject; */ public class X509V1CertificateGenerator { + private final JcaJceHelper bcHelper = new BCJcaJceHelper(); // needed to force provider loading + private final CertificateFactory certificateFactory = new CertificateFactory(); + private V1TBSCertificateGenerator tbsGen; private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; @@ -353,9 +358,10 @@ public class X509V1CertificateGenerator try { - return new X509CertificateObject(Certificate.getInstance(new DERSequence(v))); + return (X509Certificate)certificateFactory.engineGenerateCertificate( + new ByteArrayInputStream(new DERSequence(v).getEncoded(ASN1Encoding.DER))); } - catch (CertificateParsingException e) + catch (Exception e) { throw new ExtCertificateEncodingException("exception producing certificate object", e); } diff --git a/bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java b/bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java index 54be0016..28bf5507 100644 --- a/bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java +++ b/bcprov/src/main/java/org/bouncycastle/x509/X509V3CertificateGenerator.java @@ -1,5 +1,6 @@ package org.bouncycastle.x509; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.GeneralSecurityException; @@ -20,26 +21,24 @@ import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.TBSCertificate; import org.bouncycastle.asn1.x509.Time; import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; import org.bouncycastle.asn1.x509.X509ExtensionsGenerator; import org.bouncycastle.asn1.x509.X509Name; -import org.bouncycastle.jce.X509Principal; -// BEGIN ANDROID-ADDED -// See the definition of the jcaJceHelper field for details. -import org.bouncycastle.jcajce.provider.asymmetric.x509.X509CertificateObject; +import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory; import org.bouncycastle.jcajce.util.BCJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; -// END ANDROID-ADDED +import org.bouncycastle.jce.X509Principal; + import org.bouncycastle.x509.extension.X509ExtensionUtil; /** @@ -48,17 +47,14 @@ import org.bouncycastle.x509.extension.X509ExtensionUtil; */ public class X509V3CertificateGenerator { + private final JcaJceHelper bcHelper = new BCJcaJceHelper(); // needed to force provider loading + private final CertificateFactory certificateFactory = new CertificateFactory(); + private V3TBSCertificateGenerator tbsGen; private ASN1ObjectIdentifier sigOID; private AlgorithmIdentifier sigAlgId; private String signatureAlgorithm; private X509ExtensionsGenerator extGenerator; - // BEGIN ANDROID-ADDED - // Use org.bouncycastle.jcajce.provider.asymmetric.x509.X509CertificateObject - // instead of org.bouncycastle.jce.provider.X509CertificateObject. - // We need to pass one instance of JcaJceHelper in the constructor of the former class. - private final JcaJceHelper jcaJceHelper = new BCJcaJceHelper(); - // END ANDROID-ADDED public X509V3CertificateGenerator() { @@ -452,7 +448,7 @@ public class X509V3CertificateGenerator { return generateJcaObject(tbsCert, signature); } - catch (CertificateParsingException e) + catch (Exception e) { throw new ExtCertificateEncodingException("exception producing certificate object", e); } @@ -497,7 +493,7 @@ public class X509V3CertificateGenerator { return generateJcaObject(tbsCert, signature); } - catch (CertificateParsingException e) + catch (Exception e) { throw new ExtCertificateEncodingException("exception producing certificate object", e); } @@ -514,19 +510,16 @@ public class X509V3CertificateGenerator } private X509Certificate generateJcaObject(TBSCertificate tbsCert, byte[] signature) - throws CertificateParsingException + throws Exception { ASN1EncodableVector v = new ASN1EncodableVector(); v.add(tbsCert); v.add(sigAlgId); v.add(new DERBitString(signature)); - // BEGIN ANDROID-CHANGED - // Was: return new X509CertificateObject(Certificate.getInstance(new DERSequence(v))); - // We are using a different X509CertificateObject class than the original, see definition - // of the jcaJceHelper field for details. - return new X509CertificateObject(jcaJceHelper, Certificate.getInstance(new DERSequence(v))); - // END ANDROID-CHANGED + + return (X509Certificate)certificateFactory.engineGenerateCertificate( + new ByteArrayInputStream(new DERSequence(v).getEncoded(ASN1Encoding.DER))); } /** diff --git a/bouncycastle.version b/bouncycastle.version index 00639910..c7e252d8 100644 --- a/bouncycastle.version +++ b/bouncycastle.version @@ -1,2 +1,2 @@ BOUNCYCASTLE_JDK=15on -BOUNCYCASTLE_VERSION=154 +BOUNCYCASTLE_VERSION=156 |