1 package org.bouncycastle.x509;
2 
3 import java.io.IOException;
4 import java.security.InvalidKeyException;
5 import java.security.NoSuchAlgorithmException;
6 import java.security.NoSuchProviderException;
7 import java.security.PrivateKey;
8 import java.security.Provider;
9 import java.security.SecureRandom;
10 import java.security.Security;
11 import java.security.Signature;
12 import java.security.SignatureException;
13 import java.util.ArrayList;
14 import java.util.Enumeration;
15 import java.util.HashSet;
16 import java.util.Hashtable;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Set;
20 
21 import javax.security.auth.x500.X500Principal;
22 
23 import org.bouncycastle.asn1.ASN1Encodable;
24 import org.bouncycastle.asn1.ASN1Encoding;
25 import org.bouncycastle.asn1.ASN1Integer;
26 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
27 import org.bouncycastle.asn1.DERNull;
28 import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
29 import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
30 import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
31 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
32 import org.bouncycastle.asn1.pkcs.RSASSAPSSparams;
33 import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
34 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
35 import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
36 import org.bouncycastle.jce.X509Principal;
37 import org.bouncycastle.util.Strings;
38 
39 class X509Util
40 {
41     private static Hashtable algorithms = new Hashtable();
42     private static Hashtable params = new Hashtable();
43     private static Set       noParams = new HashSet();
44 
45     static
46     {
47         algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption);
48         algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption);
49         algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption);
50         algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption);
51         algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption);
52         algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption);
53         algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption);
54         algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption);
55         algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption);
56         algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption);
57         algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption);
58         algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption);
59         algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption);
60         algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption);
61         algorithms.put("SHA1WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
62         algorithms.put("SHA224WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
63         algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
64         algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
65         algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
66         algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
67         algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
68         algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
69         algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
70         algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
71         algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
72         algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1);
73         algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1);
74         algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224);
75         algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256);
76         algorithms.put("SHA384WITHDSA", NISTObjectIdentifiers.dsa_with_sha384);
77         algorithms.put("SHA512WITHDSA", NISTObjectIdentifiers.dsa_with_sha512);
78         algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1);
79         algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1);
80         algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224);
81         algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256);
82         algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384);
83         algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512);
84         algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
85         algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
86         algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
87         algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
88         algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
89 
90         //
91         // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
92         // The parameters field SHALL be NULL for RSA based signature algorithms.
93         //
94         noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1);
95         noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224);
96         noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256);
97         noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384);
98         noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512);
99         noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1);
100         noParams.add(OIWObjectIdentifiers.dsaWithSHA1);
101         noParams.add(NISTObjectIdentifiers.dsa_with_sha224);
102         noParams.add(NISTObjectIdentifiers.dsa_with_sha256);
103         noParams.add(NISTObjectIdentifiers.dsa_with_sha384);
104         noParams.add(NISTObjectIdentifiers.dsa_with_sha512);
105 
106         //
107         // RFC 4491
108         //
109         noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
110         noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
111 
112         //
113         // explicit params
114         //
115         AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
116         params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20));
117 
118         AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224, DERNull.INSTANCE);
119         params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId, 28));
120 
121         AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, DERNull.INSTANCE);
122         params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId, 32));
123 
124         AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384, DERNull.INSTANCE);
125         params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId, 48));
126 
127         AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha512, DERNull.INSTANCE);
128         params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId, 64));
129     }
130 
creatPSSParams(AlgorithmIdentifier hashAlgId, int saltSize)131     private static RSASSAPSSparams creatPSSParams(AlgorithmIdentifier hashAlgId, int saltSize)
132     {
133         return new RSASSAPSSparams(
134             hashAlgId,
135             new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId),
136             new ASN1Integer(saltSize),
137             new ASN1Integer(1));
138     }
139 
getAlgorithmOID( String algorithmName)140     static ASN1ObjectIdentifier getAlgorithmOID(
141         String algorithmName)
142     {
143         algorithmName = Strings.toUpperCase(algorithmName);
144 
145         if (algorithms.containsKey(algorithmName))
146         {
147             return (ASN1ObjectIdentifier)algorithms.get(algorithmName);
148         }
149 
150         return new ASN1ObjectIdentifier(algorithmName);
151     }
152 
getSigAlgID( ASN1ObjectIdentifier sigOid, String algorithmName)153     static AlgorithmIdentifier getSigAlgID(
154         ASN1ObjectIdentifier sigOid,
155         String              algorithmName)
156     {
157         if (noParams.contains(sigOid))
158         {
159             return new AlgorithmIdentifier(sigOid);
160         }
161 
162         algorithmName = Strings.toUpperCase(algorithmName);
163 
164         if (params.containsKey(algorithmName))
165         {
166             return new AlgorithmIdentifier(sigOid, (ASN1Encodable)params.get(algorithmName));
167         }
168         else
169         {
170             return new AlgorithmIdentifier(sigOid, DERNull.INSTANCE);
171         }
172     }
173 
getAlgNames()174     static Iterator getAlgNames()
175     {
176         Enumeration e = algorithms.keys();
177         List        l = new ArrayList();
178 
179         while (e.hasMoreElements())
180         {
181             l.add(e.nextElement());
182         }
183 
184         return l.iterator();
185     }
186 
getSignatureInstance( String algorithm)187     static Signature getSignatureInstance(
188         String algorithm)
189         throws NoSuchAlgorithmException
190     {
191         return Signature.getInstance(algorithm);
192     }
193 
getSignatureInstance( String algorithm, String provider)194     static Signature getSignatureInstance(
195         String algorithm,
196         String provider)
197         throws NoSuchProviderException, NoSuchAlgorithmException
198     {
199         if (provider != null)
200         {
201             return Signature.getInstance(algorithm, provider);
202         }
203         else
204         {
205             return Signature.getInstance(algorithm);
206         }
207     }
208 
calculateSignature( ASN1ObjectIdentifier sigOid, String sigName, PrivateKey key, SecureRandom random, ASN1Encodable object)209     static byte[] calculateSignature(
210         ASN1ObjectIdentifier sigOid,
211         String              sigName,
212         PrivateKey          key,
213         SecureRandom        random,
214         ASN1Encodable       object)
215         throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException
216     {
217         Signature sig;
218 
219         if (sigOid == null)
220         {
221             throw new IllegalStateException("no signature algorithm specified");
222         }
223 
224         sig = X509Util.getSignatureInstance(sigName);
225 
226         if (random != null)
227         {
228             sig.initSign(key, random);
229         }
230         else
231         {
232             sig.initSign(key);
233         }
234 
235         sig.update(object.toASN1Primitive().getEncoded(ASN1Encoding.DER));
236 
237         return sig.sign();
238     }
239 
calculateSignature( ASN1ObjectIdentifier sigOid, String sigName, String provider, PrivateKey key, SecureRandom random, ASN1Encodable object)240     static byte[] calculateSignature(
241         ASN1ObjectIdentifier sigOid,
242         String              sigName,
243         String              provider,
244         PrivateKey          key,
245         SecureRandom        random,
246         ASN1Encodable       object)
247         throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException
248     {
249         Signature sig;
250 
251         if (sigOid == null)
252         {
253             throw new IllegalStateException("no signature algorithm specified");
254         }
255 
256         sig = X509Util.getSignatureInstance(sigName, provider);
257 
258         if (random != null)
259         {
260             sig.initSign(key, random);
261         }
262         else
263         {
264             sig.initSign(key);
265         }
266 
267         sig.update(object.toASN1Primitive().getEncoded(ASN1Encoding.DER));
268 
269         return sig.sign();
270     }
271 
convertPrincipal( X500Principal principal)272     static X509Principal convertPrincipal(
273         X500Principal principal)
274     {
275         try
276         {
277             return new X509Principal(principal.getEncoded());
278         }
279         catch (IOException e)
280         {
281             throw new IllegalArgumentException("cannot convert principal");
282         }
283     }
284 
285     static class Implementation
286     {
287         Object      engine;
288         Provider provider;
289 
Implementation( Object engine, Provider provider)290         Implementation(
291             Object      engine,
292             Provider    provider)
293         {
294             this.engine = engine;
295             this.provider = provider;
296         }
297 
getEngine()298         Object getEngine()
299         {
300             return engine;
301         }
302 
getProvider()303         Provider getProvider()
304         {
305             return provider;
306         }
307     }
308 
309     /**
310      * see if we can find an algorithm (or its alias and what it represents) in
311      * the property table for the given provider.
312      */
getImplementation( String baseName, String algorithm, Provider prov)313     static Implementation getImplementation(
314         String      baseName,
315         String      algorithm,
316         Provider    prov)
317         throws NoSuchAlgorithmException
318     {
319         algorithm = Strings.toUpperCase(algorithm);
320 
321         String      alias;
322 
323         while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null)
324         {
325             algorithm = alias;
326         }
327 
328         String      className = prov.getProperty(baseName + "." + algorithm);
329 
330         if (className != null)
331         {
332             try
333             {
334                 Class       cls;
335                 ClassLoader clsLoader = prov.getClass().getClassLoader();
336 
337                 if (clsLoader != null)
338                 {
339                     cls = clsLoader.loadClass(className);
340                 }
341                 else
342                 {
343                     cls = Class.forName(className);
344                 }
345 
346                 return new Implementation(cls.newInstance(), prov);
347             }
348             catch (ClassNotFoundException e)
349             {
350                 throw new IllegalStateException(
351                     "algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!");
352             }
353             catch (Exception e)
354             {
355                 throw new IllegalStateException(
356                     "algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!");
357             }
358         }
359 
360         throw new NoSuchAlgorithmException("cannot find implementation " + algorithm + " for provider " + prov.getName());
361     }
362 
363     /**
364      * return an implementation for a given algorithm/provider.
365      * If the provider is null, we grab the first avalaible who has the required algorithm.
366      */
getImplementation( String baseName, String algorithm)367     static Implementation getImplementation(
368         String      baseName,
369         String      algorithm)
370         throws NoSuchAlgorithmException
371     {
372         Provider[] prov = Security.getProviders();
373 
374         //
375         // search every provider looking for the algorithm we want.
376         //
377         for (int i = 0; i != prov.length; i++)
378         {
379             //
380             // try case insensitive
381             //
382             Implementation imp = getImplementation(baseName, Strings.toUpperCase(algorithm), prov[i]);
383             if (imp != null)
384             {
385                 return imp;
386             }
387 
388             try
389             {
390                 imp = getImplementation(baseName, algorithm, prov[i]);
391             }
392             catch (NoSuchAlgorithmException e)
393             {
394                 // continue
395             }
396         }
397 
398         throw new NoSuchAlgorithmException("cannot find implementation " + algorithm);
399     }
400 
getProvider(String provider)401     static Provider getProvider(String provider)
402         throws NoSuchProviderException
403     {
404         Provider prov = Security.getProvider(provider);
405 
406         if (prov == null)
407         {
408             throw new NoSuchProviderException("Provider " + provider + " not found");
409         }
410 
411         return prov;
412     }
413 }
414