diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 00:53:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 00:53:35 +0000 |
commit | 69c6a41ffb878ef98c9378ed4b1634a404cfaa7f (patch) | |
tree | b2a4f704565d62fbb129ab9dc3b35977c50e6e7f /tests/libdnssec | |
parent | Initial commit. (diff) | |
download | knot-upstream/2.7.6.tar.xz knot-upstream/2.7.6.zip |
Adding upstream version 2.7.6.upstream/2.7.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | tests/libdnssec/sample_keys.h | 407 | ||||
-rw-r--r-- | tests/libdnssec/test_binary.c | 93 | ||||
-rw-r--r-- | tests/libdnssec/test_crypto.c | 37 | ||||
-rw-r--r-- | tests/libdnssec/test_key.c | 212 | ||||
-rw-r--r-- | tests/libdnssec/test_key_algorithm.c | 84 | ||||
-rw-r--r-- | tests/libdnssec/test_key_ds.c | 116 | ||||
-rw-r--r-- | tests/libdnssec/test_keyid.c | 81 | ||||
-rw-r--r-- | tests/libdnssec/test_keystore_pkcs11.c | 484 | ||||
-rw-r--r-- | tests/libdnssec/test_keystore_pkcs8.c | 219 | ||||
-rw-r--r-- | tests/libdnssec/test_keystore_pkcs8_dir.c | 151 | ||||
-rw-r--r-- | tests/libdnssec/test_keytag.c | 61 | ||||
-rw-r--r-- | tests/libdnssec/test_list.c | 127 | ||||
-rw-r--r-- | tests/libdnssec/test_nsec_bitmap.c | 102 | ||||
-rw-r--r-- | tests/libdnssec/test_nsec_hash.c | 114 | ||||
-rw-r--r-- | tests/libdnssec/test_random.c | 82 | ||||
-rw-r--r-- | tests/libdnssec/test_shared_bignum.c | 128 | ||||
-rw-r--r-- | tests/libdnssec/test_shared_dname.c | 79 | ||||
-rw-r--r-- | tests/libdnssec/test_sign.c | 184 | ||||
-rw-r--r-- | tests/libdnssec/test_sign_der.c | 202 | ||||
-rw-r--r-- | tests/libdnssec/test_tsig.c | 145 |
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, ¶ms->public_key); + ok(r == DNSSEC_INVALID_KEY_ALGORITHM, + "set public key (fails, no algorithm set)"); + + check_attr_scalar(key, uint16_t, flags, 256, params->flags); + check_attr_scalar(key, uint8_t, protocol, 3, params->protocol); + check_attr_scalar(key, uint8_t, algorithm, 0, params->algorithm); + + r = dnssec_key_set_pubkey(key, ¶ms->public_key); + ok(r == DNSSEC_EOK, "set public key (succeeds)"); + + r = dnssec_key_set_pubkey(key, ¶ms->public_key); + ok(r == DNSSEC_KEY_ALREADY_PRESENT, + "set public key (fails, already present)"); + + dnssec_binary_t rdata = { 0 }; + r = dnssec_key_get_rdata(key, &rdata); + ok(r == DNSSEC_EOK && dnssec_binary_cmp(&rdata, ¶ms->rdata) == 0, + "get RDATA"); + + check_key_tag(key, params); + + // create from RDATA + + dnssec_key_clear(key); + r = dnssec_key_set_rdata(key, ¶ms->rdata); + ok(r == DNSSEC_EOK, "set RDATA"); + + check_key_tag(key, params); + check_key_size(key, params); + check_usage(key, true, false); + + // create copy + + dnssec_key_t *copy = dnssec_key_dup(key); + ok(copy != NULL, "duplicate key"); + + check_key_tag(copy, params); + check_key_size(copy, params); + check_usage(copy, true, false); + + dnssec_key_free(copy); + dnssec_key_free(key); +} + +static void test_private_key(const key_parameters_t *params) +{ + dnssec_key_t *key = NULL; + int r = dnssec_key_new(&key); + ok(r == DNSSEC_EOK && key != NULL, "create key"); + + // import to public + + r = dnssec_key_set_rdata(key, ¶ms->rdata); + ok(r == DNSSEC_EOK, "set RDATA"); + + r = dnssec_key_load_pkcs8(key, ¶ms->pem); + ok(r == DNSSEC_EOK, "load private key (1)"); + + ok(dnssec_key_can_verify(key), "can verify"); + ok(dnssec_key_can_sign(key), "can sign"); + + // purely from parameters + + dnssec_key_clear(key); + + dnssec_key_set_algorithm(key, params->algorithm); + dnssec_key_set_flags(key, params->flags); + r = dnssec_key_load_pkcs8(key, ¶ms->pem); + ok(r == DNSSEC_EOK, "load private key (2)"); + + dnssec_binary_t rdata = { 0 }; + r = dnssec_key_get_rdata(key, &rdata); + ok(r == DNSSEC_EOK && dnssec_binary_cmp(&rdata, ¶ms->rdata) == 0, + "get RDATA"); + + check_key_tag(key, params); + check_key_size(key, params); + check_usage(key, true, true); + + // create copy + + dnssec_key_t *copy = dnssec_key_dup(key); + ok(copy != NULL, "duplicate key"); + + check_key_tag(copy, params); + check_key_size(copy, params); + check_usage(copy, true, false); + + dnssec_key_free(copy); + dnssec_key_free(key); +} + +static void test_naming(void) +{ + dnssec_key_t *key = NULL; + dnssec_key_new(&key); + + const uint8_t *input = (uint8_t *)"\x07""eXample""\x03""COM"; + const uint8_t *expected = (uint8_t *)"\x07""example""\x03""com"; + size_t expected_size = 13; + + ok(dnssec_key_get_dname(key) == NULL, "implicit key name"); + + dnssec_key_set_dname(key, input); + const uint8_t *output = dnssec_key_get_dname(key); + + ok(strlen((char *)output) + 1 == 13 && + memcmp(output, expected, expected_size) == 0, + "set key name"); + + dnssec_key_set_dname(key, NULL); + ok(dnssec_key_get_dname(key) == NULL, "clear key name"); + + dnssec_key_free(key); +} + +typedef struct keyinfo { + const char *name; + const key_parameters_t *parameters; +} keyinfo_t; + +int main(void) +{ + plan_lazy(); + + dnssec_crypto_init(); + + static const keyinfo_t keys[] = { + { "RSA", &SAMPLE_RSA_KEY }, + { "ECDSA", &SAMPLE_ECDSA_KEY }, +#ifdef HAVE_ED25519 + { "ED25519", &SAMPLE_ED25519_KEY }, +#endif + { 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, ¶ms->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, ¶ms->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, ¶ms->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(¶ms, &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(¶ms); + 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, ¶ms, &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(¶ms, &RDATA); + ok(result == DNSSEC_EOK, "dnssec_nsec3_params_from_rdata()"); + + ok(memcmp(¶ms, &empty, sizeof(dnssec_nsec3_params_t)) != 0, + "non-empty after dnssec_nsec3_params_from_rdata()"); + + dnssec_nsec3_params_free(¶ms); + + ok(memcmp(¶ms, &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; +} |