diff options
author | Adam Vartanian <flooey@google.com> | 2017-06-29 08:40:17 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-06-29 08:40:17 +0000 |
commit | d454d2c786f2d7a2fe06c16b2b6856ce70e9aa77 (patch) | |
tree | 4f447468ea3515dd6a374aab68c728db6906a30b | |
parent | 50e3e4fbaecc803ea6f392fb4fa031ea6439ad54 (diff) | |
parent | c34afae88221d80487edbee59119dad461a7e33a (diff) | |
download | bouncycastle-d454d2c786f2d7a2fe06c16b2b6856ce70e9aa77.tar.gz |
Merge "external/bouncycastle: Upgrade to version 1.57" am: 6ec33a667c
am: c34afae882
Change-Id: Iebe265984f341f88597a55fe6d726ca7c0add8b4
57 files changed, 1015 insertions, 119 deletions
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/CertUtils.java b/bcpkix/src/main/java/org/bouncycastle/cert/CertUtils.java index 9e2e488d..87cddd9e 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/CertUtils.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/CertUtils.java @@ -15,6 +15,7 @@ import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1GeneralizedTime; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DEROutputStream; @@ -35,6 +36,18 @@ class CertUtils private static Set EMPTY_SET = Collections.unmodifiableSet(new HashSet()); private static List EMPTY_LIST = Collections.unmodifiableList(new ArrayList()); + static ASN1Primitive parseNonEmptyASN1(byte[] encoding) + throws IOException + { + ASN1Primitive p = ASN1Primitive.fromByteArray(encoding); + + if (p == null) + { + throw new IOException("no content found"); + } + return p; + } + static X509CertificateHolder generateFullCert(ContentSigner signer, TBSCertificate tbsCert) { try diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java index e6b0d7ec..fac9b441 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Set; import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; @@ -39,7 +38,7 @@ public class X509AttributeCertificateHolder { try { - return AttributeCertificate.getInstance(ASN1Primitive.fromByteArray(certEncoding)); + return AttributeCertificate.getInstance(CertUtils.parseNonEmptyASN1(certEncoding)); } catch (ClassCastException e) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java index 4b773e2e..67abd313 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java @@ -13,6 +13,7 @@ import java.util.Set; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.CertificateList; @@ -42,7 +43,12 @@ public class X509CRLHolder { try { - return CertificateList.getInstance(new ASN1InputStream(stream, true).readObject()); + ASN1Primitive obj = new ASN1InputStream(stream, true).readObject(); + if (obj == null) + { + throw new IOException("no content found"); + } + return CertificateList.getInstance(obj); } catch (ClassCastException e) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java index b5ad578d..2396aacf 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java +++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java @@ -8,7 +8,6 @@ import java.util.List; import java.util.Set; import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DEROutputStream; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; @@ -35,7 +34,7 @@ public class X509CertificateHolder { try { - return Certificate.getInstance(ASN1Primitive.fromByteArray(certEncoding)); + return Certificate.getInstance(CertUtils.parseNonEmptyASN1(certEncoding)); } catch (ClassCastException e) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cmc/CMCException.java b/bcpkix/src/main/java/org/bouncycastle/cmc/CMCException.java new file mode 100644 index 00000000..eaa1294d --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/cmc/CMCException.java @@ -0,0 +1,23 @@ +package org.bouncycastle.cmc; + +public class CMCException + extends Exception +{ + private final Throwable cause; + + public CMCException(String msg) + { + this(msg, null); + } + + public CMCException(String msg, Throwable cause) + { + super(msg); + this.cause = cause; + } + + public Throwable getCause() + { + return cause; + } +} diff --git a/bcpkix/src/main/java/org/bouncycastle/cmc/SimplePKIResponse.java b/bcpkix/src/main/java/org/bouncycastle/cmc/SimplePKIResponse.java new file mode 100644 index 00000000..23f70d68 --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/cmc/SimplePKIResponse.java @@ -0,0 +1,106 @@ +package org.bouncycastle.cmc; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.cert.X509CRLHolder; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.util.Encodable; +import org.bouncycastle.util.Store; + +/** + * Carrier for a Simple PKI Response. + * <p> + * A Simple PKI Response is defined in RFC 5272 as a CMS SignedData object with no EncapsulatedContentInfo + * and no SignerInfos attached. + * </p> + */ +public class SimplePKIResponse + implements Encodable +{ + private final CMSSignedData certificateResponse; + + private static ContentInfo parseBytes(byte[] responseEncoding) + throws CMCException + { + try + { + return ContentInfo.getInstance(ASN1Primitive.fromByteArray(responseEncoding)); + } + catch (Exception e) + { + throw new CMCException("malformed data: " + e.getMessage(), e); + } + } + + /** + * Create a SimplePKIResponse from the passed in bytes. + * + * @param responseEncoding BER/DER encoding of the certificate. + * @throws IOException in the event of corrupted data, or an incorrect structure. + */ + public SimplePKIResponse(byte[] responseEncoding) + throws CMCException + { + this(parseBytes(responseEncoding)); + } + + /** + * Create a SimplePKIResponse from the passed in ASN.1 structure. + * + * @param signedData a ContentInfo containing a SignedData. + */ + public SimplePKIResponse(ContentInfo signedData) + throws CMCException + { + try + { + this.certificateResponse = new CMSSignedData(signedData); + } + catch (CMSException e) + { + throw new CMCException("malformed response: " + e.getMessage(), e); + } + + if (certificateResponse.getSignerInfos().size() != 0) + { + throw new CMCException("malformed response: SignerInfo structures found"); + } + if (certificateResponse.getSignedContent() != null) + { + throw new CMCException("malformed response: Signed Content found"); + } + } + + /** + * Return any X.509 certificate objects in this SimplePKIResponse structure as a Store of X509CertificateHolder objects. + * + * @return a Store of X509CertificateHolder objects. + */ + public Store<X509CertificateHolder> getCertificates() + { + return certificateResponse.getCertificates(); + } + + /** + * Return any X.509 CRL objects in this SimplePKIResponse structure as a Store of X509CRLHolder objects. + * + * @return a Store of X509CRLHolder objects. + */ + public Store<X509CRLHolder> getCRLs() + { + return certificateResponse.getCRLs(); + } + + /** + * return the ASN.1 encoded representation of this object. + */ + public byte[] getEncoded() + throws IOException + { + return certificateResponse.getEncoded(); + } +} diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java index 7f6d4a2c..31197159 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java @@ -26,6 +26,9 @@ import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.SignedData; import org.bouncycastle.asn1.cms.SignerInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.cert.X509AttributeCertificateHolder; +import org.bouncycastle.cert.X509CRLHolder; +import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.util.Encodable; import org.bouncycastle.util.Store; @@ -292,7 +295,7 @@ public class CMSSignedData * * @return a Store of X509CertificateHolder objects. */ - public Store getCertificates() + public Store<X509CertificateHolder> getCertificates() { return HELPER.getCertificates(signedData.getCertificates()); } @@ -302,7 +305,7 @@ public class CMSSignedData * * @return a Store of X509CRLHolder objects. */ - public Store getCRLs() + public Store<X509CRLHolder> getCRLs() { return HELPER.getCRLs(signedData.getCRLs()); } @@ -312,7 +315,7 @@ public class CMSSignedData * * @return a Store of X509AttributeCertificateHolder objects. */ - public Store getAttributeCertificates() + public Store<X509AttributeCertificateHolder> getAttributeCertificates() { return HELPER.getAttributeCertificates(signedData.getCertificates()); } diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java index 7dd16e03..0cd1f5f6 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSUtils.java @@ -262,7 +262,13 @@ class CMSUtils { try { - return ContentInfo.getInstance(in.readObject()); + ContentInfo info = ContentInfo.getInstance(in.readObject()); + if (info == null) + { + throw new CMSException("No content found."); + } + + return info; } catch (IOException e) { diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformationVerifier.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformationVerifier.java index ada4d0ea..06d2c1b3 100644 --- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformationVerifier.java +++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformationVerifier.java @@ -37,9 +37,10 @@ public class SignerInformationVerifier public ContentVerifier getContentVerifier(AlgorithmIdentifier signingAlgorithm, AlgorithmIdentifier digestAlgorithm) throws OperatorCreationException { - String signatureName = sigNameGenerator.getSignatureName(digestAlgorithm, signingAlgorithm); + String signatureName = sigNameGenerator.getSignatureName(digestAlgorithm, signingAlgorithm); + AlgorithmIdentifier baseAlgID = sigAlgorithmFinder.find(signatureName); - return verifierProvider.get(sigAlgorithmFinder.find(signatureName)); + return verifierProvider.get(new AlgorithmIdentifier(baseAlgID.getAlgorithm(), signingAlgorithm.getParameters())); } public DigestCalculator getDigestCalculator(AlgorithmIdentifier algorithmIdentifier) diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/bc/package.html b/bcpkix/src/main/java/org/bouncycastle/cms/bc/package.html new file mode 100644 index 00000000..7182ae35 --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/cms/bc/package.html @@ -0,0 +1,5 @@ +<html> +<body bgcolor="#ffffff"> +CMS operator implementations for doing message encryption, signing, digesting, and MACing operations using the BC lightweight API. +</body> +</html> diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/package.html b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/package.html new file mode 100644 index 00000000..5221afe2 --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/cms/jcajce/package.html @@ -0,0 +1,5 @@ +<html> +<body bgcolor="#ffffff"> +CMS operator implementations for doing message encryption, signing, digesting, and MACing operations using the JCA and the JCE. +</body> +</html> diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java index 57920181..e369185c 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java @@ -103,13 +103,17 @@ public class DefaultDigestAlgorithmIdentifierFinder digestNameToOids.put("SHA-256", NISTObjectIdentifiers.id_sha256); digestNameToOids.put("SHA-384", NISTObjectIdentifiers.id_sha384); digestNameToOids.put("SHA-512", NISTObjectIdentifiers.id_sha512); - // BEGIN android-removed + // digestNameToOids.put("SHA-512-224", NISTObjectIdentifiers.id_sha512_224); + // digestNameToOids.put("SHA-512-256", NISTObjectIdentifiers.id_sha512_256); + // // digestNameToOids.put("SHA1", OIWObjectIdentifiers.idSHA1); // digestNameToOids.put("SHA224", NISTObjectIdentifiers.id_sha224); // digestNameToOids.put("SHA256", NISTObjectIdentifiers.id_sha256); // digestNameToOids.put("SHA384", NISTObjectIdentifiers.id_sha384); // digestNameToOids.put("SHA512", NISTObjectIdentifiers.id_sha512); + // digestNameToOids.put("SHA512-224", NISTObjectIdentifiers.id_sha512_224); + // digestNameToOids.put("SHA512-256", NISTObjectIdentifiers.id_sha512_256); // digestNameToOids.put("SHA3-224", NISTObjectIdentifiers.id_sha3_224); // digestNameToOids.put("SHA3-256", NISTObjectIdentifiers.id_sha3_256); diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java index 77f358a0..d1976afb 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java @@ -14,6 +14,7 @@ import org.bouncycastle.asn1.DERNull; // import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers; // import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; // import org.bouncycastle.asn1.eac.EACObjectIdentifiers; +// import org.bouncycastle.asn1.gm.GMObjectIdentifiers; // END android-removed import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; @@ -105,6 +106,7 @@ public class DefaultSignatureAlgorithmIdentifierFinder // 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); + // algorithms.put("SM3WITHSM2", GMObjectIdentifiers.sm2sign_with_sm3); // END android-removed // @@ -122,20 +124,22 @@ public class DefaultSignatureAlgorithmIdentifierFinder noParams.add(NISTObjectIdentifiers.dsa_with_sha384); noParams.add(NISTObjectIdentifiers.dsa_with_sha512); + // BEGIN Android-removed // // RFC 4491 // - // BEGIN android-removed // noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94); // 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); + + // + // SM2 + // + // noParams.add(GMObjectIdentifiers.sm2sign_with_sm3); // END android-removed // diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/bc/package.html b/bcpkix/src/main/java/org/bouncycastle/operator/bc/package.html new file mode 100644 index 00000000..6d7ebbae --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/operator/bc/package.html @@ -0,0 +1,5 @@ +<html> +<body bgcolor="#ffffff"> +Basic operator implementations for doing encryption, signing, and digest operations using the BC lightweight API. +</body> +</html> 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 532d3b51..8ac72ea6 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java @@ -23,6 +23,7 @@ import javax.crypto.Cipher; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERNull; // BEGIN android-removed // import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers; @@ -319,6 +320,27 @@ class OperatorHelper } } + if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS)) + { + ASN1Sequence seq = ASN1Sequence.getInstance(sigAlgId.getParameters()); + + if (notDefaultPSSParams(seq)) + { + try + { + AlgorithmParameters algParams = helper.createAlgorithmParameters("PSS"); + + algParams.init(seq.getEncoded()); + + sig.setParameter(algParams.getParameterSpec(PSSParameterSpec.class)); + } + catch (IOException e) + { + throw new GeneralSecurityException("unable to process PSS parameters: " + e.getMessage()); + } + } + } + return sig; } @@ -468,4 +490,31 @@ class OperatorHelper return oid.getId(); } + + // for our purposes default includes varient digest with salt the same size as digest + private boolean notDefaultPSSParams(ASN1Sequence seq) + throws GeneralSecurityException + { + if (seq == null || seq.size() == 0) + { + return false; + } + + RSASSAPSSparams pssParams = RSASSAPSSparams.getInstance(seq); + + if (!pssParams.getMaskGenAlgorithm().getAlgorithm().equals(PKCSObjectIdentifiers.id_mgf1)) + { + return true; + } + + // same digest for sig and MGF1 + if (!pssParams.getHashAlgorithm().equals(AlgorithmIdentifier.getInstance(pssParams.getMaskGenAlgorithm().getParameters()))) + { + return true; + } + + MessageDigest digest = createDigest(pssParams.getHashAlgorithm()); + + return pssParams.getSaltLength().intValue() != digest.getDigestLength(); + } } diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/package.html b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/package.html new file mode 100644 index 00000000..5a7fa1cf --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/package.html @@ -0,0 +1,5 @@ +<html> +<body bgcolor="#ffffff"> +Basic operator implementations for doing encryption, signing, and digest operations using the JCA and the JCE. +</body> +</html> diff --git a/bcpkix/src/main/java/org/bouncycastle/pkcs/bc/package.html b/bcpkix/src/main/java/org/bouncycastle/pkcs/bc/package.html new file mode 100644 index 00000000..bb47e1a0 --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/pkcs/bc/package.html @@ -0,0 +1,7 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<body bgcolor="#ffffff"> +BC lightweight API extensions and operators for the PKCS#10 certification request package. +</body> +</html> diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/gm/GMObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/gm/GMObjectIdentifiers.java new file mode 100644 index 00000000..ade67827 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/gm/GMObjectIdentifiers.java @@ -0,0 +1,84 @@ +package org.bouncycastle.asn1.gm; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; + +public interface GMObjectIdentifiers +{ + ASN1ObjectIdentifier sm_scheme = new ASN1ObjectIdentifier("1.2.156.10197.1"); + + ASN1ObjectIdentifier sm6_ecb = sm_scheme.branch("101.1"); + ASN1ObjectIdentifier sm6_cbc = sm_scheme.branch("101.2"); + ASN1ObjectIdentifier sm6_ofb128 = sm_scheme.branch("101.3"); + ASN1ObjectIdentifier sm6_cfb128 = sm_scheme.branch("101.4"); + + ASN1ObjectIdentifier sm1_ecb = sm_scheme.branch("102.1"); + ASN1ObjectIdentifier sm1_cbc = sm_scheme.branch("102.2"); + ASN1ObjectIdentifier sm1_ofb128 = sm_scheme.branch("102.3"); + ASN1ObjectIdentifier sm1_cfb128 = sm_scheme.branch("102.4"); + ASN1ObjectIdentifier sm1_cfb1 = sm_scheme.branch("102.5"); + ASN1ObjectIdentifier sm1_cfb8 = sm_scheme.branch("102.6"); + + ASN1ObjectIdentifier ssf33_ecb = sm_scheme.branch("103.1"); + ASN1ObjectIdentifier ssf33_cbc = sm_scheme.branch("103.2"); + ASN1ObjectIdentifier ssf33_ofb128 = sm_scheme.branch("103.3"); + ASN1ObjectIdentifier ssf33_cfb128 = sm_scheme.branch("103.4"); + ASN1ObjectIdentifier ssf33_cfb1 = sm_scheme.branch("103.5"); + ASN1ObjectIdentifier ssf33_cfb8 = sm_scheme.branch("103.6"); + + ASN1ObjectIdentifier sms4_ecb = sm_scheme.branch("104.1"); + ASN1ObjectIdentifier sms4_cbc = sm_scheme.branch("104.2"); + ASN1ObjectIdentifier sms4_ofb128 = sm_scheme.branch("104.3"); + ASN1ObjectIdentifier sms4_cfb128 = sm_scheme.branch("104.4"); + ASN1ObjectIdentifier sms4_cfb1 = sm_scheme.branch("104.5"); + ASN1ObjectIdentifier sms4_cfb8 = sm_scheme.branch("104.6"); + ASN1ObjectIdentifier sms4_ctr = sm_scheme.branch("104.7"); + ASN1ObjectIdentifier sms4_gcm = sm_scheme.branch("104.8"); + ASN1ObjectIdentifier sms4_ccm = sm_scheme.branch("104.9"); + ASN1ObjectIdentifier sms4_xts = sm_scheme.branch("104.10"); + ASN1ObjectIdentifier sms4_wrap = sm_scheme.branch("104.11"); + ASN1ObjectIdentifier sms4_wrap_pad = sm_scheme.branch("104.12"); + ASN1ObjectIdentifier sms4_ocb = sm_scheme.branch("104.100"); + + ASN1ObjectIdentifier sm5 = sm_scheme.branch("201"); + + ASN1ObjectIdentifier sm2p256v1 = sm_scheme.branch("301"); + ASN1ObjectIdentifier sm2sign = sm_scheme.branch("301.1"); + ASN1ObjectIdentifier sm2exchange = sm_scheme.branch("301.2"); + ASN1ObjectIdentifier sm2encrypt = sm_scheme.branch("301.3"); + + ASN1ObjectIdentifier wapip192v1 = sm_scheme.branch("301.101"); + + ASN1ObjectIdentifier sm2encrypt_recommendedParameters = sm2encrypt.branch("1"); + ASN1ObjectIdentifier sm2encrypt_specifiedParameters = sm2encrypt.branch("2"); + ASN1ObjectIdentifier sm2encrypt_with_sm3 = sm2encrypt.branch("2.1"); + ASN1ObjectIdentifier sm2encrypt_with_sha1 = sm2encrypt.branch("2.2"); + ASN1ObjectIdentifier sm2encrypt_with_sha224 = sm2encrypt.branch("2.3"); + ASN1ObjectIdentifier sm2encrypt_with_sha256 = sm2encrypt.branch("2.4"); + ASN1ObjectIdentifier sm2encrypt_with_sha384 = sm2encrypt.branch("2.5"); + ASN1ObjectIdentifier sm2encrypt_with_sha512 = sm2encrypt.branch("2.6"); + ASN1ObjectIdentifier sm2encrypt_with_rmd160 = sm2encrypt.branch("2.7"); + ASN1ObjectIdentifier sm2encrypt_with_whirlpool =sm2encrypt.branch("2.8"); + ASN1ObjectIdentifier sm2encrypt_with_blake2b512 = sm2encrypt.branch("2.9"); + ASN1ObjectIdentifier sm2encrypt_with_blake2s256 = sm2encrypt.branch("2.10"); + ASN1ObjectIdentifier sm2encrypt_with_md5 = sm2encrypt.branch("2.11"); + + ASN1ObjectIdentifier id_sm9PublicKey = sm_scheme.branch("302"); + ASN1ObjectIdentifier sm9sign = sm_scheme.branch("302.1"); + ASN1ObjectIdentifier sm9keyagreement = sm_scheme.branch("302.2"); + ASN1ObjectIdentifier sm9encrypt = sm_scheme.branch("302.3"); + + ASN1ObjectIdentifier sm3 = sm_scheme.branch("401"); + + ASN1ObjectIdentifier hmac_sm3 = sm3.branch("2"); + + ASN1ObjectIdentifier sm2sign_with_sm3 = sm_scheme.branch("501"); + ASN1ObjectIdentifier sm2sign_with_sha1 = sm_scheme.branch("502"); + ASN1ObjectIdentifier sm2sign_with_sha256 = sm_scheme.branch("503"); + ASN1ObjectIdentifier sm2sign_with_sha512 = sm_scheme.branch("504"); + ASN1ObjectIdentifier sm2sign_with_sha224 = sm_scheme.branch("505"); + ASN1ObjectIdentifier sm2sign_with_sha384 = sm_scheme.branch("506"); + ASN1ObjectIdentifier sm2sign_with_rmd160 = sm_scheme.branch("507"); + ASN1ObjectIdentifier sm2sign_with_whirlpool = sm_scheme.branch("520"); + ASN1ObjectIdentifier sm2sign_with_blake2b512 = sm_scheme.branch("521"); + ASN1ObjectIdentifier sm2sign_with_blake2s256 = sm_scheme.branch("522"); +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/nsri/NSRIObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/nsri/NSRIObjectIdentifiers.java new file mode 100644 index 00000000..4ef8148a --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/nsri/NSRIObjectIdentifiers.java @@ -0,0 +1,58 @@ +package org.bouncycastle.asn1.nsri; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; + +public interface NSRIObjectIdentifiers +{ + static final ASN1ObjectIdentifier nsri = new ASN1ObjectIdentifier("1.2.410.200046"); + + static final ASN1ObjectIdentifier id_algorithm = nsri.branch("1"); + + static final ASN1ObjectIdentifier id_sea = id_algorithm.branch("1"); + static final ASN1ObjectIdentifier id_pad = id_algorithm.branch("2"); + + static final ASN1ObjectIdentifier id_pad_null = id_algorithm.branch("0"); + static final ASN1ObjectIdentifier id_pad_1 = id_algorithm.branch("1"); + + static final ASN1ObjectIdentifier id_aria128_ecb = id_sea.branch("1"); + static final ASN1ObjectIdentifier id_aria128_cbc = id_sea.branch("2"); + static final ASN1ObjectIdentifier id_aria128_cfb = id_sea.branch("3"); + static final ASN1ObjectIdentifier id_aria128_ofb = id_sea.branch("4"); + static final ASN1ObjectIdentifier id_aria128_ctr = id_sea.branch("5"); + + static final ASN1ObjectIdentifier id_aria192_ecb = id_sea.branch("6"); + static final ASN1ObjectIdentifier id_aria192_cbc = id_sea.branch("7"); + static final ASN1ObjectIdentifier id_aria192_cfb = id_sea.branch("8"); + static final ASN1ObjectIdentifier id_aria192_ofb = id_sea.branch("9"); + static final ASN1ObjectIdentifier id_aria192_ctr = id_sea.branch("10"); + + static final ASN1ObjectIdentifier id_aria256_ecb = id_sea.branch("11"); + static final ASN1ObjectIdentifier id_aria256_cbc = id_sea.branch("12"); + static final ASN1ObjectIdentifier id_aria256_cfb = id_sea.branch("13"); + static final ASN1ObjectIdentifier id_aria256_ofb = id_sea.branch("14"); + static final ASN1ObjectIdentifier id_aria256_ctr = id_sea.branch("15"); + + static final ASN1ObjectIdentifier id_aria128_cmac = id_sea.branch("21"); + static final ASN1ObjectIdentifier id_aria192_cmac = id_sea.branch("22"); + static final ASN1ObjectIdentifier id_aria256_cmac = id_sea.branch("23"); + + static final ASN1ObjectIdentifier id_aria128_ocb2 = id_sea.branch("31"); + static final ASN1ObjectIdentifier id_aria192_ocb2 = id_sea.branch("32"); + static final ASN1ObjectIdentifier id_aria256_ocb2 = id_sea.branch("33"); + + static final ASN1ObjectIdentifier id_aria128_gcm = id_sea.branch("34"); + static final ASN1ObjectIdentifier id_aria192_gcm = id_sea.branch("35"); + static final ASN1ObjectIdentifier id_aria256_gcm = id_sea.branch("36"); + + static final ASN1ObjectIdentifier id_aria128_ccm = id_sea.branch("37"); + static final ASN1ObjectIdentifier id_aria192_ccm = id_sea.branch("38"); + static final ASN1ObjectIdentifier id_aria256_ccm = id_sea.branch("39"); + + static final ASN1ObjectIdentifier id_aria128_kw = id_sea.branch("40"); + static final ASN1ObjectIdentifier id_aria192_kw = id_sea.branch("41"); + static final ASN1ObjectIdentifier id_aria256_kw = id_sea.branch("42"); + + static final ASN1ObjectIdentifier id_aria128_kwp = id_sea.branch("43"); + static final ASN1ObjectIdentifier id_aria192_kwp = id_sea.branch("44"); + static final ASN1ObjectIdentifier id_aria256_kwp = id_sea.branch("45"); +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/Attribute.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/Attribute.java new file mode 100644 index 00000000..6374c980 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/Attribute.java @@ -0,0 +1,88 @@ +package org.bouncycastle.asn1.pkcs; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Object; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DERSequence; + +public class Attribute + extends ASN1Object +{ + private ASN1ObjectIdentifier attrType; + private ASN1Set attrValues; + + /** + * return an Attribute object from the given object. + * + * @param o the object we want converted. + * @exception IllegalArgumentException if the object cannot be converted. + */ + public static Attribute getInstance( + Object o) + { + if (o == null || o instanceof Attribute) + { + return (Attribute)o; + } + + if (o instanceof ASN1Sequence) + { + return new Attribute((ASN1Sequence)o); + } + + throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName()); + } + + public Attribute( + ASN1Sequence seq) + { + attrType = (ASN1ObjectIdentifier)seq.getObjectAt(0); + attrValues = (ASN1Set)seq.getObjectAt(1); + } + + public Attribute( + ASN1ObjectIdentifier attrType, + ASN1Set attrValues) + { + this.attrType = attrType; + this.attrValues = attrValues; + } + + public ASN1ObjectIdentifier getAttrType() + { + return attrType; + } + + public ASN1Set getAttrValues() + { + return attrValues; + } + + public ASN1Encodable[] getAttributeValues() + { + return attrValues.toArray(); + } + + /** + * Produce an object suitable for an ASN1OutputStream. + * <pre> + * Attribute ::= SEQUENCE { + * attrType OBJECT IDENTIFIER, + * attrValues SET OF AttributeValue + * } + * </pre> + */ + public ASN1Primitive toASN1Primitive() + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(attrType); + v.add(attrValues); + + return new DERSequence(v); + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequest.java b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequest.java index 987d4eba..e089cbc4 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequest.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequest.java @@ -54,6 +54,9 @@ public class CertificationRequest this.sigBits = signature; } + /** + * @deprecated use getInstance() + */ public CertificationRequest( ASN1Sequence seq) { 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 dca0719c..25e62863 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java @@ -1,5 +1,7 @@ package org.bouncycastle.asn1.pkcs; +import java.util.Enumeration; + import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Object; @@ -77,6 +79,8 @@ public class CertificationRequestInfo throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator."); } + validateAttributes(attributes); + this.subject = subject; this.subjectPKInfo = pkInfo; this.attributes = attributes; @@ -90,14 +94,7 @@ public class CertificationRequestInfo SubjectPublicKeyInfo pkInfo, ASN1Set attributes) { - if ((subject == null) || (pkInfo == null)) - { - throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator."); - } - - this.subject = X500Name.getInstance(subject.toASN1Primitive()); - this.subjectPKInfo = pkInfo; - this.attributes = attributes; + this(X500Name.getInstance(subject.toASN1Primitive()), pkInfo, attributes); } /** @@ -121,6 +118,8 @@ public class CertificationRequestInfo attributes = ASN1Set.getInstance(tagobj, false); } + validateAttributes(attributes); + if ((subject == null) || (version == null) || (subjectPKInfo == null)) { throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator."); @@ -162,4 +161,24 @@ public class CertificationRequestInfo return new DERSequence(v); } + + private static void validateAttributes(ASN1Set attributes) + { + if (attributes == null) + { + return; + } + + for (Enumeration en = attributes.getObjects(); en.hasMoreElements();) + { + Attribute attr = Attribute.getInstance(en.nextElement()); + if (attr.getAttrType().equals(PKCSObjectIdentifiers.pkcs_9_at_challengePassword)) + { + if (attr.getAttrValues().size() != 1) + { + throw new IllegalArgumentException("challengePassword attribute must have one value"); + } + } + } + } } 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 6e50f552..75df2aa7 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java @@ -343,6 +343,20 @@ public interface PKCSObjectIdentifiers /** PKCS#9: 1.2.840.113549.1.9.16.6.2.27 - <a href="http://tools.ietf.org/html/rfc3126">RFC 3126</a> */ static final ASN1ObjectIdentifier id_aa_ets_archiveTimestamp = id_aa.branch("27"); + /** PKCS#9: 1.2.840.113549.1.9.16.6.2.37 - <a href="https://tools.ietf.org/html/rfc4108#section-2.2.5">RFC 4108</a> */ + static final ASN1ObjectIdentifier id_aa_decryptKeyID = id_aa.branch("37"); + + /** PKCS#9: 1.2.840.113549.1.9.16.6.2.38 - <a href="https://tools.ietf.org/html/rfc4108#section-2.2.6">RFC 4108</a> */ + static final ASN1ObjectIdentifier id_aa_implCryptoAlgs = id_aa.branch("38"); + + /** PKCS#9: 1.2.840.113549.1.9.16.2.54 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/ + static final ASN1ObjectIdentifier id_aa_asymmDecryptKeyID = id_aa.branch("54"); + + /** PKCS#9: 1.2.840.113549.1.9.16.2.43 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/ + static final ASN1ObjectIdentifier id_aa_implCompressAlgs = id_aa.branch("43"); + /** PKCS#9: 1.2.840.113549.1.9.16.2.40 <a href="https://tools.ietf.org/html/rfc7030">RFC7030</a>*/ + static final ASN1ObjectIdentifier id_aa_communityIdentifiers = id_aa.branch("40"); + /** @deprecated use id_aa_ets_sigPolicyId instead */ static final ASN1ObjectIdentifier id_aa_sigPolicyId = id_aa_ets_sigPolicyId; /** @deprecated use id_aa_ets_commitmentType instead */ diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java index 01c9aa2a..f545d0b6 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/KeyPurposeId.java @@ -9,7 +9,7 @@ import org.bouncycastle.asn1.ASN1Primitive; * <pre> * KeyPurposeId ::= OBJECT IDENTIFIER * - * id-kp ::= OBJECT IDENTIFIER { iso(1) identified-organization(3) + * id-kp ::= OBJECT IDENTIFIER { iso(1) identified-organization(3) * dod(6) internet(1) security(5) mechanisms(5) pkix(7) 3} * * </pre> @@ -115,6 +115,24 @@ public class KeyPurposeId */ public static final KeyPurposeId id_kp_smartcardlogon = new KeyPurposeId(new ASN1ObjectIdentifier("1.3.6.1.4.1.311.20.2.2")); + + /** + * + */ + public static final KeyPurposeId id_kp_macAddress = new KeyPurposeId(new ASN1ObjectIdentifier("1.3.6.1.1.1.1.22")); + + + /** + * Microsoft Server Gated Crypto (msSGC) see http://www.alvestrand.no/objectid/1.3.6.1.4.1.311.10.3.3.html + */ + public static final KeyPurposeId id_kp_msSGC = new KeyPurposeId(new ASN1ObjectIdentifier("1.3.6.1.4.1.311.10.3.3")); + + /** + * Netscape Server Gated Crypto (nsSGC) see http://www.alvestrand.no/objectid/2.16.840.1.113730.4.1.html + */ + public static final KeyPurposeId id_kp_nsSGC = new KeyPurposeId(new ASN1ObjectIdentifier("2.16.840.1.113730.4.1")); + + private ASN1ObjectIdentifier id; private KeyPurposeId(ASN1ObjectIdentifier id) @@ -123,8 +141,8 @@ public class KeyPurposeId } /** - * @deprecated use getInstance and an OID or one of the constants above. * @param id string representation of an OID. + * @deprecated use getInstance and an OID or one of the constants above. */ public KeyPurposeId(String id) { diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java index aeb53f09..e2d22a73 100644 --- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java +++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/PolicyConstraints.java @@ -93,12 +93,12 @@ public class PolicyConstraints if (requireExplicitPolicyMapping != null) { - v.add(new DERTaggedObject(0, new ASN1Integer(requireExplicitPolicyMapping))); + v.add(new DERTaggedObject(false,0, new ASN1Integer(requireExplicitPolicyMapping))); } if (inhibitPolicyMapping != null) { - v.add(new DERTaggedObject(1, new ASN1Integer(inhibitPolicyMapping))); + v.add(new DERTaggedObject(false, 1, new ASN1Integer(inhibitPolicyMapping))); } return new DERSequence(v); 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 54e54cec..1ba5ebb1 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java @@ -37,6 +37,7 @@ public class GCMBlockCipher // These fields are set by init and not modified by processing private boolean forEncryption; + private boolean initialised; private int macSize; private byte[] lastKey; private byte[] nonce; @@ -99,6 +100,7 @@ public class GCMBlockCipher { this.forEncryption = forEncryption; this.macBlock = null; + this.initialised = true; KeyParameter keyParam; byte[] newNonce = null; @@ -260,6 +262,7 @@ public class GCMBlockCipher public void processAADByte(byte in) { + checkStatus(); // BEGIN android-added if (getTotalInputSizeAfterNewInput(1) > MAX_INPUT_SIZE) { throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes"); @@ -319,11 +322,13 @@ public class GCMBlockCipher public int processByte(byte in, byte[] out, int outOff) throws DataLengthException { + checkStatus(); // BEGIN android-added if (getTotalInputSizeAfterNewInput(1) > MAX_INPUT_SIZE) { throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes"); } // END android-added + bufBlock[bufOff] = in; if (++bufOff == bufBlock.length) { @@ -336,11 +341,13 @@ public class GCMBlockCipher public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { + checkStatus(); // BEGIN android-added if (getTotalInputSizeAfterNewInput(len) > MAX_INPUT_SIZE) { throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes"); } // END android-added + if (in.length < (inOff + len)) { throw new DataLengthException("Input buffer too short"); @@ -385,6 +392,8 @@ public class GCMBlockCipher public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException { + checkStatus(); + if (totalLength == 0) { initCipher(); @@ -534,9 +543,16 @@ public class GCMBlockCipher macBlock = null; } - if (initialAssociatedText != null) + if (forEncryption) { - processAADBytes(initialAssociatedText, 0, initialAssociatedText.length); + initialised = false; + } + else + { + if (initialAssociatedText != null) + { + processAADBytes(initialAssociatedText, 0, initialAssociatedText.length); + } } } @@ -604,4 +620,16 @@ public class GCMBlockCipher cipher.processBlock(counter, 0, tmp, 0); return tmp; } + + private void checkStatus() + { + if (!initialised) + { + if (forEncryption) + { + throw new IllegalStateException("GCM cipher cannot be reused for encryption"); + } + throw new IllegalStateException("GCM cipher needs to be initialised"); + } + } } diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/ParametersWithID.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/ParametersWithID.java new file mode 100644 index 00000000..e942a5a8 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/ParametersWithID.java @@ -0,0 +1,28 @@ +package org.bouncycastle.crypto.params; + +import org.bouncycastle.crypto.CipherParameters; + +public class ParametersWithID + implements CipherParameters +{ + private CipherParameters parameters; + private byte[] id; + + public ParametersWithID( + CipherParameters parameters, + byte[] id) + { + this.parameters = parameters; + this.id = id; + } + + public byte[] getID() + { + return id; + } + + public CipherParameters getParameters() + { + return parameters; + } +} diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNoCloseNotifyException.java b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNoCloseNotifyException.java new file mode 100644 index 00000000..a5c583b0 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/crypto/tls/TlsNoCloseNotifyException.java @@ -0,0 +1,15 @@ +package org.bouncycastle.crypto.tls; + +import java.io.EOFException; + +/** + * This exception will be thrown (only) when the connection is closed by the peer without sending a + * {@link AlertDescription#close_notify close_notify} warning alert. If this happens, the TLS + * protocol cannot rule out truncation of the connection data (potentially malicious). It may be + * possible to check for truncation via some property of a higher level protocol built upon TLS, + * e.g. the Content-Length header for HTTPS. + */ +public class TlsNoCloseNotifyException + extends EOFException +{ +} 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 da326f47..579b9735 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 @@ -1,5 +1,8 @@ package org.bouncycastle.jcajce.provider.asymmetric; +import java.util.HashMap; +import java.util.Map; + import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.jcajce.provider.asymmetric.dh.KeyFactorySpi; @@ -10,6 +13,14 @@ public class DH { private static final String PREFIX = "org.bouncycastle.jcajce.provider.asymmetric" + ".dh."; + private static final Map<String, String> generalDhAttributes = new HashMap<String, String>(); + + static + { + generalDhAttributes.put("SupportedKeyClasses", "javax.crypto.interfaces.DHPublicKey|javax.crypto.interfaces.DHPrivateKey"); + generalDhAttributes.put("SupportedKeyFormats", "PKCS#8|X.509"); + } + public static class Mappings extends AsymmetricAlgorithmProvider { @@ -22,6 +33,7 @@ public class DH provider.addAlgorithm("KeyPairGenerator.DH", PREFIX + "KeyPairGeneratorSpi"); provider.addAlgorithm("Alg.Alias.KeyPairGenerator.DIFFIEHELLMAN", "DH"); + provider.addAttributes("KeyAgreement.DH", generalDhAttributes); provider.addAlgorithm("KeyAgreement.DH", PREFIX + "KeyAgreementSpi"); provider.addAlgorithm("Alg.Alias.KeyAgreement.DIFFIEHELLMAN", "DH"); // BEGIN android-removed 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 92581f47..70ae1203 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 @@ -97,7 +97,7 @@ public class DSA // END android-changed registerOid(provider, DSAUtil.dsaOids[i], "DSA", keyFact); - registerOidAlgorithmParameters(provider, DSAUtil.dsaOids[i], "DSA"); + registerOidAlgorithmParameterGenerator(provider, DSAUtil.dsaOids[i], "DSA"); } } } 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 7d0baa94..1c49da9f 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 @@ -1,5 +1,8 @@ package org.bouncycastle.jcajce.provider.asymmetric; +import java.util.HashMap; +import java.util.Map; + // BEGIN android-removed // import org.bouncycastle.asn1.bsi.BSIObjectIdentifiers; // import org.bouncycastle.asn1.eac.EACObjectIdentifiers; @@ -19,6 +22,14 @@ public class EC { private static final String PREFIX = "org.bouncycastle.jcajce.provider.asymmetric" + ".ec."; + private static final Map<String, String> generalEcAttributes = new HashMap<String, String>(); + + static + { + generalEcAttributes.put("SupportedKeyClasses", "java.security.interfaces.ECPublicKey|java.security.interfaces.ECPrivateKey"); + generalEcAttributes.put("SupportedKeyFormats", "PKCS#8|X.509"); + } + public static class Mappings extends AsymmetricAlgorithmProvider { @@ -30,9 +41,12 @@ public class EC { provider.addAlgorithm("AlgorithmParameters.EC", PREFIX + "AlgorithmParametersSpi"); + provider.addAttributes("KeyAgreement.ECDH", generalEcAttributes); provider.addAlgorithm("KeyAgreement.ECDH", PREFIX + "KeyAgreementSpi$DH"); // BEGIN android-removed + // provider.addAttributes("KeyAgreement.ECDHC", generalEcAttributes); // provider.addAlgorithm("KeyAgreement.ECDHC", PREFIX + "KeyAgreementSpi$DHC"); + // provider.addAttributes("KeyAgreement.ECCDH", generalEcAttributes); // provider.addAlgorithm("KeyAgreement.ECCDH", PREFIX + "KeyAgreementSpi$DHC"); // // provider.addAlgorithm("KeyAgreement." + X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, PREFIX + "KeyAgreementSpi$DHwithSHA1KDFAndSharedInfo"); 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 20899c91..86026ccd 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,5 +1,8 @@ package org.bouncycastle.jcajce.provider.asymmetric; +import java.util.HashMap; +import java.util.Map; + import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; @@ -17,6 +20,14 @@ public class RSA { private static final String PREFIX = "org.bouncycastle.jcajce.provider.asymmetric" + ".rsa."; + private static final Map<String, String> generalRsaAttributes = new HashMap<String, String>(); + + static + { + generalRsaAttributes.put("SupportedKeyClasses", "javax.crypto.interfaces.RSAPublicKey|javax.crypto.interfaces.RSAPrivateKey"); + generalRsaAttributes.put("SupportedKeyFormats", "PKCS#8|X.509"); + } + public static class Mappings extends AsymmetricAlgorithmProvider { @@ -48,6 +59,7 @@ public class RSA // provider.addAlgorithm("Alg.Alias.AlgorithmParameters.NONEWITHRSAANDMGF1", "PSS"); // END android-removed + provider.addAttributes("Cipher.RSA", generalRsaAttributes); provider.addAlgorithm("Cipher.RSA", PREFIX + "CipherSpi$NoPadding"); // BEGIN android-changed provider.addAlgorithm("Alg.Alias.Cipher.RSA/RAW", "RSA"); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java index e4c8172c..bf6bfe71 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/AlgorithmParameterGeneratorSpi.java @@ -11,12 +11,13 @@ import javax.crypto.spec.DHParameterSpec; import org.bouncycastle.crypto.generators.DHParametersGenerator; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAlgorithmParameterGeneratorSpi; +import org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator; public class AlgorithmParameterGeneratorSpi extends BaseAlgorithmParameterGeneratorSpi { protected SecureRandom random; - protected int strength = 1024; + protected int strength = 2048; private int l = 0; @@ -48,13 +49,15 @@ public class AlgorithmParameterGeneratorSpi { DHParametersGenerator pGen = new DHParametersGenerator(); + int certainty = PrimeCertaintyCalculator.getDefaultCertainty(strength); + if (random != null) { - pGen.init(strength, 20, random); + pGen.init(strength, certainty, random); } else { - pGen.init(strength, 20, new SecureRandom()); + pGen.init(strength, certainty, new SecureRandom()); } DHParameters p = pGen.generateParameters(); 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 793f7299..864bf56f 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 @@ -15,6 +15,7 @@ import org.bouncycastle.crypto.params.DHKeyGenerationParameters; import org.bouncycastle.crypto.params.DHParameters; import org.bouncycastle.crypto.params.DHPrivateKeyParameters; import org.bouncycastle.crypto.params.DHPublicKeyParameters; +import org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.Integers; @@ -26,8 +27,7 @@ public class KeyPairGeneratorSpi DHKeyGenerationParameters param; DHBasicKeyPairGenerator engine = new DHBasicKeyPairGenerator(); - int strength = 1024; - int certainty = 20; + int strength = 2048; SecureRandom random = new SecureRandom(); boolean initialised = false; @@ -95,7 +95,7 @@ public class KeyPairGeneratorSpi DHParametersGenerator pGen = new DHParametersGenerator(); - pGen.init(strength, certainty, random); + pGen.init(strength, PrimeCertaintyCalculator.getDefaultCertainty(strength), random); param = new DHKeyGenerationParameters(random, pGen.generateParameters()); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java index 2d7c4c5d..6a0dffa1 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java @@ -12,11 +12,16 @@ import org.bouncycastle.crypto.generators.DSAParametersGenerator; import org.bouncycastle.crypto.params.DSAParameterGenerationParameters; import org.bouncycastle.crypto.params.DSAParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAlgorithmParameterGeneratorSpi; +import org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator; public class AlgorithmParameterGeneratorSpi extends BaseAlgorithmParameterGeneratorSpi { protected SecureRandom random; + // Android-changed: Change default strength to 1024 + // In 1.57, the default strength was changed to 2048. We keep it at 1024 for app + // compatibility, particularly because the default digest (SHA-1) doesn't have + // a sufficiently long digest to work with 2048-bit keys. protected int strength = 1024; protected DSAParameterGenerationParameters params; @@ -69,19 +74,21 @@ public class AlgorithmParameterGeneratorSpi random = new SecureRandom(); } + int certainty = PrimeCertaintyCalculator.getDefaultCertainty(strength); + if (strength == 1024) { - params = new DSAParameterGenerationParameters(1024, 160, 80, random); + params = new DSAParameterGenerationParameters(1024, 160, certainty, random); pGen.init(params); } else if (strength > 1024) { - params = new DSAParameterGenerationParameters(strength, 256, 80, random); + params = new DSAParameterGenerationParameters(strength, 256, certainty, random); pGen.init(params); } else { - pGen.init(strength, 20, random); + pGen.init(strength, certainty, random); } DSAParameters p = pGen.generateParameters(); 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 bacbb6c2..366e6dca 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 @@ -17,6 +17,7 @@ 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.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator; import org.bouncycastle.util.Integers; import org.bouncycastle.util.Properties; @@ -28,8 +29,12 @@ public class KeyPairGeneratorSpi DSAKeyGenerationParameters param; DSAKeyPairGenerator engine = new DSAKeyPairGenerator(); + // Android-changed: Change default strength to 1024 + // In 1.57, the default strength was changed to 2048. We keep it at 1024 for app + // compatibility, particularly because the default digest (SHA-1) doesn't have + // a sufficiently long digest to work with 2048-bit keys. int strength = 1024; - int certainty = 20; + SecureRandom random = new SecureRandom(); boolean initialised = false; @@ -94,6 +99,8 @@ public class KeyPairGeneratorSpi DSAParametersGenerator pGen; DSAParameterGenerationParameters dsaParams; + int certainty = PrimeCertaintyCalculator.getDefaultCertainty(strength); + // Typical combination of keysize and size of q. // keysize = 1024, q's size = 160 // keysize = 2048, q's size = 224 diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java index adb130e7..4c3089af 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/KeyPairGeneratorSpi.java @@ -12,6 +12,7 @@ import org.bouncycastle.crypto.generators.RSAKeyPairGenerator; import org.bouncycastle.crypto.params.RSAKeyGenerationParameters; import org.bouncycastle.crypto.params.RSAKeyParameters; import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters; +import org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator; public class KeyPairGeneratorSpi extends java.security.KeyPairGenerator @@ -23,7 +24,6 @@ public class KeyPairGeneratorSpi } final static BigInteger defaultPublicExponent = BigInteger.valueOf(0x10001); - final static int defaultTests = 112; RSAKeyGenerationParameters param; RSAKeyPairGenerator engine; @@ -34,7 +34,7 @@ public class KeyPairGeneratorSpi engine = new RSAKeyPairGenerator(); param = new RSAKeyGenerationParameters(defaultPublicExponent, - new SecureRandom(), 2048, defaultTests); + new SecureRandom(), 2048, PrimeCertaintyCalculator.getDefaultCertainty(2048)); engine.init(param); } @@ -44,8 +44,8 @@ public class KeyPairGeneratorSpi { param = new RSAKeyGenerationParameters(defaultPublicExponent, // BEGIN android-changed - // Was: random, strength, defaultTests); - (random != null) ? random : new SecureRandom(), strength, defaultTests); + // Was: random, strength, PrimeCertaintyCalculator.getDefaultCertainty(strength)); + (random != null) ? random : new SecureRandom(), strength, PrimeCertaintyCalculator.getDefaultCertainty(strength)); // END android-changed engine.init(param); @@ -65,8 +65,8 @@ public class KeyPairGeneratorSpi param = new RSAKeyGenerationParameters( rsaParams.getPublicExponent(), // BEGIN android-changed - // Was: random, rsaParams.getKeysize(), defaultTests); - (random != null) ? random : new SecureRandom(), rsaParams.getKeysize(), defaultTests); + // Was: random, rsaParams.getKeysize(), PrimeCertaintyCalculator.getDefaultCertainty(2048)); + (random != null) ? random : new SecureRandom(), rsaParams.getKeysize(), PrimeCertaintyCalculator.getDefaultCertainty(2048)); // END android-changed engine.init(param); 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 6fd4a0dd..cba154a7 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 @@ -11,6 +11,7 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; // BEGIN android-removed // import org.bouncycastle.asn1.anssi.ANSSINamedCurves; // import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; +// import org.bouncycastle.asn1.gm.GMNamedCurves; // END android-removed import org.bouncycastle.asn1.nist.NISTNamedCurves; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; @@ -350,6 +351,10 @@ public class ECUtil // { // oid = ANSSINamedCurves.getOID(name); // } + // if (oid == null) + // { + // oid = GMNamedCurves.getOID(name); + // } // END android-removed } @@ -398,6 +403,10 @@ public class ECUtil // { // params = TeleTrusTNamedCurves.getByOID(oid); // } + // if (params == null) + // { + // params = GMNamedCurves.getByOID(oid); + // } // END android-removed } @@ -425,6 +434,10 @@ public class ECUtil // { // params = TeleTrusTNamedCurves.getByName(curveName); // } + // if (params == null) + // { + // params = GMNamedCurves.getByName(curveName); + // } // END android-removed } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/PrimeCertaintyCalculator.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/PrimeCertaintyCalculator.java new file mode 100644 index 00000000..92431ef4 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/PrimeCertaintyCalculator.java @@ -0,0 +1,21 @@ +package org.bouncycastle.jcajce.provider.asymmetric.util; + +public class PrimeCertaintyCalculator +{ + private PrimeCertaintyCalculator() + { + + } + + /** + * Return the current wisdom on prime certainty requirements. + * + * @param keySizeInBits size of the key being generated. + * @return a certainty value. + */ + public static int getDefaultCertainty(int keySizeInBits) + { + // Based on FIPS 186-4 Table C.1 + return keySizeInBits <= 1024 ? 80 : (96 + 16 * ((keySizeInBits - 1) / 1024)); + } +} 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 f00ee7bd..58310c72 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 @@ -4,7 +4,9 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +// BEGIN Android-added import java.io.PushbackInputStream; +// END Android-added import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.CertPath; @@ -44,6 +46,7 @@ public class CertificateFactory private static final PEMUtil PEM_CERT_PARSER = new PEMUtil("CERTIFICATE"); private static final PEMUtil PEM_CRL_PARSER = new PEMUtil("CRL"); + private static final PEMUtil PEM_PKCS7_PARSER = new PEMUtil("PKCS7"); private ASN1Set sData = null; private int sDataObjectCount = 0; @@ -57,8 +60,24 @@ public class CertificateFactory ASN1InputStream dIn) throws IOException, CertificateParsingException { - ASN1Sequence seq = (ASN1Sequence)dIn.readObject(); + return getCertificate(ASN1Sequence.getInstance(dIn.readObject())); + } + + private java.security.cert.Certificate readPEMCertificate( + InputStream in) + throws IOException, CertificateParsingException + { + return getCertificate(PEM_CERT_PARSER.readPEMObject(in)); + } + private java.security.cert.Certificate getCertificate(ASN1Sequence seq) + throws CertificateParsingException + { + if (seq == null) + { + return null; + } + if (seq.size() > 1 && seq.getObjectAt(0) instanceof ASN1ObjectIdentifier) { @@ -95,23 +114,9 @@ public class CertificateFactory return null; } - private java.security.cert.Certificate readPEMCertificate( - InputStream in) - throws IOException, CertificateParsingException - { - ASN1Sequence seq = PEM_CERT_PARSER.readPEMObject(in); - - if (seq != null) - { - return new X509CertificateObject(bcHelper, - Certificate.getInstance(seq)); - } - - return null; - } protected CRL createCRL(CertificateList c) - throws CRLException + throws CRLException { return new X509CRLObject(bcHelper, c); } @@ -120,23 +125,24 @@ public class CertificateFactory InputStream in) throws IOException, CRLException { - ASN1Sequence seq = PEM_CRL_PARSER.readPEMObject(in); - - if (seq != null) - { - return createCRL( - CertificateList.getInstance(seq)); - } - - return null; + return getCRL(PEM_CRL_PARSER.readPEMObject(in)); } private CRL readDERCRL( ASN1InputStream aIn) throws IOException, CRLException { - ASN1Sequence seq = (ASN1Sequence)aIn.readObject(); + return getCRL(ASN1Sequence.getInstance(aIn.readObject())); + } + private CRL getCRL(ASN1Sequence seq) + throws CRLException + { + if (seq == null) + { + return null; + } + if (seq.size() > 1 && seq.getObjectAt(0) instanceof ASN1ObjectIdentifier) { @@ -144,7 +150,7 @@ public class CertificateFactory { sCrlData = SignedData.getInstance(ASN1Sequence.getInstance( (ASN1TaggedObject)seq.getObjectAt(1), true)).getCRLs(); - + return getCRL(); } } 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 3efd2d69..7badbdc1 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 @@ -10,16 +10,20 @@ class PEMUtil { private final String _header1; private final String _header2; + private final String _header3; private final String _footer1; private final String _footer2; + private final String _footer3; PEMUtil( String type) { _header1 = "-----BEGIN " + type + "-----"; _header2 = "-----BEGIN X509 " + type + "-----"; + _header3 = "-----BEGIN PKCS7-----"; _footer1 = "-----END " + type + "-----"; _footer2 = "-----END X509 " + type + "-----"; + _footer3 = "-----END PKCS7-----"; } private String readLine( @@ -71,7 +75,7 @@ class PEMUtil while ((line = readLine(in)) != null) { - if (line.startsWith(_header1) || line.startsWith(_header2)) + if (line.startsWith(_header1) || line.startsWith(_header2) || line.startsWith(_header3)) { break; } @@ -79,7 +83,7 @@ class PEMUtil while ((line = readLine(in)) != null) { - if (line.startsWith(_footer1) || line.startsWith(_footer2)) + if (line.startsWith(_footer1) || line.startsWith(_footer2) || line.startsWith(_footer3)) { break; } 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 0865b576..768df66e 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 @@ -1,5 +1,7 @@ package org.bouncycastle.jcajce.provider.config; +import java.util.Map; + import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; @@ -48,4 +50,6 @@ public interface ConfigurableProvider boolean hasAlgorithm(String type, String name); void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter); + + void addAttributes(String key, Map<String, String> attributeMap); } 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 ed7342d8..f118e5c8 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 @@ -11,6 +11,8 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; +import java.util.HashMap; +import java.util.Map; import javax.crypto.spec.IvParameterSpec; @@ -33,6 +35,7 @@ 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.AESWrapPadEngine; // import org.bouncycastle.crypto.engines.RFC3211WrapEngine; // import org.bouncycastle.crypto.engines.RFC5649WrapEngine; // import org.bouncycastle.crypto.generators.Poly1305KeyGenerator; @@ -67,6 +70,14 @@ public final class AES { private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec"); + private static final Map<String, String> generalAesAttributes = new HashMap<String, String>(); + + static + { + generalAesAttributes.put("SupportedKeyClasses", "javax.crypto.SecretKey"); + generalAesAttributes.put("SupportedKeyFormats", "RAW"); + } + private AES() { } @@ -262,6 +273,15 @@ public final class AES } // BEGIN android-removed + // public static class WrapPad + // extends BaseWrapCipher + // { + // public WrapPad() + // { + // super(new AESWrapPadEngine()); + // } + // } + // public static class RFC3211Wrap // extends BaseWrapCipher // { @@ -852,6 +872,7 @@ public final class AES // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_CBC, "AES"); // END android-removed + provider.addAttributes("Cipher.AES", generalAesAttributes); provider.addAlgorithm("Cipher.AES", PREFIX + "$ECB"); provider.addAlgorithm("Alg.Alias.Cipher." + wrongAES128, "AES"); provider.addAlgorithm("Alg.Alias.Cipher." + wrongAES192, "AES"); @@ -870,6 +891,8 @@ public final class AES // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes192_CFB, PREFIX + "$CFB"); // provider.addAlgorithm("Cipher", NISTObjectIdentifiers.id_aes256_CFB, PREFIX + "$CFB"); // END android-removed + + provider.addAttributes("Cipher.AESWRAP", generalAesAttributes); provider.addAlgorithm("Cipher.AESWRAP", PREFIX + "$Wrap"); provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes128_wrap, "AESWRAP"); provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes192_wrap, "AESWRAP"); @@ -877,6 +900,13 @@ public final class AES provider.addAlgorithm("Alg.Alias.Cipher.AESKW", "AESWRAP"); // BEGIN android-removed + // provider.addAttributes("Cipher.AESWRAPPAD", generalAesAttributes); + // provider.addAlgorithm("Cipher.AESWRAPPAD", PREFIX + "$WrapPad"); + // provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes128_wrap_pad, "AESWRAPPAD"); + // provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes192_wrap_pad, "AESWRAPPAD"); + // provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes256_wrap_pad, "AESWRAPPAD"); + // provider.addAlgorithm("Alg.Alias.Cipher.AESKWP", "AESWRAPPAD"); + // // provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap"); // provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap"); // @@ -885,6 +915,7 @@ public final class AES // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_CCM, "CCM"); // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_CCM, "CCM"); // + // provider.addAttributes("Cipher.CCM", generalAesAttributes); // provider.addAlgorithm("Cipher.CCM", PREFIX + "$CCM"); // provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes128_CCM, "CCM"); // provider.addAlgorithm("Alg.Alias.Cipher", NISTObjectIdentifiers.id_aes192_CCM, "CCM"); @@ -897,6 +928,7 @@ public final class AES // END android-removed // BEGIN android-changed + provider.addAttributes("Cipher.AES/GCM/NOPADDING", generalAesAttributes); provider.addAlgorithm("Cipher.AES/GCM/NOPADDING", PREFIX + "$GCM"); provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_GCM, "AES/GCM/NOPADDING"); provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes192_GCM, "AES/GCM/NOPADDING"); @@ -930,6 +962,10 @@ 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("KeyGenerator.AESWRAPPAD", PREFIX + "$KeyGen"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes128_wrap_pad, PREFIX + "$KeyGen128"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes192_wrap_pad, PREFIX + "$KeyGen192"); + // provider.addAlgorithm("KeyGenerator", NISTObjectIdentifiers.id_aes256_wrap_pad, PREFIX + "$KeyGen256"); // provider.addAlgorithm("Mac.AESCMAC", PREFIX + "$AESCMAC"); 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 51c29d96..7102db50 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 @@ -18,6 +18,7 @@ import javax.crypto.spec.RC2ParameterSpec; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Mac; +import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.AEADParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; @@ -39,8 +40,8 @@ public class BaseMac private Mac macEngine; private int scheme = PKCS12; - private int pbeHash = SHA1; - private int keySize = 160; + private int pbeHash = SHA1; + private int keySize = 160; protected BaseMac( Mac macEngine) @@ -109,12 +110,44 @@ public class BaseMac // keySize = 256; // } // BEGIN android-changed - // Was: else if (macEngine.getAlgorithmName().startsWith("SHA256")) - if (macEngine.getAlgorithmName().startsWith("SHA256")) + // Was: else if (macEngine instanceof HMac) + if (macEngine instanceof HMac) // END android-changed { - digest = SHA256; - keySize = 256; + if (!macEngine.getAlgorithmName().startsWith("SHA-1")) + { + if (macEngine.getAlgorithmName().startsWith("SHA-224")) + { + digest = SHA224; + keySize = 224; + } + else if (macEngine.getAlgorithmName().startsWith("SHA-256")) + { + digest = SHA256; + keySize = 256; + } + else if (macEngine.getAlgorithmName().startsWith("SHA-384")) + { + digest = SHA384; + keySize = 384; + } + else if (macEngine.getAlgorithmName().startsWith("SHA-512")) + { + digest = SHA512; + keySize = 512; + } + // BEGIN android-removed + // else if (macEngine.getAlgorithmName().startsWith("RIPEMD160")) + // { + // digest = RIPEMD160; + // keySize = 160; + // } + // END android-removed + else + { + throw new InvalidAlgorithmParameterException("no PKCS12 mapping for HMAC: " + macEngine.getAlgorithmName()); + } + } } // TODO: add correct handling for other digests param = PBE.Util.makePBEMacParameters(k, PKCS12, digest, keySize, pbeSpec); diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java index ea3ac5b0..f2893080 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java @@ -5,6 +5,7 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.Key; +import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; @@ -123,10 +124,11 @@ public class BaseStreamCipher */ protected void engineSetMode( String mode) + throws NoSuchAlgorithmException { if (!mode.equalsIgnoreCase("ECB")) { - throw new IllegalArgumentException("can't support mode " + mode); + throw new NoSuchAlgorithmException("can't support mode " + mode); } } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java index c4010844..448c3527 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/util/AsymmetricAlgorithmProvider.java @@ -36,6 +36,11 @@ public abstract class AsymmetricAlgorithmProvider protected void registerOidAlgorithmParameters(ConfigurableProvider provider, ASN1ObjectIdentifier oid, String name) { + provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + oid, name); + } + + protected void registerOidAlgorithmParameterGenerator(ConfigurableProvider provider, ASN1ObjectIdentifier oid, String name) + { provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + oid, name); provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + oid, name); } 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 6a7c9e62..5cb5d526 100644 --- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java +++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java @@ -7,6 +7,7 @@ import java.security.PrivilegedAction; import java.security.Provider; import java.security.PublicKey; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import org.bouncycastle.asn1.ASN1ObjectIdentifier; @@ -44,7 +45,7 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; public final class BouncyCastleProvider extends Provider implements ConfigurableProvider { - private static String info = "BouncyCastle Security Provider v1.56"; + private static String info = "BouncyCastle Security Provider v1.57"; public static final String PROVIDER_NAME = "BC"; @@ -74,7 +75,7 @@ public final class BouncyCastleProvider extends Provider private static final String[] SYMMETRIC_CIPHERS = { // BEGIN android-removed - // "AES", "ARC4", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede", + // "AES", "ARC4", "ARIA", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede", // "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5", // "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "SM4", "TEA", "Twofish", "Threefish", // "VMPC", "VMPCKSA3", "XTEA", "XSalsa20", "OpenSSLPBKDF" @@ -104,7 +105,7 @@ public final class BouncyCastleProvider extends Provider private static final String[] ASYMMETRIC_CIPHERS = { // BEGIN android-removed - // "DSA", "DH", "EC", "RSA", "GOST", "ECGOST", "ElGamal", "DSTU4145" + // "DSA", "DH", "EC", "RSA", "GOST", "ECGOST", "ElGamal", "DSTU4145", "GM" // END android-removed // BEGIN android-added "DSA", "DH", "EC", "RSA", @@ -152,7 +153,7 @@ public final class BouncyCastleProvider extends Provider */ public BouncyCastleProvider() { - super(PROVIDER_NAME, 1.56, info); + super(PROVIDER_NAME, 1.57, info); AccessController.doPrivileged(new PrivilegedAction() { @@ -305,6 +306,21 @@ public final class BouncyCastleProvider extends Provider } } + public void addAttributes(String key, Map<String, String> attributeMap) + { + for (Iterator it = attributeMap.keySet().iterator(); it.hasNext();) + { + String attributeName = (String)it.next(); + String attributeKey = key + " " + attributeName; + if (containsKey(attributeKey)) + { + throw new IllegalStateException("duplicate provider attribute key (" + attributeKey + ") found"); + } + + put(attributeKey, attributeMap.get(attributeName)); + } + } + private static AsymmetricKeyInfoConverter getAsymmetricKeyInfoConverter(ASN1ObjectIdentifier algorithm) { synchronized (keyInfoConverters) diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java index 9fe00b9b..c91de7b1 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointCombMultiplier.java @@ -47,7 +47,7 @@ public class FixedPointCombMultiplier extends AbstractECMultiplier R = R.twicePlus(lookupTable[index]); } - return R; + return R.add(info.getOffset()); } protected int getWidthForCombSize(int combSize) diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java index b7569aae..31f5d101 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointPreCompInfo.java @@ -5,6 +5,8 @@ package org.bouncycastle.math.ec; */ public class FixedPointPreCompInfo implements PreCompInfo { + protected ECPoint offset = null; + /** * Array holding the precomputed <code>ECPoint</code>s used for a fixed * point multiplication. @@ -18,6 +20,16 @@ public class FixedPointPreCompInfo implements PreCompInfo */ protected int width = -1; + public ECPoint getOffset() + { + return offset; + } + + public void setOffset(ECPoint offset) + { + this.offset = offset; + } + public ECPoint[] getPreComp() { return preComp; diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java index e4fbb8d0..93b435c5 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java +++ b/bcprov/src/main/java/org/bouncycastle/math/ec/FixedPointUtil.java @@ -35,18 +35,21 @@ public class FixedPointUtil int bits = getCombSize(c); int d = (bits + minWidth - 1) / minWidth; - ECPoint[] pow2Table = new ECPoint[minWidth]; + ECPoint[] pow2Table = new ECPoint[minWidth + 1]; pow2Table[0] = p; for (int i = 1; i < minWidth; ++i) { pow2Table[i] = pow2Table[i - 1].timesPow2(d); } - + + // This will be the 'offset' value + pow2Table[minWidth] = pow2Table[0].subtract(pow2Table[1]); + c.normalizeAll(pow2Table); - + lookupTable = new ECPoint[n]; - lookupTable[0] = c.getInfinity(); - + lookupTable[0] = pow2Table[0]; + for (int bit = minWidth - 1; bit >= 0; --bit) { ECPoint pow2 = pow2Table[bit]; @@ -60,6 +63,7 @@ public class FixedPointUtil c.normalizeAll(lookupTable); + info.setOffset(pow2Table[minWidth]); info.setPreComp(lookupTable); info.setWidth(minWidth); diff --git a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java index 2057c8bc..6b77f8fa 100644 --- a/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java +++ b/bcprov/src/main/java/org/bouncycastle/math/raw/Nat.java @@ -1075,4 +1075,12 @@ public abstract class Nat z[i] = 0; } } + + public static void zero64(int len, long[] z) + { + for (int i = 0; i < len; ++i) + { + z[i] = 0L; + } + } } diff --git a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java index ae609280..6873117a 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java @@ -944,6 +944,22 @@ public final class Arrays return result; } + public static String[] append(String[] a, String b) + { + if (a == null) + { + return new String[]{ b }; + } + + int length = a.length; + String[] result = new String[length + 1]; + System.arraycopy(a, 0, result, 0, length); + result[length] = b; + return result; + } + + + public static byte[] concatenate(byte[] a, byte[] b) { if (a != null && b != null) diff --git a/bcprov/src/main/java/org/bouncycastle/util/Properties.java b/bcprov/src/main/java/org/bouncycastle/util/Properties.java index 96cef357..e533b586 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/Properties.java +++ b/bcprov/src/main/java/org/bouncycastle/util/Properties.java @@ -3,6 +3,10 @@ package org.bouncycastle.util; import java.security.AccessControlException; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.StringTokenizer; /** * Utility method for accessing system properties. @@ -33,4 +37,19 @@ public class Properties return false; } } + + public static Set<String> asKeySet(final String propertyName) + { + Set<String> set = new HashSet<String>(); + String p = System.getProperty(propertyName); + if (p != null) + { + StringTokenizer sTok = new StringTokenizer(p, ","); + while (sTok.hasMoreElements()) + { + set.add(Strings.toLowerCase(sTok.nextToken()).trim()); + } + } + return Collections.unmodifiableSet(set); + } } diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java index c04a8cc1..e3129f0f 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java +++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64.java @@ -12,7 +12,7 @@ import org.bouncycastle.util.Strings; public class Base64 { private static final Encoder encoder = new Base64Encoder(); - + public static String toBase64String( byte[] data) { @@ -21,8 +21,8 @@ public class Base64 public static String toBase64String( byte[] data, - int off, - int length) + int off, + int length) { byte[] encoded = encode(data, off, length); return Strings.fromByteArray(encoded); @@ -34,7 +34,7 @@ public class Base64 * @return a byte array containing the base 64 encoded data. */ public static byte[] encode( - byte[] data) + byte[] data) { return encode(data, 0, data.length); } @@ -46,8 +46,8 @@ public class Base64 */ public static byte[] encode( byte[] data, - int off, - int length) + int off, + int length) { int len = (length + 2) / 3 * 4; ByteArrayOutputStream bOut = new ByteArrayOutputStream(len); @@ -60,7 +60,7 @@ public class Base64 { throw new EncoderException("exception encoding base64 string: " + e.getMessage(), e); } - + return bOut.toByteArray(); } @@ -70,39 +70,39 @@ public class Base64 * @return the number of bytes produced. */ public static int encode( - byte[] data, - OutputStream out) + byte[] data, + OutputStream out) throws IOException { return encoder.encode(data, 0, data.length, out); } - + /** * Encode the byte data to base 64 writing it to the given output stream. * * @return the number of bytes produced. */ public static int encode( - byte[] data, - int off, - int length, - OutputStream out) + byte[] data, + int off, + int length, + OutputStream out) throws IOException { return encoder.encode(data, off, length, out); } - + /** * decode the base 64 encoded input data. It is assumed the input data is valid. * * @return a byte array representing the decoded data. */ public static byte[] decode( - byte[] data) + byte[] data) { int len = data.length / 4 * 3; ByteArrayOutputStream bOut = new ByteArrayOutputStream(len); - + try { encoder.decode(data, 0, data.length, bOut); @@ -111,21 +111,21 @@ public class Base64 { throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e); } - + return bOut.toByteArray(); } - + /** * decode the base 64 encoded String data - whitespace will be ignored. * * @return a byte array representing the decoded data. */ public static byte[] decode( - String data) + String data) { int len = data.length() / 4 * 3; ByteArrayOutputStream bOut = new ByteArrayOutputStream(len); - + try { encoder.decode(data, bOut); @@ -134,10 +134,10 @@ public class Base64 { throw new DecoderException("unable to decode base64 string: " + e.getMessage(), e); } - + return bOut.toByteArray(); } - + /** * decode the base 64 encoded String data writing it to the given output stream, * whitespace characters will be ignored. @@ -145,10 +145,31 @@ public class Base64 * @return the number of bytes produced. */ public static int decode( - String data, - OutputStream out) + String data, + OutputStream out) throws IOException { return encoder.decode(data, out); } + + /** + * Decode to an output stream; + * + * @param base64Data The source data. + * @param start Start position. + * @param length the length. + * @param out The output stream to write to. + */ + public static int decode(byte[] base64Data, int start, int length, OutputStream out) + { + try + { + return encoder.decode(base64Data, start, length, out); + } + catch (Exception e) + { + throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e); + } + + } } diff --git a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java index abad02c5..4216674a 100644 --- a/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java +++ b/bcprov/src/main/java/org/bouncycastle/util/encoders/Base64Encoder.java @@ -272,6 +272,11 @@ public class Base64Encoder if (c3 == padding) { + if (c4 != padding) + { + throw new IOException("invalid characters encountered at end of base64 data"); + } + b1 = decodingTable[c1]; b2 = decodingTable[c2]; diff --git a/bcprov/src/main/java/org/bouncycastle/util/io/SimpleOutputStream.java b/bcprov/src/main/java/org/bouncycastle/util/io/SimpleOutputStream.java new file mode 100644 index 00000000..af2f45f7 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/util/io/SimpleOutputStream.java @@ -0,0 +1,21 @@ +package org.bouncycastle.util.io; + +import java.io.IOException; +import java.io.OutputStream; + +public abstract class SimpleOutputStream extends OutputStream +{ + public void close() + { + } + + public void flush() + { + } + + public void write(int b) throws IOException + { + byte[] buf = new byte[]{ (byte)b }; + write(buf, 0, 1); + } +} diff --git a/bouncycastle.version b/bouncycastle.version index c7e252d8..e258c891 100644 --- a/bouncycastle.version +++ b/bouncycastle.version @@ -1,2 +1,2 @@ BOUNCYCASTLE_JDK=15on -BOUNCYCASTLE_VERSION=156 +BOUNCYCASTLE_VERSION=157 |