Home | History | Annotate | Download | only in ec
      1 package org.bouncycastle.jcajce.provider.asymmetric.ec;
      2 
      3 import java.math.BigInteger;
      4 import java.security.InvalidAlgorithmParameterException;
      5 import java.security.InvalidKeyException;
      6 import java.security.Key;
      7 import java.security.PrivateKey;
      8 import java.security.PublicKey;
      9 import java.security.SecureRandom;
     10 import java.security.spec.AlgorithmParameterSpec;
     11 
     12 import org.bouncycastle.asn1.x9.X9IntegerConverter;
     13 import org.bouncycastle.crypto.BasicAgreement;
     14 import org.bouncycastle.crypto.CipherParameters;
     15 import org.bouncycastle.crypto.DerivationFunction;
     16 import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
     17 // BEGIN Android-removed: Unsupported algorithms
     18 // import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
     19 // import org.bouncycastle.crypto.agreement.ECMQVBasicAgreement;
     20 // import org.bouncycastle.crypto.agreement.kdf.ConcatenationKDFGenerator;
     21 // import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
     22 // END Android-removed: Unsupported algorithms
     23 import org.bouncycastle.crypto.params.ECDomainParameters;
     24 import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
     25 import org.bouncycastle.crypto.params.ECPublicKeyParameters;
     26 // BEGIN Android-removed: Unsupported algorithms
     27 // import org.bouncycastle.crypto.params.MQVPrivateParameters;
     28 // import org.bouncycastle.crypto.params.MQVPublicParameters;
     29 // import org.bouncycastle.crypto.util.DigestFactory;
     30 // END Android-removed: Unsupported algorithms
     31 import org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi;
     32 import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
     33 // BEGIN Android-removed: Unsupported algorithms
     34 // import org.bouncycastle.jcajce.spec.MQVParameterSpec;
     35 // END Android-removed: Unsupported algorithms
     36 import org.bouncycastle.jcajce.spec.UserKeyingMaterialSpec;
     37 import org.bouncycastle.jce.interfaces.ECPrivateKey;
     38 import org.bouncycastle.jce.interfaces.ECPublicKey;
     39 // BEGIN Android-removed: Unsupported algorithms
     40 // import org.bouncycastle.jce.interfaces.MQVPrivateKey;
     41 // import org.bouncycastle.jce.interfaces.MQVPublicKey;
     42 // END Android-removed: Unsupported algorithms
     43 
     44 /**
     45  * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363
     46  * both the simple one, and the simple one with cofactors are supported.
     47  *
     48  * Also, MQV key agreement per SEC-1
     49  */
     50 public class KeyAgreementSpi
     51     extends BaseAgreementSpi
     52 {
     53     private static final X9IntegerConverter converter = new X9IntegerConverter();
     54 
     55     private String                 kaAlgorithm;
     56 
     57     private ECDomainParameters     parameters;
     58     private BasicAgreement         agreement;
     59 
     60     // Android-removed: Unsupported algorithms
     61     // private MQVParameterSpec       mqvParameters;
     62     private BigInteger             result;
     63 
     64     protected KeyAgreementSpi(
     65         String kaAlgorithm,
     66         BasicAgreement agreement,
     67         DerivationFunction kdf)
     68     {
     69         super(kaAlgorithm, kdf);
     70 
     71         this.kaAlgorithm = kaAlgorithm;
     72         this.agreement = agreement;
     73     }
     74 
     75     protected byte[] bigIntToBytes(
     76         BigInteger    r)
     77     {
     78         return converter.integerToBytes(r, converter.getByteLength(parameters.getCurve()));
     79     }
     80 
     81     protected Key engineDoPhase(
     82         Key     key,
     83         boolean lastPhase)
     84         throws InvalidKeyException, IllegalStateException
     85     {
     86         if (parameters == null)
     87         {
     88             throw new IllegalStateException(kaAlgorithm + " not initialised.");
     89         }
     90 
     91         if (!lastPhase)
     92         {
     93             throw new IllegalStateException(kaAlgorithm + " can only be between two parties.");
     94         }
     95 
     96         CipherParameters pubKey;
     97         // BEGIN Android-removed: Unsupported algorithms
     98         /*
     99         if (agreement instanceof ECMQVBasicAgreement)
    100         {
    101             if (!(key instanceof MQVPublicKey))
    102             {
    103                 ECPublicKeyParameters staticKey = (ECPublicKeyParameters)
    104                     ECUtils.generatePublicKeyParameter((PublicKey)key);
    105                 ECPublicKeyParameters ephemKey = (ECPublicKeyParameters)
    106                     ECUtils.generatePublicKeyParameter(mqvParameters.getOtherPartyEphemeralKey());
    107 
    108                 pubKey = new MQVPublicParameters(staticKey, ephemKey);
    109             }
    110             else
    111             {
    112                 MQVPublicKey mqvPubKey = (MQVPublicKey)key;
    113                 ECPublicKeyParameters staticKey = (ECPublicKeyParameters)
    114                     ECUtils.generatePublicKeyParameter(mqvPubKey.getStaticKey());
    115                 ECPublicKeyParameters ephemKey = (ECPublicKeyParameters)
    116                     ECUtils.generatePublicKeyParameter(mqvPubKey.getEphemeralKey());
    117 
    118                 pubKey = new MQVPublicParameters(staticKey, ephemKey);
    119             }
    120         }
    121         else
    122         */
    123         // END Android-removed: Unsupported algorithms
    124         {
    125             if (!(key instanceof PublicKey))
    126             {
    127                 throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
    128                     + getSimpleName(ECPublicKey.class) + " for doPhase");
    129             }
    130 
    131             pubKey = ECUtils.generatePublicKeyParameter((PublicKey)key);
    132         }
    133 
    134         try
    135         {
    136             result = agreement.calculateAgreement(pubKey);
    137         }
    138         catch (final Exception e)
    139         {
    140             throw new InvalidKeyException("calculation failed: " + e.getMessage())
    141             {
    142                 public Throwable getCause()
    143                             {
    144                                 return e;
    145                             }
    146             };
    147         }
    148 
    149         return null;
    150     }
    151 
    152     protected void engineInit(
    153         Key                     key,
    154         AlgorithmParameterSpec  params,
    155         SecureRandom            random)
    156         throws InvalidKeyException, InvalidAlgorithmParameterException
    157     {
    158         // Android-removed: Unsupported algorithms
    159         // if (params != null && !(params instanceof MQVParameterSpec || params instanceof UserKeyingMaterialSpec))
    160         if (params != null && !(params instanceof UserKeyingMaterialSpec))
    161         {
    162             throw new InvalidAlgorithmParameterException("No algorithm parameters supported");
    163         }
    164 
    165         initFromKey(key, params);
    166     }
    167 
    168     protected void engineInit(
    169         Key             key,
    170         SecureRandom    random)
    171         throws InvalidKeyException
    172     {
    173         initFromKey(key, null);
    174     }
    175 
    176     private void initFromKey(Key key, AlgorithmParameterSpec parameterSpec)
    177         throws InvalidKeyException
    178     {
    179         // BEGIN Android-removed: Unsupported algorithms
    180         /*
    181         if (agreement instanceof ECMQVBasicAgreement)
    182         {
    183             mqvParameters = null;
    184             if (!(key instanceof MQVPrivateKey) && !(parameterSpec instanceof MQVParameterSpec))
    185             {
    186                 throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
    187                     + getSimpleName(MQVParameterSpec.class) + " for initialisation");
    188             }
    189 
    190             ECPrivateKeyParameters staticPrivKey;
    191             ECPrivateKeyParameters ephemPrivKey;
    192             ECPublicKeyParameters ephemPubKey;
    193             if (key instanceof MQVPrivateKey)
    194             {
    195                 MQVPrivateKey mqvPrivKey = (MQVPrivateKey)key;
    196                 staticPrivKey = (ECPrivateKeyParameters)
    197                     ECUtil.generatePrivateKeyParameter(mqvPrivKey.getStaticPrivateKey());
    198                 ephemPrivKey = (ECPrivateKeyParameters)
    199                     ECUtil.generatePrivateKeyParameter(mqvPrivKey.getEphemeralPrivateKey());
    200 
    201                 ephemPubKey = null;
    202                 if (mqvPrivKey.getEphemeralPublicKey() != null)
    203                 {
    204                     ephemPubKey = (ECPublicKeyParameters)
    205                         ECUtils.generatePublicKeyParameter(mqvPrivKey.getEphemeralPublicKey());
    206                 }
    207             }
    208             else
    209             {
    210                 MQVParameterSpec mqvParameterSpec = (MQVParameterSpec)parameterSpec;
    211 
    212                 staticPrivKey = (ECPrivateKeyParameters)
    213                     ECUtil.generatePrivateKeyParameter((PrivateKey)key);
    214                 ephemPrivKey = (ECPrivateKeyParameters)
    215                     ECUtil.generatePrivateKeyParameter(mqvParameterSpec.getEphemeralPrivateKey());
    216 
    217                 ephemPubKey = null;
    218                 if (mqvParameterSpec.getEphemeralPublicKey() != null)
    219                 {
    220                     ephemPubKey = (ECPublicKeyParameters)
    221                         ECUtils.generatePublicKeyParameter(mqvParameterSpec.getEphemeralPublicKey());
    222                 }
    223                 mqvParameters = mqvParameterSpec;
    224                 ukmParameters = mqvParameterSpec.getUserKeyingMaterial();
    225             }
    226 
    227             MQVPrivateParameters localParams = new MQVPrivateParameters(staticPrivKey, ephemPrivKey, ephemPubKey);
    228             this.parameters = staticPrivKey.getParameters();
    229 
    230             // TODO Validate that all the keys are using the same parameters?
    231 
    232             agreement.init(localParams);
    233         }
    234         else
    235         */
    236         // END Android-removed: Unsupported algorithms
    237         {
    238             if (!(key instanceof PrivateKey))
    239             {
    240                 throw new InvalidKeyException(kaAlgorithm + " key agreement requires "
    241                     + getSimpleName(ECPrivateKey.class) + " for initialisation");
    242             }
    243 
    244             ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)ECUtil.generatePrivateKeyParameter((PrivateKey)key);
    245             this.parameters = privKey.getParameters();
    246             ukmParameters = (parameterSpec instanceof UserKeyingMaterialSpec) ? ((UserKeyingMaterialSpec)parameterSpec).getUserKeyingMaterial() : null;
    247             agreement.init(privKey);
    248         }
    249     }
    250 
    251     private static String getSimpleName(Class clazz)
    252     {
    253         String fullName = clazz.getName();
    254 
    255         return fullName.substring(fullName.lastIndexOf('.') + 1);
    256     }
    257 
    258 
    259     protected byte[] calcSecret()
    260     {
    261         return bigIntToBytes(result);
    262     }
    263 
    264     public static class DH
    265         extends KeyAgreementSpi
    266     {
    267         public DH()
    268         {
    269             super("ECDH", new ECDHBasicAgreement(), null);
    270         }
    271     }
    272 
    273     // BEGIN Android-removed: Unsupported algorithms
    274     /*
    275     public static class DHC
    276         extends KeyAgreementSpi
    277     {
    278         public DHC()
    279         {
    280             super("ECDHC", new ECDHCBasicAgreement(), null);
    281         }
    282     }
    283 
    284     public static class MQV
    285         extends KeyAgreementSpi
    286     {
    287         public MQV()
    288         {
    289             super("ECMQV", new ECMQVBasicAgreement(), null);
    290         }
    291     }
    292 
    293     public static class DHwithSHA1KDF
    294         extends KeyAgreementSpi
    295     {
    296         public DHwithSHA1KDF()
    297         {
    298             super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1()));
    299         }
    300     }
    301 
    302     public static class DHwithSHA1KDFAndSharedInfo
    303         extends KeyAgreementSpi
    304     {
    305         public DHwithSHA1KDFAndSharedInfo()
    306         {
    307             super("ECDHwithSHA1KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1()));
    308         }
    309     }
    310 
    311     public static class CDHwithSHA1KDFAndSharedInfo
    312         extends KeyAgreementSpi
    313     {
    314         public CDHwithSHA1KDFAndSharedInfo()
    315         {
    316             super("ECCDHwithSHA1KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1()));
    317         }
    318     }
    319 
    320     public static class DHwithSHA224KDFAndSharedInfo
    321         extends KeyAgreementSpi
    322     {
    323         public DHwithSHA224KDFAndSharedInfo()
    324         {
    325             super("ECDHwithSHA224KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224()));
    326         }
    327     }
    328 
    329     public static class CDHwithSHA224KDFAndSharedInfo
    330         extends KeyAgreementSpi
    331     {
    332         public CDHwithSHA224KDFAndSharedInfo()
    333         {
    334             super("ECCDHwithSHA224KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224()));
    335         }
    336     }
    337 
    338     public static class DHwithSHA256KDFAndSharedInfo
    339         extends KeyAgreementSpi
    340     {
    341         public DHwithSHA256KDFAndSharedInfo()
    342         {
    343             super("ECDHwithSHA256KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256()));
    344         }
    345     }
    346 
    347     public static class CDHwithSHA256KDFAndSharedInfo
    348         extends KeyAgreementSpi
    349     {
    350         public CDHwithSHA256KDFAndSharedInfo()
    351         {
    352             super("ECCDHwithSHA256KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256()));
    353         }
    354     }
    355 
    356     public static class DHwithSHA384KDFAndSharedInfo
    357         extends KeyAgreementSpi
    358     {
    359         public DHwithSHA384KDFAndSharedInfo()
    360         {
    361             super("ECDHwithSHA384KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384()));
    362         }
    363     }
    364 
    365     public static class CDHwithSHA384KDFAndSharedInfo
    366         extends KeyAgreementSpi
    367     {
    368         public CDHwithSHA384KDFAndSharedInfo()
    369         {
    370             super("ECCDHwithSHA384KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384()));
    371         }
    372     }
    373 
    374     public static class DHwithSHA512KDFAndSharedInfo
    375          extends KeyAgreementSpi
    376      {
    377          public DHwithSHA512KDFAndSharedInfo()
    378          {
    379              super("ECDHwithSHA512KDF", new ECDHBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
    380          }
    381      }
    382 
    383      public static class CDHwithSHA512KDFAndSharedInfo
    384          extends KeyAgreementSpi
    385      {
    386          public CDHwithSHA512KDFAndSharedInfo()
    387          {
    388              super("ECCDHwithSHA512KDF", new ECDHCBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
    389          }
    390      }
    391 
    392     public static class MQVwithSHA1KDFAndSharedInfo
    393         extends KeyAgreementSpi
    394     {
    395         public MQVwithSHA1KDFAndSharedInfo()
    396         {
    397             super("ECMQVwithSHA1KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA1()));
    398         }
    399     }
    400 
    401     public static class MQVwithSHA224KDFAndSharedInfo
    402         extends KeyAgreementSpi
    403     {
    404         public MQVwithSHA224KDFAndSharedInfo()
    405         {
    406             super("ECMQVwithSHA224KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA224()));
    407         }
    408     }
    409 
    410     public static class MQVwithSHA256KDFAndSharedInfo
    411         extends KeyAgreementSpi
    412     {
    413         public MQVwithSHA256KDFAndSharedInfo()
    414         {
    415             super("ECMQVwithSHA256KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA256()));
    416         }
    417     }
    418 
    419     public static class MQVwithSHA384KDFAndSharedInfo
    420         extends KeyAgreementSpi
    421     {
    422         public MQVwithSHA384KDFAndSharedInfo()
    423         {
    424             super("ECMQVwithSHA384KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA384()));
    425         }
    426     }
    427 
    428     public static class MQVwithSHA512KDFAndSharedInfo
    429         extends KeyAgreementSpi
    430     {
    431         public MQVwithSHA512KDFAndSharedInfo()
    432         {
    433             super("ECMQVwithSHA512KDF", new ECMQVBasicAgreement(), new KDF2BytesGenerator(DigestFactory.createSHA512()));
    434         }
    435     }
    436 
    437     public static class DHwithSHA1CKDF
    438         extends KeyAgreementSpi
    439     {
    440         public DHwithSHA1CKDF()
    441         {
    442             super("ECDHwithSHA1CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA1()));
    443         }
    444     }
    445 
    446     public static class DHwithSHA256CKDF
    447         extends KeyAgreementSpi
    448     {
    449         public DHwithSHA256CKDF()
    450         {
    451             super("ECDHwithSHA256CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA256()));
    452         }
    453     }
    454 
    455     public static class DHwithSHA384CKDF
    456         extends KeyAgreementSpi
    457     {
    458         public DHwithSHA384CKDF()
    459         {
    460             super("ECDHwithSHA384CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA384()));
    461         }
    462     }
    463 
    464     public static class DHwithSHA512CKDF
    465         extends KeyAgreementSpi
    466     {
    467         public DHwithSHA512CKDF()
    468         {
    469             super("ECDHwithSHA512CKDF", new ECDHCBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA512()));
    470         }
    471     }
    472 
    473     public static class MQVwithSHA1CKDF
    474         extends KeyAgreementSpi
    475     {
    476         public MQVwithSHA1CKDF()
    477         {
    478             super("ECMQVwithSHA1CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA1()));
    479         }
    480     }
    481 
    482     public static class MQVwithSHA224CKDF
    483         extends KeyAgreementSpi
    484     {
    485         public MQVwithSHA224CKDF()
    486         {
    487             super("ECMQVwithSHA224CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA224()));
    488         }
    489     }
    490 
    491     public static class MQVwithSHA256CKDF
    492         extends KeyAgreementSpi
    493     {
    494         public MQVwithSHA256CKDF()
    495         {
    496             super("ECMQVwithSHA256CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA256()));
    497         }
    498     }
    499 
    500     public static class MQVwithSHA384CKDF
    501         extends KeyAgreementSpi
    502     {
    503         public MQVwithSHA384CKDF()
    504         {
    505             super("ECMQVwithSHA384CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA384()));
    506         }
    507     }
    508 
    509     public static class MQVwithSHA512CKDF
    510         extends KeyAgreementSpi
    511     {
    512         public MQVwithSHA512CKDF()
    513         {
    514             super("ECMQVwithSHA512CKDF", new ECMQVBasicAgreement(), new ConcatenationKDFGenerator(DigestFactory.createSHA512()));
    515         }
    516     }
    517     */
    518     // END Android-removed: Unsupported algorithms
    519 }
    520