xref: /minix3/external/bsd/bind/dist/lib/dns/tests/gost_test.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1 /*	$NetBSD: gost_test.c,v 1.1.1.6 2015/07/08 15:38:04 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /* Id */
20 
21 /* ! \file */
22 
23 #include <config.h>
24 
25 #include <atf-c.h>
26 
27 #include <stdio.h>
28 #include <string.h>
29 
30 #include <isc/util.h>
31 #include <isc/string.h>
32 
33 #include "dnstest.h"
34 
35 #ifdef HAVE_OPENSSL_GOST
36 #include "../dst_gost.h"
37 #include <openssl/err.h>
38 #include <openssl/objects.h>
39 #include <openssl/rsa.h>
40 #include <openssl/engine.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 /*
53  * Test data from Wikipedia GOST (hash function)
54  */
55 
56 unsigned char digest[ISC_GOST_DIGESTLENGTH];
57 unsigned char buffer[1024];
58 const char *s;
59 char str[2 * ISC_GOST_DIGESTLENGTH + 1];
60 int i = 0;
61 
62 isc_result_t
63 tohexstr(unsigned char *d, unsigned int len, char *out);
64 /*
65  * Precondition: a hexadecimal number in *d, the length of that number in len,
66  *   and a pointer to a character array to put the output (*out).
67  * Postcondition: A String representation of the given hexadecimal number is
68  *   placed into the array *out
69  *
70  * 'out' MUST point to an array of at least len * 2 + 1
71  *
72  * Return values: ISC_R_SUCCESS if the operation is sucessful
73  */
74 
75 isc_result_t
tohexstr(unsigned char * d,unsigned int len,char * out)76 tohexstr(unsigned char *d, unsigned int len, char *out) {
77 
78 	out[0]='\0';
79 	char c_ret[] = "AA";
80 	unsigned int j;
81 	strcat(out, "0x");
82 	for (j = 0; j < len; j++) {
83 		sprintf(c_ret, "%02X", d[j]);
84 		strcat(out, c_ret);
85 	}
86 	strcat(out, "\0");
87 	return (ISC_R_SUCCESS);
88 }
89 
90 
91 #define TEST_INPUT(x) (x), sizeof(x)-1
92 
93 typedef struct hash_testcase {
94 	const char *input;
95 	size_t input_len;
96 	const char *result;
97 	int repeats;
98 } hash_testcase_t;
99 
100 ATF_TC(isc_gost_md);
ATF_TC_HEAD(isc_gost_md,tc)101 ATF_TC_HEAD(isc_gost_md, tc) {
102 	atf_tc_set_md_var(tc, "descr",
103 			  "GOST R 34.11-94 examples from Wikipedia");
104 }
ATF_TC_BODY(isc_gost_md,tc)105 ATF_TC_BODY(isc_gost_md, tc) {
106 	isc_gost_t gost;
107 	isc_result_t result;
108 
109 	UNUSED(tc);
110 
111 	/*
112 	 * These are the various test vectors.  All of these are passed
113 	 * through the hash function and the results are compared to the
114 	 * result specified here.
115 	 */
116 	hash_testcase_t testcases[] = {
117 		/* Test 1 */
118 		{
119 			TEST_INPUT(""),
120 			"0x981E5F3CA30C841487830F84FB433E1"
121 			"3AC1101569B9C13584AC483234CD656C0",
122 			1
123 		},
124 		/* Test 2 */
125 		{
126 			TEST_INPUT("a"),
127 			"0xE74C52DD282183BF37AF0079C9F7805"
128 			"5715A103F17E3133CEFF1AACF2F403011",
129 			1
130 		},
131 		/* Test 3 */
132 		{
133 			TEST_INPUT("abc"),
134 			"0xB285056DBF18D7392D7677369524DD1"
135 			"4747459ED8143997E163B2986F92FD42C",
136 			1
137 		},
138 		/* Test 4 */
139 		{
140 			TEST_INPUT("message digest"),
141 			"0xBC6041DD2AA401EBFA6E9886734174F"
142 			"EBDB4729AA972D60F549AC39B29721BA0",
143 			1
144 		},
145 		/* Test 5 */
146 		{
147 			TEST_INPUT("The quick brown fox jumps "
148 				   "over the lazy dog"),
149 			"0x9004294A361A508C586FE53D1F1B027"
150 			"46765E71B765472786E4770D565830A76",
151 			1
152 		},
153 
154 		/* Test 6 */
155 		{
156 			TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"
157 				   "fghijklmnopqrstuvwxyz0123456789"),
158 			"0x73B70A39497DE53A6E08C67B6D4DB85"
159 			"3540F03E9389299D9B0156EF7E85D0F61",
160 			1
161 		},
162 		/* Test 7 */
163 		{
164 			TEST_INPUT("1234567890123456789012345678901"
165 				   "2345678901234567890123456789012"
166 				   "345678901234567890"),
167 			"0x6BC7B38989B28CF93AE8842BF9D7529"
168 			"05910A7528A61E5BCE0782DE43E610C90",
169 			1
170 		},
171 		/* Test 8 */
172 		{
173 			TEST_INPUT("This is message, length=32 bytes"),
174 			"0x2CEFC2F7B7BDC514E18EA57FA74FF35"
175 			"7E7FA17D652C75F69CB1BE7893EDE48EB",
176 			1
177 		},
178 		/* Test 9 */
179 		{
180 			TEST_INPUT("Suppose the original message "
181 				   "has length = 50 bytes"),
182 			"0xC3730C5CBCCACF915AC292676F21E8B"
183 			"D4EF75331D9405E5F1A61DC3130A65011",
184 			1
185 		},
186 		/* Test 10 */
187 		{
188 			TEST_INPUT("U") /* times 128 */,
189 			"0x1C4AC7614691BBF427FA2316216BE8F"
190 			"10D92EDFD37CD1027514C1008F649C4E8",
191 			128
192 		},
193 		/* Test 11 */
194 		{
195 			TEST_INPUT("a") /* times 1000000 */,
196 			"0x8693287AA62F9478F7CB312EC0866B6"
197 			"C4E4A0F11160441E8F4FFCD2715DD554F",
198 			1000000
199 		},
200 		{ NULL, 0, NULL, 1 }
201 	};
202 
203 	result = dns_test_begin(NULL, ISC_FALSE);
204 	ATF_REQUIRE(result == ISC_R_SUCCESS);
205 
206 	hash_testcase_t *testcase = testcases;
207 
208 	while (testcase->input != NULL && testcase->result != NULL) {
209 		result = isc_gost_init(&gost);
210 		ATF_REQUIRE(result == ISC_R_SUCCESS);
211 		for(i = 0; i < testcase->repeats; i++) {
212 			result = isc_gost_update(&gost,
213 					(const isc_uint8_t *) testcase->input,
214 					testcase->input_len);
215 			ATF_REQUIRE(result == ISC_R_SUCCESS);
216 		}
217 		result = isc_gost_final(&gost, digest);
218 		ATF_REQUIRE(result == ISC_R_SUCCESS);
219 		tohexstr(digest, ISC_GOST_DIGESTLENGTH, str);
220 		ATF_CHECK_STREQ(str, testcase->result);
221 
222 		testcase++;
223 	}
224 
225 	dns_test_end();
226 }
227 
228 ATF_TC(isc_gost_private);
ATF_TC_HEAD(isc_gost_private,tc)229 ATF_TC_HEAD(isc_gost_private, tc) {
230   atf_tc_set_md_var(tc, "descr", "GOST R 34.10-2001 private key");
231 }
ATF_TC_BODY(isc_gost_private,tc)232 ATF_TC_BODY(isc_gost_private, tc) {
233 	isc_result_t result;
234 	unsigned char privraw[31] = {
235 		0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
236 		0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
237 		0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
238 		0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
239 	};
240 #ifdef HAVE_OPENSSL_GOST
241 	unsigned char rbuf[32];
242 	unsigned char privasn1[70] = {
243 		0x30, 0x44, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
244 		0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
245 		0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
246 		0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
247 		0x02, 0x1e, 0x01, 0x04, 0x21, 0x02, 0x1f, 0x01,
248 		0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
249 		0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
250 		0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
251 		0x1a, 0x1b, 0x1c, 0x1d, 0x1e
252 	};
253 	unsigned char abuf[71];
254 	unsigned char gost_dummy_key[71] = {
255 		0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
256 		0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
257 		0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
258 		0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
259 		0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20, 0x1b,
260 		0x3f, 0x94, 0xf7, 0x1a, 0x5f, 0x2f, 0xe7, 0xe5,
261 		0x74, 0x0b, 0x8c, 0xd4, 0xb7, 0x18, 0xdd, 0x65,
262 		0x68, 0x26, 0xd1, 0x54, 0xfb, 0x77, 0xba, 0x63,
263 		0x72, 0xd9, 0xf0, 0x63, 0x87, 0xe0, 0xd6
264 	};
265 	EVP_PKEY *pkey;
266 	EC_KEY *eckey;
267 	BIGNUM *privkey;
268 	const BIGNUM *privkey1;
269 	const unsigned char *p;
270 	int len;
271 	unsigned char *q;
272 
273 	result = dns_test_begin(NULL, ISC_FALSE);
274 	ATF_REQUIRE(result == ISC_R_SUCCESS);
275 
276 	/* raw parse */
277 	privkey = BN_bin2bn(privraw, (int) sizeof(privraw), NULL);
278 	ATF_REQUIRE(privkey != NULL);
279 	p = gost_dummy_key;
280 	pkey = NULL;
281 	ATF_REQUIRE(d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
282 				   (long) sizeof(gost_dummy_key)) != NULL);
283 	ATF_REQUIRE(pkey != NULL);
284 	ATF_REQUIRE(EVP_PKEY_bits(pkey) == 256);
285 	eckey = EVP_PKEY_get0(pkey);
286 	ATF_REQUIRE(eckey != NULL);
287 	ATF_REQUIRE(EC_KEY_set_private_key(eckey, privkey) == 1);
288 	BN_clear_free(privkey);
289 
290 	/* asn1 tofile */
291 	len = i2d_PrivateKey(pkey, NULL);
292 	ATF_REQUIRE(len == 70);
293 	q = abuf;
294 	ATF_REQUIRE(i2d_PrivateKey(pkey, &q) == len);
295 	ATF_REQUIRE(memcmp(abuf, privasn1, len) == 0);
296 	EVP_PKEY_free(pkey);
297 
298 	/* asn1 parse */
299 	p = privasn1;
300 	pkey = NULL;
301 	ATF_REQUIRE(d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
302 				   (long) len) != NULL);
303 	ATF_REQUIRE(pkey != NULL);
304 	eckey = EVP_PKEY_get0(pkey);
305 	ATF_REQUIRE(eckey != NULL);
306 	privkey1 = EC_KEY_get0_private_key(eckey);
307 	len = BN_num_bytes(privkey1);
308 	ATF_REQUIRE(len == 31);
309 	ATF_REQUIRE(BN_bn2bin(privkey1, rbuf) == len);
310 	ATF_REQUIRE(memcmp(rbuf, privraw, len) == 0);
311 
312 	dns_test_end();
313 #else
314 	CK_BBOOL truevalue = TRUE;
315 	CK_BBOOL falsevalue = FALSE;
316 	CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
317 	CK_KEY_TYPE keyType = CKK_GOSTR3410;
318 	CK_ATTRIBUTE keyTemplate[] =
319 	{
320 		{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
321 		{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
322 		{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
323 		{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
324 		{ CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
325 		{ CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
326 		{ CKA_VALUE, privraw, sizeof(privraw) },
327 		{ CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset,
328 		  (CK_ULONG) sizeof(pk11_gost_a_paramset) },
329 		{ CKA_GOSTR3411_PARAMS, pk11_gost_paramset,
330 		  (CK_ULONG) sizeof(pk11_gost_paramset) }
331 	};
332 	CK_MECHANISM mech = { CKM_GOSTR3410_WITH_GOSTR3411, NULL, 0 };
333 	CK_BYTE sig[64];
334 	CK_ULONG siglen;
335 	pk11_context_t pk11_ctx;
336 
337 	result = dns_test_begin(NULL, ISC_FALSE);
338 	ATF_REQUIRE(result == ISC_R_SUCCESS);
339 
340 	/* create the private key */
341 	memset(&pk11_ctx, 0, sizeof(pk11_ctx));
342 	ATF_REQUIRE(pk11_get_session(&pk11_ctx, OP_GOST, ISC_TRUE,
343 				     ISC_FALSE, ISC_FALSE, NULL,
344 				     pk11_get_best_token(OP_GOST)) ==
345 		    ISC_R_SUCCESS);
346 	pk11_ctx.object = CK_INVALID_HANDLE;
347 	pk11_ctx.ontoken = ISC_FALSE;
348 	ATF_REQUIRE(pkcs_C_CreateObject(pk11_ctx.session, keyTemplate,
349 					(CK_ULONG) 9, &pk11_ctx.object) ==
350 		    CKR_OK);
351 	ATF_REQUIRE(pk11_ctx.object != CK_INVALID_HANDLE);
352 
353 	/* sign something */
354 	ATF_REQUIRE(pkcs_C_SignInit(pk11_ctx.session, &mech,
355 				    pk11_ctx.object) == CKR_OK);
356 	siglen = 0;
357 	ATF_REQUIRE(pkcs_C_Sign(pk11_ctx.session, sig, 64,
358 				NULL, &siglen) == CKR_OK);
359 	ATF_REQUIRE(siglen == 64);
360 	ATF_REQUIRE(pkcs_C_Sign(pk11_ctx.session, sig, 64,
361 				sig, &siglen) == CKR_OK);
362 	ATF_REQUIRE(siglen == 64);
363 
364 	dns_test_end();
365 #endif
366 };
367 #else
368 ATF_TC(untested);
ATF_TC_HEAD(untested,tc)369 ATF_TC_HEAD(untested, tc) {
370 	atf_tc_set_md_var(tc, "descr", "skipping gost test");
371 }
ATF_TC_BODY(untested,tc)372 ATF_TC_BODY(untested, tc) {
373 	UNUSED(tc);
374 	atf_tc_skip("GOST not available");
375 }
376 #endif
377 /*
378  * Main
379  */
ATF_TP_ADD_TCS(tp)380 ATF_TP_ADD_TCS(tp) {
381 #if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
382 	ATF_TP_ADD_TC(tp, isc_gost_md);
383 	ATF_TP_ADD_TC(tp, isc_gost_private);
384 #else
385 	ATF_TP_ADD_TC(tp, untested);
386 #endif
387 	return (atf_no_error());
388 }
389 
390