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