summaryrefslogtreecommitdiffstats
path: root/tests/libdnssec
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/libdnssec/sample_keys.h407
-rw-r--r--tests/libdnssec/test_binary.c93
-rw-r--r--tests/libdnssec/test_crypto.c37
-rw-r--r--tests/libdnssec/test_key.c212
-rw-r--r--tests/libdnssec/test_key_algorithm.c84
-rw-r--r--tests/libdnssec/test_key_ds.c116
-rw-r--r--tests/libdnssec/test_keyid.c81
-rw-r--r--tests/libdnssec/test_keystore_pkcs11.c484
-rw-r--r--tests/libdnssec/test_keystore_pkcs8.c219
-rw-r--r--tests/libdnssec/test_keystore_pkcs8_dir.c151
-rw-r--r--tests/libdnssec/test_keytag.c61
-rw-r--r--tests/libdnssec/test_list.c127
-rw-r--r--tests/libdnssec/test_nsec_bitmap.c102
-rw-r--r--tests/libdnssec/test_nsec_hash.c114
-rw-r--r--tests/libdnssec/test_random.c82
-rw-r--r--tests/libdnssec/test_shared_bignum.c128
-rw-r--r--tests/libdnssec/test_shared_dname.c79
-rw-r--r--tests/libdnssec/test_sign.c184
-rw-r--r--tests/libdnssec/test_sign_der.c202
-rw-r--r--tests/libdnssec/test_tsig.c145
20 files changed, 3108 insertions, 0 deletions
diff --git a/tests/libdnssec/sample_keys.h b/tests/libdnssec/sample_keys.h
new file mode 100644
index 0000000..c788ed5
--- /dev/null
+++ b/tests/libdnssec/sample_keys.h
@@ -0,0 +1,407 @@
+/* Copyright (C) 2018 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/>.
+*/
+
+#pragma once
+
+#include <binary.h>
+
+typedef struct key_parameters {
+ // DNSSEC fields
+ uint8_t *name;
+ uint16_t flags;
+ uint8_t protocol;
+ uint8_t algorithm;
+ dnssec_binary_t public_key;
+
+ // DNSSEC wire format
+ dnssec_binary_t rdata;
+
+ // Hashes
+ const char *key_id;
+ uint16_t keytag;
+ dnssec_binary_t ds_sha1;
+ dnssec_binary_t ds_sha256;
+ dnssec_binary_t ds_sha384;
+
+ // Key information
+ unsigned bit_size;
+
+ // Private key in PEM
+ dnssec_binary_t pem;
+} key_parameters_t;
+
+/*
+
+RSA-SHA-256
+
+rsa. IN DNSKEY 256 3 8 AwEAAaqwL+O6GcCPkRZjoObfIJHcHPwQQY9mnAg6kROea2gsyRJOAwBNQPCfXoPtmrU0BiZ0aGBVTVPAvZh+HJRu9NEfTNDPK2HSyHdSucjY1qs6WAub6oWHJuLBxMesftpnUwoLnVZyN+pOblUZUMsvxP3PlS+mA+E6NyQX0F/fcfGL
+rsa. IN DS 37335 8 1 2ABEFAAB07A900F8CB5B266FC930EEBEF51766F6
+rsa. IN DS 37335 8 2 30226484F230814C08C6DD9E2DF6E7A3DB860C2552A418CBF70D0FEE94DFA15F
+rsa. IN DS 37335 8 4 978E0F7766096E131E3E90C50B63DBD825E7428E864BC5A3D32F3135A3786F0CDC6A070B6B8D760190F0F572B03CA4C0
+
+Modulus: qrAv47oZwI+RFmOg5t8gkdwc/BBBj2acCDqRE55raCzJEk4DAE1A8J9eg+2atTQGJnRoYFVNU8C9mH4clG700R9M0M8rYdLId1K5yNjWqzpYC5vqhYcm4sHEx6x+2mdTCgudVnI36k5uVRlQyy/E/c+VL6YD4To3JBfQX99x8Ys=
+PublicExponent: AQAB
+PrivateExponent: NGDSoVBHfMbRoAw8oPxRk1D3eAZJCAdV1FSclmej0BkGLt7PnvUV+4D8UQHF2ts3E+/e48jpbM0VoUj53jbaWx1ULVmQ1cpJY0XLsRUmaQdOwEnSgXjtQy2htlth8RinB+LnVG8eUS9jWnEEikfvCLH0ptkOa/u6GKFUMj+Q95k=
+Prime1: 4ZZj/YD5xvjxEuE0uR0KedsZeGT6iHqwtmJuLNuhFaeXIw5vXXZmg88U/lIo2t0DESYTbfXglw0eu62MwWb+5w==
+Prime2: wbMU0wM6MYaDs4FfEeuTXT14P3cXZOFGikJPWiIUGoMGvDgYzxdiFoHzGdLkapsPizTqBKMtYQ9CYQa8g1cXvQ==
+Exponent1: ywKuZVqGbdtmB9mHuvc5kEPuffxRwjS3hsq538CfDH/PcYryCagdxYy8lcqWXa/7rJkZbyGQxh7Wg4tBWmM4DQ==
+Exponent2: L8MYv29sSgoBL6IW7zRHghZGMGANRLLH0g/HwVHl4yOr5X1voKEDbslcSGHYMPFLQ+goTDxwVB6PH52pnjk7gQ==
+Coefficient: USHiV/UQkTz3BlxZc1IAiUQv9/Ba8wtHWSVp+YqPhxt1sfdiyUMXtlA4f6WAKAGMraoRw4wIcYr+N6Wx+wwXZw==
+
+-----BEGIN PRIVATE KEY-----
+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKqwL+O6GcCPkRZj
+oObfIJHcHPwQQY9mnAg6kROea2gsyRJOAwBNQPCfXoPtmrU0BiZ0aGBVTVPAvZh+
+HJRu9NEfTNDPK2HSyHdSucjY1qs6WAub6oWHJuLBxMesftpnUwoLnVZyN+pOblUZ
+UMsvxP3PlS+mA+E6NyQX0F/fcfGLAgMBAAECgYA0YNKhUEd8xtGgDDyg/FGTUPd4
+BkkIB1XUVJyWZ6PQGQYu3s+e9RX7gPxRAcXa2zcT797jyOlszRWhSPneNtpbHVQt
+WZDVykljRcuxFSZpB07ASdKBeO1DLaG2W2HxGKcH4udUbx5RL2NacQSKR+8IsfSm
+2Q5r+7oYoVQyP5D3mQJBAOGWY/2A+cb48RLhNLkdCnnbGXhk+oh6sLZibizboRWn
+lyMOb112ZoPPFP5SKNrdAxEmE2314JcNHrutjMFm/ucCQQDBsxTTAzoxhoOzgV8R
+65NdPXg/dxdk4UaKQk9aIhQagwa8OBjPF2IWgfMZ0uRqmw+LNOoEoy1hD0JhBryD
+Vxe9AkEAywKuZVqGbdtmB9mHuvc5kEPuffxRwjS3hsq538CfDH/PcYryCagdxYy8
+lcqWXa/7rJkZbyGQxh7Wg4tBWmM4DQJAL8MYv29sSgoBL6IW7zRHghZGMGANRLLH
+0g/HwVHl4yOr5X1voKEDbslcSGHYMPFLQ+goTDxwVB6PH52pnjk7gQJAUSHiV/UQ
+kTz3BlxZc1IAiUQv9/Ba8wtHWSVp+YqPhxt1sfdiyUMXtlA4f6WAKAGMraoRw4wI
+cYr+N6Wx+wwXZw==
+-----END PRIVATE KEY-----
+
+*/
+
+static const key_parameters_t SAMPLE_RSA_KEY = {
+ .name = (uint8_t *)"\x03""rsa",
+ .flags = 256,
+ .protocol = 3,
+ .algorithm = 8,
+ .public_key = { .size = 132, .data = (uint8_t []) {
+ 0x03, 0x01, 0x00, 0x01, 0xaa, 0xb0, 0x2f, 0xe3, 0xba, 0x19,
+ 0xc0, 0x8f, 0x91, 0x16, 0x63, 0xa0, 0xe6, 0xdf, 0x20, 0x91,
+ 0xdc, 0x1c, 0xfc, 0x10, 0x41, 0x8f, 0x66, 0x9c, 0x08, 0x3a,
+ 0x91, 0x13, 0x9e, 0x6b, 0x68, 0x2c, 0xc9, 0x12, 0x4e, 0x03,
+ 0x00, 0x4d, 0x40, 0xf0, 0x9f, 0x5e, 0x83, 0xed, 0x9a, 0xb5,
+ 0x34, 0x06, 0x26, 0x74, 0x68, 0x60, 0x55, 0x4d, 0x53, 0xc0,
+ 0xbd, 0x98, 0x7e, 0x1c, 0x94, 0x6e, 0xf4, 0xd1, 0x1f, 0x4c,
+ 0xd0, 0xcf, 0x2b, 0x61, 0xd2, 0xc8, 0x77, 0x52, 0xb9, 0xc8,
+ 0xd8, 0xd6, 0xab, 0x3a, 0x58, 0x0b, 0x9b, 0xea, 0x85, 0x87,
+ 0x26, 0xe2, 0xc1, 0xc4, 0xc7, 0xac, 0x7e, 0xda, 0x67, 0x53,
+ 0x0a, 0x0b, 0x9d, 0x56, 0x72, 0x37, 0xea, 0x4e, 0x6e, 0x55,
+ 0x19, 0x50, 0xcb, 0x2f, 0xc4, 0xfd, 0xcf, 0x95, 0x2f, 0xa6,
+ 0x03, 0xe1, 0x3a, 0x37, 0x24, 0x17, 0xd0, 0x5f, 0xdf, 0x71,
+ 0xf1, 0x8b,
+ }},
+ .rdata = { .size = 136, .data = (uint8_t []) {
+ 0x01, 0x00, 0x03, 0x08,
+ 0x03, 0x01, 0x00, 0x01, 0xaa, 0xb0, 0x2f, 0xe3, 0xba, 0x19,
+ 0xc0, 0x8f, 0x91, 0x16, 0x63, 0xa0, 0xe6, 0xdf, 0x20, 0x91,
+ 0xdc, 0x1c, 0xfc, 0x10, 0x41, 0x8f, 0x66, 0x9c, 0x08, 0x3a,
+ 0x91, 0x13, 0x9e, 0x6b, 0x68, 0x2c, 0xc9, 0x12, 0x4e, 0x03,
+ 0x00, 0x4d, 0x40, 0xf0, 0x9f, 0x5e, 0x83, 0xed, 0x9a, 0xb5,
+ 0x34, 0x06, 0x26, 0x74, 0x68, 0x60, 0x55, 0x4d, 0x53, 0xc0,
+ 0xbd, 0x98, 0x7e, 0x1c, 0x94, 0x6e, 0xf4, 0xd1, 0x1f, 0x4c,
+ 0xd0, 0xcf, 0x2b, 0x61, 0xd2, 0xc8, 0x77, 0x52, 0xb9, 0xc8,
+ 0xd8, 0xd6, 0xab, 0x3a, 0x58, 0x0b, 0x9b, 0xea, 0x85, 0x87,
+ 0x26, 0xe2, 0xc1, 0xc4, 0xc7, 0xac, 0x7e, 0xda, 0x67, 0x53,
+ 0x0a, 0x0b, 0x9d, 0x56, 0x72, 0x37, 0xea, 0x4e, 0x6e, 0x55,
+ 0x19, 0x50, 0xcb, 0x2f, 0xc4, 0xfd, 0xcf, 0x95, 0x2f, 0xa6,
+ 0x03, 0xe1, 0x3a, 0x37, 0x24, 0x17, 0xd0, 0x5f, 0xdf, 0x71,
+ 0xf1, 0x8b,
+ }},
+ .key_id = "76f0d6c093d8328bc7f0e25bd8cde5575bad9b44",
+ .keytag = 37335,
+ .ds_sha1 = { .size = 24, .data = (uint8_t []) {
+ 0x91, 0xd7, 0x08, 0x01,
+ 0x2a, 0xbe, 0xfa, 0xab, 0x07, 0xa9, 0x00, 0xf8, 0xcb, 0x5b,
+ 0x26, 0x6f, 0xc9, 0x30, 0xee, 0xbe, 0xf5, 0x17, 0x66, 0xf6,
+ }},
+ .ds_sha256 = { .size = 36, .data = (uint8_t []) {
+ 0x91, 0xd7, 0x08, 0x02,
+ 0x30, 0x22, 0x64, 0x84, 0xf2, 0x30, 0x81, 0x4c, 0x08, 0xc6,
+ 0xdd, 0x9e, 0x2d, 0xf6, 0xe7, 0xa3, 0xdb, 0x86, 0x0c, 0x25,
+ 0x52, 0xa4, 0x18, 0xcb, 0xf7, 0x0d, 0x0f, 0xee, 0x94, 0xdf,
+ 0xa1, 0x5f,
+ }},
+ .ds_sha384 = { .size = 52, .data = (uint8_t []) {
+ 0x91, 0xd7, 0x08, 0x04,
+ 0x97, 0x8e, 0x0f, 0x77, 0x66, 0x09, 0x6e, 0x13, 0x1e, 0x3e,
+ 0x90, 0xc5, 0x0b, 0x63, 0xdb, 0xd8, 0x25, 0xe7, 0x42, 0x8e,
+ 0x86, 0x4b, 0xc5, 0xa3, 0xd3, 0x2f, 0x31, 0x35, 0xa3, 0x78,
+ 0x6f, 0x0c, 0xdc, 0x6a, 0x07, 0x0b, 0x6b, 0x8d, 0x76, 0x01,
+ 0x90, 0xf0, 0xf5, 0x72, 0xb0, 0x3c, 0xa4, 0xc0,
+ }},
+ .bit_size = 1024,
+ .pem = { .size = 916, .data = (uint8_t []) {
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e,
+ 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b,
+ 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49,
+ 0x49, 0x43, 0x64, 0x67, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4e,
+ 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77,
+ 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43,
+ 0x41, 0x6d, 0x41, 0x77, 0x67, 0x67, 0x4a, 0x63, 0x41, 0x67,
+ 0x45, 0x41, 0x41, 0x6f, 0x47, 0x42, 0x41, 0x4b, 0x71, 0x77,
+ 0x4c, 0x2b, 0x4f, 0x36, 0x47, 0x63, 0x43, 0x50, 0x6b, 0x52,
+ 0x5a, 0x6a, 0x0a, 0x6f, 0x4f, 0x62, 0x66, 0x49, 0x4a, 0x48,
+ 0x63, 0x48, 0x50, 0x77, 0x51, 0x51, 0x59, 0x39, 0x6d, 0x6e,
+ 0x41, 0x67, 0x36, 0x6b, 0x52, 0x4f, 0x65, 0x61, 0x32, 0x67,
+ 0x73, 0x79, 0x52, 0x4a, 0x4f, 0x41, 0x77, 0x42, 0x4e, 0x51,
+ 0x50, 0x43, 0x66, 0x58, 0x6f, 0x50, 0x74, 0x6d, 0x72, 0x55,
+ 0x30, 0x42, 0x69, 0x5a, 0x30, 0x61, 0x47, 0x42, 0x56, 0x54,
+ 0x56, 0x50, 0x41, 0x76, 0x5a, 0x68, 0x2b, 0x0a, 0x48, 0x4a,
+ 0x52, 0x75, 0x39, 0x4e, 0x45, 0x66, 0x54, 0x4e, 0x44, 0x50,
+ 0x4b, 0x32, 0x48, 0x53, 0x79, 0x48, 0x64, 0x53, 0x75, 0x63,
+ 0x6a, 0x59, 0x31, 0x71, 0x73, 0x36, 0x57, 0x41, 0x75, 0x62,
+ 0x36, 0x6f, 0x57, 0x48, 0x4a, 0x75, 0x4c, 0x42, 0x78, 0x4d,
+ 0x65, 0x73, 0x66, 0x74, 0x70, 0x6e, 0x55, 0x77, 0x6f, 0x4c,
+ 0x6e, 0x56, 0x5a, 0x79, 0x4e, 0x2b, 0x70, 0x4f, 0x62, 0x6c,
+ 0x55, 0x5a, 0x0a, 0x55, 0x4d, 0x73, 0x76, 0x78, 0x50, 0x33,
+ 0x50, 0x6c, 0x53, 0x2b, 0x6d, 0x41, 0x2b, 0x45, 0x36, 0x4e,
+ 0x79, 0x51, 0x58, 0x30, 0x46, 0x2f, 0x66, 0x63, 0x66, 0x47,
+ 0x4c, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x45, 0x43, 0x67,
+ 0x59, 0x41, 0x30, 0x59, 0x4e, 0x4b, 0x68, 0x55, 0x45, 0x64,
+ 0x38, 0x78, 0x74, 0x47, 0x67, 0x44, 0x44, 0x79, 0x67, 0x2f,
+ 0x46, 0x47, 0x54, 0x55, 0x50, 0x64, 0x34, 0x0a, 0x42, 0x6b,
+ 0x6b, 0x49, 0x42, 0x31, 0x58, 0x55, 0x56, 0x4a, 0x79, 0x57,
+ 0x5a, 0x36, 0x50, 0x51, 0x47, 0x51, 0x59, 0x75, 0x33, 0x73,
+ 0x2b, 0x65, 0x39, 0x52, 0x58, 0x37, 0x67, 0x50, 0x78, 0x52,
+ 0x41, 0x63, 0x58, 0x61, 0x32, 0x7a, 0x63, 0x54, 0x37, 0x39,
+ 0x37, 0x6a, 0x79, 0x4f, 0x6c, 0x73, 0x7a, 0x52, 0x57, 0x68,
+ 0x53, 0x50, 0x6e, 0x65, 0x4e, 0x74, 0x70, 0x62, 0x48, 0x56,
+ 0x51, 0x74, 0x0a, 0x57, 0x5a, 0x44, 0x56, 0x79, 0x6b, 0x6c,
+ 0x6a, 0x52, 0x63, 0x75, 0x78, 0x46, 0x53, 0x5a, 0x70, 0x42,
+ 0x30, 0x37, 0x41, 0x53, 0x64, 0x4b, 0x42, 0x65, 0x4f, 0x31,
+ 0x44, 0x4c, 0x61, 0x47, 0x32, 0x57, 0x32, 0x48, 0x78, 0x47,
+ 0x4b, 0x63, 0x48, 0x34, 0x75, 0x64, 0x55, 0x62, 0x78, 0x35,
+ 0x52, 0x4c, 0x32, 0x4e, 0x61, 0x63, 0x51, 0x53, 0x4b, 0x52,
+ 0x2b, 0x38, 0x49, 0x73, 0x66, 0x53, 0x6d, 0x0a, 0x32, 0x51,
+ 0x35, 0x72, 0x2b, 0x37, 0x6f, 0x59, 0x6f, 0x56, 0x51, 0x79,
+ 0x50, 0x35, 0x44, 0x33, 0x6d, 0x51, 0x4a, 0x42, 0x41, 0x4f,
+ 0x47, 0x57, 0x59, 0x2f, 0x32, 0x41, 0x2b, 0x63, 0x62, 0x34,
+ 0x38, 0x52, 0x4c, 0x68, 0x4e, 0x4c, 0x6b, 0x64, 0x43, 0x6e,
+ 0x6e, 0x62, 0x47, 0x58, 0x68, 0x6b, 0x2b, 0x6f, 0x68, 0x36,
+ 0x73, 0x4c, 0x5a, 0x69, 0x62, 0x69, 0x7a, 0x62, 0x6f, 0x52,
+ 0x57, 0x6e, 0x0a, 0x6c, 0x79, 0x4d, 0x4f, 0x62, 0x31, 0x31,
+ 0x32, 0x5a, 0x6f, 0x50, 0x50, 0x46, 0x50, 0x35, 0x53, 0x4b,
+ 0x4e, 0x72, 0x64, 0x41, 0x78, 0x45, 0x6d, 0x45, 0x32, 0x33,
+ 0x31, 0x34, 0x4a, 0x63, 0x4e, 0x48, 0x72, 0x75, 0x74, 0x6a,
+ 0x4d, 0x46, 0x6d, 0x2f, 0x75, 0x63, 0x43, 0x51, 0x51, 0x44,
+ 0x42, 0x73, 0x78, 0x54, 0x54, 0x41, 0x7a, 0x6f, 0x78, 0x68,
+ 0x6f, 0x4f, 0x7a, 0x67, 0x56, 0x38, 0x52, 0x0a, 0x36, 0x35,
+ 0x4e, 0x64, 0x50, 0x58, 0x67, 0x2f, 0x64, 0x78, 0x64, 0x6b,
+ 0x34, 0x55, 0x61, 0x4b, 0x51, 0x6b, 0x39, 0x61, 0x49, 0x68,
+ 0x51, 0x61, 0x67, 0x77, 0x61, 0x38, 0x4f, 0x42, 0x6a, 0x50,
+ 0x46, 0x32, 0x49, 0x57, 0x67, 0x66, 0x4d, 0x5a, 0x30, 0x75,
+ 0x52, 0x71, 0x6d, 0x77, 0x2b, 0x4c, 0x4e, 0x4f, 0x6f, 0x45,
+ 0x6f, 0x79, 0x31, 0x68, 0x44, 0x30, 0x4a, 0x68, 0x42, 0x72,
+ 0x79, 0x44, 0x0a, 0x56, 0x78, 0x65, 0x39, 0x41, 0x6b, 0x45,
+ 0x41, 0x79, 0x77, 0x4b, 0x75, 0x5a, 0x56, 0x71, 0x47, 0x62,
+ 0x64, 0x74, 0x6d, 0x42, 0x39, 0x6d, 0x48, 0x75, 0x76, 0x63,
+ 0x35, 0x6b, 0x45, 0x50, 0x75, 0x66, 0x66, 0x78, 0x52, 0x77,
+ 0x6a, 0x53, 0x33, 0x68, 0x73, 0x71, 0x35, 0x33, 0x38, 0x43,
+ 0x66, 0x44, 0x48, 0x2f, 0x50, 0x63, 0x59, 0x72, 0x79, 0x43,
+ 0x61, 0x67, 0x64, 0x78, 0x59, 0x79, 0x38, 0x0a, 0x6c, 0x63,
+ 0x71, 0x57, 0x58, 0x61, 0x2f, 0x37, 0x72, 0x4a, 0x6b, 0x5a,
+ 0x62, 0x79, 0x47, 0x51, 0x78, 0x68, 0x37, 0x57, 0x67, 0x34,
+ 0x74, 0x42, 0x57, 0x6d, 0x4d, 0x34, 0x44, 0x51, 0x4a, 0x41,
+ 0x4c, 0x38, 0x4d, 0x59, 0x76, 0x32, 0x39, 0x73, 0x53, 0x67,
+ 0x6f, 0x42, 0x4c, 0x36, 0x49, 0x57, 0x37, 0x7a, 0x52, 0x48,
+ 0x67, 0x68, 0x5a, 0x47, 0x4d, 0x47, 0x41, 0x4e, 0x52, 0x4c,
+ 0x4c, 0x48, 0x0a, 0x30, 0x67, 0x2f, 0x48, 0x77, 0x56, 0x48,
+ 0x6c, 0x34, 0x79, 0x4f, 0x72, 0x35, 0x58, 0x31, 0x76, 0x6f,
+ 0x4b, 0x45, 0x44, 0x62, 0x73, 0x6c, 0x63, 0x53, 0x47, 0x48,
+ 0x59, 0x4d, 0x50, 0x46, 0x4c, 0x51, 0x2b, 0x67, 0x6f, 0x54,
+ 0x44, 0x78, 0x77, 0x56, 0x42, 0x36, 0x50, 0x48, 0x35, 0x32,
+ 0x70, 0x6e, 0x6a, 0x6b, 0x37, 0x67, 0x51, 0x4a, 0x41, 0x55,
+ 0x53, 0x48, 0x69, 0x56, 0x2f, 0x55, 0x51, 0x0a, 0x6b, 0x54,
+ 0x7a, 0x33, 0x42, 0x6c, 0x78, 0x5a, 0x63, 0x31, 0x49, 0x41,
+ 0x69, 0x55, 0x51, 0x76, 0x39, 0x2f, 0x42, 0x61, 0x38, 0x77,
+ 0x74, 0x48, 0x57, 0x53, 0x56, 0x70, 0x2b, 0x59, 0x71, 0x50,
+ 0x68, 0x78, 0x74, 0x31, 0x73, 0x66, 0x64, 0x69, 0x79, 0x55,
+ 0x4d, 0x58, 0x74, 0x6c, 0x41, 0x34, 0x66, 0x36, 0x57, 0x41,
+ 0x4b, 0x41, 0x47, 0x4d, 0x72, 0x61, 0x6f, 0x52, 0x77, 0x34,
+ 0x77, 0x49, 0x0a, 0x63, 0x59, 0x72, 0x2b, 0x4e, 0x36, 0x57,
+ 0x78, 0x2b, 0x77, 0x77, 0x58, 0x5a, 0x77, 0x3d, 0x3d, 0x0a,
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50,
+ 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59,
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a,
+ }},
+};
+
+/*
+
+ECDSA-P256-SHA256
+
+ecdsa. IN DNSKEY 256 3 13 8uD7C4THTM/w7uhryRSToeE/jKT78/p853RX0L5EwrZrSLBubLPiBw7g bvUP6SsIga5ZQ4CSAxNmYA/gZsuXzA==
+ecdsa. IN DS 5345 13 1 954103ac7c43810ce9f414e80f30ab1cbe49b236
+ecdsa. IN DS 5345 13 2 bac2107036e735b50f85006ce409a19a3438cab272e70769ebda032239a3d0ca
+ecdsa. IN DS 5345 13 4 a0ac6790483872be72a258314200a88ab75cdd70f66a18a09f0f414c074df0989fdb1df0e67d82d4312cda67b93a76c1
+
+PrivateKey: iyLIPdk3DOIxVmmSYlmTstbtUPiVlEyDX46psyCwNVQ=
+
+-----BEGIN PRIVATE KEY-----
+MIGUAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHoweAIBAQQhAIsiyD3ZNwziMVZp
+kmJZk7LW7VD4lZRMg1+OqbMgsDVUoAoGCCqGSM49AwEHoUQDQgAE8uD7C4THTM/w
+7uhryRSToeE/jKT78/p853RX0L5EwrZrSLBubLPiBw7gbvUP6SsIga5ZQ4CSAxNm
+YA/gZsuXzA==
+-----END PRIVATE KEY-----
+
+*/
+
+static const key_parameters_t SAMPLE_ECDSA_KEY = {
+ .name = (uint8_t *)"\x05""ecdsa",
+ .flags = 256,
+ .protocol = 3,
+ .algorithm = 13,
+ .public_key = { .size = 64, .data = (uint8_t []) {
+ 0xf2, 0xe0, 0xfb, 0x0b, 0x84, 0xc7, 0x4c, 0xcf, 0xf0, 0xee,
+ 0xe8, 0x6b, 0xc9, 0x14, 0x93, 0xa1, 0xe1, 0x3f, 0x8c, 0xa4,
+ 0xfb, 0xf3, 0xfa, 0x7c, 0xe7, 0x74, 0x57, 0xd0, 0xbe, 0x44,
+ 0xc2, 0xb6, 0x6b, 0x48, 0xb0, 0x6e, 0x6c, 0xb3, 0xe2, 0x07,
+ 0x0e, 0xe0, 0x6e, 0xf5, 0x0f, 0xe9, 0x2b, 0x08, 0x81, 0xae,
+ 0x59, 0x43, 0x80, 0x92, 0x03, 0x13, 0x66, 0x60, 0x0f, 0xe0,
+ 0x66, 0xcb, 0x97, 0xcc,
+ }},
+ .rdata = { .size = 68, .data = (uint8_t []) {
+ 0x01, 0x00, 0x03, 0x0d,
+ 0xf2, 0xe0, 0xfb, 0x0b, 0x84, 0xc7, 0x4c, 0xcf, 0xf0, 0xee,
+ 0xe8, 0x6b, 0xc9, 0x14, 0x93, 0xa1, 0xe1, 0x3f, 0x8c, 0xa4,
+ 0xfb, 0xf3, 0xfa, 0x7c, 0xe7, 0x74, 0x57, 0xd0, 0xbe, 0x44,
+ 0xc2, 0xb6, 0x6b, 0x48, 0xb0, 0x6e, 0x6c, 0xb3, 0xe2, 0x07,
+ 0x0e, 0xe0, 0x6e, 0xf5, 0x0f, 0xe9, 0x2b, 0x08, 0x81, 0xae,
+ 0x59, 0x43, 0x80, 0x92, 0x03, 0x13, 0x66, 0x60, 0x0f, 0xe0,
+ 0x66, 0xcb, 0x97, 0xcc,
+ }},
+ .keytag = 5345,
+ .key_id = "47fd10011e76cc6741af586041eae5519465fc8d",
+ .ds_sha1 = { .size = 24, .data = (uint8_t []) {
+ 0x14, 0xe1, 0x0d, 0x01,
+ 0x95, 0x41, 0x03, 0xac, 0x7c, 0x43, 0x81, 0x0c, 0xe9, 0xf4,
+ 0x14, 0xe8, 0x0f, 0x30, 0xab, 0x1c, 0xbe, 0x49, 0xb2, 0x36,
+ }},
+ .ds_sha256 = { .size = 36, .data = (uint8_t []) {
+ 0x14, 0xe1, 0x0d, 0x02,
+ 0xba, 0xc2, 0x10, 0x70, 0x36, 0xe7, 0x35, 0xb5, 0x0f, 0x85,
+ 0x00, 0x6c, 0xe4, 0x09, 0xa1, 0x9a, 0x34, 0x38, 0xca, 0xb2,
+ 0x72, 0xe7, 0x07, 0x69, 0xeb, 0xda, 0x03, 0x22, 0x39, 0xa3,
+ 0xd0, 0xca,
+ }},
+ .ds_sha384 = { .size = 52, .data = (uint8_t []) {
+ 0x14, 0xe1, 0x0d, 0x04,
+ 0xa0, 0xac, 0x67, 0x90, 0x48, 0x38, 0x72, 0xbe, 0x72, 0xa2,
+ 0x58, 0x31, 0x42, 0x00, 0xa8, 0x8a, 0xb7, 0x5c, 0xdd, 0x70,
+ 0xf6, 0x6a, 0x18, 0xa0, 0x9f, 0x0f, 0x41, 0x4c, 0x07, 0x4d,
+ 0xf0, 0x98, 0x9f, 0xdb, 0x1d, 0xf0, 0xe6, 0x7d, 0x82, 0xd4,
+ 0x31, 0x2c, 0xda, 0x67, 0xb9, 0x3a, 0x76, 0xc1,
+ }},
+ .bit_size = 256,
+ .pem = { .size = 262, .data = (uint8_t []) {
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e,
+ 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b,
+ 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49,
+ 0x47, 0x55, 0x41, 0x67, 0x45, 0x41, 0x4d, 0x42, 0x4d, 0x47,
+ 0x42, 0x79, 0x71, 0x47, 0x53, 0x4d, 0x34, 0x39, 0x41, 0x67,
+ 0x45, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4d, 0x34, 0x39,
+ 0x41, 0x77, 0x45, 0x48, 0x42, 0x48, 0x6f, 0x77, 0x65, 0x41,
+ 0x49, 0x42, 0x41, 0x51, 0x51, 0x68, 0x41, 0x49, 0x73, 0x69,
+ 0x79, 0x44, 0x33, 0x5a, 0x4e, 0x77, 0x7a, 0x69, 0x4d, 0x56,
+ 0x5a, 0x70, 0x0a, 0x6b, 0x6d, 0x4a, 0x5a, 0x6b, 0x37, 0x4c,
+ 0x57, 0x37, 0x56, 0x44, 0x34, 0x6c, 0x5a, 0x52, 0x4d, 0x67,
+ 0x31, 0x2b, 0x4f, 0x71, 0x62, 0x4d, 0x67, 0x73, 0x44, 0x56,
+ 0x55, 0x6f, 0x41, 0x6f, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53,
+ 0x4d, 0x34, 0x39, 0x41, 0x77, 0x45, 0x48, 0x6f, 0x55, 0x51,
+ 0x44, 0x51, 0x67, 0x41, 0x45, 0x38, 0x75, 0x44, 0x37, 0x43,
+ 0x34, 0x54, 0x48, 0x54, 0x4d, 0x2f, 0x77, 0x0a, 0x37, 0x75,
+ 0x68, 0x72, 0x79, 0x52, 0x53, 0x54, 0x6f, 0x65, 0x45, 0x2f,
+ 0x6a, 0x4b, 0x54, 0x37, 0x38, 0x2f, 0x70, 0x38, 0x35, 0x33,
+ 0x52, 0x58, 0x30, 0x4c, 0x35, 0x45, 0x77, 0x72, 0x5a, 0x72,
+ 0x53, 0x4c, 0x42, 0x75, 0x62, 0x4c, 0x50, 0x69, 0x42, 0x77,
+ 0x37, 0x67, 0x62, 0x76, 0x55, 0x50, 0x36, 0x53, 0x73, 0x49,
+ 0x67, 0x61, 0x35, 0x5a, 0x51, 0x34, 0x43, 0x53, 0x41, 0x78,
+ 0x4e, 0x6d, 0x0a, 0x59, 0x41, 0x2f, 0x67, 0x5a, 0x73, 0x75,
+ 0x58, 0x7a, 0x41, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d,
+ 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41,
+ 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d,
+ 0x2d, 0x0a,
+ }},
+};
+
+/*
+ * Private-key-format: v1.2
+ * Algorithm: 15 (ED25519)
+ * PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=
+ *
+ * example.com. 3600 IN DNSKEY 256 3 15 (
+ * l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4= )
+ *
+ * example.com. 3600 IN DS 3612 15 2 (
+ * 3aa5ab37efce57f737fc1627013fee07bdf241bd10f3b1964ab55c78e79
+ * a304b )
+ *
+ * example.com. 3600 IN MX 10 mail.example.com.
+ *
+ * example.com. 3600 IN RRSIG MX 15 2 3600 (
+ * 1440021600 1438207200 3613 example.com. (
+ * oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3f
+ * x8A4M3e23mRZ9VrbpMngwcrqNAg== )
+ */
+
+static const key_parameters_t SAMPLE_ED25519_KEY = {
+ .name = (uint8_t *)"\x07""ed25519",
+ .flags = 256,
+ .protocol = 3,
+ .algorithm = 15,
+ .public_key = { .size = 32, .data = (uint8_t []) {
+ 0x97, 0x4d, 0x96, 0xa2, 0x2d, 0x22, 0x4b, 0xc0, 0x1a, 0xdb, 0x91, 0x50,
+ 0x91, 0x47, 0x7d, 0x44, 0xcc, 0xd9, 0x1c, 0x9a, 0x41, 0xa1, 0x14, 0x30,
+ 0x01, 0x01, 0x17, 0xd5, 0x2c, 0x59, 0x24, 0x0e,
+ }},
+ .rdata = { .size = 36, .data = (uint8_t []) {
+ 0x01, 0x00, 0x03, 0x0f,
+ 0x97, 0x4d, 0x96, 0xa2, 0x2d, 0x22, 0x4b, 0xc0, 0x1a, 0xdb, 0x91, 0x50,
+ 0x91, 0x47, 0x7d, 0x44, 0xcc, 0xd9, 0x1c, 0x9a, 0x41, 0xa1, 0x14, 0x30,
+ 0x01, 0x01, 0x17, 0xd5, 0x2c, 0x59, 0x24, 0x0e,
+ }},
+ .keytag = 3612,
+ .key_id = "bea75b99fb22ee1a68106ad6399e4acc43eb9929",
+ .ds_sha1 = { .size = 24, .data = (uint8_t []) {
+ 0x0e, 0x1c, 0x0f, 0x01,
+ 0x50, 0x12, 0x49, 0x72, 0x1e, 0x1f, 0x09, 0xa7, 0x9d, 0x30, 0xd5, 0xc6,
+ 0xc4, 0xdc, 0xa1, 0xdc, 0x1d, 0xa4, 0xed, 0x5d,
+ }},
+ .ds_sha256 = { .size = 36, .data = (uint8_t []) {
+ 0x0e, 0x1c, 0x0f, 0x02,
+ 0x1b, 0x1c, 0x87, 0x66, 0xb2, 0xa9, 0x65, 0x66, 0xff, 0x19, 0x6f, 0x77,
+ 0xc0, 0xc4, 0x19, 0x4a, 0xf8, 0x6a, 0xaa, 0x10, 0x9c, 0x53, 0x46, 0xff,
+ 0x60, 0x23, 0x1a, 0x27, 0xd2, 0xb0, 0x7a, 0xc0,
+ }},
+ .ds_sha384 = { .size = 52, .data = (uint8_t []) {
+ 0x0e, 0x1c, 0x0f, 0x04,
+ 0xd1, 0x18, 0x31, 0x15, 0x3a, 0xf4, 0x98, 0x5e, 0xfb, 0xd0, 0xae, 0x79,
+ 0x2c, 0x96, 0x7e, 0xb4, 0xaf, 0xf3, 0xc3, 0x54, 0x88, 0xdb, 0x95, 0xf7,
+ 0xe2, 0xf8, 0x5d, 0xce, 0xc7, 0x4a, 0xe8, 0xf5, 0x9f, 0x9a, 0x72, 0x64,
+ 0x17, 0x98, 0xc9, 0x1c, 0x67, 0xc6, 0x75, 0xdb, 0x1d, 0x71, 0x0c, 0x18,
+ }},
+ .bit_size = 256,
+ .pem = { .size = 119, .data = (uint8_t []) {
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x50,
+ 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d,
+ 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x43, 0x34, 0x43, 0x41, 0x51, 0x41, 0x77,
+ 0x42, 0x51, 0x59, 0x44, 0x4b, 0x32, 0x56, 0x77, 0x42, 0x43, 0x49, 0x45,
+ 0x49, 0x44, 0x67, 0x79, 0x4d, 0x6a, 0x59, 0x77, 0x4d, 0x7a, 0x67, 0x30,
+ 0x4e, 0x6a, 0x49, 0x34, 0x4d, 0x44, 0x67, 0x77, 0x4d, 0x54, 0x49, 0x79,
+ 0x4e, 0x6a, 0x51, 0x31, 0x4d, 0x54, 0x6b, 0x77, 0x4d, 0x6a, 0x41, 0x30,
+ 0x4d, 0x54, 0x51, 0x79, 0x4d, 0x6a, 0x59, 0x79, 0x0a, 0x2d, 0x2d, 0x2d,
+ 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54,
+ 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a
+ }},
+};
diff --git a/tests/libdnssec/test_binary.c b/tests/libdnssec/test_binary.c
new file mode 100644
index 0000000..cab3185
--- /dev/null
+++ b/tests/libdnssec/test_binary.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2018 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 <stdint.h>
+#include <string.h>
+#include <tap/basic.h>
+
+#include "binary.h"
+#include "error.h"
+
+typedef struct test_string {
+ const char *encoded;
+ size_t encoded_size;
+ const char *decoded;
+ size_t decoded_size;
+} test_string_t;
+
+static void test_base64(void)
+{
+ test_string_t data[] = {
+ { "", 0, "", 0 },
+ { "YQ==", 4, "a", 1 },
+ { "YWI=", 4, "ab", 2 },
+ { "YWJj", 4, "abc", 3 },
+ { "YWJjZA==", 8, "abcd", 4 },
+ { "YWJjZGU=", 8, "abcde", 5 },
+ { "YWJjZGVm", 8, "abcdef", 6 },
+ { NULL }
+ };
+
+ for (int i = 0; data[i].encoded != NULL; i++) {
+ test_string_t *ts = &data[i];
+
+ const dnssec_binary_t base64 = {
+ .size = ts->encoded_size,
+ .data = (uint8_t *) ts->encoded
+ };
+
+ dnssec_binary_t binary = { 0 };
+
+ int r = dnssec_binary_from_base64(&base64, &binary);
+ ok(r == DNSSEC_EOK &&
+ binary.size == ts->decoded_size &&
+ (binary.size == 0 || memcmp(binary.data, ts->decoded, binary.size) == 0),
+ "dnssec_binary_from_base64() for '%s'", ts->encoded);
+
+ dnssec_binary_t encoded = { 0 };
+ r = dnssec_binary_to_base64(&binary, &encoded);
+ ok(r == DNSSEC_EOK &&
+ encoded.size == ts->encoded_size &&
+ memcmp(encoded.data, ts->encoded, encoded.size) == 0,
+ "dnssec_binary_to_base64() for '%s'", ts->encoded);
+
+ dnssec_binary_free(&binary);
+ dnssec_binary_free(&encoded);
+ }
+}
+
+static void test_dup(void)
+{
+ dnssec_binary_t src = { .size = 5, .data = (uint8_t *) "ahoj" };
+ dnssec_binary_t dst = { 0 };
+
+ int r = dnssec_binary_dup(&src, &dst);
+ ok(r == DNSSEC_EOK &&
+ src.size == dst.size && memcmp(src.data, dst.data, src.size) == 0,
+ "dnssec_binary_dup()");
+
+ dnssec_binary_free(&dst);
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ test_base64();
+ test_dup();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_crypto.c b/tests/libdnssec/test_crypto.c
new file mode 100644
index 0000000..617637b
--- /dev/null
+++ b/tests/libdnssec/test_crypto.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+
+#include "crypto.h"
+
+int main(void)
+{
+ plan_lazy();
+
+ // not much we can test
+
+ dnssec_crypto_init();
+ ok(1, "dnssec_crypto_init() didn't crash");
+
+ dnssec_crypto_reinit();
+ ok(1, "dnssec_crypto_reinit() didn't crash");
+
+ dnssec_crypto_cleanup();
+ ok(1, "dnssec_crypto_cleanup() didn't crash");
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_key.c b/tests/libdnssec/test_key.c
new file mode 100644
index 0000000..0a73739
--- /dev/null
+++ b/tests/libdnssec/test_key.c
@@ -0,0 +1,212 @@
+/* Copyright (C) 2018 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 <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"); \
+ int 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, &params->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, &params->public_key);
+ ok(r == DNSSEC_EOK, "set public key (succeeds)");
+
+ r = dnssec_key_set_pubkey(key, &params->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, &params->rdata) == 0,
+ "get RDATA");
+
+ check_key_tag(key, params);
+
+ // create from RDATA
+
+ dnssec_key_clear(key);
+ r = dnssec_key_set_rdata(key, &params->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, &params->rdata);
+ ok(r == DNSSEC_EOK, "set RDATA");
+
+ r = dnssec_key_load_pkcs8(key, &params->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, &params->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, &params->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
+ { 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;
+}
diff --git a/tests/libdnssec/test_key_algorithm.c b/tests/libdnssec/test_key_algorithm.c
new file mode 100644
index 0000000..edffbaa
--- /dev/null
+++ b/tests/libdnssec/test_key_algorithm.c
@@ -0,0 +1,84 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+
+#include "error.h"
+#include "key.h"
+
+static void ok_range(dnssec_key_algorithm_t algo,
+ unsigned exp_min, unsigned exp_max,
+ const char *name)
+{
+ unsigned min = 0, max = 0;
+ int r = dnssec_algorithm_key_size_range(algo, &min, &max);
+ ok(r == DNSSEC_EOK && min == exp_min && max == exp_max,
+ "dnssec_algorithm_key_size_range() for %s", name);
+}
+
+static void null_range(void)
+{
+ dnssec_key_algorithm_t algo = DNSSEC_KEY_ALGORITHM_RSA_SHA256;
+ unsigned val = 0;
+ int r;
+
+ r = dnssec_algorithm_key_size_range(algo, NULL, NULL);
+ ok(r == DNSSEC_EINVAL, "dnssec_algorithm_key_size_range() all null");
+ r = dnssec_algorithm_key_size_range(algo, &val, NULL);
+ ok(r == DNSSEC_EOK && val == 1024, "dnssec_algorithm_key_size_range() min only");
+ r = dnssec_algorithm_key_size_range(algo, NULL, &val);
+ ok(r == DNSSEC_EOK && val == 4096, "dnssec_algorithm_key_size_range() max only");
+}
+
+static void check_borders(void)
+{
+ dnssec_key_algorithm_t rsa = DNSSEC_KEY_ALGORITHM_RSA_SHA1;
+
+ ok(dnssec_algorithm_key_size_check(rsa, 1023) == false, "rsa 1023");
+ ok(dnssec_algorithm_key_size_check(rsa, 1024) == true, "rsa 1024");
+ ok(dnssec_algorithm_key_size_check(rsa, 1025) == true, "rsa 1025");
+ ok(dnssec_algorithm_key_size_check(rsa, 4095) == true, "rsa 4095");
+ ok(dnssec_algorithm_key_size_check(rsa, 4096) == true, "rsa 4096");
+ ok(dnssec_algorithm_key_size_check(rsa, 4097) == false, "rsa 4097");
+}
+
+static void check_defaults(void)
+{
+ is_int(2048, dnssec_algorithm_key_size_default(DNSSEC_KEY_ALGORITHM_RSA_SHA1_NSEC3), "rsa default");
+ is_int(256, dnssec_algorithm_key_size_default(DNSSEC_KEY_ALGORITHM_ECDSA_P256_SHA256), "ecc default");
+#ifdef HAVE_ED25519
+ is_int(256, dnssec_algorithm_key_size_default(DNSSEC_KEY_ALGORITHM_ED25519), "ed25519 default");
+#endif
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ // ranges
+ ok_range(DNSSEC_KEY_ALGORITHM_RSA_SHA512, 1024, 4096, "RSA/SHA256");
+ ok_range(DNSSEC_KEY_ALGORITHM_ECDSA_P384_SHA384, 384, 384, "ECDSA/SHA384");
+#ifdef HAVE_ED25519
+ ok_range(DNSSEC_KEY_ALGORITHM_ED25519, 256, 256, "ED25519");
+#endif
+ null_range();
+
+ check_borders();
+
+ check_defaults();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_key_ds.c b/tests/libdnssec/test_key_ds.c
new file mode 100644
index 0000000..25d7c9d
--- /dev/null
+++ b/tests/libdnssec/test_key_ds.c
@@ -0,0 +1,116 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+
+#include <stddef.h>
+#include <string.h>
+
+#include "libdnssec/crypto.h"
+#include "libdnssec/error.h"
+#include "libdnssec/key.h"
+#include "sample_keys.h"
+
+static void test_key(const char *name, const struct key_parameters *params)
+{
+ dnssec_key_t *key = NULL;
+
+ dnssec_key_new(&key);
+ dnssec_key_set_dname(key, params->name);
+ dnssec_key_set_rdata(key, &params->rdata);
+
+ struct ds_type {
+ const char *name;
+ dnssec_key_digest_t digest;
+ size_t params_offset;
+ };
+
+ static const struct ds_type DS_TYPES[] = {
+ { "SHA-1", DNSSEC_KEY_DIGEST_SHA1, offsetof(typeof(*params), ds_sha1) },
+ { "SHA-256", DNSSEC_KEY_DIGEST_SHA256, offsetof(typeof(*params), ds_sha256) },
+ { "SHA-384", DNSSEC_KEY_DIGEST_SHA384, offsetof(typeof(*params), ds_sha384) },
+ { NULL }
+ };
+
+ for (const struct ds_type *dt = DS_TYPES; dt->name != NULL; dt++) {
+ dnssec_binary_t ds = { 0 };
+ int r = dnssec_key_create_ds(key, dt->digest, &ds);
+
+ const dnssec_binary_t *expect = (void *)params + dt->params_offset;
+
+ ok(r == DNSSEC_EOK &&
+ ds.size == expect->size &&
+ memcmp(ds.data, expect->data, ds.size) == 0,
+ "dnssec_key_create_ds() for %s/%s", name, dt->name);
+
+ dnssec_binary_free(&ds);
+ }
+
+ dnssec_key_free(key);
+}
+
+static void test_errors(const struct key_parameters *params)
+{
+ dnssec_key_t *key = NULL;
+ dnssec_binary_t ds = { 0 };
+
+ int r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, &ds);
+ is_int(DNSSEC_EINVAL, r, "dnssec_key_create_ds() no key");
+ dnssec_binary_free(&ds);
+
+ dnssec_key_new(&key);
+ r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, &ds);
+ is_int(DNSSEC_INVALID_KEY_NAME, r, "dnssec_key_create_ds() no key name");
+
+ dnssec_key_set_dname(key, params->name);
+ r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, &ds);
+ is_int(DNSSEC_INVALID_PUBLIC_KEY, r, "dnssec_key_create_ds() no public key");
+
+ dnssec_key_set_rdata(key, &params->rdata);
+ r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, NULL);
+ is_int(DNSSEC_EINVAL, r, "dnssec_key_create_ds() no RDATA buffer");
+
+ r = dnssec_key_create_ds(key, 3, &ds);
+ is_int(DNSSEC_INVALID_DS_ALGORITHM, r, "dnssec_key_create_ds() unsupported algorithm");
+
+ r = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA1, &ds);
+ is_int(DNSSEC_EOK, r, "dnssec_key_create_ds() valid parameters");
+
+ dnssec_binary_free(&ds);
+ dnssec_key_free(key);
+}
+
+int main(int argc, char *argv[])
+{
+ plan_lazy();
+
+ dnssec_crypto_init();
+
+ test_key("RSA", &SAMPLE_RSA_KEY);
+ test_key("ECDSA", &SAMPLE_ECDSA_KEY);
+#ifdef HAVE_ED25519
+ test_key("ED25519", &SAMPLE_ED25519_KEY);
+#endif
+
+ test_errors(&SAMPLE_ECDSA_KEY);
+#ifdef HAVE_ED25519
+ test_errors(&SAMPLE_ED25519_KEY);
+#endif
+
+ dnssec_crypto_cleanup();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_keyid.c b/tests/libdnssec/test_keyid.c
new file mode 100644
index 0000000..15bfe98
--- /dev/null
+++ b/tests/libdnssec/test_keyid.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "error.h"
+#include "keyid.h"
+
+static void test_keyid_is_valid_run(const char *param, bool should_ok)
+{
+ ok(dnssec_keyid_is_valid(param) == should_ok,
+ "dnssec_keyid_is_valid(\"%s\")", param);
+}
+
+static void test_keyid_is_valid(void)
+{
+ test_keyid_is_valid_run(NULL, false);
+ test_keyid_is_valid_run("3e90c5cb1fad5f8512da2028fda3808e749d3bf", false);
+ test_keyid_is_valid_run("9aa6dAAC706fb6fe4aceb327452a7b5FEA457544", true);
+ test_keyid_is_valid_run("eac45c184b7f476472c16d5b0c4f0c52389848001", false);
+ test_keyid_is_valid_run("9aa6daac706fb6fe4aceb32g452a7b5fea457544", false);
+}
+
+static void test_keyid_normalize(void)
+{
+ char id[] = "3711927404f64CE7df88253d763e442CE39f9B5c";
+ const char *id_norm = "3711927404f64ce7df88253d763e442ce39f9b5c";
+
+ dnssec_keyid_normalize(id);
+ ok(strcmp(id, id_norm) == 0, "dnssec_keyid_normalize()");
+}
+
+static void test_keyid_copy(void)
+{
+ const char *id = "21669f1eca6418f9aBBBf0007e6f73463d467424";
+ const char *expected = "21669f1eca6418f9abbbf0007e6f73463d467424";
+
+ char *copy = dnssec_keyid_copy(id);
+ ok(copy && strcmp(copy, expected) == 0, "dnssec_keyid_copy()");
+
+ free(copy);
+}
+
+static void test_keyid_equal(void)
+{
+ const char *id = "dd63237d4a07867de715499690c9ad12990519f0";
+ const char *id_case = "dd63237d4a07867de715499690C9AD12990519F0";
+ const char *id_diff = "dd63237d4a07867de715499690c9ad12990519f1";
+
+ ok(dnssec_keyid_equal(id, NULL) == false, "dnssec_keyid_equal(id, NULL)");
+ ok(dnssec_keyid_equal(id, id) == true, "dnssec_keyid_equal(id, id)");
+ ok(dnssec_keyid_equal(id, id_case) == true, "dnssec_keyid_equal(id, ID)");
+ ok(dnssec_keyid_equal(id, id_diff) == false, "dnssec_keyid_equal(ida, idb)");
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ test_keyid_is_valid();
+ test_keyid_normalize();
+ test_keyid_copy();
+ test_keyid_equal();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_keystore_pkcs11.c b/tests/libdnssec/test_keystore_pkcs11.c
new file mode 100644
index 0000000..c83eb82
--- /dev/null
+++ b/tests/libdnssec/test_keystore_pkcs11.c
@@ -0,0 +1,484 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+#include <tap/files.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "libdnssec/crypto.h"
+#include "libdnssec/error.h"
+#include "libdnssec/keystore.h"
+#include "libdnssec/sign.h"
+
+#include "sample_keys.h"
+
+#define ENV_SOFTHSM_DSO "KNOT_SOFTHSM2_DSO"
+#define ENV_SOFTHSM_UTIL "KNOT_SOFTHSM2_UTIL"
+
+#define SOFTHSM_DSO "libsofthsm2.so"
+#define SOFTHSM_CONF "softhsm2.conf"
+#define SOFTHSM_CONF_ENV "SOFTHSM2_CONF"
+#define SOFTHSM_UTIL "softhsm2-util"
+
+#define TOKEN_LABEL "libdnssec-test"
+#define TOKEN_PIN "1234"
+#define TOKEN_SOPIN "123456"
+
+#define EXIT_EXEC_FAILED 127
+
+#ifndef LIBDIR
+# include <bits/wordsize.h>
+# if __WORDSIZE == 32
+# define LIBDIR "/usr/lib32"
+# elif __WORDSIZE == 64
+# define LIBDIR "/usr/lib64"
+# endif
+#endif
+
+#define MSG_SOFTWARE "soft -"
+#define MSG_PKCS11 "p11 -"
+
+/*!
+ * Get SoftHSM DSO path.
+ */
+static char *libsofthsm_dso(void)
+{
+ // prefer environment variable
+
+ const char *env = getenv(ENV_SOFTHSM_DSO);
+ if (env) {
+ return (env[0] != '\0' ? strdup(env) : NULL);
+ }
+
+ // autodetection
+
+ static const char *paths[] = {
+ LIBDIR "/pkcs11/" SOFTHSM_DSO,
+ LIBDIR "/softhsm/" SOFTHSM_DSO,
+ LIBDIR "/" SOFTHSM_DSO,
+ NULL
+ };
+
+ for (const char **path_ptr = paths; *path_ptr; path_ptr += 1) {
+ const char *path = *path_ptr;
+ if (access(path, R_OK|X_OK) == 0) {
+ return strdup(path);
+ }
+ }
+
+ return NULL;
+}
+
+/*!
+ * Get SoftHSM utility path.
+ */
+static char *libsofthsm_util(void)
+{
+ // prefer environment variable
+
+ const char *env = getenv(ENV_SOFTHSM_UTIL);
+ if (env && env[0] != '\0') {
+ return strdup(env);
+ }
+
+ // fallback, will rely on PATH
+
+ return strdup(SOFTHSM_UTIL);
+}
+
+/*!
+ * Path to temporary token data.
+ */
+static char *token_path = NULL;
+
+/*!
+ * Cleanup token test data.
+ */
+static void token_cleanup(void)
+{
+ test_rm_rf(token_path);
+ free(token_path);
+}
+
+/*!
+ * Initialize token using the support tool.
+ */
+static bool token_init_exec(const char *util)
+{
+ pid_t child = fork();
+ if (child == -1) {
+ return false;
+ }
+
+ // child
+
+ if (child == 0) {
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+
+ const char *basename = strrchr(util, '/');
+ if (basename) {
+ basename += 1;
+ } else {
+ basename = util;
+ }
+
+ execlp(util, basename,
+ "--init-token", "--slot=0", "--label=" TOKEN_LABEL,
+ "--pin=" TOKEN_PIN, "--so-pin=" TOKEN_SOPIN,
+ NULL);
+
+ exit(EXIT_EXEC_FAILED);
+ }
+
+ // parent
+
+ int status = 0;
+ if (waitpid(child, &status, 0) == -1) {
+ return false;
+ }
+
+ int exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
+ if (exit_code != 0) {
+ diag("%s exit status %d", util, exit_code);
+ if (exit_code == EXIT_EXEC_FAILED) {
+ diag("set %s environment variable to adjust the path",
+ ENV_SOFTHSM_UTIL);
+ }
+ }
+
+ return exit_code == 0;
+}
+
+/*!
+ * Initialize environment and token for testing.
+ */
+static bool token_init(void)
+{
+ token_path = test_mkdtemp();
+ if (!token_path) {
+ return false;
+ }
+
+ // generate configuration file for unit test
+
+ char config[4096] = { 0 };
+ int r = snprintf(config, sizeof(config), "%s/%s", token_path, SOFTHSM_CONF);
+ if (r <= 0 || r >= sizeof(config)) {
+ return false;
+ }
+
+ FILE *file = fopen(config, "w");
+ if (!file) {
+ return false;
+ }
+
+ fprintf(file, "directories.tokendir = %s\n", token_path);
+ fprintf(file, "objectstore.backend = file\n");
+ fprintf(file, "log.debug = INFO\n");
+
+ fclose(file);
+
+ // update environment to use the config
+
+ if (setenv(SOFTHSM_CONF_ENV, config, 1) != 0) {
+ return false;
+ }
+
+ // initialize token
+
+ char *util = libsofthsm_util();
+ if (!util) {
+ return false;
+ }
+
+ bool inited = token_init_exec(util);
+ free(util);
+
+ return inited;
+}
+
+static void create_dnskeys(dnssec_keystore_t *keystore,
+ dnssec_key_algorithm_t algorithm, const char *id,
+ dnssec_key_t **p11_key_ptr, dnssec_key_t **soft_key_ptr)
+{
+ int r;
+
+ // construct PKCS #11 privkey-pubkey key pair
+
+ dnssec_key_t *p11_key = NULL;
+ r = dnssec_key_new(&p11_key);
+ ok(r == DNSSEC_EOK && p11_key != NULL, MSG_PKCS11 " dnssec_key_new()");
+
+ r = dnssec_key_set_algorithm(p11_key, algorithm);
+ ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_set_key_algorithm()");
+
+ r = dnssec_key_import_keystore(p11_key, keystore, id);
+ ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_key_import_keystore()");
+
+ // construct software public key
+
+ dnssec_key_t *soft_key = NULL;
+ r = dnssec_key_new(&soft_key);
+ ok(r == DNSSEC_EOK && soft_key != NULL, MSG_SOFTWARE " dnssec_key_new()");
+
+ dnssec_binary_t rdata = { 0 };
+ dnssec_key_get_rdata(p11_key, &rdata);
+ r = dnssec_key_set_rdata(soft_key, &rdata);
+ ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_key_set_rdata()");
+
+ *p11_key_ptr = p11_key;
+ *soft_key_ptr = soft_key;
+}
+
+static void test_sign(dnssec_key_t *p11_key, dnssec_key_t *soft_key)
+{
+ int r;
+
+ static const dnssec_binary_t input = {
+ .data = (uint8_t *)"So Long, and Thanks for All the Fish.",
+ .size = 37
+ };
+
+ dnssec_binary_t sign = { 0 };
+
+ // usage constraints
+
+ ok(dnssec_key_can_sign(p11_key), MSG_PKCS11 " dnssec_key_can_sign()");
+ ok(dnssec_key_can_verify(p11_key), MSG_PKCS11 " dnssec_key_can_verify()");
+
+ ok(!dnssec_key_can_sign(soft_key), MSG_SOFTWARE " dnssec_key_can_sign()");
+ ok(dnssec_key_can_verify(soft_key), MSG_SOFTWARE " dnssec_key_can_verify()");
+
+ // PKCS #11 key signature
+
+ dnssec_sign_ctx_t *ctx = NULL;
+ r = dnssec_sign_new(&ctx, p11_key);
+ ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_init() ");
+
+ r = dnssec_sign_add(ctx, &input);
+ ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_add()");
+
+ r = dnssec_sign_write(ctx, &sign);
+ ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_write()");
+
+ // PKCS #11 key verification
+
+ r = dnssec_sign_init(ctx);
+ ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_init()");
+
+ r = dnssec_sign_add(ctx, &input);
+ ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_add()");
+
+ r = dnssec_sign_verify(ctx, &sign);
+ ok(r == DNSSEC_EOK, MSG_PKCS11 " dnssec_sign_verify()");
+
+ // software verification
+
+ dnssec_sign_free(ctx);
+ ctx = NULL;
+
+ r = dnssec_sign_new(&ctx, soft_key);
+ ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_init()");
+
+ r = dnssec_sign_add(ctx, &input);
+ ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_add()");
+
+ r = dnssec_sign_verify(ctx, &sign);
+ ok(r == DNSSEC_EOK, MSG_SOFTWARE " dnssec_sign_verify()");
+
+ dnssec_binary_free(&sign);
+ dnssec_sign_free(ctx);
+}
+
+static void test_key_use(dnssec_keystore_t *store,
+ dnssec_key_algorithm_t algorithm,
+ const char *keyid)
+{
+ dnssec_key_t *p11_key = NULL;
+ dnssec_key_t *soft_key = NULL;
+
+ create_dnskeys(store, algorithm, keyid, &p11_key, &soft_key);
+ test_sign(p11_key, soft_key);
+
+ dnssec_key_free(p11_key);
+ dnssec_key_free(soft_key);
+}
+
+static void test_algorithm(dnssec_keystore_t *store,
+ const key_parameters_t *params)
+{
+ char *id_generate = NULL;
+ char *id_import = NULL;
+
+ int r;
+
+ diag("algorithm %d, generated key", params->algorithm);
+
+ r = dnssec_keystore_generate_key(store, params->algorithm, params->bit_size, &id_generate);
+ ok(r == DNSSEC_EOK && id_generate != NULL, "dnssec_keystore_generate_key()");
+ test_key_use(store, params->algorithm, id_generate);
+
+ diag("algorithm %d, imported key", params->algorithm);
+
+ r = dnssec_keystore_import(store, &params->pem, &id_import);
+ ok(r == DNSSEC_EOK && id_import != NULL, "dnssec_keystore_import()");
+ test_key_use(store, params->algorithm, id_import);
+
+ free(id_generate);
+ free(id_import);
+}
+
+static void test_key_listing(dnssec_keystore_t *store,
+ const key_parameters_t **key_params, int count)
+{
+ dnssec_list_t *keys = NULL;
+ int r = dnssec_keystore_list_keys(store, &keys);
+ ok(r == DNSSEC_EOK && dnssec_list_size(keys) == count * 2,
+ "dnssec_keystore_list_keys(), two keys per algorithm");
+
+ bool imported_found[count];
+ for (int i = 0; i < count; i++) {
+ imported_found[i] = false;
+ }
+
+ dnssec_list_foreach(item, keys) {
+ const char *id = dnssec_item_get(item);
+ for (int i = 0; i < count; i++) {
+ if (strcmp(id, key_params[i]->key_id) == 0) {
+ imported_found[i] = true;
+ break;
+ }
+ }
+ }
+
+ int imported_count = 0;
+ for (int i = 0; i < count; i++) {
+ imported_count += imported_found[i] ? 1 : 0;
+ }
+
+ ok(imported_count == count, "list contains key for all algorithms");
+ dnssec_list_free_full(keys, NULL, NULL);
+
+ // key removal
+
+ assert(count > 0);
+ const key_parameters_t *key_remove = key_params[0];
+
+ r = dnssec_keystore_remove_key(store, key_remove->key_id);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_remove_key");
+
+ keys = NULL;
+ r = dnssec_keystore_list_keys(store, &keys);
+ ok(r == DNSSEC_EOK && dnssec_list_size(keys) == count * 2 - 1,
+ "dnssec_keystore_list_keys(), one less key than before");
+
+ bool removed_found = false;
+ dnssec_list_foreach(item, keys) {
+ const char *id = dnssec_item_get(item);
+ if (strcmp(id, key_remove->key_id) == 0) {
+ removed_found = true;
+ break;
+ }
+ }
+
+ ok(!removed_found, "dnssec_keystore_list_keys(), removed key not found");
+
+ dnssec_list_free_full(keys, NULL, NULL);
+}
+
+int main(int argc, char *argv[])
+{
+ plan_lazy();
+
+ dnssec_crypto_init();
+
+ // PKCS #11 initialization
+
+ dnssec_keystore_t *store = NULL;
+ int r = dnssec_keystore_init_pkcs11(&store);
+ if (r == DNSSEC_NOT_IMPLEMENTED_ERROR) {
+ skip_all("not supported");
+ goto done;
+ }
+ ok(r == DNSSEC_EOK && store, "dnssec_keystore_init_pkcs11()");
+
+ char *dso_name = libsofthsm_dso();
+ if (!dso_name) {
+ skip_all("%s not found, set %s environment variable",
+ SOFTHSM_DSO, ENV_SOFTHSM_DSO);
+ goto done;
+ }
+ ok(dso_name != NULL, "find token DSO");
+
+ bool success = token_init();
+ if (!success) {
+ skip_all("failed to configure and initialize the token");
+ goto done;
+ }
+ ok(success, "initialize the token");
+
+ char config[4096] = { 0 };
+ r = snprintf(config, sizeof(config), "pkcs11:token=%s;pin-value=%s %s",
+ TOKEN_LABEL, TOKEN_PIN, dso_name);
+ free(dso_name);
+ ok(r > 0 && r < sizeof(config), "build configuration");
+
+ // key store access
+
+ r = dnssec_keystore_init(store, config);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_init()");
+
+ r = dnssec_keystore_open(store, config);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_open()");
+
+ dnssec_list_t *keys = NULL;
+ r = dnssec_keystore_list_keys(store, &keys);
+ ok(r == DNSSEC_EOK && dnssec_list_size(keys) == 0, "dnssec_keystore_list_keys(), empty");
+ dnssec_list_free_full(keys, NULL, NULL);
+
+ // key manipulation
+
+ static const int KEYS_COUNT = 2;
+ static const key_parameters_t *KEYS[] = {
+ &SAMPLE_RSA_KEY,
+ &SAMPLE_ECDSA_KEY,
+ };
+ assert(KEYS_COUNT == sizeof(KEYS) / sizeof(*KEYS));
+
+ for (int i = 0; i < KEYS_COUNT; i++) {
+ test_algorithm(store, KEYS[i]);
+ }
+
+ test_key_listing(store, KEYS, KEYS_COUNT);
+
+ r = dnssec_keystore_close(store);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_close()");
+done:
+ dnssec_keystore_deinit(store);
+ dnssec_crypto_cleanup();
+ token_cleanup();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_keystore_pkcs8.c b/tests/libdnssec/test_keystore_pkcs8.c
new file mode 100644
index 0000000..b7c74e7
--- /dev/null
+++ b/tests/libdnssec/test_keystore_pkcs8.c
@@ -0,0 +1,219 @@
+/* Copyright (C) 2018 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 <string.h>
+#include <tap/basic.h>
+#include <stdbool.h>
+
+#include "binary.h"
+#include "crypto.h"
+#include "error.h"
+#include "key.h"
+#include "keyid.h"
+#include "keystore.h"
+
+/* -- mock key store ------------------------------------------------------- */
+
+static void *test_handle = (void *)0x42;
+
+static bool test_handle_new_ok = false;
+static int test_handle_new(void **handle_ptr)
+{
+ if (handle_ptr) {
+ *handle_ptr = test_handle;
+ test_handle_new_ok = true;
+ }
+
+ return DNSSEC_EOK;
+}
+
+static bool test_handle_free_ok = false;
+static int test_handle_free(void *handle)
+{
+ test_handle_free_ok = (handle == test_handle);
+
+ return DNSSEC_EOK;
+}
+
+static bool test_init_ok = false;
+static int test_init(void *handle, const char *config)
+{
+ test_init_ok = (handle == test_handle && config && strcmp(config, "init config") == 0);
+
+ return DNSSEC_EOK;
+}
+
+static bool test_open_ok = false;
+static int test_open(void *handle, const char *config)
+{
+ test_open_ok = (handle == test_handle && config && strcmp(config, "open config") == 0);
+
+ return DNSSEC_EOK;
+}
+
+static bool test_close_ok = false;
+static int test_close(void *handle)
+{
+ test_close_ok = (handle == test_handle);
+
+ return DNSSEC_EOK;
+}
+
+static bool test_write_ok = false;
+static char *test_write_id = NULL;
+static dnssec_binary_t test_write_pem = { 0 };
+static int test_write(void *handle, const char *id, const dnssec_binary_t *pem)
+{
+ if (handle == test_handle && id && pem) {
+ test_write_ok = true;
+ test_write_id = dnssec_keyid_copy(id);
+ dnssec_binary_dup(pem, &test_write_pem);
+ }
+
+ return DNSSEC_EOK;
+}
+
+static bool test_read_ok = false;
+static char *test_read_id = NULL;
+static int test_read(void *handle, const char *id, dnssec_binary_t *pem)
+{
+ if (handle == test_handle && id && pem) {
+ test_read_ok = true;
+ test_read_id = dnssec_keyid_copy(id);
+ dnssec_binary_dup(&test_write_pem, pem);
+ }
+
+ return DNSSEC_EOK;
+}
+
+static bool test_list_ok = false;
+static int test_list(void *handle, dnssec_list_t **list_ptr)
+{
+ if (handle == test_handle && list_ptr) {
+ test_list_ok = true;
+ }
+
+ if (list_ptr) {
+ *list_ptr = dnssec_list_new();
+ }
+
+ return DNSSEC_EOK;
+}
+
+static bool test_remove_ok = false;
+static char *test_remove_id = NULL;
+static int test_remove(void *handle, const char *id)
+{
+ test_remove_ok = (handle == test_handle && id);
+ test_remove_id = dnssec_keyid_copy(id);
+
+ return DNSSEC_EOK;
+}
+
+static const dnssec_keystore_pkcs8_functions_t test_store = {
+ .handle_new = test_handle_new,
+ .handle_free = test_handle_free,
+ .init = test_init,
+ .open = test_open,
+ .close = test_close,
+ .read = test_read,
+ .write = test_write,
+ .list = test_list,
+ .remove = test_remove,
+};
+
+/* -- test plan ------------------------------------------------------------ */
+
+int main(void)
+{
+ plan_lazy();
+
+ dnssec_crypto_init();
+
+ int r = 0;
+
+ // create/init/open
+
+ dnssec_keystore_t *store = NULL;
+ r = dnssec_keystore_init_pkcs8_custom(&store, &test_store);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_init_pkcs8_custom()");
+ ok(test_handle_new_ok, "test_handle_new_ok() called");
+
+ r = dnssec_keystore_init(store, "init config");
+ ok(r == DNSSEC_EOK, "dnssec_keystore_init()");
+ ok(test_init_ok, "test_init() called");
+
+ r = dnssec_keystore_open(store, "open config");
+ ok(r == DNSSEC_EOK && test_open_ok, "dnssec_keystore_open()");
+ ok(test_open_ok, "test_open() called");
+
+ // write
+
+ char *gen_id = NULL;
+ r = dnssec_keystore_generate_key(store, DNSSEC_KEY_ALGORITHM_RSA_SHA256,
+ 1024, &gen_id);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_generate_key()");
+ ok(test_write_ok, "test_write() called");
+ is_string(gen_id, test_write_id, "test_write() correct key ID");
+
+ // read
+
+ dnssec_key_t *key = NULL;
+ dnssec_key_new(&key);
+ dnssec_key_set_algorithm(key, DNSSEC_KEY_ALGORITHM_RSA_SHA256);
+ r = dnssec_key_import_keystore(key, store, gen_id);
+ ok(r == DNSSEC_EOK, "dnssec_key_import_keystore()");
+ ok(test_read_ok, "test_read() called");
+ is_string(gen_id, test_read_id, "test_read() correct key ID");
+ dnssec_key_free(key);
+
+ // remove
+
+ r = dnssec_keystore_remove_key(store, gen_id);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_remove_key()");
+ ok(test_remove_ok, "test_remove() called");
+ is_string(gen_id, test_remove_id, "test_remove() correct key ID");
+
+ // close
+
+ r = dnssec_keystore_close(store);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_clse()");
+ ok(test_close_ok, "test_close() called");
+
+ // list
+
+ dnssec_list_t *list = NULL;
+ r = dnssec_keystore_list_keys(store, &list);
+ ok(r == DNSSEC_EOK, "dnssec_keystore_list_keys()");
+ ok(test_list_ok, "test_list() called");
+ ok(list && dnssec_list_size(list) == 0, "dnssec_list() correct output");
+ dnssec_list_free(list);
+
+ // cleanup
+
+ dnssec_keystore_deinit(store);
+ ok(test_handle_free_ok, "test_handle_free() called");
+
+ dnssec_crypto_cleanup();
+
+ free(gen_id);
+ free(test_write_id);
+ dnssec_binary_free(&test_write_pem);
+ free(test_read_id);
+ free(test_remove_id);
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_keystore_pkcs8_dir.c b/tests/libdnssec/test_keystore_pkcs8_dir.c
new file mode 100644
index 0000000..124b8c3
--- /dev/null
+++ b/tests/libdnssec/test_keystore_pkcs8_dir.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2018 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 <stdio.h>
+#include <string.h>
+#include <tap/basic.h>
+#include <unistd.h>
+
+#include "binary.h"
+#include "error.h"
+#include "key.h"
+#include "keystore.h"
+#include "keystore/pkcs8_dir.c"
+
+typedef struct test_pem {
+ const char *id;
+ dnssec_binary_t data;
+} test_pem_t;
+
+extern const dnssec_keystore_pkcs8_functions_t PKCS8_DIR_FUNCTIONS;
+
+const test_pem_t TEST_PEM_A = {
+ "7b0c9f6a59b1c76b26ed93ea8684f300821eee41",
+ { .size = 5, .data = (uint8_t *)"hello" }
+};
+
+const test_pem_t TEST_PEM_B = {
+ "f4f3e73cf4ee605993c2ef2d790571ade827244c",
+ { .size = 4, .data = (uint8_t *)"knot" }
+};
+
+static void rm(const char *dir, const char *file)
+{
+ char buffer[4096] = { 0 };
+ int r = snprintf(buffer, 4096, "%s/%s", dir, file);
+ if (r < 0) {
+ ok(0, "rm");
+ return;
+ }
+
+ r = unlink(buffer);
+ ok(r == 0, "rm %s", buffer);
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ int r = 0;
+ void *handle = NULL;
+ dnssec_binary_t bin = { 0 };
+
+ char *dir = test_tmpdir();
+ if (!dir) {
+ return 1;
+ }
+
+ // create context
+
+ const dnssec_keystore_pkcs8_functions_t *func = &PKCS8_DIR_FUNCTIONS;
+
+ r = func->handle_new(&handle);
+ ok(r == DNSSEC_EOK && handle != NULL, "new handle");
+
+ r = func->init(handle, dir);
+ ok(r == DNSSEC_EOK, "init");
+
+ r = func->open(handle, dir);
+ ok(r == DNSSEC_EOK, "open");
+
+ // non-existent reads
+
+ r = func->read(handle, TEST_PEM_A.id, &bin);
+ ok(r == DNSSEC_ENOENT && bin.size == 0, "read non-existent");
+
+ // writing new content
+
+ r = func->write(handle, TEST_PEM_A.id, &TEST_PEM_A.data);
+ ok(r == DNSSEC_EOK, "write A");
+
+ r = func->write(handle, TEST_PEM_B.id, &TEST_PEM_B.data);
+ ok(r == DNSSEC_EOK, "write B");
+
+ r = func->write(handle, TEST_PEM_A.id, &TEST_PEM_A.data);
+ ok(r == DNSSEC_EOK, "write A (duplicate)");
+
+ // content listing
+
+ dnssec_list_t *list = NULL;
+ r = func->list(handle, &list);
+ ok(r == DNSSEC_EOK, "get list");
+ is_int(2, dnssec_list_size(list), "list size");
+
+ bool found_a = false;
+ bool found_b = false;
+ dnssec_list_foreach(item, list) {
+ char *id = dnssec_item_get(item);
+ if (id && strcmp(TEST_PEM_A.id, id) == 0) { found_a = true; }
+ if (id && strcmp(TEST_PEM_B.id, id) == 0) { found_b = true; }
+ }
+ ok(found_a && found_b, "list content");
+
+ dnssec_list_free_full(list, NULL, NULL);
+
+ // reading existing content
+
+ r = func->read(handle, TEST_PEM_A.id, &bin);
+ ok(r == DNSSEC_EOK && dnssec_binary_cmp(&TEST_PEM_A.data, &bin) == 0,
+ "read A");
+ dnssec_binary_free(&bin);
+
+ r = func->read(handle, TEST_PEM_B.id, &bin);
+ ok(r == DNSSEC_EOK && dnssec_binary_cmp(&TEST_PEM_B.data, &bin) == 0,
+ "read B");
+ dnssec_binary_free(&bin);
+
+ // content removal
+
+ r = func->remove(handle, TEST_PEM_A.id);
+ ok(r == DNSSEC_EOK, "remove A");
+
+ r = func->read(handle, TEST_PEM_A.id, &bin);
+ ok(r == DNSSEC_ENOENT && bin.size == 0, "read removed");
+
+ // cleanup
+
+ r = func->close(handle);
+ ok(r == DNSSEC_EOK, "close");
+
+ r = func->handle_free(handle);
+ ok(r == DNSSEC_EOK, "free handle");
+
+ rm(dir, "f4f3e73cf4ee605993c2ef2d790571ade827244c.pem");
+
+ test_tmpdir_free(dir);
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_keytag.c b/tests/libdnssec/test_keytag.c
new file mode 100644
index 0000000..f71426e
--- /dev/null
+++ b/tests/libdnssec/test_keytag.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+#include <stdint.h>
+
+#include "binary.h"
+#include "error.h"
+#include "keytag.h"
+
+int main(void)
+{
+ plan_lazy();
+
+ const dnssec_binary_t rsa_md5_rdata = { .size = 72, .data = (uint8_t []) {
+ 0x01, 0x00, 0x03, 0x01,
+ 0x03, 0x01, 0x00, 0x01, 0xa6, 0x83, 0x41, 0x42, 0x58, 0x1b,
+ 0xc2, 0xa7, 0xc7, 0xd5, 0xef, 0xb5, 0x6c, 0xec, 0x34, 0xc5,
+ 0xc9, 0x5e, 0x84, 0xa8, 0x35, 0x4a, 0xe0, 0xc2, 0x70, 0xf5,
+ 0x40, 0xe9, 0x92, 0x06, 0x70, 0x45, 0x88, 0xd3, 0x86, 0xcf,
+ 0xf5, 0xff, 0x83, 0x08, 0x06, 0x98, 0xe7, 0x8a, 0xa9, 0x2c,
+ 0xe7, 0xe1, 0x4d, 0xa6, 0x46, 0xef, 0x3a, 0x96, 0x93, 0x8c,
+ 0xc1, 0x02, 0x00, 0x6f, 0x31, 0x9f, 0xa2, 0x1d
+ }};
+
+ uint16_t tag = 0;
+ ok(dnssec_keytag(&rsa_md5_rdata, &tag) == DNSSEC_EOK && tag == 40866,
+ "keytag for RSA/MD5");
+
+ const dnssec_binary_t ecdsa_rdata = { .size = 100, .data = (uint8_t []) {
+ 0x01, 0x00, 0x03, 0x0e,
+ 0xbe, 0x8f, 0x42, 0x92, 0x34, 0xa0, 0x06, 0x5f, 0x18, 0xa1,
+ 0x15, 0x01, 0x84, 0x50, 0x33, 0x1f, 0x44, 0xa2, 0xbb, 0x61,
+ 0x2a, 0xc8, 0x86, 0x9c, 0xf3, 0x4b, 0x2e, 0xf9, 0x63, 0xd1,
+ 0x81, 0x72, 0x56, 0x96, 0xc7, 0x67, 0x34, 0xa1, 0x55, 0xc2,
+ 0xf3, 0x1d, 0x03, 0xbe, 0x1b, 0x39, 0xeb, 0xa7, 0xb8, 0x2c,
+ 0x72, 0x2e, 0x58, 0x75, 0x56, 0x42, 0x0b, 0x6f, 0x21, 0xa2,
+ 0x33, 0xf4, 0x21, 0x00, 0xb7, 0x0f, 0x5a, 0xf7, 0x1a, 0xf0,
+ 0xe9, 0x94, 0xfa, 0x43, 0xb0, 0x4a, 0x48, 0xb8, 0x64, 0x89,
+ 0x7b, 0xc9, 0xe0, 0xf7, 0x97, 0x52, 0xf4, 0x85, 0x0f, 0xb4,
+ 0xf4, 0xfc, 0xe2, 0x10, 0xd4, 0x26
+ }};
+
+ ok(dnssec_keytag(&ecdsa_rdata, &tag) == DNSSEC_EOK && tag == 61768,
+ "keytag for ECDSA/SHA384");
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_list.c b/tests/libdnssec/test_list.c
new file mode 100644
index 0000000..cd0a060
--- /dev/null
+++ b/tests/libdnssec/test_list.c
@@ -0,0 +1,127 @@
+/* Copyright (C) 2018 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 <stdint.h>
+#include <tap/basic.h>
+
+#include "list.h"
+
+static void * const free_context = (void *)0xcafe;
+static int counter = 0;
+
+static void item_free(void *pointer, void *data)
+{
+ if (pointer && data == free_context) {
+ counter += 1;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ plan_lazy();
+
+ /* new list */
+
+ dnssec_list_t *list = dnssec_list_new();
+ ok(list != NULL, "create new list");
+
+ ok(dnssec_list_size(list) == 0, "new list has zero size");
+ ok(dnssec_list_is_empty(list), "new list is empty");
+ ok(dnssec_list_head(list) == NULL, "new list has no head");
+ ok(dnssec_list_tail(list) == NULL, "new list has no tail");
+
+ /* populate the list */
+
+ dnssec_list_append(list, (void *)7);
+ dnssec_list_append(list, (void *)9);
+ // 7, 9
+
+ dnssec_list_prepend(list, (void *)5);
+ dnssec_list_prepend(list, (void *)2);
+ // 2, 5, 7, 9
+
+ dnssec_item_t *head = dnssec_list_head(list);
+ dnssec_list_insert_before(head, (void *)1);
+ dnssec_list_insert_after(head, (void *)3);
+ // 1, 2, 3, 5, 7, 9
+
+ dnssec_item_t *tail = dnssec_list_tail(list);
+ dnssec_list_insert_before(tail, (void *)8);
+ dnssec_list_insert_after(tail, (void *)10);
+ // 1, 2, 3, 5, 7, 8, 9, 10
+
+ dnssec_item_t *item_5 = dnssec_list_nth(list, 3);
+ dnssec_list_insert_before(item_5, (void *)4);
+ dnssec_list_insert_after(item_5, (void *)6);
+ // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+
+ ok(dnssec_list_size(list) == 10, "populated list has expected size");
+ ok(!dnssec_list_is_empty(list), "populated list is non-empty");
+
+ // content iteration
+
+ int sum = 0;
+ int previous = 0;
+ bool increasing = true;
+
+ for (dnssec_item_t *i = dnssec_list_head(list); i; i = dnssec_list_next(list, i)) {
+ int number = (int)(intptr_t)dnssec_item_get(i);
+ sum += number;
+
+ if (previous + 1 != number) {
+ increasing = false;
+ }
+
+ previous = number;
+ }
+
+ ok(sum == 55, "all items are in the list");
+ ok(increasing, "append and prepend work");
+
+ // content lookup
+
+ ok(dnssec_list_contains(list, (void *)7), "contains: positive");
+ ok(!dnssec_list_contains(list, (void *)17), "contains: negative");
+
+ ok(dnssec_list_search(list, (void *)3) == dnssec_list_nth(list, 2), "search: positive");
+ ok(dnssec_list_search(list, (void *)12) == NULL, "search: negative");
+
+ // item removal
+
+ dnssec_list_remove(dnssec_list_head(list));
+ dnssec_list_remove(dnssec_list_tail(list));
+ dnssec_list_remove(dnssec_list_nth(list, 5));
+
+ ok(dnssec_list_size(list) == 7, "three items removed");
+
+ // full free
+
+ counter = 0;
+ dnssec_list_free_full(list, item_free, free_context);
+ ok(counter == 7, "list full free");
+
+ // non-full free
+
+ list = dnssec_list_new();
+ dnssec_list_append(list, NULL);
+ ok(!dnssec_list_is_empty(list), "new list with one item");
+
+ counter = 0;
+ dnssec_list_free(list);
+ ok(counter == 0, "list non-full free");
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_nsec_bitmap.c b/tests/libdnssec/test_nsec_bitmap.c
new file mode 100644
index 0000000..37676fe
--- /dev/null
+++ b/tests/libdnssec/test_nsec_bitmap.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 2018 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 <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tap/basic.h>
+
+#include "nsec.h"
+#include "libknot/descriptor.h"
+
+#define TEST_BITMAP_SIZE 18
+
+int main(void)
+{
+ plan_lazy();
+
+ // Which rrtypes will be contained in the bitmap.
+ int test_contains_count = 8;
+ enum knot_rr_type test_contains[] = {
+ KNOT_RRTYPE_A,
+ KNOT_RRTYPE_NS,
+ KNOT_RRTYPE_SOA,
+ KNOT_RRTYPE_RRSIG,
+ KNOT_RRTYPE_NSEC,
+ KNOT_RRTYPE_DNSKEY,
+ KNOT_RRTYPE_SPF,
+ KNOT_RRTYPE_CAA
+ };
+
+ // Which rrtypes will not be contained in the bitmap.
+ int test_not_contains_count = 4;
+ enum knot_rr_type test_not_contains[] = {
+ KNOT_RRTYPE_AAAA,
+ KNOT_RRTYPE_MX,
+ KNOT_RRTYPE_AXFR,
+ KNOT_RRTYPE_CNAME
+ };
+
+ // Allocate new bitmap.
+ dnssec_nsec_bitmap_t *bitmap = dnssec_nsec_bitmap_new();
+ ok(bitmap != NULL, "allocate bitmap");
+ if (!bitmap) {
+ return 1;
+ }
+
+ // Add the desired RR types to bitmap.
+ for (int i = 0; i < test_contains_count; i++) {
+ dnssec_nsec_bitmap_add(bitmap, test_contains[i]);
+ }
+
+ size_t size = dnssec_nsec_bitmap_size(bitmap);
+ ok(size == TEST_BITMAP_SIZE, "valid bitmap size");
+ if (size != TEST_BITMAP_SIZE) {
+ dnssec_nsec_bitmap_free(bitmap);
+ return 1;
+ }
+
+ const uint8_t expected[TEST_BITMAP_SIZE] = {
+ 0x00, 0x0D, 0x62, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x01, 0x01, 0x40
+ };
+ uint8_t encoded[TEST_BITMAP_SIZE] = { 0 };
+ dnssec_nsec_bitmap_write(bitmap, encoded);
+
+ ok(memcmp(encoded, expected, TEST_BITMAP_SIZE) == 0, "valid bitmap");
+
+ // Test contained types.
+ char rrtype_str[50];
+ for (int i = 0; i < test_contains_count; i++) {
+ bool contains = dnssec_nsec_bitmap_contains(encoded, size, test_contains[i]);
+ (void)knot_rrtype_to_string(test_contains[i], rrtype_str, 50);
+ ok(contains, "bitmap contains %s", rrtype_str);
+ }
+
+ // Test not contained types.
+ for (int i = 0; i < test_not_contains_count; i++) {
+ bool contains = dnssec_nsec_bitmap_contains(encoded, size, test_not_contains[i]);
+ (void)knot_rrtype_to_string(test_not_contains[i], rrtype_str, 50);
+ ok(!contains, "bitmap does not contain %s", rrtype_str);
+ }
+
+ dnssec_nsec_bitmap_clear(bitmap);
+ ok(dnssec_nsec_bitmap_size(bitmap) == 0, "bitmap clear");
+
+ dnssec_nsec_bitmap_free(bitmap);
+ return 0;
+}
diff --git a/tests/libdnssec/test_nsec_hash.c b/tests/libdnssec/test_nsec_hash.c
new file mode 100644
index 0000000..47e4501
--- /dev/null
+++ b/tests/libdnssec/test_nsec_hash.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 2018 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 <string.h>
+#include <tap/basic.h>
+
+#include "crypto.h"
+#include "error.h"
+#include "nsec.h"
+
+static const dnssec_binary_t RDATA = { .size = 9, .data = (uint8_t []) {
+ 0x01, // algorithm
+ 0x00, // flags
+ 0x00, 0x0a, // iterations
+ 0x04, // salt length
+ 'a', 'b', 'c', 'd' // salt
+}};
+
+static void test_length(void)
+{
+ ok(dnssec_nsec3_hash_length(DNSSEC_NSEC3_ALGORITHM_SHA1) == 20,
+ "dnssec_nsec3_hash_length() for SHA1");
+}
+
+static void test_parsing(void)
+{
+
+ dnssec_nsec3_params_t params = { 0 };
+ int result = dnssec_nsec3_params_from_rdata(&params, &RDATA);
+ ok(result == DNSSEC_EOK, "dnssec_nsec3_params_from_rdata()");
+
+ ok(params.algorithm == 1, "algorithm");
+ ok(params.flags == 0, "flags");
+ ok(params.iterations == 10, "iterations");
+ ok(params.salt.size == 4, "salt length");
+ ok(params.salt.data != NULL && memcmp(params.salt.data, "abcd", 4) == 0,
+ "salt content");
+
+ dnssec_nsec3_params_free(&params);
+ ok(params.salt.data == NULL, "dnssec_nsec3_params_free()");
+}
+
+static void test_hashing(void)
+{
+ const dnssec_binary_t dname = {
+ .size = 13,
+ .data = (uint8_t *) "\x08""knot-dns""\x02""cz"
+ };
+
+ const dnssec_nsec3_params_t params = {
+ .algorithm = DNSSEC_NSEC3_ALGORITHM_SHA1,
+ .flags = 0,
+ .iterations = 7,
+ .salt = { .size = 14, .data = (uint8_t *) "happywithnsec3" }
+ };
+
+ const dnssec_binary_t expected = { .size = 20, .data = (uint8_t []) {
+ 0x72, 0x40, 0x55, 0x83, 0x92, 0x93, 0x95, 0x28, 0xee, 0xa2,
+ 0xcc, 0xe1, 0x13, 0xbe, 0xcd, 0x41, 0xee, 0x8a, 0x71, 0xfd
+ }};
+
+ dnssec_binary_t hash = { 0 };
+
+ int result = dnssec_nsec3_hash(&dname, &params, &hash);
+ ok(result == DNSSEC_EOK, "dnssec_nsec3_hash()");
+
+ ok(hash.size == expected.size && hash.data != NULL &&
+ memcmp(hash.data, expected.data, expected.size) == 0,
+ "valid hash");
+
+ dnssec_binary_free(&hash);
+}
+
+static void test_clear(void)
+{
+ const dnssec_nsec3_params_t empty = { 0 };
+ dnssec_nsec3_params_t params = { 0 };
+
+ int result = dnssec_nsec3_params_from_rdata(&params, &RDATA);
+ ok(result == DNSSEC_EOK, "dnssec_nsec3_params_from_rdata()");
+
+ ok(memcmp(&params, &empty, sizeof(dnssec_nsec3_params_t)) != 0,
+ "non-empty after dnssec_nsec3_params_from_rdata()");
+
+ dnssec_nsec3_params_free(&params);
+
+ ok(memcmp(&params, &empty, sizeof(dnssec_nsec3_params_t)) == 0,
+ "cleared after dnssec_nsec3_params_free()");
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ test_length();
+ test_parsing();
+ test_hashing();
+ test_clear();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_random.c b/tests/libdnssec/test_random.c
new file mode 100644
index 0000000..7c86aa6
--- /dev/null
+++ b/tests/libdnssec/test_random.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2018 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 <stdint.h>
+#include <string.h>
+#include <tap/basic.h>
+
+#include "crypto.h"
+#include "error.h"
+#include "random.h"
+
+int check_buffer(void)
+{
+ const size_t buffer_size = 128;
+ uint8_t buffer_prev[buffer_size];
+ memset(buffer_prev, 0, buffer_size);
+ uint8_t buffer[buffer_size];
+ memset(buffer, 0, buffer_size);
+
+ for (int i = 0; i < 10; i++) {
+ int result = dnssec_random_buffer(buffer, buffer_size);
+ if (result != DNSSEC_EOK) {
+ return 1;
+ }
+
+ if (memcmp(buffer, buffer_prev, buffer_size) == 0) {
+ return 1;
+ }
+
+ memmove(buffer_prev, buffer, buffer_size);
+ }
+
+ return 0;
+}
+
+int check_random_type(void)
+{
+ uint16_t numbers[1000] = { 0 };
+ int conflicts = 0;
+
+ for (int i = 0; i < 1000; i++) {
+ numbers[i] = dnssec_random_uint16_t();
+ // check all previous
+ for (int j = 0; j < i; j++) {
+ if (numbers[i] == numbers[j]) {
+ conflicts += 1;
+ }
+ }
+ }
+
+ // allow 5 % of conflicts
+ return conflicts <= 50 ? 0 : 1;
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ dnssec_crypto_init();
+
+ // quite stupid, just check if it does something
+
+ ok(check_buffer() == 0, "dnssec_random_buffer()");
+ ok(check_random_type() == 0, "dnssec_random_uint16_t()");
+
+ dnssec_crypto_cleanup();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_shared_bignum.c b/tests/libdnssec/test_shared_bignum.c
new file mode 100644
index 0000000..0e8f8d5
--- /dev/null
+++ b/tests/libdnssec/test_shared_bignum.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+#include <string.h>
+
+#include "bignum.h"
+#include "binary.h"
+
+#define bin_init(array) { .data = array, .size = sizeof(array) }
+
+#define test_size(value, usize, ssize, msg) \
+ dnssec_binary_t __bin = bin_init(value); \
+ is_int(usize, bignum_size_u(&__bin), "bignum_size_u, " msg); \
+ is_int(ssize, bignum_size_s(&__bin), "bignum_size_s, " msg)
+
+#define test_write(num, expect, msg) \
+ uint8_t __buffer[sizeof(expect)]; \
+ memset(__buffer, 0xaa, sizeof(__buffer)); \
+ wire_ctx_t __ctx = wire_ctx_init(__buffer, sizeof(expect)); \
+ dnssec_binary_t __num = bin_init(num); \
+ dnssec_binary_t __exp = bin_init(expect); \
+ bignum_write(&__ctx, sizeof(expect), &__num); \
+ dnssec_binary_t __dst = bin_init(__buffer); \
+ ok(dnssec_binary_cmp(&__dst, &__exp) == 0, "bignum_write, " msg)
+
+int main(int argc, char *argv[])
+{
+ plan_lazy();
+
+ {
+ uint8_t num[] = { };
+ test_size(num, 1, 1, "empty string");
+ }
+
+ {
+ uint8_t num[] = { 0x00 };
+ test_size(num, 1, 1, "zero");
+ }
+
+ {
+ uint8_t num[] = { 0x00, 0x00, 0x00 };
+ test_size(num, 1, 1, "long zero");
+ }
+
+ {
+ uint8_t num[] = { 0x01, 0x02, 0x03 };
+ test_size(num, 3, 3, "no MSB");
+ }
+
+ {
+ uint8_t num[] = { 0x7f, 0xff, 0x00, 0x00, 0x00 };
+ test_size(num, 5, 5, "no MSB but all other bits");
+ }
+
+ {
+ uint8_t num[] = { 0x84, 0x42 };
+ test_size(num, 2, 3, "MSB");
+ }
+
+ {
+ uint8_t num[] = { 0x00, 0x84, 0x42 };
+ test_size(num, 2, 3, "MSB and leading zero");
+ }
+
+ {
+ uint8_t num[] = { 0x00, 0x00, 0x00, 0x00, 0xfc, 0xe1, 0xda };
+ test_size(num, 3, 4, "MSB, many leading zeroes");
+ }
+
+ {
+ uint8_t num[] = { 0x00, 0x00, 0x00, 0x01 };
+ test_size(num, 1, 1, "no MSB, many leading zeroes");
+ }
+
+ // test writing
+
+ {
+ uint8_t num[] = { };
+ uint8_t exp[] = { 0x00 };
+ test_write(num, exp, "empty string");
+ }
+
+ {
+ uint8_t num[] = { 0x00 };
+ uint8_t exp[] = { 0x00 };
+ test_write(num, exp, "zero");
+ }
+
+ {
+ uint8_t num[] = { 0x11, 0x22, 0x33 };
+ uint8_t exp[] = { 0x00, 0x00, 0x00, 0x11, 0x22, 0x33 };
+ test_write(num, exp, "no MSB, right-aligned");
+ }
+
+ {
+ uint8_t num[] = { 0xff, 0xee, 0xdd };
+ uint8_t exp[] = { 0x00, 0x00, 0x00, 0xff, 0xee, 0xdd };
+ test_write(num, exp, "MSB, right-aligned");
+ }
+
+ {
+ uint8_t num[] = { 0x11, 0x22, 0x33 };
+ uint8_t exp[] = { 0x11, 0x22, 0x33 };
+ test_write(num, exp, "no MSB, fitting exactly");
+ }
+
+ {
+ uint8_t num[] = { 0xff, 0xee, 0xdd };
+ uint8_t exp[] = { 0xff, 0xee, 0xdd };
+ test_write(num, exp, "MSB, fitting exactly");
+ }
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_shared_dname.c b/tests/libdnssec/test_shared_dname.c
new file mode 100644
index 0000000..8eb93cf
--- /dev/null
+++ b/tests/libdnssec/test_shared_dname.c
@@ -0,0 +1,79 @@
+/* Copyright (C) 2018 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 <stdbool.h>
+#include <string.h>
+#include <tap/basic.h>
+
+#include "dname.h"
+
+static void ok_length(const char *dname, size_t length, const char *info)
+{
+ ok(dname_length((uint8_t *)dname) == length,
+ "dname_length() for %s", info);
+}
+
+static void test_length(void)
+{
+ ok_length(NULL, 0, "NULL");
+ ok_length("", 1, ".");
+ ok_length("\x2""cz", 4, "cz.");
+ ok_length("\x7""example""\x3""com", 13, "example.com.");
+}
+
+static bool dname_binary_equal(const uint8_t *one, const uint8_t *two)
+{
+ return one && two && strcmp((char *)one, (char *)two) == 0;
+}
+
+static void test_copy(void)
+{
+ const uint8_t *dname = (uint8_t *)"\x3""www""\x8""KNOT-DNS""\x2""cz";
+ uint8_t *copy = dname_copy(dname);
+ ok(dname_binary_equal(dname, copy), "dname_copy()");
+ free(copy);
+}
+
+static void test_equal(void)
+{
+ #define eq(a, b) dname_equal((uint8_t *)a, (uint8_t *)b)
+
+ ok(eq("\x4""kiwi""\x4""limo", "\x4""kiwi""\x4""limo") == true,
+ "dname_equal() same");
+ ok(eq("\x6""orange", "\x6""ORANGE") == true,
+ "dname_equal() case single label");
+ ok(eq("\x6""Banana""\03""Tea", "\x6""bANAna""\x3""tea") == true,
+ "dname_equal() case two labels");
+ ok(eq("\x4""Coco""\x4""MILK", "\x3""cow""\x4""milk") == false,
+ "dname_equal() different first");
+ ok(eq("\x4""LIME""\x5""syrup", "\x4""LIme""\x4""beer") == false,
+ "dname_equal() different last");
+ ok(eq("\x5""apple", "\x5""apple""\x5""shake") == false,
+ "dname_equal() a prefix of b");
+ ok(eq("\x5""apple""\x5""juice", "\x5""apple") == false,
+ "dname_equal() b prefix of a");
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ test_length();
+ test_copy();
+ test_equal();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_sign.c b/tests/libdnssec/test_sign.c
new file mode 100644
index 0000000..1f61d96
--- /dev/null
+++ b/tests/libdnssec/test_sign.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 2018 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 <string.h>
+#include <tap/basic.h>
+
+#include "sample_keys.h"
+
+#include "binary.h"
+#include "crypto.h"
+#include "error.h"
+#include "key.h"
+#include "sign.h"
+
+static const dnssec_binary_t input_data = {
+ .size = 25,
+ .data = (uint8_t *)"Very good, young padawan."
+};
+
+static const dnssec_binary_t signed_rsa = { .size = 128, .data = (uint8_t []) {
+ 0x21, 0xba, 0xff, 0x0c, 0x15, 0x10, 0x73, 0x25, 0xa7, 0x8e,
+ 0xf4, 0x71, 0x4b, 0xd3, 0x97, 0x6d, 0x95, 0x52, 0xc2, 0x0b,
+ 0x43, 0xb3, 0x7d, 0x82, 0xe4, 0x3e, 0x2a, 0xc3, 0xb7, 0x17,
+ 0x5b, 0x05, 0xe9, 0x1e, 0x13, 0xac, 0x27, 0x6f, 0x20, 0x93,
+ 0x1a, 0xeb, 0xe2, 0x2c, 0x72, 0x70, 0x14, 0xe6, 0x49, 0xa7,
+ 0x62, 0xdd, 0x4c, 0x72, 0x1e, 0x1d, 0xd8, 0xf9, 0xba, 0xbc,
+ 0x96, 0x0e, 0xc3, 0xd4, 0xc1, 0x8f, 0x95, 0xdb, 0x01, 0x18,
+ 0x24, 0x43, 0xbd, 0x2b, 0x52, 0x9b, 0x10, 0x1f, 0xba, 0x0a,
+ 0x76, 0xbe, 0x0e, 0xaa, 0x91, 0x27, 0x7b, 0x9f, 0xed, 0x5a,
+ 0xad, 0x96, 0x1a, 0x02, 0x97, 0x42, 0x91, 0x30, 0x03, 0x2b,
+ 0x5c, 0xb8, 0xcc, 0x6b, 0xcf, 0x39, 0x62, 0x5e, 0x47, 0xae,
+ 0x6d, 0x5b, 0x43, 0xd2, 0xc2, 0xd8, 0x22, 0x5d, 0xf5, 0x5e,
+ 0x0a, 0x97, 0x65, 0x41, 0xc7, 0xaa, 0x28, 0x67,
+}};
+
+static const dnssec_binary_t signed_ecdsa = { .size = 64, .data = (uint8_t []) {
+ 0xa2, 0x95, 0x76, 0xb5, 0xf5, 0x7e, 0xbd, 0xdd, 0xf5, 0x62,
+ 0xa2, 0xc3, 0xa4, 0x8d, 0xd4, 0x53, 0x5c, 0xba, 0x29, 0x71,
+ 0x8c, 0xcc, 0x28, 0x7b, 0x58, 0xf3, 0x1e, 0x4e, 0x58, 0xe2,
+ 0x36, 0x7e,
+ 0xa0, 0x1a, 0xb6, 0xe6, 0x29, 0x71, 0x1b, 0xd3, 0x8c, 0x88,
+ 0xc3, 0xee, 0x12, 0x0e, 0x69, 0x70, 0x55, 0x99, 0xec, 0xd5,
+ 0xf6, 0x4f, 0x4b, 0xe2, 0x41, 0xd9, 0x10, 0x7e, 0x67, 0xe5,
+ 0xad, 0x2f,
+}};
+
+#ifdef HAVE_ED25519
+static const dnssec_binary_t signed_ed25519 = { .size = 64, .data = (uint8_t []) {
+ 0x0a, 0x9e, 0x51, 0x5f, 0x16, 0x89, 0x49, 0x27,
+ 0x0e, 0x98, 0x34, 0xd3, 0x48, 0xef, 0x5a, 0x6e,
+ 0x85, 0x2f, 0x7c, 0xd6, 0xd7, 0xc8, 0xd0, 0xf4,
+ 0x2c, 0x68, 0x8c, 0x1f, 0xf7, 0xdf, 0xeb, 0x7c,
+ 0x25, 0xd6, 0x1a, 0x76, 0x3e, 0xaf, 0x28, 0x1f,
+ 0x1d, 0x08, 0x10, 0x20, 0x1c, 0x01, 0x77, 0x1b,
+ 0x5a, 0x48, 0xd6, 0xe5, 0x1c, 0xf9, 0xe3, 0xe0,
+ 0x70, 0x34, 0x5e, 0x02, 0x49, 0xfb, 0x9e, 0x05,
+ }};
+#endif
+
+static dnssec_binary_t binary_set_string(char *str)
+{
+ dnssec_binary_t result = { .data = (uint8_t *)str, .size = strlen(str) };
+ return result;
+}
+
+static void check_key(const key_parameters_t *key_data, const dnssec_binary_t *data,
+ const dnssec_binary_t *signature, bool signature_match)
+{
+ int r;
+
+ // initialize key from public parameters
+
+ dnssec_key_t *key = NULL;
+ r = dnssec_key_new(&key);
+ ok(r == DNSSEC_EOK && key != NULL, "create key");
+ r = dnssec_key_set_rdata(key, &key_data->rdata);
+ ok(r == DNSSEC_EOK, "set RDATA");
+
+ // check validation on static signature
+
+ dnssec_sign_ctx_t *ctx = NULL;
+ r = dnssec_sign_new(&ctx, key);
+ ok(r == DNSSEC_EOK, "create signing context");
+ r = dnssec_sign_add(ctx, data);
+ ok(r == DNSSEC_EOK, "add data to be signed");
+ r = dnssec_sign_verify(ctx, signature);
+ ok(r == DNSSEC_EOK, "signature verified");
+
+ // create new signature and self-validate
+
+ r = dnssec_key_load_pkcs8(key, &key_data->pem);
+ ok(r == DNSSEC_EOK, "load private key");
+
+ if (signature_match) {
+ r = dnssec_sign_init(ctx);
+ ok(r == DNSSEC_EOK, "reinitialize context");
+ r = dnssec_sign_add(ctx, data);
+ ok(r == DNSSEC_EOK, "add data to be signed");
+ dnssec_binary_t new_signature = { 0 };
+ r = dnssec_sign_write(ctx, &new_signature);
+ ok(r == DNSSEC_EOK, "write the signature");
+ ok(dnssec_binary_cmp(signature, &new_signature) == 0,
+ "signature exact match");
+ r = dnssec_sign_verify(ctx, &new_signature);
+ ok(r == DNSSEC_EOK, "reverify the new signature");
+ dnssec_binary_free(&new_signature);
+ }
+
+ // context reinitialization
+
+ dnssec_binary_t tmp = { 0 };
+
+ r = dnssec_sign_init(ctx);
+ ok(r == DNSSEC_EOK, "reinitialize context");
+
+ tmp = binary_set_string("bind");
+ r = dnssec_sign_add(ctx, &tmp);
+ ok(r == DNSSEC_EOK, "add data (1)");
+
+ r = dnssec_sign_init(ctx);
+ ok(r == DNSSEC_EOK, "reinitialize context");
+
+ tmp = binary_set_string("knot");
+ r = dnssec_sign_add(ctx, &tmp);
+ ok(r == DNSSEC_EOK, "add data (2)");
+
+ tmp = binary_set_string(" is the best");
+ r = dnssec_sign_add(ctx, &tmp);
+ ok(r == DNSSEC_EOK, "add data (3)");
+
+ dnssec_binary_t new_signature = { 0 };
+ r = dnssec_sign_write(ctx, &new_signature);
+ ok(r == DNSSEC_EOK, "write signature");
+
+ r = dnssec_sign_init(ctx);
+ ok(r == DNSSEC_EOK, "reinitialize context");
+
+ tmp = binary_set_string("knot is the best");
+ r = dnssec_sign_add(ctx, &tmp);
+ ok(r == DNSSEC_EOK, "add data (4)");
+
+ r = dnssec_sign_verify(ctx, &new_signature);
+ ok(r == DNSSEC_EOK, "verify signature");
+
+ dnssec_binary_free(&new_signature);
+
+ // cleanup
+
+ dnssec_sign_free(ctx);
+ dnssec_key_free(key);
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ dnssec_crypto_init();
+
+ diag("RSA signing");
+ check_key(&SAMPLE_RSA_KEY, &input_data, &signed_rsa, true);
+ diag("ECDSA signing");
+ check_key(&SAMPLE_ECDSA_KEY, &input_data, &signed_ecdsa, false);
+#ifdef HAVE_ED25519
+ diag("ED25519 signing");
+ check_key(&SAMPLE_ED25519_KEY, &input_data, &signed_ed25519, true);
+#endif
+
+ dnssec_crypto_cleanup();
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_sign_der.c b/tests/libdnssec/test_sign_der.c
new file mode 100644
index 0000000..04bfeac
--- /dev/null
+++ b/tests/libdnssec/test_sign_der.c
@@ -0,0 +1,202 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "binary.h"
+#include "error.h"
+#include "sign/der.c"
+
+static int binary_eq(const dnssec_binary_t *a, const dnssec_binary_t *b)
+{
+ return a && b &&
+ a->size == b->size &&
+ memcmp(a->data, b->data, a->size) == 0;
+}
+
+#define DECODE_OK(der, r, s, message) \
+ dnssec_binary_t __der = { .data = der, .size = sizeof(der) }; \
+ dnssec_binary_t __r = { .data = r, .size = sizeof(r) }; \
+ dnssec_binary_t __s = { .data = s, .size = sizeof(s) }; \
+ dnssec_binary_t __out_s = { 0 }; \
+ dnssec_binary_t __out_r = { 0 }; \
+ int _result = dss_sig_value_decode(&__der, &__out_r, &__out_s); \
+ ok(_result == DNSSEC_EOK && \
+ binary_eq(&__r, &__out_r) && \
+ binary_eq(&__s, &__out_s), \
+ "decode ok, " message)
+
+#define DECODE_FAIL(der, message) \
+ dnssec_binary_t __der = { .data = der, .size = sizeof(der) }; \
+ dnssec_binary_t __out_r = { 0 }; \
+ dnssec_binary_t __out_s = { 0 }; \
+ int _result = dss_sig_value_decode(&__der, &__out_r, &__out_s); \
+ ok(_result != DNSSEC_EOK, \
+ "decode fail, " message)
+
+#define ENCODE_OK(r, s, der, message) \
+ dnssec_binary_t __r = { .data = r, .size = sizeof(r) }; \
+ dnssec_binary_t __s = { .data = s, .size = sizeof(s) }; \
+ dnssec_binary_t __der = { .data = der, .size = sizeof(der) }; \
+ dnssec_binary_t __out_der = { 0 }; \
+ int _result = dss_sig_value_encode(&__r, &__s, &__out_der); \
+ ok(_result == DNSSEC_EOK && \
+ binary_eq(&__der, &__out_der), \
+ "encode ok, " message); \
+ dnssec_binary_free(&__out_der)
+
+#define ENCODE_FAIL(r, s, message) \
+ dnssec_binary_t __r = { .data = r, .size = sizeof(r) }; \
+ dnssec_binary_t __s = { .data = s, .size = sizeof(s) }; \
+ dnssec_binary_t __out_der = { 0 }; \
+ int _result = dss_sig_value_encode(&__r, &__s, &__out_der); \
+ ok(_result != DNSSEC_EOK, \
+ "encode fail, " message); \
+ dnssec_binary_free(&__out_der)
+
+#define ONE_64_TIMES \
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, \
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, \
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, \
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, \
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, \
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, \
+ 0x01,0x01,0x01,0x01
+
+#define ONE_128_TIMES \
+ ONE_64_TIMES, ONE_64_TIMES
+
+int main(void)
+{
+ plan_lazy();
+
+ {
+ uint8_t der[] = { 0x30,0x08, 0x02,0x02,0x1a,0x2b, 0x02,0x02,0x3c,0x4d };
+ uint8_t r[] = { 0x1a, 0x2b };
+ uint8_t s[] = { 0x3c, 0x4d };
+ DECODE_OK(der, r, s, "simple without MSB");
+ }
+
+ {
+ uint8_t der[] = { 0x30,0x08, 0x02,0x02,0xff,0xff, 0x02,0x02,0x80,0x00 };
+ uint8_t r[] = { 0xff, 0xff };
+ uint8_t s[] = { 0x80, 0x00 };
+ DECODE_OK(der, r, s, "simple with MSB");
+ }
+
+ {
+ uint8_t der[] = { 0x30,0x09, 0x02,0x04,0x00,0x00,0x00,0xfa, 0x02,0x01,0x07 };
+ uint8_t r[] = { 0xfa };
+ uint8_t s[] = { 0x07 };
+ DECODE_OK(der, r, s, "leading zeros");
+ }
+
+ {
+ uint8_t der[] = { 0x30,0x07, 0x02,0x01,0x00, 0x02,0x02,0x00,0x00 };
+ uint8_t r[] = { 0x00 };
+ uint8_t s[] = { 0x00 };
+ DECODE_OK(der, r, s, "zero values" );
+ }
+
+ {
+ uint8_t der[] = { };
+ DECODE_FAIL(der, "empty input");
+ }
+
+ {
+ uint8_t der[] = { 0x30,0x04, 0x02,0x01,0x01 };
+ DECODE_FAIL(der, "partial sequence");
+ }
+
+ {
+ uint8_t der[] = { 0x30,0x06, 0x02,0x01,0x01, 0x02,0x02,0x01 };
+ DECODE_FAIL(der, "partial integer");
+ }
+
+ {
+ uint8_t der[] = { 0x30,0x00 };
+ DECODE_FAIL(der, "zero-length sequence");
+ }
+
+ {
+ uint8_t der[] = { 0x30,0x05, 0x02,0x01,0xff, 0x02,0x00 };
+ DECODE_FAIL(der, "zero-length integer");
+ }
+
+ {
+ uint8_t der[] = { 0x30,0x84, 0x02,0x40,ONE_64_TIMES, 0x02,0x40,ONE_64_TIMES };
+ DECODE_FAIL(der, "unsupported size");
+ }
+
+ {
+ uint8_t r[] = { 0x01, };
+ uint8_t s[] = { 0x02,0x03 };
+ uint8_t der[] = { 0x30,0x07, 0x02,0x01,0x01, 0x02,0x02,0x02,0x03 };
+ ENCODE_OK(r, s, der, "simple");
+ }
+
+ {
+ uint8_t r[] = { 0x00,0x01, };
+ uint8_t s[] = { 0x00,0x00,0x02,0x03 };
+ uint8_t der[] = { 0x30,0x07, 0x02,0x01,0x01, 0x02,0x02,0x02,0x03 };
+ ENCODE_OK(r, s, der, "unnecessary leading zeros");
+ }
+
+ {
+ uint8_t r[] = { 0x00,0x8f };
+ uint8_t s[] = { 0x00,0x00,0xff };
+ uint8_t der[] = { 0x30,0x08, 0x02,0x02,0x00,0x8f, 0x02,0x02,0x00,0xff };
+ ENCODE_OK(r, s, der, "required zero not removed");
+ }
+
+ {
+ uint8_t r[] = { 0x8c };
+ uint8_t s[] = { 0xff,0xee };
+ uint8_t der[] = { 0x30,0x09, 0x02,0x02,0x00,0x8c, 0x02,0x03,0x00,0xff,0xee };
+ ENCODE_OK(r, s, der, "implicitly added zero");
+ }
+
+ {
+ uint8_t r[] = { 0x00 };
+ uint8_t s[] = { 0x00,0x00 };
+ uint8_t der[] = { 0x30,0x06, 0x02,0x01,0x00, 0x02,0x01,0x00 };
+ ENCODE_OK(r, s, der, "zero");
+ }
+
+ {
+ uint8_t r[] = { 0x01 };
+ uint8_t s[] = { };
+ uint8_t der[] = { 0x30,0x06, 0x02,0x01,0x01, 0x02,0x01,0x00 };
+ ENCODE_OK(r, s, der, "zero-length input");
+ }
+
+ {
+ uint8_t r[] = { ONE_128_TIMES };
+ uint8_t s[] = { 0x01 };
+ ENCODE_FAIL(r, s, "input too long");
+ }
+
+ {
+ uint8_t r[] = { ONE_64_TIMES };
+ uint8_t s[] = { ONE_64_TIMES };
+ ENCODE_FAIL(r, s, "result too long");
+ }
+
+ return 0;
+}
diff --git a/tests/libdnssec/test_tsig.c b/tests/libdnssec/test_tsig.c
new file mode 100644
index 0000000..91674be
--- /dev/null
+++ b/tests/libdnssec/test_tsig.c
@@ -0,0 +1,145 @@
+/* Copyright (C) 2018 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 <tap/basic.h>
+#include <string.h>
+
+#include "binary.h"
+#include "dname.h"
+#include "tsig.h"
+
+static const dnssec_binary_t payload = {
+ .size = 40,
+ .data = (uint8_t []){
+ 0xfd, 0x07, 0xca, 0x30, 0xf9, 0xff, 0x38, 0xb1, 0x32, 0x54,
+ 0xd1, 0x16, 0x24, 0xaa, 0x81, 0x2c, 0x97, 0xa0, 0x7a, 0xac,
+ 0x68, 0x7a, 0x3a, 0x60, 0xde, 0xc9, 0xf7, 0x7a, 0x5a, 0x58,
+ 0xff, 0xc9, 0x0c, 0xef, 0x31, 0xc7, 0x45, 0x2c, 0xee, 0x9d,
+ }
+};
+
+static const dnssec_binary_t key = {
+ .size = 16,
+ .data = (uint8_t []){
+ 0xa8, 0x05, 0x9c, 0x5c, 0x20, 0xc5, 0x00, 0x22, 0x6f, 0xad,
+ 0xf2, 0x55, 0xdf, 0x89, 0x8a, 0x68
+ }
+};
+
+typedef struct hmac {
+ int algorithm;
+ const char *name;
+ const dnssec_binary_t hmac;
+} hmac_t;
+
+static const hmac_t HMACS[] = {
+ { DNSSEC_TSIG_HMAC_MD5, "md5", { .size = 16, .data = (uint8_t []) {
+ 0x12, 0x38, 0x17, 0x4f, 0xa9, 0xc7, 0x5b, 0xcf, 0xd7, 0x08,
+ 0x19, 0x97, 0xf9, 0x3d, 0x5e, 0xe7
+ }}},
+ { DNSSEC_TSIG_HMAC_SHA1, "sha1", { .size = 20, .data = (uint8_t []) {
+ 0xb8, 0x18, 0x2a, 0x5d, 0xf8, 0x2e, 0xa0, 0xb7, 0xcc, 0xcc,
+ 0xed, 0xc1, 0xaa, 0x34, 0xeb, 0x92, 0x48, 0xf9, 0x65, 0x7b
+ }}},
+ { DNSSEC_TSIG_HMAC_SHA224, "sha224", { .size = 28, .data = (uint8_t []) {
+ 0xb7, 0x43, 0xcd, 0x0d, 0x9d, 0x51, 0x8c, 0x61, 0xc6, 0x43,
+ 0x98, 0x73, 0x5c, 0x16, 0x01, 0x1b, 0xfc, 0x82, 0xe9, 0x99,
+ 0xc2, 0x21, 0xde, 0x16, 0xb1, 0x94, 0x2d, 0xd5
+ }}},
+ { DNSSEC_TSIG_HMAC_SHA256, "sha256", { .size = 32, .data = (uint8_t []) {
+ 0x16, 0x5e, 0xf6, 0xed, 0x9b, 0x1a, 0xe5, 0x67, 0x58, 0x7b,
+ 0xf1, 0x35, 0x9e, 0x59, 0xbd, 0x50, 0x6d, 0x72, 0xf8, 0x87,
+ 0x0e, 0x22, 0xda, 0x65, 0x00, 0xd6, 0x76, 0x91, 0xde, 0x5f,
+ 0xec, 0xd8
+ }}},
+ { DNSSEC_TSIG_HMAC_SHA384, "sha384", { .size = 48, .data = (uint8_t []) {
+ 0x8a, 0xcf, 0xf3, 0xb7, 0x1c, 0xbe, 0x5c, 0x3e, 0x05, 0x74,
+ 0x97, 0x46, 0x04, 0x79, 0x3a, 0xe7, 0x8a, 0x5b, 0x7b, 0x12,
+ 0xca, 0xcd, 0xf2, 0xe2, 0xdf, 0xa9, 0x17, 0xfc, 0x8e, 0x61,
+ 0xc5, 0x86, 0x3e, 0xdc, 0xad, 0x84, 0x9e, 0x13, 0x0d, 0xa0,
+ 0x04, 0xb6, 0x6f, 0x7c, 0x85, 0x1b, 0x5c, 0xdf
+ }}},
+ { DNSSEC_TSIG_HMAC_SHA512, "sha512", { .size = 64, .data = (uint8_t []) {
+ 0xc3, 0x41, 0xd0, 0x96, 0x50, 0xd7, 0xf7, 0xfd, 0x59, 0x73,
+ 0xde, 0xd6, 0xc7, 0x4c, 0xda, 0xf1, 0x5d, 0xe1, 0x59, 0x34,
+ 0x79, 0xdc, 0x93, 0x23, 0xcb, 0xf2, 0x1f, 0x25, 0x4e, 0x35,
+ 0xb0, 0xd0, 0x9f, 0xfc, 0x22, 0xf1, 0xea, 0xbf, 0x9c, 0x18,
+ 0xd8, 0xcc, 0xcd, 0xb6, 0xb1, 0x4a, 0x06, 0x09, 0xc4, 0x3f,
+ 0x28, 0x93, 0x71, 0xd6, 0xca, 0xce, 0xf3, 0xa6, 0x08, 0x38,
+ 0xe3, 0x99, 0xc1, 0xb2
+ }}},
+ { 0 }
+};
+
+static void test_lookup_dname(const uint8_t *dname, int algorithm)
+{
+ dnssec_tsig_algorithm_t alg = dnssec_tsig_algorithm_from_dname(dname);
+ const char *name = dnssec_tsig_algorithm_to_name(algorithm);
+ if (name == NULL) name = "invalid";
+ ok(alg == algorithm, "dnssec_tsig_algorithm_from_dname(%s)", name);
+
+ const uint8_t *reverse = dnssec_tsig_algorithm_to_dname(algorithm);
+ ok((algorithm == DNSSEC_TSIG_UNKNOWN && reverse == NULL) ||
+ (algorithm != DNSSEC_TSIG_UNKNOWN && dname_equal(reverse, dname)),
+ "dnssec_tsig_algorithm_to_dname(%d)", algorithm);
+}
+
+static void test_lookup_name(const char *name, int algorithm)
+{
+ ok(dnssec_tsig_algorithm_from_name(name) == algorithm,
+ "dnssec_tsig_algorithm_from_name(%s)", name);
+
+ const char *reverse = dnssec_tsig_algorithm_to_name(algorithm);
+ ok((algorithm == DNSSEC_TSIG_UNKNOWN && reverse == NULL) ||
+ (algorithm != DNSSEC_TSIG_UNKNOWN && strcasecmp(reverse, name) == 0),
+ "dnssec_tsig_algorithm_to_name(%d)", algorithm);
+}
+
+static void test_tsig_hmac(const hmac_t *params)
+{
+ dnssec_tsig_ctx_t *ctx = NULL;
+ dnssec_tsig_new(&ctx, params->algorithm, &key);
+ dnssec_tsig_add(ctx, &payload);
+
+ size_t size = dnssec_tsig_size(ctx);
+ uint8_t hmac[size];
+ dnssec_tsig_write(ctx, hmac);
+ dnssec_tsig_free(ctx);
+
+ ok(size == params->hmac.size && memcmp(hmac, params->hmac.data, size) == 0,
+ "dnssec_tsig_write(%s)", params->name);
+}
+
+int main(void)
+{
+ plan_lazy();
+
+ test_lookup_dname((uint8_t *)"\x08""HMAC-MD5""\x07""SIG-ALG""\x03""REG""\x03""INT",
+ DNSSEC_TSIG_HMAC_MD5);
+ test_lookup_dname((uint8_t *)"\x0B""hmac-sha224", DNSSEC_TSIG_HMAC_SHA224);
+ test_lookup_dname((uint8_t *)"\x06""foobar", DNSSEC_TSIG_UNKNOWN);
+
+ test_lookup_name("hmac-md5", DNSSEC_TSIG_HMAC_MD5);
+ test_lookup_name("hmac-sha512", DNSSEC_TSIG_HMAC_SHA512);
+ test_lookup_name("barfoo", DNSSEC_TSIG_UNKNOWN);
+ test_lookup_name("hmac-foo", DNSSEC_TSIG_UNKNOWN);
+
+ for (const hmac_t *h = HMACS; h->algorithm != 0; h++) {
+ test_tsig_hmac(h);
+ }
+
+ return 0;
+}