summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric
diff options
context:
space:
mode:
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/DH.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/EC.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParameterGeneratorSpi.java47
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java14
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java1
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java29
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DHUtil.java (renamed from bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/DHUtil.java)2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java (renamed from bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/EC5Util.java)2
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java (renamed from bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtil.java)3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/CertificateFactory.java4
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/ExtCRLException.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java301
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java578
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java916
-rw-r--r--bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java144
20 files changed, 2036 insertions, 35 deletions
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 ba7dd80..28a1a6a 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
@@ -37,7 +37,6 @@ public class DH
// provider.addAlgorithm("Cipher.DHIESwithAES", PREFIX + "IESCipher$IESwithAES");
// provider.addAlgorithm("Cipher.DHIESWITHAES", PREFIX + "IESCipher$IESwithAES");
// provider.addAlgorithm("Cipher.DHIESWITHDESEDE", PREFIX + "IESCipher$IESwithDESede");
- // provider.addAlgorithm("KeyPairGenerator.IES", PREFIX + "KeyPairGeneratorSpi");
// END android-removed
}
}
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 8f93a68..8d50a54 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
@@ -99,6 +99,8 @@ public class EC
// addSignatureAlgorithm(provider, "SHA1", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1);
// addSignatureAlgorithm(provider, "SHA224", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA224", EACObjectIdentifiers.id_TA_ECDSA_SHA_224);
// addSignatureAlgorithm(provider, "SHA256", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA256", EACObjectIdentifiers.id_TA_ECDSA_SHA_256);
+ // addSignatureAlgorithm(provider, "SHA384", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA384", EACObjectIdentifiers.id_TA_ECDSA_SHA_384);
+ // addSignatureAlgorithm(provider, "SHA512", "CVC-ECDSA", PREFIX + "SignatureSpi$ecCVCDSA512", EACObjectIdentifiers.id_TA_ECDSA_SHA_512);
// END android-removed
}
}
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 2e5ee56..d850e5d 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
@@ -7,25 +7,36 @@ import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
+import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.generators.DSAParametersGenerator;
+import org.bouncycastle.crypto.params.DSAParameterGenerationParameters;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-//import org.bouncycastle.jce.spec.GOST3410ParameterSpec;
-//import org.bouncycastle.jce.spec.GOST3410PublicKeyParameterSetSpec;
public class AlgorithmParameterGeneratorSpi
extends java.security.AlgorithmParameterGeneratorSpi
{
protected SecureRandom random;
protected int strength = 1024;
+ protected DSAParameterGenerationParameters params;
protected void engineInit(
int strength,
SecureRandom random)
{
- if (strength < 512 || strength > 1024 || strength % 64 != 0)
+ if (strength < 512 || strength > 3072)
{
- throw new InvalidParameterException("strength must be from 512 - 1024 and a multiple of 64");
+ throw new InvalidParameterException("strength must be from 512 - 3072");
+ }
+
+ if (strength <= 1024 && strength % 64 != 0)
+ {
+ throw new InvalidParameterException("strength must be a multiple of 64 below 1024 bits.");
+ }
+
+ if (strength > 1024 && strength % 1024 != 0)
+ {
+ throw new InvalidParameterException("strength must be a multiple of 1024 above 1024 bits.");
}
this.strength = strength;
@@ -42,15 +53,35 @@ public class AlgorithmParameterGeneratorSpi
protected AlgorithmParameters engineGenerateParameters()
{
- DSAParametersGenerator pGen = new DSAParametersGenerator();
+ DSAParametersGenerator pGen;
- if (random != null)
+ if (strength <= 1024)
{
- pGen.init(strength, 20, random);
+ pGen = new DSAParametersGenerator();
}
else
{
- pGen.init(strength, 20, new SecureRandom());
+ pGen = new DSAParametersGenerator(new SHA256Digest());
+ }
+
+ if (random == null)
+ {
+ random = new SecureRandom();
+ }
+
+ if (strength == 1024)
+ {
+ params = new DSAParameterGenerationParameters(1024, 160, 80, random);
+ pGen.init(params);
+ }
+ else if (strength > 1024)
+ {
+ params = new DSAParameterGenerationParameters(strength, 256, 80, random);
+ pGen.init(params);
+ }
+ else
+ {
+ pGen.init(strength, 20, random);
}
DSAParameters p = pGen.generateParameters();
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java
index 1ddb815..61fa33c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dsa/AlgorithmParametersSpi.java
@@ -7,7 +7,6 @@ import java.security.spec.InvalidParameterSpecException;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Primitive;
-import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.x509.DSAParameter;
public class AlgorithmParametersSpi
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 d9d5857..c8b326f 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
@@ -57,11 +57,6 @@ public class DSASigner
{
CipherParameters param;
-// if (publicKey instanceof GOST3410Key)
-// {
-// param = GOST3410Util.generatePublicKeyParameter(publicKey);
-// }
-// else if (publicKey instanceof DSAKey)
if (publicKey instanceof DSAKey)
{
param = DSAUtil.generatePublicKeyParameter(publicKey);
@@ -108,14 +103,7 @@ public class DSASigner
{
CipherParameters param;
-// if (privateKey instanceof GOST3410Key)
-// {
-// param = GOST3410Util.generatePrivateKeyParameter(privateKey);
-// }
-// else
-// {
- param = DSAUtil.generatePrivateKeyParameter(privateKey);
-// }
+ param = DSAUtil.generatePrivateKeyParameter(privateKey);
if (random != null)
{
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 f34f482..3d64c83 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
@@ -31,6 +31,8 @@ import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
+import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jce.interfaces.ECPointEncoder;
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 14cc9dc..2b61727 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
@@ -26,6 +26,8 @@ import org.bouncycastle.asn1.x9.X9IntegerConverter;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
+import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jce.interfaces.ECPointEncoder;
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 cade228..35a804c 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
@@ -37,6 +37,7 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
// import org.bouncycastle.crypto.params.MQVPrivateParameters;
// import org.bouncycastle.crypto.params.MQVPublicParameters;
// END android-removed
+import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;
// BEGIN 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 156b1d0..5769bac 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
@@ -15,6 +15,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.EC5Util;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
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 4cbefb6..c0c825c 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
@@ -23,6 +23,7 @@ import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
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 86a407c..c6b4bce 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
@@ -8,9 +8,9 @@ import java.security.PublicKey;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DSA;
@@ -34,6 +34,7 @@ import org.bouncycastle.crypto.signers.ECDSASigner;
// 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;
public class SignatureSpi
extends DSABase
@@ -215,6 +216,24 @@ public class SignatureSpi
// super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder());
// }
// }
+ //
+ // static public class ecCVCDSA384
+ // extends SignatureSpi
+ // {
+ // public ecCVCDSA384()
+ // {
+ // super(new SHA384Digest(), new ECDSASigner(), new CVCDSAEncoder());
+ // }
+ // }
+ //
+ // static public class ecCVCDSA512
+ // extends SignatureSpi
+ // {
+ // public ecCVCDSA512()
+ // {
+ // super(new SHA512Digest(), new ECDSASigner(), new CVCDSAEncoder());
+ // }
+ // }
// END android-removed
private static class StdDSAEncoder
@@ -227,8 +246,8 @@ public class SignatureSpi
{
ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(new DERInteger(r));
- v.add(new DERInteger(s));
+ v.add(new ASN1Integer(r));
+ v.add(new ASN1Integer(s));
return new DERSequence(v).getEncoded(ASN1Encoding.DER);
}
@@ -240,8 +259,8 @@ public class SignatureSpi
ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
BigInteger[] sig = new BigInteger[2];
- sig[0] = ((DERInteger)s.getObjectAt(0)).getValue();
- sig[1] = ((DERInteger)s.getObjectAt(1)).getValue();
+ sig[0] = ASN1Integer.getInstance(s.getObjectAt(0)).getValue();
+ sig[1] = ASN1Integer.getInstance(s.getObjectAt(1)).getValue();
return sig;
}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/DHUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DHUtil.java
index 4bd7805..52c84ec 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/dh/DHUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/DHUtil.java
@@ -1,4 +1,4 @@
-package org.bouncycastle.jcajce.provider.asymmetric.dh;
+package org.bouncycastle.jcajce.provider.asymmetric.util;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/EC5Util.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java
index 38025e7..d4065ac 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/EC5Util.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/EC5Util.java
@@ -1,4 +1,4 @@
-package org.bouncycastle.jcajce.provider.asymmetric.ec;
+package org.bouncycastle.jcajce.provider.asymmetric.util;
import java.math.BigInteger;
import java.security.spec.ECField;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
index 820bf4b..442b340 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/ECUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
@@ -1,4 +1,4 @@
-package org.bouncycastle.jcajce.provider.asymmetric.ec;
+package org.bouncycastle.jcajce.provider.asymmetric.util;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
@@ -21,6 +21,7 @@ import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
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 5b79864..03a1fe8 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
@@ -24,8 +24,6 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.SignedData;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.CertificateList;
-import org.bouncycastle.jce.provider.X509CRLObject;
-import org.bouncycastle.jce.provider.X509CertificateObject;
/**
* class for dealing with X509 certificates.
@@ -334,9 +332,7 @@ public class CertificateFactory
public Iterator engineGetCertPathEncodings()
{
- // BEGIN android-changed
return PKIXCertPath.certPathEncodings.iterator();
- // END android-changed
}
public CertPath engineGenerateCertPath(
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/ExtCRLException.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/ExtCRLException.java
new file mode 100644
index 0000000..e27acfb
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/ExtCRLException.java
@@ -0,0 +1,20 @@
+package org.bouncycastle.jcajce.provider.asymmetric.x509;
+
+import java.security.cert.CRLException;
+
+class ExtCRLException
+ extends CRLException
+{
+ Throwable cause;
+
+ ExtCRLException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java
new file mode 100644
index 0000000..1888328
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLEntryObject.java
@@ -0,0 +1,301 @@
+package org.bouncycastle.jcajce.provider.asymmetric.x509;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CRLException;
+import java.security.cert.X509CRLEntry;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1Enumerated;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.util.ASN1Dump;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.CRLReason;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.TBSCertList;
+import org.bouncycastle.asn1.x509.X509Extension;
+
+/**
+ * The following extensions are listed in RFC 2459 as relevant to CRL Entries
+ *
+ * ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
+ * (critical)
+ */
+class X509CRLEntryObject extends X509CRLEntry
+{
+ private TBSCertList.CRLEntry c;
+
+ private X500Name certificateIssuer;
+ private int hashValue;
+ private boolean isHashValueSet;
+
+ public X509CRLEntryObject(TBSCertList.CRLEntry c)
+ {
+ this.c = c;
+ this.certificateIssuer = null;
+ }
+
+ /**
+ * Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code>
+ * is <code>false</code> {@link #getCertificateIssuer()} will always
+ * return <code>null</code>, <code>previousCertificateIssuer</code> is
+ * ignored. If this <code>isIndirect</code> is specified and this CRLEntry
+ * has no certificate issuer CRL entry extension
+ * <code>previousCertificateIssuer</code> is returned by
+ * {@link #getCertificateIssuer()}.
+ *
+ * @param c
+ * TBSCertList.CRLEntry object.
+ * @param isIndirect
+ * <code>true</code> if the corresponding CRL is a indirect
+ * CRL.
+ * @param previousCertificateIssuer
+ * Certificate issuer of the previous CRLEntry.
+ */
+ public X509CRLEntryObject(
+ TBSCertList.CRLEntry c,
+ boolean isIndirect,
+ X500Name previousCertificateIssuer)
+ {
+ this.c = c;
+ this.certificateIssuer = loadCertificateIssuer(isIndirect, previousCertificateIssuer);
+ }
+
+ /**
+ * Will return true if any extensions are present and marked as critical as
+ * we currently don't handle any extensions!
+ */
+ public boolean hasUnsupportedCriticalExtension()
+ {
+ Set extns = getCriticalExtensionOIDs();
+
+ return extns != null && !extns.isEmpty();
+ }
+
+ private X500Name loadCertificateIssuer(boolean isIndirect, X500Name previousCertificateIssuer)
+ {
+ if (!isIndirect)
+ {
+ return null;
+ }
+
+ Extension ext = getExtension(Extension.certificateIssuer);
+ if (ext == null)
+ {
+ return previousCertificateIssuer;
+ }
+
+ try
+ {
+ GeneralName[] names = GeneralNames.getInstance(ext.getParsedValue()).getNames();
+ for (int i = 0; i < names.length; i++)
+ {
+ if (names[i].getTagNo() == GeneralName.directoryName)
+ {
+ return X500Name.getInstance(names[i].getName());
+ }
+ }
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public X500Principal getCertificateIssuer()
+ {
+ if (certificateIssuer == null)
+ {
+ return null;
+ }
+ try
+ {
+ return new X500Principal(certificateIssuer.getEncoded());
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+
+ private Set getExtensionOIDs(boolean critical)
+ {
+ Extensions extensions = c.getExtensions();
+
+ if (extensions != null)
+ {
+ Set set = new HashSet();
+ Enumeration e = extensions.oids();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) e.nextElement();
+ Extension ext = extensions.getExtension(oid);
+
+ if (critical == ext.isCritical())
+ {
+ set.add(oid.getId());
+ }
+ }
+
+ return set;
+ }
+
+ return null;
+ }
+
+ public Set getCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(true);
+ }
+
+ public Set getNonCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(false);
+ }
+
+ private Extension getExtension(ASN1ObjectIdentifier oid)
+ {
+ Extensions exts = c.getExtensions();
+
+ if (exts != null)
+ {
+ return exts.getExtension(oid);
+ }
+
+ return null;
+ }
+
+ public byte[] getExtensionValue(String oid)
+ {
+ Extension ext = getExtension(new ASN1ObjectIdentifier(oid));
+
+ if (ext != null)
+ {
+ try
+ {
+ return ext.getExtnValue().getEncoded();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("error encoding " + e.toString());
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Cache the hashCode value - calculating it with the standard method.
+ * @return calculated hashCode.
+ */
+ public int hashCode()
+ {
+ if (!isHashValueSet)
+ {
+ hashValue = super.hashCode();
+ isHashValueSet = true;
+ }
+
+ return hashValue;
+ }
+
+ public byte[] getEncoded()
+ throws CRLException
+ {
+ try
+ {
+ return c.getEncoded(ASN1Encoding.DER);
+ }
+ catch (IOException e)
+ {
+ throw new CRLException(e.toString());
+ }
+ }
+
+ public BigInteger getSerialNumber()
+ {
+ return c.getUserCertificate().getValue();
+ }
+
+ public Date getRevocationDate()
+ {
+ return c.getRevocationDate().getDate();
+ }
+
+ public boolean hasExtensions()
+ {
+ return c.getExtensions() != null;
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = System.getProperty("line.separator");
+
+ buf.append(" userCertificate: ").append(this.getSerialNumber()).append(nl);
+ buf.append(" revocationDate: ").append(this.getRevocationDate()).append(nl);
+ buf.append(" certificateIssuer: ").append(this.getCertificateIssuer()).append(nl);
+
+ Extensions extensions = c.getExtensions();
+
+ if (extensions != null)
+ {
+ Enumeration e = extensions.oids();
+ if (e.hasMoreElements())
+ {
+ buf.append(" crlEntryExtensions:").append(nl);
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ Extension ext = extensions.getExtension(oid);
+ if (ext.getExtnValue() != null)
+ {
+ byte[] octs = ext.getExtnValue().getOctets();
+ ASN1InputStream dIn = new ASN1InputStream(octs);
+ buf.append(" critical(").append(ext.isCritical()).append(") ");
+ try
+ {
+ if (oid.equals(X509Extension.reasonCode))
+ {
+ buf.append(CRLReason.getInstance(ASN1Enumerated.getInstance(dIn.readObject()))).append(nl);
+ }
+ else if (oid.equals(X509Extension.certificateIssuer))
+ {
+ buf.append("Certificate issuer: ").append(GeneralNames.getInstance(dIn.readObject())).append(nl);
+ }
+ else
+ {
+ buf.append(oid.getId());
+ buf.append(" value = ").append(ASN1Dump.dumpAsString(dIn.readObject())).append(nl);
+ }
+ }
+ catch (Exception ex)
+ {
+ buf.append(oid.getId());
+ buf.append(" value = ").append("*****").append(nl);
+ }
+ }
+ else
+ {
+ buf.append(nl);
+ }
+ }
+ }
+ }
+
+ return buf.toString();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java
new file mode 100644
index 0000000..2fc0826
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CRLObject.java
@@ -0,0 +1,578 @@
+package org.bouncycastle.jcajce.provider.asymmetric.x509;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.CRLException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509CRLEntry;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.util.ASN1Dump;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.CRLDistPoint;
+import org.bouncycastle.asn1.x509.CRLNumber;
+import org.bouncycastle.asn1.x509.CertificateList;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
+import org.bouncycastle.asn1.x509.TBSCertList;
+import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.provider.RFC3280CertPathUtilities;
+import org.bouncycastle.util.encoders.Hex;
+
+/**
+ * The following extensions are listed in RFC 2459 as relevant to CRLs
+ *
+ * Authority Key Identifier
+ * Issuer Alternative Name
+ * CRL Number
+ * Delta CRL Indicator (critical)
+ * Issuing Distribution Point (critical)
+ */
+class X509CRLObject
+ extends X509CRL
+{
+ private CertificateList c;
+ private String sigAlgName;
+ private byte[] sigAlgParams;
+ private boolean isIndirect;
+
+ static boolean isIndirectCRL(X509CRL crl)
+ throws CRLException
+ {
+ try
+ {
+ byte[] idp = crl.getExtensionValue(Extension.issuingDistributionPoint.getId());
+ return idp != null
+ && IssuingDistributionPoint.getInstance(ASN1OctetString.getInstance(idp).getOctets()).isIndirectCRL();
+ }
+ catch (Exception e)
+ {
+ throw new ExtCRLException(
+ "Exception reading IssuingDistributionPoint", e);
+ }
+ }
+
+ public X509CRLObject(
+ CertificateList c)
+ throws CRLException
+ {
+ this.c = c;
+
+ try
+ {
+ this.sigAlgName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm());
+
+ if (c.getSignatureAlgorithm().getParameters() != null)
+ {
+ this.sigAlgParams = ((ASN1Encodable)c.getSignatureAlgorithm().getParameters()).toASN1Primitive().getEncoded(ASN1Encoding.DER);
+ }
+ else
+ {
+ this.sigAlgParams = null;
+ }
+
+ this.isIndirect = isIndirectCRL(this);
+ }
+ catch (Exception e)
+ {
+ throw new CRLException("CRL contents invalid: " + e);
+ }
+ }
+
+ /**
+ * Will return true if any extensions are present and marked
+ * as critical as we currently dont handle any extensions!
+ */
+ public boolean hasUnsupportedCriticalExtension()
+ {
+ Set extns = getCriticalExtensionOIDs();
+
+ if (extns == null)
+ {
+ return false;
+ }
+
+ extns.remove(RFC3280CertPathUtilities.ISSUING_DISTRIBUTION_POINT);
+ extns.remove(RFC3280CertPathUtilities.DELTA_CRL_INDICATOR);
+
+ return !extns.isEmpty();
+ }
+
+ private Set getExtensionOIDs(boolean critical)
+ {
+ if (this.getVersion() == 2)
+ {
+ Extensions extensions = c.getTBSCertList().getExtensions();
+
+ if (extensions != null)
+ {
+ Set set = new HashSet();
+ Enumeration e = extensions.oids();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ Extension ext = extensions.getExtension(oid);
+
+ if (critical == ext.isCritical())
+ {
+ set.add(oid.getId());
+ }
+ }
+
+ return set;
+ }
+ }
+
+ return null;
+ }
+
+ public Set getCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(true);
+ }
+
+ public Set getNonCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(false);
+ }
+
+ public byte[] getExtensionValue(String oid)
+ {
+ Extensions exts = c.getTBSCertList().getExtensions();
+
+ if (exts != null)
+ {
+ Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid));
+
+ if (ext != null)
+ {
+ try
+ {
+ return ext.getExtnValue().getEncoded();
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException("error parsing " + e.toString());
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public byte[] getEncoded()
+ throws CRLException
+ {
+ try
+ {
+ return c.getEncoded(ASN1Encoding.DER);
+ }
+ catch (IOException e)
+ {
+ throw new CRLException(e.toString());
+ }
+ }
+
+ public void verify(PublicKey key)
+ throws CRLException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException
+ {
+ verify(key, BouncyCastleProvider.PROVIDER_NAME);
+ }
+
+ public void verify(PublicKey key, String sigProvider)
+ throws CRLException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException
+ {
+ if (!c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature()))
+ {
+ throw new CRLException("Signature algorithm on CertificateList does not match TBSCertList.");
+ }
+
+ Signature sig;
+
+ if (sigProvider != null)
+ {
+ sig = Signature.getInstance(getSigAlgName(), sigProvider);
+ }
+ else
+ {
+ sig = Signature.getInstance(getSigAlgName());
+ }
+
+ sig.initVerify(key);
+ sig.update(this.getTBSCertList());
+
+ if (!sig.verify(this.getSignature()))
+ {
+ throw new SignatureException("CRL does not verify with supplied public key.");
+ }
+ }
+
+ public int getVersion()
+ {
+ return c.getVersionNumber();
+ }
+
+ public Principal getIssuerDN()
+ {
+ return new X509Principal(X500Name.getInstance(c.getIssuer().toASN1Primitive()));
+ }
+
+ public X500Principal getIssuerX500Principal()
+ {
+ try
+ {
+ return new X500Principal(c.getIssuer().getEncoded());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("can't encode issuer DN");
+ }
+ }
+
+ public Date getThisUpdate()
+ {
+ return c.getThisUpdate().getDate();
+ }
+
+ public Date getNextUpdate()
+ {
+ if (c.getNextUpdate() != null)
+ {
+ return c.getNextUpdate().getDate();
+ }
+
+ return null;
+ }
+
+ private Set loadCRLEntries()
+ {
+ Set entrySet = new HashSet();
+ Enumeration certs = c.getRevokedCertificateEnumeration();
+
+ X500Name previousCertificateIssuer = null; // the issuer
+ while (certs.hasMoreElements())
+ {
+ TBSCertList.CRLEntry entry = (TBSCertList.CRLEntry)certs.nextElement();
+ X509CRLEntryObject crlEntry = new X509CRLEntryObject(entry, isIndirect, previousCertificateIssuer);
+ entrySet.add(crlEntry);
+ if (isIndirect && entry.hasExtensions())
+ {
+ Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer);
+
+ if (currentCaName != null)
+ {
+ previousCertificateIssuer = X500Name.getInstance(GeneralNames.getInstance(currentCaName.getParsedValue()).getNames()[0].getName());
+ }
+ }
+ }
+
+ return entrySet;
+ }
+
+ public X509CRLEntry getRevokedCertificate(BigInteger serialNumber)
+ {
+ Enumeration certs = c.getRevokedCertificateEnumeration();
+
+ X500Name previousCertificateIssuer = null; // the issuer
+ while (certs.hasMoreElements())
+ {
+ TBSCertList.CRLEntry entry = (TBSCertList.CRLEntry)certs.nextElement();
+
+ if (serialNumber.equals(entry.getUserCertificate().getValue()))
+ {
+ return new X509CRLEntryObject(entry, isIndirect, previousCertificateIssuer);
+ }
+
+ if (isIndirect && entry.hasExtensions())
+ {
+ Extension currentCaName = entry.getExtensions().getExtension(Extension.certificateIssuer);
+
+ if (currentCaName != null)
+ {
+ previousCertificateIssuer = X500Name.getInstance(GeneralNames.getInstance(currentCaName.getParsedValue()).getNames()[0].getName());
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public Set getRevokedCertificates()
+ {
+ Set entrySet = loadCRLEntries();
+
+ if (!entrySet.isEmpty())
+ {
+ return Collections.unmodifiableSet(entrySet);
+ }
+
+ return null;
+ }
+
+ public byte[] getTBSCertList()
+ throws CRLException
+ {
+ try
+ {
+ return c.getTBSCertList().getEncoded("DER");
+ }
+ catch (IOException e)
+ {
+ throw new CRLException(e.toString());
+ }
+ }
+
+ public byte[] getSignature()
+ {
+ return c.getSignature().getBytes();
+ }
+
+ public String getSigAlgName()
+ {
+ return sigAlgName;
+ }
+
+ public String getSigAlgOID()
+ {
+ return c.getSignatureAlgorithm().getAlgorithm().getId();
+ }
+
+ public byte[] getSigAlgParams()
+ {
+ if (sigAlgParams != null)
+ {
+ byte[] tmp = new byte[sigAlgParams.length];
+
+ System.arraycopy(sigAlgParams, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a string representation of this CRL.
+ *
+ * @return a string representation of this CRL.
+ */
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = System.getProperty("line.separator");
+
+ buf.append(" Version: ").append(this.getVersion()).append(
+ nl);
+ buf.append(" IssuerDN: ").append(this.getIssuerDN())
+ .append(nl);
+ buf.append(" This update: ").append(this.getThisUpdate())
+ .append(nl);
+ buf.append(" Next update: ").append(this.getNextUpdate())
+ .append(nl);
+ buf.append(" Signature Algorithm: ").append(this.getSigAlgName())
+ .append(nl);
+
+ byte[] sig = this.getSignature();
+
+ buf.append(" Signature: ").append(
+ new String(Hex.encode(sig, 0, 20))).append(nl);
+ for (int i = 20; i < sig.length; i += 20)
+ {
+ if (i < sig.length - 20)
+ {
+ buf.append(" ").append(
+ new String(Hex.encode(sig, i, 20))).append(nl);
+ }
+ else
+ {
+ buf.append(" ").append(
+ new String(Hex.encode(sig, i, sig.length - i))).append(nl);
+ }
+ }
+
+ Extensions extensions = c.getTBSCertList().getExtensions();
+
+ if (extensions != null)
+ {
+ Enumeration e = extensions.oids();
+
+ if (e.hasMoreElements())
+ {
+ buf.append(" Extensions: ").append(nl);
+ }
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) e.nextElement();
+ Extension ext = extensions.getExtension(oid);
+
+ if (ext.getExtnValue() != null)
+ {
+ byte[] octs = ext.getExtnValue().getOctets();
+ ASN1InputStream dIn = new ASN1InputStream(octs);
+ buf.append(" critical(").append(
+ ext.isCritical()).append(") ");
+ try
+ {
+ if (oid.equals(Extension.cRLNumber))
+ {
+ buf.append(
+ new CRLNumber(ASN1Integer.getInstance(
+ dIn.readObject()).getPositiveValue()))
+ .append(nl);
+ }
+ else if (oid.equals(Extension.deltaCRLIndicator))
+ {
+ buf.append(
+ "Base CRL: "
+ + new CRLNumber(ASN1Integer.getInstance(
+ dIn.readObject()).getPositiveValue()))
+ .append(nl);
+ }
+ else if (oid
+ .equals(Extension.issuingDistributionPoint))
+ {
+ buf.append(
+ IssuingDistributionPoint.getInstance(dIn.readObject())).append(nl);
+ }
+ else if (oid
+ .equals(Extension.cRLDistributionPoints))
+ {
+ buf.append(
+ CRLDistPoint.getInstance(dIn.readObject())).append(nl);
+ }
+ else if (oid.equals(Extension.freshestCRL))
+ {
+ buf.append(
+ CRLDistPoint.getInstance(dIn.readObject())).append(nl);
+ }
+ else
+ {
+ buf.append(oid.getId());
+ buf.append(" value = ").append(
+ ASN1Dump.dumpAsString(dIn.readObject()))
+ .append(nl);
+ }
+ }
+ catch (Exception ex)
+ {
+ buf.append(oid.getId());
+ buf.append(" value = ").append("*****").append(nl);
+ }
+ }
+ else
+ {
+ buf.append(nl);
+ }
+ }
+ }
+ Set set = getRevokedCertificates();
+ if (set != null)
+ {
+ Iterator it = set.iterator();
+ while (it.hasNext())
+ {
+ buf.append(it.next());
+ buf.append(nl);
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Checks whether the given certificate is on this CRL.
+ *
+ * @param cert the certificate to check for.
+ * @return true if the given certificate is on this CRL,
+ * false otherwise.
+ */
+ public boolean isRevoked(Certificate cert)
+ {
+ if (!cert.getType().equals("X.509"))
+ {
+ throw new RuntimeException("X.509 CRL used with non X.509 Cert");
+ }
+
+ TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
+
+ X500Name caName = c.getIssuer();
+
+ if (certs != null)
+ {
+ BigInteger serial = ((X509Certificate)cert).getSerialNumber();
+
+ for (int i = 0; i < certs.length; i++)
+ {
+ if (isIndirect && certs[i].hasExtensions())
+ {
+ Extension currentCaName = certs[i].getExtensions().getExtension(Extension.certificateIssuer);
+
+ if (currentCaName != null)
+ {
+ caName = X500Name.getInstance(GeneralNames.getInstance(currentCaName.getParsedValue()).getNames()[0].getName());
+ }
+ }
+
+ if (certs[i].getUserCertificate().getValue().equals(serial))
+ {
+ X500Name issuer;
+
+ if (cert instanceof X509Certificate)
+ {
+ issuer = X500Name.getInstance(((X509Certificate)cert).getIssuerX500Principal().getEncoded());
+ }
+ else
+ {
+ try
+ {
+ issuer = org.bouncycastle.asn1.x509.Certificate.getInstance(cert.getEncoded()).getIssuer();
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw new RuntimeException("Cannot process certificate");
+ }
+ }
+
+ if (!caName.equals(issuer))
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+}
+
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
new file mode 100644
index 0000000..6604b4a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java
@@ -0,0 +1,916 @@
+package org.bouncycastle.jcajce.provider.asymmetric.x509;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OutputStream;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1String;
+import org.bouncycastle.asn1.DERBitString;
+import org.bouncycastle.asn1.DERIA5String;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
+import org.bouncycastle.asn1.misc.NetscapeCertType;
+import org.bouncycastle.asn1.misc.NetscapeRevocationURL;
+import org.bouncycastle.asn1.misc.VerisignCzagExtension;
+import org.bouncycastle.asn1.util.ASN1Dump;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.RFC4519Style;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.KeyUsage;
+// BEGIN android-added
+import org.bouncycastle.asn1.x509.X509Name;
+// END android-added
+import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
+import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jce.provider.RFC3280CertPathUtilities;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Integers;
+import org.bouncycastle.util.encoders.Hex;
+
+class X509CertificateObject
+ extends X509Certificate
+ implements PKCS12BagAttributeCarrier
+{
+ private org.bouncycastle.asn1.x509.Certificate c;
+ private BasicConstraints basicConstraints;
+ private boolean[] keyUsage;
+ private boolean hashValueSet;
+ private int hashValue;
+
+ private PKCS12BagAttributeCarrier attrCarrier = new PKCS12BagAttributeCarrierImpl();
+
+ public X509CertificateObject(
+ org.bouncycastle.asn1.x509.Certificate c)
+ throws CertificateParsingException
+ {
+ this.c = c;
+
+ try
+ {
+ byte[] bytes = this.getExtensionBytes("2.5.29.19");
+
+ if (bytes != null)
+ {
+ basicConstraints = BasicConstraints.getInstance(ASN1Primitive.fromByteArray(bytes));
+ }
+ }
+ catch (Exception e)
+ {
+ throw new CertificateParsingException("cannot construct BasicConstraints: " + e);
+ }
+
+ try
+ {
+ byte[] bytes = this.getExtensionBytes("2.5.29.15");
+ if (bytes != null)
+ {
+ DERBitString bits = DERBitString.getInstance(ASN1Primitive.fromByteArray(bytes));
+
+ bytes = bits.getBytes();
+ int length = (bytes.length * 8) - bits.getPadBits();
+
+ keyUsage = new boolean[(length < 9) ? 9 : length];
+
+ for (int i = 0; i != length; i++)
+ {
+ keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
+ }
+ }
+ else
+ {
+ keyUsage = null;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new CertificateParsingException("cannot construct KeyUsage: " + e);
+ }
+ }
+
+ public void checkValidity()
+ throws CertificateExpiredException, CertificateNotYetValidException
+ {
+ this.checkValidity(new Date());
+ }
+
+ public void checkValidity(
+ Date date)
+ throws CertificateExpiredException, CertificateNotYetValidException
+ {
+ if (date.getTime() > this.getNotAfter().getTime()) // for other VM compatibility
+ {
+ throw new CertificateExpiredException("certificate expired on " + c.getEndDate().getTime());
+ }
+
+ if (date.getTime() < this.getNotBefore().getTime())
+ {
+ throw new CertificateNotYetValidException("certificate not valid till " + c.getStartDate().getTime());
+ }
+ }
+
+ public int getVersion()
+ {
+ return c.getVersionNumber();
+ }
+
+ public BigInteger getSerialNumber()
+ {
+ return c.getSerialNumber().getValue();
+ }
+
+ public Principal getIssuerDN()
+ {
+ try
+ {
+ return new X509Principal(X500Name.getInstance(c.getIssuer().getEncoded()));
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+
+ public X500Principal getIssuerX500Principal()
+ {
+ try
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(c.getIssuer());
+
+ return new X500Principal(bOut.toByteArray());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("can't encode issuer DN");
+ }
+ }
+
+ public Principal getSubjectDN()
+ {
+ return new X509Principal(X500Name.getInstance(c.getSubject().toASN1Primitive()));
+ }
+
+ public X500Principal getSubjectX500Principal()
+ {
+ try
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(c.getSubject());
+
+ return new X500Principal(bOut.toByteArray());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("can't encode issuer DN");
+ }
+ }
+
+ public Date getNotBefore()
+ {
+ return c.getStartDate().getDate();
+ }
+
+ public Date getNotAfter()
+ {
+ return c.getEndDate().getDate();
+ }
+
+ public byte[] getTBSCertificate()
+ throws CertificateEncodingException
+ {
+ try
+ {
+ return c.getTBSCertificate().getEncoded(ASN1Encoding.DER);
+ }
+ catch (IOException e)
+ {
+ throw new CertificateEncodingException(e.toString());
+ }
+ }
+
+ public byte[] getSignature()
+ {
+ return c.getSignature().getBytes();
+ }
+
+ /**
+ * return a more "meaningful" representation for the signature algorithm used in
+ * the certficate.
+ */
+ public String getSigAlgName()
+ {
+ Provider prov = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
+
+ if (prov != null)
+ {
+ String algName = prov.getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
+
+ if (algName != null)
+ {
+ return algName;
+ }
+ }
+
+ Provider[] provs = Security.getProviders();
+
+ //
+ // search every provider looking for a real algorithm
+ //
+ for (int i = 0; i != provs.length; i++)
+ {
+ String algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
+ if (algName != null)
+ {
+ return algName;
+ }
+ }
+
+ return this.getSigAlgOID();
+ }
+
+ /**
+ * return the object identifier for the signature.
+ */
+ public String getSigAlgOID()
+ {
+ return c.getSignatureAlgorithm().getAlgorithm().getId();
+ }
+
+ /**
+ * return the signature parameters, or null if there aren't any.
+ */
+ public byte[] getSigAlgParams()
+ {
+ if (c.getSignatureAlgorithm().getParameters() != null)
+ {
+ try
+ {
+ return c.getSignatureAlgorithm().getParameters().toASN1Primitive().getEncoded(ASN1Encoding.DER);
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public boolean[] getIssuerUniqueID()
+ {
+ DERBitString id = c.getTBSCertificate().getIssuerUniqueId();
+
+ if (id != null)
+ {
+ byte[] bytes = id.getBytes();
+ boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()];
+
+ for (int i = 0; i != boolId.length; i++)
+ {
+ boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
+ }
+
+ return boolId;
+ }
+
+ return null;
+ }
+
+ public boolean[] getSubjectUniqueID()
+ {
+ DERBitString id = c.getTBSCertificate().getSubjectUniqueId();
+
+ if (id != null)
+ {
+ byte[] bytes = id.getBytes();
+ boolean[] boolId = new boolean[bytes.length * 8 - id.getPadBits()];
+
+ for (int i = 0; i != boolId.length; i++)
+ {
+ boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
+ }
+
+ return boolId;
+ }
+
+ return null;
+ }
+
+ public boolean[] getKeyUsage()
+ {
+ return keyUsage;
+ }
+
+ public List getExtendedKeyUsage()
+ throws CertificateParsingException
+ {
+ byte[] bytes = this.getExtensionBytes("2.5.29.37");
+
+ if (bytes != null)
+ {
+ try
+ {
+ ASN1InputStream dIn = new ASN1InputStream(bytes);
+ ASN1Sequence seq = (ASN1Sequence)dIn.readObject();
+ List list = new ArrayList();
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ list.add(((ASN1ObjectIdentifier)seq.getObjectAt(i)).getId());
+ }
+
+ return Collections.unmodifiableList(list);
+ }
+ catch (Exception e)
+ {
+ throw new CertificateParsingException("error processing extended key usage extension");
+ }
+ }
+
+ return null;
+ }
+
+ public int getBasicConstraints()
+ {
+ if (basicConstraints != null)
+ {
+ if (basicConstraints.isCA())
+ {
+ if (basicConstraints.getPathLenConstraint() == null)
+ {
+ return Integer.MAX_VALUE;
+ }
+ else
+ {
+ return basicConstraints.getPathLenConstraint().intValue();
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ return -1;
+ }
+
+ public Collection getSubjectAlternativeNames()
+ throws CertificateParsingException
+ {
+ return getAlternativeNames(getExtensionBytes(Extension.subjectAlternativeName.getId()));
+ }
+
+ public Collection getIssuerAlternativeNames()
+ throws CertificateParsingException
+ {
+ return getAlternativeNames(getExtensionBytes(Extension.issuerAlternativeName.getId()));
+ }
+
+ public Set getCriticalExtensionOIDs()
+ {
+ if (this.getVersion() == 3)
+ {
+ Set set = new HashSet();
+ Extensions extensions = c.getTBSCertificate().getExtensions();
+
+ if (extensions != null)
+ {
+ Enumeration e = extensions.oids();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ Extension ext = extensions.getExtension(oid);
+
+ if (ext.isCritical())
+ {
+ set.add(oid.getId());
+ }
+ }
+
+ return set;
+ }
+ }
+
+ return null;
+ }
+
+ private byte[] getExtensionBytes(String oid)
+ {
+ Extensions exts = c.getTBSCertificate().getExtensions();
+
+ if (exts != null)
+ {
+ Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid));
+ if (ext != null)
+ {
+ return ext.getExtnValue().getOctets();
+ }
+ }
+
+ return null;
+ }
+
+ public byte[] getExtensionValue(String oid)
+ {
+ Extensions exts = c.getTBSCertificate().getExtensions();
+
+ if (exts != null)
+ {
+ Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid));
+
+ if (ext != null)
+ {
+ try
+ {
+ return ext.getExtnValue().getEncoded();
+ }
+ catch (Exception e)
+ {
+ throw new IllegalStateException("error parsing " + e.toString());
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public Set getNonCriticalExtensionOIDs()
+ {
+ if (this.getVersion() == 3)
+ {
+ Set set = new HashSet();
+ Extensions extensions = c.getTBSCertificate().getExtensions();
+
+ if (extensions != null)
+ {
+ Enumeration e = extensions.oids();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ Extension ext = extensions.getExtension(oid);
+
+ if (!ext.isCritical())
+ {
+ set.add(oid.getId());
+ }
+ }
+
+ return set;
+ }
+ }
+
+ return null;
+ }
+
+ public boolean hasUnsupportedCriticalExtension()
+ {
+ if (this.getVersion() == 3)
+ {
+ Extensions extensions = c.getTBSCertificate().getExtensions();
+
+ if (extensions != null)
+ {
+ Enumeration e = extensions.oids();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ String oidId = oid.getId();
+
+ if (oidId.equals(RFC3280CertPathUtilities.KEY_USAGE)
+ || oidId.equals(RFC3280CertPathUtilities.CERTIFICATE_POLICIES)
+ || oidId.equals(RFC3280CertPathUtilities.POLICY_MAPPINGS)
+ || oidId.equals(RFC3280CertPathUtilities.INHIBIT_ANY_POLICY)
+ || oidId.equals(RFC3280CertPathUtilities.CRL_DISTRIBUTION_POINTS)
+ || oidId.equals(RFC3280CertPathUtilities.ISSUING_DISTRIBUTION_POINT)
+ || oidId.equals(RFC3280CertPathUtilities.DELTA_CRL_INDICATOR)
+ || oidId.equals(RFC3280CertPathUtilities.POLICY_CONSTRAINTS)
+ || oidId.equals(RFC3280CertPathUtilities.BASIC_CONSTRAINTS)
+ || oidId.equals(RFC3280CertPathUtilities.SUBJECT_ALTERNATIVE_NAME)
+ || oidId.equals(RFC3280CertPathUtilities.NAME_CONSTRAINTS))
+ {
+ continue;
+ }
+
+ Extension ext = extensions.getExtension(oid);
+
+ if (ext.isCritical())
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public PublicKey getPublicKey()
+ {
+ try
+ {
+ return BouncyCastleProvider.getPublicKey(c.getSubjectPublicKeyInfo());
+ }
+ catch (IOException e)
+ {
+ return null; // should never happen...
+ }
+ }
+
+ // BEGIN android-changed
+ private byte[] encoded;
+ // END android-changed
+ public byte[] getEncoded()
+ throws CertificateEncodingException
+ {
+ try
+ {
+ // BEGIN android-changed
+ if (encoded == null) {
+ encoded = c.getEncoded(ASN1Encoding.DER);
+ }
+ return encoded;
+ // END android-changed
+ }
+ catch (IOException e)
+ {
+ throw new CertificateEncodingException(e.toString());
+ }
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (o == this)
+ {
+ return true;
+ }
+
+ if (!(o instanceof Certificate))
+ {
+ return false;
+ }
+
+ Certificate other = (Certificate)o;
+
+ try
+ {
+ byte[] b1 = this.getEncoded();
+ byte[] b2 = other.getEncoded();
+
+ return Arrays.areEqual(b1, b2);
+ }
+ catch (CertificateEncodingException e)
+ {
+ return false;
+ }
+ }
+
+ public synchronized int hashCode()
+ {
+ if (!hashValueSet)
+ {
+ hashValue = calculateHashCode();
+ hashValueSet = true;
+ }
+
+ return hashValue;
+ }
+
+ private int calculateHashCode()
+ {
+ try
+ {
+ int hashCode = 0;
+ byte[] certData = this.getEncoded();
+ for (int i = 1; i < certData.length; i++)
+ {
+ hashCode += certData[i] * i;
+ }
+ return hashCode;
+ }
+ catch (CertificateEncodingException e)
+ {
+ return 0;
+ }
+ }
+
+ public void setBagAttribute(
+ ASN1ObjectIdentifier oid,
+ ASN1Encodable attribute)
+ {
+ attrCarrier.setBagAttribute(oid, attribute);
+ }
+
+ public ASN1Encodable getBagAttribute(
+ ASN1ObjectIdentifier oid)
+ {
+ return attrCarrier.getBagAttribute(oid);
+ }
+
+ public Enumeration getBagAttributeKeys()
+ {
+ return attrCarrier.getBagAttributeKeys();
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String nl = System.getProperty("line.separator");
+
+ buf.append(" [0] Version: ").append(this.getVersion()).append(nl);
+ buf.append(" SerialNumber: ").append(this.getSerialNumber()).append(nl);
+ buf.append(" IssuerDN: ").append(this.getIssuerDN()).append(nl);
+ buf.append(" Start Date: ").append(this.getNotBefore()).append(nl);
+ buf.append(" Final Date: ").append(this.getNotAfter()).append(nl);
+ buf.append(" SubjectDN: ").append(this.getSubjectDN()).append(nl);
+ buf.append(" Public Key: ").append(this.getPublicKey()).append(nl);
+ buf.append(" Signature Algorithm: ").append(this.getSigAlgName()).append(nl);
+
+ byte[] sig = this.getSignature();
+
+ buf.append(" Signature: ").append(new String(Hex.encode(sig, 0, 20))).append(nl);
+ for (int i = 20; i < sig.length; i += 20)
+ {
+ if (i < sig.length - 20)
+ {
+ buf.append(" ").append(new String(Hex.encode(sig, i, 20))).append(nl);
+ }
+ else
+ {
+ buf.append(" ").append(new String(Hex.encode(sig, i, sig.length - i))).append(nl);
+ }
+ }
+
+ Extensions extensions = c.getTBSCertificate().getExtensions();
+
+ if (extensions != null)
+ {
+ Enumeration e = extensions.oids();
+
+ if (e.hasMoreElements())
+ {
+ buf.append(" Extensions: \n");
+ }
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ Extension ext = extensions.getExtension(oid);
+
+ if (ext.getExtnValue() != null)
+ {
+ byte[] octs = ext.getExtnValue().getOctets();
+ ASN1InputStream dIn = new ASN1InputStream(octs);
+ buf.append(" critical(").append(ext.isCritical()).append(") ");
+ try
+ {
+ if (oid.equals(Extension.basicConstraints))
+ {
+ buf.append(BasicConstraints.getInstance(dIn.readObject())).append(nl);
+ }
+ else if (oid.equals(Extension.keyUsage))
+ {
+ buf.append(KeyUsage.getInstance(dIn.readObject())).append(nl);
+ }
+ else if (oid.equals(MiscObjectIdentifiers.netscapeCertType))
+ {
+ buf.append(new NetscapeCertType((DERBitString)dIn.readObject())).append(nl);
+ }
+ else if (oid.equals(MiscObjectIdentifiers.netscapeRevocationURL))
+ {
+ buf.append(new NetscapeRevocationURL((DERIA5String)dIn.readObject())).append(nl);
+ }
+ else if (oid.equals(MiscObjectIdentifiers.verisignCzagExtension))
+ {
+ buf.append(new VerisignCzagExtension((DERIA5String)dIn.readObject())).append(nl);
+ }
+ else
+ {
+ buf.append(oid.getId());
+ buf.append(" value = ").append(ASN1Dump.dumpAsString(dIn.readObject())).append(nl);
+ //buf.append(" value = ").append("*****").append(nl);
+ }
+ }
+ catch (Exception ex)
+ {
+ buf.append(oid.getId());
+ // buf.append(" value = ").append(new String(Hex.encode(ext.getExtnValue().getOctets()))).append(nl);
+ buf.append(" value = ").append("*****").append(nl);
+ }
+ }
+ else
+ {
+ buf.append(nl);
+ }
+ }
+ }
+
+ return buf.toString();
+ }
+
+ public final void verify(
+ PublicKey key)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException
+ {
+ Signature signature;
+ String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm());
+
+ try
+ {
+ signature = Signature.getInstance(sigName, BouncyCastleProvider.PROVIDER_NAME);
+ }
+ catch (Exception e)
+ {
+ signature = Signature.getInstance(sigName);
+ }
+
+ checkSignature(key, signature);
+ }
+
+ public final void verify(
+ PublicKey key,
+ String sigProvider)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException
+ {
+ String sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm());
+ Signature signature = Signature.getInstance(sigName, sigProvider);
+
+ checkSignature(key, signature);
+ }
+
+ private void checkSignature(
+ PublicKey key,
+ Signature signature)
+ throws CertificateException, NoSuchAlgorithmException,
+ SignatureException, InvalidKeyException
+ {
+ if (!isAlgIdEqual(c.getSignatureAlgorithm(), c.getTBSCertificate().getSignature()))
+ {
+ throw new CertificateException("signature algorithm in TBS cert not same as outer cert");
+ }
+
+ ASN1Encodable params = c.getSignatureAlgorithm().getParameters();
+
+ // TODO This should go after the initVerify?
+ X509SignatureUtil.setSignatureParameters(signature, params);
+
+ signature.initVerify(key);
+
+ signature.update(this.getTBSCertificate());
+
+ if (!signature.verify(this.getSignature()))
+ {
+ throw new SignatureException("certificate does not verify with supplied key");
+ }
+ }
+
+ private boolean isAlgIdEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)
+ {
+ if (!id1.getAlgorithm().equals(id2.getAlgorithm()))
+ {
+ return false;
+ }
+
+ if (id1.getParameters() == null)
+ {
+ if (id2.getParameters() != null && !id2.getParameters().equals(DERNull.INSTANCE))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ if (id2.getParameters() == null)
+ {
+ if (id1.getParameters() != null && !id1.getParameters().equals(DERNull.INSTANCE))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ return id1.getParameters().equals(id2.getParameters());
+ }
+
+ private static Collection getAlternativeNames(byte[] extVal)
+ throws CertificateParsingException
+ {
+ if (extVal == null)
+ {
+ return null;
+ }
+ try
+ {
+ Collection temp = new ArrayList();
+ Enumeration it = ASN1Sequence.getInstance(extVal).getObjects();
+ while (it.hasMoreElements())
+ {
+ GeneralName genName = GeneralName.getInstance(it.nextElement());
+ List list = new ArrayList();
+ list.add(Integers.valueOf(genName.getTagNo()));
+ switch (genName.getTagNo())
+ {
+ case GeneralName.ediPartyName:
+ case GeneralName.x400Address:
+ case GeneralName.otherName:
+ list.add(genName.getEncoded());
+ break;
+ case GeneralName.directoryName:
+ // BEGIN android-changed
+ list.add(X509Name.getInstance(genName.getName()).toString(true, X509Name.DefaultSymbols));
+ // END android-changed
+ break;
+ case GeneralName.dNSName:
+ case GeneralName.rfc822Name:
+ case GeneralName.uniformResourceIdentifier:
+ list.add(((ASN1String)genName.getName()).getString());
+ break;
+ case GeneralName.registeredID:
+ list.add(ASN1ObjectIdentifier.getInstance(genName.getName()).getId());
+ break;
+ case GeneralName.iPAddress:
+ byte[] addrBytes = DEROctetString.getInstance(genName.getName()).getOctets();
+ final String addr;
+ try
+ {
+ addr = InetAddress.getByAddress(addrBytes).getHostAddress();
+ }
+ catch (UnknownHostException e)
+ {
+ continue;
+ }
+ list.add(addr);
+ break;
+ default:
+ throw new IOException("Bad tag number: " + genName.getTagNo());
+ }
+
+ temp.add(Collections.unmodifiableList(list));
+ }
+ if (temp.size() == 0)
+ {
+ return null;
+ }
+ return Collections.unmodifiableCollection(temp);
+ }
+ catch (Exception e)
+ {
+ throw new CertificateParsingException(e.getMessage());
+ }
+ }
+}
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
new file mode 100644
index 0000000..4ca9e89
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
@@ -0,0 +1,144 @@
+package org.bouncycastle.jcajce.provider.asymmetric.x509;
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.PSSParameterSpec;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Null;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+// 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;
+
+class X509SignatureUtil
+{
+ private static final ASN1Null derNull = DERNull.INSTANCE;
+
+ static void setSignatureParameters(
+ Signature signature,
+ ASN1Encodable params)
+ throws NoSuchAlgorithmException, SignatureException, InvalidKeyException
+ {
+ if (params != null && !derNull.equals(params))
+ {
+ AlgorithmParameters sigParams = AlgorithmParameters.getInstance(signature.getAlgorithm(), signature.getProvider());
+
+ try
+ {
+ sigParams.init(params.toASN1Primitive().getEncoded());
+ }
+ catch (IOException e)
+ {
+ throw new SignatureException("IOException decoding parameters: " + e.getMessage());
+ }
+
+ if (signature.getAlgorithm().endsWith("MGF1"))
+ {
+ try
+ {
+ signature.setParameter(sigParams.getParameterSpec(PSSParameterSpec.class));
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new SignatureException("Exception extracting parameters: " + e.getMessage());
+ }
+ }
+ }
+ }
+
+ static String getSignatureName(
+ AlgorithmIdentifier sigAlgId)
+ {
+ ASN1Encodable params = sigAlgId.getParameters();
+
+ if (params != null && !derNull.equals(params))
+ {
+ if (sigAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
+ {
+ RSASSAPSSparams rsaParams = RSASSAPSSparams.getInstance(params);
+
+ return getDigestAlgName(rsaParams.getHashAlgorithm().getAlgorithm()) + "withRSAandMGF1";
+ }
+ if (sigAlgId.getAlgorithm().equals(X9ObjectIdentifiers.ecdsa_with_SHA2))
+ {
+ ASN1Sequence ecDsaParams = ASN1Sequence.getInstance(params);
+
+ return getDigestAlgName((DERObjectIdentifier)ecDsaParams.getObjectAt(0)) + "withECDSA";
+ }
+ }
+
+ return sigAlgId.getAlgorithm().getId();
+ }
+
+ /**
+ * Return the digest algorithm using one of the standard JCA string
+ * representations rather the the algorithm identifier (if possible).
+ */
+ private static String getDigestAlgName(
+ DERObjectIdentifier 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
+ {
+ return digestAlgOID.getId();
+ }
+ }
+}