1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-12-15 18:32:26 +03:00

Fix mbedTLS issues caused by v3 API changes

Signed-off-by: Juraj Vijtiuk <vijtiuk.juraj@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Juraj Vijtiuk
2022-06-07 00:39:13 +02:00
committed by Jakub Jelen
parent 9caedca2c6
commit 0c08159f53
4 changed files with 507 additions and 115 deletions

View File

@@ -34,6 +34,7 @@
#include <mbedtls/ecdh.h> #include <mbedtls/ecdh.h>
#include <mbedtls/ecp.h> #include <mbedtls/ecp.h>
#include "mbedcrypto-compat.h"
#ifdef HAVE_ECDH #ifdef HAVE_ECDH
@@ -54,6 +55,10 @@ int ssh_client_ecdh_init(ssh_session session)
mbedtls_ecp_group grp; mbedtls_ecp_group grp;
int rc; int rc;
mbedtls_ecp_group_id curve; 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); curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type);
if (curve == MBEDTLS_ECP_DP_NONE) { if (curve == MBEDTLS_ECP_DP_NONE) {
@@ -70,7 +75,9 @@ int ssh_client_ecdh_init(ssh_session session)
return SSH_ERROR; 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); mbedtls_ecp_group_init(&grp);
rc = mbedtls_ecp_group_load(&grp, curve); 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, rc = mbedtls_ecp_gen_keypair(&grp,
&session->next_crypto->ecdh_privkey->d, &ecdh_privkey->MBEDTLS_PRIVATE(d),
&session->next_crypto->ecdh_privkey->Q, &ecdh_privkey->MBEDTLS_PRIVATE(Q),
mbedtls_ctr_drbg_random, mbedtls_ctr_drbg_random,
ssh_get_mbedtls_ctr_drbg_context()); ctr_drbg);
if (rc != 0) { if (rc != 0) {
rc = SSH_ERROR; rc = SSH_ERROR;
@@ -91,7 +98,7 @@ int ssh_client_ecdh_init(ssh_session session)
} }
client_pubkey = make_ecpoint_string(&grp, client_pubkey = make_ecpoint_string(&grp,
&session->next_crypto->ecdh_privkey->Q); &ecdh_privkey->MBEDTLS_PRIVATE(Q));
if (client_pubkey == NULL) { if (client_pubkey == NULL) {
rc = SSH_ERROR; rc = SSH_ERROR;
goto out; goto out;
@@ -124,6 +131,10 @@ int ecdh_build_k(ssh_session session)
mbedtls_ecp_point pubkey; mbedtls_ecp_point pubkey;
int rc; int rc;
mbedtls_ecp_group_id curve; 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); curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type);
if (curve == MBEDTLS_ECP_DP_NONE) { 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); mbedtls_mpi_init(session->next_crypto->shared_secret);
ecdh_privkey = session->next_crypto->ecdh_privkey;
rc = mbedtls_ecdh_compute_shared(&grp, rc = mbedtls_ecdh_compute_shared(&grp,
session->next_crypto->shared_secret, session->next_crypto->shared_secret,
&pubkey, &pubkey,
&session->next_crypto->ecdh_privkey->d, &ecdh_privkey->MBEDTLS_PRIVATE(d),
mbedtls_ctr_drbg_random, mbedtls_ctr_drbg_random,
ssh_get_mbedtls_ctr_drbg_context()); ctr_drbg);
if (rc != 0) { if (rc != 0) {
rc = SSH_ERROR; rc = SSH_ERROR;
goto out; goto out;
} }
out: out:
mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey); mbedtls_ecp_keypair_free(ecdh_privkey);
SAFE_FREE(session->next_crypto->ecdh_privkey); SAFE_FREE(session->next_crypto->ecdh_privkey);
mbedtls_ecp_group_free(&grp); mbedtls_ecp_group_free(&grp);
mbedtls_ecp_point_free(&pubkey); 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_c_string = NULL;
ssh_string q_s_string = NULL; ssh_string q_s_string = NULL;
mbedtls_ecp_group grp; mbedtls_ecp_group grp;
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
mbedtls_ecp_keypair *ecdh_privkey = NULL;
ssh_key privkey = NULL; ssh_key privkey = NULL;
enum ssh_digest_e digest = SSH_DIGEST_AUTO; enum ssh_digest_e digest = SSH_DIGEST_AUTO;
ssh_string sig_blob = NULL; ssh_string sig_blob = NULL;
@@ -214,10 +228,14 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
return SSH_ERROR; return SSH_ERROR;
} }
ecdh_privkey = session->next_crypto->ecdh_privkey;
session->next_crypto->ecdh_client_pubkey = q_c_string; session->next_crypto->ecdh_client_pubkey = q_c_string;
ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
mbedtls_ecp_group_init(&grp); 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); rc = mbedtls_ecp_group_load(&grp, curve);
if (rc != 0) { if (rc != 0) {
@@ -226,16 +244,16 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){
} }
rc = mbedtls_ecp_gen_keypair(&grp, rc = mbedtls_ecp_gen_keypair(&grp,
&session->next_crypto->ecdh_privkey->d, &ecdh_privkey->MBEDTLS_PRIVATE(d),
&session->next_crypto->ecdh_privkey->Q, &ecdh_privkey->MBEDTLS_PRIVATE(Q),
mbedtls_ctr_drbg_random, mbedtls_ctr_drbg_random,
ssh_get_mbedtls_ctr_drbg_context()); ctr_drbg);
if (rc != 0) { if (rc != 0) {
rc = SSH_ERROR; rc = SSH_ERROR;
goto out; 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) { if (q_s_string == NULL) {
rc = SSH_ERROR; rc = SSH_ERROR;
goto out; goto out;

View File

@@ -27,6 +27,7 @@
#include "libssh/crypto.h" #include "libssh/crypto.h"
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/misc.h" #include "libssh/misc.h"
#include "mbedcrypto-compat.h"
#if defined(MBEDTLS_CHACHA20_C) && defined(MBEDTLS_POLY1305_C) #if defined(MBEDTLS_CHACHA20_C) && defined(MBEDTLS_POLY1305_C)
#include "libssh/bytearray.h" #include "libssh/bytearray.h"
#include "libssh/chacha20-poly1305-common.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) 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_finish(ctx, md);
mbedtls_md_free(ctx); mbedtls_md_free(ctx);
SAFE_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) 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_hmac_finish(c, hashmacbuf);
mbedtls_md_free(c); mbedtls_md_free(c);
SAFE_FREE(c); SAFE_FREE(c);
@@ -467,6 +468,8 @@ cipher_init(struct ssh_cipher_struct *cipher,
{ {
const mbedtls_cipher_info_t *cipher_info = NULL; const mbedtls_cipher_info_t *cipher_info = NULL;
mbedtls_cipher_context_t *ctx; mbedtls_cipher_context_t *ctx;
size_t key_bitlen = 0;
size_t iv_size = 0;
int rc; int rc;
if (operation == MBEDTLS_ENCRYPT) { if (operation == MBEDTLS_ENCRYPT) {
@@ -487,15 +490,15 @@ cipher_init(struct ssh_cipher_struct *cipher,
goto error; goto error;
} }
rc = mbedtls_cipher_setkey(ctx, key, key_bitlen = mbedtls_cipher_info_get_key_bitlen(cipher_info);
cipher_info->key_bitlen, rc = mbedtls_cipher_setkey(ctx, key, key_bitlen, operation);
operation);
if (rc != 0) { if (rc != 0) {
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed"); SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed");
goto error; 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) { if (rc != 0) {
SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed"); SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed");
goto error; goto error;
@@ -573,15 +576,16 @@ cipher_set_key_gcm(struct ssh_cipher_struct *cipher,
void *IV) void *IV)
{ {
const mbedtls_cipher_info_t *cipher_info = NULL; const mbedtls_cipher_info_t *cipher_info = NULL;
size_t key_bitlen = 0;
int rc; int rc;
mbedtls_gcm_init(&cipher->gcm_ctx); mbedtls_gcm_init(&cipher->gcm_ctx);
cipher_info = mbedtls_cipher_info_from_type(cipher->type); cipher_info = mbedtls_cipher_info_from_type(cipher->type);
rc = mbedtls_gcm_setkey(&cipher->gcm_ctx, key_bitlen = mbedtls_cipher_info_get_key_bitlen(cipher_info);
MBEDTLS_CIPHER_ID_AES, rc = mbedtls_gcm_setkey(&cipher->gcm_ctx, MBEDTLS_CIPHER_ID_AES,
key, key, key_bitlen);
cipher_info->key_bitlen);
if (rc != 0) { if (rc != 0) {
SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_setkey failed"); SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_setkey failed");
goto error; goto error;

39
src/mbedcrypto-compat.h Normal file
View File

@@ -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 <mbedtls/version.h>
#include <mbedtls/cipher.h>
#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 <mbedtls/build_info.h>
#if MBEDTLS_VERSION_MAJOR < 3
#define MBEDTLS_PRIVATE(X) X
#endif /* MBEDTLS_VERSION_MAJOR < 3 */
#endif /* MBEDTLS_VERSION_MAJOR */
#endif /* MBEDCRYPTO_COMPAT_H */

View File

@@ -26,6 +26,7 @@
#ifdef HAVE_LIBMBEDCRYPTO #ifdef HAVE_LIBMBEDCRYPTO
#include <mbedtls/pk.h> #include <mbedtls/pk.h>
#include <mbedtls/error.h> #include <mbedtls/error.h>
#include "mbedcrypto-compat.h"
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/pki.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; mbedtls_ecp_group_id id;
id = ecdsa->grp.id; id = ecdsa->MBEDTLS_PRIVATE(grp.id);
if (id == MBEDTLS_ECP_DP_SECP256R1) { if (id == MBEDTLS_ECP_DP_SECP256R1) {
return NID_mbedtls_nistp256; return NID_mbedtls_nistp256;
} else if (id == MBEDTLS_ECP_DP_SECP384R1) { } 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 */ /* mbedtls pk_parse_key expects strlen to count the 0 byte */
size_t b64len = strlen(b64_key) + 1; size_t b64len = strlen(b64_key) + 1;
unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0}; 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); type = pki_privatekey_type_from_string(b64_key);
if (type == SSH_KEYTYPE_UNKNOWN) { 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; goto fail;
} }
/* TODO fix signedness and strlen */ /* 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, valid = mbedtls_pk_parse_key(rsa,
(const unsigned char *) b64_key, (const unsigned char *) b64_key,
b64len, tmp, b64len, tmp,
strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
#endif
} else { } 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, valid = mbedtls_pk_parse_key(rsa,
(const unsigned char *) b64_key, (const unsigned char *) b64_key,
b64len, NULL, b64len, NULL,
0); 0);
#endif
} }
} else { } 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, valid = mbedtls_pk_parse_key(rsa,
(const unsigned char *) b64_key, b64len, (const unsigned char *) b64_key, b64len,
(const unsigned char *) passphrase, (const unsigned char *) passphrase,
strnlen(passphrase, MAX_PASSPHRASE_SIZE)); strnlen(passphrase, MAX_PASSPHRASE_SIZE));
#endif
} }
if (valid != 0) { 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_P256:
case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P384:
case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_ECDSA_P521:
#if MBEDTLS_VERSION_MAJOR > 2
ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
#else
ecdsa = malloc(sizeof(mbedtls_pk_context)); ecdsa = malloc(sizeof(mbedtls_pk_context));
#endif
if (ecdsa == NULL) { if (ecdsa == NULL) {
return NULL; return NULL;
} }
@@ -157,21 +188,44 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
if (valid < 0) { if (valid < 0) {
goto fail; 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, valid = mbedtls_pk_parse_key(ecdsa,
(const unsigned char *) b64_key, (const unsigned char *) b64_key,
b64len, tmp, b64len, tmp,
strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
#endif
} else { } 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, valid = mbedtls_pk_parse_key(ecdsa,
(const unsigned char *) b64_key, (const unsigned char *) b64_key,
b64len, NULL, b64len, NULL,
0); 0);
#endif
} }
} else { } 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, valid = mbedtls_pk_parse_key(ecdsa,
(const unsigned char *) b64_key, b64len, (const unsigned char *) b64_key, b64len,
(const unsigned char *) passphrase, (const unsigned char *) passphrase,
strnlen(passphrase, MAX_PASSPHRASE_SIZE)); strnlen(passphrase, MAX_PASSPHRASE_SIZE));
#endif
} }
if (valid != 0) { 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; mbedtls_rsa_context *rsa = NULL;
const mbedtls_pk_info_t *pk_info = NULL; const mbedtls_pk_info_t *pk_info = NULL;
#if MBEDTLS_VERSION_MAJOR > 2
mbedtls_mpi N;
mbedtls_mpi E;
#endif
int rc; int rc;
key->rsa = malloc(sizeof(mbedtls_pk_context)); 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; goto fail;
} }
#if MBEDTLS_VERSION_MAJOR > 2
mbedtls_mpi_init(&N);
mbedtls_mpi_init(&E);
#endif
rsa = mbedtls_pk_rsa(*key->rsa); 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), rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n),
ssh_string_len(n)); ssh_string_len(n));
#endif
if (rc != 0) { if (rc != 0) {
goto fail; 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), rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e),
ssh_string_len(e)); ssh_string_len(e));
#endif
if (rc != 0) { if (rc != 0) {
goto fail; 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; rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3;
#endif
return SSH_OK; rc = SSH_OK;
goto exit;
fail: fail:
rc = SSH_ERROR;
mbedtls_pk_free(key->rsa); mbedtls_pk_free(key->rsa);
SAFE_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) 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; ssh_key new = NULL;
int rc; int rc;
const mbedtls_pk_info_t *pk_info = NULL; 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(); new = ssh_key_new();
if (new == NULL) { if (new == NULL) {
@@ -362,6 +459,13 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
new->flags = key->flags; 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) { switch(key->type) {
case SSH_KEYTYPE_RSA: { 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); pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
mbedtls_pk_setup(new->rsa, pk_info); mbedtls_pk_setup(new->rsa, pk_info);
if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) && if (!mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) ||
mbedtls_pk_can_do(new->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); 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); rc = mbedtls_mpi_copy(&new_rsa->N, &rsa->N);
if (rc != 0) { if (rc != 0) {
goto fail; goto fail;
@@ -390,42 +509,70 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
if (rc != 0) { if (rc != 0) {
goto fail; goto fail;
} }
new_rsa->len = (mbedtls_mpi_bitlen(&new_rsa->N) + 7) >> 3; 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);
rc = mbedtls_mpi_copy(&new_rsa->D, &rsa->D); if (rc != 0) {
if (rc != 0) { goto fail;
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->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 { } 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; goto fail;
} }
#endif
break; break;
} }
@@ -443,12 +590,14 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
mbedtls_ecdsa_init(new->ecdsa); mbedtls_ecdsa_init(new->ecdsa);
if (demote && ssh_key_is_private(key)) { 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) { if (rc != 0) {
goto fail; 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) { if (rc != 0) {
goto fail; goto fail;
} }
@@ -467,10 +616,19 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail; goto fail;
} }
return new; goto cleanup;
fail: fail:
ssh_key_free(new); SSH_KEY_FREE(new);
return NULL; 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) 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 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) { switch (k1->type) {
case SSH_KEYTYPE_RSA: { case SSH_KEYTYPE_RSA: {
mbedtls_rsa_context *rsa1, *rsa2; mbedtls_rsa_context *rsa1, *rsa2;
if (mbedtls_pk_can_do(k1->rsa, MBEDTLS_PK_RSA) && if (!mbedtls_pk_can_do(k1->rsa, MBEDTLS_PK_RSA) ||
mbedtls_pk_can_do(k2->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) != break;
mbedtls_pk_get_bitlen(k2->rsa)) { }
return 1;
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); rsa1 = mbedtls_pk_rsa(*k1->rsa);
rsa2 = mbedtls_pk_rsa(*k2->rsa); rsa2 = mbedtls_pk_rsa(*k2->rsa);
if (mbedtls_mpi_cmp_mpi(&rsa1->N, &rsa2->N) != 0) { 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) { 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) { rsa2 = mbedtls_pk_rsa(*k2->rsa);
if (mbedtls_mpi_cmp_mpi(&rsa1->P, &rsa2->P) != 0) { rc = mbedtls_rsa_export(rsa2, &N2, &P2, &Q2, NULL, &E2);
return 1; if (rc != 0) {
} rc = 1;
goto cleanup;
if (mbedtls_mpi_cmp_mpi(&rsa1->Q, &rsa2->Q) != 0) {
return 1;
}
} }
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; 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 *ecdsa1 = k1->ecdsa;
mbedtls_ecp_keypair *ecdsa2 = k2->ecdsa; mbedtls_ecp_keypair *ecdsa2 = k2->ecdsa;
if (ecdsa1->grp.id != ecdsa2->grp.id) { if (ecdsa1->MBEDTLS_PRIVATE(grp).id !=
return 1; ecdsa2->MBEDTLS_PRIVATE(grp).id) {
rc = 1;
goto cleanup;
} }
if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.X, &ecdsa2->Q.X)) { if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X),
return 1; &ecdsa2->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)))
{
rc = 1;
goto cleanup;
} }
if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.Y, &ecdsa2->Q.Y)) { if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
return 1; &ecdsa2->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)))
{
rc = 1;
goto cleanup;
} }
if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.Z, &ecdsa2->Q.Z)) { if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z),
return 1; &ecdsa2->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z)))
{
rc = 1;
goto cleanup;
} }
if (what == SSH_KEY_CMP_PRIVATE) { if (what == SSH_KEY_CMP_PRIVATE) {
if (mbedtls_mpi_cmp_mpi(&ecdsa1->d, &ecdsa2->d)) { if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(d),
return 1; &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_ED25519:
case SSH_KEYTYPE_SK_ED25519: case SSH_KEYTYPE_SK_ED25519:
/* ed25519 keys handled globally */ /* ed25519 keys handled globally */
return 0; rc = 0;
break;
default: 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 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 e = NULL;
ssh_string n = NULL; ssh_string n = NULL;
ssh_string str = NULL; ssh_string str = NULL;
#if MBEDTLS_VERSION_MAJOR > 2
mbedtls_mpi E;
mbedtls_mpi N;
#endif
int rc; int rc;
#if MBEDTLS_VERSION_MAJOR > 2
mbedtls_mpi_init(&E);
mbedtls_mpi_init(&N);
#endif
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
return NULL; return NULL;
@@ -685,6 +983,22 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
rsa = mbedtls_pk_rsa(*key->rsa); 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); e = ssh_make_bignum_string(&rsa->E);
if (e == NULL) { if (e == NULL) {
goto fail; goto fail;
@@ -694,6 +1008,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
if (n == NULL) { if (n == NULL) {
goto fail; goto fail;
} }
#endif
if (ssh_buffer_add_ssh_string(buffer, e) < 0) { if (ssh_buffer_add_ssh_string(buffer, e) < 0) {
goto fail; goto fail;
@@ -730,7 +1045,8 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
return NULL; 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) { if (e == NULL) {
SSH_BUFFER_FREE(buffer); SSH_BUFFER_FREE(buffer);
@@ -779,6 +1095,10 @@ makestring:
} }
SSH_BUFFER_FREE(buffer); SSH_BUFFER_FREE(buffer);
#if MBEDTLS_VERSION_MAJOR > 2
mbedtls_mpi_free(&N);
mbedtls_mpi_free(&E);
#endif
return str; return str;
fail: fail:
SSH_BUFFER_FREE(buffer); SSH_BUFFER_FREE(buffer);
@@ -788,6 +1108,10 @@ fail:
SSH_STRING_FREE(e); SSH_STRING_FREE(e);
ssh_string_burn(n); ssh_string_burn(n);
SSH_STRING_FREE(n); SSH_STRING_FREE(n);
#if MBEDTLS_VERSION_MAJOR > 2
mbedtls_mpi_free(&N);
mbedtls_mpi_free(&E);
#endif
return NULL; return NULL;
} }
@@ -1051,6 +1375,7 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest,
mbedtls_md_type_t md = 0; mbedtls_md_type_t md = 0;
unsigned char *sig = NULL; unsigned char *sig = NULL;
size_t slen; size_t slen;
size_t sig_size;
int ok; int ok;
switch (hash_type) { switch (hash_type) {
@@ -1069,7 +1394,8 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest,
return NULL; 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) { if (sig == NULL) {
return NULL; return NULL;
} }
@@ -1079,6 +1405,9 @@ static ssh_string rsa_do_sign_hash(const unsigned char *digest,
digest, digest,
dlen, dlen,
sig, sig,
#if MBEDTLS_VERSION_MAJOR > 2
sig_size,
#endif
&slen, &slen,
mbedtls_ctr_drbg_random, mbedtls_ctr_drbg_random,
ssh_get_mbedtls_ctr_drbg_context()); ssh_get_mbedtls_ctr_drbg_context());
@@ -1145,10 +1474,10 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey,
return NULL; 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.r,
sig->ecdsa_sig.s, sig->ecdsa_sig.s,
&privkey->ecdsa->d, &privkey->ecdsa->MBEDTLS_PRIVATE(d),
hash, hash,
hlen, hlen,
mbedtls_ctr_drbg_random, 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_ECDSA_P521_CERT01:
case SSH_KEYTYPE_SK_ECDSA: case SSH_KEYTYPE_SK_ECDSA:
case SSH_KEYTYPE_SK_ECDSA_CERT01: case SSH_KEYTYPE_SK_ECDSA_CERT01:
rc = mbedtls_ecdsa_verify(&pubkey->ecdsa->grp, hash, hlen, rc = mbedtls_ecdsa_verify(&pubkey->ecdsa->MBEDTLS_PRIVATE(grp), hash,
&pubkey->ecdsa->Q, signature->ecdsa_sig.r, hlen, &pubkey->ecdsa->MBEDTLS_PRIVATE(Q),
signature->ecdsa_sig.r,
signature->ecdsa_sig.s); signature->ecdsa_sig.s);
if (rc != 0) { if (rc != 0) {
char error_buf[100]; 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; goto fail;
} }
rc = mbedtls_ecp_copy(&keypair.Q, &Q); rc = mbedtls_ecp_copy(&keypair.MBEDTLS_PRIVATE(Q), &Q);
if (rc != 0) { if (rc != 0) {
goto fail; goto fail;
} }
rc = mbedtls_ecp_group_copy(&keypair.grp, &group); rc = mbedtls_ecp_group_copy(&keypair.MBEDTLS_PRIVATE(grp), &group);
if (rc != 0) { if (rc != 0) {
goto fail; goto fail;
} }
rc = mbedtls_mpi_read_binary(&keypair.d, ssh_string_data(exp), rc = mbedtls_mpi_read_binary(&keypair.MBEDTLS_PRIVATE(d),
ssh_string_len(exp)); ssh_string_data(exp),
ssh_string_len(exp));
if (rc != 0) { if (rc != 0) {
goto fail; goto fail;
} }
@@ -1522,17 +1853,17 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
goto fail; goto fail;
} }
rc = mbedtls_ecp_copy(&keypair.Q, &Q); rc = mbedtls_ecp_copy(&keypair.MBEDTLS_PRIVATE(Q), &Q);
if (rc != 0) { if (rc != 0) {
goto fail; goto fail;
} }
rc = mbedtls_ecp_group_copy(&keypair.grp, &group); rc = mbedtls_ecp_group_copy(&keypair.MBEDTLS_PRIVATE(grp), &group);
if (rc != 0) { if (rc != 0) {
goto fail; goto fail;
} }
mbedtls_mpi_init(&keypair.d); mbedtls_mpi_init(&keypair.MBEDTLS_PRIVATE(d));
rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair); rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair);
if (rc != 0) { if (rc != 0) {