/* init things to blank */
s->in_handshake++;
- if (!SSL_in_init(s) || SSL_in_before(s))
- SSL_clear(s);
-
- if (s->cert == NULL) {
- SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_NO_CERTIFICATE_SET);
- return (-1);
+ if (!SSL_in_init(s) || SSL_in_before(s)) {
+ if (!SSL_clear(s))
+ return -1;
}
+
#ifndef OPENSSL_NO_HEARTBEATS
/*
* If we're awaiting a HeartbeatResponse, pretend we already got and
{
if (s->state == SSL3_ST_SW_HELLO_REQ_A) {
- ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0);
+ if (!ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0)) {
+ SSLerr(SSL_F_SSL3_SEND_HELLO_REQUEST, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
s->state = SSL3_ST_SW_HELLO_REQ_B;
}
s->first_packet = 0;
d = p = (unsigned char *)s->init_msg;
+ /*
+ * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte
+ * for session id length
+ */
+ if (n < 2 + SSL3_RANDOM_SIZE + 1) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
/*
* use version from inside client hello, not from record header (may
* differ: see RFC 2246, Appendix E, second paragraph)
unsigned int session_length, cookie_length;
session_length = *(p + SSL3_RANDOM_SIZE);
+
+ if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
if (cookie_length == 0)
/* get the session-id */
j = *(p++);
+ if (p + j > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
s->hit = 0;
/*
* Versions before 0.9.7 always allow clients to resume sessions in
if (SSL_IS_DTLS(s)) {
/* cookie stuff */
+ if (p + 1 > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
cookie_len = *(p++);
+ if (p + cookie_len > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
/*
* The ClientHello may contain a cookie even if the
* HelloVerify message has not been sent--make sure that it
}
}
+ if (p + 2 > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
n2s(p, i);
- if ((i == 0) && (j != 0)) {
- /* we need a cipher if we are not resuming a session */
+
+ if (i == 0) {
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
goto f_err;
}
- if ((p + i) >= (d + n)) {
+
+ /* i bytes of cipher data + 1 byte for compression length later */
+ if ((p + i + 1) > (d + n)) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
- if ((i > 0) && (ssl_bytes_to_cipher_list(s, p, i, &(ciphers))
- == NULL)) {
+ if (ssl_bytes_to_cipher_list(s, p, i, &(ciphers)) == NULL) {
goto err;
}
p += i;
/* If it is a hit, check that the cipher is in the list */
- if ((s->hit) && (i > 0)) {
+ if (s->hit) {
j = 0;
id = s->session->cipher->id;
sk_SSL_CIPHER_free(s->session->ciphers);
s->session->ciphers = ciphers;
if (ciphers == NULL) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_PASSED);
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto f_err;
}
ciphers = NULL;
#endif
/* do the header */
l = (p - d);
- ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l);
+ if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l)) {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
s->state = SSL3_ST_SW_SRVR_HELLO_B;
}
{
if (s->state == SSL3_ST_SW_SRVR_DONE_A) {
- ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0);
+ if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0)) {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_DONE, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
s->state = SSL3_ST_SW_SRVR_DONE_B;
}
#ifndef OPENSSL_NO_DH
DH *dh = NULL, *dhp;
#endif
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
EC_KEY *ecdh = NULL, *ecdhp;
unsigned char *encodedPoint = NULL;
int encodedlen = 0;
r[2] = dh->pub_key;
} else
#endif
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
if (type & SSL_kECDHE) {
const EC_GROUP *group;
r[2] = NULL;
r[3] = NULL;
} else
-#endif /* !OPENSSL_NO_ECDH */
+#endif /* !OPENSSL_NO_EC */
#ifndef OPENSSL_NO_PSK
if (type & SSL_kPSK) {
/*
p += nr[i];
}
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
if (type & SSL_kECDHE) {
/*
* XXX: For now, we only support named (not generic) curves. In
}
}
- ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n);
+ if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
}
s->state = SSL3_ST_SW_KEY_EXCH_B;
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
if (encodedPoint != NULL)
OPENSSL_free(encodedPoint);
BN_CTX_free(bn_ctx);
p = ssl_handshake_start(s) + off;
s2n(nl, p);
- ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n);
+ if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n)) {
+ SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
s->state = SSL3_ST_SW_CERT_REQ_B;
}
KSSL_ERR kssl_err;
#endif /* OPENSSL_NO_KRB5 */
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
EC_KEY *srvr_ecdh = NULL;
EVP_PKEY *clnt_pub_pkey = NULL;
EC_POINT *clnt_ecpoint = NULL;
* fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
*/
- /*
- * should be RAND_bytes, but we cannot work around a failure.
- */
- if (RAND_pseudo_bytes(rand_premaster_secret,
+ if (RAND_bytes(rand_premaster_secret,
sizeof(rand_premaster_secret)) <= 0)
goto err;
decrypt_len =
sizeof
(rand_premaster_secret));
OPENSSL_cleanse(p, sizeof(rand_premaster_secret));
+ if (s->session->master_key_length < 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
} else
#endif
#ifndef OPENSSL_NO_DH
if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) {
int idx = -1;
EVP_PKEY *skey = NULL;
- if (n)
+ if (n > 1) {
n2s(p, i);
- else
+ } else {
+ if (alg_k & SSL_kDHE) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
+ goto f_err;
+ }
i = 0;
+ }
if (n && n != i + 2) {
if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG)) {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
session->master_key,
p, i);
OPENSSL_cleanse(p, i);
+ if (s->session->master_key_length < 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
if (dh_clnt)
return 2;
} else
s->
session->master_key,
pms, outl);
+ if (s->session->master_key_length < 0) {
+ al = SSL_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
if (kssl_ctx->client_princ) {
size_t len = strlen(kssl_ctx->client_princ);
} else
#endif /* OPENSSL_NO_KRB5 */
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)) {
int ret = 1;
int field_size = 0;
p, i);
OPENSSL_cleanse(p, i);
+ if (s->session->master_key_length < 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
return (ret);
} else
#endif
session->master_key,
psk_or_pre_ms,
pre_ms_len);
+ if (s->session->master_key_length < 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto psk_err;
+ }
psk_err = 0;
psk_err:
OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
s->
session->master_key,
premaster_secret, 32);
+ if (s->session->master_key_length < 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
/* 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)
EVP_PKEY_CTX_free(pkey_ctx);
if (ret)
return ret;
- else
- goto err;
+ goto err;
} else {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_UNKNOWN_CIPHER_TYPE);
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) || defined(OPENSSL_NO_SRP)
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_EC) || defined(OPENSSL_NO_SRP)
err:
#endif
-#ifndef OPENSSL_NO_ECDH
+#ifndef OPENSSL_NO_EC
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);
#endif
return (-1);
}
} else
#endif
-#ifndef OPENSSL_NO_ECDSA
+#ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC) {
j = ECDSA_verify(pkey->save_type,
&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
/* send a new session ticket (not necessarily for a new session) */
int ssl3_send_newsession_ticket(SSL *s)
{
+ unsigned char *senc = NULL;
+ EVP_CIPHER_CTX ctx;
+ HMAC_CTX hctx;
+
if (s->state == SSL3_ST_SW_SESSION_TICKET_A) {
- unsigned char *p, *senc, *macstart;
+ unsigned char *p, *macstart;
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];
* Some length values are 16 bits, so forget it if session is too
* long
*/
- if (slen_full > 0xFF00)
+ if (slen_full == 0 || slen_full > 0xFF00)
return -1;
senc = OPENSSL_malloc(slen_full);
if (!senc)
return -1;
+
+ EVP_CIPHER_CTX_init(&ctx);
+ HMAC_CTX_init(&hctx);
+
p = senc;
- i2d_SSL_SESSION(s->session, &p);
+ if (!i2d_SSL_SESSION(s->session, &p))
+ goto err;
/*
* 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;
- }
+ if (sess == NULL)
+ goto err;
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;
+ if (slen == 0 || slen > slen_full) { /* shouldn't ever happen */
+ SSL_SESSION_free(sess);
+ goto err;
}
p = senc;
- i2d_SSL_SESSION(sess, &p);
+ if (!i2d_SSL_SESSION(sess, &p)) {
+ SSL_SESSION_free(sess);
+ goto err;
+ }
SSL_SESSION_free(sess);
/*-
if (!BUF_MEM_grow(s->init_buf,
SSL_HM_HEADER_LENGTH(s) + 22 + EVP_MAX_IV_LENGTH +
EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
- return -1;
+ goto err;
+
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 (tctx->tlsext_ticket_key_cb) {
if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
- &hctx, 1) < 0) {
- OPENSSL_free(senc);
- return -1;
- }
+ &hctx, 1) < 0)
+ goto err;
} else {
- RAND_pseudo_bytes(iv, 16);
- EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
- tctx->tlsext_tick_aes_key, iv);
- HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
- EVP_sha256(), NULL);
+ if (RAND_bytes(iv, 16) <= 0)
+ goto err;
+ if (!EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+ tctx->tlsext_tick_aes_key, iv))
+ goto err;
+ if (!HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+ EVP_sha256(), NULL))
+ goto err;
memcpy(key_name, tctx->tlsext_tick_key_name, 16);
}
memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
p += EVP_CIPHER_CTX_iv_length(&ctx);
/* Encrypt session data */
- EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+ if (!EVP_EncryptUpdate(&ctx, p, &len, senc, slen))
+ goto err;
p += len;
- EVP_EncryptFinal(&ctx, p, &len);
+ if (!EVP_EncryptFinal(&ctx, p, &len))
+ goto err;
p += len;
- EVP_CIPHER_CTX_cleanup(&ctx);
- HMAC_Update(&hctx, macstart, p - macstart);
- HMAC_Final(&hctx, p, &hlen);
+ if (!HMAC_Update(&hctx, macstart, p - macstart))
+ goto err;
+ if (!HMAC_Final(&hctx, p, &hlen))
+ goto err;
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
HMAC_CTX_cleanup(&hctx);
p += hlen;
/* Now write out lengths: p points to end of data written */
/* Total length */
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);
+ if (!ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len))
+ goto err;
s->state = SSL3_ST_SW_SESSION_TICKET_B;
OPENSSL_free(senc);
}
/* SSL3_ST_SW_SESSION_TICKET_B */
return ssl_do_write(s);
+ err:
+ if (senc)
+ OPENSSL_free(senc);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&hctx);
+ return -1;
}
int ssl3_send_cert_status(SSL *s)