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