diff options
Diffstat (limited to 'tests/libdnssec/test_key.c')
-rw-r--r-- | tests/libdnssec/test_key.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/tests/libdnssec/test_key.c b/tests/libdnssec/test_key.c new file mode 100644 index 0000000..cd0aaee --- /dev/null +++ b/tests/libdnssec/test_key.c @@ -0,0 +1,215 @@ +/* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>. + */ + +#include <tap/basic.h> +#include <string.h> + +#include "binary.h" +#include "crypto.h" +#include "error.h" +#include "key.h" + +#include "sample_keys.h" + +#define check_attr_scalar(key, type, name, def_val, set_val) { \ + type value = dnssec_key_get_##name(key); \ + ok(value == def_val, #name " default"); \ + r = dnssec_key_set_##name(key, set_val); \ + ok(r == DNSSEC_EOK, #name " set"); \ + value = dnssec_key_get_##name(key); \ + ok(value == set_val, #name " get"); \ +} + +static void check_key_tag(dnssec_key_t *key, const key_parameters_t *params) +{ + uint16_t keytag = dnssec_key_get_keytag(key); + ok(keytag == params->keytag, "get keytag"); +} + +static void check_key_size(dnssec_key_t *key, const key_parameters_t *params) +{ + ok(dnssec_key_get_size(key) == params->bit_size, + "key size %u bits", params->bit_size); +} + +static void check_usage(dnssec_key_t *key, bool ok_verify, bool ok_sign) +{ + ok(dnssec_key_can_verify(key) == ok_verify, + "%s verify", ok_verify ? "can" : "cannot"); + ok(dnssec_key_can_sign(key) == ok_sign, + "%s sign", ok_sign ? "can" : "cannot"); +} + +static void test_public_key(const key_parameters_t *params) +{ + dnssec_key_t *key = NULL; + int r = dnssec_key_new(&key); + ok(r == DNSSEC_EOK && key != NULL, "create key"); + + // create from parameters + + r = dnssec_key_set_pubkey(key, ¶ms->public_key); + ok(r == DNSSEC_INVALID_KEY_ALGORITHM, + "set public key (fails, no algorithm set)"); + + check_attr_scalar(key, uint16_t, flags, 256, params->flags); + check_attr_scalar(key, uint8_t, protocol, 3, params->protocol); + check_attr_scalar(key, uint8_t, algorithm, 0, params->algorithm); + + r = dnssec_key_set_pubkey(key, ¶ms->public_key); + ok(r == DNSSEC_EOK, "set public key (succeeds)"); + + r = dnssec_key_set_pubkey(key, ¶ms->public_key); + ok(r == DNSSEC_KEY_ALREADY_PRESENT, + "set public key (fails, already present)"); + + dnssec_binary_t rdata = { 0 }; + r = dnssec_key_get_rdata(key, &rdata); + ok(r == DNSSEC_EOK && dnssec_binary_cmp(&rdata, ¶ms->rdata) == 0, + "get RDATA"); + + check_key_tag(key, params); + + // create from RDATA + + dnssec_key_clear(key); + r = dnssec_key_set_rdata(key, ¶ms->rdata); + ok(r == DNSSEC_EOK, "set RDATA"); + + check_key_tag(key, params); + check_key_size(key, params); + check_usage(key, true, false); + + // create copy + + dnssec_key_t *copy = dnssec_key_dup(key); + ok(copy != NULL, "duplicate key"); + + check_key_tag(copy, params); + check_key_size(copy, params); + check_usage(copy, true, false); + + dnssec_key_free(copy); + dnssec_key_free(key); +} + +static void test_private_key(const key_parameters_t *params) +{ + dnssec_key_t *key = NULL; + int r = dnssec_key_new(&key); + ok(r == DNSSEC_EOK && key != NULL, "create key"); + + // import to public + + r = dnssec_key_set_rdata(key, ¶ms->rdata); + ok(r == DNSSEC_EOK, "set RDATA"); + + r = dnssec_key_load_pkcs8(key, ¶ms->pem); + ok(r == DNSSEC_EOK, "load private key (1)"); + + ok(dnssec_key_can_verify(key), "can verify"); + ok(dnssec_key_can_sign(key), "can sign"); + + // purely from parameters + + dnssec_key_clear(key); + + dnssec_key_set_algorithm(key, params->algorithm); + dnssec_key_set_flags(key, params->flags); + r = dnssec_key_load_pkcs8(key, ¶ms->pem); + ok(r == DNSSEC_EOK, "load private key (2)"); + + dnssec_binary_t rdata = { 0 }; + r = dnssec_key_get_rdata(key, &rdata); + ok(r == DNSSEC_EOK && dnssec_binary_cmp(&rdata, ¶ms->rdata) == 0, + "get RDATA"); + + check_key_tag(key, params); + check_key_size(key, params); + check_usage(key, true, true); + + // create copy + + dnssec_key_t *copy = dnssec_key_dup(key); + ok(copy != NULL, "duplicate key"); + + check_key_tag(copy, params); + check_key_size(copy, params); + check_usage(copy, true, false); + + dnssec_key_free(copy); + dnssec_key_free(key); +} + +static void test_naming(void) +{ + dnssec_key_t *key = NULL; + dnssec_key_new(&key); + + const uint8_t *input = (uint8_t *)"\x07""eXample""\x03""COM"; + const uint8_t *expected = (uint8_t *)"\x07""example""\x03""com"; + size_t expected_size = 13; + + ok(dnssec_key_get_dname(key) == NULL, "implicit key name"); + + dnssec_key_set_dname(key, input); + const uint8_t *output = dnssec_key_get_dname(key); + + ok(strlen((char *)output) + 1 == 13 && + memcmp(output, expected, expected_size) == 0, + "set key name"); + + dnssec_key_set_dname(key, NULL); + ok(dnssec_key_get_dname(key) == NULL, "clear key name"); + + dnssec_key_free(key); +} + +typedef struct keyinfo { + const char *name; + const key_parameters_t *parameters; +} keyinfo_t; + +int main(void) +{ + plan_lazy(); + + dnssec_crypto_init(); + + static const keyinfo_t keys[] = { + { "RSA", &SAMPLE_RSA_KEY }, + { "ECDSA", &SAMPLE_ECDSA_KEY }, +#ifdef HAVE_ED25519 + { "ED25519", &SAMPLE_ED25519_KEY }, +#endif +#ifdef HAVE_ED448 + { "ED448", &SAMPLE_ED448_KEY }, +#endif + { NULL } + }; + + for (const keyinfo_t *k = keys; k->name != NULL; k += 1) { + diag("%s key", k->name); + test_public_key(k->parameters); + test_private_key(k->parameters); + } + + test_naming(); + + dnssec_crypto_cleanup(); + + return 0; +} |