| Index: openssl/ssl/s3_srvr.c
|
| ===================================================================
|
| --- openssl/ssl/s3_srvr.c (revision 105093)
|
| +++ openssl/ssl/s3_srvr.c (working copy)
|
| @@ -1,4 +1,4 @@
|
| -/* ssl/s3_srvr.c */
|
| +/* ssl/s3_srvr.c -*- mode:C; c-file-style: "eay" -*- */
|
| /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
| * All rights reserved.
|
| *
|
| @@ -56,7 +56,7 @@
|
| * [including the GNU Public Licence.]
|
| */
|
| /* ====================================================================
|
| - * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
|
| + * 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
|
| @@ -121,6 +121,32 @@
|
| * 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.
|
| + */
|
|
|
| #define REUSE_CIPHER_BUG
|
| #define NETSCAPE_HANG_BUG
|
| @@ -143,15 +169,9 @@
|
| #endif
|
| #include <openssl/md5.h>
|
|
|
| -#include "fnv1a64.h"
|
| +static const SSL_METHOD *ssl3_get_server_method(int ver);
|
|
|
| -static SSL_METHOD *ssl3_get_server_method(int ver);
|
| -static int ssl3_snap_start_evaluate_handshake(SSL* s);
|
| -#ifndef OPENSSL_NO_ECDH
|
| -static int nid2curve_id(int nid);
|
| -#endif
|
| -
|
| -static SSL_METHOD *ssl3_get_server_method(int ver)
|
| +static const SSL_METHOD *ssl3_get_server_method(int ver)
|
| {
|
| if (ver == SSL3_VERSION)
|
| return(SSLv3_server_method());
|
| @@ -167,7 +187,7 @@
|
| int ssl3_accept(SSL *s)
|
| {
|
| BUF_MEM *buf;
|
| - unsigned long l,Time=(unsigned long)time(NULL);
|
| + unsigned long alg_k,Time=(unsigned long)time(NULL);
|
| void (*cb)(const SSL *ssl,int type,int val)=NULL;
|
| int ret= -1;
|
| int new_state,state,skip=0;
|
| @@ -238,6 +258,7 @@
|
| }
|
|
|
| s->init_num=0;
|
| + s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
|
|
|
| if (s->state != SSL_ST_RENEGOTIATE)
|
| {
|
| @@ -295,6 +316,7 @@
|
| s->shutdown=0;
|
| ret=ssl3_get_client_hello(s);
|
| if (ret <= 0) goto end;
|
| +
|
| s->new_session = 2;
|
| s->state=SSL3_ST_SW_SRVR_HELLO_A;
|
| s->init_num=0;
|
| @@ -303,36 +325,10 @@
|
| case SSL3_ST_SW_SRVR_HELLO_A:
|
| case SSL3_ST_SW_SRVR_HELLO_B:
|
| ret=ssl3_send_server_hello(s);
|
| - if (ret == SERVER_RANDOM_VALIDATION_PENDING)
|
| - {
|
| - s->rwstate = SSL_SERVER_RANDOM_VALIDATE;
|
| - s->state = SSL3_ST_SW_SRVR_HELLO_A;
|
| - s->init_num = 0;
|
| - goto end;
|
| - }
|
| if (ret <= 0) goto end;
|
| #ifndef OPENSSL_NO_TLSEXT
|
| - if ((s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK) != SSL_kRSA &&
|
| - (s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK) != SSL_kKRB5 &&
|
| - (s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK) != SSL_kDHr &&
|
| - (s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK) != SSL_kDHd &&
|
| - (s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK) != SSL_kECDH &&
|
| - s->s3->snap_start_requested)
|
| - {
|
| - /* There's no point in carrying on with a Snap
|
| - * Start handshake if we're using a cipher
|
| - * suite which is going to send a
|
| - * ServerKeyExchange message. */
|
| - ssl3_snap_start_reset_for_recovery(s);
|
| - s->state = SSL3_ST_SW_SRVR_HELLO_A;
|
| - break;
|
| - }
|
| -
|
| if (s->hit)
|
| {
|
| - if (ssl3_snap_start_evaluate_handshake(s))
|
| - break;
|
| -
|
| if (s->tlsext_ticket_expected)
|
| s->state=SSL3_ST_SW_SESSION_TICKET_A;
|
| else
|
| @@ -349,9 +345,11 @@
|
|
|
| case SSL3_ST_SW_CERT_A:
|
| case SSL3_ST_SW_CERT_B:
|
| - /* Check if it is anon DH or anon ECDH or KRB5 */
|
| - if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
|
| - && !(s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
|
| + /* Check if it is anon DH or anon ECDH, */
|
| + /* normal PSK or KRB5 */
|
| + if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
|
| + && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
|
| + && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
|
| {
|
| ret=ssl3_send_server_certificate(s);
|
| if (ret <= 0) goto end;
|
| @@ -378,13 +376,13 @@
|
|
|
| case SSL3_ST_SW_KEY_EXCH_A:
|
| case SSL3_ST_SW_KEY_EXCH_B:
|
| - l=s->s3->tmp.new_cipher->algorithms;
|
| + alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
|
|
| /* clear this, it may get reset by
|
| * send_server_key_exchange */
|
| if ((s->options & SSL_OP_EPHEMERAL_RSA)
|
| #ifndef OPENSSL_NO_KRB5
|
| - && !(l & SSL_KRB5)
|
| + && !(alg_k & SSL_kKRB5)
|
| #endif /* OPENSSL_NO_KRB5 */
|
| )
|
| /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
|
| @@ -399,16 +397,23 @@
|
| /* only send if a DH key exchange, fortezza or
|
| * RSA but we have a sign only certificate
|
| *
|
| + * PSK: may send PSK identity hints
|
| + *
|
| * For ECC ciphersuites, we send a serverKeyExchange
|
| * message only if the cipher suite is either
|
| * ECDH-anon or ECDHE. In other cases, the
|
| - * server certificate contains the server's
|
| + * server certificate contains the server's
|
| * public key for key exchange.
|
| */
|
| if (s->s3->tmp.use_rsa_tmp
|
| - || (l & SSL_kECDHE)
|
| - || (l & (SSL_DH|SSL_kFZA))
|
| - || ((l & SSL_kRSA)
|
| + /* PSK: send ServerKeyExchange if PSK identity
|
| + * hint if provided */
|
| +#ifndef OPENSSL_NO_PSK
|
| + || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
|
| +#endif
|
| + || (alg_k & (SSL_kDHr|SSL_kDHd|SSL_kEDH))
|
| + || (alg_k & SSL_kEECDH)
|
| + || ((alg_k & SSL_kRSA)
|
| && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
|
| || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
|
| && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
|
| @@ -438,12 +443,15 @@
|
| /* never request cert in anonymous ciphersuites
|
| * (see section "Certificate request" in SSL 3 drafts
|
| * and in RFC 2246): */
|
| - ((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) &&
|
| + ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
|
| /* ... except when the application insists on verification
|
| * (against the specs, but s3_clnt.c accepts this for SSL 3) */
|
| !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
|
| - /* never request cert in Kerberos ciphersuites */
|
| - (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
|
| + /* never request cert in Kerberos ciphersuites */
|
| + (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)
|
| + /* With normal PSK Certificates and
|
| + * Certificate Requests are omitted */
|
| + || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
|
| {
|
| /* no cert request */
|
| skip=1;
|
| @@ -469,19 +477,8 @@
|
| case SSL3_ST_SW_SRVR_DONE_B:
|
| ret=ssl3_send_server_done(s);
|
| if (ret <= 0) goto end;
|
| -
|
| - if (s->s3->snap_start_requested)
|
| - {
|
| - if (ssl3_snap_start_evaluate_handshake(s))
|
| - break;
|
| - s->state = SSL3_ST_SR_CERT_A;
|
| - }
|
| - else
|
| - {
|
| - s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
|
| - s->state=SSL3_ST_SW_FLUSH;
|
| - }
|
| -
|
| + s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
|
| + s->state=SSL3_ST_SW_FLUSH;
|
| s->init_num=0;
|
| break;
|
|
|
| @@ -530,7 +527,7 @@
|
| case SSL3_ST_SR_KEY_EXCH_A:
|
| case SSL3_ST_SR_KEY_EXCH_B:
|
| ret=ssl3_get_client_key_exchange(s);
|
| - if (ret <= 0)
|
| + if (ret <= 0)
|
| goto end;
|
| if (ret == 2)
|
| {
|
| @@ -538,27 +535,50 @@
|
| * the client sends its ECDH pub key in
|
| * a certificate, the CertificateVerify
|
| * message is not sent.
|
| + * Also for GOST ciphersuites when
|
| + * the client uses its key from the certificate
|
| + * for key exchange.
|
| */
|
| +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
|
| + s->state=SSL3_ST_SR_FINISHED_A;
|
| +#else
|
| if (s->s3->next_proto_neg_seen)
|
| s->state=SSL3_ST_SR_NEXT_PROTO_A;
|
| else
|
| s->state=SSL3_ST_SR_FINISHED_A;
|
| +#endif
|
| s->init_num = 0;
|
| }
|
| - else
|
| + else
|
| {
|
| + int offset=0;
|
| + int dgst_num;
|
| +
|
| s->state=SSL3_ST_SR_CERT_VRFY_A;
|
| s->init_num=0;
|
|
|
| /* We need to get hashes here so if there is
|
| * a client cert, it can be verified
|
| - */
|
| - s->method->ssl3_enc->cert_verify_mac(s,
|
| - &(s->s3->finish_dgst1),
|
| - &(s->s3->tmp.cert_verify_md[0]));
|
| - s->method->ssl3_enc->cert_verify_mac(s,
|
| - &(s->s3->finish_dgst2),
|
| - &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
|
| + * FIXME - digest processing for CertificateVerify
|
| + * should be generalized. But it is next step
|
| + */
|
| + if (s->s3->handshake_buffer)
|
| + if (!ssl3_digest_cached_records(s))
|
| + return -1;
|
| + for (dgst_num=0; dgst_num<SSL_MAX_DIGEST;dgst_num++)
|
| + if (s->s3->handshake_dgst[dgst_num])
|
| + {
|
| + int dgst_size;
|
| +
|
| + s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
|
| + dgst_size=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
|
| + if (dgst_size < 0)
|
| + {
|
| + ret = -1;
|
| + goto end;
|
| + }
|
| + offset+=dgst_size;
|
| + }
|
| }
|
| break;
|
|
|
| @@ -569,13 +589,18 @@
|
| ret=ssl3_get_cert_verify(s);
|
| if (ret <= 0) goto end;
|
|
|
| +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
|
| + s->state=SSL3_ST_SR_FINISHED_A;
|
| +#else
|
| if (s->s3->next_proto_neg_seen)
|
| s->state=SSL3_ST_SR_NEXT_PROTO_A;
|
| else
|
| s->state=SSL3_ST_SR_FINISHED_A;
|
| +#endif
|
| s->init_num=0;
|
| break;
|
|
|
| +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
| case SSL3_ST_SR_NEXT_PROTO_A:
|
| case SSL3_ST_SR_NEXT_PROTO_B:
|
| ret=ssl3_get_next_proto(s);
|
| @@ -583,17 +608,21 @@
|
| s->init_num = 0;
|
| s->state=SSL3_ST_SR_FINISHED_A;
|
| break;
|
| +#endif
|
|
|
| case SSL3_ST_SR_FINISHED_A:
|
| case SSL3_ST_SR_FINISHED_B:
|
| ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
|
| SSL3_ST_SR_FINISHED_B);
|
| if (ret <= 0) goto end;
|
| +#ifndef OPENSSL_NO_TLSEXT
|
| + if (s->tlsext_ticket_expected)
|
| + s->state=SSL3_ST_SW_SESSION_TICKET_A;
|
| + else if (s->hit)
|
| + s->state=SSL_ST_OK;
|
| +#else
|
| if (s->hit)
|
| s->state=SSL_ST_OK;
|
| -#ifndef OPENSSL_NO_TLSEXT
|
| - else if (s->tlsext_ticket_expected)
|
| - s->state=SSL3_ST_SW_SESSION_TICKET_A;
|
| #endif
|
| else
|
| s->state=SSL3_ST_SW_CHANGE_A;
|
| @@ -652,10 +681,14 @@
|
| s->state=SSL3_ST_SW_FLUSH;
|
| if (s->hit)
|
| {
|
| +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
|
| + s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
|
| +#else
|
| if (s->s3->next_proto_neg_seen)
|
| s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A;
|
| else
|
| s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
|
| +#endif
|
| }
|
| else
|
| s->s3->tmp.next_state=SSL_ST_OK;
|
| @@ -756,6 +789,14 @@
|
| int ok;
|
| long n;
|
|
|
| + /* We only allow the client to restart the handshake once per
|
| + * negotiation. */
|
| + if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE)
|
| + {
|
| + SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS);
|
| + return -1;
|
| + }
|
| +
|
| /* this function is called when we really expect a Certificate message,
|
| * so permit appropriate message length */
|
| n=s->method->ssl_get_message(s,
|
| @@ -769,9 +810,7 @@
|
| if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO)
|
| {
|
| /* Throw away what we have done so far in the current handshake,
|
| - * which will now be aborted. (A full SSL_clear would be too much.)
|
| - * I hope that tmp.dh is the only thing that may need to be cleared
|
| - * when a handshake is not completed ... */
|
| + * which will now be aborted. (A full SSL_clear would be too much.) */
|
| #ifndef OPENSSL_NO_DH
|
| if (s->s3->tmp.dh != NULL)
|
| {
|
| @@ -779,6 +818,14 @@
|
| s->s3->tmp.dh = NULL;
|
| }
|
| #endif
|
| +#ifndef OPENSSL_NO_ECDH
|
| + if (s->s3->tmp.ecdh != NULL)
|
| + {
|
| + EC_KEY_free(s->s3->tmp.ecdh);
|
| + s->s3->tmp.ecdh = NULL;
|
| + }
|
| +#endif
|
| + s->s3->flags |= SSL3_FLAGS_SGC_RESTART_DONE;
|
| return 2;
|
| }
|
| return 1;
|
| @@ -828,7 +875,7 @@
|
| (s->version != DTLS1_VERSION && s->client_version < s->version))
|
| {
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
|
| - if ((s->client_version>>8) == SSL3_VERSION_MAJOR)
|
| + if ((s->client_version>>8) == SSL3_VERSION_MAJOR)
|
| {
|
| /* similar to ssl3_get_record, send alert using remote version number */
|
| s->version = s->client_version;
|
| @@ -870,6 +917,12 @@
|
| */
|
| if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
|
| {
|
| + if (!s->session_creation_enabled)
|
| + {
|
| + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
|
| + goto err;
|
| + }
|
| if (!ssl_get_new_session(s,1))
|
| goto err;
|
| }
|
| @@ -884,6 +937,12 @@
|
| goto err;
|
| else /* i == 0 */
|
| {
|
| + if (!s->session_creation_enabled)
|
| + {
|
| + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
|
| + goto err;
|
| + }
|
| if (!ssl_get_new_session(s,1))
|
| goto err;
|
| }
|
| @@ -986,6 +1045,10 @@
|
| break;
|
| }
|
| }
|
| +/* Disabled because it can be used in a ciphersuite downgrade
|
| + * attack: CVE-2010-4180.
|
| + */
|
| +#if 0
|
| if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1))
|
| {
|
| /* Special case as client bug workaround: the previously used cipher may
|
| @@ -1000,6 +1063,7 @@
|
| j = 1;
|
| }
|
| }
|
| +#endif
|
| if (j == 0)
|
| {
|
| /* we need to have the cipher in the cipher
|
| @@ -1049,13 +1113,110 @@
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_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 long Time;
|
| + unsigned char *pos;
|
| + Time=(unsigned long)time(NULL); /* Time */
|
| + pos=s->s3->server_random;
|
| + l2n(Time,pos);
|
| + if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
|
| + {
|
| + al=SSL_AD_INTERNAL_ERROR;
|
| + 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_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
|
| + goto f_err;
|
| + }
|
| +
|
| + s->session->cipher=pref_cipher;
|
| +
|
| + if (s->cipher_list)
|
| + sk_SSL_CIPHER_free(s->cipher_list);
|
| +
|
| + if (s->cipher_list_by_id)
|
| + sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
| +
|
| + s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
|
| + s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
|
| + }
|
| + }
|
| #endif
|
| +
|
| /* Worst case, we will use the NULL compression, but if we have other
|
| * options, we will now look for them. We have i-1 compression
|
| * algorithms from the client, starting at q. */
|
| s->s3->tmp.new_compression=NULL;
|
| #ifndef OPENSSL_NO_COMP
|
| - if (s->ctx->comp_methods != NULL)
|
| + /* This only happens if we have a cache hit */
|
| + if (s->session->compress_meth != 0)
|
| + {
|
| + int m, comp_id = s->session->compress_meth;
|
| + /* Perform sanity checks on resumed compression algorithm */
|
| + /* Can't disable compression */
|
| + if (s->options & SSL_OP_NO_COMPRESSION)
|
| + {
|
| + al=SSL_AD_INTERNAL_ERROR;
|
| + SSLerr(SSL_F_SSL3_GET_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)
|
| + {
|
| + al=SSL_AD_INTERNAL_ERROR;
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INVALID_COMPRESSION_ALGORITHM);
|
| + goto f_err;
|
| + }
|
| + /* Look for resumed method in compression list */
|
| + for (m = 0; m < i; m++)
|
| + {
|
| + if (q[m] == comp_id)
|
| + break;
|
| + }
|
| + if (m >= i)
|
| + {
|
| + al=SSL_AD_ILLEGAL_PARAMETER;
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
|
| + goto f_err;
|
| + }
|
| + }
|
| + else if (s->hit)
|
| + comp = NULL;
|
| + else if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods)
|
| { /* See if we have a match */
|
| int m,nn,o,v,done=0;
|
|
|
| @@ -1079,22 +1240,15 @@
|
| else
|
| comp=NULL;
|
| }
|
| -#endif
|
| -
|
| - /* TLS does not mind if there is extra stuff */
|
| -#if 0 /* SSL 3.0 does not mind either, so we should disable this test
|
| - * (was enabled in 0.9.6d through 0.9.6j and 0.9.7 through 0.9.7b,
|
| - * in earlier SSLeay/OpenSSL releases this test existed but was buggy) */
|
| - if (s->version == SSL3_VERSION)
|
| +#else
|
| + /* If compression is disabled we'd better not try to resume a session
|
| + * using compression.
|
| + */
|
| + if (s->session->compress_meth != 0)
|
| {
|
| - if (p < (d+n))
|
| - {
|
| - /* wrong number of bytes,
|
| - * there could be more to follow */
|
| - al=SSL_AD_DECODE_ERROR;
|
| - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
|
| - goto f_err;
|
| - }
|
| + al=SSL_AD_INTERNAL_ERROR;
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
|
| + goto f_err;
|
| }
|
| #endif
|
|
|
| @@ -1143,7 +1297,7 @@
|
| for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
|
| {
|
| c=sk_SSL_CIPHER_value(sk,i);
|
| - if (c->algorithms & SSL_eNULL)
|
| + if (c->algorithm_enc & SSL_eNULL)
|
| nc=c;
|
| if (SSL_C_IS_EXPORT(c))
|
| ec=c;
|
| @@ -1159,6 +1313,9 @@
|
| #endif
|
| s->s3->tmp.new_cipher=s->session->cipher;
|
| }
|
| +
|
| + if (!ssl3_digest_cached_records(s))
|
| + goto f_err;
|
|
|
| /* we now have the following setup.
|
| * client_random
|
| @@ -1187,24 +1344,22 @@
|
| unsigned char *buf;
|
| unsigned char *p,*d;
|
| int i,sl;
|
| - unsigned long l,Time;
|
| + unsigned long l;
|
| +#ifdef OPENSSL_NO_TLSEXT
|
| + unsigned long Time;
|
| +#endif
|
|
|
| if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
|
| {
|
| buf=(unsigned char *)s->init_buf->data;
|
| - if (!s->s3->snap_start_requested)
|
| - {
|
| - p=s->s3->server_random;
|
| - Time=(unsigned long)time(NULL); /* Time */
|
| - l2n(Time,p);
|
| - if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
| - return -1;
|
| - }
|
| - else if (s->s3->server_random_suggestion_valid == 0)
|
| - {
|
| - return SERVER_RANDOM_VALIDATION_PENDING;
|
| - }
|
| -
|
| +#ifdef OPENSSL_NO_TLSEXT
|
| + p=s->s3->server_random;
|
| + /* Generate server_random if it was not needed previously */
|
| + Time=(unsigned long)time(NULL); /* Time */
|
| + l2n(Time,p);
|
| + if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
|
| + return -1;
|
| +#endif
|
| /* Do the message type and length last */
|
| d=p= &(buf[4]);
|
|
|
| @@ -1258,6 +1413,11 @@
|
| *(p++)=s->s3->tmp.new_compression->id;
|
| #endif
|
| #ifndef OPENSSL_NO_TLSEXT
|
| + if (ssl_prepare_serverhello_tlsext(s) <= 0)
|
| + {
|
| + SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
|
| + return -1;
|
| + }
|
| if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
|
| {
|
| SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
|
| @@ -1337,7 +1497,7 @@
|
| EVP_MD_CTX_init(&md_ctx);
|
| if (s->state == SSL3_ST_SW_KEY_EXCH_A)
|
| {
|
| - type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK;
|
| + type=s->s3->tmp.new_cipher->algorithm_mkey;
|
| cert=s->cert;
|
|
|
| buf=s->init_buf;
|
| @@ -1391,7 +1551,6 @@
|
|
|
| if (s->s3->tmp.dh != NULL)
|
| {
|
| - DH_free(dh);
|
| SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
| goto err;
|
| }
|
| @@ -1432,7 +1591,7 @@
|
| else
|
| #endif
|
| #ifndef OPENSSL_NO_ECDH
|
| - if (type & SSL_kECDHE)
|
| + if (type & SSL_kEECDH)
|
| {
|
| const EC_GROUP *group;
|
|
|
| @@ -1452,7 +1611,6 @@
|
|
|
| if (s->s3->tmp.ecdh != NULL)
|
| {
|
| - EC_KEY_free(s->s3->tmp.ecdh);
|
| SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
| goto err;
|
| }
|
| @@ -1463,12 +1621,11 @@
|
| SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
|
| goto err;
|
| }
|
| - if (!EC_KEY_up_ref(ecdhp))
|
| + if ((ecdh = EC_KEY_dup(ecdhp)) == NULL)
|
| {
|
| SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
|
| goto err;
|
| }
|
| - ecdh = ecdhp;
|
|
|
| s->s3->tmp.ecdh=ecdh;
|
| if ((EC_KEY_get0_public_key(ecdh) == NULL) ||
|
| @@ -1502,7 +1659,7 @@
|
| * supported named curves, curve_id is non-zero.
|
| */
|
| if ((curve_id =
|
| - nid2curve_id(EC_GROUP_get_curve_name(group)))
|
| + tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group)))
|
| == 0)
|
| {
|
| SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
|
| @@ -1559,6 +1716,14 @@
|
| }
|
| else
|
| #endif /* !OPENSSL_NO_ECDH */
|
| +#ifndef OPENSSL_NO_PSK
|
| + if (type & SSL_kPSK)
|
| + {
|
| + /* reserve size for record length and PSK identity hint*/
|
| + n+=2+strlen(s->ctx->psk_identity_hint);
|
| + }
|
| + else
|
| +#endif /* !OPENSSL_NO_PSK */
|
| {
|
| al=SSL_AD_HANDSHAKE_FAILURE;
|
| SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
|
| @@ -1570,7 +1735,8 @@
|
| n+=2+nr[i];
|
| }
|
|
|
| - if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
|
| + if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
|
| + && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
|
| {
|
| if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
|
| == NULL)
|
| @@ -1602,7 +1768,7 @@
|
| }
|
|
|
| #ifndef OPENSSL_NO_ECDH
|
| - if (type & SSL_kECDHE)
|
| + if (type & SSL_kEECDH)
|
| {
|
| /* XXX: For now, we only support named (not generic) curves.
|
| * In this situation, the serverKeyExchange message has:
|
| @@ -1622,10 +1788,21 @@
|
| (unsigned char *)encodedPoint,
|
| encodedlen);
|
| OPENSSL_free(encodedPoint);
|
| + encodedPoint = NULL;
|
| p += encodedlen;
|
| }
|
| #endif
|
|
|
| +#ifndef OPENSSL_NO_PSK
|
| + if (type & SSL_kPSK)
|
| + {
|
| + /* copy PSK identity hint */
|
| + s2n(strlen(s->ctx->psk_identity_hint), p);
|
| + strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
|
| + p+=strlen(s->ctx->psk_identity_hint);
|
| + }
|
| +#endif
|
| +
|
| /* not anonymous */
|
| if (pkey != NULL)
|
| {
|
| @@ -1638,8 +1815,6 @@
|
| j=0;
|
| for (num=2; num > 0; num--)
|
| {
|
| - EVP_MD_CTX_set_flags(&md_ctx,
|
| - EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
| EVP_DigestInit_ex(&md_ctx,(num == 2)
|
| ?s->ctx->md5:s->ctx->sha1, NULL);
|
| EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
|
| @@ -1823,7 +1998,7 @@
|
| {
|
| int i,al,ok;
|
| long n;
|
| - unsigned long l;
|
| + unsigned long alg_k;
|
| unsigned char *p;
|
| #ifndef OPENSSL_NO_RSA
|
| RSA *rsa=NULL;
|
| @@ -1834,7 +2009,7 @@
|
| DH *dh_srvr;
|
| #endif
|
| #ifndef OPENSSL_NO_KRB5
|
| - KSSL_ERR kssl_err;
|
| + KSSL_ERR kssl_err;
|
| #endif /* OPENSSL_NO_KRB5 */
|
|
|
| #ifndef OPENSSL_NO_ECDH
|
| @@ -1854,10 +2029,10 @@
|
| if (!ok) return((int)n);
|
| p=(unsigned char *)s->init_msg;
|
|
|
| - l=s->s3->tmp.new_cipher->algorithms;
|
| + alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
|
|
| #ifndef OPENSSL_NO_RSA
|
| - if (l & SSL_kRSA)
|
| + if (alg_k & SSL_kRSA)
|
| {
|
| /* FIX THIS UP EAY EAY EAY EAY */
|
| if (s->s3->tmp.use_rsa_tmp)
|
| @@ -1888,9 +2063,8 @@
|
| rsa=pkey->pkey.rsa;
|
| }
|
|
|
| - /* TLS and [incidentally] DTLS, including pre-0.9.8f */
|
| - if (s->version > SSL3_VERSION &&
|
| - s->client_version != DTLS1_BAD_VER)
|
| + /* TLS and [incidentally] DTLS{0xFEFF} */
|
| + if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER)
|
| {
|
| n2s(p,i);
|
| if (n != i+2)
|
| @@ -1964,7 +2138,7 @@
|
| else
|
| #endif
|
| #ifndef OPENSSL_NO_DH
|
| - if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
|
| + if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
|
| {
|
| n2s(p,i);
|
| if (n != i+2)
|
| @@ -2011,6 +2185,7 @@
|
| if (i <= 0)
|
| {
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
|
| + BN_clear_free(pub);
|
| goto err;
|
| }
|
|
|
| @@ -2027,30 +2202,30 @@
|
| else
|
| #endif
|
| #ifndef OPENSSL_NO_KRB5
|
| - if (l & SSL_kKRB5)
|
| - {
|
| - krb5_error_code krb5rc;
|
| + if (alg_k & SSL_kKRB5)
|
| + {
|
| + krb5_error_code krb5rc;
|
| krb5_data enc_ticket;
|
| krb5_data authenticator;
|
| krb5_data enc_pms;
|
| - KSSL_CTX *kssl_ctx = s->kssl_ctx;
|
| + KSSL_CTX *kssl_ctx = s->kssl_ctx;
|
| EVP_CIPHER_CTX ciph_ctx;
|
| - EVP_CIPHER *enc = NULL;
|
| + const EVP_CIPHER *enc = NULL;
|
| unsigned char iv[EVP_MAX_IV_LENGTH];
|
| unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH
|
| - + EVP_MAX_BLOCK_LENGTH];
|
| - int padl, outl;
|
| + + EVP_MAX_BLOCK_LENGTH];
|
| + int padl, outl;
|
| krb5_timestamp authtime = 0;
|
| krb5_ticket_times ttimes;
|
|
|
| EVP_CIPHER_CTX_init(&ciph_ctx);
|
|
|
| - if (!kssl_ctx) kssl_ctx = kssl_ctx_new();
|
| + if (!kssl_ctx) kssl_ctx = kssl_ctx_new();
|
|
|
| n2s(p,i);
|
| enc_ticket.length = i;
|
|
|
| - if (n < (int)enc_ticket.length + 6)
|
| + if (n < (long)(enc_ticket.length + 6))
|
| {
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| SSL_R_DATA_LENGTH_TOO_LONG);
|
| @@ -2063,7 +2238,7 @@
|
| n2s(p,i);
|
| authenticator.length = i;
|
|
|
| - if (n < (int)(enc_ticket.length + authenticator.length) + 6)
|
| + if (n < (long)(enc_ticket.length + authenticator.length + 6))
|
| {
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| SSL_R_DATA_LENGTH_TOO_LONG);
|
| @@ -2096,19 +2271,19 @@
|
| goto err;
|
| }
|
|
|
| - if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes,
|
| + if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes,
|
| &kssl_err)) != 0)
|
| - {
|
| + {
|
| #ifdef KSSL_DEBUG
|
| - printf("kssl_sget_tkt rtn %d [%d]\n",
|
| - krb5rc, kssl_err.reason);
|
| - if (kssl_err.text)
|
| - printf("kssl_err text= %s\n", kssl_err.text);
|
| + printf("kssl_sget_tkt rtn %d [%d]\n",
|
| + krb5rc, kssl_err.reason);
|
| + if (kssl_err.text)
|
| + printf("kssl_err text= %s\n", kssl_err.text);
|
| #endif /* KSSL_DEBUG */
|
| - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| - kssl_err.reason);
|
| - goto err;
|
| - }
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + kssl_err.reason);
|
| + goto err;
|
| + }
|
|
|
| /* Note: no authenticator is not considered an error,
|
| ** but will return authtime == 0.
|
| @@ -2117,29 +2292,29 @@
|
| &authtime, &kssl_err)) != 0)
|
| {
|
| #ifdef KSSL_DEBUG
|
| - printf("kssl_check_authent rtn %d [%d]\n",
|
| - krb5rc, kssl_err.reason);
|
| - if (kssl_err.text)
|
| - printf("kssl_err text= %s\n", kssl_err.text);
|
| + printf("kssl_check_authent rtn %d [%d]\n",
|
| + krb5rc, kssl_err.reason);
|
| + if (kssl_err.text)
|
| + printf("kssl_err text= %s\n", kssl_err.text);
|
| #endif /* KSSL_DEBUG */
|
| - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| - kssl_err.reason);
|
| - goto err;
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + kssl_err.reason);
|
| + goto err;
|
| }
|
|
|
| if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0)
|
| {
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc);
|
| - goto err;
|
| + goto err;
|
| }
|
|
|
| #ifdef KSSL_DEBUG
|
| - kssl_ctx_show(kssl_ctx);
|
| + kssl_ctx_show(kssl_ctx);
|
| #endif /* KSSL_DEBUG */
|
|
|
| enc = kssl_map_enc(kssl_ctx->enctype);
|
| - if (enc == NULL)
|
| - goto err;
|
| + if (enc == NULL)
|
| + goto err;
|
|
|
| memset(iv, 0, sizeof iv); /* per RFC 1510 */
|
|
|
| @@ -2186,7 +2361,7 @@
|
| * (Perhaps we should have a separate BUG value for the Kerberos cipher)
|
| */
|
| if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG))
|
| - {
|
| + {
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| SSL_AD_DECODE_ERROR);
|
| goto err;
|
| @@ -2195,32 +2370,32 @@
|
|
|
| EVP_CIPHER_CTX_cleanup(&ciph_ctx);
|
|
|
| - s->session->master_key_length=
|
| - s->method->ssl3_enc->generate_master_secret(s,
|
| - s->session->master_key, pms, outl);
|
| + s->session->master_key_length=
|
| + s->method->ssl3_enc->generate_master_secret(s,
|
| + s->session->master_key, pms, outl);
|
|
|
| - if (kssl_ctx->client_princ)
|
| - {
|
| - size_t len = strlen(kssl_ctx->client_princ);
|
| - if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH )
|
| - {
|
| - s->session->krb5_client_princ_len = len;
|
| - memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len);
|
| - }
|
| - }
|
| + if (kssl_ctx->client_princ)
|
| + {
|
| + size_t len = strlen(kssl_ctx->client_princ);
|
| + if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH )
|
| + {
|
| + s->session->krb5_client_princ_len = len;
|
| + memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len);
|
| + }
|
| + }
|
|
|
|
|
| - /* Was doing kssl_ctx_free() here,
|
| + /* Was doing kssl_ctx_free() here,
|
| ** but it caused problems for apache.
|
| - ** kssl_ctx = kssl_ctx_free(kssl_ctx);
|
| - ** if (s->kssl_ctx) s->kssl_ctx = NULL;
|
| - */
|
| - }
|
| + ** kssl_ctx = kssl_ctx_free(kssl_ctx);
|
| + ** if (s->kssl_ctx) s->kssl_ctx = NULL;
|
| + */
|
| + }
|
| else
|
| #endif /* OPENSSL_NO_KRB5 */
|
|
|
| #ifndef OPENSSL_NO_ECDH
|
| - if ((l & SSL_kECDH) || (l & SSL_kECDHE))
|
| + if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
|
| {
|
| int ret = 1;
|
| int field_size = 0;
|
| @@ -2228,18 +2403,18 @@
|
| const EC_GROUP *group;
|
| const BIGNUM *priv_key;
|
|
|
| - /* initialize structures for server's ECDH key pair */
|
| + /* initialize structures for server's ECDH key pair */
|
| if ((srvr_ecdh = EC_KEY_new()) == NULL)
|
| {
|
| - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| ERR_R_MALLOC_FAILURE);
|
| - goto err;
|
| + goto err;
|
| }
|
|
|
| /* Let's get server private key and group information */
|
| - if (l & SSL_kECDH)
|
| + if (alg_k & (SSL_kECDHr|SSL_kECDHe))
|
| {
|
| - /* use the certificate */
|
| + /* use the certificate */
|
| tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec;
|
| }
|
| else
|
| @@ -2269,20 +2444,20 @@
|
| goto err;
|
| }
|
|
|
| - if (n == 0L)
|
| - {
|
| + if (n == 0L)
|
| + {
|
| /* Client Publickey was in Client Certificate */
|
|
|
| - if (l & SSL_kECDHE)
|
| + if (alg_k & SSL_kEECDH)
|
| {
|
| al=SSL_AD_HANDSHAKE_FAILURE;
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
|
| goto f_err;
|
| }
|
| - if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer))
|
| + if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer))
|
| == NULL) ||
|
| (clnt_pub_pkey->type != EVP_PKEY_EC))
|
| - {
|
| + {
|
| /* XXX: For now, we do not support client
|
| * authentication using ECDH certificates
|
| * so this branch (n == 0L) of the code is
|
| @@ -2294,11 +2469,11 @@
|
| * the two ECDH shares are for the same
|
| * group.
|
| */
|
| - al=SSL_AD_HANDSHAKE_FAILURE;
|
| - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + al=SSL_AD_HANDSHAKE_FAILURE;
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| SSL_R_UNABLE_TO_DECODE_ECDH_CERTS);
|
| - goto f_err;
|
| - }
|
| + goto f_err;
|
| + }
|
|
|
| if (EC_POINT_copy(clnt_ecpoint,
|
| EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0)
|
| @@ -2307,10 +2482,10 @@
|
| ERR_R_EC_LIB);
|
| goto err;
|
| }
|
| - ret = 2; /* Skip certificate verify processing */
|
| - }
|
| - else
|
| - {
|
| + ret = 2; /* Skip certificate verify processing */
|
| + }
|
| + else
|
| + {
|
| /* Get client's public key from encoded point
|
| * in the ClientKeyExchange message.
|
| */
|
| @@ -2321,21 +2496,27 @@
|
| goto err;
|
| }
|
|
|
| - /* Get encoded point length */
|
| - i = *p;
|
| + /* Get encoded point length */
|
| + i = *p;
|
| p += 1;
|
| - if (EC_POINT_oct2point(group,
|
| + if (n != 1 + i)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + ERR_R_EC_LIB);
|
| + goto err;
|
| + }
|
| + if (EC_POINT_oct2point(group,
|
| clnt_ecpoint, p, i, bn_ctx) == 0)
|
| {
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| ERR_R_EC_LIB);
|
| goto err;
|
| }
|
| - /* p is pointing to somewhere in the buffer
|
| - * currently, so set it to the start
|
| - */
|
| - p=(unsigned char *)s->init_buf->data;
|
| - }
|
| + /* p is pointing to somewhere in the buffer
|
| + * currently, so set it to the start
|
| + */
|
| + p=(unsigned char *)s->init_buf->data;
|
| + }
|
|
|
| /* Compute the shared pre-master secret */
|
| field_size = EC_GROUP_get_degree(group);
|
| @@ -2346,28 +2527,197 @@
|
| goto err;
|
| }
|
| i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL);
|
| - if (i <= 0)
|
| - {
|
| - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + if (i <= 0)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| ERR_R_ECDH_LIB);
|
| - goto err;
|
| - }
|
| + goto err;
|
| + }
|
|
|
| EVP_PKEY_free(clnt_pub_pkey);
|
| EC_POINT_free(clnt_ecpoint);
|
| - if (srvr_ecdh != NULL)
|
| - EC_KEY_free(srvr_ecdh);
|
| + EC_KEY_free(srvr_ecdh);
|
| BN_CTX_free(bn_ctx);
|
| + EC_KEY_free(s->s3->tmp.ecdh);
|
| + s->s3->tmp.ecdh = NULL;
|
|
|
| /* Compute the master secret */
|
| - s->session->master_key_length = s->method->ssl3_enc-> \
|
| + s->session->master_key_length = s->method->ssl3_enc-> \
|
| generate_master_secret(s, s->session->master_key, p, i);
|
|
|
| - OPENSSL_cleanse(p, i);
|
| - return (ret);
|
| + OPENSSL_cleanse(p, i);
|
| + return (ret);
|
| }
|
| else
|
| #endif
|
| +#ifndef OPENSSL_NO_PSK
|
| + if (alg_k & SSL_kPSK)
|
| + {
|
| + unsigned char *t = NULL;
|
| + unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
|
| + unsigned int pre_ms_len = 0, psk_len = 0;
|
| + int psk_err = 1;
|
| + char tmp_id[PSK_MAX_IDENTITY_LEN+1];
|
| +
|
| + al=SSL_AD_HANDSHAKE_FAILURE;
|
| +
|
| + n2s(p,i);
|
| + if (n != i+2)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + SSL_R_LENGTH_MISMATCH);
|
| + goto psk_err;
|
| + }
|
| + if (i > PSK_MAX_IDENTITY_LEN)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + SSL_R_DATA_LENGTH_TOO_LONG);
|
| + goto psk_err;
|
| + }
|
| + if (s->psk_server_callback == NULL)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + SSL_R_PSK_NO_SERVER_CB);
|
| + goto psk_err;
|
| + }
|
| +
|
| + /* Create guaranteed NULL-terminated identity
|
| + * string for the callback */
|
| + memcpy(tmp_id, p, i);
|
| + memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
|
| + psk_len = s->psk_server_callback(s, tmp_id,
|
| + psk_or_pre_ms, sizeof(psk_or_pre_ms));
|
| + OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
|
| +
|
| + if (psk_len > PSK_MAX_PSK_LEN)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + ERR_R_INTERNAL_ERROR);
|
| + goto psk_err;
|
| + }
|
| + else if (psk_len == 0)
|
| + {
|
| + /* PSK related to the given identity not found */
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + SSL_R_PSK_IDENTITY_NOT_FOUND);
|
| + al=SSL_AD_UNKNOWN_PSK_IDENTITY;
|
| + goto psk_err;
|
| + }
|
| +
|
| + /* create PSK pre_master_secret */
|
| + pre_ms_len=2+psk_len+2+psk_len;
|
| + t = psk_or_pre_ms;
|
| + memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
|
| + s2n(psk_len, t);
|
| + memset(t, 0, psk_len);
|
| + t+=psk_len;
|
| + s2n(psk_len, t);
|
| +
|
| + if (s->session->psk_identity != NULL)
|
| + OPENSSL_free(s->session->psk_identity);
|
| + s->session->psk_identity = BUF_strdup((char *)p);
|
| + if (s->session->psk_identity == NULL)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + ERR_R_MALLOC_FAILURE);
|
| + goto psk_err;
|
| + }
|
| +
|
| + if (s->session->psk_identity_hint != NULL)
|
| + OPENSSL_free(s->session->psk_identity_hint);
|
| + s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
|
| + if (s->ctx->psk_identity_hint != NULL &&
|
| + s->session->psk_identity_hint == NULL)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| + ERR_R_MALLOC_FAILURE);
|
| + goto psk_err;
|
| + }
|
| +
|
| + s->session->master_key_length=
|
| + s->method->ssl3_enc->generate_master_secret(s,
|
| + s->session->master_key, psk_or_pre_ms, pre_ms_len);
|
| + psk_err = 0;
|
| + psk_err:
|
| + OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
|
| + if (psk_err != 0)
|
| + goto f_err;
|
| + }
|
| + else
|
| +#endif
|
| + if (alg_k & SSL_kGOST)
|
| + {
|
| + int ret = 0;
|
| + EVP_PKEY_CTX *pkey_ctx;
|
| + EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
|
| + unsigned char premaster_secret[32], *start;
|
| + size_t outlen=32, inlen;
|
| + unsigned long alg_a;
|
| +
|
| + /* Get our certificate private key*/
|
| + alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
| + if (alg_a & SSL_aGOST94)
|
| + pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey;
|
| + else if (alg_a & SSL_aGOST01)
|
| + pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
|
| +
|
| + pkey_ctx = EVP_PKEY_CTX_new(pk,NULL);
|
| + EVP_PKEY_decrypt_init(pkey_ctx);
|
| + /* If client certificate is present and is of the same type, maybe
|
| + * use it for key exchange. Don't mind errors from
|
| + * EVP_PKEY_derive_set_peer, because it is completely valid to use
|
| + * a client certificate for authorization only. */
|
| + client_pub_pkey = X509_get_pubkey(s->session->peer);
|
| + if (client_pub_pkey)
|
| + {
|
| + if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
|
| + ERR_clear_error();
|
| + }
|
| + /* Decrypt session key */
|
| + if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED)))
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
|
| + goto gerr;
|
| + }
|
| + if (p[1] == 0x81)
|
| + {
|
| + start = p+3;
|
| + inlen = p[2];
|
| + }
|
| + else if (p[1] < 0x80)
|
| + {
|
| + start = p+2;
|
| + inlen = p[1];
|
| + }
|
| + else
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
|
| + goto gerr;
|
| + }
|
| + if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0)
|
| +
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
|
| + goto gerr;
|
| + }
|
| + /* Generate master secret */
|
| + s->session->master_key_length=
|
| + s->method->ssl3_enc->generate_master_secret(s,
|
| + s->session->master_key,premaster_secret,32);
|
| + /* Check if pubkey from client certificate was used */
|
| + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
|
| + ret = 2;
|
| + else
|
| + ret = 1;
|
| + gerr:
|
| + EVP_PKEY_free(client_pub_pkey);
|
| + EVP_PKEY_CTX_free(pkey_ctx);
|
| + if (ret)
|
| + return ret;
|
| + else
|
| + goto err;
|
| + }
|
| + else
|
| {
|
| al=SSL_AD_HANDSHAKE_FAILURE;
|
| SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
| @@ -2391,70 +2741,6 @@
|
| return(-1);
|
| }
|
|
|
| -/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
|
| - * sets the next_proto member in s if found */
|
| -int ssl3_get_next_proto(SSL *s)
|
| - {
|
| - int ok;
|
| - unsigned proto_len, padding_len;
|
| - long n;
|
| - const unsigned char *p;
|
| -
|
| - /* Clients cannot send a NextProtocol message if we didn't see the
|
| - * extension in their ClientHello */
|
| - if (!s->s3->next_proto_neg_seen) {
|
| - SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
|
| - return -1;
|
| - }
|
| -
|
| - n=s->method->ssl_get_message(s,
|
| - SSL3_ST_SR_NEXT_PROTO_A,
|
| - SSL3_ST_SR_NEXT_PROTO_B,
|
| - SSL3_MT_NEXT_PROTO,
|
| - 129,
|
| - &ok);
|
| -
|
| - if (!ok)
|
| - return((int)n);
|
| -
|
| - /* s->state doesn't reflect whether ChangeCipherSpec has been received
|
| - * in this handshake, but s->s3->change_cipher_spec does (will be reset
|
| - * by ssl3_get_finished). */
|
| - if (!s->s3->change_cipher_spec)
|
| - {
|
| - SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS);
|
| - return -1;
|
| - }
|
| -
|
| - if (n < 2)
|
| - return 0; // The body must be > 1 bytes long */
|
| -
|
| - p=(unsigned char *)s->init_msg;
|
| -
|
| - /* The payload looks like:
|
| - * uint8 proto_len;
|
| - * uint8 proto[proto_len];
|
| - * uint8 padding_len;
|
| - * uint8 padding[padding_len];
|
| - */
|
| - proto_len = p[0];
|
| - if (proto_len + 2 > s->init_num)
|
| - return 0;
|
| - padding_len = p[proto_len + 1];
|
| - if (proto_len + padding_len + 2 != s->init_num)
|
| - return 0;
|
| -
|
| - s->next_proto_negotiated = OPENSSL_malloc(proto_len);
|
| - if (!s->next_proto_negotiated) {
|
| - SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE);
|
| - return 0;
|
| - }
|
| - memcpy(s->next_proto_negotiated, p + 1, proto_len);
|
| - s->next_proto_negotiated_len = proto_len;
|
| -
|
| - return 1;
|
| - }
|
| -
|
| int ssl3_get_cert_verify(SSL *s)
|
| {
|
| EVP_PKEY *pkey=NULL;
|
| @@ -2521,15 +2807,25 @@
|
|
|
| /* we now have a signature that we need to verify */
|
| p=(unsigned char *)s->init_msg;
|
| - n2s(p,i);
|
| - n-=2;
|
| - if (i > n)
|
| + /* Check for broken implementations of GOST ciphersuites */
|
| + /* If key is GOST and n is exactly 64, it is bare
|
| + * signature without length field */
|
| + if (n==64 && (pkey->type==NID_id_GostR3410_94 ||
|
| + pkey->type == NID_id_GostR3410_2001) )
|
| {
|
| - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
|
| - al=SSL_AD_DECODE_ERROR;
|
| - goto f_err;
|
| - }
|
| -
|
| + i=64;
|
| + }
|
| + else
|
| + {
|
| + n2s(p,i);
|
| + n-=2;
|
| + if (i > n)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
|
| + al=SSL_AD_DECODE_ERROR;
|
| + goto f_err;
|
| + }
|
| + }
|
| j=EVP_PKEY_size(pkey);
|
| if ((i > j) || (n > j) || (n <= 0))
|
| {
|
| @@ -2592,6 +2888,28 @@
|
| }
|
| else
|
| #endif
|
| + if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)
|
| + { unsigned char signature[64];
|
| + int idx;
|
| + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey,NULL);
|
| + EVP_PKEY_verify_init(pctx);
|
| + if (i!=64) {
|
| + fprintf(stderr,"GOST signature length is %d",i);
|
| + }
|
| + for (idx=0;idx<64;idx++) {
|
| + signature[63-idx]=p[idx];
|
| + }
|
| + j=EVP_PKEY_verify(pctx,signature,64,s->s3->tmp.cert_verify_md,32);
|
| + EVP_PKEY_CTX_free(pctx);
|
| + if (j<=0)
|
| + {
|
| + al=SSL_AD_DECRYPT_ERROR;
|
| + SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
|
| + SSL_R_BAD_ECDSA_SIGNATURE);
|
| + goto f_err;
|
| + }
|
| + }
|
| + else
|
| {
|
| SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
|
| al=SSL_AD_UNSUPPORTED_CERTIFICATE;
|
| @@ -2774,14 +3092,15 @@
|
| if (s->state == SSL3_ST_SW_CERT_A)
|
| {
|
| x=ssl_get_server_send_cert(s);
|
| - if (x == NULL &&
|
| - /* VRS: allow null cert if auth == KRB5 */
|
| - (s->s3->tmp.new_cipher->algorithms
|
| - & (SSL_MKEY_MASK|SSL_AUTH_MASK))
|
| - != (SSL_aKRB5|SSL_kKRB5))
|
| + if (x == NULL)
|
| {
|
| - SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
|
| - return(0);
|
| + /* VRS: allow null cert if auth == KRB5 */
|
| + if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) ||
|
| + (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5))
|
| + {
|
| + SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
|
| + return(0);
|
| + }
|
| }
|
|
|
| l=ssl3_output_cert_chain(s,x);
|
| @@ -2793,70 +3112,6 @@
|
| /* SSL3_ST_SW_CERT_B */
|
| return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
|
| }
|
| -
|
| -
|
| -#ifndef OPENSSL_NO_ECDH
|
| -/* This is the complement of curve_id2nid in s3_clnt.c. */
|
| -static int nid2curve_id(int nid)
|
| -{
|
| - /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001)
|
| - * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */
|
| - switch (nid) {
|
| - case NID_sect163k1: /* sect163k1 (1) */
|
| - return 1;
|
| - case NID_sect163r1: /* sect163r1 (2) */
|
| - return 2;
|
| - case NID_sect163r2: /* sect163r2 (3) */
|
| - return 3;
|
| - case NID_sect193r1: /* sect193r1 (4) */
|
| - return 4;
|
| - case NID_sect193r2: /* sect193r2 (5) */
|
| - return 5;
|
| - case NID_sect233k1: /* sect233k1 (6) */
|
| - return 6;
|
| - case NID_sect233r1: /* sect233r1 (7) */
|
| - return 7;
|
| - case NID_sect239k1: /* sect239k1 (8) */
|
| - return 8;
|
| - case NID_sect283k1: /* sect283k1 (9) */
|
| - return 9;
|
| - case NID_sect283r1: /* sect283r1 (10) */
|
| - return 10;
|
| - case NID_sect409k1: /* sect409k1 (11) */
|
| - return 11;
|
| - case NID_sect409r1: /* sect409r1 (12) */
|
| - return 12;
|
| - case NID_sect571k1: /* sect571k1 (13) */
|
| - return 13;
|
| - case NID_sect571r1: /* sect571r1 (14) */
|
| - return 14;
|
| - case NID_secp160k1: /* secp160k1 (15) */
|
| - return 15;
|
| - case NID_secp160r1: /* secp160r1 (16) */
|
| - return 16;
|
| - case NID_secp160r2: /* secp160r2 (17) */
|
| - return 17;
|
| - case NID_secp192k1: /* secp192k1 (18) */
|
| - return 18;
|
| - case NID_X9_62_prime192v1: /* secp192r1 (19) */
|
| - return 19;
|
| - case NID_secp224k1: /* secp224k1 (20) */
|
| - return 20;
|
| - case NID_secp224r1: /* secp224r1 (21) */
|
| - return 21;
|
| - case NID_secp256k1: /* secp256k1 (22) */
|
| - return 22;
|
| - case NID_X9_62_prime256v1: /* secp256r1 (23) */
|
| - return 23;
|
| - case NID_secp384r1: /* secp384r1 (24) */
|
| - return 24;
|
| - case NID_secp521r1: /* secp521r1 (25) */
|
| - return 25;
|
| - default:
|
| - return 0;
|
| - }
|
| -}
|
| -#endif
|
| #ifndef OPENSSL_NO_TLSEXT
|
| int ssl3_send_newsession_ticket(SSL *s)
|
| {
|
| @@ -2999,56 +3254,72 @@
|
| /* SSL3_ST_SW_CERT_STATUS_B */
|
| return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
|
| }
|
| -#endif
|
|
|
| -/* ssl3_snap_start_evaluate_handshake verifies the Snap Start prediction (if
|
| - * this is a Snap Start handshake). If it returns non-zero, then we are
|
| - * entering recovery and |s->state| has been set accordingly. */
|
| -static int ssl3_snap_start_evaluate_handshake(SSL* s)
|
| +# ifndef OPENSSL_NO_NPN
|
| +/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
|
| + * sets the next_proto member in s if found */
|
| +int ssl3_get_next_proto(SSL *s)
|
| {
|
| - unsigned char digest[8];
|
| + int ok;
|
| + unsigned proto_len, padding_len;
|
| + long n;
|
| + const unsigned char *p;
|
|
|
| - if (!s->s3->snap_start_requested)
|
| - return 0;
|
| -
|
| - /* Drop the currently queued messages. Either we're entering recovery,
|
| - * in which case they're wrong, or we're doing snap start, in which
|
| - * case we don't want to send them. */
|
| - if (!ssl_init_wbio_buffer(s, 1 /* push new BIO */))
|
| + /* Clients cannot send a NextProtocol message if we didn't see the
|
| + * extension in their ClientHello */
|
| + if (!s->s3->next_proto_neg_seen)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
|
| return -1;
|
| + }
|
|
|
| - fnv1a64_final(digest, (FNV1A64*) s->s3->response_hash);
|
| + n=s->method->ssl_get_message(s,
|
| + SSL3_ST_SR_NEXT_PROTO_A,
|
| + SSL3_ST_SR_NEXT_PROTO_B,
|
| + SSL3_MT_NEXT_PROTO,
|
| + 514, /* See the payload format below */
|
| + &ok);
|
|
|
| - /* Turn off FNV hashing of handshake messages. */
|
| - s->s3->snap_start_requested = 0;
|
| + if (!ok)
|
| + return((int)n);
|
|
|
| - if (memcmp(digest, s->s3->predicted_response_hash, sizeof(digest)) != 0)
|
| + /* s->state doesn't reflect whether ChangeCipherSpec has been received
|
| + * in this handshake, but s->s3->change_cipher_spec does (will be reset
|
| + * by ssl3_get_finished). */
|
| + if (!s->s3->change_cipher_spec)
|
| {
|
| - /* The predicted handshake didn't match. */
|
| - ssl3_snap_start_reset_for_recovery(s);
|
| - s->state = SSL3_ST_SW_SRVR_HELLO_A;
|
| - return 1;
|
| + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS);
|
| + return -1;
|
| }
|
|
|
| - return 0;
|
| - }
|
| + if (n < 2)
|
| + return 0; /* The body must be > 1 bytes long */
|
|
|
| -/* ssl3_snap_start_reset_for_recovery is called is called when a Snap Start
|
| - * handshake is impossible because either the application layer has rejected
|
| - * the client's suggested server random, or predicated_response_hash failed to
|
| - * match response_hash */
|
| -int ssl3_snap_start_reset_for_recovery(SSL* s)
|
| - {
|
| - s->s3->snap_start_requested = 0;
|
| - s->s3->snap_start_records.left = 0;
|
| - s->init_num = 0;
|
| + p=(unsigned char *)s->init_msg;
|
|
|
| - /* Reset the handshake hash and hash in the original ClientHello. */
|
| - ssl3_init_finished_mac(s);
|
| - ssl3_finish_mac(s, s->s3->snap_start_client_hello.buf, s->s3->snap_start_client_hello.left);
|
| + /* The payload looks like:
|
| + * uint8 proto_len;
|
| + * uint8 proto[proto_len];
|
| + * uint8 padding_len;
|
| + * uint8 padding[padding_len];
|
| + */
|
| + proto_len = p[0];
|
| + if (proto_len + 2 > s->init_num)
|
| + return 0;
|
| + padding_len = p[proto_len + 1];
|
| + if (proto_len + padding_len + 2 != s->init_num)
|
| + return 0;
|
|
|
| - OPENSSL_free(s->s3->snap_start_client_hello.buf);
|
| - s->s3->snap_start_client_hello.buf = NULL;
|
| + s->next_proto_negotiated = OPENSSL_malloc(proto_len);
|
| + if (!s->next_proto_negotiated)
|
| + {
|
| + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE);
|
| + return 0;
|
| + }
|
| + memcpy(s->next_proto_negotiated, p + 1, proto_len);
|
| + s->next_proto_negotiated_len = proto_len;
|
|
|
| - return 0;
|
| + return 1;
|
| }
|
| +# endif
|
| +#endif
|
|
|