ipseckey: Add support for ECDSA and EdDSA public keys
This commit is contained in:
@@ -207,4 +207,3 @@ ipseckey_t *ipseckey_create_frm_rr(rr_t *rr)
|
|||||||
reader->destroy(reader);
|
reader->destroy(reader);
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ enum ipseckey_algorithm_t {
|
|||||||
IPSECKEY_ALGORITHM_DSA = 1,
|
IPSECKEY_ALGORITHM_DSA = 1,
|
||||||
/** RSA key */
|
/** RSA key */
|
||||||
IPSECKEY_ALGORITHM_RSA = 2,
|
IPSECKEY_ALGORITHM_RSA = 2,
|
||||||
|
/** ECDSA key (RFC 8005) */
|
||||||
|
IPSECKEY_ALGORITHM_ECDSA = 3,
|
||||||
|
/** EdDSA key (RFC 9373) */
|
||||||
|
IPSECKEY_ALGORITHM_EDDSA = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Tobias Brunner
|
* Copyright (C) 2013-2023 Tobias Brunner
|
||||||
* Copyright (C) 2012 Reto Guadagnini
|
* Copyright (C) 2012 Reto Guadagnini
|
||||||
*
|
*
|
||||||
* Copyright (C) secunet Security Networks AG
|
* Copyright (C) secunet Security Networks AG
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
#include "ipseckey_cred.h"
|
#include "ipseckey_cred.h"
|
||||||
#include "ipseckey.h"
|
#include "ipseckey.h"
|
||||||
|
|
||||||
|
#include <asn1/asn1.h>
|
||||||
|
#include <asn1/oid.h>
|
||||||
#include <bio/bio_reader.h>
|
#include <bio/bio_reader.h>
|
||||||
|
|
||||||
typedef struct private_ipseckey_cred_t private_ipseckey_cred_t;
|
typedef struct private_ipseckey_cred_t private_ipseckey_cred_t;
|
||||||
@@ -69,13 +71,17 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool,
|
|||||||
ipseckey_t *cur_ipseckey;
|
ipseckey_t *cur_ipseckey;
|
||||||
public_key_t *public;
|
public_key_t *public;
|
||||||
rr_t *cur_rr;
|
rr_t *cur_rr;
|
||||||
chunk_t key;
|
chunk_t key, parsed_key;
|
||||||
|
|
||||||
VA_ARGS_VGET(args, cert);
|
VA_ARGS_VGET(args, cert);
|
||||||
|
|
||||||
/* Get the next supported IPSECKEY using the inner enumerator. */
|
/* Get the next supported IPSECKEY using the inner enumerator. */
|
||||||
while (this->inner->enumerate(this->inner, &cur_rr))
|
while (this->inner->enumerate(this->inner, &cur_rr))
|
||||||
{
|
{
|
||||||
|
key_type_t type = KEY_ANY;
|
||||||
|
builder_part_t subtype = BUILD_BLOB_DNSKEY;
|
||||||
|
int curve = 0;
|
||||||
|
|
||||||
cur_ipseckey = ipseckey_create_frm_rr(cur_rr);
|
cur_ipseckey = ipseckey_create_frm_rr(cur_rr);
|
||||||
|
|
||||||
if (!cur_ipseckey)
|
if (!cur_ipseckey)
|
||||||
@@ -84,7 +90,62 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_ipseckey->get_algorithm(cur_ipseckey) != IPSECKEY_ALGORITHM_RSA)
|
key = parsed_key = cur_ipseckey->get_public_key(cur_ipseckey);
|
||||||
|
|
||||||
|
switch (cur_ipseckey->get_algorithm(cur_ipseckey))
|
||||||
|
{
|
||||||
|
case IPSECKEY_ALGORITHM_RSA:
|
||||||
|
type = KEY_RSA;
|
||||||
|
break;
|
||||||
|
case IPSECKEY_ALGORITHM_ECDSA:
|
||||||
|
/* the format in RFC 8005 is defined as the algorithm-specific
|
||||||
|
* part of the encoding defined in RFC 6605 (i.e. everything
|
||||||
|
* after the first four octets), which in turn is the
|
||||||
|
* uncompressed curve point Q i.e. "x | y". as RFC 6605 has
|
||||||
|
* different algorithm identifiers for P-256 and P-384 but
|
||||||
|
* RFC 8005 does not, we don't have an identifier for the curve.
|
||||||
|
* but since only two curves are currently specified for DNSSEC,
|
||||||
|
* we guess the curve from the key's length */
|
||||||
|
if (key.len == 64)
|
||||||
|
{
|
||||||
|
curve = OID_PRIME256V1;
|
||||||
|
}
|
||||||
|
else if (key.len == 96)
|
||||||
|
{
|
||||||
|
curve = OID_SECT384R1;
|
||||||
|
}
|
||||||
|
if (curve)
|
||||||
|
{
|
||||||
|
type = KEY_ECDSA;
|
||||||
|
subtype = BUILD_BLOB_ASN1_DER;
|
||||||
|
/* we currently can only parse complete subjectPublicKeyInfo
|
||||||
|
* structures for ECDSA keys */
|
||||||
|
key = asn1_wrap(ASN1_SEQUENCE, "mm",
|
||||||
|
asn1_wrap(ASN1_SEQUENCE, "mm",
|
||||||
|
asn1_build_known_oid(OID_EC_PUBLICKEY),
|
||||||
|
asn1_build_known_oid(curve)),
|
||||||
|
asn1_bitstring("m",
|
||||||
|
chunk_cat("cc", chunk_from_chars(0x04), key)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPSECKEY_ALGORITHM_EDDSA:
|
||||||
|
/* similar to ECDSA, we don't know the exact type, so we use the
|
||||||
|
* key length again */
|
||||||
|
subtype = BUILD_EDDSA_PUB;
|
||||||
|
if (key.len == 32)
|
||||||
|
{
|
||||||
|
type = KEY_ED25519;
|
||||||
|
}
|
||||||
|
else if (key.len == 57)
|
||||||
|
{
|
||||||
|
type = KEY_ED448;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == KEY_ANY)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, " unsupported IPSECKEY algorithm, skipping");
|
DBG1(DBG_CFG, " unsupported IPSECKEY algorithm, skipping");
|
||||||
cur_ipseckey->destroy(cur_ipseckey);
|
cur_ipseckey->destroy(cur_ipseckey);
|
||||||
@@ -93,10 +154,12 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool,
|
|||||||
|
|
||||||
/* wrap the key of the IPSECKEY in a certificate and return this
|
/* wrap the key of the IPSECKEY in a certificate and return this
|
||||||
* certificate */
|
* certificate */
|
||||||
key = cur_ipseckey->get_public_key(cur_ipseckey);
|
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
|
||||||
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
|
subtype, key, BUILD_END);
|
||||||
BUILD_BLOB_DNSKEY, key,
|
if (key.ptr != parsed_key.ptr)
|
||||||
BUILD_END);
|
{
|
||||||
|
chunk_free(&key);
|
||||||
|
}
|
||||||
cur_ipseckey->destroy(cur_ipseckey);
|
cur_ipseckey->destroy(cur_ipseckey);
|
||||||
if (!public)
|
if (!public)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user