Path: blob/master/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java
41159 views
/*1* Copyright (c) 2015, 2020, 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.ByteArrayInputStream;28import java.io.IOException;29import java.nio.ByteBuffer;30import java.security.PublicKey;31import java.security.cert.CertPathValidatorException;32import java.security.cert.CertPathValidatorException.BasicReason;33import java.security.cert.CertPathValidatorException.Reason;34import java.security.cert.CertificateEncodingException;35import java.security.cert.CertificateException;36import java.security.cert.CertificateFactory;37import java.security.cert.CertificateParsingException;38import java.security.cert.X509Certificate;39import java.text.MessageFormat;40import java.util.ArrayList;41import java.util.Arrays;42import java.util.Collection;43import java.util.Collections;44import java.util.HashSet;45import java.util.LinkedList;46import java.util.List;47import java.util.Locale;48import javax.net.ssl.SSLEngine;49import javax.net.ssl.SSLException;50import javax.net.ssl.SSLProtocolException;51import javax.net.ssl.SSLSocket;52import javax.net.ssl.X509ExtendedTrustManager;53import javax.net.ssl.X509TrustManager;54import javax.security.auth.x500.X500Principal;55import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED;56import sun.security.ssl.ClientHello.ClientHelloMessage;57import sun.security.ssl.SSLHandshake.HandshakeMessage;58import sun.security.ssl.X509Authentication.X509Credentials;59import sun.security.ssl.X509Authentication.X509Possession;6061/**62* Pack of the CertificateMessage handshake message.63*/64final class CertificateMessage {65static final SSLConsumer t12HandshakeConsumer =66new T12CertificateConsumer();67static final HandshakeProducer t12HandshakeProducer =68new T12CertificateProducer();6970static final SSLConsumer t13HandshakeConsumer =71new T13CertificateConsumer();72static final HandshakeProducer t13HandshakeProducer =73new T13CertificateProducer();7475/**76* The Certificate handshake message for TLS 1.2 and previous77* SSL/TLS protocol versions.78*79* In server mode, the certificate handshake message is sent whenever the80* agreed-upon key exchange method uses certificates for authentication.81* In client mode, this message is only sent if the server requests a82* certificate for client authentication.83*84* opaque ASN.1Cert<1..2^24-1>;85*86* SSL 3.0:87* struct {88* ASN.1Cert certificate_list<1..2^24-1>;89* } Certificate;90* Note: For SSL 3.0 client authentication, if no suitable certificate91* is available, the client should send a no_certificate alert instead.92* This alert is only a warning; however, the server may respond with93* a fatal handshake failure alert if client authentication is required.94*95* TLS 1.0/1.1/1.2:96* struct {97* ASN.1Cert certificate_list<0..2^24-1>;98* } Certificate;99*/100static final class T12CertificateMessage extends HandshakeMessage {101final List<byte[]> encodedCertChain;102103T12CertificateMessage(HandshakeContext handshakeContext,104X509Certificate[] certChain) throws SSLException {105super(handshakeContext);106107List<byte[]> encodedCerts = new ArrayList<>(certChain.length);108for (X509Certificate cert : certChain) {109try {110encodedCerts.add(cert.getEncoded());111} catch (CertificateEncodingException cee) {112// unlikely113throw handshakeContext.conContext.fatal(114Alert.INTERNAL_ERROR,115"Could not encode certificate (" +116cert.getSubjectX500Principal() + ")", cee);117}118}119120this.encodedCertChain = encodedCerts;121}122123T12CertificateMessage(HandshakeContext handshakeContext,124ByteBuffer m) throws IOException {125super(handshakeContext);126127int listLen = Record.getInt24(m);128if (listLen > m.remaining()) {129throw handshakeContext.conContext.fatal(130Alert.ILLEGAL_PARAMETER,131"Error parsing certificate message:no sufficient data");132}133if (listLen > 0) {134List<byte[]> encodedCerts = new LinkedList<>();135while (listLen > 0) {136byte[] encodedCert = Record.getBytes24(m);137listLen -= (3 + encodedCert.length);138encodedCerts.add(encodedCert);139if (encodedCerts.size() > SSLConfiguration.maxCertificateChainLength) {140throw new SSLProtocolException(141"The certificate chain length ("142+ encodedCerts.size()143+ ") exceeds the maximum allowed length ("144+ SSLConfiguration.maxCertificateChainLength145+ ")");146}147148}149this.encodedCertChain = encodedCerts;150} else {151this.encodedCertChain = Collections.emptyList();152}153}154155@Override156public SSLHandshake handshakeType() {157return SSLHandshake.CERTIFICATE;158}159160@Override161public int messageLength() {162int msgLen = 3;163for (byte[] encodedCert : encodedCertChain) {164msgLen += (encodedCert.length + 3);165}166167return msgLen;168}169170@Override171public void send(HandshakeOutStream hos) throws IOException {172int listLen = 0;173for (byte[] encodedCert : encodedCertChain) {174listLen += (encodedCert.length + 3);175}176177hos.putInt24(listLen);178for (byte[] encodedCert : encodedCertChain) {179hos.putBytes24(encodedCert);180}181}182183@Override184public String toString() {185if (encodedCertChain.isEmpty()) {186return "\"Certificates\": <empty list>";187}188189Object[] x509Certs = new Object[encodedCertChain.size()];190try {191CertificateFactory cf = CertificateFactory.getInstance("X.509");192int i = 0;193for (byte[] encodedCert : encodedCertChain) {194Object obj;195try {196obj = (X509Certificate)cf.generateCertificate(197new ByteArrayInputStream(encodedCert));198} catch (CertificateException ce) {199obj = encodedCert;200}201x509Certs[i++] = obj;202}203} catch (CertificateException ce) {204// no X.509 certificate factory service205int i = 0;206for (byte[] encodedCert : encodedCertChain) {207x509Certs[i++] = encodedCert;208}209}210211MessageFormat messageFormat = new MessageFormat(212"\"Certificates\": [\n" +213"{0}\n" +214"]",215Locale.ENGLISH);216Object[] messageFields = {217SSLLogger.toString(x509Certs)218};219220return messageFormat.format(messageFields);221}222}223224/**225* The "Certificate" handshake message producer for TLS 1.2 and226* previous SSL/TLS protocol versions.227*/228private static final229class T12CertificateProducer implements HandshakeProducer {230// Prevent instantiation of this class.231private T12CertificateProducer() {232// blank233}234235@Override236public byte[] produce(ConnectionContext context,237HandshakeMessage message) throws IOException {238// The producing happens in handshake context only.239HandshakeContext hc = (HandshakeContext)context;240if (hc.sslConfig.isClientMode) {241return onProduceCertificate(242(ClientHandshakeContext)context, message);243} else {244return onProduceCertificate(245(ServerHandshakeContext)context, message);246}247}248249private byte[] onProduceCertificate(ServerHandshakeContext shc,250SSLHandshake.HandshakeMessage message) throws IOException {251X509Possession x509Possession = null;252for (SSLPossession possession : shc.handshakePossessions) {253if (possession instanceof X509Possession) {254x509Possession = (X509Possession)possession;255break;256}257}258259if (x509Possession == null) { // unlikely260throw shc.conContext.fatal(Alert.INTERNAL_ERROR,261"No expected X.509 certificate for server authentication");262}263264shc.handshakeSession.setLocalPrivateKey(265x509Possession.popPrivateKey);266shc.handshakeSession.setLocalCertificates(x509Possession.popCerts);267T12CertificateMessage cm =268new T12CertificateMessage(shc, x509Possession.popCerts);269if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {270SSLLogger.fine(271"Produced server Certificate handshake message", cm);272}273274// Output the handshake message.275cm.write(shc.handshakeOutput);276shc.handshakeOutput.flush();277278// The handshake message has been delivered.279return null;280}281282private byte[] onProduceCertificate(ClientHandshakeContext chc,283SSLHandshake.HandshakeMessage message) throws IOException {284X509Possession x509Possession = null;285for (SSLPossession possession : chc.handshakePossessions) {286if (possession instanceof X509Possession) {287x509Possession = (X509Possession)possession;288break;289}290}291292// Report to the server if no appropriate cert was found. For293// SSL 3.0, send a no_certificate alert; TLS 1.0/1.1/1.2 uses294// an empty cert chain instead.295if (x509Possession == null) {296if (chc.negotiatedProtocol.useTLS10PlusSpec()) {297if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {298SSLLogger.fine(299"No X.509 certificate for client authentication, " +300"use empty Certificate message instead");301}302303x509Possession =304new X509Possession(null, new X509Certificate[0]);305} else {306if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {307SSLLogger.fine(308"No X.509 certificate for client authentication, " +309"send a no_certificate alert");310}311312chc.conContext.warning(Alert.NO_CERTIFICATE);313return null;314}315}316317chc.handshakeSession.setLocalPrivateKey(318x509Possession.popPrivateKey);319if (x509Possession.popCerts != null &&320x509Possession.popCerts.length != 0) {321chc.handshakeSession.setLocalCertificates(322x509Possession.popCerts);323} else {324chc.handshakeSession.setLocalCertificates(null);325}326T12CertificateMessage cm =327new T12CertificateMessage(chc, x509Possession.popCerts);328if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {329SSLLogger.fine(330"Produced client Certificate handshake message", cm);331}332333// Output the handshake message.334cm.write(chc.handshakeOutput);335chc.handshakeOutput.flush();336337// The handshake message has been delivered.338return null;339}340}341342/**343* The "Certificate" handshake message consumer for TLS 1.2 and344* previous SSL/TLS protocol versions.345*/346static final347class T12CertificateConsumer implements SSLConsumer {348// Prevent instantiation of this class.349private T12CertificateConsumer() {350// blank351}352353@Override354public void consume(ConnectionContext context,355ByteBuffer message) throws IOException {356// The consuming happens in handshake context only.357HandshakeContext hc = (HandshakeContext)context;358359// clean up this consumer360hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id);361362T12CertificateMessage cm = new T12CertificateMessage(hc, message);363if (hc.sslConfig.isClientMode) {364if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {365SSLLogger.fine(366"Consuming server Certificate handshake message", cm);367}368onCertificate((ClientHandshakeContext)context, cm);369} else {370if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {371SSLLogger.fine(372"Consuming client Certificate handshake message", cm);373}374onCertificate((ServerHandshakeContext)context, cm);375}376}377378private void onCertificate(ServerHandshakeContext shc,379T12CertificateMessage certificateMessage )throws IOException {380List<byte[]> encodedCerts = certificateMessage.encodedCertChain;381if (encodedCerts == null || encodedCerts.isEmpty()) {382// For empty Certificate messages, we should not expect383// a CertificateVerify message to follow384shc.handshakeConsumers.remove(385SSLHandshake.CERTIFICATE_VERIFY.id);386if (shc.sslConfig.clientAuthType !=387ClientAuthType.CLIENT_AUTH_REQUESTED) {388// unexpected or require client authentication389throw shc.conContext.fatal(Alert.BAD_CERTIFICATE,390"Empty server certificate chain");391} else {392return;393}394}395396X509Certificate[] x509Certs =397new X509Certificate[encodedCerts.size()];398try {399CertificateFactory cf = CertificateFactory.getInstance("X.509");400int i = 0;401for (byte[] encodedCert : encodedCerts) {402x509Certs[i++] = (X509Certificate)cf.generateCertificate(403new ByteArrayInputStream(encodedCert));404}405} catch (CertificateException ce) {406throw shc.conContext.fatal(Alert.BAD_CERTIFICATE,407"Failed to parse server certificates", ce);408}409410checkClientCerts(shc, x509Certs);411412//413// update414//415shc.handshakeCredentials.add(416new X509Credentials(x509Certs[0].getPublicKey(), x509Certs));417shc.handshakeSession.setPeerCertificates(x509Certs);418}419420private void onCertificate(ClientHandshakeContext chc,421T12CertificateMessage certificateMessage) throws IOException {422List<byte[]> encodedCerts = certificateMessage.encodedCertChain;423if (encodedCerts == null || encodedCerts.isEmpty()) {424throw chc.conContext.fatal(Alert.BAD_CERTIFICATE,425"Empty server certificate chain");426}427428X509Certificate[] x509Certs =429new X509Certificate[encodedCerts.size()];430try {431CertificateFactory cf = CertificateFactory.getInstance("X.509");432int i = 0;433for (byte[] encodedCert : encodedCerts) {434x509Certs[i++] = (X509Certificate)cf.generateCertificate(435new ByteArrayInputStream(encodedCert));436}437} catch (CertificateException ce) {438throw chc.conContext.fatal(Alert.BAD_CERTIFICATE,439"Failed to parse server certificates", ce);440}441442// Allow server certificate change in client side during443// renegotiation after a session-resumption abbreviated444// initial handshake?445//446// DO NOT need to check allowUnsafeServerCertChange here. We only447// reserve server certificates when allowUnsafeServerCertChange is448// false.449if (chc.reservedServerCerts != null &&450!chc.handshakeSession.useExtendedMasterSecret) {451// It is not necessary to check the certificate update if452// endpoint identification is enabled.453String identityAlg = chc.sslConfig.identificationProtocol;454if ((identityAlg == null || identityAlg.isEmpty()) &&455!isIdentityEquivalent(x509Certs[0],456chc.reservedServerCerts[0])) {457throw chc.conContext.fatal(Alert.BAD_CERTIFICATE,458"server certificate change is restricted " +459"during renegotiation");460}461}462463// ask the trust manager to verify the chain464if (chc.staplingActive) {465// Defer the certificate check until after we've received the466// CertificateStatus message. If that message doesn't come in467// immediately following this message we will execute the468// check from CertificateStatus' absent handler.469chc.deferredCerts = x509Certs;470} else {471// We're not doing stapling, so perform the check right now472checkServerCerts(chc, x509Certs);473}474475//476// update477//478chc.handshakeCredentials.add(479new X509Credentials(x509Certs[0].getPublicKey(), x509Certs));480chc.handshakeSession.setPeerCertificates(x509Certs);481}482483/*484* Whether the certificates can represent the same identity?485*486* The certificates can be used to represent the same identity:487* 1. If the subject alternative names of IP address are present488* in both certificates, they should be identical; otherwise,489* 2. if the subject alternative names of DNS name are present in490* both certificates, they should be identical; otherwise,491* 3. if the subject fields are present in both certificates, the492* certificate subjects and issuers should be identical.493*/494private static boolean isIdentityEquivalent(X509Certificate thisCert,495X509Certificate prevCert) {496if (thisCert.equals(prevCert)) {497return true;498}499500// check subject alternative names501Collection<List<?>> thisSubjectAltNames = null;502try {503thisSubjectAltNames = thisCert.getSubjectAlternativeNames();504} catch (CertificateParsingException cpe) {505if (SSLLogger.isOn && SSLLogger.isOn("handshake")) {506SSLLogger.fine(507"Attempt to obtain subjectAltNames extension failed!");508}509}510511Collection<List<?>> prevSubjectAltNames = null;512try {513prevSubjectAltNames = prevCert.getSubjectAlternativeNames();514} catch (CertificateParsingException cpe) {515if (SSLLogger.isOn && SSLLogger.isOn("handshake")) {516SSLLogger.fine(517"Attempt to obtain subjectAltNames extension failed!");518}519}520521if (thisSubjectAltNames != null && prevSubjectAltNames != null) {522// check the iPAddress field in subjectAltName extension523//524// 7: subject alternative name of type IP.525Collection<String> thisSubAltIPAddrs =526getSubjectAltNames(thisSubjectAltNames, 7);527Collection<String> prevSubAltIPAddrs =528getSubjectAltNames(prevSubjectAltNames, 7);529if (thisSubAltIPAddrs != null && prevSubAltIPAddrs != null &&530isEquivalent(thisSubAltIPAddrs, prevSubAltIPAddrs)) {531return true;532}533534// check the dNSName field in subjectAltName extension535// 2: subject alternative name of type IP.536Collection<String> thisSubAltDnsNames =537getSubjectAltNames(thisSubjectAltNames, 2);538Collection<String> prevSubAltDnsNames =539getSubjectAltNames(prevSubjectAltNames, 2);540if (thisSubAltDnsNames != null && prevSubAltDnsNames != null &&541isEquivalent(thisSubAltDnsNames, prevSubAltDnsNames)) {542return true;543}544}545546// check the certificate subject and issuer547X500Principal thisSubject = thisCert.getSubjectX500Principal();548X500Principal prevSubject = prevCert.getSubjectX500Principal();549X500Principal thisIssuer = thisCert.getIssuerX500Principal();550X500Principal prevIssuer = prevCert.getIssuerX500Principal();551552return (!thisSubject.getName().isEmpty() &&553!prevSubject.getName().isEmpty() &&554thisSubject.equals(prevSubject) &&555thisIssuer.equals(prevIssuer));556}557558/*559* Returns the subject alternative name of the specified type in the560* subjectAltNames extension of a certificate.561*562* Note that only those subjectAltName types that use String data563* should be passed into this function.564*/565private static Collection<String> getSubjectAltNames(566Collection<List<?>> subjectAltNames, int type) {567HashSet<String> subAltDnsNames = null;568for (List<?> subjectAltName : subjectAltNames) {569int subjectAltNameType = (Integer)subjectAltName.get(0);570if (subjectAltNameType == type) {571String subAltDnsName = (String)subjectAltName.get(1);572if ((subAltDnsName != null) && !subAltDnsName.isEmpty()) {573if (subAltDnsNames == null) {574subAltDnsNames =575new HashSet<>(subjectAltNames.size());576}577subAltDnsNames.add(subAltDnsName);578}579}580}581582return subAltDnsNames;583}584585private static boolean isEquivalent(Collection<String> thisSubAltNames,586Collection<String> prevSubAltNames) {587for (String thisSubAltName : thisSubAltNames) {588for (String prevSubAltName : prevSubAltNames) {589// Only allow the exactly match. No wildcard character590// checking.591if (thisSubAltName.equalsIgnoreCase(prevSubAltName)) {592return true;593}594}595}596597return false;598}599600/**601* Perform client-side checking of server certificates.602*603* @param certs an array of {@code X509Certificate} objects presented604* by the server in the ServerCertificate message.605*606* @throws IOException if a failure occurs during validation or607* the trust manager associated with the {@code SSLContext} is not608* an {@code X509ExtendedTrustManager}.609*/610static void checkServerCerts(ClientHandshakeContext chc,611X509Certificate[] certs) throws IOException {612613X509TrustManager tm = chc.sslContext.getX509TrustManager();614615// find out the key exchange algorithm used616// use "RSA" for non-ephemeral "RSA_EXPORT"617String keyExchangeString;618if (chc.negotiatedCipherSuite.keyExchange ==619CipherSuite.KeyExchange.K_RSA_EXPORT ||620chc.negotiatedCipherSuite.keyExchange ==621CipherSuite.KeyExchange.K_DHE_RSA_EXPORT) {622keyExchangeString = CipherSuite.KeyExchange.K_RSA.name;623} else {624keyExchangeString = chc.negotiatedCipherSuite.keyExchange.name;625}626627try {628if (tm instanceof X509ExtendedTrustManager) {629if (chc.conContext.transport instanceof SSLEngine) {630SSLEngine engine = (SSLEngine)chc.conContext.transport;631((X509ExtendedTrustManager)tm).checkServerTrusted(632certs.clone(),633keyExchangeString,634engine);635} else {636SSLSocket socket = (SSLSocket)chc.conContext.transport;637((X509ExtendedTrustManager)tm).checkServerTrusted(638certs.clone(),639keyExchangeString,640socket);641}642} else {643// Unlikely to happen, because we have wrapped the old644// X509TrustManager with the new X509ExtendedTrustManager.645throw new CertificateException(646"Improper X509TrustManager implementation");647}648649// Once the server certificate chain has been validated, set650// the certificate chain in the TLS session.651chc.handshakeSession.setPeerCertificates(certs);652} catch (CertificateException ce) {653throw chc.conContext.fatal(getCertificateAlert(chc, ce), ce);654}655}656657private static void checkClientCerts(ServerHandshakeContext shc,658X509Certificate[] certs) throws IOException {659X509TrustManager tm = shc.sslContext.getX509TrustManager();660661// find out the types of client authentication used662PublicKey key = certs[0].getPublicKey();663String keyAlgorithm = key.getAlgorithm();664String authType;665switch (keyAlgorithm) {666case "RSA":667case "DSA":668case "EC":669case "RSASSA-PSS":670authType = keyAlgorithm;671break;672default:673// unknown public key type674authType = "UNKNOWN";675}676677try {678if (tm instanceof X509ExtendedTrustManager) {679if (shc.conContext.transport instanceof SSLEngine) {680SSLEngine engine = (SSLEngine)shc.conContext.transport;681((X509ExtendedTrustManager)tm).checkClientTrusted(682certs.clone(),683authType,684engine);685} else {686SSLSocket socket = (SSLSocket)shc.conContext.transport;687((X509ExtendedTrustManager)tm).checkClientTrusted(688certs.clone(),689authType,690socket);691}692} else {693// Unlikely to happen, because we have wrapped the old694// X509TrustManager with the new X509ExtendedTrustManager.695throw new CertificateException(696"Improper X509TrustManager implementation");697}698} catch (CertificateException ce) {699throw shc.conContext.fatal(Alert.CERTIFICATE_UNKNOWN, ce);700}701}702703/**704* When a failure happens during certificate checking from an705* {@link X509TrustManager}, determine what TLS alert description706* to use.707*708* @param cexc The exception thrown by the {@link X509TrustManager}709*710* @return A byte value corresponding to a TLS alert description number.711*/712private static Alert getCertificateAlert(713ClientHandshakeContext chc, CertificateException cexc) {714// The specific reason for the failure will determine how to715// set the alert description value716Alert alert = Alert.CERTIFICATE_UNKNOWN;717718Throwable baseCause = cexc.getCause();719if (baseCause instanceof CertPathValidatorException) {720CertPathValidatorException cpve =721(CertPathValidatorException)baseCause;722Reason reason = cpve.getReason();723if (reason == BasicReason.REVOKED) {724alert = chc.staplingActive ?725Alert.BAD_CERT_STATUS_RESPONSE :726Alert.CERTIFICATE_REVOKED;727} else if (728reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) {729alert = chc.staplingActive ?730Alert.BAD_CERT_STATUS_RESPONSE :731Alert.CERTIFICATE_UNKNOWN;732} else if (reason == BasicReason.ALGORITHM_CONSTRAINED) {733alert = Alert.UNSUPPORTED_CERTIFICATE;734} else if (reason == BasicReason.EXPIRED) {735alert = Alert.CERTIFICATE_EXPIRED;736} else if (reason == BasicReason.INVALID_SIGNATURE ||737reason == BasicReason.NOT_YET_VALID) {738alert = Alert.BAD_CERTIFICATE;739}740}741742return alert;743}744745}746747/**748* The certificate entry used in Certificate handshake message for TLS 1.3.749*/750static final class CertificateEntry {751final byte[] encoded; // encoded cert or public key752private final SSLExtensions extensions;753754CertificateEntry(byte[] encoded, SSLExtensions extensions) {755this.encoded = encoded;756this.extensions = extensions;757}758759private int getEncodedSize() {760int extLen = extensions.length();761if (extLen == 0) {762extLen = 2; // empty extensions763}764return 3 + encoded.length + extLen;765}766767@Override768public String toString() {769MessageFormat messageFormat = new MessageFormat(770"\n'{'\n" +771"{0}\n" + // X.509 certificate772" \"extensions\": '{'\n" +773"{1}\n" +774" '}'\n" +775"'}',", Locale.ENGLISH);776777Object x509Certs;778try {779// Don't support certificate type extension (RawPublicKey) yet.780CertificateFactory cf = CertificateFactory.getInstance("X.509");781x509Certs =782cf.generateCertificate(new ByteArrayInputStream(encoded));783} catch (CertificateException ce) {784// no X.509 certificate factory service785x509Certs = encoded;786}787788Object[] messageFields = {789SSLLogger.toString(x509Certs),790Utilities.indent(extensions.toString(), " ")791};792793return messageFormat.format(messageFields);794}795}796797/**798* The Certificate handshake message for TLS 1.3.799*/800static final class T13CertificateMessage extends HandshakeMessage {801private final byte[] requestContext;802private final List<CertificateEntry> certEntries;803804T13CertificateMessage(HandshakeContext context,805byte[] requestContext, X509Certificate[] certificates)806throws SSLException, CertificateException {807super(context);808809this.requestContext = requestContext.clone();810this.certEntries = new LinkedList<>();811for (X509Certificate cert : certificates) {812byte[] encoded = cert.getEncoded();813SSLExtensions extensions = new SSLExtensions(this);814certEntries.add(new CertificateEntry(encoded, extensions));815}816}817818T13CertificateMessage(HandshakeContext handshakeContext,819byte[] requestContext, List<CertificateEntry> certificates) {820super(handshakeContext);821822this.requestContext = requestContext.clone();823this.certEntries = certificates;824}825826T13CertificateMessage(HandshakeContext handshakeContext,827ByteBuffer m) throws IOException {828super(handshakeContext);829830// struct {831// opaque certificate_request_context<0..2^8-1>;832// CertificateEntry certificate_list<0..2^24-1>;833// } Certificate;834if (m.remaining() < 4) {835throw new SSLProtocolException(836"Invalid Certificate message: " +837"insufficient data (length=" + m.remaining() + ")");838}839this.requestContext = Record.getBytes8(m);840841if (m.remaining() < 3) {842throw new SSLProtocolException(843"Invalid Certificate message: " +844"insufficient certificate entries data (length=" +845m.remaining() + ")");846}847848int listLen = Record.getInt24(m);849if (listLen != m.remaining()) {850throw new SSLProtocolException(851"Invalid Certificate message: " +852"incorrect list length (length=" + listLen + ")");853}854855SSLExtension[] enabledExtensions =856handshakeContext.sslConfig.getEnabledExtensions(857SSLHandshake.CERTIFICATE);858List<CertificateEntry> certList = new LinkedList<>();859while (m.hasRemaining()) {860// Note: support only X509 CertificateType right now.861byte[] encodedCert = Record.getBytes24(m);862if (encodedCert.length == 0) {863throw new SSLProtocolException(864"Invalid Certificate message: empty cert_data");865}866867SSLExtensions extensions =868new SSLExtensions(this, m, enabledExtensions);869certList.add(new CertificateEntry(encodedCert, extensions));870if (certList.size() > SSLConfiguration.maxCertificateChainLength) {871throw new SSLProtocolException(872"The certificate chain length ("873+ certList.size()874+ ") exceeds the maximum allowed length ("875+ SSLConfiguration.maxCertificateChainLength876+ ")");877}878}879880this.certEntries = Collections.unmodifiableList(certList);881}882883@Override884public SSLHandshake handshakeType() {885return SSLHandshake.CERTIFICATE;886}887888@Override889public int messageLength() {890int msgLen = 4 + requestContext.length;891for (CertificateEntry entry : certEntries) {892msgLen += entry.getEncodedSize();893}894895return msgLen;896}897898@Override899public void send(HandshakeOutStream hos) throws IOException {900int entryListLen = 0;901for (CertificateEntry entry : certEntries) {902entryListLen += entry.getEncodedSize();903}904905hos.putBytes8(requestContext);906hos.putInt24(entryListLen);907for (CertificateEntry entry : certEntries) {908hos.putBytes24(entry.encoded);909// Is it an empty extensions?910if (entry.extensions.length() == 0) {911hos.putInt16(0);912} else {913entry.extensions.send(hos);914}915}916}917918@Override919public String toString() {920MessageFormat messageFormat = new MessageFormat(921"\"Certificate\": '{'\n" +922" \"certificate_request_context\": \"{0}\",\n" +923" \"certificate_list\": [{1}\n]\n" +924"'}'",925Locale.ENGLISH);926927StringBuilder builder = new StringBuilder(512);928for (CertificateEntry entry : certEntries) {929builder.append(entry.toString());930}931932Object[] messageFields = {933Utilities.toHexString(requestContext),934Utilities.indent(builder.toString())935};936937return messageFormat.format(messageFields);938}939}940941/**942* The "Certificate" handshake message producer for TLS 1.3.943*/944private static final945class T13CertificateProducer implements HandshakeProducer {946// Prevent instantiation of this class.947private T13CertificateProducer() {948// blank949}950951@Override952public byte[] produce(ConnectionContext context,953HandshakeMessage message) throws IOException {954// The producing happens in handshake context only.955HandshakeContext hc = (HandshakeContext)context;956if (hc.sslConfig.isClientMode) {957return onProduceCertificate(958(ClientHandshakeContext)context, message);959} else {960return onProduceCertificate(961(ServerHandshakeContext)context, message);962}963}964965private byte[] onProduceCertificate(ServerHandshakeContext shc,966HandshakeMessage message) throws IOException {967ClientHelloMessage clientHello = (ClientHelloMessage)message;968969SSLPossession pos = choosePossession(shc, clientHello);970if (pos == null) {971throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,972"No available authentication scheme");973}974975if (!(pos instanceof X509Possession)) {976throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,977"No X.509 certificate for server authentication");978}979980X509Possession x509Possession = (X509Possession)pos;981X509Certificate[] localCerts = x509Possession.popCerts;982if (localCerts == null || localCerts.length == 0) {983throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,984"No X.509 certificate for server authentication");985}986987// update the context988shc.handshakePossessions.add(x509Possession);989shc.handshakeSession.setLocalPrivateKey(990x509Possession.popPrivateKey);991shc.handshakeSession.setLocalCertificates(localCerts);992T13CertificateMessage cm;993try {994cm = new T13CertificateMessage(shc, (new byte[0]), localCerts);995} catch (SSLException | CertificateException ce) {996throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,997"Failed to produce server Certificate message", ce);998}9991000// Check the OCSP stapling extensions and attempt1001// to get responses. If the resulting stapleParams is non1002// null, it implies that stapling is enabled on the server side.1003shc.stapleParams = StatusResponseManager.processStapling(shc);1004shc.staplingActive = (shc.stapleParams != null);10051006// Process extensions for each CertificateEntry.1007// Since there can be multiple CertificateEntries within a1008// single CT message, we will pin a specific CertificateEntry1009// into the ServerHandshakeContext so individual extension1010// producers know which X509Certificate it is processing in1011// each call.1012SSLExtension[] enabledCTExts = shc.sslConfig.getEnabledExtensions(1013SSLHandshake.CERTIFICATE,1014Arrays.asList(ProtocolVersion.PROTOCOLS_OF_13));1015for (CertificateEntry certEnt : cm.certEntries) {1016shc.currentCertEntry = certEnt;1017certEnt.extensions.produce(shc, enabledCTExts);1018}10191020if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1021SSLLogger.fine("Produced server Certificate message", cm);1022}10231024// Output the handshake message.1025cm.write(shc.handshakeOutput);1026shc.handshakeOutput.flush();10271028// The handshake message has been delivered.1029return null;1030}10311032private static SSLPossession choosePossession(1033HandshakeContext hc,1034ClientHelloMessage clientHello) throws IOException {1035if (hc.peerRequestedCertSignSchemes == null ||1036hc.peerRequestedCertSignSchemes.isEmpty()) {1037if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1038SSLLogger.warning(1039"No signature_algorithms(_cert) in ClientHello");1040}1041return null;1042}10431044Collection<String> checkedKeyTypes = new HashSet<>();1045for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) {1046if (checkedKeyTypes.contains(ss.keyAlgorithm)) {1047if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1048SSLLogger.warning(1049"Unsupported authentication scheme: " + ss.name);1050}1051continue;1052}10531054// Don't select a signature scheme unless we will be able to1055// produce a CertificateVerify message later1056if (SignatureScheme.getPreferableAlgorithm(1057hc.algorithmConstraints,1058hc.peerRequestedSignatureSchemes,1059ss, hc.negotiatedProtocol) == null) {10601061if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1062SSLLogger.warning(1063"Unable to produce CertificateVerify for " +1064"signature scheme: " + ss.name);1065}1066checkedKeyTypes.add(ss.keyAlgorithm);1067continue;1068}10691070SSLAuthentication ka = X509Authentication.valueOf(ss);1071if (ka == null) {1072if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1073SSLLogger.warning(1074"Unsupported authentication scheme: " + ss.name);1075}1076checkedKeyTypes.add(ss.keyAlgorithm);1077continue;1078}10791080SSLPossession pos = ka.createPossession(hc);1081if (pos == null) {1082if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1083SSLLogger.warning(1084"Unavailable authentication scheme: " + ss.name);1085}1086continue;1087}10881089return pos;1090}10911092if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1093SSLLogger.warning("No available authentication scheme");1094}1095return null;1096}10971098private byte[] onProduceCertificate(ClientHandshakeContext chc,1099HandshakeMessage message) throws IOException {1100ClientHelloMessage clientHello = (ClientHelloMessage)message;1101SSLPossession pos = choosePossession(chc, clientHello);1102X509Certificate[] localCerts;1103if (pos == null) {1104if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1105SSLLogger.fine("No available client authentication scheme");1106}1107localCerts = new X509Certificate[0];1108} else {1109chc.handshakePossessions.add(pos);1110if (!(pos instanceof X509Possession)) {1111if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1112SSLLogger.fine(1113"No X.509 certificate for client authentication");1114}1115localCerts = new X509Certificate[0];1116} else {1117X509Possession x509Possession = (X509Possession)pos;1118localCerts = x509Possession.popCerts;1119chc.handshakeSession.setLocalPrivateKey(1120x509Possession.popPrivateKey);1121}1122}11231124if (localCerts != null && localCerts.length != 0) {1125chc.handshakeSession.setLocalCertificates(localCerts);1126} else {1127chc.handshakeSession.setLocalCertificates(null);1128}11291130T13CertificateMessage cm;1131try {1132cm = new T13CertificateMessage(1133chc, chc.certRequestContext, localCerts);1134} catch (SSLException | CertificateException ce) {1135throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,1136"Failed to produce client Certificate message", ce);1137}1138if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1139SSLLogger.fine("Produced client Certificate message", cm);1140}11411142// Output the handshake message.1143cm.write(chc.handshakeOutput);1144chc.handshakeOutput.flush();11451146// The handshake message has been delivered.1147return null;1148}1149}11501151/**1152* The "Certificate" handshake message consumer for TLS 1.3.1153*/1154private static final class T13CertificateConsumer implements SSLConsumer {1155// Prevent instantiation of this class.1156private T13CertificateConsumer() {1157// blank1158}11591160@Override1161public void consume(ConnectionContext context,1162ByteBuffer message) throws IOException {1163// The consuming happens in handshake context only.1164HandshakeContext hc = (HandshakeContext)context;11651166// clean up this consumer1167hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id);1168T13CertificateMessage cm = new T13CertificateMessage(hc, message);1169if (hc.sslConfig.isClientMode) {1170if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1171SSLLogger.fine(1172"Consuming server Certificate handshake message", cm);1173}1174onConsumeCertificate((ClientHandshakeContext)context, cm);1175} else {1176if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1177SSLLogger.fine(1178"Consuming client Certificate handshake message", cm);1179}1180onConsumeCertificate((ServerHandshakeContext)context, cm);1181}1182}11831184private void onConsumeCertificate(ServerHandshakeContext shc,1185T13CertificateMessage certificateMessage )throws IOException {1186if (certificateMessage.certEntries == null ||1187certificateMessage.certEntries.isEmpty()) {1188// For empty Certificate messages, we should not expect1189// a CertificateVerify message to follow1190shc.handshakeConsumers.remove(1191SSLHandshake.CERTIFICATE_VERIFY.id);1192if (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED) {1193throw shc.conContext.fatal(Alert.BAD_CERTIFICATE,1194"Empty client certificate chain");1195} else {1196// optional client authentication1197return;1198}1199}12001201// check client certificate entries1202X509Certificate[] cliCerts =1203checkClientCerts(shc, certificateMessage.certEntries);12041205//1206// update1207//1208shc.handshakeCredentials.add(1209new X509Credentials(cliCerts[0].getPublicKey(), cliCerts));1210shc.handshakeSession.setPeerCertificates(cliCerts);1211}12121213private void onConsumeCertificate(ClientHandshakeContext chc,1214T13CertificateMessage certificateMessage )throws IOException {1215if (certificateMessage.certEntries == null ||1216certificateMessage.certEntries.isEmpty()) {1217throw chc.conContext.fatal(Alert.BAD_CERTIFICATE,1218"Empty server certificate chain");1219}12201221// Each CertificateEntry will have its own set of extensions1222// which must be consumed.1223SSLExtension[] enabledExtensions =1224chc.sslConfig.getEnabledExtensions(SSLHandshake.CERTIFICATE);1225for (CertificateEntry certEnt : certificateMessage.certEntries) {1226certEnt.extensions.consumeOnLoad(chc, enabledExtensions);1227}12281229// check server certificate entries1230X509Certificate[] srvCerts =1231checkServerCerts(chc, certificateMessage.certEntries);12321233//1234// update1235//1236chc.handshakeCredentials.add(1237new X509Credentials(srvCerts[0].getPublicKey(), srvCerts));1238chc.handshakeSession.setPeerCertificates(srvCerts);1239}12401241private static X509Certificate[] checkClientCerts(1242ServerHandshakeContext shc,1243List<CertificateEntry> certEntries) throws IOException {1244X509Certificate[] certs =1245new X509Certificate[certEntries.size()];1246try {1247CertificateFactory cf = CertificateFactory.getInstance("X.509");1248int i = 0;1249for (CertificateEntry entry : certEntries) {1250certs[i++] = (X509Certificate)cf.generateCertificate(1251new ByteArrayInputStream(entry.encoded));1252}1253} catch (CertificateException ce) {1254throw shc.conContext.fatal(Alert.BAD_CERTIFICATE,1255"Failed to parse server certificates", ce);1256}12571258// find out the types of client authentication used1259String keyAlgorithm = certs[0].getPublicKey().getAlgorithm();1260String authType;1261switch (keyAlgorithm) {1262case "RSA":1263case "DSA":1264case "EC":1265case "RSASSA-PSS":1266authType = keyAlgorithm;1267break;1268default:1269// unknown public key type1270authType = "UNKNOWN";1271}12721273try {1274X509TrustManager tm = shc.sslContext.getX509TrustManager();1275if (tm instanceof X509ExtendedTrustManager) {1276if (shc.conContext.transport instanceof SSLEngine) {1277SSLEngine engine = (SSLEngine)shc.conContext.transport;1278((X509ExtendedTrustManager)tm).checkClientTrusted(1279certs.clone(),1280authType,1281engine);1282} else {1283SSLSocket socket = (SSLSocket)shc.conContext.transport;1284((X509ExtendedTrustManager)tm).checkClientTrusted(1285certs.clone(),1286authType,1287socket);1288}1289} else {1290// Unlikely to happen, because we have wrapped the old1291// X509TrustManager with the new X509ExtendedTrustManager.1292throw new CertificateException(1293"Improper X509TrustManager implementation");1294}12951296// Once the client certificate chain has been validated, set1297// the certificate chain in the TLS session.1298shc.handshakeSession.setPeerCertificates(certs);1299} catch (CertificateException ce) {1300throw shc.conContext.fatal(Alert.CERTIFICATE_UNKNOWN, ce);1301}13021303return certs;1304}13051306private static X509Certificate[] checkServerCerts(1307ClientHandshakeContext chc,1308List<CertificateEntry> certEntries) throws IOException {1309X509Certificate[] certs =1310new X509Certificate[certEntries.size()];1311try {1312CertificateFactory cf = CertificateFactory.getInstance("X.509");1313int i = 0;1314for (CertificateEntry entry : certEntries) {1315certs[i++] = (X509Certificate)cf.generateCertificate(1316new ByteArrayInputStream(entry.encoded));1317}1318} catch (CertificateException ce) {1319throw chc.conContext.fatal(Alert.BAD_CERTIFICATE,1320"Failed to parse server certificates", ce);1321}13221323// find out the types of server authentication used1324//1325// Note that the "UNKNOWN" authentication type is sufficient to1326// check the required digitalSignature KeyUsage for TLS 1.3.1327String authType = "UNKNOWN";13281329try {1330X509TrustManager tm = chc.sslContext.getX509TrustManager();1331if (tm instanceof X509ExtendedTrustManager) {1332if (chc.conContext.transport instanceof SSLEngine) {1333SSLEngine engine = (SSLEngine)chc.conContext.transport;1334((X509ExtendedTrustManager)tm).checkServerTrusted(1335certs.clone(),1336authType,1337engine);1338} else {1339SSLSocket socket = (SSLSocket)chc.conContext.transport;1340((X509ExtendedTrustManager)tm).checkServerTrusted(1341certs.clone(),1342authType,1343socket);1344}1345} else {1346// Unlikely to happen, because we have wrapped the old1347// X509TrustManager with the new X509ExtendedTrustManager.1348throw new CertificateException(1349"Improper X509TrustManager implementation");1350}13511352// Once the server certificate chain has been validated, set1353// the certificate chain in the TLS session.1354chc.handshakeSession.setPeerCertificates(certs);1355} catch (CertificateException ce) {1356throw chc.conContext.fatal(getCertificateAlert(chc, ce), ce);1357}13581359return certs;1360}13611362/**1363* When a failure happens during certificate checking from an1364* {@link X509TrustManager}, determine what TLS alert description1365* to use.1366*1367* @param cexc The exception thrown by the {@link X509TrustManager}1368*1369* @return A byte value corresponding to a TLS alert description number.1370*/1371private static Alert getCertificateAlert(1372ClientHandshakeContext chc, CertificateException cexc) {1373// The specific reason for the failure will determine how to1374// set the alert description value1375Alert alert = Alert.CERTIFICATE_UNKNOWN;13761377Throwable baseCause = cexc.getCause();1378if (baseCause instanceof CertPathValidatorException) {1379CertPathValidatorException cpve =1380(CertPathValidatorException)baseCause;1381Reason reason = cpve.getReason();1382if (reason == BasicReason.REVOKED) {1383alert = chc.staplingActive ?1384Alert.BAD_CERT_STATUS_RESPONSE :1385Alert.CERTIFICATE_REVOKED;1386} else if (1387reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) {1388alert = chc.staplingActive ?1389Alert.BAD_CERT_STATUS_RESPONSE :1390Alert.CERTIFICATE_UNKNOWN;1391}1392}13931394return alert;1395}1396}1397}139813991400