Path: blob/master/src/java.base/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java
41159 views
/*1* Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.2* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation. Oracle designates this8* particular file as subject to the "Classpath" exception as provided9* by Oracle in the LICENSE file that accompanied this code.10*11* This code is distributed in the hope that it will be useful, but WITHOUT12* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or13* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License14* version 2 for more details (a copy is included in the LICENSE file that15* accompanied this code).16*17* You should have received a copy of the GNU General Public License version18* 2 along with this work; if not, write to the Free Software Foundation,19* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.20*21* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA22* or visit www.oracle.com if you need additional information or have any23* questions.24*/2526package sun.security.ssl;2728import java.io.IOException;29import java.nio.ByteBuffer;30import javax.net.ssl.SSLProtocolException;31import static sun.security.ssl.SSLExtension.CH_EXTENDED_MASTER_SECRET;32import sun.security.ssl.SSLExtension.ExtensionConsumer;33import static sun.security.ssl.SSLExtension.SH_EXTENDED_MASTER_SECRET;34import sun.security.ssl.SSLExtension.SSLExtensionSpec;35import sun.security.ssl.SSLHandshake.HandshakeMessage;3637/**38* Pack of the "extended_master_secret" extensions [RFC 7627].39*/40final class ExtendedMasterSecretExtension {41static final HandshakeProducer chNetworkProducer =42new CHExtendedMasterSecretProducer();43static final ExtensionConsumer chOnLoadConsumer =44new CHExtendedMasterSecretConsumer();45static final HandshakeAbsence chOnLoadAbsence =46new CHExtendedMasterSecretAbsence();4748static final HandshakeProducer shNetworkProducer =49new SHExtendedMasterSecretProducer();50static final ExtensionConsumer shOnLoadConsumer =51new SHExtendedMasterSecretConsumer();52static final HandshakeAbsence shOnLoadAbsence =53new SHExtendedMasterSecretAbsence();5455static final SSLStringizer emsStringizer =56new ExtendedMasterSecretStringizer();5758/**59* The "extended_master_secret" extension.60*/61static final class ExtendedMasterSecretSpec implements SSLExtensionSpec {62// A nominal object that does not holding any real renegotiation info.63static final ExtendedMasterSecretSpec NOMINAL =64new ExtendedMasterSecretSpec();6566private ExtendedMasterSecretSpec() {67// blank68}6970private ExtendedMasterSecretSpec(HandshakeContext hc,71ByteBuffer m) throws IOException {72// Parse the extension.73if (m.hasRemaining()) {74throw hc.conContext.fatal(Alert.DECODE_ERROR,75new SSLProtocolException(76"Invalid extended_master_secret extension data: " +77"not empty"));78}79}8081@Override82public String toString() {83return "<empty>";84}85}8687private static final88class ExtendedMasterSecretStringizer implements SSLStringizer {89@Override90public String toString(HandshakeContext hc, ByteBuffer buffer) {91try {92return (new ExtendedMasterSecretSpec(hc, buffer)).toString();93} catch (IOException ioe) {94// For debug logging only, so please swallow exceptions.95return ioe.getMessage();96}97}98}99100/**101* Network data producer of a "extended_master_secret" extension in102* the ClientHello handshake message.103*/104private static final105class CHExtendedMasterSecretProducer implements HandshakeProducer {106// Prevent instantiation of this class.107private CHExtendedMasterSecretProducer() {108// blank109}110111@Override112public byte[] produce(ConnectionContext context,113HandshakeMessage message) throws IOException {114// The producing happens in client side only.115ClientHandshakeContext chc = (ClientHandshakeContext)context;116117// Is it a supported and enabled extension?118if (!chc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) ||119!SSLConfiguration.useExtendedMasterSecret ||120!chc.conContext.protocolVersion.useTLS10PlusSpec()) {121if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {122SSLLogger.fine(123"Ignore unavailable extended_master_secret extension");124}125126return null;127}128129if (chc.handshakeSession == null ||130chc.handshakeSession.useExtendedMasterSecret) {131byte[] extData = new byte[0];132chc.handshakeExtensions.put(CH_EXTENDED_MASTER_SECRET,133ExtendedMasterSecretSpec.NOMINAL);134135return extData;136}137138return null;139}140}141142/**143* Network data producer of a "extended_master_secret" extension in144* the ServerHello handshake message.145*/146private static final147class CHExtendedMasterSecretConsumer implements ExtensionConsumer {148// Prevent instantiation of this class.149private CHExtendedMasterSecretConsumer() {150// blank151}152153@Override154public void consume(ConnectionContext context,155HandshakeMessage message, ByteBuffer buffer) throws IOException {156157// The consuming happens in server side only.158ServerHandshakeContext shc = (ServerHandshakeContext)context;159160// Is it a supported and enabled extension?161if (!shc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) ||162!SSLConfiguration.useExtendedMasterSecret ||163!shc.negotiatedProtocol.useTLS10PlusSpec()) {164if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {165SSLLogger.fine("Ignore unavailable extension: " +166CH_EXTENDED_MASTER_SECRET.name);167}168return; // ignore the extension169}170171// Parse the extension.172ExtendedMasterSecretSpec spec =173new ExtendedMasterSecretSpec(shc, buffer);174if (shc.isResumption && shc.resumingSession != null &&175!shc.resumingSession.useExtendedMasterSecret) {176// For abbreviated handshake request, If the original177// session did not use the "extended_master_secret"178// extension but the new ClientHello contains the179// extension, then the server MUST NOT perform the180// abbreviated handshake. Instead, it SHOULD continue181// with a full handshake.182shc.isResumption = false;183shc.resumingSession = null;184if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {185SSLLogger.fine(186"abort session resumption which did not use " +187"Extended Master Secret extension");188}189}190191// Update the context.192//193shc.handshakeExtensions.put(194CH_EXTENDED_MASTER_SECRET, ExtendedMasterSecretSpec.NOMINAL);195196// No impact on session resumption.197}198}199200/**201* The absence processing if a "extended_master_secret" extension is202* not present in the ClientHello handshake message.203*/204private static final205class CHExtendedMasterSecretAbsence implements HandshakeAbsence {206@Override207public void absent(ConnectionContext context,208HandshakeMessage message) throws IOException {209// The producing happens in server side only.210ServerHandshakeContext shc = (ServerHandshakeContext)context;211212// Is it a supported and enabled extension?213if (!shc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) ||214!SSLConfiguration.useExtendedMasterSecret) {215if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {216SSLLogger.fine("Ignore unavailable extension: " +217CH_EXTENDED_MASTER_SECRET.name);218}219return; // ignore the extension220}221222if (shc.negotiatedProtocol.useTLS10PlusSpec() &&223!SSLConfiguration.allowLegacyMasterSecret) {224// For full handshake, if the server receives a ClientHello225// without the extension, it SHOULD abort the handshake if226// it does not wish to interoperate with legacy clients.227//228// As if extended master extension is required for full229// handshake, it MUST be used in abbreviated handshake too.230throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,231"Extended Master Secret extension is required");232}233234if (shc.isResumption && shc.resumingSession != null) {235if (shc.resumingSession.useExtendedMasterSecret) {236// For abbreviated handshake request, if the original237// session used the "extended_master_secret" extension238// but the new ClientHello does not contain it, the239// server MUST abort the abbreviated handshake.240throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,241"Missing Extended Master Secret extension " +242"on session resumption");243} else {244// For abbreviated handshake request, if neither the245// original session nor the new ClientHello uses the246// extension, the server SHOULD abort the handshake.247if (!SSLConfiguration.allowLegacyResumption) {248throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,249"Missing Extended Master Secret extension " +250"on session resumption");251} else { // Otherwise, continue with a full handshake.252shc.isResumption = false;253shc.resumingSession = null;254if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {255SSLLogger.fine(256"abort session resumption, " +257"missing Extended Master Secret extension");258}259}260}261}262}263}264265/**266* Network data producer of a "extended_master_secret" extension in267* the ServerHello handshake message.268*/269private static final270class SHExtendedMasterSecretProducer implements HandshakeProducer {271// Prevent instantiation of this class.272private SHExtendedMasterSecretProducer() {273// blank274}275276@Override277public byte[] produce(ConnectionContext context,278HandshakeMessage message) throws IOException {279// The producing happens in server side only.280ServerHandshakeContext shc = (ServerHandshakeContext)context;281282if (shc.handshakeSession.useExtendedMasterSecret) {283byte[] extData = new byte[0];284shc.handshakeExtensions.put(SH_EXTENDED_MASTER_SECRET,285ExtendedMasterSecretSpec.NOMINAL);286287return extData;288}289290return null;291}292}293294/**295* Network data consumer of a "extended_master_secret" extension in296* the ServerHello handshake message.297*/298private static final299class SHExtendedMasterSecretConsumer implements ExtensionConsumer {300// Prevent instantiation of this class.301private SHExtendedMasterSecretConsumer() {302// blank303}304305@Override306public void consume(ConnectionContext context,307HandshakeMessage message, ByteBuffer buffer) throws IOException {308// The producing happens in client side only.309ClientHandshakeContext chc = (ClientHandshakeContext)context;310311// In response to the client extended_master_secret extension312// request, which is mandatory for ClientHello message.313ExtendedMasterSecretSpec requstedSpec = (ExtendedMasterSecretSpec)314chc.handshakeExtensions.get(CH_EXTENDED_MASTER_SECRET);315if (requstedSpec == null) {316throw chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION,317"Server sent the extended_master_secret " +318"extension improperly");319}320321// Parse the extension.322ExtendedMasterSecretSpec spec =323new ExtendedMasterSecretSpec(chc, buffer);324if (chc.isResumption && chc.resumingSession != null &&325!chc.resumingSession.useExtendedMasterSecret) {326throw chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION,327"Server sent an unexpected extended_master_secret " +328"extension on session resumption");329}330331// Update the context.332chc.handshakeExtensions.put(333SH_EXTENDED_MASTER_SECRET, ExtendedMasterSecretSpec.NOMINAL);334335// No impact on session resumption.336}337}338339/**340* The absence processing if a "extended_master_secret" extension is341* not present in the ServerHello handshake message.342*/343private static final344class SHExtendedMasterSecretAbsence implements HandshakeAbsence {345@Override346public void absent(ConnectionContext context,347HandshakeMessage message) throws IOException {348// The producing happens in client side only.349ClientHandshakeContext chc = (ClientHandshakeContext)context;350351if (SSLConfiguration.useExtendedMasterSecret &&352!SSLConfiguration.allowLegacyMasterSecret) {353// For full handshake, if a client receives a ServerHello354// without the extension, it SHOULD abort the handshake if355// it does not wish to interoperate with legacy servers.356throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,357"Extended Master Secret extension is required");358}359360if (chc.isResumption && chc.resumingSession != null) {361if (chc.resumingSession.useExtendedMasterSecret) {362// For abbreviated handshake, if the original session used363// the "extended_master_secret" extension but the new364// ServerHello does not contain the extension, the client365// MUST abort the handshake.366throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,367"Missing Extended Master Secret extension " +368"on session resumption");369} else if (SSLConfiguration.useExtendedMasterSecret &&370!SSLConfiguration.allowLegacyResumption &&371chc.negotiatedProtocol.useTLS10PlusSpec()) {372// Unlikely, abbreviated handshake should be discarded.373throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,374"Extended Master Secret extension is required");375}376}377}378}379}380381382383