mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 23:34:52 +02:00
8166596
: TLS support for the EdDSA signature algorithm
Reviewed-by: xuelei
This commit is contained in:
parent
3932527288
commit
d80ae05f61
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 @@ 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,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 {
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue