ServerHandshaker.java revision 4102
1472N/A * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. 986N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 986N/A * This code is free software; you can redistribute it and/or modify it 986N/A * under the terms of the GNU General Public License version 2 only, as 986N/A * published by the Free Software Foundation. Oracle designates this 986N/A * particular file as subject to the "Classpath" exception as provided 986N/A * by Oracle in the LICENSE file that accompanied this code. 986N/A * This code is distributed in the hope that it will be useful, but WITHOUT 986N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 986N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 986N/A * version 2 for more details (a copy is included in the LICENSE file that 986N/A * accompanied this code). 986N/A * You should have received a copy of the GNU General Public License version 986N/A * 2 along with this work; if not, write to the Free Software Foundation, 1472N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 986N/A * or visit www.oracle.com if you need additional information or have any * ServerHandshaker does the protocol handshaking from the point * of view of a server. It is driven asychronously by handshake messages * as delivered by the parent Handshaker class, and also uses * common functionality (e.g. key generation) that is provided there. // is the server going to require the client to authenticate? // our authentication info // flag to check for clientCertificateVerify message * For exportable ciphersuites using non-exportable key sizes, we use * ephemeral RSA keys. We could also do anonymous RSA in the same way * but there are no such ciphersuites currently defined. * For anonymous and ephemeral Diffie-Hellman key exchange, we use * ephemeral Diffie-Hellman keys. // Helper for ECDH based key exchanges // version request by the client in its ClientHello // we remember it for the RSA premaster secret version check // the preferable signature algorithm used by ServerKeyExchange message * Constructor ... use the keys found in the auth context. * Constructor ... use the keys found in the auth context. * As long as handshaking has not started, we can change * whether client authentication is required. Otherwise, * we will need to wait for the next handshake. * This routine handles all the server side handshake messages, one at * a time. Given the message type (and in some cases the pending cipher * spec) it parses the type-specific message. Then it calls a function * that handles that specific message. * It updates the state machine as each message is processed, and writes * responses as needed using the connection in the constructor. // In SSLv3 and TLS, messages follow strictly increasing // numerical order _except_ for one annoying special case. "Handshake message sequence violation, state = " +
state * send it off for processing. "client sent unsolicited cert chain");
* The client's pre-master secret is decrypted using * either the server's normal private RSA key, or the * temporary one used for non-export or signing-only * The pre-master secret is derived using the normal * Diffie-Hellman calculation. Note that the main * protocol difference in these five flavors is in how * the ServerKeyExchange message was constructed! // All keys are calculated from the premaster secret // and the exchanged nonces in the same way. "Illegal server handshake msg, " +
type);
// Move the state machine forward except for that annoying // special case. This means that clients could send extra // cert verify messages; not a problem so long as all of // them actually check out. * ClientHello presents the server with a bunch of options, to which the * server replies with a ServerHello listing the ones which this session * will use. If needed, it also writes its Certificate plus in some cases * a ServerKeyExchange message. It may also write a CertificateRequest, * to elicit a client certificate. * All these messages are terminated by a ServerHelloDone message. In * most cases, all this can be sent in a single Record. // Does the message include security renegotiation indication? // check the TLS_EMPTY_RENEGOTIATION_INFO_SCSV // abort the handshake with a fatal handshake_failure alert "The SCSV is present in a secure renegotiation");
"The SCSV is present in a insecure renegotiation");
// check the "renegotiation_info" extension // verify the length of the "renegotiated_connection" field // abort the handshake with a fatal handshake_failure alert "The renegotiation_info field is not empty");
// unexpected RI extension for insecure renegotiation, // abort the handshake with a fatal handshake_failure alert "The renegotiation_info is present in a insecure " +
// verify the client_verify_data value "Incorrect verify data in ClientHello " +
"renegotiation_info message");
// if the connection's "secure_renegotiation" flag is set to TRUE // and the "renegotiation_info" extension is not present, abort "Inconsistent secure renegotiation indication");
// if there is no security renegotiation indication or the previous // handshake is insecure. // abort the handshake with a fatal handshake_failure alert "Failed to negotiate the use of secure renegotiation");
// continue with legacy ClientHello "indication in ClientHello, allow legacy ClientHello");
// response with a no_renegotiation warning, // invalidate the handshake so that the caller can // If there is still unread block in the handshake // input stream, it would be truncated with the disposal // and the next handshake message will become incomplete. // However, according to SSL/TLS specifications, no more // handshake message could immediately follow ClientHello // or HelloRequest. But in case of any improper messages, // we'd better check to ensure there is no remaining bytes // in the handshake input stream. "ClientHello followed by an unexpected " +
// For SSLv3, send the handshake_failure fatal error. // Note that SSLv3 does not define a no_renegotiation // alert like TLSv1. However we cannot ignore the message // simply, otherwise the other side was waiting for a // response that would never come. "Renegotiation is not allowed");
}
else {
// !isInitialHandshake && allowUnsafeRenegotiation // continue with unsafe renegotiation. "Warning: continue with insecure renegotiation");
* Always make sure this entire record has been digested before we * start emitting output, to ensure correct digesting order. * FIRST, construct the ServerHello using the options and priorities * from the ClientHello. Update the (pending) cipher spec as we do * so, and save the client's version to protect against rollback * There are a bunch of minor tasks here, and one major one: deciding * if the short or the full handshake sequence will be used. // select a proper protocol version. " not enabled or not supported");
// random ... save client and server values for later use // in computing the master secret (from pre-master secret) // and thence the other crypto keys. // NOTE: this use of three inputs to generating _each_ set // of ciphers slows things down, but it does increase the // security since each connection in the session can hold // its own authenticated (and strong) keys. One could make // creation of a session a rare thing... // Here we go down either of two paths: (a) the fast one, where // the client's asked to rejoin an existing session, and the server // permits this; (b) the other one, where a new session is created. // client is trying to resume a session, let's see... // Check if we can use the fast path, resuming a session. We // can do so iff we have a valid record for that session, and // the cipher suite for that session was on the list which the // client requested, and if we're not forgetting any needed // authentication on the part of the client. // cannot resume session with different version // validate subject identity // Eliminate dependency on KerberosPrincipal " not present in the current Subject;" +
" javax.security.auth.useSubjectAsCreds" +
" system property has been set to false");
// verify that the ciphersuite from the cached session // is in the list of client requested ciphersuites and // everything looks ok, set the ciphersuite // this should be done last when we are sure we }
// else client did not try to resume // If client hasn't specified a session we can resume, start a // new one and choose its cipher suite and compression options. // Unless new session creation is disabled for this connection! // We only need to handle the "signature_algorithm" extension // for full handshakes and TLS 1.2 or later. "No peer supported signature algorithms");
"No supported signature and hash algorithm " +
}
// else, need to use peer implicit supported signature algs }
// else, we will set the implicit peer supported signature // algorithms in chooseCipherSuite() // set the handshake session // choose cipher suite and corresponding private key // chooseCompression(mesg); // set the handshake session // For ServerHellos that are initial handshakes, then the // "renegotiated_connection" field in "renegotiation_info" // extension is of zero length. // For ServerHellos that are renegotiating, this field contains // the concatenation of client_verify_data and server_verify_data. // Note that for initial handshakes, both the clientVerifyData // variable and serverVerifyData variable are of zero length. // If we are resuming a session, we finish writing handshake // messages right now and then finish. * SECOND, write the server Certificate(s) if we need to. * NOTE: while an "anonymous RSA" mode is explicitly allowed by * the protocol, we can't support it since all of the SSL flavors * defined in the protocol spec are explicitly stated to require * using RSA certificates. // Server certificates are omitted for Kerberos ciphers * Set local certs in the SSLSession, output * debug info, and then actually write to the client. // XXX has some side effects with OS TCP buffering, // let client verify chain in the meantime... * THIRD, the ServerKeyExchange message ... iff it's needed. * It's usually needed unless there's an encryption-capable * RSA cert, or a D-H cert. The notable exception is that * exportable ciphers used with big RSA keys need to downgrade * to use short RSA keys, even when the key/cert encrypts OK. // no server key exchange for RSA or KRB5 ciphersuites (
"Error generating RSA server key exchange", e);
m3 =
null;
// make compiler happy // RSA_EXPORT with short key, don't need ServerKeyExchange m3 =
null;
// make compiler happy "Error generating ECDH server key exchange", e);
m3 =
null;
// make compiler happy // ServerKeyExchange not used for fixed ECDH // FOURTH, the CertificateRequest message. The details of // the message can be affected by the key exchange algorithm // in use. For example, certs with fixed Diffie-Hellman keys // are only useful with the DH_DSS and DH_RSA key exchange // Needed only if server requires client to authenticate self. // Illegal for anonymous flavors, so we need to check that. // CertificateRequest is omitted for Kerberos ciphers // We currently use all local upported signature and hash // algorithms. However, to minimize the computation cost // of requested hash algorithms, we may use a restricted // set of signature algorithms in the future. "No supported signature algorithm");
"No supported signature algorithm");
* FIFTH, say ServerHelloDone. * Flush any buffered messages so the client will see them. * Ideally, all the messages above go in a single network level * message to the client. Without big Certificate chains, it's * going to be the common case. * Choose cipher suite from among those supported by client. Sets * the cipherSuite and keyExchange variables. "no cipher suites in common");
* Set the given CipherSuite, if possible. Return the result. * The call succeeds if the CipherSuite is available and we have * the necessary certificates to complete the handshake. We don't * check if the CipherSuite is actually enabled. * If successful, this method also generates ephemeral keys if * required for this ciphersuite. This may take some time, so this * method should only be called if you really want to use the * This method is called from chooseCipherSuite() in this class. * If we're resuming a session we know we can * support this key exchange algorithm and in fact * have already cached the result of it in // must not negotiate the obsoleted weak cipher suites. // must not negotiate unsupported cipher suites. // null out any existing references // we may optimize the performance // If the negotiated key exchange algorithm is one of // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), // behave as if client had sent the value {sha1,rsa}. // If the negotiated key exchange algorithm is one of // (DHE_DSS, DH_DSS), behave as if the client had // sent the value {sha1,dsa}. // If the negotiated key exchange algorithm is one of // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client // had sent value {sha1,ecdsa}. // no peer supported signature algorithms // Sets the peer supported signature algorithm to use in KM // need RSA certs for authentication // need RSA certs for authentication // could not determine keylength, ignore key // get preferable peer signature algorithm for server key exchange // need RSA certs for authentication // get preferable peer signature algorithm for server key exchange // need RSA certs for authentication // get preferable peer signature algorithm for server key exchange // need DSS certs for authentication // get preferable peer signature algorithm for server key exchange // need EC cert signed using EC // need EC cert signed using RSA // need EC cert signed using EC // no certs needed for anonymous // no certs needed for anonymous // internal error, unknown key exchange // set the peer implicit supported signature algorithms // we had alreay update the session * Get some "ephemeral" RSA keys for this context. This means * generating them if it's not already been done. * Note that we currently do not implement any ciphersuites that use * strong ephemeral RSA. (We do not support the EXPORT1024 ciphersuites * and standard RSA ciphersuites prohibit ephemeral mode for some reason) * This means that export is always true and 512 bit keys are generated. * Acquire some "ephemeral" Diffie-Hellman keys for this handshake. * We don't reuse these, for improved forward secrecy. * Diffie-Hellman keys ... we use 768 bit private keys due * to the "use twice as many key bits as bits you want secret" * rule of thumb, assuming we want the same size premaster * secret with Diffie-Hellman and RSA key exchanges. Except * that exportable ciphers max out at 512 bits modulus values. // Setup the ephemeral ECDH parameters. // If we cannot continue because we do not support any of the curves that // the client requested, return false. Otherwise (all is well), return true. // if the client sent the supported curves extension, pick the // first one that we support; // no match found, cannot use this ciphersuite // don't need to check whether the curve is supported, already done // in setupPrivateKeyAndChain(). * Retrieve the server key and certificate for the specified algorithm * from the KeyManager and set the instance variables. * @return true if successful, false if not available or invalid // For ECC certs, check whether we support the EC domain parameters. // If the client sent a SupportedEllipticCurves ClientHello extension, // check against that too. * Retrieve the Kerberos key for the specified server principal * from the JAAS configuration file. * @return true if successful, false if not available or invalid // Eliminate dependency on KerberosKey // get kerberos key for the default principal // check permission to access and use the secret key of the // Kerberized "host" service // Eliminate dependency on ServicePermission // %%% destroy keys? or will that affect Subject? // Likely exception here is LoginExceptin * For Kerberos ciphers, the premaster secret is encrypted using * the session key. See RFC 2712. // Record the principals involved in exchange * Diffie Hellman key exchange is used when the server presented * D-H parameters in its certificate (signed using RSA or DSS/DSA), * or else the server presented no certificate but sent D-H params * in a ServerKeyExchange message. Use of D-H is specified by the * The message optionally contains the client's D-H public key (if * it wasn't not sent in a client certificate). As always with D-H, * if a client and a server have each other's D-H public keys and * they use common algorithm parameters, they have a shared key * that's derived via the D-H calculation. That key becomes the * Client wrote a message to verify the certificate it sent earlier. * Note that this certificate isn't involved in key exchange. Client * authentication messages are included in the checksums used to * validate the handshake (e.g. Finished messages). Other than that, * the _exact_ identity of the client is less fundamental to protocol * security than its role in selecting keys via the pre-master secret. "Illegal CertificateVerify message");
"No supported hash algorithm");
"certificate verify message signature error");
"certificate verify format error", e);
// reset the flag for clientCertificateVerify message * Client writes "finished" at the end of its handshake, after cipher * spec is changed. We verify it and then send ours. * When we're resuming a session, we'll have already sent our own * Finished message so just the verification is needed. * Verify if client did send the certificate when client * authentication was required, otherwise server should not proceed // get X500Principal of the end-entity certificate for X509-based // ciphersuites, or Kerberos principal for Kerberos ciphersuites * Verify if client did send clientCertificateVerify message following * the client Certificate, otherwise server should not proceed "client did not send certificate verify message");
* Verify the client's message with the "before" digest of messages, * and forget about continuing to use that digest. "client 'finished' message doesn't verify");
* save client verify data for secure renegotiation * OK, it verified. If we're doing the full handshake, add that * "Finished" message to the hash of handshake messages, then send * the change_cipher_spec and Finished message. * Update the session cache only after the handshake completed, else * we're open to an attack against a partially completed handshake. "%% Cached server session: " +
session);
"%% Didn't cache non-resumable server session: " * Compute finished message with the "server" digest (and then forget * about that digest, it can't be used again). * Send the change_cipher_spec record; then our Finished handshake * message will be the last handshake message. Flush, and now we * are ready for application data!! * save server verify data for secure renegotiation * Update state machine so client MUST send 'finished' next * The update should only take place if it is not in the fast * handshake mode since the server has to wait for a finished * message from the client. * Returns a HelloRequest message to kickstart renegotiations * Fault detected during handshake. * It's ok to get a no_certificate alert from a client of which * we *requested* authentication information. * However, if we *required* it, then this is not acceptable. * Anyone calling getPeerCertificates() on the * session will get an SSLPeerUnverifiedException. * RSA key exchange is normally used. The client encrypts a "pre-master * secret" with the server's public key, from the Certificate (or else * ServerKeyExchange) message that was sent to it by the server. That's * decrypted using the private key before we get here. * Verify the certificate sent by the client. We'll only get one if we * sent a CertificateRequest to request client authentication. If we * are in TLS mode, the client may send a message with no certificates * to indicate it does not have an appropriate chain. (In SSLv3 mode, * it would send a no certificate alert). * If the client authentication is only *REQUESTED* (e.g. * not *REQUIRED*, this is an acceptable condition.) // Smart (aka stupid) to forecast that no CertificateVerify // message will be received. // ask the trust manager to verify the chain // find out the types of client authentication used // unknown public key type // Unlikely to happen, because we have wrapped the old // X509TrustManager with the new X509ExtendedTrustManager. "Improper X509TrustManager implementation");
// This will throw an exception, so include the original error. // set the flag for clientCertificateVerify message