Home | History | Annotate | Download | only in ec
      1 package org.bouncycastle.jce.provider.asymmetric.ec;
      2 
      3 import java.math.BigInteger;
      4 import java.security.InvalidAlgorithmParameterException;
      5 import java.security.InvalidParameterException;
      6 import java.security.KeyPair;
      7 import java.security.SecureRandom;
      8 import java.security.spec.AlgorithmParameterSpec;
      9 import java.security.spec.ECGenParameterSpec;
     10 import java.util.Hashtable;
     11 
     12 import org.bouncycastle.asn1.DERObjectIdentifier;
     13 // BEGIN android-removed
     14 // import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
     15 // END android-removed
     16 import org.bouncycastle.asn1.nist.NISTNamedCurves;
     17 import org.bouncycastle.asn1.sec.SECNamedCurves;
     18 // BEGIN android-removed
     19 // import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
     20 // END android-removed
     21 import org.bouncycastle.asn1.x9.X962NamedCurves;
     22 import org.bouncycastle.asn1.x9.X9ECParameters;
     23 import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
     24 import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
     25 import org.bouncycastle.crypto.params.ECDomainParameters;
     26 import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
     27 import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
     28 import org.bouncycastle.crypto.params.ECPublicKeyParameters;
     29 import org.bouncycastle.jce.provider.JCEECPrivateKey;
     30 import org.bouncycastle.jce.provider.JCEECPublicKey;
     31 import org.bouncycastle.jce.provider.JDKKeyPairGenerator;
     32 import org.bouncycastle.jce.provider.ProviderUtil;
     33 import org.bouncycastle.jce.spec.ECNamedCurveSpec;
     34 import org.bouncycastle.jce.spec.ECParameterSpec;
     35 import org.bouncycastle.math.ec.ECCurve;
     36 import org.bouncycastle.math.ec.ECPoint;
     37 
     38 public abstract class KeyPairGenerator
     39     extends JDKKeyPairGenerator
     40 {
     41     public KeyPairGenerator(String algorithmName)
     42     {
     43         super(algorithmName);
     44     }
     45 
     46     public static class EC
     47         extends KeyPairGenerator
     48     {
     49         ECKeyGenerationParameters   param;
     50         ECKeyPairGenerator          engine = new ECKeyPairGenerator();
     51         Object                      ecParams = null;
     52         int                         strength = 239;
     53         int                         certainty = 50;
     54         SecureRandom                random = new SecureRandom();
     55         boolean                     initialised = false;
     56         String                      algorithm;
     57 
     58         static private Hashtable    ecParameters;
     59 
     60         static {
     61             ecParameters = new Hashtable();
     62 
     63             // BEGIN android-changed
     64             ecParameters.put(Integer.valueOf(192), new ECGenParameterSpec("prime192v1")); // a.k.a P-192
     65             ecParameters.put(Integer.valueOf(239), new ECGenParameterSpec("prime239v1"));
     66             ecParameters.put(Integer.valueOf(256), new ECGenParameterSpec("prime256v1")); // a.k.a P-256
     67 
     68             ecParameters.put(Integer.valueOf(224), new ECGenParameterSpec("P-224"));
     69             ecParameters.put(Integer.valueOf(384), new ECGenParameterSpec("P-384"));
     70             ecParameters.put(Integer.valueOf(521), new ECGenParameterSpec("P-521"));
     71             // END android-changed
     72         }
     73 
     74         public EC()
     75         {
     76             super("EC");
     77             this.algorithm = "EC";
     78         }
     79 
     80         public EC(
     81             String  algorithm)
     82         {
     83             super(algorithm);
     84             this.algorithm = algorithm;
     85         }
     86 
     87         public void initialize(
     88             int             strength,
     89             SecureRandom    random)
     90         {
     91             this.strength = strength;
     92             // BEGIN android-added
     93             if (random != null) {
     94             // END android-added
     95             this.random = random;
     96             // BEGIN android-added
     97             }
     98             // END android-added
     99             // BEGIN android-changed
    100             this.ecParams = ecParameters.get(Integer.valueOf(strength));
    101             // END android-changed
    102 
    103             if (ecParams != null)
    104             {
    105                 try
    106                 {
    107                     initialize((ECGenParameterSpec)ecParams, random);
    108                 }
    109                 catch (InvalidAlgorithmParameterException e)
    110                 {
    111                     throw new InvalidParameterException("key size not configurable.");
    112                 }
    113             }
    114             else
    115             {
    116                 throw new InvalidParameterException("unknown key size.");
    117             }
    118         }
    119 
    120         public void initialize(
    121             AlgorithmParameterSpec  params,
    122             SecureRandom            random)
    123             throws InvalidAlgorithmParameterException
    124         {
    125             // BEGIN android-added
    126             if (random == null) {
    127                 random = this.random;
    128             }
    129             // END android-added
    130             if (params instanceof ECParameterSpec)
    131             {
    132                 ECParameterSpec p = (ECParameterSpec)params;
    133                 this.ecParams = params;
    134 
    135                 param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random);
    136 
    137                 engine.init(param);
    138                 initialised = true;
    139             }
    140             else if (params instanceof java.security.spec.ECParameterSpec)
    141             {
    142                 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)params;
    143                 this.ecParams = params;
    144 
    145                 ECCurve curve = EC5Util.convertCurve(p.getCurve());
    146                 ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false);
    147 
    148                 param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random);
    149 
    150                 engine.init(param);
    151                 initialised = true;
    152             }
    153             else if (params instanceof ECGenParameterSpec)
    154             {
    155                 final String curveName = ((ECGenParameterSpec)params).getName();
    156 
    157                 // BEGIN android-removed
    158                 // if (this.algorithm.equals("ECGOST3410"))
    159                 // {
    160                 //     ECDomainParameters  ecP = ECGOST3410NamedCurves.getByName(curveName);
    161                 //     if (ecP == null)
    162                 //     {
    163                 //         throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
    164                 //     }
    165                 //
    166                 //     this.ecParams = new ECNamedCurveSpec(
    167                 //                                     curveName,
    168                 //                                     ecP.getCurve(),
    169                 //                                     ecP.getG(),
    170                 //                                     ecP.getN(),
    171                 //                                     ecP.getH(),
    172                 //                                     ecP.getSeed());
    173                 // }
    174                 // else
    175                 // END android-removed
    176                 {
    177                     X9ECParameters  ecP = X962NamedCurves.getByName(curveName);
    178                     if (ecP == null)
    179                     {
    180                         ecP = SECNamedCurves.getByName(curveName);
    181                         if (ecP == null)
    182                         {
    183                             ecP = NISTNamedCurves.getByName(curveName);
    184                         }
    185                         // BEGIN android-removed
    186                         // if (ecP == null)
    187                         // {
    188                         //     ecP = TeleTrusTNamedCurves.getByName(curveName);
    189                         // }
    190                         // END android-removed
    191                         if (ecP == null)
    192                         {
    193                             // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
    194                             try
    195                             {
    196                                 DERObjectIdentifier oid = new DERObjectIdentifier(curveName);
    197                                 ecP = X962NamedCurves.getByOID(oid);
    198                                 if (ecP == null)
    199                                 {
    200                                     ecP = SECNamedCurves.getByOID(oid);
    201                                 }
    202                                 if (ecP == null)
    203                                 {
    204                                     ecP = NISTNamedCurves.getByOID(oid);
    205                                 }
    206                                 // BEGIN android-removed
    207                                 // if (ecP == null)
    208                                 // {
    209                                 //     ecP = TeleTrusTNamedCurves.getByOID(oid);
    210                                 // }
    211                                 // END android-removed
    212                                 if (ecP == null)
    213                                 {
    214                                     throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName);
    215                                 }
    216                             }
    217                             catch (IllegalArgumentException ex)
    218                             {
    219                                 throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
    220                             }
    221                         }
    222                     }
    223 
    224                     this.ecParams = new ECNamedCurveSpec(
    225                             curveName,
    226                             ecP.getCurve(),
    227                             ecP.getG(),
    228                             ecP.getN(),
    229                             ecP.getH(),
    230                             null); // ecP.getSeed());   Work-around JDK bug -- it won't look up named curves properly if seed is present
    231                 }
    232 
    233                 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams;
    234 
    235                 ECCurve curve = EC5Util.convertCurve(p.getCurve());
    236                 ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false);
    237 
    238                 param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random);
    239 
    240                 engine.init(param);
    241                 initialised = true;
    242             }
    243             else if (params == null && ProviderUtil.getEcImplicitlyCa() != null)
    244             {
    245                 ECParameterSpec p = ProviderUtil.getEcImplicitlyCa();
    246                 this.ecParams = params;
    247 
    248                 param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random);
    249 
    250                 engine.init(param);
    251                 initialised = true;
    252             }
    253             else if (params == null && ProviderUtil.getEcImplicitlyCa() == null)
    254             {
    255                 throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set");
    256             }
    257             else
    258             {
    259                 throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec");
    260             }
    261         }
    262 
    263         public KeyPair generateKeyPair()
    264         {
    265             if (!initialised)
    266             {
    267                 // BEGIN android-removed
    268                 // throw new IllegalStateException("EC Key Pair Generator not initialised");
    269                 // END android-removed
    270                 // BEGIN android-added
    271                 /*
    272                  * KeyPairGenerator documentation says that a default initialization must be provided
    273                  */
    274                 initialize(192, random);
    275                 // END android-added
    276             }
    277 
    278             AsymmetricCipherKeyPair     pair = engine.generateKeyPair();
    279             ECPublicKeyParameters       pub = (ECPublicKeyParameters)pair.getPublic();
    280             ECPrivateKeyParameters      priv = (ECPrivateKeyParameters)pair.getPrivate();
    281 
    282             if (ecParams instanceof ECParameterSpec)
    283             {
    284                 ECParameterSpec p = (ECParameterSpec)ecParams;
    285 
    286                 JCEECPublicKey pubKey = new JCEECPublicKey(algorithm, pub, p);
    287                 return new KeyPair(pubKey,
    288                                    new JCEECPrivateKey(algorithm, priv, pubKey, p));
    289             }
    290             else if (ecParams == null)
    291             {
    292                return new KeyPair(new JCEECPublicKey(algorithm, pub),
    293                                    new JCEECPrivateKey(algorithm, priv));
    294             }
    295             else
    296             {
    297                 java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams;
    298 
    299                 JCEECPublicKey pubKey = new JCEECPublicKey(algorithm, pub, p);
    300 
    301                 return new KeyPair(pubKey, new JCEECPrivateKey(algorithm, priv, pubKey, p));
    302             }
    303         }
    304     }
    305 
    306     public static class ECDSA
    307         extends EC
    308     {
    309         public ECDSA()
    310         {
    311             super("ECDSA");
    312         }
    313     }
    314 
    315     // BEGIN android-removed
    316     // public static class ECGOST3410
    317     //     extends EC
    318     // {
    319     //     public ECGOST3410()
    320     //     {
    321     //         super("ECGOST3410");
    322     //     }
    323     // }
    324     // END android-removed
    325 
    326     public static class ECDH
    327         extends EC
    328     {
    329         public ECDH()
    330         {
    331             super("ECDH");
    332         }
    333     }
    334 
    335     public static class ECDHC
    336         extends EC
    337     {
    338         public ECDHC()
    339         {
    340             super("ECDHC");
    341         }
    342     }
    343 
    344     public static class ECMQV
    345         extends EC
    346     {
    347         public ECMQV()
    348         {
    349             super("ECMQV");
    350         }
    351     }
    352 }
    353