jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
changeset 2 90ce3da70b43
child 2942 37d9baeb7518
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1996-2007 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 
       
    27 package sun.security.ssl;
       
    28 
       
    29 import java.io.*;
       
    30 import java.util.*;
       
    31 import java.security.*;
       
    32 import java.security.cert.*;
       
    33 import java.security.interfaces.*;
       
    34 import java.security.spec.ECParameterSpec;
       
    35 
       
    36 import javax.crypto.SecretKey;
       
    37 import javax.crypto.spec.SecretKeySpec;
       
    38 
       
    39 import javax.net.ssl.*;
       
    40 
       
    41 import javax.security.auth.Subject;
       
    42 import javax.security.auth.kerberos.KerberosKey;
       
    43 import javax.security.auth.kerberos.KerberosPrincipal;
       
    44 import javax.security.auth.kerberos.ServicePermission;
       
    45 import sun.security.jgss.krb5.Krb5Util;
       
    46 import sun.security.jgss.GSSUtil;
       
    47 
       
    48 import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
       
    49 
       
    50 import sun.security.ssl.HandshakeMessage.*;
       
    51 import sun.security.ssl.CipherSuite.*;
       
    52 import static sun.security.ssl.CipherSuite.*;
       
    53 import static sun.security.ssl.CipherSuite.KeyExchange.*;
       
    54 
       
    55 /**
       
    56  * ServerHandshaker does the protocol handshaking from the point
       
    57  * of view of a server.  It is driven asychronously by handshake messages
       
    58  * as delivered by the parent Handshaker class, and also uses
       
    59  * common functionality (e.g. key generation) that is provided there.
       
    60  *
       
    61  * @author David Brownell
       
    62  */
       
    63 final class ServerHandshaker extends Handshaker {
       
    64 
       
    65     // is the server going to require the client to authenticate?
       
    66     private byte                doClientAuth;
       
    67 
       
    68     // our authentication info
       
    69     private X509Certificate[]   certs;
       
    70     private PrivateKey          privateKey;
       
    71 
       
    72     private KerberosKey[]       kerberosKeys;
       
    73 
       
    74     // flag to check for clientCertificateVerify message
       
    75     private boolean             needClientVerify = false;
       
    76 
       
    77     /*
       
    78      * For exportable ciphersuites using non-exportable key sizes, we use
       
    79      * ephemeral RSA keys. We could also do anonymous RSA in the same way
       
    80      * but there are no such ciphersuites currently defined.
       
    81      */
       
    82     private PrivateKey          tempPrivateKey;
       
    83     private PublicKey           tempPublicKey;
       
    84 
       
    85     /*
       
    86      * For anonymous and ephemeral Diffie-Hellman key exchange, we use
       
    87      * ephemeral Diffie-Hellman keys.
       
    88      */
       
    89     private DHCrypt dh;
       
    90 
       
    91     // Helper for ECDH based key exchanges
       
    92     private ECDHCrypt ecdh;
       
    93 
       
    94     // version request by the client in its ClientHello
       
    95     // we remember it for the RSA premaster secret version check
       
    96     private ProtocolVersion clientRequestedVersion;
       
    97 
       
    98     private SupportedEllipticCurvesExtension supportedCurves;
       
    99 
       
   100     /*
       
   101      * Constructor ... use the keys found in the auth context.
       
   102      */
       
   103     ServerHandshaker(SSLSocketImpl socket, SSLContextImpl context,
       
   104             ProtocolList enabledProtocols, byte clientAuth) {
       
   105         super(socket, context, enabledProtocols,
       
   106                         (clientAuth != SSLEngineImpl.clauth_none), false);
       
   107         doClientAuth = clientAuth;
       
   108     }
       
   109 
       
   110     /*
       
   111      * Constructor ... use the keys found in the auth context.
       
   112      */
       
   113     ServerHandshaker(SSLEngineImpl engine, SSLContextImpl context,
       
   114             ProtocolList enabledProtocols, byte clientAuth) {
       
   115         super(engine, context, enabledProtocols,
       
   116                         (clientAuth != SSLEngineImpl.clauth_none), false);
       
   117         doClientAuth = clientAuth;
       
   118     }
       
   119 
       
   120     /*
       
   121      * As long as handshaking has not started, we can change
       
   122      * whether client authentication is required.  Otherwise,
       
   123      * we will need to wait for the next handshake.
       
   124      */
       
   125     void setClientAuth(byte clientAuth) {
       
   126         doClientAuth = clientAuth;
       
   127     }
       
   128 
       
   129     /*
       
   130      * This routine handles all the server side handshake messages, one at
       
   131      * a time.  Given the message type (and in some cases the pending cipher
       
   132      * spec) it parses the type-specific message.  Then it calls a function
       
   133      * that handles that specific message.
       
   134      *
       
   135      * It updates the state machine as each message is processed, and writes
       
   136      * responses as needed using the connection in the constructor.
       
   137      */
       
   138     void processMessage(byte type, int message_len)
       
   139             throws IOException {
       
   140         //
       
   141         // In SSLv3 and TLS, messages follow strictly increasing
       
   142         // numerical order _except_ for one annoying special case.
       
   143         //
       
   144         if ((state > type)
       
   145                 && (state != HandshakeMessage.ht_client_key_exchange
       
   146                     && type != HandshakeMessage.ht_certificate_verify)) {
       
   147             throw new SSLProtocolException(
       
   148                     "Handshake message sequence violation, state = " + state
       
   149                     + ", type = " + type);
       
   150         }
       
   151 
       
   152         switch (type) {
       
   153             case HandshakeMessage.ht_client_hello:
       
   154                 ClientHello ch = new ClientHello(input, message_len);
       
   155                 /*
       
   156                  * send it off for processing.
       
   157                  */
       
   158                 this.clientHello(ch);
       
   159                 break;
       
   160 
       
   161             case HandshakeMessage.ht_certificate:
       
   162                 if (doClientAuth == SSLEngineImpl.clauth_none) {
       
   163                     fatalSE(Alerts.alert_unexpected_message,
       
   164                                 "client sent unsolicited cert chain");
       
   165                     // NOTREACHED
       
   166                 }
       
   167                 this.clientCertificate(new CertificateMsg(input));
       
   168                 break;
       
   169 
       
   170             case HandshakeMessage.ht_client_key_exchange:
       
   171                 SecretKey preMasterSecret;
       
   172                 switch (keyExchange) {
       
   173                 case K_RSA:
       
   174                 case K_RSA_EXPORT:
       
   175                     /*
       
   176                      * The client's pre-master secret is decrypted using
       
   177                      * either the server's normal private RSA key, or the
       
   178                      * temporary one used for non-export or signing-only
       
   179                      * certificates/keys.
       
   180                      */
       
   181                     RSAClientKeyExchange pms = new RSAClientKeyExchange
       
   182                         (protocolVersion, input, message_len, privateKey);
       
   183                     preMasterSecret = this.clientKeyExchange(pms);
       
   184                     break;
       
   185                 case K_KRB5:
       
   186                 case K_KRB5_EXPORT:
       
   187                     preMasterSecret = this.clientKeyExchange(
       
   188                         new KerberosClientKeyExchange(protocolVersion,
       
   189                             clientRequestedVersion,
       
   190                             sslContext.getSecureRandom(),
       
   191                             input,
       
   192                             kerberosKeys));
       
   193                     break;
       
   194                 case K_DHE_RSA:
       
   195                 case K_DHE_DSS:
       
   196                 case K_DH_ANON:
       
   197                     /*
       
   198                      * The pre-master secret is derived using the normal
       
   199                      * Diffie-Hellman calculation.   Note that the main
       
   200                      * protocol difference in these five flavors is in how
       
   201                      * the ServerKeyExchange message was constructed!
       
   202                      */
       
   203                     preMasterSecret = this.clientKeyExchange(
       
   204                             new DHClientKeyExchange(input));
       
   205                     break;
       
   206                 case K_ECDH_RSA:
       
   207                 case K_ECDH_ECDSA:
       
   208                 case K_ECDHE_RSA:
       
   209                 case K_ECDHE_ECDSA:
       
   210                 case K_ECDH_ANON:
       
   211                     preMasterSecret = this.clientKeyExchange
       
   212                                             (new ECDHClientKeyExchange(input));
       
   213                     break;
       
   214                 default:
       
   215                     throw new SSLProtocolException
       
   216                         ("Unrecognized key exchange: " + keyExchange);
       
   217                 }
       
   218 
       
   219                 //
       
   220                 // All keys are calculated from the premaster secret
       
   221                 // and the exchanged nonces in the same way.
       
   222                 //
       
   223                 calculateKeys(preMasterSecret, clientRequestedVersion);
       
   224                 break;
       
   225 
       
   226             case HandshakeMessage.ht_certificate_verify:
       
   227                 this.clientCertificateVerify(new CertificateVerify(input));
       
   228                 break;
       
   229 
       
   230             case HandshakeMessage.ht_finished:
       
   231                 this.clientFinished(new Finished(protocolVersion, input));
       
   232                 break;
       
   233 
       
   234             default:
       
   235                 throw new SSLProtocolException(
       
   236                         "Illegal server handshake msg, " + type);
       
   237         }
       
   238 
       
   239         //
       
   240         // Move the state machine forward except for that annoying
       
   241         // special case.  This means that clients could send extra
       
   242         // cert verify messages; not a problem so long as all of
       
   243         // them actually check out.
       
   244         //
       
   245         if (state < type && type != HandshakeMessage.ht_certificate_verify) {
       
   246             state = type;
       
   247         }
       
   248     }
       
   249 
       
   250 
       
   251     /*
       
   252      * ClientHello presents the server with a bunch of options, to which the
       
   253      * server replies with a ServerHello listing the ones which this session
       
   254      * will use.  If needed, it also writes its Certificate plus in some cases
       
   255      * a ServerKeyExchange message.  It may also write a CertificateRequest,
       
   256      * to elicit a client certificate.
       
   257      *
       
   258      * All these messages are terminated by a ServerHelloDone message.  In
       
   259      * most cases, all this can be sent in a single Record.
       
   260      */
       
   261     private void clientHello(ClientHello mesg) throws IOException {
       
   262         if (debug != null && Debug.isOn("handshake")) {
       
   263             mesg.print(System.out);
       
   264         }
       
   265         /*
       
   266          * Always make sure this entire record has been digested before we
       
   267          * start emitting output, to ensure correct digesting order.
       
   268          */
       
   269         input.digestNow();
       
   270 
       
   271         /*
       
   272          * FIRST, construct the ServerHello using the options and priorities
       
   273          * from the ClientHello.  Update the (pending) cipher spec as we do
       
   274          * so, and save the client's version to protect against rollback
       
   275          * attacks.
       
   276          *
       
   277          * There are a bunch of minor tasks here, and one major one: deciding
       
   278          * if the short or the full handshake sequence will be used.
       
   279          */
       
   280         ServerHello m1 = new ServerHello();
       
   281 
       
   282         clientRequestedVersion = mesg.protocolVersion;
       
   283 
       
   284         // check if clientVersion is recent enough for us
       
   285         if (clientRequestedVersion.v < enabledProtocols.min.v) {
       
   286             fatalSE(Alerts.alert_handshake_failure,
       
   287                 "Client requested protocol " + clientRequestedVersion +
       
   288                  " not enabled or not supported");
       
   289         }
       
   290 
       
   291         // now we know we have an acceptable version
       
   292         // use the lower of our max and the client requested version
       
   293         ProtocolVersion selectedVersion;
       
   294         if (clientRequestedVersion.v <= enabledProtocols.max.v) {
       
   295             selectedVersion = clientRequestedVersion;
       
   296         } else {
       
   297             selectedVersion = enabledProtocols.max;
       
   298         }
       
   299         setVersion(selectedVersion);
       
   300 
       
   301         m1.protocolVersion = protocolVersion;
       
   302 
       
   303         //
       
   304         // random ... save client and server values for later use
       
   305         // in computing the master secret (from pre-master secret)
       
   306         // and thence the other crypto keys.
       
   307         //
       
   308         // NOTE:  this use of three inputs to generating _each_ set
       
   309         // of ciphers slows things down, but it does increase the
       
   310         // security since each connection in the session can hold
       
   311         // its own authenticated (and strong) keys.  One could make
       
   312         // creation of a session a rare thing...
       
   313         //
       
   314         clnt_random = mesg.clnt_random;
       
   315         svr_random = new RandomCookie(sslContext.getSecureRandom());
       
   316         m1.svr_random = svr_random;
       
   317 
       
   318         session = null; // forget about the current session
       
   319         //
       
   320         // Here we go down either of two paths:  (a) the fast one, where
       
   321         // the client's asked to rejoin an existing session, and the server
       
   322         // permits this; (b) the other one, where a new session is created.
       
   323         //
       
   324         if (mesg.sessionId.length() != 0) {
       
   325             // client is trying to resume a session, let's see...
       
   326 
       
   327             SSLSessionImpl previous = ((SSLSessionContextImpl)sslContext
       
   328                         .engineGetServerSessionContext())
       
   329                         .get(mesg.sessionId.getId());
       
   330             //
       
   331             // Check if we can use the fast path, resuming a session.  We
       
   332             // can do so iff we have a valid record for that session, and
       
   333             // the cipher suite for that session was on the list which the
       
   334             // client requested, and if we're not forgetting any needed
       
   335             // authentication on the part of the client.
       
   336             //
       
   337             if (previous != null) {
       
   338                 resumingSession = previous.isRejoinable();
       
   339 
       
   340                 if (resumingSession) {
       
   341                     ProtocolVersion oldVersion = previous.getProtocolVersion();
       
   342                     // cannot resume session with different version
       
   343                     if (oldVersion != protocolVersion) {
       
   344                         resumingSession = false;
       
   345                     }
       
   346                 }
       
   347 
       
   348                 if (resumingSession &&
       
   349                         (doClientAuth == SSLEngineImpl.clauth_required)) {
       
   350                     try {
       
   351                         previous.getPeerPrincipal();
       
   352                     } catch (SSLPeerUnverifiedException e) {
       
   353                         resumingSession = false;
       
   354                     }
       
   355                 }
       
   356 
       
   357                 // validate subject identity
       
   358                 if (resumingSession) {
       
   359                     CipherSuite suite = previous.getSuite();
       
   360                     if (suite.keyExchange == K_KRB5 ||
       
   361                         suite.keyExchange == K_KRB5_EXPORT) {
       
   362                         Principal localPrincipal = previous.getLocalPrincipal();
       
   363 
       
   364                         Subject subject = null;
       
   365                         try {
       
   366                             subject = AccessController.doPrivileged(
       
   367                                 new PrivilegedExceptionAction<Subject>() {
       
   368                                 public Subject run() throws Exception {
       
   369                                     return Krb5Util.getSubject(
       
   370                                         GSSUtil.CALLER_SSL_SERVER,
       
   371                                         getAccSE());
       
   372                             }});
       
   373                         } catch (PrivilegedActionException e) {
       
   374                             subject = null;
       
   375                             if (debug != null && Debug.isOn("session")) {
       
   376                                 System.out.println("Attempt to obtain" +
       
   377                                                 " subject failed!");
       
   378                             }
       
   379                         }
       
   380 
       
   381                         if (subject != null) {
       
   382                             Set<KerberosPrincipal> principals =
       
   383                                 subject.getPrincipals(KerberosPrincipal.class);
       
   384                             if (!principals.contains(localPrincipal)) {
       
   385                                 resumingSession = false;
       
   386                                 if (debug != null && Debug.isOn("session")) {
       
   387                                     System.out.println("Subject identity" +
       
   388                                                         " is not the same");
       
   389                                 }
       
   390                             } else {
       
   391                                 if (debug != null && Debug.isOn("session"))
       
   392                                     System.out.println("Subject identity" +
       
   393                                                         " is same");
       
   394                             }
       
   395                         } else {
       
   396                             resumingSession = false;
       
   397                             if (debug != null && Debug.isOn("session"))
       
   398                                 System.out.println("Kerberos credentials are" +
       
   399                                     " not present in the current Subject;" +
       
   400                                     " check if " +
       
   401                                     " javax.security.auth.useSubjectAsCreds" +
       
   402                                     " system property has been set to false");
       
   403                         }
       
   404                     }
       
   405                 }
       
   406 
       
   407                 if (resumingSession) {
       
   408                     CipherSuite suite = previous.getSuite();
       
   409                     // verify that the ciphersuite from the cached session
       
   410                     // is in the list of client requested ciphersuites and
       
   411                     // we have it enabled
       
   412                     if ((isEnabled(suite) == false) ||
       
   413                             (mesg.getCipherSuites().contains(suite) == false)) {
       
   414                         resumingSession = false;
       
   415                     } else {
       
   416                         // everything looks ok, set the ciphersuite
       
   417                         // this should be done last when we are sure we
       
   418                         // will resume
       
   419                         setCipherSuite(suite);
       
   420                     }
       
   421                 }
       
   422 
       
   423                 if (resumingSession) {
       
   424                     session = previous;
       
   425                     if (debug != null &&
       
   426                         (Debug.isOn("handshake") || Debug.isOn("session"))) {
       
   427                         System.out.println("%% Resuming " + session);
       
   428                     }
       
   429                 }
       
   430             }
       
   431         } // else client did not try to resume
       
   432 
       
   433         //
       
   434         // If client hasn't specified a session we can resume, start a
       
   435         // new one and choose its cipher suite and compression options.
       
   436         // Unless new session creation is disabled for this connection!
       
   437         //
       
   438         if (session == null) {
       
   439             if (!enableNewSession) {
       
   440                 throw new SSLException("Client did not resume a session");
       
   441             }
       
   442             supportedCurves = (SupportedEllipticCurvesExtension)mesg.extensions.get
       
   443                                         (ExtensionType.EXT_ELLIPTIC_CURVES);
       
   444             chooseCipherSuite(mesg);
       
   445             session = new SSLSessionImpl(protocolVersion, cipherSuite,
       
   446                 sslContext.getSecureRandom(),
       
   447                 getHostAddressSE(), getPortSE());
       
   448             session.setLocalPrivateKey(privateKey);
       
   449             // chooseCompression(mesg);
       
   450         }
       
   451 
       
   452         m1.cipherSuite = cipherSuite;
       
   453         m1.sessionId = session.getSessionId();
       
   454         m1.compression_method = session.getCompression();
       
   455 
       
   456         if (debug != null && Debug.isOn("handshake")) {
       
   457             m1.print(System.out);
       
   458             System.out.println("Cipher suite:  " + session.getSuite());
       
   459         }
       
   460         m1.write(output);
       
   461 
       
   462         //
       
   463         // If we are resuming a session, we finish writing handshake
       
   464         // messages right now and then finish.
       
   465         //
       
   466         if (resumingSession) {
       
   467             calculateConnectionKeys(session.getMasterSecret());
       
   468             sendChangeCipherAndFinish(false);
       
   469             return;
       
   470         }
       
   471 
       
   472 
       
   473         /*
       
   474          * SECOND, write the server Certificate(s) if we need to.
       
   475          *
       
   476          * NOTE:  while an "anonymous RSA" mode is explicitly allowed by
       
   477          * the protocol, we can't support it since all of the SSL flavors
       
   478          * defined in the protocol spec are explicitly stated to require
       
   479          * using RSA certificates.
       
   480          */
       
   481         if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
       
   482             // Server certificates are omitted for Kerberos ciphers
       
   483 
       
   484         } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {
       
   485             if (certs == null) {
       
   486                 throw new RuntimeException("no certificates");
       
   487             }
       
   488 
       
   489             CertificateMsg m2 = new CertificateMsg(certs);
       
   490 
       
   491             /*
       
   492              * Set local certs in the SSLSession, output
       
   493              * debug info, and then actually write to the client.
       
   494              */
       
   495             session.setLocalCertificates(certs);
       
   496             if (debug != null && Debug.isOn("handshake")) {
       
   497                 m2.print(System.out);
       
   498             }
       
   499             m2.write(output);
       
   500 
       
   501             // XXX has some side effects with OS TCP buffering,
       
   502             // leave it out for now
       
   503 
       
   504             // let client verify chain in the meantime...
       
   505             // output.flush();
       
   506         } else {
       
   507             if (certs != null) {
       
   508                 throw new RuntimeException("anonymous keyexchange with certs");
       
   509             }
       
   510         }
       
   511 
       
   512         /*
       
   513          * THIRD, the ServerKeyExchange message ... iff it's needed.
       
   514          *
       
   515          * It's usually needed unless there's an encryption-capable
       
   516          * RSA cert, or a D-H cert.  The notable exception is that
       
   517          * exportable ciphers used with big RSA keys need to downgrade
       
   518          * to use short RSA keys, even when the key/cert encrypts OK.
       
   519          */
       
   520 
       
   521         ServerKeyExchange m3;
       
   522         switch (keyExchange) {
       
   523         case K_RSA:
       
   524         case K_KRB5:
       
   525         case K_KRB5_EXPORT:
       
   526             // no server key exchange for RSA or KRB5 ciphersuites
       
   527             m3 = null;
       
   528             break;
       
   529         case K_RSA_EXPORT:
       
   530             if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
       
   531                 try {
       
   532                     m3 = new RSA_ServerKeyExchange(
       
   533                         tempPublicKey, privateKey,
       
   534                         clnt_random, svr_random,
       
   535                         sslContext.getSecureRandom());
       
   536                     privateKey = tempPrivateKey;
       
   537                 } catch (GeneralSecurityException e) {
       
   538                     throwSSLException
       
   539                         ("Error generating RSA server key exchange", e);
       
   540                     m3 = null; // make compiler happy
       
   541                 }
       
   542             } else {
       
   543                 // RSA_EXPORT with short key, don't need ServerKeyExchange
       
   544                 m3 = null;
       
   545             }
       
   546             break;
       
   547         case K_DHE_RSA:
       
   548         case K_DHE_DSS:
       
   549             try {
       
   550                 m3 = new DH_ServerKeyExchange(dh,
       
   551                     privateKey,
       
   552                     clnt_random.random_bytes,
       
   553                     svr_random.random_bytes,
       
   554                     sslContext.getSecureRandom());
       
   555             } catch (GeneralSecurityException e) {
       
   556                 throwSSLException("Error generating DH server key exchange", e);
       
   557                 m3 = null; // make compiler happy
       
   558             }
       
   559             break;
       
   560         case K_DH_ANON:
       
   561             m3 = new DH_ServerKeyExchange(dh);
       
   562             break;
       
   563         case K_ECDHE_RSA:
       
   564         case K_ECDHE_ECDSA:
       
   565         case K_ECDH_ANON:
       
   566             try {
       
   567                 m3 = new ECDH_ServerKeyExchange(ecdh,
       
   568                     privateKey,
       
   569                     clnt_random.random_bytes,
       
   570                     svr_random.random_bytes,
       
   571                     sslContext.getSecureRandom());
       
   572             } catch (GeneralSecurityException e) {
       
   573                 throwSSLException("Error generating ECDH server key exchange", e);
       
   574                 m3 = null; // make compiler happy
       
   575             }
       
   576             break;
       
   577         case K_ECDH_RSA:
       
   578         case K_ECDH_ECDSA:
       
   579             // ServerKeyExchange not used for fixed ECDH
       
   580             m3 = null;
       
   581             break;
       
   582         default:
       
   583             throw new RuntimeException("internal error: " + keyExchange);
       
   584         }
       
   585         if (m3 != null) {
       
   586             if (debug != null && Debug.isOn("handshake")) {
       
   587                 m3.print(System.out);
       
   588             }
       
   589             m3.write(output);
       
   590         }
       
   591 
       
   592         //
       
   593         // FOURTH, the CertificateRequest message.  The details of
       
   594         // the message can be affected by the key exchange algorithm
       
   595         // in use.  For example, certs with fixed Diffie-Hellman keys
       
   596         // are only useful with the DH_DSS and DH_RSA key exchange
       
   597         // algorithms.
       
   598         //
       
   599         // Needed only if server requires client to authenticate self.
       
   600         // Illegal for anonymous flavors, so we need to check that.
       
   601         //
       
   602         if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
       
   603             // CertificateRequest is omitted for Kerberos ciphers
       
   604 
       
   605         } else if (doClientAuth != SSLEngineImpl.clauth_none &&
       
   606                 keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON) {
       
   607             CertificateRequest m4;
       
   608             X509Certificate caCerts[];
       
   609 
       
   610             caCerts = sslContext.getX509TrustManager().getAcceptedIssuers();
       
   611             m4 = new CertificateRequest(caCerts, keyExchange);
       
   612 
       
   613             if (debug != null && Debug.isOn("handshake")) {
       
   614                 m4.print(System.out);
       
   615             }
       
   616             m4.write(output);
       
   617         }
       
   618 
       
   619         /*
       
   620          * FIFTH, say ServerHelloDone.
       
   621          */
       
   622         ServerHelloDone m5 = new ServerHelloDone();
       
   623 
       
   624         if (debug != null && Debug.isOn("handshake")) {
       
   625             m5.print(System.out);
       
   626         }
       
   627         m5.write(output);
       
   628 
       
   629         /*
       
   630          * Flush any buffered messages so the client will see them.
       
   631          * Ideally, all the messages above go in a single network level
       
   632          * message to the client.  Without big Certificate chains, it's
       
   633          * going to be the common case.
       
   634          */
       
   635         output.flush();
       
   636     }
       
   637 
       
   638     /*
       
   639      * Choose cipher suite from among those supported by client. Sets
       
   640      * the cipherSuite and keyExchange variables.
       
   641      */
       
   642     private void chooseCipherSuite(ClientHello mesg) throws IOException {
       
   643         for (CipherSuite suite : mesg.getCipherSuites().collection()) {
       
   644             if (isEnabled(suite) == false) {
       
   645                 continue;
       
   646             }
       
   647             if (doClientAuth == SSLEngineImpl.clauth_required) {
       
   648                 if ((suite.keyExchange == K_DH_ANON) || (suite.keyExchange == K_ECDH_ANON)) {
       
   649                     continue;
       
   650                 }
       
   651             }
       
   652             if (trySetCipherSuite(suite) == false) {
       
   653                 continue;
       
   654             }
       
   655             return;
       
   656         }
       
   657         fatalSE(Alerts.alert_handshake_failure,
       
   658                     "no cipher suites in common");
       
   659     }
       
   660 
       
   661     /**
       
   662      * Set the given CipherSuite, if possible. Return the result.
       
   663      * The call succeeds if the CipherSuite is available and we have
       
   664      * the necessary certificates to complete the handshake. We don't
       
   665      * check if the CipherSuite is actually enabled.
       
   666      *
       
   667      * If successful, this method also generates ephemeral keys if
       
   668      * required for this ciphersuite. This may take some time, so this
       
   669      * method should only be called if you really want to use the
       
   670      * CipherSuite.
       
   671      *
       
   672      * This method is called from chooseCipherSuite() in this class
       
   673      * and SSLServerSocketImpl.checkEnabledSuites() (as a sanity check).
       
   674      */
       
   675     boolean trySetCipherSuite(CipherSuite suite) {
       
   676         /*
       
   677          * If we're resuming a session we know we can
       
   678          * support this key exchange algorithm and in fact
       
   679          * have already cached the result of it in
       
   680          * the session state.
       
   681          */
       
   682         if (resumingSession) {
       
   683             return true;
       
   684         }
       
   685 
       
   686         if (suite.isAvailable() == false) {
       
   687             return false;
       
   688         }
       
   689 
       
   690         KeyExchange keyExchange = suite.keyExchange;
       
   691 
       
   692         // null out any existing references
       
   693         privateKey = null;
       
   694         certs = null;
       
   695         dh = null;
       
   696         tempPrivateKey = null;
       
   697         tempPublicKey = null;
       
   698 
       
   699         switch (keyExchange) {
       
   700         case K_RSA:
       
   701         case K_RSA_EXPORT:
       
   702         case K_DHE_RSA:
       
   703         case K_ECDHE_RSA:
       
   704             // need RSA certs for authentication
       
   705             if (setupPrivateKeyAndChain("RSA") == false) {
       
   706                 return false;
       
   707             }
       
   708 
       
   709             if (keyExchange == K_RSA_EXPORT) {
       
   710                 try {
       
   711                    if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
       
   712                         if (!setupEphemeralRSAKeys(suite.exportable)) {
       
   713                             return false;
       
   714                         }
       
   715                    }
       
   716                 } catch (RuntimeException e) {
       
   717                     // could not determine keylength, ignore key
       
   718                     return false;
       
   719                 }
       
   720             } else if (keyExchange == K_DHE_RSA) {
       
   721                 setupEphemeralDHKeys(suite.exportable);
       
   722             } else if (keyExchange == K_ECDHE_RSA) {
       
   723                 if (setupEphemeralECDHKeys() == false) {
       
   724                     return false;
       
   725                 }
       
   726             } // else nothing more to do for K_RSA
       
   727             break;
       
   728         case K_DHE_DSS:
       
   729             // need DSS certs for authentication
       
   730             if (setupPrivateKeyAndChain("DSA") == false) {
       
   731                 return false;
       
   732             }
       
   733             setupEphemeralDHKeys(suite.exportable);
       
   734             break;
       
   735         case K_ECDHE_ECDSA:
       
   736             // need EC cert signed using EC
       
   737             if (setupPrivateKeyAndChain("EC_EC") == false) {
       
   738                 return false;
       
   739             }
       
   740             if (setupEphemeralECDHKeys() == false) {
       
   741                 return false;
       
   742             }
       
   743             break;
       
   744         case K_ECDH_RSA:
       
   745             // need EC cert signed using RSA
       
   746             if (setupPrivateKeyAndChain("EC_RSA") == false) {
       
   747                 return false;
       
   748             }
       
   749             setupStaticECDHKeys();
       
   750             break;
       
   751         case K_ECDH_ECDSA:
       
   752             // need EC cert signed using EC
       
   753             if (setupPrivateKeyAndChain("EC_EC") == false) {
       
   754                 return false;
       
   755             }
       
   756             setupStaticECDHKeys();
       
   757             break;
       
   758         case K_KRB5:
       
   759         case K_KRB5_EXPORT:
       
   760             // need Kerberos Key
       
   761             if (!setupKerberosKeys()) {
       
   762                 return false;
       
   763             }
       
   764             break;
       
   765         case K_DH_ANON:
       
   766             // no certs needed for anonymous
       
   767             setupEphemeralDHKeys(suite.exportable);
       
   768             break;
       
   769         case K_ECDH_ANON:
       
   770             // no certs needed for anonymous
       
   771             if (setupEphemeralECDHKeys() == false) {
       
   772                 return false;
       
   773             }
       
   774             break;
       
   775         default:
       
   776             // internal error, unknown key exchange
       
   777             throw new RuntimeException("Unrecognized cipherSuite: " + suite);
       
   778         }
       
   779         setCipherSuite(suite);
       
   780         return true;
       
   781     }
       
   782 
       
   783     /*
       
   784      * Get some "ephemeral" RSA keys for this context. This means
       
   785      * generating them if it's not already been done.
       
   786      *
       
   787      * Note that we currently do not implement any ciphersuites that use
       
   788      * strong ephemeral RSA. (We do not support the EXPORT1024 ciphersuites
       
   789      * and standard RSA ciphersuites prohibit ephemeral mode for some reason)
       
   790      * This means that export is always true and 512 bit keys are generated.
       
   791      */
       
   792     private boolean setupEphemeralRSAKeys(boolean export) {
       
   793         KeyPair kp = sslContext.getEphemeralKeyManager().
       
   794                         getRSAKeyPair(export, sslContext.getSecureRandom());
       
   795         if (kp == null) {
       
   796             return false;
       
   797         } else {
       
   798             tempPublicKey = kp.getPublic();
       
   799             tempPrivateKey = kp.getPrivate();
       
   800             return true;
       
   801         }
       
   802     }
       
   803 
       
   804     /*
       
   805      * Acquire some "ephemeral" Diffie-Hellman  keys for this handshake.
       
   806      * We don't reuse these, for improved forward secrecy.
       
   807      */
       
   808     private void setupEphemeralDHKeys(boolean export) {
       
   809         /*
       
   810          * Diffie-Hellman keys ... we use 768 bit private keys due
       
   811          * to the "use twice as many key bits as bits you want secret"
       
   812          * rule of thumb, assuming we want the same size premaster
       
   813          * secret with Diffie-Hellman and RSA key exchanges.  Except
       
   814          * that exportable ciphers max out at 512 bits modulus values.
       
   815          */
       
   816         dh = new DHCrypt((export ? 512 : 768), sslContext.getSecureRandom());
       
   817     }
       
   818 
       
   819     // Setup the ephemeral ECDH parameters.
       
   820     // If we cannot continue because we do not support any of the curves that
       
   821     // the client requested, return false. Otherwise (all is well), return true.
       
   822     private boolean setupEphemeralECDHKeys() {
       
   823         int index = -1;
       
   824         if (supportedCurves != null) {
       
   825             // if the client sent the supported curves extension, pick the
       
   826             // first one that we support;
       
   827             for (int curveId : supportedCurves.curveIds()) {
       
   828                 if (SupportedEllipticCurvesExtension.isSupported(curveId)) {
       
   829                     index = curveId;
       
   830                     break;
       
   831                 }
       
   832             }
       
   833             if (index < 0) {
       
   834                 // no match found, cannot use this ciphersuite
       
   835                 return false;
       
   836             }
       
   837         } else {
       
   838             // pick our preference
       
   839             index = SupportedEllipticCurvesExtension.DEFAULT.curveIds()[0];
       
   840         }
       
   841         String oid = SupportedEllipticCurvesExtension.getCurveOid(index);
       
   842         ecdh = new ECDHCrypt(oid, sslContext.getSecureRandom());
       
   843         return true;
       
   844     }
       
   845 
       
   846     private void setupStaticECDHKeys() {
       
   847         // don't need to check whether the curve is supported, already done
       
   848         // in setupPrivateKeyAndChain().
       
   849         ecdh = new ECDHCrypt(privateKey, certs[0].getPublicKey());
       
   850     }
       
   851 
       
   852     /**
       
   853      * Retrieve the server key and certificate for the specified algorithm
       
   854      * from the KeyManager and set the instance variables.
       
   855      *
       
   856      * @return true if successful, false if not available or invalid
       
   857      */
       
   858     private boolean setupPrivateKeyAndChain(String algorithm) {
       
   859         X509ExtendedKeyManager km = sslContext.getX509KeyManager();
       
   860         String alias;
       
   861         if (conn != null) {
       
   862             alias = km.chooseServerAlias(algorithm, null, conn);
       
   863         } else {
       
   864             alias = km.chooseEngineServerAlias(algorithm, null, engine);
       
   865         }
       
   866         if (alias == null) {
       
   867             return false;
       
   868         }
       
   869         PrivateKey tempPrivateKey = km.getPrivateKey(alias);
       
   870         if (tempPrivateKey == null) {
       
   871             return false;
       
   872         }
       
   873         X509Certificate[] tempCerts = km.getCertificateChain(alias);
       
   874         if ((tempCerts == null) || (tempCerts.length == 0)) {
       
   875             return false;
       
   876         }
       
   877         String keyAlgorithm = algorithm.split("_")[0];
       
   878         PublicKey publicKey = tempCerts[0].getPublicKey();
       
   879         if ((tempPrivateKey.getAlgorithm().equals(keyAlgorithm) == false)
       
   880                 || (publicKey.getAlgorithm().equals(keyAlgorithm) == false)) {
       
   881             return false;
       
   882         }
       
   883         // For ECC certs, check whether we support the EC domain parameters.
       
   884         // If the client sent a SupportedEllipticCurves ClientHello extension,
       
   885         // check against that too.
       
   886         if (keyAlgorithm.equals("EC")) {
       
   887             if (publicKey instanceof ECPublicKey == false) {
       
   888                 return false;
       
   889             }
       
   890             ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
       
   891             int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
       
   892             if (SupportedEllipticCurvesExtension.isSupported(index) == false) {
       
   893                 return false;
       
   894             }
       
   895             if ((supportedCurves != null) && !supportedCurves.contains(index)) {
       
   896                 return false;
       
   897             }
       
   898         }
       
   899         this.privateKey = tempPrivateKey;
       
   900         this.certs = tempCerts;
       
   901         return true;
       
   902     }
       
   903 
       
   904     /**
       
   905      * Retrieve the Kerberos key for the specified server principal
       
   906      * from the JAAS configuration file.
       
   907      *
       
   908      * @return true if successful, false if not available or invalid
       
   909      */
       
   910     private boolean setupKerberosKeys() {
       
   911         if (kerberosKeys != null) {
       
   912             return true;
       
   913         }
       
   914         try {
       
   915             final AccessControlContext acc = getAccSE();
       
   916             kerberosKeys = AccessController.doPrivileged(
       
   917                 new PrivilegedExceptionAction<KerberosKey[]>() {
       
   918                 public KerberosKey[] run() throws Exception {
       
   919                     // get kerberos key for the default principal
       
   920                     return Krb5Util.getKeys(
       
   921                         GSSUtil.CALLER_SSL_SERVER, null, acc);
       
   922                         }});
       
   923 
       
   924             // check permission to access and use the secret key of the
       
   925             // Kerberized "host" service
       
   926             if (kerberosKeys != null) {
       
   927 
       
   928                 if (debug != null && Debug.isOn("handshake")) {
       
   929                     System.out.println("Using Kerberos key: " +
       
   930                         kerberosKeys[0]);
       
   931                 }
       
   932 
       
   933                 String serverPrincipal =
       
   934                     kerberosKeys[0].getPrincipal().getName();
       
   935                 SecurityManager sm = System.getSecurityManager();
       
   936                 try {
       
   937                    if (sm != null) {
       
   938                       sm.checkPermission(new ServicePermission(serverPrincipal,
       
   939                                                 "accept"), acc);
       
   940                    }
       
   941                 } catch (SecurityException se) {
       
   942                    kerberosKeys = null;
       
   943                    // %%% destroy keys? or will that affect Subject?
       
   944                    if (debug != null && Debug.isOn("handshake"))
       
   945                       System.out.println("Permission to access Kerberos"
       
   946                                 + " secret key denied");
       
   947                    return false;
       
   948                 }
       
   949             }
       
   950             return (kerberosKeys != null);
       
   951         } catch (PrivilegedActionException e) {
       
   952             // Likely exception here is LoginExceptin
       
   953             if (debug != null && Debug.isOn("handshake")) {
       
   954                 System.out.println("Attempt to obtain Kerberos key failed: "
       
   955                                 + e.toString());
       
   956             }
       
   957             return false;
       
   958         }
       
   959     }
       
   960 
       
   961     /*
       
   962      * For Kerberos ciphers, the premaster secret is encrypted using
       
   963      * the session key. See RFC 2712.
       
   964      */
       
   965     private SecretKey clientKeyExchange(KerberosClientKeyExchange mesg)
       
   966         throws IOException {
       
   967 
       
   968         if (debug != null && Debug.isOn("handshake")) {
       
   969             mesg.print(System.out);
       
   970         }
       
   971 
       
   972         // Record the principals involved in exchange
       
   973         session.setPeerPrincipal(mesg.getPeerPrincipal());
       
   974         session.setLocalPrincipal(mesg.getLocalPrincipal());
       
   975 
       
   976         byte[] b = mesg.getPreMasterSecret().getUnencrypted();
       
   977         return new SecretKeySpec(b, "TlsPremasterSecret");
       
   978     }
       
   979 
       
   980     /*
       
   981      * Diffie Hellman key exchange is used when the server presented
       
   982      * D-H parameters in its certificate (signed using RSA or DSS/DSA),
       
   983      * or else the server presented no certificate but sent D-H params
       
   984      * in a ServerKeyExchange message.  Use of D-H is specified by the
       
   985      * cipher suite chosen.
       
   986      *
       
   987      * The message optionally contains the client's D-H public key (if
       
   988      * it wasn't not sent in a client certificate).  As always with D-H,
       
   989      * if a client and a server have each other's D-H public keys and
       
   990      * they use common algorithm parameters, they have a shared key
       
   991      * that's derived via the D-H calculation.  That key becomes the
       
   992      * pre-master secret.
       
   993      */
       
   994     private SecretKey clientKeyExchange(DHClientKeyExchange mesg)
       
   995             throws IOException {
       
   996 
       
   997         if (debug != null && Debug.isOn("handshake")) {
       
   998             mesg.print(System.out);
       
   999         }
       
  1000         return dh.getAgreedSecret(mesg.getClientPublicKey());
       
  1001     }
       
  1002 
       
  1003     private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
       
  1004             throws IOException {
       
  1005 
       
  1006         if (debug != null && Debug.isOn("handshake")) {
       
  1007             mesg.print(System.out);
       
  1008         }
       
  1009         return ecdh.getAgreedSecret(mesg.getEncodedPoint());
       
  1010     }
       
  1011 
       
  1012     /*
       
  1013      * Client wrote a message to verify the certificate it sent earlier.
       
  1014      *
       
  1015      * Note that this certificate isn't involved in key exchange.  Client
       
  1016      * authentication messages are included in the checksums used to
       
  1017      * validate the handshake (e.g. Finished messages).  Other than that,
       
  1018      * the _exact_ identity of the client is less fundamental to protocol
       
  1019      * security than its role in selecting keys via the pre-master secret.
       
  1020      */
       
  1021     private void clientCertificateVerify(CertificateVerify mesg)
       
  1022             throws IOException {
       
  1023 
       
  1024         if (debug != null && Debug.isOn("handshake")) {
       
  1025             mesg.print(System.out);
       
  1026         }
       
  1027 
       
  1028         try {
       
  1029             PublicKey publicKey =
       
  1030                 session.getPeerCertificates()[0].getPublicKey();
       
  1031 
       
  1032             boolean valid = mesg.verify(protocolVersion, handshakeHash,
       
  1033                                         publicKey, session.getMasterSecret());
       
  1034             if (valid == false) {
       
  1035                 fatalSE(Alerts.alert_bad_certificate,
       
  1036                             "certificate verify message signature error");
       
  1037             }
       
  1038         } catch (GeneralSecurityException e) {
       
  1039             fatalSE(Alerts.alert_bad_certificate,
       
  1040                 "certificate verify format error", e);
       
  1041         }
       
  1042 
       
  1043         // reset the flag for clientCertificateVerify message
       
  1044         needClientVerify = false;
       
  1045     }
       
  1046 
       
  1047 
       
  1048     /*
       
  1049      * Client writes "finished" at the end of its handshake, after cipher
       
  1050      * spec is changed.   We verify it and then send ours.
       
  1051      *
       
  1052      * When we're resuming a session, we'll have already sent our own
       
  1053      * Finished message so just the verification is needed.
       
  1054      */
       
  1055     private void clientFinished(Finished mesg) throws IOException {
       
  1056         if (debug != null && Debug.isOn("handshake")) {
       
  1057             mesg.print(System.out);
       
  1058         }
       
  1059 
       
  1060         /*
       
  1061          * Verify if client did send the certificate when client
       
  1062          * authentication was required, otherwise server should not proceed
       
  1063          */
       
  1064         if (doClientAuth == SSLEngineImpl.clauth_required) {
       
  1065            // get X500Principal of the end-entity certificate for X509-based
       
  1066            // ciphersuites, or Kerberos principal for Kerberos ciphersuites
       
  1067            session.getPeerPrincipal();
       
  1068         }
       
  1069 
       
  1070         /*
       
  1071          * Verify if client did send clientCertificateVerify message following
       
  1072          * the client Certificate, otherwise server should not proceed
       
  1073          */
       
  1074         if (needClientVerify) {
       
  1075                 fatalSE(Alerts.alert_handshake_failure,
       
  1076                         "client did not send certificate verify message");
       
  1077         }
       
  1078 
       
  1079         /*
       
  1080          * Verify the client's message with the "before" digest of messages,
       
  1081          * and forget about continuing to use that digest.
       
  1082          */
       
  1083         boolean verified = mesg.verify(protocolVersion, handshakeHash,
       
  1084                                 Finished.CLIENT, session.getMasterSecret());
       
  1085 
       
  1086         if (!verified) {
       
  1087             fatalSE(Alerts.alert_handshake_failure,
       
  1088                         "client 'finished' message doesn't verify");
       
  1089             // NOTREACHED
       
  1090         }
       
  1091 
       
  1092         /*
       
  1093          * OK, it verified.  If we're doing the full handshake, add that
       
  1094          * "Finished" message to the hash of handshake messages, then send
       
  1095          * the change_cipher_spec and Finished message.
       
  1096          */
       
  1097         if (!resumingSession) {
       
  1098             input.digestNow();
       
  1099             sendChangeCipherAndFinish(true);
       
  1100         }
       
  1101 
       
  1102         /*
       
  1103          * Update the session cache only after the handshake completed, else
       
  1104          * we're open to an attack against a partially completed handshake.
       
  1105          */
       
  1106         session.setLastAccessedTime(System.currentTimeMillis());
       
  1107         if (!resumingSession && session.isRejoinable()) {
       
  1108             ((SSLSessionContextImpl)sslContext.engineGetServerSessionContext())
       
  1109                 .put(session);
       
  1110             if (debug != null && Debug.isOn("session")) {
       
  1111                 System.out.println(
       
  1112                     "%% Cached server session: " + session);
       
  1113             }
       
  1114         } else if (!resumingSession &&
       
  1115                 debug != null && Debug.isOn("session")) {
       
  1116             System.out.println(
       
  1117                 "%% Didn't cache non-resumable server session: "
       
  1118                 + session);
       
  1119         }
       
  1120     }
       
  1121 
       
  1122     /*
       
  1123      * Compute finished message with the "server" digest (and then forget
       
  1124      * about that digest, it can't be used again).
       
  1125      */
       
  1126     private void sendChangeCipherAndFinish(boolean finishedTag)
       
  1127             throws IOException {
       
  1128 
       
  1129         output.flush();
       
  1130 
       
  1131         Finished mesg = new Finished(protocolVersion, handshakeHash,
       
  1132                                 Finished.SERVER, session.getMasterSecret());
       
  1133 
       
  1134         /*
       
  1135          * Send the change_cipher_spec record; then our Finished handshake
       
  1136          * message will be the last handshake message.  Flush, and now we
       
  1137          * are ready for application data!!
       
  1138          */
       
  1139         sendChangeCipherSpec(mesg, finishedTag);
       
  1140 
       
  1141         /*
       
  1142          * Update state machine so client MUST send 'finished' next
       
  1143          * The update should only take place if it is not in the fast
       
  1144          * handshake mode since the server has to wait for a finished
       
  1145          * message from the client.
       
  1146          */
       
  1147         if (finishedTag) {
       
  1148             state = HandshakeMessage.ht_finished;
       
  1149         }
       
  1150     }
       
  1151 
       
  1152 
       
  1153     /*
       
  1154      * Returns a HelloRequest message to kickstart renegotiations
       
  1155      */
       
  1156     HandshakeMessage getKickstartMessage() {
       
  1157         return new HelloRequest();
       
  1158     }
       
  1159 
       
  1160 
       
  1161     /*
       
  1162      * Fault detected during handshake.
       
  1163      */
       
  1164     void handshakeAlert(byte description) throws SSLProtocolException {
       
  1165 
       
  1166         String message = Alerts.alertDescription(description);
       
  1167 
       
  1168         if (debug != null && Debug.isOn("handshake")) {
       
  1169             System.out.println("SSL -- handshake alert:  "
       
  1170                 + message);
       
  1171         }
       
  1172 
       
  1173         /*
       
  1174          * It's ok to get a no_certificate alert from a client of which
       
  1175          * we *requested* authentication information.
       
  1176          * However, if we *required* it, then this is not acceptable.
       
  1177          *
       
  1178          * Anyone calling getPeerCertificates() on the
       
  1179          * session will get an SSLPeerUnverifiedException.
       
  1180          */
       
  1181         if ((description == Alerts.alert_no_certificate) &&
       
  1182                 (doClientAuth == SSLEngineImpl.clauth_requested)) {
       
  1183             return;
       
  1184         }
       
  1185 
       
  1186         throw new SSLProtocolException("handshake alert: " + message);
       
  1187     }
       
  1188 
       
  1189     /*
       
  1190      * RSA key exchange is normally used.  The client encrypts a "pre-master
       
  1191      * secret" with the server's public key, from the Certificate (or else
       
  1192      * ServerKeyExchange) message that was sent to it by the server.  That's
       
  1193      * decrypted using the private key before we get here.
       
  1194      */
       
  1195     private SecretKey clientKeyExchange(RSAClientKeyExchange mesg) throws IOException {
       
  1196 
       
  1197         if (debug != null && Debug.isOn("handshake")) {
       
  1198             mesg.print(System.out);
       
  1199         }
       
  1200         return mesg.preMaster;
       
  1201     }
       
  1202 
       
  1203     /*
       
  1204      * Verify the certificate sent by the client. We'll only get one if we
       
  1205      * sent a CertificateRequest to request client authentication. If we
       
  1206      * are in TLS mode, the client may send a message with no certificates
       
  1207      * to indicate it does not have an appropriate chain. (In SSLv3 mode,
       
  1208      * it would send a no certificate alert).
       
  1209      */
       
  1210     private void clientCertificate(CertificateMsg mesg) throws IOException {
       
  1211         if (debug != null && Debug.isOn("handshake")) {
       
  1212             mesg.print(System.out);
       
  1213         }
       
  1214 
       
  1215         X509Certificate[] peerCerts = mesg.getCertificateChain();
       
  1216 
       
  1217         if (peerCerts.length == 0) {
       
  1218             /*
       
  1219              * If the client authentication is only *REQUESTED* (e.g.
       
  1220              * not *REQUIRED*, this is an acceptable condition.)
       
  1221              */
       
  1222             if (doClientAuth == SSLEngineImpl.clauth_requested) {
       
  1223                 return;
       
  1224             } else {
       
  1225                 fatalSE(Alerts.alert_bad_certificate,
       
  1226                     "null cert chain");
       
  1227             }
       
  1228         }
       
  1229 
       
  1230         // ask the trust manager to verify the chain
       
  1231         X509TrustManager tm = sslContext.getX509TrustManager();
       
  1232 
       
  1233         try {
       
  1234             // find out the types of client authentication used
       
  1235             PublicKey key = peerCerts[0].getPublicKey();
       
  1236             String keyAlgorithm = key.getAlgorithm();
       
  1237             String authType;
       
  1238             if (keyAlgorithm.equals("RSA")) {
       
  1239                 authType = "RSA";
       
  1240             } else if (keyAlgorithm.equals("DSA")) {
       
  1241                 authType = "DSA";
       
  1242             } else if (keyAlgorithm.equals("EC")) {
       
  1243                 authType = "EC";
       
  1244             } else {
       
  1245                 // unknown public key type
       
  1246                 authType = "UNKNOWN";
       
  1247             }
       
  1248 
       
  1249             String identificator = getHostnameVerificationSE();
       
  1250             if (tm instanceof X509ExtendedTrustManager) {
       
  1251                 ((X509ExtendedTrustManager)tm).checkClientTrusted(
       
  1252                         (peerCerts != null ?
       
  1253                             peerCerts.clone() :
       
  1254                             null),
       
  1255                         authType,
       
  1256                         getHostSE(),
       
  1257                         identificator);
       
  1258             } else {
       
  1259                 if (identificator != null) {
       
  1260                     throw new RuntimeException(
       
  1261                         "trust manager does not support peer identification");
       
  1262                 }
       
  1263 
       
  1264                 tm.checkClientTrusted(
       
  1265                     (peerCerts != null ?
       
  1266                         peerCerts.clone() :
       
  1267                         peerCerts),
       
  1268                     authType);
       
  1269             }
       
  1270         } catch (CertificateException e) {
       
  1271             // This will throw an exception, so include the original error.
       
  1272             fatalSE(Alerts.alert_certificate_unknown, e);
       
  1273         }
       
  1274         // set the flag for clientCertificateVerify message
       
  1275         needClientVerify = true;
       
  1276 
       
  1277         session.setPeerCertificates(peerCerts);
       
  1278     }
       
  1279 }