From: Tobias Brunner Date: Thu, 9 Aug 2018 11:00:50 +0000 (+0200) Subject: botan: Load public/private keys generically X-Git-Tag: 5.7.0rc1~4^2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=607f10dca409d6c278cd6fb69e332bbed22e5268;p=thirdparty%2Fstrongswan.git botan: Load public/private keys generically Simplifies public key loading and this way unencrypted PKCS#8-encoded keys can be loaded directly without pkcs8 plugin (code for encrypted keys could probably later be added, if necessary). It also simplifies the implementation of private_key_t::get_public_key() a lot. --- diff --git a/src/libstrongswan/plugins/botan/Makefile.am b/src/libstrongswan/plugins/botan/Makefile.am index bbad715410..1188841d39 100644 --- a/src/libstrongswan/plugins/botan/Makefile.am +++ b/src/libstrongswan/plugins/botan/Makefile.am @@ -24,6 +24,7 @@ libstrongswan_botan_la_SOURCES = \ botan_ec_public_key.h botan_ec_public_key.c \ botan_ec_private_key.h botan_ec_private_key.c \ botan_util.h botan_util.c \ + botan_util_keys.h botan_util_keys.c \ botan_gcm.h botan_gcm.c libstrongswan_botan_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/botan/botan_ec_private_key.c b/src/libstrongswan/plugins/botan/botan_ec_private_key.c index bfe8f3833f..78ba43f811 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_private_key.c +++ b/src/libstrongswan/plugins/botan/botan_ec_private_key.c @@ -27,6 +27,7 @@ #include "botan_ec_private_key.h" +#include "botan_ec_public_key.h" #include "botan_util.h" #include @@ -177,39 +178,13 @@ METHOD(private_key_t, get_type, key_type_t, METHOD(private_key_t, get_public_key, public_key_t*, private_botan_ec_private_key_t *this) { - public_key_t *public; botan_pubkey_t pubkey; - chunk_t key = chunk_empty; if (botan_privkey_export_pubkey(&pubkey, this->key)) { - return FALSE; - } - - if (botan_pubkey_export(pubkey, NULL, &key.len, - BOTAN_PRIVKEY_EXPORT_FLAG_DER) - != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE) - { - botan_pubkey_destroy(pubkey); - return FALSE; - } - - key = chunk_alloc(key.len); - - if (botan_pubkey_export(pubkey, key.ptr, &key.len, - BOTAN_PRIVKEY_EXPORT_FLAG_DER)) - { - chunk_free(&key); - botan_pubkey_destroy(pubkey); - return FALSE; + return NULL; } - - public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA, - BUILD_BLOB_ASN1_DER, key, BUILD_END); - - chunk_free(&key); - botan_pubkey_destroy(pubkey); - return public; + return (public_key_t*)botan_ec_public_key_adopt(pubkey); } METHOD(private_key_t, get_fingerprint, bool, @@ -402,6 +377,19 @@ static private_botan_ec_private_key_t *create_empty(int oid) return this; } +/* + * Described in header + */ +botan_ec_private_key_t *botan_ec_private_key_adopt(botan_privkey_t key, int oid) +{ + private_botan_ec_private_key_t *this; + + this = create_empty(oid); + this->key = key; + + return &this->public; +} + /* * Described in header */ diff --git a/src/libstrongswan/plugins/botan/botan_ec_private_key.h b/src/libstrongswan/plugins/botan/botan_ec_private_key.h index 9450331a45..2b9686cebf 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_private_key.h +++ b/src/libstrongswan/plugins/botan/botan_ec_private_key.h @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 René Korthaus * Copyright (C) 2018 Konstantinos Kolelis * Rohde & Schwarz Cybersecurity GmbH @@ -30,6 +33,8 @@ #ifndef BOTAN_EC_PRIVATE_KEY_H_ #define BOTAN_EC_PRIVATE_KEY_H_ +#include + #include #include @@ -69,4 +74,14 @@ botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args); botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args); +/** + * Load a ECDSA private key by adopting a botan_privkey_t object. + * + * @param key private key object (adopted) + * @param oid EC curve OID + * @return loaded key, NULL on failure + */ +botan_ec_private_key_t *botan_ec_private_key_adopt(botan_privkey_t key, + int oid); + #endif /** BOTAN_EC_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_ec_public_key.c b/src/libstrongswan/plugins/botan/botan_ec_public_key.c index 54782bcbff..4c85dbcec6 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_public_key.c +++ b/src/libstrongswan/plugins/botan/botan_ec_public_key.c @@ -248,33 +248,9 @@ METHOD(public_key_t, destroy, void, /* * Described in header */ -botan_ec_public_key_t *botan_ec_public_key_load(key_type_t type, va_list args) +botan_ec_public_key_t *botan_ec_public_key_adopt(botan_pubkey_t key) { private_botan_ec_public_key_t *this; - chunk_t blob = chunk_empty; - botan_rng_t rng; - size_t namesize = 0; - char *namebuf; - - if (type != KEY_ECDSA) - { - return NULL; - } - - 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 = { @@ -291,52 +267,10 @@ botan_ec_public_key_t *botan_ec_public_key_load(key_type_t type, va_list args) .destroy = _destroy, }, }, + .key = key, .ref = 1, ); - if (botan_pubkey_load(&this->key, blob.ptr, blob.len)) - { - free(this); - return NULL; - } - - if (botan_pubkey_algo_name(this->key, NULL, &namesize) - != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE) - { - destroy(this); - return NULL; - } - - namebuf = malloc(namesize); - if (botan_pubkey_algo_name(this->key, namebuf, &namesize)) - { - free(namebuf); - destroy(this); - return NULL; - } - - if (!strneq(namebuf, "ECDSA", namesize)) - { - free(namebuf); - destroy(this); - return NULL; - } - free(namebuf); - - if (botan_rng_init(&rng, "user")) - { - return NULL; - } - - if (botan_pubkey_check_key(this->key, rng, BOTAN_CHECK_KEY_EXPENSIVE_TESTS)) - { - DBG1(DBG_LIB, "public key failed key checks"); - botan_rng_destroy(rng); - destroy(this); - return NULL; - } - - botan_rng_destroy(rng); return &this->public; } diff --git a/src/libstrongswan/plugins/botan/botan_ec_public_key.h b/src/libstrongswan/plugins/botan/botan_ec_public_key.h index eb49ec3cbe..ddb3d5b046 100644 --- a/src/libstrongswan/plugins/botan/botan_ec_public_key.h +++ b/src/libstrongswan/plugins/botan/botan_ec_public_key.h @@ -25,11 +25,13 @@ #ifndef BOTAN_EC_PUBLIC_KEY_H_ #define BOTAN_EC_PUBLIC_KEY_H_ -typedef struct botan_ec_public_key_t botan_ec_public_key_t; +#include #include #include +typedef struct botan_ec_public_key_t botan_ec_public_key_t; + /** * public_key_t implementation of ECDSA using botan. */ @@ -42,14 +44,11 @@ struct botan_ec_public_key_t { }; /** - * Load a ECDSA public key using botan. - * - * Accepts a BUILD_BLOB_ASN1_DER argument. + * Load a ECDSA public key by adopting a botan_pubkey_t object. * - * @param type type of the key, must be KEY_ECDSA - * @param args builder_part_t argument list - * @return loaded key, NULL on failure + * @param key public key object (adopted) + * @return loaded key, NULL on failure */ -botan_ec_public_key_t *botan_ec_public_key_load(key_type_t type, va_list args); +botan_ec_public_key_t *botan_ec_public_key_adopt(botan_pubkey_t key); #endif /** BOTAN_EC_PUBLIC_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_plugin.c b/src/libstrongswan/plugins/botan/botan_plugin.c index 468d505301..b387a2bd1c 100644 --- a/src/libstrongswan/plugins/botan/botan_plugin.c +++ b/src/libstrongswan/plugins/botan/botan_plugin.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 René Korthaus * Copyright (C) 2018 Konstantinos Kolelis * Rohde & Schwarz Cybersecurity GmbH @@ -34,6 +37,7 @@ #include "botan_ec_public_key.h" #include "botan_ec_private_key.h" #include "botan_gcm.h" +#include "botan_util_keys.h" #include @@ -79,6 +83,16 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(DH, MODP_1024_160), PLUGIN_PROVIDE(DH, MODP_768_BIT), PLUGIN_PROVIDE(DH, MODP_CUSTOM), +#endif +#ifdef BOTAN_HAS_ECDH + /* EC DH groups */ + PLUGIN_REGISTER(DH, botan_ec_diffie_hellman_create), + PLUGIN_PROVIDE(DH, ECP_256_BIT), + PLUGIN_PROVIDE(DH, ECP_384_BIT), + PLUGIN_PROVIDE(DH, ECP_521_BIT), + PLUGIN_PROVIDE(DH, ECP_256_BP), + PLUGIN_PROVIDE(DH, ECP_384_BP), + PLUGIN_PROVIDE(DH, ECP_512_BP), #endif /* crypters */ PLUGIN_REGISTER(CRYPTER, botan_crypter_create), @@ -147,15 +161,24 @@ METHOD(plugin_t, get_features, int, #endif #endif /* BOTAN_HAS_HMAC */ -#ifdef BOTAN_HAS_ECDH - /* EC DH groups */ - PLUGIN_REGISTER(DH, botan_ec_diffie_hellman_create), - PLUGIN_PROVIDE(DH, ECP_256_BIT), - PLUGIN_PROVIDE(DH, ECP_384_BIT), - PLUGIN_PROVIDE(DH, ECP_521_BIT), - PLUGIN_PROVIDE(DH, ECP_256_BP), - PLUGIN_PROVIDE(DH, ECP_384_BP), - PLUGIN_PROVIDE(DH, ECP_512_BP), + /* generic key loaders */ +#if defined (BOTAN_HAS_RSA) || defined(BOTAN_HAS_ECDSA) + PLUGIN_REGISTER(PUBKEY, botan_public_key_load, TRUE), + PLUGIN_PROVIDE(PUBKEY, KEY_ANY), +#ifdef BOTAN_HAS_RSA + PLUGIN_PROVIDE(PUBKEY, KEY_RSA), +#endif +#ifdef BOTAN_HAS_ECDSA + PLUGIN_PROVIDE(PUBKEY, KEY_ECDSA), +#endif + PLUGIN_REGISTER(PRIVKEY, botan_private_key_load, TRUE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), +#ifdef BOTAN_HAS_RSA + PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), +#endif +#ifdef BOTAN_HAS_ECDSA + PLUGIN_PROVIDE(PRIVKEY, KEY_ECDSA), +#endif #endif /* RSA */ #ifdef BOTAN_HAS_RSA @@ -164,6 +187,7 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PUBKEY, KEY_RSA), PLUGIN_REGISTER(PRIVKEY, botan_rsa_private_key_load, TRUE), PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), + PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_REGISTER(PRIVKEY_GEN, botan_rsa_private_key_gen, FALSE), PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA), /* encryption/signature schemes */ @@ -214,8 +238,6 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_REGISTER(PRIVKEY_GEN, botan_ec_private_key_gen, FALSE), PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_ECDSA), - PLUGIN_REGISTER(PUBKEY, botan_ec_public_key_load, TRUE), - PLUGIN_PROVIDE(PUBKEY, KEY_ECDSA), #ifdef BOTAN_HAS_EMSA_RAW PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_WITH_NULL), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_WITH_NULL), diff --git a/src/libstrongswan/plugins/botan/botan_rsa_private_key.c b/src/libstrongswan/plugins/botan/botan_rsa_private_key.c index 29f6923337..8b2583b96c 100644 --- a/src/libstrongswan/plugins/botan/botan_rsa_private_key.c +++ b/src/libstrongswan/plugins/botan/botan_rsa_private_key.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 René Korthaus * Rohde & Schwarz Cybersecurity GmbH * @@ -22,6 +25,7 @@ */ #include "botan_rsa_private_key.h" +#include "botan_rsa_public_key.h" #include @@ -56,39 +60,6 @@ struct private_botan_rsa_private_key_t { refcount_t ref; }; -/** - * Get the binary representation of a named RSA parameter - */ -static bool get_rsa_field(botan_privkey_t *key, const char *field_name, - chunk_t *value) -{ - botan_mp_t field; - size_t field_size = 0; - - if (botan_mp_init(&field)) - { - return FALSE; - } - - if (botan_privkey_get_field(field, *key, field_name) || - botan_mp_num_bytes(field, &field_size) || - !field_size) - { - botan_mp_destroy(field); - return FALSE; - } - - *value = chunk_alloc(field_size); - if (botan_mp_to_bin(field, value->ptr)) - { - botan_mp_destroy(field); - chunk_clear(value); - return FALSE; - } - botan_mp_destroy(field); - return TRUE; -} - /** * Build an EMSA PSS signature described in PKCS#1 */ @@ -251,27 +222,13 @@ METHOD(private_key_t, get_keysize, int, METHOD(private_key_t, get_public_key, public_key_t*, private_botan_rsa_private_key_t *this) { - public_key_t *pub_key; - chunk_t n, e; - - if (!get_rsa_field(&this->key, "n", &n)) - { - return NULL; - } + botan_pubkey_t pubkey; - if (!get_rsa_field(&this->key, "e", &e)) + if (botan_privkey_export_pubkey(&pubkey, this->key)) { - chunk_free(&n); return NULL; } - - pub_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, - BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, - BUILD_END); - - chunk_free(&n); - chunk_free(&e); - return pub_key; + return (public_key_t*)botan_rsa_public_key_adopt(pubkey); } METHOD(private_key_t, get_fingerprint, bool, @@ -382,6 +339,19 @@ static private_botan_rsa_private_key_t *create_empty() return this; } +/* + * Described in header + */ +botan_rsa_private_key_t *botan_rsa_private_key_adopt(botan_privkey_t key) +{ + private_botan_rsa_private_key_t *this; + + this = create_empty(); + this->key = key; + + return &this->public; +} + /* * Described in header */ @@ -650,6 +620,11 @@ botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type, break; } + if (type == KEY_ANY && !blob.ptr) + { + return NULL; + } + if (blob.ptr) { this = create_empty(); diff --git a/src/libstrongswan/plugins/botan/botan_rsa_private_key.h b/src/libstrongswan/plugins/botan/botan_rsa_private_key.h index 546b88dacd..f0f419c7ff 100644 --- a/src/libstrongswan/plugins/botan/botan_rsa_private_key.h +++ b/src/libstrongswan/plugins/botan/botan_rsa_private_key.h @@ -29,6 +29,8 @@ #ifndef BOTAN_RSA_PRIVATE_KEY_H_ #define BOTAN_RSA_PRIVATE_KEY_H_ +#include + #include #include @@ -69,4 +71,12 @@ botan_rsa_private_key_t *botan_rsa_private_key_gen(key_type_t type, botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type, va_list args); +/** + * Load a RSA private key by adopting a botan_privkey_t object. + * + * @param key private key object (adopted) + * @return loaded key, NULL on failure + */ +botan_rsa_private_key_t *botan_rsa_private_key_adopt(botan_privkey_t key); + #endif /** BOTAN_RSA_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_rsa_public_key.c b/src/libstrongswan/plugins/botan/botan_rsa_public_key.c index 617fad5d1c..6adb1c4b77 100644 --- a/src/libstrongswan/plugins/botan/botan_rsa_public_key.c +++ b/src/libstrongswan/plugins/botan/botan_rsa_public_key.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 René Korthaus * Rohde & Schwarz Cybersecurity GmbH * @@ -316,6 +319,19 @@ static private_botan_rsa_public_key_t *create_empty() return this; } +/* + * Described in header + */ +botan_rsa_public_key_t *botan_rsa_public_key_adopt(botan_pubkey_t key) +{ + private_botan_rsa_public_key_t *this; + + this = create_empty(); + this->key = key; + + return &this->public; +} + /* * Described in header */ @@ -323,16 +339,13 @@ botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type, va_list args) { private_botan_rsa_public_key_t *this = NULL; - chunk_t blob, n, e; + chunk_t n, e; - n = e = blob = chunk_empty; + n = e = chunk_empty; while (TRUE) { switch (va_arg(args, builder_part_t)) { - case BUILD_BLOB_ASN1_DER: - blob = va_arg(args, chunk_t); - continue; case BUILD_RSA_MODULUS: n = va_arg(args, chunk_t); continue; @@ -347,54 +360,7 @@ botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type, break; } - if (blob.ptr) - { - switch (type) - { - /* SubjectPublicKeyInfo */ - case KEY_RSA: - case KEY_ANY: - { - size_t namesize = 0; - char *namebuf; - - this = create_empty(); - - if (botan_pubkey_load(&this->key, blob.ptr, blob.len)) - { - free(this); - return NULL; - } - - if (botan_pubkey_algo_name(this->key, NULL, &namesize) - != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE) - { - destroy(this); - return NULL; - } - - namebuf = malloc(namesize); - if (botan_pubkey_algo_name(this->key, namebuf, &namesize)) - { - free(namebuf); - destroy(this); - return NULL; - } - - if (!strneq(namebuf, "RSA", namesize)) - { - free(namebuf); - destroy(this); - return NULL; - } - free(namebuf); - break; - } - default: - return NULL; - } - } - else if (n.ptr && e.ptr && type == KEY_RSA) + if (n.ptr && e.ptr && type == KEY_RSA) { botan_mp_t mp_n, mp_e; diff --git a/src/libstrongswan/plugins/botan/botan_rsa_public_key.h b/src/libstrongswan/plugins/botan/botan_rsa_public_key.h index 4f6be83336..1d80df9fff 100644 --- a/src/libstrongswan/plugins/botan/botan_rsa_public_key.h +++ b/src/libstrongswan/plugins/botan/botan_rsa_public_key.h @@ -1,4 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2018 René Korthaus * Rohde & Schwarz Cybersecurity GmbH * @@ -29,10 +32,12 @@ #ifndef BOTAN_RSA_PUBLIC_KEY_H_ #define BOTAN_RSA_PUBLIC_KEY_H_ -typedef struct botan_rsa_public_key_t botan_rsa_public_key_t; +#include #include +typedef struct botan_rsa_public_key_t botan_rsa_public_key_t; + /** * public_key_t implementation of RSA algorithm using Botan. */ @@ -47,7 +52,7 @@ struct botan_rsa_public_key_t { /** * Load a RSA public key using Botan. * - * Accepts a BUILD_BLOB_ASN1_DER argument. + * Accepts a BUILD_RSA_MODULUS/BUILD_RSA_PUB_EXP arguments. * * @param type type of the key, must be KEY_RSA * @param args builder_part_t argument list @@ -56,4 +61,12 @@ struct botan_rsa_public_key_t { botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type, va_list args); +/** + * Load a RSA public key by adopting a botan_pubkey_t object. + * + * @param key public key object (adopted) + * @return loaded key, NULL on failure + */ +botan_rsa_public_key_t *botan_rsa_public_key_adopt(botan_pubkey_t key); + #endif /** BOTAN_RSA_PUBLIC_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/botan/botan_util_keys.c b/src/libstrongswan/plugins/botan/botan_util_keys.c new file mode 100644 index 0000000000..176c2caf9a --- /dev/null +++ b/src/libstrongswan/plugins/botan/botan_util_keys.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "botan_util_keys.h" +#include "botan_ec_public_key.h" +#include "botan_ec_private_key.h" +#include "botan_rsa_public_key.h" +#include "botan_rsa_private_key.h" + +#include +#include + +/** + * Get the algorithm name of a public key + */ +static char *get_algo_name(botan_pubkey_t pubkey) +{ + char *name; + size_t len = 0; + + if (botan_pubkey_algo_name(pubkey, NULL, &len) + != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE) + { + return NULL; + } + + name = malloc(len); + if (botan_pubkey_algo_name(pubkey, name, &len)) + { + free(name); + return NULL; + } + return name; +} + +/* + * Described in header + */ +public_key_t *botan_public_key_load(key_type_t type, va_list args) +{ + public_key_t *this = NULL; + botan_pubkey_t pubkey; + chunk_t blob = chunk_empty; + botan_rng_t rng; + char *name; + + 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; + } + + if (botan_rng_init(&rng, "user")) + { + return NULL; + } + if (botan_pubkey_load(&pubkey, blob.ptr, blob.len)) + { + botan_rng_destroy(rng); + return NULL; + } + if (botan_pubkey_check_key(pubkey, rng, BOTAN_CHECK_KEY_EXPENSIVE_TESTS)) + { + DBG1(DBG_LIB, "public key failed key checks"); + botan_pubkey_destroy(pubkey); + botan_rng_destroy(rng); + return NULL; + } + botan_rng_destroy(rng); + + name = get_algo_name(pubkey); + if (!name) + { + botan_pubkey_destroy(pubkey); + return NULL; + } + + if (streq(name, "RSA") && (type == KEY_ANY || type == KEY_RSA)) + { + this = (public_key_t*)botan_rsa_public_key_adopt(pubkey); + } + else if (streq(name, "ECDSA") && (type == KEY_ANY || type == KEY_ECDSA)) + { + this = (public_key_t*)botan_ec_public_key_adopt(pubkey); + } + else + { + botan_pubkey_destroy(pubkey); + } + free(name); + return this; +} + +/** + * Determine the curve OID from a PKCS#8 structure + */ +static int determine_ec_oid(chunk_t pkcs8) +{ + int oid = OID_UNKNOWN; + chunk_t inner, params = chunk_empty; + + if (asn1_unwrap(&pkcs8, &pkcs8) == ASN1_SEQUENCE && + asn1_unwrap(&pkcs8, &inner) == ASN1_INTEGER && + asn1_parse_integer_uint64(inner) == 0 && + asn1_parse_algorithmIdentifier(pkcs8, 0, ¶ms) == OID_EC_PUBLICKEY && + params.len && + asn1_unwrap(¶ms, ¶ms) == ASN1_OID) + { + oid = asn1_known_oid(params); + } + return oid; +} + +/* + * Described in header + */ +private_key_t *botan_private_key_load(key_type_t type, va_list args) +{ + private_key_t *this = NULL; + botan_privkey_t key; + botan_pubkey_t pubkey; + chunk_t blob = chunk_empty; + botan_rng_t rng; + char *name; + int 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; + } + + if (botan_rng_init(&rng, "user")) + { + return NULL; + } + if (botan_privkey_load(&key, rng, blob.ptr, blob.len, NULL)) + { + botan_rng_destroy(rng); + return NULL; + } + botan_rng_destroy(rng); + + if (botan_privkey_export_pubkey(&pubkey, key)) + { + botan_privkey_destroy(key); + return NULL; + } + name = get_algo_name(pubkey); + botan_pubkey_destroy(pubkey); + if (!name) + { + return NULL; + } + if (streq(name, "RSA") && (type == KEY_ANY || type == KEY_RSA)) + { + this = (private_key_t*)botan_rsa_private_key_adopt(key); + } + else if (streq(name, "ECDSA") && (type == KEY_ANY || type == KEY_ECDSA)) + { + oid = determine_ec_oid(blob); + if (oid != OID_UNKNOWN) + { + this = (private_key_t*)botan_ec_private_key_adopt(key, oid); + } + } + if (!this) + { + botan_privkey_destroy(key); + } + free(name); + return this; +} diff --git a/src/libstrongswan/plugins/botan/botan_util_keys.h b/src/libstrongswan/plugins/botan/botan_util_keys.h new file mode 100644 index 0000000000..f05f7ce5e5 --- /dev/null +++ b/src/libstrongswan/plugins/botan/botan_util_keys.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Helper functions to load public and private keys in a generic way + * + * @defgroup botan_util_keys botan_util_keys + * @{ @ingroup botan_p + */ + +#ifndef BOTAN_UTIL_KEYS_H_ +#define BOTAN_UTIL_KEYS_H_ + +#include + +#include +#include + +/** + * Load a public key in subjectPublicKeyInfo encoding + * + * Accepts a BUILD_BLOB_ASN1_DER argument. + * + * @param type type of the key + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +public_key_t *botan_public_key_load(key_type_t type, va_list args); + +/** + * Load a private key in PKCS#8 encoding + * + * Accepts a BUILD_BLOB_ASN1_DER argument. + * + * @param type type of the key + * @param args builder_part_t argument list + * @return loaded key, NULL on failure + */ +private_key_t *botan_private_key_load(key_type_t type, va_list args); + +#endif /** BOTAN_UTIL_KEYS_H_ @}*/