return(NULL);
}
+#ifndef OPENSSL_NO_SRP
+static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
+ {
+ int ret = SSL_ERROR_NONE;
+
+ *al = SSL_AD_UNRECOGNIZED_NAME;
+
+ if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
+ (s->srp_ctx.TLS_ext_srp_username_callback != NULL))
+ {
+ if(s->srp_ctx.login == NULL)
+ {
+ /* RFC 5054 says SHOULD reject,
+ we do so if There is no srp login name */
+ ret = SSL3_AL_FATAL;
+ *al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+ }
+ else
+ {
+ ret = SSL_srp_server_param_with_username(s,al);
+ }
+ }
+ return ret;
+ }
+#endif
+
IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
ssl3_accept,
ssl_undefined_function,
BUF_MEM *buf;
unsigned long alg_k,Time=(unsigned long)time(NULL);
void (*cb)(const SSL *ssl,int type,int val)=NULL;
- long num1;
int ret= -1;
int new_state,state,skip=0;
return(-1);
}
+#ifndef OPENSSL_NO_HEARTBEATS
+ /* If we're awaiting a HeartbeatResponse, pretend we
+ * already got and don't await it anymore, because
+ * Heartbeats don't make sense during handshakes anyway.
+ */
+ if (s->tlsext_hb_pending)
+ {
+ s->tlsext_hb_pending = 0;
+ s->tlsext_hb_seq++;
+ }
+#endif
+
for (;;)
{
state=s->state;
switch (s->state)
{
case SSL_ST_RENEGOTIATE:
- s->new_session=1;
+ s->renegotiate=1;
/* s->state=SSL_ST_ACCEPT; */
case SSL_ST_BEFORE:
}
s->init_num=0;
+ s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
+ s->s3->flags &= ~TLS1_FLAGS_SKIP_CERT_VERIFY;
if (s->state != SSL_ST_RENEGOTIATE)
{
s->state=SSL3_ST_SR_CLNT_HELLO_A;
s->ctx->stats.sess_accept++;
}
+ else if (!s->s3->send_connection_binding &&
+ !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+ {
+ /* Server attempting to renegotiate with
+ * client that doesn't support secure
+ * renegotiation.
+ */
+ SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+ ret = -1;
+ goto end;
+ }
else
{
/* s->state == SSL_ST_RENEGOTIATE,
case SSL3_ST_SR_CLNT_HELLO_B:
case SSL3_ST_SR_CLNT_HELLO_C:
- s->shutdown=0;
ret=ssl3_get_client_hello(s);
if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_SRP
+ s->state = SSL3_ST_SR_CLNT_HELLO_D;
+ case SSL3_ST_SR_CLNT_HELLO_D:
+ {
+ int al;
+ if ((ret = ssl_check_srp_ext_ClientHello(s,&al)) < 0)
+ {
+ /* callback indicates firther work to be done */
+ s->rwstate=SSL_X509_LOOKUP;
+ goto end;
+ }
+ if (ret != SSL_ERROR_NONE)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ /* This is not really an error but the only means to
+ for a client to detect whether srp is supported. */
+ if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)
+ SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLSEXT);
+ ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+ ret= -1;
+ goto end;
+ }
+ }
+#endif
- s->new_session = 2;
+ s->renegotiate = 2;
s->state=SSL3_ST_SW_SRVR_HELLO_A;
s->init_num=0;
break;
s->state=SSL3_ST_SW_CHANGE_A;
#endif
else
- s->state=SSL3_ST_SW_CERT_A;
- s->init_num=0;
+#ifndef OPENSSL_NO_TLSEXT
+ s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_A;
+#else
+ s->state = SSL3_ST_SW_CERT_A;
+#endif
+ s->init_num = 0;
+ break;
+
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL3_ST_SW_SUPPLEMENTAL_DATA_A:
+ case SSL3_ST_SW_SUPPLEMENTAL_DATA_B:
+ ret = tls1_send_server_supplemental_data(s, &skip);
+ if (ret <= 0) goto end;
+
+ s->state = SSL3_ST_SW_CERT_A;
+ s->init_num = 0;
break;
+#endif
case SSL3_ST_SW_CERT_A:
case SSL3_ST_SW_CERT_B:
/* Check if it is anon DH or anon ECDH, */
- /* normal PSK or KRB5 */
+ /* normal PSK or KRB5 or SRP */
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))
#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)
+#ifndef OPENSSL_NO_SRP
+ /* SRP: send ServerKeyExchange */
+ || (alg_k & SSL_kSRP)
+#endif
+ || (alg_k & SSL_kDHE)
+ || (alg_k & SSL_kECDHE)
|| ((alg_k & SSL_kRSA)
&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
|| (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
skip=1;
s->s3->tmp.cert_request=0;
s->state=SSL3_ST_SW_SRVR_DONE_A;
+ if (s->s3->handshake_buffer)
+ if (!ssl3_digest_cached_records(s))
+ return -1;
}
else
{
break;
case SSL3_ST_SW_FLUSH:
- /* number of bytes to be flushed */
- num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
- if (num1 > 0)
+
+ /* This code originally checked to see if
+ * any data was pending using BIO_CTRL_INFO
+ * and then flushed. This caused problems
+ * as documented in PR#1939. The proposed
+ * fix doesn't completely resolve this issue
+ * as buggy implementations of BIO_CTRL_PENDING
+ * still exist. So instead we just flush
+ * unconditionally.
+ */
+
+ s->rwstate=SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0)
{
- s->rwstate=SSL_WRITING;
- num1=BIO_flush(s->wbio);
- if (num1 <= 0) { ret= -1; goto end; }
- s->rwstate=SSL_NOTHING;
+ ret= -1;
+ goto end;
}
+ s->rwstate=SSL_NOTHING;
s->state=s->s3->tmp.next_state;
break;
-
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL3_ST_SR_SUPPLEMENTAL_DATA_A:
+ case SSL3_ST_SR_SUPPLEMENTAL_DATA_B:
+ ret=tls1_get_client_supplemental_data(s);
+ if (ret <= 0) goto end;
+ s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
+ s->state=SSL3_ST_SW_FLUSH;
+ s->init_num=0;
+ break;
+#endif
case SSL3_ST_SR_CERT_A:
case SSL3_ST_SR_CERT_B:
/* Check for second client hello (MS SGC) */
goto end;
if (ret == 2)
s->state = SSL3_ST_SR_CLNT_HELLO_C;
+#ifndef OPENSSL_NO_TLSEXT
+ else if (ret == 3)
+ s->state = SSL3_ST_SR_SUPPLEMENTAL_DATA_A;
+#endif
else {
if (s->s3->tmp.cert_request)
{
* 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 if (SSL_USE_SIGALGS(s))
+ {
+ s->state=SSL3_ST_SR_CERT_VRFY_A;
+ s->init_num=0;
+ if (!s->session->peer)
+ break;
+ /* For sigalgs freeze the handshake buffer
+ * at this point and digest cached records.
+ */
+ if (!s->s3->handshake_buffer)
+ {
+ SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
+ if (!ssl3_digest_cached_records(s))
+ return -1;
+ }
else
{
int offset=0;
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);
+ if (ret <= 0) goto end;
+ 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;
if (ret <= 0) goto end;
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;
s->init_num=0;
s->init_num=0;
- if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
+ if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
{
- /* actually not necessarily a 'new' session unless
- * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
-
+ s->renegotiate=0;
s->new_session=0;
ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
int ssl3_send_hello_request(SSL *s)
{
- unsigned char *p;
if (s->state == SSL3_ST_SW_HELLO_REQ_A)
{
- p=(unsigned char *)s->init_buf->data;
- *(p++)=SSL3_MT_HELLO_REQUEST;
- *(p++)=0;
- *(p++)=0;
- *(p++)=0;
-
+ ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0);
s->state=SSL3_ST_SW_HELLO_REQ_B;
- /* number of bytes to write */
- s->init_num=4;
- s->init_off=0;
}
/* SSL3_ST_SW_HELLO_REQ_B */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
}
int ssl3_check_client_hello(SSL *s)
&ok);
if (!ok) return((int)n);
s->s3->tmp.reuse_message = 1;
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->s3->tmp.message_type == SSL3_MT_SUPPLEMENTAL_DATA)
+ return 3;
+#endif
if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO)
{
+ /* 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;
+ }
/* 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)
{
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;
int ssl3_get_client_hello(SSL *s)
{
- int i,j,ok,al,ret= -1;
+ int i,j,ok,al=SSL_AD_INTERNAL_ERROR,ret= -1;
unsigned int cookie_len;
long n;
unsigned long id;
- unsigned char *p,*d,*q;
+ unsigned char *p,*d;
SSL_CIPHER *c;
#ifndef OPENSSL_NO_COMP
+ unsigned char *q;
SSL_COMP *comp=NULL;
#endif
STACK_OF(SSL_CIPHER) *ciphers=NULL;
+ if (s->state == SSL3_ST_SR_CLNT_HELLO_C)
+ goto retry_cert;
+
/* We do this so that we will respond with our native type.
* If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
* This down switching should be handled by a different method.
* If we are SSLv3, we will respond with SSLv3, even if prompted with
* TLSv1.
*/
- if (s->state == SSL3_ST_SR_CLNT_HELLO_A)
+ if (s->state == SSL3_ST_SR_CLNT_HELLO_A
+ )
{
s->state=SSL3_ST_SR_CLNT_HELLO_B;
}
s->client_version=(((int)p[0])<<8)|(int)p[1];
p+=2;
- if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
- (s->version != DTLS1_VERSION && s->client_version < s->version))
+ if (SSL_IS_DTLS(s) ? (s->client_version > s->version &&
+ s->method->version != DTLS_ANY_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 &&
+ !s->enc_write_ctx && !s->write_hash)
{
/* similar to ssl3_get_record, send alert using remote version number */
s->version = s->client_version;
goto f_err;
}
+ /* If we require cookies and this ClientHello doesn't
+ * contain one, just return since we do not want to
+ * allocate any memory yet. So check cookie length...
+ */
+ if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
+ {
+ unsigned int session_length, cookie_length;
+
+ session_length = *(p + SSL3_RANDOM_SIZE);
+ cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
+
+ if (cookie_length == 0)
+ return 1;
+ }
+
/* load the client random */
memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE);
p+=SSL3_RANDOM_SIZE;
j= *(p++);
s->hit=0;
- /* Versions before 0.9.7 always allow session reuse during renegotiation
- * (i.e. when s->new_session is true), option
- * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7.
- * Maybe this optional behaviour should always have been the default,
- * but we cannot safely change the default behaviour (or new applications
- * might be written that become totally unsecure when compiled with
- * an earlier library version)
+ /* Versions before 0.9.7 always allow clients to resume sessions in renegotiation.
+ * 0.9.7 and later allow this by default, but optionally ignore resumption requests
+ * with flag SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather
+ * than a change to default behavior so that applications relying on this for security
+ * won't even compile against older library versions).
+ *
+ * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to request
+ * renegotiation but not a new session (s->new_session remains unset): for servers,
+ * this essentially just means that the SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+ * setting will be ignored.
*/
if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
{
p+=j;
- if (s->version == DTLS1_VERSION)
+ if (SSL_IS_DTLS(s))
{
/* cookie stuff */
cookie_len = *(p++);
- if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
- s->d1->send_cookie == 0)
- {
- /* HelloVerifyMessage has already been sent */
- if ( cookie_len != s->d1->cookie_len)
- {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
- goto f_err;
- }
- }
-
/*
* The ClientHello may contain a cookie even if the
* HelloVerify message has not been sent--make sure that it
}
/* verify the cookie if appropriate option is set. */
- if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
+ if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
cookie_len > 0)
{
memcpy(s->d1->rcvd_cookie, p, cookie_len);
SSL_R_COOKIE_MISMATCH);
goto f_err;
}
+ /* Set to -2 so if successful we return 2 */
+ ret = -2;
}
p += cookie_len;
+ if (s->method->version == DTLS_ANY_VERSION)
+ {
+ /* Select version to use */
+ if (s->client_version <= DTLS1_2_VERSION &&
+ !(s->options & SSL_OP_NO_DTLSv1_2))
+ {
+ s->version = DTLS1_2_VERSION;
+ s->method = DTLSv1_2_server_method();
+ }
+ else if (tls1_suiteb(s))
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
+ s->version = s->client_version;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ else if (s->client_version <= DTLS1_VERSION &&
+ !(s->options & SSL_OP_NO_DTLSv1))
+ {
+ s->version = DTLS1_VERSION;
+ s->method = DTLSv1_server_method();
+ }
+ else
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
+ s->version = s->client_version;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ s->session->ssl_version = s->version;
+ }
}
n2s(p,i);
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
j = 1;
}
}
+#endif
if (j == 0)
{
/* we need to have the cipher in the cipher
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
+#ifndef OPENSSL_NO_COMP
q=p;
+#endif
for (j=0; j<i; j++)
{
if (p[j] == 0) break;
#ifndef OPENSSL_NO_TLSEXT
/* TLS extensions*/
- if (s->version > SSL3_VERSION)
+ if (s->version >= SSL3_VERSION)
{
- if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al))
+ if (!ssl_parse_clienthello_tlsext(s,&p,d,n))
{
- /* 'al' set by ssl_parse_clienthello_tlsext */
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT);
- goto f_err;
- }
- }
- if (ssl_check_clienthello_tlsext(s) <= 0) {
- 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
* 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)
+ if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE) <= 0)
{
- al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
}
* algorithms from the client, starting at q. */
s->s3->tmp.new_compression=NULL;
#ifndef OPENSSL_NO_COMP
- if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods)
+ /* 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)
+ {
+ 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)
+ {
+ 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;
else
comp=NULL;
}
+#else
+ /* If compression is disabled we'd better not try to resume a session
+ * using compression.
+ */
+ if (s->session->compress_meth != 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
+ goto f_err;
+ }
#endif
/* Given s->session->ciphers and SSL_get_ciphers, we must
goto f_err;
}
ciphers=NULL;
+ /* Let cert callback update server certificates if required */
+ retry_cert:
+ if (s->cert->cert_cb)
+ {
+ int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+ if (rv == 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR);
+ goto f_err;
+ }
+ if (rv < 0)
+ {
+ s->rwstate=SSL_X509_LOOKUP;
+ return -1;
+ }
+ s->rwstate = SSL_NOTHING;
+ }
c=ssl3_choose_cipher(s,s->session->ciphers,
SSL_get_ciphers(s));
goto f_err;
}
s->s3->tmp.new_cipher=c;
+ /* check whether we should disable session resumption */
+ if (s->not_resumable_session_cb != NULL)
+ s->session->not_resumable=s->not_resumable_session_cb(s,
+ ((c->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) != 0));
+ if (s->session->not_resumable)
+ /* do not send a session ticket */
+ s->tlsext_ticket_expected = 0;
}
else
{
s->s3->tmp.new_cipher=s->session->cipher;
}
- if (!ssl3_digest_cached_records(s))
- goto f_err;
+ if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER))
+ {
+ if (!ssl3_digest_cached_records(s))
+ goto f_err;
+ }
/* we now have the following setup.
* client_random
* s->tmp.new_cipher - the new cipher to use.
*/
- ret=1;
+ /* Handles TLS extensions that we couldn't check earlier */
+ if (s->version >= SSL3_VERSION)
+ {
+ if (ssl_check_clienthello_tlsext_late(s) <= 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ goto err;
+ }
+ }
+
+ if (ret < 0) ret=-ret;
if (0)
{
f_err:
}
err:
if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers);
- return(ret);
+ return ret < 0 ? -1 : ret;
}
int ssl3_send_server_hello(SSL *s)
unsigned char *p,*d;
int i,sl;
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;
#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)
+ if (ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE) <= 0)
return -1;
#endif
/* Do the message type and length last */
- d=p= &(buf[4]);
+ d=p= ssl_handshake_start(s);
*(p++)=s->version>>8;
*(p++)=s->version&0xff;
memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
p+=SSL3_RANDOM_SIZE;
- /* now in theory we have 3 options to sending back the
- * session id. If it is a re-use, we send back the
- * old session-id, if it is a new session, we send
- * back the new session-id or we send back a 0 length
- * session-id if we want it to be single use.
- * Currently I will not implement the '0' length session-id
- * 12-Jan-98 - I'll now support the '0' length stuff.
- *
- * We also have an additional case where stateless session
- * resumption is successful: we always send back the old
- * session id. In this case s->hit is non zero: this can
- * only happen if stateless session resumption is succesful
- * if session caching is disabled so existing functionality
- * is unaffected.
+ /* There are several cases for the session ID to send
+ * back in the server hello:
+ * - For session reuse from the session cache,
+ * we send back the old session ID.
+ * - If stateless session reuse (using a session ticket)
+ * is successful, we send back the client's "session ID"
+ * (which doesn't actually identify the session).
+ * - If it is a new session, we send back the new
+ * session ID.
+ * - However, if we want the new session to be single-use,
+ * we send back a 0-length session ID.
+ * s->hit is non-zero in either case of session reuse,
+ * so the following won't overwrite an ID that we're supposed
+ * to send back.
*/
- if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
- && !s->hit)
+ if (s->session->not_resumable ||
+ (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
+ && !s->hit))
s->session->session_id_length=0;
sl=s->session->session_id_length;
#endif
/* do the header */
l=(p-d);
- d=buf;
- *(d++)=SSL3_MT_SERVER_HELLO;
- l2n3(l,d);
-
+ ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l);
s->state=SSL3_ST_SW_SRVR_HELLO_B;
- /* number of bytes to write */
- s->init_num=p-buf;
- s->init_off=0;
}
/* SSL3_ST_SW_SRVR_HELLO_B */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
}
int ssl3_send_server_done(SSL *s)
{
- unsigned char *p;
if (s->state == SSL3_ST_SW_SRVR_DONE_A)
{
- p=(unsigned char *)s->init_buf->data;
-
- /* do the header */
- *(p++)=SSL3_MT_SERVER_DONE;
- *(p++)=0;
- *(p++)=0;
- *(p++)=0;
-
- s->state=SSL3_ST_SW_SRVR_DONE_B;
- /* number of bytes to write */
- s->init_num=4;
- s->init_off=0;
+ ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0);
+ s->state = SSL3_ST_SW_SRVR_DONE_B;
}
/* SSL3_ST_SW_SRVR_DONE_B */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
}
int ssl3_send_server_key_exchange(SSL *s)
BN_CTX *bn_ctx = NULL;
#endif
EVP_PKEY *pkey;
+ const EVP_MD *md = NULL;
unsigned char *p,*d;
int al,i;
unsigned long type;
else
#endif
#ifndef OPENSSL_NO_DH
- if (type & SSL_kEDH)
+ if (type & SSL_kDHE)
{
dhp=cert->dh_tmp;
if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
if (s->s3->tmp.dh != NULL)
{
- DH_free(dh);
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
else
#endif
#ifndef OPENSSL_NO_ECDH
- if (type & SSL_kEECDH)
+ if (type & SSL_kECDHE)
{
const EC_GROUP *group;
ecdhp=cert->ecdh_tmp;
- if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL))
+ if (s->cert->ecdh_tmp_auto)
+ {
+ /* Get NID of appropriate shared curve */
+ int nid = tls1_shared_curve(s, -2);
+ if (nid != NID_undef)
+ ecdhp = EC_KEY_new_by_curve_name(nid);
+ }
+ else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb)
{
ecdhp=s->cert->ecdh_tmp_cb(s,
SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
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;
}
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB);
goto err;
}
- if (!EC_KEY_up_ref(ecdhp))
+ if (s->cert->ecdh_tmp_auto)
+ ecdh = ecdhp;
+ else 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) ||
}
else
#endif /* !OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (type & SSL_kSRP)
+ {
+ if ((s->srp_ctx.N == NULL) ||
+ (s->srp_ctx.g == NULL) ||
+ (s->srp_ctx.s == NULL) ||
+ (s->srp_ctx.B == NULL))
+ {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_SRP_PARAM);
+ goto err;
+ }
+ r[0]=s->srp_ctx.N;
+ r[1]=s->srp_ctx.g;
+ r[2]=s->srp_ctx.s;
+ r[3]=s->srp_ctx.B;
+ }
+ else
+#endif
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
goto f_err;
}
- for (i=0; r[i] != NULL; i++)
+ for (i=0; r[i] != NULL && i<4; i++)
{
nr[i]=BN_num_bytes(r[i]);
+#ifndef OPENSSL_NO_SRP
+ if ((i == 2) && (type & SSL_kSRP))
+ n+=1+nr[i];
+ else
+#endif
n+=2+nr[i];
}
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))
+ if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
== NULL)
{
al=SSL_AD_DECODE_ERROR;
kn=0;
}
- if (!BUF_MEM_grow_clean(buf,n+4+kn))
+ if (!BUF_MEM_grow_clean(buf,n+SSL_HM_HEADER_LENGTH(s)+kn))
{
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF);
goto err;
}
- d=(unsigned char *)s->init_buf->data;
- p= &(d[4]);
+ d = p = ssl_handshake_start(s);
- for (i=0; r[i] != NULL; i++)
+ for (i=0; r[i] != NULL && i<4; i++)
{
+#ifndef OPENSSL_NO_SRP
+ if ((i == 2) && (type & SSL_kSRP))
+ {
+ *p = nr[i];
+ p++;
+ }
+ else
+#endif
s2n(nr[i],p);
BN_bn2bin(r[i],p);
p+=nr[i];
}
#ifndef OPENSSL_NO_ECDH
- if (type & SSL_kEECDH)
+ if (type & SSL_kECDHE)
{
/* XXX: For now, we only support named (not generic) curves.
* In this situation, the serverKeyExchange message has:
(unsigned char *)encodedPoint,
encodedlen);
OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
p += encodedlen;
}
#endif
/* n is the length of the params, they start at &(d[4])
* and p points to the space at the end. */
#ifndef OPENSSL_NO_RSA
- if (pkey->type == EVP_PKEY_RSA)
+ if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s))
{
q=md_buf;
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);
EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
- EVP_DigestUpdate(&md_ctx,&(d[4]),n);
+ EVP_DigestUpdate(&md_ctx,d,n);
EVP_DigestFinal_ex(&md_ctx,q,
(unsigned int *)&i);
q+=i;
}
else
#endif
-#if !defined(OPENSSL_NO_DSA)
- if (pkey->type == EVP_PKEY_DSA)
+ if (md)
{
- /* lets do DSS */
- EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
- EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx,&(d[4]),n);
- if (!EVP_SignFinal(&md_ctx,&(p[2]),
- (unsigned int *)&i,pkey))
+ /* send signature algorithm */
+ if (SSL_USE_SIGALGS(s))
{
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);
- goto err;
+ if (!tls12_get_sigandhash(p, pkey, md))
+ {
+ /* Should never happen */
+ al=SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ p+=2;
}
- s2n(i,p);
- n+=i+2;
- }
- else
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using hash %s\n",
+ EVP_MD_name(md));
#endif
-#if !defined(OPENSSL_NO_ECDSA)
- if (pkey->type == EVP_PKEY_EC)
- {
- /* let's do ECDSA */
- EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+ EVP_SignInit_ex(&md_ctx, md, NULL);
EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx,&(d[4]),n);
+ EVP_SignUpdate(&md_ctx,d,n);
if (!EVP_SignFinal(&md_ctx,&(p[2]),
(unsigned int *)&i,pkey))
{
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA);
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_EVP);
goto err;
}
s2n(i,p);
n+=i+2;
+ if (SSL_USE_SIGALGS(s))
+ n+= 2;
}
else
-#endif
{
/* Is this error check actually needed? */
al=SSL_AD_HANDSHAKE_FAILURE;
}
}
- *(d++)=SSL3_MT_SERVER_KEY_EXCHANGE;
- l2n3(n,d);
-
- /* we should now have things packed up, so lets send
- * it off */
- s->init_num=n+4;
- s->init_off=0;
+ ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n);
}
s->state = SSL3_ST_SW_KEY_EXCH_B;
EVP_MD_CTX_cleanup(&md_ctx);
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
{
buf=s->init_buf;
- d=p=(unsigned char *)&(buf->data[4]);
+ d=p=ssl_handshake_start(s);
/* get the list of acceptable cert types */
p++;
p+=n;
n++;
+ if (SSL_USE_SIGALGS(s))
+ {
+ const unsigned char *psigs;
+ nl = tls12_get_psigalgs(s, &psigs);
+ s2n(nl, p);
+ memcpy(p, psigs, nl);
+ p += nl;
+ n += nl + 2;
+ }
+
off=n;
p+=2;
n+=2;
{
name=sk_X509_NAME_value(sk,i);
j=i2d_X509_NAME(name,NULL);
- if (!BUF_MEM_grow_clean(buf,4+n+j+2))
+ if (!BUF_MEM_grow_clean(buf,SSL_HM_HEADER_LENGTH(s)+n+j+2))
{
SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
goto err;
}
- p=(unsigned char *)&(buf->data[4+n]);
+ p = ssl_handshake_start(s) + n;
if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
{
s2n(j,p);
}
}
/* else no CA names */
- p=(unsigned char *)&(buf->data[4+off]);
+ p = ssl_handshake_start(s) + off;
s2n(nl,p);
- d=(unsigned char *)buf->data;
- *(d++)=SSL3_MT_CERTIFICATE_REQUEST;
- l2n3(n,d);
-
- /* we should now have things packed up, so lets send
- * it off */
+ ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n);
- s->init_num=n+4;
- s->init_off=0;
#ifdef NETSCAPE_HANG_BUG
- p=(unsigned char *)s->init_buf->data + s->init_num;
-
- /* do the header */
- *(p++)=SSL3_MT_SERVER_DONE;
- *(p++)=0;
- *(p++)=0;
- *(p++)=0;
- s->init_num += 4;
+ if (!SSL_IS_DTLS(s))
+ {
+ p=(unsigned char *)s->init_buf->data + s->init_num;
+ /* do the header */
+ *(p++)=SSL3_MT_SERVER_DONE;
+ *(p++)=0;
+ *(p++)=0;
+ *(p++)=0;
+ s->init_num += 4;
+ }
#endif
s->state = SSL3_ST_SW_CERT_REQ_B;
}
/* SSL3_ST_SW_CERT_REQ_B */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
err:
return(-1);
}
#endif
#ifndef OPENSSL_NO_DH
BIGNUM *pub=NULL;
- DH *dh_srvr;
+ DH *dh_srvr, *dh_clnt = NULL;
#endif
#ifndef OPENSSL_NO_KRB5
KSSL_ERR kssl_err;
#ifndef OPENSSL_NO_RSA
if (alg_k & SSL_kRSA)
{
+ unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
+ int decrypt_len, decrypt_good_mask;
+ unsigned char version_good;
+
/* FIX THIS UP EAY EAY EAY EAY */
if (s->s3->tmp.use_rsa_tmp)
{
n=i;
}
- i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
-
- al = -1;
-
- if (i != SSL_MAX_MASTER_KEY_LENGTH)
- {
- al=SSL_AD_DECODE_ERROR;
- /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */
- }
-
- if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff))))
- {
- /* The premaster secret must contain the same version number as the
- * ClientHello to detect version rollback attacks (strangely, the
- * protocol does not offer such protection for DH ciphersuites).
- * However, buggy clients exist that send the negotiated protocol
- * version instead if the server does not support the requested
- * protocol version.
- * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
- if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) &&
- (p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff))))
- {
- al=SSL_AD_DECODE_ERROR;
- /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */
+ /* We must not leak whether a decryption failure occurs because
+ * of Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see
+ * RFC 2246, section 7.4.7.1). The code follows that advice of
+ * the TLS RFC and generates a random premaster secret for the
+ * case that the decrypt fails. See
+ * https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */
- /* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
- * (http://eprint.iacr.org/2003/052/) exploits the version
- * number check as a "bad version oracle" -- an alert would
- * reveal that the plaintext corresponding to some ciphertext
- * made up by the adversary is properly formatted except
- * that the version number is wrong. To avoid such attacks,
- * we should treat this just like any other decryption error. */
- }
+ /* should be RAND_bytes, but we cannot work around a failure. */
+ if (RAND_pseudo_bytes(rand_premaster_secret,
+ sizeof(rand_premaster_secret)) <= 0)
+ goto err;
+ decrypt_len = RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
+ ERR_clear_error();
+
+ /* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH.
+ * decrypt_good_mask will be zero if so and non-zero otherwise. */
+ decrypt_good_mask = decrypt_len ^ SSL_MAX_MASTER_KEY_LENGTH;
+
+ /* If the version in the decrypted pre-master secret is correct
+ * then version_good will be zero. The Klima-Pokorny-Rosa
+ * extension of Bleichenbacher's attack
+ * (http://eprint.iacr.org/2003/052/) exploits the version
+ * number check as a "bad version oracle". Thus version checks
+ * are done in constant time and are treated like any other
+ * decryption error. */
+ version_good = p[0] ^ (s->client_version>>8);
+ version_good |= p[1] ^ (s->client_version&0xff);
+
+ /* The premaster secret must contain the same version number as
+ * the ClientHello to detect version rollback attacks
+ * (strangely, the protocol does not offer such protection for
+ * DH ciphersuites). However, buggy clients exist that send the
+ * negotiated protocol version instead if the server does not
+ * support the requested protocol version. If
+ * SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
+ if (s->options & SSL_OP_TLS_ROLLBACK_BUG)
+ {
+ unsigned char workaround_mask = version_good;
+ unsigned char workaround;
+
+ /* workaround_mask will be 0xff if version_good is
+ * non-zero (i.e. the version match failed). Otherwise
+ * it'll be 0x00. */
+ workaround_mask |= workaround_mask >> 4;
+ workaround_mask |= workaround_mask >> 2;
+ workaround_mask |= workaround_mask >> 1;
+ workaround_mask = ~((workaround_mask & 1) - 1);
+
+ workaround = p[0] ^ (s->version>>8);
+ workaround |= p[1] ^ (s->version&0xff);
+
+ /* If workaround_mask is 0xff (i.e. there was a version
+ * mismatch) then we copy the value of workaround over
+ * version_good. */
+ version_good = (workaround & workaround_mask) |
+ (version_good & ~workaround_mask);
+ }
+
+ /* If any bits in version_good are set then they'll poision
+ * decrypt_good_mask and cause rand_premaster_secret to be
+ * used. */
+ decrypt_good_mask |= version_good;
+
+ /* decrypt_good_mask will be zero iff decrypt_len ==
+ * SSL_MAX_MASTER_KEY_LENGTH and the version check passed. We
+ * fold the bottom 32 bits of it with an OR so that the LSB
+ * will be zero iff everything is good. This assumes that we'll
+ * never decrypt a value > 2**31 bytes, which seems safe. */
+ decrypt_good_mask |= decrypt_good_mask >> 16;
+ decrypt_good_mask |= decrypt_good_mask >> 8;
+ decrypt_good_mask |= decrypt_good_mask >> 4;
+ decrypt_good_mask |= decrypt_good_mask >> 2;
+ decrypt_good_mask |= decrypt_good_mask >> 1;
+ /* Now select only the LSB and subtract one. If decrypt_len ==
+ * SSL_MAX_MASTER_KEY_LENGTH and the version check passed then
+ * decrypt_good_mask will be all ones. Otherwise it'll be all
+ * zeros. */
+ decrypt_good_mask &= 1;
+ decrypt_good_mask--;
+
+ /* Now copy rand_premaster_secret over p using
+ * decrypt_good_mask. */
+ for (i = 0; i < (int) sizeof(rand_premaster_secret); i++)
+ {
+ p[i] = (p[i] & decrypt_good_mask) |
+ (rand_premaster_secret[i] & ~decrypt_good_mask);
}
- if (al != -1)
- {
- /* Some decryption failure -- use random value instead as countermeasure
- * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding
- * (see RFC 2246, section 7.4.7.1). */
- ERR_clear_error();
- i = SSL_MAX_MASTER_KEY_LENGTH;
- p[0] = s->client_version >> 8;
- p[1] = s->client_version & 0xff;
- if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */
- goto err;
- }
-
s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,
else
#endif
#ifndef OPENSSL_NO_DH
- if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+ if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd))
{
- n2s(p,i);
- if (n != i+2)
+ int idx = -1;
+ EVP_PKEY *skey = NULL;
+ if (n)
+ n2s(p,i);
+ else
+ i = 0;
+ if (n && n != i+2)
{
if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG))
{
i=(int)n;
}
}
-
- if (n == 0L) /* the parameters are in the cert */
+ if (alg_k & SSL_kDHr)
+ idx = SSL_PKEY_DH_RSA;
+ else if (alg_k & SSL_kDHd)
+ idx = SSL_PKEY_DH_DSA;
+ if (idx >= 0)
+ {
+ skey = s->cert->pkeys[idx].privatekey;
+ if ((skey == NULL) ||
+ (skey->type != EVP_PKEY_DH) ||
+ (skey->pkey.dh == NULL))
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE);
+ goto f_err;
+ }
+ dh_srvr = skey->pkey.dh;
+ }
+ else if (s->s3->tmp.dh == NULL)
{
al=SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS);
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
goto f_err;
}
else
+ dh_srvr=s->s3->tmp.dh;
+
+ if (n == 0L)
{
- if (s->s3->tmp.dh == NULL)
+ /* Get pubkey from cert */
+ EVP_PKEY *clkey=X509_get_pubkey(s->session->peer);
+ if (clkey)
+ {
+ if (EVP_PKEY_cmp_parameters(clkey, skey) == 1)
+ dh_clnt = EVP_PKEY_get1_DH(clkey);
+ }
+ if (dh_clnt == NULL)
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
goto f_err;
}
- else
- dh_srvr=s->s3->tmp.dh;
+ EVP_PKEY_free(clkey);
+ pub = dh_clnt->pub_key;
}
-
- pub=BN_bin2bn(p,i,NULL);
+ else
+ pub=BN_bin2bn(p,i,NULL);
if (pub == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BN_LIB);
if (i <= 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+ BN_clear_free(pub);
goto err;
}
DH_free(s->s3->tmp.dh);
s->s3->tmp.dh=NULL;
-
- BN_clear_free(pub);
+ if (dh_clnt)
+ DH_free(dh_clnt);
+ else
+ BN_clear_free(pub);
pub=NULL;
s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,p,i);
OPENSSL_cleanse(p,i);
+ if (dh_clnt)
+ return 2;
}
else
#endif
krb5_data enc_pms;
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];
n2s(p,i);
enc_ticket.length = i;
- if (n < 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);
n2s(p,i);
authenticator.length = i;
- if (n < 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);
SSL_R_DATA_LENGTH_TOO_LONG);
goto err;
}
- if (!((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff))))
+ if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff))))
{
/* The premaster secret must contain the same version number as the
* ClientHello to detect version rollback attacks (strangely, the
* If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients.
* (Perhaps we should have a separate BUG value for the Kerberos cipher)
*/
- if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) &&
- (p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff))))
+ if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_AD_DECODE_ERROR);
#endif /* OPENSSL_NO_KRB5 */
#ifndef OPENSSL_NO_ECDH
- if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
+ if (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe))
{
int ret = 1;
int field_size = 0;
{
/* Client Publickey was in Client Certificate */
- if (alg_k & SSL_kEECDH)
+ if (alg_k & SSL_kECDHE)
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
/* Get encoded point length */
i = *p;
p += 1;
+ 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)
{
EC_POINT_free(clnt_ecpoint);
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-> \
}
else
#endif
+#ifndef OPENSSL_NO_SRP
+ if (alg_k & SSL_kSRP)
+ {
+ int param_len;
+
+ n2s(p,i);
+ param_len=i+2;
+ if (param_len > n)
+ {
+ al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH);
+ goto f_err;
+ }
+ if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL)))
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB);
+ goto err;
+ }
+ if (s->session->srp_username != NULL)
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = BUF_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ p+=i;
+ }
+ else
+#endif /* OPENSSL_NO_SRP */
if (alg_k & SSL_kGOST)
- {
+ {
+ int ret = 0;
EVP_PKEY_CTX *pkey_ctx;
- unsigned char premaster_secret[32];
- size_t outlen;
-
- /* Get our certificate privatec key*/
- pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL);
+ 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)) || p[1]!=0x81 )
+ if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED)))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
- goto err;
- }
- if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,p+3,p[2]) <0)
+ 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 err;
+ goto gerr;
}
/* Generate master secret */
- EVP_PKEY_CTX_free(pkey_ctx);
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;
return(1);
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
-#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH)
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH) || defined(OPENSSL_NO_SRP)
err:
#endif
#ifndef OPENSSL_NO_ECDH
long n;
int type=0,i,j;
X509 *peer;
+ const EVP_MD *md = NULL;
+ EVP_MD_CTX mctx;
+ EVP_MD_CTX_init(&mctx);
n=s->method->ssl_get_message(s,
SSL3_ST_SR_CERT_VRFY_A,
SSL3_ST_SR_CERT_VRFY_B,
-1,
- 514, /* 514? */
+ 516, /* Enough for 4096 bit RSA key with TLS v1.2 */
&ok);
if (!ok) return((int)n);
if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY)
{
s->s3->tmp.reuse_message=1;
- if ((peer != NULL) && (type | EVP_PKT_SIGN))
+ if ((peer != NULL) && (type & EVP_PKT_SIGN))
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE);
}
else
{
+ if (SSL_USE_SIGALGS(s))
+ {
+ int rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+ if (rv == -1)
+ {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ else if (rv == 0)
+ {
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+#ifdef SSL_DEBUG
+fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
+#endif
+ p += 2;
+ n -= 2;
+ }
n2s(p,i);
n-=2;
if (i > n)
goto f_err;
}
+ if (SSL_USE_SIGALGS(s))
+ {
+ long hdatalen = 0;
+ void *hdata;
+ hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
+ if (hdatalen <= 0)
+ {
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+#ifdef SSL_DEBUG
+ fprintf(stderr, "Using TLS 1.2 with client verify alg %s\n",
+ EVP_MD_name(md));
+#endif
+ if (!EVP_VerifyInit_ex(&mctx, md, NULL)
+ || !EVP_VerifyUpdate(&mctx, hdata, hdatalen))
+ {
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_EVP_LIB);
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+
+ if (EVP_VerifyFinal(&mctx, p , i, pkey) <= 0)
+ {
+ al=SSL_AD_DECRYPT_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_SIGNATURE);
+ goto f_err;
+ }
+ }
+ else
#ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA)
{
ssl3_send_alert(s,SSL3_AL_FATAL,al);
}
end:
+ if (s->s3->handshake_buffer)
+ {
+ BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
+ s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
+ }
+ EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_free(pkey);
return(ret);
}
al=SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
+ /* No client certificate so digest cached records */
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
}
else
{
if (i <= 0)
{
al=ssl_verify_alarm_type(s->verify_result);
- SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
+ SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
goto f_err;
}
}
int ssl3_send_server_certificate(SSL *s)
{
- unsigned long l;
- X509 *x;
+ CERT_PKEY *cpk;
if (s->state == SSL3_ST_SW_CERT_A)
{
- x=ssl_get_server_send_cert(s);
- if (x == NULL)
+ cpk=ssl_get_server_send_pkey(s);
+ if (cpk == NULL)
{
/* VRS: allow null cert if auth == KRB5 */
if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) ||
}
}
- l=ssl3_output_cert_chain(s,x);
+ ssl3_output_cert_chain(s,cpk);
s->state=SSL3_ST_SW_CERT_B;
- s->init_num=(int)l;
- s->init_off=0;
}
/* SSL3_ST_SW_CERT_B */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
}
+
#ifndef OPENSSL_NO_TLSEXT
+/* send a new session ticket (not necessarily for a new session) */
int ssl3_send_newsession_ticket(SSL *s)
{
if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
{
unsigned char *p, *senc, *macstart;
- int len, slen;
+ const unsigned char *const_p;
+ int len, slen_full, slen;
+ SSL_SESSION *sess;
unsigned int hlen;
EVP_CIPHER_CTX ctx;
HMAC_CTX hctx;
+ SSL_CTX *tctx = s->initial_ctx;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char key_name[16];
/* get session encoding length */
- slen = i2d_SSL_SESSION(s->session, NULL);
+ slen_full = i2d_SSL_SESSION(s->session, NULL);
/* Some length values are 16 bits, so forget it if session is
* too long
*/
- if (slen > 0xFF00)
+ if (slen_full > 0xFF00)
+ return -1;
+ senc = OPENSSL_malloc(slen_full);
+ if (!senc)
return -1;
+ p = senc;
+ i2d_SSL_SESSION(s->session, &p);
+
+ /* create a fresh copy (not shared with other threads) to clean up */
+ const_p = senc;
+ sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
+ if (sess == NULL)
+ {
+ OPENSSL_free(senc);
+ return -1;
+ }
+ sess->session_id_length = 0; /* ID is irrelevant for the ticket */
+
+ slen = i2d_SSL_SESSION(sess, NULL);
+ if (slen > slen_full) /* shouldn't ever happen */
+ {
+ OPENSSL_free(senc);
+ return -1;
+ }
+ p = senc;
+ i2d_SSL_SESSION(sess, &p);
+ SSL_SESSION_free(sess);
+
/* Grow buffer if need be: the length calculation is as
- * follows 1 (size of message name) + 3 (message length
- * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
+ * follows handshake_header_length +
+ * 4 (ticket lifetime hint) + 2 (ticket length) +
* 16 (key name) + max_iv_len (iv length) +
* session_length + max_enc_block_size (max encrypted session
* length) + max_md_size (HMAC).
*/
if (!BUF_MEM_grow(s->init_buf,
- 26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
- EVP_MAX_MD_SIZE + slen))
- return -1;
- senc = OPENSSL_malloc(slen);
- if (!senc)
+ SSL_HM_HEADER_LENGTH(s) + 22 + EVP_MAX_IV_LENGTH +
+ EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
return -1;
- p = senc;
- i2d_SSL_SESSION(s->session, &p);
-
- p=(unsigned char *)s->init_buf->data;
- /* do the header */
- *(p++)=SSL3_MT_NEWSESSION_TICKET;
- /* Skip message length for now */
- p += 3;
+ p = ssl_handshake_start(s);
EVP_CIPHER_CTX_init(&ctx);
HMAC_CTX_init(&hctx);
/* Initialize HMAC and cipher contexts. If callback present
* it does all the work otherwise use generated values
* from parent ctx.
*/
- if (s->ctx->tlsext_ticket_key_cb)
+ if (tctx->tlsext_ticket_key_cb)
{
- if (s->ctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+ if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
&hctx, 1) < 0)
{
OPENSSL_free(senc);
{
RAND_pseudo_bytes(iv, 16);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
- s->ctx->tlsext_tick_aes_key, iv);
- HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
+ tctx->tlsext_tick_aes_key, iv);
+ HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
tlsext_tick_md(), NULL);
- memcpy(key_name, s->ctx->tlsext_tick_key_name, 16);
+ memcpy(key_name, tctx->tlsext_tick_key_name, 16);
}
- l2n(s->session->tlsext_tick_lifetime_hint, p);
+
+ /* Ticket lifetime hint (advisory only):
+ * We leave this unspecified for resumed session (for simplicity),
+ * and guess that tickets for new sessions will live as long
+ * as their sessions. */
+ l2n(s->hit ? 0 : s->session->timeout, p);
+
/* Skip ticket length for now */
p += 2;
/* Output key name */
p += hlen;
/* Now write out lengths: p points to end of data written */
/* Total length */
- len = p - (unsigned char *)s->init_buf->data;
- p=(unsigned char *)s->init_buf->data + 1;
- l2n3(len - 4, p); /* Message length */
- p += 4;
- s2n(len - 10, p); /* Ticket length */
-
- /* number of bytes to write */
- s->init_num= len;
+ len = p - ssl_handshake_start(s);
+ ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len);
+ /* Skip ticket lifetime hint */
+ p = ssl_handshake_start(s) + 4;
+ s2n(len - 6, p);
s->state=SSL3_ST_SW_SESSION_TICKET_B;
- s->init_off=0;
OPENSSL_free(senc);
}
/* SSL3_ST_SW_SESSION_TICKET_B */
- return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+ return ssl_do_write(s);
}
int ssl3_send_cert_status(SSL *s)
/* SSL3_ST_SW_CERT_STATUS_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+/* 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;
+ int 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,
+ 514, /* See the payload format below */
+ &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;
+ }
+# endif
+
+int tls1_send_server_supplemental_data(SSL *s, int *skip)
+ {
+ if (s->ctx->srv_supp_data_records_count)
+ {
+ unsigned char *p = NULL;
+ unsigned char *size_loc = NULL;
+ srv_supp_data_record *record = NULL;
+ size_t length = 0;
+ size_t i = 0;
+
+ for (i = 0; i < s->ctx->srv_supp_data_records_count; i++)
+ {
+ const unsigned char *out = NULL;
+ unsigned short outlen = 0;
+ int cb_retval = 0;
+ record = &s->ctx->srv_supp_data_records[i];
+
+ /* NULL callback or -1 omits supp data entry */
+ if (!record->fn1)
+ continue;
+ cb_retval = record->fn1(s, record->supp_data_type,
+ &out, &outlen,
+ record->arg);
+ if (cb_retval == -1)
+ continue; /* skip this supp data entry */
+ if (cb_retval == 0)
+ {
+ SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length)
+ {
+ SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ /* write supp data entry...
+ * if first entry, write handshake message type
+ * jump back to write length at end */
+ if (length == 0)
+ {
+ /* 1 byte message type + 3 bytes for
+ * message length */
+ if (!BUF_MEM_grow_clean(s->init_buf, 4))
+ {
+ SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ p = (unsigned char *)s->init_buf->data;
+ *(p++) = SSL3_MT_SUPPLEMENTAL_DATA;
+ /* hold on to length field to update later */
+ size_loc = p;
+ /* skip over handshake length field (3
+ * bytes) and supp_data length field
+ * (3 bytes) */
+ p += 3 + 3;
+ length += 1 +3 +3;
+ }
+ /* 2 byte supp data type + 2 byte length + outlen */
+ if (!BUF_MEM_grow(s->init_buf, outlen + 4))
+ {
+ SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ s2n(record->supp_data_type, p);
+ s2n(outlen, p);
+ memcpy(p, out, outlen);
+ /* update length to supp data type (2 bytes) +
+ * supp data length (2 bytes) + supp data */
+ length += (outlen + 4);
+ p += outlen;
+ }
+ if (length > 0)
+ {
+ /* write handshake length */
+ l2n3(length - 4, size_loc);
+ /* supp_data length */
+ l2n3(length - 7, size_loc);
+ s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B;
+ s->init_num = length;
+ s->init_off = 0;
+
+ return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+ }
+ }
+
+ /* no supp data message sent */
+ *skip = 1;
+ s->init_num = 0;
+ s->init_off = 0;
+ return 1;
+ }
+
+int tls1_get_client_supplemental_data(SSL *s)
+ {
+ int al = 0;
+ int cb_retval = 0;
+ int ok;
+ long n;
+ const unsigned char *p, *d;
+ unsigned short supp_data_entry_type = 0;
+ unsigned long supp_data_entry_len = 0;
+ unsigned long supp_data_len = 0;
+ size_t i = 0;
+
+ n=s->method->ssl_get_message(s,
+ SSL3_ST_SR_SUPPLEMENTAL_DATA_A,
+ SSL3_ST_SR_SUPPLEMENTAL_DATA_B,
+ SSL3_MT_SUPPLEMENTAL_DATA,
+ /* use default limit */
+ TLSEXT_MAXLEN_supplemental_data,
+ &ok);
+
+ if (!ok) return((int)n);
+
+ p = (unsigned char *)s->init_msg;
+ d = p;
+
+ /* The message cannot be empty */
+ if (n < 3)
+ {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS1_GET_CLIENT_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ n2l3(p, supp_data_len);
+ while (p<d+supp_data_len)
+ {
+ n2s(p, supp_data_entry_type);
+ n2s(p, supp_data_entry_len);
+ /* if there is a callback for this supp data type, send it */
+ for (i=0; i < s->ctx->srv_supp_data_records_count; i++)
+ {
+ if (s->ctx->srv_supp_data_records[i].supp_data_type == supp_data_entry_type && s->ctx->srv_supp_data_records[i].fn2)
+ {
+ cb_retval = s->ctx->srv_supp_data_records[i].fn2(s, supp_data_entry_type, p, supp_data_entry_len, &al, s->ctx->srv_supp_data_records[i].arg);
+ if (cb_retval == 0)
+ {
+ SSLerr(SSL_F_TLS1_GET_CLIENT_SUPPLEMENTAL_DATA, ERR_R_SSL_LIB);
+ goto f_err;
+ }
+ }
+ }
+ p+=supp_data_entry_len;
+ }
+ return 1;
+f_err:
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ return -1;
+ }
#endif