1 /* 2 * Copyright (c) 2015, 2018, 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.ByteArrayInputStream; 29 import java.io.IOException; 30 import java.nio.ByteBuffer; 31 import java.security.PublicKey; 32 import java.security.cert.CertPathValidatorException; 33 import java.security.cert.CertPathValidatorException.BasicReason; 34 import java.security.cert.CertPathValidatorException.Reason; 35 import java.security.cert.CertificateEncodingException; 36 import java.security.cert.CertificateException; 37 import java.security.cert.CertificateFactory; 38 import java.security.cert.CertificateParsingException; 39 import java.security.cert.X509Certificate; 40 import java.text.MessageFormat; 41 import java.util.ArrayList; 42 import java.util.Arrays; 43 import java.util.Collection; 44 import java.util.Collections; 45 import java.util.HashSet; 46 import java.util.LinkedList; 47 import java.util.List; 48 import java.util.Locale; 49 import javax.net.ssl.SSLEngine; 50 import javax.net.ssl.SSLException; 51 import javax.net.ssl.SSLProtocolException; 52 import javax.net.ssl.SSLSocket; 53 import javax.net.ssl.X509ExtendedTrustManager; 54 import javax.net.ssl.X509TrustManager; 55 import javax.security.auth.x500.X500Principal; 56 import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED; 57 import sun.security.ssl.ClientHello.ClientHelloMessage; 58 import sun.security.ssl.SSLHandshake.HandshakeMessage; 59 import sun.security.ssl.X509Authentication.X509Credentials; 60 import sun.security.ssl.X509Authentication.X509Possession; 61 62 /** 63 * Pack of the CertificateMessage handshake message. 64 */ 65 final class CertificateMessage { 66 static final SSLConsumer t12HandshakeConsumer = 67 new T12CertificateConsumer(); 68 static final HandshakeProducer t12HandshakeProducer = 69 new T12CertificateProducer(); 70 71 static final SSLConsumer t13HandshakeConsumer = 72 new T13CertificateConsumer(); 73 static final HandshakeProducer t13HandshakeProducer = 74 new T13CertificateProducer(); 75 76 /** 77 * The Certificate handshake message for TLS 1.2 and previous 78 * SSL/TLS protocol versions. 79 * 80 * In server mode, the certificate handshake message is sent whenever the 81 * agreed-upon key exchange method uses certificates for authentication. 82 * In client mode, this message is only sent if the server requests a 83 * certificate for client authentication. 84 * 85 * opaque ASN.1Cert<1..2^24-1>; 86 * 87 * SSL 3.0: 88 * struct { 89 * ASN.1Cert certificate_list<1..2^24-1>; 90 * } Certificate; 91 * Note: For SSL 3.0 client authentication, if no suitable certificate 92 * is available, the client should send a no_certificate alert instead. 93 * This alert is only a warning; however, the server may respond with 94 * a fatal handshake failure alert if client authentication is required. 95 * 96 * TLS 1.0/1.1/1.2: 97 * struct { 98 * ASN.1Cert certificate_list<0..2^24-1>; 99 * } Certificate; 100 */ 101 static final class T12CertificateMessage extends HandshakeMessage { 102 final List<byte[]> encodedCertChain; 103 T12CertificateMessage(HandshakeContext handshakeContext, X509Certificate[] certChain)104 T12CertificateMessage(HandshakeContext handshakeContext, 105 X509Certificate[] certChain) throws SSLException { 106 super(handshakeContext); 107 108 List<byte[]> encodedCerts = new ArrayList<>(certChain.length); 109 for (X509Certificate cert : certChain) { 110 try { 111 encodedCerts.add(cert.getEncoded()); 112 } catch (CertificateEncodingException cee) { 113 // unlikely 114 throw handshakeContext.conContext.fatal( 115 Alert.INTERNAL_ERROR, 116 "Could not encode certificate (" + 117 cert.getSubjectX500Principal() + ")", cee); 118 } 119 } 120 121 this.encodedCertChain = encodedCerts; 122 } 123 T12CertificateMessage(HandshakeContext handshakeContext, ByteBuffer m)124 T12CertificateMessage(HandshakeContext handshakeContext, 125 ByteBuffer m) throws IOException { 126 super(handshakeContext); 127 128 int listLen = Record.getInt24(m); 129 if (listLen > m.remaining()) { 130 throw handshakeContext.conContext.fatal( 131 Alert.ILLEGAL_PARAMETER, 132 "Error parsing certificate message:no sufficient data"); 133 } 134 if (listLen > 0) { 135 List<byte[]> encodedCerts = new LinkedList<>(); 136 while (listLen > 0) { 137 byte[] encodedCert = Record.getBytes24(m); 138 listLen -= (3 + encodedCert.length); 139 encodedCerts.add(encodedCert); 140 } 141 this.encodedCertChain = encodedCerts; 142 } else { 143 this.encodedCertChain = Collections.emptyList(); 144 } 145 } 146 147 @Override handshakeType()148 public SSLHandshake handshakeType() { 149 return SSLHandshake.CERTIFICATE; 150 } 151 152 @Override messageLength()153 public int messageLength() { 154 int msgLen = 3; 155 for (byte[] encodedCert : encodedCertChain) { 156 msgLen += (encodedCert.length + 3); 157 } 158 159 return msgLen; 160 } 161 162 @Override send(HandshakeOutStream hos)163 public void send(HandshakeOutStream hos) throws IOException { 164 int listLen = 0; 165 for (byte[] encodedCert : encodedCertChain) { 166 listLen += (encodedCert.length + 3); 167 } 168 169 hos.putInt24(listLen); 170 for (byte[] encodedCert : encodedCertChain) { 171 hos.putBytes24(encodedCert); 172 } 173 } 174 175 @Override toString()176 public String toString() { 177 if (encodedCertChain.isEmpty()) { 178 return "\"Certificates\": <empty list>"; 179 } 180 181 Object[] x509Certs = new Object[encodedCertChain.size()]; 182 try { 183 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 184 int i = 0; 185 for (byte[] encodedCert : encodedCertChain) { 186 Object obj; 187 try { 188 obj = (X509Certificate)cf.generateCertificate( 189 new ByteArrayInputStream(encodedCert)); 190 } catch (CertificateException ce) { 191 obj = encodedCert; 192 } 193 x509Certs[i++] = obj; 194 } 195 } catch (CertificateException ce) { 196 // no X.509 certificate factory service 197 int i = 0; 198 for (byte[] encodedCert : encodedCertChain) { 199 x509Certs[i++] = encodedCert; 200 } 201 } 202 203 MessageFormat messageFormat = new MessageFormat( 204 "\"Certificates\": [\n" + 205 "{0}\n" + 206 "]", 207 Locale.ENGLISH); 208 Object[] messageFields = { 209 SSLLogger.toString(x509Certs) 210 }; 211 212 return messageFormat.format(messageFields); 213 } 214 } 215 216 /** 217 * The "Certificate" handshake message producer for TLS 1.2 and 218 * previous SSL/TLS protocol versions. 219 */ 220 private static final 221 class T12CertificateProducer implements HandshakeProducer { 222 // Prevent instantiation of this class. T12CertificateProducer()223 private T12CertificateProducer() { 224 // blank 225 } 226 227 @Override produce(ConnectionContext context, HandshakeMessage message)228 public byte[] produce(ConnectionContext context, 229 HandshakeMessage message) throws IOException { 230 // The producing happens in handshake context only. 231 HandshakeContext hc = (HandshakeContext)context; 232 if (hc.sslConfig.isClientMode) { 233 return onProduceCertificate( 234 (ClientHandshakeContext)context, message); 235 } else { 236 return onProduceCertificate( 237 (ServerHandshakeContext)context, message); 238 } 239 } 240 onProduceCertificate(ServerHandshakeContext shc, SSLHandshake.HandshakeMessage message)241 private byte[] onProduceCertificate(ServerHandshakeContext shc, 242 SSLHandshake.HandshakeMessage message) throws IOException { 243 X509Possession x509Possession = null; 244 for (SSLPossession possession : shc.handshakePossessions) { 245 if (possession instanceof X509Possession) { 246 x509Possession = (X509Possession)possession; 247 break; 248 } 249 } 250 251 if (x509Possession == null) { // unlikely 252 throw shc.conContext.fatal(Alert.INTERNAL_ERROR, 253 "No expected X.509 certificate for server authentication"); 254 } 255 256 shc.handshakeSession.setLocalPrivateKey( 257 x509Possession.popPrivateKey); 258 shc.handshakeSession.setLocalCertificates(x509Possession.popCerts); 259 T12CertificateMessage cm = 260 new T12CertificateMessage(shc, x509Possession.popCerts); 261 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 262 SSLLogger.fine( 263 "Produced server Certificate handshake message", cm); 264 } 265 266 // Output the handshake message. 267 cm.write(shc.handshakeOutput); 268 shc.handshakeOutput.flush(); 269 270 // The handshake message has been delivered. 271 return null; 272 } 273 onProduceCertificate(ClientHandshakeContext chc, SSLHandshake.HandshakeMessage message)274 private byte[] onProduceCertificate(ClientHandshakeContext chc, 275 SSLHandshake.HandshakeMessage message) throws IOException { 276 X509Possession x509Possession = null; 277 for (SSLPossession possession : chc.handshakePossessions) { 278 if (possession instanceof X509Possession) { 279 x509Possession = (X509Possession)possession; 280 break; 281 } 282 } 283 284 // Report to the server if no appropriate cert was found. For 285 // SSL 3.0, send a no_certificate alert; TLS 1.0/1.1/1.2 uses 286 // an empty cert chain instead. 287 if (x509Possession == null) { 288 if (chc.negotiatedProtocol.useTLS10PlusSpec()) { 289 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 290 SSLLogger.fine( 291 "No X.509 certificate for client authentication, " + 292 "use empty Certificate message instead"); 293 } 294 295 x509Possession = 296 new X509Possession(null, new X509Certificate[0]); 297 } else { 298 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 299 SSLLogger.fine( 300 "No X.509 certificate for client authentication, " + 301 "send a no_certificate alert"); 302 } 303 304 chc.conContext.warning(Alert.NO_CERTIFICATE); 305 return null; 306 } 307 } 308 309 chc.handshakeSession.setLocalPrivateKey( 310 x509Possession.popPrivateKey); 311 if (x509Possession.popCerts != null && 312 x509Possession.popCerts.length != 0) { 313 chc.handshakeSession.setLocalCertificates( 314 x509Possession.popCerts); 315 } else { 316 chc.handshakeSession.setLocalCertificates(null); 317 } 318 T12CertificateMessage cm = 319 new T12CertificateMessage(chc, x509Possession.popCerts); 320 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 321 SSLLogger.fine( 322 "Produced client Certificate handshake message", cm); 323 } 324 325 // Output the handshake message. 326 cm.write(chc.handshakeOutput); 327 chc.handshakeOutput.flush(); 328 329 // The handshake message has been delivered. 330 return null; 331 } 332 } 333 334 /** 335 * The "Certificate" handshake message consumer for TLS 1.2 and 336 * previous SSL/TLS protocol versions. 337 */ 338 static final 339 class T12CertificateConsumer implements SSLConsumer { 340 // Prevent instantiation of this class. T12CertificateConsumer()341 private T12CertificateConsumer() { 342 // blank 343 } 344 345 @Override consume(ConnectionContext context, ByteBuffer message)346 public void consume(ConnectionContext context, 347 ByteBuffer message) throws IOException { 348 // The consuming happens in handshake context only. 349 HandshakeContext hc = (HandshakeContext)context; 350 351 // clean up this consumer 352 hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id); 353 354 T12CertificateMessage cm = new T12CertificateMessage(hc, message); 355 if (hc.sslConfig.isClientMode) { 356 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 357 SSLLogger.fine( 358 "Consuming server Certificate handshake message", cm); 359 } 360 onCertificate((ClientHandshakeContext)context, cm); 361 } else { 362 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 363 SSLLogger.fine( 364 "Consuming client Certificate handshake message", cm); 365 } 366 onCertificate((ServerHandshakeContext)context, cm); 367 } 368 } 369 onCertificate(ServerHandshakeContext shc, T12CertificateMessage certificateMessage )370 private void onCertificate(ServerHandshakeContext shc, 371 T12CertificateMessage certificateMessage )throws IOException { 372 List<byte[]> encodedCerts = certificateMessage.encodedCertChain; 373 if (encodedCerts == null || encodedCerts.isEmpty()) { 374 if (shc.sslConfig.clientAuthType != 375 ClientAuthType.CLIENT_AUTH_REQUESTED) { 376 // unexpected or require client authentication 377 throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, 378 "Empty server certificate chain"); 379 } else { 380 return; 381 } 382 } 383 384 X509Certificate[] x509Certs = 385 new X509Certificate[encodedCerts.size()]; 386 try { 387 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 388 int i = 0; 389 for (byte[] encodedCert : encodedCerts) { 390 x509Certs[i++] = (X509Certificate)cf.generateCertificate( 391 new ByteArrayInputStream(encodedCert)); 392 } 393 } catch (CertificateException ce) { 394 throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, 395 "Failed to parse server certificates", ce); 396 } 397 398 checkClientCerts(shc, x509Certs); 399 400 // 401 // update 402 // 403 shc.handshakeCredentials.add( 404 new X509Credentials(x509Certs[0].getPublicKey(), x509Certs)); 405 shc.handshakeSession.setPeerCertificates(x509Certs); 406 } 407 onCertificate(ClientHandshakeContext chc, T12CertificateMessage certificateMessage)408 private void onCertificate(ClientHandshakeContext chc, 409 T12CertificateMessage certificateMessage) throws IOException { 410 List<byte[]> encodedCerts = certificateMessage.encodedCertChain; 411 if (encodedCerts == null || encodedCerts.isEmpty()) { 412 throw chc.conContext.fatal(Alert.BAD_CERTIFICATE, 413 "Empty server certificate chain"); 414 } 415 416 X509Certificate[] x509Certs = 417 new X509Certificate[encodedCerts.size()]; 418 try { 419 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 420 int i = 0; 421 for (byte[] encodedCert : encodedCerts) { 422 x509Certs[i++] = (X509Certificate)cf.generateCertificate( 423 new ByteArrayInputStream(encodedCert)); 424 } 425 } catch (CertificateException ce) { 426 throw chc.conContext.fatal(Alert.BAD_CERTIFICATE, 427 "Failed to parse server certificates", ce); 428 } 429 430 // Allow server certificate change in client side during 431 // renegotiation after a session-resumption abbreviated 432 // initial handshake? 433 // 434 // DO NOT need to check allowUnsafeServerCertChange here. We only 435 // reserve server certificates when allowUnsafeServerCertChange is 436 // false. 437 if (chc.reservedServerCerts != null && 438 !chc.handshakeSession.useExtendedMasterSecret) { 439 // It is not necessary to check the certificate update if 440 // endpoint identification is enabled. 441 String identityAlg = chc.sslConfig.identificationProtocol; 442 if ((identityAlg == null || identityAlg.isEmpty()) && 443 !isIdentityEquivalent(x509Certs[0], 444 chc.reservedServerCerts[0])) { 445 throw chc.conContext.fatal(Alert.BAD_CERTIFICATE, 446 "server certificate change is restricted " + 447 "during renegotiation"); 448 } 449 } 450 451 // ask the trust manager to verify the chain 452 if (chc.staplingActive) { 453 // Defer the certificate check until after we've received the 454 // CertificateStatus message. If that message doesn't come in 455 // immediately following this message we will execute the 456 // check from CertificateStatus' absent handler. 457 chc.deferredCerts = x509Certs; 458 } else { 459 // We're not doing stapling, so perform the check right now 460 checkServerCerts(chc, x509Certs); 461 } 462 463 // 464 // update 465 // 466 chc.handshakeCredentials.add( 467 new X509Credentials(x509Certs[0].getPublicKey(), x509Certs)); 468 chc.handshakeSession.setPeerCertificates(x509Certs); 469 } 470 471 /* 472 * Whether the certificates can represent the same identity? 473 * 474 * The certificates can be used to represent the same identity: 475 * 1. If the subject alternative names of IP address are present 476 * in both certificates, they should be identical; otherwise, 477 * 2. if the subject alternative names of DNS name are present in 478 * both certificates, they should be identical; otherwise, 479 * 3. if the subject fields are present in both certificates, the 480 * certificate subjects and issuers should be identical. 481 */ isIdentityEquivalent(X509Certificate thisCert, X509Certificate prevCert)482 private static boolean isIdentityEquivalent(X509Certificate thisCert, 483 X509Certificate prevCert) { 484 if (thisCert.equals(prevCert)) { 485 return true; 486 } 487 488 // check subject alternative names 489 Collection<List<?>> thisSubjectAltNames = null; 490 try { 491 thisSubjectAltNames = thisCert.getSubjectAlternativeNames(); 492 } catch (CertificateParsingException cpe) { 493 if (SSLLogger.isOn && SSLLogger.isOn("handshake")) { 494 SSLLogger.fine( 495 "Attempt to obtain subjectAltNames extension failed!"); 496 } 497 } 498 499 Collection<List<?>> prevSubjectAltNames = null; 500 try { 501 prevSubjectAltNames = prevCert.getSubjectAlternativeNames(); 502 } catch (CertificateParsingException cpe) { 503 if (SSLLogger.isOn && SSLLogger.isOn("handshake")) { 504 SSLLogger.fine( 505 "Attempt to obtain subjectAltNames extension failed!"); 506 } 507 } 508 509 if (thisSubjectAltNames != null && prevSubjectAltNames != null) { 510 // check the iPAddress field in subjectAltName extension 511 // 512 // 7: subject alternative name of type IP. 513 Collection<String> thisSubAltIPAddrs = 514 getSubjectAltNames(thisSubjectAltNames, 7); 515 Collection<String> prevSubAltIPAddrs = 516 getSubjectAltNames(prevSubjectAltNames, 7); 517 if (thisSubAltIPAddrs != null && prevSubAltIPAddrs != null && 518 isEquivalent(thisSubAltIPAddrs, prevSubAltIPAddrs)) { 519 return true; 520 } 521 522 // check the dNSName field in subjectAltName extension 523 // 2: subject alternative name of type IP. 524 Collection<String> thisSubAltDnsNames = 525 getSubjectAltNames(thisSubjectAltNames, 2); 526 Collection<String> prevSubAltDnsNames = 527 getSubjectAltNames(prevSubjectAltNames, 2); 528 if (thisSubAltDnsNames != null && prevSubAltDnsNames != null && 529 isEquivalent(thisSubAltDnsNames, prevSubAltDnsNames)) { 530 return true; 531 } 532 } 533 534 // check the certificate subject and issuer 535 X500Principal thisSubject = thisCert.getSubjectX500Principal(); 536 X500Principal prevSubject = prevCert.getSubjectX500Principal(); 537 X500Principal thisIssuer = thisCert.getIssuerX500Principal(); 538 X500Principal prevIssuer = prevCert.getIssuerX500Principal(); 539 540 return (!thisSubject.getName().isEmpty() && 541 !prevSubject.getName().isEmpty() && 542 thisSubject.equals(prevSubject) && 543 thisIssuer.equals(prevIssuer)); 544 } 545 546 /* 547 * Returns the subject alternative name of the specified type in the 548 * subjectAltNames extension of a certificate. 549 * 550 * Note that only those subjectAltName types that use String data 551 * should be passed into this function. 552 */ getSubjectAltNames( Collection<List<?>> subjectAltNames, int type)553 private static Collection<String> getSubjectAltNames( 554 Collection<List<?>> subjectAltNames, int type) { 555 HashSet<String> subAltDnsNames = null; 556 for (List<?> subjectAltName : subjectAltNames) { 557 int subjectAltNameType = (Integer)subjectAltName.get(0); 558 if (subjectAltNameType == type) { 559 String subAltDnsName = (String)subjectAltName.get(1); 560 if ((subAltDnsName != null) && !subAltDnsName.isEmpty()) { 561 if (subAltDnsNames == null) { 562 subAltDnsNames = 563 new HashSet<>(subjectAltNames.size()); 564 } 565 subAltDnsNames.add(subAltDnsName); 566 } 567 } 568 } 569 570 return subAltDnsNames; 571 } 572 isEquivalent(Collection<String> thisSubAltNames, Collection<String> prevSubAltNames)573 private static boolean isEquivalent(Collection<String> thisSubAltNames, 574 Collection<String> prevSubAltNames) { 575 for (String thisSubAltName : thisSubAltNames) { 576 for (String prevSubAltName : prevSubAltNames) { 577 // Only allow the exactly match. No wildcard character 578 // checking. 579 if (thisSubAltName.equalsIgnoreCase(prevSubAltName)) { 580 return true; 581 } 582 } 583 } 584 585 return false; 586 } 587 588 /** 589 * Perform client-side checking of server certificates. 590 * 591 * @param certs an array of {@code X509Certificate} objects presented 592 * by the server in the ServerCertificate message. 593 * 594 * @throws IOException if a failure occurs during validation or 595 * the trust manager associated with the {@code SSLContext} is not 596 * an {@code X509ExtendedTrustManager}. 597 */ checkServerCerts(ClientHandshakeContext chc, X509Certificate[] certs)598 static void checkServerCerts(ClientHandshakeContext chc, 599 X509Certificate[] certs) throws IOException { 600 601 X509TrustManager tm = chc.sslContext.getX509TrustManager(); 602 603 // find out the key exchange algorithm used 604 // use "RSA" for non-ephemeral "RSA_EXPORT" 605 String keyExchangeString; 606 if (chc.negotiatedCipherSuite.keyExchange == 607 CipherSuite.KeyExchange.K_RSA_EXPORT || 608 chc.negotiatedCipherSuite.keyExchange == 609 CipherSuite.KeyExchange.K_DHE_RSA_EXPORT) { 610 keyExchangeString = CipherSuite.KeyExchange.K_RSA.name; 611 } else { 612 keyExchangeString = chc.negotiatedCipherSuite.keyExchange.name; 613 } 614 615 try { 616 if (tm instanceof X509ExtendedTrustManager) { 617 if (chc.conContext.transport instanceof SSLEngine) { 618 SSLEngine engine = (SSLEngine)chc.conContext.transport; 619 ((X509ExtendedTrustManager)tm).checkServerTrusted( 620 certs.clone(), 621 keyExchangeString, 622 engine); 623 } else { 624 SSLSocket socket = (SSLSocket)chc.conContext.transport; 625 ((X509ExtendedTrustManager)tm).checkServerTrusted( 626 certs.clone(), 627 keyExchangeString, 628 socket); 629 } 630 } else { 631 // Unlikely to happen, because we have wrapped the old 632 // X509TrustManager with the new X509ExtendedTrustManager. 633 throw new CertificateException( 634 "Improper X509TrustManager implementation"); 635 } 636 637 // Once the server certificate chain has been validated, set 638 // the certificate chain in the TLS session. 639 chc.handshakeSession.setPeerCertificates(certs); 640 } catch (CertificateException ce) { 641 throw chc.conContext.fatal(getCertificateAlert(chc, ce), ce); 642 } 643 } 644 checkClientCerts(ServerHandshakeContext shc, X509Certificate[] certs)645 private static void checkClientCerts(ServerHandshakeContext shc, 646 X509Certificate[] certs) throws IOException { 647 X509TrustManager tm = shc.sslContext.getX509TrustManager(); 648 649 // find out the types of client authentication used 650 PublicKey key = certs[0].getPublicKey(); 651 String keyAlgorithm = key.getAlgorithm(); 652 String authType; 653 switch (keyAlgorithm) { 654 case "RSA": 655 case "DSA": 656 case "EC": 657 case "RSASSA-PSS": 658 authType = keyAlgorithm; 659 break; 660 default: 661 // unknown public key type 662 authType = "UNKNOWN"; 663 } 664 665 try { 666 if (tm instanceof X509ExtendedTrustManager) { 667 if (shc.conContext.transport instanceof SSLEngine) { 668 SSLEngine engine = (SSLEngine)shc.conContext.transport; 669 ((X509ExtendedTrustManager)tm).checkClientTrusted( 670 certs.clone(), 671 authType, 672 engine); 673 } else { 674 SSLSocket socket = (SSLSocket)shc.conContext.transport; 675 ((X509ExtendedTrustManager)tm).checkClientTrusted( 676 certs.clone(), 677 authType, 678 socket); 679 } 680 } else { 681 // Unlikely to happen, because we have wrapped the old 682 // X509TrustManager with the new X509ExtendedTrustManager. 683 throw new CertificateException( 684 "Improper X509TrustManager implementation"); 685 } 686 } catch (CertificateException ce) { 687 throw shc.conContext.fatal(Alert.CERTIFICATE_UNKNOWN, ce); 688 } 689 } 690 691 /** 692 * When a failure happens during certificate checking from an 693 * {@link X509TrustManager}, determine what TLS alert description 694 * to use. 695 * 696 * @param cexc The exception thrown by the {@link X509TrustManager} 697 * 698 * @return A byte value corresponding to a TLS alert description number. 699 */ getCertificateAlert( ClientHandshakeContext chc, CertificateException cexc)700 private static Alert getCertificateAlert( 701 ClientHandshakeContext chc, CertificateException cexc) { 702 // The specific reason for the failure will determine how to 703 // set the alert description value 704 Alert alert = Alert.CERTIFICATE_UNKNOWN; 705 706 Throwable baseCause = cexc.getCause(); 707 if (baseCause instanceof CertPathValidatorException) { 708 CertPathValidatorException cpve = 709 (CertPathValidatorException)baseCause; 710 Reason reason = cpve.getReason(); 711 if (reason == BasicReason.REVOKED) { 712 alert = chc.staplingActive ? 713 Alert.BAD_CERT_STATUS_RESPONSE : 714 Alert.CERTIFICATE_REVOKED; 715 } else if ( 716 reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { 717 alert = chc.staplingActive ? 718 Alert.BAD_CERT_STATUS_RESPONSE : 719 Alert.CERTIFICATE_UNKNOWN; 720 } 721 } 722 723 return alert; 724 } 725 726 } 727 728 /** 729 * The certificate entry used in Certificate handshake message for TLS 1.3. 730 */ 731 static final class CertificateEntry { 732 final byte[] encoded; // encoded cert or public key 733 private final SSLExtensions extensions; 734 CertificateEntry(byte[] encoded, SSLExtensions extensions)735 CertificateEntry(byte[] encoded, SSLExtensions extensions) { 736 this.encoded = encoded; 737 this.extensions = extensions; 738 } 739 getEncodedSize()740 private int getEncodedSize() { 741 int extLen = extensions.length(); 742 if (extLen == 0) { 743 extLen = 2; // empty extensions 744 } 745 return 3 + encoded.length + extLen; 746 } 747 748 @Override toString()749 public String toString() { 750 MessageFormat messageFormat = new MessageFormat( 751 "\n'{'\n" + 752 "{0}\n" + // X.509 certificate 753 " \"extensions\": '{'\n" + 754 "{1}\n" + 755 " '}'\n" + 756 "'}',", Locale.ENGLISH); 757 758 Object x509Certs; 759 try { 760 // Don't support certificate type extension (RawPublicKey) yet. 761 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 762 x509Certs = 763 cf.generateCertificate(new ByteArrayInputStream(encoded)); 764 } catch (CertificateException ce) { 765 // no X.509 certificate factory service 766 x509Certs = encoded; 767 } 768 769 Object[] messageFields = { 770 SSLLogger.toString(x509Certs), 771 Utilities.indent(extensions.toString(), " ") 772 }; 773 774 return messageFormat.format(messageFields); 775 } 776 } 777 778 /** 779 * The Certificate handshake message for TLS 1.3. 780 */ 781 static final class T13CertificateMessage extends HandshakeMessage { 782 private final byte[] requestContext; 783 private final List<CertificateEntry> certEntries; 784 T13CertificateMessage(HandshakeContext context, byte[] requestContext, X509Certificate[] certificates)785 T13CertificateMessage(HandshakeContext context, 786 byte[] requestContext, X509Certificate[] certificates) 787 throws SSLException, CertificateException { 788 super(context); 789 790 this.requestContext = requestContext.clone(); 791 this.certEntries = new LinkedList<>(); 792 for (X509Certificate cert : certificates) { 793 byte[] encoded = cert.getEncoded(); 794 SSLExtensions extensions = new SSLExtensions(this); 795 certEntries.add(new CertificateEntry(encoded, extensions)); 796 } 797 } 798 T13CertificateMessage(HandshakeContext handshakeContext, byte[] requestContext, List<CertificateEntry> certificates)799 T13CertificateMessage(HandshakeContext handshakeContext, 800 byte[] requestContext, List<CertificateEntry> certificates) { 801 super(handshakeContext); 802 803 this.requestContext = requestContext.clone(); 804 this.certEntries = certificates; 805 } 806 T13CertificateMessage(HandshakeContext handshakeContext, ByteBuffer m)807 T13CertificateMessage(HandshakeContext handshakeContext, 808 ByteBuffer m) throws IOException { 809 super(handshakeContext); 810 811 // struct { 812 // opaque certificate_request_context<0..2^8-1>; 813 // CertificateEntry certificate_list<0..2^24-1>; 814 // } Certificate; 815 if (m.remaining() < 4) { 816 throw new SSLProtocolException( 817 "Invalid Certificate message: " + 818 "insufficient data (length=" + m.remaining() + ")"); 819 } 820 this.requestContext = Record.getBytes8(m); 821 822 if (m.remaining() < 3) { 823 throw new SSLProtocolException( 824 "Invalid Certificate message: " + 825 "insufficient certificate entries data (length=" + 826 m.remaining() + ")"); 827 } 828 829 int listLen = Record.getInt24(m); 830 if (listLen != m.remaining()) { 831 throw new SSLProtocolException( 832 "Invalid Certificate message: " + 833 "incorrect list length (length=" + listLen + ")"); 834 } 835 836 SSLExtension[] enabledExtensions = 837 handshakeContext.sslConfig.getEnabledExtensions( 838 SSLHandshake.CERTIFICATE); 839 List<CertificateEntry> certList = new LinkedList<>(); 840 while (m.hasRemaining()) { 841 // Note: support only X509 CertificateType right now. 842 byte[] encodedCert = Record.getBytes24(m); 843 if (encodedCert.length == 0) { 844 throw new SSLProtocolException( 845 "Invalid Certificate message: empty cert_data"); 846 } 847 848 SSLExtensions extensions = 849 new SSLExtensions(this, m, enabledExtensions); 850 certList.add(new CertificateEntry(encodedCert, extensions)); 851 } 852 853 this.certEntries = Collections.unmodifiableList(certList); 854 } 855 856 @Override handshakeType()857 public SSLHandshake handshakeType() { 858 return SSLHandshake.CERTIFICATE; 859 } 860 861 @Override messageLength()862 public int messageLength() { 863 int msgLen = 4 + requestContext.length; 864 for (CertificateEntry entry : certEntries) { 865 msgLen += entry.getEncodedSize(); 866 } 867 868 return msgLen; 869 } 870 871 @Override send(HandshakeOutStream hos)872 public void send(HandshakeOutStream hos) throws IOException { 873 int entryListLen = 0; 874 for (CertificateEntry entry : certEntries) { 875 entryListLen += entry.getEncodedSize(); 876 } 877 878 hos.putBytes8(requestContext); 879 hos.putInt24(entryListLen); 880 for (CertificateEntry entry : certEntries) { 881 hos.putBytes24(entry.encoded); 882 // Is it an empty extensions? 883 if (entry.extensions.length() == 0) { 884 hos.putInt16(0); 885 } else { 886 entry.extensions.send(hos); 887 } 888 } 889 } 890 891 @Override toString()892 public String toString() { 893 MessageFormat messageFormat = new MessageFormat( 894 "\"Certificate\": '{'\n" + 895 " \"certificate_request_context\": \"{0}\",\n" + 896 " \"certificate_list\": [{1}\n]\n" + 897 "'}'", 898 Locale.ENGLISH); 899 900 StringBuilder builder = new StringBuilder(512); 901 for (CertificateEntry entry : certEntries) { 902 builder.append(entry.toString()); 903 } 904 905 Object[] messageFields = { 906 Utilities.toHexString(requestContext), 907 Utilities.indent(builder.toString()) 908 }; 909 910 return messageFormat.format(messageFields); 911 } 912 } 913 914 /** 915 * The "Certificate" handshake message producer for TLS 1.3. 916 */ 917 private static final 918 class T13CertificateProducer implements HandshakeProducer { 919 // Prevent instantiation of this class. T13CertificateProducer()920 private T13CertificateProducer() { 921 // blank 922 } 923 924 @Override produce(ConnectionContext context, HandshakeMessage message)925 public byte[] produce(ConnectionContext context, 926 HandshakeMessage message) throws IOException { 927 // The producing happens in handshake context only. 928 HandshakeContext hc = (HandshakeContext)context; 929 if (hc.sslConfig.isClientMode) { 930 return onProduceCertificate( 931 (ClientHandshakeContext)context, message); 932 } else { 933 return onProduceCertificate( 934 (ServerHandshakeContext)context, message); 935 } 936 } 937 onProduceCertificate(ServerHandshakeContext shc, HandshakeMessage message)938 private byte[] onProduceCertificate(ServerHandshakeContext shc, 939 HandshakeMessage message) throws IOException { 940 ClientHelloMessage clientHello = (ClientHelloMessage)message; 941 942 SSLPossession pos = choosePossession(shc, clientHello); 943 if (pos == null) { 944 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 945 "No available authentication scheme"); 946 } 947 948 if (!(pos instanceof X509Possession)) { 949 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 950 "No X.509 certificate for server authentication"); 951 } 952 953 X509Possession x509Possession = (X509Possession)pos; 954 X509Certificate[] localCerts = x509Possession.popCerts; 955 if (localCerts == null || localCerts.length == 0) { 956 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 957 "No X.509 certificate for server authentication"); 958 } 959 960 // update the context 961 shc.handshakePossessions.add(x509Possession); 962 shc.handshakeSession.setLocalPrivateKey( 963 x509Possession.popPrivateKey); 964 shc.handshakeSession.setLocalCertificates(localCerts); 965 T13CertificateMessage cm; 966 try { 967 cm = new T13CertificateMessage(shc, (new byte[0]), localCerts); 968 } catch (SSLException | CertificateException ce) { 969 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 970 "Failed to produce server Certificate message", ce); 971 } 972 973 // Check the OCSP stapling extensions and attempt 974 // to get responses. If the resulting stapleParams is non 975 // null, it implies that stapling is enabled on the server side. 976 shc.stapleParams = StatusResponseManager.processStapling(shc); 977 shc.staplingActive = (shc.stapleParams != null); 978 979 // Process extensions for each CertificateEntry. 980 // Since there can be multiple CertificateEntries within a 981 // single CT message, we will pin a specific CertificateEntry 982 // into the ServerHandshakeContext so individual extension 983 // producers know which X509Certificate it is processing in 984 // each call. 985 SSLExtension[] enabledCTExts = shc.sslConfig.getEnabledExtensions( 986 SSLHandshake.CERTIFICATE, 987 Arrays.asList(ProtocolVersion.PROTOCOLS_OF_13)); 988 for (CertificateEntry certEnt : cm.certEntries) { 989 shc.currentCertEntry = certEnt; 990 certEnt.extensions.produce(shc, enabledCTExts); 991 } 992 993 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 994 SSLLogger.fine("Produced server Certificate message", cm); 995 } 996 997 // Output the handshake message. 998 cm.write(shc.handshakeOutput); 999 shc.handshakeOutput.flush(); 1000 1001 // The handshake message has been delivered. 1002 return null; 1003 } 1004 choosePossession( HandshakeContext hc, ClientHelloMessage clientHello)1005 private static SSLPossession choosePossession( 1006 HandshakeContext hc, 1007 ClientHelloMessage clientHello) throws IOException { 1008 if (hc.peerRequestedCertSignSchemes == null || 1009 hc.peerRequestedCertSignSchemes.isEmpty()) { 1010 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1011 SSLLogger.warning( 1012 "No signature_algorithms(_cert) in ClientHello"); 1013 } 1014 return null; 1015 } 1016 1017 Collection<String> checkedKeyTypes = new HashSet<>(); 1018 for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) { 1019 if (checkedKeyTypes.contains(ss.keyAlgorithm)) { 1020 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1021 SSLLogger.warning( 1022 "Unsupported authentication scheme: " + ss.name); 1023 } 1024 continue; 1025 } 1026 1027 // Don't select a signature scheme unless we will be able to 1028 // produce a CertificateVerify message later 1029 if (SignatureScheme.getPreferableAlgorithm( 1030 hc.peerRequestedSignatureSchemes, 1031 ss, hc.negotiatedProtocol) == null) { 1032 1033 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1034 SSLLogger.warning( 1035 "Unable to produce CertificateVerify for " + 1036 "signature scheme: " + ss.name); 1037 } 1038 checkedKeyTypes.add(ss.keyAlgorithm); 1039 continue; 1040 } 1041 1042 SSLAuthentication ka = X509Authentication.valueOf(ss); 1043 if (ka == null) { 1044 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1045 SSLLogger.warning( 1046 "Unsupported authentication scheme: " + ss.name); 1047 } 1048 checkedKeyTypes.add(ss.keyAlgorithm); 1049 continue; 1050 } 1051 1052 SSLPossession pos = ka.createPossession(hc); 1053 if (pos == null) { 1054 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1055 SSLLogger.warning( 1056 "Unavailable authentication scheme: " + ss.name); 1057 } 1058 continue; 1059 } 1060 1061 return pos; 1062 } 1063 1064 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1065 SSLLogger.warning("No available authentication scheme"); 1066 } 1067 return null; 1068 } 1069 onProduceCertificate(ClientHandshakeContext chc, HandshakeMessage message)1070 private byte[] onProduceCertificate(ClientHandshakeContext chc, 1071 HandshakeMessage message) throws IOException { 1072 ClientHelloMessage clientHello = (ClientHelloMessage)message; 1073 SSLPossession pos = choosePossession(chc, clientHello); 1074 X509Certificate[] localCerts; 1075 if (pos == null) { 1076 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1077 SSLLogger.fine("No available client authentication scheme"); 1078 } 1079 localCerts = new X509Certificate[0]; 1080 } else { 1081 chc.handshakePossessions.add(pos); 1082 if (!(pos instanceof X509Possession)) { 1083 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1084 SSLLogger.fine( 1085 "No X.509 certificate for client authentication"); 1086 } 1087 localCerts = new X509Certificate[0]; 1088 } else { 1089 X509Possession x509Possession = (X509Possession)pos; 1090 localCerts = x509Possession.popCerts; 1091 chc.handshakeSession.setLocalPrivateKey( 1092 x509Possession.popPrivateKey); 1093 } 1094 } 1095 1096 if (localCerts != null && localCerts.length != 0) { 1097 chc.handshakeSession.setLocalCertificates(localCerts); 1098 } else { 1099 chc.handshakeSession.setLocalCertificates(null); 1100 } 1101 1102 T13CertificateMessage cm; 1103 try { 1104 cm = new T13CertificateMessage( 1105 chc, chc.certRequestContext, localCerts); 1106 } catch (SSLException | CertificateException ce) { 1107 throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 1108 "Failed to produce client Certificate message", ce); 1109 } 1110 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1111 SSLLogger.fine("Produced client Certificate message", cm); 1112 } 1113 1114 // Output the handshake message. 1115 cm.write(chc.handshakeOutput); 1116 chc.handshakeOutput.flush(); 1117 1118 // The handshake message has been delivered. 1119 return null; 1120 } 1121 } 1122 1123 /** 1124 * The "Certificate" handshake message consumer for TLS 1.3. 1125 */ 1126 private static final class T13CertificateConsumer implements SSLConsumer { 1127 // Prevent instantiation of this class. T13CertificateConsumer()1128 private T13CertificateConsumer() { 1129 // blank 1130 } 1131 1132 @Override consume(ConnectionContext context, ByteBuffer message)1133 public void consume(ConnectionContext context, 1134 ByteBuffer message) throws IOException { 1135 // The consuming happens in handshake context only. 1136 HandshakeContext hc = (HandshakeContext)context; 1137 1138 // clean up this consumer 1139 hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id); 1140 T13CertificateMessage cm = new T13CertificateMessage(hc, message); 1141 if (hc.sslConfig.isClientMode) { 1142 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1143 SSLLogger.fine( 1144 "Consuming server Certificate handshake message", cm); 1145 } 1146 onConsumeCertificate((ClientHandshakeContext)context, cm); 1147 } else { 1148 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 1149 SSLLogger.fine( 1150 "Consuming client Certificate handshake message", cm); 1151 } 1152 onConsumeCertificate((ServerHandshakeContext)context, cm); 1153 } 1154 } 1155 onConsumeCertificate(ServerHandshakeContext shc, T13CertificateMessage certificateMessage )1156 private void onConsumeCertificate(ServerHandshakeContext shc, 1157 T13CertificateMessage certificateMessage )throws IOException { 1158 if (certificateMessage.certEntries == null || 1159 certificateMessage.certEntries.isEmpty()) { 1160 if (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED) { 1161 throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, 1162 "Empty client certificate chain"); 1163 } else { 1164 // optional client authentication 1165 return; 1166 } 1167 } 1168 1169 // check client certificate entries 1170 X509Certificate[] cliCerts = 1171 checkClientCerts(shc, certificateMessage.certEntries); 1172 1173 // 1174 // update 1175 // 1176 shc.handshakeCredentials.add( 1177 new X509Credentials(cliCerts[0].getPublicKey(), cliCerts)); 1178 shc.handshakeSession.setPeerCertificates(cliCerts); 1179 } 1180 onConsumeCertificate(ClientHandshakeContext chc, T13CertificateMessage certificateMessage )1181 private void onConsumeCertificate(ClientHandshakeContext chc, 1182 T13CertificateMessage certificateMessage )throws IOException { 1183 if (certificateMessage.certEntries == null || 1184 certificateMessage.certEntries.isEmpty()) { 1185 throw chc.conContext.fatal(Alert.BAD_CERTIFICATE, 1186 "Empty server certificate chain"); 1187 } 1188 1189 // Each CertificateEntry will have its own set of extensions 1190 // which must be consumed. 1191 SSLExtension[] enabledExtensions = 1192 chc.sslConfig.getEnabledExtensions(SSLHandshake.CERTIFICATE); 1193 for (CertificateEntry certEnt : certificateMessage.certEntries) { 1194 certEnt.extensions.consumeOnLoad(chc, enabledExtensions); 1195 } 1196 1197 // check server certificate entries 1198 X509Certificate[] srvCerts = 1199 checkServerCerts(chc, certificateMessage.certEntries); 1200 1201 // 1202 // update 1203 // 1204 chc.handshakeCredentials.add( 1205 new X509Credentials(srvCerts[0].getPublicKey(), srvCerts)); 1206 chc.handshakeSession.setPeerCertificates(srvCerts); 1207 } 1208 checkClientCerts( ServerHandshakeContext shc, List<CertificateEntry> certEntries)1209 private static X509Certificate[] checkClientCerts( 1210 ServerHandshakeContext shc, 1211 List<CertificateEntry> certEntries) throws IOException { 1212 X509Certificate[] certs = 1213 new X509Certificate[certEntries.size()]; 1214 try { 1215 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 1216 int i = 0; 1217 for (CertificateEntry entry : certEntries) { 1218 certs[i++] = (X509Certificate)cf.generateCertificate( 1219 new ByteArrayInputStream(entry.encoded)); 1220 } 1221 } catch (CertificateException ce) { 1222 throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, 1223 "Failed to parse server certificates", ce); 1224 } 1225 1226 // find out the types of client authentication used 1227 String keyAlgorithm = certs[0].getPublicKey().getAlgorithm(); 1228 String authType; 1229 switch (keyAlgorithm) { 1230 case "RSA": 1231 case "DSA": 1232 case "EC": 1233 case "RSASSA-PSS": 1234 authType = keyAlgorithm; 1235 break; 1236 default: 1237 // unknown public key type 1238 authType = "UNKNOWN"; 1239 } 1240 1241 try { 1242 X509TrustManager tm = shc.sslContext.getX509TrustManager(); 1243 if (tm instanceof X509ExtendedTrustManager) { 1244 if (shc.conContext.transport instanceof SSLEngine) { 1245 SSLEngine engine = (SSLEngine)shc.conContext.transport; 1246 ((X509ExtendedTrustManager)tm).checkClientTrusted( 1247 certs.clone(), 1248 authType, 1249 engine); 1250 } else { 1251 SSLSocket socket = (SSLSocket)shc.conContext.transport; 1252 ((X509ExtendedTrustManager)tm).checkClientTrusted( 1253 certs.clone(), 1254 authType, 1255 socket); 1256 } 1257 } else { 1258 // Unlikely to happen, because we have wrapped the old 1259 // X509TrustManager with the new X509ExtendedTrustManager. 1260 throw new CertificateException( 1261 "Improper X509TrustManager implementation"); 1262 } 1263 1264 // Once the client certificate chain has been validated, set 1265 // the certificate chain in the TLS session. 1266 shc.handshakeSession.setPeerCertificates(certs); 1267 } catch (CertificateException ce) { 1268 throw shc.conContext.fatal(Alert.CERTIFICATE_UNKNOWN, ce); 1269 } 1270 1271 return certs; 1272 } 1273 checkServerCerts( ClientHandshakeContext chc, List<CertificateEntry> certEntries)1274 private static X509Certificate[] checkServerCerts( 1275 ClientHandshakeContext chc, 1276 List<CertificateEntry> certEntries) throws IOException { 1277 X509Certificate[] certs = 1278 new X509Certificate[certEntries.size()]; 1279 try { 1280 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 1281 int i = 0; 1282 for (CertificateEntry entry : certEntries) { 1283 certs[i++] = (X509Certificate)cf.generateCertificate( 1284 new ByteArrayInputStream(entry.encoded)); 1285 } 1286 } catch (CertificateException ce) { 1287 throw chc.conContext.fatal(Alert.BAD_CERTIFICATE, 1288 "Failed to parse server certificates", ce); 1289 } 1290 1291 // find out the types of server authentication used 1292 // 1293 // Note that the "UNKNOWN" authentication type is sufficient to 1294 // check the required digitalSignature KeyUsage for TLS 1.3. 1295 String authType = "UNKNOWN"; 1296 1297 try { 1298 X509TrustManager tm = chc.sslContext.getX509TrustManager(); 1299 if (tm instanceof X509ExtendedTrustManager) { 1300 if (chc.conContext.transport instanceof SSLEngine) { 1301 SSLEngine engine = (SSLEngine)chc.conContext.transport; 1302 ((X509ExtendedTrustManager)tm).checkServerTrusted( 1303 certs.clone(), 1304 authType, 1305 engine); 1306 } else { 1307 SSLSocket socket = (SSLSocket)chc.conContext.transport; 1308 ((X509ExtendedTrustManager)tm).checkServerTrusted( 1309 certs.clone(), 1310 authType, 1311 socket); 1312 } 1313 } else { 1314 // Unlikely to happen, because we have wrapped the old 1315 // X509TrustManager with the new X509ExtendedTrustManager. 1316 throw new CertificateException( 1317 "Improper X509TrustManager implementation"); 1318 } 1319 1320 // Once the server certificate chain has been validated, set 1321 // the certificate chain in the TLS session. 1322 chc.handshakeSession.setPeerCertificates(certs); 1323 } catch (CertificateException ce) { 1324 throw chc.conContext.fatal(getCertificateAlert(chc, ce), ce); 1325 } 1326 1327 return certs; 1328 } 1329 1330 /** 1331 * When a failure happens during certificate checking from an 1332 * {@link X509TrustManager}, determine what TLS alert description 1333 * to use. 1334 * 1335 * @param cexc The exception thrown by the {@link X509TrustManager} 1336 * 1337 * @return A byte value corresponding to a TLS alert description number. 1338 */ getCertificateAlert( ClientHandshakeContext chc, CertificateException cexc)1339 private static Alert getCertificateAlert( 1340 ClientHandshakeContext chc, CertificateException cexc) { 1341 // The specific reason for the failure will determine how to 1342 // set the alert description value 1343 Alert alert = Alert.CERTIFICATE_UNKNOWN; 1344 1345 Throwable baseCause = cexc.getCause(); 1346 if (baseCause instanceof CertPathValidatorException) { 1347 CertPathValidatorException cpve = 1348 (CertPathValidatorException)baseCause; 1349 Reason reason = cpve.getReason(); 1350 if (reason == BasicReason.REVOKED) { 1351 alert = chc.staplingActive ? 1352 Alert.BAD_CERT_STATUS_RESPONSE : 1353 Alert.CERTIFICATE_REVOKED; 1354 } else if ( 1355 reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) { 1356 alert = chc.staplingActive ? 1357 Alert.BAD_CERT_STATUS_RESPONSE : 1358 Alert.CERTIFICATE_UNKNOWN; 1359 } 1360 } 1361 1362 return alert; 1363 } 1364 } 1365 } 1366