err:
/* No valid transition found */
ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
- SSLerr(SSL_F_READ_STATE_MACHINE, SSL_R_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
return ret;
}
-MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
+static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
{
- EVP_MD_CTX *md_ctx;
- int al, j;
- long alg_k, alg_a;
- EVP_PKEY *pkey = NULL;
- const EVP_MD *md = NULL;
-#ifndef OPENSSL_NO_RSA
- RSA *rsa = NULL;
-#endif
-#ifndef OPENSSL_NO_EC
- EVP_PKEY_CTX *pctx = NULL;
+#ifndef OPENSSL_NO_PSK
+ PACKET psk_identity_hint;
+
+ /* PSK ciphersuites are preceded by an identity hint */
+
+ if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /*
+ * Store PSK identity hint for later use, hint is used in
+ * tls_construct_client_key_exchange. Assume that the maximum length of
+ * a PSK identity hint can be as long as the maximum length of a PSK
+ * identity.
+ */
+ if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+
+ if (PACKET_remaining(&psk_identity_hint) == 0) {
+ OPENSSL_free(s->session->psk_identity_hint);
+ s->session->psk_identity_hint = NULL;
+ } else if (!PACKET_strndup(&psk_identity_hint,
+ &s->session->psk_identity_hint)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ return 1;
+#else
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
#endif
- PACKET save_param_start, signature;
+}
- md_ctx = EVP_MD_CTX_new();
- if (md_ctx == NULL) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
- goto f_err;
+static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+{
+#ifndef OPENSSL_NO_SRP
+ PACKET prime, generator, salt, server_pub;
+
+ if (!PACKET_get_length_prefixed_2(pkt, &prime)
+ || !PACKET_get_length_prefixed_2(pkt, &generator)
+ || !PACKET_get_length_prefixed_1(pkt, &salt)
+ || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+ return 0;
}
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ if ((s->srp_ctx.N =
+ BN_bin2bn(PACKET_data(&prime),
+ PACKET_remaining(&prime), NULL)) == NULL
+ || (s->srp_ctx.g =
+ BN_bin2bn(PACKET_data(&generator),
+ PACKET_remaining(&generator), NULL)) == NULL
+ || (s->srp_ctx.s =
+ BN_bin2bn(PACKET_data(&salt),
+ PACKET_remaining(&salt), NULL)) == NULL
+ || (s->srp_ctx.B =
+ BN_bin2bn(PACKET_data(&server_pub),
+ PACKET_remaining(&server_pub), NULL)) == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+ return 0;
+ }
- save_param_start = *pkt;
+ if (!srp_verify_server_param(s, al)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SRP_PARAMETERS);
+ return 0;
+ }
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
- EVP_PKEY_free(s->s3->peer_tmp);
- s->s3->peer_tmp = NULL;
+ /* We must check if there is a certificate */
+ if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA|SSL_aDSS))
+ *pkey = X509_get0_pubkey(s->session->peer);
+
+ return 1;
+#else
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
#endif
+}
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
+{
+#ifndef OPENSSL_NO_DH
+ PACKET prime, generator, pub_key;
+ EVP_PKEY *peer_tmp = NULL;
- al = SSL_AD_DECODE_ERROR;
+ DH *dh = NULL;
+ BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
-#ifndef OPENSSL_NO_PSK
- /* PSK ciphersuites are preceded by an identity hint */
- if (alg_k & SSL_PSK) {
- PACKET psk_identity_hint;
- if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
+ if (!PACKET_get_length_prefixed_2(pkt, &prime)
+ || !PACKET_get_length_prefixed_2(pkt, &generator)
+ || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
- /*
- * Store PSK identity hint for later use, hint is used in
- * ssl3_send_client_key_exchange. Assume that the maximum length of
- * a PSK identity hint can be as long as the maximum length of a PSK
- * identity.
- */
- if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG);
- goto f_err;
- }
+ peer_tmp = EVP_PKEY_new();
+ dh = DH_new();
- if (PACKET_remaining(&psk_identity_hint) == 0) {
- OPENSSL_free(s->session->psk_identity_hint);
- s->session->psk_identity_hint = NULL;
- } else if (!PACKET_strndup(&psk_identity_hint,
- &s->session->psk_identity_hint)) {
- al = SSL_AD_INTERNAL_ERROR;
- goto f_err;
- }
+ if (peer_tmp == NULL || dh == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto err;
}
- /* Nothing else to do for plain PSK or RSAPSK */
- if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
- } else
-#endif /* !OPENSSL_NO_PSK */
- /*
- * Dummy "if" to ensure sane C code in the event of various OPENSSL_NO_*
- * options
- */
- if (0) {
+ p = BN_bin2bn(PACKET_data(&prime), PACKET_remaining(&prime), NULL);
+ g = BN_bin2bn(PACKET_data(&generator), PACKET_remaining(&generator),
+ NULL);
+ bnpub_key = BN_bin2bn(PACKET_data(&pub_key), PACKET_remaining(&pub_key),
+ NULL);
+ if (p == NULL || g == NULL || bnpub_key == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto err;
}
-#ifndef OPENSSL_NO_SRP
- else if (alg_k & SSL_kSRP) {
- PACKET prime, generator, salt, server_pub;
- if (!PACKET_get_length_prefixed_2(pkt, &prime)
- || !PACKET_get_length_prefixed_2(pkt, &generator)
- || !PACKET_get_length_prefixed_1(pkt, &salt)
- || !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- if ((s->srp_ctx.N =
- BN_bin2bn(PACKET_data(&prime),
- PACKET_remaining(&prime), NULL)) == NULL
- || (s->srp_ctx.g =
- BN_bin2bn(PACKET_data(&generator),
- PACKET_remaining(&generator), NULL)) == NULL
- || (s->srp_ctx.s =
- BN_bin2bn(PACKET_data(&salt),
- PACKET_remaining(&salt), NULL)) == NULL
- || (s->srp_ctx.B =
- BN_bin2bn(PACKET_data(&server_pub),
- PACKET_remaining(&server_pub), NULL)) == NULL) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
- goto err;
- }
+ if (BN_is_zero(p) || BN_is_zero(g) || BN_is_zero(bnpub_key)) {
+ *al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
+ goto err;
+ }
- if (!srp_verify_server_param(s, &al)) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SRP_PARAMETERS);
- goto f_err;
- }
+ if (!DH_set0_pqg(dh, p, NULL, g)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto err;
+ }
+ p = g = NULL;
-/* We must check if there is a certificate */
- if (alg_a & (SSL_aRSA|SSL_aDSS))
- pkey = X509_get0_pubkey(s->session->peer);
+ if (!DH_set0_key(dh, bnpub_key, NULL)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto err;
}
-#endif /* !OPENSSL_NO_SRP */
-#ifndef OPENSSL_NO_DH
- else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
- PACKET prime, generator, pub_key;
- EVP_PKEY *peer_tmp = NULL;
+ bnpub_key = NULL;
- DH *dh = NULL;
- BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
+ if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
+ goto err;
+ }
- if (!PACKET_get_length_prefixed_2(pkt, &prime)
- || !PACKET_get_length_prefixed_2(pkt, &generator)
- || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
+ if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ goto err;
+ }
- peer_tmp = EVP_PKEY_new();
- dh = DH_new();
+ s->s3->peer_tmp = peer_tmp;
- if (peer_tmp == NULL || dh == NULL) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
- goto dherr;
- }
+ /*
+ * FIXME: This makes assumptions about which ciphersuites come with
+ * public keys. We should have a less ad-hoc way of doing this
+ */
+ if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA|SSL_aDSS))
+ *pkey = X509_get0_pubkey(s->session->peer);
+ /* else anonymous DH, so no certificate or pkey. */
- p = BN_bin2bn(PACKET_data(&prime), PACKET_remaining(&prime), NULL);
- g = BN_bin2bn(PACKET_data(&generator), PACKET_remaining(&generator),
- NULL);
- bnpub_key = BN_bin2bn(PACKET_data(&pub_key), PACKET_remaining(&pub_key),
- NULL);
- if (p == NULL || g == NULL || bnpub_key == NULL) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
- goto dherr;
- }
+ return 1;
- if (BN_is_zero(p) || BN_is_zero(g) || BN_is_zero(bnpub_key)) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
- goto dherr;
- }
+ err:
+ BN_free(p);
+ BN_free(g);
+ BN_free(bnpub_key);
+ DH_free(dh);
+ EVP_PKEY_free(peer_tmp);
- if (!DH_set0_pqg(dh, p, NULL, g)) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
- goto dherr;
- }
- p = g = NULL;
+ return 0;
+#else
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
- if (!DH_set0_key(dh, bnpub_key, NULL)) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
- goto dherr;
- }
- bnpub_key = NULL;
+MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
+{
+ EVP_MD_CTX *md_ctx;
+ int al = -1;
+ long alg_k, alg_a;
+ EVP_PKEY *pkey = NULL;
+ PACKET save_param_start, signature;
- if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
- goto dherr;
- }
+ md_ctx = EVP_MD_CTX_new();
+ if (md_ctx == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
- if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
- goto dherr;
- }
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
- s->s3->peer_tmp = peer_tmp;
+ save_param_start = *pkt;
- goto dhend;
- dherr:
- BN_free(p);
- BN_free(g);
- BN_free(bnpub_key);
- DH_free(dh);
- EVP_PKEY_free(peer_tmp);
- goto f_err;
- dhend:
- /*
- * FIXME: This makes assumptions about which ciphersuites come with
- * public keys. We should have a less ad-hoc way of doing this
- */
- if (alg_a & (SSL_aRSA|SSL_aDSS))
- pkey = X509_get0_pubkey(s->session->peer);
- /* else anonymous DH, so no certificate or pkey. */
+#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
+ EVP_PKEY_free(s->s3->peer_tmp);
+ s->s3->peer_tmp = NULL;
+#endif
+
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ if (alg_k & SSL_PSK) {
+ if (!tls_process_ske_psk_preamble(s, pkt, &al))
+ goto err;
}
-#endif /* !OPENSSL_NO_DH */
+ /* Nothing else to do for plain PSK or RSAPSK */
+ if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
+ } else if (alg_k & SSL_kSRP) {
+ if (!tls_process_ske_srp(s, pkt, &pkey, &al))
+ goto err;
+ } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
+ if (!tls_process_ske_dhe(s, pkt, &pkey, &al))
+ goto err;
+ }
#ifndef OPENSSL_NO_EC
else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
PACKET encoded_pt;
const unsigned char *ecparams;
int curve_nid;
+ EVP_PKEY_CTX *pctx = NULL;
/*
* Extract elliptic curve parameters and the server's ephemeral ECDH
|| EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ EVP_PKEY_CTX_free(pctx);
goto f_err;
}
EVP_PKEY_CTX_free(pctx);
/* if it was signed, check the signature */
if (pkey != NULL) {
PACKET params;
+ int maxsig;
+ const EVP_MD *md = NULL;
/*
* |pkt| now points to the beginning of the signature, so the difference
* equals the length of the parameters.
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
- j = EVP_PKEY_size(pkey);
- if (j < 0) {
+ maxsig = EVP_PKEY_size(pkey);
+ if (maxsig < 0) {
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto f_err;
}
/*
* Check signature length
*/
- if (PACKET_remaining(&signature) > (size_t)j) {
+ if (PACKET_remaining(&signature) > (size_t)maxsig) {
/* wrong packet length */
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_WRONG_SIGNATURE_LENGTH);
goto f_err;
EVP_MD_CTX_free(md_ctx);
return MSG_PROCESS_CONTINUE_READING;
f_err:
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ if (al == -1)
+ al = SSL_AD_DECODE_ERROR;
err:
-#ifndef OPENSSL_NO_RSA
- RSA_free(rsa);
-#endif
-#ifndef OPENSSL_NO_EC
- EVP_PKEY_CTX_free(pctx);
-#endif
+ if (al != -1)
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
EVP_MD_CTX_free(md_ctx);
ossl_statem_set_error(s);
return MSG_PROCESS_ERROR;
*/
if (i & SSL_SESS_CACHE_CLIENT) {
/*
- * Remove the old session from the cache
+ * Remove the old session from the cache. We carry on if this fails
*/
- if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
- if (s->session_ctx->remove_session_cb != NULL)
- s->session_ctx->remove_session_cb(s->session_ctx,
- s->session);
- } else {
- /* We carry on if this fails */
- SSL_CTX_remove_session(s->session_ctx, s->session);
- }
+ SSL_CTX_remove_session(s->session_ctx, s->session);
}
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
size_t psklen = 0;
if (s->psk_client_callback == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- SSL_R_PSK_NO_CLIENT_CB);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, SSL_R_PSK_NO_CLIENT_CB);
*al = SSL_AD_INTERNAL_ERROR;
goto err;
}
psk, sizeof(psk));
if (psklen > PSK_MAX_PSK_LEN) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
*al = SSL_AD_HANDSHAKE_FAILURE;
goto err;
} else if (psklen == 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
SSL_R_PSK_IDENTITY_NOT_FOUND);
*al = SSL_AD_HANDSHAKE_FAILURE;
goto err;
identitylen = strlen(identity);
if (identitylen > PSK_MAX_IDENTITY_LEN) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
*al = SSL_AD_HANDSHAKE_FAILURE;
goto err;
}
tmppsk = OPENSSL_memdup(psk, psklen);
tmpidentity = OPENSSL_strdup(identity);
if (tmppsk == NULL || tmpidentity == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
*al = SSL_AD_INTERNAL_ERROR;
goto err;
}
return ret;
#else
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
*al = SSL_AD_INTERNAL_ERROR;
return 0;
#endif
/*
* We should always have a server certificate with SSL_kRSA.
*/
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
pkey = X509_get0_pubkey(s->session->peer);
if (EVP_PKEY_get0_RSA(pkey) == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
return 0;
}
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE);
*al = SSL_AD_INTERNAL_ERROR;
return 0;
}
pctx = EVP_PKEY_CTX_new(pkey, NULL);
if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0
|| EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_EVP_LIB);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_EVP_LIB);
goto err;
}
if (EVP_PKEY_encrypt(pctx, *p, &enclen, pms, pmslen) <= 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- SSL_R_BAD_RSA_ENCRYPT);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, SSL_R_BAD_RSA_ENCRYPT);
goto err;
}
*len = enclen;
return 0;
#else
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
*al = SSL_AD_INTERNAL_ERROR;
return 0;
#endif
skey = s->s3->peer_tmp;
if (skey == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
return 0;
}
ckey = ssl_generate_pkey(skey, NID_undef);
dh_clnt = EVP_PKEY_get0_DH(ckey);
if (dh_clnt == NULL || ssl_derive(s, ckey, skey) == 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
EVP_PKEY_free(ckey);
return 0;
}
return 1;
#else
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
*al = SSL_AD_INTERNAL_ERROR;
return 0;
#endif
skey = s->s3->peer_tmp;
if ((skey == NULL) || EVP_PKEY_get0_EC_KEY(skey) == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
return 0;
}
ckey = ssl_generate_pkey(skey, NID_undef);
if (ssl_derive(s, ckey, skey) == 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EVP_LIB);
goto err;
}
&encodedPoint, NULL);
if (encoded_pt_len == 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EC_LIB);
goto err;
}
EVP_PKEY_free(ckey);
return 0;
#else
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
+{
+#ifndef OPENSSL_NO_GOST
+ /* GOST key exchange message creation */
+ EVP_PKEY_CTX *pkey_ctx = NULL;
+ X509 *peer_cert;
+ size_t msglen;
+ unsigned int md_len;
+ unsigned char shared_ukm[32], tmp[256];
+ EVP_MD_CTX *ukm_hash = NULL;
+ int dgst_nid = NID_id_GostR3411_94;
+ unsigned char *pms = NULL;
+ size_t pmslen = 0;
+
+ if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
+ dgst_nid = NID_id_GostR3411_2012_256;
+
+ /*
+ * Get server sertificate PKEY and create ctx from it
+ */
+ peer_cert = s->session->peer;
+ if (!peer_cert) {
+ *al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST,
+ SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+ return 0;
+ }
+
+ pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
+ if (pkey_ctx == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ /*
+ * If we have send a certificate, and certificate key
+ * parameters match those of server certificate, use
+ * certificate key for key exchange
+ */
+
+ /* Otherwise, generate ephemeral key pair */
+ pmslen = 32;
+ pms = OPENSSL_malloc(pmslen);
+ if (pms == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
+ /* Generate session key */
+ || RAND_bytes(pms, pmslen) <= 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+ goto err;
+ };
+ /*
+ * If we have client certificate, use its secret as peer key
+ */
+ if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
+ if (EVP_PKEY_derive_set_peer
+ (pkey_ctx, s->cert->key->privatekey) <= 0) {
+ /*
+ * If there was an error - just ignore it. Ephemeral key
+ * * would be used
+ */
+ ERR_clear_error();
+ }
+ }
+ /*
+ * Compute shared IV and store it in algorithm-specific context
+ * data
+ */
+ ukm_hash = EVP_MD_CTX_new();
+ if (ukm_hash == NULL
+ || EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0
+ || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
+ SSL3_RANDOM_SIZE) <= 0
+ || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ EVP_MD_CTX_free(ukm_hash);
+ ukm_hash = NULL;
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
+ EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+ /* Make GOST keytransport blob message */
+ /*
+ * Encapsulate it into sequence
+ */
+ *((*p)++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
+ msglen = 255;
+ if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+ if (msglen >= 0x80) {
+ *((*p)++) = 0x81;
+ *((*p)++) = msglen & 0xff;
+ *len = msglen + 3;
+ } else {
+ *((*p)++) = msglen & 0xff;
+ *len = msglen + 2;
+ }
+ memcpy(*p, tmp, msglen);
+ /* 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) {
+ /* Set flag "skip certificate verify" */
+ s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
+ }
+ EVP_PKEY_CTX_free(pkey_ctx);
+ s->s3->tmp.pms = pms;
+ s->s3->tmp.pmslen = pmslen;
+
+ return 1;
+ err:
+ EVP_PKEY_CTX_free(pkey_ctx);
+ OPENSSL_clear_free(pms, pmslen);
+ EVP_MD_CTX_free(ukm_hash);
+ return 0;
+#else
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+#endif
+}
+
+static int tls_construct_cke_srp(SSL *s, unsigned char **p, int *len, int *al)
+{
+#ifndef OPENSSL_NO_SRT
+ if (s->srp_ctx.A != NULL) {
+ /* send off the data */
+ *len = BN_num_bytes(s->srp_ctx.A);
+ s2n(*len, *p);
+ BN_bn2bin(s->srp_ctx.A, *p);
+ *len += 2;
+ } else {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ OPENSSL_free(s->session->srp_username);
+ s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
+ if (s->session->srp_username == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+#else
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
*al = SSL_AD_INTERNAL_ERROR;
return 0;
#endif
int tls_construct_client_key_exchange(SSL *s)
{
unsigned char *p;
- int n;
+ int len;
size_t pskhdrlen = 0;
unsigned long alg_k;
int al = -1;
p = ssl_handshake_start(s);
-
-
if ((alg_k & SSL_PSK)
&& !tls_construct_cke_psk_preamble(s, &p, &pskhdrlen, &al))
goto err;
if (alg_k & SSL_kPSK) {
- n = 0;
+ len = 0;
} else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
- if (!tls_construct_cke_rsa(s, &p, &n, &al))
+ if (!tls_construct_cke_rsa(s, &p, &len, &al))
goto err;
} else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
- if (!tls_construct_cke_dhe(s, &p, &n, &al))
+ if (!tls_construct_cke_dhe(s, &p, &len, &al))
goto err;
} else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
- if (!tls_construct_cke_ecdhe(s, &p, &n, &al))
+ if (!tls_construct_cke_ecdhe(s, &p, &len, &al))
goto err;
- }
-#ifndef OPENSSL_NO_GOST
- else if (alg_k & SSL_kGOST) {
- /* GOST key exchange message creation */
- EVP_PKEY_CTX *pkey_ctx;
- X509 *peer_cert;
- size_t msglen;
- unsigned int md_len;
- unsigned char shared_ukm[32], tmp[256];
- EVP_MD_CTX *ukm_hash;
- int dgst_nid = NID_id_GostR3411_94;
- unsigned char *pms = NULL;
- size_t pmslen = 0;
-
- if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
- dgst_nid = NID_id_GostR3411_2012_256;
-
-
- /*
- * Get server sertificate PKEY and create ctx from it
- */
- peer_cert = s->session->peer;
- if (!peer_cert) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
+ } else if (alg_k & SSL_kGOST) {
+ if (!tls_construct_cke_gost(s, &p, &len, &al))
goto err;
- }
-
- pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
- if (pkey_ctx == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
+ } else if (alg_k & SSL_kSRP) {
+ if (!tls_construct_cke_srp(s, &p, &len, &al))
goto err;
- }
- /*
- * If we have send a certificate, and certificate key
- * parameters match those of server certificate, use
- * certificate key for key exchange
- */
-
- /* Otherwise, generate ephemeral key pair */
- pmslen = 32;
- pms = OPENSSL_malloc(pmslen);
- if (pms == NULL)
- goto memerr;
-
- if (pkey_ctx == NULL
- || EVP_PKEY_encrypt_init(pkey_ctx) <= 0
- /* Generate session key */
- || RAND_bytes(pms, pmslen) <= 0) {
- EVP_PKEY_CTX_free(pkey_ctx);
- OPENSSL_clear_free(pms, pmslen);
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- };
- /*
- * If we have client certificate, use its secret as peer key
- */
- if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
- if (EVP_PKEY_derive_set_peer
- (pkey_ctx, s->cert->key->privatekey) <= 0) {
- /*
- * If there was an error - just ignore it. Ephemeral key
- * * would be used
- */
- ERR_clear_error();
- }
- }
- /*
- * Compute shared IV and store it in algorithm-specific context
- * data
- */
- ukm_hash = EVP_MD_CTX_new();
- if (EVP_DigestInit(ukm_hash,
- EVP_get_digestbynid(dgst_nid)) <= 0
- || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
- SSL3_RANDOM_SIZE) <= 0
- || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
- SSL3_RANDOM_SIZE) <= 0
- || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
- EVP_MD_CTX_free(ukm_hash);
- OPENSSL_clear_free(pms, pmslen);
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- EVP_MD_CTX_free(ukm_hash);
- if (EVP_PKEY_CTX_ctrl
- (pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 8,
- shared_ukm) < 0) {
- OPENSSL_clear_free(pms, pmslen);
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- SSL_R_LIBRARY_BUG);
- goto err;
- }
- /* Make GOST keytransport blob message */
- /*
- * Encapsulate it into sequence
- */
- *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
- msglen = 255;
- if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
- OPENSSL_clear_free(pms, pmslen);
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- SSL_R_LIBRARY_BUG);
- goto err;
- }
- if (msglen >= 0x80) {
- *(p++) = 0x81;
- *(p++) = msglen & 0xff;
- n = msglen + 3;
- } else {
- *(p++) = msglen & 0xff;
- n = msglen + 2;
- }
- memcpy(p, tmp, msglen);
- /* 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) {
- /* Set flag "skip certificate verify" */
- s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
- }
- EVP_PKEY_CTX_free(pkey_ctx);
- s->s3->tmp.pms = pms;
- s->s3->tmp.pmslen = pmslen;
- }
-#endif
-#ifndef OPENSSL_NO_SRP
- else if (alg_k & SSL_kSRP) {
- if (s->srp_ctx.A != NULL) {
- /* send off the data */
- n = BN_num_bytes(s->srp_ctx.A);
- s2n(n, p);
- BN_bn2bin(s->srp_ctx.A, p);
- n += 2;
- } else {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- }
- OPENSSL_free(s->session->srp_username);
- s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
- if (s->session->srp_username == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-#endif
- else {
+ } else {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
- n += pskhdrlen;
+ len += pskhdrlen;
- if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) {
+ if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, len)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
return 1;
- memerr:
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
- al = SSL_AD_INTERNAL_ERROR;
err:
if (al != -1)
ssl3_send_alert(s, SSL3_AL_FATAL, al);