xref: /freebsd/crypto/libecc/src/examples/sig/kcdsa/kcdsa.c (revision dd21556857e8d40f66bf5ad54754d9d52669ebf7)
1 /*
2  *  Copyright (C) 2021 - This file is part of libecc project
3  *
4  *  Authors:
5  *      Ryad BENADJILA <ryadbenadjila@gmail.com>
6  *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7  *
8  *  This software is licensed under a dual BSD and GPL v2 license.
9  *  See LICENSE file at the root folder of the project.
10  */
11 #include "kcdsa.h"
12 
13 /* We include the rand external dependency because we have to generate
14  * some random data for the nonces.
15  */
16 #include <libecc/external_deps/rand.h>
17 /* We include the printf external dependency for printf output */
18 #include <libecc/external_deps/print.h>
19 /* We include our common helpers */
20 #include "../common/common.h"
21 
22 /*
23  * The purpose of this example is to implement the KCDSA signature scheme
24  * based on libecc arithmetic primitives, as described in the ISO14888-3
25  * standard.
26  *
27  * XXX: Please be aware that libecc has been designed for Elliptic
28  * Curve cryptography, and as so the arithmetic primitives are
29  * not optimized for big numbers >= 1024 bits usually used for KCDSA.
30  * Additionnaly, a hard limit of our NN values makes it impossible
31  * to exceed ~5300 bits in the best case (words of size 64 bits).
32  *
33  * All in all, please see this as a proof of concept.
34  * Use it at your own risk!
35  *
36  * !! DISCLAIMER !!
37  * ================
38  *
39  * Althoug some efforts have been made to secure this implementation
40  * of KCDSA (e.g. by protecting the private key and nonces using constant
41  * time and blinding WHEN activated with BLINDING=1), please consider this
42  * code as a proof of concept and use it at your own risk.
43  *
44  * All-in-all, this piece of code can be useful in some contexts, or risky to
45  * use in other sensitive ones where advanced side-channels or fault attacks
46  * have to be considered. Use this KCDSA code knowingly and at your own risk!
47  *
48  */
49 
50 /* NOTE: since KCDSA is very similar to DSA, we reuse some of our DSA
51  * primitives to factorize some code. Also, KCDSA private and public keys
52  * have the exact same type as DSA keys.
53  */
54 
55 /* Import a KCDSA private key from buffers */
56 int kcdsa_import_priv_key(kcdsa_priv_key *priv, const u8 *p, u16 plen,
57 			const u8 *q, u16 qlen,
58 			const u8 *g, u16 glen,
59 			const u8 *x, u16 xlen)
60 {
61 	return dsa_import_priv_key(priv, p, plen, q, qlen, g, glen, x, xlen);
62 }
63 
64 /* Import a KCDSA public key from buffers */
65 int kcdsa_import_pub_key(kcdsa_pub_key *pub, const u8 *p, u16 plen,
66 			const u8 *q, u16 qlen,
67 			const u8 *g, u16 glen,
68 			const u8 *y, u16 ylen)
69 {
70 	return dsa_import_pub_key(pub, p, plen, q, qlen, g, glen, y, ylen);
71 }
72 
73 
74 
75 /* Compute a KCDSA public key from a private key.
76  * The public key is computed using modular exponentiation of the generator
77  * with the private key inverse.
78  */
79 int kcdsa_compute_pub_from_priv(kcdsa_pub_key *pub, const kcdsa_priv_key *priv)
80 {
81 	int ret;
82 	kcdsa_priv_key priv_;
83 
84 	MUST_HAVE((priv != NULL), ret, err);
85 
86 	ret = local_memcpy(&priv_, priv, sizeof(kcdsa_priv_key)); EG(ret, err);
87 	/* Replace the x of the private key by its inverse */
88 	ret = nn_modinv_fermat(&(priv_.x), &(priv_.x), &(priv_.q)); EG(ret, err);
89 
90 	/* Use the DSA computation with the computed inverse x */
91 	ret = dsa_compute_pub_from_priv(pub, &priv_);
92 
93 err:
94 	IGNORE_RET_VAL(local_memset(&priv_, 0, sizeof(kcdsa_priv_key)));
95 
96 	return ret;
97 }
98 
99 
100 ATTRIBUTE_WARN_UNUSED_RET static int buf_lshift(u8 *buf, u16 buflen, u16 shift)
101 {
102         u16 i;
103         int ret;
104 
105         MUST_HAVE((buf != NULL), ret, err);
106 
107         if (shift > buflen) {
108                 shift = buflen;
109         }
110 
111         /* Start by shifting all trailing bytes to the left ... */
112         for (i = shift; i < buflen; i++) {
113                 buf[i - shift] = buf[i];
114         }
115 
116         /* Let's now zeroize the end of the buffer ... */
117         for (i = 1; i <= shift; i++) {
118                 buf[buflen - i] = 0;
119         }
120 
121         ret = 0;
122 
123 err:
124         return ret;
125 }
126 
127 /* Generate a KCDSA signature
128  */
129 int kcdsa_sign(const kcdsa_priv_key *priv, const u8 *msg, u32 msglen,
130 	     const u8 *nonce, u16 noncelen,
131 	     u8 *sig, u16 siglen, gen_hash_alg_type kcdsa_hash)
132 {
133 	int ret, iszero;
134 	u16 curr_rlen, curr_siglen;
135 	/* alpha is the bit length of p, beta is the bit length of q */
136 	bitcnt_t alpha, beta;
137 	/* Length of the hash function (hlen is "gamma") */
138 	u8 hlen, block_size;
139 	nn_src_t p, q, g, x;
140 	/* The public key for the witness */
141 	kcdsa_pub_key pub;
142 	nn_src_t y;
143 	/* The nonce and its protected version */
144 	nn k, k_;
145 	/* r, s, pi */
146 	nn r, s;
147 	nn_t pi;
148 	/* This is a bit too much for stack space, but we need it for
149 	 * the computation of "pi" I2BS representation ...
150 	 */
151 	u8 pi_buf[NN_USABLE_MAX_BYTE_LEN];
152 	/* hash context */
153 	gen_hash_context hash_ctx;
154 	u8 hash[MAX_DIGEST_SIZE];
155 #ifdef USE_SIG_BLINDING
156 	/* b is the blinding mask */
157 	nn b;
158 	b.magic = WORD(0);
159 #endif /* USE_SIG_BLINDING */
160 	k.magic = k_.magic = r.magic = s.magic = WORD(0);
161 
162 	/* Sanity checks */
163 	MUST_HAVE((priv != NULL) && (msg != NULL) && (sig != NULL), ret, err);
164 
165 	ret = local_memset(&pub, 0, sizeof(kcdsa_pub_key)); EG(ret, err);
166 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
167 	ret = local_memset(pi_buf, 0, sizeof(pi_buf)); EG(ret, err);
168 
169 	/* Make things more readable */
170 	p = &(priv->p);
171 	q = &(priv->q);
172 	g = &(priv->g);
173 	x = &(priv->x);
174 
175 	/* Sanity checks */
176 	ret = nn_check_initialized(p); EG(ret, err);
177 	ret = nn_check_initialized(q); EG(ret, err);
178 	ret = nn_check_initialized(g); EG(ret, err);
179 	ret = nn_check_initialized(x); EG(ret, err);
180 
181 	/* Let alpha be the bit length of p */
182 	ret = nn_bitlen(p, &alpha); EG(ret, err);
183 	/* Let beta be the bit length of q */
184 	ret = nn_bitlen(q, &beta); EG(ret, err);
185 	/* Get the hash sizes (8*"gamma") */
186 	ret = gen_hash_get_hash_sizes(kcdsa_hash, &hlen, &block_size); EG(ret, err);
187 	MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);
188 
189 	/* Sanity check on the signature length:
190 	 * If "gamma" <= beta, length of R is "gamma", else length of R
191 	 * The signature size is either "gamma" + beta or 2 * beta
192 	 */
193 	if(hlen <= (u16)BYTECEIL(beta)){
194 		curr_rlen = hlen;
195 	}
196 	else{
197 		curr_rlen = (u16)BYTECEIL(beta);
198 	}
199 	curr_siglen = (u16)(curr_rlen + BYTECEIL(beta));
200 	MUST_HAVE((siglen == curr_siglen), ret, err);
201 
202 	/* Compute our public key for the witness */
203 	ret = kcdsa_compute_pub_from_priv(&pub, priv); EG(ret, err);
204 	y = &(pub.y);
205 
206 restart:
207 	/* If the nonce is imposed, use it. Else get a random modulo q */
208 	if(nonce != NULL){
209 		ret = _os2ip(&k, nonce, noncelen); EG(ret, err);
210 	}
211 	else{
212 		ret = nn_get_random_mod(&k, q); EG(ret, err);
213 	}
214 
215 	/* Fix the MSB of our scalar */
216 	ret = nn_copy(&k_, &k); EG(ret, err);
217 #ifdef USE_SIG_BLINDING
218 	/* Blind the scalar */
219 	ret = _blind_scalar(&k_, q, &k_); EG(ret, err);
220 #endif /* USE_SIG_BLINDING */
221 	ret = _fix_scalar_msb(&k_, q, &k_); EG(ret, err);
222 	/* Use r as aliasing for pi to save some space */
223 	pi = &r;
224 	/* pi = (g**k mod p) */
225 	ret = nn_init(pi, 0); EG(ret, err);
226 	/* Exponentiation modulo p */
227 	ret = nn_mod_pow(pi, g, &k_, p); EG(ret, err);
228 
229 	/* Compute I2BS(alpha, pi)
230 	 */
231 	MUST_HAVE((sizeof(pi_buf) >= (u16)BYTECEIL(alpha)), ret, err);
232 	ret = _i2osp(pi, pi_buf, (u16)BYTECEIL(alpha)); EG(ret, err);
233 
234 	if(hlen <= (u16)BYTECEIL(beta)){
235 		unsigned int i;
236 		/* r = h(I2BS(alpha, pi)) */
237 		ret = gen_hash_init(&hash_ctx, kcdsa_hash); EG(ret, err);
238 		ret = gen_hash_update(&hash_ctx, pi_buf, (u16)BYTECEIL(alpha), kcdsa_hash); EG(ret, err);
239 		/* Export r result of the hash function in sig */
240 		ret = gen_hash_final(&hash_ctx, sig, kcdsa_hash); EG(ret, err);
241 		/* Compute v */
242 		MUST_HAVE((block_size <= (u16)BYTECEIL(alpha)), ret, err);
243 		ret = _i2osp(y, pi_buf, (u16)BYTECEIL(alpha)); EG(ret, err);
244 		ret = buf_lshift(pi_buf, (u16)BYTECEIL(alpha), (u16)(BYTECEIL(alpha) - block_size)); EG(ret, err);
245 		ret = gen_hash_init(&hash_ctx, kcdsa_hash); EG(ret, err);
246 		ret = gen_hash_update(&hash_ctx, pi_buf, block_size, kcdsa_hash); EG(ret, err);
247 		ret = gen_hash_update(&hash_ctx, msg, msglen, kcdsa_hash); EG(ret, err);
248 		ret = gen_hash_final(&hash_ctx, hash, kcdsa_hash); EG(ret, err);
249 		for(i = 0; i < hlen; i++){
250 			hash[i] = (hash[i] ^ sig[i]);
251 		}
252 		ret = _os2ip(&s, hash, hlen); EG(ret, err);
253 	}
254 	else{
255 		unsigned int i;
256 		/* h(I2BS(alpha, pi)) */
257 		ret = gen_hash_init(&hash_ctx, kcdsa_hash); EG(ret, err);
258 		ret = gen_hash_update(&hash_ctx, pi_buf, (u16)BYTECEIL(alpha), kcdsa_hash); EG(ret, err);
259 		/* Export r result of the hash function in sig ... */
260 		ret = gen_hash_final(&hash_ctx, hash, kcdsa_hash); EG(ret, err);
261 		/* ... and proceed with the appropriate tuncation */
262 		ret = buf_lshift(hash, hlen, (u16)(hlen - BYTECEIL(beta))); EG(ret, err);
263 		ret = local_memcpy(sig, hash, (u16)BYTECEIL(beta)); EG(ret, err);
264 		/* Compute v */
265 		MUST_HAVE((block_size <= (u16)BYTECEIL(alpha)), ret, err);
266 		ret = _i2osp(y, pi_buf, (u16)BYTECEIL(alpha)); EG(ret, err);
267 		ret = buf_lshift(pi_buf, (u16)BYTECEIL(alpha), (u16)(BYTECEIL(alpha) - block_size)); EG(ret, err);
268 		ret = gen_hash_init(&hash_ctx, kcdsa_hash); EG(ret, err);
269 		ret = gen_hash_update(&hash_ctx, pi_buf, block_size, kcdsa_hash); EG(ret, err);
270 		ret = gen_hash_update(&hash_ctx, msg, msglen, kcdsa_hash); EG(ret, err);
271 		ret = gen_hash_final(&hash_ctx, hash, kcdsa_hash); EG(ret, err);
272 		/* ... and proceed with the appropriate tuncation */
273 		ret = buf_lshift(hash, hlen, (u16)(hlen - BYTECEIL(beta))); EG(ret, err);
274 		for(i = 0; i < (u16)BYTECEIL(beta); i++){
275 			hash[i] = (hash[i] ^ sig[i]);
276 		}
277 		ret = _os2ip(&s, hash, (u16)BYTECEIL(beta)); EG(ret, err);
278 	}
279 
280 	/* Reduce v modulo q */
281 	ret = nn_mod(&s, &s, q); EG(ret, err);
282 
283 #ifdef USE_SIG_BLINDING
284 	/* Note: if we use blinding, v and k are multiplied by
285 	 * a random value b in ]0,q[ */
286 	ret = nn_get_random_mod(&b, q); EG(ret, err);
287         /* Blind r with b */
288         ret = nn_mod_mul(&s, &s, &b, q); EG(ret, err);
289         /* Blind k with b */
290         ret = nn_mod_mul(&k, &k, &b, q); EG(ret, err);
291         /*
292          * In case of blinding, we compute b^-1 with
293 	 * little Fermat theorem. This will be used to
294 	 * unblind s.
295          */
296         ret = nn_modinv_fermat(&b, &b, q); EG(ret, err);
297 #endif /* USE_SIG_BLINDING */
298 
299 	/* Compute s = x (k - v) mod q  */
300 	ret = nn_mod_sub(&s, &k, &s, q); EG(ret, err);
301 	ret = nn_mod_mul(&s, &s, x, q); EG(ret, err);
302 
303 #ifdef USE_SIG_BLINDING
304 	/* In case of blinding, unblind s */
305 	ret = nn_mod_mul(&s, &s, &b, q); EG(ret, err);
306 #endif /* USE_SIG_BLINDING */
307 	/* If s is 0, restart the process */
308 	ret = nn_iszero(&s, &iszero); EG(ret, err);
309 	if (iszero) {
310 		goto restart;
311  	}
312 
313 	/* Export s */
314 	ret = _i2osp(&s, sig + curr_rlen, (u16)BYTECEIL(beta));
315 
316 err:
317 	if(ret && (sig != NULL)){
318 		IGNORE_RET_VAL(local_memset(sig, 0, siglen));
319 	}
320 
321 	IGNORE_RET_VAL(local_memset(&pub, 0, sizeof(kcdsa_pub_key)));
322 
323 	nn_uninit(&k);
324 	nn_uninit(&k_);
325 #ifdef USE_SIG_BLINDING
326 	nn_uninit(&b);
327 #endif
328 	nn_uninit(&r);
329 	nn_uninit(&s);
330 
331 	PTR_NULLIFY(pi);
332 	PTR_NULLIFY(y);
333 	PTR_NULLIFY(p);
334 	PTR_NULLIFY(q);
335 	PTR_NULLIFY(g);
336 	PTR_NULLIFY(x);
337 
338 	return ret;
339 }
340 
341 
342 
343 /* Verify a KCDSA signature
344  */
345 int kcdsa_verify(const kcdsa_pub_key *pub, const u8 *msg, u32 msglen,
346 	     const u8 *sig, u16 siglen, gen_hash_alg_type kcdsa_hash)
347 {
348 	int ret, iszero, cmp;
349 	u16 curr_rlen, curr_siglen;
350 	/* alpha is the bit length of p, beta is the bit length of q */
351 	bitcnt_t alpha, beta;
352 	/* Length of the hash function */
353 	u8 hlen, block_size;
354 	nn_src_t p, q, g, y;
355 	/* s */
356 	nn s;
357 	/* u, v and pi */
358 	nn u, v, pi;
359 	/* This is a bit too much for stack space, but we need it for
360 	 * the computation of "pi" I2BS representation ...
361 	 */
362 	u8 pi_buf[NN_USABLE_MAX_BYTE_LEN];
363 	/* Hash */
364 	u8 hash[MAX_DIGEST_SIZE];
365 	/* hash context */
366 	gen_hash_context hash_ctx;
367 	s.magic = v.magic = u.magic = pi.magic = WORD(0);
368 
369 	/* Sanity checks */
370 	MUST_HAVE((pub != NULL) && (msg != NULL) && (sig != NULL), ret, err);
371 
372 	ret = local_memset(pi_buf, 0, sizeof(pi_buf)); EG(ret, err);
373 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
374 
375 	/* Make things more readable */
376 	p = &(pub->p);
377 	q = &(pub->q);
378 	g = &(pub->g);
379 	y = &(pub->y);
380 
381 	/* Sanity checks */
382 	ret = nn_check_initialized(p); EG(ret, err);
383 	ret = nn_check_initialized(q); EG(ret, err);
384 	ret = nn_check_initialized(g); EG(ret, err);
385 	ret = nn_check_initialized(y); EG(ret, err);
386 
387 	/* Let alpha be the bit length of p */
388 	ret = nn_bitlen(p, &alpha); EG(ret, err);
389 	/* Let beta be the bit length of q */
390 	ret = nn_bitlen(q, &beta); EG(ret, err);
391 	/* Get the hash sizes (8*"gamma") */
392 	ret = gen_hash_get_hash_sizes(kcdsa_hash, &hlen, &block_size); EG(ret, err);
393 	MUST_HAVE((hlen <= MAX_DIGEST_SIZE), ret, err);
394 
395 	/* Sanity check on the signature length:
396 	 * If "gamma" <= beta, length of R is "gamma", else length of R
397 	 * The signature size is either "gamma" + beta or 2 * beta
398 	 */
399 	if(hlen <= (u16)BYTECEIL(beta)){
400 		curr_rlen = hlen;
401 	}
402 	else{
403 		curr_rlen = (u16)BYTECEIL(beta);
404 	}
405 	curr_siglen = (u16)(curr_rlen + BYTECEIL(beta));
406 	MUST_HAVE((siglen == curr_siglen), ret, err);
407 
408 	/* Extract s */
409 	ret = _os2ip(&s, sig + curr_rlen, (u16)(siglen - curr_rlen)); EG(ret, err);
410 
411 	/* Return an error if s = 0 */
412 	ret = nn_iszero(&s, &iszero); EG(ret, err);
413 	MUST_HAVE((!iszero), ret, err);
414 	/* Check that 0 < s < q */
415 	ret = nn_cmp(&s, q, &cmp); EG(ret, err);
416 	MUST_HAVE((cmp < 0), ret, err);
417 
418 	/* Initialize internal variables */
419 	ret = nn_init(&u, 0); EG(ret, err);
420 	ret = nn_init(&pi, 0); EG(ret, err);
421 
422 	/* Compute v */
423 	if(hlen <= (u16)BYTECEIL(beta)){
424 		unsigned int i;
425 		/* r is of size hlen */
426 		MUST_HAVE((block_size <= (u16)BYTECEIL(alpha)), ret, err);
427 		ret = _i2osp(y, pi_buf, (u16)BYTECEIL(alpha)); EG(ret, err);
428 		ret = buf_lshift(pi_buf, (u16)BYTECEIL(alpha), (u16)(BYTECEIL(alpha) - block_size)); EG(ret, err);
429 		ret = gen_hash_init(&hash_ctx, kcdsa_hash); EG(ret, err);
430 		ret = gen_hash_update(&hash_ctx, pi_buf, block_size, kcdsa_hash); EG(ret, err);
431 		ret = gen_hash_update(&hash_ctx, msg, msglen, kcdsa_hash); EG(ret, err);
432 		ret = gen_hash_final(&hash_ctx, hash, kcdsa_hash); EG(ret, err);
433 		for(i = 0; i < hlen; i++){
434 			hash[i] = (hash[i] ^ sig[i]);
435 		}
436 		ret = _os2ip(&v, hash, hlen); EG(ret, err);
437 	}
438 	else{
439 		unsigned int i;
440 		/* r is of size beta */
441 		MUST_HAVE((block_size <= (u16)BYTECEIL(alpha)), ret, err);
442 		ret = _i2osp(y, pi_buf, (u16)BYTECEIL(alpha)); EG(ret, err);
443 		ret = buf_lshift(pi_buf, (u16)BYTECEIL(alpha), (u16)(BYTECEIL(alpha) - block_size)); EG(ret, err);
444 		ret = gen_hash_init(&hash_ctx, kcdsa_hash); EG(ret, err);
445 		ret = gen_hash_update(&hash_ctx, pi_buf, block_size, kcdsa_hash); EG(ret, err);
446 		ret = gen_hash_update(&hash_ctx, msg, msglen, kcdsa_hash); EG(ret, err);
447 		ret = gen_hash_final(&hash_ctx, hash, kcdsa_hash); EG(ret, err);
448 		/* ... and proceed with the appropriate tuncation */
449 		ret = buf_lshift(hash, hlen, (u16)(hlen - BYTECEIL(beta))); EG(ret, err);
450 		for(i = 0; i < (u16)BYTECEIL(beta); i++){
451 			hash[i] = (hash[i] ^ sig[i]);
452 		}
453 		ret = _os2ip(&v, hash, (u16)BYTECEIL(beta)); EG(ret, err);
454 	}
455 
456 	/* Reduce v modulo q */
457 	ret = nn_mod(&v, &v, q); EG(ret, err);
458 
459 	/* NOTE: no need to use a secure exponentiation here as we only
460 	 * manipulate public data.
461 	 */
462 	/* Compute (y ** s) mod (p) */
463 	ret = _nn_mod_pow_insecure(&u, y, &s, p); EG(ret, err);
464 	/* Compute (g ** v) mod (p) */
465 	ret = _nn_mod_pow_insecure(&pi, g, &v, p); EG(ret, err);
466 	/* Compute (y ** s) (g ** v) mod (p) */
467 	ret = nn_mod_mul(&pi, &pi, &u, p); EG(ret, err);
468 
469 	/* Compute I2BS(alpha, pi)
470 	 */
471 	MUST_HAVE((sizeof(pi_buf) >= (u16)BYTECEIL(alpha)), ret, err);
472 	ret = _i2osp(&pi, pi_buf, (u16)BYTECEIL(alpha)); EG(ret, err);
473 
474 	if(hlen <= (u16)BYTECEIL(beta)){
475 		/* r = h(I2BS(alpha, pi)) */
476 		ret = gen_hash_init(&hash_ctx, kcdsa_hash); EG(ret, err);
477 		ret = gen_hash_update(&hash_ctx, pi_buf, (u16)BYTECEIL(alpha), kcdsa_hash); EG(ret, err);
478 		/* Export r result of the hash function in sig */
479 		ret = gen_hash_final(&hash_ctx, hash, kcdsa_hash); EG(ret, err);
480 	}
481 	else{
482 		/* h(I2BS(alpha, pi)) */
483 		ret = gen_hash_init(&hash_ctx, kcdsa_hash); EG(ret, err);
484 		ret = gen_hash_update(&hash_ctx, pi_buf, (u16)BYTECEIL(alpha), kcdsa_hash); EG(ret, err);
485 		/* Export r result of the hash function in sig ... */
486 		ret = gen_hash_final(&hash_ctx, hash, kcdsa_hash); EG(ret, err);
487 		/* ... and proceed with the appropriate tuncation */
488 		ret = buf_lshift(hash, hlen, (u16)(hlen - BYTECEIL(beta))); EG(ret, err);
489 	}
490 
491 	/* Now check that r == r' */
492 	ret = are_equal(sig, hash, curr_rlen, &cmp); EG(ret, err);
493 	ret = (cmp != 1) ? -1 : 0;
494 
495 err:
496 	nn_uninit(&s);
497 	nn_uninit(&u);
498 	nn_uninit(&v);
499 	nn_uninit(&pi);
500 
501 	PTR_NULLIFY(p);
502 	PTR_NULLIFY(q);
503 	PTR_NULLIFY(g);
504 	PTR_NULLIFY(y);
505 
506 	return ret;
507 }
508 
509 #ifdef KCDSA
510 #include <libecc/utils/print_buf.h>
511 int main(int argc, char *argv[])
512 {
513  	int ret = 0;
514 
515 #if 0
516 	/* This example is taken from ISO14888-3 KCDSA (Appendix F "Numerical examples" */
517 	const u8 p[] = {
518 0x8D, 0xA8, 0xC1, 0xB5, 0xC9, 0x5D, 0x11, 0xBE, 0x46, 0x66, 0x1D, 0xF5, 0x8C, 0x9F, 0x80, 0x3E, 0xB7, 0x29, 0xB8, 0x00, 0xDD, 0x92, 0x75, 0x1B,
519 0x3A, 0x4F, 0x10, 0xC6, 0xA5, 0x44, 0x8E, 0x9F, 0x3B, 0xC0, 0xE9, 0x16, 0xF0, 0x42, 0xE3, 0x99, 0xB3, 0x4A, 0xF9, 0xBE, 0xE5, 0x82, 0xCC, 0xFC,
520 0x3F, 0xF5, 0x00, 0x0C, 0xFF, 0x23, 0x56, 0x94, 0x94, 0x35, 0x1C, 0xFE, 0xA5, 0x52, 0x9E, 0xA3, 0x47, 0xDC, 0xF4, 0x3F, 0x30, 0x2F, 0x58, 0x94,
521 0x38, 0x07, 0x09, 0xEA, 0x2E, 0x1C, 0x41, 0x6B, 0x51, 0xA5, 0xCD, 0xFC, 0x75, 0x93, 0xB1, 0x8B, 0x7E, 0x37, 0x88, 0xD5, 0x1B, 0x9C, 0xC9, 0xAE,
522 0x82, 0x8B, 0x4F, 0x8F, 0xB0, 0x6E, 0x0E, 0x90, 0x57, 0xF7, 0xFA, 0x0F, 0x93, 0xBB, 0x03, 0x97, 0x03, 0x1F, 0xE7, 0xD5, 0x0A, 0x68, 0x28, 0xDA,
523 0x0C, 0x11, 0x60, 0xA0, 0xE6, 0x6D, 0x4E, 0x5D, 0x2A, 0x18, 0xAD, 0x17, 0xA8, 0x11, 0xE7, 0x0B, 0x14, 0xF4, 0xF4, 0x31, 0x1A, 0x02, 0x82, 0x60,
524 0x32, 0x33, 0x44, 0x4F, 0x98, 0x76, 0x3C, 0x5A, 0x1E, 0x82, 0x9C, 0x76, 0x4C, 0xF3, 0x6A, 0xDB, 0x56, 0x98, 0x0B, 0xD4, 0xC5, 0x4B, 0xBE, 0x29,
525 0x7E, 0x79, 0x02, 0x28, 0x42, 0x92, 0xD7, 0x5C, 0xA3, 0x60, 0x0F, 0xF4, 0x59, 0x31, 0x0B, 0x09, 0x29, 0x1C, 0xBE, 0xFB, 0xC7, 0x21, 0x52, 0x8A,
526 0x13, 0x40, 0x3B, 0x8B, 0x93, 0xB7, 0x11, 0xC3, 0x03, 0xA2, 0x18, 0x2B, 0x6E, 0x63, 0x97, 0xE0, 0x83, 0x38, 0x0B, 0xF2, 0x88, 0x6A, 0xF3, 0xB9,
527 0xAF, 0xCC, 0x9F, 0x50, 0x55, 0xD8, 0xB7, 0x13, 0x6C, 0x0E, 0xBD, 0x08, 0xC5, 0xCF, 0x0B, 0x38, 0x88, 0x8C, 0xD1, 0x15, 0x72, 0x78, 0x7F, 0x6D,
528 0xF3, 0x84, 0xC9, 0x7C, 0x91, 0xB5, 0x8C, 0x31, 0xDE, 0xE5, 0x65, 0x5E, 0xCB, 0xF3, 0xFA, 0x53,
529 	};
530 
531 	const u8 q[] = {
532 0x86, 0x4F, 0x18, 0x84, 0x1E, 0xC1, 0x03, 0xCD, 0xFD, 0x1B, 0xE7, 0xFE, 0xE5, 0x46, 0x50, 0xF2, 0x2A, 0x3B, 0xB9, 0x97, 0x53, 0x7F, 0x32, 0xCC,
533 0x79, 0xA5, 0x1F, 0x53,
534 	};
535 
536 	const u8 g[] = {
537 0x0E, 0x9B, 0xE1, 0xF8, 0x7A, 0x41, 0x4D, 0x16, 0x7A, 0x9A, 0x5A, 0x96, 0x8B, 0x07, 0x9E, 0x4A, 0xD3, 0x85, 0xA3, 0x57, 0x3E, 0xDB, 0x21, 0xAA,
538 0x67, 0xA6, 0xF6, 0x1C, 0x0D, 0x00, 0xC1, 0x4A, 0x7A, 0x22, 0x50, 0x44, 0xB6, 0xE9, 0xEB, 0x03, 0x68, 0xC1, 0xEB, 0x57, 0xB2, 0x4B, 0x45, 0xCD,
539 0x85, 0x4F, 0xD9, 0x3C, 0x1B, 0x2D, 0xFB, 0x0A, 0x3E, 0xA3, 0x02, 0xD2, 0x36, 0x7E, 0x4E, 0xC7, 0x2F, 0x6E, 0x7E, 0xE8, 0xEA, 0x7F, 0x80, 0x02,
540 0xF7, 0x70, 0x4E, 0x99, 0x0B, 0x95, 0x4F, 0x25, 0xBA, 0xDA, 0x8D, 0xA6, 0x2B, 0xAE, 0xB6, 0xF0, 0x69, 0x53, 0xC0, 0xC8, 0x51, 0x04, 0xAD, 0x03,
541 0xF3, 0x66, 0x18, 0xF7, 0x6C, 0x62, 0xF4, 0xEC, 0xF3, 0x48, 0x01, 0x83, 0x69, 0x85, 0x0A, 0x56, 0x17, 0xC9, 0x99, 0xDB, 0xE6, 0x8B, 0xA1, 0x7D,
542 0x5B, 0xC7, 0x25, 0x56, 0x74, 0xEF, 0x48, 0x39, 0x22, 0xC6, 0xA3, 0xF9, 0x9D, 0x3C, 0x3C, 0x6F, 0x35, 0x88, 0x96, 0xC4, 0xE6, 0x3C, 0x60, 0x5E,
543 0xE7, 0xDB, 0x16, 0xFC, 0xBD, 0x9B, 0xE3, 0x54, 0xE2, 0x81, 0xF7, 0xFE, 0x78, 0x13, 0xD0, 0x54, 0x27, 0xED, 0x19, 0x12, 0xB5, 0xC7, 0x65, 0x3A,
544 0x16, 0x7B, 0x94, 0x34, 0x91, 0x47, 0xEE, 0xAF, 0x85, 0xCC, 0x9C, 0xE2, 0xE8, 0x16, 0x61, 0xF3, 0x21, 0x51, 0x2D, 0x5D, 0x2C, 0x05, 0x80, 0xB0,
545 0x3D, 0x17, 0x04, 0xEE, 0xF2, 0x31, 0x7F, 0x45, 0x18, 0x5C, 0x82, 0x58, 0x38, 0x7E, 0x7E, 0xC9, 0x79, 0xC0, 0x47, 0x07, 0xEF, 0x54, 0x62, 0x41,
546 0x27, 0x84, 0xAF, 0xE4, 0x1A, 0x7B, 0x45, 0xC8, 0x3B, 0x9C, 0xBE, 0x48, 0xF9, 0x12, 0x7C, 0xB4, 0x40, 0x0B, 0xE9, 0xE9, 0x6A, 0xC5, 0xDE, 0x17,
547 0xF2, 0xC9, 0xDE, 0xA3, 0x5E, 0x37, 0x34, 0xE7, 0x9B, 0x64, 0x67, 0x3F, 0x85, 0x68, 0x1C, 0x4E,
548 	};
549 
550 	const u8 x[] = {
551 0x2F, 0x19, 0x91, 0xC1, 0xAF, 0x40, 0x18, 0x72, 0x8A, 0x5A, 0x43, 0x1B, 0x9B, 0x54, 0x59, 0xDF, 0xB1, 0x6F, 0x6D, 0x25, 0x67, 0x97, 0xFE, 0x57,
552 0x0E, 0xC6, 0xBC, 0x65,
553 	};
554 
555 	const u8 y[] = {
556 0x04, 0xED, 0xE5, 0xC6, 0x7E, 0xA2, 0x92, 0x97, 0xA8, 0xCA, 0xCB, 0x6B, 0xDE, 0x6F, 0x46, 0x66, 0xAE, 0xA2, 0x7D, 0x10, 0x3D, 0xD1, 0xE9, 0xE9,
557 0x58, 0x2F, 0x76, 0xA2, 0xF2, 0x2B, 0x8B, 0x1B, 0x32, 0x23, 0x0B, 0xC5, 0x8F, 0x06, 0xB7, 0x68, 0xF8, 0x10, 0x2B, 0x49, 0xFA, 0x1C, 0xAE, 0x5E,
558 0x18, 0x92, 0x14, 0x94, 0x7F, 0x62, 0x39, 0xB6, 0xC6, 0xCE, 0x7C, 0x9B, 0xC2, 0xD2, 0x30, 0xE8, 0x9A, 0x40, 0xBE, 0xE2, 0xC3, 0x3A, 0x88, 0x61,
559 0xFD, 0x4F, 0x7D, 0x35, 0xB7, 0x88, 0xFE, 0x95, 0xB2, 0xD5, 0x88, 0x5D, 0x8C, 0x8F, 0xAE, 0xA8, 0x1C, 0x90, 0xBE, 0x4C, 0xEE, 0x27, 0x84, 0xE3,
560 0x35, 0x77, 0xA7, 0x1D, 0x3B, 0x7F, 0x08, 0x5D, 0x71, 0xE9, 0xA1, 0xD4, 0x78, 0x15, 0xC7, 0x3F, 0xA0, 0x87, 0xAC, 0xAA, 0xB9, 0xFC, 0xB5, 0x65,
561 0x5A, 0xC9, 0x57, 0x0E, 0x68, 0x52, 0xBE, 0x7C, 0x9C, 0x0A, 0xEC, 0xEA, 0x8B, 0xD9, 0xAA, 0x75, 0xA4, 0x4F, 0xC3, 0x14, 0x7F, 0x73, 0x3E, 0x90,
562 0x6A, 0xDB, 0x0F, 0xD7, 0x6D, 0x61, 0x35, 0x61, 0xB1, 0xDB, 0x36, 0x4B, 0xBD, 0xC9, 0xAF, 0xD3, 0xCE, 0x8F, 0x5F, 0x17, 0xE3, 0xE7, 0x12, 0x03,
563 0x4A, 0x99, 0x93, 0x50, 0x80, 0x59, 0xFA, 0x52, 0x44, 0x1F, 0xA9, 0x0D, 0xDF, 0xE9, 0xA0, 0xF2, 0xA0, 0xB9, 0x19, 0x2F, 0xE2, 0x22, 0x0C, 0x08,
564 0x1B, 0xD0, 0xC0, 0xF0, 0xE0, 0x7C, 0xB5, 0xF1, 0xEE, 0x4F, 0xF4, 0x05, 0x23, 0x59, 0x1F, 0x17, 0x8A, 0x4F, 0xC7, 0xCB, 0x50, 0x65, 0xF6, 0xA3,
565 0x82, 0x16, 0xE9, 0xA0, 0x99, 0xC2, 0x05, 0xB2, 0x9B, 0x87, 0x46, 0xD8, 0x65, 0xE1, 0xAF, 0x6D, 0x90, 0x3E, 0x5A, 0x13, 0x80, 0x04, 0x91, 0x0B,
566 0x70, 0xEB, 0x5B, 0x84, 0xEE, 0xD9, 0x76, 0x0E, 0xA6, 0x05, 0x78, 0xBF, 0x08, 0x85, 0x28, 0x98,
567 	};
568 
569 	const u8 msg[] = "This is a test message for KCDSA usage!";
570 
571 	const u8 nonce[] = {
572 0x49, 0x56, 0x19, 0x94, 0xFD, 0x2B, 0xAD, 0x5E, 0x41, 0x0C, 0xA1, 0xC1, 0x5C, 0x3F, 0xD3, 0xF1, 0x2E, 0x70, 0x26, 0x3F, 0x28, 0x20, 0xAD, 0x5C,
573 0x56, 0x6D, 0xED, 0x80,
574 	};
575 	u8 sig[28*2] = { 0 };
576 	gen_hash_alg_type kcdsa_hash = HASH_SHA224;
577 #endif
578 
579 #if 0
580 	/* This example is taken from ISO14888-3 KCDSA (Appendix F "Numerical examples" */
581 	const u8 p[] = {
582 0x8D, 0xA8, 0xC1, 0xB5, 0xC9, 0x5D, 0x11, 0xBE, 0x46, 0x66, 0x1D, 0xF5, 0x8C, 0x9F, 0x80, 0x3E, 0xB7, 0x29, 0xB8, 0x00, 0xDD, 0x92, 0x75, 0x1B,
583 0x3A, 0x4F, 0x10, 0xC6, 0xA5, 0x44, 0x8E, 0x9F, 0x3B, 0xC0, 0xE9, 0x16, 0xF0, 0x42, 0xE3, 0x99, 0xB3, 0x4A, 0xF9, 0xBE, 0xE5, 0x82, 0xCC, 0xFC,
584 0x3F, 0xF5, 0x00, 0x0C, 0xFF, 0x23, 0x56, 0x94, 0x94, 0x35, 0x1C, 0xFE, 0xA5, 0x52, 0x9E, 0xA3, 0x47, 0xDC, 0xF4, 0x3F, 0x30, 0x2F, 0x58, 0x94,
585 0x38, 0x07, 0x09, 0xEA, 0x2E, 0x1C, 0x41, 0x6B, 0x51, 0xA5, 0xCD, 0xFC, 0x75, 0x93, 0xB1, 0x8B, 0x7E, 0x37, 0x88, 0xD5, 0x1B, 0x9C, 0xC9, 0xAE,
586 0x82, 0x8B, 0x4F, 0x8F, 0xB0, 0x6E, 0x0E, 0x90, 0x57, 0xF7, 0xFA, 0x0F, 0x93, 0xBB, 0x03, 0x97, 0x03, 0x1F, 0xE7, 0xD5, 0x0A, 0x68, 0x28, 0xDA,
587 0x0C, 0x11, 0x60, 0xA0, 0xE6, 0x6D, 0x4E, 0x5D, 0x2A, 0x18, 0xAD, 0x17, 0xA8, 0x11, 0xE7, 0x0B, 0x14, 0xF4, 0xF4, 0x31, 0x1A, 0x02, 0x82, 0x60,
588 0x32, 0x33, 0x44, 0x4F, 0x98, 0x76, 0x3C, 0x5A, 0x1E, 0x82, 0x9C, 0x76, 0x4C, 0xF3, 0x6A, 0xDB, 0x56, 0x98, 0x0B, 0xD4, 0xC5, 0x4B, 0xBE, 0x29,
589 0x7E, 0x79, 0x02, 0x28, 0x42, 0x92, 0xD7, 0x5C, 0xA3, 0x60, 0x0F, 0xF4, 0x59, 0x31, 0x0B, 0x09, 0x29, 0x1C, 0xBE, 0xFB, 0xC7, 0x21, 0x52, 0x8A,
590 0x13, 0x40, 0x3B, 0x8B, 0x93, 0xB7, 0x11, 0xC3, 0x03, 0xA2, 0x18, 0x2B, 0x6E, 0x63, 0x97, 0xE0, 0x83, 0x38, 0x0B, 0xF2, 0x88, 0x6A, 0xF3, 0xB9,
591 0xAF, 0xCC, 0x9F, 0x50, 0x55, 0xD8, 0xB7, 0x13, 0x6C, 0x0E, 0xBD, 0x08, 0xC5, 0xCF, 0x0B, 0x38, 0x88, 0x8C, 0xD1, 0x15, 0x72, 0x78, 0x7F, 0x6D,
592 0xF3, 0x84, 0xC9, 0x7C, 0x91, 0xB5, 0x8C, 0x31, 0xDE, 0xE5, 0x65, 0x5E, 0xCB, 0xF3, 0xFA, 0x53,
593 	};
594 
595 	const u8 q[] = {
596 0x86, 0x4F, 0x18, 0x84, 0x1E, 0xC1, 0x03, 0xCD, 0xFD, 0x1B, 0xE7, 0xFE, 0xE5, 0x46, 0x50, 0xF2, 0x2A, 0x3B, 0xB9, 0x97, 0x53, 0x7F, 0x32, 0xCC,
597 0x79, 0xA5, 0x1F, 0x53,
598 	};
599 
600 	const u8 g[] = {
601 0x0E, 0x9B, 0xE1, 0xF8, 0x7A, 0x41, 0x4D, 0x16, 0x7A, 0x9A, 0x5A, 0x96, 0x8B, 0x07, 0x9E, 0x4A, 0xD3, 0x85, 0xA3, 0x57, 0x3E, 0xDB, 0x21, 0xAA,
602 0x67, 0xA6, 0xF6, 0x1C, 0x0D, 0x00, 0xC1, 0x4A, 0x7A, 0x22, 0x50, 0x44, 0xB6, 0xE9, 0xEB, 0x03, 0x68, 0xC1, 0xEB, 0x57, 0xB2, 0x4B, 0x45, 0xCD,
603 0x85, 0x4F, 0xD9, 0x3C, 0x1B, 0x2D, 0xFB, 0x0A, 0x3E, 0xA3, 0x02, 0xD2, 0x36, 0x7E, 0x4E, 0xC7, 0x2F, 0x6E, 0x7E, 0xE8, 0xEA, 0x7F, 0x80, 0x02,
604 0xF7, 0x70, 0x4E, 0x99, 0x0B, 0x95, 0x4F, 0x25, 0xBA, 0xDA, 0x8D, 0xA6, 0x2B, 0xAE, 0xB6, 0xF0, 0x69, 0x53, 0xC0, 0xC8, 0x51, 0x04, 0xAD, 0x03,
605 0xF3, 0x66, 0x18, 0xF7, 0x6C, 0x62, 0xF4, 0xEC, 0xF3, 0x48, 0x01, 0x83, 0x69, 0x85, 0x0A, 0x56, 0x17, 0xC9, 0x99, 0xDB, 0xE6, 0x8B, 0xA1, 0x7D,
606 0x5B, 0xC7, 0x25, 0x56, 0x74, 0xEF, 0x48, 0x39, 0x22, 0xC6, 0xA3, 0xF9, 0x9D, 0x3C, 0x3C, 0x6F, 0x35, 0x88, 0x96, 0xC4, 0xE6, 0x3C, 0x60, 0x5E,
607 0xE7, 0xDB, 0x16, 0xFC, 0xBD, 0x9B, 0xE3, 0x54, 0xE2, 0x81, 0xF7, 0xFE, 0x78, 0x13, 0xD0, 0x54, 0x27, 0xED, 0x19, 0x12, 0xB5, 0xC7, 0x65, 0x3A,
608 0x16, 0x7B, 0x94, 0x34, 0x91, 0x47, 0xEE, 0xAF, 0x85, 0xCC, 0x9C, 0xE2, 0xE8, 0x16, 0x61, 0xF3, 0x21, 0x51, 0x2D, 0x5D, 0x2C, 0x05, 0x80, 0xB0,
609 0x3D, 0x17, 0x04, 0xEE, 0xF2, 0x31, 0x7F, 0x45, 0x18, 0x5C, 0x82, 0x58, 0x38, 0x7E, 0x7E, 0xC9, 0x79, 0xC0, 0x47, 0x07, 0xEF, 0x54, 0x62, 0x41,
610 0x27, 0x84, 0xAF, 0xE4, 0x1A, 0x7B, 0x45, 0xC8, 0x3B, 0x9C, 0xBE, 0x48, 0xF9, 0x12, 0x7C, 0xB4, 0x40, 0x0B, 0xE9, 0xE9, 0x6A, 0xC5, 0xDE, 0x17,
611 0xF2, 0xC9, 0xDE, 0xA3, 0x5E, 0x37, 0x34, 0xE7, 0x9B, 0x64, 0x67, 0x3F, 0x85, 0x68, 0x1C, 0x4E,
612 	};
613 
614 	const u8 x[] = {
615 0x2F, 0x19, 0x91, 0xC1, 0xAF, 0x40, 0x18, 0x72, 0x8A, 0x5A, 0x43, 0x1B, 0x9B, 0x54, 0x59, 0xDF, 0xB1, 0x6F, 0x6D, 0x25, 0x67, 0x97, 0xFE, 0x57,
616 0x0E, 0xC6, 0xBC, 0x65,
617 	};
618 
619 	const u8 y[] = {
620 0x04, 0xED, 0xE5, 0xC6, 0x7E, 0xA2, 0x92, 0x97, 0xA8, 0xCA, 0xCB, 0x6B, 0xDE, 0x6F, 0x46, 0x66, 0xAE, 0xA2, 0x7D, 0x10, 0x3D, 0xD1, 0xE9, 0xE9,
621 0x58, 0x2F, 0x76, 0xA2, 0xF2, 0x2B, 0x8B, 0x1B, 0x32, 0x23, 0x0B, 0xC5, 0x8F, 0x06, 0xB7, 0x68, 0xF8, 0x10, 0x2B, 0x49, 0xFA, 0x1C, 0xAE, 0x5E,
622 0x18, 0x92, 0x14, 0x94, 0x7F, 0x62, 0x39, 0xB6, 0xC6, 0xCE, 0x7C, 0x9B, 0xC2, 0xD2, 0x30, 0xE8, 0x9A, 0x40, 0xBE, 0xE2, 0xC3, 0x3A, 0x88, 0x61,
623 0xFD, 0x4F, 0x7D, 0x35, 0xB7, 0x88, 0xFE, 0x95, 0xB2, 0xD5, 0x88, 0x5D, 0x8C, 0x8F, 0xAE, 0xA8, 0x1C, 0x90, 0xBE, 0x4C, 0xEE, 0x27, 0x84, 0xE3,
624 0x35, 0x77, 0xA7, 0x1D, 0x3B, 0x7F, 0x08, 0x5D, 0x71, 0xE9, 0xA1, 0xD4, 0x78, 0x15, 0xC7, 0x3F, 0xA0, 0x87, 0xAC, 0xAA, 0xB9, 0xFC, 0xB5, 0x65,
625 0x5A, 0xC9, 0x57, 0x0E, 0x68, 0x52, 0xBE, 0x7C, 0x9C, 0x0A, 0xEC, 0xEA, 0x8B, 0xD9, 0xAA, 0x75, 0xA4, 0x4F, 0xC3, 0x14, 0x7F, 0x73, 0x3E, 0x90,
626 0x6A, 0xDB, 0x0F, 0xD7, 0x6D, 0x61, 0x35, 0x61, 0xB1, 0xDB, 0x36, 0x4B, 0xBD, 0xC9, 0xAF, 0xD3, 0xCE, 0x8F, 0x5F, 0x17, 0xE3, 0xE7, 0x12, 0x03,
627 0x4A, 0x99, 0x93, 0x50, 0x80, 0x59, 0xFA, 0x52, 0x44, 0x1F, 0xA9, 0x0D, 0xDF, 0xE9, 0xA0, 0xF2, 0xA0, 0xB9, 0x19, 0x2F, 0xE2, 0x22, 0x0C, 0x08,
628 0x1B, 0xD0, 0xC0, 0xF0, 0xE0, 0x7C, 0xB5, 0xF1, 0xEE, 0x4F, 0xF4, 0x05, 0x23, 0x59, 0x1F, 0x17, 0x8A, 0x4F, 0xC7, 0xCB, 0x50, 0x65, 0xF6, 0xA3,
629 0x82, 0x16, 0xE9, 0xA0, 0x99, 0xC2, 0x05, 0xB2, 0x9B, 0x87, 0x46, 0xD8, 0x65, 0xE1, 0xAF, 0x6D, 0x90, 0x3E, 0x5A, 0x13, 0x80, 0x04, 0x91, 0x0B,
630 0x70, 0xEB, 0x5B, 0x84, 0xEE, 0xD9, 0x76, 0x0E, 0xA6, 0x05, 0x78, 0xBF, 0x08, 0x85, 0x28, 0x98,
631 	};
632 
633 	const u8 msg[] = "This is a test message for KCDSA usage!";
634 
635 	const u8 nonce[] = {
636 0x49, 0x56, 0x19, 0x94, 0xFD, 0x2B, 0xAD, 0x5E, 0x41, 0x0C, 0xA1, 0xC1, 0x5C, 0x3F, 0xD3, 0xF1, 0x2E, 0x70, 0x26, 0x3F, 0x28, 0x20, 0xAD, 0x5C,
637 0x56, 0x6D, 0xED, 0x80,
638 	};
639 	u8 sig[28*2] = { 0 };
640 	gen_hash_alg_type kcdsa_hash = HASH_SHA256;
641 #endif
642 
643 #if 1
644 	/* This example is taken from ISO14888-3 KCDSA (Appendix F "Numerical examples" */
645 	const u8 p[] = {
646 0xCB, 0xAE, 0xAC, 0xE3, 0x67, 0x7E, 0x98, 0xAD, 0xB2, 0xE4, 0x9C, 0x00, 0x2B, 0x8B, 0x0F, 0x43, 0x41, 0x43, 0xB4, 0x66, 0x51, 0x58, 0x39, 0xBF,
647 0x81, 0x3B, 0x09, 0x7D, 0x2D, 0x1E, 0xE6, 0x81, 0x50, 0x08, 0xC2, 0x7A, 0x34, 0x15, 0xBC, 0x22, 0x31, 0x60, 0x98, 0x74, 0x5E, 0x58, 0x44, 0xF3,
648 0x3E, 0xCC, 0x88, 0x87, 0xC1, 0x6D, 0xFB, 0x1C, 0xFB, 0x77, 0xDC, 0x4C, 0x3F, 0x35, 0x71, 0xCC, 0xEE, 0xFD, 0x42, 0x91, 0x8F, 0x6C, 0x48, 0xC3,
649 0x70, 0x2A, 0xB6, 0xEF, 0x09, 0x19, 0xB7, 0xE8, 0x40, 0x2F, 0xC8, 0x9B, 0x35, 0xD0, 0x9A, 0x0E, 0x50, 0x40, 0xE3, 0x09, 0x1E, 0xE4, 0x67, 0x4B,
650 0xE8, 0x91, 0x93, 0x3C, 0x10, 0x07, 0xE0, 0x17, 0xED, 0xD4, 0x08, 0x18, 0x7E, 0x41, 0x14, 0xB6, 0xBE, 0x55, 0x48, 0xD7, 0x8D, 0xB5, 0x8B, 0x84,
651 0x84, 0x75, 0xA4, 0x22, 0x62, 0xD7, 0xEB, 0x79, 0x5F, 0x08, 0xD1, 0x61, 0x10, 0x55, 0xEF, 0xEA, 0x8A, 0x6A, 0xEB, 0x20, 0xEB, 0x0F, 0x1C, 0x22,
652 0xF0, 0x02, 0xA2, 0xE8, 0x19, 0x5B, 0xCB, 0xBA, 0x83, 0x0B, 0x84, 0x61, 0x35, 0x31, 0xBD, 0xD9, 0xEC, 0x71, 0xE5, 0xA9, 0x7A, 0x9D, 0xCC, 0xC6,
653 0x5D, 0x61, 0x17, 0xB8, 0x5D, 0x0C, 0xA6, 0x6C, 0x3F, 0xDA, 0xA3, 0x47, 0x6E, 0x97, 0xAD, 0xCD, 0x05, 0xA1, 0xF4, 0x90, 0x2B, 0xD0, 0x4B, 0x92,
654 0xF4, 0x00, 0xC4, 0x2B, 0xA0, 0xC9, 0x94, 0x0A, 0x32, 0x60, 0x04, 0x43, 0x3B, 0x6D, 0x30, 0x01, 0x28, 0xBF, 0x93, 0x0F, 0x48, 0x4E, 0xAA, 0x63,
655 0x02, 0xCD, 0x7A, 0x31, 0x9E, 0xE5, 0xE5, 0x61, 0xA1, 0x2A, 0x36, 0x25, 0x59, 0x40, 0x20, 0xC2, 0x40, 0xDB, 0xA3, 0xBE, 0xBD, 0x8A, 0x47, 0x51,
656 0x58, 0x41, 0xF1, 0x98, 0xEB, 0xE4, 0x32, 0x18, 0x26, 0x39, 0x61, 0x6F, 0x6A, 0x7F, 0x9B, 0xD7, 0x43, 0x4F, 0x05, 0x34, 0x8F, 0x7F, 0x1D, 0xB3,
657 0x11, 0x5A, 0x9F, 0xEE, 0xBA, 0x98, 0x4A, 0x2B, 0x73, 0x78, 0x43, 0x34, 0xDE, 0x77, 0x37, 0xEE, 0x37, 0x04, 0x53, 0x5F, 0xCA, 0x2F, 0x49, 0x04,
658 0xCB, 0x4A, 0xD5, 0x8F, 0x17, 0x2F, 0x26, 0x48, 0xE1, 0xD6, 0x2D, 0x05, 0x85, 0x39, 0xAC, 0x78, 0x3D, 0x03, 0x2D, 0x18, 0x33, 0xD2, 0xB9, 0xAA,
659 0xD9, 0x69, 0x82, 0xC9, 0x69, 0x2E, 0x0D, 0xDB, 0xB6, 0x61, 0x55, 0x08, 0x83, 0xED, 0x66, 0xF7, 0xAA, 0x8B, 0xCE, 0x8F, 0xF0, 0x66, 0x3A, 0x0A,
660 0xDD, 0xA2, 0x26, 0xC7, 0xBD, 0x0E, 0x06, 0xDF, 0xC7, 0x25, 0x94, 0xA3, 0x87, 0xC6, 0x76, 0xA3, 0xCA, 0x06, 0xA3, 0x00, 0x62, 0xBE, 0x1D, 0x85,
661 0xF2, 0x3E, 0x3E, 0x02, 0xC4, 0xD6, 0x5E, 0x06, 0x1B, 0x61, 0x9B, 0x04, 0xE8, 0x3A, 0x31, 0x8E, 0xC5, 0x5E, 0xCA, 0x06, 0x9E, 0xB8, 0x56, 0x03,
662 	};
663 
664 	const u8 q[] = {
665 0xC2, 0xA8, 0xCA, 0xF4, 0x87, 0x18, 0x00, 0x79, 0x66, 0xF2, 0xEC, 0x13, 0x4E, 0xAB, 0xA3, 0xCB, 0xB0, 0x7F, 0x31, 0xA8, 0xF2, 0x66, 0x7A, 0xCB,
666 0x5D, 0x9B, 0x87, 0x2F, 0xA7, 0x60, 0xA4, 0x01,
667 	};
668 
669 	const u8 g[] = {
670 0x17, 0xA1, 0xC1, 0x67, 0xAF, 0x83, 0x6C, 0xC8, 0x51, 0x49, 0xBE, 0x43, 0x63, 0xF1, 0xBB, 0x4F, 0x00, 0x10, 0x84, 0x8F, 0xC9, 0xB6, 0x78, 0xB4,
671 0xE0, 0x26, 0xF1, 0xF3, 0x87, 0x13, 0x37, 0x49, 0xA4, 0xB1, 0xBB, 0xA4, 0xC2, 0x32, 0x52, 0xA4, 0xC8, 0x6F, 0x31, 0xE2, 0x1E, 0x8A, 0xCA, 0xCB,
672 0x4E, 0x33, 0xAD, 0x89, 0xB7, 0xC3, 0xD7, 0x9A, 0x54, 0x09, 0x26, 0x8B, 0xFB, 0xA8, 0x2B, 0x45, 0x81, 0x4E, 0x43, 0x52, 0x0C, 0x09, 0xD6, 0x31,
673 0x61, 0x3F, 0xA3, 0x5D, 0xB9, 0xCA, 0xF1, 0x8F, 0x79, 0x1C, 0x27, 0x29, 0xA4, 0xB0, 0x14, 0xBC, 0x79, 0xA8, 0x5A, 0x90, 0xCD, 0x54, 0x10, 0x37,
674 0x11, 0x9E, 0xCC, 0xDE, 0x07, 0x78, 0x86, 0x3F, 0xFC, 0xB9, 0xC2, 0x59, 0x31, 0xFC, 0xD3, 0x3A, 0x67, 0x06, 0xE5, 0xFE, 0x1F, 0x49, 0x5B, 0xB8,
675 0xBC, 0xB3, 0xD0, 0xEE, 0xC9, 0xB6, 0xD5, 0xA9, 0x37, 0x31, 0x27, 0xA2, 0x12, 0x1E, 0x37, 0xD9, 0x8A, 0x84, 0x03, 0x30, 0x25, 0x8D, 0xBF, 0xCE,
676 0xE7, 0xE0, 0x6F, 0x81, 0x5B, 0x69, 0xC1, 0x6C, 0x5D, 0x17, 0x28, 0x9C, 0x4C, 0xC3, 0x7E, 0x71, 0x9B, 0x85, 0x62, 0x98, 0xD4, 0xE1, 0x57, 0x4E,
677 0x4F, 0x4F, 0x85, 0x15, 0xBA, 0xF9, 0xA8, 0x50, 0xD1, 0x1D, 0xDA, 0x09, 0x55, 0xBC, 0x30, 0xFA, 0x5B, 0x16, 0x79, 0x2D, 0x67, 0x3A, 0x3B, 0x1F,
678 0x41, 0x51, 0x2F, 0xC3, 0xEB, 0x89, 0x45, 0x2D, 0x51, 0x50, 0x9F, 0x97, 0x4D, 0x87, 0x8B, 0x48, 0x2D, 0x2A, 0xD2, 0xED, 0x32, 0xBE, 0x19, 0x05,
679 0x6F, 0x57, 0x45, 0x04, 0x2B, 0xFF, 0x80, 0x4F, 0xB7, 0x48, 0x27, 0x96, 0x61, 0x2B, 0x74, 0x6F, 0xE8, 0xD7, 0x0A, 0x83, 0x8C, 0xC6, 0xF4, 0x96,
680 0xDD, 0x0F, 0xFC, 0x3D, 0x95, 0xC1, 0xE0, 0xB1, 0x98, 0x18, 0x4D, 0x73, 0x52, 0x36, 0x56, 0xA0, 0x64, 0x31, 0xBC, 0x52, 0x5C, 0x2B, 0xC1, 0x61,
681 0x97, 0x29, 0xE8, 0xC0, 0x88, 0xF6, 0xDF, 0x91, 0x56, 0x45, 0xE0, 0x60, 0x92, 0x2A, 0x4A, 0xF3, 0xED, 0xD6, 0x30, 0x47, 0xC7, 0xB6, 0x07, 0x7C,
682 0x66, 0x7C, 0x07, 0xD8, 0x8E, 0xB0, 0x0F, 0x4C, 0xFE, 0x59, 0xD3, 0x2E, 0x5F, 0x54, 0x50, 0x12, 0xC5, 0x66, 0x51, 0x6B, 0x78, 0x74, 0xFB, 0x3D,
683 0xAE, 0xD5, 0x14, 0x03, 0x31, 0xF2, 0x95, 0x28, 0xB3, 0x0F, 0xC8, 0xB8, 0xA9, 0x37, 0x1C, 0x28, 0x18, 0x01, 0x7B, 0x09, 0x53, 0xA8, 0x4F, 0xFC,
684 0x9F, 0xBF, 0xF8, 0x4B, 0x64, 0xBF, 0x02, 0x38, 0xAA, 0x7E, 0x2A, 0xF2, 0xEC, 0xAD, 0xC1, 0x5A, 0x1C, 0x06, 0xDA, 0xDC, 0xF1, 0xF2, 0xE7, 0xB1,
685 0x24, 0x0A, 0x5E, 0x64, 0x5A, 0x64, 0x69, 0xC9, 0xB0, 0x02, 0x21, 0x5D, 0x9A, 0x91, 0xC2, 0xA4, 0xED, 0x2F, 0xB5, 0x47, 0xA9, 0x42, 0xD7, 0x77,
686 	};
687 
688 	const u8 x[] = {
689 0x7C, 0x28, 0x56, 0x9A, 0x94, 0xB4, 0x6F, 0xA7, 0x45, 0xC8, 0xD3, 0x06, 0xAD, 0x7D, 0xC1, 0x89, 0x96, 0xCE, 0x04, 0x6E, 0xEB, 0xE0, 0x43, 0x83,
690 0x83, 0x91, 0xC2, 0x32, 0x07, 0x8D, 0xB0, 0x5A,
691 	};
692 
693 	const u8 y[] = {
694 0x25, 0x74, 0xE1, 0x0E, 0x80, 0x6F, 0x1C, 0x42, 0x58, 0xF7, 0xCF, 0x8F, 0xA4, 0xA6, 0xCF, 0x2B, 0xEB, 0x17, 0x7D, 0xBE, 0x60, 0xE4, 0xEC, 0x17,
695 0xDF, 0x21, 0xDC, 0xDB, 0xA7, 0x20, 0x73, 0xF6, 0x55, 0x65, 0x50, 0x6D, 0xA3, 0xDF, 0x98, 0xD5, 0xA6, 0xC8, 0xEE, 0xE6, 0x1B, 0x6B, 0x5D, 0x88,
696 0xB9, 0x8C, 0x47, 0xC2, 0xB2, 0xF6, 0xFC, 0x6F, 0x50, 0x4F, 0xA4, 0xFB, 0xC7, 0xF4, 0x11, 0xE2, 0x3E, 0xAA, 0x3B, 0x18, 0x7A, 0x35, 0x3D, 0xAE,
697 0xD4, 0x15, 0x33, 0xA9, 0x55, 0x8A, 0xB9, 0x32, 0x0A, 0x15, 0x4C, 0xAE, 0xCC, 0x54, 0x4E, 0x43, 0x00, 0x08, 0x88, 0x9A, 0x2C, 0x89, 0x93, 0x73,
698 0xEC, 0x75, 0xA2, 0x4C, 0xFF, 0x26, 0x24, 0x7C, 0xF2, 0x97, 0xD2, 0x93, 0x74, 0x7E, 0xCC, 0x05, 0xB3, 0x48, 0x36, 0x47, 0xA8, 0x7B, 0xCB, 0xB8,
699 0xD4, 0x50, 0x00, 0x92, 0x09, 0xF5, 0xE4, 0x49, 0xA0, 0x0A, 0x65, 0x9B, 0x63, 0x7C, 0xE1, 0x39, 0xCF, 0x64, 0x87, 0xAC, 0xA7, 0x0F, 0x9C, 0x00,
700 0xCB, 0x67, 0x0C, 0x7F, 0x3B, 0x95, 0xBF, 0xD7, 0xCF, 0x23, 0x6A, 0x0A, 0x6F, 0x3C, 0x93, 0xBE, 0x8D, 0x9C, 0xF5, 0x91, 0xC9, 0xD3, 0x06, 0x86,
701 0x94, 0x15, 0xB1, 0xAA, 0x97, 0x26, 0x4B, 0x90, 0x41, 0x67, 0x85, 0x0A, 0x47, 0x94, 0xC7, 0x80, 0xBE, 0x45, 0x27, 0xDF, 0xFE, 0xB6, 0x7B, 0xE6,
702 0xE6, 0x67, 0x86, 0xC5, 0xCC, 0xE0, 0x37, 0x8C, 0xCB, 0x49, 0x92, 0x0D, 0x85, 0x55, 0x58, 0xF4, 0xDA, 0xC4, 0xC4, 0x2F, 0x92, 0xDD, 0x22, 0x9B,
703 0x48, 0x3B, 0x22, 0x57, 0xDB, 0x0C, 0xE3, 0x5D, 0xC7, 0x37, 0xF9, 0x80, 0x1A, 0x26, 0x1A, 0x02, 0xBD, 0xF7, 0x18, 0xC2, 0xFD, 0x4D, 0x69, 0xC5,
704 0x2E, 0x0D, 0x97, 0x12, 0xB4, 0x2C, 0x48, 0x97, 0xBA, 0xE7, 0xC6, 0x84, 0xD3, 0xD3, 0x5B, 0xC5, 0x72, 0x6C, 0xE8, 0x99, 0x26, 0x96, 0xB0, 0x44,
705 0xD7, 0x22, 0xAF, 0xBA, 0x78, 0xEF, 0xA8, 0x58, 0xC4, 0xD1, 0x0F, 0x19, 0x72, 0x11, 0x2C, 0xE8, 0xFF, 0xD3, 0x97, 0x92, 0x49, 0xBF, 0x14, 0xE4,
706 0x9D, 0x8E, 0x0D, 0x9A, 0xCB, 0x1B, 0x0A, 0x9C, 0xA9, 0x0D, 0x05, 0x51, 0x18, 0x03, 0x84, 0x5D, 0x7C, 0x67, 0x0B, 0xCF, 0x1B, 0x06, 0x64, 0x97,
707 0xA7, 0x74, 0x3B, 0x08, 0xA2, 0x19, 0xE7, 0x64, 0xEA, 0x0A, 0x3A, 0x2A, 0x61, 0x76, 0x61, 0xC1, 0x6A, 0x37, 0x2F, 0xE0, 0x58, 0xB5, 0x47, 0xA2,
708 0x8B, 0x62, 0x6E, 0xCF, 0x44, 0x22, 0x22, 0xE1, 0x8E, 0xEF, 0x48, 0x7C, 0xC1, 0x01, 0xDB, 0xFB, 0x71, 0x5B, 0xC3, 0x3A, 0xB8, 0x59, 0x28, 0xEC,
709 0xF0, 0xBD, 0x4D, 0xEA, 0x30, 0xF2, 0x50, 0xA6, 0xA5, 0xC8, 0x61, 0x78, 0x83, 0xEA, 0x0F, 0x87, 0x3E, 0x7A, 0x46, 0x51, 0x98, 0xC4, 0x64, 0x4B,
710 	};
711 
712 	const u8 msg[] = "This is a test message for KCDSA usage!";
713 
714 	const u8 nonce[] = {
715 0x83, 0xF3, 0x00, 0x8F, 0xCE, 0xBA, 0xE5, 0x7E, 0xC7, 0xA6, 0x4A, 0x3A, 0xF7, 0xEE, 0x6E, 0xE1, 0x9C, 0xC1, 0x97, 0xA6, 0xD5, 0xEB, 0xA3, 0xA5,
716 0xB3, 0xEF, 0x79, 0xB2, 0xF8, 0xF3, 0xDD, 0x53,
717 	};
718 	u8 sig[32*2] = { 0 };
719 	gen_hash_alg_type kcdsa_hash = HASH_SHA256;
720 #endif
721 
722 	kcdsa_priv_key priv;
723 	kcdsa_pub_key pub;
724 	kcdsa_pub_key pub2;
725 
726 	FORCE_USED_VAR(argc);
727 	FORCE_USED_VAR(argv);
728 
729 	/* Sanity check on size for DSA.
730 	 * NOTE: the double parentheses are here to handle -Wunreachable-code
731 	 */
732 	if((NN_USABLE_MAX_BIT_LEN) < (4096)){
733 		ext_printf("Error: you seem to have compiled libecc with usable NN size < 4096, not suitable for DSA.\n");
734 		ext_printf("  => Please recompile libecc with EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\"\n");
735 		ext_printf("     This will increase usable NN for proper DSA up to 4096 bits.\n");
736 		ext_printf("     Then recompile the current examples with the same EXTRA_CFLAGS=\"-DUSER_NN_BIT_LEN=4096\" flag and execute again!\n");
737 		/* NOTE: ret = 0 here to pass self tests even if the library is not compatible */
738 		ret = 0;
739 		goto err;
740 	}
741 
742 
743 	ret = kcdsa_import_priv_key(&priv, p, sizeof(p), q, sizeof(q), g, sizeof(g), x, sizeof(x)); EG(ret, err);
744 	ret = kcdsa_import_pub_key(&pub, p, sizeof(p), q, sizeof(q), g, sizeof(g), y, sizeof(y)); EG(ret, err);
745 	ret = kcdsa_compute_pub_from_priv(&pub2, &priv); EG(ret, err);
746 
747 	nn_print("y", &(pub2.y));
748 
749 	ret = kcdsa_sign(&priv, msg, sizeof(msg)-1, nonce, sizeof(nonce), sig, sizeof(sig), kcdsa_hash); EG(ret, err);
750 
751 	buf_print("sig", sig, sizeof(sig));
752 
753 	ret = kcdsa_verify(&pub, msg, sizeof(msg)-1, sig, sizeof(sig), kcdsa_hash);
754 	ext_printf("Signature result %d\n", ret);
755 
756 err:
757 	return ret;
758 }
759 #endif
760