2 * Test GOST 34.10 Sign/Verify operation for every curve parameter
4 * Copyright (C) 2019 vt@altlinux.org. All Rights Reserved.
6 * Contents licensed under the terms of the OpenSSL license
7 * See https://www.openssl.org/source/license.html for details
11 # pragma warning(push, 3)
12 # include <openssl/applink.c>
16 #include <openssl/evp.h>
17 #include <openssl/rand.h>
18 #include <openssl/err.h>
19 #include <openssl/asn1.h>
20 #include <openssl/obj_mac.h>
21 #include <openssl/ec.h>
22 #include <openssl/bn.h>
23 #include <openssl/store.h>
24 #include <openssl/engine.h>
30 ERR_print_errors_fp(stderr); \
31 OpenSSLDie(__FILE__, __LINE__, #e); \
35 ERR_print_errors_fp(stderr); \
36 fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \
40 #define cRED "\033[1;31m"
41 #define cDRED "\033[0;31m"
42 #define cGREEN "\033[1;32m"
43 #define cDGREEN "\033[0;32m"
44 #define cBLUE "\033[1;34m"
45 #define cDBLUE "\033[0;34m"
46 #define cCYAN "\033[1;36m"
47 #define cNORM "\033[m"
48 #define TEST_ASSERT(e) {if ((test = (e))) \
49 printf(cRED " Test FAILED" cNORM "\n"); \
51 printf(cGREEN " Test passed" cNORM "\n");}
60 #define D(x,y,z) { .name = #x, .nid = x, .bits = y, .paramset = z }
61 static struct test_sign test_signs[] = {
62 D(NID_id_GostR3410_2001_CryptoPro_A_ParamSet, 256, "A"),
63 D(NID_id_GostR3410_2001_CryptoPro_B_ParamSet, 256, "B"),
64 D(NID_id_GostR3410_2001_CryptoPro_C_ParamSet, 256, "C"),
65 D(NID_id_tc26_gost_3410_2012_256_paramSetA, 256, "TCA"),
66 D(NID_id_tc26_gost_3410_2012_256_paramSetB, 256, "TCB"),
67 D(NID_id_tc26_gost_3410_2012_256_paramSetC, 256, "TCC"),
68 D(NID_id_tc26_gost_3410_2012_256_paramSetD, 256, "TCD"),
69 D(NID_id_tc26_gost_3410_2012_512_paramSetA, 512, "A"),
70 D(NID_id_tc26_gost_3410_2012_512_paramSetB, 512, "B"),
71 D(NID_id_tc26_gost_3410_2012_512_paramSetC, 512, "C"),
76 static void hexdump(const void *ptr, size_t len)
78 const unsigned char *p = ptr;
81 for (i = 0; i < len; i += j) {
82 for (j = 0; j < 16 && i + j < len; j++)
83 printf("%s %02x", j? "" : "\n", p[i + j]);
88 static void print_test_tf(int err, int val, const char *t, const char *f)
91 printf(cGREEN "%s" cNORM "\n", t);
93 printf(cRED "%s [%d]" cNORM "\n", f, val);
96 static void print_test_result(int err)
99 printf(cGREEN "success" cNORM "\n");
101 printf(cRED "failure" cNORM "\n");
103 ERR_print_errors_fp(stderr);
106 static int test_sign(struct test_sign *t)
109 size_t len = t->bits / 8;
111 printf(cBLUE "Test %s:" cNORM "\n", t->name);
113 /* Signature type from size. */
115 const char *algname = NULL;
118 type = NID_id_GostR3410_2012_256;
119 algname = "gost2012_256";
122 type = NID_id_GostR3410_2012_512;
123 algname = "gost2012_512";
131 T(pkey = EVP_PKEY_new());
132 TE(EVP_PKEY_set_type(pkey, type));
134 T(ctx = EVP_PKEY_CTX_new(pkey, NULL));
135 T(EVP_PKEY_keygen_init(ctx));
136 T(EVP_PKEY_CTX_ctrl(ctx, type, -1, EVP_PKEY_CTRL_GOST_PARAMSET, t->nid, NULL));
137 EVP_PKEY *priv_key = NULL;
138 err = EVP_PKEY_keygen(ctx, &priv_key);
139 printf("\tEVP_PKEY_keygen:\t");
140 print_test_result(err);
141 EVP_PKEY_CTX_free(ctx);
146 /* Convert to PEM and back. */
148 T(bp = BIO_new(BIO_s_secmem()));
149 T(PEM_write_bio_PrivateKey(bp, priv_key, NULL, NULL, 0, NULL, NULL));
151 T(PEM_read_bio_PrivateKey(bp, &pkey, NULL, NULL));
152 printf("\tPEM_read_bio_PrivateKey:");
153 /* Yes, it compares only public part. */
154 err = !EVP_PKEY_cmp(priv_key, pkey);
155 print_test_result(!err);
159 /* Convert to DER and back, using _PrivateKey_bio API. */
161 T(i2d_PrivateKey_bio(bp, priv_key));
162 T(d2i_PrivateKey_bio(bp, &pkey));
163 printf("\td2i_PrivateKey_bio:\t");
164 err = !EVP_PKEY_cmp(priv_key, pkey);
165 print_test_result(!err);
169 #if OPENSSL_VERSION_MAJOR >= 3
170 /* Try d2i_PrivateKey_ex_bio, added in 3.0. */
172 T(i2d_PrivateKey_bio(bp, priv_key));
173 T(d2i_PrivateKey_ex_bio(bp, &pkey, NULL, NULL));
174 printf("\td2i_PrivateKey_ex_bio:\t");
175 err = !EVP_PKEY_cmp(priv_key, pkey);
176 print_test_result(!err);
181 /* Convert to DER and back, using OSSL_STORE API. */
183 T(i2d_PrivateKey_bio(bp, priv_key));
184 printf("\tOSSL_STORE_attach:\t");
188 T(cts = OSSL_STORE_attach(bp, "file", NULL, NULL, NULL, NULL, NULL, NULL, NULL));
190 OSSL_STORE_INFO *info = OSSL_STORE_load(cts);
192 ERR_print_errors_fp(stderr);
193 T(OSSL_STORE_eof(cts));
196 if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
197 T((pkey = OSSL_STORE_INFO_get1_PKEY(info)));
199 OSSL_STORE_INFO_free(info);
201 OSSL_STORE_close(cts);
203 err = !EVP_PKEY_cmp(priv_key, pkey);
204 print_test_result(!err);
208 printf(cCYAN "skipped" cNORM "\n");
211 /* Convert to DER and back, using memory API. */
212 unsigned char *kptr = NULL;
214 T(klen = i2d_PrivateKey(priv_key, &kptr));
215 const unsigned char *tptr = kptr; /* will be moved by d2i_PrivateKey */
217 T(d2i_PrivateKey(type, &pkey, &tptr, klen));
218 printf("\td2i_PrivateKey:\t\t");
219 err = !EVP_PKEY_cmp(priv_key, pkey);
220 print_test_result(!err);
225 /* Create another key using string interface. */
227 T(key1 = EVP_PKEY_new());
228 T(EVP_PKEY_set_type_str(key1, algname, strlen(algname)));
230 T(ctx1 = EVP_PKEY_CTX_new(key1, NULL));
231 T(EVP_PKEY_keygen_init(ctx1));
232 T(EVP_PKEY_CTX_ctrl_str(ctx1, "paramset", t->paramset));
233 EVP_PKEY *key2 = NULL;
234 err = EVP_PKEY_keygen(ctx1, &key2);
235 printf("\tEVP_PKEY_*_str:\t\t");
236 print_test_result(err);
239 /* Check if key type and curve_name match expected values. */
240 int id = EVP_PKEY_id(key2);
242 printf("\tEVP_PKEY_id (%d):\t", type);
243 print_test_tf(err, id, "match", "mismatch");
246 const EC_KEY *ec = EVP_PKEY_get0(key2);
247 const EC_GROUP *group = EC_KEY_get0_group(ec);
248 int curve_name = EC_GROUP_get_curve_name(group);
249 err = curve_name == t->nid;
250 printf("\tcurve_name (%d):\t", t->nid);
251 print_test_tf(err, curve_name, "match", "mismatch");
254 /* Compare both keys.
255 * Parameters should match, public keys should mismatch.
257 err = EVP_PKEY_cmp_parameters(priv_key, key2);
258 printf("\tEVP_PKEY_cmp_parameters:");
259 print_test_tf(err, err, "success", "failure");
262 err = EVP_PKEY_cmp(priv_key, key2);
263 err = (err < 0) ? err : !err;
264 printf("\tEVP_PKEY_cmp:\t\t");
265 print_test_tf(err, err, "differ (good)", "equal (error)");
267 EVP_PKEY_CTX_free(ctx1);
271 * Prepare for sign testing.
273 size_t siglen = EVP_PKEY_size(priv_key);
275 T(sig = OPENSSL_malloc(siglen));
277 T(hash = OPENSSL_zalloc(len));
278 T(ctx = EVP_PKEY_CTX_new(priv_key, NULL));
281 T(EVP_PKEY_sign_init(ctx));
282 err = EVP_PKEY_sign(ctx, sig, &siglen, hash, len);
283 printf("\tEVP_PKEY_sign:\t\t");
284 print_test_result(err);
287 /* Non-determinism test.
288 * Check that different signatures for the same data
291 T(sig2 = OPENSSL_malloc(siglen));
292 TE(EVP_PKEY_sign(ctx, sig2, &siglen, hash, len) == 1);
293 printf("\tNon-determinism:\t");
294 err = !!memcmp(sig, sig2, siglen);
295 print_test_result(err);
300 T(EVP_PKEY_verify_init(ctx));
302 err = EVP_PKEY_verify(ctx, sig, siglen, hash, len);
303 printf("\tEVP_PKEY_verify:\t");
304 print_test_result(err);
307 /* False positive Verify. */
308 T(EVP_PKEY_verify_init(ctx));
310 err = EVP_PKEY_verify(ctx, sig, siglen, hash, len);
311 err = (err < 0) ? err : !err;
312 printf("\tFalse positive test:\t");
313 print_test_result(err);
316 EVP_PKEY_CTX_free(ctx);
319 EVP_PKEY_free(priv_key);
325 int main(int argc, char **argv)
329 OPENSSL_add_all_algorithms_conf();
331 struct test_sign *sp;
332 for (sp = test_signs; sp->name; sp++)
333 ret |= test_sign(sp);
336 printf(cDRED "= Some tests FAILED!" cNORM "\n");
338 printf(cDGREEN "= All tests passed!" cNORM "\n");