pki_crypto: Fix ecdsa memory leak

Fixed a memory leak in pki_privkey_build_ecdsa. The BIGNUM bexp was
getting allocated, but not free'd. It gets stored by reference in
param_bld.

Signed-off-by: roytak <xjanot04@fit.vutbr.cz>
Reviewed-by: Norbert Pocs <npocs@redhat.com>
This commit is contained in:
roytak
2023-04-21 10:34:00 +02:00
committed by Jakub Jelen
parent 4f64aa3a5a
commit 9b263cf5e1

View File

@@ -204,111 +204,125 @@ int pki_key_ecdsa_nid_from_name(const char *name)
int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
{ {
int rc; int rc = 0;
BIGNUM *bexp = NULL;
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if OPENSSL_VERSION_NUMBER < 0x30000000L
EC_POINT *p = NULL; EC_POINT *p = NULL;
const EC_GROUP *g = NULL; const EC_GROUP *g = NULL;
int ok;
BIGNUM *bexp = NULL;
EC_KEY *ecdsa = NULL; EC_KEY *ecdsa = NULL;
#else #else
const BIGNUM *expb;
const char *group_name = OSSL_EC_curve_nid2name(nid); const char *group_name = OSSL_EC_curve_nid2name(nid);
OSSL_PARAM_BLD *param_bld = NULL; OSSL_PARAM_BLD *param_bld = NULL;
if (group_name == NULL) { if (group_name == NULL) {
return -1; return -1;
} }
expb = ssh_make_string_bn(exp);
#endif /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_VERSION_NUMBER */
bexp = ssh_make_string_bn(exp);
if (bexp == NULL) {
return -1;
}
key->ecdsa_nid = nid; key->ecdsa_nid = nid;
key->type_c = pki_key_ecdsa_nid_to_name(nid); key->type_c = pki_key_ecdsa_nid_to_name(nid);
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if OPENSSL_VERSION_NUMBER < 0x30000000L
ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
if (ecdsa == NULL) { if (ecdsa == NULL) {
return -1; rc = -1;
goto cleanup;
} }
g = EC_KEY_get0_group(ecdsa); g = EC_KEY_get0_group(ecdsa);
p = EC_POINT_new(g); p = EC_POINT_new(g);
if (p == NULL) { if (p == NULL) {
EC_KEY_free(ecdsa); rc = -1;
return -1; goto cleanup;
} }
ok = EC_POINT_oct2point(g, rc = EC_POINT_oct2point(g,
p, p,
ssh_string_data(e), ssh_string_data(e),
ssh_string_len(e), ssh_string_len(e),
NULL); NULL);
if (!ok) { if (rc != 1) {
EC_KEY_free(ecdsa); rc = -1;
EC_POINT_free(p); goto cleanup;
return -1;
} }
/* EC_KEY_set_public_key duplicates p */ /* EC_KEY_set_public_key duplicates p */
ok = EC_KEY_set_public_key(ecdsa, p); rc = EC_KEY_set_public_key(ecdsa, p);
EC_POINT_free(p); if (rc != 1) {
if (!ok) { rc = -1;
EC_KEY_free(ecdsa); goto cleanup;
return -1;
} }
bexp = ssh_make_string_bn(exp);
if (bexp == NULL) {
EC_KEY_free(ecdsa);
return -1;
}
/* EC_KEY_set_private_key duplicates exp */ /* EC_KEY_set_private_key duplicates exp */
ok = EC_KEY_set_private_key(ecdsa, bexp); rc = EC_KEY_set_private_key(ecdsa, bexp);
BN_free(bexp); if (rc != 1) {
if (!ok) { rc = -1;
EC_KEY_free(ecdsa); goto cleanup;
return -1;
} }
key->key = EVP_PKEY_new(); key->key = EVP_PKEY_new();
if (key->key == NULL) { if (key->key == NULL) {
EC_KEY_free(ecdsa); rc = -1;
return -1; goto cleanup;
} }
/* ecdsa will be freed when the EVP_PKEY key->key is freed */
rc = EVP_PKEY_assign_EC_KEY(key->key, ecdsa); rc = EVP_PKEY_assign_EC_KEY(key->key, ecdsa);
if (rc != 1) { if (rc != 1) {
EVP_PKEY_free(key->key); rc = -1;
EC_KEY_free(ecdsa); goto cleanup;
return -1;
} }
/* ssh_key is now the owner of this memory */
ecdsa = NULL;
return 0; /* set rc to 0 if everything went well */
rc = 0;
cleanup:
EC_KEY_free(ecdsa);
EC_POINT_free(p);
BN_free(bexp);
return rc;
#else #else
param_bld = OSSL_PARAM_BLD_new(); param_bld = OSSL_PARAM_BLD_new();
if (param_bld == NULL) if (param_bld == NULL){
goto err; rc = -1;
goto cleanup;
}
rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_PKEY_PARAM_GROUP_NAME, rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_PKEY_PARAM_GROUP_NAME,
group_name, strlen(group_name)); group_name, strlen(group_name));
if (rc != 1) if (rc != 1) {
goto err; rc = -1;
goto cleanup;
}
rc = OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_PKEY_PARAM_PUB_KEY, rc = OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_PKEY_PARAM_PUB_KEY,
ssh_string_data(e), ssh_string_len(e)); ssh_string_data(e), ssh_string_len(e));
if (rc != 1) if (rc != 1) {
goto err; rc = -1;
rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, expb); goto cleanup;
if (rc != 1) }
goto err;
rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, bexp);
if (rc != 1) {
rc = -1;
goto cleanup;
}
rc = evp_build_pkey("EC", param_bld, &(key->key), EVP_PKEY_KEYPAIR); rc = evp_build_pkey("EC", param_bld, &(key->key), EVP_PKEY_KEYPAIR);
OSSL_PARAM_BLD_free(param_bld);
return rc; cleanup:
err:
OSSL_PARAM_BLD_free(param_bld); OSSL_PARAM_BLD_free(param_bld);
return -1; BN_free(bexp);
return rc;
#endif /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_VERSION_NUMBER */
} }