From b982473a860ec0c7b2f6834945b59cad53937b6a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 19 Oct 2018 15:35:56 +0200 Subject: [PATCH 1/5] charon-cmd: Print plugin list before parsing arguments Helps debugging e.g. failures to load certs/keys. --- src/charon-cmd/charon-cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/charon-cmd/charon-cmd.c b/src/charon-cmd/charon-cmd.c index 1293ec4c0..82bc3ee84 100644 --- a/src/charon-cmd/charon-cmd.c +++ b/src/charon-cmd/charon-cmd.c @@ -358,9 +358,6 @@ int main(int argc, char *argv[]) creds = cmd_creds_create(); atexit(cleanup_creds); - /* handle all arguments */ - handle_arguments(argc, argv, FALSE); - if (uname(&utsname) != 0) { memset(&utsname, 0, sizeof(utsname)); @@ -369,6 +366,9 @@ int main(int argc, char *argv[]) VERSION, utsname.sysname, utsname.release, utsname.machine); lib->plugins->status(lib->plugins, LEVEL_CTRL); + /* handle all arguments */ + handle_arguments(argc, argv, FALSE); + /* add handler for SEGV and ILL, * INT, TERM and HUP are handled by sigwaitinfo() in run() */ action.sa_handler = segv_handler; From 20f74adbaea1bcb98ccd8f6efa7e4a2aee393e30 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 22 Oct 2018 14:33:36 +0200 Subject: [PATCH 2/5] curve25519: Support loading Ed25519 public keys from simple blobs --- src/libstrongswan/credentials/builder.c | 1 + src/libstrongswan/credentials/builder.h | 2 + .../curve25519/curve25519_public_key.c | 97 +++++++++++-------- 3 files changed, 61 insertions(+), 39 deletions(-) diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c index 0239ee17e..61dfbbcad 100644 --- a/src/libstrongswan/credentials/builder.c +++ b/src/libstrongswan/credentials/builder.c @@ -73,6 +73,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END, "BUILD_SAFE_PRIMES", "BUILD_SHARES", "BUILD_THRESHOLD", + "BUILD_EDDSA_PUB", "BUILD_EDDSA_PRIV_ASN1_DER", "BUILD_END", ); diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h index 7928ef487..b283bd166 100644 --- a/src/libstrongswan/credentials/builder.h +++ b/src/libstrongswan/credentials/builder.h @@ -156,6 +156,8 @@ enum builder_part_t { BUILD_SHARES, /** minimum number of participating private key shares */ BUILD_THRESHOLD, + /** EdDSA public key blob */ + BUILD_EDDSA_PUB, /** DER encoded ASN.1 EdDSA private key */ BUILD_EDDSA_PRIV_ASN1_DER, /** end of variable argument builder list */ diff --git a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c index 1d4dec565..6eb80a119 100644 --- a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c +++ b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2018 Tobias Brunner * Copyright (C) 2016 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * @@ -200,50 +201,16 @@ static const asn1Object_t pubkeyObjects[] = { #define ED25519_SUBJECT_PUBLIC_KEY 2 /** - * See header. + * Parse the ASN.1-encoded subjectPublicKeyInfo */ -curve25519_public_key_t *curve25519_public_key_load(key_type_t type, - va_list args) +static bool parse_public_key_info(private_curve25519_public_key_t *this, + chunk_t blob) { - private_curve25519_public_key_t *this; - chunk_t blob = chunk_empty, object; asn1_parser_t *parser; + chunk_t object; bool success = FALSE; int objectID, oid; - while (TRUE) - { - switch (va_arg(args, builder_part_t)) - { - case BUILD_BLOB_ASN1_DER: - blob = va_arg(args, chunk_t); - continue; - case BUILD_END: - break; - default: - return NULL; - } - break; - } - - INIT(this, - .public = { - .key = { - .get_type = _get_type, - .verify = _verify, - .encrypt = _encrypt_, - .equals = public_key_equals, - .get_keysize = _get_keysize, - .get_fingerprint = _get_fingerprint, - .has_fingerprint = public_key_has_fingerprint, - .get_encoding = _get_encoding, - .get_ref = _get_ref, - .destroy = _destroy, - }, - }, - .ref = 1, - ); - parser = asn1_parser_create(pubkeyObjects, blob); while (parser->iterate(parser, &objectID, &object)) @@ -276,7 +243,59 @@ curve25519_public_key_t *curve25519_public_key_load(key_type_t type, end: parser->destroy(parser); - if (!success) + return success; +} + +/** + * See header. + */ +curve25519_public_key_t *curve25519_public_key_load(key_type_t type, + va_list args) +{ + private_curve25519_public_key_t *this; + chunk_t asn1 = chunk_empty, blob = chunk_empty; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_BLOB_ASN1_DER: + asn1 = va_arg(args, chunk_t); + continue; + case BUILD_EDDSA_PUB: + blob = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + + INIT(this, + .public = { + .key = { + .get_type = _get_type, + .verify = _verify, + .encrypt = _encrypt_, + .equals = public_key_equals, + .get_keysize = _get_keysize, + .get_fingerprint = _get_fingerprint, + .has_fingerprint = public_key_has_fingerprint, + .get_encoding = _get_encoding, + .get_ref = _get_ref, + .destroy = _destroy, + }, + }, + .ref = 1, + ); + + if (blob.len == ED25519_KEY_LEN) + { + this->pubkey = chunk_clone(blob); + } + else if (!asn1.len || !parse_public_key_info(this, asn1)) { destroy(this); return NULL; From 7de07293577d1fd62f376cfce72a7ef21c1a23e8 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 22 Oct 2018 14:37:01 +0200 Subject: [PATCH 3/5] sshkey: Add support for parsing Ed25519/Ed448 SSH keys --- .../plugins/sshkey/sshkey_builder.c | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.c b/src/libstrongswan/plugins/sshkey/sshkey_builder.c index eab6559b3..934514249 100644 --- a/src/libstrongswan/plugins/sshkey/sshkey_builder.c +++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Tobias Brunner + * Copyright (C) 2013-2018 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -89,6 +89,34 @@ 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 (chunk_equals(format, chunk_from_str("ssh-ed25519"))) + { + chunk_t blob; + + if (!reader->read_data32(reader, &blob)) + { + DBG1(DBG_LIB, "invalid Ed25519 key in SSH key"); + reader->destroy(reader); + return NULL; + } + reader->destroy(reader); + return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED25519, + BUILD_EDDSA_PUB, blob, BUILD_END); + } + else if (chunk_equals(format, chunk_from_str("ssh-ed448"))) + { + chunk_t blob; + + if (!reader->read_data32(reader, &blob)) + { + DBG1(DBG_LIB, "invalid Ed448 key in SSH key"); + reader->destroy(reader); + return NULL; + } + reader->destroy(reader); + return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED448, + BUILD_EDDSA_PUB, blob, BUILD_END); + } else if (format.len > strlen(ECDSA_PREFIX) && strpfx(format.ptr, ECDSA_PREFIX)) { @@ -140,8 +168,9 @@ static sshkey_public_key_t *load_from_stream(FILE *file) char line[1024], *token; while (!public && fgets(line, sizeof(line), file)) - { /* the format is: ssh-rsa|ecdsa-... */ - if (!strpfx(line, "ssh-rsa") && !strpfx(line, ECDSA_PREFIX)) + { /* the format is: ssh- */ + if (!strpfx(line, "ssh-rsa") && !strpfx(line, ECDSA_PREFIX) && + !strpfx(line, "ssh-ed25519") && !strpfx(line, "ssh-ed448")) { continue; } From 87dd08b13987859136bb1b1fc92e426f1645e10b Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 22 Oct 2018 15:04:48 +0200 Subject: [PATCH 4/5] sshkey: Support encoding Ed25519/Ed448 SSH public keys --- .../plugins/sshkey/sshkey_encoder.c | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/sshkey/sshkey_encoder.c b/src/libstrongswan/plugins/sshkey/sshkey_encoder.c index 9f5f8bd1f..ed35fc010 100644 --- a/src/libstrongswan/plugins/sshkey/sshkey_encoder.c +++ b/src/libstrongswan/plugins/sshkey/sshkey_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2013-2018 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -72,6 +72,42 @@ static bool build_public_key(chunk_t *encoding, va_list args) writer->destroy(writer); return TRUE; } + else if (cred_encoding_args(args, CRED_PART_EDDSA_PUB_ASN1_DER, &n, + CRED_PART_END)) + { + chunk_t alg; + char *prefix; + int oid; + + /* parse subjectPublicKeyInfo */ + if (asn1_unwrap(&n, &n) != ASN1_SEQUENCE) + { + return FALSE; + } + oid = asn1_parse_algorithmIdentifier(n, 1, NULL); + switch (oid) + { + case OID_ED25519: + prefix = "ssh-ed25519"; + break; + case OID_ED448: + prefix = "ssh-ed448"; + break; + default: + return FALSE; + } + if (asn1_unwrap(&n, &alg) != ASN1_SEQUENCE || + asn1_unwrap(&n, &n) != ASN1_BIT_STRING || !n.len) + { + return FALSE; + } + writer = bio_writer_create(0); + writer->write_data32(writer, chunk_from_str(prefix)); + writer->write_data32(writer, chunk_skip(n, 1)); + *encoding = chunk_to_base64(writer->get_buf(writer), NULL); + writer->destroy(writer); + return TRUE; + } else if (cred_encoding_args(args, CRED_PART_ECDSA_PUB_ASN1_DER, &n, CRED_PART_END)) { From 8f23e64ee578942bf582c6599f994b28e10db229 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 22 Oct 2018 15:15:13 +0200 Subject: [PATCH 5/5] agent: Support signatures with Ed25519/Ed448 keys --- .../plugins/agent/agent_private_key.c | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c index 961b30a04..db87affc9 100644 --- a/src/libstrongswan/plugins/agent/agent_private_key.c +++ b/src/libstrongswan/plugins/agent/agent_private_key.c @@ -248,6 +248,12 @@ static bool scheme_supported(private_agent_private_key_t *this, break; } return FALSE; + case KEY_ED25519: + *prefix = "ssh-ed25519"; + return scheme == SIGN_ED25519; + case KEY_ED448: + *prefix = "ssh-ed448"; + return scheme == SIGN_ED448; case KEY_ECDSA: return scheme == SIGN_ECDSA_256 || scheme == SIGN_ECDSA_384 || @@ -261,6 +267,7 @@ METHOD(private_key_t, sign, bool, private_agent_private_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t *signature) { + key_type_t type; uint32_t len, flags = 0; char buf[2048], *prefix = NULL; chunk_t blob; @@ -321,9 +328,9 @@ METHOD(private_key_t, sign, bool, DBG1(DBG_LIB, "ssh-agent didn't return requested %s signature", prefix); return FALSE; } - - if (this->pubkey->get_type(this->pubkey) == KEY_RSA) - { /* for RSA, the signature has no special encoding */ + type = this->pubkey->get_type(this->pubkey); + if (type == KEY_RSA || type == KEY_ED25519 || type == KEY_ED448) + { /* for RSA/EdDSA, the signature has no special encoding */ blob = read_string(&blob); if (blob.len) { @@ -429,12 +436,16 @@ static enumerator_t *create_rsa_enumerator(private_agent_private_key_t *this) METHOD(private_key_t, supported_signature_schemes, enumerator_t*, private_agent_private_key_t *this) { - switch (get_type(this)) + key_type_t type = get_type(this); + + switch (type) { case KEY_RSA: return create_rsa_enumerator(this); + case KEY_ED25519: + case KEY_ED448: case KEY_ECDSA: - return signature_schemes_for_key(KEY_ECDSA, get_keysize(this)); + return signature_schemes_for_key(type, get_keysize(this)); default: break; }