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.
This commit is contained in:
Tobias Brunner
2016-10-05 11:32:52 +02:00
parent 1798e490da
commit 437610ace5
2 changed files with 73 additions and 5 deletions
@@ -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;
}
}
@@ -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),