8215712: Parsing extension failure may alert decode_error

Reviewed-by: jnimeh
This commit is contained in:
Xue-Lei Andrew Fan 2020-03-22 09:30:16 -07:00
parent ef335c75e3
commit 36af90acc0
21 changed files with 313 additions and 429 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, 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
@ -72,19 +72,22 @@ final class AlpnExtension {
Arrays.asList(applicationProtocols));
}
private AlpnSpec(ByteBuffer buffer) throws IOException {
private AlpnSpec(HandshakeContext hc,
ByteBuffer buffer) throws IOException {
// ProtocolName protocol_name_list<2..2^16-1>, RFC 7301.
if (buffer.remaining() < 2) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid application_layer_protocol_negotiation: " +
"insufficient data (length=" + buffer.remaining() + ")");
"insufficient data (length=" + buffer.remaining() + ")"));
}
int listLen = Record.getInt16(buffer);
if (listLen < 2 || listLen != buffer.remaining()) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid application_layer_protocol_negotiation: " +
"incorrect list length (length=" + listLen + ")");
"incorrect list length (length=" + listLen + ")"));
}
List<String> protocolNames = new LinkedList<>();
@ -92,9 +95,10 @@ final class AlpnExtension {
// opaque ProtocolName<1..2^8-1>, RFC 7301.
byte[] bytes = Record.getBytes8(buffer);
if (bytes.length == 0) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid application_layer_protocol_negotiation " +
"extension: empty application protocol name");
"extension: empty application protocol name"));
}
String appProtocol = new String(bytes, StandardCharsets.UTF_8);
@ -113,9 +117,9 @@ final class AlpnExtension {
private static final class AlpnStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new AlpnSpec(buffer)).toString();
return (new AlpnSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -282,12 +286,7 @@ final class AlpnExtension {
}
// Parse the extension.
AlpnSpec spec;
try {
spec = new AlpnSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
AlpnSpec spec = new AlpnSpec(shc, buffer);
// Update the context.
if (noAPSelector) { // noAlpnProtocols is false
@ -463,12 +462,7 @@ final class AlpnExtension {
}
// Parse the extension.
AlpnSpec spec;
try {
spec = new AlpnSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
AlpnSpec spec = new AlpnSpec(chc, buffer);
// Only one application protocol is allowed.
if (spec.applicationProtocols.size() != 1) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -56,9 +56,10 @@ final class CertSignAlgsExtension {
private static final
class CertSignatureSchemesStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new SignatureSchemesSpec(buffer)).toString();
return (new SignatureSchemesSpec(hc, buffer))
.toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -149,12 +150,7 @@ final class CertSignAlgsExtension {
}
// Parse the extension.
SignatureSchemesSpec spec;
try {
spec = new SignatureSchemesSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SignatureSchemesSpec spec = new SignatureSchemesSpec(shc, buffer);
// Update the context.
shc.handshakeExtensions.put(
@ -292,12 +288,7 @@ final class CertSignAlgsExtension {
}
// Parse the extension.
SignatureSchemesSpec spec;
try {
spec = new SignatureSchemesSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SignatureSchemesSpec spec = new SignatureSchemesSpec(chc, buffer);
// Update the context.
chc.handshakeExtensions.put(

View file

@ -121,7 +121,8 @@ final class CertStatusExtension {
this.statusRequest = statusRequest;
}
private CertStatusRequestSpec(ByteBuffer buffer) throws IOException {
private CertStatusRequestSpec(HandshakeContext hc,
ByteBuffer buffer) throws IOException {
// Is it a empty extension_data?
if (buffer.remaining() == 0) {
// server response
@ -130,8 +131,9 @@ final class CertStatusExtension {
}
if (buffer.remaining() < 1) {
throw new SSLProtocolException(
"Invalid status_request extension: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid status_request extension: insufficient data"));
}
byte statusType = (byte)Record.getInt8(buffer);
@ -178,10 +180,12 @@ final class CertStatusExtension {
this.statusResponse = resp;
}
private CertStatusResponseSpec(ByteBuffer buffer) throws IOException {
private CertStatusResponseSpec(HandshakeContext hc,
ByteBuffer buffer) throws IOException {
if (buffer.remaining() < 2) {
throw new SSLProtocolException(
"Invalid status_request extension: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid status_request extension: insufficient data"));
}
// Get the status type (1 byte) and response data (vector)
@ -212,9 +216,9 @@ final class CertStatusExtension {
private static final
class CertStatusRequestStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new CertStatusRequestSpec(buffer)).toString();
return (new CertStatusRequestSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -225,9 +229,9 @@ final class CertStatusExtension {
private static final
class CertStatusRespStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new CertStatusResponseSpec(buffer)).toString();
return (new CertStatusResponseSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -599,12 +603,7 @@ final class CertStatusExtension {
}
// Parse the extension.
CertStatusRequestSpec spec;
try {
spec = new CertStatusRequestSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
CertStatusRequestSpec spec = new CertStatusRequestSpec(shc, buffer);
// Update the context.
shc.handshakeExtensions.put(SSLExtension.CH_STATUS_REQUEST, spec);
@ -776,7 +775,8 @@ final class CertStatusExtension {
this.certStatusRequests = certStatusRequests;
}
private CertStatusRequestV2Spec(ByteBuffer message) throws IOException {
private CertStatusRequestV2Spec(HandshakeContext hc,
ByteBuffer message) throws IOException {
// Is it a empty extension_data?
if (message.remaining() == 0) {
// server response
@ -787,15 +787,17 @@ final class CertStatusExtension {
if (message.remaining() < 5) { // 2: certificate_status_req_list
// +1: status_type
// +2: request_length
throw new SSLProtocolException(
"Invalid status_request_v2 extension: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid status_request_v2 extension: insufficient data"));
}
int listLen = Record.getInt16(message);
if (listLen <= 0) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"certificate_status_req_list length must be positive " +
"(received length: " + listLen + ")");
"(received length: " + listLen + ")"));
}
int remaining = listLen;
@ -805,10 +807,12 @@ final class CertStatusExtension {
int requestLen = Record.getInt16(message);
if (message.remaining() < requestLen) {
throw new SSLProtocolException(
throw hc.conContext.fatal(
Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid status_request_v2 extension: " +
"insufficient data (request_length=" + requestLen +
", remining=" + message.remaining() + ")");
", remining=" + message.remaining() + ")"));
}
byte[] encoded = new byte[requestLen];
@ -823,9 +827,11 @@ final class CertStatusExtension {
if (encoded.length < 4) {
// 2: length of responder_id_list
// +2: length of request_extensions
throw new SSLProtocolException(
throw hc.conContext.fatal(
Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid status_request_v2 extension: " +
"insufficient data");
"insufficient data"));
}
statusRequests.add(
new OCSPStatusRequest(statusType, encoded));
@ -874,9 +880,9 @@ final class CertStatusExtension {
private static final
class CertStatusRequestsStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new CertStatusRequestV2Spec(buffer)).toString();
return (new CertStatusRequestV2Spec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -957,12 +963,7 @@ final class CertStatusExtension {
}
// Parse the extension.
CertStatusRequestV2Spec spec;
try {
spec = new CertStatusRequestV2Spec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
CertStatusRequestV2Spec spec = new CertStatusRequestV2Spec(shc, buffer);
// Update the context.
shc.handshakeExtensions.put(SSLExtension.CH_STATUS_REQUEST_V2,
@ -1185,12 +1186,7 @@ final class CertStatusExtension {
ClientHandshakeContext chc = (ClientHandshakeContext)context;
// Parse the extension.
CertStatusResponseSpec spec;
try {
spec = new CertStatusResponseSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.DECODE_ERROR, ioe);
}
CertStatusResponseSpec spec = new CertStatusResponseSpec(chc, buffer);
if (chc.sslContext.isStaplingEnabled(true)) {
// Activate stapling

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -63,11 +63,13 @@ public class CookieExtension {
static class CookieSpec implements SSLExtensionSpec {
final byte[] cookie;
private CookieSpec(ByteBuffer m) throws IOException {
private CookieSpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
// opaque cookie<1..2^16-1>;
if (m.remaining() < 3) {
throw new SSLProtocolException(
"Invalid cookie extension: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid cookie extension: insufficient data"));
}
this.cookie = Record.getBytes16(m);
@ -90,9 +92,9 @@ public class CookieExtension {
private static final class CookieStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new CookieSpec(buffer)).toString();
return (new CookieSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -159,13 +161,7 @@ public class CookieExtension {
return; // ignore the extension
}
CookieSpec spec;
try {
spec = new CookieSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
CookieSpec spec = new CookieSpec(shc, buffer);
shc.handshakeExtensions.put(SSLExtension.CH_COOKIE, spec);
// No impact on session resumption.
@ -264,13 +260,7 @@ public class CookieExtension {
return; // ignore the extension
}
CookieSpec spec;
try {
spec = new CookieSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
CookieSpec spec = new CookieSpec(chc, buffer);
chc.handshakeExtensions.put(SSLExtension.HRR_COOKIE, spec);
}
}

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
@ -64,11 +64,13 @@ final class ECPointFormatsExtension {
this.formats = formats;
}
private ECPointFormatsSpec(ByteBuffer m) throws IOException {
private ECPointFormatsSpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
if (!m.hasRemaining()) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid ec_point_formats extension: " +
"insufficient data");
"insufficient data"));
}
this.formats = Record.getBytes8(m);
@ -117,9 +119,9 @@ final class ECPointFormatsExtension {
private static final class ECPointFormatsStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new ECPointFormatsSpec(buffer)).toString();
return (new ECPointFormatsSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -227,12 +229,7 @@ final class ECPointFormatsExtension {
}
// Parse the extension.
ECPointFormatsSpec spec;
try {
spec = new ECPointFormatsSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
ECPointFormatsSpec spec = new ECPointFormatsSpec(shc, buffer);
// per RFC 4492, uncompressed points must always be supported.
if (!spec.hasUncompressedFormat()) {
@ -276,12 +273,7 @@ final class ECPointFormatsExtension {
}
// Parse the extension.
ECPointFormatsSpec spec;
try {
spec = new ECPointFormatsSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
ECPointFormatsSpec spec = new ECPointFormatsSpec(chc, buffer);
// per RFC 4492, uncompressed points must always be supported.
if (!spec.hasUncompressedFormat()) {

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -68,12 +68,14 @@ final class ExtendedMasterSecretExtension {
// blank
}
private ExtendedMasterSecretSpec(ByteBuffer m) throws IOException {
private ExtendedMasterSecretSpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
// Parse the extension.
if (m.hasRemaining()) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid extended_master_secret extension data: " +
"not empty");
"not empty"));
}
}
@ -86,9 +88,9 @@ final class ExtendedMasterSecretExtension {
private static final
class ExtendedMasterSecretStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new ExtendedMasterSecretSpec(buffer)).toString();
return (new ExtendedMasterSecretSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -168,13 +170,8 @@ final class ExtendedMasterSecretExtension {
}
// Parse the extension.
ExtendedMasterSecretSpec spec;
try {
spec = new ExtendedMasterSecretSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
ExtendedMasterSecretSpec spec =
new ExtendedMasterSecretSpec(shc, buffer);
if (shc.isResumption && shc.resumingSession != null &&
!shc.resumingSession.useExtendedMasterSecret) {
// For abbreviated handshake request, If the original
@ -323,13 +320,8 @@ final class ExtendedMasterSecretExtension {
}
// Parse the extension.
ExtendedMasterSecretSpec spec;
try {
spec = new ExtendedMasterSecretSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
ExtendedMasterSecretSpec spec =
new ExtendedMasterSecretSpec(chc, buffer);
if (chc.isResumption && chc.resumingSession != null &&
!chc.resumingSession.useExtendedMasterSecret) {
throw chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION,

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
@ -137,21 +137,24 @@ final class KeyShareExtension {
this.clientShares = clientShares;
}
private CHKeyShareSpec(ByteBuffer buffer) throws IOException {
private CHKeyShareSpec(HandshakeContext handshakeContext,
ByteBuffer buffer) throws IOException {
// struct {
// KeyShareEntry client_shares<0..2^16-1>;
// } KeyShareClientHello;
if (buffer.remaining() < 2) {
throw new SSLProtocolException(
throw handshakeContext.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid key_share extension: " +
"insufficient data (length=" + buffer.remaining() + ")");
"insufficient data (length=" + buffer.remaining() + ")"));
}
int listLen = Record.getInt16(buffer);
if (listLen != buffer.remaining()) {
throw new SSLProtocolException(
throw handshakeContext.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid key_share extension: " +
"incorrect list length (length=" + listLen + ")");
"incorrect list length (length=" + listLen + ")"));
}
List<KeyShareEntry> keyShares = new LinkedList<>();
@ -159,8 +162,9 @@ final class KeyShareExtension {
int namedGroupId = Record.getInt16(buffer);
byte[] keyExchange = Record.getBytes16(buffer);
if (keyExchange.length == 0) {
throw new SSLProtocolException(
"Invalid key_share extension: empty key_exchange");
throw handshakeContext.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid key_share extension: empty key_exchange"));
}
keyShares.add(new KeyShareEntry(namedGroupId, keyExchange));
@ -189,9 +193,10 @@ final class KeyShareExtension {
private static final class CHKeyShareStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(
HandshakeContext handshakeContext, ByteBuffer buffer) {
try {
return (new CHKeyShareSpec(buffer)).toString();
return (new CHKeyShareSpec(handshakeContext, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -324,13 +329,7 @@ final class KeyShareExtension {
}
// Parse the extension
CHKeyShareSpec spec;
try {
spec = new CHKeyShareSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
CHKeyShareSpec spec = new CHKeyShareSpec(shc, buffer);
List<SSLCredentials> credentials = new LinkedList<>();
for (KeyShareEntry entry : spec.clientShares) {
NamedGroup ng = NamedGroup.valueOf(entry.namedGroupId);
@ -383,22 +382,25 @@ final class KeyShareExtension {
this.serverShare = serverShare;
}
private SHKeyShareSpec(ByteBuffer buffer) throws IOException {
private SHKeyShareSpec(HandshakeContext handshakeContext,
ByteBuffer buffer) throws IOException {
// struct {
// KeyShareEntry server_share;
// } KeyShareServerHello;
if (buffer.remaining() < 5) { // 5: minimal server_share
throw new SSLProtocolException(
throw handshakeContext.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid key_share extension: " +
"insufficient data (length=" + buffer.remaining() + ")");
"insufficient data (length=" + buffer.remaining() + ")"));
}
int namedGroupId = Record.getInt16(buffer);
byte[] keyExchange = Record.getBytes16(buffer);
if (buffer.hasRemaining()) {
throw new SSLProtocolException(
"Invalid key_share extension: unknown extra data");
throw handshakeContext.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid key_share extension: unknown extra data"));
}
this.serverShare = new KeyShareEntry(namedGroupId, keyExchange);
@ -427,9 +429,10 @@ final class KeyShareExtension {
private static final class SHKeyShareStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext handshakeContext,
ByteBuffer buffer) {
try {
return (new SHKeyShareSpec(buffer)).toString();
return (new SHKeyShareSpec(handshakeContext, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -581,13 +584,7 @@ final class KeyShareExtension {
}
// Parse the extension
SHKeyShareSpec spec;
try {
spec = new SHKeyShareSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SHKeyShareSpec spec = new SHKeyShareSpec(chc, buffer);
KeyShareEntry keyShare = spec.serverShare;
NamedGroup ng = NamedGroup.valueOf(keyShare.namedGroupId);
if (ng == null || !SupportedGroups.isActivatable(
@ -660,14 +657,16 @@ final class KeyShareExtension {
this.selectedGroup = serverGroup.id;
}
private HRRKeyShareSpec(ByteBuffer buffer) throws IOException {
private HRRKeyShareSpec(HandshakeContext handshakeContext,
ByteBuffer buffer) throws IOException {
// struct {
// NamedGroup selected_group;
// } KeyShareHelloRetryRequest;
if (buffer.remaining() != 2) {
throw new SSLProtocolException(
throw handshakeContext.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid key_share extension: " +
"improper data (length=" + buffer.remaining() + ")");
"improper data (length=" + buffer.remaining() + ")"));
}
this.selectedGroup = Record.getInt16(buffer);
@ -687,9 +686,10 @@ final class KeyShareExtension {
private static final class HRRKeyShareStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext handshakeContext,
ByteBuffer buffer) {
try {
return (new HRRKeyShareSpec(buffer)).toString();
return (new HRRKeyShareSpec(handshakeContext, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -833,22 +833,16 @@ final class KeyShareExtension {
}
// Parse the extension
HRRKeyShareSpec spec;
try {
spec = new HRRKeyShareSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
HRRKeyShareSpec spec = new HRRKeyShareSpec(chc, buffer);
NamedGroup serverGroup = NamedGroup.valueOf(spec.selectedGroup);
if (serverGroup == null) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Unsupported HelloRetryRequest selected group: " +
NamedGroup.nameOf(spec.selectedGroup));
}
if (!chc.clientRequestedNamedGroups.contains(serverGroup)) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Unexpected HelloRetryRequest selected group: " +
serverGroup.name);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, 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
@ -71,10 +71,12 @@ final class MaxFragExtension {
this.id = id;
}
private MaxFragLenSpec(ByteBuffer buffer) throws IOException {
private MaxFragLenSpec(HandshakeContext hc,
ByteBuffer buffer) throws IOException {
if (buffer.remaining() != 1) {
throw new SSLProtocolException(
"Invalid max_fragment_length extension data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid max_fragment_length extension data"));
}
this.id = buffer.get();
@ -88,9 +90,9 @@ final class MaxFragExtension {
private static final class MaxFragLenStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new MaxFragLenSpec(buffer)).toString();
return (new MaxFragLenSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -249,13 +251,7 @@ final class MaxFragExtension {
}
// Parse the extension.
MaxFragLenSpec spec;
try {
spec = new MaxFragLenSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
MaxFragLenSpec spec = new MaxFragLenSpec(shc, buffer);
MaxFragLenEnum mfle = MaxFragLenEnum.valueOf(spec.id);
if (mfle == null) {
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
@ -363,13 +359,7 @@ final class MaxFragExtension {
}
// Parse the extension.
MaxFragLenSpec spec;
try {
spec = new MaxFragLenSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
MaxFragLenSpec spec = new MaxFragLenSpec(chc, buffer);
if (spec.id != requestedSpec.id) {
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"The maximum fragment length response is not requested");
@ -535,13 +525,7 @@ final class MaxFragExtension {
}
// Parse the extension.
MaxFragLenSpec spec;
try {
spec = new MaxFragLenSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
MaxFragLenSpec spec = new MaxFragLenSpec(chc, buffer);
if (spec.id != requestedSpec.id) {
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"The maximum fragment length response is not requested");

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
@ -36,6 +36,7 @@ import java.util.Collection;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLProtocolException;
import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED;
import sun.security.ssl.ClientHello.ClientHelloMessage;
import sun.security.ssl.SSLExtension.ExtensionConsumer;
@ -105,23 +106,25 @@ final class PreSharedKeyExtension {
this.binders = binders;
}
CHPreSharedKeySpec(HandshakeContext context,
CHPreSharedKeySpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
// struct {
// PskIdentity identities<7..2^16-1>;
// PskBinderEntry binders<33..2^16-1>;
// } OfferedPsks;
if (m.remaining() < 44) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid pre_shared_key extension: " +
"insufficient data (length=" + m.remaining() + ")");
"insufficient data (length=" + m.remaining() + ")"));
}
int idEncodedLength = Record.getInt16(m);
if (idEncodedLength < 7) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid pre_shared_key extension: " +
"insufficient identities (length=" + idEncodedLength + ")");
"insufficient identities (length=" + idEncodedLength + ")"));
}
identities = new ArrayList<>();
@ -129,9 +132,10 @@ final class PreSharedKeyExtension {
while (idReadLength < idEncodedLength) {
byte[] id = Record.getBytes16(m);
if (id.length < 1) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid pre_shared_key extension: " +
"insufficient identity (length=" + id.length + ")");
"insufficient identity (length=" + id.length + ")"));
}
int obfuscatedTicketAge = Record.getInt32(m);
@ -141,18 +145,20 @@ final class PreSharedKeyExtension {
}
if (m.remaining() < 35) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Invalid pre_shared_key extension: " +
"insufficient binders data (length=" +
m.remaining() + ")");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid pre_shared_key extension: " +
"insufficient binders data (length=" +
m.remaining() + ")"));
}
int bindersEncodedLen = Record.getInt16(m);
if (bindersEncodedLen < 33) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Invalid pre_shared_key extension: " +
"insufficient binders (length=" +
bindersEncodedLen + ")");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid pre_shared_key extension: " +
"insufficient binders (length=" +
bindersEncodedLen + ")"));
}
binders = new ArrayList<>();
@ -160,10 +166,11 @@ final class PreSharedKeyExtension {
while (bindersReadLength < bindersEncodedLen) {
byte[] binder = Record.getBytes8(m);
if (binder.length < 32) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Invalid pre_shared_key extension: " +
"insufficient binder entry (length=" +
binder.length + ")");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid pre_shared_key extension: " +
"insufficient binder entry (length=" +
binder.length + ")"));
}
binders.add(binder);
bindersReadLength += 1 + binder.length;
@ -251,15 +258,9 @@ final class PreSharedKeyExtension {
private static final
class CHPreSharedKeyStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
// As the HandshakeContext parameter of CHPreSharedKeySpec
// constructor is used for fatal alert only, we can use
// null HandshakeContext here as we don't care about exception.
//
// Please take care of this code if the CHPreSharedKeySpec
// constructor is updated in the future.
return (new CHPreSharedKeySpec(null, buffer)).toString();
return (new CHPreSharedKeySpec(hc, buffer)).toString();
} catch (Exception ex) {
// For debug logging only, so please swallow exceptions.
return ex.getMessage();
@ -275,13 +276,14 @@ final class PreSharedKeyExtension {
this.selectedIdentity = selectedIdentity;
}
SHPreSharedKeySpec(HandshakeContext context,
SHPreSharedKeySpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
if (m.remaining() < 2) {
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Invalid pre_shared_key extension: " +
"insufficient selected_identity (length=" +
m.remaining() + ")");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid pre_shared_key extension: " +
"insufficient selected_identity (length=" +
m.remaining() + ")"));
}
this.selectedIdentity = Record.getInt16(m);
}
@ -312,15 +314,9 @@ final class PreSharedKeyExtension {
private static final
class SHPreSharedKeyStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
// As the HandshakeContext parameter of SHPreSharedKeySpec
// constructor is used for fatal alert only, we can use
// null HandshakeContext here as we don't care about exception.
//
// Please take care of this code if the SHPreSharedKeySpec
// constructor is updated in the future.
return (new SHPreSharedKeySpec(null, buffer)).toString();
return (new SHPreSharedKeySpec(hc, buffer)).toString();
} catch (Exception ex) {
// For debug logging only, so please swallow exceptions.
return ex.getMessage();
@ -351,12 +347,7 @@ final class PreSharedKeyExtension {
}
// Parse the extension.
CHPreSharedKeySpec pskSpec = null;
try {
pskSpec = new CHPreSharedKeySpec(shc, buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
CHPreSharedKeySpec pskSpec = new CHPreSharedKeySpec(shc, buffer);
// The "psk_key_exchange_modes" extension should have been loaded.
if (!shc.handshakeExtensions.containsKey(
@ -388,7 +379,7 @@ final class PreSharedKeyExtension {
requestedId.identity.length > SessionId.MAX_LENGTH &&
sessionCache.statelessEnabled()) {
ByteBuffer b =
new SessionTicketSpec(requestedId.identity).
new SessionTicketSpec(shc, requestedId.identity).
decrypt(shc);
if (b != null) {
try {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -95,11 +95,13 @@ final class PskKeyExchangeModesExtension {
this.modes = modes;
}
PskKeyExchangeModesSpec(ByteBuffer m) throws IOException {
PskKeyExchangeModesSpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
if (m.remaining() < 2) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid psk_key_exchange_modes extension: " +
"insufficient data");
"insufficient data"));
}
this.modes = Record.getBytes8(m);
@ -151,9 +153,9 @@ final class PskKeyExchangeModesExtension {
private static final
class PskKeyExchangeModesStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new PskKeyExchangeModesSpec(buffer)).toString();
return (new PskKeyExchangeModesSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -197,12 +199,8 @@ final class PskKeyExchangeModesExtension {
}
// Parse the extension.
PskKeyExchangeModesSpec spec;
try {
spec = new PskKeyExchangeModesSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
PskKeyExchangeModesSpec spec =
new PskKeyExchangeModesSpec(shc, buffer);
// Update the context.
shc.handshakeExtensions.put(

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
@ -74,12 +74,14 @@ final class RenegoInfoExtension {
renegotiatedConnection, renegotiatedConnection.length);
}
private RenegotiationInfoSpec(ByteBuffer m) throws IOException {
private RenegotiationInfoSpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
// Parse the extension.
if (!m.hasRemaining() || m.remaining() < 1) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid renegotiation_info extension data: " +
"insufficient data");
"insufficient data"));
}
this.renegotiatedConnection = Record.getBytes8(m);
}
@ -105,9 +107,9 @@ final class RenegoInfoExtension {
private static final
class RenegotiationInfoStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new RenegotiationInfoSpec(buffer)).toString();
return (new RenegotiationInfoSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -220,13 +222,7 @@ final class RenegoInfoExtension {
}
// Parse the extension.
RenegotiationInfoSpec spec;
try {
spec = new RenegotiationInfoSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
RenegotiationInfoSpec spec = new RenegotiationInfoSpec(shc, buffer);
if (!shc.conContext.isNegotiated) {
// initial handshaking.
if (spec.renegotiatedConnection.length != 0) {
@ -433,14 +429,7 @@ final class RenegoInfoExtension {
}
// Parse the extension.
RenegotiationInfoSpec spec;
try {
spec = new RenegotiationInfoSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
RenegotiationInfoSpec spec = new RenegotiationInfoSpec(chc, buffer);
if (!chc.conContext.isNegotiated) { // initial handshake
// If the extension is present, set the secure_renegotiation
// flag to TRUE. The client MUST then verify that the

View file

@ -641,7 +641,8 @@ enum SSLExtension implements SSLStringizer {
}
@Override
public String toString(ByteBuffer byteBuffer) {
public String toString(
HandshakeContext handshakeContext, ByteBuffer byteBuffer) {
MessageFormat messageFormat = new MessageFormat(
"\"{0} ({1})\": '{'\n" +
"{2}\n" +
@ -654,7 +655,7 @@ enum SSLExtension implements SSLStringizer {
String encoded = hexEncoder.encode(byteBuffer.duplicate());
extData = encoded;
} else {
extData = stringizer.toString(byteBuffer);
extData = stringizer.toString(handshakeContext, byteBuffer);
}
Object[] messageFields = {

View file

@ -346,7 +346,8 @@ final class SSLExtensions {
}
if (ext != null) {
builder.append(
ext.toString(ByteBuffer.wrap(en.getValue())));
ext.toString(handshakeMessage.handshakeContext,
ByteBuffer.wrap(en.getValue())));
} else {
builder.append(toString(en.getKey(), en.getValue()));
}
@ -359,7 +360,8 @@ final class SSLExtensions {
builder.append(",\n");
}
builder.append(
en.getKey().toString(ByteBuffer.wrap(en.getValue())));
en.getKey().toString(handshakeMessage.handshakeContext,
ByteBuffer.wrap(en.getValue())));
}
return builder.toString();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -37,5 +37,5 @@ interface SSLStringizer {
* Note that the implementation MUST not change the internal status of
* the {@code buffer}.
*/
String toString(ByteBuffer buffer);
String toString(HandshakeContext handshakeContext, ByteBuffer buffer);
}

View file

@ -49,8 +49,6 @@ import sun.security.ssl.SSLCipher.SSLWriteCipher;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
import sun.security.ssl.SupportedVersionsExtension.SHSupportedVersionsSpec;
import static sun.security.ssl.SSLExtension.SH_SESSION_TICKET;
/**
* Pack of the ServerHello/HelloRetryRequest handshake message.
*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, 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
@ -93,16 +93,19 @@ final class ServerNameExtension {
new ArrayList<>(serverNames));
}
private CHServerNamesSpec(ByteBuffer buffer) throws IOException {
private CHServerNamesSpec(HandshakeContext hc,
ByteBuffer buffer) throws IOException {
if (buffer.remaining() < 2) {
throw new SSLProtocolException(
"Invalid server_name extension: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid server_name extension: insufficient data"));
}
int sniLen = Record.getInt16(buffer);
if ((sniLen == 0) || sniLen != buffer.remaining()) {
throw new SSLProtocolException(
"Invalid server_name extension: incomplete data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid server_name extension: incomplete data"));
}
Map<Integer, SNIServerName> sniMap = new LinkedHashMap<>();
@ -121,8 +124,9 @@ final class ServerNameExtension {
byte[] encoded = Record.getBytes16(buffer);
if (nameType == StandardConstants.SNI_HOST_NAME) {
if (encoded.length == 0) {
throw new SSLProtocolException(
"Empty HostName in server_name extension");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Empty HostName in server_name extension"));
}
try {
@ -134,7 +138,8 @@ final class ServerNameExtension {
(new String(encoded, StandardCharsets.UTF_8)) +
", value={" +
Utilities.toHexString(encoded) + "}");
throw (SSLProtocolException)spe.initCause(iae);
throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
(SSLProtocolException)spe.initCause(iae));
}
} else {
try {
@ -144,15 +149,17 @@ final class ServerNameExtension {
"Illegal server name, type=(" + nameType +
"), value={" +
Utilities.toHexString(encoded) + "}");
throw (SSLProtocolException)spe.initCause(iae);
throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
(SSLProtocolException)spe.initCause(iae));
}
}
// check for duplicated server name type
if (sniMap.put(serverName.getType(), serverName) != null) {
throw new SSLProtocolException(
throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
new SSLProtocolException(
"Duplicated server name of type " +
serverName.getType());
serverName.getType()));
}
}
@ -183,9 +190,9 @@ final class ServerNameExtension {
private static final class CHServerNamesStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new CHServerNamesSpec(buffer)).toString();
return (new CHServerNamesSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -291,12 +298,7 @@ final class ServerNameExtension {
}
// Parse the extension.
CHServerNamesSpec spec;
try {
spec = new CHServerNamesSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
CHServerNamesSpec spec = new CHServerNamesSpec(shc, buffer);
// Update the context.
shc.handshakeExtensions.put(CH_SERVER_NAME, spec);
@ -390,10 +392,12 @@ final class ServerNameExtension {
// blank
}
private SHServerNamesSpec(ByteBuffer buffer) throws IOException {
private SHServerNamesSpec(HandshakeContext hc,
ByteBuffer buffer) throws IOException {
if (buffer.remaining() != 0) {
throw new SSLProtocolException(
"Invalid ServerHello server_name extension: not empty");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid ServerHello server_name extension: not empty"));
}
}
@ -405,9 +409,9 @@ final class ServerNameExtension {
private static final class SHServerNamesStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new SHServerNamesSpec(buffer)).toString();
return (new SHServerNamesSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 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
@ -237,18 +237,21 @@ final class SessionTicketExtension {
data = zero;
}
SessionTicketSpec(byte[] b) throws IOException {
this(ByteBuffer.wrap(b));
SessionTicketSpec(HandshakeContext hc, byte[] b) throws IOException {
this(hc, ByteBuffer.wrap(b));
}
SessionTicketSpec(ByteBuffer buf) throws IOException {
SessionTicketSpec(HandshakeContext hc,
ByteBuffer buf) throws IOException {
if (buf == null) {
throw new SSLProtocolException(
"SessionTicket buffer too small");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"SessionTicket buffer too small"));
}
if (buf.remaining() > 65536) {
throw new SSLProtocolException(
"SessionTicket buffer too large. " + buf.remaining());
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"SessionTicket buffer too large. " + buf.remaining()));
}
data = buf;
@ -366,12 +369,10 @@ final class SessionTicketExtension {
}
static final class SessionTicketStringizer implements SSLStringizer {
SessionTicketStringizer() {}
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return new SessionTicketSpec(buffer).toString();
return new SessionTicketSpec(hc, buffer).toString();
} catch (IOException e) {
return e.getMessage();
}
@ -455,16 +456,7 @@ final class SessionTicketExtension {
}
// Parse the extension.
SessionTicketSpec spec;
try {
spec = new SessionTicketSpec(buffer);
} catch (IOException | RuntimeException e) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine("SessionTicket data invalid. Doing full " +
"handshake.");
}
return;
}
SessionTicketSpec spec = new SessionTicketSpec(shc, buffer);
ByteBuffer b = spec.decrypt(shc);
if (b != null) {
shc.resumingSession = new SSLSessionImpl(shc, b);
@ -531,14 +523,8 @@ final class SessionTicketExtension {
return;
}
try {
if (new SessionTicketSpec(buffer) == null) {
return;
}
chc.statelessResumption = true;
} catch (IOException e) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, e);
}
SessionTicketSpec spec = new SessionTicketSpec(chc, buffer);
chc.statelessResumption = true;
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, 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
@ -82,21 +82,25 @@ final class SignatureAlgorithmsExtension {
}
}
SignatureSchemesSpec(ByteBuffer buffer) throws IOException {
SignatureSchemesSpec(HandshakeContext hc,
ByteBuffer buffer) throws IOException {
if (buffer.remaining() < 2) { // 2: the length of the list
throw new SSLProtocolException(
"Invalid signature_algorithms: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid signature_algorithms: insufficient data"));
}
byte[] algs = Record.getBytes16(buffer);
if (buffer.hasRemaining()) {
throw new SSLProtocolException(
"Invalid signature_algorithms: unknown extra data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid signature_algorithms: unknown extra data"));
}
if (algs == null || algs.length == 0 || (algs.length & 0x01) != 0) {
throw new SSLProtocolException(
"Invalid signature_algorithms: incomplete data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid signature_algorithms: incomplete data"));
}
int[] schemes = new int[algs.length / 2];
@ -144,9 +148,9 @@ final class SignatureAlgorithmsExtension {
private static final
class SignatureSchemesStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new SignatureSchemesSpec(buffer)).toString();
return (new SignatureSchemesSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -234,12 +238,7 @@ final class SignatureAlgorithmsExtension {
}
// Parse the extension.
SignatureSchemesSpec spec;
try {
spec = new SignatureSchemesSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SignatureSchemesSpec spec = new SignatureSchemesSpec(shc, buffer);
// Update the context.
shc.handshakeExtensions.put(
@ -458,12 +457,7 @@ final class SignatureAlgorithmsExtension {
}
// Parse the extension.
SignatureSchemesSpec spec;
try {
spec = new SignatureSchemesSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SignatureSchemesSpec spec = new SignatureSchemesSpec(chc, buffer);
List<SignatureScheme> knownSignatureSchemes = new LinkedList<>();
for (int id : spec.signatureSchemes) {

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
@ -78,21 +78,25 @@ final class SupportedGroupsExtension {
}
}
private SupportedGroupsSpec(ByteBuffer m) throws IOException {
private SupportedGroupsSpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
if (m.remaining() < 2) { // 2: the length of the list
throw new SSLProtocolException(
"Invalid supported_groups extension: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid supported_groups extension: insufficient data"));
}
byte[] ngs = Record.getBytes16(m);
if (m.hasRemaining()) {
throw new SSLProtocolException(
"Invalid supported_groups extension: unknown extra data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid supported_groups extension: unknown extra data"));
}
if ((ngs == null) || (ngs.length == 0) || (ngs.length % 2 != 0)) {
throw new SSLProtocolException(
"Invalid supported_groups extension: incomplete data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid supported_groups extension: incomplete data"));
}
int[] ids = new int[ngs.length / 2];
@ -138,9 +142,9 @@ final class SupportedGroupsExtension {
private static final
class SupportedGroupsStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new SupportedGroupsSpec(buffer)).toString();
return (new SupportedGroupsSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -414,12 +418,7 @@ final class SupportedGroupsExtension {
}
// Parse the extension.
SupportedGroupsSpec spec;
try {
spec = new SupportedGroupsSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SupportedGroupsSpec spec = new SupportedGroupsSpec(shc, buffer);
// Update the context.
List<NamedGroup> knownNamedGroups = new LinkedList<>();
@ -535,12 +534,7 @@ final class SupportedGroupsExtension {
}
// Parse the extension.
SupportedGroupsSpec spec;
try {
spec = new SupportedGroupsSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SupportedGroupsSpec spec = new SupportedGroupsSpec(chc, buffer);
// Update the context.
List<NamedGroup> knownNamedGroups =

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, 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
@ -73,22 +73,26 @@ final class SupportedVersionsExtension {
this.requestedProtocols = requestedProtocols;
}
private CHSupportedVersionsSpec(ByteBuffer m) throws IOException {
private CHSupportedVersionsSpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
if (m.remaining() < 3) { // 1: the length of the list
// +2: one version at least
throw new SSLProtocolException(
"Invalid supported_versions extension: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid supported_versions extension: insufficient data"));
}
byte[] vbs = Record.getBytes8(m); // Get the version bytes.
if (m.hasRemaining()) {
throw new SSLProtocolException(
"Invalid supported_versions extension: unknown extra data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid supported_versions extension: unknown extra data"));
}
if (vbs == null || vbs.length == 0 || (vbs.length & 0x01) != 0) {
throw new SSLProtocolException(
"Invalid supported_versions extension: incomplete data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid supported_versions extension: incomplete data"));
}
int[] protocols = new int[vbs.length >> 1];
@ -136,9 +140,9 @@ final class SupportedVersionsExtension {
private static final
class CHSupportedVersionsStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new CHSupportedVersionsSpec(buffer)).toString();
return (new CHSupportedVersionsSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -221,12 +225,8 @@ final class SupportedVersionsExtension {
}
// Parse the extension.
CHSupportedVersionsSpec spec;
try {
spec = new CHSupportedVersionsSpec(buffer);
} catch (IOException ioe) {
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
CHSupportedVersionsSpec spec =
new CHSupportedVersionsSpec(shc, buffer);
// Update the context.
shc.handshakeExtensions.put(CH_SUPPORTED_VERSIONS, spec);
@ -249,10 +249,12 @@ final class SupportedVersionsExtension {
this.selectedVersion = selectedVersion.id;
}
private SHSupportedVersionsSpec(ByteBuffer m) throws IOException {
private SHSupportedVersionsSpec(HandshakeContext hc,
ByteBuffer m) throws IOException {
if (m.remaining() != 2) { // 2: the selected version
throw new SSLProtocolException(
"Invalid supported_versions: insufficient data");
throw hc.conContext.fatal(Alert.DECODE_ERROR,
new SSLProtocolException(
"Invalid supported_versions: insufficient data"));
}
byte major = m.get();
@ -275,9 +277,9 @@ final class SupportedVersionsExtension {
private static final
class SHSupportedVersionsStringizer implements SSLStringizer {
@Override
public String toString(ByteBuffer buffer) {
public String toString(HandshakeContext hc, ByteBuffer buffer) {
try {
return (new SHSupportedVersionsSpec(buffer)).toString();
return (new SHSupportedVersionsSpec(hc, buffer)).toString();
} catch (IOException ioe) {
// For debug logging only, so please swallow exceptions.
return ioe.getMessage();
@ -363,12 +365,8 @@ final class SupportedVersionsExtension {
}
// Parse the extension.
SHSupportedVersionsSpec spec;
try {
spec = new SHSupportedVersionsSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SHSupportedVersionsSpec spec =
new SHSupportedVersionsSpec(chc, buffer);
// Update the context.
chc.handshakeExtensions.put(SH_SUPPORTED_VERSIONS, spec);
@ -452,12 +450,8 @@ final class SupportedVersionsExtension {
}
// Parse the extension.
SHSupportedVersionsSpec spec;
try {
spec = new SHSupportedVersionsSpec(buffer);
} catch (IOException ioe) {
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
}
SHSupportedVersionsSpec spec =
new SHSupportedVersionsSpec(chc, buffer);
// Update the context.
chc.handshakeExtensions.put(HRR_SUPPORTED_VERSIONS, spec);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -43,7 +43,7 @@ import javax.net.ssl.SSLSocket;
/**
* SSL/(D)TLS transportation context.
*/
class TransportContext implements ConnectionContext {
final class TransportContext implements ConnectionContext {
final SSLTransport transport;
// registered plaintext consumers