44 import javax.crypto.spec.DHParameterSpec;
45 import javax.crypto.spec.DHPublicKeySpec;
46 import javax.crypto.spec.SecretKeySpec;
47 import javax.net.ssl.SSLHandshakeException;
48 import sun.security.action.GetPropertyAction;
49 import sun.security.ssl.CipherSuite.HashAlg;
50 import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
51 import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
52 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
53 import sun.security.ssl.X509Authentication.X509Possession;
54 import sun.security.util.KeyUtil;
55
56 final class DHKeyExchange {
57 static final SSLPossessionGenerator poGenerator =
58 new DHEPossessionGenerator(false);
59 static final SSLPossessionGenerator poExportableGenerator =
60 new DHEPossessionGenerator(true);
61 static final SSLKeyAgreementGenerator kaGenerator =
62 new DHEKAGenerator();
63
64 static final class DHECredentials implements SSLCredentials {
65 final DHPublicKey popPublicKey;
66 final NamedGroup namedGroup;
67
68 DHECredentials(DHPublicKey popPublicKey, NamedGroup namedGroup) {
69 this.popPublicKey = popPublicKey;
70 this.namedGroup = namedGroup;
71 }
72
73 static DHECredentials valueOf(NamedGroup ng,
74 byte[] encodedPublic) throws IOException, GeneralSecurityException {
75
76 if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
77 throw new RuntimeException(
78 "Credentials decoding: Not FFDHE named group");
79 }
80
81 if (encodedPublic == null || encodedPublic.length == 0) {
82 return null;
83 }
84
85 DHParameterSpec params = (DHParameterSpec)ng.getParameterSpec();
86 if (params == null) {
87 return null;
88 }
89
90 KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
91 DHPublicKeySpec spec = new DHPublicKeySpec(
92 new BigInteger(1, encodedPublic),
425 DHParameterSpec cps = dhec.popPublicKey.getParams();
426 if (pps.getP().equals(cps.getP()) &&
427 pps.getG().equals(cps.getG())) {
428 dheCredentials = (DHECredentials)cred;
429 break;
430 }
431 }
432 }
433
434 if (dheCredentials != null) {
435 dhePossession = (DHEPossession)poss;
436 break;
437 }
438 }
439
440 if (dhePossession == null || dheCredentials == null) {
441 context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
442 "No sufficient DHE key agreement parameters negotiated");
443 }
444
445 return new DHEKAKeyDerivation(context,
446 dhePossession.privateKey, dheCredentials.popPublicKey);
447 }
448
449 private static final
450 class DHEKAKeyDerivation implements SSLKeyDerivation {
451 private final HandshakeContext context;
452 private final PrivateKey localPrivateKey;
453 private final PublicKey peerPublicKey;
454
455 DHEKAKeyDerivation(HandshakeContext context,
456 PrivateKey localPrivateKey,
457 PublicKey peerPublicKey) {
458 this.context = context;
459 this.localPrivateKey = localPrivateKey;
460 this.peerPublicKey = peerPublicKey;
461 }
462
463 @Override
464 public SecretKey deriveKey(String algorithm,
465 AlgorithmParameterSpec params) throws IOException {
466 if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
467 return t12DeriveKey(algorithm, params);
468 } else {
469 return t13DeriveKey(algorithm, params);
470 }
471 }
472
473 private SecretKey t12DeriveKey(String algorithm,
474 AlgorithmParameterSpec params) throws IOException {
475 try {
476 KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
477 ka.init(localPrivateKey);
478 ka.doPhase(peerPublicKey, true);
479 SecretKey preMasterSecret =
480 ka.generateSecret("TlsPremasterSecret");
481 SSLMasterKeyDerivation mskd =
482 SSLMasterKeyDerivation.valueOf(
483 context.negotiatedProtocol);
484 if (mskd == null) {
485 // unlikely
486 throw new SSLHandshakeException(
487 "No expected master key derivation for protocol: " +
488 context.negotiatedProtocol.name);
489 }
490 SSLKeyDerivation kd = mskd.createKeyDerivation(
491 context, preMasterSecret);
492 return kd.deriveKey("MasterSecret", params);
493 } catch (GeneralSecurityException gse) {
494 throw (SSLHandshakeException) new SSLHandshakeException(
495 "Could not generate secret").initCause(gse);
496 }
497 }
498
499 private SecretKey t13DeriveKey(String algorithm,
500 AlgorithmParameterSpec params) throws IOException {
501 try {
502 KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
503 ka.init(localPrivateKey);
504 ka.doPhase(peerPublicKey, true);
505 SecretKey sharedSecret =
506 ka.generateSecret("TlsPremasterSecret");
507
508 HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
509 SSLKeyDerivation kd = context.handshakeKeyDerivation;
510 HKDF hkdf = new HKDF(hashAlg.name);
511 if (kd == null) { // No PSK is in use.
512 // If PSK is not in use Early Secret will still be
513 // HKDF-Extract(0, 0).
514 byte[] zeros = new byte[hashAlg.hashLength];
515 SecretKeySpec ikm =
516 new SecretKeySpec(zeros, "TlsPreSharedSecret");
517 SecretKey earlySecret =
518 hkdf.extract(zeros, ikm, "TlsEarlySecret");
519 kd = new SSLSecretDerivation(context, earlySecret);
520 }
521
522 // derive salt secret
523 SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
524
525 // derive handshake secret
526 return hkdf.extract(saltSecret, sharedSecret, algorithm);
527 } catch (GeneralSecurityException gse) {
528 throw (SSLHandshakeException) new SSLHandshakeException(
529 "Could not generate secret").initCause(gse);
530 }
531 }
532 }
533 }
534 }
|
44 import javax.crypto.spec.DHParameterSpec;
45 import javax.crypto.spec.DHPublicKeySpec;
46 import javax.crypto.spec.SecretKeySpec;
47 import javax.net.ssl.SSLHandshakeException;
48 import sun.security.action.GetPropertyAction;
49 import sun.security.ssl.CipherSuite.HashAlg;
50 import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
51 import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
52 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
53 import sun.security.ssl.X509Authentication.X509Possession;
54 import sun.security.util.KeyUtil;
55
56 final class DHKeyExchange {
57 static final SSLPossessionGenerator poGenerator =
58 new DHEPossessionGenerator(false);
59 static final SSLPossessionGenerator poExportableGenerator =
60 new DHEPossessionGenerator(true);
61 static final SSLKeyAgreementGenerator kaGenerator =
62 new DHEKAGenerator();
63
64 static final class DHECredentials implements SSLKeyAgreementCredentials {
65 final DHPublicKey popPublicKey;
66 final NamedGroup namedGroup;
67
68 DHECredentials(DHPublicKey popPublicKey, NamedGroup namedGroup) {
69 this.popPublicKey = popPublicKey;
70 this.namedGroup = namedGroup;
71 }
72
73 @Override
74 public PublicKey getPublicKey() {
75 return popPublicKey;
76 }
77
78 static DHECredentials valueOf(NamedGroup ng,
79 byte[] encodedPublic) throws IOException, GeneralSecurityException {
80
81 if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
82 throw new RuntimeException(
83 "Credentials decoding: Not FFDHE named group");
84 }
85
86 if (encodedPublic == null || encodedPublic.length == 0) {
87 return null;
88 }
89
90 DHParameterSpec params = (DHParameterSpec)ng.getParameterSpec();
91 if (params == null) {
92 return null;
93 }
94
95 KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
96 DHPublicKeySpec spec = new DHPublicKeySpec(
97 new BigInteger(1, encodedPublic),
430 DHParameterSpec cps = dhec.popPublicKey.getParams();
431 if (pps.getP().equals(cps.getP()) &&
432 pps.getG().equals(cps.getG())) {
433 dheCredentials = (DHECredentials)cred;
434 break;
435 }
436 }
437 }
438
439 if (dheCredentials != null) {
440 dhePossession = (DHEPossession)poss;
441 break;
442 }
443 }
444
445 if (dhePossession == null || dheCredentials == null) {
446 context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
447 "No sufficient DHE key agreement parameters negotiated");
448 }
449
450 return new KAKeyDerivation("DiffieHellman", context,
451 dhePossession.privateKey, dheCredentials.popPublicKey);
452 }
453 }
454 }
|