-/* $OpenBSD: ssl_clnt.c,v 1.119 2021/11/26 16:41:42 tb Exp $ */
+/* $OpenBSD: ssl_clnt.c,v 1.120 2021/11/29 16:00:32 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
static int
ssl3_get_server_kex_dhe(SSL *s, EVP_PKEY **pkey, CBS *cbs)
{
- CBS dhp, dhg, dhpk;
- BN_CTX *bn_ctx = NULL;
SESS_CERT *sc = NULL;
DH *dh = NULL;
long alg_a;
- int al;
alg_a = S3I(s)->hs.cipher->algorithm_auth;
sc = s->session->sess_cert;
- if ((dh = DH_new()) == NULL) {
- SSLerror(s, ERR_R_DH_LIB);
- goto err;
- }
-
- if (!CBS_get_u16_length_prefixed(cbs, &dhp))
- goto decode_err;
- if ((dh->p = BN_bin2bn(CBS_data(&dhp), CBS_len(&dhp), NULL)) == NULL) {
- SSLerror(s, ERR_R_BN_LIB);
+ if ((dh = DH_new()) == NULL)
goto err;
- }
- if (!CBS_get_u16_length_prefixed(cbs, &dhg))
+ if (!ssl_kex_peer_params_dhe(dh, cbs))
goto decode_err;
- if ((dh->g = BN_bin2bn(CBS_data(&dhg), CBS_len(&dhg), NULL)) == NULL) {
- SSLerror(s, ERR_R_BN_LIB);
- goto err;
- }
-
- if (!CBS_get_u16_length_prefixed(cbs, &dhpk))
+ if (!ssl_kex_peer_public_dhe(dh, cbs))
goto decode_err;
- if ((dh->pub_key = BN_bin2bn(CBS_data(&dhpk), CBS_len(&dhpk),
- NULL)) == NULL) {
- SSLerror(s, ERR_R_BN_LIB);
- goto err;
- }
/*
* Check the strength of the DH key just constructed.
- * Discard keys weaker than 1024 bits.
+ * Reject keys weaker than 1024 bits.
*/
if (DH_size(dh) < 1024 / 8) {
SSLerror(s, SSL_R_BAD_DH_P_LENGTH);
return (1);
decode_err:
- al = SSL_AD_DECODE_ERROR;
SSLerror(s, SSL_R_BAD_PACKET_LENGTH);
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
err:
DH_free(dh);
- BN_CTX_free(bn_ctx);
return (-1);
}
static int
ssl3_send_client_kex_dhe(SSL *s, SESS_CERT *sess_cert, CBB *cbb)
{
- DH *dh_srvr = NULL, *dh_clnt = NULL;
- unsigned char *key = NULL;
- int key_size = 0, key_len;
- unsigned char *data;
+ DH *dh_clnt = NULL;
+ DH *dh_srvr;
+ uint8_t *key = NULL;
+ size_t key_len = 0;
int ret = -1;
- CBB dh_Yc;
- /* Ensure that we have an ephemeral key for DHE. */
- if (sess_cert->peer_dh_tmp == NULL) {
+ /* Ensure that we have an ephemeral key from the server for DHE. */
+ if ((dh_srvr = sess_cert->peer_dh_tmp) == NULL) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
SSLerror(s, SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
goto err;
}
- dh_srvr = sess_cert->peer_dh_tmp;
- /* Generate a new random key. */
- if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) {
- SSLerror(s, ERR_R_DH_LIB);
+ if ((dh_clnt = DH_new()) == NULL)
goto err;
- }
- if (!DH_generate_key(dh_clnt)) {
- SSLerror(s, ERR_R_DH_LIB);
- goto err;
- }
- if ((key_size = DH_size(dh_clnt)) <= 0) {
- SSLerror(s, ERR_R_DH_LIB);
- goto err;
- }
- if ((key = malloc(key_size)) == NULL) {
- SSLerror(s, ERR_R_MALLOC_FAILURE);
+
+ if (!ssl_kex_generate_dhe(dh_clnt, dh_srvr))
goto err;
- }
- if ((key_len = DH_compute_key(key, dh_srvr->pub_key, dh_clnt)) <= 0) {
- SSLerror(s, ERR_R_DH_LIB);
+ if (!ssl_kex_public_dhe(dh_clnt, cbb))
goto err;
- }
- if (!tls12_derive_master_secret(s, key, key_len))
+ if (!ssl_kex_derive_dhe(dh_clnt, dh_srvr, &key, &key_len))
goto err;
- if (!CBB_add_u16_length_prefixed(cbb, &dh_Yc))
- goto err;
- if (!CBB_add_space(&dh_Yc, &data, BN_num_bytes(dh_clnt->pub_key)))
- goto err;
- BN_bn2bin(dh_clnt->pub_key, data);
- if (!CBB_flush(cbb))
+ if (!tls12_derive_master_secret(s, key, key_len))
goto err;
ret = 1;
err:
DH_free(dh_clnt);
- freezero(key, key_size);
+ freezero(key, key_len);
return (ret);
}
if (!ssl_kex_derive_ecdhe_ecp(ecdh, sc->peer_ecdh_tmp, &key, &key_len))
goto err;
+
if (!tls12_derive_master_secret(s, key, key_len))
goto err;
-/* $OpenBSD: ssl_kex.c,v 1.2 2020/04/18 14:07:56 jsing Exp $ */
+/* $OpenBSD: ssl_kex.c,v 1.3 2021/11/29 16:00:32 jsing Exp $ */
/*
* Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
*
#include <stdlib.h>
+#include <openssl/dh.h>
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/evp.h>
#include "bytestring.h"
+int
+ssl_kex_generate_dhe(DH *dh, DH *dh_params)
+{
+ BN_free(dh->p);
+ BN_free(dh->g);
+ dh->p = NULL;
+ dh->g = NULL;
+
+ if ((dh->p = BN_dup(dh_params->p)) == NULL)
+ return 0;
+ if ((dh->g = BN_dup(dh_params->g)) == NULL)
+ return 0;
+
+ if (!DH_generate_key(dh))
+ return 0;
+
+ return 1;
+}
+
+int
+ssl_kex_params_dhe(DH *dh, CBB *cbb)
+{
+ int dh_p_len, dh_g_len;
+ CBB dh_p, dh_g;
+ uint8_t *data;
+
+ if ((dh_p_len = BN_num_bytes(dh->p)) <= 0)
+ return 0;
+ if ((dh_g_len = BN_num_bytes(dh->g)) <= 0)
+ return 0;
+
+ if (!CBB_add_u16_length_prefixed(cbb, &dh_p))
+ return 0;
+ if (!CBB_add_space(&dh_p, &data, dh_p_len))
+ return 0;
+ if (BN_bn2bin(dh->p, data) != dh_p_len)
+ return 0;
+
+ if (!CBB_add_u16_length_prefixed(cbb, &dh_g))
+ return 0;
+ if (!CBB_add_space(&dh_g, &data, dh_g_len))
+ return 0;
+ if (BN_bn2bin(dh->g, data) != dh_g_len)
+ return 0;
+
+ if (!CBB_flush(cbb))
+ return 0;
+
+ return 1;
+}
+
+int
+ssl_kex_public_dhe(DH *dh, CBB *cbb)
+{
+ uint8_t *data;
+ int dh_y_len;
+ CBB dh_y;
+
+ if ((dh_y_len = BN_num_bytes(dh->pub_key)) <= 0)
+ return 0;
+
+ if (!CBB_add_u16_length_prefixed(cbb, &dh_y))
+ return 0;
+ if (!CBB_add_space(&dh_y, &data, dh_y_len))
+ return 0;
+ if (BN_bn2bin(dh->pub_key, data) != dh_y_len)
+ return 0;
+
+ if (!CBB_flush(cbb))
+ return 0;
+
+ return 1;
+}
+
+int
+ssl_kex_peer_params_dhe(DH *dh, CBS *cbs)
+{
+ CBS dh_p, dh_g;
+
+ BN_free(dh->p);
+ BN_free(dh->g);
+ dh->p = NULL;
+ dh->g = NULL;
+
+ if (!CBS_get_u16_length_prefixed(cbs, &dh_p))
+ return 0;
+ if (!CBS_get_u16_length_prefixed(cbs, &dh_g))
+ return 0;
+
+ if ((dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)) == NULL)
+ return 0;
+ if ((dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL)
+ return 0;
+
+ return 1;
+}
+
+int
+ssl_kex_peer_public_dhe(DH *dh, CBS *cbs)
+{
+ CBS dh_y;
+
+ BN_free(dh->pub_key);
+ dh->pub_key = NULL;
+
+ if (!CBS_get_u16_length_prefixed(cbs, &dh_y))
+ return 0;
+ if ((dh->pub_key = BN_bin2bn(CBS_data(&dh_y), CBS_len(&dh_y),
+ NULL)) == NULL)
+ return 0;
+
+ return 1;
+}
+
+int
+ssl_kex_derive_dhe(DH *dh, DH *dh_peer,
+ uint8_t **shared_key, size_t *shared_key_len)
+{
+ uint8_t *key = NULL;
+ int key_len = 0;
+ int ret = 0;
+
+ if ((key_len = DH_size(dh)) <= 0)
+ goto err;
+ if ((key = calloc(1, key_len)) == NULL)
+ goto err;
+
+ if ((key_len = DH_compute_key(key, dh_peer->pub_key, dh)) <= 0)
+ goto err;
+
+ *shared_key = key;
+ *shared_key_len = key_len;
+ key = NULL;
+
+ ret = 1;
+
+ err:
+ freezero(key, key_len);
+
+ return ret;
+}
+
int
ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey)
{
-/* $OpenBSD: ssl_locl.h,v 1.368 2021/10/25 10:09:28 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.369 2021/11/29 16:00:32 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
int ssl3_get_client_key_exchange(SSL *s);
int ssl3_get_cert_verify(SSL *s);
+int ssl_kex_generate_dhe(DH *dh, DH *dh_params);
+int ssl_kex_params_dhe(DH *dh, CBB *cbb);
+int ssl_kex_public_dhe(DH *dh, CBB *cbb);
+int ssl_kex_peer_params_dhe(DH *dh, CBS *cbs);
+int ssl_kex_peer_public_dhe(DH *dh, CBS *cbs);
+int ssl_kex_derive_dhe(DH *dh, DH *dh_peer,
+ uint8_t **shared_key, size_t *shared_key_len);
+
int ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey);
int ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid);
int ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb);