From 19cd909c8d77ec937798fffac3150646f5d8a3a3 Mon Sep 17 00:00:00 2001 From: Ben Toews Date: Tue, 12 Mar 2019 10:27:35 -0600 Subject: [PATCH] pki: support ECDSA/ED25519 certificates As with RSA/DSS, support is still quite limited. This is mostly about adding new ssh_keytypes_e values and updating sites that check keys' types. Signed-off-by: Ben Toews Reviewed-by: Jakub Jelen --- include/libssh/libssh.h | 4 +++ include/libssh/pki.h | 6 +++++ src/pki.c | 42 +++++++++++++++++++++++++++---- src/pki_crypto.c | 8 ++++++ src/pki_gcrypt.c | 4 +++ tests/unittests/torture_options.c | 2 +- 6 files changed, 60 insertions(+), 6 deletions(-) diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index 68ddbac1..e7eb6e04 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -300,6 +300,10 @@ enum ssh_keytypes_e{ SSH_KEYTYPE_ECDSA_P256, SSH_KEYTYPE_ECDSA_P384, SSH_KEYTYPE_ECDSA_P521, + SSH_KEYTYPE_ECDSA_P256_CERT01, + SSH_KEYTYPE_ECDSA_P384_CERT01, + SSH_KEYTYPE_ECDSA_P521_CERT01, + SSH_KEYTYPE_ED25519_CERT01, }; enum ssh_keycmp_e { diff --git a/include/libssh/pki.h b/include/libssh/pki.h index 19e1ad54..c0102382 100644 --- a/include/libssh/pki.h +++ b/include/libssh/pki.h @@ -104,6 +104,12 @@ enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name); #define is_ecdsa_key_type(t) \ ((t) >= SSH_KEYTYPE_ECDSA_P256 && (t) <= SSH_KEYTYPE_ECDSA_P521) +#define is_cert_type(kt)\ + ((kt) == SSH_KEYTYPE_DSS_CERT01 ||\ + (kt) == SSH_KEYTYPE_RSA_CERT01 ||\ + ((kt) >= SSH_KEYTYPE_ECDSA_P256_CERT01 &&\ + (kt) <= SSH_KEYTYPE_ED25519_CERT01)) + /* SSH Signature Functions */ ssh_signature ssh_signature_new(void); void ssh_signature_free(ssh_signature sign); diff --git a/src/pki.c b/src/pki.c index 77b0ba92..c27bb085 100644 --- a/src/pki.c +++ b/src/pki.c @@ -190,7 +190,9 @@ void ssh_key_free (ssh_key key){ * @returns one of SSH_KEYTYPE_RSA, SSH_KEYTYPE_DSS, * SSH_KEYTYPE_ECDSA_P256, SSH_KEYTYPE_ECDSA_P384, * SSH_KEYTYPE_ECDSA_P521, SSH_KEYTYPE_ED25519, SSH_KEYTYPE_DSS_CERT01, - * or SSH_KEYTYPE_RSA_CERT01. + * SSH_KEYTYPE_RSA_CERT01, SSH_KEYTYPE_ECDSA_P256_CERT01, + * SSH_KEYTYPE_ECDSA_P384_CERT01, SSH_KEYTYPE_ECDSA_P521_CERT01, or + * SSH_KEYTYPE_ED25519_CERT01. * @returns SSH_KEYTYPE_UNKNOWN if the type is unknown */ enum ssh_keytypes_e ssh_key_type(const ssh_key key){ @@ -258,6 +260,14 @@ const char *ssh_key_type_to_char(enum ssh_keytypes_e type) { return "ssh-dss-cert-v01@openssh.com"; case SSH_KEYTYPE_RSA_CERT01: return "ssh-rsa-cert-v01@openssh.com"; + case SSH_KEYTYPE_ECDSA_P256_CERT01: + return "ecdsa-sha2-nistp256-cert-v01@openssh.com"; + case SSH_KEYTYPE_ECDSA_P384_CERT01: + return "ecdsa-sha2-nistp384-cert-v01@openssh.com"; + case SSH_KEYTYPE_ECDSA_P521_CERT01: + return "ecdsa-sha2-nistp521-cert-v01@openssh.com"; + case SSH_KEYTYPE_ED25519_CERT01: + return "ssh-ed25519-cert-v01@openssh.com"; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: return NULL; @@ -420,6 +430,14 @@ enum ssh_keytypes_e ssh_key_type_from_name(const char *name) { return SSH_KEYTYPE_DSS_CERT01; } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) { return SSH_KEYTYPE_RSA_CERT01; + } else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0) { + return SSH_KEYTYPE_ECDSA_P256_CERT01; + } else if (strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0) { + return SSH_KEYTYPE_ECDSA_P384_CERT01; + } else if (strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) { + return SSH_KEYTYPE_ECDSA_P521_CERT01; + } else if (strcmp(name, "ssh-ed25519-cert-v01@openssh.com") == 0) { + return SSH_KEYTYPE_ED25519_CERT01; } return SSH_KEYTYPE_UNKNOWN; @@ -546,6 +564,10 @@ void ssh_signature_free(ssh_signature sig) break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: + case SSH_KEYTYPE_ECDSA_P256_CERT01: + case SSH_KEYTYPE_ECDSA_P384_CERT01: + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: @@ -1043,6 +1065,10 @@ int pki_import_privkey_buffer(enum ssh_keytypes_e type, break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: + case SSH_KEYTYPE_ECDSA_P256_CERT01: + case SSH_KEYTYPE_ECDSA_P384_CERT01: + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: @@ -1194,6 +1220,10 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer, break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: + case SSH_KEYTYPE_ECDSA_P256_CERT01: + case SSH_KEYTYPE_ECDSA_P384_CERT01: + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: @@ -1298,8 +1328,7 @@ int ssh_pki_import_pubkey_base64(const char *b64_key, } ssh_string_free(type_s); - if (type == SSH_KEYTYPE_RSA_CERT01 || - type == SSH_KEYTYPE_DSS_CERT01) { + if (is_cert_type(type)) { rc = pki_import_cert_buffer(buffer, type, pkey); } else { rc = pki_import_pubkey_buffer(buffer, type, pkey); @@ -1361,8 +1390,7 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob, } ssh_string_free(type_s); - if (type == SSH_KEYTYPE_RSA_CERT01 || - type == SSH_KEYTYPE_DSS_CERT01) { + if (is_cert_type(type)) { rc = pki_import_cert_buffer(buffer, type, pkey); } else { rc = pki_import_pubkey_buffer(buffer, type, pkey); @@ -1626,6 +1654,10 @@ int ssh_pki_generate(enum ssh_keytypes_e type, int parameter, break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: + case SSH_KEYTYPE_ECDSA_P256_CERT01: + case SSH_KEYTYPE_ECDSA_P384_CERT01: + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: diff --git a/src/pki_crypto.c b/src/pki_crypto.c index d5dd3f63..11f0754a 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -809,6 +809,10 @@ ssh_string pki_private_key_to_pem(const ssh_key key, return NULL; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: + case SSH_KEYTYPE_ECDSA_P256_CERT01: + case SSH_KEYTYPE_ECDSA_P384_CERT01: + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_UNKNOWN: default: BIO_free(mem); @@ -947,6 +951,10 @@ ssh_key pki_private_key_from_base64(const char *b64_key, case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA: + case SSH_KEYTYPE_ECDSA_P256_CERT01: + case SSH_KEYTYPE_ECDSA_P384_CERT01: + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_UNKNOWN: BIO_free(mem); SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type); diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c index 0e55078c..40280c52 100644 --- a/src/pki_gcrypt.c +++ b/src/pki_gcrypt.c @@ -1526,6 +1526,10 @@ int pki_key_compare(const ssh_key k1, case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA: + case SSH_KEYTYPE_ECDSA_P256_CERT01: + case SSH_KEYTYPE_ECDSA_P384_CERT01: + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: return 1; diff --git a/tests/unittests/torture_options.c b/tests/unittests/torture_options.c index bfe40ce8..ea45aa32 100644 --- a/tests/unittests/torture_options.c +++ b/tests/unittests/torture_options.c @@ -781,7 +781,7 @@ static int ssh_bind_setup_files(void **state) /* For ed25519 the test keys are not available in legacy PEM format. Using * the new OpenSSH format for all algorithms */ torture_write_file(LIBSSH_RSA_TESTKEY, - torture_get_openssh_testkey(SSH_KEYTYPE_RSA 0)); + torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0)); torture_write_file(LIBSSH_ED25519_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0));