Convert ssl3_send_client_key_exchange to CBB.
This relieves some complexity budget for adding Curve25519 to this
code.
This also adds a BN_bn2cbb_padded helper function since this seems to be a
fairly common need.
Change-Id: Ied0066fdaec9d02659abd6eb1a13f33502c9e198
Reviewed-on: https://boringssl-review.googlesource.com/6767
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/bn/convert.c b/crypto/bn/convert.c
index 0122709..1f7af64 100644
--- a/crypto/bn/convert.c
+++ b/crypto/bn/convert.c
@@ -63,6 +63,7 @@
#include <string.h>
#include <openssl/bio.h>
+#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -195,6 +196,11 @@
return 1;
}
+int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
+ uint8_t *ptr;
+ return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
+}
+
static const char hextable[] = "0123456789abcdef";
char *BN_bn2hex(const BIGNUM *bn) {
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index bc30d0a..6e971e4 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -253,6 +253,9 @@
* returns 0. Otherwise, it returns 1. */
OPENSSL_EXPORT int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in);
+/* BN_bn2cbb_padded behaves like |BN_bn2bin_padded| but writes to a |CBB|. */
+OPENSSL_EXPORT int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in);
+
/* BN_bn2hex returns an allocated string that contains a NUL-terminated, hex
* representation of |bn|. If |bn| is negative, the first char in the resulting
* string will be '-'. Returns NULL on allocation failure. */
diff --git a/ssl/internal.h b/ssl/internal.h
index bbbd939..a72d5d6 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1079,7 +1079,7 @@
int ssl3_send_cert_verify(SSL *s);
int ssl3_send_client_certificate(SSL *s);
int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
-int ssl3_send_client_key_exchange(SSL *s);
+int ssl3_send_client_key_exchange(SSL *ssl);
int ssl3_get_server_key_exchange(SSL *s);
int ssl3_get_server_certificate(SSL *s);
int ssl3_send_next_proto(SSL *ssl);
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 43a77d4..7f61c89 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1588,333 +1588,264 @@
OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned),
SIZE_T_IS_SMALLER_THAN_UNSIGNED);
-int ssl3_send_client_key_exchange(SSL *s) {
- uint8_t *p;
- int n = 0;
- uint32_t alg_k;
- uint32_t alg_a;
- uint8_t *q;
- EVP_PKEY *pkey = NULL;
- EC_KEY *clnt_ecdh = NULL;
- const EC_POINT *srvr_ecpoint = NULL;
- EVP_PKEY *srvr_pub_pkey = NULL;
- uint8_t *encodedPoint = NULL;
- int encoded_pt_len = 0;
- BN_CTX *bn_ctx = NULL;
- unsigned int psk_len = 0;
- uint8_t psk[PSK_MAX_PSK_LEN];
+int ssl3_send_client_key_exchange(SSL *ssl) {
+ if (ssl->state == SSL3_ST_CW_KEY_EXCH_B) {
+ return ssl_do_write(ssl);
+ }
+ assert(ssl->state == SSL3_ST_CW_KEY_EXCH_A);
+
uint8_t *pms = NULL;
size_t pms_len = 0;
+ EC_KEY *eckey = NULL;
+ CBB cbb;
+ if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
+ ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
+ goto err;
+ }
- if (s->state == SSL3_ST_CW_KEY_EXCH_A) {
- p = ssl_handshake_start(s);
+ uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
+ uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-
- /* If using a PSK key exchange, prepare the pre-shared key. */
- if (alg_a & SSL_aPSK) {
- char identity[PSK_MAX_IDENTITY_LEN + 1];
- size_t identity_len;
-
- if (s->psk_client_callback == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
- goto err;
- }
-
- memset(identity, 0, sizeof(identity));
- psk_len =
- s->psk_client_callback(s, s->s3->tmp.peer_psk_identity_hint, identity,
- sizeof(identity), psk, sizeof(psk));
- if (psk_len > PSK_MAX_PSK_LEN) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- } else if (psk_len == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
- }
-
- identity_len = OPENSSL_strnlen(identity, sizeof(identity));
- if (identity_len > PSK_MAX_IDENTITY_LEN) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- OPENSSL_free(s->session->psk_identity);
- s->session->psk_identity = BUF_strdup(identity);
- if (s->session->psk_identity == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Write out psk_identity. */
- s2n(identity_len, p);
- memcpy(p, identity, identity_len);
- p += identity_len;
- n = 2 + identity_len;
+ /* If using a PSK key exchange, prepare the pre-shared key. */
+ unsigned psk_len = 0;
+ uint8_t psk[PSK_MAX_PSK_LEN];
+ if (alg_a & SSL_aPSK) {
+ if (ssl->psk_client_callback == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
+ goto err;
}
- /* Depending on the key exchange method, compute |pms| and |pms_len|. */
- if (alg_k & SSL_kRSA) {
- size_t enc_pms_len;
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+ memset(identity, 0, sizeof(identity));
+ psk_len = ssl->psk_client_callback(
+ ssl, ssl->s3->tmp.peer_psk_identity_hint, identity, sizeof(identity),
+ psk, sizeof(psk));
+ if (psk_len == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
+ }
+ assert(psk_len <= PSK_MAX_PSK_LEN);
- pms_len = SSL_MAX_MASTER_KEY_LENGTH;
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ OPENSSL_free(ssl->session->psk_identity);
+ ssl->session->psk_identity = BUF_strdup(identity);
+ if (ssl->session->psk_identity == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- pkey = X509_get_pubkey(s->session->peer);
- if (pkey == NULL) {
- goto err;
- }
+ /* Write out psk_identity. */
+ CBB child;
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, (const uint8_t *)identity,
+ OPENSSL_strnlen(identity, sizeof(identity))) ||
+ !CBB_flush(&cbb)) {
+ goto err;
+ }
+ }
- RSA *rsa = EVP_PKEY_get0_RSA(pkey);
- if (rsa == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- EVP_PKEY_free(pkey);
- goto err;
- }
+ /* Depending on the key exchange method, compute |pms| and |pms_len|. */
+ if (alg_k & SSL_kRSA) {
+ pms_len = SSL_MAX_MASTER_KEY_LENGTH;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- s->session->key_exchange_info = EVP_PKEY_bits(pkey);
+ EVP_PKEY *pkey = X509_get_pubkey(ssl->session->peer);
+ if (pkey == NULL) {
+ goto err;
+ }
+
+ RSA *rsa = EVP_PKEY_get0_RSA(pkey);
+ if (rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
EVP_PKEY_free(pkey);
+ goto err;
+ }
- pms[0] = s->client_version >> 8;
- pms[1] = s->client_version & 0xff;
- if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
+ ssl->session->key_exchange_info = EVP_PKEY_bits(pkey);
+ EVP_PKEY_free(pkey);
+
+ pms[0] = ssl->client_version >> 8;
+ pms[1] = ssl->client_version & 0xff;
+ if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
+ goto err;
+ }
+
+ CBB child, *enc_pms = &cbb;
+ size_t enc_pms_len;
+ /* In TLS, there is a length prefix. */
+ if (ssl->version > SSL3_VERSION) {
+ if (!CBB_add_u16_length_prefixed(&cbb, &child)) {
goto err;
}
+ enc_pms = &child;
+ }
- s->session->master_key_length = SSL_MAX_MASTER_KEY_LENGTH;
-
- q = p;
- /* In TLS and beyond, reserve space for the length prefix. */
- if (s->version > SSL3_VERSION) {
- p += 2;
- n += 2;
- }
- if (!RSA_encrypt(rsa, &enc_pms_len, p, RSA_size(rsa), pms, pms_len,
- RSA_PKCS1_PADDING)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_RSA_ENCRYPT);
- goto err;
- }
- n += enc_pms_len;
-
- /* Log the premaster secret, if logging is enabled. */
- if (!ssl_log_rsa_client_key_exchange(s, p, enc_pms_len, pms, pms_len)) {
- goto err;
- }
-
- /* Fill in the length prefix. */
- if (s->version > SSL3_VERSION) {
- s2n(enc_pms_len, q);
- }
- } else if (alg_k & SSL_kDHE) {
- DH *dh_srvr, *dh_clnt;
- int dh_len;
- size_t pub_len;
-
- if (s->s3->tmp.peer_dh_tmp == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- dh_srvr = s->s3->tmp.peer_dh_tmp;
-
- /* generate a new random key */
- dh_clnt = DHparams_dup(dh_srvr);
- if (dh_clnt == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
- goto err;
- }
- if (!DH_generate_key(dh_clnt)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
- DH_free(dh_clnt);
- goto err;
- }
-
- pms_len = DH_size(dh_clnt);
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- DH_free(dh_clnt);
- goto err;
- }
-
- dh_len = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);
- if (dh_len <= 0) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
- DH_free(dh_clnt);
- goto err;
- }
- pms_len = dh_len;
-
- /* send off the data */
- pub_len = BN_num_bytes(dh_clnt->pub_key);
- s2n(pub_len, p);
- BN_bn2bin(dh_clnt->pub_key, p);
- n += 2 + pub_len;
-
- DH_free(dh_clnt);
- } else if (alg_k & SSL_kECDHE) {
- const EC_GROUP *srvr_group = NULL;
- EC_KEY *tkey;
- int ecdh_len;
-
- if (s->s3->tmp.peer_ecdh_tmp == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- tkey = s->s3->tmp.peer_ecdh_tmp;
-
- srvr_group = EC_KEY_get0_group(tkey);
- srvr_ecpoint = EC_KEY_get0_public_key(tkey);
- if (srvr_group == NULL || srvr_ecpoint == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- clnt_ecdh = EC_KEY_new();
- if (clnt_ecdh == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_EC_LIB);
- goto err;
- }
-
- /* Generate a new ECDH key pair */
- if (!EC_KEY_generate_key(clnt_ecdh)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB);
- goto err;
- }
-
- unsigned field_size = EC_GROUP_get_degree(srvr_group);
- if (field_size == 0) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB);
- goto err;
- }
-
- pms_len = (field_size + 7) / 8;
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- ecdh_len = ECDH_compute_key(pms, pms_len, srvr_ecpoint, clnt_ecdh, NULL);
- if (ecdh_len <= 0) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB);
- goto err;
- }
- pms_len = ecdh_len;
-
- /* First check the size of encoding and allocate memory accordingly. */
- encoded_pt_len =
- EC_POINT_point2oct(srvr_group, EC_KEY_get0_public_key(clnt_ecdh),
- POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
-
- encodedPoint =
- (uint8_t *)OPENSSL_malloc(encoded_pt_len * sizeof(uint8_t));
- bn_ctx = BN_CTX_new();
- if (encodedPoint == NULL || bn_ctx == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Encode the public key */
- encoded_pt_len = EC_POINT_point2oct(
- srvr_group, EC_KEY_get0_public_key(clnt_ecdh),
- POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encoded_pt_len, bn_ctx);
-
- *p = encoded_pt_len; /* length of encoded point */
- /* Encoded point will be copied here */
- p += 1;
- n += 1;
- /* copy the point */
- memcpy(p, encodedPoint, encoded_pt_len);
- /* increment n to account for length field */
- n += encoded_pt_len;
-
- /* Free allocated memory */
- BN_CTX_free(bn_ctx);
- bn_ctx = NULL;
- OPENSSL_free(encodedPoint);
- encodedPoint = NULL;
- EC_KEY_free(clnt_ecdh);
- clnt_ecdh = NULL;
- EVP_PKEY_free(srvr_pub_pkey);
- srvr_pub_pkey = NULL;
- } else if (alg_k & SSL_kPSK) {
- /* For plain PSK, other_secret is a block of 0s with the same length as
- * the pre-shared key. */
- pms_len = psk_len;
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memset(pms, 0, pms_len);
- } else {
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ uint8_t *ptr;
+ if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) ||
+ !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms, pms_len,
+ RSA_PKCS1_PADDING) ||
+ /* Log the premaster secret, if logging is enabled. */
+ !ssl_log_rsa_client_key_exchange(ssl, ptr, enc_pms_len, pms, pms_len) ||
+ !CBB_did_write(enc_pms, enc_pms_len) ||
+ !CBB_flush(&cbb)) {
+ goto err;
+ }
+ } else if (alg_k & SSL_kDHE) {
+ if (ssl->s3->tmp.peer_dh_tmp == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto err;
}
+ DH *peer_dh = ssl->s3->tmp.peer_dh_tmp;
- /* For a PSK cipher suite, other_secret is combined with the pre-shared
- * key. */
- if (alg_a & SSL_aPSK) {
- CBB cbb, child;
- uint8_t *new_pms;
- size_t new_pms_len;
-
- CBB_zero(&cbb);
- if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len) ||
- !CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, pms, pms_len) ||
- !CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, psk, psk_len) ||
- !CBB_finish(&cbb, &new_pms, &new_pms_len)) {
- CBB_cleanup(&cbb);
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- OPENSSL_cleanse(pms, pms_len);
- OPENSSL_free(pms);
- pms = new_pms;
- pms_len = new_pms_len;
- }
-
- /* The message must be added to the finished hash before calculating the
- * master secret. */
- if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) {
+ /* Generate a keypair. */
+ DH *dh = DHparams_dup(peer_dh);
+ if (dh == NULL || !DH_generate_key(dh)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
+ DH_free(dh);
goto err;
}
- s->state = SSL3_ST_CW_KEY_EXCH_B;
- s->session->master_key_length = s->enc_method->generate_master_secret(
- s, s->session->master_key, pms, pms_len);
- if (s->session->master_key_length == 0) {
+ pms_len = DH_size(dh);
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ DH_free(dh);
goto err;
}
- s->session->extended_master_secret = s->s3->tmp.extended_master_secret;
- OPENSSL_cleanse(pms, pms_len);
- OPENSSL_free(pms);
+
+ int dh_len = DH_compute_key(pms, peer_dh->pub_key, dh);
+ if (dh_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
+ DH_free(dh);
+ goto err;
+ }
+ pms_len = dh_len;
+
+ /* Write the public key. */
+ CBB child;
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !BN_bn2cbb_padded(&child, BN_num_bytes(dh->pub_key), dh->pub_key) ||
+ !CBB_flush(&cbb)) {
+ DH_free(dh);
+ goto err;
+ }
+
+ DH_free(dh);
+ } else if (alg_k & SSL_kECDHE) {
+ if (ssl->s3->tmp.peer_ecdh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ EC_KEY *peer_eckey = ssl->s3->tmp.peer_ecdh_tmp;
+
+ const EC_GROUP *group = EC_KEY_get0_group(peer_eckey);
+ eckey = EC_KEY_new();
+ if (eckey == NULL ||
+ !EC_KEY_set_group(eckey, group) ||
+ !EC_KEY_generate_key(eckey)) {
+ goto err;
+ }
+
+ pms_len = (EC_GROUP_get_degree(group) + 7) / 8;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ int ecdh_len = ECDH_compute_key(
+ pms, pms_len, EC_KEY_get0_public_key(peer_eckey), eckey, NULL);
+ if (ecdh_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_ECDH_LIB);
+ goto err;
+ }
+ pms_len = ecdh_len;
+
+ size_t encoded_len =
+ EC_POINT_point2oct(group, EC_KEY_get0_public_key(eckey),
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+ uint8_t *ptr;
+ CBB child;
+ if (encoded_len == 0 ||
+ !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ !CBB_add_space(&child, &ptr, encoded_len) ||
+ EC_POINT_point2oct(group, EC_KEY_get0_public_key(eckey),
+ POINT_CONVERSION_UNCOMPRESSED, ptr, encoded_len,
+ NULL) != encoded_len ||
+ !CBB_flush(&cbb)) {
+ goto err;
+ }
+
+ EC_KEY_free(eckey);
+ eckey = NULL;
+ } else if (alg_k & SSL_kPSK) {
+ /* For plain PSK, other_secret is a block of 0s with the same length as
+ * the pre-shared key. */
+ pms_len = psk_len;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(pms, 0, pms_len);
+ } else {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ goto err;
}
+ /* For a PSK cipher suite, other_secret is combined with the pre-shared
+ * key. */
+ if (alg_a & SSL_aPSK) {
+ CBB pms_cbb, child;
+ uint8_t *new_pms;
+ size_t new_pms_len;
+
+ CBB_zero(&pms_cbb);
+ if (!CBB_init(&pms_cbb, 2 + psk_len + 2 + pms_len) ||
+ !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+ !CBB_add_bytes(&child, pms, pms_len) ||
+ !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+ !CBB_add_bytes(&child, psk, psk_len) ||
+ !CBB_finish(&pms_cbb, &new_pms, &new_pms_len)) {
+ CBB_cleanup(&pms_cbb);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ pms = new_pms;
+ pms_len = new_pms_len;
+ }
+
+ /* The message must be added to the finished hash before calculating the
+ * master secret. */
+ size_t length;
+ if (!CBB_finish(&cbb, NULL, &length) ||
+ !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE, length)) {
+ goto err;
+ }
+ ssl->state = SSL3_ST_CW_KEY_EXCH_B;
+
+ ssl->session->master_key_length = ssl->enc_method->generate_master_secret(
+ ssl, ssl->session->master_key, pms, pms_len);
+ if (ssl->session->master_key_length == 0) {
+ goto err;
+ }
+ ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret;
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+
/* SSL3_ST_CW_KEY_EXCH_B */
- return s->method->do_write(s);
+ return ssl_do_write(ssl);
err:
- BN_CTX_free(bn_ctx);
- OPENSSL_free(encodedPoint);
- EC_KEY_free(clnt_ecdh);
- EVP_PKEY_free(srvr_pub_pkey);
- if (pms) {
+ EC_KEY_free(eckey);
+ if (pms != NULL) {
OPENSSL_cleanse(pms, pms_len);
OPENSSL_free(pms);
}
@@ -2124,12 +2055,6 @@
return ssl_do_write(ssl);
}
-static int write_32_byte_big_endian(CBB *out, const BIGNUM *in) {
- uint8_t *ptr;
- return CBB_add_space(out, &ptr, 32) &&
- BN_bn2bin_padded(ptr, 32, in);
-}
-
int ssl3_send_channel_id(SSL *ssl) {
if (ssl->state == SSL3_ST_CW_CHANNEL_ID_B) {
return ssl_do_write(ssl);
@@ -2190,10 +2115,10 @@
ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
!CBB_add_u16(&cbb, TLSEXT_TYPE_channel_id) ||
!CBB_add_u16_length_prefixed(&cbb, &child) ||
- !write_32_byte_big_endian(&child, x) ||
- !write_32_byte_big_endian(&child, y) ||
- !write_32_byte_big_endian(&child, sig->r) ||
- !write_32_byte_big_endian(&child, sig->s) ||
+ !BN_bn2cbb_padded(&child, 32, x) ||
+ !BN_bn2cbb_padded(&child, 32, y) ||
+ !BN_bn2cbb_padded(&child, 32, sig->r) ||
+ !BN_bn2cbb_padded(&child, 32, sig->s) ||
!CBB_finish(&cbb, NULL, &length) ||
!ssl_set_handshake_header(ssl, SSL3_MT_ENCRYPTED_EXTENSIONS, length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);