From 0c08159f537d9ee343a7ec65fec3b5a47b5193ef Mon Sep 17 00:00:00 2001 From: Juraj Vijtiuk Date: Tue, 7 Jun 2022 00:39:13 +0200 Subject: [PATCH] Fix mbedTLS issues caused by v3 API changes Signed-off-by: Juraj Vijtiuk Reviewed-by: Jakub Jelen Reviewed-by: Andreas Schneider --- src/ecdh_mbedcrypto.c | 54 +++-- src/libmbedcrypto.c | 24 +- src/mbedcrypto-compat.h | 39 ++++ src/pki_mbedcrypto.c | 505 +++++++++++++++++++++++++++++++++------- 4 files changed, 507 insertions(+), 115 deletions(-) create mode 100644 src/mbedcrypto-compat.h diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c index 718f1522..cfe017a0 100644 --- a/src/ecdh_mbedcrypto.c +++ b/src/ecdh_mbedcrypto.c @@ -34,6 +34,7 @@ #include #include +#include "mbedcrypto-compat.h" #ifdef HAVE_ECDH @@ -54,6 +55,10 @@ int ssh_client_ecdh_init(ssh_session session) mbedtls_ecp_group grp; int rc; mbedtls_ecp_group_id curve; + mbedtls_ctr_drbg_context *ctr_drbg = NULL; + mbedtls_ecp_keypair *ecdh_privkey = NULL; + + ctr_drbg = ssh_get_mbedtls_ctr_drbg_context(); curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == MBEDTLS_ECP_DP_NONE) { @@ -70,7 +75,9 @@ int ssh_client_ecdh_init(ssh_session session) return SSH_ERROR; } - mbedtls_ecp_keypair_init(session->next_crypto->ecdh_privkey); + ecdh_privkey = session->next_crypto->ecdh_privkey; + + mbedtls_ecp_keypair_init(ecdh_privkey); mbedtls_ecp_group_init(&grp); rc = mbedtls_ecp_group_load(&grp, curve); @@ -80,10 +87,10 @@ int ssh_client_ecdh_init(ssh_session session) } rc = mbedtls_ecp_gen_keypair(&grp, - &session->next_crypto->ecdh_privkey->d, - &session->next_crypto->ecdh_privkey->Q, - mbedtls_ctr_drbg_random, - ssh_get_mbedtls_ctr_drbg_context()); + &ecdh_privkey->MBEDTLS_PRIVATE(d), + &ecdh_privkey->MBEDTLS_PRIVATE(Q), + mbedtls_ctr_drbg_random, + ctr_drbg); if (rc != 0) { rc = SSH_ERROR; @@ -91,7 +98,7 @@ int ssh_client_ecdh_init(ssh_session session) } client_pubkey = make_ecpoint_string(&grp, - &session->next_crypto->ecdh_privkey->Q); + &ecdh_privkey->MBEDTLS_PRIVATE(Q)); if (client_pubkey == NULL) { rc = SSH_ERROR; goto out; @@ -124,6 +131,10 @@ int ecdh_build_k(ssh_session session) mbedtls_ecp_point pubkey; int rc; mbedtls_ecp_group_id curve; + mbedtls_ctr_drbg_context *ctr_drbg = NULL; + mbedtls_ecp_keypair *ecdh_privkey = NULL; + + ctr_drbg = ssh_get_mbedtls_ctr_drbg_context(); curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == MBEDTLS_ECP_DP_NONE) { @@ -162,19 +173,20 @@ int ecdh_build_k(ssh_session session) mbedtls_mpi_init(session->next_crypto->shared_secret); + ecdh_privkey = session->next_crypto->ecdh_privkey; rc = mbedtls_ecdh_compute_shared(&grp, - session->next_crypto->shared_secret, - &pubkey, - &session->next_crypto->ecdh_privkey->d, - mbedtls_ctr_drbg_random, - ssh_get_mbedtls_ctr_drbg_context()); + session->next_crypto->shared_secret, + &pubkey, + &ecdh_privkey->MBEDTLS_PRIVATE(d), + mbedtls_ctr_drbg_random, + ctr_drbg); if (rc != 0) { rc = SSH_ERROR; goto out; } out: - mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey); + mbedtls_ecp_keypair_free(ecdh_privkey); SAFE_FREE(session->next_crypto->ecdh_privkey); mbedtls_ecp_group_free(&grp); mbedtls_ecp_point_free(&pubkey); @@ -187,6 +199,8 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ ssh_string q_c_string = NULL; ssh_string q_s_string = NULL; mbedtls_ecp_group grp; + mbedtls_ctr_drbg_context *ctr_drbg = NULL; + mbedtls_ecp_keypair *ecdh_privkey = NULL; ssh_key privkey = NULL; enum ssh_digest_e digest = SSH_DIGEST_AUTO; ssh_string sig_blob = NULL; @@ -214,10 +228,14 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ return SSH_ERROR; } + ecdh_privkey = session->next_crypto->ecdh_privkey; + session->next_crypto->ecdh_client_pubkey = q_c_string; + ctr_drbg = ssh_get_mbedtls_ctr_drbg_context(); + mbedtls_ecp_group_init(&grp); - mbedtls_ecp_keypair_init(session->next_crypto->ecdh_privkey); + mbedtls_ecp_keypair_init(ecdh_privkey); rc = mbedtls_ecp_group_load(&grp, curve); if (rc != 0) { @@ -226,16 +244,16 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ } rc = mbedtls_ecp_gen_keypair(&grp, - &session->next_crypto->ecdh_privkey->d, - &session->next_crypto->ecdh_privkey->Q, - mbedtls_ctr_drbg_random, - ssh_get_mbedtls_ctr_drbg_context()); + &ecdh_privkey->MBEDTLS_PRIVATE(d), + &ecdh_privkey->MBEDTLS_PRIVATE(Q), + mbedtls_ctr_drbg_random, + ctr_drbg); if (rc != 0) { rc = SSH_ERROR; goto out; } - q_s_string = make_ecpoint_string(&grp, &session->next_crypto->ecdh_privkey->Q); + q_s_string = make_ecpoint_string(&grp, &ecdh_privkey->MBEDTLS_PRIVATE(Q)); if (q_s_string == NULL) { rc = SSH_ERROR; goto out; diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c index 7c93ea75..2a8ce62c 100644 --- a/src/libmbedcrypto.c +++ b/src/libmbedcrypto.c @@ -27,6 +27,7 @@ #include "libssh/crypto.h" #include "libssh/priv.h" #include "libssh/misc.h" +#include "mbedcrypto-compat.h" #if defined(MBEDTLS_CHACHA20_C) && defined(MBEDTLS_POLY1305_C) #include "libssh/bytearray.h" #include "libssh/chacha20-poly1305-common.h" @@ -177,7 +178,7 @@ void evp_update(EVPCTX ctx, const void *data, size_t len) void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) { - *mdlen = mbedtls_md_get_size(ctx->md_info); + *mdlen = mbedtls_md_get_size(ctx->MBEDTLS_PRIVATE(md_info)); mbedtls_md_finish(ctx, md); mbedtls_md_free(ctx); SAFE_FREE(ctx); @@ -453,7 +454,7 @@ void hmac_update(HMACCTX c, const void *data, size_t len) void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len) { - *len = mbedtls_md_get_size(c->md_info); + *len = mbedtls_md_get_size(c->MBEDTLS_PRIVATE(md_info)); mbedtls_md_hmac_finish(c, hashmacbuf); mbedtls_md_free(c); SAFE_FREE(c); @@ -467,6 +468,8 @@ cipher_init(struct ssh_cipher_struct *cipher, { const mbedtls_cipher_info_t *cipher_info = NULL; mbedtls_cipher_context_t *ctx; + size_t key_bitlen = 0; + size_t iv_size = 0; int rc; if (operation == MBEDTLS_ENCRYPT) { @@ -487,15 +490,15 @@ cipher_init(struct ssh_cipher_struct *cipher, goto error; } - rc = mbedtls_cipher_setkey(ctx, key, - cipher_info->key_bitlen, - operation); + key_bitlen = mbedtls_cipher_info_get_key_bitlen(cipher_info); + rc = mbedtls_cipher_setkey(ctx, key, key_bitlen, operation); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed"); goto error; } - rc = mbedtls_cipher_set_iv(ctx, IV, cipher_info->iv_size); + iv_size = mbedtls_cipher_info_get_iv_size(cipher_info); + rc = mbedtls_cipher_set_iv(ctx, IV, iv_size); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed"); goto error; @@ -573,15 +576,16 @@ cipher_set_key_gcm(struct ssh_cipher_struct *cipher, void *IV) { const mbedtls_cipher_info_t *cipher_info = NULL; + size_t key_bitlen = 0; int rc; mbedtls_gcm_init(&cipher->gcm_ctx); cipher_info = mbedtls_cipher_info_from_type(cipher->type); - rc = mbedtls_gcm_setkey(&cipher->gcm_ctx, - MBEDTLS_CIPHER_ID_AES, - key, - cipher_info->key_bitlen); + key_bitlen = mbedtls_cipher_info_get_key_bitlen(cipher_info); + rc = mbedtls_gcm_setkey(&cipher->gcm_ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen); + if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_setkey failed"); goto error; diff --git a/src/mbedcrypto-compat.h b/src/mbedcrypto-compat.h new file mode 100644 index 00000000..705294a7 --- /dev/null +++ b/src/mbedcrypto-compat.h @@ -0,0 +1,39 @@ +#ifndef MBEDCRYPTO_COMPAT_H +#define MBEDCRYPTO_COMPAT_H + +/* mbedtls/version.h should be available for both v2 and v3 + * v3 defines the version inside build_info.h so if it isn't defined + * in version.h we should have v3 + */ +#include +#include +#ifdef MBEDTLS_VERSION_MAJOR +#if MBEDTLS_VERSION_MAJOR < 3 + +static inline size_t mbedtls_cipher_info_get_key_bitlen( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + return info->key_bitlen; +} + +static inline size_t mbedtls_cipher_info_get_iv_size( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + return (size_t)info->iv_size; +} + +#define MBEDTLS_PRIVATE(X) X +#endif /* MBEDTLS_VERSION_MAJOR < 3 */ +#else /* MBEDTLS_VERSION_MAJOR */ +#include +#if MBEDTLS_VERSION_MAJOR < 3 +#define MBEDTLS_PRIVATE(X) X +#endif /* MBEDTLS_VERSION_MAJOR < 3 */ +#endif /* MBEDTLS_VERSION_MAJOR */ +#endif /* MBEDCRYPTO_COMPAT_H */ diff --git a/src/pki_mbedcrypto.c b/src/pki_mbedcrypto.c index 5bdd7484..d83074e6 100644 --- a/src/pki_mbedcrypto.c +++ b/src/pki_mbedcrypto.c @@ -26,6 +26,7 @@ #ifdef HAVE_LIBMBEDCRYPTO #include #include +#include "mbedcrypto-compat.h" #include "libssh/priv.h" #include "libssh/pki.h" @@ -50,7 +51,7 @@ static int pki_key_ecdsa_to_nid(mbedtls_ecdsa_context *ecdsa) { mbedtls_ecp_group_id id; - id = ecdsa->grp.id; + id = ecdsa->MBEDTLS_PRIVATE(grp.id); if (id == MBEDTLS_ECP_DP_SECP256R1) { return NID_mbedtls_nistp256; } else if (id == MBEDTLS_ECP_DP_SECP384R1) { @@ -92,6 +93,9 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, /* mbedtls pk_parse_key expects strlen to count the 0 byte */ size_t b64len = strlen(b64_key) + 1; unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0}; +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_ctr_drbg_context *ctr_drbg = ssh_get_mbedtls_ctr_drbg_context(); +#endif type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { @@ -116,21 +120,44 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, goto fail; } /* TODO fix signedness and strlen */ +#if MBEDTLS_VERSION_MAJOR > 2 + valid = mbedtls_pk_parse_key(rsa, + (const unsigned char *) b64_key, + b64len, tmp, + strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE), + mbedtls_ctr_drbg_random, ctr_drbg); +#else valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); +#endif } else { +#if MBEDTLS_VERSION_MAJOR > 2 + valid = mbedtls_pk_parse_key(rsa, + (const unsigned char *) b64_key, + b64len, NULL, + 0, mbedtls_ctr_drbg_random, ctr_drbg); +#else valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, NULL, 0); +#endif } } else { +#if MBEDTLS_VERSION_MAJOR > 2 + valid = mbedtls_pk_parse_key(rsa, + (const unsigned char *) b64_key, b64len, + (const unsigned char *) passphrase, + strnlen(passphrase, MAX_PASSPHRASE_SIZE), + mbedtls_ctr_drbg_random, ctr_drbg); +#else valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); +#endif } if (valid != 0) { @@ -143,7 +170,11 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: +#if MBEDTLS_VERSION_MAJOR > 2 + ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); +#else ecdsa = malloc(sizeof(mbedtls_pk_context)); +#endif if (ecdsa == NULL) { return NULL; } @@ -157,21 +188,44 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, if (valid < 0) { goto fail; } +#if MBEDTLS_VERSION_MAJOR > 2 + valid = mbedtls_pk_parse_key(ecdsa, + (const unsigned char *) b64_key, + b64len, tmp, + strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE), + mbedtls_ctr_drbg_random, ctr_drbg); +#else valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); +#endif } else { +#if MBEDTLS_VERSION_MAJOR > 2 + valid = mbedtls_pk_parse_key(ecdsa, + (const unsigned char *) b64_key, + b64len, NULL, + 0, mbedtls_ctr_drbg_random, ctr_drbg); +#else valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, NULL, 0); +#endif } } else { +#if MBEDTLS_VERSION_MAJOR > 2 + valid = mbedtls_pk_parse_key(ecdsa, + (const unsigned char *) b64_key, b64len, + (const unsigned char *) passphrase, + strnlen(passphrase, MAX_PASSPHRASE_SIZE), + mbedtls_ctr_drbg_random, ctr_drbg); +#else valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); +#endif } if (valid != 0) { @@ -304,6 +358,10 @@ int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n) { mbedtls_rsa_context *rsa = NULL; const mbedtls_pk_info_t *pk_info = NULL; +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi N; + mbedtls_mpi E; +#endif int rc; key->rsa = malloc(sizeof(mbedtls_pk_context)); @@ -320,26 +378,59 @@ int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n) goto fail; } +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi_init(&N); + mbedtls_mpi_init(&E); +#endif + rsa = mbedtls_pk_rsa(*key->rsa); +#if MBEDTLS_VERSION_MAJOR > 2 + rc = mbedtls_mpi_read_binary(&N, ssh_string_data(n), + ssh_string_len(n)); +#else rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n), ssh_string_len(n)); +#endif if (rc != 0) { goto fail; } +#if MBEDTLS_VERSION_MAJOR > 2 + rc = mbedtls_mpi_read_binary(&E, ssh_string_data(e), + ssh_string_len(e)); +#else rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e), ssh_string_len(e)); +#endif if (rc != 0) { goto fail; } +#if MBEDTLS_VERSION_MAJOR > 2 + rc = mbedtls_rsa_import(rsa, &N, NULL, NULL, NULL, &E); + if (rc != 0) { + goto fail; + } + + rc = mbedtls_rsa_complete(rsa); + if (rc != 0) { + goto fail; + } + +#else rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3; - - return SSH_OK; - +#endif + rc = SSH_OK; + goto exit; fail: + rc = SSH_ERROR; mbedtls_pk_free(key->rsa); SAFE_FREE(key->rsa); - return SSH_ERROR; +exit: +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi_free(&N); + mbedtls_mpi_free(&E); +#endif + return rc; } ssh_key pki_key_dup(const ssh_key key, int demote) @@ -347,7 +438,13 @@ ssh_key pki_key_dup(const ssh_key key, int demote) ssh_key new = NULL; int rc; const mbedtls_pk_info_t *pk_info = NULL; - +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi N; + mbedtls_mpi E; + mbedtls_mpi D; + mbedtls_mpi P; + mbedtls_mpi Q; +#endif new = ssh_key_new(); if (new == NULL) { @@ -362,6 +459,13 @@ ssh_key pki_key_dup(const ssh_key key, int demote) new->flags = key->flags; } +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi_init(&N); + mbedtls_mpi_init(&E); + mbedtls_mpi_init(&D); + mbedtls_mpi_init(&P); + mbedtls_mpi_init(&Q); +#endif switch(key->type) { case SSH_KEYTYPE_RSA: { @@ -376,11 +480,26 @@ ssh_key pki_key_dup(const ssh_key key, int demote) pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); mbedtls_pk_setup(new->rsa, pk_info); - if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) && - mbedtls_pk_can_do(new->rsa, MBEDTLS_PK_RSA)) { - rsa = mbedtls_pk_rsa(*key->rsa); - new_rsa = mbedtls_pk_rsa(*new->rsa); + if (!mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) || + !mbedtls_pk_can_do(new->rsa, MBEDTLS_PK_RSA)) + { + goto fail; + } + rsa = mbedtls_pk_rsa(*key->rsa); + new_rsa = mbedtls_pk_rsa(*new->rsa); + + if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { +#if MBEDTLS_VERSION_MAJOR > 2 + rc = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E); + if (rc != 0) { + goto fail; + } + rc = mbedtls_rsa_import(new_rsa, &N, &P, &Q, &D, &E); + if (rc != 0) { + goto fail; + } +#else rc = mbedtls_mpi_copy(&new_rsa->N, &rsa->N); if (rc != 0) { goto fail; @@ -390,42 +509,70 @@ ssh_key pki_key_dup(const ssh_key key, int demote) if (rc != 0) { goto fail; } + new_rsa->len = (mbedtls_mpi_bitlen(&new_rsa->N) + 7) >> 3; - if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { - rc = mbedtls_mpi_copy(&new_rsa->D, &rsa->D); - if (rc != 0) { - goto fail; - } - - rc = mbedtls_mpi_copy(&new_rsa->P, &rsa->P); - if (rc != 0) { - goto fail; - } - - rc = mbedtls_mpi_copy(&new_rsa->Q, &rsa->Q); - if (rc != 0) { - goto fail; - } - - rc = mbedtls_mpi_copy(&new_rsa->DP, &rsa->DP); - if (rc != 0) { - goto fail; - } - - rc = mbedtls_mpi_copy(&new_rsa->DQ, &rsa->DQ); - if (rc != 0) { - goto fail; - } - - rc = mbedtls_mpi_copy(&new_rsa->QP, &rsa->QP); - if (rc != 0) { - goto fail; - } + rc = mbedtls_mpi_copy(&new_rsa->D, &rsa->D); + if (rc != 0) { + goto fail; } + + rc = mbedtls_mpi_copy(&new_rsa->P, &rsa->P); + if (rc != 0) { + goto fail; + } + + rc = mbedtls_mpi_copy(&new_rsa->Q, &rsa->Q); + if (rc != 0) { + goto fail; + } + + rc = mbedtls_mpi_copy(&new_rsa->DP, &rsa->DP); + if (rc != 0) { + goto fail; + } + + rc = mbedtls_mpi_copy(&new_rsa->DQ, &rsa->DQ); + if (rc != 0) { + goto fail; + } + + rc = mbedtls_mpi_copy(&new_rsa->QP, &rsa->QP); + if (rc != 0) { + goto fail; + } +#endif } else { +#if MBEDTLS_VERSION_MAJOR > 2 + rc = mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, &E); + if (rc != 0) { + goto fail; + } + rc = mbedtls_rsa_import(new_rsa, &N, NULL, NULL, NULL, &E); + if (rc != 0) { + goto fail; + } +#else + rc = mbedtls_mpi_copy(&new_rsa->N, &rsa->N); + if (rc != 0) { + goto fail; + } + + rc = mbedtls_mpi_copy(&new_rsa->E, &rsa->E); + if (rc != 0) { + goto fail; + } + + new_rsa->len = (mbedtls_mpi_bitlen(&new_rsa->N) + 7) >> 3; +#endif + } + +#if MBEDTLS_VERSION_MAJOR > 2 + rc = mbedtls_rsa_complete(new_rsa); + if (rc != 0) { goto fail; } +#endif break; } @@ -443,12 +590,14 @@ ssh_key pki_key_dup(const ssh_key key, int demote) mbedtls_ecdsa_init(new->ecdsa); if (demote && ssh_key_is_private(key)) { - rc = mbedtls_ecp_copy(&new->ecdsa->Q, &key->ecdsa->Q); + rc = mbedtls_ecp_copy(&new->ecdsa->MBEDTLS_PRIVATE(Q), + &key->ecdsa->MBEDTLS_PRIVATE(Q)); if (rc != 0) { goto fail; } - rc = mbedtls_ecp_group_copy(&new->ecdsa->grp, &key->ecdsa->grp); + rc = mbedtls_ecp_group_copy(&new->ecdsa->MBEDTLS_PRIVATE(grp), + &key->ecdsa->MBEDTLS_PRIVATE(grp)); if (rc != 0) { goto fail; } @@ -467,10 +616,19 @@ ssh_key pki_key_dup(const ssh_key key, int demote) goto fail; } - return new; + goto cleanup; + fail: - ssh_key_free(new); - return NULL; + SSH_KEY_FREE(new); +cleanup: +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi_free(&N); + mbedtls_mpi_free(&E); + mbedtls_mpi_free(&D); + mbedtls_mpi_free(&P); + mbedtls_mpi_free(&Q); +#endif + return new; } int pki_key_generate_rsa(ssh_key key, int parameter) @@ -508,36 +666,140 @@ int pki_key_generate_rsa(ssh_key key, int parameter) int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) { + int rc = 0; +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi N1; + mbedtls_mpi N2; + mbedtls_mpi P1; + mbedtls_mpi P2; + mbedtls_mpi Q1; + mbedtls_mpi Q2; + mbedtls_mpi E1; + mbedtls_mpi E2; + + mbedtls_mpi_init(&N1); + mbedtls_mpi_init(&N2); + mbedtls_mpi_init(&P1); + mbedtls_mpi_init(&P2); + mbedtls_mpi_init(&Q1); + mbedtls_mpi_init(&Q2); + mbedtls_mpi_init(&E1); + mbedtls_mpi_init(&E2); +#endif + switch (k1->type) { case SSH_KEYTYPE_RSA: { mbedtls_rsa_context *rsa1, *rsa2; - if (mbedtls_pk_can_do(k1->rsa, MBEDTLS_PK_RSA) && - mbedtls_pk_can_do(k2->rsa, MBEDTLS_PK_RSA)) { - if (mbedtls_pk_get_type(k1->rsa) != mbedtls_pk_get_type(k2->rsa) || - mbedtls_pk_get_bitlen(k1->rsa) != - mbedtls_pk_get_bitlen(k2->rsa)) { - return 1; + if (!mbedtls_pk_can_do(k1->rsa, MBEDTLS_PK_RSA) || + !mbedtls_pk_can_do(k2->rsa, MBEDTLS_PK_RSA)) + { + break; + } + + if (mbedtls_pk_get_type(k1->rsa) != mbedtls_pk_get_type(k2->rsa) || + mbedtls_pk_get_bitlen(k1->rsa) != + mbedtls_pk_get_bitlen(k2->rsa)) + { + rc = 1; + goto cleanup; + } + + if (what == SSH_KEY_CMP_PUBLIC) { +#if MBEDTLS_VERSION_MAJOR > 2 + rsa1 = mbedtls_pk_rsa(*k1->rsa); + rc = mbedtls_rsa_export(rsa1, &N1, NULL, NULL, NULL, &E1); + if (rc != 0) { + rc = 1; + goto cleanup; } + rsa2 = mbedtls_pk_rsa(*k2->rsa); + rc = mbedtls_rsa_export(rsa2, &N2, NULL, NULL, NULL, &E2); + if (rc != 0) { + rc = 1; + goto cleanup; + } + + if (mbedtls_mpi_cmp_mpi(&N1, &N2) != 0) { + rc = 1; + goto cleanup; + } + + if (mbedtls_mpi_cmp_mpi(&E1, &E2) != 0) { + rc = 1; + goto cleanup; + } +#else rsa1 = mbedtls_pk_rsa(*k1->rsa); rsa2 = mbedtls_pk_rsa(*k2->rsa); if (mbedtls_mpi_cmp_mpi(&rsa1->N, &rsa2->N) != 0) { - return 1; + rc = 1; + goto cleanup; } if (mbedtls_mpi_cmp_mpi(&rsa1->E, &rsa2->E) != 0) { - return 1; + rc = 1; + goto cleanup; + } +#endif + } else if (what == SSH_KEY_CMP_PRIVATE) { +#if MBEDTLS_VERSION_MAJOR > 2 + rsa1 = mbedtls_pk_rsa(*k1->rsa); + rc = mbedtls_rsa_export(rsa1, &N1, &P1, &Q1, NULL, &E1); + if (rc != 0) { + rc = 1; + goto cleanup; } - if (what == SSH_KEY_CMP_PRIVATE) { - if (mbedtls_mpi_cmp_mpi(&rsa1->P, &rsa2->P) != 0) { - return 1; - } - - if (mbedtls_mpi_cmp_mpi(&rsa1->Q, &rsa2->Q) != 0) { - return 1; - } + rsa2 = mbedtls_pk_rsa(*k2->rsa); + rc = mbedtls_rsa_export(rsa2, &N2, &P2, &Q2, NULL, &E2); + if (rc != 0) { + rc = 1; + goto cleanup; } + + if (mbedtls_mpi_cmp_mpi(&N1, &N2) != 0) { + rc = 1; + goto cleanup; + } + + if (mbedtls_mpi_cmp_mpi(&E1, &E2) != 0) { + rc = 1; + goto cleanup; + } + + if (mbedtls_mpi_cmp_mpi(&P1, &P2) != 0) { + rc = 1; + goto cleanup; + } + + if (mbedtls_mpi_cmp_mpi(&Q1, &Q2) != 0) { + rc = 1; + goto cleanup; + } +#else + rsa1 = mbedtls_pk_rsa(*k1->rsa); + rsa2 = mbedtls_pk_rsa(*k2->rsa); + if (mbedtls_mpi_cmp_mpi(&rsa1->N, &rsa2->N) != 0) { + rc = 1; + goto cleanup; + } + + if (mbedtls_mpi_cmp_mpi(&rsa1->E, &rsa2->E) != 0) { + rc = 1; + goto cleanup; + } + + if (mbedtls_mpi_cmp_mpi(&rsa1->P, &rsa2->P) != 0) { + rc = 1; + goto cleanup; + } + + if (mbedtls_mpi_cmp_mpi(&rsa1->Q, &rsa2->Q) != 0) { + rc = 1; + goto cleanup; + } +#endif } break; } @@ -548,25 +810,39 @@ int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) mbedtls_ecp_keypair *ecdsa1 = k1->ecdsa; mbedtls_ecp_keypair *ecdsa2 = k2->ecdsa; - if (ecdsa1->grp.id != ecdsa2->grp.id) { - return 1; + if (ecdsa1->MBEDTLS_PRIVATE(grp).id != + ecdsa2->MBEDTLS_PRIVATE(grp).id) { + rc = 1; + goto cleanup; } - if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.X, &ecdsa2->Q.X)) { - return 1; + if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), + &ecdsa2->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X))) + { + rc = 1; + goto cleanup; } - if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.Y, &ecdsa2->Q.Y)) { - return 1; + if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), + &ecdsa2->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y))) + { + rc = 1; + goto cleanup; } - if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.Z, &ecdsa2->Q.Z)) { - return 1; + if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), + &ecdsa2->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z))) + { + rc = 1; + goto cleanup; } if (what == SSH_KEY_CMP_PRIVATE) { - if (mbedtls_mpi_cmp_mpi(&ecdsa1->d, &ecdsa2->d)) { - return 1; + if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(d), + &ecdsa2->MBEDTLS_PRIVATE(d))) + { + rc = 1; + goto cleanup; } } @@ -575,12 +851,25 @@ int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_SK_ED25519: /* ed25519 keys handled globally */ - return 0; + rc = 0; + break; default: - return 1; + rc = 1; + break; } - return 0; +cleanup: +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi_free(&N1); + mbedtls_mpi_free(&N2); + mbedtls_mpi_free(&P1); + mbedtls_mpi_free(&P2); + mbedtls_mpi_free(&Q1); + mbedtls_mpi_free(&Q2); + mbedtls_mpi_free(&E1); + mbedtls_mpi_free(&E2); +#endif + return rc; } ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const @@ -645,8 +934,17 @@ ssh_string pki_publickey_to_blob(const ssh_key key) ssh_string e = NULL; ssh_string n = NULL; ssh_string str = NULL; +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi E; + mbedtls_mpi N; +#endif int rc; +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi_init(&E); + mbedtls_mpi_init(&N); +#endif + buffer = ssh_buffer_new(); if (buffer == NULL) { return NULL; @@ -685,6 +983,22 @@ ssh_string pki_publickey_to_blob(const ssh_key key) rsa = mbedtls_pk_rsa(*key->rsa); +#if MBEDTLS_VERSION_MAJOR > 2 + rc = mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, &E); + if (rc != 0) { + goto fail; + } + + e = ssh_make_bignum_string(&E); + if (e == NULL) { + goto fail; + } + + n = ssh_make_bignum_string(&N); + if (n == NULL) { + goto fail; + } +#else e = ssh_make_bignum_string(&rsa->E); if (e == NULL) { goto fail; @@ -694,6 +1008,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key) if (n == NULL) { goto fail; } +#endif if (ssh_buffer_add_ssh_string(buffer, e) < 0) { goto fail; @@ -730,7 +1045,8 @@ ssh_string pki_publickey_to_blob(const ssh_key key) return NULL; } - e = make_ecpoint_string(&key->ecdsa->grp, &key->ecdsa->Q); + e = make_ecpoint_string(&key->ecdsa->MBEDTLS_PRIVATE(grp), + &key->ecdsa->MBEDTLS_PRIVATE(Q)); if (e == NULL) { SSH_BUFFER_FREE(buffer); @@ -779,6 +1095,10 @@ makestring: } SSH_BUFFER_FREE(buffer); +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi_free(&N); + mbedtls_mpi_free(&E); +#endif return str; fail: SSH_BUFFER_FREE(buffer); @@ -788,6 +1108,10 @@ fail: SSH_STRING_FREE(e); ssh_string_burn(n); SSH_STRING_FREE(n); +#if MBEDTLS_VERSION_MAJOR > 2 + mbedtls_mpi_free(&N); + mbedtls_mpi_free(&E); +#endif return NULL; } @@ -1051,6 +1375,7 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest, mbedtls_md_type_t md = 0; unsigned char *sig = NULL; size_t slen; + size_t sig_size; int ok; switch (hash_type) { @@ -1069,7 +1394,8 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest, return NULL; } - sig = malloc(mbedtls_pk_get_bitlen(privkey) / 8); + sig_size = mbedtls_pk_get_bitlen(privkey) / 8; + sig = malloc(sig_size); if (sig == NULL) { return NULL; } @@ -1079,6 +1405,9 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest, digest, dlen, sig, +#if MBEDTLS_VERSION_MAJOR > 2 + sig_size, +#endif &slen, mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context()); @@ -1145,10 +1474,10 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, return NULL; } - rc = mbedtls_ecdsa_sign(&privkey->ecdsa->grp, + rc = mbedtls_ecdsa_sign(&privkey->ecdsa->MBEDTLS_PRIVATE(grp), sig->ecdsa_sig.r, sig->ecdsa_sig.s, - &privkey->ecdsa->d, + &privkey->ecdsa->MBEDTLS_PRIVATE(d), hash, hlen, mbedtls_ctr_drbg_random, @@ -1351,8 +1680,9 @@ int pki_verify_data_signature(ssh_signature signature, case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_SK_ECDSA: case SSH_KEYTYPE_SK_ECDSA_CERT01: - rc = mbedtls_ecdsa_verify(&pubkey->ecdsa->grp, hash, hlen, - &pubkey->ecdsa->Q, signature->ecdsa_sig.r, + rc = mbedtls_ecdsa_verify(&pubkey->ecdsa->MBEDTLS_PRIVATE(grp), hash, + hlen, &pubkey->ecdsa->MBEDTLS_PRIVATE(Q), + signature->ecdsa_sig.r, signature->ecdsa_sig.s); if (rc != 0) { char error_buf[100]; @@ -1455,18 +1785,19 @@ int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) goto fail; } - rc = mbedtls_ecp_copy(&keypair.Q, &Q); + rc = mbedtls_ecp_copy(&keypair.MBEDTLS_PRIVATE(Q), &Q); if (rc != 0) { goto fail; } - rc = mbedtls_ecp_group_copy(&keypair.grp, &group); + rc = mbedtls_ecp_group_copy(&keypair.MBEDTLS_PRIVATE(grp), &group); if (rc != 0) { goto fail; } - rc = mbedtls_mpi_read_binary(&keypair.d, ssh_string_data(exp), - ssh_string_len(exp)); + rc = mbedtls_mpi_read_binary(&keypair.MBEDTLS_PRIVATE(d), + ssh_string_data(exp), + ssh_string_len(exp)); if (rc != 0) { goto fail; } @@ -1522,17 +1853,17 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) goto fail; } - rc = mbedtls_ecp_copy(&keypair.Q, &Q); + rc = mbedtls_ecp_copy(&keypair.MBEDTLS_PRIVATE(Q), &Q); if (rc != 0) { goto fail; } - rc = mbedtls_ecp_group_copy(&keypair.grp, &group); + rc = mbedtls_ecp_group_copy(&keypair.MBEDTLS_PRIVATE(grp), &group); if (rc != 0) { goto fail; } - mbedtls_mpi_init(&keypair.d); + mbedtls_mpi_init(&keypair.MBEDTLS_PRIVATE(d)); rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair); if (rc != 0) {