1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 #include <config.h>
13
14 #if HAVE_CMOCKA
15
16 #include <stdarg.h>
17 #include <stddef.h>
18 #include <setjmp.h>
19
20 #include <sched.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #define UNIT_TESTING
26 #include <cmocka.h>
27
28 #include <isc/util.h>
29 #include <isc/print.h>
30 #include <isc/string.h>
31
32 #include "dnstest.h"
33
34 #ifdef HAVE_OPENSSL_GOST
35 #include "../dst_gost.h"
36 #include <openssl/err.h>
37 #include <openssl/objects.h>
38 #include <openssl/rsa.h>
39 #include <openssl/engine.h>
40 #include <openssl/bn.h>
41 #endif
42
43 #ifdef HAVE_PKCS11_GOST
44 #include "../dst_gost.h"
45 #include <pk11/internal.h>
46 #define WANT_GOST_PARAMS
47 #include <pk11/constants.h>
48 #include <pkcs11/pkcs11.h>
49 #endif
50
51 #if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
52 static int
_setup(void ** state)53 _setup(void **state) {
54 isc_result_t result;
55
56 UNUSED(state);
57
58 result = dns_test_begin(NULL, false);
59 assert_int_equal(result, ISC_R_SUCCESS);
60
61 return (0);
62 }
63
64 static int
_teardown(void ** state)65 _teardown(void **state) {
66 UNUSED(state);
67
68 dns_test_end();
69
70 return (0);
71 }
72
73 /*
74 * Test data from Wikipedia GOST (hash function)
75 */
76
77 unsigned char digest[ISC_GOST_DIGESTLENGTH];
78 unsigned char buffer[1024];
79 const char *s;
80 char str[2 * ISC_GOST_DIGESTLENGTH + 3];
81 int i = 0;
82
83 /*
84 * Precondition: a hexadecimal number in *d, the length of that number in len,
85 * and a pointer to a character array to put the output (*out).
86 * Postcondition: A String representation of the given hexadecimal number is
87 * placed into the array *out
88 *
89 * 'out' MUST point to an array of at least len * 2 + 1
90 *
91 * Return values: ISC_R_SUCCESS if the operation is successful
92 */
93 static isc_result_t
tohexstr(unsigned char * d,unsigned int len,char * out,size_t out_size)94 tohexstr(unsigned char *d, unsigned int len, char *out, size_t out_size) {
95 char c_ret[] = "AA";
96 unsigned int j;
97
98 out[0] = '\0';
99 strlcat(out, "0x", out_size);
100 for (j = 0; j < len; j++) {
101 snprintf(c_ret, sizeof(c_ret), "%02X", d[j]);
102 strlcat(out, c_ret, out_size);
103 }
104 return (ISC_R_SUCCESS);
105 }
106
107
108 #define TEST_INPUT(x) (x), sizeof(x)-1
109
110 typedef struct hash_testcase {
111 const char *input;
112 size_t input_len;
113 const char *result;
114 int repeats;
115 } hash_testcase_t;
116
117 /* GOST R 34.11-94 examples from Wikipedia */
118 static void
isc_gost_md(void ** state)119 isc_gost_md(void **state) {
120 isc_gost_t gost;
121 isc_result_t result;
122
123 UNUSED(state);
124
125 /*
126 * These are the various test vectors. All of these are passed
127 * through the hash function and the results are compared to the
128 * result specified here.
129 */
130 hash_testcase_t testcases[] = {
131 /* Test 1 */
132 {
133 TEST_INPUT(""),
134 "0x981E5F3CA30C841487830F84FB433E1"
135 "3AC1101569B9C13584AC483234CD656C0",
136 1
137 },
138 /* Test 2 */
139 {
140 TEST_INPUT("a"),
141 "0xE74C52DD282183BF37AF0079C9F7805"
142 "5715A103F17E3133CEFF1AACF2F403011",
143 1
144 },
145 /* Test 3 */
146 {
147 TEST_INPUT("abc"),
148 "0xB285056DBF18D7392D7677369524DD1"
149 "4747459ED8143997E163B2986F92FD42C",
150 1
151 },
152 /* Test 4 */
153 {
154 TEST_INPUT("message digest"),
155 "0xBC6041DD2AA401EBFA6E9886734174F"
156 "EBDB4729AA972D60F549AC39B29721BA0",
157 1
158 },
159 /* Test 5 */
160 {
161 TEST_INPUT("The quick brown fox jumps "
162 "over the lazy dog"),
163 "0x9004294A361A508C586FE53D1F1B027"
164 "46765E71B765472786E4770D565830A76",
165 1
166 },
167
168 /* Test 6 */
169 {
170 TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"
171 "fghijklmnopqrstuvwxyz0123456789"),
172 "0x73B70A39497DE53A6E08C67B6D4DB85"
173 "3540F03E9389299D9B0156EF7E85D0F61",
174 1
175 },
176 /* Test 7 */
177 {
178 TEST_INPUT("1234567890123456789012345678901"
179 "2345678901234567890123456789012"
180 "345678901234567890"),
181 "0x6BC7B38989B28CF93AE8842BF9D7529"
182 "05910A7528A61E5BCE0782DE43E610C90",
183 1
184 },
185 /* Test 8 */
186 {
187 TEST_INPUT("This is message, length=32 bytes"),
188 "0x2CEFC2F7B7BDC514E18EA57FA74FF35"
189 "7E7FA17D652C75F69CB1BE7893EDE48EB",
190 1
191 },
192 /* Test 9 */
193 {
194 TEST_INPUT("Suppose the original message "
195 "has length = 50 bytes"),
196 "0xC3730C5CBCCACF915AC292676F21E8B"
197 "D4EF75331D9405E5F1A61DC3130A65011",
198 1
199 },
200 /* Test 10 */
201 {
202 TEST_INPUT("U") /* times 128 */,
203 "0x1C4AC7614691BBF427FA2316216BE8F"
204 "10D92EDFD37CD1027514C1008F649C4E8",
205 128
206 },
207 /* Test 11 */
208 {
209 TEST_INPUT("a") /* times 1000000 */,
210 "0x8693287AA62F9478F7CB312EC0866B6"
211 "C4E4A0F11160441E8F4FFCD2715DD554F",
212 1000000
213 },
214 { NULL, 0, NULL, 1 }
215 };
216
217 hash_testcase_t *testcase = testcases;
218
219 while (testcase->input != NULL && testcase->result != NULL) {
220 result = isc_gost_init(&gost);
221 assert_int_equal(result, ISC_R_SUCCESS);
222 for(i = 0; i < testcase->repeats; i++) {
223 result = isc_gost_update(&gost,
224 (const uint8_t *) testcase->input,
225 testcase->input_len);
226 assert_int_equal(result, ISC_R_SUCCESS);
227 }
228 result = isc_gost_final(&gost, digest);
229 assert_int_equal(result, ISC_R_SUCCESS);
230 tohexstr(digest, ISC_GOST_DIGESTLENGTH, str, sizeof(str));
231 assert_string_equal(str, testcase->result);
232
233 testcase++;
234 }
235 }
236
237 /* GOST R 34.10-2001 private key */
238 static void
isc_gost_private(void ** state)239 isc_gost_private(void **state) {
240 unsigned char privraw[31] = {
241 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
242 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
243 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
244 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
245 };
246 #ifdef HAVE_OPENSSL_GOST
247 unsigned char rbuf[32];
248 unsigned char privasn1[70] = {
249 0x30, 0x44, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
250 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
251 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
252 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
253 0x02, 0x1e, 0x01, 0x04, 0x21, 0x02, 0x1f, 0x01,
254 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
255 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
256 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
257 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
258 };
259 unsigned char abuf[71];
260 unsigned char gost_dummy_key[71] = {
261 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
262 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
263 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
264 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
265 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20, 0x1b,
266 0x3f, 0x94, 0xf7, 0x1a, 0x5f, 0x2f, 0xe7, 0xe5,
267 0x74, 0x0b, 0x8c, 0xd4, 0xb7, 0x18, 0xdd, 0x65,
268 0x68, 0x26, 0xd1, 0x54, 0xfb, 0x77, 0xba, 0x63,
269 0x72, 0xd9, 0xf0, 0x63, 0x87, 0xe0, 0xd6
270 };
271 EVP_PKEY *pkey;
272 EC_KEY *eckey;
273 BIGNUM *privkey;
274 const BIGNUM *privkey1;
275 const unsigned char *p;
276 int len;
277 unsigned char *q;
278
279 UNUSED(state);
280
281 /* raw parse */
282 privkey = BN_bin2bn(privraw, (int) sizeof(privraw), NULL);
283 assert_non_null(privkey);
284 p = gost_dummy_key;
285 pkey = NULL;
286 assert_non_null(d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
287 (long) sizeof(gost_dummy_key)));
288 assert_non_null(pkey);
289 assert_int_equal(EVP_PKEY_bits(pkey), 256);
290 eckey = EVP_PKEY_get0(pkey);
291 assert_non_null(eckey);
292 assert_int_equal(EC_KEY_set_private_key(eckey, privkey), 1);
293 BN_clear_free(privkey);
294
295 /* asn1 tofile */
296 len = i2d_PrivateKey(pkey, NULL);
297 assert_int_equal(len, 70);
298 q = abuf;
299 assert_int_equal(i2d_PrivateKey(pkey, &q), len);
300 assert_int_equal(memcmp(abuf, privasn1, len), 0);
301 EVP_PKEY_free(pkey);
302
303 /* asn1 parse */
304 p = privasn1;
305 pkey = NULL;
306 assert_non_null(d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
307 (long) len));
308 assert_non_null(pkey);
309 eckey = EVP_PKEY_get0(pkey);
310 assert_non_null(eckey);
311 privkey1 = EC_KEY_get0_private_key(eckey);
312 len = BN_num_bytes(privkey1);
313 assert_int_equal(len, 31);
314 assert_int_equal(BN_bn2bin(privkey1, rbuf), len);
315 assert_memory_equal(rbuf, privraw, len);
316 #else
317 CK_BBOOL truevalue = TRUE;
318 CK_BBOOL falsevalue = FALSE;
319 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
320 CK_KEY_TYPE keyType = CKK_GOSTR3410;
321 CK_ATTRIBUTE keyTemplate[] =
322 {
323 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
324 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
325 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
326 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
327 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
328 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
329 { CKA_VALUE, privraw, sizeof(privraw) },
330 { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset,
331 (CK_ULONG) sizeof(pk11_gost_a_paramset) },
332 { CKA_GOSTR3411_PARAMS, pk11_gost_paramset,
333 (CK_ULONG) sizeof(pk11_gost_paramset) }
334 };
335 CK_MECHANISM mech = { CKM_GOSTR3410_WITH_GOSTR3411, NULL, 0 };
336 CK_BYTE sig[64];
337 CK_ULONG siglen;
338 pk11_context_t pk11_ctx;
339
340 /* create the private key */
341 memset(&pk11_ctx, 0, sizeof(pk11_ctx));
342 assert_int_equal(pk11_get_session(&pk11_ctx, OP_GOST, true,
343 false, false, NULL,
344 pk11_get_best_token(OP_GOST)),
345 ISC_R_SUCCESS);
346 pk11_ctx.object = CK_INVALID_HANDLE;
347 pk11_ctx.ontoken = false;
348 assert_int_equal(pkcs_C_CreateObject(pk11_ctx.session, keyTemplate,
349 (CK_ULONG) 9,
350 &pk11_ctx.object),
351 CKR_OK);
352 assert_int_not_equal(pk11_ctx.object, CK_INVALID_HANDLE);
353
354 /* sign something */
355 assert_int_equal(pkcs_C_SignInit(pk11_ctx.session, &mech,
356 pk11_ctx.object),
357 CKR_OK);
358 siglen = 0;
359 assert_int_equal(pkcs_C_Sign(pk11_ctx.session, sig, 64,
360 NULL, &siglen),
361 CKR_OK);
362 assert_int_equal(siglen, 64);
363 assert_int_equal(pkcs_C_Sign(pk11_ctx.session, sig, 64,
364 sig, &siglen),
365 CKR_OK);
366 assert_int_equal(siglen, 64);
367 #endif
368 };
369 #endif
370
371 int
main(void)372 main(void) {
373 #if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
374 const struct CMUnitTest tests[] = {
375 cmocka_unit_test_setup_teardown(isc_gost_md,
376 _setup, _teardown),
377 cmocka_unit_test_setup_teardown(isc_gost_private,
378 _setup, _teardown),
379 };
380
381 return (cmocka_run_group_tests(tests, dns_test_init, dns_test_final));
382 #else
383 print_message("1..0 # Skip GOST is unavailable");
384 #endif
385 }
386
387 #else /* HAVE_CMOCKA */
388
389 #include <stdio.h>
390
391 int
main(void)392 main(void) {
393 printf("1..0 # Skipped: cmocka not available\n");
394 return (0);
395 }
396
397 #endif
398