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