summaryrefslogtreecommitdiffstats
path: root/lib/dns/tests/dst_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/tests/dst_test.c')
-rw-r--r--lib/dns/tests/dst_test.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/lib/dns/tests/dst_test.c b/lib/dns/tests/dst_test.c
new file mode 100644
index 0000000..421ab2f
--- /dev/null
+++ b/lib/dns/tests/dst_test.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* ! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <isc/file.h>
+#include <isc/util.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+
+#include <dst/dst.h>
+#include <dst/result.h>
+
+#include "../dst_internal.h"
+
+#include "dnstest.h"
+
+ATF_TC(sig);
+ATF_TC_HEAD(sig, tc) {
+ atf_tc_set_md_var(tc, "descr", "signature ineffability");
+}
+
+/*
+ * Read sig in file at path to buf.
+ */
+static isc_result_t
+sig_fromfile(const char *path, isc_buffer_t *buf) {
+ isc_result_t result;
+ size_t rval, len;
+ FILE *fp = NULL;
+ unsigned char val;
+ char *p, *data;
+ off_t size;
+
+ result = isc_stdio_open(path, "rb", &fp);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_file_getsizefd(fileno(fp), &size);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ data = isc_mem_get(mctx, (size + 1));
+ ATF_REQUIRE(data != NULL);
+
+ len = (size_t)size;
+ p = data;
+ while (len != 0U) {
+ result = isc_stdio_read(p, 1, len, fp, &rval);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ len -= rval;
+ p += rval;
+ }
+ isc_stdio_close(fp);
+
+ p = data;
+ len = size;
+ while (len > 0U) {
+ if ((*p == '\r') || (*p == '\n')) {
+ ++p;
+ --len;
+ continue;
+ } else if (len < 2U)
+ goto err;
+ if (('0' <= *p) && (*p <= '9')) {
+ val = *p - '0';
+ } else if (('A' <= *p) && (*p <= 'F')) {
+ val = *p - 'A' + 10;
+ } else {
+ result = ISC_R_BADHEX;
+ goto err;
+ }
+ ++p;
+ val <<= 4;
+ --len;
+ if (('0' <= *p) && (*p <= '9')) {
+ val |= (*p - '0');
+ } else if (('A' <= *p) && (*p <= 'F')) {
+ val |= (*p - 'A' + 10);
+ } else {
+ result = ISC_R_BADHEX;
+ goto err;
+ }
+ ++p;
+ --len;
+ isc_buffer_putuint8(buf, val);
+ }
+
+ result = ISC_R_SUCCESS;
+
+ err:
+ isc_mem_put(mctx, data, size + 1);
+ return (result);
+}
+
+static void
+check_sig(const char *datapath, const char *sigpath, const char *keyname,
+ dns_keytag_t id, dns_secalg_t alg, int type, bool expect)
+{
+ isc_result_t result;
+ size_t rval, len;
+ FILE *fp;
+ dst_key_t *key = NULL;
+ unsigned char sig[512];
+ unsigned char *p;
+ unsigned char *data;
+ off_t size;
+ isc_buffer_t b;
+ isc_buffer_t databuf, sigbuf;
+ isc_region_t datareg, sigreg;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ dst_context_t *ctx = NULL;
+
+ /*
+ * Read data from file in a form usable by dst_verify.
+ */
+ result = isc_stdio_open(datapath, "rb", &fp);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = isc_file_getsizefd(fileno(fp), &size);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ data = isc_mem_get(mctx, (size + 1));
+ ATF_REQUIRE(data != NULL);
+
+ p = data;
+ len = (size_t)size;
+ do {
+ result = isc_stdio_read(p, 1, len, fp, &rval);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ len -= rval;
+ p += rval;
+ } while (len);
+ isc_stdio_close(fp);
+
+ /*
+ * Read key from file in a form usable by dst_verify.
+ */
+ name = dns_fixedname_initname(&fname);
+ isc_buffer_constinit(&b, keyname, strlen(keyname));
+ isc_buffer_add(&b, strlen(keyname));
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ result = dst_key_fromfile(name, id, alg, type, "testdata/dst",
+ mctx, &key);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ isc_buffer_init(&databuf, data, (unsigned int)size);
+ isc_buffer_add(&databuf, (unsigned int)size);
+ isc_buffer_usedregion(&databuf, &datareg);
+
+ memset(sig, 0, sizeof(sig));
+ isc_buffer_init(&sigbuf, sig, sizeof(sig));
+
+ /*
+ * Read precomputed signature from file in a form usable by dst_verify.
+ */
+ result = sig_fromfile(sigpath, &sigbuf);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ /*
+ * Verify that the key signed the data.
+ */
+ isc_buffer_remainingregion(&sigbuf, &sigreg);
+
+ result = dst_context_create3(key, mctx, DNS_LOGCATEGORY_GENERAL,
+ false, &ctx);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ result = dst_context_adddata(ctx, &datareg);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ result = dst_context_verify(ctx, &sigreg);
+
+ ATF_REQUIRE((expect && (result == ISC_R_SUCCESS)) ||
+ (!expect && (result != ISC_R_SUCCESS)));
+
+
+ isc_mem_put(mctx, data, size + 1);
+ dst_context_destroy(&ctx);
+ dst_key_free(&key);
+
+ return;
+}
+
+ATF_TC_BODY(sig, tc) {
+ isc_result_t result;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, false);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+ struct {
+ const char *datapath;
+ const char *sigpath;
+ const char *keyname;
+ dns_keytag_t keyid;
+ dns_secalg_t alg;
+ bool expect;
+ } testcases[] = {
+ {
+ "testdata/dst/test1.data",
+ "testdata/dst/test1.dsasig",
+ "test.", 23616, DST_ALG_DSA, true
+ },
+ {
+ "testdata/dst/test1.data",
+ "testdata/dst/test1.rsasig",
+ "test.", 54622, DST_ALG_RSAMD5, true
+ },
+ {
+ /* wrong sig */
+ "testdata/dst/test1.data",
+ "testdata/dst/test1.dsasig",
+ "test.", 54622, DST_ALG_RSAMD5, false
+ },
+ {
+ /* wrong data */
+ "testdata/dst/test2.data",
+ "testdata/dst/test1.dsasig",
+ "test.", 23616, DST_ALG_DSA, false
+ },
+ };
+ unsigned int i;
+
+ for (i = 0; i < (sizeof(testcases)/sizeof(testcases[0])); i++) {
+ if (!dst_algorithm_supported(testcases[i].alg)) {
+ continue;
+ }
+
+ check_sig(testcases[i].datapath,
+ testcases[i].sigpath,
+ testcases[i].keyname,
+ testcases[i].keyid,
+ testcases[i].alg,
+ DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+ testcases[i].expect);
+ }
+
+ dns_test_end();
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+ ATF_TP_ADD_TC(tp, sig);
+
+ return (atf_no_error());
+}