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