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