Skip to content
This repository has been archived by the owner before Nov 9, 2022. It is now read-only.
Permalink
Browse files
8166596: TLS support for the EdDSA signature algorithm
Reviewed-by: xuelei
  • Loading branch information
Jamil Nimeh committed Dec 3, 2020
1 parent 3932527 commit d80ae05f617b35bd327e03869284de0c41adb94d
Show file tree
Hide file tree
Showing 9 changed files with 825 additions and 60 deletions.
@@ -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 @@ private static enum ClientCertificateType {
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,15 +96,15 @@ private static enum ClientCertificateType {

final byte id;
final String name;
final String keyAlgorithm;
final List<String> keyAlgorithm;
final boolean isAvailable;

private ClientCertificateType(byte id, String name) {
this(id, name, null, false);
}

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 @@ private static String[] getKeyTypes(byte[] ids) {
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);
}
});
}
}

@@ -459,6 +459,9 @@ private static Signature getSignature(String algorithm,
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);
@@ -424,6 +424,9 @@ private static Signature getSignature(String keyAlgorithm,
case "EC":
signer = Signature.getInstance(JsseJce.SIGNATURE_ECDSA);
break;
case "EdDSA":
signer = Signature.getInstance(JsseJce.SIGNATURE_EDDSA);
break;
case "RSA":
signer = RSASignature.getInstance();
break;
@@ -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.
@@ -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"),
@@ -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,26 +29,39 @@
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;
}

SSLPossession[] createPossessions(HandshakeContext context) {
// 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 @@ public SSLKeyDerivation createKeyDerivation(
@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 @@ public SSLHandshake[] getRelatedHandshakers(
@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 @@ public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers(
@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 @@ static SSLKeyExchange valueOf(NamedGroup namedGroup) {

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 @@ private static class SSLKeyExDHANONExport {

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 {
@@ -47,14 +47,6 @@
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 @@ private SignatureScheme(int id, String name,

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.
//
@@ -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;

0 comments on commit d80ae05

Please sign in to comment.