Commit b11d8186 authored by Libor Peltan's avatar Libor Peltan

introduced kkeymgr for manipulating KASP db

parent 98020d0b
......@@ -75,6 +75,7 @@
/src/keymgr
/src/khost
/src/kjournalprint
/src/kkeymgr
/src/knot1to2
/src/knotc
/src/knotd
......
......@@ -503,6 +503,11 @@ src/utils/khost/khost_main.c
src/utils/khost/khost_params.c
src/utils/khost/khost_params.h
src/utils/kjournalprint/main.c
src/utils/kkeymgr/bind_privkey.c
src/utils/kkeymgr/bind_privkey.h
src/utils/kkeymgr/functions.c
src/utils/kkeymgr/functions.h
src/utils/kkeymgr/main.c
src/utils/knot1to2/cf-lex.c
src/utils/knot1to2/cf-lex.l
src/utils/knot1to2/cf-parse.tab.c
......
......@@ -3,6 +3,7 @@
# sphinx-build manpages
/man/kdig.1
/man/keymgr.8
/man/kkeymgr.8
/man/pykeymgr.8
/man/khost.1
/man/kjournalprint.1
......
MANPAGES_IN = man/knot.conf.5in man/knotc.8in man/knotd.8in man/kdig.1in man/khost.1in man/kjournalprint.1in man/knsupdate.1in man/knot1to2.1in man/knsec3hash.1in man/keymgr.8in man/pykeymgr.8in man/kzonecheck.1in
MANPAGES_RST = reference.rst man_knotc.rst man_knotd.rst man_kdig.rst man_khost.rst man_kjournalprint.rst man_knsupdate.rst man_knot1to2.rst man_knsec3hash.rst man_keymgr.rst man_pykeymgr.rst man_kzonecheck.rst
MANPAGES_IN = man/knot.conf.5in man/knotc.8in man/knotd.8in man/kdig.1in man/khost.1in man/kjournalprint.1in man/knsupdate.1in man/knot1to2.1in man/knsec3hash.1in man/keymgr.8in man/kkeymgr.8in man/pykeymgr.8in man/kzonecheck.1in
MANPAGES_RST = reference.rst man_knotc.rst man_knotd.rst man_kdig.rst man_khost.rst man_kjournalprint.rst man_knsupdate.rst man_knot1to2.rst man_knsec3hash.rst man_keymgr.rst man_kkeymgr.rst man_pykeymgr.rst man_kzonecheck.rst
EXTRA_DIST = \
conf.py \
......@@ -62,7 +62,7 @@ man_MANS += man/knot.conf.5 man/knotc.8 man/knotd.8
endif # HAVE_DAEMON
if HAVE_UTILS
man_MANS += man/kdig.1 man/khost.1 man/kjournalprint.1 man/knsupdate.1 man/knot1to2.1 man/knsec3hash.1 man/keymgr.8 man/pykeymgr.8 man/kzonecheck.1
man_MANS += man/kdig.1 man/khost.1 man/kjournalprint.1 man/knsupdate.1 man/knot1to2.1 man/knsec3hash.1 man/keymgr.8 man/kkeymgr.8 man/pykeymgr.8 man/kzonecheck.1
endif # HAVE_UTILS
man/knot.conf.5: man/knot.conf.5in
......@@ -75,6 +75,7 @@ man/knsupdate.1: man/knsupdate.1in
man/knot1to2.1: man/knot1to2.1in
man/knsec3hash.1: man/knsec3hash.1in
man/keymgr.8: man/keymgr.8in
man/kkeymgr.8: man/kkeymgr.8in
man/pykeymgr.8: man/pykeymgr.8in
man/kzonecheck.1: man/kzonecheck.1in
......
......@@ -221,6 +221,7 @@ man_pages = [
('reference', 'knot.conf', 'Knot DNS configuration file', author, 5),
('man_kdig', 'kdig', 'Advanced DNS lookup utility', author, 1),
('man_keymgr', 'keymgr', ' DNSSEC key management utility', author, 8),
('man_kkeymgr', 'kkeymgr', ' DNSSEC key management utility', author, 8),
('man_pykeymgr', 'pykeymgr', ' DNSSEC key management utility', author, 8),
('man_khost', 'khost', 'Simple DNS lookup utility', author, 1),
('man_kjournalprint', 'kjournalprint', 'Knot DNS journal print utility', author, 1),
......
......@@ -88,7 +88,7 @@ Access control list (ACL)
An ACL list specifies which remotes are allowed to send the server a specific
request. A remote can be a single IP address or a network subnet. Also a TSIG
key can be assigned (see :doc:`keymgr <man_keymgr>` how to generate a TSIG key).
key can be assigned (see :doc:`kkeymgr <man_kkeymgr>` how to generate a TSIG key).
With no ACL rule, all the actions are denied for the zone. Each ACL rule
can allow one or more actions for given address/subnet/TSIG, or deny them.
......@@ -361,7 +361,7 @@ with manual key management flag has to be set::
dnssec-signing: on
dnssec-policy: manual
To generate signing keys, use the :doc:`keymgr <man_keymgr>` utility.
To generate signing keys, use the :doc:`kkeymgr <man_kkeymgr>` utility.
Let's use the Single-Type Signing scheme with two algorithms. Run:
.. code-block:: console
......
.\" Man page generated from reStructuredText.
.
.TH "KKEYMGR" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
.SH NAME
kkeymgr \- DNSSEC key management utility
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.SH SYNOPSIS
.sp
\fBkkeymgr\fP \fIbasic_option\fP [\fIparameters\fP\&...]
.sp
\fBkkeymgr\fP \fIconfig_option\fP \fIconfig_storage\fP \fIzone_name\fP \fIaction\fP \fIparameters\fP\&...
.SH DESCRIPTION
.sp
The \fBkkeymgr\fP utility serves for key management in Knot DNS server.
.sp
Functions for DNSSEC keys and KASP (Key And Signature Policy)
management are provided.
.sp
The DNSSEC and KASP configuration is stored in a so called KASP database.
The databse is backed by LMDB.
.SS Basic options
.INDENT 0.0
.TP
\fB\-h\fP
Print the program help.
.TP
\fB\-t\fP [\fItsig_algorithm\fP] [\fItsig_bits\fP]
Generates TSIG key. TSIG algorithm can be specified by string (default: hmac\-sha256),
bit length of the key by number (default: optimal length given by algorithm).
.UNINDENT
.SS Config options
.INDENT 0.0
.TP
\fB\-d\fP
Use KASP database directory specified by config_storage.
.TP
\fB\-c\fP
Determine KASP database location from Knot DNS configuration file, specified
by config_storage.
.TP
\fB\-C\fP
Determine KASP database location from Knot DNS configuration database,
specified by config_storage.
.UNINDENT
.SS Actions
.INDENT 0.0
.TP
\fBgenerate\fP [\fIarguments\fP\&...]
Generates new DNSSEC key and stores it in KASP database. Prints the key ID.
This action takes some number of arguments (see below). Values for unspecified arguments are taken
from corresponding policy (if \fI\-c\fP or \fI\-C\fP options used) or from Knot policy defaults.
.TP
\fBimport\-bind\fP \fIBIND_key_file\fP
Imports a BIND\-style key into KASP database (converting it to PEM format).
Takes one argument: path to BIND key file (private or public, but both MUST exist).
.UNINDENT
.SS Generate arguments
.sp
Arguments are separated by space, each of them is in format \(aqname=value\(aq.
.INDENT 0.0
.TP
\fBalgorithm\fP
Either an algorithm number (e.g. 14), or text name without dashes (e.g. ECDSAP384SHA384).
.TP
\fBsize\fP
Key length in bits.
.TP
\fBksk\fP
Either \(aqtrue\(aq (KSK will be generated) or \(aqfalse\(aq (ZSK wil be generated).
.TP
\fBcreated\fP
Timestamp of key creation.
.TP
\fBpublish\fP
Timestamp for key to be published.
.TP
\fBactive\fP
Timestamp for key to be activated.
.TP
\fBretire\fP
Timestamp for key to be de\-activated.
.TP
\fBremove\fP
Timestamp for key ot be deleted.
.UNINDENT
.SS Timestamps
.INDENT 0.0
.TP
\fIUNIX_time\fP
Positive number of seconds since 1970.
.TP
\fIYYYYMMDDHHMMSS\fP
Date and time in this format without any punctuation.
.TP
\fIrelative_timestamp\fP
The word "now" followed by sign (+, \-), a number and a shortcut for time unit
(y, mo, d, h, mi, (nothing = seconds)), e.g. now+1mi, now\-2mo, now+10,
now+0, now\-1y, ...
.UNINDENT
.SH EXAMPLES
.INDENT 0.0
.IP 1. 3
Generate TSIG key:
.INDENT 3.0
.INDENT 3.5
.sp
.nf
.ft C
$ kkeymgr \-t my_name hmac\-sha384
.ft P
.fi
.UNINDENT
.UNINDENT
.IP 2. 3
Import a key from BIND:
.INDENT 3.0
.INDENT 3.5
.sp
.nf
.ft C
$ kkeymgr \-d ${knot_data_dir}/keys example.com. import\-bind ~/bind/Kharbinge4d5.+007+63089.key
.ft P
.fi
.UNINDENT
.UNINDENT
.IP 3. 3
Generate new key:
.INDENT 3.0
.INDENT 3.5
.sp
.nf
.ft C
$ kkeymgr \-c ${knot_data_dir}/knot.conf example.com. generate algorithm=ECDSAP256SHA256 size=256 \e
ksk=true created=1488034625 publish=20170223205611 retire=now+10mo remove=now+1y
.ft P
.fi
.UNINDENT
.UNINDENT
.UNINDENT
.SH SEE ALSO
.sp
\fI\%RFC 6781\fP \- DNSSEC Operational Practices.
.sp
\fBknot.conf(5)\fP,
\fBknotc(8)\fP,
\fBknotd(8)\fP\&.
.SH AUTHOR
CZ.NIC Labs <http://www.knot-dns.cz>
.SH COPYRIGHT
Copyright 2010–2017, CZ.NIC, z.s.p.o.
.\" Generated by docutils manpage writer.
.
.. highlight:: console
kkeymgr – Key management utility
=================================
Synopsis
--------
:program:`kkeymgr` *basic_option* [*parameters*...]
:program:`kkeymgr` *config_option* *config_storage* *zone_name* *action* *parameters*...
Description
-----------
The :program:`kkeymgr` utility serves for key management in Knot DNS server.
Functions for DNSSEC keys and KASP (Key And Signature Policy)
management are provided.
The DNSSEC and KASP configuration is stored in a so called KASP database.
The databse is backed by LMDB.
Basic options
..............
**-h**
Print the program help.
**-t** [*tsig_algorithm*] [*tsig_bits*]
Generates TSIG key. TSIG algorithm can be specified by string (default: hmac-sha256),
bit length of the key by number (default: optimal length given by algorithm).
Config options
..............
**-d**
Use KASP database directory specified by config_storage.
**-c**
Determine KASP database location from Knot DNS configuration file, specified
by config_storage.
**-C**
Determine KASP database location from Knot DNS configuration database,
specified by config_storage.
Actions
.......
**generate** [*arguments*...]
Generates new DNSSEC key and stores it in KASP database. Prints the key ID.
This action takes some number of arguments (see below). Values for unspecified arguments are taken
from corresponding policy (if *-c* or *-C* options used) or from Knot policy defaults.
**import-bind** *BIND_key_file*
Imports a BIND-style key into KASP database (converting it to PEM format).
Takes one argument: path to BIND key file (private or public, but both MUST exist).
Generate arguments
..................
Arguments are separated by space, each of them is in format 'name=value'.
**algorithm**
Either an algorithm number (e.g. 14), or text name without dashes (e.g. ECDSAP384SHA384).
**size**
Key length in bits.
**ksk**
Either 'true' (KSK will be generated) or 'false' (ZSK wil be generated).
**created**
Timestamp of key creation.
**publish**
Timestamp for key to be published.
**active**
Timestamp for key to be activated.
**retire**
Timestamp for key to be de-activated.
**remove**
Timestamp for key ot be deleted.
Timestamps
..........
*UNIX_time*
Positive number of seconds since 1970.
*YYYYMMDDHHMMSS*
Date and time in this format without any punctuation.
*relative_timestamp*
The word "now" followed by sign (+, -), a number and a shortcut for time unit
(y, mo, d, h, mi, (nothing = seconds)), e.g. now+1mi, now-2mo, now+10,
now+0, now-1y, ...
Examples
--------
1. Generate TSIG key::
$ kkeymgr -t my_name hmac-sha384
2. Import a key from BIND::
$ kkeymgr -d ${knot_data_dir}/keys example.com. import-bind ~/bind/Kharbinge4d5.+007+63089.key
3. Generate new key::
$ kkeymgr -c ${knot_data_dir}/knot.conf example.com. generate algorithm=ECDSAP256SHA256 size=256 \
ksk=true created=1488034625 publish=20170223205611 retire=now+10mo remove=now+1y
See Also
--------
:rfc:`6781` - DNSSEC Operational Practices.
:manpage:`knot.conf(5)`,
:manpage:`knotc(8)`,
:manpage:`knotd(8)`.
......@@ -12,6 +12,7 @@ the server. This section collects manual pages for all provided binaries:
man_kdig
man_keymgr
man_kkeymgr
man_pykeymgr
man_khost
man_kjournalprint
......
......@@ -512,7 +512,7 @@ if HAVE_UTILS
bin_PROGRAMS = kdig khost knsec3hash knsupdate
if HAVE_DAEMON
bin_PROGRAMS += kzonecheck kjournalprint
bin_PROGRAMS += kzonecheck kjournalprint kkeymgr
endif # HAVE_DAEMON
kdig_SOURCES = \
......@@ -550,6 +550,13 @@ kzonecheck_SOURCES = \
kjournalprint_SOURCES = \
utils/kjournalprint/main.c
kkeymgr_SOURCES = \
utils/kkeymgr/bind_privkey.c \
utils/kkeymgr/bind_privkey.h \
utils/kkeymgr/functions.c \
utils/kkeymgr/functions.h \
utils/kkeymgr/main.c
# bin programs
kdig_CPPFLAGS = $(AM_CPPFLAGS) $(gnutls_CFLAGS)
kdig_LDADD = $(libidn_LIBS) libknotus.la
......@@ -562,6 +569,9 @@ knsec3hash_LDADD = dnssec/libdnssec.la dnssec/libshared.la
kzonecheck_LDADD = libknotd.la libcontrib.la
kjournalprint_CPPFLAGS = $(AM_CPPFLAGS) $(gnutls_CFLAGS) $(liburcu_CFLAGS)
kjournalprint_LDADD = $(libidn_LIBS) $(liburcu_LIBS) libknotd.la libcontrib.la
kkeymgr_CPPFLAGS = $(AM_CPPFLAGS) $(liburcu_CFLAGS) -I$(srcdir)/dnssec/lib/dnssec -I$(srcdir)/dnssec $(gnutls_CFLAGS)
kkeymgr_LDADD = $(libidn_LIBS) $(liburcu_LIBS) libknotd.la libcontrib.la libknotd.la libknotus.la dnssec/libdnssec.la dnssec/libshared.la zscanner/libzscanner.la $(gnutls_LIBS)
# TODO wrap
#######################################
# Optional Knot DNS Utilities modules #
......
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
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 Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <string.h>
#include "contrib/strtonum.h"
#include "dnssec/binary.h"
#include "dnssec/error.h"
#include "shared/pem.h"
#include "shared/shared.h"
#include "utils/kkeymgr/bind_privkey.h"
/* -- private key params conversion ---------------------------------------- */
/*!
* Private key attribute conversion.
*/
typedef struct param_t {
char *name;
size_t offset;
int (*parse_cb)(char *string, void *data);
void (*free_cb)(void *data);
} param_t;
static int parse_algorithm(char *string, void *_algorithm);
static int parse_binary(char *string, void *_binary);
static int parse_time(char *string, void *_time);
static void binary_free(void *_binary)
{
dnssec_binary_t *binary = _binary;
dnssec_binary_free(binary);
}
/*!
* Know attributes in private key file.
*/
const param_t PRIVKEY_CONVERSION_TABLE[] = {
#define o(field) offsetof(bind_privkey_t, field)
{ "Algorithm", o(algorithm), parse_algorithm, NULL },
{ "Modulus", o(modulus), parse_binary, binary_free },
{ "PublicExponent", o(public_exponent), parse_binary, binary_free },
{ "PrivateExponent", o(private_exponent), parse_binary, binary_free },
{ "Prime1", o(prime_one), parse_binary, binary_free },
{ "Prime2", o(prime_two), parse_binary, binary_free },
{ "Exponent1", o(exponent_one), parse_binary, binary_free },
{ "Exponent2", o(exponent_two), parse_binary, binary_free },
{ "Coefficient", o(coefficient), parse_binary, binary_free },
{ "Prime(p)", o(prime), parse_binary, binary_free },
{ "Subprime(q)", o(subprime), parse_binary, binary_free },
{ "Base(g)", o(base), parse_binary, binary_free },
{ "Private_value(x)",o(private_value), parse_binary, binary_free },
{ "Public_value(y)", o(public_value), parse_binary, binary_free },
{ "PrivateKey", o(private_key), parse_binary, binary_free },
{ "Created", o(time_created), parse_time, NULL },
{ "Publish", o(time_publish), parse_time, NULL },
{ "Activate", o(time_activate), parse_time, NULL },
{ "Revoke", o(time_revoke), parse_time, NULL },
{ "Inactive", o(time_inactive), parse_time, NULL },
{ "Delete", o(time_delete), parse_time, NULL },
{ NULL }
#undef o
};
/* -- attribute parsing ---------------------------------------------------- */
/*!
* Parse key algorithm field.
*
* Example: 7 (NSEC3RSASHA1)
*
* Only the numeric value is decoded, the rest of the value is ignored.
*/
static int parse_algorithm(char *string, void *_algorithm)
{
char *end = string;
while (*end != '\0' && !isspace((int)*end)) {
end += 1;
}
*end = '\0';
uint8_t *algorithm = _algorithm;
int r = str_to_u8(string, algorithm);
return (r == KNOT_EOK ? DNSSEC_EOK : DNSSEC_INVALID_KEY_ALGORITHM);
}
/*!
* Parse binary data encoded in Base64.
*
* Example: AQAB
*/
static int parse_binary(char *string, void *_binary)
{
dnssec_binary_t base64 = {
.data = (uint8_t *)string,
.size = strlen(string)
};
dnssec_binary_t *binary = _binary;
return dnssec_binary_from_base64(&base64, binary);
}
#define LEGACY_DATE_FORMAT "%Y%m%d%H%M%S"
/*!
* Parse timestamp in a format in \ref LEGACY_DATE_FORMAT.
*
* Example: 20140415151855
*/
static int parse_time(char *string, void *_time)
{
struct tm tm = { 0 };
char *end = strptime(string, LEGACY_DATE_FORMAT, &tm);
if (end == NULL || *end != '\0') {
return DNSSEC_MALFORMED_DATA;
}
time_t *time = _time;
*time = timegm(&tm);
return DNSSEC_EOK;
}
/* -- key parsing ---------------------------------------------------------- */
/*!
* Strip string value of left and right whitespaces.
*
* \param[in,out] value Start of the string.
* \param[in,out] length Length of the string.
*
*/
static void strip(char **value, size_t *length)
{
// strip from left
while (*length > 0 && isspace((int)**value)) {
*value += 1;
*length -= 1;
}
// strip from right
while (*length > 0 && isspace((int)(*value)[*length - 1])) {
*length -= 1;
}
}
/*!
* Parse one line of the private key file.
*/
static int parse_line(bind_privkey_t *params, char *line, size_t length)
{
assert(params);
assert(line);
char *separator = memchr(line, ':', length);
if (!separator) {
return DNSSEC_MALFORMED_DATA;
}
char *key = line;
size_t key_length = separator - key;
strip(&key, &key_length);
char *value = separator + 1;
size_t value_length = (line + length) - value;
strip(&value, &value_length);
if (key_length == 0 || value_length == 0) {
return DNSSEC_MALFORMED_DATA;
}
key[key_length] = '\0';
value[value_length] = '\0';
for (const param_t *p = PRIVKEY_CONVERSION_TABLE; p->name != NULL; p++) {
size_t name_length = strlen(p->name);
if (name_length != key_length) {
continue;
}
if (strcasecmp(p->name, key) != 0) {
continue;
}
return p->parse_cb(value, (void *)params + p->offset);
}
// ignore unknown attributes
return DNSSEC_EOK;
}
int bind_privkey_parse(const char *filename, bind_privkey_t *params_ptr)
{
_cleanup_fclose_ FILE *file = fopen(filename, "r");
if (!file) {
return DNSSEC_NOT_FOUND;
}
bind_privkey_t params = { 0 };
_cleanup_free_ char *line = NULL;
size_t size = 0;
ssize_t read = 0;
while ((read = getline(&line, &size, file)) != -1) {
int r = parse_line(&params, line, read);
if (r != DNSSEC_EOK) {
bind_privkey_free(&params);
return r;
}
}
*params_ptr = params;
return DNSSEC_EOK;
}
/* -- freeing -------------------------------------------------------------- */
/*!
* Free private key parameters.
*/
void bind_privkey_free(bind_privkey_t *params)
{
if (!params) {
return;
}
for (const param_t *p = PRIVKEY_CONVERSION_TABLE; p->name != NULL; p++) {
if (p->free_cb) {
p->free_cb((void *)params + p->offset);
}
}
clear_struct(params);
}
/* -- export to PEM -------------------------------------------------------- */
static int rsa_params_to_pem(const bind_privkey_t *params, dnssec_binary_t *pem)
{
_cleanup_x509_privkey_ gnutls_x509_privkey_t key = NULL;
int result = gnutls_x509_privkey_init(&key);
if (result != GNUTLS_E_SUCCESS) {
return DNSSEC_ENOMEM;
}
gnutls_datum_t m = binary_to_datum(&params->modulus);
gnutls_datum_t e = binary_to_datum(&params->public_exponent);
gnutls_datum_t d = binary_to_datum(&params->private_exponent);
gnutls_datum_t p = binary_to_datum(&params->prime_one);
gnutls_datum_t q = binary_to_datum(&params->prime_two);
gnutls_datum_t u = binary_to_datum(&params->coefficient);
result = gnutls_x509_privkey_import_rsa_raw(key, &m, &e, &d, &p, &q, &u);
if (result != GNUTLS_E_SUCCESS) {
return DNSSEC_KEY_IMPORT_ERROR;
}
return pem_from_x509(key, pem);
}
static int dsa_params_to_pem(const bind_privkey_t *params, dnssec_binary_t *pem)
{
_cleanup_x509_privkey_ gnutls_x509_privkey_t key = NULL;
int result = gnutls_x509_privkey_init(&key);
if (result != GNUTLS_E_SUCCESS) {
return DNSSEC_ENOMEM;
}
gnutls_datum_t p = binary_to_datum(&params->prime);
gnutls_datum_t q = binary_to_datum(&params->subprime);
gnutls_datum_t g = binary_to_datum(&params->base);
gnutls_datum_t x = binary_to_datum(&params->private_value);
gnutls_datum_t y = binary_to_datum(&params->public_value);
result = gnutls_x509_privkey_import_dsa_raw(key, &p, &q, &g, &y, &x);
if (result != DNSSEC_EOK) {
return DNSSEC_KEY_IMPORT_ERROR;
}
return pem_from_x509(key, pem);
}
/*!
* \see lib/key/convert.h
*/
static gnutls_ecc_curve_t choose_ecdsa_curve(size_t pubkey_size)
{
switch (pubkey_size) {
case 64: return GNUTLS_ECC_CURVE_SECP256R1;
case 96: return GNUTLS_ECC_CURVE_SECP384R1;
default: return GNUTLS_ECC_CURVE_INVALID;
}
}
static void ecdsa_extract_public_params(dnssec_key_t *key, gnutls_ecc_curve_t *curve,
gnutls_datum_t *x, gnutls_datum_t *y)
{
dnssec_binary_t pubkey = { 0 };
dnssec_key_get_pubkey(key, &pubkey);
*curve = choose_ecdsa_curve(pubkey.size);
size_t param_size = pubkey.size / 2;
x->data = pubkey.data;
x->size = param_size;
y->data = pubkey.data + param_size;
y->size = param_size;
}
static int ecdsa_params_to_pem(dnssec_key_t *dnskey, const bind_privkey_t *params,
dnssec_binary_t *pem)
{
_cleanup_x509_privkey_ gnutls_x509_privkey_t key = NULL;
int result = gnutls_x5