Path: blob/master/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java
41159 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.ssl;2627import java.io.IOException;28import java.nio.ByteBuffer;29import java.security.PrivateKey;30import java.security.cert.X509Certificate;31import java.text.MessageFormat;32import java.util.ArrayList;33import java.util.Collection;34import java.util.Collections;35import java.util.HashSet;36import java.util.LinkedList;37import java.util.List;38import java.util.Locale;39import javax.net.ssl.SSLEngine;40import javax.net.ssl.SSLSocket;41import javax.net.ssl.X509ExtendedKeyManager;42import javax.security.auth.x500.X500Principal;43import sun.security.ssl.CipherSuite.KeyExchange;44import sun.security.ssl.SSLHandshake.HandshakeMessage;45import sun.security.ssl.X509Authentication.X509Possession;4647/**48* Pack of the CertificateRequest handshake message.49*/50final class CertificateRequest {51static final SSLConsumer t10HandshakeConsumer =52new T10CertificateRequestConsumer();53static final HandshakeProducer t10HandshakeProducer =54new T10CertificateRequestProducer();5556static final SSLConsumer t12HandshakeConsumer =57new T12CertificateRequestConsumer();58static final HandshakeProducer t12HandshakeProducer =59new T12CertificateRequestProducer();6061static final SSLConsumer t13HandshakeConsumer =62new T13CertificateRequestConsumer();63static final HandshakeProducer t13HandshakeProducer =64new T13CertificateRequestProducer();6566// TLS 1.2 and prior versions67private static enum ClientCertificateType {68// RFC 224669RSA_SIGN ((byte)0x01, "rsa_sign", List.of("RSA"), true),70DSS_SIGN ((byte)0x02, "dss_sign", List.of("DSA"), true),71RSA_FIXED_DH ((byte)0x03, "rsa_fixed_dh"),72DSS_FIXED_DH ((byte)0x04, "dss_fixed_dh"),7374// RFC 434675RSA_EPHEMERAL_DH ((byte)0x05, "rsa_ephemeral_dh"),76DSS_EPHEMERAL_DH ((byte)0x06, "dss_ephemeral_dh"),77FORTEZZA_DMS ((byte)0x14, "fortezza_dms"),7879// RFC 4492 and 844280ECDSA_SIGN ((byte)0x40, "ecdsa_sign",81List.of("EC", "EdDSA"),82JsseJce.isEcAvailable()),83RSA_FIXED_ECDH ((byte)0x41, "rsa_fixed_ecdh"),84ECDSA_FIXED_ECDH ((byte)0x42, "ecdsa_fixed_ecdh");8586private static final byte[] CERT_TYPES =87JsseJce.isEcAvailable() ? new byte[] {88ECDSA_SIGN.id,89RSA_SIGN.id,90DSS_SIGN.id91} : new byte[] {92RSA_SIGN.id,93DSS_SIGN.id94};9596final byte id;97final String name;98final List<String> keyAlgorithm;99final boolean isAvailable;100101private ClientCertificateType(byte id, String name) {102this(id, name, null, false);103}104105private ClientCertificateType(byte id, String name,106List<String> keyAlgorithm, boolean isAvailable) {107this.id = id;108this.name = name;109this.keyAlgorithm = keyAlgorithm;110this.isAvailable = isAvailable;111}112113private static String nameOf(byte id) {114for (ClientCertificateType cct : ClientCertificateType.values()) {115if (cct.id == id) {116return cct.name;117}118}119return "UNDEFINED-CLIENT-CERTIFICATE-TYPE(" + (int)id + ")";120}121122private static ClientCertificateType valueOf(byte id) {123for (ClientCertificateType cct : ClientCertificateType.values()) {124if (cct.id == id) {125return cct;126}127}128129return null;130}131132private static String[] getKeyTypes(byte[] ids) {133ArrayList<String> keyTypes = new ArrayList<>(3);134for (byte id : ids) {135ClientCertificateType cct = ClientCertificateType.valueOf(id);136if (cct.isAvailable) {137cct.keyAlgorithm.forEach(key -> {138if (!keyTypes.contains(key)) {139keyTypes.add(key);140}141});142}143}144145return keyTypes.toArray(new String[0]);146}147}148149/**150* The "CertificateRequest" handshake message for SSL 3.0 and TLS 1.0/1.1.151*/152static final class T10CertificateRequestMessage extends HandshakeMessage {153final byte[] types; // certificate types154final List<byte[]> authorities; // certificate authorities155156T10CertificateRequestMessage(HandshakeContext handshakeContext,157X509Certificate[] trustedCerts, KeyExchange keyExchange) {158super(handshakeContext);159160this.authorities = new ArrayList<>(trustedCerts.length);161for (X509Certificate cert : trustedCerts) {162X500Principal x500Principal = cert.getSubjectX500Principal();163authorities.add(x500Principal.getEncoded());164}165166this.types = ClientCertificateType.CERT_TYPES;167}168169T10CertificateRequestMessage(HandshakeContext handshakeContext,170ByteBuffer m) throws IOException {171super(handshakeContext);172173// struct {174// ClientCertificateType certificate_types<1..2^8-1>;175// DistinguishedName certificate_authorities<0..2^16-1>;176// } CertificateRequest;177if (m.remaining() < 4) {178throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,179"Incorrect CertificateRequest message: no sufficient data");180}181this.types = Record.getBytes8(m);182183int listLen = Record.getInt16(m);184if (listLen > m.remaining()) {185throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,186"Incorrect CertificateRequest message:no sufficient data");187}188189if (listLen > 0) {190this.authorities = new LinkedList<>();191while (listLen > 0) {192// opaque DistinguishedName<1..2^16-1>;193byte[] encoded = Record.getBytes16(m);194listLen -= (2 + encoded.length);195authorities.add(encoded);196}197} else {198this.authorities = Collections.emptyList();199}200}201202String[] getKeyTypes() {203return ClientCertificateType.getKeyTypes(types);204}205206X500Principal[] getAuthorities() {207X500Principal[] principals = new X500Principal[authorities.size()];208int i = 0;209for (byte[] encoded : authorities) {210principals[i++] = new X500Principal(encoded);211}212213return principals;214}215216@Override217public SSLHandshake handshakeType() {218return SSLHandshake.CERTIFICATE_REQUEST;219}220221@Override222public int messageLength() {223int len = 1 + types.length + 2;224for (byte[] encoded : authorities) {225len += encoded.length + 2;226}227return len;228}229230@Override231public void send(HandshakeOutStream hos) throws IOException {232hos.putBytes8(types);233234int listLen = 0;235for (byte[] encoded : authorities) {236listLen += encoded.length + 2;237}238239hos.putInt16(listLen);240for (byte[] encoded : authorities) {241hos.putBytes16(encoded);242}243}244245@Override246public String toString() {247MessageFormat messageFormat = new MessageFormat(248"\"CertificateRequest\": '{'\n" +249" \"certificate types\": {0}\n" +250" \"certificate authorities\": {1}\n" +251"'}'",252Locale.ENGLISH);253254List<String> typeNames = new ArrayList<>(types.length);255for (byte type : types) {256typeNames.add(ClientCertificateType.nameOf(type));257}258259List<String> authorityNames = new ArrayList<>(authorities.size());260for (byte[] encoded : authorities) {261X500Principal principal = new X500Principal(encoded);262authorityNames.add(principal.toString());263}264Object[] messageFields = {265typeNames,266authorityNames267};268269return messageFormat.format(messageFields);270}271}272273/**274* The "CertificateRequest" handshake message producer for SSL 3.0 and275* TLS 1.0/1.1.276*/277private static final278class T10CertificateRequestProducer implements HandshakeProducer {279// Prevent instantiation of this class.280private T10CertificateRequestProducer() {281// blank282}283284@Override285public byte[] produce(ConnectionContext context,286HandshakeMessage message) throws IOException {287// The producing happens in server side only.288ServerHandshakeContext shc = (ServerHandshakeContext)context;289290X509Certificate[] caCerts =291shc.sslContext.getX509TrustManager().getAcceptedIssuers();292T10CertificateRequestMessage crm = new T10CertificateRequestMessage(293shc, caCerts, shc.negotiatedCipherSuite.keyExchange);294if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {295SSLLogger.fine(296"Produced CertificateRequest handshake message", crm);297}298299// Output the handshake message.300crm.write(shc.handshakeOutput);301shc.handshakeOutput.flush();302303//304// update305//306shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,307SSLHandshake.CERTIFICATE);308shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,309SSLHandshake.CERTIFICATE_VERIFY);310311// The handshake message has been delivered.312return null;313}314}315316/**317* The "CertificateRequest" handshake message consumer for SSL 3.0 and318* TLS 1.0/1.1.319*/320private static final321class T10CertificateRequestConsumer implements SSLConsumer {322// Prevent instantiation of this class.323private T10CertificateRequestConsumer() {324// blank325}326327@Override328public void consume(ConnectionContext context,329ByteBuffer message) throws IOException {330// The consuming happens in client side only.331ClientHandshakeContext chc = (ClientHandshakeContext)context;332333// clean up this consumer334chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);335336SSLConsumer certStatCons = chc.handshakeConsumers.remove(337SSLHandshake.CERTIFICATE_STATUS.id);338if (certStatCons != null) {339// Stapling was active but no certificate status message340// was sent. We need to run the absence handler which will341// check the certificate chain.342CertificateStatus.handshakeAbsence.absent(context, null);343}344345T10CertificateRequestMessage crm =346new T10CertificateRequestMessage(chc, message);347if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {348SSLLogger.fine(349"Consuming CertificateRequest handshake message", crm);350}351352//353// validate354//355// blank356357//358// update359//360361// An empty client Certificate handshake message may be allow.362chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,363SSLHandshake.CERTIFICATE);364365X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();366String clientAlias = null;367if (chc.conContext.transport instanceof SSLSocketImpl) {368clientAlias = km.chooseClientAlias(crm.getKeyTypes(),369crm.getAuthorities(), (SSLSocket)chc.conContext.transport);370} else if (chc.conContext.transport instanceof SSLEngineImpl) {371clientAlias = km.chooseEngineClientAlias(crm.getKeyTypes(),372crm.getAuthorities(), (SSLEngine)chc.conContext.transport);373}374375376if (clientAlias == null) {377if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {378SSLLogger.warning("No available client authentication");379}380return;381}382383PrivateKey clientPrivateKey = km.getPrivateKey(clientAlias);384if (clientPrivateKey == null) {385if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {386SSLLogger.warning("No available client private key");387}388return;389}390391X509Certificate[] clientCerts = km.getCertificateChain(clientAlias);392if ((clientCerts == null) || (clientCerts.length == 0)) {393if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {394SSLLogger.warning("No available client certificate");395}396return;397}398399chc.handshakePossessions.add(400new X509Possession(clientPrivateKey, clientCerts));401chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,402SSLHandshake.CERTIFICATE_VERIFY);403}404}405406/**407* The CertificateRequest handshake message for TLS 1.2.408*/409static final class T12CertificateRequestMessage extends HandshakeMessage {410final byte[] types; // certificate types411final int[] algorithmIds; // supported signature algorithms412final List<byte[]> authorities; // certificate authorities413414T12CertificateRequestMessage(HandshakeContext handshakeContext,415X509Certificate[] trustedCerts, KeyExchange keyExchange,416List<SignatureScheme> signatureSchemes) throws IOException {417super(handshakeContext);418419this.types = ClientCertificateType.CERT_TYPES;420421if (signatureSchemes == null || signatureSchemes.isEmpty()) {422throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,423"No signature algorithms specified for " +424"CertificateRequest hanshake message");425}426this.algorithmIds = new int[signatureSchemes.size()];427int i = 0;428for (SignatureScheme scheme : signatureSchemes) {429algorithmIds[i++] = scheme.id;430}431432this.authorities = new ArrayList<>(trustedCerts.length);433for (X509Certificate cert : trustedCerts) {434X500Principal x500Principal = cert.getSubjectX500Principal();435authorities.add(x500Principal.getEncoded());436}437}438439T12CertificateRequestMessage(HandshakeContext handshakeContext,440ByteBuffer m) throws IOException {441super(handshakeContext);442443// struct {444// ClientCertificateType certificate_types<1..2^8-1>;445// SignatureAndHashAlgorithm446// supported_signature_algorithms<2..2^16-2>;447// DistinguishedName certificate_authorities<0..2^16-1>;448// } CertificateRequest;449450// certificate_authorities451if (m.remaining() < 8) {452throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,453"Invalid CertificateRequest handshake message: " +454"no sufficient data");455}456this.types = Record.getBytes8(m);457458// supported_signature_algorithms459if (m.remaining() < 6) {460throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,461"Invalid CertificateRequest handshake message: " +462"no sufficient data");463}464465byte[] algs = Record.getBytes16(m);466if (algs == null || algs.length == 0 || (algs.length & 0x01) != 0) {467throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,468"Invalid CertificateRequest handshake message: " +469"incomplete signature algorithms");470}471472this.algorithmIds = new int[(algs.length >> 1)];473for (int i = 0, j = 0; i < algs.length;) {474byte hash = algs[i++];475byte sign = algs[i++];476algorithmIds[j++] = ((hash & 0xFF) << 8) | (sign & 0xFF);477}478479// certificate_authorities480if (m.remaining() < 2) {481throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,482"Invalid CertificateRequest handshake message: " +483"no sufficient data");484}485486int listLen = Record.getInt16(m);487if (listLen > m.remaining()) {488throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,489"Invalid CertificateRequest message: no sufficient data");490}491492if (listLen > 0) {493this.authorities = new LinkedList<>();494while (listLen > 0) {495// opaque DistinguishedName<1..2^16-1>;496byte[] encoded = Record.getBytes16(m);497listLen -= (2 + encoded.length);498authorities.add(encoded);499}500} else {501this.authorities = Collections.emptyList();502}503}504505String[] getKeyTypes() {506return ClientCertificateType.getKeyTypes(types);507}508509X500Principal[] getAuthorities() {510X500Principal[] principals = new X500Principal[authorities.size()];511int i = 0;512for (byte[] encoded : authorities) {513principals[i++] = new X500Principal(encoded);514}515516return principals;517}518519@Override520public SSLHandshake handshakeType() {521return SSLHandshake.CERTIFICATE_REQUEST;522}523524@Override525public int messageLength() {526int len = 1 + types.length + 2 + (algorithmIds.length << 1) + 2;527for (byte[] encoded : authorities) {528len += encoded.length + 2;529}530return len;531}532533@Override534public void send(HandshakeOutStream hos) throws IOException {535hos.putBytes8(types);536537int listLen = 0;538for (byte[] encoded : authorities) {539listLen += encoded.length + 2;540}541542hos.putInt16(algorithmIds.length << 1);543for (int algorithmId : algorithmIds) {544hos.putInt16(algorithmId);545}546547hos.putInt16(listLen);548for (byte[] encoded : authorities) {549hos.putBytes16(encoded);550}551}552553@Override554public String toString() {555MessageFormat messageFormat = new MessageFormat(556"\"CertificateRequest\": '{'\n" +557" \"certificate types\": {0}\n" +558" \"supported signature algorithms\": {1}\n" +559" \"certificate authorities\": {2}\n" +560"'}'",561Locale.ENGLISH);562563List<String> typeNames = new ArrayList<>(types.length);564for (byte type : types) {565typeNames.add(ClientCertificateType.nameOf(type));566}567568List<String> algorithmNames = new ArrayList<>(algorithmIds.length);569for (int algorithmId : algorithmIds) {570algorithmNames.add(SignatureScheme.nameOf(algorithmId));571}572573List<String> authorityNames = new ArrayList<>(authorities.size());574for (byte[] encoded : authorities) {575X500Principal principal = new X500Principal(encoded);576authorityNames.add(principal.toString());577}578Object[] messageFields = {579typeNames,580algorithmNames,581authorityNames582};583584return messageFormat.format(messageFields);585}586}587588/**589* The "CertificateRequest" handshake message producer for TLS 1.2.590*/591private static final592class T12CertificateRequestProducer implements HandshakeProducer {593// Prevent instantiation of this class.594private T12CertificateRequestProducer() {595// blank596}597598@Override599public byte[] produce(ConnectionContext context,600HandshakeMessage message) throws IOException {601// The producing happens in server side only.602ServerHandshakeContext shc = (ServerHandshakeContext)context;603if (shc.localSupportedSignAlgs == null) {604shc.localSupportedSignAlgs =605SignatureScheme.getSupportedAlgorithms(606shc.sslConfig,607shc.algorithmConstraints, shc.activeProtocols);608}609610if (shc.localSupportedSignAlgs == null ||611shc.localSupportedSignAlgs.isEmpty()) {612throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,613"No supported signature algorithm");614}615616X509Certificate[] caCerts =617shc.sslContext.getX509TrustManager().getAcceptedIssuers();618T12CertificateRequestMessage crm = new T12CertificateRequestMessage(619shc, caCerts, shc.negotiatedCipherSuite.keyExchange,620shc.localSupportedSignAlgs);621if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {622SSLLogger.fine(623"Produced CertificateRequest handshake message", crm);624}625626// Output the handshake message.627crm.write(shc.handshakeOutput);628shc.handshakeOutput.flush();629630//631// update632//633shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,634SSLHandshake.CERTIFICATE);635shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,636SSLHandshake.CERTIFICATE_VERIFY);637638// The handshake message has been delivered.639return null;640}641}642643/**644* The "CertificateRequest" handshake message consumer for TLS 1.2.645*/646private static final647class T12CertificateRequestConsumer implements SSLConsumer {648// Prevent instantiation of this class.649private T12CertificateRequestConsumer() {650// blank651}652653@Override654public void consume(ConnectionContext context,655ByteBuffer message) throws IOException {656// The consuming happens in client side only.657ClientHandshakeContext chc = (ClientHandshakeContext)context;658659// clean up this consumer660chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);661662SSLConsumer certStatCons = chc.handshakeConsumers.remove(663SSLHandshake.CERTIFICATE_STATUS.id);664if (certStatCons != null) {665// Stapling was active but no certificate status message666// was sent. We need to run the absence handler which will667// check the certificate chain.668CertificateStatus.handshakeAbsence.absent(context, null);669}670671T12CertificateRequestMessage crm =672new T12CertificateRequestMessage(chc, message);673if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {674SSLLogger.fine(675"Consuming CertificateRequest handshake message", crm);676}677678//679// validate680//681// blank682683//684// update685//686687// An empty client Certificate handshake message may be allow.688chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,689SSLHandshake.CERTIFICATE);690691List<SignatureScheme> sss =692SignatureScheme.getSupportedAlgorithms(693chc.sslConfig,694chc.algorithmConstraints, chc.negotiatedProtocol,695crm.algorithmIds);696if (sss == null || sss.isEmpty()) {697throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,698"No supported signature algorithm");699}700701chc.peerRequestedSignatureSchemes = sss;702chc.peerRequestedCertSignSchemes = sss; // use the same schemes703chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss);704chc.peerSupportedAuthorities = crm.getAuthorities();705706// For TLS 1.2, we no longer use the certificate_types field707// from the CertificateRequest message to directly determine708// the SSLPossession. Instead, the choosePossession method709// will use the accepted signature schemes in the message to710// determine the set of acceptable certificate types to select from.711SSLPossession pos = choosePossession(chc);712if (pos == null) {713return;714}715716chc.handshakePossessions.add(pos);717chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,718SSLHandshake.CERTIFICATE_VERIFY);719}720721private static SSLPossession choosePossession(HandshakeContext hc)722throws IOException {723if (hc.peerRequestedCertSignSchemes == null ||724hc.peerRequestedCertSignSchemes.isEmpty()) {725if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {726SSLLogger.warning("No signature and hash algorithms " +727"in CertificateRequest");728}729return null;730}731732Collection<String> checkedKeyTypes = new HashSet<>();733for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) {734if (checkedKeyTypes.contains(ss.keyAlgorithm)) {735if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {736SSLLogger.warning(737"Unsupported authentication scheme: " + ss.name);738}739continue;740}741742// Don't select a signature scheme unless we will be able to743// produce a CertificateVerify message later744if (SignatureScheme.getPreferableAlgorithm(745hc.algorithmConstraints,746hc.peerRequestedSignatureSchemes,747ss, hc.negotiatedProtocol) == null) {748749if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {750SSLLogger.warning(751"Unable to produce CertificateVerify for " +752"signature scheme: " + ss.name);753}754checkedKeyTypes.add(ss.keyAlgorithm);755continue;756}757758SSLAuthentication ka = X509Authentication.valueOf(ss);759if (ka == null) {760if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {761SSLLogger.warning(762"Unsupported authentication scheme: " + ss.name);763}764checkedKeyTypes.add(ss.keyAlgorithm);765continue;766}767768SSLPossession pos = ka.createPossession(hc);769if (pos == null) {770if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {771SSLLogger.warning(772"Unavailable authentication scheme: " + ss.name);773}774continue;775}776777return pos;778}779780if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {781SSLLogger.warning("No available authentication scheme");782}783return null;784}785}786787/**788* The CertificateRequest handshake message for TLS 1.3.789*/790static final class T13CertificateRequestMessage extends HandshakeMessage {791private final byte[] requestContext;792private final SSLExtensions extensions;793794T13CertificateRequestMessage(795HandshakeContext handshakeContext) throws IOException {796super(handshakeContext);797798this.requestContext = new byte[0];799this.extensions = new SSLExtensions(this);800}801802T13CertificateRequestMessage(HandshakeContext handshakeContext,803ByteBuffer m) throws IOException {804super(handshakeContext);805806// struct {807// opaque certificate_request_context<0..2^8-1>;808// Extension extensions<2..2^16-1>;809// } CertificateRequest;810if (m.remaining() < 5) {811throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,812"Invalid CertificateRequest handshake message: " +813"no sufficient data");814}815this.requestContext = Record.getBytes8(m);816817if (m.remaining() < 4) {818throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,819"Invalid CertificateRequest handshake message: " +820"no sufficient extensions data");821}822SSLExtension[] enabledExtensions =823handshakeContext.sslConfig.getEnabledExtensions(824SSLHandshake.CERTIFICATE_REQUEST);825this.extensions = new SSLExtensions(this, m, enabledExtensions);826}827828@Override829SSLHandshake handshakeType() {830return SSLHandshake.CERTIFICATE_REQUEST;831}832833@Override834int messageLength() {835// In TLS 1.3, use of certain extensions is mandatory.836return 1 + requestContext.length + extensions.length();837}838839@Override840void send(HandshakeOutStream hos) throws IOException {841hos.putBytes8(requestContext);842843// In TLS 1.3, use of certain extensions is mandatory.844extensions.send(hos);845}846847@Override848public String toString() {849MessageFormat messageFormat = new MessageFormat(850"\"CertificateRequest\": '{'\n" +851" \"certificate_request_context\": \"{0}\",\n" +852" \"extensions\": [\n" +853"{1}\n" +854" ]\n" +855"'}'",856Locale.ENGLISH);857Object[] messageFields = {858Utilities.toHexString(requestContext),859Utilities.indent(Utilities.indent(extensions.toString()))860};861862return messageFormat.format(messageFields);863}864}865866/**867* The "CertificateRequest" handshake message producer for TLS 1.3.868*/869private static final870class T13CertificateRequestProducer implements HandshakeProducer {871// Prevent instantiation of this class.872private T13CertificateRequestProducer() {873// blank874}875876@Override877public byte[] produce(ConnectionContext context,878HandshakeMessage message) throws IOException {879// The producing happens in server side only.880ServerHandshakeContext shc = (ServerHandshakeContext)context;881882T13CertificateRequestMessage crm =883new T13CertificateRequestMessage(shc);884// Produce extensions for CertificateRequest handshake message.885SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(886SSLHandshake.CERTIFICATE_REQUEST, shc.negotiatedProtocol);887crm.extensions.produce(shc, extTypes);888if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {889SSLLogger.fine("Produced CertificateRequest message", crm);890}891892// Output the handshake message.893crm.write(shc.handshakeOutput);894shc.handshakeOutput.flush();895896//897// update898//899shc.certRequestContext = crm.requestContext.clone();900shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,901SSLHandshake.CERTIFICATE);902shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,903SSLHandshake.CERTIFICATE_VERIFY);904905// The handshake message has been delivered.906return null;907}908}909910/**911* The "CertificateRequest" handshake message consumer for TLS 1.3.912*/913private static final914class T13CertificateRequestConsumer implements SSLConsumer {915// Prevent instantiation of this class.916private T13CertificateRequestConsumer() {917// blank918}919920@Override921public void consume(ConnectionContext context,922ByteBuffer message) throws IOException {923// The consuming happens in client side only.924ClientHandshakeContext chc = (ClientHandshakeContext)context;925926// clean up this consumer927chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);928929T13CertificateRequestMessage crm =930new T13CertificateRequestMessage(chc, message);931if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {932SSLLogger.fine(933"Consuming CertificateRequest handshake message", crm);934}935936//937// validate938//939SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(940SSLHandshake.CERTIFICATE_REQUEST);941crm.extensions.consumeOnLoad(chc, extTypes);942943//944// update945//946crm.extensions.consumeOnTrade(chc, extTypes);947948//949// produce950//951chc.certRequestContext = crm.requestContext.clone();952chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,953SSLHandshake.CERTIFICATE);954chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,955SSLHandshake.CERTIFICATE_VERIFY);956}957}958}959960961