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;
}
/* Check if it is anon DH/ECDH, SRP auth */
/* or PSK */
- if (!
- (s->s3->tmp.
- new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
- && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ if (!(s->s3->tmp.new_cipher->algorithm_auth &
+ (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
ret = ssl3_get_server_certificate(s);
if (ret <= 0)
goto end;
goto end;
s->state = SSL3_ST_CW_FLUSH;
- /* clear flags */
- s->s3->flags &= ~SSL3_FLAGS_POP_BUFFER;
if (s->hit) {
s->s3->tmp.next_state = SSL_ST_OK;
- if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED) {
- s->state = SSL_ST_OK;
- s->s3->flags |= SSL3_FLAGS_POP_BUFFER;
- s->s3->delay_buf_pop_ret = 0;
- }
} else {
/*
* Allow NewSessionTicket if ticket expected
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)
BUF_MEM_free(s->init_buf);
s->init_buf = NULL;
- /*
- * If we are not 'joining' the last two packets, remove the
- * buffering now
- */
- if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
- ssl_free_wbio_buffer(s);
- /* else do it later in ssl3_write */
+ /* remove the buffering */
+ ssl_free_wbio_buffer(s);
s->init_num = 0;
s->renegotiate = 0;
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);
* Can't skip server key exchange if this is an ephemeral
* ciphersuite.
*/
- if (alg_k & (SSL_kDHE | SSL_kECDHE)) {
+ if (alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK)) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
al = SSL_AD_UNEXPECTED_MESSAGE;
goto f_err;
al = SSL_AD_DECODE_ERROR;
#ifndef OPENSSL_NO_PSK
- if (alg_k & SSL_kPSK) {
- char tmp_id_hint[PSK_MAX_IDENTITY_LEN + 1];
+ /* PSK ciphersuites are preceded by an identity hint */
+ if (alg_k & SSL_PSK) {
param_len = 2;
if (param_len > n) {
}
param_len += i;
- /*
- * If received PSK identity hint contains NULL characters, the hint
- * is truncated from the first NULL. p may not be ending with NULL,
- * so create a NULL-terminated string.
- */
- memcpy(tmp_id_hint, p, i);
- memset(tmp_id_hint + i, 0, PSK_MAX_IDENTITY_LEN + 1 - i);
OPENSSL_free(s->session->psk_identity_hint);
- s->session->psk_identity_hint = BUF_strdup(tmp_id_hint);
- if (s->session->psk_identity_hint == NULL) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
- goto f_err;
+ if (i != 0) {
+ s->session->psk_identity_hint = BUF_strndup((char *)p, i);
+ if (s->session->psk_identity_hint == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ } else {
+ s->session->psk_identity_hint = NULL;
}
p += i;
n -= param_len;
+ }
+
+ /* Nothing else to do for plain PSK or RSAPSK */
+ if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
} else
#endif /* !OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_SRP
if (0) ;
#endif
#ifndef OPENSSL_NO_DH
- else if (alg_k & SSL_kDHE) {
+ else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
if ((dh = DH_new()) == NULL) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_DH_LIB);
goto err;
}
p += i;
+ if (BN_is_zero(dh->p)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_P_VALUE);
+ goto f_err;
+ }
+
+
if (2 > n - param_len) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
p += i;
+ if (BN_is_zero(dh->g)) {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_BAD_DH_G_VALUE);
+ goto f_err;
+ }
+
if (2 > n - param_len) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
goto f_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;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
#endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_EC
- else if (alg_k & SSL_kECDHE) {
+ else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
EC_GROUP *ngroup;
const EC_GROUP *group;
}
}
} else {
- /* aNULL, aSRP or kPSK do not need public keys */
- if (!(alg_a & (SSL_aNULL | SSL_aSRP)) && !(alg_k & SSL_kPSK)) {
+ /* aNULL, aSRP or PSK do not need public keys */
+ if (!(alg_a & (SSL_aNULL | SSL_aSRP)) && !(alg_k & SSL_PSK)) {
/* Might be wrong key type, check it */
if (ssl3_check_cert_and_algorithm(s))
/* Otherwise this shouldn't happen */
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;
{
unsigned char *p;
int n;
+#ifndef OPENSSL_NO_PSK
+ size_t pskhdrlen = 0;
+#endif
unsigned long alg_k;
#ifndef OPENSSL_NO_RSA
unsigned char *q;
#endif
unsigned char *pms = NULL;
size_t pmslen = 0;
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
if (s->state == SSL3_ST_CW_KEY_EXCH_A) {
p = ssl_handshake_start(s);
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+#ifndef OPENSSL_NO_PSK
+ if (alg_k & SSL_PSK) {
+ int psk_err = 1;
+ /*
+ * The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a
+ * \0-terminated identity. The last byte is for us for simulating
+ * strnlen.
+ */
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+ size_t identitylen;
+ unsigned char psk[PSK_MAX_PSK_LEN];
+ size_t psklen;
+
+ if (s->psk_client_callback == NULL) {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ SSL_R_PSK_NO_CLIENT_CB);
+ goto err;
+ }
+
+ memset(identity, 0, sizeof(identity));
+
+ psklen = s->psk_client_callback(s, s->session->psk_identity_hint,
+ identity, sizeof(identity) - 1,
+ psk, sizeof(psk));
+
+ if (psklen > PSK_MAX_PSK_LEN) {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto psk_err;
+ } else if (psklen == 0) {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ goto psk_err;
+ }
+
+ OPENSSL_free(s->s3->tmp.psk);
+ s->s3->tmp.psk = BUF_memdup(psk, psklen);
+ OPENSSL_cleanse(psk, psklen);
+
+ if (s->s3->tmp.psk == NULL) {
+ OPENSSL_cleanse(identity, sizeof(identity));
+ goto memerr;
+ }
+
+ s->s3->tmp.psklen = psklen;
+
+ identitylen = strlen(identity);
+ if (identitylen > PSK_MAX_IDENTITY_LEN) {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto psk_err;
+ }
+ OPENSSL_free(s->session->psk_identity);
+ s->session->psk_identity = BUF_strdup(identity);
+ if (s->session->psk_identity == NULL) {
+ OPENSSL_cleanse(identity, sizeof(identity));
+ goto memerr;
+ }
+
+ s2n(identitylen, p);
+ memcpy(p, identity, identitylen);
+ pskhdrlen = 2 + identitylen;
+ p += identitylen;
+ psk_err = 0;
+ psk_err:
+ OPENSSL_cleanse(identity, sizeof(identity));
+ if (psk_err != 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
+ }
+ }
+ if (alg_k & SSL_kPSK) {
+ n = 0;
+ } else
+#endif
/* Fool emacs indentation */
if (0) {
}
#ifndef OPENSSL_NO_RSA
- else if (alg_k & SSL_kRSA) {
+ else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
RSA *rsa;
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
pms = OPENSSL_malloc(pmslen);
}
#endif
#ifndef OPENSSL_NO_DH
- else if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) {
+ else if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd | SSL_kDHEPSK)) {
DH *dh_srvr, *dh_clnt;
if (s->s3->peer_dh_tmp != NULL)
dh_srvr = s->s3->peer_dh_tmp;
#endif
#ifndef OPENSSL_NO_EC
- else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)) {
+ else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) {
const EC_GROUP *srvr_group = NULL;
EC_KEY *tkey;
int ecdh_clnt_cert = 0;
goto err;
}
}
-#endif
-#ifndef OPENSSL_NO_PSK
- else if (alg_k & SSL_kPSK) {
- /*
- * The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a
- * \0-terminated identity. The last byte is for us for simulating
- * strnlen.
- */
- char identity[PSK_MAX_IDENTITY_LEN + 2];
- size_t identity_len;
- unsigned char *t = NULL;
- unsigned int psk_len = 0;
- int psk_err = 1;
-
- n = 0;
- if (s->psk_client_callback == NULL) {
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- SSL_R_PSK_NO_CLIENT_CB);
- goto err;
- }
-
- memset(identity, 0, sizeof(identity));
- /* Allocate maximum size buffer */
- pmslen = PSK_MAX_PSK_LEN * 2 + 4;
- pms = OPENSSL_malloc(pmslen);
- if (!pms)
- goto memerr;
-
- psk_len = s->psk_client_callback(s, s->session->psk_identity_hint,
- identity, sizeof(identity) - 1,
- pms, pmslen);
- if (psk_len > PSK_MAX_PSK_LEN) {
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto psk_err;
- } else if (psk_len == 0) {
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- SSL_R_PSK_IDENTITY_NOT_FOUND);
- goto psk_err;
- }
- /* Change pmslen to real length */
- pmslen = 2 + psk_len + 2 + psk_len;
- identity[PSK_MAX_IDENTITY_LEN + 1] = '\0';
- identity_len = strlen(identity);
- if (identity_len > PSK_MAX_IDENTITY_LEN) {
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto psk_err;
- }
- /* create PSK pre_master_secret */
- t = pms;
- memmove(pms + psk_len + 4, pms, psk_len);
- s2n(psk_len, t);
- memset(t, 0, psk_len);
- t += psk_len;
- s2n(psk_len, t);
-
- OPENSSL_free(s->session->psk_identity);
- s->session->psk_identity = BUF_strdup(identity);
- if (s->session->psk_identity == NULL) {
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
- goto psk_err;
- }
-
- s2n(identity_len, p);
- memcpy(p, identity, identity_len);
- n = 2 + identity_len;
- psk_err = 0;
- psk_err:
- OPENSSL_cleanse(identity, sizeof(identity));
- if (psk_err != 0) {
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
- }
- }
#endif
else {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
goto err;
}
+#ifndef OPENSSL_NO_PSK
+ n += pskhdrlen;
+#endif
+
if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
n = ssl_do_write(s);
#ifndef OPENSSL_NO_SRP
/* Check for SRP */
- if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+ if (alg_k & SSL_kSRP) {
/*
* If everything written generate master key: no need to save PMS as
* srp_generate_client_master_secret generates it internally.
pms = s->s3->tmp.pms;
pmslen = s->s3->tmp.pmslen;
}
- if (pms == NULL) {
+ if (pms == NULL && !(alg_k & SSL_kPSK)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
goto err;
OPENSSL_free(encodedPoint);
EC_KEY_free(clnt_ecdh);
EVP_PKEY_free(srvr_pub_pkey);
+#endif
+#ifndef OPENSSL_NO_PSK
+ OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
+ s->s3->tmp.psk = NULL;
#endif
s->state = SSL_ST_ERR;
return (-1);
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;
}
#endif
#ifndef OPENSSL_NO_RSA
- if (alg_k & SSL_kRSA) {
+ if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
* 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;
}