1 /*
2  * Copyright (c) 2015, 2021, 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 it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * 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 WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 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 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.security.ssl;
27 
28 import java.io.IOException;
29 import java.nio.ByteBuffer;
30 import java.security.PrivateKey;
31 import java.security.cert.X509Certificate;
32 import java.text.MessageFormat;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.HashSet;
38 import java.util.LinkedList;
39 import java.util.List;
40 import java.util.Locale;
41 import javax.net.ssl.SSLEngine;
42 import javax.net.ssl.SSLSocket;
43 import javax.net.ssl.X509ExtendedKeyManager;
44 import javax.security.auth.x500.X500Principal;
45 import sun.security.ssl.CipherSuite.KeyExchange;
46 import sun.security.ssl.SSLHandshake.HandshakeMessage;
47 import sun.security.ssl.X509Authentication.X509Possession;
48 import sun.security.ssl.X509Authentication.X509PossessionGenerator;
49 
50 /**
51  * Pack of the CertificateRequest handshake message.
52  */
53 final class CertificateRequest {
54     static final SSLConsumer t10HandshakeConsumer =
55         new T10CertificateRequestConsumer();
56     static final HandshakeProducer t10HandshakeProducer =
57         new T10CertificateRequestProducer();
58 
59     static final SSLConsumer t12HandshakeConsumer =
60         new T12CertificateRequestConsumer();
61     static final HandshakeProducer t12HandshakeProducer =
62         new T12CertificateRequestProducer();
63 
64     static final SSLConsumer t13HandshakeConsumer =
65         new T13CertificateRequestConsumer();
66     static final HandshakeProducer t13HandshakeProducer =
67         new T13CertificateRequestProducer();
68 
69     // TLS 1.2 and prior versions
70     private static enum ClientCertificateType {
71         // RFC 2246
72         RSA_SIGN            ((byte)0x01, "rsa_sign", List.of("RSA"), true),
73         DSS_SIGN            ((byte)0x02, "dss_sign", List.of("DSA"), true),
74         RSA_FIXED_DH        ((byte)0x03, "rsa_fixed_dh"),
75         DSS_FIXED_DH        ((byte)0x04, "dss_fixed_dh"),
76 
77         // RFC 4346
78         RSA_EPHEMERAL_DH    ((byte)0x05, "rsa_ephemeral_dh"),
79         DSS_EPHEMERAL_DH    ((byte)0x06, "dss_ephemeral_dh"),
80         FORTEZZA_DMS        ((byte)0x14, "fortezza_dms"),
81 
82         // RFC 4492 and 8442
83         ECDSA_SIGN          ((byte)0x40, "ecdsa_sign",
84                                             List.of("EC", "EdDSA"),
85                                             JsseJce.isEcAvailable()),
86         RSA_FIXED_ECDH      ((byte)0x41, "rsa_fixed_ecdh"),
87         ECDSA_FIXED_ECDH    ((byte)0x42, "ecdsa_fixed_ecdh");
88 
89         private static final byte[] CERT_TYPES =
90                 JsseJce.isEcAvailable() ? new byte[] {
91                         ECDSA_SIGN.id,
92                         RSA_SIGN.id,
93                         DSS_SIGN.id
94                     } :  new byte[] {
95                         RSA_SIGN.id,
96                         DSS_SIGN.id
97                     };
98 
99         final byte id;
100         final String name;
101         final List<String> keyAlgorithm;
102         final boolean isAvailable;
103 
ClientCertificateType(byte id, String name)104         private ClientCertificateType(byte id, String name) {
105             this(id, name, null, false);
106         }
107 
ClientCertificateType(byte id, String name, List<String> keyAlgorithm, boolean isAvailable)108         private ClientCertificateType(byte id, String name,
109                 List<String> keyAlgorithm, boolean isAvailable) {
110             this.id = id;
111             this.name = name;
112             this.keyAlgorithm = keyAlgorithm;
113             this.isAvailable = isAvailable;
114         }
115 
nameOf(byte id)116         private static String nameOf(byte id) {
117             for (ClientCertificateType cct : ClientCertificateType.values()) {
118                 if (cct.id == id) {
119                     return cct.name;
120                 }
121             }
122             return "UNDEFINED-CLIENT-CERTIFICATE-TYPE(" + (int)id + ")";
123         }
124 
valueOf(byte id)125         private static ClientCertificateType valueOf(byte id) {
126             for (ClientCertificateType cct : ClientCertificateType.values()) {
127                 if (cct.id == id) {
128                     return cct;
129                 }
130             }
131 
132             return null;
133         }
134 
getKeyTypes(byte[] ids)135         private static String[] getKeyTypes(byte[] ids) {
136             ArrayList<String> keyTypes = new ArrayList<>(3);
137             for (byte id : ids) {
138                 ClientCertificateType cct = ClientCertificateType.valueOf(id);
139                 if (cct.isAvailable) {
140                     cct.keyAlgorithm.forEach(key -> {
141                         if (!keyTypes.contains(key)) {
142                             keyTypes.add(key);
143                         }
144                     });
145                 }
146             }
147 
148             return keyTypes.toArray(new String[0]);
149         }
150     }
151 
152     /**
153      * The "CertificateRequest" handshake message for SSL 3.0 and TLS 1.0/1.1.
154      */
155     static final class T10CertificateRequestMessage extends HandshakeMessage {
156         final byte[] types;                 // certificate types
157         final List<byte[]> authorities;     // certificate authorities
158 
T10CertificateRequestMessage(HandshakeContext handshakeContext, X509Certificate[] trustedCerts, KeyExchange keyExchange)159         T10CertificateRequestMessage(HandshakeContext handshakeContext,
160                 X509Certificate[] trustedCerts, KeyExchange keyExchange) {
161             super(handshakeContext);
162 
163             this.authorities = new ArrayList<>(trustedCerts.length);
164             for (X509Certificate cert : trustedCerts) {
165                 X500Principal x500Principal = cert.getSubjectX500Principal();
166                 authorities.add(x500Principal.getEncoded());
167             }
168 
169             this.types = ClientCertificateType.CERT_TYPES;
170         }
171 
T10CertificateRequestMessage(HandshakeContext handshakeContext, ByteBuffer m)172         T10CertificateRequestMessage(HandshakeContext handshakeContext,
173                 ByteBuffer m) throws IOException {
174             super(handshakeContext);
175 
176             // struct {
177             //     ClientCertificateType certificate_types<1..2^8-1>;
178             //     DistinguishedName certificate_authorities<0..2^16-1>;
179             // } CertificateRequest;
180             if (m.remaining() < 4) {
181                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
182                     "Incorrect CertificateRequest message: no sufficient data");
183             }
184             this.types = Record.getBytes8(m);
185 
186             int listLen = Record.getInt16(m);
187             if (listLen > m.remaining()) {
188                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
189                     "Incorrect CertificateRequest message:no sufficient data");
190             }
191 
192             if (listLen > 0) {
193                 this.authorities = new LinkedList<>();
194                 while (listLen > 0) {
195                     // opaque DistinguishedName<1..2^16-1>;
196                     byte[] encoded = Record.getBytes16(m);
197                     listLen -= (2 + encoded.length);
198                     authorities.add(encoded);
199                 }
200             } else {
201                 this.authorities = Collections.emptyList();
202             }
203         }
204 
getKeyTypes()205         String[] getKeyTypes() {
206             return  ClientCertificateType.getKeyTypes(types);
207         }
208 
getAuthorities()209         X500Principal[] getAuthorities() {
210             X500Principal[] principals = new X500Principal[authorities.size()];
211             int i = 0;
212             for (byte[] encoded : authorities) {
213                 principals[i++] = new X500Principal(encoded);
214             }
215 
216             return principals;
217         }
218 
219         @Override
handshakeType()220         public SSLHandshake handshakeType() {
221             return SSLHandshake.CERTIFICATE_REQUEST;
222         }
223 
224         @Override
messageLength()225         public int messageLength() {
226             int len = 1 + types.length + 2;
227             for (byte[] encoded : authorities) {
228                 len += encoded.length + 2;
229             }
230             return len;
231         }
232 
233         @Override
send(HandshakeOutStream hos)234         public void send(HandshakeOutStream hos) throws IOException {
235             hos.putBytes8(types);
236 
237             int listLen = 0;
238             for (byte[] encoded : authorities) {
239                 listLen += encoded.length + 2;
240             }
241 
242             hos.putInt16(listLen);
243             for (byte[] encoded : authorities) {
244                 hos.putBytes16(encoded);
245             }
246         }
247 
248         @Override
toString()249         public String toString() {
250             MessageFormat messageFormat = new MessageFormat(
251                     "\"CertificateRequest\": '{'\n" +
252                     "  \"certificate types\": {0}\n" +
253                     "  \"certificate authorities\": {1}\n" +
254                     "'}'",
255                     Locale.ENGLISH);
256 
257             List<String> typeNames = new ArrayList<>(types.length);
258             for (byte type : types) {
259                 typeNames.add(ClientCertificateType.nameOf(type));
260             }
261 
262             List<String> authorityNames = new ArrayList<>(authorities.size());
263             for (byte[] encoded : authorities) {
264                 X500Principal principal = new X500Principal(encoded);
265                 authorityNames.add(principal.toString());
266             }
267             Object[] messageFields = {
268                 typeNames,
269                 authorityNames
270             };
271 
272             return messageFormat.format(messageFields);
273         }
274     }
275 
276     /**
277      * The "CertificateRequest" handshake message producer for SSL 3.0 and
278      * TLS 1.0/1.1.
279      */
280     private static final
281             class T10CertificateRequestProducer implements HandshakeProducer {
282         // Prevent instantiation of this class.
T10CertificateRequestProducer()283         private T10CertificateRequestProducer() {
284             // blank
285         }
286 
287         @Override
produce(ConnectionContext context, HandshakeMessage message)288         public byte[] produce(ConnectionContext context,
289                 HandshakeMessage message) throws IOException {
290             // The producing happens in server side only.
291             ServerHandshakeContext shc = (ServerHandshakeContext)context;
292 
293             X509Certificate[] caCerts =
294                     shc.sslContext.getX509TrustManager().getAcceptedIssuers();
295             T10CertificateRequestMessage crm = new T10CertificateRequestMessage(
296                     shc, caCerts, shc.negotiatedCipherSuite.keyExchange);
297             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
298                 SSLLogger.fine(
299                     "Produced CertificateRequest handshake message", crm);
300             }
301 
302             // Output the handshake message.
303             crm.write(shc.handshakeOutput);
304             shc.handshakeOutput.flush();
305 
306             //
307             // update
308             //
309             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
310                     SSLHandshake.CERTIFICATE);
311             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
312                     SSLHandshake.CERTIFICATE_VERIFY);
313 
314             // The handshake message has been delivered.
315             return null;
316         }
317     }
318 
319     /**
320      * The "CertificateRequest" handshake message consumer for SSL 3.0 and
321      * TLS 1.0/1.1.
322      */
323     private static final
324             class T10CertificateRequestConsumer implements SSLConsumer {
325         // Prevent instantiation of this class.
T10CertificateRequestConsumer()326         private T10CertificateRequestConsumer() {
327             // blank
328         }
329 
330         @Override
consume(ConnectionContext context, ByteBuffer message)331         public void consume(ConnectionContext context,
332                 ByteBuffer message) throws IOException {
333             // The consuming happens in client side only.
334             ClientHandshakeContext chc = (ClientHandshakeContext)context;
335 
336             // clean up this consumer
337             chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
338             chc.receivedCertReq = true;
339 
340             // If we're processing this message and the server's certificate
341             // message consumer has not already run then this is a state
342             // machine violation.
343             if (chc.handshakeConsumers.containsKey(
344                     SSLHandshake.CERTIFICATE.id)) {
345                 throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
346                         "Unexpected CertificateRequest handshake message");
347             }
348 
349             SSLConsumer certStatCons = chc.handshakeConsumers.remove(
350                     SSLHandshake.CERTIFICATE_STATUS.id);
351             if (certStatCons != null) {
352                 // Stapling was active but no certificate status message
353                 // was sent.  We need to run the absence handler which will
354                 // check the certificate chain.
355                 CertificateStatus.handshakeAbsence.absent(context, null);
356             }
357 
358             T10CertificateRequestMessage crm =
359                     new T10CertificateRequestMessage(chc, message);
360             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
361                 SSLLogger.fine(
362                         "Consuming CertificateRequest handshake message", crm);
363             }
364 
365             //
366             // validate
367             //
368             // blank
369 
370             //
371             // update
372             //
373 
374             // An empty client Certificate handshake message may be allow.
375             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
376                     SSLHandshake.CERTIFICATE);
377 
378             X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
379             String clientAlias = null;
380             if (chc.conContext.transport instanceof SSLSocketImpl) {
381                 clientAlias = km.chooseClientAlias(crm.getKeyTypes(),
382                     crm.getAuthorities(), (SSLSocket)chc.conContext.transport);
383             } else if (chc.conContext.transport instanceof SSLEngineImpl) {
384                 clientAlias = km.chooseEngineClientAlias(crm.getKeyTypes(),
385                     crm.getAuthorities(), (SSLEngine)chc.conContext.transport);
386             }
387 
388 
389             if (clientAlias == null) {
390                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
391                     SSLLogger.warning("No available client authentication");
392                 }
393                 return;
394             }
395 
396             PrivateKey clientPrivateKey = km.getPrivateKey(clientAlias);
397             if (clientPrivateKey == null) {
398                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
399                     SSLLogger.warning("No available client private key");
400                 }
401                 return;
402             }
403 
404             X509Certificate[] clientCerts = km.getCertificateChain(clientAlias);
405             if ((clientCerts == null) || (clientCerts.length == 0)) {
406                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
407                     SSLLogger.warning("No available client certificate");
408                 }
409                 return;
410             }
411 
412             chc.handshakePossessions.add(
413                     new X509Possession(clientPrivateKey, clientCerts));
414             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
415                     SSLHandshake.CERTIFICATE_VERIFY);
416         }
417     }
418 
419     /**
420      * The CertificateRequest handshake message for TLS 1.2.
421      */
422     static final class T12CertificateRequestMessage extends HandshakeMessage {
423         final byte[] types;                 // certificate types
424         final int[] algorithmIds;           // supported signature algorithms
425         final List<byte[]> authorities;     // certificate authorities
426 
T12CertificateRequestMessage(HandshakeContext handshakeContext, X509Certificate[] trustedCerts, KeyExchange keyExchange, List<SignatureScheme> signatureSchemes)427         T12CertificateRequestMessage(HandshakeContext handshakeContext,
428                 X509Certificate[] trustedCerts, KeyExchange keyExchange,
429                 List<SignatureScheme> signatureSchemes) throws IOException {
430             super(handshakeContext);
431 
432             this.types = ClientCertificateType.CERT_TYPES;
433 
434             if (signatureSchemes == null || signatureSchemes.isEmpty()) {
435                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
436                         "No signature algorithms specified for " +
437                         "CertificateRequest hanshake message");
438             }
439             this.algorithmIds = new int[signatureSchemes.size()];
440             int i = 0;
441             for (SignatureScheme scheme : signatureSchemes) {
442                 algorithmIds[i++] = scheme.id;
443             }
444 
445             this.authorities = new ArrayList<>(trustedCerts.length);
446             for (X509Certificate cert : trustedCerts) {
447                 X500Principal x500Principal = cert.getSubjectX500Principal();
448                 authorities.add(x500Principal.getEncoded());
449             }
450         }
451 
T12CertificateRequestMessage(HandshakeContext handshakeContext, ByteBuffer m)452         T12CertificateRequestMessage(HandshakeContext handshakeContext,
453                 ByteBuffer m) throws IOException {
454             super(handshakeContext);
455 
456             // struct {
457             //     ClientCertificateType certificate_types<1..2^8-1>;
458             //     SignatureAndHashAlgorithm
459             //       supported_signature_algorithms<2..2^16-2>;
460             //     DistinguishedName certificate_authorities<0..2^16-1>;
461             // } CertificateRequest;
462 
463             // certificate_authorities
464             if (m.remaining() < 8) {
465                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
466                         "Invalid CertificateRequest handshake message: " +
467                         "no sufficient data");
468             }
469             this.types = Record.getBytes8(m);
470 
471             // supported_signature_algorithms
472             if (m.remaining() < 6) {
473                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
474                         "Invalid CertificateRequest handshake message: " +
475                         "no sufficient data");
476             }
477 
478             byte[] algs = Record.getBytes16(m);
479             if (algs == null || algs.length == 0 || (algs.length & 0x01) != 0) {
480                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
481                         "Invalid CertificateRequest handshake message: " +
482                         "incomplete signature algorithms");
483             }
484 
485             this.algorithmIds = new int[(algs.length >> 1)];
486             for (int i = 0, j = 0; i < algs.length;) {
487                 byte hash = algs[i++];
488                 byte sign = algs[i++];
489                 algorithmIds[j++] = ((hash & 0xFF) << 8) | (sign & 0xFF);
490             }
491 
492             // certificate_authorities
493             if (m.remaining() < 2) {
494                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
495                         "Invalid CertificateRequest handshake message: " +
496                         "no sufficient data");
497             }
498 
499             int listLen = Record.getInt16(m);
500             if (listLen > m.remaining()) {
501                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
502                     "Invalid CertificateRequest message: no sufficient data");
503             }
504 
505             if (listLen > 0) {
506                 this.authorities = new LinkedList<>();
507                 while (listLen > 0) {
508                     // opaque DistinguishedName<1..2^16-1>;
509                     byte[] encoded = Record.getBytes16(m);
510                     listLen -= (2 + encoded.length);
511                     authorities.add(encoded);
512                 }
513             } else {
514                 this.authorities = Collections.emptyList();
515             }
516         }
517 
getKeyTypes()518         String[] getKeyTypes() {
519             return ClientCertificateType.getKeyTypes(types);
520         }
521 
getAuthorities()522         X500Principal[] getAuthorities() {
523             X500Principal[] principals = new X500Principal[authorities.size()];
524             int i = 0;
525             for (byte[] encoded : authorities) {
526                 principals[i++] = new X500Principal(encoded);
527             }
528 
529             return principals;
530         }
531 
532         @Override
handshakeType()533         public SSLHandshake handshakeType() {
534             return SSLHandshake.CERTIFICATE_REQUEST;
535         }
536 
537         @Override
messageLength()538         public int messageLength() {
539             int len = 1 + types.length + 2 + (algorithmIds.length << 1) + 2;
540             for (byte[] encoded : authorities) {
541                 len += encoded.length + 2;
542             }
543             return len;
544         }
545 
546         @Override
send(HandshakeOutStream hos)547         public void send(HandshakeOutStream hos) throws IOException {
548             hos.putBytes8(types);
549 
550             int listLen = 0;
551             for (byte[] encoded : authorities) {
552                 listLen += encoded.length + 2;
553             }
554 
555             hos.putInt16(algorithmIds.length << 1);
556             for (int algorithmId : algorithmIds) {
557                 hos.putInt16(algorithmId);
558             }
559 
560             hos.putInt16(listLen);
561             for (byte[] encoded : authorities) {
562                 hos.putBytes16(encoded);
563             }
564         }
565 
566         @Override
toString()567         public String toString() {
568             MessageFormat messageFormat = new MessageFormat(
569                     "\"CertificateRequest\": '{'\n" +
570                     "  \"certificate types\": {0}\n" +
571                     "  \"supported signature algorithms\": {1}\n" +
572                     "  \"certificate authorities\": {2}\n" +
573                     "'}'",
574                     Locale.ENGLISH);
575 
576             List<String> typeNames = new ArrayList<>(types.length);
577             for (byte type : types) {
578                 typeNames.add(ClientCertificateType.nameOf(type));
579             }
580 
581             List<String> algorithmNames = new ArrayList<>(algorithmIds.length);
582             for (int algorithmId : algorithmIds) {
583                 algorithmNames.add(SignatureScheme.nameOf(algorithmId));
584             }
585 
586             List<String> authorityNames = new ArrayList<>(authorities.size());
587             for (byte[] encoded : authorities) {
588                 X500Principal principal = new X500Principal(encoded);
589                 authorityNames.add(principal.toString());
590             }
591             Object[] messageFields = {
592                 typeNames,
593                 algorithmNames,
594                 authorityNames
595             };
596 
597             return messageFormat.format(messageFields);
598         }
599     }
600 
601     /**
602      * The "CertificateRequest" handshake message producer for TLS 1.2.
603      */
604     private static final
605             class T12CertificateRequestProducer implements HandshakeProducer {
606         // Prevent instantiation of this class.
T12CertificateRequestProducer()607         private T12CertificateRequestProducer() {
608             // blank
609         }
610 
611         @Override
produce(ConnectionContext context, HandshakeMessage message)612         public byte[] produce(ConnectionContext context,
613                 HandshakeMessage message) throws IOException {
614             // The producing happens in server side only.
615             ServerHandshakeContext shc = (ServerHandshakeContext)context;
616             if (shc.localSupportedSignAlgs == null) {
617                 shc.localSupportedSignAlgs =
618                     SignatureScheme.getSupportedAlgorithms(
619                             shc.sslConfig,
620                             shc.algorithmConstraints, shc.activeProtocols);
621             }
622 
623             if (shc.localSupportedSignAlgs == null ||
624                     shc.localSupportedSignAlgs.isEmpty()) {
625                 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
626                     "No supported signature algorithm");
627             }
628 
629             X509Certificate[] caCerts =
630                     shc.sslContext.getX509TrustManager().getAcceptedIssuers();
631             T12CertificateRequestMessage crm = new T12CertificateRequestMessage(
632                     shc, caCerts, shc.negotiatedCipherSuite.keyExchange,
633                     shc.localSupportedSignAlgs);
634             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
635                 SSLLogger.fine(
636                     "Produced CertificateRequest handshake message", crm);
637             }
638 
639             // Output the handshake message.
640             crm.write(shc.handshakeOutput);
641             shc.handshakeOutput.flush();
642 
643             //
644             // update
645             //
646             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
647                     SSLHandshake.CERTIFICATE);
648             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
649                     SSLHandshake.CERTIFICATE_VERIFY);
650 
651             // The handshake message has been delivered.
652             return null;
653         }
654     }
655 
656     /**
657      * The "CertificateRequest" handshake message consumer for TLS 1.2.
658      */
659     private static final
660             class T12CertificateRequestConsumer implements SSLConsumer {
661         // Prevent instantiation of this class.
T12CertificateRequestConsumer()662         private T12CertificateRequestConsumer() {
663             // blank
664         }
665 
666         @Override
consume(ConnectionContext context, ByteBuffer message)667         public void consume(ConnectionContext context,
668                 ByteBuffer message) throws IOException {
669             // The consuming happens in client side only.
670             ClientHandshakeContext chc = (ClientHandshakeContext)context;
671 
672             // clean up this consumer
673             chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
674             chc.receivedCertReq = true;
675 
676             // If we're processing this message and the server's certificate
677             // message consumer has not already run then this is a state
678             // machine violation.
679             if (chc.handshakeConsumers.containsKey(
680                     SSLHandshake.CERTIFICATE.id)) {
681                 throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
682                         "Unexpected CertificateRequest handshake message");
683             }
684 
685             SSLConsumer certStatCons = chc.handshakeConsumers.remove(
686                     SSLHandshake.CERTIFICATE_STATUS.id);
687             if (certStatCons != null) {
688                 // Stapling was active but no certificate status message
689                 // was sent.  We need to run the absence handler which will
690                 // check the certificate chain.
691                 CertificateStatus.handshakeAbsence.absent(context, null);
692             }
693 
694             T12CertificateRequestMessage crm =
695                     new T12CertificateRequestMessage(chc, message);
696             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
697                 SSLLogger.fine(
698                         "Consuming CertificateRequest handshake message", crm);
699             }
700 
701             //
702             // validate
703             //
704             // blank
705 
706             //
707             // update
708             //
709 
710             // An empty client Certificate handshake message may be allow.
711             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
712                     SSLHandshake.CERTIFICATE);
713 
714             List<SignatureScheme> sss =
715                     SignatureScheme.getSupportedAlgorithms(
716                             chc.sslConfig,
717                             chc.algorithmConstraints, chc.negotiatedProtocol,
718                             crm.algorithmIds);
719             if (sss == null || sss.isEmpty()) {
720                 throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
721                         "No supported signature algorithm");
722             }
723 
724             chc.peerRequestedSignatureSchemes = sss;
725             chc.peerRequestedCertSignSchemes = sss;     // use the same schemes
726             chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss);
727             chc.peerSupportedAuthorities = crm.getAuthorities();
728 
729             // For TLS 1.2, we need to use a combination of the CR message's
730             // allowed key types and the signature algorithms in order to
731             // find a certificate chain that has the right key and all certs
732             // using one or more of the allowed cert signature schemes.
733             SSLPossession pos = choosePossession(chc, crm);
734             if (pos == null) {
735                 return;
736             }
737 
738             chc.handshakePossessions.add(pos);
739             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
740                     SSLHandshake.CERTIFICATE_VERIFY);
741         }
742 
choosePossession(HandshakeContext hc, T12CertificateRequestMessage crm)743         private static SSLPossession choosePossession(HandshakeContext hc,
744                 T12CertificateRequestMessage crm) throws IOException {
745             if (hc.peerRequestedCertSignSchemes == null ||
746                     hc.peerRequestedCertSignSchemes.isEmpty()) {
747                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
748                     SSLLogger.warning("No signature and hash algorithms " +
749                             "in CertificateRequest");
750                 }
751                 return null;
752             }
753 
754             // Put the CR key type into a more friendly format for searching
755             List<String> crKeyTypes = new ArrayList<>(
756                     Arrays.asList(crm.getKeyTypes()));
757             // For TLS 1.2 only if RSA is a requested key type then we
758             // should also allow RSASSA-PSS.
759             if (crKeyTypes.contains("RSA")) {
760                 crKeyTypes.add("RSASSA-PSS");
761             }
762 
763             Collection<String> checkedKeyTypes = new HashSet<>();
764             for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) {
765                 if (checkedKeyTypes.contains(ss.keyAlgorithm)) {
766                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
767                         SSLLogger.warning(
768                             "Unsupported authentication scheme: " + ss.name);
769                     }
770                     continue;
771                 }
772 
773                 // Don't select a signature scheme unless we will be able to
774                 // produce a CertificateVerify message later
775                 if (SignatureScheme.getPreferableAlgorithm(
776                         hc.algorithmConstraints,
777                         hc.peerRequestedSignatureSchemes,
778                         ss, hc.negotiatedProtocol) == null) {
779 
780                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
781                         SSLLogger.warning(
782                             "Unable to produce CertificateVerify for " +
783                             "signature scheme: " + ss.name);
784                     }
785                     checkedKeyTypes.add(ss.keyAlgorithm);
786                     continue;
787                 }
788 
789                 X509Authentication ka = X509Authentication.valueOf(ss);
790                 if (ka == null) {
791                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
792                         SSLLogger.warning(
793                             "Unsupported authentication scheme: " + ss.name);
794                     }
795                     checkedKeyTypes.add(ss.keyAlgorithm);
796                     continue;
797                 } else {
798                     // Any auth object will have a possession generator and
799                     // we need to make sure the key types for that generator
800                     // share at least one common algorithm with the CR's
801                     // allowed key types.
802                     if (ka.possessionGenerator instanceof
803                             X509PossessionGenerator xpg) {
804                         if (Collections.disjoint(crKeyTypes,
805                                 Arrays.asList(xpg.keyTypes))) {
806                             if (SSLLogger.isOn &&
807                                     SSLLogger.isOn("ssl,handshake")) {
808                                 SSLLogger.warning(
809                                         "Unsupported authentication scheme: " +
810                                                 ss.name);
811                             }
812                             checkedKeyTypes.add(ss.keyAlgorithm);
813                             continue;
814                         }
815                     }
816                 }
817 
818                 SSLPossession pos = ka.createPossession(hc);
819                 if (pos == null) {
820                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
821                         SSLLogger.warning(
822                             "Unavailable authentication scheme: " + ss.name);
823                     }
824                     continue;
825                 }
826 
827                 return pos;
828             }
829 
830             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
831                 SSLLogger.warning("No available authentication scheme");
832             }
833             return null;
834         }
835     }
836 
837     /**
838      * The CertificateRequest handshake message for TLS 1.3.
839      */
840     static final class T13CertificateRequestMessage extends HandshakeMessage {
841         private final byte[] requestContext;
842         private final SSLExtensions extensions;
843 
T13CertificateRequestMessage( HandshakeContext handshakeContext)844         T13CertificateRequestMessage(
845                 HandshakeContext handshakeContext) throws IOException {
846             super(handshakeContext);
847 
848             this.requestContext = new byte[0];
849             this.extensions = new SSLExtensions(this);
850         }
851 
T13CertificateRequestMessage(HandshakeContext handshakeContext, ByteBuffer m)852         T13CertificateRequestMessage(HandshakeContext handshakeContext,
853                 ByteBuffer m) throws IOException {
854             super(handshakeContext);
855 
856             // struct {
857             //      opaque certificate_request_context<0..2^8-1>;
858             //      Extension extensions<2..2^16-1>;
859             //  } CertificateRequest;
860             if (m.remaining() < 5) {
861                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
862                         "Invalid CertificateRequest handshake message: " +
863                         "no sufficient data");
864             }
865             this.requestContext = Record.getBytes8(m);
866 
867             if (m.remaining() < 4) {
868                 throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
869                         "Invalid CertificateRequest handshake message: " +
870                         "no sufficient extensions data");
871             }
872             SSLExtension[] enabledExtensions =
873                 handshakeContext.sslConfig.getEnabledExtensions(
874                         SSLHandshake.CERTIFICATE_REQUEST);
875             this.extensions = new SSLExtensions(this, m, enabledExtensions);
876         }
877 
878         @Override
handshakeType()879         SSLHandshake handshakeType() {
880             return SSLHandshake.CERTIFICATE_REQUEST;
881         }
882 
883         @Override
messageLength()884         int messageLength() {
885             // In TLS 1.3, use of certain extensions is mandatory.
886             return 1 + requestContext.length + extensions.length();
887         }
888 
889         @Override
send(HandshakeOutStream hos)890         void send(HandshakeOutStream hos) throws IOException {
891             hos.putBytes8(requestContext);
892 
893             // In TLS 1.3, use of certain extensions is mandatory.
894             extensions.send(hos);
895         }
896 
897         @Override
toString()898         public String toString() {
899             MessageFormat messageFormat = new MessageFormat(
900                 "\"CertificateRequest\": '{'\n" +
901                 "  \"certificate_request_context\": \"{0}\",\n" +
902                 "  \"extensions\": [\n" +
903                 "{1}\n" +
904                 "  ]\n" +
905                 "'}'",
906                 Locale.ENGLISH);
907             Object[] messageFields = {
908                 Utilities.toHexString(requestContext),
909                 Utilities.indent(Utilities.indent(extensions.toString()))
910             };
911 
912             return messageFormat.format(messageFields);
913         }
914     }
915 
916     /**
917      * The "CertificateRequest" handshake message producer for TLS 1.3.
918      */
919     private static final
920             class T13CertificateRequestProducer implements HandshakeProducer {
921         // Prevent instantiation of this class.
T13CertificateRequestProducer()922         private T13CertificateRequestProducer() {
923             // blank
924         }
925 
926         @Override
produce(ConnectionContext context, HandshakeMessage message)927         public byte[] produce(ConnectionContext context,
928                 HandshakeMessage message) throws IOException {
929             // The producing happens in server side only.
930             ServerHandshakeContext shc = (ServerHandshakeContext)context;
931 
932             T13CertificateRequestMessage crm =
933                     new T13CertificateRequestMessage(shc);
934             // Produce extensions for CertificateRequest handshake message.
935             SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
936                     SSLHandshake.CERTIFICATE_REQUEST, shc.negotiatedProtocol);
937             crm.extensions.produce(shc, extTypes);
938             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
939                 SSLLogger.fine("Produced CertificateRequest message", crm);
940             }
941 
942             // Output the handshake message.
943             crm.write(shc.handshakeOutput);
944             shc.handshakeOutput.flush();
945 
946             //
947             // update
948             //
949             shc.certRequestContext = crm.requestContext.clone();
950             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
951                     SSLHandshake.CERTIFICATE);
952             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
953                     SSLHandshake.CERTIFICATE_VERIFY);
954 
955             // The handshake message has been delivered.
956             return null;
957         }
958     }
959 
960     /**
961      * The "CertificateRequest" handshake message consumer for TLS 1.3.
962      */
963     private static final
964             class T13CertificateRequestConsumer implements SSLConsumer {
965         // Prevent instantiation of this class.
T13CertificateRequestConsumer()966         private T13CertificateRequestConsumer() {
967             // blank
968         }
969 
970         @Override
consume(ConnectionContext context, ByteBuffer message)971         public void consume(ConnectionContext context,
972                 ByteBuffer message) throws IOException {
973             // The consuming happens in client side only.
974             ClientHandshakeContext chc = (ClientHandshakeContext)context;
975 
976             // clean up this consumer
977             chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
978             chc.receivedCertReq = true;
979 
980             // Ensure that the CertificateRequest has not been sent prior
981             // to EncryptedExtensions
982             if (chc.handshakeConsumers.containsKey(
983                     SSLHandshake.ENCRYPTED_EXTENSIONS.id)) {
984                 throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
985                         "Unexpected CertificateRequest handshake message");
986             }
987 
988             T13CertificateRequestMessage crm =
989                     new T13CertificateRequestMessage(chc, message);
990             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
991                 SSLLogger.fine(
992                         "Consuming CertificateRequest handshake message", crm);
993             }
994 
995             //
996             // validate
997             //
998             SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
999                     SSLHandshake.CERTIFICATE_REQUEST);
1000             crm.extensions.consumeOnLoad(chc, extTypes);
1001 
1002             //
1003             // update
1004             //
1005             crm.extensions.consumeOnTrade(chc, extTypes);
1006 
1007             //
1008             // produce
1009             //
1010             chc.certRequestContext = crm.requestContext.clone();
1011             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
1012                     SSLHandshake.CERTIFICATE);
1013             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
1014                     SSLHandshake.CERTIFICATE_VERIFY);
1015         }
1016     }
1017 }
1018