package sun.security.ssl;
import java.security.*;
import java.security.interfaces.ECPublicKey;
import java.security.spec.*;
import java.util.EnumSet;
import javax.crypto.SecretKey;
import javax.crypto.KeyAgreement;
import javax.net.ssl.SSLHandshakeException;
final class ECDHCrypt {
private PrivateKey privateKey;
private ECPublicKey publicKey;
ECDHCrypt(PrivateKey privateKey, PublicKey publicKey) {
this.privateKey = privateKey;
this.publicKey = (ECPublicKey)publicKey;
}
ECDHCrypt(NamedGroup namedGroup, SecureRandom random) {
try {
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
ECGenParameterSpec params =
SupportedGroupsExtension.getECGenParamSpec(namedGroup);
kpg.initialize(params, random);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
publicKey = (ECPublicKey)kp.getPublic();
} catch (GeneralSecurityException e) {
throw new RuntimeException("Could not generate ECDH keypair", e);
}
}
ECDHCrypt(ECParameterSpec params, SecureRandom random) {
try {
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
kpg.initialize(params, random);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
publicKey = (ECPublicKey)kp.getPublic();
} catch (GeneralSecurityException e) {
throw new RuntimeException("Could not generate ECDH keypair", e);
}
}
PublicKey getPublicKey() {
return publicKey;
}
SecretKey getAgreedSecret(
PublicKey peerPublicKey) throws SSLHandshakeException {
try {
KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
ka.init(privateKey);
ka.doPhase(peerPublicKey, true);
return ka.generateSecret("TlsPremasterSecret");
} catch (GeneralSecurityException e) {
throw (SSLHandshakeException) new SSLHandshakeException(
"Could not generate secret").initCause(e);
}
}
SecretKey getAgreedSecret(
byte[] encodedPoint) throws SSLHandshakeException {
try {
ECParameterSpec params = publicKey.getParams();
ECPoint point =
JsseJce.decodePoint(encodedPoint, params.getCurve());
KeyFactory kf = JsseJce.getKeyFactory("EC");
ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
PublicKey peerPublicKey = kf.generatePublic(spec);
return getAgreedSecret(peerPublicKey);
} catch (GeneralSecurityException | java.io.IOException e) {
throw (SSLHandshakeException) new SSLHandshakeException(
"Could not generate secret").initCause(e);
}
}
void checkConstraints(AlgorithmConstraints constraints,
byte[] encodedPoint) throws SSLHandshakeException {
try {
ECParameterSpec params = publicKey.getParams();
ECPoint point =
JsseJce.decodePoint(encodedPoint, params.getCurve());
ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
KeyFactory kf = JsseJce.getKeyFactory("EC");
ECPublicKey publicKey = (ECPublicKey)kf.generatePublic(spec);
if (!constraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
throw new SSLHandshakeException(
"ECPublicKey does not comply to algorithm constraints");
}
} catch (GeneralSecurityException | java.io.IOException e) {
throw (SSLHandshakeException) new SSLHandshakeException(
"Could not generate ECPublicKey").initCause(e);
}
}
}