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