Home | History | Annotate | Download | only in provider
      1 package org.bouncycastle.jce.provider;
      2 
      3 import java.io.IOException;
      4 import java.security.AccessController;
      5 import java.security.PrivateKey;
      6 import java.security.PrivilegedAction;
      7 import java.security.Provider;
      8 import java.security.PublicKey;
      9 import java.util.HashMap;
     10 import java.util.Map;
     11 
     12 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
     13 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
     14 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
     15 import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
     16 import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
     17 import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
     18 import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
     19 
     20 /**
     21  * To add the provider at runtime use:
     22  * <pre>
     23  * import java.security.Security;
     24  * import org.bouncycastle.jce.provider.BouncyCastleProvider;
     25  *
     26  * Security.addProvider(new BouncyCastleProvider());
     27  * </pre>
     28  * The provider can also be configured as part of your environment via
     29  * static registration by adding an entry to the java.security properties
     30  * file (found in $JAVA_HOME/jre/lib/security/java.security, where
     31  * $JAVA_HOME is the location of your JDK/JRE distribution). You'll find
     32  * detailed instructions in the file but basically it comes down to adding
     33  * a line:
     34  * <pre>
     35  * <code>
     36  *    security.provider.&lt;n&gt;=org.bouncycastle.jce.provider.BouncyCastleProvider
     37  * </code>
     38  * </pre>
     39  * Where &lt;n&gt; is the preference you want the provider at (1 being the
     40  * most preferred).
     41  * <p>Note: JCE algorithm names should be upper-case only so the case insensitive
     42  * test for getInstance works.
     43  */
     44 public final class BouncyCastleProvider extends Provider
     45     implements ConfigurableProvider
     46 {
     47     private static String info = "BouncyCastle Security Provider v1.50";
     48 
     49     public static final String PROVIDER_NAME = "BC";
     50 
     51     public static final ProviderConfiguration CONFIGURATION = new BouncyCastleProviderConfiguration();
     52 
     53     private static final Map keyInfoConverters = new HashMap();
     54 
     55     /*
     56      * Configurable symmetric ciphers
     57      */
     58     private static final String SYMMETRIC_PACKAGE = "org.bouncycastle.jcajce.provider.symmetric.";
     59 
     60     private static final String[] SYMMETRIC_GENERIC =
     61     {
     62         "PBEPBKDF2", "PBEPKCS12"
     63     };
     64 
     65     private static final String[] SYMMETRIC_MACS =
     66     {
     67         // BEGIN android-removed
     68         // "SipHash"
     69         // END android-removed
     70     };
     71 
     72     private static final String[] SYMMETRIC_CIPHERS =
     73     {
     74         // BEGIN android-removed
     75         // "AES", "ARC4", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede",
     76         // "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5",
     77         // "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "TEA", "Twofish", "Threefish",
     78         // "VMPC", "VMPCKSA3", "XTEA", "XSalsa20"
     79         // END android-removed
     80         // BEGIN android-added
     81         "AES", "ARC4", "Blowfish", "DES", "DESede", "RC2", "Twofish",
     82         // END android-added
     83     };
     84 
     85      /*
     86      * Configurable asymmetric ciphers
     87      */
     88     private static final String ASYMMETRIC_PACKAGE = "org.bouncycastle.jcajce.provider.asymmetric.";
     89 
     90     // this one is required for GNU class path - it needs to be loaded first as the
     91     // later ones configure it.
     92     private static final String[] ASYMMETRIC_GENERIC =
     93     {
     94         // BEGIN android-removed
     95         // "X509", "IES"
     96         // END android-removed
     97         // BEGIN android-added
     98         "X509"
     99         // END android-added
    100     };
    101 
    102     private static final String[] ASYMMETRIC_CIPHERS =
    103     {
    104         // BEGIN android-removed
    105         // "DSA", "DH", "EC", "RSA", "GOST", "ECGOST", "ElGamal", "DSTU4145"
    106         // END android-removed
    107         // BEGIN android-added
    108         "DSA", "DH", "EC", "RSA",
    109         // END android-added
    110     };
    111 
    112     /*
    113      * Configurable digests
    114      */
    115     private static final String DIGEST_PACKAGE = "org.bouncycastle.jcajce.provider.digest.";
    116     private static final String[] DIGESTS =
    117     {
    118         // BEGIN android-removed
    119         // "GOST3411", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool"
    120         // END android-removed
    121         // BEGIN android-added
    122         "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512",
    123         // END android-added
    124     };
    125 
    126     /*
    127      * Configurable keystores
    128      */
    129     private static final String KEYSTORE_PACKAGE = "org.bouncycastle.jcajce.provider.keystore.";
    130     private static final String[] KEYSTORES =
    131     {
    132         "BC", "PKCS12"
    133     };
    134 
    135     /**
    136      * Construct a new provider.  This should only be required when
    137      * using runtime registration of the provider using the
    138      * <code>Security.addProvider()</code> mechanism.
    139      */
    140     public BouncyCastleProvider()
    141     {
    142         super(PROVIDER_NAME, 1.50, info);
    143 
    144         AccessController.doPrivileged(new PrivilegedAction()
    145         {
    146             public Object run()
    147             {
    148                 setup();
    149                 return null;
    150             }
    151         });
    152     }
    153 
    154     private void setup()
    155     {
    156         loadAlgorithms(DIGEST_PACKAGE, DIGESTS);
    157 
    158         loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_GENERIC);
    159 
    160         loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_MACS);
    161 
    162         loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_CIPHERS);
    163 
    164         loadAlgorithms(ASYMMETRIC_PACKAGE, ASYMMETRIC_GENERIC);
    165 
    166         loadAlgorithms(ASYMMETRIC_PACKAGE, ASYMMETRIC_CIPHERS);
    167 
    168         loadAlgorithms(KEYSTORE_PACKAGE, KEYSTORES);
    169 
    170         // BEGIN android-removed
    171         // //
    172         // // X509Store
    173         // //
    174         // put("X509Store.CERTIFICATE/COLLECTION", "org.bouncycastle.jce.provider.X509StoreCertCollection");
    175         // put("X509Store.ATTRIBUTECERTIFICATE/COLLECTION", "org.bouncycastle.jce.provider.X509StoreAttrCertCollection");
    176         // put("X509Store.CRL/COLLECTION", "org.bouncycastle.jce.provider.X509StoreCRLCollection");
    177         // put("X509Store.CERTIFICATEPAIR/COLLECTION", "org.bouncycastle.jce.provider.X509StoreCertPairCollection");
    178         //
    179         // put("X509Store.CERTIFICATE/LDAP", "org.bouncycastle.jce.provider.X509StoreLDAPCerts");
    180         // put("X509Store.CRL/LDAP", "org.bouncycastle.jce.provider.X509StoreLDAPCRLs");
    181         // put("X509Store.ATTRIBUTECERTIFICATE/LDAP", "org.bouncycastle.jce.provider.X509StoreLDAPAttrCerts");
    182         // put("X509Store.CERTIFICATEPAIR/LDAP", "org.bouncycastle.jce.provider.X509StoreLDAPCertPairs");
    183         //
    184         // //
    185         // // X509StreamParser
    186         // //
    187         // put("X509StreamParser.CERTIFICATE", "org.bouncycastle.jce.provider.X509CertParser");
    188         // put("X509StreamParser.ATTRIBUTECERTIFICATE", "org.bouncycastle.jce.provider.X509AttrCertParser");
    189         // put("X509StreamParser.CRL", "org.bouncycastle.jce.provider.X509CRLParser");
    190         // put("X509StreamParser.CERTIFICATEPAIR", "org.bouncycastle.jce.provider.X509CertPairParser");
    191         //
    192         // //
    193         // // cipher engines
    194         // //
    195         // put("Cipher.BROKENPBEWITHMD5ANDDES", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithMD5AndDES");
    196         //
    197         // put("Cipher.BROKENPBEWITHSHA1ANDDES", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithSHA1AndDES");
    198         //
    199         //
    200         // put("Cipher.OLDPBEWITHSHAANDTWOFISH-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$OldPBEWithSHAAndTwofish");
    201         //
    202         // // Certification Path API
    203         // put("CertPathValidator.RFC3281", "org.bouncycastle.jce.provider.PKIXAttrCertPathValidatorSpi");
    204         // put("CertPathBuilder.RFC3281", "org.bouncycastle.jce.provider.PKIXAttrCertPathBuilderSpi");
    205         // put("CertPathValidator.RFC3280", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi");
    206         // put("CertPathBuilder.RFC3280", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi");
    207         // END android-removed
    208         put("CertPathValidator.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi");
    209         put("CertPathBuilder.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi");
    210         put("CertStore.Collection", "org.bouncycastle.jce.provider.CertStoreCollectionSpi");
    211         // BEGIN android-removed
    212         // put("CertStore.LDAP", "org.bouncycastle.jce.provider.X509LDAPCertStoreSpi");
    213         // put("CertStore.Multi", "org.bouncycastle.jce.provider.MultiCertStoreSpi");
    214         // put("Alg.Alias.CertStore.X509LDAP", "LDAP");
    215         // END android-removed
    216     }
    217 
    218     private void loadAlgorithms(String packageName, String[] names)
    219     {
    220         for (int i = 0; i != names.length; i++)
    221         {
    222             Class clazz = null;
    223             try
    224             {
    225                 ClassLoader loader = this.getClass().getClassLoader();
    226 
    227                 if (loader != null)
    228                 {
    229                     clazz = loader.loadClass(packageName + names[i] + "$Mappings");
    230                 }
    231                 else
    232                 {
    233                     clazz = Class.forName(packageName + names[i] + "$Mappings");
    234                 }
    235             }
    236             catch (ClassNotFoundException e)
    237             {
    238                 // ignore
    239             }
    240 
    241             if (clazz != null)
    242             {
    243                 try
    244                 {
    245                     ((AlgorithmProvider)clazz.newInstance()).configure(this);
    246                 }
    247                 catch (Exception e)
    248                 {   // this should never ever happen!!
    249                     throw new InternalError("cannot create instance of "
    250                         + packageName + names[i] + "$Mappings : " + e);
    251                 }
    252             }
    253         }
    254     }
    255 
    256     public void setParameter(String parameterName, Object parameter)
    257     {
    258         synchronized (CONFIGURATION)
    259         {
    260             ((BouncyCastleProviderConfiguration)CONFIGURATION).setParameter(parameterName, parameter);
    261         }
    262     }
    263 
    264     public boolean hasAlgorithm(String type, String name)
    265     {
    266         return containsKey(type + "." + name) || containsKey("Alg.Alias." + type + "." + name);
    267     }
    268 
    269     public void addAlgorithm(String key, String value)
    270     {
    271         if (containsKey(key))
    272         {
    273             throw new IllegalStateException("duplicate provider key (" + key + ") found");
    274         }
    275 
    276         put(key, value);
    277     }
    278 
    279     public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter)
    280     {
    281         keyInfoConverters.put(oid, keyInfoConverter);
    282     }
    283 
    284     public static PublicKey getPublicKey(SubjectPublicKeyInfo publicKeyInfo)
    285         throws IOException
    286     {
    287         AsymmetricKeyInfoConverter converter = (AsymmetricKeyInfoConverter)keyInfoConverters.get(publicKeyInfo.getAlgorithm().getAlgorithm());
    288 
    289         if (converter == null)
    290         {
    291             return null;
    292         }
    293 
    294         return converter.generatePublic(publicKeyInfo);
    295     }
    296 
    297     public static PrivateKey getPrivateKey(PrivateKeyInfo privateKeyInfo)
    298         throws IOException
    299     {
    300         AsymmetricKeyInfoConverter converter = (AsymmetricKeyInfoConverter)keyInfoConverters.get(privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm());
    301 
    302         if (converter == null)
    303         {
    304             return null;
    305         }
    306 
    307         return converter.generatePrivate(privateKeyInfo);
    308     }
    309 }
    310