Skip to content

Commit d80ae05

Browse files
author
Jamil Nimeh
committed
8166596: TLS support for the EdDSA signature algorithm
Reviewed-by: xuelei
1 parent 3932527 commit d80ae05

File tree

9 files changed

+825
-60
lines changed

9 files changed

+825
-60
lines changed

src/java.base/share/classes/sun/security/ssl/CertificateRequest.java

+12-7
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ final class CertificateRequest {
6767
// TLS 1.2 and prior versions
6868
private static enum ClientCertificateType {
6969
// RFC 2246
70-
RSA_SIGN ((byte)0x01, "rsa_sign", "RSA", true),
71-
DSS_SIGN ((byte)0x02, "dss_sign", "DSA", true),
70+
RSA_SIGN ((byte)0x01, "rsa_sign", List.of("RSA"), true),
71+
DSS_SIGN ((byte)0x02, "dss_sign", List.of("DSA"), true),
7272
RSA_FIXED_DH ((byte)0x03, "rsa_fixed_dh"),
7373
DSS_FIXED_DH ((byte)0x04, "dss_fixed_dh"),
7474

@@ -77,9 +77,10 @@ private static enum ClientCertificateType {
7777
DSS_EPHEMERAL_DH ((byte)0x06, "dss_ephemeral_dh"),
7878
FORTEZZA_DMS ((byte)0x14, "fortezza_dms"),
7979

80-
// RFC 4492
80+
// RFC 4492 and 8442
8181
ECDSA_SIGN ((byte)0x40, "ecdsa_sign",
82-
"EC", JsseJce.isEcAvailable()),
82+
List.of("EC", "EdDSA"),
83+
JsseJce.isEcAvailable()),
8384
RSA_FIXED_ECDH ((byte)0x41, "rsa_fixed_ecdh"),
8485
ECDSA_FIXED_ECDH ((byte)0x42, "ecdsa_fixed_ecdh");
8586

@@ -95,15 +96,15 @@ private static enum ClientCertificateType {
9596

9697
final byte id;
9798
final String name;
98-
final String keyAlgorithm;
99+
final List<String> keyAlgorithm;
99100
final boolean isAvailable;
100101

101102
private ClientCertificateType(byte id, String name) {
102103
this(id, name, null, false);
103104
}
104105

105106
private ClientCertificateType(byte id, String name,
106-
String keyAlgorithm, boolean isAvailable) {
107+
List<String> keyAlgorithm, boolean isAvailable) {
107108
this.id = id;
108109
this.name = name;
109110
this.keyAlgorithm = keyAlgorithm;
@@ -134,7 +135,11 @@ private static String[] getKeyTypes(byte[] ids) {
134135
for (byte id : ids) {
135136
ClientCertificateType cct = ClientCertificateType.valueOf(id);
136137
if (cct.isAvailable) {
137-
keyTypes.add(cct.keyAlgorithm);
138+
cct.keyAlgorithm.forEach(key -> {
139+
if (!keyTypes.contains(key)) {
140+
keyTypes.add(key);
141+
}
142+
});
138143
}
139144
}
140145

src/java.base/share/classes/sun/security/ssl/CertificateVerify.java

+3
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,9 @@ private static Signature getSignature(String algorithm,
459459
case "EC":
460460
signer = Signature.getInstance(JsseJce.SIGNATURE_RAWECDSA);
461461
break;
462+
case "EdDSA":
463+
signer = Signature.getInstance(JsseJce.SIGNATURE_EDDSA);
464+
break;
462465
default:
463466
throw new SignatureException("Unrecognized algorithm: "
464467
+ algorithm);

src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java

+3
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,9 @@ private static Signature getSignature(String keyAlgorithm,
424424
case "EC":
425425
signer = Signature.getInstance(JsseJce.SIGNATURE_ECDSA);
426426
break;
427+
case "EdDSA":
428+
signer = Signature.getInstance(JsseJce.SIGNATURE_EDDSA);
429+
break;
427430
case "RSA":
428431
signer = RSASignature.getInstance();
429432
break;

src/java.base/share/classes/sun/security/ssl/JsseJce.java

+5
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ final class JsseJce {
9090
*/
9191
static final String SIGNATURE_ECDSA = "SHA1withECDSA";
9292

93+
/**
94+
* JCA identifier for EdDSA signatures.
95+
*/
96+
static final String SIGNATURE_EDDSA = "EdDSA";
97+
9398
/**
9499
* JCA identifier string for Raw DSA, i.e. a DSA signature without
95100
* hashing where the application provides the SHA-1 hash of the data.

src/java.base/share/classes/sun/security/ssl/SSLExtension.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,11 @@ enum SSLExtension implements SSLStringizer {
274274
SIGNED_CERT_TIMESTAMP (0x0012, "signed_certificate_timestamp"),
275275

276276
// extensions defined in RFC 7250
277-
CLIENT_CERT_TYPE (0x0013, "padding"),
277+
CLIENT_CERT_TYPE (0x0013, "client_certificate_type"),
278278
SERVER_CERT_TYPE (0x0014, "server_certificate_type"),
279279

280280
// extensions defined in RFC 7685
281-
PADDING (0x0015, "client_certificate_type"),
281+
PADDING (0x0015, "padding"),
282282

283283
// extensions defined in RFC 7366
284284
ENCRYPT_THEN_MAC (0x0016, "encrypt_then_mac"),

src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java

+52-32
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,26 +29,39 @@
2929
import java.util.AbstractMap.SimpleImmutableEntry;
3030
import java.util.Arrays;
3131
import java.util.HashMap;
32+
import java.util.List;
3233
import java.util.Map;
3334
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
3435
import sun.security.ssl.X509Authentication.X509Possession;
3536

3637
final class SSLKeyExchange implements SSLKeyAgreementGenerator,
3738
SSLHandshakeBinding {
38-
private final SSLAuthentication authentication;
39+
private final List<SSLAuthentication> authentication;
3940
private final SSLKeyAgreement keyAgreement;
4041

41-
SSLKeyExchange(X509Authentication authentication,
42+
SSLKeyExchange(List<X509Authentication> authentication,
4243
SSLKeyAgreement keyAgreement) {
43-
this.authentication = authentication;
44+
if (authentication != null) {
45+
this.authentication = List.copyOf(authentication);
46+
} else {
47+
this.authentication = null;
48+
}
4449
this.keyAgreement = keyAgreement;
4550
}
4651

4752
SSLPossession[] createPossessions(HandshakeContext context) {
4853
// authentication
4954
SSLPossession authPossession = null;
5055
if (authentication != null) {
51-
authPossession = authentication.createPossession(context);
56+
// Loop through potential authentication types and end at
57+
// the first non-null possession.
58+
for (SSLAuthentication authType : authentication) {
59+
if ((authPossession = authType.createPossession(context))
60+
!= null) {
61+
break;
62+
}
63+
}
64+
5265
if (authPossession == null) {
5366
return new SSLPossession[0];
5467
} else if (context instanceof ServerHandshakeContext) {
@@ -109,12 +122,14 @@ public SSLKeyDerivation createKeyDerivation(
109122
@Override
110123
public SSLHandshake[] getRelatedHandshakers(
111124
HandshakeContext handshakeContext) {
112-
SSLHandshake[] auHandshakes;
125+
SSLHandshake[] auHandshakes = null;
113126
if (authentication != null) {
114-
auHandshakes =
115-
authentication.getRelatedHandshakers(handshakeContext);
116-
} else {
117-
auHandshakes = null;
127+
for (SSLAuthentication authType : authentication) {
128+
auHandshakes = authType.getRelatedHandshakers(handshakeContext);
129+
if (auHandshakes != null && auHandshakes.length > 0) {
130+
break;
131+
}
132+
}
118133
}
119134

120135
SSLHandshake[] kaHandshakes =
@@ -136,12 +151,14 @@ public SSLHandshake[] getRelatedHandshakers(
136151
@Override
137152
public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers(
138153
HandshakeContext handshakeContext) {
139-
Map.Entry<Byte, HandshakeProducer>[] auProducers;
154+
Map.Entry<Byte, HandshakeProducer>[] auProducers = null;
140155
if (authentication != null) {
141-
auProducers =
142-
authentication.getHandshakeProducers(handshakeContext);
143-
} else {
144-
auProducers = null;
156+
for (SSLAuthentication authType : authentication) {
157+
auProducers = authType.getHandshakeProducers(handshakeContext);
158+
if (auProducers != null && auProducers.length > 0) {
159+
break;
160+
}
161+
}
145162
}
146163

147164
Map.Entry<Byte, HandshakeProducer>[] kaProducers =
@@ -163,12 +180,14 @@ public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers(
163180
@Override
164181
public Map.Entry<Byte, SSLConsumer>[] getHandshakeConsumers(
165182
HandshakeContext handshakeContext) {
166-
Map.Entry<Byte, SSLConsumer>[] auConsumers;
183+
Map.Entry<Byte, SSLConsumer>[] auConsumers = null;
167184
if (authentication != null) {
168-
auConsumers =
169-
authentication.getHandshakeConsumers(handshakeContext);
170-
} else {
171-
auConsumers = null;
185+
for (SSLAuthentication authType : authentication) {
186+
auConsumers = authType.getHandshakeConsumers(handshakeContext);
187+
if (auConsumers != null && auConsumers.length > 0) {
188+
break;
189+
}
190+
}
172191
}
173192

174193
Map.Entry<Byte, SSLConsumer>[] kaConsumers =
@@ -247,37 +266,37 @@ static SSLKeyExchange valueOf(NamedGroup namedGroup) {
247266

248267
private static class SSLKeyExRSA {
249268
private static SSLKeyExchange KE = new SSLKeyExchange(
250-
X509Authentication.RSA, T12KeyAgreement.RSA);
269+
List.of(X509Authentication.RSA), T12KeyAgreement.RSA);
251270
}
252271

253272
private static class SSLKeyExRSAExport {
254273
private static SSLKeyExchange KE = new SSLKeyExchange(
255-
X509Authentication.RSA, T12KeyAgreement.RSA_EXPORT);
274+
List.of(X509Authentication.RSA), T12KeyAgreement.RSA_EXPORT);
256275
}
257276

258277
private static class SSLKeyExDHEDSS {
259278
private static SSLKeyExchange KE = new SSLKeyExchange(
260-
X509Authentication.DSA, T12KeyAgreement.DHE);
279+
List.of(X509Authentication.DSA), T12KeyAgreement.DHE);
261280
}
262281

263282
private static class SSLKeyExDHEDSSExport {
264283
private static SSLKeyExchange KE = new SSLKeyExchange(
265-
X509Authentication.DSA, T12KeyAgreement.DHE_EXPORT);
284+
List.of(X509Authentication.DSA), T12KeyAgreement.DHE_EXPORT);
266285
}
267286

268287
private static class SSLKeyExDHERSA {
269288
private static SSLKeyExchange KE = new SSLKeyExchange(
270-
X509Authentication.RSA, T12KeyAgreement.DHE);
289+
List.of(X509Authentication.RSA), T12KeyAgreement.DHE);
271290
}
272291

273292
private static class SSLKeyExDHERSAOrPSS {
274293
private static SSLKeyExchange KE = new SSLKeyExchange(
275-
X509Authentication.RSA_OR_PSS, T12KeyAgreement.DHE);
294+
List.of(X509Authentication.RSA_OR_PSS), T12KeyAgreement.DHE);
276295
}
277296

278297
private static class SSLKeyExDHERSAExport {
279298
private static SSLKeyExchange KE = new SSLKeyExchange(
280-
X509Authentication.RSA, T12KeyAgreement.DHE_EXPORT);
299+
List.of(X509Authentication.RSA), T12KeyAgreement.DHE_EXPORT);
281300
}
282301

283302
private static class SSLKeyExDHANON {
@@ -292,27 +311,28 @@ private static class SSLKeyExDHANONExport {
292311

293312
private static class SSLKeyExECDHECDSA {
294313
private static SSLKeyExchange KE = new SSLKeyExchange(
295-
X509Authentication.EC, T12KeyAgreement.ECDH);
314+
List.of(X509Authentication.EC), T12KeyAgreement.ECDH);
296315
}
297316

298317
private static class SSLKeyExECDHRSA {
299318
private static SSLKeyExchange KE = new SSLKeyExchange(
300-
X509Authentication.EC, T12KeyAgreement.ECDH);
319+
List.of(X509Authentication.EC), T12KeyAgreement.ECDH);
301320
}
302321

303322
private static class SSLKeyExECDHEECDSA {
304323
private static SSLKeyExchange KE = new SSLKeyExchange(
305-
X509Authentication.EC, T12KeyAgreement.ECDHE);
324+
List.of(X509Authentication.EC, X509Authentication.EDDSA),
325+
T12KeyAgreement.ECDHE);
306326
}
307327

308328
private static class SSLKeyExECDHERSA {
309329
private static SSLKeyExchange KE = new SSLKeyExchange(
310-
X509Authentication.RSA, T12KeyAgreement.ECDHE);
330+
List.of(X509Authentication.RSA), T12KeyAgreement.ECDHE);
311331
}
312332

313333
private static class SSLKeyExECDHERSAOrPSS {
314334
private static SSLKeyExchange KE = new SSLKeyExchange(
315-
X509Authentication.RSA_OR_PSS, T12KeyAgreement.ECDHE);
335+
List.of(X509Authentication.RSA_OR_PSS), T12KeyAgreement.ECDHE);
316336
}
317337

318338
private static class SSLKeyExECDHANON {

src/java.base/share/classes/sun/security/ssl/SignatureScheme.java

+8-18
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,6 @@
4747
import sun.security.util.SignatureUtil;
4848

4949
enum SignatureScheme {
50-
// EdDSA algorithms
51-
ED25519 (0x0807, "ed25519", "ed25519",
52-
"ed25519",
53-
ProtocolVersion.PROTOCOLS_OF_13),
54-
ED448 (0x0808, "ed448", "ed448",
55-
"ed448",
56-
ProtocolVersion.PROTOCOLS_OF_13),
57-
5850
// ECDSA algorithms
5951
ECDSA_SECP256R1_SHA256 (0x0403, "ecdsa_secp256r1_sha256",
6052
"SHA256withECDSA",
@@ -72,6 +64,14 @@ enum SignatureScheme {
7264
NamedGroup.SECP521_R1,
7365
ProtocolVersion.PROTOCOLS_TO_13),
7466

67+
// EdDSA algorithms
68+
ED25519 (0x0807, "ed25519", "Ed25519",
69+
"EdDSA",
70+
ProtocolVersion.PROTOCOLS_12_13),
71+
ED448 (0x0808, "ed448", "Ed448",
72+
"EdDSA",
73+
ProtocolVersion.PROTOCOLS_12_13),
74+
7575
// RSASSA-PSS algorithms with public key OID rsaEncryption
7676
//
7777
// The minimalKeySize is calculated as (See RFC 8017 for details):
@@ -275,16 +275,6 @@ private SignatureScheme(int id, String name,
275275

276276
boolean mediator = true;
277277

278-
// Disable EdDSA algorithms for TLS. Remove this when support is added.
279-
if (id == 0x0807 || id == 0x0808) {
280-
mediator = false;
281-
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
282-
SSLLogger.warning(
283-
"Signature algorithm, " + algorithm +
284-
", not supported by JSSE");
285-
}
286-
}
287-
288278
// An EC provider, for example the SunEC provider, may support
289279
// AlgorithmParameters but not KeyPairGenerator or Signature.
290280
//

src/java.base/share/classes/sun/security/ssl/X509Authentication.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ enum X509Authentication implements SSLAuthentication {
6464

6565
// Require EC public key
6666
EC ("EC", new X509PossessionGenerator(
67-
new String[] {"EC"}));
67+
new String[] {"EC"})),
68+
// Edwards-Curve key
69+
EDDSA ("EdDSA", new X509PossessionGenerator(
70+
new String[] {"EdDSA"}));
6871

6972
final String keyType;
7073
final SSLPossessionGenerator possessionGenerator;

0 commit comments

Comments
 (0)