diff options
author | Matt Caswell <matt@openssl.org> | 2015-09-11 10:48:59 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2015-10-30 08:38:18 +0000 |
commit | 8ba708e5166b02ab61f2762d36b3e7b7455e9c06 (patch) | |
tree | 656a9eea1a383757494ea7058d7ea680ba46e93c /ssl/s3_srvr.c | |
parent | 1aeaa7ec06ccd4c819a3ca94139c3ab79463fada (diff) |
Reorganise state machine files
Pull out the state machine into a separate sub directory. Also moved some
functions which were nothing to do with the state machine but were in state
machine files. Pulled all the SSL_METHOD definitions into one place...most
of those files had very little left in them any more.
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
Diffstat (limited to 'ssl/s3_srvr.c')
-rw-r--r-- | ssl/s3_srvr.c | 2878 |
1 files changed, 0 insertions, 2878 deletions
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c deleted file mode 100644 index 4442223282..0000000000 --- a/ssl/s3_srvr.c +++ /dev/null @@ -1,2878 +0,0 @@ -/* ssl/s3_srvr.c -*- mode:C; c-file-style: "eay" -*- */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * - * Portions of the attached software ("Contribution") are developed by - * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. - * - * The Contribution is licensed pursuant to the OpenSSL open source - * license provided above. - * - * ECC cipher suite support in OpenSSL originally written by - * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. - * - */ -/* ==================================================================== - * Copyright 2005 Nokia. All rights reserved. - * - * The portions of the attached software ("Contribution") is developed by - * Nokia Corporation and is licensed pursuant to the OpenSSL open source - * license. - * - * The Contribution, originally written by Mika Kousa and Pasi Eronen of - * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites - * support (see RFC 4279) to OpenSSL. - * - * No patent licenses or other rights except those expressly stated in - * the OpenSSL open source license shall be deemed granted or received - * expressly, by implication, estoppel, or otherwise. - * - * No assurances are provided by Nokia that the Contribution does not - * infringe the patent or other intellectual property rights of any third - * party or that the license provides you with all the necessary rights - * to make use of the Contribution. - * - * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN - * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA - * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY - * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR - * OTHERWISE. - */ - - -#include <stdio.h> -#include "ssl_locl.h" -#include "internal/constant_time_locl.h" -#include <openssl/buffer.h> -#include <openssl/rand.h> -#include <openssl/objects.h> -#include <openssl/evp.h> -#include <openssl/hmac.h> -#include <openssl/x509.h> -#ifndef OPENSSL_NO_DH -# include <openssl/dh.h> -#endif -#include <openssl/bn.h> -#include <openssl/md5.h> - -static STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, - PACKET *cipher_suites, - STACK_OF(SSL_CIPHER) **skp, - int sslv2format, int *al); - -#ifndef OPENSSL_NO_SRP -static int ssl_check_srp_ext_ClientHello(SSL *s, int *al) -{ - int ret = SSL_ERROR_NONE; - - *al = SSL_AD_UNRECOGNIZED_NAME; - - if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) && - (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) { - if (s->srp_ctx.login == NULL) { - /* - * RFC 5054 says SHOULD reject, we do so if There is no srp - * login name - */ - ret = SSL3_AL_FATAL; - *al = SSL_AD_UNKNOWN_PSK_IDENTITY; - } else { - ret = SSL_srp_server_param_with_username(s, al); - } - } - return ret; -} -#endif - -int tls_construct_hello_request(SSL *s) -{ - if (!ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0)) { - SSLerr(SSL_F_TLS_CONSTRUCT_HELLO_REQUEST, ERR_R_INTERNAL_ERROR); - statem_set_error(s); - return 0; - } - - return 1; -} - -enum MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) -{ - int i, al = SSL_AD_INTERNAL_ERROR; - unsigned int j, complen = 0; - unsigned long id; - SSL_CIPHER *c; -#ifndef OPENSSL_NO_COMP - SSL_COMP *comp = NULL; -#endif - STACK_OF(SSL_CIPHER) *ciphers = NULL; - int protverr = 1; - /* |cookie| will only be initialized for DTLS. */ - PACKET session_id, cipher_suites, compression, extensions, cookie; - int is_v2_record; - - is_v2_record = RECORD_LAYER_is_sslv2_record(&s->rlayer); - - PACKET_null_init(&cookie); - /* First lets get s->client_version set correctly */ - if (is_v2_record) { - unsigned int version; - unsigned int mt; - /*- - * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2 - * header is sent directly on the wire, not wrapped as a TLS - * record. Our record layer just processes the message length and passes - * the rest right through. Its format is: - * Byte Content - * 0-1 msg_length - decoded by the record layer - * 2 msg_type - s->init_msg points here - * 3-4 version - * 5-6 cipher_spec_length - * 7-8 session_id_length - * 9-10 challenge_length - * ... ... - */ - - if (!PACKET_get_1(pkt, &mt) - || mt != SSL2_MT_CLIENT_HELLO) { - /* - * Should never happen. We should have tested this in the record - * layer in order to have determined that this is a SSLv2 record - * in the first place - */ - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - goto err; - } - - if (!PACKET_get_net_2(pkt, &version)) { - /* No protocol version supplied! */ - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); - goto err; - } - if (version == 0x0002) { - /* This is real SSLv2. We don't support it. */ - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); - goto err; - } else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) { - /* SSLv3/TLS */ - s->client_version = version; - } else { - /* No idea what protocol this is */ - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); - goto err; - } - } else { - /* - * use version from inside client hello, not from record header (may - * differ: see RFC 2246, Appendix E, second paragraph) - */ - if(!PACKET_get_net_2(pkt, (unsigned int *)&s->client_version)) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - } - - /* Do SSL/TLS version negotiation if applicable */ - if (!SSL_IS_DTLS(s)) { - if (s->version != TLS_ANY_VERSION) { - if (s->client_version >= s->version) { - protverr = 0; - } - } else if (s->client_version >= SSL3_VERSION) { - switch(s->client_version) { - default: - case TLS1_2_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1_2)) { - s->version = TLS1_2_VERSION; - s->method = TLSv1_2_server_method(); - protverr = 0; - break; - } - /* Deliberately fall through */ - case TLS1_1_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1_1)) { - s->version = TLS1_1_VERSION; - s->method = TLSv1_1_server_method(); - protverr = 0; - break; - } - /* Deliberately fall through */ - case TLS1_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1)) { - s->version = TLS1_VERSION; - s->method = TLSv1_server_method(); - protverr = 0; - break; - } - /* Deliberately fall through */ - case SSL3_VERSION: -#ifndef OPENSSL_NO_SSL3 - if(!(s->options & SSL_OP_NO_SSLv3)) { - s->version = SSL3_VERSION; - s->method = SSLv3_server_method(); - protverr = 0; - break; - } -#else - break; -#endif - } - } - } else if (s->client_version <= s->version - || s->method->version == DTLS_ANY_VERSION) { - /* - * For DTLS we just check versions are potentially compatible. Version - * negotiation comes later. - */ - protverr = 0; - } - - if (protverr) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); - if ((!s->enc_write_ctx && !s->write_hash)) { - /* - * similar to ssl3_get_record, send alert using remote version - * number - */ - s->version = s->client_version; - } - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - - /* Parse the message and load client random. */ - if (is_v2_record) { - /* - * Handle an SSLv2 backwards compatible ClientHello - * Note, this is only for SSLv3+ using the backward compatible format. - * Real SSLv2 is not supported, and is rejected above. - */ - unsigned int cipher_len, session_id_len, challenge_len; - PACKET challenge; - - if (!PACKET_get_net_2(pkt, &cipher_len) - || !PACKET_get_net_2(pkt, &session_id_len) - || !PACKET_get_net_2(pkt, &challenge_len)) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, - SSL_R_RECORD_LENGTH_MISMATCH); - al = SSL_AD_DECODE_ERROR; - goto f_err; - } - - if (!PACKET_get_sub_packet(pkt, &cipher_suites, cipher_len) - || !PACKET_get_sub_packet(pkt, &session_id, session_id_len) - || !PACKET_get_sub_packet(pkt, &challenge, challenge_len) - /* No extensions. */ - || PACKET_remaining(pkt) != 0) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH); - al = SSL_AD_DECODE_ERROR; - goto f_err; - } - - /* Load the client random */ - challenge_len = challenge_len > SSL3_RANDOM_SIZE ? SSL3_RANDOM_SIZE : - challenge_len; - memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE); - if (!PACKET_copy_bytes(&challenge, - s->s3->client_random + SSL3_RANDOM_SIZE - - challenge_len, challenge_len)) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } - - PACKET_null_init(&compression); - PACKET_null_init(&extensions); - } else { - /* Regular ClientHello. */ - if (!PACKET_copy_bytes(pkt, s->s3->client_random, SSL3_RANDOM_SIZE) - || !PACKET_get_length_prefixed_1(pkt, &session_id)) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); - goto f_err; - } - - if (SSL_IS_DTLS(s)) { - if (!PACKET_get_length_prefixed_1(pkt, &cookie)) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); - goto f_err; - } - /* - * If we require cookies and this ClientHello doesn't contain one, - * just return since we do not want to allocate any memory yet. - * So check cookie length... - */ - if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { - if (PACKET_remaining(&cookie) == 0) - return 1; - } - } - - if (!PACKET_get_length_prefixed_2(pkt, &cipher_suites) - || !PACKET_get_length_prefixed_1(pkt, &compression)) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); - goto f_err; - } - /* Could be empty. */ - extensions = *pkt; - } - - s->hit = 0; - - /* - * We don't allow resumption in a backwards compatible ClientHello. - * TODO(openssl-team): in TLS1.1+, session_id MUST be empty. - * - * Versions before 0.9.7 always allow clients to resume sessions in - * renegotiation. 0.9.7 and later allow this by default, but optionally - * ignore resumption requests with flag - * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather - * than a change to default behavior so that applications relying on - * this for security won't even compile against older library versions). - * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to - * request renegotiation but not a new session (s->new_session remains - * unset): for servers, this essentially just means that the - * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be - * ignored. - */ - if (is_v2_record || - (s->new_session && - (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { - if (!ssl_get_new_session(s, 1)) - goto err; - } else { - i = ssl_get_prev_session(s, &extensions, &session_id); - /* - * Only resume if the session's version matches the negotiated - * version. - * RFC 5246 does not provide much useful advice on resumption - * with a different protocol version. It doesn't forbid it but - * the sanity of such behaviour would be questionable. - * In practice, clients do not accept a version mismatch and - * will abort the handshake with an error. - */ - if (i == 1 && s->version == s->session->ssl_version) { - /* previous session */ - s->hit = 1; - } else if (i == -1) { - goto err; - } else { - /* i == 0 */ - if (!ssl_get_new_session(s, 1)) - goto err; - } - } - - if (SSL_IS_DTLS(s)) { - /* Empty cookie was already handled above by returning early. */ - if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { - if (s->ctx->app_verify_cookie_cb != NULL) { - if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookie), - PACKET_remaining(&cookie)) == 0) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_COOKIE_MISMATCH); - goto f_err; - /* else cookie verification succeeded */ - } - /* default verification */ - } else if (!PACKET_equal(&cookie, s->d1->cookie, - s->d1->cookie_len)) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); - goto f_err; - } - s->d1->cookie_verified = 1; - } - if (s->method->version == DTLS_ANY_VERSION) { - /* Select version to use */ - if (s->client_version <= DTLS1_2_VERSION && - !(s->options & SSL_OP_NO_DTLSv1_2)) { - s->version = DTLS1_2_VERSION; - s->method = DTLSv1_2_server_method(); - } else if (tls1_suiteb(s)) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } else if (s->client_version <= DTLS1_VERSION && - !(s->options & SSL_OP_NO_DTLSv1)) { - s->version = DTLS1_VERSION; - s->method = DTLSv1_server_method(); - } else { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_WRONG_VERSION_NUMBER); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - s->session->ssl_version = s->version; - } - } - - if (ssl_bytes_to_cipher_list(s, &cipher_suites, &(ciphers), - is_v2_record, &al) == NULL) { - goto f_err; - } - - /* If it is a hit, check that the cipher is in the list */ - if (s->hit) { - j = 0; - id = s->session->cipher->id; - -#ifdef CIPHER_DEBUG - fprintf(stderr, "client sent %d ciphers\n", - sk_SSL_CIPHER_num(ciphers)); -#endif - for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { - c = sk_SSL_CIPHER_value(ciphers, i); -#ifdef CIPHER_DEBUG - fprintf(stderr, "client [%2d of %2d]:%s\n", - i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c)); -#endif - if (c->id == id) { - j = 1; - break; - } - } - if (j == 0) { - /* - * we need to have the cipher in the cipher list if we are asked - * to reuse it - */ - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_REQUIRED_CIPHER_MISSING); - goto f_err; - } - } - - complen = PACKET_remaining(&compression); - for (j = 0; j < complen; j++) { - if (PACKET_data(&compression)[j] == 0) - break; - } - - if (j >= complen) { - /* no compress */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED); - goto f_err; - } - - /* TLS extensions */ - if (s->version >= SSL3_VERSION) { - if (!ssl_parse_clienthello_tlsext(s, &extensions)) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT); - goto err; - } - } - - /* - * Check if we want to use external pre-shared secret for this handshake - * for not reused session only. We need to generate server_random before - * calling tls_session_secret_cb in order to allow SessionTicket - * processing to use it in key derivation. - */ - { - unsigned char *pos; - pos = s->s3->server_random; - if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE) <= 0) { - goto f_err; - } - } - - if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) { - SSL_CIPHER *pref_cipher = NULL; - - s->session->master_key_length = sizeof(s->session->master_key); - if (s->tls_session_secret_cb(s, s->session->master_key, - &s->session->master_key_length, ciphers, - &pref_cipher, - s->tls_session_secret_cb_arg)) { - s->hit = 1; - s->session->ciphers = ciphers; - s->session->verify_result = X509_V_OK; - - ciphers = NULL; - - /* check if some cipher was preferred by call back */ - pref_cipher = - pref_cipher ? pref_cipher : ssl3_choose_cipher(s, - s-> - session->ciphers, - SSL_get_ciphers - (s)); - if (pref_cipher == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER); - goto f_err; - } - - s->session->cipher = pref_cipher; - sk_SSL_CIPHER_free(s->cipher_list); - s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); - sk_SSL_CIPHER_free(s->cipher_list_by_id); - s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); - } - } - - /* - * Worst case, we will use the NULL compression, but if we have other - * options, we will now look for them. We have complen-1 compression - * algorithms from the client, starting at q. - */ - s->s3->tmp.new_compression = NULL; -#ifndef OPENSSL_NO_COMP - /* This only happens if we have a cache hit */ - if (s->session->compress_meth != 0) { - int m, comp_id = s->session->compress_meth; - unsigned int k; - /* Perform sanity checks on resumed compression algorithm */ - /* Can't disable compression */ - if (!ssl_allow_compression(s)) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, - SSL_R_INCONSISTENT_COMPRESSION); - goto f_err; - } - /* Look for resumed compression method */ - for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) { - comp = sk_SSL_COMP_value(s->ctx->comp_methods, m); - if (comp_id == comp->id) { - s->s3->tmp.new_compression = comp; - break; - } - } - if (s->s3->tmp.new_compression == NULL) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, - SSL_R_INVALID_COMPRESSION_ALGORITHM); - goto f_err; - } - /* Look for resumed method in compression list */ - for (k = 0; k < complen; k++) { - if (PACKET_data(&compression)[k] == comp_id) - break; - } - if (k >= complen) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, - SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING); - goto f_err; - } - } else if (s->hit) - comp = NULL; - else if (ssl_allow_compression(s) && s->ctx->comp_methods) { - /* See if we have a match */ - int m, nn, v, done = 0; - unsigned int o; - - nn = sk_SSL_COMP_num(s->ctx->comp_methods); - for (m = 0; m < nn; m++) { - comp = sk_SSL_COMP_value(s->ctx->comp_methods, m); - v = comp->id; - for (o = 0; o < complen; o++) { - if (v == PACKET_data(&compression)[o]) { - done = 1; - break; - } - } - if (done) - break; - } - if (done) - s->s3->tmp.new_compression = comp; - else - comp = NULL; - } -#else - /* - * If compression is disabled we'd better not try to resume a session - * using compression. - */ - if (s->session->compress_meth != 0) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_INCONSISTENT_COMPRESSION); - goto f_err; - } -#endif - - /* - * Given s->session->ciphers and SSL_get_ciphers, we must pick a cipher - */ - - if (!s->hit) { -#ifdef OPENSSL_NO_COMP - s->session->compress_meth = 0; -#else - s->session->compress_meth = (comp == NULL) ? 0 : comp->id; -#endif - sk_SSL_CIPHER_free(s->session->ciphers); - s->session->ciphers = ciphers; - if (ciphers == NULL) { - al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - goto f_err; - } - ciphers = NULL; - if (!tls1_set_server_sigalgs(s)) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT); - goto err; - } - } - - sk_SSL_CIPHER_free(ciphers); - return MSG_PROCESS_CONTINUE_PROCESSING; - f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - err: - statem_set_error(s); - - sk_SSL_CIPHER_free(ciphers); - return MSG_PROCESS_ERROR; - -} - -enum WORK_STATE tls_post_process_client_hello(SSL *s, enum WORK_STATE wst) -{ - int al; - SSL_CIPHER *cipher; - - if (wst == WORK_MORE_A) { - if (!s->hit) { - /* Let cert callback update server certificates if required */ - if (s->cert->cert_cb) { - int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); - if (rv == 0) { - al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, SSL_R_CERT_CB_ERROR); - goto f_err; - } - if (rv < 0) { - s->rwstate = SSL_X509_LOOKUP; - return WORK_MORE_A; - } - s->rwstate = SSL_NOTHING; - } - cipher = ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); - - if (cipher == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER); - goto f_err; - } - s->s3->tmp.new_cipher = cipher; - /* check whether we should disable session resumption */ - if (s->not_resumable_session_cb != NULL) - s->session->not_resumable = s->not_resumable_session_cb(s, - ((cipher->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) != 0)); - if (s->session->not_resumable) - /* do not send a session ticket */ - s->tlsext_ticket_expected = 0; - } else { - /* Session-id reuse */ - s->s3->tmp.new_cipher = s->session->cipher; - } - - if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) { - if (!ssl3_digest_cached_records(s, 0)) - goto f_err; - } - - /*- - * we now have the following setup. - * client_random - * cipher_list - our prefered list of ciphers - * ciphers - the clients prefered list of ciphers - * compression - basically ignored right now - * ssl version is set - sslv3 - * s->session - The ssl session has been setup. - * s->hit - session reuse flag - * s->s3->tmp.new_cipher- the new cipher to use. - */ - - /* Handles TLS extensions that we couldn't check earlier */ - if (s->version >= SSL3_VERSION) { - if (ssl_check_clienthello_tlsext_late(s) <= 0) { - SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT); - goto f_err; - } - } - - wst = WORK_MORE_B; - } -#ifndef OPENSSL_NO_SRP - if (wst == WORK_MORE_B) { - int ret; - if ((ret = ssl_check_srp_ext_ClientHello(s, &al)) < 0) { - /* - * callback indicates further work to be done - */ - s->rwstate = SSL_X509_LOOKUP; - return WORK_MORE_B; - } - if (ret != SSL_ERROR_NONE) { - /* - * This is not really an error but the only means to for - * a client to detect whether srp is supported. - */ - if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY) - SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, - SSL_R_CLIENTHELLO_TLSEXT); - goto f_err; - } - } -#endif - s->renegotiate = 2; - - return WORK_FINISHED_STOP; - f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, al); - statem_set_error(s); - return WORK_ERROR; -} - -int tls_construct_server_hello(SSL *s) -{ - unsigned char *buf; - unsigned char *p, *d; - int i, sl; - int al = 0; - unsigned long l; - - buf = (unsigned char *)s->init_buf->data; - - /* Do the message type and length last */ - d = p = ssl_handshake_start(s); - - *(p++) = s->version >> 8; - *(p++) = s->version & 0xff; - - /* - * Random stuff. Filling of the server_random takes place in - * tls_process_client_hello() - */ - memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; - - /*- - * There are several cases for the session ID to send - * back in the server hello: - * - For session reuse from the session cache, - * we send back the old session ID. - * - If stateless session reuse (using a session ticket) - * is successful, we send back the client's "session ID" - * (which doesn't actually identify the session). - * - If it is a new session, we send back the new - * session ID. - * - However, if we want the new session to be single-use, - * we send back a 0-length session ID. - * s->hit is non-zero in either case of session reuse, - * so the following won't overwrite an ID that we're supposed - * to send back. - */ - if (s->session->not_resumable || - (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) - && !s->hit)) - s->session->session_id_length = 0; - - sl = s->session->session_id_length; - if (sl > (int)sizeof(s->session->session_id)) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR); - statem_set_error(s); - return 0; - } - *(p++) = sl; - memcpy(p, s->session->session_id, sl); - p += sl; - - /* put the cipher */ - i = ssl3_put_cipher_by_char(s->s3->tmp.new_cipher, p); - p += i; - - /* put the compression method */ -#ifdef OPENSSL_NO_COMP - *(p++) = 0; -#else - if (s->s3->tmp.new_compression == NULL) - *(p++) = 0; - else - *(p++) = s->s3->tmp.new_compression->id; -#endif - - if |