From: Tobias Brunner Date: Wed, 31 Aug 2016 15:34:00 +0000 (+0200) Subject: pkcs1: Support building of KEY_ANY private keys X-Git-Tag: 5.5.1rc1~11^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=437610ace528ec8f51c356bdca49cb5dc71f88ba;p=thirdparty%2Fstrongswan.git pkcs1: Support building of KEY_ANY private keys We try to detect the type of key by parsing the basic structure of the passed ASN.1 blob. --- diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c b/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c index 767b3acf24..766832d396 100644 --- a/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c +++ b/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c @@ -1,8 +1,8 @@ /* + * Copyright (C) 2008-2016 Tobias Brunner * Copyright (C) 2008-2009 Martin Willi - * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2000-2008 Andreas Steffen - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -204,7 +204,6 @@ static private_key_t *parse_rsa_private_key(chunk_t blob) case PRIV_KEY_VERSION: if (object.len > 0 && *object.ptr != 0) { - DBG1(DBG_ASN, "PKCS#1 private key format is not version 1"); goto end; } break; @@ -248,6 +247,63 @@ end: BUILD_RSA_EXP2, exp2, BUILD_RSA_COEFF, coeff, BUILD_END); } +/** + * Check if the ASN.1 structure looks like an EC private key according to + * RFC 5915. + * + * ECPrivateKey :=: SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + * + * While the parameters and publicKey fields are OPTIONAL, RFC 5915 says that + * paramaters MUST be included and publicKey SHOULD be. + */ +static bool is_ec_private_key(chunk_t blob) +{ + chunk_t data; + return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE && + asn1_unwrap(&blob, &data) == ASN1_INTEGER && + asn1_parse_integer_uint64(data) == 1 && + asn1_unwrap(&blob, &data) == ASN1_OCTET_STRING && + asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_0 && + asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_1; +} + +/** + * Check if the ASN.1 structure looks like a BLISS private key. + */ +static bool is_bliss_private_key(chunk_t blob) +{ + chunk_t data; + return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE && + asn1_unwrap(&blob, &data) == ASN1_OID && + asn1_unwrap(&blob, &data) == ASN1_BIT_STRING && + asn1_unwrap(&blob, &data) == ASN1_BIT_STRING && + asn1_unwrap(&blob, &data) == ASN1_BIT_STRING; +} + +/** + * Load a private key from an ASN.1 encoded blob trying to detect the type + * automatically. + */ +static private_key_t *parse_private_key(chunk_t blob) +{ + if (is_ec_private_key(blob)) + { + return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA, + BUILD_BLOB_ASN1_DER, blob, BUILD_END); + } + else if (is_bliss_private_key(blob)) + { + return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA, + BUILD_BLOB_ASN1_DER, blob, BUILD_END); + } + return parse_rsa_private_key(blob); +} + /** * See header. */ @@ -301,6 +357,14 @@ private_key_t *pkcs1_private_key_load(key_type_t type, va_list args) } break; } - return parse_rsa_private_key(blob); + switch (type) + { + case KEY_ANY: + return parse_private_key(blob); + case KEY_RSA: + return parse_rsa_private_key(blob); + default: + return NULL; + } } diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c b/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c index eb0903d470..ec1bdf5654 100644 --- a/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c +++ b/src/libstrongswan/plugins/pkcs1/pkcs1_plugin.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -42,6 +42,10 @@ METHOD(plugin_t, get_features, int, private_pkcs1_plugin_t *this, plugin_feature_t *features[]) { static plugin_feature_t f[] = { + PLUGIN_REGISTER(PRIVKEY, pkcs1_private_key_load, FALSE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), + PLUGIN_SDEPEND(PRIVKEY, KEY_RSA), + PLUGIN_SDEPEND(PRIVKEY, KEY_ECDSA), PLUGIN_REGISTER(PRIVKEY, pkcs1_private_key_load, FALSE), PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), PLUGIN_REGISTER(PUBKEY, pkcs1_public_key_load, FALSE),