bouncycastle: upgrade to version 1.52

Change-Id: I227db8e458e67af46ccb1c07bfca77a733f25979
diff --git a/NOTICE b/NOTICE
index f1591ef..b3cbfab 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,4 +1,4 @@
-Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org)
+Copyright (c) 2000-2015 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org)
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 associated documentation files (the "Software"), to deal in the Software without restriction,
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/AttributeCertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/AttributeCertificateHolder.java
index 074d3fc..0fc3433 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/AttributeCertificateHolder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/AttributeCertificateHolder.java
@@ -53,20 +53,36 @@
         holder = Holder.getInstance(seq);
     }
 
+    /**
+     * Create a holder using the baseCertificateID element.
+     *
+     * @param issuerName name of associated certificate's issuer.
+     * @param serialNumber serial number of associated certificate.
+     */
     public AttributeCertificateHolder(X500Name issuerName,
         BigInteger serialNumber)
     {
         holder = new Holder(new IssuerSerial(
-            new GeneralNames(new GeneralName(issuerName)),
+            generateGeneralNames(issuerName),
             new ASN1Integer(serialNumber)));
     }
 
+    /**
+     * Create a holder using the baseCertificateID option based on the passed in associated certificate,
+     *
+     * @param cert the certificate to be associated with this holder.
+     */
     public AttributeCertificateHolder(X509CertificateHolder cert)
     {
         holder = new Holder(new IssuerSerial(generateGeneralNames(cert.getIssuer()),
             new ASN1Integer(cert.getSerialNumber())));
     }
 
+    /**
+     * Create a holder using the entityName option based on the passed in principal.
+     *
+     * @param principal the entityName to be associated with the attribute certificate.
+     */
     public AttributeCertificateHolder(X500Name principal)
     {
         holder = new Holder(generateGeneralNames(principal));
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java
index a34b3b3..c465c83 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509AttributeCertificateHolder.java
@@ -21,11 +21,13 @@
 import org.bouncycastle.asn1.x509.Extensions;
 import org.bouncycastle.operator.ContentVerifier;
 import org.bouncycastle.operator.ContentVerifierProvider;
+import org.bouncycastle.util.Encodable;
 
 /**
  * Holding class for an X.509 AttributeCertificate structure.
  */
 public class X509AttributeCertificateHolder
+    implements Encodable
 {
     private static Attribute[] EMPTY_ARRAY = new Attribute[0];
     
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java
index b3723f3..29c48fa 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509CRLHolder.java
@@ -24,11 +24,13 @@
 import org.bouncycastle.asn1.x509.TBSCertList;
 import org.bouncycastle.operator.ContentVerifier;
 import org.bouncycastle.operator.ContentVerifierProvider;
+import org.bouncycastle.util.Encodable;
 
 /**
  * Holding class for an X.509 CRL structure.
  */
 public class X509CRLHolder
+    implements Encodable
 {
     private CertificateList x509CRL;
     private boolean isIndirect;
diff --git a/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java b/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java
index 1081d93..dc61c78 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cert/X509CertificateHolder.java
@@ -19,11 +19,13 @@
 import org.bouncycastle.asn1.x509.TBSCertificate;
 import org.bouncycastle.operator.ContentVerifier;
 import org.bouncycastle.operator.ContentVerifierProvider;
+import org.bouncycastle.util.Encodable;
 
 /**
  * Holding class for an X.509 Certificate structure.
  */
 public class X509CertificateHolder
+    implements Encodable
 {
     private Certificate x509Certificate;
     private Extensions  extensions;
@@ -214,7 +216,7 @@
     /**
      * Return the underlying ASN.1 structure for the certificate in this holder.
      *
-     * @return a X509CertificateStructure object.
+     * @return a Certificate object.
      */
     public Certificate toASN1Structure()
     {
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
index ec4da91..5ef95ee 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/CMSSignedData.java
@@ -23,6 +23,7 @@
 import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
 import org.bouncycastle.operator.OperatorCreationException;
 import org.bouncycastle.operator.SignatureAlgorithmIdentifierFinder;
+import org.bouncycastle.util.Encodable;
 import org.bouncycastle.util.Store;
 
 /**
@@ -54,6 +55,7 @@
  * </pre>
  */
 public class CMSSignedData
+    implements Encodable
 {
     private static final CMSSignedHelper HELPER = CMSSignedHelper.INSTANCE;
     
@@ -347,7 +349,7 @@
     // {
     //     return verifySignatures(verifierProvider, false);
     // }
-    //
+    // 
     // /**
     //  * Verify all the SignerInformation objects and optionally their associated counter signatures attached
     //  * to this CMS SignedData object.
@@ -361,30 +363,27 @@
     //     throws CMSException
     // {
     //     Collection signers = this.getSignerInfos().getSigners();
-    //
+    // 
     //     for (Iterator it = signers.iterator(); it.hasNext();)
     //     {
     //         SignerInformation signer = (SignerInformation)it.next();
-    //
+    // 
     //         try
     //         {
     //             SignerInformationVerifier verifier = verifierProvider.get(signer.getSID());
-    //
+    // 
     //             if (!signer.verify(verifier))
     //             {
     //                 return false;
     //             }
-    //
+    // 
     //             if (!ignoreCounterSignatures)
     //             {
     //                 Collection counterSigners = signer.getCounterSignatures().getSigners();
-    //
+    // 
     //                 for  (Iterator cIt = counterSigners.iterator(); cIt.hasNext();)
     //                 {
-    //                     SignerInformation counterSigner = (SignerInformation)cIt.next();
-    //                     SignerInformationVerifier counterVerifier = verifierProvider.get(signer.getSID());
-    //
-    //                     if (!counterSigner.verify(counterVerifier))
+    //                     if (!verifyCounterSignature((SignerInformation)cIt.next(), verifierProvider))
     //                     {
     //                         return false;
     //                     }
@@ -396,7 +395,29 @@
     //             throw new CMSException("failure in verifier provider: " + e.getMessage(), e);
     //         }
     //     }
-    //
+    // 
+    //     return true;
+    // }
+    // 
+    // private boolean verifyCounterSignature(SignerInformation counterSigner, SignerInformationVerifierProvider verifierProvider)
+    //     throws OperatorCreationException, CMSException
+    // {
+    //     SignerInformationVerifier counterVerifier = verifierProvider.get(counterSigner.getSID());
+    // 
+    //     if (!counterSigner.verify(counterVerifier))
+    //     {
+    //         return false;
+    //     }
+    // 
+    //     Collection counterSigners = counterSigner.getCounterSignatures().getSigners();
+    //     for  (Iterator cIt = counterSigners.iterator(); cIt.hasNext();)
+    //     {
+    //         if (!verifyCounterSignature((SignerInformation)cIt.next(), verifierProvider))
+    //         {
+    //             return false;
+    //         }
+    //     }
+    // 
     //     return true;
     // }
     // END android-removed
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
index f69772d..d454fa6 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
@@ -52,6 +52,11 @@
         addEntries(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256", "RSA");
         addEntries(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384", "RSA");
         addEntries(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512", "RSA");
+
+        addEntries(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128, "RIPEMD128", "RSA");
+        addEntries(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160, "RIPEMD160", "RSA");
+        addEntries(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256, "RIPEMD256", "RSA");
+
         addEntries(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1", "ECDSA");
         addEntries(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224", "ECDSA");
         addEntries(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256", "ECDSA");
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java
index 7e178d6..081d121 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformation.java
@@ -302,7 +302,7 @@
     {
         if (signedAttributeSet != null)
         {
-            return signedAttributeSet.getEncoded();
+            return signedAttributeSet.getEncoded(ASN1Encoding.DER);
         }
 
         return null;
diff --git a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformationStore.java b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformationStore.java
index b65ab5e..79ec0a0 100644
--- a/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformationStore.java
+++ b/bcpkix/src/main/java/org/bouncycastle/cms/SignerInformationStore.java
@@ -7,13 +7,37 @@
 import java.util.List;
 import java.util.Map;
 
+import org.bouncycastle.util.Iterable;
+
 public class SignerInformationStore
+    implements Iterable<SignerInformation>
 {
     private List all = new ArrayList();
     private Map table = new HashMap();
 
+    /**
+     * Create a store containing a single SignerInformation object.
+     *
+     * @param signerInfo the signer information to contain.
+     */
     public SignerInformationStore(
-        Collection  signerInfos)
+        SignerInformation  signerInfo)
+    {
+        this.all = new ArrayList(1);
+        this.all.add(signerInfo);
+
+        SignerId sid = signerInfo.getSID();
+
+        table.put(sid, all);
+    }
+
+    /**
+     * Create a store containing a collection of SignerInformation objects.
+     *
+     * @param signerInfos a collection signer information objects to contain.
+     */
+    public SignerInformationStore(
+        Collection<SignerInformation>  signerInfos)
     {
         Iterator    it = signerInfos.iterator();
 
@@ -65,7 +89,7 @@
      * 
      * @return a collection of signers.
      */
-    public Collection getSigners()
+    public Collection<SignerInformation> getSigners()
     {
         return new ArrayList(all);
     }
@@ -76,7 +100,7 @@
      * @param selector a signer id to select against.
      * @return a collection of SignerInformation objects.
      */
-    public Collection getSigners(
+    public Collection<SignerInformation> getSigners(
         SignerId selector)
     {
         if (selector.getIssuer() != null && selector.getSubjectKeyIdentifier() != null)
@@ -106,4 +130,12 @@
             return list == null ? new ArrayList() : new ArrayList(list);
         }
     }
+
+    /**
+     * Support method for Iterable where available.
+     */
+    public Iterator<SignerInformation> iterator()
+    {
+        return getSigners().iterator();
+    }
 }
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
index 14ab78d..5f82d40 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java
@@ -190,9 +190,10 @@
     private class SigVerifier
         implements ContentVerifier
     {
-        private SignatureOutputStream stream;
         private AlgorithmIdentifier algorithm;
 
+        protected SignatureOutputStream stream;
+
         SigVerifier(AlgorithmIdentifier algorithm, SignatureOutputStream stream)
         {
             this.algorithm = algorithm;
@@ -239,6 +240,27 @@
             this.rawSignature = rawSignature;
         }
 
+        public boolean verify(byte[] expected)
+        {
+            try
+            {
+                return super.verify(expected);
+            }
+            finally
+            {
+                // we need to do this as in some PKCS11 implementations the session associated with the init of the
+                // raw signature will not be freed if verify is not called on it.
+                try
+                {
+                    rawSignature.verify(expected);
+                }
+                catch (Exception e)
+                {
+                    // ignore
+                }
+            }
+        }
+
         public boolean verify(byte[] digest, byte[] expected)
         {
             try
@@ -251,6 +273,19 @@
             {
                 throw new RuntimeOperatorException("exception obtaining raw signature: " + e.getMessage(), e);
             }
+            finally
+            {
+                // we need to do this as in some PKCS11 implementations the session associated with the init of the
+                // standard signature will not be freed if verify is not called on it.
+                try
+                {
+                    stream.verify(expected);
+                }
+                catch (Exception e)
+                {
+                    // ignore
+                }
+            }
         }
     }
 
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 927b4d7..a0847fb 100644
--- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java
+++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java
@@ -368,10 +368,6 @@
         {
             throw new OpCertificateException("cannot get encoded form of certificate: " + e.getMessage(), e);
         }
-        catch (NoSuchAlgorithmException e)
-        {
-            throw new OpCertificateException("cannot create certificate factory: " + e.getMessage(), e);
-        }
         catch (NoSuchProviderException e)
         {
             throw new OpCertificateException("cannot find factory provider: " + e.getMessage(), e);
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
index d760a1f..bbe5ae1 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1GeneralizedTime.java
@@ -153,7 +153,7 @@
     /**
      * return the time - always in the form of
      * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
-     * <p/>
+     * <p>
      * Normally in a certificate we would expect "Z" rather than "GMT",
      * however adding the "GMT" means we can just use:
      * <pre>
@@ -161,6 +161,7 @@
      * </pre>
      * To read in the time and get a date which is compatible with our local
      * time zone.
+     * </p>
      */
     public String getTime()
     {
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java
index cfda1a6..304866f 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Object.java
@@ -3,11 +3,13 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
+import org.bouncycastle.util.Encodable;
+
 /**
  * Base class for defining an ASN.1 object.
  */
 public abstract class ASN1Object
-    implements ASN1Encodable
+    implements ASN1Encodable, Encodable
 {
     /**
      * Return the default BER or DER encoding for this object.
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
index 895f002..b4d263a 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/ASN1Set.java
@@ -481,22 +481,17 @@
         return len == a.length;
     }
 
-    private byte[] getEncoded(
+    private byte[] getDEREncoded(
         ASN1Encodable obj)
     {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
-
         try
         {
-            aOut.writeObject(obj);
+            return obj.toASN1Primitive().getEncoded(ASN1Encoding.DER);
         }
         catch (IOException e)
         {
             throw new IllegalArgumentException("cannot encode object added to SET");
         }
-
-        return bOut.toByteArray();
     }
 
     protected void sort()
@@ -513,13 +508,13 @@
                 {
                     int    index = 0;
                     int    swapIndex = 0;
-                    byte[] a = getEncoded((ASN1Encodable)set.elementAt(0));
+                    byte[] a = getDEREncoded((ASN1Encodable)set.elementAt(0));
 
                     swapped = false;
 
                     while (index != lastSwap)
                     {
-                        byte[] b = getEncoded((ASN1Encodable)set.elementAt(index + 1));
+                        byte[] b = getDEREncoded((ASN1Encodable)set.elementAt(index + 1));
 
                         if (lessThanOrEqual(a, b))
                         {
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
index dfc3121..098656c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
@@ -35,9 +35,16 @@
     static final ASN1ObjectIdentifier   verisign                = new ASN1ObjectIdentifier("2.16.840.1.113733.1");
 
     /** Verisign CZAG (Country,Zip,Age,Gender) Extension OID: 2.16.840.1.113733.1.6.3 */
-    static final ASN1ObjectIdentifier    verisignCzagExtension   = verisign.branch("6.3");
+    static final ASN1ObjectIdentifier   verisignCzagExtension   = verisign.branch("6.3");
+
+    static final ASN1ObjectIdentifier   verisignPrivate_6_9     = verisign.branch("6.9");
+    static final ASN1ObjectIdentifier   verisignOnSiteJurisdictionHash = verisign.branch("6.11");
+    static final ASN1ObjectIdentifier   verisignBitString_6_13   = verisign.branch("6.13");
+
     /** Verisign D&amp;B D-U-N-S number Extension OID: 2.16.840.1.113733.1.6.15 */
-    static final ASN1ObjectIdentifier    verisignDnbDunsNumber   = verisign.branch("6.15");
+    static final ASN1ObjectIdentifier   verisignDnbDunsNumber   = verisign.branch("6.15");
+
+    static final ASN1ObjectIdentifier   verisignIssStrongCrypto = verisign.branch("8.1");
 
     //
     // Novell
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 d2acd30..fb418ae 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
@@ -67,18 +67,18 @@
      * @param attributes any attributes to be associated with the request.
      */
     public CertificationRequestInfo(
-        X500Name subject,
+        X500Name                subject,
         SubjectPublicKeyInfo    pkInfo,
         ASN1Set                 attributes)
     {
-        this.subject = subject;
-        this.subjectPKInfo = pkInfo;
-        this.attributes = attributes;
-
-        if ((subject == null) || (version == null) || (subjectPKInfo == null))
+        if ((subject == null) || (pkInfo == null))
         {
             throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
         }
+
+        this.subject = subject;
+        this.subjectPKInfo = pkInfo;
+        this.attributes = attributes;
     }
 
     /**
@@ -89,14 +89,14 @@
         SubjectPublicKeyInfo    pkInfo,
         ASN1Set                 attributes)
     {
-        this.subject = X500Name.getInstance(subject.toASN1Primitive());
-        this.subjectPKInfo = pkInfo;
-        this.attributes = attributes;
-
-        if ((subject == null) || (version == null) || (subjectPKInfo == null))
+        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;
     }
 
     /**
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java b/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
index df2238a..269466d 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/sec/ECPrivateKey.java
@@ -47,10 +47,26 @@
         return null;
     }
 
+    /**
+     * @deprecated use constructor which takes orderBitLength to guarantee correct encoding.
+     */
     public ECPrivateKey(
         BigInteger key)
     {
-        byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+        this(key.bitLength(), key);
+    }
+
+    /**
+     * Base constructor.
+     *
+     * @param orderBitLength the bitLength of the order of the curve.
+     * @param key the private key value.
+     */
+    public ECPrivateKey(
+        int        orderBitLength,
+        BigInteger key)
+    {
+        byte[] bytes = BigIntegers.asUnsignedByteArray((orderBitLength + 7) / 8, key);
 
         ASN1EncodableVector v = new ASN1EncodableVector();
 
@@ -60,6 +76,9 @@
         seq = new DERSequence(v);
     }
 
+    /**
+     * @deprecated use constructor which takes orderBitLength to guarantee correct encoding.
+     */
     public ECPrivateKey(
         BigInteger key,
         ASN1Encodable parameters)
@@ -67,12 +86,32 @@
         this(key, null, parameters);
     }
 
+    /**
+     * @deprecated use constructor which takes orderBitLength to guarantee correct encoding.
+     */
     public ECPrivateKey(
         BigInteger key,
         DERBitString publicKey,
         ASN1Encodable parameters)
     {
-        byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+        this(key.bitLength(), key, publicKey, parameters);
+    }
+
+    public ECPrivateKey(
+        int orderBitLength,
+        BigInteger key,
+        ASN1Encodable parameters)
+    {
+        this(orderBitLength, key, null, parameters);
+    }
+
+    public ECPrivateKey(
+        int orderBitLength,
+        BigInteger key,
+        DERBitString publicKey,
+        ASN1Encodable parameters)
+    {
+        byte[] bytes = BigIntegers.asUnsignedByteArray((orderBitLength + 7) / 8, key);
 
         ASN1EncodableVector v = new ASN1EncodableVector();
 
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
index b4f1794..9df924c 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java
@@ -322,7 +322,10 @@
         }
         else
         {
-            IETFUtils.appendTypeAndValue(buf, rdn.getFirst(), oidSymbols);
+            if (rdn.getFirst() != null)
+            {
+                IETFUtils.appendTypeAndValue(buf, rdn.getFirst(), oidSymbols);
+            }
         }
     }
 
@@ -438,7 +441,7 @@
 
     public static String canonicalize(String s)
     {
-        String value = Strings.toLowerCase(s.trim());
+        String value = Strings.toLowerCase(s);
 
         if (value.length() > 0 && value.charAt(0) == '#')
         {
@@ -446,7 +449,27 @@
 
             if (obj instanceof ASN1String)
             {
-                value = Strings.toLowerCase(((ASN1String)obj).getString().trim());
+                value = Strings.toLowerCase(((ASN1String)obj).getString());
+            }
+        }
+
+        if (value.length() > 1)
+        {
+            int start = 0;
+            while (start + 1 < value.length() && value.charAt(start) == '\\' && value.charAt(start + 1) == ' ')
+            {
+                start += 2;
+            }
+
+            int end = value.length() - 1;
+            while (end - 1 > 0 && value.charAt(end - 1) == '\\' && value.charAt(end) == ' ')
+            {
+                end -= 2;
+            }
+
+            if (start > 0 || end < value.length() - 1)
+            {
+                value = value.substring(start, end + 1);
             }
         }
 
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java
index 1aeed15..6508f93 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x509/Extensions.java
@@ -43,8 +43,9 @@
 
     /**
      * Constructor from ASN1Sequence.
-     * <p/>
-     * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
+     * <p>
+     * The extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
+     * </p>
      */
     private Extensions(
         ASN1Sequence seq)
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
index eabf90e..53a4373 100644
--- a/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
+++ b/bcprov/src/main/java/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
@@ -63,78 +63,78 @@
     /**
      * Named curves base
      * <p>
-     * OID: 1.2.840.10045.1
+     * OID: 1.2.840.10045.3
      */
     static final ASN1ObjectIdentifier ellipticCurve = ansi_X9_62.branch("3");
 
     /**
      * Two Curves
      * <p>
-     * OID: 1.2.840.10045.1.0
+     * OID: 1.2.840.10045.3.0
      */
     static final ASN1ObjectIdentifier  cTwoCurve = ellipticCurve.branch("0");
 
-    /** Two Curve c2pnb163v1, OID: 1.2.840.10045.1.0.1 */
+    /** Two Curve c2pnb163v1, OID: 1.2.840.10045.3.0.1 */
     static final ASN1ObjectIdentifier c2pnb163v1 = cTwoCurve.branch("1");
-    /** Two Curve c2pnb163v2, OID: 1.2.840.10045.1.0.2 */
+    /** Two Curve c2pnb163v2, OID: 1.2.840.10045.3.0.2 */
     static final ASN1ObjectIdentifier c2pnb163v2 = cTwoCurve.branch("2");
-    /** Two Curve c2pnb163v3, OID: 1.2.840.10045.1.0.3 */
+    /** Two Curve c2pnb163v3, OID: 1.2.840.10045.3.0.3 */
     static final ASN1ObjectIdentifier c2pnb163v3 = cTwoCurve.branch("3");
-    /** Two Curve c2pnb176w1, OID: 1.2.840.10045.1.0.4 */
+    /** Two Curve c2pnb176w1, OID: 1.2.840.10045.3.0.4 */
     static final ASN1ObjectIdentifier c2pnb176w1 = cTwoCurve.branch("4");
-    /** Two Curve c2tnb191v1, OID: 1.2.840.10045.1.0.5 */
+    /** Two Curve c2tnb191v1, OID: 1.2.840.10045.3.0.5 */
     static final ASN1ObjectIdentifier c2tnb191v1 = cTwoCurve.branch("5");
-    /** Two Curve c2tnb191v2, OID: 1.2.840.10045.1.0.6 */
+    /** Two Curve c2tnb191v2, OID: 1.2.840.10045.3.0.6 */
     static final ASN1ObjectIdentifier c2tnb191v2 = cTwoCurve.branch("6");
-    /** Two Curve c2tnb191v3, OID: 1.2.840.10045.1.0.7 */
+    /** Two Curve c2tnb191v3, OID: 1.2.840.10045.3.0.7 */
     static final ASN1ObjectIdentifier c2tnb191v3 = cTwoCurve.branch("7");
-    /** Two Curve c2onb191v4, OID: 1.2.840.10045.1.0.8 */
+    /** Two Curve c2onb191v4, OID: 1.2.840.10045.3.0.8 */
     static final ASN1ObjectIdentifier c2onb191v4 = cTwoCurve.branch("8");
-    /** Two Curve c2onb191v5, OID: 1.2.840.10045.1.0.9 */
+    /** Two Curve c2onb191v5, OID: 1.2.840.10045.3.0.9 */
     static final ASN1ObjectIdentifier c2onb191v5 = cTwoCurve.branch("9");
-    /** Two Curve c2pnb208w1, OID: 1.2.840.10045.1.0.10 */
+    /** Two Curve c2pnb208w1, OID: 1.2.840.10045.3.0.10 */
     static final ASN1ObjectIdentifier c2pnb208w1 = cTwoCurve.branch("10");
-    /** Two Curve c2tnb239v1, OID: 1.2.840.10045.1.0.11 */
+    /** Two Curve c2tnb239v1, OID: 1.2.840.10045.3.0.11 */
     static final ASN1ObjectIdentifier c2tnb239v1 = cTwoCurve.branch("11");
-    /** Two Curve c2tnb239v2, OID: 1.2.840.10045.1.0.12 */
+    /** Two Curve c2tnb239v2, OID: 1.2.840.10045.3.0.12 */
     static final ASN1ObjectIdentifier c2tnb239v2 = cTwoCurve.branch("12");
-    /** Two Curve c2tnb239v3, OID: 1.2.840.10045.1.0.13 */
+    /** Two Curve c2tnb239v3, OID: 1.2.840.10045.3.0.13 */
     static final ASN1ObjectIdentifier c2tnb239v3 = cTwoCurve.branch("13");
-    /** Two Curve c2onb239v4, OID: 1.2.840.10045.1.0.14 */
+    /** Two Curve c2onb239v4, OID: 1.2.840.10045.3.0.14 */
     static final ASN1ObjectIdentifier c2onb239v4 = cTwoCurve.branch("14");
-    /** Two Curve c2onb239v5, OID: 1.2.840.10045.1.0.15 */
+    /** Two Curve c2onb239v5, OID: 1.2.840.10045.3.0.15 */
     static final ASN1ObjectIdentifier c2onb239v5 = cTwoCurve.branch("15");
-    /** Two Curve c2pnb272w1, OID: 1.2.840.10045.1.0.16 */
+    /** Two Curve c2pnb272w1, OID: 1.2.840.10045.3.0.16 */
     static final ASN1ObjectIdentifier c2pnb272w1 = cTwoCurve.branch("16");
-    /** Two Curve c2pnb304w1, OID: 1.2.840.10045.1.0.17 */
+    /** Two Curve c2pnb304w1, OID: 1.2.840.10045.3.0.17 */
     static final ASN1ObjectIdentifier c2pnb304w1 = cTwoCurve.branch("17");
-    /** Two Curve c2tnb359v1, OID: 1.2.840.10045.1.0.18 */
+    /** Two Curve c2tnb359v1, OID: 1.2.840.10045.3.0.18 */
     static final ASN1ObjectIdentifier c2tnb359v1 = cTwoCurve.branch("18");
-    /** Two Curve c2pnb368w1, OID: 1.2.840.10045.1.0.19 */
+    /** Two Curve c2pnb368w1, OID: 1.2.840.10045.3.0.19 */
     static final ASN1ObjectIdentifier c2pnb368w1 = cTwoCurve.branch("19");
-    /** Two Curve c2tnb431r1, OID: 1.2.840.10045.1.0.20 */
+    /** Two Curve c2tnb431r1, OID: 1.2.840.10045.3.0.20 */
     static final ASN1ObjectIdentifier c2tnb431r1 = cTwoCurve.branch("20");
 
     /**
      * Prime Curves
      * <p>
-     * OID: 1.2.840.10045.1.1
+     * OID: 1.2.840.10045.3.1
      */
     static final ASN1ObjectIdentifier primeCurve = ellipticCurve.branch("1");
 
-    /** Prime Curve prime192v1, OID: 1.2.840.10045.1.1.1 */
+    /** Prime Curve prime192v1, OID: 1.2.840.10045.3.1.1 */
     static final ASN1ObjectIdentifier prime192v1 = primeCurve.branch("1");
-    /** Prime Curve prime192v2, OID: 1.2.840.10045.1.1.2 */
+    /** Prime Curve prime192v2, OID: 1.2.840.10045.3.1.2 */
     static final ASN1ObjectIdentifier prime192v2 = primeCurve.branch("2");
-    /** Prime Curve prime192v3, OID: 1.2.840.10045.1.1.3 */
+    /** Prime Curve prime192v3, OID: 1.2.840.10045.3.1.3 */
     static final ASN1ObjectIdentifier prime192v3 = primeCurve.branch("3");
-    /** Prime Curve prime239v1, OID: 1.2.840.10045.1.1.4 */
+    /** Prime Curve prime239v1, OID: 1.2.840.10045.3.1.4 */
     static final ASN1ObjectIdentifier prime239v1 = primeCurve.branch("4");
-    /** Prime Curve prime239v2, OID: 1.2.840.10045.1.1.5 */
+    /** Prime Curve prime239v2, OID: 1.2.840.10045.3.1.5 */
     static final ASN1ObjectIdentifier prime239v2 = primeCurve.branch("5");
-    /** Prime Curve prime239v3, OID: 1.2.840.10045.1.1.6 */
+    /** Prime Curve prime239v3, OID: 1.2.840.10045.3.1.6 */
     static final ASN1ObjectIdentifier prime239v3 = primeCurve.branch("6");
-    /** Prime Curve prime256v1, OID: 1.2.840.10045.1.1.7 */
+    /** Prime Curve prime256v1, OID: 1.2.840.10045.3.1.7 */
     static final ASN1ObjectIdentifier prime256v1 = primeCurve.branch("7");
 
     /**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
index 8e41e49..39f59da 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/BufferedBlockCipher.java
@@ -141,7 +141,7 @@
     }
 
     /**
-     * process a single byte, producing an output block if neccessary.
+     * process a single byte, producing an output block if necessary.
      *
      * @param in the input byte.
      * @param out the space for any output that might be produced.
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
index c78b1a5..7ba71c7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
@@ -70,7 +70,7 @@
 	 * @param cipher
 	 *            The cipher to use for cryptographic operation.
 	 * @param fallback
-	 *            The fallback value, we don't to a arraycopy here.
+	 *            The fallback value, we don't do an arraycopy here.
 	 */
 	public PKCS1Encoding(
     	AsymmetricBlockCipher   cipher,
@@ -350,7 +350,8 @@
          * If the length of the expected plaintext is known, we use a constant-time decryption.
          * If the decryption fails, we return a random value.
          */
-		if (this.pLen != -1) {
+		if (this.pLen != -1)
+        {
     		return this.decodeBlockOrRandom(in, inOff, inLen);
     	}
     	
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java
index 5d316ac..6d3e5ac 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESWrapEngine.java
@@ -9,8 +9,21 @@
 public class AESWrapEngine
     extends RFC3394WrapEngine
 {
+    /**
+     * Create a regular AESWrapEngine specifying the encrypt for wrapping, decrypt for unwrapping.
+     */
     public AESWrapEngine()
     {
         super(new AESEngine());
     }
+
+    /**
+     * Create an AESWrapEngine where the underlying cipher is set to decrypt for wrapping, encrypt for unwrapping.
+     *
+     * @param useReverseDirection true if underlying cipher should be used in decryption mode, false otherwise.
+     */
+    public AESWrapEngine(boolean useReverseDirection)
+    {
+        super(new AESEngine(), useReverseDirection);
+    }
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
index cfd86fb..d2886e7 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
@@ -21,6 +21,7 @@
     implements Wrapper
 {
     private BlockCipher     engine;
+    private boolean         wrapCipherMode;
     private KeyParameter    param;
     private boolean         forWrapping;
 
@@ -28,9 +29,26 @@
                               (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6,
                               (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6 };
 
+    /**
+     * Create a RFC 3394 WrapEngine specifying the encrypt for wrapping, decrypt for unwrapping.
+     *
+     * @param engine the block cipher to be used for wrapping.
+     */
     public RFC3394WrapEngine(BlockCipher engine)
     {
+        this(engine, false);
+    }
+
+    /**
+     * Create a RFC 3394 WrapEngine specifying the direction for wrapping and unwrapping..
+     *
+     * @param engine the block cipher to be used for wrapping.
+     * @param useReverseDirection true if engine should be used in decryption mode for wrapping, false otherwise.
+     */
+    public RFC3394WrapEngine(BlockCipher engine, boolean useReverseDirection)
+    {
         this.engine = engine;
+        this.wrapCipherMode = (useReverseDirection) ? false : true;
     }
 
     public void init(
@@ -87,7 +105,7 @@
         System.arraycopy(iv, 0, block, 0, iv.length);
         System.arraycopy(in, inOff, block, iv.length, inLen);
 
-        engine.init(true, param);
+        engine.init(wrapCipherMode, param);
 
         for (int j = 0; j != 6; j++)
         {
@@ -140,7 +158,7 @@
         System.arraycopy(in, inOff, a, 0, iv.length);
         System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length);
 
-        engine.init(false, param);
+        engine.init(!wrapCipherMode, param);
 
         n = n - 1;
 
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
index 928c6a6..7277045 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
@@ -1,5 +1,7 @@
 package org.bouncycastle.crypto.generators;
 
+import java.math.BigInteger;
+
 import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
 import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
 import org.bouncycastle.crypto.KeyGenerationParameters;
@@ -8,8 +10,6 @@
 import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
 import org.bouncycastle.math.ec.WNafUtil;
 
-import java.math.BigInteger;
-
 /**
  * an RSA key pair generator.
  */
@@ -27,96 +27,118 @@
 
     public AsymmetricCipherKeyPair generateKeyPair()
     {
-        BigInteger p, q, n, d, e, pSub1, qSub1, phi;
+        AsymmetricCipherKeyPair result = null;
+        boolean done = false;
 
-        //
-        // p and q values should have a length of half the strength in bits
-        //
-        int strength = param.getStrength();
-        int qBitlength = strength >>> 1;
-        int pBitlength = strength - qBitlength;
-        int mindiffbits = strength / 3;
-        int minWeight = strength >>> 2;
-
-        e = param.getPublicExponent();
-
-        // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
-        // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
-
-        p = chooseRandomPrime(pBitlength, e);
-
-        //
-        // generate a modulus of the required length
-        //
-        for (;;)
+        while (!done)
         {
-            q = chooseRandomPrime(qBitlength, e);
+            BigInteger p, q, n, d, e, pSub1, qSub1, phi, lcm, dLowerBound;
 
-            // p and q should not be too close together (or equal!)
-            BigInteger diff = q.subtract(p).abs();
-            if (diff.bitLength() < mindiffbits)
+            //
+            // p and q values should have a length of half the strength in bits
+            //
+            int strength = param.getStrength();
+            int pbitlength = (strength + 1) / 2;
+            int qbitlength = strength - pbitlength;
+            int mindiffbits = strength / 3;
+            int minWeight = strength >> 2;
+
+            e = param.getPublicExponent();
+
+            // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
+            // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
+
+            p = chooseRandomPrime(pbitlength, e);
+
+            //
+            // generate a modulus of the required length
+            //
+            for (;;)
+            {
+                q = chooseRandomPrime(qbitlength, e);
+
+                // p and q should not be too close together (or equal!)
+                BigInteger diff = q.subtract(p).abs();
+                if (diff.bitLength() < mindiffbits)
+                {
+                    continue;
+                }
+
+                //
+                // calculate the modulus
+                //
+                n = p.multiply(q);
+
+                if (n.bitLength() != strength)
+                {
+                    //
+                    // if we get here our primes aren't big enough, make the largest
+                    // of the two p and try again
+                    //
+                    p = p.max(q);
+                    continue;
+                }
+
+	            /*
+	             * Require a minimum weight of the NAF representation, since low-weight composites may
+	             * be weak against a version of the number-field-sieve for factoring.
+	             *
+	             * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+	             */
+                if (WNafUtil.getNafWeight(n) < minWeight)
+                {
+                    p = chooseRandomPrime(pbitlength, e);
+                    continue;
+                }
+
+                break;
+            }
+
+            if (p.compareTo(q) < 0)
+            {
+                phi = p;
+                p = q;
+                q = phi;
+            }
+
+            pSub1 = p.subtract(ONE);
+            qSub1 = q.subtract(ONE);
+            phi = pSub1.multiply(qSub1);
+            lcm = phi.divide(pSub1.gcd(qSub1));
+
+            //
+            // calculate the private exponent
+            //
+            d = e.modInverse(lcm);
+
+            // if d is less than or equal to dLowerBound, we need to start over
+            // also, for backward compatibility, if d is not the same as
+            // e.modInverse(phi), we need to start over
+
+            if (d.bitLength() <= qbitlength || !d.equals(e.modInverse(phi)))
             {
                 continue;
             }
-
-            //
-            // calculate the modulus
-            //
-            n = p.multiply(q);
-
-            if (n.bitLength() != strength) 
+            else
             {
-                //
-                // if we get here our primes aren't big enough, make the largest
-                // of the two p and try again
-                //
-                p = p.max(q);
-                continue;
-            } 
-
-            /*
-             * Require a minimum weight of the NAF representation, since low-weight composites may
-             * be weak against a version of the number-field-sieve for factoring.
-             * 
-             * See "The number field sieve for integers of low weight", Oliver Schirokauer.
-             */
-            if (WNafUtil.getNafWeight(n) < minWeight)
-            {
-                p = chooseRandomPrime(pBitlength, e);
-                continue;
+                done = true;
             }
 
-            break;
+            //
+            // calculate the CRT factors
+            //
+            BigInteger dP, dQ, qInv;
+
+            dP = d.remainder(pSub1);
+            dQ = d.remainder(qSub1);
+            qInv = q.modInverse(p);
+
+            result = new AsymmetricCipherKeyPair(
+                new RSAKeyParameters(false, n, e),
+                new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
         }
 
-        if (p.compareTo(q) < 0)
-        {
-            phi = p;
-            p = q;
-            q = phi;
-        }
-
-        pSub1 = p.subtract(ONE);
-        qSub1 = q.subtract(ONE);
-        phi = pSub1.multiply(qSub1);
-
-        //
-        // calculate the private exponent
-        //
-        d = e.modInverse(phi);
-
-        //
-        // calculate the CRT factors
-        //
-        BigInteger dP, dQ, qInv;
-
-        dP = d.remainder(pSub1);
-        dQ = d.remainder(qSub1);
-        qInv = q.modInverse(p);
-
-        return new AsymmetricCipherKeyPair(
-            new RSAKeyParameters(false, n, e),
-            new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
+        return result;
     }
 
     /**
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
index 5388b40..64b076d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
@@ -4,6 +4,7 @@
 import org.bouncycastle.crypto.BufferedBlockCipher;
 import org.bouncycastle.crypto.DataLengthException;
 import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.StreamBlockCipher;
 
 /**
  * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
@@ -22,9 +23,8 @@
     public CTSBlockCipher(
         BlockCipher     cipher)
     {
-        if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher) || (cipher instanceof SICBlockCipher))
+        if (cipher instanceof StreamBlockCipher)
         {
-            // TODO: This is broken - need to introduce marker interface to differentiate block cipher primitive from mode?
             throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
         }
 
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 024eb86..93f0fe9 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
@@ -7,6 +7,7 @@
 import org.bouncycastle.crypto.OutputLengthException;
 import org.bouncycastle.crypto.modes.gcm.GCMExponentiator;
 import org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
+import org.bouncycastle.crypto.modes.gcm.GCMUtil;
 import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
 import org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
 import org.bouncycastle.crypto.params.AEADParameters;
@@ -366,7 +367,7 @@
             // Find the difference between the AAD hashes
             if (atLengthPre > 0)
             {
-                xor(S_at, S_atPre);
+                GCMUtil.xor(S_at, S_atPre);
             }
 
             // Number of cipher-text blocks produced
@@ -382,10 +383,10 @@
             exp.exponentiateX(c, H_c);
 
             // Carry the difference forward
-            multiply(S_at, H_c);
+            GCMUtil.multiply(S_at, H_c);
 
             // Adjust the current hash
-            xor(S, S_at);
+            GCMUtil.xor(S, S_at);
         }
 
         // Final gHASH
@@ -398,7 +399,7 @@
         // T = MSBt(GCTRk(J0,S))
         byte[] tag = new byte[BLOCK_SIZE];
         cipher.processBlock(J0, 0, tag, 0);
-        xor(tag, S);
+        GCMUtil.xor(tag, S);
 
         int resultLen = extra;
 
@@ -473,7 +474,7 @@
     {
         byte[] tmp = getNextCounterBlock();
 
-        xor(tmp, block);
+        GCMUtil.xor(tmp, block);
         System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE);
 
         gHASHBlock(S, forEncryption ? tmp : block);
@@ -485,7 +486,7 @@
     {
         byte[] tmp = getNextCounterBlock();
 
-        xor(tmp, buf, off, len);
+        GCMUtil.xor(tmp, buf, off, len);
         System.arraycopy(tmp, 0, out, outOff, len);
 
         gHASHPartial(S, forEncryption ? tmp : buf, 0, len);
@@ -504,13 +505,13 @@
 
     private void gHASHBlock(byte[] Y, byte[] b)
     {
-        xor(Y, b);
+        GCMUtil.xor(Y, b);
         multiplier.multiplyH(Y);
     }
 
     private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
     {
-        xor(Y, b, off, len);
+        GCMUtil.xor(Y, b, off, len);
         multiplier.multiplyH(Y);
     }
 
@@ -532,65 +533,4 @@
         cipher.processBlock(counter, 0, tmp, 0);
         return tmp;
     }
-
-    private static void multiply(byte[] block, byte[] val)
-    {
-        byte[] tmp = Arrays.clone(block);
-        byte[] c = new byte[16];
-
-        for (int i = 0; i < 16; ++i)
-        {
-            byte bits = val[i];
-            for (int j = 7; j >= 0; --j)
-            {
-                if ((bits & (1 << j)) != 0)
-                {
-                    xor(c, tmp);
-                }
-
-                boolean lsb = (tmp[15] & 1) != 0;
-                shiftRight(tmp);
-                if (lsb)
-                {
-                    // R = new byte[]{ 0xe1, ... };
-//                    xor(v, R);
-                    tmp[0] ^= (byte)0xe1;
-                }
-            }
-        }
-
-        System.arraycopy(c, 0, block, 0, 16);
-    }
-
-    private static void shiftRight(byte[] block)
-    {
-        int i = 0;
-        int bit = 0;
-        for (;;)
-        {
-            int b = block[i] & 0xff;
-            block[i] = (byte) ((b >>> 1) | bit);
-            if (++i == 16)
-            {
-                break;
-            }
-            bit = (b & 1) << 7;
-        }
-    }
-
-    private static void xor(byte[] block, byte[] val)
-    {
-        for (int i = 15; i >= 0; --i)
-        {
-            block[i] ^= val[i];
-        }
-    }
-
-    private static void xor(byte[] block, byte[] val, int off, int len)
-    {
-        while (len-- > 0)
-        {
-            block[len] ^= val[off + len];
-        }
-    }
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
index 5dd47ae..fbc8bf4 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/SICBlockCipher.java
@@ -106,6 +106,27 @@
         return rv;
     }
 
+    private void incrementCounterPow2(int pow2Div8)
+    {
+        // increment counter by 1 << 8 * pow2Div8
+        for (int i = counter.length - (1 + pow2Div8); i >= 0 && ++counter[i] == 0; i--)
+        {
+            ; // do nothing - pre-increment and test for 0 in counter does the job.
+        }
+    }
+
+    private void incrementCounter(int offSet)
+    {
+        byte old = counter[counter.length - 1];
+
+        counter[counter.length - 1] += offSet;
+
+        if (old != 0 && counter[counter.length - 1] < old)
+        {
+            incrementCounterPow2(1);
+        }
+    }
+
     private void incrementCounter()
     {
         // increment counter by 1.
@@ -115,6 +136,33 @@
         }
     }
 
+    private void decrementCounterPow2(int pow2Div8)
+    {
+        if (counter[pow2Div8] == 0)
+        {
+            boolean nonZero = false;
+
+            for (int i = counter.length - (1 + pow2Div8); i > 0; i--)
+            {
+                if (counter[i] != 0)
+                {
+                    nonZero = true;
+                }
+            }
+
+            if (!nonZero)
+            {
+                throw new IllegalStateException("attempt to reduce counter past zero.");
+            }
+        }
+
+        // decrement counter by 1.
+        for (int i = counter.length - (1 + pow2Div8); i >= 0 && --counter[i] == -1; i--)
+        {
+            ;
+        }
+    }
+
     private void decrementCounter()
     {
         if (counter[0] == 0)
@@ -148,9 +196,27 @@
         {
             long numBlocks = (n + byteCount) / blockSize;
 
-            for (long i = 0; i != numBlocks; i++)
+            if (numBlocks > 255)
             {
-                incrementCounter();
+                long gap = numBlocks;
+
+                for (int i = 5; i >= 1; i--)
+                {
+                    long diff = 1L << (8 * i);
+
+                    while (gap >= diff)
+                    {
+                        incrementCounterPow2(i);
+
+                        gap -= diff;
+                    }
+                }
+
+                incrementCounter((int)gap);
+            }
+            else
+            {
+                incrementCounter((int)numBlocks);
             }
 
             byteCount = (int)((n + byteCount) - (blockSize * numBlocks));
@@ -159,9 +225,33 @@
         {
             long numBlocks = (-n - byteCount) / blockSize;
 
-            for (long i = 0; i != numBlocks; i++)
+            if (numBlocks > 255)
             {
-                decrementCounter();
+                long gap = numBlocks;
+
+                for (int i = 5; i >= 1; i--)
+                {
+                    long diff = 1L << (8 * i);
+
+                    while (gap > diff)
+                    {
+                        decrementCounterPow2(i);
+
+                        gap -= diff;
+                    }
+                }
+
+                for (long i = 0; i != gap; i++)
+                {
+                    decrementCounter();
+                }
+            }
+            else
+            {
+                for (long i = 0; i != numBlocks; i++)
+                {
+                    decrementCounter();
+                }
             }
 
             int gap = (int)(byteCount + n + (blockSize * numBlocks));
@@ -209,7 +299,7 @@
 
         for (int i = res.length - 1; i >= 1; i--)
         {
-            int v = (res[i] - IV[i]);
+            int v = (res[i] & 0xff) - (IV[i] & 0xff);
 
             if (v < 0)
             {
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
index f5ed7e4..58f4078 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
@@ -1,13 +1,11 @@
 package org.bouncycastle.crypto.modes.gcm;
 
-import org.bouncycastle.util.Arrays;
 import org.bouncycastle.util.Pack;
 
-abstract class GCMUtil
+public abstract class GCMUtil
 {
     private static final int E1 = 0xe1000000;
-    private static final byte E1B = (byte)0xe1;
-    private static final long E1L = (E1 & 0xFFFFFFFFL) << 24;
+    private static final long E1L = (E1 & 0xFFFFFFFFL) << 32;
 
     private static int[] generateLookup()
     {
@@ -31,170 +29,151 @@
 
     private static final int[] LOOKUP = generateLookup();
 
-    static byte[] oneAsBytes()
+    public static byte[] oneAsBytes()
     {
         byte[] tmp = new byte[16];
         tmp[0] = (byte)0x80;
         return tmp;
     }
 
-    static int[] oneAsInts()
+    public static int[] oneAsInts()
     {
         int[] tmp = new int[4];
         tmp[0] = 1 << 31;
         return tmp;
     }
 
-    static long[] oneAsLongs()
+    public static long[] oneAsLongs()
     {
         long[] tmp = new long[2];
         tmp[0] = 1L << 63;
         return tmp;
     }
 
-    static byte[] asBytes(int[] x)
+    public static byte[] asBytes(int[] x)
     {
         byte[] z = new byte[16];
         Pack.intToBigEndian(x, z, 0);
         return z;
     }
 
-    static void asBytes(int[] x, byte[] z)
+    public static void asBytes(int[] x, byte[] z)
     {
         Pack.intToBigEndian(x, z, 0);
     }
 
-    static byte[] asBytes(long[] x)
+    public static byte[] asBytes(long[] x)
     {
         byte[] z = new byte[16];
         Pack.longToBigEndian(x, z, 0);
         return z;
     }
 
-    static void asBytes(long[] x, byte[] z)
+    public static void asBytes(long[] x, byte[] z)
     {
         Pack.longToBigEndian(x, z, 0);
     }
 
-    static int[] asInts(byte[] x)
+    public static int[] asInts(byte[] x)
     {
         int[] z = new int[4];
         Pack.bigEndianToInt(x, 0, z);
         return z;
     }
 
-    static void asInts(byte[] x, int[] z)
+    public static void asInts(byte[] x, int[] z)
     {
         Pack.bigEndianToInt(x, 0, z);
     }
 
-    static long[] asLongs(byte[] x)
+    public static long[] asLongs(byte[] x)
     {
         long[] z = new long[2];
         Pack.bigEndianToLong(x, 0, z);
         return z;
     }
 
-    static void asLongs(byte[] x, long[] z)
+    public static void asLongs(byte[] x, long[] z)
     {
         Pack.bigEndianToLong(x, 0, z);
     }
 
-    static void multiply(byte[] x, byte[] y)
+    public static void multiply(byte[] x, byte[] y)
     {
-        byte[] r0 = Arrays.clone(x);
-        byte[] r1 = new byte[16];
-
-        for (int i = 0; i < 16; ++i)
-        {
-            byte bits = y[i];
-            for (int j = 7; j >= 0; --j)
-            {
-                if ((bits & (1 << j)) != 0)
-                {
-                    xor(r1, r0);
-                }
-
-                if (shiftRight(r0) != 0)
-                {
-                    r0[0] ^= E1B;
-                }
-            }
-        }
-
-        System.arraycopy(r1, 0, x, 0, 16);
+        int[] t1 = GCMUtil.asInts(x);
+        int[] t2 = GCMUtil.asInts(y);
+        GCMUtil.multiply(t1, t2);
+        GCMUtil.asBytes(t1, x);
     }
 
-    static void multiply(int[] x, int[] y)
+    public static void multiply(int[] x, int[] y)
     {
-        int[] r0 = Arrays.clone(x);
-        int[] r1 = new int[4];
-
+        int r00 = x[0], r01 = x[1], r02 = x[2], r03 = x[3];
+        int r10 = 0, r11 = 0, r12 = 0, r13 = 0;
+        
         for (int i = 0; i < 4; ++i)
         {
             int bits = y[i];
-            for (int j = 31; j >= 0; --j)
+            for (int j = 0; j < 32; ++j)
             {
-                if ((bits & (1 << j)) != 0)
-                {
-                    xor(r1, r0);
-                }
+                int m1 = bits >> 31; bits <<= 1;
+                r10 ^= (r00 & m1);
+                r11 ^= (r01 & m1);
+                r12 ^= (r02 & m1);
+                r13 ^= (r03 & m1);
 
-                if (shiftRight(r0) != 0)
-                {
-                    r0[0] ^= E1;
-                }
+                int m2 = (r03 << 31) >> 8;
+                r03 = (r03 >>> 1) | (r02 << 63);
+                r02 = (r02 >>> 1) | (r01 << 63);
+                r01 = (r01 >>> 1) | (r00 << 63);
+                r00 = (r00 >>> 1) ^ (m2 & E1);
             }
         }
 
-        System.arraycopy(r1, 0, x, 0, 4);
+        x[0] = r10;
+        x[1] = r11;
+        x[2] = r12;
+        x[3] = r13;
     }
 
-    static void multiply(long[] x, long[] y)
+    public static void multiply(long[] x, long[] y)
     {
-        long[] r0 = new long[]{ x[0], x[1] };
-        long[] r1 = new long[2];
+        long r00 = x[0], r01 = x[1], r10 = 0, r11 = 0;
 
         for (int i = 0; i < 2; ++i)
         {
             long bits = y[i];
-            for (int j = 63; j >= 0; --j)
+            for (int j = 0; j < 64; ++j)
             {
-                if ((bits & (1L << j)) != 0)
-                {
-                    xor(r1, r0);
-                }
+                long m1 = bits >> 63; bits <<= 1;
+                r10 ^= (r00 & m1);
+                r11 ^= (r01 & m1);
 
-                if (shiftRight(r0) != 0)
-                {
-                    r0[0] ^= E1L;
-                }
+                long m2 = (r01 << 63) >> 8;
+                r01 = (r01 >>> 1) | (r00 << 63);
+                r00 = (r00 >>> 1) ^ (m2 & E1L);
             }
         }
 
-        x[0] = r1[0];
-        x[1] = r1[1];
+        x[0] = r10;
+        x[1] = r11;
     }
 
     // P is the value with only bit i=1 set
-    static void multiplyP(int[] x)
+    public static void multiplyP(int[] x)
     {
-        if (shiftRight(x) != 0)
-        {
-            x[0] ^= E1;
-        }
+        int m = shiftRight(x) >> 8;
+        x[0] ^= (m & E1);
     }
 
-    static void multiplyP(int[] x, int[] y)
+    public static void multiplyP(int[] x, int[] z)
     {
-        if (shiftRight(x, y) != 0)
-        {
-            y[0] ^= E1;
-        }
+        int m = shiftRight(x, z) >> 8;
+        z[0] ^= (m & E1);
     }
 
     // P is the value with only bit i=1 set
-    static void multiplyP8(int[] x)
+    public static void multiplyP8(int[] x)
     {
 //        for (int i = 8; i != 0; --i)
 //        {
@@ -205,74 +184,12 @@
         x[0] ^= LOOKUP[c >>> 24];
     }
 
-    static void multiplyP8(int[] x, int[] y)
+    public static void multiplyP8(int[] x, int[] y)
     {
         int c = shiftRightN(x, 8, y);
         y[0] ^= LOOKUP[c >>> 24];
     }
 
-    static byte shiftRight(byte[] x)
-    {
-//        int c = 0;
-//        for (int i = 0; i < 16; ++i)
-//        {
-//            int b = x[i] & 0xff;
-//            x[i] = (byte)((b >>> 1) | c);
-//            c = (b & 1) << 7;
-//        }
-//        return (byte)c;
-
-        int i = 0, c = 0;
-        do
-        {
-            int b = x[i] & 0xff;
-            x[i++] = (byte)((b >>> 1) | c);
-            c = (b & 1) << 7;
-            b = x[i] & 0xff;
-            x[i++] = (byte)((b >>> 1) | c);
-            c = (b & 1) << 7;
-            b = x[i] & 0xff;
-            x[i++] = (byte)((b >>> 1) | c);
-            c = (b & 1) << 7;
-            b = x[i] & 0xff;
-            x[i++] = (byte)((b >>> 1) | c);
-            c = (b & 1) << 7;
-        }
-        while (i < 16);
-        return (byte)c;
-    }
-
-    static byte shiftRight(byte[] x, byte[] z)
-    {
-//        int c = 0;
-//        for (int i = 0; i < 16; ++i)
-//        {
-//            int b = x[i] & 0xff;
-//            z[i] = (byte) ((b >>> 1) | c);
-//            c = (b & 1) << 7;
-//        }
-//        return (byte) c;
-
-        int i = 0, c = 0;
-        do
-        {
-            int b = x[i] & 0xff;
-            z[i++] = (byte)((b >>> 1) | c);
-            c = (b & 1) << 7;
-            b = x[i] & 0xff;
-            z[i++] = (byte)((b >>> 1) | c);
-            c = (b & 1) << 7;
-            b = x[i] & 0xff;
-            z[i++] = (byte)((b >>> 1) | c);
-            c = (b & 1) << 7;
-            b = x[i] & 0xff;
-            z[i++] = (byte)((b >>> 1) | c);
-            c = (b & 1) << 7;
-        }
-        while (i < 16);
-        return (byte)c;
-    }
-
     static int shiftRight(int[] x)
     {
 //        int c = 0;
@@ -393,7 +310,7 @@
         return b << nInv;
     }
 
-    static void xor(byte[] x, byte[] y)
+    public static void xor(byte[] x, byte[] y)
     {
         int i = 0;
         do
@@ -406,15 +323,15 @@
         while (i < 16);
     }
 
-    static void xor(byte[] x, byte[] y, int yOff, int yLen)
+    public static void xor(byte[] x, byte[] y, int yOff, int yLen)
     {
-        while (yLen-- > 0)
+        while (--yLen >= 0)
         {
             x[yLen] ^= y[yOff + yLen];
         }
     }
 
-    static void xor(byte[] x, byte[] y, byte[] z)
+    public static void xor(byte[] x, byte[] y, byte[] z)
     {
         int i = 0;
         do
@@ -427,7 +344,7 @@
         while (i < 16);
     }
 
-    static void xor(int[] x, int[] y)
+    public static void xor(int[] x, int[] y)
     {
         x[0] ^= y[0];
         x[1] ^= y[1];
@@ -435,7 +352,7 @@
         x[3] ^= y[3];
     }
 
-    static void xor(int[] x, int[] y, int[] z)
+    public static void xor(int[] x, int[] y, int[] z)
     {
         z[0] = x[0] ^ y[0];
         z[1] = x[1] ^ y[1];
@@ -443,13 +360,13 @@
         z[3] = x[3] ^ y[3];
     }
 
-    static void xor(long[] x, long[] y)
+    public static void xor(long[] x, long[] y)
     {
         x[0] ^= y[0];
         x[1] ^= y[1];
     }
 
-    static void xor(long[] x, long[] y, long[] z)
+    public static void xor(long[] x, long[] y, long[] z)
     {
         z[0] = x[0] ^ y[0];
         z[1] = x[1] ^ y[1];
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
index 93b149f..8b30398 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/paddings/PKCS7Padding.java
@@ -57,19 +57,20 @@
         throws InvalidCipherTextException
     {
         int count = in[in.length - 1] & 0xff;
+        byte countAsbyte = (byte)count;
 
-        if (count > in.length || count == 0)
+        // constant time version
+        boolean failed = (count > in.length | count == 0);
+
+        for (int i = 0; i < in.length; i++)
+        {
+            failed |= (in.length - i <= count) & (in[i] != countAsbyte);
+        }
+
+        if (failed)
         {
             throw new InvalidCipherTextException("pad block corrupted");
         }
-        
-        for (int i = 1; i <= count; i++)
-        {
-            if (in[in.length - i] != count)
-            {
-                throw new InvalidCipherTextException("pad block corrupted");
-            }
-        }
 
         return count;
     }
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
index b679287..fec6dfd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/params/DHParameters.java
@@ -84,8 +84,7 @@
     {
         if (l != 0)
         {
-            BigInteger bigL = BigInteger.valueOf(2L ^ (l - 1));
-            if (bigL.compareTo(p) == 1)
+            if (l > p.bitLength())
             {
                 throw new IllegalArgumentException("when l value specified, it must satisfy 2^(l-1) <= p");
             }
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
index f3614f3..44f838b 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/DSASigner.java
@@ -80,32 +80,28 @@
         byte[] message)
     {
         DSAParameters   params = key.getParameters();
-        BigInteger      m = calculateE(params.getQ(), message);
+        BigInteger      q = params.getQ();
+        BigInteger      m = calculateE(q, message);
+        BigInteger      x = ((DSAPrivateKeyParameters)key).getX();
 
         if (kCalculator.isDeterministic())
         {
-            kCalculator.init(params.getQ(), ((DSAPrivateKeyParameters)key).getX(), message);
+            kCalculator.init(q, x, message);
         }
         else
         {
-            kCalculator.init(params.getQ(), random);
+            kCalculator.init(q, random);
         }
 
         BigInteger  k = kCalculator.nextK();
 
-        BigInteger  r = params.getG().modPow(k, params.getP()).mod(params.getQ());
+        BigInteger  r = params.getG().modPow(k, params.getP()).mod(q);
 
-        k = k.modInverse(params.getQ()).multiply(
-                    m.add(((DSAPrivateKeyParameters)key).getX().multiply(r)));
+        k = k.modInverse(q).multiply(m.add(x.multiply(r)));
 
-        BigInteger  s = k.mod(params.getQ());
+        BigInteger  s = k.mod(q);
 
-        BigInteger[]  res = new BigInteger[2];
-
-        res[0] = r;
-        res[1] = s;
-
-        return res;
+        return new BigInteger[]{ r, s };
     }
 
     /**
@@ -119,28 +115,30 @@
         BigInteger  s)
     {
         DSAParameters   params = key.getParameters();
-        BigInteger      m = calculateE(params.getQ(), message);
+        BigInteger      q = params.getQ();
+        BigInteger      m = calculateE(q, message);
         BigInteger      zero = BigInteger.valueOf(0);
 
-        if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
+        if (zero.compareTo(r) >= 0 || q.compareTo(r) <= 0)
         {
             return false;
         }
 
-        if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
+        if (zero.compareTo(s) >= 0 || q.compareTo(s) <= 0)
         {
             return false;
         }
 
-        BigInteger  w = s.modInverse(params.getQ());
+        BigInteger  w = s.modInverse(q);
 
-        BigInteger  u1 = m.multiply(w).mod(params.getQ());
-        BigInteger  u2 = r.multiply(w).mod(params.getQ());
+        BigInteger  u1 = m.multiply(w).mod(q);
+        BigInteger  u2 = r.multiply(w).mod(q);
 
-        u1 = params.getG().modPow(u1, params.getP());
-        u2 = ((DSAPublicKeyParameters)key).getY().modPow(u2, params.getP());
+        BigInteger p = params.getP();
+        u1 = params.getG().modPow(u1, p);
+        u2 = ((DSAPublicKeyParameters)key).getY().modPow(u2, p);
 
-        BigInteger  v = u1.multiply(u2).mod(params.getP()).mod(params.getQ());
+        BigInteger  v = u1.multiply(u2).mod(p).mod(q);
 
         return v.equals(r);
     }
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
index 2a32278..a8ef959 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RSADigestSigner.java
@@ -224,6 +224,8 @@
         }
         else
         {
+            Arrays.constantTimeAreEqual(expected, expected);  // keep time "steady".
+
             return false;
         }
     }
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
index bbd8cda..6a69308 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/signers/RandomDSAKCalculator.java
@@ -3,7 +3,7 @@
 import java.math.BigInteger;
 import java.security.SecureRandom;
 
-class RandomDSAKCalculator
+public class RandomDSAKCalculator
     implements DSAKCalculator
 {
     private static final BigInteger ZERO = BigInteger.valueOf(0);
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12StoreParameter.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12StoreParameter.java
new file mode 100644
index 0000000..b53eca5
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKCS12StoreParameter.java
@@ -0,0 +1,62 @@
+package org.bouncycastle.jcajce;
+
+import java.io.OutputStream;
+import java.security.KeyStore;
+import java.security.KeyStore.LoadStoreParameter;
+import java.security.KeyStore.ProtectionParameter;
+
+/**
+ * LoadStoreParameter to allow for additional config with PKCS12 files.
+ * <p>
+ * Note: if you want a straight DER encoding of a PKCS#12 file you should use this.
+ * </p>
+ */
+public class PKCS12StoreParameter
+    implements LoadStoreParameter
+{
+    private final OutputStream out;
+    private final ProtectionParameter protectionParameter;
+    private final boolean forDEREncoding;
+
+    public PKCS12StoreParameter(OutputStream out, char[] password)
+    {
+        this(out, password, false);
+    }
+
+    public PKCS12StoreParameter(OutputStream out, ProtectionParameter protectionParameter)
+    {
+        this(out, protectionParameter, false);
+    }
+
+    public PKCS12StoreParameter(OutputStream out, char[] password, boolean forDEREncoding)
+    {
+        this(out, new KeyStore.PasswordProtection(password), forDEREncoding);
+    }
+
+    public PKCS12StoreParameter(OutputStream out, ProtectionParameter protectionParameter, boolean forDEREncoding)
+    {
+        this.out = out;
+        this.protectionParameter = protectionParameter;
+        this.forDEREncoding = forDEREncoding;
+    }
+
+    public OutputStream getOutputStream()
+    {
+        return out;
+    }
+
+    public ProtectionParameter getProtectionParameter()
+    {
+        return protectionParameter;
+    }
+
+    /**
+     * Return whether the KeyStore used with this parameter should be DER encoded on saving.
+     *
+     * @return true for straight DER encoding, false otherwise,
+     */
+    public boolean isForDEREncoding()
+    {
+        return forDEREncoding;
+    }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStore.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStore.java
new file mode 100644
index 0000000..b344720
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStore.java
@@ -0,0 +1,15 @@
+package org.bouncycastle.jcajce;
+
+import java.security.cert.CRL;
+import java.util.Collection;
+
+import org.bouncycastle.util.Selector;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.util.StoreException;
+
+public interface PKIXCRLStore<T extends CRL>
+    extends Store<T>
+{
+    Collection<T> getMatches(Selector<T> selector)
+        throws StoreException;
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStoreSelector.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStoreSelector.java
new file mode 100644
index 0000000..9c68433
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCRLStoreSelector.java
@@ -0,0 +1,313 @@
+package org.bouncycastle.jcajce;
+
+import java.math.BigInteger;
+import java.security.cert.CRL;
+import java.security.cert.CRLSelector;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509CRLSelector;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.Selector;
+
+/**
+ * This class is a Selector implementation for X.509 certificate revocation
+ * lists.
+ * 
+ * @see org.bouncycastle.util.Selector
+ */
+public class PKIXCRLStoreSelector<T extends CRL>
+    implements Selector<T>
+{
+    public static class Builder
+    {
+        private final CRLSelector baseSelector;
+
+        private boolean deltaCRLIndicator = false;
+        private boolean completeCRLEnabled = false;
+        private BigInteger maxBaseCRLNumber = null;
+        private byte[] issuingDistributionPoint = null;
+        private boolean issuingDistributionPointEnabled = false;
+
+        public Builder(CRLSelector certSelector)
+        {
+            this.baseSelector = (CRLSelector)certSelector.clone();
+        }
+
+
+        /**
+         * If set to <code>true</code> only complete CRLs are returned.
+         * <p>
+         * {@link #setCompleteCRLEnabled(boolean)} and
+         * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other.
+         *
+         * @param completeCRLEnabled <code>true</code> if only complete CRLs
+         *            should be returned.
+         */
+        public Builder setCompleteCRLEnabled(boolean completeCRLEnabled)
+        {
+            this.completeCRLEnabled = completeCRLEnabled;
+
+            return this;
+        }
+
+        /**
+         * If this is set to <code>true</code> the CRL reported contains the delta
+         * CRL indicator CRL extension.
+         * <p>
+         * {@link #setCompleteCRLEnabled(boolean)} and
+         * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other.
+         *
+         * @param deltaCRLIndicator <code>true</code> if the delta CRL indicator
+         *            extension must be in the CRL.
+         */
+        public Builder setDeltaCRLIndicatorEnabled(boolean deltaCRLIndicator)
+        {
+            this.deltaCRLIndicator = deltaCRLIndicator;
+
+            return this;
+        }
+
+        /**
+         * Sets the maximum base CRL number. Setting to <code>null</code> disables
+         * this cheack.
+         * <p>
+         * This is only meaningful for delta CRLs. Complete CRLs must have a CRL
+         * number which is greater or equal than the base number of the
+         * corresponding CRL.
+         *
+         * @param maxBaseCRLNumber The maximum base CRL number to set.
+         */
+        public void setMaxBaseCRLNumber(BigInteger maxBaseCRLNumber)
+        {
+            this.maxBaseCRLNumber = maxBaseCRLNumber;
+        }
+
+        /**
+         * Enables or disables the issuing distribution point check.
+         *
+         * @param issuingDistributionPointEnabled <code>true</code> to enable the
+         *            issuing distribution point check.
+         */
+        public void setIssuingDistributionPointEnabled(
+            boolean issuingDistributionPointEnabled)
+        {
+            this.issuingDistributionPointEnabled = issuingDistributionPointEnabled;
+        }
+
+        /**
+         * Sets the issuing distribution point.
+         * <p>
+         * The issuing distribution point extension is a CRL extension which
+         * identifies the scope and the distribution point of a CRL. The scope
+         * contains among others information about revocation reasons contained in
+         * the CRL. Delta CRLs and complete CRLs must have matching issuing
+         * distribution points.
+         * <p>
+         * The byte array is cloned to protect against subsequent modifications.
+         * <p>
+         * You must also enable or disable this criteria with
+         * {@link #setIssuingDistributionPointEnabled(boolean)}.
+         *
+         * @param issuingDistributionPoint The issuing distribution point to set.
+         *            This is the DER encoded OCTET STRING extension value.
+         * @see #getIssuingDistributionPoint()
+         */
+        public void setIssuingDistributionPoint(byte[] issuingDistributionPoint)
+        {
+            this.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint);
+        }
+
+        public PKIXCRLStoreSelector<? extends CRL> build()
+        {
+            return new PKIXCRLStoreSelector(this);
+        }
+    }
+
+    private final CRLSelector baseSelector;
+    private final boolean deltaCRLIndicator;
+    private final boolean completeCRLEnabled;
+    private final BigInteger maxBaseCRLNumber;
+    private final byte[] issuingDistributionPoint;
+    private final boolean issuingDistributionPointEnabled;
+
+    private PKIXCRLStoreSelector(Builder baseBuilder)
+    {
+        this.baseSelector = baseBuilder.baseSelector;
+        this.deltaCRLIndicator = baseBuilder.deltaCRLIndicator;
+        this.completeCRLEnabled = baseBuilder.completeCRLEnabled;
+        this.maxBaseCRLNumber = baseBuilder.maxBaseCRLNumber;
+        this.issuingDistributionPoint = baseBuilder.issuingDistributionPoint;
+        this.issuingDistributionPointEnabled = baseBuilder.issuingDistributionPointEnabled;
+    }
+
+
+    /**
+     * Returns if the issuing distribution point criteria should be applied.
+     * Defaults to <code>false</code>.
+     * <p>
+     * You may also set the issuing distribution point criteria if not a missing
+     * issuing distribution point should be assumed.
+     * 
+     * @return Returns if the issuing distribution point check is enabled.
+     */
+    public boolean isIssuingDistributionPointEnabled()
+    {
+        return issuingDistributionPointEnabled;
+    }
+
+
+
+    public boolean match(CRL obj)
+    {
+        if (!(obj instanceof X509CRL))
+        {
+            return baseSelector.match(obj);
+        }
+
+        X509CRL crl = (X509CRL)obj;
+        ASN1Integer dci = null;
+        try
+        {
+            byte[] bytes = crl
+                .getExtensionValue(Extension.deltaCRLIndicator.getId());
+            if (bytes != null)
+            {
+                dci = ASN1Integer.getInstance(ASN1OctetString.getInstance(bytes).getOctets());
+            }
+        }
+        catch (Exception e)
+        {
+            return false;
+        }
+        if (isDeltaCRLIndicatorEnabled())
+        {
+            if (dci == null)
+            {
+                return false;
+            }
+        }
+        if (isCompleteCRLEnabled())
+        {
+            if (dci != null)
+            {
+                return false;
+            }
+        }
+        if (dci != null)
+        {
+
+            if (maxBaseCRLNumber != null)
+            {
+                if (dci.getPositiveValue().compareTo(maxBaseCRLNumber) == 1)
+                {
+                    return false;
+                }
+            }
+        }
+        if (issuingDistributionPointEnabled)
+        {
+            byte[] idp = crl
+                .getExtensionValue(Extension.issuingDistributionPoint
+                    .getId());
+            if (issuingDistributionPoint == null)
+            {
+                if (idp != null)
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                if (!Arrays.areEqual(idp, issuingDistributionPoint))
+                {
+                    return false;
+                }
+            }
+
+        }
+        return baseSelector.match(obj);
+    }
+
+    /**
+     * Returns if this selector must match CRLs with the delta CRL indicator
+     * extension set. Defaults to <code>false</code>.
+     * 
+     * @return Returns <code>true</code> if only CRLs with the delta CRL
+     *         indicator extension are selected.
+     */
+    public boolean isDeltaCRLIndicatorEnabled()
+    {
+        return deltaCRLIndicator;
+    }
+
+    public Object clone()
+    {
+        return this;
+    }
+
+    /**
+     * If <code>true</code> only complete CRLs are returned. Defaults to
+     * <code>false</code>.
+     * 
+     * @return <code>true</code> if only complete CRLs are returned.
+     */
+    public boolean isCompleteCRLEnabled()
+    {
+        return completeCRLEnabled;
+    }
+
+    /**
+     * Get the maximum base CRL number. Defaults to <code>null</code>.
+     * 
+     * @return Returns the maximum base CRL number.
+     */
+    public BigInteger getMaxBaseCRLNumber()
+    {
+        return maxBaseCRLNumber;
+    }
+
+
+    /**
+     * Returns the issuing distribution point. Defaults to <code>null</code>,
+     * which is a missing issuing distribution point extension.
+     * <p>
+     * The internal byte array is cloned before it is returned.
+     * <p>
+     * The criteria must be enable with Builder.setIssuingDistributionPointEnabled(boolean)}.
+     * 
+     * @return Returns the issuing distribution point.
+     */
+    public byte[] getIssuingDistributionPoint()
+    {
+        return Arrays.clone(issuingDistributionPoint);
+    }
+
+    public X509Certificate getCertificateChecking()
+    {
+        return ((X509CRLSelector)baseSelector).getCertificateChecking();
+    }
+
+    public static Collection<? extends CRL> getCRLs(final PKIXCRLStoreSelector selector, CertStore certStore)
+        throws CertStoreException
+    {
+        return certStore.getCRLs(new CRLSelector()
+        {
+            public boolean match(CRL crl)
+            {
+                return selector.match(crl);
+            }
+
+            public Object clone()
+            {
+                return this;
+            }
+        });
+    }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStore.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStore.java
new file mode 100644
index 0000000..092872f
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStore.java
@@ -0,0 +1,15 @@
+package org.bouncycastle.jcajce;
+
+import java.security.cert.Certificate;
+import java.util.Collection;
+
+import org.bouncycastle.util.Selector;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.util.StoreException;
+
+public interface PKIXCertStore<T extends Certificate>
+    extends Store<T>
+{
+    Collection<T> getMatches(Selector<T> selector)
+        throws StoreException;
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStoreSelector.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStoreSelector.java
new file mode 100644
index 0000000..1775de7
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXCertStoreSelector.java
@@ -0,0 +1,67 @@
+package org.bouncycastle.jcajce;
+
+import java.security.cert.CertSelector;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreException;
+import java.security.cert.Certificate;
+import java.util.Collection;
+
+import org.bouncycastle.util.Selector;
+
+/**
+ * This class is a Selector implementation for certificates.
+ * 
+ * @see org.bouncycastle.util.Selector
+ */
+public class PKIXCertStoreSelector<T extends Certificate>
+    implements Selector<T>
+{
+    public static class Builder
+    {
+        private final CertSelector baseSelector;
+
+        public Builder(CertSelector certSelector)
+        {
+            this.baseSelector = (CertSelector)certSelector.clone();
+        }
+
+        public PKIXCertStoreSelector<? extends Certificate> build()
+        {
+            return new PKIXCertStoreSelector(baseSelector);
+        }
+    }
+
+    private final CertSelector baseSelector;
+
+    private PKIXCertStoreSelector(CertSelector baseSelector)
+    {
+        this.baseSelector = baseSelector;
+    }
+
+    public boolean match(Certificate cert)
+    {
+        return baseSelector.match(cert);
+    }
+
+    public Object clone()
+    {
+        return new PKIXCertStoreSelector(baseSelector);
+    }
+
+    public static Collection<? extends Certificate> getCertificates(final PKIXCertStoreSelector selector, CertStore certStore)
+        throws CertStoreException
+    {
+        return certStore.getCertificates(new CertSelector()
+        {
+            public boolean match(Certificate certificate)
+            {
+                return (selector == null) ? true : selector.match(certificate);
+            }
+
+            public Object clone()
+            {
+                return this;
+            }
+        });
+    }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedBuilderParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedBuilderParameters.java
new file mode 100644
index 0000000..3369d0d
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedBuilderParameters.java
@@ -0,0 +1,138 @@
+package org.bouncycastle.jcajce;
+
+import java.security.InvalidParameterException;
+import java.security.cert.CertPathParameters;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class contains extended parameters for PKIX certification path builders.
+ * 
+ * @see java.security.cert.PKIXBuilderParameters
+ */
+public class PKIXExtendedBuilderParameters
+    implements CertPathParameters
+{
+    public static class Builder
+    {
+        private final PKIXExtendedParameters baseParameters;
+
+        private int maxPathLength = 5;
+        private Set<X509Certificate> excludedCerts = new HashSet<X509Certificate>();
+
+        public Builder(PKIXBuilderParameters baseParameters)
+        {
+            this.baseParameters = new PKIXExtendedParameters.Builder(baseParameters).build();
+            this.maxPathLength = baseParameters.getMaxPathLength();
+        }
+
+        public Builder(PKIXExtendedParameters baseParameters)
+        {
+            this.baseParameters = baseParameters;
+        }
+
+        /**
+         * Adds excluded certificates which are not used for building a
+         * certification path.
+         * <p>
+         * The given set is cloned to protect it against subsequent modifications.
+         *
+         * @param excludedCerts The excluded certificates to set.
+         */
+        public Builder addExcludedCerts(Set<X509Certificate> excludedCerts)
+        {
+            this.excludedCerts.addAll(excludedCerts);
+
+            return this;
+        }
+
+        /**
+         * Sets the maximum number of intermediate non-self-issued certificates in a
+         * certification path. The PKIX <code>CertPathBuilder</code> must not
+         * build paths longer then this length.
+         * <p>
+         * A value of 0 implies that the path can only contain a single certificate.
+         * A value of -1 does not limit the length. The default length is 5.
+         *
+         * <p>
+         *
+         * The basic constraints extension of a CA certificate overrides this value
+         * if smaller.
+         *
+         * @param maxPathLength the maximum number of non-self-issued intermediate
+         *            certificates in the certification path
+         * @throws java.security.InvalidParameterException if <code>maxPathLength</code> is set
+         *             to a value less than -1
+         *
+         * @see #getMaxPathLength
+         */
+        public Builder setMaxPathLength(int maxPathLength)
+        {
+            if (maxPathLength < -1)
+            {
+                throw new InvalidParameterException("The maximum path "
+                        + "length parameter can not be less than -1.");
+            }
+            this.maxPathLength = maxPathLength;
+
+            return this;
+        }
+
+        public PKIXExtendedBuilderParameters build()
+        {
+            return new PKIXExtendedBuilderParameters(this);
+        }
+    }
+
+    private final PKIXExtendedParameters baseParameters;
+    private final Set<X509Certificate> excludedCerts;
+    private final int maxPathLength;
+
+    private PKIXExtendedBuilderParameters(Builder builder)
+    {
+        this.baseParameters = builder.baseParameters;
+        this.excludedCerts = Collections.unmodifiableSet(builder.excludedCerts);
+        this.maxPathLength = builder.maxPathLength;
+    }
+
+    public PKIXExtendedParameters getBaseParameters()
+    {
+        return baseParameters;
+    }
+
+    /**
+     * Excluded certificates are not used for building a certification path.
+     * <p>
+     * The returned set is immutable.
+     * 
+     * @return Returns the excluded certificates.
+     */
+    public Set getExcludedCerts()
+    {
+        return excludedCerts;
+    }
+
+    /**
+     * Returns the value of the maximum number of intermediate non-self-issued
+     * certificates in the certification path.
+     * 
+     * @return the maximum number of non-self-issued intermediate certificates
+     *         in the certification path, or -1 if no limit exists.
+     */
+    public int getMaxPathLength()
+    {
+        return maxPathLength;
+    }
+
+    /**
+     * @return this object
+     */
+    public Object clone()
+    {
+        return this;
+    }
+}
+
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java
new file mode 100644
index 0000000..3a86f2a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/PKIXExtendedParameters.java
@@ -0,0 +1,340 @@
+package org.bouncycastle.jcajce;
+
+import java.security.cert.CertPathParameters;
+import java.security.cert.CertSelector;
+import java.security.cert.CertStore;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.bouncycastle.asn1.x509.GeneralName;
+
+/**
+ * This class extends the PKIXParameters with a validity model parameter.
+ */
+public class PKIXExtendedParameters
+    implements CertPathParameters
+{
+    /**
+     * This is the default PKIX validity model. Actually there are two variants
+     * of this: The PKIX model and the modified PKIX model. The PKIX model
+     * verifies that all involved certificates must have been valid at the
+     * current time. The modified PKIX model verifies that all involved
+     * certificates were valid at the signing time. Both are indirectly choosen
+     * with the {@link java.security.cert.PKIXParameters#setDate(java.util.Date)} method, so this
+     * methods sets the Date when <em>all</em> certificates must have been
+     * valid.
+     */
+    public static final int PKIX_VALIDITY_MODEL = 0;
+
+    /**
+     * This model uses the following validity model. Each certificate must have
+     * been valid at the moment where is was used. That means the end
+     * certificate must have been valid at the time the signature was done. The
+     * CA certificate which signed the end certificate must have been valid,
+     * when the end certificate was signed. The CA (or Root CA) certificate must
+     * have been valid, when the CA certificate was signed and so on. So the
+     * {@link java.security.cert.PKIXParameters#setDate(java.util.Date)} method sets the time, when
+     * the <em>end certificate</em> must have been valid.
+     * <p>
+     * It is used e.g.
+     * in the German signature law.
+     * </p>
+     */
+    public static final int CHAIN_VALIDITY_MODEL = 1;
+
+    public static class Builder
+    {
+        private final PKIXParameters baseParameters;
+        private final Date date;
+
+        private PKIXCertStoreSelector targetConstraints;
+        private List<PKIXCertStore> extraCertStores = new ArrayList<PKIXCertStore>();
+        private Map<GeneralName, PKIXCertStore> namedCertificateStoreMap = new HashMap<GeneralName, PKIXCertStore>();
+        private List<PKIXCRLStore> extraCRLStores = new ArrayList<PKIXCRLStore>();
+        private Map<GeneralName, PKIXCRLStore> namedCRLStoreMap = new HashMap<GeneralName, PKIXCRLStore>();
+        private boolean revocationEnabled;
+        private int validityModel = PKIX_VALIDITY_MODEL;
+        private boolean useDeltas = false;
+        private Set<TrustAnchor> trustAnchors;
+
+        public Builder(PKIXParameters baseParameters)
+        {
+            this.baseParameters = (PKIXParameters)baseParameters.clone();
+            CertSelector constraints = baseParameters.getTargetCertConstraints();
+            if (constraints != null)
+            {
+                this.targetConstraints = new PKIXCertStoreSelector.Builder(constraints).build();
+            }
+            Date checkDate = baseParameters.getDate();
+            this.date = (checkDate == null) ? new Date() : checkDate;
+            this.revocationEnabled = baseParameters.isRevocationEnabled();
+            this.trustAnchors = baseParameters.getTrustAnchors();
+        }
+
+        public Builder(PKIXExtendedParameters baseParameters)
+        {
+            this.baseParameters = baseParameters.baseParameters;
+            this.date = baseParameters.date;
+            this.targetConstraints = baseParameters.targetConstraints;
+            this.extraCertStores = new ArrayList<PKIXCertStore>(baseParameters.extraCertStores);
+            this.namedCertificateStoreMap = new HashMap<GeneralName, PKIXCertStore>(baseParameters.namedCertificateStoreMap);
+            this.extraCRLStores = new ArrayList<PKIXCRLStore>(baseParameters.extraCRLStores);
+            this.namedCRLStoreMap = new HashMap<GeneralName, PKIXCRLStore>(baseParameters.namedCRLStoreMap);
+            this.useDeltas = baseParameters.useDeltas;
+            this.validityModel = baseParameters.validityModel;
+            this.revocationEnabled = baseParameters.isRevocationEnabled();
+            this.trustAnchors = baseParameters.getTrustAnchors();
+        }
+
+        public Builder addCertificateStore(PKIXCertStore store)
+        {
+            extraCertStores.add(store);
+
+            return this;
+        }
+
+        public Builder addNamedCertificateStore(GeneralName issuerAltName, PKIXCertStore store)
+        {
+            namedCertificateStoreMap.put(issuerAltName, store);
+
+            return this;
+        }
+
+        public Builder addCRLStore(PKIXCRLStore store)
+        {
+            extraCRLStores.add(store);
+
+            return this;
+        }
+
+        public Builder addNamedCRLStore(GeneralName issuerAltName, PKIXCRLStore store)
+        {
+            namedCRLStoreMap.put(issuerAltName, store);
+
+            return this;
+        }
+
+        public Builder setTargetConstraints(PKIXCertStoreSelector selector)
+        {
+            targetConstraints = selector;
+
+            return this;
+        }
+
+        /**
+         * Sets if delta CRLs should be used for checking the revocation status.
+         *
+         * @param useDeltas <code>true</code> if delta CRLs should be used.
+         */
+        public Builder setUseDeltasEnabled(boolean useDeltas)
+        {
+            this.useDeltas = useDeltas;
+
+            return this;
+        }
+
+        /**
+         * @param validityModel The validity model to set.
+         * @see #CHAIN_VALIDITY_MODEL
+         * @see #PKIX_VALIDITY_MODEL
+         */
+        public Builder setValidityModel(int validityModel)
+        {
+            this.validityModel = validityModel;
+
+            return this;
+        }
+
+        /**
+         * Set the trustAnchor to be used with these parameters.
+         *
+         * @param trustAnchor the trust anchor end-entity and CRLs must be based on.
+         * @return the current builder.
+         */
+        public Builder setTrustAnchor(TrustAnchor trustAnchor)
+        {
+            this.trustAnchors = Collections.singleton(trustAnchor);
+
+            return this;
+        }
+
+        /**
+         * Set the set of trustAnchors to be used with these parameters.
+         *
+         * @param trustAnchors  a set of trustAnchors, one of which a particular end-entity and it's associated CRLs must be based on.
+         * @return the current builder.
+         */
+        public Builder setTrustAnchors(Set<TrustAnchor> trustAnchors)
+        {
+            this.trustAnchors = trustAnchors;
+
+            return this;
+        }
+
+        /**
+         * Flag whether or not revocation checking is to be enabled.
+         *
+         * @param revocationEnabled  true if revocation checking to be enabled, false otherwise.
+         */
+        public void setRevocationEnabled(boolean revocationEnabled)
+        {
+            this.revocationEnabled = revocationEnabled;
+        }
+
+        public PKIXExtendedParameters build()
+        {
+            return new PKIXExtendedParameters(this);
+        }
+    }
+
+    private final PKIXParameters baseParameters;
+    private final PKIXCertStoreSelector targetConstraints;
+    private final Date date;
+    private final List<PKIXCertStore> extraCertStores;
+    private final Map<GeneralName, PKIXCertStore> namedCertificateStoreMap;
+    private final List<PKIXCRLStore> extraCRLStores;
+    private final Map<GeneralName, PKIXCRLStore> namedCRLStoreMap;
+    private final boolean revocationEnabled;
+    private final boolean useDeltas;
+    private final int validityModel;
+    private final Set<TrustAnchor> trustAnchors;
+
+    private PKIXExtendedParameters(Builder builder)
+    {
+        this.baseParameters = builder.baseParameters;
+        this.date = builder.date;
+        this.extraCertStores = Collections.unmodifiableList(builder.extraCertStores);
+        this.namedCertificateStoreMap = Collections.unmodifiableMap(new HashMap<GeneralName, PKIXCertStore>(builder.namedCertificateStoreMap));
+        this.extraCRLStores = Collections.unmodifiableList(builder.extraCRLStores);
+        this.namedCRLStoreMap = Collections.unmodifiableMap(new HashMap<GeneralName, PKIXCRLStore>(builder.namedCRLStoreMap));
+        this.targetConstraints = builder.targetConstraints;
+        this.revocationEnabled = builder.revocationEnabled;
+        this.useDeltas = builder.useDeltas;
+        this.validityModel = builder.validityModel;
+        this.trustAnchors = Collections.unmodifiableSet(builder.trustAnchors);
+    }
+
+    public List<PKIXCertStore> getCertificateStores()
+    {
+        return extraCertStores;
+    }
+
+
+    public Map<GeneralName, PKIXCertStore> getNamedCertificateStoreMap()
+    {
+        return namedCertificateStoreMap;
+    }
+
+    public List<PKIXCRLStore> getCRLStores()
+    {
+        return extraCRLStores;
+    }
+
+    public Map<GeneralName, PKIXCRLStore> getNamedCRLStoreMap()
+    {
+        return namedCRLStoreMap;
+    }
+
+    public Date getDate()
+    {
+        return new Date(date.getTime());
+    }
+
+
+
+
+    /**
+     * Defaults to <code>false</code>.
+     *
+     * @return Returns if delta CRLs should be used.
+     */
+    public boolean isUseDeltasEnabled()
+    {
+        return useDeltas;
+    }
+
+
+
+    /**
+     * @return Returns the validity model.
+     * @see #CHAIN_VALIDITY_MODEL
+     * @see #PKIX_VALIDITY_MODEL
+     */
+    public int getValidityModel()
+    {
+        return validityModel;
+    }
+
+    public Object clone()
+    {
+        return this;
+    }
+
+    /**
+     * Returns the required constraints on the target certificate.
+     * The constraints are returned as an instance of
+     * <code>Selector</code>. If <code>null</code>, no constraints are
+     * defined.
+     *
+     * @return a <code>Selector</code> specifying the constraints on the
+     *         target certificate or attribute certificate (or <code>null</code>)
+     * @see PKIXCertStoreSelector
+     */
+    public PKIXCertStoreSelector getTargetConstraints()
+    {
+        return targetConstraints;
+    }
+
+    public Set getTrustAnchors()
+    {
+        return trustAnchors;
+    }
+
+    public Set getInitialPolicies()
+    {
+        return baseParameters.getInitialPolicies();
+    }
+
+    public String getSigProvider()
+    {
+        return baseParameters.getSigProvider();
+    }
+
+    public boolean isExplicitPolicyRequired()
+    {
+        return baseParameters.isExplicitPolicyRequired();
+    }
+
+    public boolean isAnyPolicyInhibited()
+    {
+        return baseParameters.isAnyPolicyInhibited();
+    }
+
+    public boolean isPolicyMappingInhibited()
+    {
+        return baseParameters.isPolicyMappingInhibited();
+    }
+
+    public List getCertPathCheckers()
+    {
+        return baseParameters.getCertPathCheckers();
+    }
+
+    public List<CertStore> getCertStores()
+    {
+        return baseParameters.getCertStores();
+    }
+
+    public boolean isRevocationEnabled()
+    {
+        return revocationEnabled;
+    }
+
+}
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 bd83a8a..1266abd 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
@@ -37,12 +37,16 @@
             registerOid(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC", new KeyFactorySpi.EC());
             // BEGIN android-removed
             // registerOid(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV());
+            //
+            // // Android comment: the registration below is causing CTS tests to fail and doesn't seem
+            // // to be implemented by bouncycastle (so looks like an bug in bouncycastle).
+            // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
             // END android-removed
-
-            registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
             // TODO Should this be an alias for ECDH?
-            registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
             // BEGIN android-removed
+            // // Android comment: the registration below is causing CTS tests to fail and doesn't seem
+            // // to be implemented by bouncycastle (so looks like an bug in bouncycastle).
+            // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
             // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC");
             // END android-removed
 
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 2265199..d4046f9 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
@@ -155,6 +155,12 @@
                 // END android-removed
                 provider.addAlgorithm("Alg.Alias.Signature." + OIWObjectIdentifiers.sha1WithRSA, "SHA1WITHRSA");
                 provider.addAlgorithm("Alg.Alias.Signature.OID." + OIWObjectIdentifiers.sha1WithRSA, "SHA1WITHRSA");
+
+                // BEGIN android-removed
+                // provider.addAlgorithm("Alg.Alias.Signature.SHA1withRSA/X9.31", "SHA1WITHRSA/X9.31");
+                // provider.addAlgorithm("Alg.Alias.Signature.SHA1WithRSA/X9.31", "SHA1WITHRSA/X9.31");
+                // provider.addAlgorithm("Signature.SHA1WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA1WithRSAEncryption");
+                // END android-removed
             }
 
             addDigestSignature(provider, "SHA224", PREFIX + "DigestSignatureSpi$SHA224", PKCSObjectIdentifiers.sha224WithRSAEncryption);
@@ -163,26 +169,53 @@
             addDigestSignature(provider, "SHA512", PREFIX + "DigestSignatureSpi$SHA512", PKCSObjectIdentifiers.sha512WithRSAEncryption);
 
             // BEGIN android-removed
+            // provider.addAlgorithm("Alg.Alias.Signature.SHA224withRSA/X9.31", "SHA224WITHRSA/X9.31");
+            // provider.addAlgorithm("Alg.Alias.Signature.SHA224WithRSA/X9.31", "SHA224WITHRSA/X9.31");
+            // provider.addAlgorithm("Signature.SHA224WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA224WithRSAEncryption");
+            // provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSA/X9.31", "SHA256WITHRSA/X9.31");
+            // provider.addAlgorithm("Alg.Alias.Signature.SHA256WithRSA/X9.31", "SHA256WITHRSA/X9.31");
+            // provider.addAlgorithm("Signature.SHA256WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA256WithRSAEncryption");
+            // provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSA/X9.31", "SHA384WITHRSA/X9.31");
+            // provider.addAlgorithm("Alg.Alias.Signature.SHA384WithRSA/X9.31", "SHA384WITHRSA/X9.31");
+            // provider.addAlgorithm("Signature.SHA384WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA384WithRSAEncryption");
+            // provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSA/X9.31", "SHA512WITHRSA/X9.31");
+            // provider.addAlgorithm("Alg.Alias.Signature.SHA512WithRSA/X9.31", "SHA512WITHRSA/X9.31");
+            // provider.addAlgorithm("Signature.SHA512WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA512WithRSAEncryption");
+            //
             // if (provider.hasAlgorithm("MessageDigest", "RIPEMD128"))
             // {
             //     addDigestSignature(provider, "RIPEMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
             //     addDigestSignature(provider, "RMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", null);
+            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD128withRSA/X9.31", "RIPEMD128WITHRSA/X9.31");
+            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD128WithRSA/X9.31", "RIPEMD128WITHRSA/X9.31");
+            //     provider.addAlgorithm("Signature.RIPEMD128WITHRSA/X9.31", PREFIX + "X931SignatureSpi$RIPEMD128WithRSAEncryption");
             // }
-            //
+	    //
             // if (provider.hasAlgorithm("MessageDigest", "RIPEMD160"))
             // {
             //     addDigestSignature(provider, "RIPEMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
             //     addDigestSignature(provider, "RMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", null);
             //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/ISO9796-2", "RIPEMD160withRSA/ISO9796-2");
             //     provider.addAlgorithm("Signature.RIPEMD160withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$RIPEMD160WithRSAEncryption");
+            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160withRSA/X9.31", "RIPEMD160WITHRSA/X9.31");
+            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/X9.31", "RIPEMD160WITHRSA/X9.31");
+            //     provider.addAlgorithm("Signature.RIPEMD160WITHRSA/X9.31", PREFIX + "X931SignatureSpi$RIPEMD160WithRSAEncryption");
             // }
-            //
+	    //
             // if (provider.hasAlgorithm("MessageDigest", "RIPEMD256"))
             // {
             //     addDigestSignature(provider, "RIPEMD256", PREFIX + "DigestSignatureSpi$RIPEMD256", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
             //     addDigestSignature(provider, "RMD256", PREFIX + "DigestSignatureSpi$RIPEMD256", null);
             // }
-            // END android-removed
+	    //
+            // if (provider.hasAlgorithm("MessageDigest", "WHIRLPOOL"))
+            // {
+            //     provider.addAlgorithm("Alg.Alias.Signature.WhirlpoolWithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
+            //     provider.addAlgorithm("Alg.Alias.Signature.WHIRLPOOLwithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
+            //     provider.addAlgorithm("Alg.Alias.Signature.WHIRLPOOLWithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
+            //     provider.addAlgorithm("Signature.WHIRLPOOLWITHRSA/X9.31", PREFIX + "X931SignatureSpi$WhirlpoolWithRSAEncryption");
+            // }
+	    // END android-removed
         }
 
         private void addDigestSignature(
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 8bdcc55..e4c8172 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
@@ -10,10 +10,10 @@
 
 import org.bouncycastle.crypto.generators.DHParametersGenerator;
 import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAlgorithmParameterGeneratorSpi;
 
 public class AlgorithmParameterGeneratorSpi
-    extends java.security.AlgorithmParameterGeneratorSpi
+    extends BaseAlgorithmParameterGeneratorSpi
 {
     protected SecureRandom random;
     protected int strength = 1024;
@@ -63,7 +63,7 @@
 
         try
         {
-            params = AlgorithmParameters.getInstance("DH", BouncyCastleProvider.PROVIDER_NAME);
+            params = createParametersInstance("DH");
             params.init(new DHParameterSpec(p.getP(), p.getG(), l));
         }
         catch (Exception e)
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 d850e5d..2d7c4c5 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
@@ -11,10 +11,10 @@
 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.jcajce.provider.asymmetric.util.BaseAlgorithmParameterGeneratorSpi;
 
 public class AlgorithmParameterGeneratorSpi
-    extends java.security.AlgorithmParameterGeneratorSpi
+    extends BaseAlgorithmParameterGeneratorSpi
 {
     protected SecureRandom random;
     protected int strength = 1024;
@@ -90,7 +90,7 @@
 
         try
         {
-            params = AlgorithmParameters.getInstance("DSA", BouncyCastleProvider.PROVIDER_NAME);
+            params = createParametersInstance("DSA");
             params.init(new DSAParameterSpec(p.getP(), p.getQ(), p.getG()));
         }
         catch (Exception e)
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 61fa33c..5722479 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
@@ -33,7 +33,6 @@
 
     /**
      * Return the X.509 ASN.1 structure DSAParameter.
-     * <p/>
      * <pre>
      *  DSAParameter ::= SEQUENCE {
      *                   prime INTEGER, -- p
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 45d5b08..c9ad445 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
@@ -282,7 +282,8 @@
      */
     public byte[] getEncoded()
     {
-        X962Parameters          params;
+        X962Parameters  params;
+        int orderBitLength;
 
         if (ecSpec instanceof ECNamedCurveSpec)
         {
@@ -293,10 +294,12 @@
             }
 
             params = new X962Parameters(curveOid);
+            orderBitLength = ECUtil.getOrderBitLength(ecSpec.getOrder(), this.getS());
         }
         else if (ecSpec == null)
         {
             params = new X962Parameters(DERNull.INSTANCE);
+            orderBitLength = ECUtil.getOrderBitLength(null, this.getS());
         }
         else
         {
@@ -310,6 +313,7 @@
                 ecSpec.getCurve().getSeed());
 
             params = new X962Parameters(ecP);
+            orderBitLength = ECUtil.getOrderBitLength(ecSpec.getOrder(), this.getS());
         }
         
         PrivateKeyInfo          info;
@@ -317,11 +321,11 @@
 
         if (publicKey != null)
         {
-            keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), publicKey, params);
+            keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(orderBitLength, this.getS(), publicKey, params);
         }
         else
         {
-            keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(this.getS(), params);
+            keyStructure = new org.bouncycastle.asn1.sec.ECPrivateKey(orderBitLength, this.getS(), params);
         }
 
         try
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
index dcb9c23..aceb5ee 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
@@ -35,12 +35,16 @@
 import org.bouncycastle.crypto.params.ParametersWithRandom;
 import org.bouncycastle.jcajce.provider.asymmetric.util.BaseCipherSpi;
 import org.bouncycastle.jcajce.provider.util.DigestFactory;
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.util.Strings;
 
 public class CipherSpi
     extends BaseCipherSpi
 {
+    private final JcaJceHelper helper = new BCJcaJceHelper();
+
     private AsymmetricBlockCipher cipher;
     private AlgorithmParameterSpec paramSpec;
     private AlgorithmParameters engineParams;
@@ -145,7 +149,7 @@
             {
                 try
                 {
-                    engineParams = AlgorithmParameters.getInstance("OAEP", BouncyCastleProvider.PROVIDER_NAME);
+                    engineParams = helper.createAlgorithmParameters("OAEP");
                     engineParams.init(paramSpec);
                 }
                 catch (Exception e)
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
index 13f7c93..123ed41 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
@@ -44,6 +44,7 @@
 // END android-added
 import org.bouncycastle.crypto.encodings.PKCS1Encoding;
 import org.bouncycastle.crypto.engines.RSABlindedEngine;
+import org.bouncycastle.util.Arrays;
 
 public class DigestSignatureSpi
     extends SignatureSpi
@@ -178,13 +179,7 @@
 
         if (sig.length == expected.length)
         {
-            for (int i = 0; i < sig.length; i++)
-            {
-                if (sig[i] != expected[i])
-                {
-                    return false;
-                }
-            }
+            return Arrays.constantTimeAreEqual(sig, expected);
         }
         else if (sig.length == expected.length - 2)  // NULL left out
         {
@@ -194,28 +189,26 @@
             expected[1] -= 2;      // adjust lengths
             expected[3] -= 2;
 
+            int nonEqual = 0;
+
             for (int i = 0; i < hash.length; i++)
             {
-                if (sig[sigOffset + i] != expected[expectedOffset + i])  // check hash
-                {
-                    return false;
-                }
+                nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
             }
 
             for (int i = 0; i < sigOffset; i++)
             {
-                if (sig[i] != expected[i])  // check header less NULL
-                {
-                    return false;
-                }
+                nonEqual |= (sig[i] ^ expected[i]);  // check header less NULL
             }
+
+            return nonEqual == 0;
         }
         else
         {
+            Arrays.constantTimeAreEqual(expected, expected);  // keep time "steady".
+
             return false;
         }
-
-        return true;
     }
 
     protected void engineSetParameter(
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 c61e7cb..f779a66 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
@@ -23,7 +23,7 @@
     }
 
     final static BigInteger defaultPublicExponent = BigInteger.valueOf(0x10001);
-    final static int defaultTests = 12;
+    final static int defaultTests = 112;
 
     RSAKeyGenerationParameters param;
     RSAKeyPairGenerator engine;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAlgorithmParameterGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAlgorithmParameterGeneratorSpi.java
new file mode 100644
index 0000000..d9fb3fb
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseAlgorithmParameterGeneratorSpi.java
@@ -0,0 +1,25 @@
+package org.bouncycastle.jcajce.provider.asymmetric.util;
+
+import java.security.AlgorithmParameterGeneratorSpi;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
+
+public abstract class BaseAlgorithmParameterGeneratorSpi
+    extends AlgorithmParameterGeneratorSpi
+{
+    private final JcaJceHelper helper = new BCJcaJceHelper();
+
+    public BaseAlgorithmParameterGeneratorSpi()
+    {
+    }
+
+    protected final AlgorithmParameters createParametersInstance(String algorithm)
+        throws NoSuchAlgorithmException, NoSuchProviderException
+    {
+        return helper.createAlgorithmParameters(algorithm);
+    }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
index fabad43..5842b9e 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
@@ -27,6 +27,8 @@
 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
 import org.bouncycastle.crypto.InvalidCipherTextException;
 import org.bouncycastle.crypto.Wrapper;
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 public abstract class BaseCipherSpi
@@ -45,6 +47,7 @@
                                         // END android-removed
                                     };
 
+    private final JcaJceHelper helper = new BCJcaJceHelper();
 
     protected AlgorithmParameters     engineParams = null;
 
@@ -84,6 +87,12 @@
         return null;
     }
 
+    protected final AlgorithmParameters createParametersInstance(String algorithm)
+        throws NoSuchAlgorithmException, NoSuchProviderException
+    {
+        return helper.createAlgorithmParameters(algorithm);
+    }
+
     protected void engineSetMode(
         String  mode)
         throws NoSuchAlgorithmException
@@ -190,7 +199,7 @@
         {
             try
             {
-                KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
+                KeyFactory kf = helper.createKeyFactory(wrappedKeyAlgorithm);
 
                 if (wrappedKeyType == Cipher.PUBLIC_KEY)
                 {
@@ -201,17 +210,17 @@
                     return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
                 }
             }
-            catch (NoSuchProviderException e)
-            {
-                throw new InvalidKeyException("Unknown key type " + e.getMessage());
-            }
             catch (NoSuchAlgorithmException e)
             {
                 throw new InvalidKeyException("Unknown key type " + e.getMessage());
             }
-            catch (InvalidKeySpecException e2)
+            catch (InvalidKeySpecException e)
             {
-                throw new InvalidKeyException("Unknown key type " + e2.getMessage());
+                throw new InvalidKeyException("Unknown key type " + e.getMessage());
+            }
+            catch (NoSuchProviderException e)
+            {
+                throw new InvalidKeyException("Unknown key type " + e.getMessage());
             }
 
             throw new InvalidKeyException("Unknown key type " + wrappedKeyType);
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 06a93e5..b8ef398 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
@@ -1,5 +1,6 @@
 package org.bouncycastle.jcajce.provider.asymmetric.util;
 
+import java.math.BigInteger;
 import java.security.InvalidKeyException;
 import java.security.PrivateKey;
 import java.security.PublicKey;
@@ -16,6 +17,7 @@
 // END android-removed
 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
 import org.bouncycastle.asn1.x9.X962NamedCurves;
+import org.bouncycastle.asn1.x9.X962Parameters;
 import org.bouncycastle.asn1.x9.X9ECParameters;
 import org.bouncycastle.crypto.ec.CustomNamedCurves;
 import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
@@ -218,6 +220,25 @@
         throw new InvalidKeyException("can't identify EC private key.");
     }
 
+    public static int getOrderBitLength(BigInteger order, BigInteger privateValue)
+    {
+        if (order == null)     // implicitly CA
+        {
+            ECParameterSpec implicitCA = BouncyCastleProvider.CONFIGURATION.getEcImplicitlyCa();
+
+            if (implicitCA == null)
+            {
+                return privateValue.bitLength();   // a guess but better than an exception!
+            }
+
+            return implicitCA.getN().bitLength();
+        }
+        else
+        {
+            return order.bitLength();
+        }
+    }
+
     public static ASN1ObjectIdentifier getNamedCurveOid(
         String name)
     {
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 e4aaf30..8116f29 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
@@ -6,7 +6,7 @@
 import org.bouncycastle.asn1.ASN1Sequence;
 import org.bouncycastle.util.encoders.Base64;
 
-public class PEMUtil
+class PEMUtil
 {
     private final String _header1;
     private final String _header2;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
index 9b14731..8bb4c3a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
@@ -34,7 +34,8 @@
 import org.bouncycastle.asn1.pkcs.ContentInfo;
 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
 import org.bouncycastle.asn1.pkcs.SignedData;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
 import org.bouncycastle.util.io.pem.PemObject;
 // BEGIN android-removed
 // import org.bouncycastle.util.io.pem.PemWriter;
@@ -47,6 +48,8 @@
 public  class PKIXCertPath
     extends CertPath
 {
+    private final JcaJceHelper helper = new BCJcaJceHelper();
+
     static final List certPathEncodings;
 
     static
@@ -184,7 +187,7 @@
                 }
                 Enumeration e = ((ASN1Sequence)derObject).getObjects();
                 certificates = new ArrayList();
-                CertificateFactory certFactory = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
+                CertificateFactory certFactory = helper.createCertificateFactory("X.509");
                 while (e.hasMoreElements())
                 {
                     ASN1Encodable element = (ASN1Encodable)e.nextElement();
@@ -197,7 +200,7 @@
             {
                 inStream = new BufferedInputStream(inStream);
                 certificates = new ArrayList();
-                CertificateFactory certFactory= CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
+                CertificateFactory certFactory= helper.createCertificateFactory("X.509");
                 Certificate cert;
                 while ((cert = certFactory.generateCertificate(inStream)) != null)
                 {
@@ -217,7 +220,7 @@
         {
             throw new CertificateException("BouncyCastle provider not found while trying to get a CertificateFactory:\n" + ex.toString());
         }
-        
+
         this.certificates = sortCerts(certificates);
     }
     
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
index 32e595c..0b53bd3 100644
--- 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
@@ -23,7 +23,6 @@
 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
@@ -31,7 +30,7 @@
  * ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
  * (critical)
  */
-public class X509CRLEntryObject extends X509CRLEntry
+class X509CRLEntryObject extends X509CRLEntry
 {
     private TBSCertList.CRLEntry c;
 
@@ -285,11 +284,11 @@
                         buf.append("                       critical(").append(ext.isCritical()).append(") ");
                         try
                         {
-                            if (oid.equals(X509Extension.reasonCode))
+                            if (oid.equals(Extension.reasonCode))
                             {
                                 buf.append(CRLReason.getInstance(ASN1Enumerated.getInstance(dIn.readObject()))).append(nl);
                             }
-                            else if (oid.equals(X509Extension.certificateIssuer))
+                            else if (oid.equals(Extension.certificateIssuer))
                             {
                                 buf.append("Certificate issuer: ").append(GeneralNames.getInstance(dIn.readObject())).append(nl);
                             }
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
index c7d0402..cd877d0 100644
--- 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
@@ -42,7 +42,6 @@
 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;
 
 /**
@@ -54,7 +53,7 @@
  * Delta CRL Indicator (critical)
  * Issuing Distribution Point (critical)
  */
-public class X509CRLObject
+class X509CRLObject
     extends X509CRL
 {
     private CertificateList c;
@@ -120,8 +119,8 @@
             return false;
         }
 
-        extns.remove(RFC3280CertPathUtilities.ISSUING_DISTRIBUTION_POINT);
-        extns.remove(RFC3280CertPathUtilities.DELTA_CRL_INDICATOR);
+        extns.remove(Extension.issuingDistributionPoint.getId());
+        extns.remove(Extension.deltaCRLIndicator.getId());
 
         return !extns.isEmpty();
     }
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java
index 6604b4a..3157ea6 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java
@@ -9,9 +9,7 @@
 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;
@@ -64,7 +62,6 @@
 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;
@@ -241,37 +238,11 @@
 
     /**
      * return a more "meaningful" representation for the signature algorithm used in
-     * the certficate.
+     * the certificate.
      */
     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 X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm());
     }
 
     /**
@@ -525,19 +496,18 @@
                 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))
+                    if (oid.equals(Extension.keyUsage)
+                     || oid.equals(Extension.certificatePolicies)
+                     || oid.equals(Extension.policyMappings)
+                     || oid.equals(Extension.inhibitAnyPolicy)
+                     || oid.equals(Extension.cRLDistributionPoints)
+                     || oid.equals(Extension.issuingDistributionPoint)
+                     || oid.equals(Extension.deltaCRLIndicator)
+                     || oid.equals(Extension.policyConstraints)
+                     || oid.equals(Extension.basicConstraints)
+                     || oid.equals(Extension.subjectAlternativeName)
+                     || oid.equals(Extension.nameConstraints))
                     {
                         continue;
                     }
@@ -786,7 +756,16 @@
         InvalidKeyException, NoSuchProviderException, SignatureException
     {
         String    sigName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm());
-        Signature signature = Signature.getInstance(sigName, sigProvider);
+        Signature signature;
+
+        if (sigProvider  != null)
+        {
+            signature = Signature.getInstance(sigName, sigProvider);
+        }
+        else
+        {
+            signature = Signature.getInstance(sigName);
+        }
         
         checkSignature(key, signature);
     }
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
index a6959ba..61b0545 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
@@ -5,6 +5,8 @@
 import java.security.GeneralSecurityException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
 import java.security.Signature;
 import java.security.SignatureException;
 import java.security.spec.PSSParameterSpec;
@@ -26,6 +28,7 @@
 // END android-removed
 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
 import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 class X509SignatureUtil
 {
@@ -84,6 +87,32 @@
             }
         }
 
+        Provider prov = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
+
+        if (prov != null)
+        {
+            String      algName = prov.getProperty("Alg.Alias.Signature." + sigAlgId.getAlgorithm().getId());
+
+            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." + sigAlgId.getAlgorithm().getId());
+            if (algName != null)
+            {
+                return algName;
+            }
+        }
+
         return sigAlgId.getAlgorithm().getId();
     }
     
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/PKCS12StoreParameter.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/PKCS12StoreParameter.java
index 36a32b1..7d0b203 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/PKCS12StoreParameter.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/config/PKCS12StoreParameter.java
@@ -2,50 +2,31 @@
 
 import java.io.OutputStream;
 import java.security.KeyStore;
-import java.security.KeyStore.LoadStoreParameter;
 import java.security.KeyStore.ProtectionParameter;
 
+/**
+ * @deprecated use org.bouncycastle.jcajce.PKCS12StoreParameter
+ */
 public class PKCS12StoreParameter
-    implements LoadStoreParameter
+    extends org.bouncycastle.jcajce.PKCS12StoreParameter
 {
-    private final OutputStream out;
-    private final ProtectionParameter protectionParameter;
-    private final boolean forDEREncoding;
-
     public PKCS12StoreParameter(OutputStream out, char[] password)
     {
-        this(out, password, false);
+        super(out, password, false);
     }
 
     public PKCS12StoreParameter(OutputStream out, ProtectionParameter protectionParameter)
     {
-        this(out, protectionParameter, false);
+        super(out, protectionParameter, false);
     }
 
     public PKCS12StoreParameter(OutputStream out, char[] password, boolean forDEREncoding)
     {
-        this(out, new KeyStore.PasswordProtection(password), forDEREncoding);
+        super(out, new KeyStore.PasswordProtection(password), forDEREncoding);
     }
 
     public PKCS12StoreParameter(OutputStream out, ProtectionParameter protectionParameter, boolean forDEREncoding)
     {
-        this.out = out;
-        this.protectionParameter = protectionParameter;
-        this.forDEREncoding = forDEREncoding;
-    }
-
-    public OutputStream getOutputStream()
-    {
-        return out;
-    }
-
-    public ProtectionParameter getProtectionParameter()
-    {
-        return protectionParameter;
-    }
-
-    public boolean isForDEREncoding()
-    {
-        return forDEREncoding;
+        super(out, protectionParameter, forDEREncoding);
     }
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java
index ea89261..0640669 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/bc/BcKeyStoreSpi.java
@@ -14,8 +14,10 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.PrivateKey;
+import java.security.Provider;
 import java.security.PublicKey;
 import java.security.SecureRandom;
+import java.security.Security;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
@@ -46,6 +48,8 @@
 import org.bouncycastle.crypto.io.MacInputStream;
 import org.bouncycastle.crypto.io.MacOutputStream;
 import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
 import org.bouncycastle.jce.interfaces.BCKeyStore;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.bouncycastle.util.Arrays;
@@ -88,6 +92,8 @@
 
     protected int              version;
 
+    private final JcaJceHelper helper = new BCJcaJceHelper();
+
     public BcKeyStoreSpi(int version)
     {
         this.version = version;
@@ -361,7 +367,7 @@
 
         try
         {
-            CertificateFactory cFact = CertificateFactory.getInstance(type, BouncyCastleProvider.PROVIDER_NAME);
+            CertificateFactory cFact = helper.createCertificateFactory(type);
             ByteArrayInputStream bIn = new ByteArrayInputStream(cEnc);
 
             return cFact.generateCertificate(bIn);
@@ -436,11 +442,11 @@
             switch (keyType)
             {
             case KEY_PRIVATE:
-                return KeyFactory.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME).generatePrivate(spec);
+                return helper.createKeyFactory(algorithm).generatePrivate(spec);
             case KEY_PUBLIC:
-                return KeyFactory.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME).generatePublic(spec);
+                return  helper.createKeyFactory(algorithm).generatePublic(spec);
             case KEY_SECRET:
-                return SecretKeyFactory.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME).generateSecret(spec);
+                return  helper.createSecretKeyFactory(algorithm).generateSecret(spec);
             default:
                 throw new IOException("Key type " + keyType + " not recognised!");
             }
@@ -462,10 +468,10 @@
         try
         {
             PBEKeySpec          pbeSpec = new PBEKeySpec(password);
-            SecretKeyFactory    keyFact = SecretKeyFactory.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME);
+            SecretKeyFactory    keyFact = helper.createSecretKeyFactory(algorithm);
             PBEParameterSpec    defParams = new PBEParameterSpec(salt, iterationCount);
 
-            Cipher cipher = Cipher.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME);
+            Cipher cipher = helper.createCipher(algorithm);
 
             cipher.init(mode, keyFact.generateSecret(pbeSpec), defParams);
 
@@ -1041,6 +1047,18 @@
         }
     }
 
+    static Provider getBouncyCastleProvider()
+    {
+        if (Security.getProvider("BC") != null)
+        {
+            return Security.getProvider("BC");
+        }
+        else
+        {
+            return new BouncyCastleProvider();
+        }
+    }
+
     public static class Std
        extends BcKeyStoreSpi
     {
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
index f986734..53548f0 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
@@ -15,6 +15,7 @@
 import java.security.KeyStoreException;
 import java.security.KeyStoreSpi;
 import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
 import java.security.Principal;
 import java.security.PrivateKey;
 import java.security.Provider;
@@ -88,12 +89,14 @@
 import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
 import org.bouncycastle.crypto.Digest;
 import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.jcajce.provider.config.PKCS12StoreParameter;
+import org.bouncycastle.jcajce.PKCS12StoreParameter;
 import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
 // BEGIN android-removed
 // import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
 // END android-removed
 import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
 import org.bouncycastle.jce.interfaces.BCKeyStore;
 import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -107,10 +110,11 @@
     extends KeyStoreSpi
     implements PKCSObjectIdentifiers, X509ObjectIdentifiers, BCKeyStore
 {
+    private final JcaJceHelper helper = new BCJcaJceHelper();
+
     private static final int SALT_SIZE = 20;
     private static final int MIN_ITERATIONS = 1024;
 
-    private static final Provider bcProvider = new BouncyCastleProvider();
     private static final DefaultSecretKeyProvider keySizeProvider = new DefaultSecretKeyProvider();
 
     private IgnoresCaseHashtable keys = new IgnoresCaseHashtable();
@@ -605,8 +609,8 @@
                 PBEKeySpec pbeSpec = new PBEKeySpec(password);
                 PrivateKey out;
 
-                SecretKeyFactory keyFact = SecretKeyFactory.getInstance(
-                    algorithm.getId(), bcProvider);
+                SecretKeyFactory keyFact = helper.createSecretKeyFactory(
+                    algorithm.getId());
                 PBEParameterSpec defParams = new PBEParameterSpec(
                     pbeParams.getIV(),
                     pbeParams.getIterations().intValue());
@@ -615,7 +619,7 @@
 
                 ((BCPBEKey)k).setTryWrongPKCS12Zero(wrongPKCS12Zero);
 
-                Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider);
+                Cipher cipher = helper.createCipher(algorithm.getId());
 
                 cipher.init(Cipher.UNWRAP_MODE, k, defParams);
 
@@ -651,13 +655,12 @@
 
         try
         {
-            SecretKeyFactory keyFact = SecretKeyFactory.getInstance(
-                algorithm, bcProvider);
+            SecretKeyFactory keyFact =  helper.createSecretKeyFactory(algorithm);
             PBEParameterSpec defParams = new PBEParameterSpec(
                 pbeParams.getIV(),
                 pbeParams.getIterations().intValue());
 
-            Cipher cipher = Cipher.getInstance(algorithm, bcProvider);
+            Cipher cipher = helper.createCipher(algorithm);
 
             cipher.init(Cipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), defParams);
 
@@ -689,7 +692,7 @@
 
             try
             {
-                SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm.getId(), bcProvider);
+                SecretKeyFactory keyFact = helper.createSecretKeyFactory(algorithm.getId());
                 PBEParameterSpec defParams = new PBEParameterSpec(
                     pbeParams.getIV(),
                     pbeParams.getIterations().intValue());
@@ -697,7 +700,7 @@
 
                 key.setTryWrongPKCS12Zero(wrongPKCS12Zero);
 
-                Cipher cipher = Cipher.getInstance(algorithm.getId(), bcProvider);
+                Cipher cipher = helper.createCipher(algorithm.getId());
 
                 cipher.init(mode, key, defParams);
                 return cipher.doFinal(data);
@@ -727,13 +730,13 @@
     }
 
     private Cipher createCipher(int mode, char[] password, AlgorithmIdentifier algId)
-        throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException
+        throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchProviderException
     {
         PBES2Parameters alg = PBES2Parameters.getInstance(algId.getParameters());
         PBKDF2Params func = PBKDF2Params.getInstance(alg.getKeyDerivationFunc().getParameters());
         AlgorithmIdentifier encScheme = AlgorithmIdentifier.getInstance(alg.getEncryptionScheme());
 
-        SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg.getKeyDerivationFunc().getAlgorithm().getId(), bcProvider);
+        SecretKeyFactory keyFact = helper.createSecretKeyFactory(alg.getKeyDerivationFunc().getAlgorithm().getId());
         SecretKey key;
 
         if (func.isDefaultPrf())
@@ -1654,7 +1657,7 @@
         asn1Out.writeObject(pfx);
     }
 
-    private static byte[] calculatePbeMac(
+    private byte[] calculatePbeMac(
         ASN1ObjectIdentifier oid,
         byte[] salt,
         int itCount,
@@ -1663,13 +1666,13 @@
         byte[] data)
         throws Exception
     {
-        SecretKeyFactory keyFact = SecretKeyFactory.getInstance(oid.getId(), bcProvider);
+        SecretKeyFactory keyFact = helper.createSecretKeyFactory(oid.getId());
         PBEParameterSpec defParams = new PBEParameterSpec(salt, itCount);
         PBEKeySpec pbeSpec = new PBEKeySpec(password);
         BCPBEKey key = (BCPBEKey)keyFact.generateSecret(pbeSpec);
         key.setTryWrongPKCS12Zero(wrongPkcs12Zero);
 
-        Mac mac = Mac.getInstance(oid.getId(), bcProvider);
+        Mac mac = helper.createMac(oid.getId());
         mac.init(key, defParams);
         mac.update(data);
         return mac.doFinal();
@@ -1680,20 +1683,19 @@
     {
         public BCPKCS12KeyStore()
         {
-            super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
+            super(new BouncyCastleProvider(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
         }
     }
-
     // BEGIN android-removed
     // public static class BCPKCS12KeyStore3DES
     //     extends PKCS12KeyStoreSpi
     // {
     //     public BCPKCS12KeyStore3DES()
     //     {
-    //         super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
+    //         super(new BouncyCastleProvider(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
     //     }
     // }
-    //
+    // 
     // public static class DefPKCS12KeyStore
     //     extends PKCS12KeyStoreSpi
     // {
@@ -1702,7 +1704,7 @@
     //         super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
     //     }
     // }
-    //
+    // 
     // public static class DefPKCS12KeyStore3DES
     //     extends PKCS12KeyStoreSpi
     // {
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 55f5ace..630a3ca 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
@@ -16,6 +16,9 @@
 // END android-removed
 
 import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
+// BEGIN android-removed
+// import org.bouncycastle.asn1.cms.CCMParameters;
+// END android-removed
 import org.bouncycastle.asn1.cms.GCMParameters;
 import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
 import org.bouncycastle.crypto.BlockCipher;
@@ -31,6 +34,9 @@
 // import org.bouncycastle.crypto.macs.GMac;
 // END android-removed
 import org.bouncycastle.crypto.modes.CBCBlockCipher;
+// BEGIN android-removed
+// import org.bouncycastle.crypto.modes.CCMBlockCipher;
+// END android-removed
 import org.bouncycastle.crypto.modes.CFBBlockCipher;
 import org.bouncycastle.crypto.modes.GCMBlockCipher;
 import org.bouncycastle.crypto.modes.OFBBlockCipher;
@@ -48,9 +54,6 @@
 import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider;
 import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters;
 import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory;
-// BEGIN android-removed
-// import org.bouncycastle.jce.provider.BouncyCastleProvider;
-// END android-removed
 import org.bouncycastle.util.Integers;
 
 public final class AES
@@ -113,6 +116,15 @@
     }
 
     // BEGIN android-removed
+    // static public class CCM
+    //     extends BaseBlockCipher
+    // {
+    //     public CCM()
+    //     {
+    //         super(new CCMBlockCipher(new AESFastEngine()));
+    //     }
+    // }
+    //
     // public static class AESCMAC
     //     extends BaseMac
     // {
@@ -369,7 +381,7 @@
     //
     //         try
     //         {
-    //             params = AlgorithmParameters.getInstance("AES", BouncyCastleProvider.PROVIDER_NAME);
+    //             params = createParametersInstance("AES");
     //             params.init(new IvParameterSpec(iv));
     //         }
     //         catch (Exception e)
@@ -380,6 +392,82 @@
     //         return params;
     //     }
     // }
+    //
+    // public static class AlgParamGenCCM
+    //     extends BaseAlgorithmParameterGenerator
+    // {
+    //     protected void engineInit(
+    //         AlgorithmParameterSpec genParamSpec,
+    //         SecureRandom random)
+    //         throws InvalidAlgorithmParameterException
+    //     {
+    //         throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation.");
+    //     }
+    //
+    //     protected AlgorithmParameters engineGenerateParameters()
+    //     {
+    //         byte[]  iv = new byte[12];
+    //
+    //         if (random == null)
+    //         {
+    //             random = new SecureRandom();
+    //         }
+    //
+    //         random.nextBytes(iv);
+    //
+    //         AlgorithmParameters params;
+    //
+    //         try
+    //         {
+    //             params = createParametersInstance("CCM");
+    //             params.init(new CCMParameters(iv, 12).getEncoded());
+    //         }
+    //         catch (Exception e)
+    //         {
+    //             throw new RuntimeException(e.getMessage());
+    //         }
+    //
+    //         return params;
+    //     }
+    // }
+    //
+    // public static class AlgParamGenGCM
+    //     extends BaseAlgorithmParameterGenerator
+    // {
+    //     protected void engineInit(
+    //         AlgorithmParameterSpec genParamSpec,
+    //         SecureRandom random)
+    //         throws InvalidAlgorithmParameterException
+    //     {
+    //         throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation.");
+    //     }
+    //
+    //     protected AlgorithmParameters engineGenerateParameters()
+    //     {
+    //         byte[]  nonce = new byte[12];
+    //
+    //         if (random == null)
+    //         {
+    //             random = new SecureRandom();
+    //         }
+    //
+    //         random.nextBytes(nonce);
+    //
+    //         AlgorithmParameters params;
+    //
+    //         try
+    //         {
+    //             params = createParametersInstance("GCM");
+    //             params.init(new GCMParameters(nonce, 12).getEncoded());
+    //         }
+    //         catch (Exception e)
+    //         {
+    //             throw new RuntimeException(e.getMessage());
+    //         }
+    //
+    //         return params;
+    //     }
+    // }
     // END android-removed
 
     public static class AlgParams
@@ -406,8 +494,7 @@
                     Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]);
                     Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]);
 
-
-                    gcmParams = new GCMParameters((byte[])iv.invoke(paramSpec, new Object[0]), ((Integer)tLen.invoke(paramSpec, new Object[0])).intValue());
+                    gcmParams = new GCMParameters((byte[])iv.invoke(paramSpec, new Object[0]), ((Integer)tLen.invoke(paramSpec, new Object[0])).intValue() / 8);
                 }
                 catch (Exception e)
                 {
@@ -464,7 +551,7 @@
                 {
                     Constructor constructor = gcmSpecClass.getConstructor(new Class[] { Integer.TYPE, byte[].class });
 
-                    return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(gcmParams.getIcvLen()), gcmParams.getNonce() });
+                    return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(gcmParams.getIcvLen() * 8), gcmParams.getNonce() });
                 }
                 catch (NoSuchMethodException e)
                 {
@@ -480,6 +567,83 @@
         }
     }
 
+    // BEGIN android-removed
+    // public static class AlgParamsCCM
+    //     extends BaseAlgorithmParameters
+    // {
+    //     private CCMParameters ccmParams;
+    // 
+    //     protected void engineInit(AlgorithmParameterSpec paramSpec)
+    //         throws InvalidParameterSpecException
+    //     {
+    //         throw new InvalidParameterSpecException("No supported AlgorithmParameterSpec for AES parameter generation.");
+    //     }
+    // 
+    //     protected void engineInit(byte[] params)
+    //         throws IOException
+    //     {
+    //         ccmParams = CCMParameters.getInstance(params);
+    //     }
+    // 
+    //     protected void engineInit(byte[] params, String format)
+    //         throws IOException
+    //     {
+    //         if (!isASN1FormatString(format))
+    //         {
+    //             throw new IOException("unknown format specified");
+    //         }
+    // 
+    //         ccmParams = CCMParameters.getInstance(params);
+    //     }
+    // 
+    //     protected byte[] engineGetEncoded()
+    //         throws IOException
+    //     {
+    //         return ccmParams.getEncoded();
+    //     }
+    // 
+    //     protected byte[] engineGetEncoded(String format)
+    //         throws IOException
+    //     {
+    //         if (!isASN1FormatString(format))
+    //         {
+    //             throw new IOException("unknown format specified");
+    //         }
+    // 
+    //         return ccmParams.getEncoded();
+    //     }
+    // 
+    //     protected String engineToString()
+    //     {
+    //         return "CCM";
+    //     }
+    // 
+    //     protected AlgorithmParameterSpec localEngineGetParameterSpec(Class paramSpec)
+    //         throws InvalidParameterSpecException
+    //     {
+    //         if (gcmSpecClass != null)
+    //         {
+    //             try
+    //             {
+    //                 Constructor constructor = gcmSpecClass.getConstructor(new Class[] { Integer.TYPE, byte[].class });
+    // 
+    //                 return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(ccmParams.getIcvLen() * 8), ccmParams.getNonce() });
+    //             }
+    //             catch (NoSuchMethodException e)
+    //             {
+    //                 throw new InvalidParameterSpecException("no constructor found!");   // should never happen
+    //             }
+    //             catch (Exception e)
+    //             {
+    //                 throw new InvalidParameterSpecException("construction failed: " + e.getMessage());   // should never happen
+    //             }
+    //         }
+    // 
+    //         throw new InvalidParameterSpecException("unknown parameter spec: " + paramSpec.getName());
+    //     }
+    // }
+    // END android-removed
+
     public static class Mappings
         extends SymmetricAlgorithmProvider
     {
@@ -512,8 +676,12 @@
             provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
             provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
             provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
-
             // BEGIN android-removed
+            // provider.addAlgorithm("AlgorithmParameters.CCM", PREFIX + "$AlgParamsCCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes128_CCM, "CCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_CCM, "CCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
+            //
             // provider.addAlgorithm("AlgorithmParameterGenerator.AES", PREFIX + "$AlgParamGen");
             // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES128, "AES");
             // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES192, "AES");
@@ -549,6 +717,21 @@
             // BEGIN android-removed
             // provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap");
             // provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap");
+            // 
+            // provider.addAlgorithm("AlgorithmParameterGenerator.CCM", PREFIX + "$AlgParamGenCCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes128_CCM, "CCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_CCM, "CCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
+            // 
+            // 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");
+            // provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
+            // 
+            // provider.addAlgorithm("AlgorithmParameterGenerator.GCM", PREFIX + "$AlgParamGenGCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
+            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
             // END android-removed
 
             provider.addAlgorithm("Cipher.GCM", PREFIX + "$GCM");
@@ -577,7 +760,13 @@
             // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_wrap, PREFIX + "$KeyGen128");
             // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_wrap, PREFIX + "$KeyGen192");
             // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_wrap, PREFIX + "$KeyGen256");
-            //
+            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_GCM, PREFIX + "$KeyGen128");
+            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_GCM, PREFIX + "$KeyGen192");
+            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_GCM, PREFIX + "$KeyGen256");
+            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_CCM, PREFIX + "$KeyGen128");
+            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_CCM, PREFIX + "$KeyGen192");
+            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_CCM, PREFIX + "$KeyGen256");
+            // 
             // provider.addAlgorithm("Mac.AESCMAC", PREFIX + "$AESCMAC");
             // END android-removed
             
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java
index 6d5c5e8..b4c7c06 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DES.java
@@ -44,7 +44,6 @@
 import org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher;
 import org.bouncycastle.jcajce.provider.symmetric.util.PBE;
 import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 public final class DES
 {
@@ -187,7 +186,7 @@
 
             try
             {
-                params = AlgorithmParameters.getInstance("DES", BouncyCastleProvider.PROVIDER_NAME);
+                params = createParametersInstance("DES");
                 params.init(new IvParameterSpec(iv));
             }
             catch (Exception e)
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java
index 6b9b6d6..7b3addd 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/DESede.java
@@ -43,7 +43,6 @@
 import org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory;
 import org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher;
 import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 public final class DESede
 {
@@ -270,30 +269,30 @@
     //     {
     //         throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DES parameter generation.");
     //     }
-    //
+
     //     protected AlgorithmParameters engineGenerateParameters()
     //     {
     //         byte[]  iv = new byte[8];
-    //
+
     //         if (random == null)
     //         {
     //             random = new SecureRandom();
     //         }
-    //
+
     //         random.nextBytes(iv);
-    //
+
     //         AlgorithmParameters params;
-    //
+
     //         try
     //         {
-    //             params = AlgorithmParameters.getInstance("DES", BouncyCastleProvider.PROVIDER_NAME);
+    //             params = createParametersInstance("DES");
     //             params.init(new IvParameterSpec(iv));
     //         }
     //         catch (Exception e)
     //         {
     //             throw new RuntimeException(e.getMessage());
     //         }
-    //
+
     //         return params;
     //     }
     // }
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java
index 09426b2..4056aa7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/RC2.java
@@ -36,10 +36,7 @@
 // END android-removed
 import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory;
 import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-// BEGIN android-removed
-// import org.bouncycastle.util.Arrays;
-// END android-removed
+import org.bouncycastle.util.Arrays;
 
 public final class RC2
 {
@@ -218,7 +215,7 @@
     //     extends BaseAlgorithmParameterGenerator
     // {
     //     RC2ParameterSpec spec = null;
-    //
+    // 
     //     protected void engineInit(
     //         AlgorithmParameterSpec genParamSpec,
     //         SecureRandom random)
@@ -229,28 +226,28 @@
     //             spec = (RC2ParameterSpec)genParamSpec;
     //             return;
     //         }
-    //
+    // 
     //         throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for RC2 parameter generation.");
     //     }
-    //
+    // 
     //     protected AlgorithmParameters engineGenerateParameters()
     //     {
     //         AlgorithmParameters params;
-    //
+    // 
     //         if (spec == null)
     //         {
     //             byte[] iv = new byte[8];
-    //
+    // 
     //             if (random == null)
     //             {
     //                 random = new SecureRandom();
     //             }
-    //
+    // 
     //             random.nextBytes(iv);
-    //
+    // 
     //             try
     //             {
-    //                 params = AlgorithmParameters.getInstance("RC2", BouncyCastleProvider.PROVIDER_NAME);
+    //                 params = createParametersInstance("RC2");
     //                 params.init(new IvParameterSpec(iv));
     //             }
     //             catch (Exception e)
@@ -262,7 +259,7 @@
     //         {
     //             try
     //             {
-    //                 params = AlgorithmParameters.getInstance("RC2", BouncyCastleProvider.PROVIDER_NAME);
+    //                 params = createParametersInstance("RC2");
     //                 params.init(spec);
     //             }
     //             catch (Exception e)
@@ -270,11 +267,11 @@
     //                 throw new RuntimeException(e.getMessage());
     //             }
     //         }
-    //
+    // 
     //         return params;
     //     }
     // }
-    //
+    // 
     // public static class KeyGenerator
     //     extends BaseKeyGenerator
     // {
@@ -283,7 +280,7 @@
     //         super("RC2", 128, new CipherKeyGenerator());
     //     }
     // }
-    //
+    // 
     // public static class AlgParams
     //     extends BaseAlgorithmParameters
     // {
@@ -305,7 +302,7 @@
     //         0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,
     //         0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab
     //     };
-    //
+    // 
     //     private static final short[] ekb = {
     //         0x5d, 0xbe, 0x9b, 0x8b, 0x11, 0x99, 0x6e, 0x4d, 0x59, 0xf3, 0x85, 0xa6, 0x3f, 0xb7, 0x83, 0xc5,
     //         0xe4, 0x73, 0x6b, 0x3a, 0x68, 0x5a, 0xc0, 0x47, 0xa0, 0x64, 0x34, 0x0c, 0xf1, 0xd0, 0x52, 0xa5,
@@ -324,15 +321,15 @@
     //         0xbd, 0x22, 0xbf, 0x9f, 0x7e, 0xa9, 0x51, 0x4b, 0x4c, 0xfb, 0x02, 0xd3, 0x70, 0x86, 0x31, 0xe7,
     //         0x3b, 0x05, 0x03, 0x54, 0x60, 0x48, 0x65, 0x18, 0xd2, 0xcd, 0x5f, 0x32, 0x88, 0x0e, 0x35, 0xfd
     //     };
-    //
+    // 
     //     private byte[] iv;
     //     private int parameterVersion = 58;
-    //
+    // 
     //     protected byte[] engineGetEncoded()
     //     {
     //         return Arrays.clone(iv);
     //     }
-    //
+    // 
     //     protected byte[] engineGetEncoded(
     //         String format)
     //         throws IOException
@@ -348,15 +345,15 @@
     //                 return new RC2CBCParameter(parameterVersion, engineGetEncoded()).getEncoded();
     //             }
     //         }
-    //
+    // 
     //         if (format.equals("RAW"))
     //         {
     //             return engineGetEncoded();
     //         }
-    //
+    // 
     //         return null;
     //     }
-    //
+    // 
     //     protected AlgorithmParameterSpec localEngineGetParameterSpec(
     //         Class paramSpec)
     //         throws InvalidParameterSpecException
@@ -375,15 +372,15 @@
     //                 }
     //             }
     //         }
-    //
+    // 
     //         if (paramSpec == IvParameterSpec.class)
     //         {
     //             return new IvParameterSpec(iv);
     //         }
-    //
+    // 
     //         throw new InvalidParameterSpecException("unknown parameter spec passed to RC2 parameters object.");
     //     }
-    //
+    // 
     //     protected void engineInit(
     //         AlgorithmParameterSpec paramSpec)
     //         throws InvalidParameterSpecException
@@ -406,7 +403,7 @@
     //                     parameterVersion = effKeyBits;
     //                 }
     //             }
-    //
+    // 
     //             this.iv = ((RC2ParameterSpec)paramSpec).getIV();
     //         }
     //         else
@@ -414,14 +411,14 @@
     //             throw new InvalidParameterSpecException("IvParameterSpec or RC2ParameterSpec required to initialise a RC2 parameters algorithm parameters object");
     //         }
     //     }
-    //
+    // 
     //     protected void engineInit(
     //         byte[] params)
     //         throws IOException
     //     {
     //         this.iv = Arrays.clone(params);
     //     }
-    //
+    // 
     //     protected void engineInit(
     //         byte[] params,
     //         String format)
@@ -430,26 +427,26 @@
     //         if (this.isASN1FormatString(format))
     //         {
     //             RC2CBCParameter p = RC2CBCParameter.getInstance(ASN1Primitive.fromByteArray(params));
-    //
+    // 
     //             if (p.getRC2ParameterVersion() != null)
     //             {
     //                 parameterVersion = p.getRC2ParameterVersion().intValue();
     //             }
-    //
+    // 
     //             iv = p.getIV();
-    //
+    // 
     //             return;
     //         }
-    //
+    // 
     //         if (format.equals("RAW"))
     //         {
     //             engineInit(params);
     //             return;
     //         }
-    //
+    // 
     //         throw new IOException("Unknown parameters format in IV parameters object");
     //     }
-    //
+    // 
     //     protected String engineToString()
     //     {
     //         return "RC2 Parameters";
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseAlgorithmParameterGenerator.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseAlgorithmParameterGenerator.java
index 63d6548..296d692 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseAlgorithmParameterGenerator.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseAlgorithmParameterGenerator.java
@@ -1,14 +1,32 @@
 package org.bouncycastle.jcajce.provider.symmetric.util;
 
 import java.security.AlgorithmParameterGeneratorSpi;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
 import java.security.SecureRandom;
 
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
+
 public abstract class BaseAlgorithmParameterGenerator
     extends AlgorithmParameterGeneratorSpi
 {
+    private final JcaJceHelper helper = new BCJcaJceHelper();
+
     protected SecureRandom  random;
     protected int           strength = 1024;
 
+    public BaseAlgorithmParameterGenerator()
+    {
+    }
+
+    protected final AlgorithmParameters createParametersInstance(String algorithm)
+        throws NoSuchAlgorithmException, NoSuchProviderException
+    {
+        return helper.createAlgorithmParameters(algorithm);
+    }
+
     protected void engineInit(
         int             strength,
         SecureRandom    random)
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
index faf31b3..0e933b7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
@@ -207,7 +207,7 @@
             {
                 try
                 {
-                    engineParams = AlgorithmParameters.getInstance(pbeAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
+                    engineParams = createParametersInstance(pbeAlgorithm);
                     engineParams.init(pbeSpec);
                 }
                 catch (Exception e)
@@ -226,7 +226,7 @@
 
                 try
                 {
-                    engineParams = AlgorithmParameters.getInstance(name, BouncyCastleProvider.PROVIDER_NAME);
+                    engineParams = createParametersInstance(name);
                     engineParams.init(ivParam.getIV());
                 }
                 catch (Exception e)
@@ -238,7 +238,7 @@
             {
                 try
                 {
-                    engineParams = AlgorithmParameters.getInstance("GCM", BouncyCastleProvider.PROVIDER_NAME);
+                    engineParams = createParametersInstance("GCM");
                     engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize()).getEncoded());
                 }
                 catch (Exception e)
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 b37a9fe..fba61b8 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.InvalidKeyException;
 import java.security.InvalidParameterException;
 import java.security.Key;
+import java.security.Provider;
 import java.security.SecureRandom;
 import java.security.spec.AlgorithmParameterSpec;
 
@@ -89,7 +90,7 @@
             {
                 try
                 {
-                    AlgorithmParameters engineParams = AlgorithmParameters.getInstance(pbeAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
+                    AlgorithmParameters engineParams = createParametersInstance(pbeAlgorithm);
                     engineParams.init(pbeSpec);
 
                     return engineParams;
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
index 5be73e5..a26d980 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
@@ -8,7 +8,9 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.PrivateKey;
+import java.security.Provider;
 import java.security.SecureRandom;
+import java.security.Security;
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
@@ -35,6 +37,8 @@
 import org.bouncycastle.crypto.params.KeyParameter;
 import org.bouncycastle.crypto.params.ParametersWithIV;
 import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 public abstract class BaseWrapCipher
@@ -66,6 +70,8 @@
     private int                       ivSize;
     private byte[]                    iv;
 
+    private final JcaJceHelper helper = new BCJcaJceHelper();
+
     protected BaseWrapCipher()
     {
     }
@@ -111,6 +117,12 @@
         return null;
     }
 
+    protected final AlgorithmParameters createParametersInstance(String algorithm)
+        throws NoSuchAlgorithmException, NoSuchProviderException
+    {
+        return helper.createAlgorithmParameters(algorithm);
+    }
+
     protected void engineSetMode(
         String  mode)
         throws NoSuchAlgorithmException
@@ -374,7 +386,7 @@
         {
             try
             {
-                KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
+                KeyFactory kf = helper.createKeyFactory(wrappedKeyAlgorithm);
 
                 if (wrappedKeyType == Cipher.PUBLIC_KEY)
                 {
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java
new file mode 100644
index 0000000..4008761
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/BCJcaJceHelper.java
@@ -0,0 +1,30 @@
+package org.bouncycastle.jcajce.util;
+
+import java.security.Provider;
+import java.security.Security;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+/**
+ * A JCA/JCE helper that refers to the BC provider for all it's needs.
+ */
+public class BCJcaJceHelper
+    extends ProviderJcaJceHelper
+{
+    private static Provider getBouncyCastleProvider()
+    {
+        if (Security.getProvider("BC") != null)
+        {
+            return Security.getProvider("BC");
+        }
+        else
+        {
+            return new BouncyCastleProvider();
+        }
+    }
+
+    public BCJcaJceHelper()
+    {
+        super(getBouncyCastleProvider());
+    }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java
index 43a97f3..27ca55a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/DefaultJcaJceHelper.java
@@ -92,7 +92,7 @@
     }
 
     public CertificateFactory createCertificateFactory(String algorithm)
-        throws NoSuchAlgorithmException, CertificateException
+        throws CertificateException
     {
         return CertificateFactory.getInstance(algorithm);
     }
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java
index f5da335..7a78193 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/JcaJceHelper.java
@@ -58,5 +58,5 @@
         throws NoSuchAlgorithmException, NoSuchProviderException;
 
     CertificateFactory createCertificateFactory(String algorithm)
-        throws NoSuchAlgorithmException, NoSuchProviderException, CertificateException;
+        throws NoSuchProviderException, CertificateException;
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java
index ebbfacc..280539d 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/NamedJcaJceHelper.java
@@ -99,7 +99,7 @@
     }
 
     public CertificateFactory createCertificateFactory(String algorithm)
-        throws NoSuchAlgorithmException, CertificateException, NoSuchProviderException
+        throws CertificateException, NoSuchProviderException
     {
         return CertificateFactory.getInstance(algorithm, providerName);
     }
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java b/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java
index fad1048..fb4b9a7 100644
--- a/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java
+++ b/bcprov/src/main/java/org/bouncycastle/jcajce/util/ProviderJcaJceHelper.java
@@ -99,7 +99,7 @@
     }
 
     public CertificateFactory createCertificateFactory(String algorithm)
-        throws NoSuchAlgorithmException, CertificateException
+        throws CertificateException
     {
         return CertificateFactory.getInstance(algorithm, provider);
     }
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/AnnotatedException.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/AnnotatedException.java
index c9ac46e..e8a8abe 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/AnnotatedException.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/AnnotatedException.java
@@ -8,14 +8,14 @@
 {
     private Throwable _underlyingException;
 
-    AnnotatedException(String string, Throwable e)
+    public AnnotatedException(String string, Throwable e)
     {
         super(string);
 
         _underlyingException = e;
     }
 
-    AnnotatedException(String string)
+    public AnnotatedException(String string)
     {
         this(string, null);
     }
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 145186a..82c6a5a 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java
@@ -44,7 +44,7 @@
 public final class BouncyCastleProvider extends Provider
     implements ConfigurableProvider
 {
-    private static String info = "BouncyCastle Security Provider v1.51";
+    private static String info = "BouncyCastle Security Provider v1.52";
 
     public static final String PROVIDER_NAME = "BC";
 
@@ -139,7 +139,7 @@
      */
     public BouncyCastleProvider()
     {
-        super(PROVIDER_NAME, 1.51, info);
+        super(PROVIDER_NAME, 1.52, info);
 
         AccessController.doPrivileged(new PrivilegedAction()
         {
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
index b4338f6..f53f3ac 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
@@ -13,7 +13,6 @@
 import java.security.cert.CertStoreException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateParsingException;
-import java.security.cert.PKIXParameters;
 import java.security.cert.PolicyQualifierInfo;
 import java.security.cert.TrustAnchor;
 import java.security.cert.X509CRL;
@@ -27,14 +26,15 @@
 import java.text.ParseException;
 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.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import javax.security.auth.x500.X500Principal;
 
 import org.bouncycastle.asn1.ASN1Encodable;
@@ -47,10 +47,13 @@
 import org.bouncycastle.asn1.ASN1OutputStream;
 import org.bouncycastle.asn1.ASN1Primitive;
 import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERIA5String;
+import org.bouncycastle.asn1.DEROctetString;
 import org.bouncycastle.asn1.DERSequence;
 import org.bouncycastle.asn1.isismtt.ISISMTTObjectIdentifiers;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.RFC4519Style;
 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
 import org.bouncycastle.asn1.x509.CRLDistPoint;
 import org.bouncycastle.asn1.x509.CRLReason;
 import org.bouncycastle.asn1.x509.DistributionPoint;
@@ -60,27 +63,22 @@
 import org.bouncycastle.asn1.x509.GeneralNames;
 import org.bouncycastle.asn1.x509.PolicyInformation;
 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509Extension;
-// BEGIN android-removed
-// import org.bouncycastle.jce.X509LDAPCertStoreParameters;
-// END android-removed
+import org.bouncycastle.jcajce.PKIXCRLStore;
+import org.bouncycastle.jcajce.PKIXCRLStoreSelector;
+import org.bouncycastle.jcajce.PKIXCertStore;
+import org.bouncycastle.jcajce.PKIXCertStoreSelector;
+import org.bouncycastle.jcajce.PKIXExtendedParameters;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
 import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
-import org.bouncycastle.util.Integers;
 import org.bouncycastle.util.Selector;
+import org.bouncycastle.util.Store;
 import org.bouncycastle.util.StoreException;
-import org.bouncycastle.x509.ExtendedPKIXBuilderParameters;
-import org.bouncycastle.x509.ExtendedPKIXParameters;
-// BEGIN android-removed
-// import org.bouncycastle.x509.X509AttributeCertStoreSelector;
-// END android-removed
 import org.bouncycastle.x509.X509AttributeCertificate;
-import org.bouncycastle.x509.X509CRLStoreSelector;
-import org.bouncycastle.x509.X509CertStoreSelector;
 // BEGIN android-removed
-// import org.bouncycastle.x509.X509Store;
+// import org.bouncycastle.x509.extension.X509ExtensionUtil;
 // END android-removed
 
-public class CertPathValidatorUtilities
+class CertPathValidatorUtilities
 {
     protected static final PKIXCRLUtil CRL_UTIL = new PKIXCRLUtil();
 
@@ -166,7 +164,7 @@
         Exception invalidKeyEx = null;
 
         X509CertSelector certSelectX509 = new X509CertSelector();
-        X500Principal certIssuer = getEncodedIssuerPrincipal(cert);
+        X500Name certIssuer = PrincipalUtils.getEncodedIssuerPrincipal(cert);
 
         try
         {
@@ -197,7 +195,7 @@
             {
                 try
                 {
-                    X500Principal caName = new X500Principal(trust.getCAName());
+                    X500Name caName = PrincipalUtils.getCA(trust);
                     if (certIssuer.equals(caName))
                     {
                         trustPublicKey = trust.getCAPublicKey();
@@ -240,50 +238,41 @@
         return trust;
     }
 
-    protected static void addAdditionalStoresFromAltNames(
-        X509Certificate cert,
-        ExtendedPKIXParameters pkixParams)
+    static List<PKIXCertStore> getAdditionalStoresFromAltNames(
+        byte[] issuerAlternativeName,
+        Map<GeneralName, PKIXCertStore> altNameCertStoreMap)
         throws CertificateParsingException
     {
         // if in the IssuerAltName extension an URI
-        // is given, add an additinal X.509 store
-        if (cert.getIssuerAlternativeNames() != null)
+        // is given, add an additional X.509 store
+        if (issuerAlternativeName != null)
         {
-            Iterator it = cert.getIssuerAlternativeNames().iterator();
-            while (it.hasNext())
+            GeneralNames issuerAltName = GeneralNames.getInstance(ASN1OctetString.getInstance(issuerAlternativeName).getOctets());
+
+            GeneralName[] names = issuerAltName.getNames();
+            List<PKIXCertStore>  stores = new ArrayList<PKIXCertStore>();
+
+            for (int i = 0; i != names.length; i++)
             {
-                // look for URI
-                List list = (List)it.next();
-                if (list.get(0).equals(Integers.valueOf(GeneralName.uniformResourceIdentifier)))
+                GeneralName altName = names[i];
+
+                PKIXCertStore altStore = altNameCertStoreMap.get(altName);
+
+                if (altStore != null)
                 {
-                    // found
-                    String temp = (String)list.get(1);
-                    CertPathValidatorUtilities.addAdditionalStoreFromLocation(temp, pkixParams);
+                    stores.add(altStore);
                 }
             }
-        }
-    }
 
-    /**
-     * Returns the issuer of an attribute certificate or certificate.
-     *
-     * @param cert The attribute certificate or certificate.
-     * @return The issuer as <code>X500Principal</code>.
-     */
-    protected static X500Principal getEncodedIssuerPrincipal(
-        Object cert)
-    {
-        if (cert instanceof X509Certificate)
-        {
-            return ((X509Certificate)cert).getIssuerX500Principal();
+            return stores;
         }
         else
         {
-            return (X500Principal)((X509AttributeCertificate)cert).getIssuer().getPrincipals()[0];
+            return Collections.EMPTY_LIST;
         }
     }
 
-    protected static Date getValidDate(PKIXParameters paramsPKIX)
+    protected static Date getValidDate(PKIXExtendedParameters paramsPKIX)
     {
         Date validDate = paramsPKIX.getDate();
 
@@ -295,11 +284,6 @@
         return validDate;
     }
 
-    protected static X500Principal getSubjectPrincipal(X509Certificate cert)
-    {
-        return cert.getSubjectX500Principal();
-    }
-
     protected static boolean isSelfIssued(X509Certificate cert)
     {
         return cert.getSubjectDN().equals(cert.getIssuerDN());
@@ -346,11 +330,6 @@
         }
     }
 
-    protected static X500Principal getIssuerPrincipal(X509CRL crl)
-    {
-        return crl.getIssuerX500Principal();
-    }
-
     protected static AlgorithmIdentifier getAlgorithmIdentifier(
         PublicKey key)
         throws CertPathValidatorException
@@ -361,7 +340,7 @@
 
             SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject());
 
-            return info.getAlgorithmId();
+            return info.getAlgorithm();
         }
         catch (Exception e)
         {
@@ -655,73 +634,22 @@
         return policySet == null || policySet.contains(ANY_POLICY) || policySet.isEmpty();
     }
 
-    protected static void addAdditionalStoreFromLocation(String location,
-                                                         ExtendedPKIXParameters pkixParams)
-    {
-        if (pkixParams.isAdditionalLocationsEnabled())
-        {
-            try
-            {
-                // BEGIN android-removed
-                // if (location.startsWith("ldap://"))
-                // {
-                //     // ldap://directory.d-trust.net/CN=D-TRUST
-                //     // Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE
-                //     // skip "ldap://"
-                //     location = location.substring(7);
-                //     // after first / baseDN starts
-                //     String base = null;
-                //     String url = null;
-                //     if (location.indexOf("/") != -1)
-                //     {
-                //         base = location.substring(location.indexOf("/"));
-                //         // URL
-                //         url = "ldap://"
-                //             + location.substring(0, location.indexOf("/"));
-                //     }
-                //     else
-                //     {
-                //         url = "ldap://" + location;
-                //     }
-                //     // use all purpose parameters
-                //     X509LDAPCertStoreParameters params = new X509LDAPCertStoreParameters.Builder(
-                //         url, base).build();
-                //     pkixParams.addAdditionalStore(X509Store.getInstance(
-                //         "CERTIFICATE/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
-                //     pkixParams.addAdditionalStore(X509Store.getInstance(
-                //         "CRL/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
-                //     pkixParams.addAdditionalStore(X509Store.getInstance(
-                //         "ATTRIBUTECERTIFICATE/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
-                //     pkixParams.addAdditionalStore(X509Store.getInstance(
-                //         "CERTIFICATEPAIR/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
-                // }
-                // END android-removed
-            }
-            catch (Exception e)
-            {
-                // cannot happen
-                throw new RuntimeException("Exception adding X.509 stores.");
-            }
-        }
-    }
-
     /**
      * Return a Collection of all certificates or attribute certificates found
      * in the X509Store's that are matching the certSelect criteriums.
      *
      * @param certSelect a {@link Selector} object that will be used to select
      *                   the certificates
-     * @param certStores a List containing only {@link X509Store} objects. These
+     * @param certStores a List containing only {@link Store} objects. These
      *                   are used to search for certificates.
-     * @return a Collection of all found {@link X509Certificate} or
-     *         {@link org.bouncycastle.x509.X509AttributeCertificate} objects.
+     * @return a Collection of all found {@link X509Certificate}
      *         May be empty but never <code>null</code>.
      */
-    protected static Collection findCertificates(X509CertStoreSelector certSelect,
+    protected static Collection findCertificates(PKIXCertStoreSelector certSelect,
                                                  List certStores)
         throws AnnotatedException
     {
-        Set certs = new HashSet();
+        Set certs = new LinkedHashSet();
         Iterator iter = certStores.iterator();
 
         while (iter.hasNext())
@@ -749,7 +677,7 @@
 
                 try
                 {
-                    certs.addAll(certStore.getCertificates(certSelect));
+                    certs.addAll(PKIXCertStoreSelector.getCertificates(certSelect, certStore));
                 }
                 catch (CertStoreException e)
                 {
@@ -762,38 +690,7 @@
         return certs;
     }
 
-    // BEGIN android-removed
-    // protected static Collection findCertificates(X509AttributeCertStoreSelector certSelect,
-    //                                              List certStores)
-    //     throws AnnotatedException
-    // {
-    //     Set certs = new HashSet();
-    //     Iterator iter = certStores.iterator();
-    //
-    //     while (iter.hasNext())
-    //     {
-    //         Object obj = iter.next();
-    //
-    //         if (obj instanceof X509Store)
-    //         {
-    //             X509Store certStore = (X509Store)obj;
-    //             try
-    //             {
-    //                 certs.addAll(certStore.getMatches(certSelect));
-    //             }
-    //             catch (StoreException e)
-    //             {
-    //                 throw new AnnotatedException(
-    //                         "Problem while picking certificates from X.509 store.", e);
-    //             }
-    //         }
-    //     }
-    //     return certs;
-    // }
-    // END android-removed
-
-    protected static void addAdditionalStoresFromCRLDistributionPoint(
-        CRLDistPoint crldp, ExtendedPKIXParameters pkixParams)
+    static List<PKIXCRLStore> getAdditionalStoresFromCRLDistributionPoint(CRLDistPoint crldp, Map<GeneralName, PKIXCRLStore> namedCRLStoreMap)
         throws AnnotatedException
     {
         if (crldp != null)
@@ -808,6 +705,8 @@
                 throw new AnnotatedException(
                     "Distribution points could not be read.", e);
             }
+            List<PKIXCRLStore> stores = new ArrayList<PKIXCRLStore>();
+
             for (int i = 0; i < dps.length; i++)
             {
                 DistributionPointName dpn = dps[i].getDistributionPoint();
@@ -818,21 +717,31 @@
                     {
                         GeneralName[] genNames = GeneralNames.getInstance(
                             dpn.getName()).getNames();
-                        // look for an URI
+
                         for (int j = 0; j < genNames.length; j++)
                         {
-                            if (genNames[j].getTagNo() == GeneralName.uniformResourceIdentifier)
+                            // BEGIN android-removed
+                            // PKIXCRLStore store = namedCRLStoreMap.get(genNames[i]);
+                            // END android-removed
+                            // BEGIN android-added
+                            // Seems like a bug, unless there should be a guarantee that j < i,
+                            // However, it's breaking the tests.
+                            PKIXCRLStore store = namedCRLStoreMap.get(genNames[j]);
+                            // END android-added
+                            if (store != null)
                             {
-                                String location = DERIA5String.getInstance(
-                                    genNames[j].getName()).getString();
-                                CertPathValidatorUtilities
-                                    .addAdditionalStoreFromLocation(location,
-                                        pkixParams);
+                                stores.add(store);
                             }
                         }
                     }
                 }
             }
+
+            return stores;
+        }
+        else
+        {
+            return Collections.EMPTY_LIST;
         }
     }
 
@@ -840,26 +749,22 @@
      * Add the CRL issuers from the cRLIssuer field of the distribution point or
      * from the certificate if not given to the issuer criterion of the
      * <code>selector</code>.
-     * <p/>
+     * <p>
      * The <code>issuerPrincipals</code> are a collection with a single
-     * <code>X500Principal</code> for <code>X509Certificate</code>s. For
-     * {@link X509AttributeCertificate}s the issuer may contain more than one
-     * <code>X500Principal</code>.
-     *
+     * <code>X500Name</code> for <code>X509Certificate</code>s.
+     * </p>
      * @param dp               The distribution point.
      * @param issuerPrincipals The issuers of the certificate or attribute
      *                         certificate which contains the distribution point.
      * @param selector         The CRL selector.
-     * @param pkixParams       The PKIX parameters containing the cert stores.
      * @throws AnnotatedException if an exception occurs while processing.
      * @throws ClassCastException if <code>issuerPrincipals</code> does not
-     * contain only <code>X500Principal</code>s.
+     * contain only <code>X500Name</code>s.
      */
     protected static void getCRLIssuersFromDistributionPoint(
         DistributionPoint dp,
         Collection issuerPrincipals,
-        X509CRLSelector selector,
-        ExtendedPKIXParameters pkixParams)
+        X509CRLSelector selector)
         throws AnnotatedException
     {
         List issuers = new ArrayList();
@@ -874,7 +779,7 @@
                 {
                     try
                     {
-                        issuers.add(new X500Principal(genNames[j].getName()
+                        issuers.add(X500Name.getInstance(genNames[j].getName()
                             .toASN1Primitive().getEncoded()));
                     }
                     catch (IOException e)
@@ -900,7 +805,7 @@
             // add and check issuer principals
             for (Iterator it = issuerPrincipals.iterator(); it.hasNext(); )
             {
-                issuers.add((X500Principal)it.next());
+                issuers.add(it.next());
             }
         }
         // TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid
@@ -952,7 +857,7 @@
         {
             try
             {
-                selector.addIssuerName(((X500Principal)it.next()).getEncoded());
+                selector.addIssuerName(((X500Name)it.next()).getEncoded());
             }
             catch (IOException ex)
             {
@@ -965,14 +870,7 @@
     private static BigInteger getSerialNumber(
         Object cert)
     {
-        if (cert instanceof X509Certificate)
-        {
-            return ((X509Certificate)cert).getSerialNumber();
-        }
-        else
-        {
-            return ((X509AttributeCertificate)cert).getSerialNumber();
-        }
+        return ((X509Certificate)cert).getSerialNumber();
     }
 
     protected static void getCertStatus(
@@ -1002,20 +900,32 @@
             {
                 return;
             }
-
-            X500Principal certIssuer = crl_entry.getCertificateIssuer();
+            // BEGIN android-removed
+            // X500Name certIssuer = X500Name.getInstance(crl_entry.getCertificateIssuer().getEncoded());
+            // END android-removed
+            // BEGIN android-added
+            // The original code throws null pointer exception for OpenSSLX509CRL,
+            // which uses the implementation for getCertificateIssuer() in X509CRL, method
+            // whose reference implementation has the following JavaDoc: "If the certificate
+            // issuer is also the CRL issuer, this method returns null."
+            X500Name certIssuer = null;
+            X500Principal certificateIssuerPrincipal = crl_entry.getCertificateIssuer();
+            if (certificateIssuerPrincipal != null) {
+                certIssuer = X500Name.getInstance(certificateIssuerPrincipal.getEncoded());
+            }
+            // END android-added
 
             if (certIssuer == null)
             {
-                certIssuer = getIssuerPrincipal(crl);
+                certIssuer = PrincipalUtils.getIssuerPrincipal(crl);
             }
 
-            if (!getEncodedIssuerPrincipal(cert).equals(certIssuer))
+            if (! PrincipalUtils.getEncodedIssuerPrincipal(cert).equals(certIssuer))
             {
                 return;
             }
         }
-        else if (!getEncodedIssuerPrincipal(cert).equals(getIssuerPrincipal(crl)))
+        else if (! PrincipalUtils.getEncodedIssuerPrincipal(cert).equals(PrincipalUtils.getIssuerPrincipal(crl)))
         {
             return;  // not for our issuer, ignore
         }
@@ -1037,7 +947,7 @@
                 reasonCode = ASN1Enumerated
                     .getInstance(CertPathValidatorUtilities
                         .getExtensionValue(crl_entry,
-                            X509Extension.reasonCode.getId()));
+                            Extension.reasonCode.getId()));
             }
             catch (Exception e)
             {
@@ -1074,31 +984,29 @@
     /**
      * Fetches delta CRLs according to RFC 3280 section 5.2.4.
      *
-     * @param currentDate The date for which the delta CRLs must be valid.
-     * @param paramsPKIX  The extended PKIX parameters.
+     * @param validityDate The date for which the delta CRLs must be valid.
      * @param completeCRL The complete CRL the delta CRL is for.
      * @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs.
      * @throws AnnotatedException if an exception occurs while picking the delta
      * CRLs.
      */
-    protected static Set getDeltaCRLs(Date currentDate,
-                                      ExtendedPKIXParameters paramsPKIX, X509CRL completeCRL)
+    protected static Set getDeltaCRLs(Date validityDate,
+                                      X509CRL completeCRL, List<CertStore> certStores, List<PKIXCRLStore> pkixCrlStores)
         throws AnnotatedException
     {
-
-        X509CRLStoreSelector deltaSelect = new X509CRLStoreSelector();
-
+        X509CRLSelector baseDeltaSelect = new X509CRLSelector();
         // 5.2.4 (a)
         try
         {
-            deltaSelect.addIssuerName(CertPathValidatorUtilities
-                .getIssuerPrincipal(completeCRL).getEncoded());
+            baseDeltaSelect.addIssuerName(PrincipalUtils.getIssuerPrincipal(completeCRL).getEncoded());
         }
         catch (IOException e)
         {
             throw new AnnotatedException("Cannot extract issuer from CRL.", e);
         }
 
+
+
         BigInteger completeCRLNumber = null;
         try
         {
@@ -1130,17 +1038,21 @@
 
         // 5.2.4 (d)
 
-        deltaSelect.setMinCRLNumber(completeCRLNumber == null ? null : completeCRLNumber
+        baseDeltaSelect.setMinCRLNumber(completeCRLNumber == null ? null : completeCRLNumber
             .add(BigInteger.valueOf(1)));
 
-        deltaSelect.setIssuingDistributionPoint(idp);
-        deltaSelect.setIssuingDistributionPointEnabled(true);
+        PKIXCRLStoreSelector.Builder selBuilder = new PKIXCRLStoreSelector.Builder(baseDeltaSelect);
+
+        selBuilder.setIssuingDistributionPoint(idp);
+        selBuilder.setIssuingDistributionPointEnabled(true);
 
         // 5.2.4 (c)
-        deltaSelect.setMaxBaseCRLNumber(completeCRLNumber);
+        selBuilder.setMaxBaseCRLNumber(completeCRLNumber);
+
+        PKIXCRLStoreSelector deltaSelect = selBuilder.build();
 
         // find delta CRLs
-        Set temp = CRL_UTIL.findCRLs(deltaSelect, paramsPKIX, currentDate);
+        Set temp = CRL_UTIL.findCRLs(deltaSelect, validityDate, certStores, pkixCrlStores);
 
         Set result = new HashSet();
 
@@ -1173,8 +1085,7 @@
      * Fetches complete CRLs according to RFC 3280.
      *
      * @param dp          The distribution point for which the complete CRL
-     * @param cert        The <code>X509Certificate</code> or
-     *                    {@link org.bouncycastle.x509.X509AttributeCertificate} for
+     * @param cert        The <code>X509Certificate</code> for
      *                    which the CRL should be searched.
      * @param currentDate The date for which the delta CRLs must be valid.
      * @param paramsPKIX  The extended PKIX parameters.
@@ -1184,66 +1095,51 @@
      * or no CRLs are found.
      */
     protected static Set getCompleteCRLs(DistributionPoint dp, Object cert,
-                                         Date currentDate, ExtendedPKIXParameters paramsPKIX)
+                                         Date currentDate, PKIXExtendedParameters paramsPKIX)
         throws AnnotatedException
     {
-        X509CRLStoreSelector crlselect = new X509CRLStoreSelector();
+        X509CRLSelector baseCrlSelect = new X509CRLSelector();
+
         try
         {
             Set issuers = new HashSet();
-            if (cert instanceof X509AttributeCertificate)
-            {
-                issuers.add(((X509AttributeCertificate)cert)
-                    .getIssuer().getPrincipals()[0]);
-            }
-            else
-            {
-                issuers.add(getEncodedIssuerPrincipal(cert));
-            }
-            CertPathValidatorUtilities.getCRLIssuersFromDistributionPoint(dp, issuers, crlselect, paramsPKIX);
+
+            issuers.add(PrincipalUtils.getEncodedIssuerPrincipal(cert));
+
+            CertPathValidatorUtilities.getCRLIssuersFromDistributionPoint(dp, issuers, baseCrlSelect);
         }
         catch (AnnotatedException e)
         {
             throw new AnnotatedException(
                 "Could not get issuer information from distribution point.", e);
         }
+
         if (cert instanceof X509Certificate)
         {
-            crlselect.setCertificateChecking((X509Certificate)cert);
+            baseCrlSelect.setCertificateChecking((X509Certificate)cert);
         }
-        else if (cert instanceof X509AttributeCertificate)
+
+        PKIXCRLStoreSelector crlSelect = new PKIXCRLStoreSelector.Builder(baseCrlSelect).setCompleteCRLEnabled(true).build();
+
+        Date validityDate = currentDate;
+
+        if (paramsPKIX.getDate() != null)
         {
-            crlselect.setAttrCertificateChecking((X509AttributeCertificate)cert);
+            validityDate = paramsPKIX.getDate();
         }
 
+        Set crls = CRL_UTIL.findCRLs(crlSelect, validityDate, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores());
 
-        crlselect.setCompleteCRLEnabled(true);
+        checkCRLsNotEmpty(crls, cert);
 
-        Set crls = CRL_UTIL.findCRLs(crlselect, paramsPKIX, currentDate);
-
-        if (crls.isEmpty())
-        {
-            if (cert instanceof X509AttributeCertificate)
-            {
-                X509AttributeCertificate aCert = (X509AttributeCertificate)cert;
-
-                throw new AnnotatedException("No CRLs found for issuer \"" + aCert.getIssuer().getPrincipals()[0] + "\"");
-            }
-            else
-            {
-                X509Certificate xCert = (X509Certificate)cert;
-
-                throw new AnnotatedException("No CRLs found for issuer \"" + xCert.getIssuerX500Principal() + "\"");
-            }
-        }
         return crls;
     }
 
     protected static Date getValidCertDateFromValidityModel(
-        ExtendedPKIXParameters paramsPKIX, CertPath certPath, int index)
+        PKIXExtendedParameters paramsPKIX, CertPath certPath, int index)
         throws AnnotatedException
     {
-        if (paramsPKIX.getValidityModel() == ExtendedPKIXParameters.CHAIN_VALIDITY_MODEL)
+        if (paramsPKIX.getValidityModel() == PKIXExtendedParameters.CHAIN_VALIDITY_MODEL)
         {
             // if end cert use given signing/encryption/... time
             if (index <= 0)
@@ -1324,7 +1220,7 @@
      *         <code>index</code> extended with DSA parameters if applicable.
      * @throws AnnotatedException if DSA parameters cannot be inherited.
      */
-    protected static PublicKey getNextWorkingKey(List certs, int index)
+    protected static PublicKey getNextWorkingKey(List certs, int index, JcaJceHelper helper)
         throws CertPathValidatorException
     {
         Certificate cert = (Certificate)certs.get(index);
@@ -1357,7 +1253,7 @@
                 dsaPubKey.getY(), dsaParams.getP(), dsaParams.getQ(), dsaParams.getG());
             try
             {
-                KeyFactory keyFactory = KeyFactory.getInstance("DSA", BouncyCastleProvider.PROVIDER_NAME);
+                KeyFactory keyFactory = helper.createKeyFactory("DSA");
                 return keyFactory.generatePublic(dsaPubKeySpec);
             }
             catch (Exception exception)
@@ -1372,37 +1268,57 @@
      * Find the issuer certificates of a given certificate.
      *
      * @param cert       The certificate for which an issuer should be found.
-     * @param pkixParams
      * @return A <code>Collection</code> object containing the issuer
      *         <code>X509Certificate</code>s. Never <code>null</code>.
      * @throws AnnotatedException if an error occurs.
      */
-    protected static Collection findIssuerCerts(
+    static Collection findIssuerCerts(
         X509Certificate cert,
-        ExtendedPKIXBuilderParameters pkixParams)
+        List<CertStore> certStores,
+        List<PKIXCertStore> pkixCertStores)
         throws AnnotatedException
     {
-        X509CertStoreSelector certSelect = new X509CertStoreSelector();
-        Set certs = new HashSet();
+        X509CertSelector selector = new X509CertSelector();
+
         try
         {
-            certSelect.setSubject(cert.getIssuerX500Principal().getEncoded());
+            selector.setSubject(PrincipalUtils.getIssuerPrincipal(cert).getEncoded());
         }
-        catch (IOException ex)
+        catch (IOException e)
         {
             throw new AnnotatedException(
-                "Subject criteria for certificate selector to find issuer certificate could not be set.", ex);
+                           "Subject criteria for certificate selector to find issuer certificate could not be set.", e);
         }
 
+        try
+        {
+            byte[] akiExtensionValue = cert.getExtensionValue(AUTHORITY_KEY_IDENTIFIER);
+            if (akiExtensionValue != null)
+            {
+                ASN1OctetString aki = ASN1OctetString.getInstance(akiExtensionValue);
+                byte[] authorityKeyIdentifier = AuthorityKeyIdentifier.getInstance(aki.getOctets()).getKeyIdentifier();
+                if (authorityKeyIdentifier != null)
+                {
+                    selector.setSubjectKeyIdentifier(new DEROctetString(authorityKeyIdentifier).getEncoded());
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            // authority key identifier could not be retrieved from target cert, just search without it
+        }
+
+        PKIXCertStoreSelector certSelect = new PKIXCertStoreSelector.Builder(selector).build();
+        Set certs = new LinkedHashSet();
+
         Iterator iter;
 
         try
         {
             List matches = new ArrayList();
 
-            matches.addAll(CertPathValidatorUtilities.findCertificates(certSelect, pkixParams.getCertStores()));
-            matches.addAll(CertPathValidatorUtilities.findCertificates(certSelect, pkixParams.getStores()));
-            matches.addAll(CertPathValidatorUtilities.findCertificates(certSelect, pkixParams.getAdditionalStores()));
+            matches.addAll(CertPathValidatorUtilities.findCertificates(certSelect, certStores));
+            matches.addAll(CertPathValidatorUtilities.findCertificates(certSelect, pkixCertStores));
 
             iter = matches.iterator();
         }
@@ -1435,4 +1351,24 @@
             cert.verify(publicKey, sigProvider);
         }
     }
+
+    static void checkCRLsNotEmpty(Set crls, Object cert)
+        throws AnnotatedException
+    {
+        if (crls.isEmpty())
+        {
+            if (cert instanceof X509AttributeCertificate)
+            {
+                X509AttributeCertificate aCert = (X509AttributeCertificate)cert;
+
+                throw new AnnotatedException("No CRLs found for issuer \"" + aCert.getIssuer().getPrincipals()[0] + "\"");
+            }
+            else
+            {
+                X509Certificate xCert = (X509Certificate)cert;
+
+                throw new AnnotatedException("No CRLs found for issuer \"" + RFC4519Style.INSTANCE.toString(PrincipalUtils.getIssuerPrincipal(xCert)) + "\"");
+            }
+        }
+    }
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java
deleted file mode 100644
index c5b6292..0000000
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/JCEStreamCipher.java
+++ /dev/null
@@ -1,609 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.CipherSpi;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.SecretKey;
-import javax.crypto.ShortBufferException;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.PBEParameterSpec;
-// BEGIN android-removed
-// import javax.crypto.spec.RC2ParameterSpec;
-// import javax.crypto.spec.RC5ParameterSpec;
-// END android-removed
-import javax.crypto.spec.SecretKeySpec;
-
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.StreamCipher;
-// BEGIN android-removed
-// import org.bouncycastle.crypto.engines.BlowfishEngine;
-// import org.bouncycastle.crypto.engines.DESEngine;
-// import org.bouncycastle.crypto.engines.DESedeEngine;
-// import org.bouncycastle.crypto.engines.SkipjackEngine;
-// import org.bouncycastle.crypto.engines.TwofishEngine;
-// END android-removed
-import org.bouncycastle.crypto.modes.CFBBlockCipher;
-import org.bouncycastle.crypto.modes.OFBBlockCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
-import org.bouncycastle.jcajce.provider.symmetric.util.PBE;
-
-public class JCEStreamCipher
-    extends CipherSpi
-    implements PBE
-{
-    //
-    // specs we can handle.
-    //
-    private Class[]                 availableSpecs =
-                                    {
-                                        // BEGIN android-removed
-                                        // RC2ParameterSpec.class,
-                                        // RC5ParameterSpec.class,
-                                        // END android-removed
-                                        IvParameterSpec.class,
-                                        PBEParameterSpec.class
-                                    };
-
-    private StreamCipher       cipher;
-    private ParametersWithIV   ivParam;
-
-    private int                     ivLength = 0;
-
-    private PBEParameterSpec        pbeSpec = null;
-    private String                  pbeAlgorithm = null;
-
-    private AlgorithmParameters engineParams;
-
-    protected JCEStreamCipher(
-        StreamCipher engine,
-        int          ivLength)
-    {
-        cipher = engine;
-        this.ivLength = ivLength;
-    }
-
-    protected int engineGetBlockSize() 
-    {
-        return 0;
-    }
-
-    protected byte[] engineGetIV() 
-    {
-        return (ivParam != null) ? ivParam.getIV() : null;
-    }
-
-    protected int engineGetKeySize(
-        Key     key) 
-    {
-        return key.getEncoded().length * 8;
-    }
-
-    protected int engineGetOutputSize(
-        int     inputLen) 
-    {
-        return inputLen;
-    }
-
-    protected AlgorithmParameters engineGetParameters() 
-    {
-        if (engineParams == null)
-        {
-            if (pbeSpec != null)
-            {
-                try
-                {
-                    AlgorithmParameters engineParams = AlgorithmParameters.getInstance(pbeAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
-                    engineParams.init(pbeSpec);
-                    
-                    return engineParams;
-                }
-                catch (Exception e)
-                {
-                    return null;
-                }
-            }
-        }
-        
-        return engineParams;
-    }
-
-    /**
-     * should never be called.
-     */
-    protected void engineSetMode(
-        String  mode) 
-    {
-        if (!mode.equalsIgnoreCase("ECB"))
-        {
-            throw new IllegalArgumentException("can't support mode " + mode);
-        }
-    }
-
-    /**
-     * should never be called.
-     */
-    protected void engineSetPadding(
-        String  padding) 
-    throws NoSuchPaddingException
-    {
-        if (!padding.equalsIgnoreCase("NoPadding"))
-        {
-            throw new NoSuchPaddingException("Padding " + padding + " unknown.");
-        }
-    }
-
-    protected void engineInit(
-        int                     opmode,
-        Key                     key,
-        AlgorithmParameterSpec  params,
-        SecureRandom            random) 
-        throws InvalidKeyException, InvalidAlgorithmParameterException
-    {
-        CipherParameters        param;
-
-        this.pbeSpec = null;
-        this.pbeAlgorithm = null;
-        
-        this.engineParams = null;
-        
-        //
-        // basic key check
-        //
-        if (!(key instanceof SecretKey))
-        {
-            throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption.");
-        }
-        
-        if (key instanceof BCPBEKey)
-        {
-            BCPBEKey k = (BCPBEKey)key;
-            
-            if (k.getOID() != null)
-            {
-                pbeAlgorithm = k.getOID().getId();
-            }
-            else
-            {
-                pbeAlgorithm = k.getAlgorithm();
-            }
-            
-            if (k.getParam() != null)
-            {
-                param = k.getParam();                
-                pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount());
-            }
-            else if (params instanceof PBEParameterSpec)
-            {
-                param = PBE.Util.makePBEParameters(k, params, cipher.getAlgorithmName());
-                pbeSpec = (PBEParameterSpec)params;
-            }
-            else
-            {
-                throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set.");
-            }
-            
-            if (k.getIvSize() != 0)
-            {
-                ivParam = (ParametersWithIV)param;
-            }
-        }
-        else if (params == null)
-        {
-            param = new KeyParameter(key.getEncoded());
-        }
-        else if (params instanceof IvParameterSpec)
-        {
-            param = new ParametersWithIV(new KeyParameter(key.getEncoded()), ((IvParameterSpec)params).getIV());
-            ivParam = (ParametersWithIV)param;
-        }
-        else
-        {
-            throw new IllegalArgumentException("unknown parameter type.");
-        }
-
-        if ((ivLength != 0) && !(param instanceof ParametersWithIV))
-        {
-            SecureRandom    ivRandom = random;
-
-            if (ivRandom == null)
-            {
-                ivRandom = new SecureRandom();
-            }
-
-            if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE))
-            {
-                byte[]  iv = new byte[ivLength];
-
-                ivRandom.nextBytes(iv);
-                param = new ParametersWithIV(param, iv);
-                ivParam = (ParametersWithIV)param;
-            }
-            else
-            {
-                throw new InvalidAlgorithmParameterException("no IV set when one expected");
-            }
-        }
-
-        switch (opmode)
-        {
-        case Cipher.ENCRYPT_MODE:
-        case Cipher.WRAP_MODE:
-            cipher.init(true, param);
-            break;
-        case Cipher.DECRYPT_MODE:
-        case Cipher.UNWRAP_MODE:
-            cipher.init(false, param);
-            break;
-        default:
-            System.out.println("eeek!");
-        }
-    }
-
-    protected void engineInit(
-        int                 opmode,
-        Key                 key,
-        AlgorithmParameters params,
-        SecureRandom        random) 
-        throws InvalidKeyException, InvalidAlgorithmParameterException
-    {
-        AlgorithmParameterSpec  paramSpec = null;
-
-        if (params != null)
-        {
-            for (int i = 0; i != availableSpecs.length; i++)
-            {
-                try
-                {
-                    paramSpec = params.getParameterSpec(availableSpecs[i]);
-                    break;
-                }
-                catch (Exception e)
-                {
-                    continue;
-                }
-            }
-
-            if (paramSpec == null)
-            {
-                throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
-            }
-        }
-
-        engineInit(opmode, key, paramSpec, random);
-        engineParams = params;
-    }
-
-    protected void engineInit(
-        int                 opmode,
-        Key                 key,
-        SecureRandom        random) 
-        throws InvalidKeyException
-    {
-        try
-        {
-            engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
-        }
-        catch (InvalidAlgorithmParameterException e)
-        {
-            throw new InvalidKeyException(e.getMessage());
-        }
-    }
-
-    protected byte[] engineUpdate(
-        byte[]  input,
-        int     inputOffset,
-        int     inputLen) 
-    {
-        byte[]  out = new byte[inputLen];
-
-        cipher.processBytes(input, inputOffset, inputLen, out, 0);
-
-        return out;
-    }
-
-    protected int engineUpdate(
-        byte[]  input,
-        int     inputOffset,
-        int     inputLen,
-        byte[]  output,
-        int     outputOffset) 
-        throws ShortBufferException 
-    {
-        try
-        {
-        cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
-
-        return inputLen;
-        }
-        catch (DataLengthException e)
-        {
-            throw new ShortBufferException(e.getMessage());
-        }
-    }
-
-    protected byte[] engineDoFinal(
-        byte[]  input,
-        int     inputOffset,
-        int     inputLen)
-        throws BadPaddingException, IllegalBlockSizeException
-    {
-        if (inputLen != 0)
-        {
-            byte[] out = engineUpdate(input, inputOffset, inputLen);
-
-            cipher.reset();
-            
-            return out;
-        }
-
-        cipher.reset();
-        
-        return new byte[0];
-    }
-
-    protected int engineDoFinal(
-        byte[]  input,
-        int     inputOffset,
-        int     inputLen,
-        byte[]  output,
-        int     outputOffset)
-        throws BadPaddingException
-    {
-        if (inputLen != 0)
-        {
-            cipher.processBytes(input, inputOffset, inputLen, output, outputOffset);
-        }
-
-        cipher.reset();
-        
-        return inputLen;
-    }
-
-    protected byte[] engineWrap(
-         Key     key)
-     throws IllegalBlockSizeException, InvalidKeyException
-     {
-         byte[] encoded = key.getEncoded();
-         if (encoded == null)
-         {
-             throw new InvalidKeyException("Cannot wrap key, null encoding.");
-         }
-
-         try
-         {
-             return engineDoFinal(encoded, 0, encoded.length);
-         }
-         catch (BadPaddingException e)
-         {
-             throw new IllegalBlockSizeException(e.getMessage());
-         }
-     }
-
-     protected Key engineUnwrap(
-         byte[] wrappedKey,
-         String wrappedKeyAlgorithm,
-         int wrappedKeyType)
-         throws InvalidKeyException
-     {
-         byte[] encoded;
-         try
-         {
-             encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
-         }
-         catch (BadPaddingException e)
-         {
-             throw new InvalidKeyException(e.getMessage());
-         }
-         catch (IllegalBlockSizeException e2)
-         {
-             throw new InvalidKeyException(e2.getMessage());
-         }
-
-         if (wrappedKeyType == Cipher.SECRET_KEY)
-         {
-             return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
-         }
-         else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY)
-         {
-             /*
-              * The caller doesn't know the algorithm as it is part of
-              * the encrypted data.
-              */
-             try
-             {
-                 PrivateKeyInfo in = PrivateKeyInfo.getInstance(encoded);
-
-                 PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in);
-
-                 if (privKey != null)
-                 {
-                     return privKey;
-                 }
-                 else
-                 {
-                     throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported");
-                 }
-             }
-             catch (Exception e)
-             {
-                 throw new InvalidKeyException("Invalid key encoding.");
-             }
-         }
-         else
-         {
-             try
-             {
-                 KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
-
-                 if (wrappedKeyType == Cipher.PUBLIC_KEY)
-                 {
-                     return kf.generatePublic(new X509EncodedKeySpec(encoded));
-                 }
-                 else if (wrappedKeyType == Cipher.PRIVATE_KEY)
-                 {
-                     return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
-                 }
-             }
-             catch (NoSuchProviderException e)
-             {
-                 throw new InvalidKeyException("Unknown key type " + e.getMessage());
-             }
-             catch (NoSuchAlgorithmException e)
-             {
-                 throw new InvalidKeyException("Unknown key type " + e.getMessage());
-             }
-             catch (InvalidKeySpecException e2)
-             {
-                 throw new InvalidKeyException("Unknown key type " + e2.getMessage());
-             }
-
-             throw new InvalidKeyException("Unknown key type " + wrappedKeyType);
-         }
-     }
-
-    /*
-     * The ciphers that inherit from us.
-     */
-
-    // BEGIN android-removed
-    // /**
-    //  * DES
-    //  */
-    // static public class DES_CFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public DES_CFB8()
-    //     {
-    //         super(new CFBBlockCipher(new DESEngine(), 8), 64);
-    //     }
-    // }
-    //
-    // /**
-    //  * DESede
-    //  */
-    // static public class DESede_CFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public DESede_CFB8()
-    //     {
-    //         super(new CFBBlockCipher(new DESedeEngine(), 8), 64);
-    //     }
-    // }
-    //
-    // /**
-    //  * SKIPJACK
-    //  */
-    // static public class Skipjack_CFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public Skipjack_CFB8()
-    //     {
-    //         super(new CFBBlockCipher(new SkipjackEngine(), 8), 64);
-    //     }
-    // }
-    //
-    // /**
-    //  * Blowfish
-    //  */
-    // static public class Blowfish_CFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public Blowfish_CFB8()
-    //     {
-    //         super(new CFBBlockCipher(new BlowfishEngine(), 8), 64);
-    //     }
-    // }
-    //
-    // /**
-    //  * Twofish
-    //  */
-    // static public class Twofish_CFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public Twofish_CFB8()
-    //     {
-    //         super(new CFBBlockCipher(new TwofishEngine(), 8), 128);
-    //     }
-    // }
-    //
-    // /**
-    //  * DES
-    //  */
-    // static public class DES_OFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public DES_OFB8()
-    //     {
-    //         super(new OFBBlockCipher(new DESEngine(), 8), 64);
-    //     }
-    // }
-    //
-    // /**
-    //  * DESede
-    //  */
-    // static public class DESede_OFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public DESede_OFB8()
-    //     {
-    //         super(new OFBBlockCipher(new DESedeEngine(), 8), 64);
-    //     }
-    // }
-    //
-    // /**
-    //  * SKIPJACK
-    //  */
-    // static public class Skipjack_OFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public Skipjack_OFB8()
-    //     {
-    //         super(new OFBBlockCipher(new SkipjackEngine(), 8), 64);
-    //     }
-    // }
-    //
-    // /**
-    //  * Blowfish
-    //  */
-    // static public class Blowfish_OFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public Blowfish_OFB8()
-    //     {
-    //         super(new OFBBlockCipher(new BlowfishEngine(), 8), 64);
-    //     }
-    // }
-    //
-    // /**
-    //  * Twofish
-    //  */
-    // static public class Twofish_OFB8
-    //     extends JCEStreamCipher
-    // {
-    //     public Twofish_OFB8()
-    //     {
-    //         super(new OFBBlockCipher(new TwofishEngine(), 8), 128);
-    //     }
-    // }
-    // END android-removed
-}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java
index ebd2f2a..b53b7aa 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCRLUtil.java
@@ -2,7 +2,6 @@
 
 import java.security.cert.CertStore;
 import java.security.cert.CertStoreException;
-import java.security.cert.PKIXParameters;
 import java.security.cert.X509CRL;
 import java.security.cert.X509Certificate;
 import java.util.Collection;
@@ -12,16 +11,14 @@
 import java.util.List;
 import java.util.Set;
 
+import org.bouncycastle.jcajce.PKIXCRLStore;
+import org.bouncycastle.jcajce.PKIXCRLStoreSelector;
+import org.bouncycastle.util.Store;
 import org.bouncycastle.util.StoreException;
-import org.bouncycastle.x509.ExtendedPKIXParameters;
-import org.bouncycastle.x509.X509CRLStoreSelector;
-// BEGIN android-removed
-// import org.bouncycastle.x509.X509Store;
-// END android-removed
 
-public class PKIXCRLUtil
+class PKIXCRLUtil
 {
-    public Set findCRLs(X509CRLStoreSelector crlselect, ExtendedPKIXParameters paramsPKIX, Date currentDate)
+    public Set findCRLs(PKIXCRLStoreSelector crlselect, Date validityDate, List certStores, List pkixCrlStores)
         throws AnnotatedException
     {
         Set initialSet = new HashSet();
@@ -29,9 +26,8 @@
         // get complete CRL(s)
         try
         {
-            initialSet.addAll(findCRLs(crlselect, paramsPKIX.getAdditionalStores()));
-            initialSet.addAll(findCRLs(crlselect, paramsPKIX.getStores()));
-            initialSet.addAll(findCRLs(crlselect, paramsPKIX.getCertStores()));
+            initialSet.addAll(findCRLs(crlselect, pkixCrlStores));
+            initialSet.addAll(findCRLs(crlselect, certStores));
         }
         catch (AnnotatedException e)
         {
@@ -39,12 +35,6 @@
         }
 
         Set finalSet = new HashSet();
-        Date validityDate = currentDate;
-
-        if (paramsPKIX.getDate() != null)
-        {
-            validityDate = paramsPKIX.getDate();
-        }
 
         // based on RFC 5280 6.3.3
         for (Iterator it = initialSet.iterator(); it.hasNext();)
@@ -72,38 +62,20 @@
         return finalSet;
     }
 
-    public Set findCRLs(X509CRLStoreSelector crlselect, PKIXParameters paramsPKIX)
-        throws AnnotatedException
-    {
-        Set completeSet = new HashSet();
-
-        // get complete CRL(s)
-        try
-        {
-            completeSet.addAll(findCRLs(crlselect, paramsPKIX.getCertStores()));
-        }
-        catch (AnnotatedException e)
-        {
-            throw new AnnotatedException("Exception obtaining complete CRLs.", e);
-        }
-
-        return completeSet;
-    }
-
-/**
+    /**
      * Return a Collection of all CRLs found in the X509Store's that are
      * matching the crlSelect criteriums.
      *
-     * @param crlSelect a {@link X509CRLStoreSelector} object that will be used
+     * @param crlSelect a {@link org.bouncycastle.jcajce.PKIXCRLStoreSelector} object that will be used
      *            to select the CRLs
      * @param crlStores a List containing only
-     *            {@link org.bouncycastle.x509.X509Store  X509Store} objects.
+     *            {@link Store} objects.
      *            These are used to search for CRLs
      *
      * @return a Collection of all found {@link java.security.cert.X509CRL X509CRL} objects. May be
      *         empty but never <code>null</code>.
      */
-    private final Collection findCRLs(X509CRLStoreSelector crlSelect,
+    private final Collection findCRLs(PKIXCRLStoreSelector crlSelect,
         List crlStores) throws AnnotatedException
     {
         Set crls = new HashSet();
@@ -117,10 +89,10 @@
             Object obj = iter.next();
 
             // BEGIN android-removed
-            // if (obj instanceof X509Store)
+	    // if (obj instanceof Store)
             // {
-            //     X509Store store = (X509Store)obj;
-            //
+            //     Store store = (Store)obj;
+
             //     try
             //     {
             //         crls.addAll(store.getMatches(crlSelect));
@@ -139,7 +111,7 @@
 
                 try
                 {
-                    crls.addAll(store.getCRLs(crlSelect));
+                    crls.addAll(PKIXCRLStoreSelector.getCRLs(crlSelect, store));
                     foundValidStore = true;
                 }
                 catch (CertStoreException e)
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java
index 384eb86..b713395 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathBuilderSpi.java
@@ -6,8 +6,6 @@
 import java.security.cert.CertPathBuilderResult;
 import java.security.cert.CertPathBuilderSpi;
 import java.security.cert.CertPathParameters;
-import java.security.cert.CertPathValidator;
-import java.security.cert.CertificateFactory;
 import java.security.cert.CertificateParsingException;
 import java.security.cert.PKIXBuilderParameters;
 import java.security.cert.PKIXCertPathBuilderResult;
@@ -19,10 +17,15 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.jcajce.PKIXCertStore;
+import org.bouncycastle.jcajce.PKIXCertStoreSelector;
+import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters;
+import org.bouncycastle.jcajce.PKIXExtendedParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;
 import org.bouncycastle.jce.exception.ExtCertPathBuilderException;
-import org.bouncycastle.util.Selector;
 import org.bouncycastle.x509.ExtendedPKIXBuilderParameters;
-import org.bouncycastle.x509.X509CertStoreSelector;
+import org.bouncycastle.x509.ExtendedPKIXParameters;
 
 /**
  * Implements the PKIX CertPathBuilding algorithm for BouncyCastle.
@@ -42,23 +45,45 @@
         throws CertPathBuilderException, InvalidAlgorithmParameterException
     {
         if (!(params instanceof PKIXBuilderParameters)
-            && !(params instanceof ExtendedPKIXBuilderParameters))
+            && !(params instanceof ExtendedPKIXBuilderParameters)
+            && !(params instanceof PKIXExtendedBuilderParameters))
         {
             throw new InvalidAlgorithmParameterException(
                 "Parameters must be an instance of "
                     + PKIXBuilderParameters.class.getName() + " or "
-                    + ExtendedPKIXBuilderParameters.class.getName() + ".");
+                    + PKIXExtendedBuilderParameters.class.getName() + ".");
         }
 
-        ExtendedPKIXBuilderParameters pkixParams = null;
-        if (params instanceof ExtendedPKIXBuilderParameters)
+        PKIXExtendedBuilderParameters paramsPKIX;
+        if (params instanceof PKIXBuilderParameters)
         {
-            pkixParams = (ExtendedPKIXBuilderParameters) params;
+            PKIXExtendedParameters.Builder paramsPKIXBldr = new PKIXExtendedParameters.Builder((PKIXBuilderParameters)params);
+            PKIXExtendedBuilderParameters.Builder paramsBldrPKIXBldr;
+
+            if (params instanceof ExtendedPKIXParameters)
+            {
+                ExtendedPKIXBuilderParameters extPKIX = (ExtendedPKIXBuilderParameters)params;
+
+ ;
+                for (Iterator it = extPKIX.getAdditionalStores().iterator(); it.hasNext();)
+                {
+                     paramsPKIXBldr.addCertificateStore((PKIXCertStore)it.next());
+                }
+                paramsBldrPKIXBldr  = new PKIXExtendedBuilderParameters.Builder(paramsPKIXBldr.build());
+
+                paramsBldrPKIXBldr.addExcludedCerts(extPKIX.getExcludedCerts());
+                paramsBldrPKIXBldr.setMaxPathLength(extPKIX.getMaxPathLength());
+            }
+            else
+            {
+                paramsBldrPKIXBldr  = new PKIXExtendedBuilderParameters.Builder((PKIXBuilderParameters)params);
+            }
+
+            paramsPKIX = paramsBldrPKIXBldr.build();
         }
         else
         {
-            pkixParams = (ExtendedPKIXBuilderParameters) ExtendedPKIXBuilderParameters
-                .getInstance((PKIXBuilderParameters) params);
+            paramsPKIX = (PKIXExtendedBuilderParameters)params;
         }
 
         Collection targets;
@@ -68,19 +93,12 @@
 
         // search target certificates
 
-        Selector certSelect = pkixParams.getTargetConstraints();
-        if (!(certSelect instanceof X509CertStoreSelector))
-        {
-            throw new CertPathBuilderException(
-                "TargetConstraints must be an instance of "
-                    + X509CertStoreSelector.class.getName() + " for "
-                    + this.getClass().getName() + " class.");
-        }
+        PKIXCertStoreSelector certSelect = paramsPKIX.getBaseParameters().getTargetConstraints();
 
         try
         {
-            targets = CertPathValidatorUtilities.findCertificates((X509CertStoreSelector)certSelect, pkixParams.getStores());
-            targets.addAll(CertPathValidatorUtilities.findCertificates((X509CertStoreSelector)certSelect, pkixParams.getCertStores()));
+            targets = CertPathValidatorUtilities.findCertificates(certSelect, paramsPKIX.getBaseParameters().getCertificateStores());
+            targets.addAll(CertPathValidatorUtilities.findCertificates(certSelect, paramsPKIX.getBaseParameters().getCertStores()));
         }
         catch (AnnotatedException e)
         {
@@ -102,7 +120,7 @@
         while (targetIter.hasNext() && result == null)
         {
             cert = (X509Certificate) targetIter.next();
-            result = build(cert, pkixParams, certPathList);
+            result = build(cert, paramsPKIX, certPathList);
         }
 
         if (result == null && certPathException != null)
@@ -128,7 +146,7 @@
     private Exception certPathException;
 
     protected CertPathBuilderResult build(X509Certificate tbvCert,
-        ExtendedPKIXBuilderParameters pkixParams, List tbvPath)
+        PKIXExtendedBuilderParameters pkixParams, List tbvPath)
     {
         // If tbvCert is readily present in tbvPath, it indicates having run
         // into a cycle in the
@@ -155,13 +173,13 @@
         tbvPath.add(tbvCert);
 
         CertificateFactory cFact;
-        CertPathValidator validator;
+        PKIXCertPathValidatorSpi validator;
         CertPathBuilderResult builderResult = null;
 
         try
         {
-            cFact = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
-            validator = CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME);
+            cFact = new CertificateFactory();
+            validator = new PKIXCertPathValidatorSpi();
         }
         catch (Exception e)
         {
@@ -172,8 +190,8 @@
         try
         {
             // check whether the issuer of <tbvCert> is a TrustAnchor
-            if (CertPathValidatorUtilities.findTrustAnchor(tbvCert, pkixParams.getTrustAnchors(),
-                pkixParams.getSigProvider()) != null)
+            if (CertPathValidatorUtilities.findTrustAnchor(tbvCert, pkixParams.getBaseParameters().getTrustAnchors(),
+                pkixParams.getBaseParameters().getSigProvider()) != null)
             {
                 // exception message from possibly later tried certification
                 // chains
@@ -181,7 +199,7 @@
                 PKIXCertPathValidatorResult result = null;
                 try
                 {
-                    certPath = cFact.generateCertPath(tbvPath);
+                    certPath = cFact.engineGenerateCertPath(tbvPath);
                 }
                 catch (Exception e)
                 {
@@ -192,7 +210,7 @@
 
                 try
                 {
-                    result = (PKIXCertPathValidatorResult) validator.validate(
+                    result = (PKIXCertPathValidatorResult) validator.engineValidate(
                         certPath, pkixParams);
                 }
                 catch (Exception e)
@@ -208,16 +226,21 @@
             }
             else
             {
+                List stores = new ArrayList();
+
+
+                stores.addAll(pkixParams.getBaseParameters().getCertificateStores());
+
                 // add additional X.509 stores from locations in certificate
                 try
                 {
-                    CertPathValidatorUtilities.addAdditionalStoresFromAltNames(
-                        tbvCert, pkixParams);
+                    stores.addAll(CertPathValidatorUtilities.getAdditionalStoresFromAltNames(
+                        tbvCert.getExtensionValue(Extension.issuerAlternativeName.getId()), pkixParams.getBaseParameters().getNamedCertificateStoreMap()));
                 }
                 catch (CertificateParsingException e)
                 {
                     throw new AnnotatedException(
-                        "No additiontal X.509 stores can be added from certificate locations.",
+                        "No additional X.509 stores can be added from certificate locations.",
                         e);
                 }
                 Collection issuers = new HashSet();
@@ -225,7 +248,7 @@
                 // of the stores
                 try
                 {
-                    issuers.addAll(CertPathValidatorUtilities.findIssuerCerts(tbvCert, pkixParams));
+                    issuers.addAll(CertPathValidatorUtilities.findIssuerCerts(tbvCert, pkixParams.getBaseParameters().getCertStores(), stores));
                 }
                 catch (AnnotatedException e)
                 {
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
index 19dc768..d902812 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
@@ -21,11 +21,14 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.security.auth.x500.X500Principal;
-
 import org.bouncycastle.asn1.ASN1Encodable;
 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.x500.X500Name;
 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters;
+import org.bouncycastle.jcajce.PKIXExtendedParameters;
+import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
 import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
 import org.bouncycastle.x509.ExtendedPKIXParameters;
 
@@ -36,6 +39,11 @@
 public class PKIXCertPathValidatorSpi
         extends CertPathValidatorSpi
 {
+    private final JcaJceHelper helper = new BCJcaJceHelper();
+
+    public PKIXCertPathValidatorSpi()
+    {
+    }
     // BEGIN android-added
     private static class NoPreloadHolder {
         private final static CertBlacklist blacklist = new CertBlacklist();
@@ -48,21 +56,36 @@
             throws CertPathValidatorException,
             InvalidAlgorithmParameterException
     {
-        if (!(params instanceof PKIXParameters))
+        if (!(params instanceof CertPathParameters))
         {
             throw new InvalidAlgorithmParameterException("Parameters must be a " + PKIXParameters.class.getName()
                     + " instance.");
         }
 
-        ExtendedPKIXParameters paramsPKIX;
-        if (params instanceof ExtendedPKIXParameters)
+        PKIXExtendedParameters paramsPKIX;
+        if (params instanceof PKIXParameters)
         {
-            paramsPKIX = (ExtendedPKIXParameters)params;
+            PKIXExtendedParameters.Builder paramsPKIXBldr = new PKIXExtendedParameters.Builder((PKIXParameters)params);
+
+            if (params instanceof ExtendedPKIXParameters)
+            {
+                ExtendedPKIXParameters extPKIX = (ExtendedPKIXParameters)params;
+
+                paramsPKIXBldr.setUseDeltasEnabled(extPKIX.isUseDeltasEnabled());
+                paramsPKIXBldr.setValidityModel(extPKIX.getValidityModel());
+            }
+
+            paramsPKIX = paramsPKIXBldr.build();
+        }
+        else if (params instanceof PKIXExtendedBuilderParameters)
+        {
+            paramsPKIX = ((PKIXExtendedBuilderParameters)params).getBaseParameters();
         }
         else
         {
-            paramsPKIX = ExtendedPKIXParameters.getInstance((PKIXParameters)params);
+            paramsPKIX = (PKIXExtendedParameters)params;
         }
+
         if (paramsPKIX.getTrustAnchors() == null)
         {
             throw new InvalidAlgorithmParameterException(
@@ -129,6 +152,9 @@
             throw new CertPathValidatorException("Trust anchor for certification path not found.", null, certPath, -1);
         }
 
+        // RFC 5280 - CRLs must originate from the same trust anchor as the target certificate.
+        paramsPKIX = new PKIXExtendedParameters.Builder(paramsPKIX).setTrustAnchor(trust).build();
+
         //
         // (e), (f), (g) are part of the paramsPKIX object.
         //
@@ -210,19 +236,19 @@
         // (g), (h), (i), (j)
         //
         PublicKey workingPublicKey;
-        X500Principal workingIssuerName;
+        X500Name workingIssuerName;
 
         X509Certificate sign = trust.getTrustedCert();
         try
         {
             if (sign != null)
             {
-                workingIssuerName = CertPathValidatorUtilities.getSubjectPrincipal(sign);
+                workingIssuerName = PrincipalUtils.getSubjectPrincipal(sign);
                 workingPublicKey = sign.getPublicKey();
             }
             else
             {
-                workingIssuerName = new X500Principal(trust.getCAName());
+                workingIssuerName = PrincipalUtils.getCA(trust);
                 workingPublicKey = trust.getCAPublicKey();
             }
         }
@@ -305,7 +331,7 @@
             //
 
             RFC3280CertPathUtilities.processCertA(certPath, paramsPKIX, index, workingPublicKey,
-                verificationAlreadyPerformed, workingIssuerName, sign);
+                verificationAlreadyPerformed, workingIssuerName, sign, helper);
 
             RFC3280CertPathUtilities.processCertBC(certPath, index, nameConstraintValidator);
 
@@ -390,12 +416,12 @@
                 sign = cert;
 
                 // (c)
-                workingIssuerName = CertPathValidatorUtilities.getSubjectPrincipal(sign);
+                workingIssuerName = PrincipalUtils.getSubjectPrincipal(sign);
 
                 // (d)
                 try
                 {
-                    workingPublicKey = CertPathValidatorUtilities.getNextWorkingKey(certPath.getCertificates(), index);
+                    workingPublicKey = CertPathValidatorUtilities.getNextWorkingKey(certPath.getCertificates(), index, helper);
                 }
                 catch (CertPathValidatorException e)
                 {
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java
index 7ecc486..0742712 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXNameConstraintValidator.java
@@ -635,13 +635,17 @@
     private boolean emailIsConstrained(String email, String constraint)
     {
         String sub = email.substring(email.indexOf('@') + 1);
-        // a particular mailbox
+        // a particular mailbox or @domain
         if (constraint.indexOf('@') != -1)
         {
             if (email.equalsIgnoreCase(constraint))
             {
                 return true;
             }
+            if (sub.equalsIgnoreCase(constraint.substring(1)))
+            {
+                return true;
+            }
         }
         // on particular host
         else if (!(constraint.charAt(0) == '.'))
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXPolicyNode.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXPolicyNode.java
index 3437605..d89e920 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXPolicyNode.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PKIXPolicyNode.java
@@ -165,4 +165,9 @@
         
         return _node;
     }
+
+    public void setExpectedPolicies(Set expectedPolicies)
+    {
+        this.expectedPolicies = expectedPolicies;
+    }
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/PrincipalUtils.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/PrincipalUtils.java
new file mode 100644
index 0000000..9059079
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/PrincipalUtils.java
@@ -0,0 +1,53 @@
+package org.bouncycastle.jce.provider;
+
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509CRL;
+import java.security.cert.X509CRLEntry;
+import java.security.cert.X509Certificate;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.x509.X509AttributeCertificate;
+
+class PrincipalUtils
+{
+    static X500Name getSubjectPrincipal(X509Certificate cert)
+    {
+        return X500Name.getInstance(cert.getSubjectX500Principal().getEncoded());
+    }
+
+    static X500Name getIssuerPrincipal(X509CRL crl)
+    {
+        return X500Name.getInstance(crl.getIssuerX500Principal().getEncoded());
+    }
+
+    static X500Name getIssuerPrincipal(X509Certificate cert)
+    {
+        return X500Name.getInstance(cert.getIssuerX500Principal().getEncoded());
+    }
+
+    static X500Name getCA(TrustAnchor trustAnchor)
+    {
+        return X500Name.getInstance(trustAnchor.getCA().getEncoded());
+    }
+
+    /**
+     * Returns the issuer of an attribute certificate or certificate.
+     *
+     * @param cert The attribute certificate or certificate.
+     * @return The issuer as <code>X500Principal</code>.
+     */
+    static X500Name getEncodedIssuerPrincipal(
+        Object cert)
+    {
+        if (cert instanceof X509Certificate)
+        {
+            return getIssuerPrincipal((X509Certificate)cert);
+        }
+        else
+        {
+            return X500Name.getInstance(((X500Principal)((X509AttributeCertificate)cert).getIssuer().getPrincipals()[0]).getEncoded());
+        }
+    }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java
index 881ceeb..d67a77e 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/RFC3280CertPathUtilities.java
@@ -5,13 +5,14 @@
 import java.security.GeneralSecurityException;
 import java.security.PublicKey;
 import java.security.cert.CertPath;
-import java.security.cert.CertPathBuilder;
 import java.security.cert.CertPathBuilderException;
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CertificateExpiredException;
 import java.security.cert.CertificateNotYetValidException;
 import java.security.cert.PKIXCertPathChecker;
 import java.security.cert.X509CRL;
+import java.security.cert.X509CRLSelector;
+import java.security.cert.X509CertSelector;
 import java.security.cert.X509Certificate;
 import java.security.cert.X509Extension;
 import java.text.SimpleDateFormat;
@@ -26,9 +27,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TimeZone;
-import java.util.Vector;
-
-import javax.security.auth.x500.X500Principal;
 
 import org.bouncycastle.asn1.ASN1Encodable;
 import org.bouncycastle.asn1.ASN1EncodableVector;
@@ -37,36 +35,42 @@
 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
 import org.bouncycastle.asn1.ASN1Primitive;
 import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1String;
 import org.bouncycastle.asn1.ASN1TaggedObject;
 import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.x500.RDN;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.BCStyle;
 import org.bouncycastle.asn1.x509.BasicConstraints;
 import org.bouncycastle.asn1.x509.CRLDistPoint;
 import org.bouncycastle.asn1.x509.CRLReason;
 import org.bouncycastle.asn1.x509.DistributionPoint;
 import org.bouncycastle.asn1.x509.DistributionPointName;
+import org.bouncycastle.asn1.x509.Extension;
 import org.bouncycastle.asn1.x509.GeneralName;
 import org.bouncycastle.asn1.x509.GeneralNames;
 import org.bouncycastle.asn1.x509.GeneralSubtree;
 import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
 import org.bouncycastle.asn1.x509.NameConstraints;
 import org.bouncycastle.asn1.x509.PolicyInformation;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Name;
+import org.bouncycastle.jcajce.PKIXCRLStore;
+import org.bouncycastle.jcajce.PKIXCRLStoreSelector;
+import org.bouncycastle.jcajce.PKIXCertStoreSelector;
+import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters;
+import org.bouncycastle.jcajce.PKIXExtendedParameters;
+import org.bouncycastle.jcajce.util.JcaJceHelper;
+import org.bouncycastle.jce.PrincipalUtil;
 import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
 import org.bouncycastle.util.Arrays;
-import org.bouncycastle.x509.ExtendedPKIXBuilderParameters;
-import org.bouncycastle.x509.ExtendedPKIXParameters;
-import org.bouncycastle.x509.X509CRLStoreSelector;
-import org.bouncycastle.x509.X509CertStoreSelector;
 
-public class RFC3280CertPathUtilities
+class RFC3280CertPathUtilities
 {
     private static final PKIXCRLUtil CRL_UTIL = new PKIXCRLUtil();
 
     /**
      * If the complete CRL includes an issuing distribution point (IDP) CRL
      * extension check the following:
-     * <p/>
+     * <p>
      * (i) If the distribution point name is present in the IDP CRL extension
      * and the distribution field is present in the DP, then verify that one of
      * the names in the IDP matches one of the names in the DP. If the
@@ -75,17 +79,17 @@
      * names in the IDP matches one of the names in the cRLIssuer field of the
      * DP.
      * </p>
-     * <p/>
+     * <p>
      * (ii) If the onlyContainsUserCerts boolean is asserted in the IDP CRL
      * extension, verify that the certificate does not include the basic
      * constraints extension with the cA boolean asserted.
      * </p>
-     * <p/>
+     * <p>
      * (iii) If the onlyContainsCACerts boolean is asserted in the IDP CRL
      * extension, verify that the certificate includes the basic constraints
      * extension with the cA boolean asserted.
      * </p>
-     * <p/>
+     * <p>
      * (iv) Verify that the onlyContainsAttributeCerts boolean is not asserted.
      * </p>
      *
@@ -133,20 +137,18 @@
                     ASN1EncodableVector vec = new ASN1EncodableVector();
                     try
                     {
-                        Enumeration e = ASN1Sequence.getInstance(
-                            ASN1Sequence.fromByteArray(CertPathValidatorUtilities.getIssuerPrincipal(crl)
-                                .getEncoded())).getObjects();
+                        Enumeration e = ASN1Sequence.getInstance(PrincipalUtils.getIssuerPrincipal(crl)).getObjects();
                         while (e.hasMoreElements())
                         {
                             vec.add((ASN1Encodable)e.nextElement());
                         }
                     }
-                    catch (IOException e)
+                    catch (Exception e)
                     {
                         throw new AnnotatedException("Could not read CRL issuer.", e);
                     }
                     vec.add(dpName.getName());
-                    names.add(new GeneralName(X509Name.getInstance(new DERSequence(vec))));
+                    names.add(new GeneralName(X500Name.getInstance(new DERSequence(vec))));
                 }
                 boolean matches = false;
                 // verify that one of the names in the IDP matches one
@@ -170,11 +172,10 @@
                             genNames = new GeneralName[1];
                             try
                             {
-                                genNames[0] = new GeneralName(new X509Name(
-                                    (ASN1Sequence)ASN1Sequence.fromByteArray(CertPathValidatorUtilities
-                                        .getEncodedIssuerPrincipal(cert).getEncoded())));
+                                genNames[0] = new GeneralName(X500Name.getInstance(PrincipalUtils
+                                    .getEncodedIssuerPrincipal(cert).getEncoded()));
                             }
-                            catch (IOException e)
+                            catch (Exception e)
                             {
                                 throw new AnnotatedException("Could not read certificate issuer.", e);
                             }
@@ -188,7 +189,7 @@
                                 vec.add((ASN1Encodable)e.nextElement());
                             }
                             vec.add(dpName.getName());
-                            genNames[j] = new GeneralName(new X509Name(new DERSequence(vec)));
+                            genNames[j] = new GeneralName(X500Name.getInstance(new DERSequence(vec)));
                         }
                     }
                     if (genNames != null)
@@ -296,7 +297,16 @@
                 isIndirect = true;
             }
         }
-        byte[] issuerBytes = CertPathValidatorUtilities.getIssuerPrincipal(crl).getEncoded();
+        byte[] issuerBytes;
+
+        try
+        {
+            issuerBytes = PrincipalUtils.getIssuerPrincipal(crl).getEncoded();
+        }
+        catch (IOException e)
+        {
+            throw new AnnotatedException("Exception encoding CRL issuer: " + e.getMessage(), e);
+        }
 
         boolean matchIssuer = false;
         if (dp.getCRLIssuer() != null)
@@ -331,8 +341,8 @@
         }
         else
         {
-            if (CertPathValidatorUtilities.getIssuerPrincipal(crl).equals(
-                CertPathValidatorUtilities.getEncodedIssuerPrincipal(cert)))
+            if (PrincipalUtils.getIssuerPrincipal(crl).equals(
+                PrincipalUtils.getEncodedIssuerPrincipal(cert)))
             {
                 matchIssuer = true;
             }
@@ -377,33 +387,33 @@
 
     }
 
-    public static final String CERTIFICATE_POLICIES = X509Extensions.CertificatePolicies.getId();
+    public static final String CERTIFICATE_POLICIES = Extension.certificatePolicies.getId();
 
-    public static final String POLICY_MAPPINGS = X509Extensions.PolicyMappings.getId();
+    public static final String POLICY_MAPPINGS = Extension.policyMappings.getId();
 
-    public static final String INHIBIT_ANY_POLICY = X509Extensions.InhibitAnyPolicy.getId();
+    public static final String INHIBIT_ANY_POLICY = Extension.inhibitAnyPolicy.getId();
 
-    public static final String ISSUING_DISTRIBUTION_POINT = X509Extensions.IssuingDistributionPoint.getId();
+    public static final String ISSUING_DISTRIBUTION_POINT = Extension.issuingDistributionPoint.getId();
 
-    public static final String FRESHEST_CRL = X509Extensions.FreshestCRL.getId();
+    public static final String FRESHEST_CRL = Extension.freshestCRL.getId();
 
-    public static final String DELTA_CRL_INDICATOR = X509Extensions.DeltaCRLIndicator.getId();
+    public static final String DELTA_CRL_INDICATOR = Extension.deltaCRLIndicator.getId();
 
-    public static final String POLICY_CONSTRAINTS = X509Extensions.PolicyConstraints.getId();
+    public static final String POLICY_CONSTRAINTS = Extension.policyConstraints.getId();
 
-    public static final String BASIC_CONSTRAINTS = X509Extensions.BasicConstraints.getId();
+    public static final String BASIC_CONSTRAINTS = Extension.basicConstraints.getId();
 
-    public static final String CRL_DISTRIBUTION_POINTS = X509Extensions.CRLDistributionPoints.getId();
+    public static final String CRL_DISTRIBUTION_POINTS = Extension.cRLDistributionPoints.getId();
 
-    public static final String SUBJECT_ALTERNATIVE_NAME = X509Extensions.SubjectAlternativeName.getId();
+    public static final String SUBJECT_ALTERNATIVE_NAME = Extension.subjectAlternativeName.getId();
 
-    public static final String NAME_CONSTRAINTS = X509Extensions.NameConstraints.getId();
+    public static final String NAME_CONSTRAINTS = Extension.nameConstraints.getId();
 
-    public static final String AUTHORITY_KEY_IDENTIFIER = X509Extensions.AuthorityKeyIdentifier.getId();
+    public static final String AUTHORITY_KEY_IDENTIFIER = Extension.authorityKeyIdentifier.getId();
 
-    public static final String KEY_USAGE = X509Extensions.KeyUsage.getId();
+    public static final String KEY_USAGE = Extension.keyUsage.getId();
 
-    public static final String CRL_NUMBER = X509Extensions.CRLNumber.getId();
+    public static final String CRL_NUMBER = Extension.cRLNumber.getId();
 
     public static final String ANY_POLICY = "2.5.29.32.0";
 
@@ -438,18 +448,19 @@
         Object cert,
         X509Certificate defaultCRLSignCert,
         PublicKey defaultCRLSignKey,
-        ExtendedPKIXParameters paramsPKIX,
-        List certPathCerts)
+        PKIXExtendedParameters paramsPKIX,
+        List certPathCerts,
+        JcaJceHelper helper)
         throws AnnotatedException
     {
         // (f)
 
         // get issuer from CRL
-        X509CertStoreSelector selector = new X509CertStoreSelector();
+        X509CertSelector certSelector = new X509CertSelector();
         try
         {
-            byte[] issuerPrincipal = CertPathValidatorUtilities.getIssuerPrincipal(crl).getEncoded();
-            selector.setSubject(issuerPrincipal);
+            byte[] issuerPrincipal = PrincipalUtils.getIssuerPrincipal(crl).getEncoded();
+            certSelector.setSubject(issuerPrincipal);
         }
         catch (IOException e)
         {
@@ -457,12 +468,13 @@
                 "Subject criteria for certificate selector to find issuer certificate for CRL could not be set.", e);
         }
 
+        PKIXCertStoreSelector selector = new PKIXCertStoreSelector.Builder(certSelector).build();
+
         // get CRL signing certs
         Collection coll;
         try
         {
-            coll = CertPathValidatorUtilities.findCertificates(selector, paramsPKIX.getStores());
-            coll.addAll(CertPathValidatorUtilities.findCertificates(selector, paramsPKIX.getAdditionalStores()));
+            coll = CertPathValidatorUtilities.findCertificates(selector, paramsPKIX.getCertificateStores());
             coll.addAll(CertPathValidatorUtilities.findCertificates(selector, paramsPKIX.getCertStores()));
         }
         catch (AnnotatedException e)
@@ -493,13 +505,13 @@
             }
             try
             {
-                CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME);
-                selector = new X509CertStoreSelector();
-                selector.setCertificate(signingCert);
-                ExtendedPKIXParameters temp = (ExtendedPKIXParameters)paramsPKIX.clone();
-                temp.setTargetCertConstraints(selector);
-                ExtendedPKIXBuilderParameters params = (ExtendedPKIXBuilderParameters)ExtendedPKIXBuilderParameters
-                    .getInstance(temp);
+                PKIXCertPathBuilderSpi builder = new PKIXCertPathBuilderSpi();
+                X509CertSelector tmpCertSelector = new X509CertSelector();
+                tmpCertSelector.setCertificate(signingCert);
+
+                PKIXExtendedParameters.Builder paramsBuilder = new PKIXExtendedParameters.Builder(paramsPKIX)
+                    .setTargetConstraints(new PKIXCertStoreSelector.Builder(tmpCertSelector).build());
+
                 /*
                  * if signingCert is placed not higher on the cert path a
                  * dependency loop results. CRL for cert is checked, but
@@ -511,19 +523,22 @@
                  */
                 if (certPathCerts.contains(signingCert))
                 {
-                    params.setRevocationEnabled(false);
+                    paramsBuilder.setRevocationEnabled(false);
                 }
                 else
                 {
-                    params.setRevocationEnabled(true);
+                    paramsBuilder.setRevocationEnabled(true);
                 }
-                List certs = builder.build(params).getCertPath().getCertificates();
+
+                PKIXExtendedBuilderParameters extParams = new PKIXExtendedBuilderParameters.Builder(paramsBuilder.build()).build();
+
+                List certs = builder.engineBuild(extParams).getCertPath().getCertificates();
                 validCerts.add(signingCert);
-                validKeys.add(CertPathValidatorUtilities.getNextWorkingKey(certs, 0));
+                validKeys.add(CertPathValidatorUtilities.getNextWorkingKey(certs, 0, helper));
             }
             catch (CertPathBuilderException e)
             {
-                throw new AnnotatedException("Internal error.", e);
+                throw new AnnotatedException("CertPath for CRL signer failed to validate.", e);
             }
             catch (CertPathValidatorException e)
             {
@@ -531,7 +546,7 @@
             }
             catch (Exception e)
             {
-                throw new RuntimeException(e.getMessage());
+                throw new AnnotatedException(e.getMessage());
             }
         }
 
@@ -618,7 +633,7 @@
 
     protected static Set processCRLA1i(
         Date currentDate,
-        ExtendedPKIXParameters paramsPKIX,
+        PKIXExtendedParameters paramsPKIX,
         X509Certificate cert,
         X509CRL crl)
         throws AnnotatedException
@@ -650,19 +665,24 @@
             }
             if (freshestCRL != null)
             {
+                List crlStores = new ArrayList();
+
+                crlStores.addAll(paramsPKIX.getCRLStores());
+
                 try
                 {
-                    CertPathValidatorUtilities.addAdditionalStoresFromCRLDistributionPoint(freshestCRL, paramsPKIX);
+                    crlStores.addAll(CertPathValidatorUtilities.getAdditionalStoresFromCRLDistributionPoint(freshestCRL, paramsPKIX.getNamedCRLStoreMap()));
                 }
                 catch (AnnotatedException e)
                 {
                     throw new AnnotatedException(
                         "No new delta CRL locations could be added from Freshest CRL extension.", e);
                 }
+
                 // get delta CRL(s)
                 try
                 {
-                    set.addAll(CertPathValidatorUtilities.getDeltaCRLs(currentDate, paramsPKIX, crl));
+                    set.addAll(CertPathValidatorUtilities.getDeltaCRLs(currentDate, crl, paramsPKIX.getCertStores(), crlStores));
                 }
                 catch (AnnotatedException e)
                 {
@@ -675,33 +695,41 @@
 
     protected static Set[] processCRLA1ii(
         Date currentDate,
-        ExtendedPKIXParameters paramsPKIX,
+        PKIXExtendedParameters paramsPKIX,
         X509Certificate cert,
         X509CRL crl)
         throws AnnotatedException
     {
         Set deltaSet = new HashSet();
-        X509CRLStoreSelector crlselect = new X509CRLStoreSelector();
+        X509CRLSelector crlselect = new X509CRLSelector();
         crlselect.setCertificateChecking(cert);
 
         try
         {
-            crlselect.addIssuerName(crl.getIssuerX500Principal().getEncoded());
+            crlselect.addIssuerName(PrincipalUtils.getIssuerPrincipal(crl).getEncoded());
         }
         catch (IOException e)
         {
             throw new AnnotatedException("Cannot extract issuer from CRL." + e, e);
         }
 
-        crlselect.setCompleteCRLEnabled(true);
-        Set completeSet = CRL_UTIL.findCRLs(crlselect, paramsPKIX, currentDate);
+        PKIXCRLStoreSelector extSelect = new PKIXCRLStoreSelector.Builder(crlselect).setCompleteCRLEnabled(true).build();
+
+        Date validityDate = currentDate;
+
+        if (paramsPKIX.getDate() != null)
+        {
+            validityDate = paramsPKIX.getDate();
+        }
+
+        Set completeSet = CRL_UTIL.findCRLs(extSelect, validityDate, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores());
 
         if (paramsPKIX.isUseDeltasEnabled())
         {
             // get delta CRL(s)
             try
             {
-                deltaSet.addAll(CertPathValidatorUtilities.getDeltaCRLs(currentDate, paramsPKIX, crl));
+                deltaSet.addAll(CertPathValidatorUtilities.getDeltaCRLs(validityDate, crl, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores()));
             }
             catch (AnnotatedException e)
             {
@@ -727,7 +755,7 @@
     protected static void processCRLC(
         X509CRL deltaCRL,
         X509CRL completeCRL,
-        ExtendedPKIXParameters pkixParams)
+        PKIXExtendedParameters pkixParams)
         throws AnnotatedException
     {
         if (deltaCRL == null)
@@ -748,7 +776,7 @@
         if (pkixParams.isUseDeltasEnabled())
         {
             // (c) (1)
-            if (!deltaCRL.getIssuerX500Principal().equals(completeCRL.getIssuerX500Principal()))
+            if (!PrincipalUtils.getIssuerPrincipal(deltaCRL).equals(PrincipalUtils.getIssuerPrincipal(completeCRL)))
             {
                 throw new AnnotatedException("Complete CRL issuer does not match delta CRL issuer.");
             }
@@ -835,7 +863,7 @@
         X509CRL deltacrl,
         Object cert,
         CertStatus certStatus,
-        ExtendedPKIXParameters pkixParams)
+        PKIXExtendedParameters pkixParams)
         throws AnnotatedException
     {
         if (pkixParams.isUseDeltasEnabled() && deltacrl != null)
@@ -1164,13 +1192,12 @@
         //
         if (!(CertPathValidatorUtilities.isSelfIssued(cert) && (i < n)))
         {
-            X500Principal principal = CertPathValidatorUtilities.getSubjectPrincipal(cert);
-            ASN1InputStream aIn = new ASN1InputStream(principal.getEncoded());
+            X500Name principal = PrincipalUtils.getSubjectPrincipal(cert);
             ASN1Sequence dns;
 
             try
             {
-                dns = DERSequence.getInstance(aIn.readObject());
+                dns = DERSequence.getInstance(principal.getEncoded());
             }
             catch (Exception e)
             {
@@ -1200,10 +1227,11 @@
                 throw new CertPathValidatorException("Subject alternative name extension could not be decoded.", e,
                     certPath, index);
             }
-            Vector emails = new X509Name(dns).getValues(X509Name.EmailAddress);
-            for (Enumeration e = emails.elements(); e.hasMoreElements();)
+            RDN[] emails = X500Name.getInstance(dns).getRDNs(BCStyle.EmailAddress);
+            for (int eI = 0; eI != emails.length; eI++)
             {
-                String email = (String)e.nextElement();
+                // TODO: this should take into account multi-valued RDNs
+                String email = ((ASN1String)emails[eI].getFirst().getValue()).getString();
                 GeneralName emailAsGeneralName = new GeneralName(GeneralName.rfc822Name, email);
                 try
                 {
@@ -1450,12 +1478,13 @@
 
     protected static void processCertA(
         CertPath certPath,
-        ExtendedPKIXParameters paramsPKIX,
+        PKIXExtendedParameters paramsPKIX,
         int index,
         PublicKey workingPublicKey,
         boolean verificationAlreadyPerformed,
-        X500Principal workingIssuerName,
-        X509Certificate sign)
+        X500Name workingIssuerName,
+        X509Certificate sign,
+        JcaJceHelper helper)
         throws ExtCertPathValidatorException
     {
         List certs = certPath.getCertificates();
@@ -1506,7 +1535,7 @@
             try
             {
                 checkCRLs(paramsPKIX, cert, CertPathValidatorUtilities.getValidCertDateFromValidityModel(paramsPKIX,
-                    certPath, index), sign, workingPublicKey, certs);
+                    certPath, index), sign, workingPublicKey, certs, helper);
             }
             catch (AnnotatedException e)
             {
@@ -1522,9 +1551,9 @@
         //
         // (a) (4) name chaining
         //
-        if (!CertPathValidatorUtilities.getEncodedIssuerPrincipal(cert).equals(workingIssuerName))
+        if (!PrincipalUtils.getEncodedIssuerPrincipal(cert).equals(workingIssuerName))
         {
-            throw new ExtCertPathValidatorException("IssuerName(" + CertPathValidatorUtilities.getEncodedIssuerPrincipal(cert)
+            throw new ExtCertPathValidatorException("IssuerName(" + PrincipalUtils.getEncodedIssuerPrincipal(cert)
                 + ") does not match SubjectName(" + workingIssuerName + ") of signing certificate.", null,
                 certPath, index);
         }
@@ -1725,14 +1754,15 @@
      */
     private static void checkCRL(
         DistributionPoint dp,
-        ExtendedPKIXParameters paramsPKIX,
+        PKIXExtendedParameters paramsPKIX,
         X509Certificate cert,
         Date validDate,
         X509Certificate defaultCRLSignCert,
         PublicKey defaultCRLSignKey,
         CertStatus certStatus,
         ReasonsMask reasonMask,
-        List certPathCerts)
+        List certPathCerts,
+        JcaJceHelper helper)
         throws AnnotatedException
     {
         Date currentDate = new Date(System.currentTimeMillis());
@@ -1776,16 +1806,23 @@
 
                 // (f)
                 Set keys = RFC3280CertPathUtilities.processCRLF(crl, cert, defaultCRLSignCert, defaultCRLSignKey,
-                    paramsPKIX, certPathCerts);
+                    paramsPKIX, certPathCerts, helper);
                 // (g)
                 PublicKey key = RFC3280CertPathUtilities.processCRLG(crl, keys);
 
                 X509CRL deltaCRL = null;
 
+                Date validityDate = currentDate;
+
+                if (paramsPKIX.getDate() != null)
+                {
+                    validityDate = paramsPKIX.getDate();
+                }
+
                 if (paramsPKIX.isUseDeltasEnabled())
                 {
                     // get delta CRLs
-                    Set deltaCRLs = CertPathValidatorUtilities.getDeltaCRLs(currentDate, paramsPKIX, crl);
+                    Set deltaCRLs = CertPathValidatorUtilities.getDeltaCRLs(validityDate, crl, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores());
                     // we only want one valid delta CRL
                     // (h)
                     deltaCRL = RFC3280CertPathUtilities.processCRLH(deltaCRLs, key);
@@ -1804,7 +1841,7 @@
                  * the CRL validity time
                  */
 
-                if (paramsPKIX.getValidityModel() != ExtendedPKIXParameters.CHAIN_VALIDITY_MODEL)
+                if (paramsPKIX.getValidityModel() != PKIXExtendedParameters.CHAIN_VALIDITY_MODEL)
                 {
                     /*
                      * if a certificate has expired, but was revoked, it is not
@@ -1844,8 +1881,8 @@
                 if (criticalExtensions != null)
                 {
                     criticalExtensions = new HashSet(criticalExtensions);
-                    criticalExtensions.remove(X509Extensions.IssuingDistributionPoint.getId());
-                    criticalExtensions.remove(X509Extensions.DeltaCRLIndicator.getId());
+                    criticalExtensions.remove(Extension.issuingDistributionPoint.getId());
+                    criticalExtensions.remove(Extension.deltaCRLIndicator.getId());
 
                     if (!criticalExtensions.isEmpty())
                     {
@@ -1859,8 +1896,8 @@
                     if (criticalExtensions != null)
                     {
                         criticalExtensions = new HashSet(criticalExtensions);
-                        criticalExtensions.remove(X509Extensions.IssuingDistributionPoint.getId());
-                        criticalExtensions.remove(X509Extensions.DeltaCRLIndicator.getId());
+                        criticalExtensions.remove(Extension.issuingDistributionPoint.getId());
+                        criticalExtensions.remove(Extension.deltaCRLIndicator.getId());
                         if (!criticalExtensions.isEmpty())
                         {
                             throw new AnnotatedException("Delta CRL contains unsupported critical extension.");
@@ -1895,12 +1932,13 @@
      *                            or some error occurs.
      */
     protected static void checkCRLs(
-        ExtendedPKIXParameters paramsPKIX,
+        PKIXExtendedParameters paramsPKIX,
         X509Certificate cert,
         Date validDate,
         X509Certificate sign,
         PublicKey workingPublicKey,
-        List certPathCerts)
+        List certPathCerts,
+        JcaJceHelper helper)
         throws AnnotatedException
     {
         AnnotatedException lastException = null;
@@ -1914,9 +1952,15 @@
         {
             throw new AnnotatedException("CRL distribution point extension could not be read.", e);
         }
+
+        PKIXExtendedParameters.Builder paramsBldr = new PKIXExtendedParameters.Builder(paramsPKIX);
         try
         {
-            CertPathValidatorUtilities.addAdditionalStoresFromCRLDistributionPoint(crldp, paramsPKIX);
+            List extras = CertPathValidatorUtilities.getAdditionalStoresFromCRLDistributionPoint(crldp, paramsPKIX.getNamedCRLStoreMap());
+            for (Iterator it = extras.iterator(); it.hasNext();)
+            {
+                paramsBldr.addCRLStore((PKIXCRLStore)it.next());
+            }
         }
         catch (AnnotatedException e)
         {
@@ -1925,6 +1969,7 @@
         }
         CertStatus certStatus = new CertStatus();
         ReasonsMask reasonsMask = new ReasonsMask();
+        PKIXExtendedParameters finalParams = paramsBldr.build();
 
         boolean validCrlFound = false;
         // for each distribution point
@@ -1943,10 +1988,9 @@
             {
                 for (int i = 0; i < dps.length && certStatus.getCertStatus() == CertStatus.UNREVOKED && !reasonsMask.isAllReasons(); i++)
                 {
-                    ExtendedPKIXParameters paramsPKIXClone = (ExtendedPKIXParameters)paramsPKIX.clone();
                     try
                     {
-                        checkCRL(dps[i], paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask, certPathCerts);
+                        checkCRL(dps[i], finalParams, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask, certPathCerts, helper);
                         validCrlFound = true;
                     }
                     catch (AnnotatedException e)
@@ -1975,7 +2019,7 @@
                 ASN1Primitive issuer = null;
                 try
                 {
-                    issuer = new ASN1InputStream(CertPathValidatorUtilities.getEncodedIssuerPrincipal(cert).getEncoded())
+                    issuer = new ASN1InputStream(PrincipalUtils.getEncodedIssuerPrincipal(cert).getEncoded())
                         .readObject();
                 }
                 catch (Exception e)
@@ -1984,9 +2028,9 @@
                 }
                 DistributionPoint dp = new DistributionPoint(new DistributionPointName(0, new GeneralNames(
                     new GeneralName(GeneralName.directoryName, issuer))), null, null);
-                ExtendedPKIXParameters paramsPKIXClone = (ExtendedPKIXParameters)paramsPKIX.clone();
+                PKIXExtendedParameters paramsPKIXClone = (PKIXExtendedParameters)paramsPKIX.clone();
                 checkCRL(dp, paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask,
-                    certPathCerts);
+                    certPathCerts, helper);
                 validCrlFound = true;
             }
             catch (AnnotatedException e)
@@ -2391,7 +2435,7 @@
 
     protected static PKIXPolicyNode wrapupCertG(
         CertPath certPath,
-        ExtendedPKIXParameters paramsPKIX,
+        PKIXExtendedParameters paramsPKIX,
         Set userInitialPolicySet,
         int index,
         List[] policyNodes,
diff --git a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
index b5b4f13..c9ee77c 100644
--- a/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
+++ b/bcprov/src/main/java/org/bouncycastle/jce/provider/X509CRLObject.java
@@ -62,7 +62,7 @@
     private boolean isHashCodeSet = false;
     private int     hashCodeValue;
 
-    static boolean isIndirectCRL(X509CRL crl)
+    public static boolean isIndirectCRL(X509CRL crl)
         throws CRLException
     {
         try
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
index 3b334d2..7165bab 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECAlgorithms.java
@@ -124,6 +124,11 @@
 
     public static void montgomeryTrick(ECFieldElement[] zs, int off, int len)
     {
+        montgomeryTrick(zs, off, len, null);
+    }
+
+    public static void montgomeryTrick(ECFieldElement[] zs, int off, int len, ECFieldElement scale)
+    {
         /*
          * Uses the "Montgomery Trick" to invert many field elements, with only a single actual
          * field inversion. See e.g. the paper:
@@ -140,7 +145,14 @@
             c[i] = c[i - 1].multiply(zs[off + i]);
         }
 
-        ECFieldElement u = c[--i].invert();
+        --i;
+
+        if (scale != null)
+        {
+            c[i] = c[i].multiply(scale);
+        }
+
+        ECFieldElement u = c[i].invert();
 
         while (i > 0)
         {
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
index 4c658f2..0dc6853 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECCurve.java
@@ -229,26 +229,57 @@
      */
     public void normalizeAll(ECPoint[] points)
     {
-        checkPoints(points);
+        normalizeAll(points, 0, points.length, null);
+    }
 
-        if (this.getCoordinateSystem() == ECCurve.COORD_AFFINE)
+    /**
+     * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+     * coordinates reflect those of the equivalent point in an affine coordinate system. Where more
+     * than one point is to be normalized, this method will generally be more efficient than
+     * normalizing each point separately. An (optional) z-scaling factor can be applied; effectively
+     * each z coordinate is scaled by this value prior to normalization (but only one
+     * actual multiplication is needed).
+     * 
+     * @param points
+     *            An array of points that will be updated in place with their normalized versions,
+     *            where necessary
+     * @param off
+     *            The start of the range of points to normalize
+     * @param len
+     *            The length of the range of points to normalize
+     * @param iso
+     *            The (optional) z-scaling factor - can be null
+     */
+    public void normalizeAll(ECPoint[] points, int off, int len, ECFieldElement iso)
+    {
+        checkPoints(points, off, len);
+
+        switch (this.getCoordinateSystem())
         {
+        case ECCurve.COORD_AFFINE:
+        case ECCurve.COORD_LAMBDA_AFFINE:
+        {
+            if (iso != null)
+            {
+                throw new IllegalArgumentException("'iso' not valid for affine coordinates");
+            }
             return;
         }
+        }
 
         /*
          * Figure out which of the points actually need to be normalized
          */
-        ECFieldElement[] zs = new ECFieldElement[points.length];
-        int[] indices = new int[points.length];
+        ECFieldElement[] zs = new ECFieldElement[len];
+        int[] indices = new int[len];
         int count = 0;
-        for (int i = 0; i < points.length; ++i)
+        for (int i = 0; i < len; ++i)
         {
-            ECPoint p = points[i];
-            if (null != p && !p.isNormalized())
+            ECPoint p = points[off + i];
+            if (null != p && (iso != null || !p.isNormalized()))
             {
                 zs[count] = p.getZCoord(0);
-                indices[count++] = i;
+                indices[count++] = off + i;
             }
         }
 
@@ -257,7 +288,7 @@
             return;
         }
 
-        ECAlgorithms.montgomeryTrick(zs, 0, count);
+        ECAlgorithms.montgomeryTrick(zs, 0, count, iso);
 
         for (int j = 0; j < count; ++j)
         {
@@ -414,14 +445,23 @@
 
     protected void checkPoints(ECPoint[] points)
     {
+        checkPoints(points, 0, points.length);
+    }
+
+    protected void checkPoints(ECPoint[] points, int off, int len)
+    {
         if (points == null)
         {
             throw new IllegalArgumentException("'points' cannot be null");
         }
-
-        for (int i = 0; i < points.length; ++i)
+        if (off < 0 || len < 0 || (off > (points.length - len)))
         {
-            ECPoint point = points[i];
+            throw new IllegalArgumentException("invalid range specified for 'points'");
+        }
+
+        for (int i = 0; i < len; ++i)
+        {
+            ECPoint point = points[off + i];
             if (null != point && this != point.getCurve())
             {
                 throw new IllegalArgumentException("'points' entries must be null or on this curve");
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
index 7cd04e4..4db27e0 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/ECPoint.java
@@ -287,6 +287,9 @@
         return x == null || y == null || (zs.length > 0 && zs[0].isZero());
     }
 
+    /**
+     * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
+     */
     public boolean isCompressed()
     {
         return this.withCompression;
@@ -435,13 +438,19 @@
         return sb.toString();
     }
 
+    /**
+     * @deprecated per-point compression property will be removed, refer {@link #getEncoded(boolean)}
+     */
     public byte[] getEncoded()
     {
         return getEncoded(this.withCompression);
     }
 
     /**
-     * return the field element encoded with point compression. (S 4.3.6)
+     * Get an encoding of the point value, optionally in compressed format.
+     * 
+     * @param compressed whether to generate a compressed point encoding.
+     * @return the point encoding
      */
     public byte[] getEncoded(boolean compressed)
     {
@@ -771,14 +780,7 @@
                     Y3 = W1.subtract(X3).multiply(dy).subtract(A1);
                     Z3 = dx;
 
-                    if (Z1IsOne)
-                    {
-                        Z3Squared = C;
-                    }
-                    else
-                    {
-                        Z3 = Z3.multiply(Z1);
-                    }
+                    Z3 = Z3.multiply(Z1);
                 }
                 else
                 {
@@ -967,7 +969,7 @@
                     }
                     else if (!a4.isZero())
                     {
-                        ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.square();
+                        ECFieldElement Z1Squared = Z1.square();
                         ECFieldElement Z1Pow4 = Z1Squared.square();
                         if (a4Neg.bitLength() < a4.bitLength())
                         {
diff --git a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
index 7ac3160..339689e 100644
--- a/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/math/ec/WNafUtil.java
@@ -10,6 +10,7 @@
 
     private static final byte[] EMPTY_BYTES = new byte[0];
     private static final int[] EMPTY_INTS = new int[0];
+    private static final ECPoint[] EMPTY_POINTS = new ECPoint[0];
 
     public static int[] generateCompactNaf(BigInteger k)
     {
@@ -386,45 +387,99 @@
         ECCurve c = p.getCurve();
         WNafPreCompInfo wnafPreCompInfo = getWNafPreCompInfo(c.getPreCompInfo(p, PRECOMP_NAME));
 
+        int iniPreCompLen = 0, reqPreCompLen = 1 << Math.max(0, width - 2);
+
         ECPoint[] preComp = wnafPreCompInfo.getPreComp();
         if (preComp == null)
         {
-            preComp = new ECPoint[]{ p };
+            preComp = EMPTY_POINTS;
+        }
+        else
+        {
+            iniPreCompLen = preComp.length;
         }
 
-        int preCompLen = preComp.length;
-        int reqPreCompLen = 1 << Math.max(0, width - 2);
-
-        if (preCompLen < reqPreCompLen)
+        if (iniPreCompLen < reqPreCompLen)
         {
             preComp = resizeTable(preComp, reqPreCompLen);
-            if (reqPreCompLen == 2)
+
+            if (reqPreCompLen == 1)
             {
-                preComp[1] = preComp[0].threeTimes();
+                preComp[0] = p.normalize();
             }
             else
             {
-                ECPoint twiceP = wnafPreCompInfo.getTwice();
-                if (twiceP == null)
+                int curPreCompLen = iniPreCompLen;
+                if (curPreCompLen == 0)
                 {
-                    twiceP = preComp[0].twice();
-                    wnafPreCompInfo.setTwice(twiceP);
+                    preComp[0] = p;
+                    curPreCompLen = 1;
                 }
 
-                for (int i = preCompLen; i < reqPreCompLen; i++)
+                ECFieldElement iso = null;
+
+                if (reqPreCompLen == 2)
                 {
-                    /*
-                     * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ...,
-                     * 2^(width-1)-1 times p are computed
-                     */
-                    preComp[i] = twiceP.add(preComp[i - 1]);
+                    preComp[1] = p.threeTimes();
                 }
+                else
+                {
+                    ECPoint twiceP = wnafPreCompInfo.getTwice(), last = preComp[curPreCompLen - 1];
+                    if (twiceP == null)
+                    {
+                        twiceP = preComp[0].twice();
+                        wnafPreCompInfo.setTwice(twiceP);
+
+                        /*
+                         * For Fp curves with Jacobian projective coordinates, use a (quasi-)isomorphism
+                         * where 'twiceP' is "affine", so that the subsequent additions are cheaper. This
+                         * also requires scaling the initial point's X, Y coordinates, and reversing the
+                         * isomorphism as part of the subsequent normalization.
+                         * 
+                         *  NOTE: The correctness of this optimization depends on:
+                         *      1) additions do not use the curve's A, B coefficients.
+                         *      2) no special cases (i.e. Q +/- Q) when calculating 1P, 3P, 5P, ...
+                         */
+                        if (ECAlgorithms.isFpCurve(c) && c.getFieldSize() >= 64)
+                        {
+                            switch (c.getCoordinateSystem())
+                            {
+                            case ECCurve.COORD_JACOBIAN:
+                            case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+                            case ECCurve.COORD_JACOBIAN_MODIFIED:
+                            {
+                                iso = twiceP.getZCoord(0);
+                                twiceP = c.createPoint(twiceP.getXCoord().toBigInteger(), twiceP.getYCoord()
+                                    .toBigInteger());
+
+                                ECFieldElement iso2 = iso.square(), iso3 = iso2.multiply(iso);
+                                last = last.scaleX(iso2).scaleY(iso3);
+
+                                if (iniPreCompLen == 0)
+                                {
+                                    preComp[0] = last;
+                                }
+                                break;
+                            }
+                            }
+                        }
+                    }
+
+                    while (curPreCompLen < reqPreCompLen)
+                    {
+                        /*
+                         * Compute the new ECPoints for the precomputation array. The values 1, 3,
+                         * 5, ..., 2^(width-1)-1 times p are computed
+                         */
+                        preComp[curPreCompLen++] = last = last.add(twiceP);
+                    }
+                }
+
+                /*
+                 * Having oft-used operands in affine form makes operations faster.
+                 */
+                c.normalizeAll(preComp, iniPreCompLen, reqPreCompLen - iniPreCompLen, iso);
             }
-
-            /*
-             * Having oft-used operands in affine form makes operations faster.
-             */
-            c.normalizeAll(preComp);
         }
 
         wnafPreCompInfo.setPreComp(preComp);
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
index 64ce17c..3c0646a 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Arrays.java
@@ -1,6 +1,7 @@
 package org.bouncycastle.util;
 
 import java.math.BigInteger;
+import java.util.Iterator;
 
 /**
  * General array utilities.
@@ -968,4 +969,43 @@
 
         return result;
     }
+
+    /**
+     * Iterator backed by a specific array.
+     */
+    public static class Iterator<T>
+        implements java.util.Iterator<T>
+    {
+        private final T[] dataArray;
+
+        private int position = 0;
+
+        /**
+         * Base constructor.
+         * <p>
+         * Note: the array is not cloned, changes to it will affect the values returned by next().
+         * </p>
+         *
+         * @param dataArray array backing the iterator.
+         */
+        public Iterator(T[] dataArray)
+        {
+            this.dataArray = dataArray;
+        }
+
+        public boolean hasNext()
+        {
+            return position < dataArray.length;
+        }
+
+        public T next()
+        {
+            return dataArray[position++];
+        }
+
+        public void remove()
+        {
+            throw new UnsupportedOperationException("Cannot remove element from an Array.");
+        }
+    }
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/util/CollectionStore.java b/bcprov/src/main/java/org/bouncycastle/util/CollectionStore.java
index 91aba14..1cc9641 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/CollectionStore.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/CollectionStore.java
@@ -8,10 +8,10 @@
 /**
  * A simple collection backed store.
  */
-public class CollectionStore
-    implements Store
+public class CollectionStore<T>
+    implements Store<T>, Iterable<T>
 {
-    private Collection _local;
+    private Collection<T> _local;
 
     /**
      * Basic constructor.
@@ -19,9 +19,9 @@
      * @param collection - initial contents for the store, this is copied.
      */
     public CollectionStore(
-        Collection collection)
+        Collection<T> collection)
     {
-        _local = new ArrayList(collection);
+        _local = new ArrayList<T>(collection);
     }
 
     /**
@@ -30,20 +30,20 @@
      * @param selector the selector to match against.
      * @return a possibly empty collection of matching objects.
      */
-    public Collection getMatches(Selector selector)
+    public Collection<T> getMatches(Selector<T> selector)
     {
         if (selector == null)
         {
-            return new ArrayList(_local);
+            return new ArrayList<T>(_local);
         }
         else
         {
-            List col = new ArrayList();
-            Iterator iter = _local.iterator();
+            List<T> col = new ArrayList<T>();
+            Iterator<T> iter = _local.iterator();
 
             while (iter.hasNext())
             {
-                Object obj = iter.next();
+                T obj = iter.next();
 
                 if (selector.match(obj))
                 {
@@ -54,4 +54,9 @@
             return col;
         }
     }
+
+    public Iterator<T> iterator()
+    {
+        return getMatches(null).iterator();
+    }
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Encodable.java b/bcprov/src/main/java/org/bouncycastle/util/Encodable.java
new file mode 100644
index 0000000..67258fb
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/util/Encodable.java
@@ -0,0 +1,18 @@
+package org.bouncycastle.util;
+
+import java.io.IOException;
+
+/**
+ * Interface implemented by objects that can be converted into byte arrays.
+ */
+public interface Encodable
+{
+    /**
+     * Return a byte array representing the implementing object.
+     *
+     * @return a byte array representing the encoding.
+     * @throws java.io.IOException if an issue arises generation the encoding.
+     */
+    byte[] getEncoded()
+        throws IOException;
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Iterable.java b/bcprov/src/main/java/org/bouncycastle/util/Iterable.java
new file mode 100644
index 0000000..a0fa9dc
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/util/Iterable.java
@@ -0,0 +1,17 @@
+package org.bouncycastle.util;
+
+import java.util.Iterator;
+
+/**
+ * Utility class to allow use of Iterable feature in JDK 1.5+
+ */
+public interface Iterable<T>
+    extends java.lang.Iterable<T>
+{
+    /**
+     * Returns an iterator over a set of elements of type T.
+     *
+     * @return an Iterator.
+     */
+    Iterator<T> iterator();
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Selector.java b/bcprov/src/main/java/org/bouncycastle/util/Selector.java
index 7ad86bf..a3a5ec8 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Selector.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Selector.java
@@ -1,9 +1,9 @@
 package org.bouncycastle.util;
 
-public interface Selector
+public interface Selector<T>
     extends Cloneable
 {
-    boolean match(Object obj);
+    boolean match(T obj);
 
     Object clone();
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Store.java b/bcprov/src/main/java/org/bouncycastle/util/Store.java
index b994c92..fd28b83 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Store.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Store.java
@@ -2,8 +2,8 @@
 
 import java.util.Collection;
 
-public interface Store
+public interface Store<T>
 {
-    Collection getMatches(Selector selector)
+    Collection<T> getMatches(Selector<T> selector)
         throws StoreException;
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/util/StringList.java b/bcprov/src/main/java/org/bouncycastle/util/StringList.java
new file mode 100644
index 0000000..e733442
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/util/StringList.java
@@ -0,0 +1,22 @@
+package org.bouncycastle.util;
+
+public interface StringList
+    extends Iterable<String>
+{
+    boolean add(String s);
+
+    String get(int index);
+
+    int size();
+
+    String[] toStringArray();
+
+    /**
+     * Return a section of the contents of the list. If the list is too short the array is filled with nulls.
+     *
+     * @param from the initial index of the range to be copied, inclusive
+     * @param to the final index of the range to be copied, exclusive.
+     * @return an array of length to - from
+     */
+    String[] toStringArray(int from, int to);
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/util/Strings.java b/bcprov/src/main/java/org/bouncycastle/util/Strings.java
index 770edaa..44ff3ae 100644
--- a/bcprov/src/main/java/org/bouncycastle/util/Strings.java
+++ b/bcprov/src/main/java/org/bouncycastle/util/Strings.java
@@ -3,6 +3,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.Vector;
 
 public final class Strings
@@ -311,4 +312,53 @@
         }
         return res;
     }
+
+    public static StringList newList()
+    {
+        return new StringListImpl();
+    }
+
+    private static class StringListImpl
+        extends ArrayList<String>
+        implements StringList
+    {
+        public boolean add(String s)
+        {
+            return super.add(s);
+        }
+
+        public String set(int index, String element)
+        {
+            return super.set(index, element);
+        }
+
+        public void add(int index, String element)
+        {
+            super.add(index, element);
+        }
+
+        public String[] toStringArray()
+        {
+            String[] strs = new String[this.size()];
+
+            for (int i = 0; i != strs.length; i++)
+            {
+                strs[i] = this.get(i);
+            }
+
+            return strs;
+        }
+
+        public String[] toStringArray(int from, int to)
+        {
+            String[] strs = new String[to - from];
+
+            for (int i = from; i != this.size() && i != to; i++)
+            {
+                strs[i - from] = this.get(i);
+            }
+
+            return strs;
+        }
+    }
 }
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXBuilderParameters.java b/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXBuilderParameters.java
index 51831d0..386fc3d 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXBuilderParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXBuilderParameters.java
@@ -17,6 +17,7 @@
  * 
  * @see java.security.cert.PKIXBuilderParameters
  * @see org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi
+ * @deprecated use PKIXExtendedBuilderParameters
  */
 public class ExtendedPKIXBuilderParameters extends ExtendedPKIXParameters
 {
diff --git a/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java b/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java
index 6386618..952f775 100644
--- a/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java
+++ b/bcprov/src/main/java/org/bouncycastle/x509/ExtendedPKIXParameters.java
@@ -18,6 +18,8 @@
 
 /**
  * This class extends the PKIXParameters with a validity model parameter.
+ *
+ * @deprecated use PKIXExtendedParameters
  */
 public class ExtendedPKIXParameters
     extends PKIXParameters
@@ -42,8 +44,11 @@
     /**
      * Creates an instance of <code>PKIXParameters</code> with the specified
      * <code>Set</code> of most-trusted CAs. Each element of the set is a
-     * {@link TrustAnchor TrustAnchor}. <p/> Note that the <code>Set</code>
+     * {@link TrustAnchor TrustAnchor}.
+     * <p>
+     *     Note that the <code>Set</code>
      * is copied to protect against subsequent modifications.
+     * </p>
      * 
      * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
      * @throws InvalidAlgorithmParameterException if the specified
@@ -154,8 +159,11 @@
      * when the end certificate was signed. The CA (or Root CA) certificate must
      * have been valid, when the CA certificate was signed and so on. So the
      * {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when
-     * the <em>end certificate</em> must have been valid. <p/> It is used e.g.
+     * the <em>end certificate</em> must have been valid.
+     * <p>
+     * It is used e.g.
      * in the German signature law.
+     * </p>
      */
     public static final int CHAIN_VALIDITY_MODEL = 1;
 
@@ -278,6 +286,7 @@
      * 
      * @param store The store to add.
      * @see #getStores()
+     * @deprectaed use addStore().
      */
     public void addAdditionalStore(Store store)
     {
diff --git a/bouncycastle.config b/bouncycastle.config
index f8caa2c..12ccaaa 100644
--- a/bouncycastle.config
+++ b/bouncycastle.config
@@ -1,6 +1,5 @@
 # directories
 UNNEEDED_BCPROV_SOURCES=" \
-org/bouncycastle/apache \
 org/bouncycastle/asn1/bsi \
 org/bouncycastle/asn1/cmp \
 org/bouncycastle/asn1/cms/ecc \
@@ -166,6 +165,8 @@
 org/bouncycastle/crypto/agreement/DHStandardGroups.java \
 org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java \
 org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java \
+org/bouncycastle/crypto/generators/BCrypt.java \
+org/bouncycastle/crypto/generators/OpenBSDBCrypt.java \
 org/bouncycastle/crypto/digests/GOST3411Digest.java \
 org/bouncycastle/crypto/digests/MD2Digest.java \
 org/bouncycastle/crypto/digests/MD4Digest.java \
@@ -282,6 +283,7 @@
 org/bouncycastle/crypto/modes/OCBBlockCipher.java \
 org/bouncycastle/crypto/modes/OldCTSBlockCipher.java \
 org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java \
+org/bouncycastle/crypto/modes/NISTCTSBlockCipher.java \
 org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java \
 org/bouncycastle/crypto/modes/PaddedBlockCipher.java \
 org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java \
@@ -322,6 +324,7 @@
 org/bouncycastle/crypto/params/ParametersWithSalt.java \
 org/bouncycastle/crypto/params/RC5Parameters.java \
 org/bouncycastle/crypto/params/RSABlindingParameters.java \
+org/bouncycastle/crypto/params/SRP6GroupParameters.java \
 org/bouncycastle/crypto/params/SkeinParameters.java \
 org/bouncycastle/crypto/params/TweakableBlockCipherParameters.java \
 org/bouncycastle/crypto/signers/DSADigestSigner.java \
@@ -334,8 +337,11 @@
 org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java \
 org/bouncycastle/crypto/signers/ISO9796d2Signer.java \
 org/bouncycastle/crypto/signers/PSSSigner.java \
+org/bouncycastle/crypto/signers/X931Signer.java \
 org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java \
 org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java \
+org/bouncycastle/jcajce/PKCS12Key.java \
+org/bouncycastle/jcajce/PKCS12KeyWithParameters.java \
 org/bouncycastle/jcajce/provider/asymmetric/DSTU4145.java \
 org/bouncycastle/jcajce/provider/asymmetric/ECGOST.java \
 org/bouncycastle/jcajce/provider/asymmetric/ElGamal.java \
@@ -345,6 +351,7 @@
 org/bouncycastle/jcajce/provider/asymmetric/ec/IESCipher.java \
 org/bouncycastle/jcajce/provider/asymmetric/rsa/ISOSignatureSpi.java \
 org/bouncycastle/jcajce/provider/asymmetric/rsa/PSSSignatureSpi.java \
+org/bouncycastle/jcajce/provider/asymmetric/rsa/X931SignatureSpi.java \
 org/bouncycastle/jcajce/provider/asymmetric/util/GOST3410Util.java \
 org/bouncycastle/jcajce/provider/asymmetric/util/IESUtil.java \
 org/bouncycastle/jcajce/provider/digest/GOST3411.java \
@@ -470,7 +477,10 @@
 org/bouncycastle/x509/CertPathReviewerException.java \
 org/bouncycastle/x509/CertPathReviewerMessages_de.properties \
 org/bouncycastle/x509/NoSuchParserException.java \
+org/bouncycastle/x509/PKIXCRLUtil.java \
 org/bouncycastle/x509/PKIXCertPathReviewer.java \
+org/bouncycastle/x509/CertPathValidatorUtilities.java \
+org/bouncycastle/x509/CertStatus.java \
 org/bouncycastle/x509/X509AttributeCertStoreSelector.java \
 org/bouncycastle/x509/X509CertPairStoreSelector.java \
 org/bouncycastle/x509/X509CertificatePair.java \
@@ -489,6 +499,7 @@
 org/bouncycastle/cert/bc \
 org/bouncycastle/cert/cmp \
 org/bouncycastle/cert/crmf \
+org/bouncycastle/cert/dane \
 org/bouncycastle/cert/ocsp \
 org/bouncycastle/cert/path \
 org/bouncycastle/cert/selector/jcajce \
@@ -499,7 +510,9 @@
 org/bouncycastle/eac \
 org/bouncycastle/mozilla \
 org/bouncycastle/openssl \
+org/bouncycastle/operator/test \
 org/bouncycastle/pkcs \
+org/bouncycastle/pkix \
 org/bouncycastle/tsp \
 org/bouncycastle/voms \
 "
@@ -622,9 +635,11 @@
 org/bouncycastle/cms/jcajce/ProviderJcaJceExtHelper.java \
 org/bouncycastle/cms/jcajce/ZlibCompressor.java \
 org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java \
+org/bouncycastle/operator/AlgorithmNameFinder.java \
 org/bouncycastle/operator/AsymmetricKeyUnwrapper.java \
 org/bouncycastle/operator/AsymmetricKeyWrapper.java \
 org/bouncycastle/operator/BufferingContentSigner.java \
+org/bouncycastle/operator/DefaultAlgorithmNameFinder.java \
 org/bouncycastle/operator/DefaultSecretKeySizeProvider.java \
 org/bouncycastle/operator/InputDecryptorProvider.java \
 org/bouncycastle/operator/InputExpander.java \
diff --git a/bouncycastle.version b/bouncycastle.version
index 1c9ab99..6bbeb95 100644
--- a/bouncycastle.version
+++ b/bouncycastle.version
@@ -1,2 +1,2 @@
 BOUNCYCASTLE_JDK=15on
-BOUNCYCASTLE_VERSION=151
+BOUNCYCASTLE_VERSION=152
diff --git a/patches/bcpkix.patch b/patches/bcpkix.patch
index b12caf7..f871201 100644
--- a/patches/bcpkix.patch
+++ b/patches/bcpkix.patch
@@ -1,7 +1,7 @@
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedData.java bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedData.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedData.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedData.java	2014-07-28 23:57:30.811988142 +0000
-@@ -285,18 +285,20 @@
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/cms/CMSSignedData.java bcpkix-jdk15on-152/org/bouncycastle/cms/CMSSignedData.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/cms/CMSSignedData.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/cms/CMSSignedData.java	2015-04-09 13:10:16.000000000 +0000
+@@ -287,18 +287,20 @@
          return HELPER.getAttributeCertificates(signedData.getCertificates());
      }
  
@@ -34,7 +34,7 @@
  
      /**
       * Return the a string representation of the OID associated with the
-@@ -331,71 +333,73 @@
+@@ -333,90 +335,92 @@
          return contentInfo.getEncoded();
      }
  
@@ -85,10 +85,7 @@
 -
 -                    for  (Iterator cIt = counterSigners.iterator(); cIt.hasNext();)
 -                    {
--                        SignerInformation counterSigner = (SignerInformation)cIt.next();
--                        SignerInformationVerifier counterVerifier = verifierProvider.get(signer.getSID());
--
--                        if (!counterSigner.verify(counterVerifier))
+-                        if (!verifyCounterSignature((SignerInformation)cIt.next(), verifierProvider))
 -                        {
 -                            return false;
 -                        }
@@ -103,6 +100,28 @@
 -
 -        return true;
 -    }
+-
+-    private boolean verifyCounterSignature(SignerInformation counterSigner, SignerInformationVerifierProvider verifierProvider)
+-        throws OperatorCreationException, CMSException
+-    {
+-        SignerInformationVerifier counterVerifier = verifierProvider.get(counterSigner.getSID());
+-
+-        if (!counterSigner.verify(counterVerifier))
+-        {
+-            return false;
+-        }
+-
+-        Collection counterSigners = counterSigner.getCounterSignatures().getSigners();
+-        for  (Iterator cIt = counterSigners.iterator(); cIt.hasNext();)
+-        {
+-            if (!verifyCounterSignature((SignerInformation)cIt.next(), verifierProvider))
+-            {
+-                return false;
+-            }
+-        }
+-
+-        return true;
+-    }
 +    // BEGIN android-removed
 +    // /**
 +    //  * Verify all the SignerInformation objects and their associated counter signatures attached
@@ -117,7 +136,7 @@
 +    // {
 +    //     return verifySignatures(verifierProvider, false);
 +    // }
-+    //
++    // 
 +    // /**
 +    //  * Verify all the SignerInformation objects and optionally their associated counter signatures attached
 +    //  * to this CMS SignedData object.
@@ -131,30 +150,27 @@
 +    //     throws CMSException
 +    // {
 +    //     Collection signers = this.getSignerInfos().getSigners();
-+    //
++    // 
 +    //     for (Iterator it = signers.iterator(); it.hasNext();)
 +    //     {
 +    //         SignerInformation signer = (SignerInformation)it.next();
-+    //
++    // 
 +    //         try
 +    //         {
 +    //             SignerInformationVerifier verifier = verifierProvider.get(signer.getSID());
-+    //
++    // 
 +    //             if (!signer.verify(verifier))
 +    //             {
 +    //                 return false;
 +    //             }
-+    //
++    // 
 +    //             if (!ignoreCounterSignatures)
 +    //             {
 +    //                 Collection counterSigners = signer.getCounterSignatures().getSigners();
-+    //
++    // 
 +    //                 for  (Iterator cIt = counterSigners.iterator(); cIt.hasNext();)
 +    //                 {
-+    //                     SignerInformation counterSigner = (SignerInformation)cIt.next();
-+    //                     SignerInformationVerifier counterVerifier = verifierProvider.get(signer.getSID());
-+    //
-+    //                     if (!counterSigner.verify(counterVerifier))
++    //                     if (!verifyCounterSignature((SignerInformation)cIt.next(), verifierProvider))
 +    //                     {
 +    //                         return false;
 +    //                     }
@@ -166,16 +182,38 @@
 +    //             throw new CMSException("failure in verifier provider: " + e.getMessage(), e);
 +    //         }
 +    //     }
-+    //
++    // 
++    //     return true;
++    // }
++    // 
++    // private boolean verifyCounterSignature(SignerInformation counterSigner, SignerInformationVerifierProvider verifierProvider)
++    //     throws OperatorCreationException, CMSException
++    // {
++    //     SignerInformationVerifier counterVerifier = verifierProvider.get(counterSigner.getSID());
++    // 
++    //     if (!counterSigner.verify(counterVerifier))
++    //     {
++    //         return false;
++    //     }
++    // 
++    //     Collection counterSigners = counterSigner.getCounterSignatures().getSigners();
++    //     for  (Iterator cIt = counterSigners.iterator(); cIt.hasNext();)
++    //     {
++    //         if (!verifyCounterSignature((SignerInformation)cIt.next(), verifierProvider))
++    //         {
++    //             return false;
++    //         }
++    //     }
++    // 
 +    //     return true;
 +    // }
 +    // END android-removed
  
      /**
       * Replace the SignerInformation store associated with this
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedGenerator.java bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedGenerator.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedGenerator.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedGenerator.java	2014-07-28 23:57:30.815988170 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/cms/CMSSignedGenerator.java bcpkix-jdk15on-152/org/bouncycastle/cms/CMSSignedGenerator.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/cms/CMSSignedGenerator.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/cms/CMSSignedGenerator.java	2013-12-12 00:35:05.000000000 +0000
 @@ -12,8 +12,10 @@
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
  import org.bouncycastle.asn1.DERTaggedObject;
@@ -276,9 +314,9 @@
  
      /**
       * Add a store of pre-calculated signers to the generator.
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedHelper.java bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedHelper.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSSignedHelper.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/cms/CMSSignedHelper.java	2014-07-28 23:57:30.795988031 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/cms/CMSSignedHelper.java bcpkix-jdk15on-152/org/bouncycastle/cms/CMSSignedHelper.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/cms/CMSSignedHelper.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/cms/CMSSignedHelper.java	2013-12-12 00:35:05.000000000 +0000
 @@ -13,8 +13,10 @@
  import org.bouncycastle.asn1.ASN1Set;
  import org.bouncycastle.asn1.ASN1TaggedObject;
@@ -427,9 +465,9 @@
 +    //     return new CollectionStore(new ArrayList());
 +    // }
  }
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSUtils.java bcpkix-jdk15on-151/org/bouncycastle/cms/CMSUtils.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/CMSUtils.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/cms/CMSUtils.java	2014-07-28 23:57:30.775987892 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/cms/CMSUtils.java bcpkix-jdk15on-152/org/bouncycastle/cms/CMSUtils.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/cms/CMSUtils.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/cms/CMSUtils.java	2014-07-28 19:51:54.000000000 +0000
 @@ -20,9 +20,11 @@
  import org.bouncycastle.asn1.DERTaggedObject;
  import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
@@ -536,9 +574,9 @@
  
      static ASN1Set createBerSetFromList(List derObjects)
      {
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java bcpkix-jdk15on-151/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java	2014-07-28 23:57:30.779987920 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java bcpkix-jdk15on-152/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/cms/DefaultCMSSignatureAlgorithmNameGenerator.java	2015-04-09 13:10:16.000000000 +0000
 @@ -4,8 +4,10 @@
  import java.util.Map;
  
@@ -573,7 +611,7 @@
          addEntries(PKCSObjectIdentifiers.md5WithRSAEncryption, "MD5", "RSA");
          addEntries(PKCSObjectIdentifiers.sha1WithRSAEncryption, "SHA1", "RSA");
          addEntries(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224", "RSA");
-@@ -61,38 +67,44 @@
+@@ -66,38 +72,44 @@
          addEntries(EACObjectIdentifiers.id_TA_RSA_v1_5_SHA_256, "SHA256", "RSA");
          addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_1, "SHA1", "RSAandMGF1");
          addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_256, "SHA256", "RSAandMGF1");
@@ -638,9 +676,9 @@
      }
  
      /**
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java bcpkix-jdk15on-151/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java	2014-07-28 23:57:30.803988086 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java bcpkix-jdk15on-152/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/cms/DefaultCMSSignatureEncryptionAlgorithmFinder.java	2013-09-26 18:06:21.000000000 +0000
 @@ -16,21 +16,27 @@
  
      static
@@ -676,9 +714,9 @@
      }
  
      public AlgorithmIdentifier findEncryptionAlgorithm(AlgorithmIdentifier signatureAlgorithm)
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java bcpkix-jdk15on-151/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java	2014-07-28 23:57:30.735987614 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java bcpkix-jdk15on-152/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/operator/DefaultDigestAlgorithmIdentifierFinder.java	2013-09-26 18:06:21.000000000 +0000
 @@ -5,7 +5,9 @@
  
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -763,9 +801,9 @@
      }
  
      public AlgorithmIdentifier find(AlgorithmIdentifier sigAlgId)
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java bcpkix-jdk15on-151/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java	2014-07-28 23:57:30.695987337 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java bcpkix-jdk15on-152/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java	2014-07-28 19:51:54.000000000 +0000
 @@ -9,9 +9,11 @@
  import org.bouncycastle.asn1.ASN1Integer;
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -927,9 +965,9 @@
 -}
 \ No newline at end of file
 +}
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java bcpkix-jdk15on-151/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java	2014-07-28 23:57:30.731987587 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java bcpkix-jdk15on-152/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/operator/bc/BcDefaultDigestProvider.java	2013-09-26 18:06:21.000000000 +0000
 @@ -4,20 +4,26 @@
  import java.util.HashMap;
  import java.util.Map;
@@ -1057,9 +1095,9 @@
  
          return Collections.unmodifiableMap(table);
      }
-diff -Naur bcpkix-jdk15on-151.orig/org/bouncycastle/operator/jcajce/OperatorHelper.java bcpkix-jdk15on-151/org/bouncycastle/operator/jcajce/OperatorHelper.java
---- bcpkix-jdk15on-151.orig/org/bouncycastle/operator/jcajce/OperatorHelper.java	2014-07-26 04:18:10.000000000 +0000
-+++ bcpkix-jdk15on-151/org/bouncycastle/operator/jcajce/OperatorHelper.java	2014-07-28 23:57:30.711987448 +0000
+diff -Naur bcpkix-jdk15on-152.orig/org/bouncycastle/operator/jcajce/OperatorHelper.java bcpkix-jdk15on-152/org/bouncycastle/operator/jcajce/OperatorHelper.java
+--- bcpkix-jdk15on-152.orig/org/bouncycastle/operator/jcajce/OperatorHelper.java	2015-03-01 12:03:46.000000000 +0000
++++ bcpkix-jdk15on-152/org/bouncycastle/operator/jcajce/OperatorHelper.java	2015-04-09 13:10:16.000000000 +0000
 @@ -24,9 +24,11 @@
  import org.bouncycastle.asn1.ASN1Encodable;
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
diff --git a/patches/bcprov.patch b/patches/bcprov.patch
index 0ebf47e..e0e0154 100644
--- a/patches/bcprov.patch
+++ b/patches/bcprov.patch
@@ -1,6 +1,6 @@
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1Boolean.java bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1Boolean.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1Boolean.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1Boolean.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/ASN1Boolean.java bcprov-jdk15on-152/org/bouncycastle/asn1/ASN1Boolean.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/ASN1Boolean.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/ASN1Boolean.java	2014-07-28 19:51:54.000000000 +0000
 @@ -23,7 +23,9 @@
      private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
      private static final byte[] FALSE_VALUE = new byte[] { 0 };
@@ -53,9 +53,9 @@
      {
          this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
      }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1Null.java bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1Null.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1Null.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1Null.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/ASN1Null.java bcprov-jdk15on-152/org/bouncycastle/asn1/ASN1Null.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/ASN1Null.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/ASN1Null.java	2014-07-28 19:51:54.000000000 +0000
 @@ -8,6 +8,12 @@
  public abstract class ASN1Null
      extends ASN1Primitive
@@ -69,9 +69,9 @@
      /**
       * Return an instance of ASN.1 NULL from the passed in object.
       * <p>
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1ObjectIdentifier.java bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/ASN1ObjectIdentifier.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/ASN1ObjectIdentifier.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/ASN1ObjectIdentifier.java bcprov-jdk15on-152/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/ASN1ObjectIdentifier.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/ASN1ObjectIdentifier.java	2014-07-28 19:51:54.000000000 +0000
 @@ -152,7 +152,13 @@
              }
          }
@@ -102,9 +102,9 @@
      }
  
       /**
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/DERNull.java bcprov-jdk15on-151/org/bouncycastle/asn1/DERNull.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/DERNull.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/DERNull.java	2013-01-31 02:26:40.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/DERNull.java bcprov-jdk15on-152/org/bouncycastle/asn1/DERNull.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/DERNull.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/DERNull.java	2013-01-31 02:26:40.000000000 +0000
 @@ -15,7 +15,9 @@
      /**
       * @deprecated use DERNull.INSTANCE
@@ -116,9 +116,9 @@
      {
      }
  
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/DERPrintableString.java bcprov-jdk15on-151/org/bouncycastle/asn1/DERPrintableString.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/DERPrintableString.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/DERPrintableString.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/DERPrintableString.java bcprov-jdk15on-152/org/bouncycastle/asn1/DERPrintableString.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/DERPrintableString.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/DERPrintableString.java	2014-07-28 19:51:54.000000000 +0000
 @@ -12,7 +12,9 @@
      extends ASN1Primitive
      implements ASN1String
@@ -130,9 +130,9 @@
  
      /**
       * return a printable string from the passed in object.
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/StreamUtil.java bcprov-jdk15on-151/org/bouncycastle/asn1/StreamUtil.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/StreamUtil.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/StreamUtil.java	2014-05-05 17:17:14.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/StreamUtil.java bcprov-jdk15on-152/org/bouncycastle/asn1/StreamUtil.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/StreamUtil.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/StreamUtil.java	2014-05-05 17:17:14.000000000 +0000
 @@ -8,7 +8,9 @@
  
  class StreamUtil
@@ -162,9 +162,9 @@
      }
  
      static int calculateBodyLength(
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/cms/ContentInfo.java bcprov-jdk15on-151/org/bouncycastle/asn1/cms/ContentInfo.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/cms/ContentInfo.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/cms/ContentInfo.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/cms/ContentInfo.java bcprov-jdk15on-152/org/bouncycastle/asn1/cms/ContentInfo.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/cms/ContentInfo.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/cms/ContentInfo.java	2013-12-12 00:35:05.000000000 +0000
 @@ -28,7 +28,9 @@
   */
  public class ContentInfo
@@ -176,9 +176,9 @@
  {
      private ASN1ObjectIdentifier contentType;
      private ASN1Encodable        content;
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java bcprov-jdk15on-151/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java bcprov-jdk15on-152/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java	2013-12-12 00:35:05.000000000 +0000
 @@ -13,10 +13,12 @@
      static final ASN1ObjectIdentifier    pkcs_1                    = new ASN1ObjectIdentifier("1.2.840.113549.1.1");
      /** PKCS#1: 1.2.840.113549.1.1.1 */
@@ -220,9 +220,9 @@
  
      //
      // md5 OBJECT IDENTIFIER ::=
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java bcprov-jdk15on-151/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java bcprov-jdk15on-152/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java	2014-07-28 19:51:54.000000000 +0000
 @@ -14,7 +14,9 @@
  import org.bouncycastle.asn1.DERSequence;
  import org.bouncycastle.asn1.DERTaggedObject;
@@ -256,9 +256,9 @@
          byte[]  resBuf = new byte[digest.getDigestSize()];
  
          byte[] bytes = spki.getPublicKeyData().getBytes();
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/X509Name.java bcprov-jdk15on-151/org/bouncycastle/asn1/x509/X509Name.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/X509Name.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/x509/X509Name.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/x509/X509Name.java bcprov-jdk15on-152/org/bouncycastle/asn1/x509/X509Name.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/x509/X509Name.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/x509/X509Name.java	2013-12-12 00:35:05.000000000 +0000
 @@ -255,8 +255,10 @@
       */
      public static final Hashtable SymbolLookUp = DefaultLookUp;
@@ -283,9 +283,9 @@
              }
          }
      }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java bcprov-jdk15on-151/org/bouncycastle/asn1/x509/X509NameTokenizer.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/x509/X509NameTokenizer.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java bcprov-jdk15on-152/org/bouncycastle/asn1/x509/X509NameTokenizer.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/x509/X509NameTokenizer.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/x509/X509NameTokenizer.java	2013-05-25 02:14:15.000000000 +0000
 @@ -78,6 +78,17 @@
                  }
                  else
@@ -304,9 +304,9 @@
                      buf.append(c);
                  }
              }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.java bcprov-jdk15on-151/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/asn1/x9/ECNamedCurveTable.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.java bcprov-jdk15on-152/org/bouncycastle/asn1/x9/ECNamedCurveTable.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/asn1/x9/ECNamedCurveTable.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/asn1/x9/ECNamedCurveTable.java	2014-07-28 19:51:54.000000000 +0000
 @@ -6,7 +6,9 @@
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
  import org.bouncycastle.asn1.nist.NISTNamedCurves;
@@ -380,9 +380,9 @@
  
          return v.elements();
      }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactory.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactory.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactory.java	1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactory.java	2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/AndroidDigestFactory.java bcprov-jdk15on-152/org/bouncycastle/crypto/digests/AndroidDigestFactory.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/AndroidDigestFactory.java	1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/digests/AndroidDigestFactory.java	2013-09-26 18:06:21.000000000 +0000
 @@ -0,0 +1,87 @@
 +/*
 + * Copyright (C) 2012 The Android Open Source Project
@@ -471,9 +471,9 @@
 +        return FACTORY.getSHA512();
 +    }
 +}
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java	1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java	2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java bcprov-jdk15on-152/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java	1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/digests/AndroidDigestFactoryBouncyCastle.java	2013-09-26 18:06:21.000000000 +0000
 @@ -0,0 +1,40 @@
 +/*
 + * Copyright (C) 2012 The Android Open Source Project
@@ -515,9 +515,9 @@
 +        return new SHA512Digest();
 +    }
 +}
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java	1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java	2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java bcprov-jdk15on-152/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java	1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/digests/AndroidDigestFactoryInterface.java	2013-09-26 18:06:21.000000000 +0000
 @@ -0,0 +1,28 @@
 +/*
 + * Copyright (C) 2012 The Android Open Source Project
@@ -547,9 +547,9 @@
 +    public Digest getSHA384();
 +    public Digest getSHA512();
 +}
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java	1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java	2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java bcprov-jdk15on-152/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java	1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/digests/AndroidDigestFactoryOpenSSL.java	2013-09-26 18:06:21.000000000 +0000
 @@ -0,0 +1,40 @@
 +/*
 + * Copyright (C) 2012 The Android Open Source Project
@@ -591,9 +591,9 @@
 +        return new OpenSSLDigest.SHA512();
 +    }
 +}
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java bcprov-jdk15on-151/org/bouncycastle/crypto/digests/OpenSSLDigest.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java	1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/digests/OpenSSLDigest.java	2014-02-27 18:09:19.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java bcprov-jdk15on-152/org/bouncycastle/crypto/digests/OpenSSLDigest.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/digests/OpenSSLDigest.java	1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/digests/OpenSSLDigest.java	2014-02-27 18:09:19.000000000 +0000
 @@ -0,0 +1,97 @@
 +/*
 + * Copyright (C) 2008 The Android Open Source Project
@@ -692,9 +692,9 @@
 +        public SHA512() { super("SHA-512", 128); }
 +    }
 +}
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/ec/CustomNamedCurves.java bcprov-jdk15on-151/org/bouncycastle/crypto/ec/CustomNamedCurves.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/ec/CustomNamedCurves.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/ec/CustomNamedCurves.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/ec/CustomNamedCurves.java bcprov-jdk15on-152/org/bouncycastle/crypto/ec/CustomNamedCurves.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/ec/CustomNamedCurves.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/ec/CustomNamedCurves.java	2014-07-28 19:51:54.000000000 +0000
 @@ -10,7 +10,9 @@
  import org.bouncycastle.asn1.x9.X9ECParametersHolder;
  import org.bouncycastle.math.ec.ECCurve;
@@ -778,9 +778,9 @@
  
          defineCurveWithOID("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
          defineCurveWithOID("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/encodings/OAEPEncoding.java bcprov-jdk15on-151/org/bouncycastle/crypto/encodings/OAEPEncoding.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/encodings/OAEPEncoding.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/encodings/OAEPEncoding.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/encodings/OAEPEncoding.java bcprov-jdk15on-152/org/bouncycastle/crypto/encodings/OAEPEncoding.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/encodings/OAEPEncoding.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/encodings/OAEPEncoding.java	2013-05-25 02:14:15.000000000 +0000
 @@ -6,7 +6,9 @@
  import org.bouncycastle.crypto.CipherParameters;
  import org.bouncycastle.crypto.Digest;
@@ -803,10 +803,10 @@
      }
      
      public OAEPEncoding(
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/encodings/PKCS1Encoding.java bcprov-jdk15on-151/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/encodings/PKCS1Encoding.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/encodings/PKCS1Encoding.java	2014-07-28 19:51:54.000000000 +0000
-@@ -377,6 +377,12 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/encodings/PKCS1Encoding.java bcprov-jdk15on-152/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/encodings/PKCS1Encoding.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/encodings/PKCS1Encoding.java	2015-04-09 13:10:16.000000000 +0000
+@@ -378,6 +378,12 @@
                  throw new InvalidCipherTextException("unknown block type");
              }
          }
@@ -819,9 +819,9 @@
  
          if (useStrictLength && block.length != engine.getOutputBlockSize())
          {
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/engines/DESedeWrapEngine.java bcprov-jdk15on-151/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/engines/DESedeWrapEngine.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/engines/DESedeWrapEngine.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/engines/DESedeWrapEngine.java bcprov-jdk15on-152/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/engines/DESedeWrapEngine.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/engines/DESedeWrapEngine.java	2014-07-28 19:51:54.000000000 +0000
 @@ -6,7 +6,9 @@
  import org.bouncycastle.crypto.Digest;
  import org.bouncycastle.crypto.InvalidCipherTextException;
@@ -844,9 +844,9 @@
      byte[]  digest = new byte[20];
  
     /**
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/DHParametersHelper.java bcprov-jdk15on-151/org/bouncycastle/crypto/generators/DHParametersHelper.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/DHParametersHelper.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/generators/DHParametersHelper.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/generators/DHParametersHelper.java bcprov-jdk15on-152/org/bouncycastle/crypto/generators/DHParametersHelper.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/generators/DHParametersHelper.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/generators/DHParametersHelper.java	2014-07-28 19:51:54.000000000 +0000
 @@ -3,11 +3,18 @@
  import java.math.BigInteger;
  import java.security.SecureRandom;
@@ -899,9 +899,9 @@
  
          return new BigInteger[] { p, q };
      }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/DSAParametersGenerator.java bcprov-jdk15on-151/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/DSAParametersGenerator.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/generators/DSAParametersGenerator.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/generators/DSAParametersGenerator.java bcprov-jdk15on-152/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/generators/DSAParametersGenerator.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/generators/DSAParametersGenerator.java	2014-07-28 19:51:54.000000000 +0000
 @@ -4,7 +4,9 @@
  import java.security.SecureRandom;
  
@@ -935,9 +935,9 @@
          {
              throw new IllegalStateException("can only use SHA-1 for generating FIPS 186-2 parameters");
          }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java bcprov-jdk15on-151/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java	2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java bcprov-jdk15on-152/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java	2012-09-17 23:04:47.000000000 +0000
 @@ -3,7 +3,9 @@
  import org.bouncycastle.crypto.CipherParameters;
  import org.bouncycastle.crypto.Digest;
@@ -960,9 +960,9 @@
  
      /**
       * Construct a OpenSSL Parameters generator. 
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java bcprov-jdk15on-151/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java bcprov-jdk15on-152/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java	2013-12-12 00:35:05.000000000 +0000
 @@ -4,7 +4,9 @@
  import org.bouncycastle.crypto.Digest;
  import org.bouncycastle.crypto.Mac;
@@ -985,9 +985,9 @@
      }
  
      public PKCS5S2ParametersGenerator(Digest digest)
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/macs/HMac.java bcprov-jdk15on-151/org/bouncycastle/crypto/macs/HMac.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/macs/HMac.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/macs/HMac.java	2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/macs/HMac.java bcprov-jdk15on-152/org/bouncycastle/crypto/macs/HMac.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/macs/HMac.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/macs/HMac.java	2013-09-26 18:06:21.000000000 +0000
 @@ -36,14 +36,18 @@
      {
          blockLengths = new Hashtable();
@@ -1026,9 +1026,9 @@
      }
      
      private static int getByteLength(
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java bcprov-jdk15on-151/org/bouncycastle/crypto/signers/RSADigestSigner.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/signers/RSADigestSigner.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java bcprov-jdk15on-152/org/bouncycastle/crypto/signers/RSADigestSigner.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/signers/RSADigestSigner.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/signers/RSADigestSigner.java	2015-04-09 13:10:16.000000000 +0000
 @@ -39,9 +39,11 @@
       */
      static
@@ -1057,9 +1057,9 @@
          oidMap.put("MD5", PKCSObjectIdentifiers.md5);
      }
  
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java bcprov-jdk15on-151/org/bouncycastle/crypto/util/PrivateKeyFactory.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/util/PrivateKeyFactory.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java bcprov-jdk15on-152/org/bouncycastle/crypto/util/PrivateKeyFactory.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/util/PrivateKeyFactory.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/util/PrivateKeyFactory.java	2014-07-28 19:51:54.000000000 +0000
 @@ -9,7 +9,9 @@
  import org.bouncycastle.asn1.ASN1Integer;
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -1109,9 +1109,9 @@
          else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
          {
              ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java bcprov-jdk15on-151/org/bouncycastle/crypto/util/PublicKeyFactory.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/crypto/util/PublicKeyFactory.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java bcprov-jdk15on-152/org/bouncycastle/crypto/util/PublicKeyFactory.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/crypto/util/PublicKeyFactory.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/crypto/util/PublicKeyFactory.java	2014-07-28 19:51:54.000000000 +0000
 @@ -11,7 +11,9 @@
  import org.bouncycastle.asn1.ASN1OctetString;
  import org.bouncycastle.asn1.ASN1Primitive;
@@ -1161,9 +1161,9 @@
          else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
              || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1))
          {
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/DH.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/DH.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/DH.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/DH.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/DH.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/DH.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/DH.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/DH.java	2014-07-28 19:51:54.000000000 +0000
 @@ -35,10 +35,12 @@
  
              provider.addAlgorithm("AlgorithmParameterGenerator.DH", PREFIX + "AlgorithmParameterGeneratorSpi");
@@ -1181,9 +1181,9 @@
  
              registerOid(provider, PKCSObjectIdentifiers.dhKeyAgreement, "DH", new KeyFactorySpi());
              registerOid(provider, X9ObjectIdentifiers.dhpublicnumber, "DH", new KeyFactorySpi());
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/DSA.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/DSA.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/DSA.java	2013-12-16 16:39:58.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/DSA.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/DSA.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/DSA.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/DSA.java	2013-12-16 16:39:58.000000000 +0000
 @@ -27,40 +27,53 @@
              provider.addAlgorithm("KeyPairGenerator.DSA", PREFIX + "KeyPairGeneratorSpi");
              provider.addAlgorithm("KeyFactory.DSA", PREFIX + "KeyFactorySpi");
@@ -1259,9 +1259,9 @@
  
                  registerOid(provider, DSAUtil.dsaOids[i], "DSA", keyFact);
                  registerOidAlgorithmParameters(provider, DSAUtil.dsaOids[i], "DSA");
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/EC.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/EC.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/EC.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/EC.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/EC.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/EC.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/EC.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/EC.java	2014-07-28 19:51:54.000000000 +0000
 @@ -1,8 +1,10 @@
  package org.bouncycastle.jcajce.provider.asymmetric;
  
@@ -1276,7 +1276,7 @@
  import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
  import org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi;
  import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
-@@ -22,45 +24,55 @@
+@@ -22,45 +24,59 @@
          public void configure(ConfigurableProvider provider)
          {
              provider.addAlgorithm("KeyAgreement.ECDH", PREFIX + "KeyAgreementSpi$DH");
@@ -1297,15 +1297,22 @@
              // TODO Should this be an alias for ECDH?
              registerOid(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC", new KeyFactorySpi.EC());
 -            registerOid(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV());
+-
+-            registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
 +            // BEGIN android-removed
 +            // registerOid(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "ECMQV", new KeyFactorySpi.ECMQV());
++            //
++            // // Android comment: the registration below is causing CTS tests to fail and doesn't seem
++            // // to be implemented by bouncycastle (so looks like an bug in bouncycastle).
++            // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
 +            // END android-removed
- 
-             registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.id_ecPublicKey, "EC");
              // TODO Should this be an alias for ECDH?
-             registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
+-            registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
 -            registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC");
 +            // BEGIN android-removed
++            // // Android comment: the registration below is causing CTS tests to fail and doesn't seem
++            // // to be implemented by bouncycastle (so looks like an bug in bouncycastle).
++            // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme, "EC");
 +            // registerOidAlgorithmParameters(provider, X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme, "EC");
 +            // END android-removed
  
@@ -1359,7 +1366,7 @@
  
              provider.addAlgorithm("Signature.ECDSA", PREFIX + "SignatureSpi$ecDSA");
              provider.addAlgorithm("Signature.NONEwithECDSA", PREFIX + "SignatureSpi$ecDSAnone");
-@@ -72,39 +84,43 @@
+@@ -72,39 +88,43 @@
              provider.addAlgorithm("Alg.Alias.Signature.SHA1WithECDSA", "ECDSA");
              provider.addAlgorithm("Alg.Alias.Signature.ECDSAWithSHA1", "ECDSA");
              provider.addAlgorithm("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
@@ -1431,9 +1438,9 @@
          }
      }
  }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/RSA.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/RSA.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/RSA.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/RSA.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/RSA.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/RSA.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/RSA.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/RSA.java	2015-04-09 13:10:16.000000000 +0000
 @@ -3,7 +3,9 @@
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
  import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
@@ -1525,7 +1532,7 @@
  
              provider.addAlgorithm("KeyFactory.RSA", PREFIX + "KeyFactorySpi");
              provider.addAlgorithm("KeyPairGenerator.RSA", PREFIX + "KeyPairGeneratorSpi");
-@@ -68,73 +78,81 @@
+@@ -68,79 +78,89 @@
              registerOid(provider, PKCSObjectIdentifiers.rsaEncryption, "RSA", keyFact);
              registerOid(provider, X509ObjectIdentifiers.id_ea_rsa, "RSA", keyFact);
              registerOid(provider, PKCSObjectIdentifiers.id_RSAES_OAEP, "RSA", keyFact);
@@ -1662,15 +1669,42 @@
 +                // END android-removed
                  provider.addAlgorithm("Alg.Alias.Signature." + OIWObjectIdentifiers.sha1WithRSA, "SHA1WITHRSA");
                  provider.addAlgorithm("Alg.Alias.Signature.OID." + OIWObjectIdentifiers.sha1WithRSA, "SHA1WITHRSA");
+ 
+-                provider.addAlgorithm("Alg.Alias.Signature.SHA1withRSA/X9.31", "SHA1WITHRSA/X9.31");
+-                provider.addAlgorithm("Alg.Alias.Signature.SHA1WithRSA/X9.31", "SHA1WITHRSA/X9.31");
+-                provider.addAlgorithm("Signature.SHA1WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA1WithRSAEncryption");
++                // BEGIN android-removed
++                // provider.addAlgorithm("Alg.Alias.Signature.SHA1withRSA/X9.31", "SHA1WITHRSA/X9.31");
++                // provider.addAlgorithm("Alg.Alias.Signature.SHA1WithRSA/X9.31", "SHA1WITHRSA/X9.31");
++                // provider.addAlgorithm("Signature.SHA1WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA1WithRSAEncryption");
++                // END android-removed
              }
-@@ -144,25 +162,27 @@
+ 
+             addDigestSignature(provider, "SHA224", PREFIX + "DigestSignatureSpi$SHA224", PKCSObjectIdentifiers.sha224WithRSAEncryption);
+@@ -148,52 +168,54 @@
              addDigestSignature(provider, "SHA384", PREFIX + "DigestSignatureSpi$SHA384", PKCSObjectIdentifiers.sha384WithRSAEncryption);
              addDigestSignature(provider, "SHA512", PREFIX + "DigestSignatureSpi$SHA512", PKCSObjectIdentifiers.sha512WithRSAEncryption);
  
+-            provider.addAlgorithm("Alg.Alias.Signature.SHA224withRSA/X9.31", "SHA224WITHRSA/X9.31");
+-            provider.addAlgorithm("Alg.Alias.Signature.SHA224WithRSA/X9.31", "SHA224WITHRSA/X9.31");
+-            provider.addAlgorithm("Signature.SHA224WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA224WithRSAEncryption");
+-            provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSA/X9.31", "SHA256WITHRSA/X9.31");
+-            provider.addAlgorithm("Alg.Alias.Signature.SHA256WithRSA/X9.31", "SHA256WITHRSA/X9.31");
+-            provider.addAlgorithm("Signature.SHA256WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA256WithRSAEncryption");
+-            provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSA/X9.31", "SHA384WITHRSA/X9.31");
+-            provider.addAlgorithm("Alg.Alias.Signature.SHA384WithRSA/X9.31", "SHA384WITHRSA/X9.31");
+-            provider.addAlgorithm("Signature.SHA384WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA384WithRSAEncryption");
+-            provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSA/X9.31", "SHA512WITHRSA/X9.31");
+-            provider.addAlgorithm("Alg.Alias.Signature.SHA512WithRSA/X9.31", "SHA512WITHRSA/X9.31");
+-            provider.addAlgorithm("Signature.SHA512WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA512WithRSAEncryption");
+-
 -            if (provider.hasAlgorithm("MessageDigest", "RIPEMD128"))
 -            {
 -                addDigestSignature(provider, "RIPEMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
 -                addDigestSignature(provider, "RMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", null);
+-                provider.addAlgorithm("Alg.Alias.Signature.RIPEMD128withRSA/X9.31", "RIPEMD128WITHRSA/X9.31");
+-                provider.addAlgorithm("Alg.Alias.Signature.RIPEMD128WithRSA/X9.31", "RIPEMD128WITHRSA/X9.31");
+-                provider.addAlgorithm("Signature.RIPEMD128WITHRSA/X9.31", PREFIX + "X931SignatureSpi$RIPEMD128WithRSAEncryption");
 -            }
 -
 -            if (provider.hasAlgorithm("MessageDigest", "RIPEMD160"))
@@ -1679,6 +1713,9 @@
 -                addDigestSignature(provider, "RMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", null);
 -                provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/ISO9796-2", "RIPEMD160withRSA/ISO9796-2");
 -                provider.addAlgorithm("Signature.RIPEMD160withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$RIPEMD160WithRSAEncryption");
+-                provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160withRSA/X9.31", "RIPEMD160WITHRSA/X9.31");
+-                provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/X9.31", "RIPEMD160WITHRSA/X9.31");
+-                provider.addAlgorithm("Signature.RIPEMD160WITHRSA/X9.31", PREFIX + "X931SignatureSpi$RIPEMD160WithRSAEncryption");
 -            }
 -
 -            if (provider.hasAlgorithm("MessageDigest", "RIPEMD256"))
@@ -1686,33 +1723,68 @@
 -                addDigestSignature(provider, "RIPEMD256", PREFIX + "DigestSignatureSpi$RIPEMD256", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
 -                addDigestSignature(provider, "RMD256", PREFIX + "DigestSignatureSpi$RIPEMD256", null);
 -            }
+-
+-            if (provider.hasAlgorithm("MessageDigest", "WHIRLPOOL"))
+-            {
+-                provider.addAlgorithm("Alg.Alias.Signature.WhirlpoolWithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
+-                provider.addAlgorithm("Alg.Alias.Signature.WHIRLPOOLwithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
+-                provider.addAlgorithm("Alg.Alias.Signature.WHIRLPOOLWithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
+-                provider.addAlgorithm("Signature.WHIRLPOOLWITHRSA/X9.31", PREFIX + "X931SignatureSpi$WhirlpoolWithRSAEncryption");
+-            }
 +            // BEGIN android-removed
++            // provider.addAlgorithm("Alg.Alias.Signature.SHA224withRSA/X9.31", "SHA224WITHRSA/X9.31");
++            // provider.addAlgorithm("Alg.Alias.Signature.SHA224WithRSA/X9.31", "SHA224WITHRSA/X9.31");
++            // provider.addAlgorithm("Signature.SHA224WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA224WithRSAEncryption");
++            // provider.addAlgorithm("Alg.Alias.Signature.SHA256withRSA/X9.31", "SHA256WITHRSA/X9.31");
++            // provider.addAlgorithm("Alg.Alias.Signature.SHA256WithRSA/X9.31", "SHA256WITHRSA/X9.31");
++            // provider.addAlgorithm("Signature.SHA256WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA256WithRSAEncryption");
++            // provider.addAlgorithm("Alg.Alias.Signature.SHA384withRSA/X9.31", "SHA384WITHRSA/X9.31");
++            // provider.addAlgorithm("Alg.Alias.Signature.SHA384WithRSA/X9.31", "SHA384WITHRSA/X9.31");
++            // provider.addAlgorithm("Signature.SHA384WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA384WithRSAEncryption");
++            // provider.addAlgorithm("Alg.Alias.Signature.SHA512withRSA/X9.31", "SHA512WITHRSA/X9.31");
++            // provider.addAlgorithm("Alg.Alias.Signature.SHA512WithRSA/X9.31", "SHA512WITHRSA/X9.31");
++            // provider.addAlgorithm("Signature.SHA512WITHRSA/X9.31", PREFIX + "X931SignatureSpi$SHA512WithRSAEncryption");
++            //
 +            // if (provider.hasAlgorithm("MessageDigest", "RIPEMD128"))
 +            // {
 +            //     addDigestSignature(provider, "RIPEMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
 +            //     addDigestSignature(provider, "RMD128", PREFIX + "DigestSignatureSpi$RIPEMD128", null);
++            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD128withRSA/X9.31", "RIPEMD128WITHRSA/X9.31");
++            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD128WithRSA/X9.31", "RIPEMD128WITHRSA/X9.31");
++            //     provider.addAlgorithm("Signature.RIPEMD128WITHRSA/X9.31", PREFIX + "X931SignatureSpi$RIPEMD128WithRSAEncryption");
 +            // }
-+            //
++	    //
 +            // if (provider.hasAlgorithm("MessageDigest", "RIPEMD160"))
 +            // {
 +            //     addDigestSignature(provider, "RIPEMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
 +            //     addDigestSignature(provider, "RMD160", PREFIX + "DigestSignatureSpi$RIPEMD160", null);
 +            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/ISO9796-2", "RIPEMD160withRSA/ISO9796-2");
 +            //     provider.addAlgorithm("Signature.RIPEMD160withRSA/ISO9796-2", PREFIX + "ISOSignatureSpi$RIPEMD160WithRSAEncryption");
++            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160withRSA/X9.31", "RIPEMD160WITHRSA/X9.31");
++            //     provider.addAlgorithm("Alg.Alias.Signature.RIPEMD160WithRSA/X9.31", "RIPEMD160WITHRSA/X9.31");
++            //     provider.addAlgorithm("Signature.RIPEMD160WITHRSA/X9.31", PREFIX + "X931SignatureSpi$RIPEMD160WithRSAEncryption");
 +            // }
-+            //
++	    //
 +            // if (provider.hasAlgorithm("MessageDigest", "RIPEMD256"))
 +            // {
 +            //     addDigestSignature(provider, "RIPEMD256", PREFIX + "DigestSignatureSpi$RIPEMD256", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
 +            //     addDigestSignature(provider, "RMD256", PREFIX + "DigestSignatureSpi$RIPEMD256", null);
 +            // }
-+            // END android-removed
++	    //
++            // if (provider.hasAlgorithm("MessageDigest", "WHIRLPOOL"))
++            // {
++            //     provider.addAlgorithm("Alg.Alias.Signature.WhirlpoolWithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
++            //     provider.addAlgorithm("Alg.Alias.Signature.WHIRLPOOLwithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
++            //     provider.addAlgorithm("Alg.Alias.Signature.WHIRLPOOLWithRSA/X9.31", "WHIRLPOOLWITHRSA/X9.31");
++            //     provider.addAlgorithm("Signature.WHIRLPOOLWITHRSA/X9.31", PREFIX + "X931SignatureSpi$WhirlpoolWithRSAEncryption");
++            // }
++	    // END android-removed
          }
  
          private void addDigestSignature(
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/X509.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/X509.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/X509.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/X509.java	2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/X509.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/X509.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/X509.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/X509.java	2012-09-17 23:04:47.000000000 +0000
 @@ -18,8 +18,10 @@
  
          public void configure(ConfigurableProvider provider)
@@ -1726,9 +1798,9 @@
  
              //
              // certificate factories.
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/dsa/DSASigner.java	2013-12-12 00:35:05.000000000 +0000
 @@ -23,13 +23,20 @@
  import org.bouncycastle.crypto.DSA;
  import org.bouncycastle.crypto.Digest;
@@ -1922,9 +1994,9 @@
  
      static public class noneDSA
          extends DSASigner
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java	2014-07-28 19:51:54.000000000 +0000
 @@ -24,22 +24,28 @@
  import org.bouncycastle.crypto.CipherParameters;
  import org.bouncycastle.crypto.DerivationFunction;
@@ -2237,9 +2309,9 @@
 +    // }
 +    // END android-removed
  }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyFactorySpi.java	2013-05-25 02:14:15.000000000 +0000
 @@ -201,14 +201,16 @@
          }
      }
@@ -2265,9 +2337,9 @@
  
      public static class ECDH
          extends KeyFactorySpi
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java	2014-07-28 19:51:54.000000000 +0000
 @@ -84,7 +84,13 @@
              SecureRandom    random)
          {
@@ -2301,9 +2373,9 @@
 -}
 \ No newline at end of file
 +}
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java	2014-07-28 19:51:54.000000000 +0000
 @@ -16,16 +16,23 @@
  import org.bouncycastle.crypto.DSA;
  import org.bouncycastle.crypto.Digest;
@@ -2845,9 +2917,9 @@
 +    // }
 +    // END android-removed
 +}
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/rsa/CipherSpi.java	2015-04-09 13:10:16.000000000 +0000
 @@ -26,7 +26,9 @@
  import org.bouncycastle.crypto.CipherParameters;
  import org.bouncycastle.crypto.Digest;
@@ -2859,7 +2931,7 @@
  import org.bouncycastle.crypto.encodings.OAEPEncoding;
  import org.bouncycastle.crypto.encodings.PKCS1Encoding;
  import org.bouncycastle.crypto.engines.RSABlindedEngine;
-@@ -197,10 +199,12 @@
+@@ -201,10 +203,12 @@
          {
              cipher = new PKCS1Encoding(new RSABlindedEngine());
          }
@@ -2876,7 +2948,7 @@
          else if (pad.equals("OAEPWITHMD5ANDMGF1PADDING"))
          {
              initFromSpec(new OAEPParameterSpec("MD5", "MGF1", new MGF1ParameterSpec("MD5"), PSource.PSpecified.DEFAULT));
-@@ -539,48 +543,50 @@
+@@ -543,48 +547,50 @@
          }
      }
  
@@ -2971,9 +3043,9 @@
 +    // }
 +    // END android-removed
  }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java	2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/rsa/DigestSignatureSpi.java	2015-04-09 13:10:16.000000000 +0000
 @@ -17,24 +17,31 @@
  import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
  import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
@@ -3018,8 +3090,8 @@
 +// END android-added
  import org.bouncycastle.crypto.encodings.PKCS1Encoding;
  import org.bouncycastle.crypto.engines.RSABlindedEngine;
- 
-@@ -261,7 +268,9 @@
+ import org.bouncycastle.util.Arrays;
+@@ -254,7 +261,9 @@
      {
          public SHA1()
          {
@@ -3030,7 +3102,7 @@
          }
      }
  
-@@ -270,7 +279,9 @@
+@@ -263,7 +272,9 @@
      {
          public SHA224()
          {
@@ -3041,7 +3113,7 @@
          }
      }
  
-@@ -279,7 +290,9 @@
+@@ -272,7 +283,9 @@
      {
          public SHA256()
          {
@@ -3052,7 +3124,7 @@
          }
      }
  
-@@ -288,7 +301,9 @@
+@@ -281,7 +294,9 @@
      {
          public SHA384()
          {
@@ -3063,7 +3135,7 @@
          }
      }
  
-@@ -297,70 +312,78 @@
+@@ -290,70 +305,78 @@
      {
          public SHA512()
          {
@@ -3196,9 +3268,9 @@
 +    // }
 +    // END android-removed
  }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java	2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/util/BaseCipherSpi.java	2015-04-09 13:10:16.000000000 +0000
 @@ -18,8 +18,10 @@
  import javax.crypto.NoSuchPaddingException;
  import javax.crypto.spec.IvParameterSpec;
@@ -3212,7 +3284,7 @@
  import javax.crypto.spec.SecretKeySpec;
  
  import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-@@ -37,8 +39,10 @@
+@@ -39,8 +41,10 @@
                                      {
                                          IvParameterSpec.class,
                                          PBEParameterSpec.class,
@@ -3224,11 +3296,11 @@
 +                                        // END android-removed
                                      };
  
- 
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java	2014-07-28 19:51:54.000000000 +0000
-@@ -5,11 +5,15 @@
+     private final JcaJceHelper helper = new BCJcaJceHelper();
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/util/ECUtil.java	2015-04-09 13:10:16.000000000 +0000
+@@ -6,11 +6,15 @@
  import java.security.PublicKey;
  
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -3245,8 +3317,8 @@
 +// END android-removed
  import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
  import org.bouncycastle.asn1.x9.X962NamedCurves;
- import org.bouncycastle.asn1.x9.X9ECParameters;
-@@ -226,14 +230,16 @@
+ import org.bouncycastle.asn1.x9.X962Parameters;
+@@ -247,14 +251,16 @@
              {
                  oid = NISTNamedCurves.getOID(name);
              }
@@ -3271,7 +3343,7 @@
          }
  
          return oid;
-@@ -255,10 +261,12 @@
+@@ -276,10 +282,12 @@
              {
                  params = NISTNamedCurves.getByOID(oid);
              }
@@ -3288,7 +3360,7 @@
          }
  
          return params;
-@@ -276,14 +284,16 @@
+@@ -297,14 +305,16 @@
              {
                  name = NISTNamedCurves.getName(oid);
              }
@@ -3313,12 +3385,12 @@
          }
  
          return name;
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java	2013-02-21 00:01:31.000000000 +0000
-@@ -36,7 +36,9 @@
- import org.bouncycastle.asn1.pkcs.SignedData;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/x509/PKIXCertPath.java	2015-04-09 13:10:16.000000000 +0000
+@@ -37,7 +37,9 @@
+ import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+ import org.bouncycastle.jcajce.util.JcaJceHelper;
  import org.bouncycastle.util.io.pem.PemObject;
 -import org.bouncycastle.util.io.pem.PemWriter;
 +// BEGIN android-removed
@@ -3327,7 +3399,7 @@
  
  /**
   * CertPath implementation for X.509 certificates.
-@@ -51,7 +53,9 @@
+@@ -54,7 +56,9 @@
      {
          List encodings = new ArrayList();
          encodings.add("PkiPath");
@@ -3338,7 +3410,7 @@
          encodings.add("PKCS7");
          certPathEncodings = Collections.unmodifiableList(encodings);
      }
-@@ -298,27 +302,29 @@
+@@ -301,27 +305,29 @@
              return toDEREncoded(new ContentInfo(
                      PKCSObjectIdentifiers.signedData, sd));
          }
@@ -3389,10 +3461,10 @@
          else
          {
              throw new CertificateEncodingException("unsupported encoding: " + encoding);
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java	2013-05-25 02:14:15.000000000 +0000
-@@ -57,6 +57,9 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/x509/X509CertificateObject.java	2015-04-09 13:10:16.000000000 +0000
+@@ -55,6 +55,9 @@
  import org.bouncycastle.asn1.x509.Extensions;
  import org.bouncycastle.asn1.x509.GeneralName;
  import org.bouncycastle.asn1.x509.KeyUsage;
@@ -3402,7 +3474,7 @@
  import org.bouncycastle.jcajce.provider.asymmetric.util.PKCS12BagAttributeCarrierImpl;
  import org.bouncycastle.jce.X509Principal;
  import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
-@@ -564,12 +567,20 @@
+@@ -534,12 +537,20 @@
          }
      }
  
@@ -3424,7 +3496,7 @@
          }
          catch (IOException e)
          {
-@@ -860,7 +871,9 @@
+@@ -839,7 +850,9 @@
                      list.add(genName.getEncoded());
                      break;
                  case GeneralName.directoryName:
@@ -3435,10 +3507,10 @@
                      break;
                  case GeneralName.dNSName:
                  case GeneralName.rfc822Name:
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java	2014-07-28 19:51:54.000000000 +0000
-@@ -14,12 +14,16 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/asymmetric/x509/X509SignatureUtil.java	2015-04-09 13:10:16.000000000 +0000
+@@ -16,12 +16,16 @@
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
  import org.bouncycastle.asn1.ASN1Sequence;
  import org.bouncycastle.asn1.DERNull;
@@ -3456,8 +3528,8 @@
 +// END android-removed
  import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
  import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
- 
-@@ -114,22 +118,24 @@
+ import org.bouncycastle.jce.provider.BouncyCastleProvider;
+@@ -143,22 +147,24 @@
          {
              return "SHA512";
          }
@@ -3498,9 +3570,9 @@
          else
          {
              return digestAlgOID.getId();            
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA256.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA256.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA256.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA256.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/digest/SHA256.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/digest/SHA256.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/digest/SHA256.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/digest/SHA256.java	2013-05-25 02:14:15.000000000 +0000
 @@ -45,17 +45,19 @@
          }
      }
@@ -3547,9 +3619,9 @@
  
              addHMACAlgorithm(provider, "SHA256", PREFIX + "$HashMac",  PREFIX + "$KeyGenerator");
              addHMACAlias(provider, "SHA256", PKCSObjectIdentifiers.id_hmacWithSHA256);
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA384.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA384.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA384.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA384.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/digest/SHA384.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/digest/SHA384.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/digest/SHA384.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/digest/SHA384.java	2013-05-25 02:14:15.000000000 +0000
 @@ -5,7 +5,9 @@
  import org.bouncycastle.crypto.CipherKeyGenerator;
  import org.bouncycastle.crypto.digests.SHA384Digest;
@@ -3597,9 +3669,9 @@
  
              addHMACAlgorithm(provider, "SHA384", PREFIX + "$HashMac",  PREFIX + "$KeyGenerator");
              addHMACAlias(provider, "SHA384", PKCSObjectIdentifiers.id_hmacWithSHA384);
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA512.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA512.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/digest/SHA512.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/digest/SHA512.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/digest/SHA512.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/digest/SHA512.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/digest/SHA512.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/digest/SHA512.java	2013-05-25 02:14:15.000000000 +0000
 @@ -4,9 +4,13 @@
  import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
  import org.bouncycastle.crypto.CipherKeyGenerator;
@@ -3844,9 +3916,9 @@
          }
      }
  
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/BC.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/BC.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/BC.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/BC.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/keystore/BC.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/keystore/BC.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/keystore/BC.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/keystore/BC.java	2013-05-25 02:14:15.000000000 +0000
 @@ -17,7 +17,9 @@
          public void configure(ConfigurableProvider provider)
          {
@@ -3858,9 +3930,9 @@
              provider.addAlgorithm("KeyStore.BouncyCastle", PREFIX + "BcKeyStoreSpi$BouncyCastleStore");
              provider.addAlgorithm("Alg.Alias.KeyStore.UBER", "BouncyCastle");
              provider.addAlgorithm("Alg.Alias.KeyStore.BOUNCYCASTLE", "BouncyCastle");
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/PKCS12.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/PKCS12.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/PKCS12.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/PKCS12.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/keystore/PKCS12.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/keystore/PKCS12.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/keystore/PKCS12.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/keystore/PKCS12.java	2013-05-25 02:14:15.000000000 +0000
 @@ -17,14 +17,16 @@
          public void configure(ConfigurableProvider provider)
          {
@@ -3886,10 +3958,10 @@
          }
      }
  }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java	2014-07-28 19:51:54.000000000 +0000
-@@ -61,8 +61,10 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/keystore/pkcs12/PKCS12KeyStoreSpi.java	2015-04-09 13:10:16.000000000 +0000
+@@ -62,8 +62,10 @@
  import org.bouncycastle.asn1.DEROutputStream;
  import org.bouncycastle.asn1.DERSequence;
  import org.bouncycastle.asn1.DERSet;
@@ -3902,18 +3974,18 @@
  import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
  import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
  import org.bouncycastle.asn1.pkcs.AuthenticatedSafe;
-@@ -88,7 +90,9 @@
+@@ -89,7 +91,9 @@
  import org.bouncycastle.crypto.digests.SHA1Digest;
- import org.bouncycastle.jcajce.provider.config.PKCS12StoreParameter;
+ import org.bouncycastle.jcajce.PKCS12StoreParameter;
  import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey;
 -import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
 +// BEGIN android-removed
 +// import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec;
 +// END android-removed
  import org.bouncycastle.jcajce.spec.PBKDF2KeySpec;
- import org.bouncycastle.jce.interfaces.BCKeyStore;
- import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
-@@ -750,13 +754,15 @@
+ import org.bouncycastle.jcajce.util.BCJcaJceHelper;
+ import org.bouncycastle.jcajce.util.JcaJceHelper;
+@@ -753,13 +757,15 @@
          {
              cipher.init(mode, key, new IvParameterSpec(ASN1OctetString.getInstance(encParams).getOctets()));
          }
@@ -3936,16 +4008,17 @@
          return cipher;
      }
  
-@@ -1678,32 +1684,34 @@
+@@ -1680,33 +1686,34 @@
+             super(new BouncyCastleProvider(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
          }
      }
- 
+-
 -    public static class BCPKCS12KeyStore3DES
 -        extends PKCS12KeyStoreSpi
 -    {
 -        public BCPKCS12KeyStore3DES()
 -        {
--            super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
+-            super(new BouncyCastleProvider(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
 -        }
 -    }
 -
@@ -3972,10 +4045,10 @@
 +    // {
 +    //     public BCPKCS12KeyStore3DES()
 +    //     {
-+    //         super(bcProvider, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
++    //         super(new BouncyCastleProvider(), pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd3_KeyTripleDES_CBC);
 +    //     }
 +    // }
-+    //
++    // 
 +    // public static class DefPKCS12KeyStore
 +    //     extends PKCS12KeyStoreSpi
 +    // {
@@ -3984,7 +4057,7 @@
 +    //         super(null, pbeWithSHAAnd3_KeyTripleDES_CBC, pbeWithSHAAnd40BitRC2_CBC);
 +    //     }
 +    // }
-+    //
++    // 
 +    // public static class DefPKCS12KeyStore3DES
 +    //     extends PKCS12KeyStoreSpi
 +    // {
@@ -3997,7 +4070,7 @@
  
      private static class IgnoresCaseHashtable
      {
-@@ -1776,7 +1784,9 @@
+@@ -1779,7 +1786,9 @@
              keySizes.put(NTTObjectIdentifiers.id_camellia192_cbc, Integers.valueOf(192));
              keySizes.put(NTTObjectIdentifiers.id_camellia256_cbc, Integers.valueOf(256));
  
@@ -4008,10 +4081,10 @@
  
              KEY_SIZES = Collections.unmodifiableMap(keySizes);
          }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/AES.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/AES.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/AES.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/AES.java	2014-07-28 19:51:54.000000000 +0000
-@@ -3,13 +3,17 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/AES.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/AES.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/AES.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/AES.java	2015-04-09 13:10:16.000000000 +0000
+@@ -3,16 +3,22 @@
  import java.io.IOException;
  import java.lang.reflect.Constructor;
  import java.lang.reflect.Method;
@@ -4031,8 +4104,14 @@
 +// END android-removed
  
  import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
+-import org.bouncycastle.asn1.cms.CCMParameters;
++// BEGIN android-removed
++// import org.bouncycastle.asn1.cms.CCMParameters;
++// END android-removed
  import org.bouncycastle.asn1.cms.GCMParameters;
-@@ -19,26 +23,34 @@
+ import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+ import org.bouncycastle.crypto.BlockCipher;
+@@ -20,22 +26,30 @@
  import org.bouncycastle.crypto.CipherKeyGenerator;
  import org.bouncycastle.crypto.engines.AESFastEngine;
  import org.bouncycastle.crypto.engines.AESWrapEngine;
@@ -4049,6 +4128,10 @@
 +// import org.bouncycastle.crypto.macs.GMac;
 +// END android-removed
  import org.bouncycastle.crypto.modes.CBCBlockCipher;
+-import org.bouncycastle.crypto.modes.CCMBlockCipher;
++// BEGIN android-removed
++// import org.bouncycastle.crypto.modes.CCMBlockCipher;
++// END android-removed
  import org.bouncycastle.crypto.modes.CFBBlockCipher;
  import org.bouncycastle.crypto.modes.GCMBlockCipher;
  import org.bouncycastle.crypto.modes.OFBBlockCipher;
@@ -4067,18 +4150,19 @@
  import org.bouncycastle.jcajce.provider.symmetric.util.BaseWrapCipher;
  import org.bouncycastle.jcajce.provider.symmetric.util.BlockCipherProvider;
  import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters;
- import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory;
--import org.bouncycastle.jce.provider.BouncyCastleProvider;
-+// BEGIN android-removed
-+// import org.bouncycastle.jce.provider.BouncyCastleProvider;
-+// END android-removed
- import org.bouncycastle.util.Integers;
- 
- public final class AES
-@@ -100,41 +112,43 @@
+@@ -101,50 +115,52 @@
          }
      }
  
+-    static public class CCM
+-        extends BaseBlockCipher
+-    {
+-        public CCM()
+-        {
+-            super(new CCMBlockCipher(new AESFastEngine()));
+-        }
+-    }
+-
 -    public static class AESCMAC
 -        extends BaseMac
 -    {
@@ -4115,6 +4199,15 @@
 -        }
 -    }
 +    // BEGIN android-removed
++    // static public class CCM
++    //     extends BaseBlockCipher
++    // {
++    //     public CCM()
++    //     {
++    //         super(new CCMBlockCipher(new AESFastEngine()));
++    //     }
++    // }
++    //
 +    // public static class AESCMAC
 +    //     extends BaseMac
 +    // {
@@ -4154,7 +4247,7 @@
  
      static public class Wrap
          extends BaseWrapCipher
-@@ -145,23 +159,25 @@
+@@ -155,23 +171,25 @@
          }
      }
  
@@ -4197,7 +4290,7 @@
  
      /**
       * PBEWithAES-CBC
-@@ -189,32 +205,34 @@
+@@ -199,32 +217,34 @@
          }
      }
  
@@ -4258,7 +4351,7 @@
      
      /**
       * PBEWithSHA1And128BitAES-BC
-@@ -324,43 +342,45 @@
+@@ -334,119 +354,121 @@
          }
      }
      
@@ -4288,7 +4381,7 @@
 -
 -            try
 -            {
--                params = AlgorithmParameters.getInstance("AES", BouncyCastleProvider.PROVIDER_NAME);
+-                params = createParametersInstance("AES");
 -                params.init(new IvParameterSpec(iv));
 -            }
 -            catch (Exception e)
@@ -4299,6 +4392,82 @@
 -            return params;
 -        }
 -    }
+-
+-    public static class AlgParamGenCCM
+-        extends BaseAlgorithmParameterGenerator
+-    {
+-        protected void engineInit(
+-            AlgorithmParameterSpec genParamSpec,
+-            SecureRandom random)
+-            throws InvalidAlgorithmParameterException
+-        {
+-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation.");
+-        }
+-
+-        protected AlgorithmParameters engineGenerateParameters()
+-        {
+-            byte[]  iv = new byte[12];
+-
+-            if (random == null)
+-            {
+-                random = new SecureRandom();
+-            }
+-
+-            random.nextBytes(iv);
+-
+-            AlgorithmParameters params;
+-
+-            try
+-            {
+-                params = createParametersInstance("CCM");
+-                params.init(new CCMParameters(iv, 12).getEncoded());
+-            }
+-            catch (Exception e)
+-            {
+-                throw new RuntimeException(e.getMessage());
+-            }
+-
+-            return params;
+-        }
+-    }
+-
+-    public static class AlgParamGenGCM
+-        extends BaseAlgorithmParameterGenerator
+-    {
+-        protected void engineInit(
+-            AlgorithmParameterSpec genParamSpec,
+-            SecureRandom random)
+-            throws InvalidAlgorithmParameterException
+-        {
+-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation.");
+-        }
+-
+-        protected AlgorithmParameters engineGenerateParameters()
+-        {
+-            byte[]  nonce = new byte[12];
+-
+-            if (random == null)
+-            {
+-                random = new SecureRandom();
+-            }
+-
+-            random.nextBytes(nonce);
+-
+-            AlgorithmParameters params;
+-
+-            try
+-            {
+-                params = createParametersInstance("GCM");
+-                params.init(new GCMParameters(nonce, 12).getEncoded());
+-            }
+-            catch (Exception e)
+-            {
+-                throw new RuntimeException(e.getMessage());
+-            }
+-
+-            return params;
+-        }
+-    }
 +    // BEGIN android-removed
 +    // public static class AlgParamGen
 +    //     extends BaseAlgorithmParameterGenerator
@@ -4326,7 +4495,7 @@
 +    //
 +    //         try
 +    //         {
-+    //             params = AlgorithmParameters.getInstance("AES", BouncyCastleProvider.PROVIDER_NAME);
++    //             params = createParametersInstance("AES");
 +    //             params.init(new IvParameterSpec(iv));
 +    //         }
 +    //         catch (Exception e)
@@ -4337,14 +4506,253 @@
 +    //         return params;
 +    //     }
 +    // }
++    //
++    // public static class AlgParamGenCCM
++    //     extends BaseAlgorithmParameterGenerator
++    // {
++    //     protected void engineInit(
++    //         AlgorithmParameterSpec genParamSpec,
++    //         SecureRandom random)
++    //         throws InvalidAlgorithmParameterException
++    //     {
++    //         throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation.");
++    //     }
++    //
++    //     protected AlgorithmParameters engineGenerateParameters()
++    //     {
++    //         byte[]  iv = new byte[12];
++    //
++    //         if (random == null)
++    //         {
++    //             random = new SecureRandom();
++    //         }
++    //
++    //         random.nextBytes(iv);
++    //
++    //         AlgorithmParameters params;
++    //
++    //         try
++    //         {
++    //             params = createParametersInstance("CCM");
++    //             params.init(new CCMParameters(iv, 12).getEncoded());
++    //         }
++    //         catch (Exception e)
++    //         {
++    //             throw new RuntimeException(e.getMessage());
++    //         }
++    //
++    //         return params;
++    //     }
++    // }
++    //
++    // public static class AlgParamGenGCM
++    //     extends BaseAlgorithmParameterGenerator
++    // {
++    //     protected void engineInit(
++    //         AlgorithmParameterSpec genParamSpec,
++    //         SecureRandom random)
++    //         throws InvalidAlgorithmParameterException
++    //     {
++    //         throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation.");
++    //     }
++    //
++    //     protected AlgorithmParameters engineGenerateParameters()
++    //     {
++    //         byte[]  nonce = new byte[12];
++    //
++    //         if (random == null)
++    //         {
++    //             random = new SecureRandom();
++    //         }
++    //
++    //         random.nextBytes(nonce);
++    //
++    //         AlgorithmParameters params;
++    //
++    //         try
++    //         {
++    //             params = createParametersInstance("GCM");
++    //             params.init(new GCMParameters(nonce, 12).getEncoded());
++    //         }
++    //         catch (Exception e)
++    //         {
++    //             throw new RuntimeException(e.getMessage());
++    //         }
++    //
++    //         return params;
++    //     }
++    // }
 +    // END android-removed
  
      public static class AlgParams
          extends IvAlgorithmParameters
-@@ -493,37 +513,43 @@
+@@ -545,80 +567,82 @@
+         }
+     }
+ 
+-    public static class AlgParamsCCM
+-        extends BaseAlgorithmParameters
+-    {
+-        private CCMParameters ccmParams;
+-
+-        protected void engineInit(AlgorithmParameterSpec paramSpec)
+-            throws InvalidParameterSpecException
+-        {
+-            throw new InvalidParameterSpecException("No supported AlgorithmParameterSpec for AES parameter generation.");
+-        }
+-
+-        protected void engineInit(byte[] params)
+-            throws IOException
+-        {
+-            ccmParams = CCMParameters.getInstance(params);
+-        }
+-
+-        protected void engineInit(byte[] params, String format)
+-            throws IOException
+-        {
+-            if (!isASN1FormatString(format))
+-            {
+-                throw new IOException("unknown format specified");
+-            }
+-
+-            ccmParams = CCMParameters.getInstance(params);
+-        }
+-
+-        protected byte[] engineGetEncoded()
+-            throws IOException
+-        {
+-            return ccmParams.getEncoded();
+-        }
+-
+-        protected byte[] engineGetEncoded(String format)
+-            throws IOException
+-        {
+-            if (!isASN1FormatString(format))
+-            {
+-                throw new IOException("unknown format specified");
+-            }
+-
+-            return ccmParams.getEncoded();
+-        }
+-
+-        protected String engineToString()
+-        {
+-            return "CCM";
+-        }
+-
+-        protected AlgorithmParameterSpec localEngineGetParameterSpec(Class paramSpec)
+-            throws InvalidParameterSpecException
+-        {
+-            if (gcmSpecClass != null)
+-            {
+-                try
+-                {
+-                    Constructor constructor = gcmSpecClass.getConstructor(new Class[] { Integer.TYPE, byte[].class });
+-
+-                    return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(ccmParams.getIcvLen() * 8), ccmParams.getNonce() });
+-                }
+-                catch (NoSuchMethodException e)
+-                {
+-                    throw new InvalidParameterSpecException("no constructor found!");   // should never happen
+-                }
+-                catch (Exception e)
+-                {
+-                    throw new InvalidParameterSpecException("construction failed: " + e.getMessage());   // should never happen
+-                }
+-            }
+-
+-            throw new InvalidParameterSpecException("unknown parameter spec: " + paramSpec.getName());
+-        }
+-    }
++    // BEGIN android-removed
++    // public static class AlgParamsCCM
++    //     extends BaseAlgorithmParameters
++    // {
++    //     private CCMParameters ccmParams;
++    // 
++    //     protected void engineInit(AlgorithmParameterSpec paramSpec)
++    //         throws InvalidParameterSpecException
++    //     {
++    //         throw new InvalidParameterSpecException("No supported AlgorithmParameterSpec for AES parameter generation.");
++    //     }
++    // 
++    //     protected void engineInit(byte[] params)
++    //         throws IOException
++    //     {
++    //         ccmParams = CCMParameters.getInstance(params);
++    //     }
++    // 
++    //     protected void engineInit(byte[] params, String format)
++    //         throws IOException
++    //     {
++    //         if (!isASN1FormatString(format))
++    //         {
++    //             throw new IOException("unknown format specified");
++    //         }
++    // 
++    //         ccmParams = CCMParameters.getInstance(params);
++    //     }
++    // 
++    //     protected byte[] engineGetEncoded()
++    //         throws IOException
++    //     {
++    //         return ccmParams.getEncoded();
++    //     }
++    // 
++    //     protected byte[] engineGetEncoded(String format)
++    //         throws IOException
++    //     {
++    //         if (!isASN1FormatString(format))
++    //         {
++    //             throw new IOException("unknown format specified");
++    //         }
++    // 
++    //         return ccmParams.getEncoded();
++    //     }
++    // 
++    //     protected String engineToString()
++    //     {
++    //         return "CCM";
++    //     }
++    // 
++    //     protected AlgorithmParameterSpec localEngineGetParameterSpec(Class paramSpec)
++    //         throws InvalidParameterSpecException
++    //     {
++    //         if (gcmSpecClass != null)
++    //         {
++    //             try
++    //             {
++    //                 Constructor constructor = gcmSpecClass.getConstructor(new Class[] { Integer.TYPE, byte[].class });
++    // 
++    //                 return (AlgorithmParameterSpec)constructor.newInstance(new Object[] { Integers.valueOf(ccmParams.getIcvLen() * 8), ccmParams.getNonce() });
++    //             }
++    //             catch (NoSuchMethodException e)
++    //             {
++    //                 throw new InvalidParameterSpecException("no constructor found!");   // should never happen
++    //             }
++    //             catch (Exception e)
++    //             {
++    //                 throw new InvalidParameterSpecException("construction failed: " + e.getMessage());   // should never happen
++    //             }
++    //         }
++    // 
++    //         throw new InvalidParameterSpecException("unknown parameter spec: " + paramSpec.getName());
++    //     }
++    // }
++    // END android-removed
+ 
+     public static class Mappings
+         extends SymmetricAlgorithmProvider
+@@ -652,58 +676,63 @@
+             provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
              provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
              provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
- 
+-
+-            provider.addAlgorithm("AlgorithmParameters.CCM", PREFIX + "$AlgParamsCCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes128_CCM, "CCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_CCM, "CCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
+-
 -            provider.addAlgorithm("AlgorithmParameterGenerator.AES", PREFIX + "$AlgParamGen");
 -            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES128, "AES");
 -            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES192, "AES");
@@ -4353,6 +4761,11 @@
 -            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_CBC, "AES");
 -            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_CBC, "AES");
 +            // BEGIN android-removed
++            // provider.addAlgorithm("AlgorithmParameters.CCM", PREFIX + "$AlgParamsCCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes128_CCM, "CCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes192_CCM, "CCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
++            //
 +            // provider.addAlgorithm("AlgorithmParameterGenerator.AES", PREFIX + "$AlgParamGen");
 +            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES128, "AES");
 +            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + wrongAES192, "AES");
@@ -4399,14 +4812,44 @@
  
 -            provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap");
 -            provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap");
+-
+-            provider.addAlgorithm("AlgorithmParameterGenerator.CCM", PREFIX + "$AlgParamGenCCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes128_CCM, "CCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_CCM, "CCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
+-
+-            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");
+-            provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
+-
+-            provider.addAlgorithm("AlgorithmParameterGenerator.GCM", PREFIX + "$AlgParamGenGCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
+-            provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
 +            // BEGIN android-removed
 +            // provider.addAlgorithm("Cipher.AESRFC3211WRAP", PREFIX + "$RFC3211Wrap");
 +            // provider.addAlgorithm("Cipher.AESRFC5649WRAP", PREFIX + "$RFC5649Wrap");
++            // 
++            // provider.addAlgorithm("AlgorithmParameterGenerator.CCM", PREFIX + "$AlgParamGenCCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes128_CCM, "CCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_CCM, "CCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
++            // 
++            // 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");
++            // provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_CCM, "CCM");
++            // 
++            // provider.addAlgorithm("AlgorithmParameterGenerator.GCM", PREFIX + "$AlgParamGenGCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes192_GCM, "GCM");
++            // provider.addAlgorithm("Alg.Alias.AlgorithmParameterGenerator." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
 +            // END android-removed
  
              provider.addAlgorithm("Cipher.GCM", PREFIX + "$GCM");
              provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes128_GCM, "GCM");
-@@ -531,27 +557,29 @@
+@@ -711,33 +740,35 @@
              provider.addAlgorithm("Alg.Alias.Cipher." + NISTObjectIdentifiers.id_aes256_GCM, "GCM");
  
              provider.addAlgorithm("KeyGenerator.AES", PREFIX + "$KeyGen");
@@ -4429,6 +4872,12 @@
 -            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_wrap, PREFIX + "$KeyGen128");
 -            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_wrap, PREFIX + "$KeyGen192");
 -            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_wrap, PREFIX + "$KeyGen256");
+-            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_GCM, PREFIX + "$KeyGen128");
+-            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_GCM, PREFIX + "$KeyGen192");
+-            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_GCM, PREFIX + "$KeyGen256");
+-            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_CCM, PREFIX + "$KeyGen128");
+-            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_CCM, PREFIX + "$KeyGen192");
+-            provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_CCM, PREFIX + "$KeyGen256");
 -
 -            provider.addAlgorithm("Mac.AESCMAC", PREFIX + "$AESCMAC");
 +            // BEGIN android-removed
@@ -4451,13 +4900,19 @@
 +            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_wrap, PREFIX + "$KeyGen128");
 +            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_wrap, PREFIX + "$KeyGen192");
 +            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_wrap, PREFIX + "$KeyGen256");
-+            //
++            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_GCM, PREFIX + "$KeyGen128");
++            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_GCM, PREFIX + "$KeyGen192");
++            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_GCM, PREFIX + "$KeyGen256");
++            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes128_CCM, PREFIX + "$KeyGen128");
++            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes192_CCM, PREFIX + "$KeyGen192");
++            // provider.addAlgorithm("KeyGenerator." + NISTObjectIdentifiers.id_aes256_CCM, PREFIX + "$KeyGen256");
++            // 
 +            // provider.addAlgorithm("Mac.AESCMAC", PREFIX + "$AESCMAC");
 +            // END android-removed
              
              provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.getId(), "PBEWITHSHAAND128BITAES-CBC-BC");
              provider.addAlgorithm("Alg.Alias.Cipher." + BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.getId(), "PBEWITHSHAAND192BITAES-CBC-BC");
-@@ -630,8 +658,10 @@
+@@ -816,8 +847,10 @@
              provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.getId(), "PKCS12PBE");
              provider.addAlgorithm("Alg.Alias.AlgorithmParameters." + BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.getId(), "PKCS12PBE");
  
@@ -4470,9 +4925,9 @@
          }
      }
  
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/ARC4.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/ARC4.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/ARC4.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/ARC4.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/ARC4.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/ARC4.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/ARC4.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/ARC4.java	2013-05-25 02:14:15.000000000 +0000
 @@ -29,7 +29,9 @@
      {
          public KeyGen()
@@ -4484,9 +4939,9 @@
          }
      }
  
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java	2012-09-17 23:04:47.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/Blowfish.java	2012-09-17 23:04:47.000000000 +0000
 @@ -64,7 +64,9 @@
          {
  
@@ -4498,9 +4953,9 @@
              provider.addAlgorithm("KeyGenerator.BLOWFISH", PREFIX + "$KeyGen");
              provider.addAlgorithm("Alg.Alias.KeyGenerator.1.3.6.1.4.1.3029.1.2", "BLOWFISH");
              provider.addAlgorithm("AlgorithmParameters.BLOWFISH", PREFIX + "$AlgParams");
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/DES.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/DES.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/DES.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/DES.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/DES.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/DES.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/DES.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/DES.java	2015-04-09 13:10:16.000000000 +0000
 @@ -19,12 +19,16 @@
  import org.bouncycastle.crypto.CipherParameters;
  import org.bouncycastle.crypto.KeyGenerationParameters;
@@ -4522,7 +4977,7 @@
  import org.bouncycastle.crypto.modes.CBCBlockCipher;
  import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
  import org.bouncycastle.crypto.params.DESParameters;
-@@ -66,17 +70,19 @@
+@@ -65,17 +69,19 @@
          }
      }
  
@@ -4553,7 +5008,7 @@
  
      /**
       * DES64
-@@ -111,47 +117,49 @@
+@@ -110,47 +116,49 @@
          }
      }
  
@@ -4644,7 +5099,7 @@
  
      public static class AlgParamGen
          extends BaseAlgorithmParameterGenerator
-@@ -351,17 +359,19 @@
+@@ -350,17 +358,19 @@
          }
      }
  
@@ -4675,7 +5130,7 @@
  
      /**
       * PBEWithMD5AndDES
-@@ -387,17 +397,19 @@
+@@ -386,17 +396,19 @@
          }
      }
  
@@ -4706,7 +5161,7 @@
  
      /**
       * PBEWithMD5AndDES
-@@ -437,61 +449,75 @@
+@@ -436,61 +448,75 @@
          {
  
              provider.addAlgorithm("Cipher.DES", PREFIX + "$ECB");
@@ -4817,9 +5272,9 @@
              provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, "PBEWITHMD5ANDDES");
              provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, "PBEWITHSHA1ANDDES");
          }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/DESede.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/DESede.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/DESede.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/DESede.java	2013-05-25 02:14:15.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/DESede.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/DESede.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/DESede.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/DESede.java	2015-04-09 13:10:16.000000000 +0000
 @@ -1,30 +1,42 @@
  package org.bouncycastle.jcajce.provider.symmetric;
  
@@ -4871,7 +5326,7 @@
  import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher;
  import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator;
  import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
-@@ -57,17 +69,19 @@
+@@ -56,17 +68,19 @@
          }
      }
  
@@ -4902,7 +5357,7 @@
  
      /**
       * DESede64
-@@ -102,15 +116,17 @@
+@@ -101,15 +115,17 @@
          }
      }
  
@@ -4929,7 +5384,7 @@
      public static class Wrap
          extends BaseWrapCipher
      {
-@@ -119,15 +135,17 @@
+@@ -118,15 +134,17 @@
              super(new DESedeWrapEngine());
          }
      }
@@ -4956,7 +5411,7 @@
  
    /**
       * DESede - the default for this is to generate a key in
-@@ -241,43 +259,45 @@
+@@ -240,43 +258,45 @@
          }
      }
  
@@ -4986,7 +5441,7 @@
 -
 -            try
 -            {
--                params = AlgorithmParameters.getInstance("DES", BouncyCastleProvider.PROVIDER_NAME);
+-                params = createParametersInstance("DES");
 -                params.init(new IvParameterSpec(iv));
 -            }
 -            catch (Exception e)
@@ -5008,30 +5463,30 @@
 +    //     {
 +    //         throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DES parameter generation.");
 +    //     }
-+    //
++
 +    //     protected AlgorithmParameters engineGenerateParameters()
 +    //     {
 +    //         byte[]  iv = new byte[8];
-+    //
++
 +    //         if (random == null)
 +    //         {
 +    //             random = new SecureRandom();
 +    //         }
-+    //
++
 +    //         random.nextBytes(iv);
-+    //
++
 +    //         AlgorithmParameters params;
-+    //
++
 +    //         try
 +    //         {
-+    //             params = AlgorithmParameters.getInstance("DES", BouncyCastleProvider.PROVIDER_NAME);
++    //             params = createParametersInstance("DES");
 +    //             params.init(new IvParameterSpec(iv));
 +    //         }
 +    //         catch (Exception e)
 +    //         {
 +    //             throw new RuntimeException(e.getMessage());
 +    //         }
-+    //
++
 +    //         return params;
 +    //     }
 +    // }
@@ -5039,7 +5494,7 @@
  
      static public class KeyFactory
          extends BaseSecretKeyFactory
-@@ -361,25 +381,37 @@
+@@ -360,25 +380,37 @@
          public void configure(ConfigurableProvider provider)
          {
              provider.addAlgorithm("Cipher.DESEDE", PREFIX + "$ECB");
@@ -5084,7 +5539,7 @@
                  provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC, "PBEWITHSHAAND3-KEYTRIPLEDES-CBC");
                  provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithSHAAnd2_KeyTripleDES_CBC, "PBEWITHSHAAND2-KEYTRIPLEDES-CBC");
                  provider.addAlgorithm("Alg.Alias.Cipher.PBEWITHSHA1ANDDESEDE", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC");
-@@ -388,31 +420,37 @@
+@@ -387,31 +419,37 @@
              }
  
              provider.addAlgorithm("KeyGenerator.DESEDE", PREFIX + "$KeyGenerator");
@@ -5140,10 +5595,10 @@
  
              provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAAND3-KEYTRIPLEDES-CBC", PREFIX + "$PBEWithSHAAndDES3KeyFactory");
              provider.addAlgorithm("SecretKeyFactory.PBEWITHSHAAND2-KEYTRIPLEDES-CBC", PREFIX + "$PBEWithSHAAndDES2KeyFactory");
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/RC2.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/RC2.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/RC2.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/RC2.java	2013-05-25 02:14:15.000000000 +0000
-@@ -12,24 +12,34 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/RC2.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/RC2.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/RC2.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/RC2.java	2015-04-09 13:10:16.000000000 +0000
+@@ -12,20 +12,28 @@
  
  import org.bouncycastle.asn1.ASN1Primitive;
  import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
@@ -5181,15 +5636,8 @@
 +// END android-removed
  import org.bouncycastle.jcajce.provider.symmetric.util.PBESecretKeyFactory;
  import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
--import org.bouncycastle.util.Arrays;
-+// BEGIN android-removed
-+// import org.bouncycastle.util.Arrays;
-+// END android-removed
- 
- public final class RC2
- {
-@@ -37,59 +47,61 @@
+ import org.bouncycastle.util.Arrays;
+@@ -36,59 +44,61 @@
      {
      }
  
@@ -5304,7 +5752,7 @@
  
      /**
       * PBEWithSHA1AndRC2
-@@ -175,17 +187,19 @@
+@@ -174,17 +184,19 @@
          }
      }
  
@@ -5335,7 +5783,7 @@
  
     /**
      * PBEWithMD5AndRC2
-@@ -199,247 +213,249 @@
+@@ -198,247 +210,249 @@
         }
     }
  
@@ -5375,7 +5823,7 @@
 -
 -                try
 -                {
--                    params = AlgorithmParameters.getInstance("RC2", BouncyCastleProvider.PROVIDER_NAME);
+-                    params = createParametersInstance("RC2");
 -                    params.init(new IvParameterSpec(iv));
 -                }
 -                catch (Exception e)
@@ -5387,7 +5835,7 @@
 -            {
 -                try
 -                {
--                    params = AlgorithmParameters.getInstance("RC2", BouncyCastleProvider.PROVIDER_NAME);
+-                    params = createParametersInstance("RC2");
 -                    params.init(spec);
 -                }
 -                catch (Exception e)
@@ -5585,7 +6033,7 @@
 +    //     extends BaseAlgorithmParameterGenerator
 +    // {
 +    //     RC2ParameterSpec spec = null;
-+    //
++    // 
 +    //     protected void engineInit(
 +    //         AlgorithmParameterSpec genParamSpec,
 +    //         SecureRandom random)
@@ -5596,28 +6044,28 @@
 +    //             spec = (RC2ParameterSpec)genParamSpec;
 +    //             return;
 +    //         }
-+    //
++    // 
 +    //         throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for RC2 parameter generation.");
 +    //     }
-+    //
++    // 
 +    //     protected AlgorithmParameters engineGenerateParameters()
 +    //     {
 +    //         AlgorithmParameters params;
-+    //
++    // 
 +    //         if (spec == null)
 +    //         {
 +    //             byte[] iv = new byte[8];
-+    //
++    // 
 +    //             if (random == null)
 +    //             {
 +    //                 random = new SecureRandom();
 +    //             }
-+    //
++    // 
 +    //             random.nextBytes(iv);
-+    //
++    // 
 +    //             try
 +    //             {
-+    //                 params = AlgorithmParameters.getInstance("RC2", BouncyCastleProvider.PROVIDER_NAME);
++    //                 params = createParametersInstance("RC2");
 +    //                 params.init(new IvParameterSpec(iv));
 +    //             }
 +    //             catch (Exception e)
@@ -5629,7 +6077,7 @@
 +    //         {
 +    //             try
 +    //             {
-+    //                 params = AlgorithmParameters.getInstance("RC2", BouncyCastleProvider.PROVIDER_NAME);
++    //                 params = createParametersInstance("RC2");
 +    //                 params.init(spec);
 +    //             }
 +    //             catch (Exception e)
@@ -5637,11 +6085,11 @@
 +    //                 throw new RuntimeException(e.getMessage());
 +    //             }
 +    //         }
-+    //
++    // 
 +    //         return params;
 +    //     }
 +    // }
-+    //
++    // 
 +    // public static class KeyGenerator
 +    //     extends BaseKeyGenerator
 +    // {
@@ -5650,7 +6098,7 @@
 +    //         super("RC2", 128, new CipherKeyGenerator());
 +    //     }
 +    // }
-+    //
++    // 
 +    // public static class AlgParams
 +    //     extends BaseAlgorithmParameters
 +    // {
@@ -5672,7 +6120,7 @@
 +    //         0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,
 +    //         0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab
 +    //     };
-+    //
++    // 
 +    //     private static final short[] ekb = {
 +    //         0x5d, 0xbe, 0x9b, 0x8b, 0x11, 0x99, 0x6e, 0x4d, 0x59, 0xf3, 0x85, 0xa6, 0x3f, 0xb7, 0x83, 0xc5,
 +    //         0xe4, 0x73, 0x6b, 0x3a, 0x68, 0x5a, 0xc0, 0x47, 0xa0, 0x64, 0x34, 0x0c, 0xf1, 0xd0, 0x52, 0xa5,
@@ -5691,15 +6139,15 @@
 +    //         0xbd, 0x22, 0xbf, 0x9f, 0x7e, 0xa9, 0x51, 0x4b, 0x4c, 0xfb, 0x02, 0xd3, 0x70, 0x86, 0x31, 0xe7,
 +    //         0x3b, 0x05, 0x03, 0x54, 0x60, 0x48, 0x65, 0x18, 0xd2, 0xcd, 0x5f, 0x32, 0x88, 0x0e, 0x35, 0xfd
 +    //     };
-+    //
++    // 
 +    //     private byte[] iv;
 +    //     private int parameterVersion = 58;
-+    //
++    // 
 +    //     protected byte[] engineGetEncoded()
 +    //     {
 +    //         return Arrays.clone(iv);
 +    //     }
-+    //
++    // 
 +    //     protected byte[] engineGetEncoded(
 +    //         String format)
 +    //         throws IOException
@@ -5715,15 +6163,15 @@
 +    //                 return new RC2CBCParameter(parameterVersion, engineGetEncoded()).getEncoded();
 +    //             }
 +    //         }
-+    //
++    // 
 +    //         if (format.equals("RAW"))
 +    //         {
 +    //             return engineGetEncoded();
 +    //         }
-+    //
++    // 
 +    //         return null;
 +    //     }
-+    //
++    // 
 +    //     protected AlgorithmParameterSpec localEngineGetParameterSpec(
 +    //         Class paramSpec)
 +    //         throws InvalidParameterSpecException
@@ -5742,15 +6190,15 @@
 +    //                 }
 +    //             }
 +    //         }
-+    //
++    // 
 +    //         if (paramSpec == IvParameterSpec.class)
 +    //         {
 +    //             return new IvParameterSpec(iv);
 +    //         }
-+    //
++    // 
 +    //         throw new InvalidParameterSpecException("unknown parameter spec passed to RC2 parameters object.");
 +    //     }
-+    //
++    // 
 +    //     protected void engineInit(
 +    //         AlgorithmParameterSpec paramSpec)
 +    //         throws InvalidParameterSpecException
@@ -5773,7 +6221,7 @@
 +    //                     parameterVersion = effKeyBits;
 +    //                 }
 +    //             }
-+    //
++    // 
 +    //             this.iv = ((RC2ParameterSpec)paramSpec).getIV();
 +    //         }
 +    //         else
@@ -5781,14 +6229,14 @@
 +    //             throw new InvalidParameterSpecException("IvParameterSpec or RC2ParameterSpec required to initialise a RC2 parameters algorithm parameters object");
 +    //         }
 +    //     }
-+    //
++    // 
 +    //     protected void engineInit(
 +    //         byte[] params)
 +    //         throws IOException
 +    //     {
 +    //         this.iv = Arrays.clone(params);
 +    //     }
-+    //
++    // 
 +    //     protected void engineInit(
 +    //         byte[] params,
 +    //         String format)
@@ -5797,26 +6245,26 @@
 +    //         if (this.isASN1FormatString(format))
 +    //         {
 +    //             RC2CBCParameter p = RC2CBCParameter.getInstance(ASN1Primitive.fromByteArray(params));
-+    //
++    // 
 +    //             if (p.getRC2ParameterVersion() != null)
 +    //             {
 +    //                 parameterVersion = p.getRC2ParameterVersion().intValue();
 +    //             }
-+    //
++    // 
 +    //             iv = p.getIV();
-+    //
++    // 
 +    //             return;
 +    //         }
-+    //
++    // 
 +    //         if (format.equals("RAW"))
 +    //         {
 +    //             engineInit(params);
 +    //             return;
 +    //         }
-+    //
++    // 
 +    //         throw new IOException("Unknown parameters format in IV parameters object");
 +    //     }
-+    //
++    // 
 +    //     protected String engineToString()
 +    //     {
 +    //         return "RC2 Parameters";
@@ -5826,7 +6274,7 @@
  
      public static class Mappings
          extends AlgorithmProvider
-@@ -453,32 +469,36 @@
+@@ -452,32 +466,36 @@
          public void configure(ConfigurableProvider provider)
          {
  
@@ -5884,7 +6332,7 @@
  
              provider.addAlgorithm("Alg.Alias.SecretKeyFactory." + PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, "PBEWITHMD5ANDRC2");
  
-@@ -486,14 +506,18 @@
+@@ -485,14 +503,18 @@
              provider.addAlgorithm("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.5", "PBEWITHSHAAND128BITRC2-CBC");
              provider.addAlgorithm("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.6", "PBEWITHSHAAND40BITRC2-CBC");
  
@@ -5905,9 +6353,9 @@
  
              provider.addAlgorithm("Alg.Alias.Cipher." + PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, "PBEWITHMD5ANDRC2");
  
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/SymmetricAlgorithmProvider.java	2013-12-12 00:35:05.000000000 +0000
 @@ -6,29 +6,31 @@
  abstract class SymmetricAlgorithmProvider
      extends AlgorithmProvider
@@ -5964,9 +6412,9 @@
 +    // END android-removed
  
  }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/Twofish.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/Twofish.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/Twofish.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/Twofish.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/Twofish.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/Twofish.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/Twofish.java	2013-12-12 00:35:05.000000000 +0000
 @@ -1,18 +1,26 @@
  package org.bouncycastle.jcajce.provider.symmetric;
  
@@ -6164,9 +6612,9 @@
          }
      }
  }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java	2015-04-09 13:10:16.000000000 +0000
 @@ -20,8 +20,10 @@
  import javax.crypto.ShortBufferException;
  import javax.crypto.spec.IvParameterSpec;
@@ -6591,9 +7039,9 @@
      }
  
      /*
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/BaseMac.java	2013-12-12 00:35:05.000000000 +0000
 @@ -16,8 +16,10 @@
  import org.bouncycastle.crypto.Mac;
  import org.bouncycastle.crypto.params.KeyParameter;
@@ -6624,10 +7072,10 @@
          else if (params == null)
          {
              param = new KeyParameter(key.getEncoded());
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java	2014-07-28 19:51:54.000000000 +0000
-@@ -14,8 +14,10 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/BaseStreamCipher.java	2015-04-09 13:10:16.000000000 +0000
+@@ -15,8 +15,10 @@
  import javax.crypto.ShortBufferException;
  import javax.crypto.spec.IvParameterSpec;
  import javax.crypto.spec.PBEParameterSpec;
@@ -6640,7 +7088,7 @@
  
  import org.bouncycastle.crypto.CipherParameters;
  import org.bouncycastle.crypto.DataLengthException;
-@@ -33,8 +35,10 @@
+@@ -34,8 +36,10 @@
      //
      private Class[]                 availableSpecs =
                                      {
@@ -6653,10 +7101,10 @@
                                          IvParameterSpec.class,
                                          PBEParameterSpec.class
                                      };
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java	2014-07-28 19:51:54.000000000 +0000
-@@ -22,8 +22,10 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/BaseWrapCipher.java	2015-04-09 13:10:16.000000000 +0000
+@@ -24,8 +24,10 @@
  import javax.crypto.ShortBufferException;
  import javax.crypto.spec.IvParameterSpec;
  import javax.crypto.spec.PBEParameterSpec;
@@ -6669,7 +7117,7 @@
  import javax.crypto.spec.SecretKeySpec;
  
  import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-@@ -46,8 +48,10 @@
+@@ -50,8 +52,10 @@
                                      {
                                          IvParameterSpec.class,
                                          PBEParameterSpec.class,
@@ -6682,7 +7130,7 @@
                                      };
  
      protected int                     pbeType = PKCS12;
-@@ -264,6 +268,8 @@
+@@ -276,6 +280,8 @@
          return null;
      }
  
@@ -6691,7 +7139,7 @@
      protected int engineDoFinal(
          byte[]  input,
          int     inputOffset,
-@@ -274,6 +280,7 @@
+@@ -286,6 +292,7 @@
      {
          return 0;
      }
@@ -6699,9 +7147,9 @@
  
      protected byte[] engineWrap(
          Key     key)
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java	2013-12-12 00:35:05.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/symmetric/util/PBE.java	2013-12-12 00:35:05.000000000 +0000
 @@ -7,13 +7,18 @@
  
  import org.bouncycastle.crypto.CipherParameters;
@@ -6888,9 +7336,9 @@
                  default:
                      throw new IllegalStateException("unknown digest scheme for PBE encryption.");
                  }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/util/DigestFactory.java bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/util/DigestFactory.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/provider/util/DigestFactory.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/provider/util/DigestFactory.java	2013-09-26 18:06:21.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/util/DigestFactory.java bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/util/DigestFactory.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/provider/util/DigestFactory.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/provider/util/DigestFactory.java	2013-09-26 18:06:21.000000000 +0000
 @@ -10,12 +10,17 @@
  import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
  import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
@@ -6961,9 +7409,9 @@
          }
          
          return null;
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/util/JcaJceUtils.java bcprov-jdk15on-151/org/bouncycastle/jcajce/util/JcaJceUtils.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jcajce/util/JcaJceUtils.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jcajce/util/JcaJceUtils.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/util/JcaJceUtils.java bcprov-jdk15on-152/org/bouncycastle/jcajce/util/JcaJceUtils.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jcajce/util/JcaJceUtils.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jcajce/util/JcaJceUtils.java	2014-07-28 19:51:54.000000000 +0000
 @@ -6,11 +6,15 @@
  import org.bouncycastle.asn1.ASN1Encodable;
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -7023,9 +7471,9 @@
          else
          {
              return digestAlgOID.getId();
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java bcprov-jdk15on-151/org/bouncycastle/jce/PKCS10CertificationRequest.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/PKCS10CertificationRequest.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java bcprov-jdk15on-152/org/bouncycastle/jce/PKCS10CertificationRequest.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/PKCS10CertificationRequest.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/PKCS10CertificationRequest.java	2014-07-28 19:51:54.000000000 +0000
 @@ -30,14 +30,18 @@
  import org.bouncycastle.asn1.ASN1Set;
  import org.bouncycastle.asn1.DERBitString;
@@ -7174,9 +7622,9 @@
          else
          {
              return digestAlgOID.getId();            
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/BouncyCastleProvider.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/BouncyCastleProvider.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/BouncyCastleProvider.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/BouncyCastleProvider.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/BouncyCastleProvider.java	2015-04-09 13:10:16.000000000 +0000
 @@ -64,15 +64,22 @@
  
      private static final String[] SYMMETRIC_MACS =
@@ -7336,9 +7784,9 @@
      }
  
      private void loadAlgorithms(String packageName, String[] names)
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/CertBlacklist.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/CertBlacklist.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/CertBlacklist.java	1970-01-01 00:00:00.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/CertBlacklist.java	2014-05-05 17:28:58.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/CertBlacklist.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/CertBlacklist.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/CertBlacklist.java	1970-01-01 00:00:00.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/CertBlacklist.java	2014-05-05 17:28:58.000000000 +0000
 @@ -0,0 +1,228 @@
 +/*
 + * Copyright (C) 2012 The Android Open Source Project
@@ -7568,117 +8016,35 @@
 +    }
 +
 +}
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java	2014-07-28 19:51:54.000000000 +0000
-@@ -61,18 +61,24 @@
- import org.bouncycastle.asn1.x509.PolicyInformation;
- import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
- import org.bouncycastle.asn1.x509.X509Extension;
--import org.bouncycastle.jce.X509LDAPCertStoreParameters;
-+// BEGIN android-removed
-+// import org.bouncycastle.jce.X509LDAPCertStoreParameters;
-+// END android-removed
- import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
- import org.bouncycastle.util.Integers;
- import org.bouncycastle.util.Selector;
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/CertPathValidatorUtilities.java	2015-04-09 13:10:16.000000000 +0000
+@@ -35,6 +35,7 @@
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
++import javax.security.auth.x500.X500Principal;
+ 
+ import org.bouncycastle.asn1.ASN1Encodable;
+ import org.bouncycastle.asn1.ASN1Enumerated;
+@@ -73,7 +74,9 @@
+ import org.bouncycastle.util.Store;
  import org.bouncycastle.util.StoreException;
- import org.bouncycastle.x509.ExtendedPKIXBuilderParameters;
- import org.bouncycastle.x509.ExtendedPKIXParameters;
--import org.bouncycastle.x509.X509AttributeCertStoreSelector;
-+// BEGIN android-removed
-+// import org.bouncycastle.x509.X509AttributeCertStoreSelector;
-+// END android-removed
  import org.bouncycastle.x509.X509AttributeCertificate;
- import org.bouncycastle.x509.X509CRLStoreSelector;
- import org.bouncycastle.x509.X509CertStoreSelector;
--import org.bouncycastle.x509.X509Store;
+-import org.bouncycastle.x509.extension.X509ExtensionUtil;
 +// BEGIN android-removed
-+// import org.bouncycastle.x509.X509Store;
++// import org.bouncycastle.x509.extension.X509ExtensionUtil;
 +// END android-removed
  
- public class CertPathValidatorUtilities
+ class CertPathValidatorUtilities
  {
-@@ -656,38 +662,40 @@
-         {
-             try
-             {
--                if (location.startsWith("ldap://"))
--                {
--                    // ldap://directory.d-trust.net/CN=D-TRUST
--                    // Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE
--                    // skip "ldap://"
--                    location = location.substring(7);
--                    // after first / baseDN starts
--                    String base = null;
--                    String url = null;
--                    if (location.indexOf("/") != -1)
--                    {
--                        base = location.substring(location.indexOf("/"));
--                        // URL
--                        url = "ldap://"
--                            + location.substring(0, location.indexOf("/"));
--                    }
--                    else
--                    {
--                        url = "ldap://" + location;
--                    }
--                    // use all purpose parameters
--                    X509LDAPCertStoreParameters params = new X509LDAPCertStoreParameters.Builder(
--                        url, base).build();
--                    pkixParams.addAdditionalStore(X509Store.getInstance(
--                        "CERTIFICATE/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
--                    pkixParams.addAdditionalStore(X509Store.getInstance(
--                        "CRL/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
--                    pkixParams.addAdditionalStore(X509Store.getInstance(
--                        "ATTRIBUTECERTIFICATE/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
--                    pkixParams.addAdditionalStore(X509Store.getInstance(
--                        "CERTIFICATEPAIR/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
--                }
-+                // BEGIN android-removed
-+                // if (location.startsWith("ldap://"))
-+                // {
-+                //     // ldap://directory.d-trust.net/CN=D-TRUST
-+                //     // Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE
-+                //     // skip "ldap://"
-+                //     location = location.substring(7);
-+                //     // after first / baseDN starts
-+                //     String base = null;
-+                //     String url = null;
-+                //     if (location.indexOf("/") != -1)
-+                //     {
-+                //         base = location.substring(location.indexOf("/"));
-+                //         // URL
-+                //         url = "ldap://"
-+                //             + location.substring(0, location.indexOf("/"));
-+                //     }
-+                //     else
-+                //     {
-+                //         url = "ldap://" + location;
-+                //     }
-+                //     // use all purpose parameters
-+                //     X509LDAPCertStoreParameters params = new X509LDAPCertStoreParameters.Builder(
-+                //         url, base).build();
-+                //     pkixParams.addAdditionalStore(X509Store.getInstance(
-+                //         "CERTIFICATE/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
-+                //     pkixParams.addAdditionalStore(X509Store.getInstance(
-+                //         "CRL/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
-+                //     pkixParams.addAdditionalStore(X509Store.getInstance(
-+                //         "ATTRIBUTECERTIFICATE/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
-+                //     pkixParams.addAdditionalStore(X509Store.getInstance(
-+                //         "CERTIFICATEPAIR/LDAP", params, BouncyCastleProvider.PROVIDER_NAME));
-+                // }
-+                // END android-removed
-             }
-             catch (Exception e)
-             {
-@@ -720,20 +728,22 @@
+@@ -653,20 +656,22 @@
          {
              Object obj = iter.next();
  
--            if (obj instanceof X509Store)
+-            if (obj instanceof Store)
 -            {
--                X509Store certStore = (X509Store)obj;
+-                Store certStore = (Store)obj;
 -                try
 -                {
 -                    certs.addAll(certStore.getMatches(certSelect));
@@ -7709,72 +8075,48 @@
              {
                  CertStore certStore = (CertStore)obj;
  
-@@ -752,33 +762,35 @@
-         return certs;
-     }
+@@ -715,7 +720,14 @@
  
--    protected static Collection findCertificates(X509AttributeCertStoreSelector certSelect,
--                                                 List certStores)
--        throws AnnotatedException
--    {
--        Set certs = new HashSet();
--        Iterator iter = certStores.iterator();
+                         for (int j = 0; j < genNames.length; j++)
+                         {
+-                            PKIXCRLStore store = namedCRLStoreMap.get(genNames[i]);
++                            // BEGIN android-removed
++                            // PKIXCRLStore store = namedCRLStoreMap.get(genNames[i]);
++                            // END android-removed
++                            // BEGIN android-added
++                            // Seems like a bug, unless there should be a guarantee that j < i,
++                            // However, it's breaking the tests.
++                            PKIXCRLStore store = namedCRLStoreMap.get(genNames[j]);
++                            // END android-added
+                             if (store != null)
+                             {
+                                 stores.add(store);
+@@ -888,8 +900,20 @@
+             {
+                 return;
+             }
 -
--        while (iter.hasNext())
--        {
--            Object obj = iter.next();
--
--            if (obj instanceof X509Store)
--            {
--                X509Store certStore = (X509Store)obj;
--                try
--                {
--                    certs.addAll(certStore.getMatches(certSelect));
--                }
--                catch (StoreException e)
--                {
--                    throw new AnnotatedException(
--                            "Problem while picking certificates from X.509 store.", e);
--                }
--            }
--        }
--        return certs;
--    }
-+    // BEGIN android-removed
-+    // protected static Collection findCertificates(X509AttributeCertStoreSelector certSelect,
-+    //                                              List certStores)
-+    //     throws AnnotatedException
-+    // {
-+    //     Set certs = new HashSet();
-+    //     Iterator iter = certStores.iterator();
-+    //
-+    //     while (iter.hasNext())
-+    //     {
-+    //         Object obj = iter.next();
-+    //
-+    //         if (obj instanceof X509Store)
-+    //         {
-+    //             X509Store certStore = (X509Store)obj;
-+    //             try
-+    //             {
-+    //                 certs.addAll(certStore.getMatches(certSelect));
-+    //             }
-+    //             catch (StoreException e)
-+    //             {
-+    //                 throw new AnnotatedException(
-+    //                         "Problem while picking certificates from X.509 store.", e);
-+    //             }
-+    //         }
-+    //     }
-+    //     return certs;
-+    // }
-+    // END android-removed
+-            X500Name certIssuer = X500Name.getInstance(crl_entry.getCertificateIssuer().getEncoded());
++            // BEGIN android-removed
++            // X500Name certIssuer = X500Name.getInstance(crl_entry.getCertificateIssuer().getEncoded());
++            // END android-removed
++            // BEGIN android-added
++            // The original code throws null pointer exception for OpenSSLX509CRL,
++            // which uses the implementation for getCertificateIssuer() in X509CRL, method
++            // whose reference implementation has the following JavaDoc: "If the certificate
++            // issuer is also the CRL issuer, this method returns null."
++            X500Name certIssuer = null;
++            X500Principal certificateIssuerPrincipal = crl_entry.getCertificateIssuer();
++            if (certificateIssuerPrincipal != null) {
++                certIssuer = X500Name.getInstance(certificateIssuerPrincipal.getEncoded());
++            }
++            // END android-added
  
-     protected static void addAdditionalStoresFromCRLDistributionPoint(
-         CRLDistPoint crldp, ExtendedPKIXParameters pkixParams)
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEECPrivateKey.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEECPrivateKey.java	2014-07-28 19:51:54.000000000 +0000
+             if (certIssuer == null)
+             {
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/JCEECPrivateKey.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/JCEECPrivateKey.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/JCEECPrivateKey.java	2014-07-28 19:51:54.000000000 +0000
 @@ -19,8 +19,10 @@
  import org.bouncycastle.asn1.ASN1Sequence;
  import org.bouncycastle.asn1.DERBitString;
@@ -7846,9 +8188,9 @@
              {
  
                  info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.toASN1Primitive()), keyStructure.toASN1Primitive());
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEECPublicKey.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEECPublicKey.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/JCEECPublicKey.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/JCEECPublicKey.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/JCEECPublicKey.java	2014-07-28 19:51:54.000000000 +0000
 @@ -18,9 +18,11 @@
  import org.bouncycastle.asn1.DERBitString;
  import org.bouncycastle.asn1.DERNull;
@@ -8107,320 +8449,21 @@
          {
              if (ecSpec instanceof ECNamedCurveSpec)
              {
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEStreamCipher.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/JCEStreamCipher.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/JCEStreamCipher.java	2014-07-28 19:51:54.000000000 +0000
-@@ -23,19 +23,23 @@
- import javax.crypto.ShortBufferException;
- import javax.crypto.spec.IvParameterSpec;
- import javax.crypto.spec.PBEParameterSpec;
--import javax.crypto.spec.RC2ParameterSpec;
--import javax.crypto.spec.RC5ParameterSpec;
-+// BEGIN android-removed
-+// import javax.crypto.spec.RC2ParameterSpec;
-+// import javax.crypto.spec.RC5ParameterSpec;
-+// END android-removed
- import javax.crypto.spec.SecretKeySpec;
- 
- import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
- import org.bouncycastle.crypto.CipherParameters;
- import org.bouncycastle.crypto.DataLengthException;
- import org.bouncycastle.crypto.StreamCipher;
--import org.bouncycastle.crypto.engines.BlowfishEngine;
--import org.bouncycastle.crypto.engines.DESEngine;
--import org.bouncycastle.crypto.engines.DESedeEngine;
--import org.bouncycastle.crypto.engines.SkipjackEngine;
--import org.bouncycastle.crypto.engines.TwofishEngine;
-+// BEGIN android-removed
-+// import org.bouncycastle.crypto.engines.BlowfishEngine;
-+// import org.bouncycastle.crypto.engines.DESEngine;
-+// import org.bouncycastle.crypto.engines.DESedeEngine;
-+// import org.bouncycastle.crypto.engines.SkipjackEngine;
-+// import org.bouncycastle.crypto.engines.TwofishEngine;
-+// END android-removed
- import org.bouncycastle.crypto.modes.CFBBlockCipher;
- import org.bouncycastle.crypto.modes.OFBBlockCipher;
- import org.bouncycastle.crypto.params.KeyParameter;
-@@ -52,8 +56,10 @@
-     //
-     private Class[]                 availableSpecs =
-                                     {
--                                        RC2ParameterSpec.class,
--                                        RC5ParameterSpec.class,
-+                                        // BEGIN android-removed
-+                                        // RC2ParameterSpec.class,
-+                                        // RC5ParameterSpec.class,
-+                                        // END android-removed
-                                         IvParameterSpec.class,
-                                         PBEParameterSpec.class
-                                     };
-@@ -479,123 +485,125 @@
-      * The ciphers that inherit from us.
-      */
- 
--    /**
--     * DES
--     */
--    static public class DES_CFB8
--        extends JCEStreamCipher
--    {
--        public DES_CFB8()
--        {
--            super(new CFBBlockCipher(new DESEngine(), 8), 64);
--        }
--    }
--
--    /**
--     * DESede
--     */
--    static public class DESede_CFB8
--        extends JCEStreamCipher
--    {
--        public DESede_CFB8()
--        {
--            super(new CFBBlockCipher(new DESedeEngine(), 8), 64);
--        }
--    }
--
--    /**
--     * SKIPJACK
--     */
--    static public class Skipjack_CFB8
--        extends JCEStreamCipher
--    {
--        public Skipjack_CFB8()
--        {
--            super(new CFBBlockCipher(new SkipjackEngine(), 8), 64);
--        }
--    }
--
--    /**
--     * Blowfish
--     */
--    static public class Blowfish_CFB8
--        extends JCEStreamCipher
--    {
--        public Blowfish_CFB8()
--        {
--            super(new CFBBlockCipher(new BlowfishEngine(), 8), 64);
--        }
--    }
--
--    /**
--     * Twofish
--     */
--    static public class Twofish_CFB8
--        extends JCEStreamCipher
--    {
--        public Twofish_CFB8()
--        {
--            super(new CFBBlockCipher(new TwofishEngine(), 8), 128);
--        }
--    }
--
--    /**
--     * DES
--     */
--    static public class DES_OFB8
--        extends JCEStreamCipher
--    {
--        public DES_OFB8()
--        {
--            super(new OFBBlockCipher(new DESEngine(), 8), 64);
--        }
--    }
--
--    /**
--     * DESede
--     */
--    static public class DESede_OFB8
--        extends JCEStreamCipher
--    {
--        public DESede_OFB8()
--        {
--            super(new OFBBlockCipher(new DESedeEngine(), 8), 64);
--        }
--    }
--
--    /**
--     * SKIPJACK
--     */
--    static public class Skipjack_OFB8
--        extends JCEStreamCipher
--    {
--        public Skipjack_OFB8()
--        {
--            super(new OFBBlockCipher(new SkipjackEngine(), 8), 64);
--        }
--    }
--
--    /**
--     * Blowfish
--     */
--    static public class Blowfish_OFB8
--        extends JCEStreamCipher
--    {
--        public Blowfish_OFB8()
--        {
--            super(new OFBBlockCipher(new BlowfishEngine(), 8), 64);
--        }
--    }
--
--    /**
--     * Twofish
--     */
--    static public class Twofish_OFB8
--        extends JCEStreamCipher
--    {
--        public Twofish_OFB8()
--        {
--            super(new OFBBlockCipher(new TwofishEngine(), 8), 128);
--        }
--    }
-+    // BEGIN android-removed
-+    // /**
-+    //  * DES
-+    //  */
-+    // static public class DES_CFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public DES_CFB8()
-+    //     {
-+    //         super(new CFBBlockCipher(new DESEngine(), 8), 64);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * DESede
-+    //  */
-+    // static public class DESede_CFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public DESede_CFB8()
-+    //     {
-+    //         super(new CFBBlockCipher(new DESedeEngine(), 8), 64);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * SKIPJACK
-+    //  */
-+    // static public class Skipjack_CFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public Skipjack_CFB8()
-+    //     {
-+    //         super(new CFBBlockCipher(new SkipjackEngine(), 8), 64);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * Blowfish
-+    //  */
-+    // static public class Blowfish_CFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public Blowfish_CFB8()
-+    //     {
-+    //         super(new CFBBlockCipher(new BlowfishEngine(), 8), 64);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * Twofish
-+    //  */
-+    // static public class Twofish_CFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public Twofish_CFB8()
-+    //     {
-+    //         super(new CFBBlockCipher(new TwofishEngine(), 8), 128);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * DES
-+    //  */
-+    // static public class DES_OFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public DES_OFB8()
-+    //     {
-+    //         super(new OFBBlockCipher(new DESEngine(), 8), 64);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * DESede
-+    //  */
-+    // static public class DESede_OFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public DESede_OFB8()
-+    //     {
-+    //         super(new OFBBlockCipher(new DESedeEngine(), 8), 64);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * SKIPJACK
-+    //  */
-+    // static public class Skipjack_OFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public Skipjack_OFB8()
-+    //     {
-+    //         super(new OFBBlockCipher(new SkipjackEngine(), 8), 64);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * Blowfish
-+    //  */
-+    // static public class Blowfish_OFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public Blowfish_OFB8()
-+    //     {
-+    //         super(new OFBBlockCipher(new BlowfishEngine(), 8), 64);
-+    //     }
-+    // }
-+    //
-+    // /**
-+    //  * Twofish
-+    //  */
-+    // static public class Twofish_OFB8
-+    //     extends JCEStreamCipher
-+    // {
-+    //     public Twofish_OFB8()
-+    //     {
-+    //         super(new OFBBlockCipher(new TwofishEngine(), 8), 128);
-+    //     }
-+    // }
-+    // END android-removed
- }
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/PKIXCRLUtil.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/PKIXCRLUtil.java	2013-12-12 00:35:05.000000000 +0000
-@@ -15,7 +15,9 @@
- import org.bouncycastle.util.StoreException;
- import org.bouncycastle.x509.ExtendedPKIXParameters;
- import org.bouncycastle.x509.X509CRLStoreSelector;
--import org.bouncycastle.x509.X509Store;
-+// BEGIN android-removed
-+// import org.bouncycastle.x509.X509Store;
-+// END android-removed
- 
- public class PKIXCRLUtil
- {
-@@ -114,22 +116,24 @@
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/PKIXCRLUtil.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/PKIXCRLUtil.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/PKIXCRLUtil.java	2015-04-09 13:10:16.000000000 +0000
+@@ -88,22 +88,24 @@
          {
              Object obj = iter.next();
  
--            if (obj instanceof X509Store)
+-            if (obj instanceof Store)
 -            {
--                X509Store store = (X509Store)obj;
--
+-                Store store = (Store)obj;
++            // BEGIN android-removed
++	    // if (obj instanceof Store)
++            // {
++            //     Store store = (Store)obj;
+ 
 -                try
 -                {
 -                    crls.addAll(store.getMatches(crlSelect));
@@ -8433,11 +8476,6 @@
 -                }
 -            }
 -            else
-+            // BEGIN android-removed
-+            // if (obj instanceof X509Store)
-+            // {
-+            //     X509Store store = (X509Store)obj;
-+            //
 +            //     try
 +            //     {
 +            //         crls.addAll(store.getMatches(crlSelect));
@@ -8454,9 +8492,9 @@
              {
                  CertStore store = (CertStore)obj;
  
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpi.java	2015-04-09 13:10:16.000000000 +0000
 @@ -1,5 +1,8 @@
  package org.bouncycastle.jce.provider;
  
@@ -8466,10 +8504,10 @@
  import java.security.InvalidAlgorithmParameterException;
  import java.security.PublicKey;
  import java.security.cert.CertPath;
-@@ -33,6 +36,11 @@
- public class PKIXCertPathValidatorSpi
-         extends CertPathValidatorSpi
- {
+@@ -41,6 +44,11 @@
+     public PKIXCertPathValidatorSpi()
+     {
+     }
 +    // BEGIN android-added
 +    private static class NoPreloadHolder {
 +        private final static CertBlacklist blacklist = new CertBlacklist();
@@ -8478,7 +8516,7 @@
  
      public CertPathValidatorResult engineValidate(
              CertPath certPath,
-@@ -75,6 +83,22 @@
+@@ -98,6 +106,22 @@
          {
              throw new CertPathValidatorException("Certification path is empty.", null, certPath, 0);
          }
@@ -8501,7 +8539,7 @@
  
          //
          // (b)
-@@ -251,6 +275,15 @@
+@@ -277,6 +301,15 @@
  
          for (index = certs.size() - 1; index >= 0; index--)
          {
@@ -8517,9 +8555,9 @@
              // try
              // {
              //
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/X509CertificateObject.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/X509CertificateObject.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/X509CertificateObject.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/X509CertificateObject.java	2013-01-31 02:26:40.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/X509CertificateObject.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/X509CertificateObject.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/X509CertificateObject.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/X509CertificateObject.java	2013-01-31 02:26:40.000000000 +0000
 @@ -57,6 +57,9 @@
  import org.bouncycastle.asn1.x509.Extensions;
  import org.bouncycastle.asn1.x509.GeneralName;
@@ -8563,9 +8601,9 @@
                      break;
                  case GeneralName.dNSName:
                  case GeneralName.rfc822Name:
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java bcprov-jdk15on-151/org/bouncycastle/jce/provider/X509SignatureUtil.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/jce/provider/X509SignatureUtil.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java bcprov-jdk15on-152/org/bouncycastle/jce/provider/X509SignatureUtil.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/jce/provider/X509SignatureUtil.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/jce/provider/X509SignatureUtil.java	2014-07-28 19:51:54.000000000 +0000
 @@ -14,7 +14,9 @@
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
  import org.bouncycastle.asn1.ASN1Sequence;
@@ -8639,9 +8677,9 @@
          else
          {
              return digestAlgOID.getId();            
-diff -Naur bcprov-jdk15on-151.orig/org/bouncycastle/x509/X509Util.java bcprov-jdk15on-151/org/bouncycastle/x509/X509Util.java
---- bcprov-jdk15on-151.orig/org/bouncycastle/x509/X509Util.java	2014-07-26 04:17:24.000000000 +0000
-+++ bcprov-jdk15on-151/org/bouncycastle/x509/X509Util.java	2014-07-28 19:51:54.000000000 +0000
+diff -Naur bcprov-jdk15on-152.orig/org/bouncycastle/x509/X509Util.java bcprov-jdk15on-152/org/bouncycastle/x509/X509Util.java
+--- bcprov-jdk15on-152.orig/org/bouncycastle/x509/X509Util.java	2015-03-01 12:03:02.000000000 +0000
++++ bcprov-jdk15on-152/org/bouncycastle/x509/X509Util.java	2014-07-28 19:51:54.000000000 +0000
 @@ -25,12 +25,16 @@
  import org.bouncycastle.asn1.ASN1Integer;
  import org.bouncycastle.asn1.ASN1ObjectIdentifier;