]>
Commit | Line | Data |
---|---|---|
22de9dc8 PD |
1 | #define BOOST_TEST_DYN_LINK |
2 | #define BOOST_TEST_NO_MAIN | |
3 | #ifdef HAVE_CONFIG_H | |
4 | #include "config.h" | |
5 | #endif | |
6 | #include <boost/test/unit_test.hpp> | |
7 | #include <boost/assign/list_of.hpp> | |
8 | ||
9 | #include <boost/tuple/tuple.hpp> | |
10 | #include <boost/scoped_ptr.hpp> | |
11 | ||
12 | #include "base64.hh" | |
13 | #include "dnsseckeeper.hh" | |
14 | #include "dnssecinfra.hh" | |
15 | #include "misc.hh" | |
22de9dc8 PD |
16 | BOOST_AUTO_TEST_SUITE(test_signers) |
17 | ||
620d4801 RG |
18 | static const std::string message = "Very good, young padawan."; |
19 | ||
20 | static const struct signerParams | |
21 | { | |
22 | std::string iscMap; | |
23 | std::string dsSHA1; | |
24 | std::string dsSHA256; | |
25 | std::string dsSHA384; | |
26 | std::vector<uint8_t> signature; | |
27 | std::string zoneRepresentation; | |
28 | std::string name; | |
29 | std::string rfcMsgDump; | |
30 | std::string rfcB64Signature; | |
31 | unsigned int bits; | |
32 | uint16_t flags; | |
33 | uint16_t rfcFlags; | |
34 | uint8_t algorithm; | |
35 | bool isDeterministic; | |
36 | } signers[] = { | |
37 | /* RSA from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sample_keys.h */ | |
38 | { "Algorithm: 8\n" | |
39 | "Modulus: qtunSiHnYq4XRLBehKAw1Glxb+48oIpAC7w3Jhpj570bb2uHt6orWGqnuyRtK8oqUi2ABoV0PFm8+IPgDMEdCQ==\n" | |
40 | "PublicExponent: AQAB\n" | |
41 | "PrivateExponent: MiItniUAngXzMeaGdWgDq/AcpvlCtOCcFlVt4TJRKkfp8DNRSxIxG53NNlOFkp1W00iLHqYC2GrH1qkKgT9l+Q==\n" | |
42 | "Prime1: 3sZmM+5FKFy5xaRt0n2ZQOZ2C+CoKzVil6/al9LmYVs=\n" | |
43 | "Prime2: xFcNWSIW6v8dDL2JQ1kxFDm/8RVeUSs1BNXXnvCjBGs=\n" | |
44 | "Exponent1: WuUwhjfN1+4djlrMxHmisixWNfpwI1Eg7Ss/UXsnrMk=\n" | |
45 | "Exponent2: vfMqas1cNsXRqP3Fym6D2Pl2BRuTQBv5E1B/ZrmQPTk=\n" | |
46 | "Coefficient: Q10z43cA3hkwOkKsj5T0W5jrX97LBwZoY5lIjDCa4+M=\n", | |
47 | "1506 8 1 172a500b374158d1a64ba3073cdbbc319b2fdf2c", | |
48 | "1506 8 2 253b099ff47b02c6ffa52695a30a94c6681c56befe0e71a5077d6f79514972f9", | |
49 | "1506 8 4 22ea940600dc2d9a98b1126c26ac0dc5c91b31eb50fe784b36ad675e9eecfe6573c1f85c53b6bc94580f3ac443d13c4c", | |
50 | /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */ | |
51 | { 0x93, 0x93, 0x5f, 0xd8, 0xa1, 0x2b, 0x4c, 0x0b, 0xf3, 0x67, 0x42, 0x13, 0x52, 0x00, 0x35, 0xdc, 0x09, 0xe0, 0xdf, 0xe0, 0x3e, 0xc2, 0xcf, 0x64, 0xab, 0x9f, 0x9f, 0x51, 0x5f, 0x5c, 0x27, 0xbe, 0x13, 0xd6, 0x17, 0x07, 0xa6, 0xe4, 0x3b, 0x63, 0x44, 0x85, 0x06, 0x13, 0xaa, 0x01, 0x3c, 0x58, 0x52, 0xa3, 0x98, 0x20, 0x65, 0x03, 0xd0, 0x40, 0xc8, 0xa0, 0xe9, 0xd2, 0xc0, 0x03, 0x5a, 0xab }, | |
52 | "256 3 8 AwEAAarbp0oh52KuF0SwXoSgMNRpcW/uPKCKQAu8NyYaY+e9G29rh7eqK1hqp7skbSvKKlItgAaFdDxZvPiD4AzBHQk=", | |
53 | "rsa.", | |
54 | "", | |
55 | "", | |
56 | 512, | |
57 | 256, | |
58 | 0, | |
59 | DNSSECKeeper::RSASHA256, | |
60 | true | |
61 | }, | |
13f34f2e | 62 | #ifdef HAVE_BOTAN |
620d4801 RG |
63 | /* ECC-GOST from rfc5933 */ |
64 | { "Algorithm: 12\n" | |
65 | "GostAsn1: MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgQg/9MiXtXKg9FDXDN/R9CmVhJDyuzRAIgh4tPwCu4NHIs=\n", | |
66 | "59732 12 1 794287b8033625ae938c0341fd800fd5ce45a728", | |
67 | "59732 12 2 a7c24528480884ef4f5c0aaf85b3a20323a96722ccda26045aa7d304c9942868", | |
68 | "59732 12 4 6f43cc67087875a5f2115adbc29604f0b5a43be6f28be0deaf71e08168967f7a1a8218d063a6f9137133a721e60eed4f", | |
69 | { 0x1f, 0x3f, 0x2a, 0x2d, 0xc6, 0x72, 0x1d, 0xc8, 0xc4, 0x1f, 0x8b, 0xa1, 0xe8, 0x07, 0x83, 0x25, 0x9a, 0xbd, 0xc3, 0x80, 0xc1, 0x67, 0x80, 0xb7, 0x07, 0xed, 0xcb, 0xb0, 0x45, 0x5e, 0x46, 0x00, 0xcb, 0xa2, 0x7c, 0xf4, 0x7a, 0xa1, 0x81, 0x0c, 0xb2, 0xd1, 0xa1, 0xba, 0xb4, 0x53, 0xed, 0x8c, 0x10, 0x79, 0x12, 0x84, 0x9f, 0x9a, 0x69, 0xf5, 0x6d, 0x00, 0x4f, 0x06, 0x30, 0xba, 0xaa, 0xe6 }, | |
70 | "256 3 12 aRS/DcPWGQj2wVJydT8EcAVoC0kXn5pDVm2IMvDDPXeD32dsSKcmq8KNVzigjL4OXZTV+t/6w4X1gpNrZiC01g==", | |
71 | "gost.", | |
72 | "00 01 0c 03 00 00 0e 10 70 db d8 80 38 6d 43 80 e9 54 07 65 78 61 6d 70 6c 65 03 6e 65 74 00 03 77 77 77 07 65 78 61 6d 70 6c 65 03 6e 65 74 00 00 01 00 01 00 00 0e 10 00 04 c0 00 02 01 ", | |
73 | /* from rfc5933 */ | |
74 | "7vzzz6iLOmvtjs5FjVjSHT8XnRKFY15ki6KpkNPkUnS8iIns0Kv4APT+D9ibmHhGri6Sfbyyzi67+wBbbW/jrA==", | |
75 | 256, | |
76 | 256, | |
77 | 256, | |
78 | DNSSECKeeper::ECCGOST, | |
79 | false | |
80 | }, | |
13f34f2e | 81 | #endif /* HAVE_BOTAN */ |
620d4801 RG |
82 | #ifdef HAVE_LIBCRYPTO_ECDSA |
83 | /* ECDSA-P256-SHA256 from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sample_keys.h */ | |
84 | { "Algorithm: 13\n" | |
85 | "PrivateKey: iyLIPdk3DOIxVmmSYlmTstbtUPiVlEyDX46psyCwNVQ=\n", | |
86 | "5345 13 1 954103ac7c43810ce9f414e80f30ab1cbe49b236", | |
87 | "5345 13 2 bac2107036e735b50f85006ce409a19a3438cab272e70769ebda032239a3d0ca", | |
88 | "5345 13 4 a0ac6790483872be72a258314200a88ab75cdd70f66a18a09f0f414c074df0989fdb1df0e67d82d4312cda67b93a76c1", | |
89 | /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */ | |
90 | { 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, }, | |
91 | "256 3 13 8uD7C4THTM/w7uhryRSToeE/jKT78/p853RX0L5EwrZrSLBubLPiBw7gbvUP6SsIga5ZQ4CSAxNmYA/gZsuXzA==", | |
92 | "ecdsa.", | |
93 | "", | |
94 | "", | |
95 | 256, | |
96 | 256, | |
97 | 0, | |
98 | DNSSECKeeper::ECDSA256, | |
99 | false | |
100 | }, | |
101 | #endif /* HAVE_LIBCRYPTO_ECDSA */ | |
2b7da695 | 102 | #if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBDECAF) |
620d4801 RG |
103 | /* ed25519 from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sample_keys.h, |
104 | also from rfc8080 section 6.1 */ | |
105 | { "Algorithm: 15\n" | |
106 | "PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=\n", | |
107 | "3612 15 1 501249721e1f09a79d30d5c6c4dca1dc1da4ed5d", | |
108 | "3612 15 2 1b1c8766b2a96566ff196f77c0c4194af86aaa109c5346ff60231a27d2b07ac0", | |
109 | "3612 15 4 d11831153af4985efbd0ae792c967eb4aff3c35488db95f7e2f85dcec74ae8f59f9a72641798c91c67c675db1d710c18", | |
110 | /* from https://github.com/CZ-NIC/knot/blob/master/src/dnssec/tests/sign.c */ | |
111 | { 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 }, | |
112 | "256 3 15 l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4=", | |
113 | "ed25519.", | |
114 | // vector extracted from https://gitlab.labs.nic.cz/labs/ietf/blob/master/dnskey.py (rev 476d6ded) by printing signature_data | |
115 | "00 0f 0f 02 00 00 0e 10 55 d4 fc 60 55 b9 4c e0 0e 1d 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 0f 00 01 00 00 0e 10 00 14 00 0a 04 6d 61 69 6c 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 ", | |
116 | // vector verified from dnskey.py as above, and confirmed with https://www.rfc-editor.org/errata_search.php?rfc=8080&eid=4935 | |
117 | "oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jPGrHpjQeRAvTdszaPD+QLs3fx8A4M3e23mRZ9VrbpMngwcrqNAg==", | |
118 | 256, | |
119 | 256, | |
120 | 257, | |
121 | DNSSECKeeper::ED25519, | |
122 | true | |
123 | }, | |
124 | #endif /* defined(HAVE_LIBSODIUM) || defined(HAVE_LIBDECAF) */ | |
125 | }; | |
22de9dc8 | 126 | |
620d4801 RG |
127 | static void checkRR(const signerParams& signer) |
128 | { | |
129 | DNSKEYRecordContent drc; | |
130 | auto dcke = DNSCryptoKeyEngine::makeFromISCString(drc, signer.iscMap); | |
131 | DNSSECPrivateKey dpk; | |
132 | dpk.setKey(dcke); | |
133 | dpk.d_flags = signer.rfcFlags; | |
22de9dc8 | 134 | |
620d4801 RG |
135 | vector<std::shared_ptr<DNSRecordContent> > rrs; |
136 | /* values taken from rfc8080 for ed25519 and ed448, rfc5933 for gost */ | |
137 | DNSName qname(dpk.d_algorithm == 12 ? "www.example.net." : "example.com."); | |
22de9dc8 | 138 | |
620d4801 | 139 | reportBasicTypes(); |
22de9dc8 | 140 | |
620d4801 RG |
141 | RRSIGRecordContent rrc; |
142 | uint32_t expire = 1440021600; | |
143 | uint32_t inception = 1438207200; | |
22de9dc8 | 144 | |
620d4801 RG |
145 | if (dpk.d_algorithm == 12) { |
146 | rrc.d_signer = DNSName("example.net."); | |
147 | inception = 946684800; | |
148 | expire = 1893456000; | |
149 | rrs.push_back(DNSRecordContent::makeunique(QType::A, QClass::IN, "192.0.2.1")); | |
150 | } | |
151 | else { | |
22de9dc8 | 152 | rrc.d_signer = qname; |
620d4801 RG |
153 | rrs.push_back(DNSRecordContent::makeunique(QType::MX, QClass::IN, "10 mail.example.com.")); |
154 | } | |
22de9dc8 | 155 | |
620d4801 RG |
156 | rrc.d_originalttl = 3600; |
157 | rrc.d_sigexpire = expire; | |
158 | rrc.d_siginception = inception; | |
159 | rrc.d_type = rrs.at(0)->getType(); | |
160 | rrc.d_labels = qname.countLabels(); | |
161 | rrc.d_tag = dpk.getTag(); | |
162 | rrc.d_algorithm = dpk.d_algorithm; | |
22de9dc8 | 163 | |
620d4801 RG |
164 | string msg = getMessageForRRSET(qname, rrc, rrs, false); |
165 | ||
166 | BOOST_CHECK_EQUAL(makeHexDump(msg), signer.rfcMsgDump); | |
167 | ||
168 | string signature = dcke->sign(msg); | |
22de9dc8 | 169 | |
620d4801 RG |
170 | BOOST_CHECK(dcke->verify(msg, signature)); |
171 | ||
172 | if (signer.isDeterministic) { | |
22de9dc8 | 173 | string b64 = Base64Encode(signature); |
620d4801 RG |
174 | BOOST_CHECK_EQUAL(b64, signer.rfcB64Signature); |
175 | } | |
176 | else { | |
177 | std::string raw; | |
178 | B64Decode(signer.rfcB64Signature, raw); | |
179 | BOOST_CHECK(dcke->verify(msg, raw)); | |
180 | } | |
181 | } | |
22de9dc8 | 182 | |
620d4801 RG |
183 | BOOST_AUTO_TEST_CASE(test_generic_signers) |
184 | { | |
185 | for (const auto signer : signers) { | |
186 | DNSKEYRecordContent drc; | |
187 | auto dcke = DNSCryptoKeyEngine::makeFromISCString(drc, signer.iscMap); | |
188 | ||
189 | BOOST_CHECK_EQUAL(dcke->getAlgorithm(), signer.algorithm); | |
190 | BOOST_CHECK_EQUAL(dcke->getBits(), signer.bits); | |
191 | BOOST_CHECK_EQUAL(dcke->checkKey(), true); | |
192 | ||
193 | BOOST_CHECK_EQUAL(drc.d_algorithm, signer.algorithm); | |
194 | ||
195 | DNSSECPrivateKey dpk; | |
196 | dpk.setKey(dcke); | |
197 | dpk.d_flags = signer.flags; | |
198 | drc = dpk.getDNSKEY(); | |
199 | ||
200 | BOOST_CHECK_EQUAL(drc.d_algorithm, signer.algorithm); | |
201 | BOOST_CHECK_EQUAL(drc.d_protocol, 3); | |
202 | BOOST_CHECK_EQUAL(drc.getZoneRepresentation(), signer.zoneRepresentation); | |
203 | ||
204 | DNSName name(signer.name); | |
205 | auto ds1 = makeDSFromDNSKey(name, drc, DNSSECKeeper::SHA1); | |
206 | if (!signer.dsSHA1.empty()) { | |
207 | BOOST_CHECK_EQUAL(ds1.getZoneRepresentation(), signer.dsSHA1); | |
208 | } | |
209 | ||
210 | auto ds2 = makeDSFromDNSKey(name, drc, DNSSECKeeper::SHA256); | |
211 | if (!signer.dsSHA256.empty()) { | |
212 | BOOST_CHECK_EQUAL(ds2.getZoneRepresentation(), signer.dsSHA256); | |
213 | } | |
214 | ||
215 | auto ds4 = makeDSFromDNSKey(name, drc, DNSSECKeeper::SHA384); | |
216 | if (!signer.dsSHA384.empty()) { | |
217 | BOOST_CHECK_EQUAL(ds4.getZoneRepresentation(), signer.dsSHA384); | |
218 | } | |
219 | ||
220 | auto signature = dcke->sign(message); | |
221 | BOOST_CHECK(dcke->verify(message, signature)); | |
222 | ||
223 | if (signer.isDeterministic) { | |
224 | BOOST_CHECK_EQUAL(signature, std::string(signer.signature.begin(), signer.signature.end())); | |
225 | } else { | |
226 | /* since the signing process is not deterministic, we can't directly compare our signature | |
227 | with the one we have. Still the one we have should also validate correctly. */ | |
228 | BOOST_CHECK(dcke->verify(message, std::string(signer.signature.begin(), signer.signature.end()))); | |
229 | } | |
230 | ||
231 | if (!signer.rfcMsgDump.empty() && !signer.rfcB64Signature.empty()) { | |
232 | checkRR(signer); | |
233 | } | |
234 | } | |
22de9dc8 | 235 | } |
22de9dc8 | 236 | |
2b7da695 KM |
237 | #ifdef HAVE_LIBDECAF |
238 | BOOST_AUTO_TEST_CASE(test_ed448_signer) { | |
239 | vector<std::shared_ptr<DNSRecordContent> > rrs; | |
240 | DNSName qname("example.com."); | |
241 | DNSKEYRecordContent drc; | |
242 | ||
243 | // TODO: make this a collection of inputs and resulting sigs for various algos | |
244 | shared_ptr<DNSCryptoKeyEngine> engine = DNSCryptoKeyEngine::makeFromISCString(drc, | |
245 | "Private-key-format: v1.2\n" | |
246 | "Algorithm: 16 (ED448)\n" | |
247 | "PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA\n"); | |
248 | ||
249 | DNSSECPrivateKey dpk; | |
250 | dpk.setKey(engine); | |
251 | ||
252 | reportBasicTypes(); | |
253 | ||
254 | rrs.push_back(DNSRecordContent::makeunique(QType::MX, 1, "10 mail.example.com.")); | |
255 | ||
256 | RRSIGRecordContent rrc; | |
257 | rrc.d_originalttl = 3600; | |
258 | rrc.d_sigexpire = 1440021600; | |
259 | rrc.d_siginception = 1438207200; | |
260 | rrc.d_signer = qname; | |
261 | rrc.d_type = QType::MX; | |
262 | rrc.d_labels = 2; | |
263 | // TODO: derive the next two from the key | |
264 | rrc.d_tag = 9713; | |
265 | rrc.d_algorithm = 16; | |
266 | ||
267 | string msg = getMessageForRRSET(qname, rrc, rrs, false); | |
268 | ||
269 | // vector extracted from https://gitlab.labs.nic.cz/labs/ietf/blob/master/dnskey.py (rev 476d6ded) by printing signature_data | |
270 | BOOST_CHECK_EQUAL(makeHexDump(msg), "00 0f 10 02 00 00 0e 10 55 d4 fc 60 55 b9 4c e0 25 f1 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 0f 00 01 00 00 0e 10 00 14 00 0a 04 6d 61 69 6c 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 "); | |
271 | ||
272 | string signature = engine->sign(msg); | |
273 | string b64 = Base64Encode(signature); | |
274 | ||
275 | // vector verified from dnskey.py as above, and confirmed with https://www.rfc-editor.org/errata_search.php?rfc=8080&eid=4935 | |
276 | BOOST_CHECK_EQUAL(b64, "3cPAHkmlnxcDHMyg7vFC34l0blBhuG1qpwLmjInI8w1CMB29FkEAIJUA0amxWndkmnBZ6SKiwZSAxGILn/NBtOXft0+Gj7FSvOKxE/07+4RQvE581N3Aj/JtIyaiYVdnYtyMWbSNyGEY2213WKsJlwEA"); | |
277 | } | |
278 | #endif | |
279 | ||
22de9dc8 | 280 | BOOST_AUTO_TEST_SUITE_END() |