mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-09 09:54:25 +09:00
pki_crypto: Reformat pki_key_to_blob()
Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
committed by
Andreas Schneider
parent
8dc29f140b
commit
faf9caafc6
772
src/pki_crypto.c
772
src/pki_crypto.c
@@ -1573,188 +1573,231 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case SSH_KEYTYPE_RSA:
|
case SSH_KEYTYPE_RSA:
|
||||||
case SSH_KEYTYPE_RSA1: {
|
case SSH_KEYTYPE_RSA1: {
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
const BIGNUM *be = NULL, *bn = NULL;
|
const BIGNUM *be = NULL, *bn = NULL;
|
||||||
const RSA *key_rsa = EVP_PKEY_get0_RSA(key->key);
|
const RSA *key_rsa = EVP_PKEY_get0_RSA(key->key);
|
||||||
RSA_get0_key(key_rsa, &bn, &be, NULL);
|
RSA_get0_key(key_rsa, &bn, &be, NULL);
|
||||||
#else
|
#else
|
||||||
const OSSL_PARAM *out_param = NULL;
|
const OSSL_PARAM *out_param = NULL;
|
||||||
rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms);
|
rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms);
|
||||||
if (rc != 1) {
|
if (rc != 1) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E);
|
|
||||||
if (out_param == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "RSA: No param E has been found");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = OSSL_PARAM_get_BN(out_param, &be);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N);
|
|
||||||
if (out_param == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "RSA: No param N has been found");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = OSSL_PARAM_get_BN(out_param, &bn);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
|
||||||
e = ssh_make_bignum_string((BIGNUM *)be);
|
|
||||||
if (e == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = ssh_make_bignum_string((BIGNUM *)bn);
|
|
||||||
if (n == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == SSH_KEY_PUBLIC) {
|
|
||||||
/* The N and E parts are swapped in the public key export ! */
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, e);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, n);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
} else if (type == SSH_KEY_PRIVATE) {
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
|
||||||
const BIGNUM *bd, *biqmp, *bp, *bq;
|
|
||||||
RSA_get0_key(key_rsa, NULL, NULL, &bd);
|
|
||||||
RSA_get0_factors(key_rsa, &bp, &bq);
|
|
||||||
RSA_get0_crt_params(key_rsa, NULL, NULL, &biqmp);
|
|
||||||
#else
|
|
||||||
OSSL_PARAM_free(params);
|
|
||||||
rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
|
|
||||||
if (out_param == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "RSA: No param D has been found");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = OSSL_PARAM_get_BN(out_param, &bd);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1);
|
|
||||||
if (out_param == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "RSA: No param P has been found");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = OSSL_PARAM_get_BN(out_param, &bp);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2);
|
|
||||||
if (out_param == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "RSA: No param Q has been found");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = OSSL_PARAM_get_BN(out_param, &bq);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1);
|
|
||||||
if (out_param == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "RSA: No param IQMP has been found");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = OSSL_PARAM_get_BN(out_param, &biqmp);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, n);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, e);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
d = ssh_make_bignum_string((BIGNUM *)bd);
|
|
||||||
if (d == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
iqmp = ssh_make_bignum_string((BIGNUM *)biqmp);
|
|
||||||
if (iqmp == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = ssh_make_bignum_string((BIGNUM *)bp);
|
|
||||||
if (p == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
q = ssh_make_bignum_string((BIGNUM *)bq);
|
|
||||||
if (q == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, d);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, iqmp);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, p);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, q);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_string_burn(d);
|
|
||||||
SSH_STRING_FREE(d);
|
|
||||||
ssh_string_burn(iqmp);
|
|
||||||
SSH_STRING_FREE(iqmp);
|
|
||||||
ssh_string_burn(p);
|
|
||||||
SSH_STRING_FREE(p);
|
|
||||||
ssh_string_burn(q);
|
|
||||||
SSH_STRING_FREE(q);
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
||||||
bignum_safe_free(bd);
|
|
||||||
bignum_safe_free(biqmp);
|
|
||||||
bignum_safe_free(bp);
|
|
||||||
bignum_safe_free(bq);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
|
||||||
}
|
|
||||||
ssh_string_burn(e);
|
|
||||||
SSH_STRING_FREE(e);
|
|
||||||
ssh_string_burn(n);
|
|
||||||
SSH_STRING_FREE(n);
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
||||||
bignum_safe_free(bn);
|
|
||||||
bignum_safe_free(be);
|
|
||||||
OSSL_PARAM_free(params);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case SSH_KEYTYPE_ED25519:
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E);
|
||||||
case SSH_KEYTYPE_SK_ED25519:
|
if (out_param == NULL) {
|
||||||
rc = EVP_PKEY_get_raw_public_key(key->key, NULL, &key_len);
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param E has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &be);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param N has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &bn);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
e = ssh_make_bignum_string((BIGNUM *)be);
|
||||||
|
if (e == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = ssh_make_bignum_string((BIGNUM *)bn);
|
||||||
|
if (n == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == SSH_KEY_PUBLIC) {
|
||||||
|
/* The N and E parts are swapped in the public key export ! */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else if (type == SSH_KEY_PRIVATE) {
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
|
const BIGNUM *bd, *biqmp, *bp, *bq;
|
||||||
|
RSA_get0_key(key_rsa, NULL, NULL, &bd);
|
||||||
|
RSA_get0_factors(key_rsa, &bp, &bq);
|
||||||
|
RSA_get0_crt_params(key_rsa, NULL, NULL, &biqmp);
|
||||||
|
#else
|
||||||
|
OSSL_PARAM_free(params);
|
||||||
|
rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param D has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &bd);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param P has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &bp);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param Q has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &bq);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1);
|
||||||
|
if (out_param == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "RSA: No param IQMP has been found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = OSSL_PARAM_get_BN(out_param, &biqmp);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, n);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = ssh_make_bignum_string((BIGNUM *)bd);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
iqmp = ssh_make_bignum_string((BIGNUM *)biqmp);
|
||||||
|
if (iqmp == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ssh_make_bignum_string((BIGNUM *)bp);
|
||||||
|
if (p == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = ssh_make_bignum_string((BIGNUM *)bq);
|
||||||
|
if (q == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, iqmp);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, p);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, q);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
ssh_string_burn(iqmp);
|
||||||
|
SSH_STRING_FREE(iqmp);
|
||||||
|
ssh_string_burn(p);
|
||||||
|
SSH_STRING_FREE(p);
|
||||||
|
ssh_string_burn(q);
|
||||||
|
SSH_STRING_FREE(q);
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
bignum_safe_free(bd);
|
||||||
|
bignum_safe_free(biqmp);
|
||||||
|
bignum_safe_free(bp);
|
||||||
|
bignum_safe_free(bq);
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
}
|
||||||
|
ssh_string_burn(e);
|
||||||
|
SSH_STRING_FREE(e);
|
||||||
|
ssh_string_burn(n);
|
||||||
|
SSH_STRING_FREE(n);
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
bignum_safe_free(bn);
|
||||||
|
bignum_safe_free(be);
|
||||||
|
OSSL_PARAM_free(params);
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SSH_KEYTYPE_ED25519:
|
||||||
|
case SSH_KEYTYPE_SK_ED25519:
|
||||||
|
rc = EVP_PKEY_get_raw_public_key(key->key, NULL, &key_len);
|
||||||
|
if (rc != 1) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"Failed to get ed25519 raw public key length: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_len != ED25519_KEY_LEN) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"Unexpected length of private key %zu. Expected %d.",
|
||||||
|
key_len,
|
||||||
|
ED25519_KEY_LEN);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ed25519_pubkey = malloc(key_len);
|
||||||
|
if (ed25519_pubkey == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = EVP_PKEY_get_raw_public_key(key->key,
|
||||||
|
(uint8_t *)ed25519_pubkey,
|
||||||
|
&key_len);
|
||||||
|
if (rc != 1) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"Failed to get ed25519 raw public key: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_pack(buffer,
|
||||||
|
"dP",
|
||||||
|
(uint32_t)ED25519_KEY_LEN,
|
||||||
|
(size_t)ED25519_KEY_LEN,
|
||||||
|
ed25519_pubkey);
|
||||||
|
if (rc == SSH_ERROR) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == SSH_KEY_PRIVATE) {
|
||||||
|
key_len = 0;
|
||||||
|
rc = EVP_PKEY_get_raw_private_key(key->key, NULL, &key_len);
|
||||||
if (rc != 1) {
|
if (rc != 1) {
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Failed to get ed25519 raw public key length: %s",
|
"Failed to get ed25519 raw private key length: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -1767,242 +1810,201 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ed25519_pubkey = malloc(key_len);
|
ed25519_privkey = malloc(key_len);
|
||||||
if (ed25519_pubkey == NULL) {
|
if (ed25519_privkey == NULL) {
|
||||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = EVP_PKEY_get_raw_public_key(key->key,
|
rc = EVP_PKEY_get_raw_private_key(key->key,
|
||||||
(uint8_t *)ed25519_pubkey,
|
ed25519_privkey,
|
||||||
&key_len);
|
&key_len);
|
||||||
if (rc != 1) {
|
if (rc != 1) {
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Failed to get ed25519 raw public key: %s",
|
"Failed to get ed25519 raw private key: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_pack(buffer,
|
rc = ssh_buffer_pack(buffer,
|
||||||
"dP",
|
"dPP",
|
||||||
(uint32_t)ED25519_KEY_LEN,
|
(uint32_t)(2 * ED25519_KEY_LEN),
|
||||||
|
(size_t)ED25519_KEY_LEN,
|
||||||
|
ed25519_privkey,
|
||||||
(size_t)ED25519_KEY_LEN,
|
(size_t)ED25519_KEY_LEN,
|
||||||
ed25519_pubkey);
|
ed25519_pubkey);
|
||||||
if (rc == SSH_ERROR) {
|
if (rc == SSH_ERROR) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
explicit_bzero(ed25519_privkey, ED25519_KEY_LEN);
|
||||||
if (type == SSH_KEY_PRIVATE) {
|
SAFE_FREE(ed25519_privkey);
|
||||||
key_len = 0;
|
} else {
|
||||||
rc = EVP_PKEY_get_raw_private_key(key->key, NULL, &key_len);
|
/* public key can contain certificate sk information */
|
||||||
if (rc != 1) {
|
if (key->type == SSH_KEYTYPE_SK_ED25519) {
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
"Failed to get ed25519 raw private key length: %s",
|
if (rc < 0) {
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_len != ED25519_KEY_LEN) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
|
||||||
"Unexpected length of private key %zu. Expected %d.",
|
|
||||||
key_len,
|
|
||||||
ED25519_KEY_LEN);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ed25519_privkey = malloc(key_len);
|
|
||||||
if (ed25519_privkey == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = EVP_PKEY_get_raw_private_key(key->key,
|
|
||||||
ed25519_privkey,
|
|
||||||
&key_len);
|
|
||||||
if (rc != 1) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
|
||||||
"Failed to get ed25519 raw private key: %s",
|
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_buffer_pack(buffer,
|
|
||||||
"dPP",
|
|
||||||
(uint32_t)(2 * ED25519_KEY_LEN),
|
|
||||||
(size_t)ED25519_KEY_LEN,
|
|
||||||
ed25519_privkey,
|
|
||||||
(size_t)ED25519_KEY_LEN,
|
|
||||||
ed25519_pubkey);
|
|
||||||
if (rc == SSH_ERROR) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
explicit_bzero(ed25519_privkey, ED25519_KEY_LEN);
|
|
||||||
SAFE_FREE(ed25519_privkey);
|
|
||||||
} else {
|
|
||||||
/* public key can contain certificate sk information */
|
|
||||||
if (key->type == SSH_KEYTYPE_SK_ED25519) {
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SAFE_FREE(ed25519_pubkey);
|
}
|
||||||
break;
|
SAFE_FREE(ed25519_pubkey);
|
||||||
case SSH_KEYTYPE_ECDSA_P256:
|
break;
|
||||||
case SSH_KEYTYPE_ECDSA_P384:
|
case SSH_KEYTYPE_ECDSA_P256:
|
||||||
case SSH_KEYTYPE_ECDSA_P521:
|
case SSH_KEYTYPE_ECDSA_P384:
|
||||||
case SSH_KEYTYPE_SK_ECDSA:
|
case SSH_KEYTYPE_ECDSA_P521:
|
||||||
|
case SSH_KEYTYPE_SK_ECDSA:
|
||||||
#ifdef HAVE_OPENSSL_ECC
|
#ifdef HAVE_OPENSSL_ECC
|
||||||
{
|
{
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
EC_GROUP *group = NULL;
|
EC_GROUP *group = NULL;
|
||||||
EC_POINT *point = NULL;
|
EC_POINT *point = NULL;
|
||||||
const void *pubkey = NULL;
|
const void *pubkey = NULL;
|
||||||
size_t pubkey_len;
|
size_t pubkey_len;
|
||||||
OSSL_PARAM *locate_param = NULL;
|
OSSL_PARAM *locate_param = NULL;
|
||||||
#else
|
#else
|
||||||
const EC_GROUP *group = NULL;
|
const EC_GROUP *group = NULL;
|
||||||
const EC_POINT *point = NULL;
|
const EC_POINT *point = NULL;
|
||||||
const BIGNUM *exp = NULL;
|
const BIGNUM *exp = NULL;
|
||||||
EC_KEY *ec = NULL;
|
EC_KEY *ec = NULL;
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
|
||||||
type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
|
type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid));
|
||||||
if (type_s == NULL) {
|
if (type_s == NULL) {
|
||||||
SSH_BUFFER_FREE(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
rc = ssh_buffer_add_ssh_string(buffer, type_s);
|
||||||
SSH_STRING_FREE(type_s);
|
SSH_STRING_FREE(type_s);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
SSH_BUFFER_FREE(buffer);
|
SSH_BUFFER_FREE(buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
ec = EVP_PKEY_get0_EC_KEY(key->key);
|
ec = EVP_PKEY_get0_EC_KEY(key->key);
|
||||||
if (ec == NULL) {
|
if (ec == NULL) {
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#ifdef WITH_PKCS11_URI
|
|
||||||
if (ssh_key_is_private(key) && !EC_KEY_get0_public_key(ec)) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "It is mandatory to have separate"
|
|
||||||
" public ECDSA key objects in the PKCS #11 device."
|
|
||||||
" Unlike RSA, ECDSA public keys cannot be derived"
|
|
||||||
" from their private keys.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#endif /* WITH_PKCS11_URI */
|
|
||||||
group = EC_KEY_get0_group(ec);
|
|
||||||
point = EC_KEY_get0_public_key(ec);
|
|
||||||
if (group == NULL || point == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
e = pki_key_make_ecpoint_string(group, point);
|
|
||||||
#else
|
|
||||||
rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
|
|
||||||
#ifdef WITH_PKCS11_URI
|
|
||||||
if (ssh_key_is_private(key) && !locate_param) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE, "It is mandatory to have separate"
|
|
||||||
" public ECDSA key objects in the PKCS #11 device."
|
|
||||||
" Unlike RSA, ECDSA public keys cannot be derived"
|
|
||||||
" from their private keys.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#endif /* WITH_PKCS11_URI */
|
|
||||||
|
|
||||||
rc = OSSL_PARAM_get_octet_string_ptr(locate_param, &pubkey, &pubkey_len);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
/* Convert the data to low-level representation */
|
|
||||||
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, key->ecdsa_nid);
|
|
||||||
point = EC_POINT_new(group);
|
|
||||||
rc = EC_POINT_oct2point(group, point, pubkey, pubkey_len, NULL);
|
|
||||||
if (group == NULL || point == NULL || rc != 1) {
|
|
||||||
EC_GROUP_free(group);
|
|
||||||
EC_POINT_free(point);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = pki_key_make_ecpoint_string(group, point);
|
|
||||||
EC_GROUP_free(group);
|
|
||||||
EC_POINT_free(point);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
|
||||||
if (e == NULL) {
|
|
||||||
SSH_BUFFER_FREE(buffer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, e);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_string_burn(e);
|
|
||||||
SSH_STRING_FREE(e);
|
|
||||||
e = NULL;
|
|
||||||
if (type == SSH_KEY_PRIVATE) {
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
||||||
OSSL_PARAM_free(params);
|
|
||||||
rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY);
|
|
||||||
rc = OSSL_PARAM_get_BN(locate_param, &bd);
|
|
||||||
if (rc != 1) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
d = ssh_make_bignum_string((BIGNUM *)bd);
|
|
||||||
if (d == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (ssh_buffer_add_ssh_string(buffer, d) < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
exp = EC_KEY_get0_private_key(ec);
|
|
||||||
if (exp == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
d = ssh_make_bignum_string((BIGNUM *)exp);
|
|
||||||
if (d == NULL) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, d);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
|
||||||
ssh_string_burn(d);
|
|
||||||
SSH_STRING_FREE(d);
|
|
||||||
d = NULL;
|
|
||||||
} else if (key->type == SSH_KEYTYPE_SK_ECDSA) {
|
|
||||||
/* public key can contain certificate sk information */
|
|
||||||
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
||||||
bignum_safe_free(bd);
|
|
||||||
OSSL_PARAM_free(params);
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif /* HAVE_OPENSSL_ECC */
|
|
||||||
case SSH_KEYTYPE_UNKNOWN:
|
|
||||||
default:
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
#ifdef WITH_PKCS11_URI
|
||||||
|
if (ssh_key_is_private(key) && !EC_KEY_get0_public_key(ec)) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"It is mandatory to have separate"
|
||||||
|
" public ECDSA key objects in the PKCS #11 device."
|
||||||
|
" Unlike RSA, ECDSA public keys cannot be derived"
|
||||||
|
" from their private keys.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* WITH_PKCS11_URI */
|
||||||
|
group = EC_KEY_get0_group(ec);
|
||||||
|
point = EC_KEY_get0_public_key(ec);
|
||||||
|
if (group == NULL || point == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
e = pki_key_make_ecpoint_string(group, point);
|
||||||
|
#else
|
||||||
|
rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
|
||||||
|
#ifdef WITH_PKCS11_URI
|
||||||
|
if (ssh_key_is_private(key) && !locate_param) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"It is mandatory to have separate"
|
||||||
|
" public ECDSA key objects in the PKCS #11 device."
|
||||||
|
" Unlike RSA, ECDSA public keys cannot be derived"
|
||||||
|
" from their private keys.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* WITH_PKCS11_URI */
|
||||||
|
|
||||||
|
rc = OSSL_PARAM_get_octet_string_ptr(locate_param, &pubkey, &pubkey_len);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* Convert the data to low-level representation */
|
||||||
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, key->ecdsa_nid);
|
||||||
|
point = EC_POINT_new(group);
|
||||||
|
rc = EC_POINT_oct2point(group, point, pubkey, pubkey_len, NULL);
|
||||||
|
if (group == NULL || point == NULL || rc != 1) {
|
||||||
|
EC_GROUP_free(group);
|
||||||
|
EC_POINT_free(point);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = pki_key_make_ecpoint_string(group, point);
|
||||||
|
EC_GROUP_free(group);
|
||||||
|
EC_POINT_free(point);
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
if (e == NULL) {
|
||||||
|
SSH_BUFFER_FREE(buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, e);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_string_burn(e);
|
||||||
|
SSH_STRING_FREE(e);
|
||||||
|
e = NULL;
|
||||||
|
if (type == SSH_KEY_PRIVATE) {
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
OSSL_PARAM_free(params);
|
||||||
|
rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY);
|
||||||
|
rc = OSSL_PARAM_get_BN(locate_param, &bd);
|
||||||
|
if (rc != 1) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
d = ssh_make_bignum_string((BIGNUM *)bd);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (ssh_buffer_add_ssh_string(buffer, d) < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
exp = EC_KEY_get0_private_key(ec);
|
||||||
|
if (exp == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
d = ssh_make_bignum_string((BIGNUM *)exp);
|
||||||
|
if (d == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, d);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
ssh_string_burn(d);
|
||||||
|
SSH_STRING_FREE(d);
|
||||||
|
d = NULL;
|
||||||
|
} else if (key->type == SSH_KEYTYPE_SK_ECDSA) {
|
||||||
|
/* public key can contain certificate sk information */
|
||||||
|
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
bignum_safe_free(bd);
|
||||||
|
OSSL_PARAM_free(params);
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_OPENSSL_ECC */
|
||||||
|
case SSH_KEYTYPE_UNKNOWN:
|
||||||
|
default:
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
makestring:
|
makestring:
|
||||||
|
|||||||
Reference in New Issue
Block a user