aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/plugins/sshkey/sshkey_builder.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2013-04-01 18:16:17 +0200
committerTobias Brunner <tobias@strongswan.org>2013-05-07 17:08:31 +0200
commitdd9e366814475f22bf22ef874cf68f8691e19c81 (patch)
tree742f461abfe44009d000940bb51a08793530179d /src/libstrongswan/plugins/sshkey/sshkey_builder.c
parent87692be21536a586e5245cdda795134b7cfb2895 (diff)
downloadstrongswan-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.c70
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);