]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_derive.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / test_derive.c
1 /*
2  * Test derive operations
3  *
4  * Copyright (C) 2020 Vitaly Chikunov <vt@altlinux.org>. All Rights Reserved.
5  *
6  * Contents licensed under the terms of the OpenSSL license
7  * See https://www.openssl.org/source/license.html for details
8  */
9
10 #ifdef _MSC_VER
11 # pragma warning(push, 3)
12 # include <openssl/applink.c>
13 # pragma warning(pop)
14 #endif
15 #include <openssl/ec.h>
16 #include <openssl/engine.h>
17 #include <openssl/err.h>
18 #include <openssl/evp.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "gost_lcl.h"
22
23 #define T(e) \
24     if (!(e)) { \
25         ERR_print_errors_fp(stderr); \
26         OpenSSLDie(__FILE__, __LINE__, #e); \
27     }
28
29 #define cRED    "\033[1;31m"
30 #define cDRED   "\033[0;31m"
31 #define cGREEN  "\033[1;32m"
32 #define cDGREEN "\033[0;32m"
33 #define cBLUE   "\033[1;34m"
34 #define cDBLUE  "\033[0;34m"
35 #define cCYAN   "\033[1;36m"
36 #define cNORM   "\033[m"
37 #define TEST_ASSERT(e) {if ((test = (e))) \
38                  printf(cRED "  Test FAILED" cNORM "\n"); \
39              else \
40                  printf(cGREEN "  Test passed" cNORM "\n");}
41
42 #ifndef OSSL_NELEM
43 # define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0]))
44 #endif
45
46 const char party_a_priv[] =
47     "\xc9\x90\xec\xd9\x72\xfc\xe8\x4e\xc4\xdb\x02\x27\x78\xf5\x0f\xca"
48     "\xc7\x26\xf4\x67\x08\x38\x4b\x8d\x45\x83\x04\x96\x2d\x71\x47\xf8"
49     "\xc2\xdb\x41\xce\xf2\x2c\x90\xb1\x02\xf2\x96\x84\x04\xf9\xb9\xbe"
50     "\x6d\x47\xc7\x96\x92\xd8\x18\x26\xb3\x2b\x8d\xac\xa4\x3c\xb6\x67";
51 const char party_a_pub[] =
52     "\xaa\xb0\xed\xa4\xab\xff\x21\x20\x8d\x18\x79\x9f\xb9\xa8\x55\x66"
53     "\x54\xba\x78\x30\x70\xeb\xa1\x0c\xb9\xab\xb2\x53\xec\x56\xdc\xf5"
54     "\xd3\xcc\xba\x61\x92\xe4\x64\xe6\xe5\xbc\xb6\xde\xa1\x37\x79\x2f"
55     "\x24\x31\xf6\xc8\x97\xeb\x1b\x3c\x0c\xc1\x43\x27\xb1\xad\xc0\xa7"
56     "\x91\x46\x13\xa3\x07\x4e\x36\x3a\xed\xb2\x04\xd3\x8d\x35\x63\x97"
57     "\x1b\xd8\x75\x8e\x87\x8c\x9d\xb1\x14\x03\x72\x1b\x48\x00\x2d\x38"
58     "\x46\x1f\x92\x47\x2d\x40\xea\x92\xf9\x95\x8c\x0f\xfa\x4c\x93\x75"
59     "\x64\x01\xb9\x7f\x89\xfd\xbe\x0b\x5e\x46\xe4\xa4\x63\x1c\xdb\x5a";
60 const char party_b_priv[] =
61     "\x48\xc8\x59\xf7\xb6\xf1\x15\x85\x88\x7c\xc0\x5e\xc6\xef\x13\x90"
62     "\xcf\xea\x73\x9b\x1a\x18\xc0\xd4\x66\x22\x93\xef\x63\xb7\x9e\x3b"
63     "\x80\x14\x07\x0b\x44\x91\x85\x90\xb4\xb9\x96\xac\xfe\xa4\xed\xfb"
64     "\xbb\xcc\xcc\x8c\x06\xed\xd8\xbf\x5b\xda\x92\xa5\x13\x92\xd0\xdb";
65 const char party_b_pub[] =
66     "\x19\x2f\xe1\x83\xb9\x71\x3a\x07\x72\x53\xc7\x2c\x87\x35\xde\x2e"
67     "\xa4\x2a\x3d\xbc\x66\xea\x31\x78\x38\xb6\x5f\xa3\x25\x23\xcd\x5e"
68     "\xfc\xa9\x74\xed\xa7\xc8\x63\xf4\x95\x4d\x11\x47\xf1\xf2\xb2\x5c"
69     "\x39\x5f\xce\x1c\x12\x91\x75\xe8\x76\xd1\x32\xe9\x4e\xd5\xa6\x51"
70     "\x04\x88\x3b\x41\x4c\x9b\x59\x2e\xc4\xdc\x84\x82\x6f\x07\xd0\xb6"
71     "\xd9\x00\x6d\xda\x17\x6c\xe4\x8c\x39\x1e\x3f\x97\xd1\x02\xe0\x3b"
72     "\xb5\x98\xbf\x13\x2a\x22\x8a\x45\xf7\x20\x1a\xba\x08\xfc\x52\x4a"
73     "\x2d\x77\xe4\x3a\x36\x2a\xb0\x22\xad\x40\x28\xf7\x5b\xde\x3b\x79";
74
75 struct test_derive {
76     const char *descr; /* Source of test vector. */
77     int dgst_nid;      /* VKO mode */
78     int key_nid;
79     int param_nid;     /* Curve id. */
80     const char *ukm;   /* User Keying Material. */
81     int ukm_len;
82     const char *key_a_priv;
83     const char *key_a_pub;
84     const char *key_b_priv;
85     const char *key_b_pub;
86     const char *kek;   /* Key Encryption Key. Output. */
87     int kek_len;
88 } derive_tests[] = {
89     {
90         .descr      = "VKO_GOSTR3410_2012_256 from R 50.1.113-2016 A.9 (p.18)",
91         .dgst_nid   = NID_id_GostR3411_2012_256,
92         .key_nid    = NID_id_GostR3410_2012_512,
93         .param_nid  = NID_id_tc26_gost_3410_2012_512_paramSetA,
94         .key_a_priv = party_a_priv,
95         .key_a_pub  = party_a_pub,
96         .key_b_priv = party_b_priv,
97         .key_b_pub  = party_b_pub,
98         .ukm        = "\x1d\x80\x60\x3c\x85\x44\xc7\x27",
99         .ukm_len    = 8,
100         .kek =
101             "\xc9\xa9\xa7\x73\x20\xe2\xcc\x55\x9e\xd7\x2d\xce\x6f\x47\xe2\x19"
102             "\x2c\xce\xa9\x5f\xa6\x48\x67\x05\x82\xc0\x54\xc0\xef\x36\xc2\x21",
103         .kek_len = 32,
104     },
105     {
106         .descr      = "VKO_GOSTR3410_2012_512 from R 50.1.113-2016 A.10 (p.19)",
107         .dgst_nid   = NID_id_GostR3411_2012_512,
108         .key_nid    = NID_id_GostR3410_2012_512,
109         .param_nid  = NID_id_tc26_gost_3410_2012_512_paramSetA,
110         .key_a_priv = party_a_priv,
111         .key_a_pub  = party_a_pub,
112         .key_b_priv = party_b_priv,
113         .key_b_pub  = party_b_pub,
114         .ukm        = "\x1d\x80\x60\x3c\x85\x44\xc7\x27",
115         .ukm_len    = 8,
116         .kek =
117             "\x79\xf0\x02\xa9\x69\x40\xce\x7b\xde\x32\x59\xa5\x2e\x01\x52\x97"
118             "\xad\xaa\xd8\x45\x97\xa0\xd2\x05\xb5\x0e\x3e\x17\x19\xf9\x7b\xfa"
119             "\x7e\xe1\xd2\x66\x1f\xa9\x97\x9a\x5a\xa2\x35\xb5\x58\xa7\xe6\xd9"
120             "\xf8\x8f\x98\x2d\xd6\x3f\xc3\x5a\x8e\xc0\xdd\x5e\x24\x2d\x3b\xdf",
121         .kek_len = 64,
122     },
123 };
124
125 static EVP_PKEY *load_private_key(int key_nid, int param_nid, const char *pk,
126                                   const char *pub)
127 {
128
129     EVP_PKEY_CTX *ctx;
130     T(ctx = EVP_PKEY_CTX_new_id(key_nid, NULL));
131     T(EVP_PKEY_paramgen_init(ctx));
132     T(EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_GOST_PARAMSET, param_nid,
133                         NULL));
134     EVP_PKEY *key = NULL;
135     T((EVP_PKEY_paramgen(ctx, &key)) == 1);
136     EVP_PKEY_CTX_free(ctx);
137
138     EC_KEY *ec;
139     T(ec = EVP_PKEY_get0(key));
140
141     const int len = EVP_PKEY_bits(key) / 8;
142     BN_CTX *bc;
143     T(bc = BN_CTX_secure_new());
144     BN_CTX_start(bc);
145     const EC_GROUP *group = EC_KEY_get0_group(ec);
146     EC_POINT *pkey = NULL;
147     if (pk) {
148         /* Read private key. */
149         BIGNUM *d = NULL;
150         T(d = BN_lebin2bn((const unsigned char *)pk, len, NULL));
151         T(EC_KEY_set_private_key(ec, d));
152
153         /* Compute public key. */
154         T(pkey = EC_POINT_new(group));
155         T(EC_POINT_mul(group, pkey, d, NULL, NULL, bc));
156         BN_free(d);
157         T(EC_KEY_set_public_key(ec, pkey));
158     } else {
159         /* Read public key. */
160         BIGNUM *x, *y;
161         T(x = BN_lebin2bn((const unsigned char *)pub, len, NULL));
162         T(y = BN_lebin2bn((const unsigned char *)pub + len, len, NULL));
163         EC_POINT *xy = EC_POINT_new(group);
164         T(EC_POINT_set_affine_coordinates(group, xy, x, y, bc));
165         BN_free(x);
166         BN_free(y);
167         T(EC_KEY_set_public_key(ec, xy));
168         EC_POINT_free(xy);
169     }
170
171 #ifdef DEBUG
172     BIO *bp = BIO_new_fd(1, BIO_NOCLOSE);
173     if (pk)
174         PEM_write_bio_PrivateKey(bp, key, NULL, NULL, 0, NULL, NULL);
175     PEM_write_bio_PUBKEY(bp, key);
176     BIO_free(bp);
177 #endif
178
179     /* Verify public key. */
180     if (pk && pub) {
181         BIGNUM *x, *y;
182         T(x = BN_lebin2bn((const unsigned char *)pub, len, NULL));
183         T(y = BN_lebin2bn((const unsigned char *)pub + len, len, NULL));
184         EC_POINT *xy = EC_POINT_new(group);
185         T(EC_POINT_set_affine_coordinates(group, xy, x, y, bc));
186         BN_free(x);
187         BN_free(y);
188         if (EC_POINT_cmp(group, pkey, xy, bc) == 0)
189             printf("Public key %08x matches private key %08x\n",
190                    *(int *)pub, *(int *)pk);
191         else {
192             printf(cRED "Public key mismatch!" cNORM "\n");
193             exit(1);
194         }
195         EC_POINT_free(xy);
196     }
197     EC_POINT_free(pkey);
198     BN_CTX_end(bc);
199     BN_CTX_free(bc);
200
201     return key;
202 }
203
204 int test_derive(struct test_derive *t, const char *name)
205 {
206     int ret = 0;
207
208     printf(cBLUE "Test %s" cNORM " for %s\n", t->descr, name);
209
210     EVP_PKEY *keyA = load_private_key(t->key_nid, t->param_nid,
211                                       t->key_a_priv, t->key_a_pub);
212     EVP_PKEY *keyB = load_private_key(t->key_nid, t->param_nid,
213                                       NULL, t->key_b_pub);
214
215     EVP_PKEY_CTX *ctx;
216     T(ctx = EVP_PKEY_CTX_new(keyA, NULL));
217     T(EVP_PKEY_derive_init(ctx));
218     T(EVP_PKEY_derive_set_peer(ctx, keyB));
219     if (t->dgst_nid)
220         T(EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_SET_VKO,
221                             t->dgst_nid, NULL));
222     T(EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_SET_IV,
223                         t->ukm_len, (unsigned char *)t->ukm));
224
225     size_t skeylen;
226     unsigned char *skey;
227     T(EVP_PKEY_derive(ctx, NULL, &skeylen));
228     T(skey = OPENSSL_malloc(skeylen));
229
230     T(EVP_PKEY_derive(ctx, skey, &skeylen));
231 #ifdef DEBUG
232     BIO_dump_fp(stdout, skey, skeylen);
233 #endif
234
235     EVP_PKEY_CTX_free(ctx);
236     EVP_PKEY_free(keyA);
237     EVP_PKEY_free(keyB);
238
239     if (t->kek_len == skeylen && memcmp(t->kek, skey, skeylen) == 0)
240         printf(cGREEN "KEK match etalon" cNORM "\n");
241     else {
242         printf(cRED "KEK mismatch etalon" cNORM "\n");
243         ret = 1;
244     }
245     OPENSSL_free(skey);
246     return ret;
247 }
248
249 int test_derive_pair(struct test_derive *t)
250 {
251     int ret = 0;
252     struct test_derive tt = *t;
253
254     tt.key_b_priv = NULL;
255     ret |= test_derive(&tt, "A");
256     /* Test swapped keys. */
257     tt.key_a_priv = t->key_b_priv;
258     tt.key_a_pub  = t->key_b_pub;
259     tt.key_b_priv = NULL;
260     tt.key_b_pub  = t->key_a_pub;
261     ret |= test_derive(&tt, "B");
262     return ret;
263 }
264
265 static EVP_PKEY *keygen(const char *algo, const char *param)
266 {
267     EVP_PKEY *key = NULL;
268
269     EVP_PKEY *tkey = EVP_PKEY_new();
270     T(EVP_PKEY_set_type_str(tkey, algo, -1));
271     int pkey_id = EVP_PKEY_id(tkey);
272     EVP_PKEY_free(tkey);
273
274     EVP_PKEY_CTX *ctx;
275     T((ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL)));
276     T(EVP_PKEY_keygen_init(ctx));
277     T(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", param));
278     T(EVP_PKEY_keygen(ctx, &key));
279     EVP_PKEY_CTX_free(ctx);
280     return key;
281 }
282
283 unsigned char *derive(EVP_PKEY *keyA, EVP_PKEY *keyB, int dgst_nid,
284                       int ukm_len, size_t *len)
285 {
286     EVP_PKEY_CTX *ctx;
287     T(ctx = EVP_PKEY_CTX_new(keyA, NULL));
288     T(EVP_PKEY_derive_init(ctx));
289     T(EVP_PKEY_derive_set_peer(ctx, keyB));
290     if (dgst_nid)
291         T(EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_SET_VKO,
292                             dgst_nid, NULL));
293     if (ukm_len) {
294         unsigned char ukm[32] = { 1 };
295
296         OPENSSL_assert(ukm_len <= sizeof(ukm));
297         T(EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_SET_IV,
298                             ukm_len, ukm));
299     }
300
301     T(EVP_PKEY_derive(ctx, NULL, len));
302     unsigned char *skey;
303     T(skey = OPENSSL_malloc(*len));
304
305     T(EVP_PKEY_derive(ctx, skey, len));
306 #ifdef DEBUG
307     BIO_dump_fp(stdout, skey, *len);
308 #endif
309     EVP_PKEY_CTX_free(ctx);
310     return skey;
311 }
312
313 int test_derive_alg(const char *algo, const char *param, int mode)
314 {
315     int ret = 0;
316
317     char *name = NULL;
318     int dgst_nid = 0;
319     int ukm_len = 0;
320     switch (mode) {
321     case 0:
322         dgst_nid = NID_id_GostR3411_2012_256;
323         name = "VKO256";
324         ukm_len = 1;
325         break;
326     case 1:
327         dgst_nid = NID_id_GostR3411_2012_512;
328         name = "VKO512";
329         ukm_len = 1;
330         break;
331     case 2:
332         name = "VKO";
333         ukm_len = 8;
334         break;
335     case 3:
336         if (!strcmp(algo, "gost2001"))
337             return 0; /* Skip. */
338         name = "KEG";
339         ukm_len = 32;
340         break;
341 #define NR_MODES 4
342     default:
343         abort();
344     }
345     printf(cBLUE "Test %s for %s %s" cNORM " - ", name, algo, param);
346
347     EVP_PKEY *keyA = keygen(algo, param);
348     EVP_PKEY *keyB = keygen(algo, param);
349
350     size_t skeyA_len, skeyB_len;
351     unsigned char *skeyA = derive(keyA, keyB, dgst_nid, ukm_len, &skeyA_len);
352     unsigned char *skeyB = derive(keyB, keyA, dgst_nid, ukm_len, &skeyB_len);
353
354     ret = memcmp(skeyA, skeyB, skeyA_len);
355     if (!ret)
356         printf(cGREEN "KEK match" cNORM "\n");
357     else
358         printf(cRED "KEK mismatch" cNORM "\n");
359
360     EVP_PKEY_free(keyA);
361     EVP_PKEY_free(keyB);
362     OPENSSL_free(skeyA);
363     OPENSSL_free(skeyB);
364     return ret;
365 }
366
367 int main(int argc, char **argv)
368 {
369     int ret = 0;
370
371     OPENSSL_add_all_algorithms_conf();
372
373     int i;
374     for (i = 0; i < OSSL_NELEM(derive_tests); i++)
375         ret |= test_derive_pair(&derive_tests[i]);
376
377     for (i = 0; i < NR_MODES; i++) {
378         ret |= test_derive_alg("gost2001", "A", i);
379         ret |= test_derive_alg("gost2001", "B", i);
380         ret |= test_derive_alg("gost2001", "C", i);
381         ret |= test_derive_alg("gost2012_256", "A", i);
382         ret |= test_derive_alg("gost2012_256", "B", i);
383         ret |= test_derive_alg("gost2012_256", "C", i);
384         ret |= test_derive_alg("gost2012_256", "TCA", i);
385         ret |= test_derive_alg("gost2012_512", "A", i);
386         ret |= test_derive_alg("gost2012_512", "B", i);
387         ret |= test_derive_alg("gost2012_512", "C", i);
388     }
389
390     if (ret)
391         printf(cDRED "= Some tests FAILED!" cNORM "\n");
392     else
393         printf(cDGREEN "= All tests passed!" cNORM "\n");
394     return ret;
395 }
396 /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */