Skip to content

Commit

Permalink
Revert KEX rewriting
Browse files Browse the repository at this point in the history
A truncated part of #445
  • Loading branch information
beldmit committed Oct 18, 2023
1 parent af8978a commit 3e395c1
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 415 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

AC_INIT([OpenSSH],[Portable],[[email protected]])
AC_INIT([OpenSSH], [Portable], [[email protected]])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([ssh.c])

Expand Down
103 changes: 0 additions & 103 deletions dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@

#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#endif

#include "dh.h"
#include "pathnames.h"
Expand Down Expand Up @@ -288,103 +283,6 @@ dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
int
dh_gen_key(DH *dh, int need)
{
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
const BIGNUM *dh_p, *dh_g;
BIGNUM *pub_key = NULL, *priv_key = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM_BLD *param_bld = NULL;
OSSL_PARAM *params = NULL;
int pbits, r = 0;

DH_get0_pqg(dh, &dh_p, NULL, &dh_g);

if (need < 0 || dh_p == NULL ||
(pbits = BN_num_bits(dh_p)) <= 0 ||
need > INT_MAX / 2 || 2 * need > pbits)
return SSH_ERR_INVALID_ARGUMENT;
if (need < 256)
need = 256;

if ((param_bld = OSSL_PARAM_BLD_new()) == NULL ||
(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL) {
OSSL_PARAM_BLD_free(param_bld);
return SSH_ERR_ALLOC_FAIL;
}

if (OSSL_PARAM_BLD_push_BN(param_bld,
OSSL_PKEY_PARAM_FFC_P, dh_p) != 1 ||
OSSL_PARAM_BLD_push_BN(param_bld,
OSSL_PKEY_PARAM_FFC_G, dh_g) != 1) {
error_f("Could not set p,q,g parameters");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
/*
* Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
* so double requested need here.
*/
if (OSSL_PARAM_BLD_push_int(param_bld,
OSSL_PKEY_PARAM_DH_PRIV_LEN,
MINIMUM(need * 2, pbits - 1)) != 1 ||
(params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (EVP_PKEY_fromdata_init(ctx) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (EVP_PKEY_fromdata(ctx, &pkey,
EVP_PKEY_KEY_PARAMETERS, params) != 1) {
error_f("Failed key generation");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}

/* reuse context for key generation */
EVP_PKEY_CTX_free(ctx);
ctx = NULL;

if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
EVP_PKEY_keygen_init(ctx) != 1) {
error_f("Could not create or init context");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (EVP_PKEY_generate(ctx, &pkey) != 1) {
error_f("Could not generate keys");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (EVP_PKEY_public_check(ctx) != 1) {
error_f("The public key is incorrect");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}

if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
&pub_key) != 1 ||
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
&priv_key) != 1 ||
DH_set0_key(dh, pub_key, priv_key) != 1) {
error_f("Could not set pub/priv keys to DH struct");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}

/* transferred */
pub_key = NULL;
priv_key = NULL;
out:
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(param_bld);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(pkey);
BN_clear_free(pub_key);
BN_clear_free(priv_key);
return r;
#else
int pbits;
const BIGNUM *dh_p, *pub_key;

Expand All @@ -409,7 +307,6 @@ dh_gen_key(DH *dh, int need)
if (!dh_pub_is_valid(dh, pub_key))
return SSH_ERR_INVALID_FORMAT;
return 0;
#endif
}

DH *
Expand Down
4 changes: 3 additions & 1 deletion kex.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,9 @@ kex_free(struct kex *kex)

#ifdef WITH_OPENSSL
DH_free(kex->dh);
EVP_PKEY_free(kex->pkey);
#ifdef OPENSSL_HAS_ECC
EC_KEY_free(kex->ec_client_key);
#endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
for (mode = 0; mode < MODE_MAX; mode++) {
kex_free_newkeys(kex->newkeys[mode]);
Expand Down
25 changes: 18 additions & 7 deletions kex.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,19 @@
# include <openssl/bn.h>
# include <openssl/dh.h>
# include <openssl/ecdsa.h>
# include <openssl/evp.h>
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
# include <openssl/core_names.h>
# include <openssl/param_build.h>
#endif
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
# else /* OPENSSL_HAS_ECC */
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
# endif /* OPENSSL_HAS_ECC */
#else /* WITH_OPENSSL */
# define DH void
# define BIGNUM void
# define EVP_PKEY void
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
#endif /* WITH_OPENSSL */

#define KEX_COOKIE_LEN 16
Expand Down Expand Up @@ -167,7 +171,8 @@ struct kex {
/* kex specific state */
DH *dh; /* DH */
u_int min, max, nbits; /* GEX */
EVP_PKEY *pkey; /* ECDH */
EC_KEY *ec_client_key; /* ECDH */
const EC_GROUP *ec_group; /* ECDH */
u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */
u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */
u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */
Expand Down Expand Up @@ -256,4 +261,10 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE],
void dump_digest(const char *, const u_char *, int);
#endif

#if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC)
# undef EC_KEY
# undef EC_GROUP
# undef EC_POINT
#endif

#endif
156 changes: 5 additions & 151 deletions kexdh.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@

#include "openbsd-compat/openssl-compat.h"
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#endif

#include "sshkey.h"
#include "kex.h"
Expand Down Expand Up @@ -79,16 +73,9 @@ int
kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
{
BIGNUM *shared_secret = NULL;
const BIGNUM *pub, *priv, *p, *q, *g;
EVP_PKEY *pkey = NULL, *dh_pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
u_char *kbuf = NULL;
size_t klen = 0;
int r = 0;
#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
DH *dh_peer = NULL;
BIGNUM *copy_p = NULL, *copy_q = NULL, *copy_g = NULL, *copy_pub = NULL;
#endif
int kout, r;

#ifdef DEBUG_KEXDH
fprintf(stderr, "dh_pub= ");
Expand All @@ -103,113 +90,24 @@ kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
r = SSH_ERR_MESSAGE_INCOMPLETE;
goto out;
}

#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
DH_get0_key(kex->dh, &pub, &priv);
DH_get0_pqg(kex->dh, &p, &q, &g);
/* import key */
r = kex_create_evp_dh(&pkey, p, q, g, pub, priv);
if (r != 0) {
error_f("Could not create EVP_PKEY for dh");
ERR_print_errors_fp(stderr);
goto out;
}
/* import peer key
* the parameters should be the same as with pkey
*/
r = kex_create_evp_dh(&dh_pkey, p, q, g, dh_pub, NULL);
if (r != 0) {
error_f("Could not import peer key for dh");
ERR_print_errors_fp(stderr);
goto out;
}
#else
DH_get0_pqg(kex->dh, &p, &q, &g);
if ((pkey = EVP_PKEY_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}

if (EVP_PKEY_set1_DH(pkey, kex->dh) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}

if ((dh_peer = DH_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}

copy_p = BN_dup(p);
copy_q = BN_dup(q);
copy_g = BN_dup(g);
if (DH_set0_pqg(dh_peer, copy_p, copy_q, copy_g) != 1) {
BN_free(copy_p);
BN_free(copy_q);
BN_free(copy_g);
DH_free(dh_peer);
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
copy_p = copy_q = copy_g = NULL;

copy_pub = BN_dup(dh_pub);
if (DH_set0_key(dh_peer, copy_pub, NULL) != 1) {
BN_free(copy_pub);
DH_free(dh_peer);
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
copy_pub = NULL;

if ((dh_pkey = EVP_PKEY_new()) == NULL) {
DH_free(dh_peer);
r = SSH_ERR_ALLOC_FAIL;
goto out;
}

if (EVP_PKEY_set1_DH(dh_pkey, dh_peer) != 1) {
DH_free(dh_peer);
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
DH_free(dh_peer);
#endif

if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
error_f("Could not init EVP_PKEY_CTX for dh");
ERR_print_errors_fp(stderr);
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (EVP_PKEY_derive_init(ctx) != 1 ||
EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 ||
EVP_PKEY_derive(ctx, NULL, &klen) != 1) {
error_f("Could not get key size");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
klen = DH_size(kex->dh);
if ((kbuf = malloc(klen)) == NULL ||
(shared_secret = BN_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1 ||
BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
error_f("Could not derive key");
if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
#ifdef DEBUG_KEXDH
dump_digest("shared secret", kbuf, klen);
dump_digest("shared secret", kbuf, kout);
#endif
r = sshbuf_put_bignum2(out, shared_secret);
out:
freezero(kbuf, klen);
BN_clear_free(shared_secret);
EVP_PKEY_free(pkey);
EVP_PKEY_free(dh_pkey);
EVP_PKEY_CTX_free(ctx);
return r;
}

Expand Down Expand Up @@ -302,48 +200,4 @@ kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob,
sshbuf_free(buf);
return r;
}
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
/*
* Creates an EVP_PKEY from the given parameters and keys.
* The private key can be omitted.
*/
int
kex_create_evp_dh(EVP_PKEY **pkey, const BIGNUM *p, const BIGNUM *q,
const BIGNUM *g, const BIGNUM *pub, const BIGNUM *priv)
{
OSSL_PARAM_BLD *param_bld = NULL;
EVP_PKEY_CTX *ctx = NULL;
int r = 0;

/* create EVP_PKEY-DH key */
if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL ||
(param_bld = OSSL_PARAM_BLD_new()) == NULL) {
error_f("EVP_PKEY_CTX or PARAM_BLD init failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 ||
OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1 ||
OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1 ||
OSSL_PARAM_BLD_push_BN(param_bld,
OSSL_PKEY_PARAM_PUB_KEY, pub) != 1) {
error_f("Failed pushing params to OSSL_PARAM_BLD");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (priv != NULL &&
OSSL_PARAM_BLD_push_BN(param_bld,
OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) {
error_f("Failed pushing private key to OSSL_PARAM_BLD");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL)
r = SSH_ERR_LIBCRYPTO_ERROR;
out:
OSSL_PARAM_BLD_free(param_bld);
EVP_PKEY_CTX_free(ctx);
return r;
}
#endif
#endif /* WITH_OPENSSL */
Loading

0 comments on commit 3e395c1

Please sign in to comment.