• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.54";
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", "SM4", "TEA", "Twofish", "Threefish",
78         // "VMPC", "VMPCKSA3", "XTEA", "XSalsa20", "OpenSSLPBKDF"
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", "Keccak", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224",
120         // "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool", "Blake2b"
121         // END android-removed
122         // BEGIN android-added
123         "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512",
124         // END android-added
125     };
126 
127     /*
128      * Configurable keystores
129      */
130     private static final String KEYSTORE_PACKAGE = "org.bouncycastle.jcajce.provider.keystore.";
131     private static final String[] KEYSTORES =
132     {
133         "BC", "PKCS12"
134     };
135 
136     /**
137      * Construct a new provider.  This should only be required when
138      * using runtime registration of the provider using the
139      * <code>Security.addProvider()</code> mechanism.
140      */
BouncyCastleProvider()141     public BouncyCastleProvider()
142     {
143         super(PROVIDER_NAME, 1.54, info);
144 
145         AccessController.doPrivileged(new PrivilegedAction()
146         {
147             public Object run()
148             {
149                 setup();
150                 return null;
151             }
152         });
153     }
154 
setup()155     private void setup()
156     {
157         loadAlgorithms(DIGEST_PACKAGE, DIGESTS);
158 
159         loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_GENERIC);
160 
161         loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_MACS);
162 
163         loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_CIPHERS);
164 
165         loadAlgorithms(ASYMMETRIC_PACKAGE, ASYMMETRIC_GENERIC);
166 
167         loadAlgorithms(ASYMMETRIC_PACKAGE, ASYMMETRIC_CIPHERS);
168 
169         loadAlgorithms(KEYSTORE_PACKAGE, KEYSTORES);
170 
171         // BEGIN android-removed
172         // //
173         // // X509Store
174         // //
175         // put("X509Store.CERTIFICATE/COLLECTION", "org.bouncycastle.jce.provider.X509StoreCertCollection");
176         // put("X509Store.ATTRIBUTECERTIFICATE/COLLECTION", "org.bouncycastle.jce.provider.X509StoreAttrCertCollection");
177         // put("X509Store.CRL/COLLECTION", "org.bouncycastle.jce.provider.X509StoreCRLCollection");
178         // put("X509Store.CERTIFICATEPAIR/COLLECTION", "org.bouncycastle.jce.provider.X509StoreCertPairCollection");
179         //
180         // put("X509Store.CERTIFICATE/LDAP", "org.bouncycastle.jce.provider.X509StoreLDAPCerts");
181         // put("X509Store.CRL/LDAP", "org.bouncycastle.jce.provider.X509StoreLDAPCRLs");
182         // put("X509Store.ATTRIBUTECERTIFICATE/LDAP", "org.bouncycastle.jce.provider.X509StoreLDAPAttrCerts");
183         // put("X509Store.CERTIFICATEPAIR/LDAP", "org.bouncycastle.jce.provider.X509StoreLDAPCertPairs");
184         //
185         // //
186         // // X509StreamParser
187         // //
188         // put("X509StreamParser.CERTIFICATE", "org.bouncycastle.jce.provider.X509CertParser");
189         // put("X509StreamParser.ATTRIBUTECERTIFICATE", "org.bouncycastle.jce.provider.X509AttrCertParser");
190         // put("X509StreamParser.CRL", "org.bouncycastle.jce.provider.X509CRLParser");
191         // put("X509StreamParser.CERTIFICATEPAIR", "org.bouncycastle.jce.provider.X509CertPairParser");
192         //
193         // //
194         // // cipher engines
195         // //
196         // put("Cipher.BROKENPBEWITHMD5ANDDES", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithMD5AndDES");
197         //
198         // put("Cipher.BROKENPBEWITHSHA1ANDDES", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithSHA1AndDES");
199         //
200         //
201         // put("Cipher.OLDPBEWITHSHAANDTWOFISH-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$OldPBEWithSHAAndTwofish");
202         //
203         // // Certification Path API
204         // put("CertPathValidator.RFC3281", "org.bouncycastle.jce.provider.PKIXAttrCertPathValidatorSpi");
205         // put("CertPathBuilder.RFC3281", "org.bouncycastle.jce.provider.PKIXAttrCertPathBuilderSpi");
206         // put("CertPathValidator.RFC3280", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi");
207         // put("CertPathBuilder.RFC3280", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi");
208         // END android-removed
209         put("CertPathValidator.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi");
210         put("CertPathBuilder.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi");
211         put("CertStore.Collection", "org.bouncycastle.jce.provider.CertStoreCollectionSpi");
212         // BEGIN android-removed
213         // put("CertStore.LDAP", "org.bouncycastle.jce.provider.X509LDAPCertStoreSpi");
214         // put("CertStore.Multi", "org.bouncycastle.jce.provider.MultiCertStoreSpi");
215         // put("Alg.Alias.CertStore.X509LDAP", "LDAP");
216         // END android-removed
217     }
218 
loadAlgorithms(String packageName, String[] names)219     private void loadAlgorithms(String packageName, String[] names)
220     {
221         for (int i = 0; i != names.length; i++)
222         {
223             Class clazz = null;
224             try
225             {
226                 ClassLoader loader = this.getClass().getClassLoader();
227 
228                 if (loader != null)
229                 {
230                     clazz = loader.loadClass(packageName + names[i] + "$Mappings");
231                 }
232                 else
233                 {
234                     clazz = Class.forName(packageName + names[i] + "$Mappings");
235                 }
236             }
237             catch (ClassNotFoundException e)
238             {
239                 // ignore
240             }
241 
242             if (clazz != null)
243             {
244                 try
245                 {
246                     ((AlgorithmProvider)clazz.newInstance()).configure(this);
247                 }
248                 catch (Exception e)
249                 {   // this should never ever happen!!
250                     throw new InternalError("cannot create instance of "
251                         + packageName + names[i] + "$Mappings : " + e);
252                 }
253             }
254         }
255     }
256 
setParameter(String parameterName, Object parameter)257     public void setParameter(String parameterName, Object parameter)
258     {
259         synchronized (CONFIGURATION)
260         {
261             ((BouncyCastleProviderConfiguration)CONFIGURATION).setParameter(parameterName, parameter);
262         }
263     }
264 
hasAlgorithm(String type, String name)265     public boolean hasAlgorithm(String type, String name)
266     {
267         return containsKey(type + "." + name) || containsKey("Alg.Alias." + type + "." + name);
268     }
269 
addAlgorithm(String key, String value)270     public void addAlgorithm(String key, String value)
271     {
272         if (containsKey(key))
273         {
274             throw new IllegalStateException("duplicate provider key (" + key + ") found");
275         }
276 
277         put(key, value);
278     }
279 
addAlgorithm(String type, ASN1ObjectIdentifier oid, String className)280     public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className)
281     {
282         addAlgorithm(type + "." + oid, className);
283         addAlgorithm(type + ".OID." + oid, className);
284     }
285 
addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter)286     public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter)
287     {
288         keyInfoConverters.put(oid, keyInfoConverter);
289     }
290 
getPublicKey(SubjectPublicKeyInfo publicKeyInfo)291     public static PublicKey getPublicKey(SubjectPublicKeyInfo publicKeyInfo)
292         throws IOException
293     {
294         AsymmetricKeyInfoConverter converter = (AsymmetricKeyInfoConverter)keyInfoConverters.get(publicKeyInfo.getAlgorithm().getAlgorithm());
295 
296         if (converter == null)
297         {
298             return null;
299         }
300 
301         return converter.generatePublic(publicKeyInfo);
302     }
303 
getPrivateKey(PrivateKeyInfo privateKeyInfo)304     public static PrivateKey getPrivateKey(PrivateKeyInfo privateKeyInfo)
305         throws IOException
306     {
307         AsymmetricKeyInfoConverter converter = (AsymmetricKeyInfoConverter)keyInfoConverters.get(privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm());
308 
309         if (converter == null)
310         {
311             return null;
312         }
313 
314         return converter.generatePrivate(privateKeyInfo);
315     }
316 }
317