static int ssl_set_version(SSL *s);
static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b);
-static int ssl3_check_finished(SSL *s);
+static int ssl3_check_change(SSL *s);
static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
unsigned char *p,
int (*put_cb) (const SSL_CIPHER *,
s->state = SSL3_ST_CW_CLNT_HELLO_A;
s->ctx->stats.sess_connect++;
s->init_num = 0;
- s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
/*
* Should have been reset by ssl3_get_finished, too.
*/
goto end;
if (s->hit) {
- s->state = SSL3_ST_CR_FINISHED_A;
+ s->state = SSL3_ST_CR_CHANGE_A;
if (s->tlsext_ticket_expected) {
/* receive renewed session ticket */
s->state = SSL3_ST_CR_SESSION_TICKET_A;
case SSL3_ST_CR_CERT_A:
case SSL3_ST_CR_CERT_B:
/* Noop (ret = 0) for everything but EAP-FAST. */
- ret = ssl3_check_finished(s);
+ ret = ssl3_check_change(s);
if (ret < 0)
goto end;
if (ret == 1) {
s->hit = 1;
- s->state = SSL3_ST_CR_FINISHED_A;
+ s->state = SSL3_ST_CR_CHANGE_A;
s->init_num = 0;
break;
}
if (s->tlsext_ticket_expected)
s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
else
- s->s3->tmp.next_state = SSL3_ST_CR_FINISHED_A;
+ s->s3->tmp.next_state = SSL3_ST_CR_CHANGE_A;
}
s->init_num = 0;
break;
ret = ssl3_get_new_session_ticket(s);
if (ret <= 0)
goto end;
- s->state = SSL3_ST_CR_FINISHED_A;
+ s->state = SSL3_ST_CR_CHANGE_A;
s->init_num = 0;
break;
s->init_num = 0;
break;
+ case SSL3_ST_CR_CHANGE_A:
+ case SSL3_ST_CR_CHANGE_B:
+ ret = ssl3_get_change_cipher_spec(s, SSL3_ST_CR_CHANGE_A,
+ SSL3_ST_CR_CHANGE_B);
+ if (ret <= 0)
+ goto end;
+
+ s->state = SSL3_ST_CR_FINISHED_A;
+ s->init_num = 0;
+ break;
+
case SSL3_ST_CR_FINISHED_A:
case SSL3_ST_CR_FINISHED_B:
- if (!s->s3->change_cipher_spec)
- s->s3->flags |= SSL3_FLAGS_CCS_OK;
ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A,
SSL3_ST_CR_FINISHED_B);
if (ret <= 0)
{
STACK_OF(SSL_CIPHER) *sk;
const SSL_CIPHER *c;
- unsigned char *p, *d;
+ PACKET pkt;
+ unsigned char *session_id, *cipherchars;
int i, al = SSL_AD_INTERNAL_ERROR, ok;
- unsigned int j;
+ unsigned int j, ciphercharlen;
long n;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp;
goto f_err;
}
- d = p = (unsigned char *)s->init_msg;
+ if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
if (s->method->version == TLS_ANY_VERSION) {
- int sversion = (p[0] << 8) | p[1];
+ unsigned int sversion;
+
+ if (!PACKET_get_net_2(&pkt, &sversion)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
#if TLS_MAX_VERSION != TLS1_2_VERSION
#error Code needs updating for new TLS version
}
} else if (s->method->version == DTLS_ANY_VERSION) {
/* Work out correct protocol version to use */
- int hversion = (p[0] << 8) | p[1];
- int options = s->options;
+ unsigned int hversion;
+ int options;
+
+ if (!PACKET_get_net_2(&pkt, &hversion)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+
+ options = s->options;
if (hversion == DTLS1_2_VERSION && !(options & SSL_OP_NO_DTLSv1_2))
s->method = DTLSv1_2_client_method();
else if (tls1_suiteb(s)) {
goto f_err;
}
s->session->ssl_version = s->version = s->method->version;
- } else if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) {
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
- s->version = (s->version & 0xff00) | p[1];
- al = SSL_AD_PROTOCOL_VERSION;
- goto f_err;
+ } else {
+ unsigned char *vers;
+
+ if (!PACKET_get_bytes(&pkt, &vers, 2)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if ((vers[0] != (s->version >> 8))
+ || (vers[1] != (s->version & 0xff))) {
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION);
+ s->version = (s->version & 0xff00) | vers[1];
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
}
- p += 2;
/* load the server hello data */
/* load the server random */
- memcpy(s->s3->server_random, p, SSL3_RANDOM_SIZE);
- p += SSL3_RANDOM_SIZE;
+ if (!PACKET_copy_bytes(&pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
s->hit = 0;
- /* get the session-id */
- j = *(p++);
-
- if ((j > sizeof s->session->session_id) || (j > SSL3_SESSION_ID_SIZE)) {
+ /* get the session-id length */
+ if (!PACKET_get_1(&pkt, &j)
+ || (j > sizeof s->session->session_id)
+ || (j > SSL3_SESSION_ID_SIZE)) {
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_SSL3_SESSION_ID_TOO_LONG);
goto f_err;
}
+ ciphercharlen = ssl_put_cipher_by_char(s, NULL, NULL);
/*
* Check if we can resume the session based on external pre-shared secret.
* EAP-FAST (RFC 4851) supports two types of session resumption.
if (s->version >= TLS1_VERSION && s->tls_session_secret_cb &&
s->session->tlsext_tick) {
SSL_CIPHER *pref_cipher = NULL;
+ size_t bookm;
+ if (!PACKET_get_bookmark(&pkt, &bookm)
+ || !PACKET_forward(&pkt, j)
+ || !PACKET_get_bytes(&pkt, &cipherchars, ciphercharlen)) {
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
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,
NULL, &pref_cipher,
s->tls_session_secret_cb_arg)) {
s->session->cipher = pref_cipher ?
- pref_cipher : ssl_get_cipher_by_char(s, p + j);
+ pref_cipher : ssl_get_cipher_by_char(s, cipherchars);
} else {
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
}
+ if (!PACKET_goto_bookmark(&pkt, bookm)) {
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ /* Get the session id */
+ if (!PACKET_get_bytes(&pkt, &session_id, j)) {
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
}
if (j != 0 && j == s->session->session_id_length
- && memcmp(p, s->session->session_id, j) == 0) {
+ && memcmp(session_id, s->session->session_id, j) == 0) {
if (s->sid_ctx_length != s->session->sid_ctx_length
|| memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
/* actually a client application bug */
}
}
s->session->session_id_length = j;
- memcpy(s->session->session_id, p, j); /* j could be 0 */
+ memcpy(s->session->session_id, session_id, j); /* j could be 0 */
}
- p += j;
- c = ssl_get_cipher_by_char(s, p);
+
+ if (!PACKET_get_bytes(&pkt, &cipherchars, ciphercharlen)) {
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+ c = ssl_get_cipher_by_char(s, cipherchars);
if (c == NULL) {
/* unknown cipher */
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
goto f_err;
}
- p += ssl_put_cipher_by_char(s, NULL, NULL);
sk = ssl_get_ciphers_by_id(s);
i = sk_SSL_CIPHER_find(sk, c);
goto f_err;
/* lets get the compression algorithm */
/* COMPRESSION */
+ if (!PACKET_get_1(&pkt, &j)) {
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
#ifdef OPENSSL_NO_COMP
- if (*(p++) != 0) {
+ if (j != 0) {
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
goto f_err;
}
#else
- j = *(p++);
if (s->hit && j != s->session->compress_meth) {
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,
#endif
/* TLS extensions */
- if (!ssl_parse_serverhello_tlsext(s, &p, d, n)) {
+ if (!ssl_parse_serverhello_tlsext(s, &pkt)) {
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_PARSE_TLSEXT);
goto err;
}
- if (p != (d + n)) {
+ if (PACKET_remaining(&pkt) != 0) {
/* wrong packet length */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
int ssl3_get_server_certificate(SSL *s)
{
int al, i, ok, ret = -1, exp_idx;
- unsigned long n, nc, llen, l;
+ unsigned long n, cert_list_len, cert_len;
X509 *x = NULL;
- const unsigned char *q, *p;
- unsigned char *d;
+ unsigned char *certstart, *certbytes;
STACK_OF(X509) *sk = NULL;
EVP_PKEY *pkey = NULL;
+ PACKET pkt;
n = s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_A,
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, SSL_R_BAD_MESSAGE_TYPE);
goto f_err;
}
- p = d = (unsigned char *)s->init_msg;
+
+ if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
if ((sk = sk_X509_new_null()) == NULL) {
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
goto err;
}
- n2l3(p, llen);
- if (llen + 3 != n) {
+ if (!PACKET_get_net_3(&pkt, &cert_list_len)
+ || PACKET_remaining(&pkt) != cert_list_len) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
- for (nc = 0; nc < llen;) {
- n2l3(p, l);
- if ((l + nc + 3) > llen) {
+ while (PACKET_remaining(&pkt)) {
+ if (!PACKET_get_net_3(&pkt, &cert_len)
+ || !PACKET_get_bytes(&pkt, &certbytes, cert_len)) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
SSL_R_CERT_LENGTH_MISMATCH);
goto f_err;
}
- q = p;
- x = d2i_X509(NULL, &q, l);
+ certstart = certbytes;
+ x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
if (x == NULL) {
al = SSL_AD_BAD_CERTIFICATE;
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
goto f_err;
}
- if (q != (p + l)) {
+ if (certbytes != (certstart + cert_len)) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
x = NULL;
- nc += l + 3;
- p = q;
}
i = ssl_verify_cert_chain(s, sk);
s->session->peer_type = i;
X509_free(s->session->peer);
- CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+ X509_up_ref(x);
s->session->peer = x;
s->session->verify_result = s->verify_result;
unsigned char *q, md_buf[EVP_MAX_MD_SIZE * 2];
#endif
EVP_MD_CTX md_ctx;
- unsigned char *param, *p;
- int al, j, ok;
- long i, param_len, n, alg_k, alg_a;
+ int al, j, verify_ret, ok;
+ unsigned int i;
+ long n, alg_k, alg_a;
EVP_PKEY *pkey = NULL;
const EVP_MD *md = NULL;
#ifndef OPENSSL_NO_RSA
BN_CTX *bn_ctx = NULL;
EC_POINT *srvr_ecpoint = NULL;
int curve_nid = 0;
- int encoded_pt_len = 0;
+ unsigned int encoded_pt_len = 0;
#endif
+ PACKET pkt;
+ unsigned char *data, *param;
+ size_t startparam, endparam;
EVP_MD_CTX_init(&md_ctx);
return (1);
}
- param = p = (unsigned char *)s->init_msg;
+ if (!PACKET_buf_init(&pkt, s->init_msg, n)
+ || !PACKET_get_bookmark(&pkt, &startparam)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
#ifndef OPENSSL_NO_RSA
RSA_free(s->s3->peer_rsa_tmp);
s->s3->peer_ecdh_tmp = NULL;
#endif
- /* Total length of the parameters including the length prefix */
- param_len = 0;
-
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
al = SSL_AD_DECODE_ERROR;
/* PSK ciphersuites are preceded by an identity hint */
if (alg_k & SSL_PSK) {
- param_len = 2;
- if (param_len > n) {
+ if (!PACKET_get_net_2(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- n2s(p, i);
/*
* Store PSK identity hint for later use, hint is used in
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG);
goto f_err;
}
- if (i > n - param_len) {
+ if (PACKET_remaining(&pkt) < i) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
goto f_err;
}
- param_len += i;
OPENSSL_free(s->session->psk_identity_hint);
if (i != 0) {
- s->session->psk_identity_hint = BUF_strndup((char *)p, i);
+ unsigned char *hint = NULL;
+
+ if (!PACKET_get_bytes(&pkt, &hint, i)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ s->session->psk_identity_hint = BUF_strndup((char *)hint, i);
if (s->session->psk_identity_hint == NULL) {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
} else {
s->session->psk_identity_hint = NULL;
}
-
- p += i;
- n -= param_len;
}
/* Nothing else to do for plain PSK or RSAPSK */
#endif /* !OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_SRP
if (alg_k & SSL_kSRP) {
- param_len = 2;
- if (param_len > n) {
+ if (!PACKET_get_net_2(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- n2s(p, i);
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_N_LENGTH);
goto f_err;
}
- param_len += i;
- if ((s->srp_ctx.N = BN_bin2bn(p, i, NULL)) == NULL) {
+ if ((s->srp_ctx.N = BN_bin2bn(data, i, NULL)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- if (2 > n - param_len) {
+ if (!PACKET_get_net_2(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- param_len += 2;
-
- n2s(p, i);
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_G_LENGTH);
goto f_err;
}
- param_len += i;
- if ((s->srp_ctx.g = BN_bin2bn(p, i, NULL)) == NULL) {
+ if ((s->srp_ctx.g = BN_bin2bn(data, i, NULL)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- if (1 > n - param_len) {
+ if (!PACKET_get_1(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- param_len += 1;
-
- i = (unsigned int)(p[0]);
- p++;
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_S_LENGTH);
goto f_err;
}
- param_len += i;
- if ((s->srp_ctx.s = BN_bin2bn(p, i, NULL)) == NULL) {
+ if ((s->srp_ctx.s = BN_bin2bn(data, i, NULL)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- if (2 > n - param_len) {
+ if (!PACKET_get_net_2(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- param_len += 2;
-
- n2s(p, i);
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_B_LENGTH);
goto f_err;
}
- param_len += i;
- if ((s->srp_ctx.B = BN_bin2bn(p, i, NULL)) == NULL) {
+ if ((s->srp_ctx.B = BN_bin2bn(data, i, NULL)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- n -= param_len;
if (!srp_verify_server_param(s, &al)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SRP_PARAMETERS);
goto err;
}
- param_len = 2;
- if (param_len > n) {
+ if (!PACKET_get_net_2(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- n2s(p, i);
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_MODULUS_LENGTH);
goto f_err;
}
- param_len += i;
- if ((rsa->n = BN_bin2bn(p, i, rsa->n)) == NULL) {
+ if ((rsa->n = BN_bin2bn(data, i, rsa->n)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- if (2 > n - param_len) {
+ if (!PACKET_get_net_2(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- param_len += 2;
-
- n2s(p, i);
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_E_LENGTH);
goto f_err;
}
- param_len += i;
- if ((rsa->e = BN_bin2bn(p, i, rsa->e)) == NULL) {
+ if ((rsa->e = BN_bin2bn(data, i, rsa->e)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- n -= param_len;
/* this should be because we are using an export cipher */
if (alg_a & SSL_aRSA)
goto err;
}
- param_len = 2;
- if (param_len > n) {
+ if (!PACKET_get_net_2(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- n2s(p, i);
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_LENGTH);
goto f_err;
}
- param_len += i;
- if ((dh->p = BN_bin2bn(p, i, NULL)) == NULL) {
+ if ((dh->p = BN_bin2bn(data, i, NULL)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- if (2 > n - param_len) {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+ if (BN_is_zero(dh->p)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_VALUE);
goto f_err;
}
- param_len += 2;
- n2s(p, i);
+ if (!PACKET_get_net_2(&pkt, &i)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_LENGTH);
goto f_err;
}
- param_len += i;
- if ((dh->g = BN_bin2bn(p, i, NULL)) == NULL) {
+ if ((dh->g = BN_bin2bn(data, i, NULL)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- if (2 > n - param_len) {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+ if (BN_is_zero(dh->g)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_VALUE);
goto f_err;
}
- param_len += 2;
- n2s(p, i);
+ if (!PACKET_get_net_2(&pkt, &i)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
- if (i > n - param_len) {
+ if (!PACKET_get_bytes(&pkt, &data, i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_PUB_KEY_LENGTH);
goto f_err;
}
- param_len += i;
- if ((dh->pub_key = BN_bin2bn(p, i, NULL)) == NULL) {
+ if ((dh->pub_key = BN_bin2bn(data, i, NULL)) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB);
goto err;
}
- p += i;
- n -= param_len;
+
+ if (BN_is_zero(dh->pub_key)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_PUB_KEY_VALUE);
+ goto f_err;
+ }
if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
al = SSL_AD_HANDSHAKE_FAILURE;
/*
* XXX: For now we only support named (not generic) curves and the
- * ECParameters in this case is just three bytes. We also need one
- * byte for the length of the encoded point
+ * ECParameters in this case is just three bytes.
*/
- param_len = 4;
- if (param_len > n) {
+ if (!PACKET_get_bytes(&pkt, &data, 3)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
* Check curve is one of our preferences, if not server has sent an
* invalid curve. ECParameters is 3 bytes.
*/
- if (!tls1_check_curve(s, p, 3)) {
+ if (!tls1_check_curve(s, data, 3)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_CURVE);
goto f_err;
}
- if ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0) {
+ if ((curve_nid = tls1_ec_curve_id2nid(*(data + 2))) == 0) {
al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
goto f_err;
}
- p += 3;
-
/* Next, get the encoded ECPoint */
if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
((bn_ctx = BN_CTX_new()) == NULL)) {
goto err;
}
- encoded_pt_len = *p; /* length of encoded point */
- p += 1;
+ if (!PACKET_get_1(&pkt, &encoded_pt_len)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
- if ((encoded_pt_len > n - param_len) ||
+ if (!PACKET_get_bytes(&pkt, &data, encoded_pt_len) ||
(EC_POINT_oct2point(group, srvr_ecpoint,
- p, encoded_pt_len, bn_ctx) == 0)) {
+ data, encoded_pt_len, bn_ctx) == 0)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_ECPOINT);
goto f_err;
}
- param_len += encoded_pt_len;
-
- n -= param_len;
- p += encoded_pt_len;
/*
* The ECC/TLS specification does not mention the use of DSA to sign
}
#endif /* !OPENSSL_NO_EC */
- /* p points to the next byte, there are 'n' bytes left */
+ if (!PACKET_get_bookmark(&pkt, &endparam)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
/* if it was signed, check the signature */
if (pkey != NULL) {
if (SSL_USE_SIGALGS(s)) {
int rv;
- if (2 > n) {
+ if (!PACKET_get_bytes(&pkt, &data, 2)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+ rv = tls12_check_peer_sigalg(&md, s, data, pkey);
if (rv == -1)
goto err;
else if (rv == 0) {
#ifdef SSL_DEBUG
fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
#endif
- p += 2;
- n -= 2;
} else
md = EVP_sha1();
- if (2 > n) {
+ if (!PACKET_get_net_2(&pkt, &i)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
- n2s(p, i);
- n -= 2;
j = EVP_PKEY_size(pkey);
+ if (j < 0) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
/*
- * Check signature length. If n is 0 then signature is empty
+ * Check signature length
*/
- if ((i != n) || (n > j) || (n <= 0)) {
+ if (i > (unsigned int)j
+ || !PACKET_get_bytes(&pkt, &data, i)
+ || PACKET_remaining(&pkt) != 0) {
/* wrong packet length */
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_WRONG_SIGNATURE_LENGTH);
goto f_err;
}
+ if (!PACKET_goto_bookmark(&pkt, startparam)
+ || !PACKET_get_bytes(&pkt, ¶m, endparam - startparam)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
#ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) {
int num;
SSL3_RANDOM_SIZE);
EVP_DigestUpdate(&md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE);
- EVP_DigestUpdate(&md_ctx, param, param_len);
+ EVP_DigestUpdate(&md_ctx, param, endparam - startparam);
EVP_DigestFinal_ex(&md_ctx, q, &size);
q += size;
j += size;
}
- i = RSA_verify(NID_md5_sha1, md_buf, j, p, n, pkey->pkey.rsa);
- if (i < 0) {
+ verify_ret =
+ RSA_verify(NID_md5_sha1, md_buf, j, data, i, pkey->pkey.rsa);
+ if (verify_ret < 0) {
al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_RSA_DECRYPT);
goto f_err;
}
- if (i == 0) {
+ if (verify_ret == 0) {
/* bad signature */
al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
SSL3_RANDOM_SIZE);
EVP_VerifyUpdate(&md_ctx, &(s->s3->server_random[0]),
SSL3_RANDOM_SIZE);
- EVP_VerifyUpdate(&md_ctx, param, param_len);
- if (EVP_VerifyFinal(&md_ctx, p, (int)n, pkey) <= 0) {
+ EVP_VerifyUpdate(&md_ctx, param, endparam - startparam);
+ if (EVP_VerifyFinal(&md_ctx, data, (int)i, pkey) <= 0) {
/* bad signature */
al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
goto err;
}
/* still data left over */
- if (n != 0) {
+ if (PACKET_remaining(&pkt) != 0) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_EXTRA_DATA_IN_MESSAGE);
goto f_err;
}
int ssl3_get_certificate_request(SSL *s)
{
int ok, ret = 0;
- unsigned long n, nc, l;
- unsigned int llen, ctype_num, i;
+ unsigned long n;
+ unsigned int list_len, ctype_num, i, name_len;
X509_NAME *xn = NULL;
- const unsigned char *p, *q;
- unsigned char *d;
+ unsigned char *data;
+ unsigned char *namestart, *namebytes;
STACK_OF(X509_NAME) *ca_sk = NULL;
+ PACKET pkt;
n = s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_REQ_A,
}
}
- p = d = (unsigned char *)s->init_msg;
+ if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) {
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
}
/* get the certificate types */
- ctype_num = *(p++);
+ if (!PACKET_get_1(&pkt, &ctype_num)
+ || !PACKET_get_bytes(&pkt, &data, ctype_num)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
OPENSSL_free(s->cert->ctypes);
s->cert->ctypes = NULL;
if (ctype_num > SSL3_CT_NUMBER) {
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
goto err;
}
- memcpy(s->cert->ctypes, p, ctype_num);
+ memcpy(s->cert->ctypes, data, ctype_num);
s->cert->ctype_num = (size_t)ctype_num;
ctype_num = SSL3_CT_NUMBER;
}
for (i = 0; i < ctype_num; i++)
- s->s3->tmp.ctype[i] = p[i];
- p += p[-1];
+ s->s3->tmp.ctype[i] = data[i];
+
if (SSL_USE_SIGALGS(s)) {
- n2s(p, llen);
- /*
- * Check we have enough room for signature algorithms and following
- * length value.
- */
- if ((unsigned long)(p - d + llen + 2) > n) {
+ if (!PACKET_get_net_2(&pkt, &list_len)
+ || !PACKET_get_bytes(&pkt, &data, list_len)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,
- SSL_R_DATA_LENGTH_TOO_LONG);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
goto err;
}
+
/* Clear certificate digests and validity flags */
for (i = 0; i < SSL_PKEY_NUM; i++) {
s->s3->tmp.md[i] = NULL;
s->s3->tmp.valid_flags[i] = 0;
}
- if ((llen & 1) || !tls1_save_sigalgs(s, p, llen)) {
+ if ((list_len & 1) || !tls1_save_sigalgs(s, data, list_len)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,
SSL_R_SIGNATURE_ALGORITHMS_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
goto err;
}
- p += llen;
}
/* get the CA RDNs */
- n2s(p, llen);
-
- if ((unsigned long)(p - d + llen) != n) {
+ if (!PACKET_get_net_2(&pkt, &list_len)
+ || PACKET_remaining(&pkt) != list_len) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
goto err;
}
- for (nc = 0; nc < llen;) {
- n2s(p, l);
- if ((l + nc + 2) > llen) {
+ while (PACKET_remaining(&pkt)) {
+ if (!PACKET_get_net_2(&pkt, &name_len)
+ || !PACKET_get_bytes(&pkt, &namebytes, name_len)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
goto err;
}
- q = p;
+ namestart = namebytes;
- if ((xn = d2i_X509_NAME(NULL, &q, l)) == NULL) {
+ if ((xn = d2i_X509_NAME(NULL, (const unsigned char **)&namebytes,
+ name_len)) == NULL) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB);
goto err;
}
- if (q != (p + l)) {
+ if (namebytes != (namestart + name_len)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,
SSL_R_CA_DN_LENGTH_MISMATCH);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
goto err;
}
-
- p += l;
- nc += l + 2;
}
/* we should setup a certificate to return.... */
int ssl3_get_new_session_ticket(SSL *s)
{
- int ok, al, ret = 0, ticklen;
+ int ok, al, ret = 0;
+ unsigned int ticklen;
long n;
- const unsigned char *p;
- unsigned char *d;
+ PACKET pkt;
n = s->method->ssl_get_message(s,
SSL3_ST_CR_SESSION_TICKET_A,
if (!ok)
return ((int)n);
- if (n < 6) {
- /* need at least ticket_lifetime_hint + ticket length */
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+ if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
goto f_err;
}
- p = d = (unsigned char *)s->init_msg;
-
if (s->session->session_id_length > 0) {
int i = s->session_ctx->session_cache_mode;
SSL_SESSION *new_sess;
s->session = new_sess;
}
- n2l(p, s->session->tlsext_tick_lifetime_hint);
- n2s(p, ticklen);
- /* ticket_lifetime_hint + ticket_length + ticket */
- if (ticklen + 6 != n) {
+ if (!PACKET_get_net_4(&pkt, &s->session->tlsext_tick_lifetime_hint)
+ || !PACKET_get_net_2(&pkt, &ticklen)
+ || PACKET_remaining(&pkt) != ticklen) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
goto f_err;
SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
goto err;
}
- memcpy(s->session->tlsext_tick, p, ticklen);
+ if (!PACKET_copy_bytes(&pkt, s->session->tlsext_tick, ticklen)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
s->session->tlsext_ticklen = ticklen;
/*
* There are two ways to detect a resumed ticket session. One is to set
* elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
* SHA256 is disabled) hash of the ticket.
*/
- EVP_Digest(p, ticklen,
+ EVP_Digest(s->session->tlsext_tick, ticklen,
s->session->session_id, &s->session->session_id_length,
EVP_sha256(), NULL);
ret = 1;
{
int ok, al;
unsigned long resplen, n;
- const unsigned char *p;
+ unsigned int type;
+ PACKET pkt;
n = s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_STATUS_A,
if (!ok)
return ((int)n);
- if (n < 4) {
- /* need at least status type + length */
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+
+ if (!PACKET_buf_init(&pkt, s->init_msg, n)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_INTERNAL_ERROR);
goto f_err;
}
- p = (unsigned char *)s->init_msg;
- if (*p++ != TLSEXT_STATUSTYPE_ocsp) {
+ if (!PACKET_get_1(&pkt, &type)
+ || type != TLSEXT_STATUSTYPE_ocsp) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE);
goto f_err;
}
- n2l3(p, resplen);
- if (resplen + 4 != n) {
+ if (!PACKET_get_net_3(&pkt, &resplen)
+ || PACKET_remaining(&pkt) != resplen) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
+ s->tlsext_ocsp_resp = OPENSSL_malloc(resplen);
if (!s->tlsext_ocsp_resp) {
al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_MALLOC_FAILURE);
goto f_err;
}
+ if (!PACKET_copy_bytes(&pkt, s->tlsext_ocsp_resp, resplen)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
s->tlsext_ocsp_resplen = resplen;
if (s->ctx->tlsext_status_cb) {
int ret;
n = j + 2;
} else
#endif
- if (pkey->type == NID_id_GostR3410_94
- || pkey->type == NID_id_GostR3410_2001) {
+ if (pkey->type == NID_id_GostR3410_2001) {
unsigned char signbuf[64];
int i;
size_t sigsize = 64;
* the session ID. EAP-FAST (RFC 4851), however, relies on the next server
* message after the ServerHello to determine if the server is resuming.
* Therefore, we allow EAP-FAST to peek ahead.
- * ssl3_check_finished returns 1 if we are resuming from an external
- * pre-shared secret, we have a "ticket" and the next server handshake message
- * is Finished; and 0 otherwise. It returns -1 upon an error.
+ * ssl3_check_change returns 1 if we are resuming from an external
+ * pre-shared secret, we have a "ticket" and the next server message
+ * is CCS; and 0 otherwise. It returns -1 upon an error.
*/
-static int ssl3_check_finished(SSL *s)
+static int ssl3_check_change(SSL *s)
{
int ok = 0;
!s->session->tlsext_tick)
return 0;
- /* Need to permit this temporarily, in case the next message is Finished. */
- s->s3->flags |= SSL3_FLAGS_CCS_OK;
/*
* This function is called when we might get a Certificate message instead,
* so permit appropriate message length.
SSL3_ST_CR_CERT_A,
SSL3_ST_CR_CERT_B,
-1, s->max_cert_list, &ok);
- s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
if (!ok)
return -1;
s->s3->tmp.reuse_message = 1;
- if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
+ if (s->s3->tmp.message_type == SSL3_MT_CHANGE_CIPHER_SPEC)
return 1;
- /* If we're not done, then the CCS arrived early and we should bail. */
- if (s->s3->change_cipher_spec) {
- SSLerr(SSL_F_SSL3_CHECK_FINISHED, SSL_R_CCS_RECEIVED_EARLY);
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
- return -1;
- }
-
return 0;
}