8166596: TLS support for the EdDSA signature algorithm

Reviewed-by: xuelei
This commit is contained in:
Jamil Nimeh 2020-12-03 06:12:07 +00:00
parent 3932527288
commit d80ae05f61
9 changed files with 825 additions and 60 deletions

View file

@ -67,8 +67,8 @@ final class CertificateRequest {
// TLS 1.2 and prior versions
private static enum ClientCertificateType {
// RFC 2246
RSA_SIGN ((byte)0x01, "rsa_sign", "RSA", true),
DSS_SIGN ((byte)0x02, "dss_sign", "DSA", true),
RSA_SIGN ((byte)0x01, "rsa_sign", List.of("RSA"), true),
DSS_SIGN ((byte)0x02, "dss_sign", List.of("DSA"), true),
RSA_FIXED_DH ((byte)0x03, "rsa_fixed_dh"),
DSS_FIXED_DH ((byte)0x04, "dss_fixed_dh"),
@ -77,9 +77,10 @@ final class CertificateRequest {
DSS_EPHEMERAL_DH ((byte)0x06, "dss_ephemeral_dh"),
FORTEZZA_DMS ((byte)0x14, "fortezza_dms"),
// RFC 4492
// RFC 4492 and 8442
ECDSA_SIGN ((byte)0x40, "ecdsa_sign",
"EC", JsseJce.isEcAvailable()),
List.of("EC", "EdDSA"),
JsseJce.isEcAvailable()),
RSA_FIXED_ECDH ((byte)0x41, "rsa_fixed_ecdh"),
ECDSA_FIXED_ECDH ((byte)0x42, "ecdsa_fixed_ecdh");
@ -95,7 +96,7 @@ final class CertificateRequest {
final byte id;
final String name;
final String keyAlgorithm;
final List<String> keyAlgorithm;
final boolean isAvailable;
private ClientCertificateType(byte id, String name) {
@ -103,7 +104,7 @@ final class CertificateRequest {
}
private ClientCertificateType(byte id, String name,
String keyAlgorithm, boolean isAvailable) {
List<String> keyAlgorithm, boolean isAvailable) {
this.id = id;
this.name = name;
this.keyAlgorithm = keyAlgorithm;
@ -134,7 +135,11 @@ final class CertificateRequest {
for (byte id : ids) {
ClientCertificateType cct = ClientCertificateType.valueOf(id);
if (cct.isAvailable) {
keyTypes.add(cct.keyAlgorithm);
cct.keyAlgorithm.forEach(key -> {
if (!keyTypes.contains(key)) {
keyTypes.add(key);
}
});
}
}

View file

@ -459,6 +459,9 @@ final class CertificateVerify {
case "EC":
signer = Signature.getInstance(JsseJce.SIGNATURE_RAWECDSA);
break;
case "EdDSA":
signer = Signature.getInstance(JsseJce.SIGNATURE_EDDSA);
break;
default:
throw new SignatureException("Unrecognized algorithm: "
+ algorithm);

View file

@ -424,6 +424,9 @@ final class ECDHServerKeyExchange {
case "EC":
signer = Signature.getInstance(JsseJce.SIGNATURE_ECDSA);
break;
case "EdDSA":
signer = Signature.getInstance(JsseJce.SIGNATURE_EDDSA);
break;
case "RSA":
signer = RSASignature.getInstance();
break;

View file

@ -90,6 +90,11 @@ final class JsseJce {
*/
static final String SIGNATURE_ECDSA = "SHA1withECDSA";
/**
* JCA identifier for EdDSA signatures.
*/
static final String SIGNATURE_EDDSA = "EdDSA";
/**
* JCA identifier string for Raw DSA, i.e. a DSA signature without
* hashing where the application provides the SHA-1 hash of the data.

View file

@ -274,11 +274,11 @@ enum SSLExtension implements SSLStringizer {
SIGNED_CERT_TIMESTAMP (0x0012, "signed_certificate_timestamp"),
// extensions defined in RFC 7250
CLIENT_CERT_TYPE (0x0013, "padding"),
CLIENT_CERT_TYPE (0x0013, "client_certificate_type"),
SERVER_CERT_TYPE (0x0014, "server_certificate_type"),
// extensions defined in RFC 7685
PADDING (0x0015, "client_certificate_type"),
PADDING (0x0015, "padding"),
// extensions defined in RFC 7366
ENCRYPT_THEN_MAC (0x0016, "encrypt_then_mac"),

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,18 +29,23 @@ import java.io.IOException;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Possession;
final class SSLKeyExchange implements SSLKeyAgreementGenerator,
SSLHandshakeBinding {
private final SSLAuthentication authentication;
private final List<SSLAuthentication> authentication;
private final SSLKeyAgreement keyAgreement;
SSLKeyExchange(X509Authentication authentication,
SSLKeyExchange(List<X509Authentication> authentication,
SSLKeyAgreement keyAgreement) {
this.authentication = authentication;
if (authentication != null) {
this.authentication = List.copyOf(authentication);
} else {
this.authentication = null;
}
this.keyAgreement = keyAgreement;
}
@ -48,7 +53,15 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
// authentication
SSLPossession authPossession = null;
if (authentication != null) {
authPossession = authentication.createPossession(context);
// Loop through potential authentication types and end at
// the first non-null possession.
for (SSLAuthentication authType : authentication) {
if ((authPossession = authType.createPossession(context))
!= null) {
break;
}
}
if (authPossession == null) {
return new SSLPossession[0];
} else if (context instanceof ServerHandshakeContext) {
@ -109,12 +122,14 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
@Override
public SSLHandshake[] getRelatedHandshakers(
HandshakeContext handshakeContext) {
SSLHandshake[] auHandshakes;
SSLHandshake[] auHandshakes = null;
if (authentication != null) {
auHandshakes =
authentication.getRelatedHandshakers(handshakeContext);
} else {
auHandshakes = null;
for (SSLAuthentication authType : authentication) {
auHandshakes = authType.getRelatedHandshakers(handshakeContext);
if (auHandshakes != null && auHandshakes.length > 0) {
break;
}
}
}
SSLHandshake[] kaHandshakes =
@ -136,12 +151,14 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
@Override
public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers(
HandshakeContext handshakeContext) {
Map.Entry<Byte, HandshakeProducer>[] auProducers;
Map.Entry<Byte, HandshakeProducer>[] auProducers = null;
if (authentication != null) {
auProducers =
authentication.getHandshakeProducers(handshakeContext);
} else {
auProducers = null;
for (SSLAuthentication authType : authentication) {
auProducers = authType.getHandshakeProducers(handshakeContext);
if (auProducers != null && auProducers.length > 0) {
break;
}
}
}
Map.Entry<Byte, HandshakeProducer>[] kaProducers =
@ -163,12 +180,14 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
@Override
public Map.Entry<Byte, SSLConsumer>[] getHandshakeConsumers(
HandshakeContext handshakeContext) {
Map.Entry<Byte, SSLConsumer>[] auConsumers;
Map.Entry<Byte, SSLConsumer>[] auConsumers = null;
if (authentication != null) {
auConsumers =
authentication.getHandshakeConsumers(handshakeContext);
} else {
auConsumers = null;
for (SSLAuthentication authType : authentication) {
auConsumers = authType.getHandshakeConsumers(handshakeContext);
if (auConsumers != null && auConsumers.length > 0) {
break;
}
}
}
Map.Entry<Byte, SSLConsumer>[] kaConsumers =
@ -247,37 +266,37 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
private static class SSLKeyExRSA {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.RSA, T12KeyAgreement.RSA);
List.of(X509Authentication.RSA), T12KeyAgreement.RSA);
}
private static class SSLKeyExRSAExport {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.RSA, T12KeyAgreement.RSA_EXPORT);
List.of(X509Authentication.RSA), T12KeyAgreement.RSA_EXPORT);
}
private static class SSLKeyExDHEDSS {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.DSA, T12KeyAgreement.DHE);
List.of(X509Authentication.DSA), T12KeyAgreement.DHE);
}
private static class SSLKeyExDHEDSSExport {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.DSA, T12KeyAgreement.DHE_EXPORT);
List.of(X509Authentication.DSA), T12KeyAgreement.DHE_EXPORT);
}
private static class SSLKeyExDHERSA {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.RSA, T12KeyAgreement.DHE);
List.of(X509Authentication.RSA), T12KeyAgreement.DHE);
}
private static class SSLKeyExDHERSAOrPSS {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.RSA_OR_PSS, T12KeyAgreement.DHE);
List.of(X509Authentication.RSA_OR_PSS), T12KeyAgreement.DHE);
}
private static class SSLKeyExDHERSAExport {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.RSA, T12KeyAgreement.DHE_EXPORT);
List.of(X509Authentication.RSA), T12KeyAgreement.DHE_EXPORT);
}
private static class SSLKeyExDHANON {
@ -292,27 +311,28 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
private static class SSLKeyExECDHECDSA {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.EC, T12KeyAgreement.ECDH);
List.of(X509Authentication.EC), T12KeyAgreement.ECDH);
}
private static class SSLKeyExECDHRSA {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.EC, T12KeyAgreement.ECDH);
List.of(X509Authentication.EC), T12KeyAgreement.ECDH);
}
private static class SSLKeyExECDHEECDSA {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.EC, T12KeyAgreement.ECDHE);
List.of(X509Authentication.EC, X509Authentication.EDDSA),
T12KeyAgreement.ECDHE);
}
private static class SSLKeyExECDHERSA {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.RSA, T12KeyAgreement.ECDHE);
List.of(X509Authentication.RSA), T12KeyAgreement.ECDHE);
}
private static class SSLKeyExECDHERSAOrPSS {
private static SSLKeyExchange KE = new SSLKeyExchange(
X509Authentication.RSA_OR_PSS, T12KeyAgreement.ECDHE);
List.of(X509Authentication.RSA_OR_PSS), T12KeyAgreement.ECDHE);
}
private static class SSLKeyExECDHANON {

View file

@ -47,14 +47,6 @@ import sun.security.util.KeyUtil;
import sun.security.util.SignatureUtil;
enum SignatureScheme {
// EdDSA algorithms
ED25519 (0x0807, "ed25519", "ed25519",
"ed25519",
ProtocolVersion.PROTOCOLS_OF_13),
ED448 (0x0808, "ed448", "ed448",
"ed448",
ProtocolVersion.PROTOCOLS_OF_13),
// ECDSA algorithms
ECDSA_SECP256R1_SHA256 (0x0403, "ecdsa_secp256r1_sha256",
"SHA256withECDSA",
@ -72,6 +64,14 @@ enum SignatureScheme {
NamedGroup.SECP521_R1,
ProtocolVersion.PROTOCOLS_TO_13),
// EdDSA algorithms
ED25519 (0x0807, "ed25519", "Ed25519",
"EdDSA",
ProtocolVersion.PROTOCOLS_12_13),
ED448 (0x0808, "ed448", "Ed448",
"EdDSA",
ProtocolVersion.PROTOCOLS_12_13),
// RSASSA-PSS algorithms with public key OID rsaEncryption
//
// The minimalKeySize is calculated as (See RFC 8017 for details):
@ -275,16 +275,6 @@ enum SignatureScheme {
boolean mediator = true;
// Disable EdDSA algorithms for TLS. Remove this when support is added.
if (id == 0x0807 || id == 0x0808) {
mediator = false;
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.warning(
"Signature algorithm, " + algorithm +
", not supported by JSSE");
}
}
// An EC provider, for example the SunEC provider, may support
// AlgorithmParameters but not KeyPairGenerator or Signature.
//

View file

@ -64,7 +64,10 @@ enum X509Authentication implements SSLAuthentication {
// Require EC public key
EC ("EC", new X509PossessionGenerator(
new String[] {"EC"}));
new String[] {"EC"})),
// Edwards-Curve key
EDDSA ("EdDSA", new X509PossessionGenerator(
new String[] {"EdDSA"}));
final String keyType;
final SSLPossessionGenerator possessionGenerator;