Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: openssl/ssl/s3_srvr.c

Issue 9254031: Upgrade chrome's OpenSSL to same version Android ships with. (Closed) Base URL: http://src.chromium.org/svn/trunk/deps/third_party/openssl/
Patch Set: '' Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « openssl/ssl/s3_pkt.c ('k') | openssl/ssl/ssl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « openssl/ssl/s3_pkt.c ('k') | openssl/ssl/ssl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698