diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-04-01 18:16:17 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-05-07 17:08:31 +0200 |
commit | dd9e366814475f22bf22ef874cf68f8691e19c81 (patch) | |
tree | 742f461abfe44009d000940bb51a08793530179d /src/libstrongswan/plugins/sshkey/sshkey_builder.c | |
parent | 87692be21536a586e5245cdda795134b7cfb2895 (diff) | |
download | strongswan-dd9e366814475f22bf22ef874cf68f8691e19c81.tar.bz2 strongswan-dd9e366814475f22bf22ef874cf68f8691e19c81.tar.xz |
sshkey: Add support for ECDSA keys
Diffstat (limited to 'src/libstrongswan/plugins/sshkey/sshkey_builder.c')
-rw-r--r-- | src/libstrongswan/plugins/sshkey/sshkey_builder.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.c b/src/libstrongswan/plugins/sshkey/sshkey_builder.c index 31c7b2164..986e860d9 100644 --- a/src/libstrongswan/plugins/sshkey/sshkey_builder.c +++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.c @@ -15,9 +15,45 @@ #include "sshkey_builder.h" +#include <asn1/oid.h> +#include <asn1/asn1.h> #include <bio/bio_reader.h> #include <utils/debug.h> +#define ECDSA_PREFIX "ecdsa-sha2-" + +/** + * Parse an EC domain parameter identifier as defined in RFC 5656 + */ +static chunk_t parse_ec_identifier(chunk_t identifier) +{ + chunk_t oid = chunk_empty; + + if (chunk_equals(identifier, chunk_from_str("nistp256"))) + { + oid = asn1_build_known_oid(OID_PRIME256V1); + } + else if (chunk_equals(identifier, chunk_from_str("nistp384"))) + { + oid = asn1_build_known_oid(OID_SECT384R1); + } + else if (chunk_equals(identifier, chunk_from_str("nistp521"))) + { + oid = asn1_build_known_oid(OID_SECT521R1); + } + else + { + char ascii[64]; + + if (snprintf(ascii, sizeof(ascii), "%.*s", (int)identifier.len, + identifier.ptr) < sizeof(ascii)) + { + oid = asn1_wrap(ASN1_OID, "m", asn1_oid_from_string(ascii)); + } + } + return oid; +} + /** * Load a generic public key from an SSH key blob */ @@ -48,6 +84,40 @@ static sshkey_public_key_t *parse_public_key(chunk_t blob) return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); } + else if (format.len > strlen(ECDSA_PREFIX) && + strneq(format.ptr, ECDSA_PREFIX, strlen(ECDSA_PREFIX))) + { + chunk_t ec_blob, identifier, q, oid, encoded; + sshkey_public_key_t *key; + + ec_blob = reader->peek(reader); + reader->destroy(reader); + reader = bio_reader_create(ec_blob); + if (!reader->read_data32(reader, &identifier) || + !reader->read_data32(reader, &q)) + { + DBG1(DBG_LIB, "invalid ECDSA key in SSH key"); + reader->destroy(reader); + return NULL; + } + oid = parse_ec_identifier(identifier); + if (!oid.ptr) + { + DBG1(DBG_LIB, "invalid ECDSA key identifier in SSH key"); + reader->destroy(reader); + return NULL; + } + reader->destroy(reader); + /* build key from subjectPublicKeyInfo */ + encoded = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_EC_PUBLICKEY), oid), + asn1_bitstring("c", q)); + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, + KEY_ECDSA, BUILD_BLOB_ASN1_DER, encoded, BUILD_END); + chunk_free(&encoded); + return key; + } DBG1(DBG_LIB, "unsupported SSH key format %.*s", (int)format.len, format.ptr); reader->destroy(reader); |