mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-11 18:50:28 +09:00
mbedcrypto: Refactor PEM parsing
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit aca482a5a5)
This commit is contained in:
committed by
Andreas Schneider
parent
146d1a620d
commit
2564246024
@@ -85,10 +85,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
|
|||||||
ssh_auth_callback auth_fn, void *auth_data)
|
ssh_auth_callback auth_fn, void *auth_data)
|
||||||
{
|
{
|
||||||
ssh_key key = NULL;
|
ssh_key key = NULL;
|
||||||
mbedtls_pk_context *rsa = NULL;
|
mbedtls_pk_context *pk = NULL;
|
||||||
mbedtls_pk_context *ecdsa = NULL;
|
mbedtls_pk_type_t mbed_type;
|
||||||
ed25519_privkey *ed25519 = NULL;
|
|
||||||
enum ssh_keytypes_e type;
|
|
||||||
int valid;
|
int valid;
|
||||||
/* 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;
|
||||||
@@ -97,159 +95,100 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
|
|||||||
mbedtls_ctr_drbg_context *ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
|
mbedtls_ctr_drbg_context *ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
type = pki_privatekey_type_from_string(b64_key);
|
pk = malloc(sizeof(mbedtls_pk_context));
|
||||||
if (type == SSH_KEYTYPE_UNKNOWN) {
|
if (pk == NULL) {
|
||||||
SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key.");
|
goto fail;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
mbedtls_pk_init(pk);
|
||||||
|
|
||||||
switch (type) {
|
if (passphrase == NULL) {
|
||||||
case SSH_KEYTYPE_RSA:
|
if (auth_fn) {
|
||||||
rsa = malloc(sizeof(mbedtls_pk_context));
|
valid = auth_fn("Passphrase for private key:",
|
||||||
if (rsa == NULL) {
|
(char *)tmp,
|
||||||
return NULL;
|
MAX_PASSPHRASE_SIZE,
|
||||||
}
|
0,
|
||||||
|
0,
|
||||||
mbedtls_pk_init(rsa);
|
auth_data);
|
||||||
|
if (valid < 0) {
|
||||||
if (passphrase == NULL) {
|
|
||||||
if (auth_fn) {
|
|
||||||
valid = auth_fn("Passphrase for private key:", (char *) tmp,
|
|
||||||
MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
|
|
||||||
if (valid < 0) {
|
|
||||||
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) {
|
|
||||||
char error_buf[100];
|
|
||||||
mbedtls_strerror(valid, error_buf, 100);
|
|
||||||
SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case SSH_KEYTYPE_ECDSA_P256:
|
|
||||||
case SSH_KEYTYPE_ECDSA_P384:
|
|
||||||
case SSH_KEYTYPE_ECDSA_P521:
|
|
||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
|
valid = mbedtls_pk_parse_key(
|
||||||
|
pk,
|
||||||
|
(const unsigned char *)b64_key,
|
||||||
|
b64len,
|
||||||
|
tmp,
|
||||||
|
strnlen((const char *)tmp, MAX_PASSPHRASE_SIZE),
|
||||||
|
mbedtls_ctr_drbg_random,
|
||||||
|
ctr_drbg);
|
||||||
#else
|
#else
|
||||||
ecdsa = malloc(sizeof(mbedtls_pk_context));
|
valid = mbedtls_pk_parse_key(
|
||||||
|
pk,
|
||||||
|
(const unsigned char *)b64_key,
|
||||||
|
b64len,
|
||||||
|
tmp,
|
||||||
|
strnlen((const char *)tmp, MAX_PASSPHRASE_SIZE));
|
||||||
#endif
|
#endif
|
||||||
if (ecdsa == NULL) {
|
} else {
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mbedtls_pk_init(ecdsa);
|
|
||||||
|
|
||||||
if (passphrase == NULL) {
|
|
||||||
if (auth_fn) {
|
|
||||||
valid = auth_fn("Passphrase for private key:", (char *) tmp,
|
|
||||||
MAX_PASSPHRASE_SIZE, 0, 0, auth_data);
|
|
||||||
if (valid < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
valid = mbedtls_pk_parse_key(ecdsa,
|
valid = mbedtls_pk_parse_key(pk,
|
||||||
(const unsigned char *) b64_key,
|
(const unsigned char *)b64_key,
|
||||||
b64len, tmp,
|
b64len,
|
||||||
strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE),
|
NULL,
|
||||||
mbedtls_ctr_drbg_random, ctr_drbg);
|
0,
|
||||||
|
mbedtls_ctr_drbg_random,
|
||||||
|
ctr_drbg);
|
||||||
#else
|
#else
|
||||||
valid = mbedtls_pk_parse_key(ecdsa,
|
valid = mbedtls_pk_parse_key(pk,
|
||||||
(const unsigned char *) b64_key,
|
(const unsigned char *)b64_key,
|
||||||
b64len, tmp,
|
b64len,
|
||||||
strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE));
|
NULL,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
}
|
||||||
|
} else {
|
||||||
#if MBEDTLS_VERSION_MAJOR > 2
|
#if MBEDTLS_VERSION_MAJOR > 2
|
||||||
valid = mbedtls_pk_parse_key(ecdsa,
|
valid = mbedtls_pk_parse_key(pk,
|
||||||
(const unsigned char *) b64_key,
|
(const unsigned char *)b64_key,
|
||||||
b64len, NULL,
|
b64len,
|
||||||
0, mbedtls_ctr_drbg_random, ctr_drbg);
|
(const unsigned char *)passphrase,
|
||||||
|
strnlen(passphrase, MAX_PASSPHRASE_SIZE),
|
||||||
|
mbedtls_ctr_drbg_random,
|
||||||
|
ctr_drbg);
|
||||||
#else
|
#else
|
||||||
valid = mbedtls_pk_parse_key(ecdsa,
|
valid = mbedtls_pk_parse_key(pk,
|
||||||
(const unsigned char *) b64_key,
|
(const unsigned char *)b64_key,
|
||||||
b64len, NULL,
|
b64len,
|
||||||
0);
|
(const unsigned char *)passphrase,
|
||||||
|
strnlen(passphrase, MAX_PASSPHRASE_SIZE));
|
||||||
#endif
|
#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) {
|
|
||||||
char error_buf[100];
|
|
||||||
mbedtls_strerror(valid, error_buf, 100);
|
|
||||||
SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SSH_KEYTYPE_ED25519:
|
|
||||||
/* Cannot open ed25519 keys with libmbedcrypto */
|
|
||||||
default:
|
|
||||||
SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d",
|
|
||||||
type);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
if (valid != 0) {
|
||||||
|
char error_buf[100];
|
||||||
|
mbedtls_strerror(valid, error_buf, 100);
|
||||||
|
SSH_LOG(SSH_LOG_WARN, "Parsing private key %s", error_buf);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbed_type = mbedtls_pk_get_type(pk);
|
||||||
|
|
||||||
key = ssh_key_new();
|
key = ssh_key_new();
|
||||||
if (key == NULL) {
|
if (key == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ecdsa != NULL) {
|
switch (mbed_type) {
|
||||||
mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*ecdsa);
|
case MBEDTLS_PK_RSA:
|
||||||
|
case MBEDTLS_PK_RSA_ALT:
|
||||||
|
key->rsa = pk;
|
||||||
|
pk = NULL;
|
||||||
|
key->type = SSH_KEYTYPE_RSA;
|
||||||
|
break;
|
||||||
|
case MBEDTLS_PK_ECKEY:
|
||||||
|
case MBEDTLS_PK_ECDSA: {
|
||||||
|
/* type will be set later */
|
||||||
|
mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*pk);
|
||||||
|
pk = NULL;
|
||||||
|
|
||||||
key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
|
key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
|
||||||
if (key->ecdsa == NULL) {
|
if (key->ecdsa == NULL) {
|
||||||
@@ -258,40 +197,36 @@ ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase,
|
|||||||
|
|
||||||
mbedtls_ecdsa_init(key->ecdsa);
|
mbedtls_ecdsa_init(key->ecdsa);
|
||||||
mbedtls_ecdsa_from_keypair(key->ecdsa, keypair);
|
mbedtls_ecdsa_from_keypair(key->ecdsa, keypair);
|
||||||
mbedtls_pk_free(ecdsa);
|
mbedtls_pk_free(pk);
|
||||||
SAFE_FREE(ecdsa);
|
SAFE_FREE(pk);
|
||||||
|
|
||||||
key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa);
|
key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa);
|
||||||
|
|
||||||
/* pki_privatekey_type_from_string always returns P256 for ECDSA
|
/* pki_privatekey_type_from_string always returns P256 for ECDSA
|
||||||
* keys, so we need to figure out the correct type here */
|
* keys, so we need to figure out the correct type here */
|
||||||
type = pki_key_ecdsa_to_key_type(key->ecdsa);
|
key->type = pki_key_ecdsa_to_key_type(key->ecdsa);
|
||||||
if (type == SSH_KEYTYPE_UNKNOWN) {
|
if (key->type == SSH_KEYTYPE_UNKNOWN) {
|
||||||
SSH_LOG(SSH_LOG_WARN, "Invalid private key.");
|
SSH_LOG(SSH_LOG_WARN, "Invalid private key.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
key->ecdsa = NULL;
|
}
|
||||||
|
default:
|
||||||
|
SSH_LOG(SSH_LOG_WARN,
|
||||||
|
"Unknown or invalid private key type %d",
|
||||||
|
mbed_type);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
key->type = type;
|
key->type_c = ssh_key_type_to_char(key->type);
|
||||||
key->type_c = ssh_key_type_to_char(type);
|
|
||||||
key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
|
key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
|
||||||
key->rsa = rsa;
|
|
||||||
key->ed25519_privkey = ed25519;
|
|
||||||
rsa = NULL;
|
|
||||||
ecdsa = NULL;
|
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
fail:
|
fail:
|
||||||
ssh_key_free(key);
|
ssh_key_free(key);
|
||||||
if (rsa != NULL) {
|
if (pk != NULL) {
|
||||||
mbedtls_pk_free(rsa);
|
mbedtls_pk_free(pk);
|
||||||
SAFE_FREE(rsa);
|
SAFE_FREE(pk);
|
||||||
}
|
|
||||||
if (ecdsa != NULL) {
|
|
||||||
mbedtls_pk_free(ecdsa);
|
|
||||||
SAFE_FREE(ecdsa);
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user