xref: /freebsd/crypto/libecc/src/sig/eddsa.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans  *  Copyright (C) 2021 - This file is part of libecc project
3*f0865ec9SKyle Evans  *
4*f0865ec9SKyle Evans  *  Authors:
5*f0865ec9SKyle Evans  *      Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans  *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans  *
8*f0865ec9SKyle Evans  *  This software is licensed under a dual BSD and GPL v2 license.
9*f0865ec9SKyle Evans  *  See LICENSE file at the root folder of the project.
10*f0865ec9SKyle Evans  */
11*f0865ec9SKyle Evans #include <libecc/lib_ecc_config.h>
12*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448)
13*f0865ec9SKyle Evans 
14*f0865ec9SKyle Evans /*
15*f0865ec9SKyle Evans  * XXX: EdDSA is incompatible with small stack devices for now ...
16*f0865ec9SKyle Evans  */
17*f0865ec9SKyle Evans #if defined(USE_SMALL_STACK)
18*f0865ec9SKyle Evans #error "Error: EDDSA25519 and EDDSA448 are incompatible with USE_SMALL_STACK (devices low on memory)"
19*f0865ec9SKyle Evans #endif
20*f0865ec9SKyle Evans 
21*f0865ec9SKyle Evans /*
22*f0865ec9SKyle Evans  * Sanity checks on the hash functions and curves depending on the EdDSA variant.
23*f0865ec9SKyle Evans  */
24*f0865ec9SKyle Evans /* EDDSA25519 used SHA-512 as a fixed hash function and WEI25519 as a fixed
25*f0865ec9SKyle Evans  * curve.
26*f0865ec9SKyle Evans  */
27*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
28*f0865ec9SKyle Evans #if !defined(WITH_HASH_SHA512) || !defined(WITH_CURVE_WEI25519)
29*f0865ec9SKyle Evans #error "Error: EDDSA25519 needs SHA-512 and WEI25519 to be defined! Please define them in libecc config file"
30*f0865ec9SKyle Evans #endif
31*f0865ec9SKyle Evans #endif
32*f0865ec9SKyle Evans /* EDDSA448 used SHAKE256 as a fixed hash function and WEI448 as a fixed
33*f0865ec9SKyle Evans  * curve.
34*f0865ec9SKyle Evans  */
35*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
36*f0865ec9SKyle Evans #if !defined(WITH_HASH_SHAKE256) || !defined(WITH_CURVE_WEI448)
37*f0865ec9SKyle Evans #error "Error: EDDSA25519 needs SHAKE256 and WEI448 to be defined! Please define them in libecc config file"
38*f0865ec9SKyle Evans #endif
39*f0865ec9SKyle Evans #endif
40*f0865ec9SKyle Evans 
41*f0865ec9SKyle Evans #include <libecc/nn/nn_rand.h>
42*f0865ec9SKyle Evans #include <libecc/nn/nn_mul_public.h>
43*f0865ec9SKyle Evans #include <libecc/nn/nn_logical.h>
44*f0865ec9SKyle Evans #include <libecc/fp/fp.h>
45*f0865ec9SKyle Evans #include <libecc/fp/fp_sqrt.h>
46*f0865ec9SKyle Evans /* Include the "internal" header as we use non public API here */
47*f0865ec9SKyle Evans #include "../nn/nn_div.h"
48*f0865ec9SKyle Evans 
49*f0865ec9SKyle Evans 
50*f0865ec9SKyle Evans #include <libecc/sig/sig_algs_internal.h>
51*f0865ec9SKyle Evans #include <libecc/sig/sig_algs.h>
52*f0865ec9SKyle Evans #include <libecc/sig/ec_key.h>
53*f0865ec9SKyle Evans #include <libecc/utils/utils.h>
54*f0865ec9SKyle Evans #ifdef VERBOSE_INNER_VALUES
55*f0865ec9SKyle Evans #define EC_SIG_ALG "EDDSA"
56*f0865ec9SKyle Evans #endif
57*f0865ec9SKyle Evans #include <libecc/utils/dbg_sig.h>
58*f0865ec9SKyle Evans 
59*f0865ec9SKyle Evans 
dom(u16 x,const u8 * y,u16 olen_y,const hash_mapping * h,hash_context * h_ctx,u8 dom_type)60*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int dom(u16 x, const u8 *y, u16 olen_y, const hash_mapping *h,
61*f0865ec9SKyle Evans 		      hash_context *h_ctx, u8 dom_type){
62*f0865ec9SKyle Evans 	u8 tmp[2];
63*f0865ec9SKyle Evans 	int ret;
64*f0865ec9SKyle Evans 
65*f0865ec9SKyle Evans 	MUST_HAVE((h != NULL) && (h_ctx != NULL), ret, err);
66*f0865ec9SKyle Evans 	/* Sanity check on ancillary data len, its size must not exceed 255 bytes as per RFC8032 */
67*f0865ec9SKyle Evans 	MUST_HAVE((x <= 255) && (olen_y <= 255), ret, err);
68*f0865ec9SKyle Evans 
69*f0865ec9SKyle Evans 	if(dom_type == 2){
70*f0865ec9SKyle Evans 		ret = h->hfunc_update(h_ctx, (const u8*)"SigEd25519 no Ed25519 collisions", 32); EG(ret, err);
71*f0865ec9SKyle Evans 	}
72*f0865ec9SKyle Evans 	else if(dom_type == 4){
73*f0865ec9SKyle Evans 		ret = h->hfunc_update(h_ctx, (const u8*)"SigEd448", 8); EG(ret, err);
74*f0865ec9SKyle Evans 	}
75*f0865ec9SKyle Evans 	else{
76*f0865ec9SKyle Evans 		ret = -1;
77*f0865ec9SKyle Evans 		goto err;
78*f0865ec9SKyle Evans 	}
79*f0865ec9SKyle Evans 	tmp[0] = (u8)x;
80*f0865ec9SKyle Evans 	tmp[1] = (u8)olen_y;
81*f0865ec9SKyle Evans 	ret = h->hfunc_update(h_ctx, tmp, 2); EG(ret, err);
82*f0865ec9SKyle Evans 	if(y != NULL){
83*f0865ec9SKyle Evans 		ret = h->hfunc_update(h_ctx, y, olen_y); EG(ret, err);
84*f0865ec9SKyle Evans 	}
85*f0865ec9SKyle Evans 
86*f0865ec9SKyle Evans err:
87*f0865ec9SKyle Evans 	return ret;
88*f0865ec9SKyle Evans }
89*f0865ec9SKyle Evans 
90*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
91*f0865ec9SKyle Evans /* Helper for dom2(x, y).
92*f0865ec9SKyle Evans  *
93*f0865ec9SKyle Evans  * See RFC8032:
94*f0865ec9SKyle Evans  *
95*f0865ec9SKyle Evans  * dom2(x, y)     The blank octet string when signing or verifying
96*f0865ec9SKyle Evans  *                Ed25519.  Otherwise, the octet string: "SigEd25519 no
97*f0865ec9SKyle Evans  *                Ed25519 collisions" || octet(x) || octet(OLEN(y)) ||
98*f0865ec9SKyle Evans  *                y, where x is in range 0-255 and y is an octet string
99*f0865ec9SKyle Evans  *                of at most 255 octets.  "SigEd25519 no Ed25519
100*f0865ec9SKyle Evans  *                collisions" is in ASCII (32 octets).
101*f0865ec9SKyle Evans  */
dom2(u16 x,const u8 * y,u16 olen_y,const hash_mapping * h,hash_context * h_ctx)102*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int dom2(u16 x, const u8 *y, u16 olen_y, const hash_mapping *h,
103*f0865ec9SKyle Evans 		       hash_context *h_ctx){
104*f0865ec9SKyle Evans 	return dom(x, y, olen_y, h, h_ctx, 2);
105*f0865ec9SKyle Evans }
106*f0865ec9SKyle Evans #endif /* defined(WITH_SIG_EDDSA25519) */
107*f0865ec9SKyle Evans 
108*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
109*f0865ec9SKyle Evans /* Helper for dom4(x, y).
110*f0865ec9SKyle Evans  *
111*f0865ec9SKyle Evans  * See RFC8032:
112*f0865ec9SKyle Evans  *
113*f0865ec9SKyle Evans  * dom4(x, y)     The octet string "SigEd448" || octet(x) ||
114*f0865ec9SKyle Evans  *                octet(OLEN(y)) || y, where x is in range 0-255 and y
115*f0865ec9SKyle Evans  *                is an octet string of at most 255 octets.  "SigEd448"
116*f0865ec9SKyle Evans  *                is in ASCII (8 octets).
117*f0865ec9SKyle Evans  */
dom4(u16 x,const u8 * y,u16 olen_y,const hash_mapping * h,hash_context * h_ctx)118*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int dom4(u16 x, const u8 *y, u16 olen_y, const hash_mapping *h,
119*f0865ec9SKyle Evans 		       hash_context *h_ctx){
120*f0865ec9SKyle Evans 	return dom(x, y, olen_y, h, h_ctx, 4);
121*f0865ec9SKyle Evans }
122*f0865ec9SKyle Evans #endif /* defined(WITH_SIG_EDDSA448) */
123*f0865ec9SKyle Evans 
124*f0865ec9SKyle Evans /* EdDSA sanity check on keys.
125*f0865ec9SKyle Evans  * EDDSA25519 and variants only support WEI25519 as a curve, and SHA-512 as a hash function.
126*f0865ec9SKyle Evans  * EDDSA448 and variants only support WEI448 as a curve, and SHAKE256 as a "hash function".
127*f0865ec9SKyle Evans  */
get_eddsa_hash_type(ec_alg_type sig_type)128*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline hash_alg_type get_eddsa_hash_type(ec_alg_type sig_type){
129*f0865ec9SKyle Evans 	hash_alg_type hash_type = UNKNOWN_HASH_ALG;
130*f0865ec9SKyle Evans 
131*f0865ec9SKyle Evans 	switch (sig_type) {
132*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
133*f0865ec9SKyle Evans 		case EDDSA25519:
134*f0865ec9SKyle Evans 		case EDDSA25519PH:
135*f0865ec9SKyle Evans 		case EDDSA25519CTX:{
136*f0865ec9SKyle Evans 			hash_type = SHA512;
137*f0865ec9SKyle Evans 			break;
138*f0865ec9SKyle Evans 		}
139*f0865ec9SKyle Evans #endif
140*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
141*f0865ec9SKyle Evans 		case EDDSA448:
142*f0865ec9SKyle Evans 		case EDDSA448PH:{
143*f0865ec9SKyle Evans 			hash_type = SHAKE256;
144*f0865ec9SKyle Evans 			break;
145*f0865ec9SKyle Evans 		}
146*f0865ec9SKyle Evans #endif
147*f0865ec9SKyle Evans 		default:{
148*f0865ec9SKyle Evans 			hash_type = UNKNOWN_HASH_ALG;
149*f0865ec9SKyle Evans 			break;
150*f0865ec9SKyle Evans 		}
151*f0865ec9SKyle Evans 	}
152*f0865ec9SKyle Evans 	return hash_type;
153*f0865ec9SKyle Evans }
154*f0865ec9SKyle Evans 
155*f0865ec9SKyle Evans /*
156*f0865ec9SKyle Evans  * Check given EdDSA key type does match given curve type. Returns 0 on success,
157*f0865ec9SKyle Evans  * and -1 on error.
158*f0865ec9SKyle Evans  */
eddsa_key_type_check_curve(ec_alg_type key_type,ec_curve_type curve_type)159*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_key_type_check_curve(ec_alg_type key_type,
160*f0865ec9SKyle Evans 				      ec_curve_type curve_type)
161*f0865ec9SKyle Evans {
162*f0865ec9SKyle Evans 	int ret;
163*f0865ec9SKyle Evans 
164*f0865ec9SKyle Evans 	switch (key_type) {
165*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
166*f0865ec9SKyle Evans 		case EDDSA25519:
167*f0865ec9SKyle Evans 		case EDDSA25519PH:
168*f0865ec9SKyle Evans 		case EDDSA25519CTX:{
169*f0865ec9SKyle Evans 			/* Check curve */
170*f0865ec9SKyle Evans 			ret = (curve_type == WEI25519) ? 0 : -1;
171*f0865ec9SKyle Evans 			break;
172*f0865ec9SKyle Evans 		}
173*f0865ec9SKyle Evans #endif
174*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
175*f0865ec9SKyle Evans 		case EDDSA448:
176*f0865ec9SKyle Evans 		case EDDSA448PH:{
177*f0865ec9SKyle Evans 			/* Check curve */
178*f0865ec9SKyle Evans 			ret = (curve_type == WEI448) ? 0 : -1;
179*f0865ec9SKyle Evans 			break;
180*f0865ec9SKyle Evans 		}
181*f0865ec9SKyle Evans #endif
182*f0865ec9SKyle Evans 		default:{
183*f0865ec9SKyle Evans 			ret = -1;
184*f0865ec9SKyle Evans 			break;
185*f0865ec9SKyle Evans 		}
186*f0865ec9SKyle Evans 	}
187*f0865ec9SKyle Evans 
188*f0865ec9SKyle Evans 	return ret;
189*f0865ec9SKyle Evans }
190*f0865ec9SKyle Evans 
eddsa_priv_key_sanity_check(const ec_priv_key * in_priv)191*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_priv_key_sanity_check(const ec_priv_key *in_priv)
192*f0865ec9SKyle Evans {
193*f0865ec9SKyle Evans 	int ret;
194*f0865ec9SKyle Evans 
195*f0865ec9SKyle Evans 	ret = priv_key_check_initialized(in_priv); EG(ret, err);
196*f0865ec9SKyle Evans 	ret = eddsa_key_type_check_curve(in_priv->key_type,
197*f0865ec9SKyle Evans 			       in_priv->params->curve_type);
198*f0865ec9SKyle Evans 
199*f0865ec9SKyle Evans err:
200*f0865ec9SKyle Evans 	return ret;
201*f0865ec9SKyle Evans }
202*f0865ec9SKyle Evans 
eddsa_pub_key_sanity_check(const ec_pub_key * in_pub)203*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_pub_key_sanity_check(const ec_pub_key *in_pub)
204*f0865ec9SKyle Evans {
205*f0865ec9SKyle Evans 	int ret;
206*f0865ec9SKyle Evans 
207*f0865ec9SKyle Evans 
208*f0865ec9SKyle Evans 	ret = pub_key_check_initialized(in_pub); EG(ret, err);
209*f0865ec9SKyle Evans 	ret = eddsa_key_type_check_curve(in_pub->key_type,
210*f0865ec9SKyle Evans 			       in_pub->params->curve_type);
211*f0865ec9SKyle Evans 
212*f0865ec9SKyle Evans err:
213*f0865ec9SKyle Evans 	return ret;
214*f0865ec9SKyle Evans }
215*f0865ec9SKyle Evans 
eddsa_key_pair_sanity_check(const ec_key_pair * key_pair)216*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_key_pair_sanity_check(const ec_key_pair *key_pair)
217*f0865ec9SKyle Evans {
218*f0865ec9SKyle Evans 	int ret;
219*f0865ec9SKyle Evans 
220*f0865ec9SKyle Evans 	MUST_HAVE((key_pair != NULL), ret, err);
221*f0865ec9SKyle Evans 	ret = eddsa_priv_key_sanity_check(&(key_pair->priv_key)); EG(ret, err);
222*f0865ec9SKyle Evans 	ret = eddsa_pub_key_sanity_check(&(key_pair->pub_key)); EG(ret, err);
223*f0865ec9SKyle Evans 	MUST_HAVE((key_pair->priv_key.key_type == key_pair->pub_key.key_type), ret, err);
224*f0865ec9SKyle Evans 
225*f0865ec9SKyle Evans err:
226*f0865ec9SKyle Evans 	return ret;
227*f0865ec9SKyle Evans }
228*f0865ec9SKyle Evans 
229*f0865ec9SKyle Evans /*
230*f0865ec9SKyle Evans  * EdDSA decode an integer from a buffer using little endian format.
231*f0865ec9SKyle Evans  */
eddsa_decode_integer(nn_t nn_out,const u8 * buf,u16 buf_size)232*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_decode_integer(nn_t nn_out, const u8 *buf, u16 buf_size)
233*f0865ec9SKyle Evans {
234*f0865ec9SKyle Evans 	u16 i;
235*f0865ec9SKyle Evans 	u8 buf_little_endian[MAX_DIGEST_SIZE];
236*f0865ec9SKyle Evans 	int ret;
237*f0865ec9SKyle Evans 
238*f0865ec9SKyle Evans 	MUST_HAVE((buf != NULL), ret, err);
239*f0865ec9SKyle Evans 	MUST_HAVE((sizeof(buf_little_endian) >= buf_size), ret, err);
240*f0865ec9SKyle Evans 
241*f0865ec9SKyle Evans 	ret = nn_init(nn_out, 0); EG(ret, err);
242*f0865ec9SKyle Evans 
243*f0865ec9SKyle Evans 	ret = local_memset(buf_little_endian, 0, sizeof(buf_little_endian)); EG(ret, err);
244*f0865ec9SKyle Evans 	if(buf_size > 1){
245*f0865ec9SKyle Evans 		/* Inverse endianness of our input buffer */
246*f0865ec9SKyle Evans 		for(i = 0; i < buf_size; i++){
247*f0865ec9SKyle Evans 			buf_little_endian[i] = buf[buf_size - 1 - i];
248*f0865ec9SKyle Evans 		}
249*f0865ec9SKyle Evans 	}
250*f0865ec9SKyle Evans 
251*f0865ec9SKyle Evans 	/* Compute an integer from the buffer */
252*f0865ec9SKyle Evans 	ret = nn_init_from_buf(nn_out, buf_little_endian, buf_size);
253*f0865ec9SKyle Evans 
254*f0865ec9SKyle Evans err:
255*f0865ec9SKyle Evans 	return ret;
256*f0865ec9SKyle Evans }
257*f0865ec9SKyle Evans 
258*f0865ec9SKyle Evans /*
259*f0865ec9SKyle Evans  * EdDSA encode an integer to a buffer using little endian format.
260*f0865ec9SKyle Evans  */
eddsa_encode_integer(nn_src_t nn_in,u8 * buf,u16 buf_size)261*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_encode_integer(nn_src_t nn_in, u8 *buf, u16 buf_size)
262*f0865ec9SKyle Evans {
263*f0865ec9SKyle Evans 	u16 i;
264*f0865ec9SKyle Evans 	u8 tmp;
265*f0865ec9SKyle Evans 	int ret;
266*f0865ec9SKyle Evans 	bitcnt_t blen;
267*f0865ec9SKyle Evans 
268*f0865ec9SKyle Evans 	MUST_HAVE((buf != NULL), ret, err);
269*f0865ec9SKyle Evans 	ret = nn_check_initialized(nn_in); EG(ret, err);
270*f0865ec9SKyle Evans 
271*f0865ec9SKyle Evans 	/* Sanity check that we do not lose information */
272*f0865ec9SKyle Evans 	ret = nn_bitlen(nn_in, &blen); EG(ret, err);
273*f0865ec9SKyle Evans 	MUST_HAVE((((u32)blen) <= (8 * (u32)buf_size)), ret, err);
274*f0865ec9SKyle Evans 
275*f0865ec9SKyle Evans 	/* Export the number to our buffer */
276*f0865ec9SKyle Evans 	ret = nn_export_to_buf(buf, buf_size, nn_in); EG(ret, err);
277*f0865ec9SKyle Evans 
278*f0865ec9SKyle Evans 	/* Now reverse endianness in place */
279*f0865ec9SKyle Evans 	if(buf_size > 1){
280*f0865ec9SKyle Evans 		for(i = 0; i < (buf_size / 2); i++){
281*f0865ec9SKyle Evans 			tmp = buf[i];
282*f0865ec9SKyle Evans 			buf[i] = buf[buf_size - 1 - i];
283*f0865ec9SKyle Evans 			buf[buf_size - 1 - i] = tmp;
284*f0865ec9SKyle Evans 		}
285*f0865ec9SKyle Evans 	}
286*f0865ec9SKyle Evans 
287*f0865ec9SKyle Evans err:
288*f0865ec9SKyle Evans 	return ret;
289*f0865ec9SKyle Evans }
290*f0865ec9SKyle Evans 
291*f0865ec9SKyle Evans /*
292*f0865ec9SKyle Evans  * EdDSA encoding of scalar s.
293*f0865ec9SKyle Evans  */
eddsa_compute_s(nn_t s,const u8 * digest,u16 digest_size)294*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_compute_s(nn_t s, const u8 *digest, u16 digest_size)
295*f0865ec9SKyle Evans {
296*f0865ec9SKyle Evans 	int ret;
297*f0865ec9SKyle Evans 
298*f0865ec9SKyle Evans 	MUST_HAVE((digest != NULL), ret, err);
299*f0865ec9SKyle Evans 	MUST_HAVE(((digest_size % 2) == 0), ret, err);
300*f0865ec9SKyle Evans 
301*f0865ec9SKyle Evans 	/* s is half of the digest size encoded in little endian format */
302*f0865ec9SKyle Evans 	ret = eddsa_decode_integer(s, digest, (digest_size / 2)); EG(ret, err);
303*f0865ec9SKyle Evans 
304*f0865ec9SKyle Evans err:
305*f0865ec9SKyle Evans 	return ret;
306*f0865ec9SKyle Evans }
307*f0865ec9SKyle Evans 
308*f0865ec9SKyle Evans /* Extract the digest from the encoded private key */
eddsa_get_digest_from_priv_key(u8 * digest,u8 * digest_size,const ec_priv_key * in_priv)309*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_get_digest_from_priv_key(u8 *digest, u8 *digest_size, const ec_priv_key *in_priv)
310*f0865ec9SKyle Evans {
311*f0865ec9SKyle Evans 	int ret;
312*f0865ec9SKyle Evans 	hash_alg_type hash_type;
313*f0865ec9SKyle Evans 	const hash_mapping *hash;
314*f0865ec9SKyle Evans 
315*f0865ec9SKyle Evans 	MUST_HAVE(((digest != NULL) && (digest_size != NULL)), ret, err);
316*f0865ec9SKyle Evans 	ret = eddsa_priv_key_sanity_check(in_priv); EG(ret, err);
317*f0865ec9SKyle Evans 
318*f0865ec9SKyle Evans 	MUST_HAVE(((hash_type = get_eddsa_hash_type(in_priv->key_type)) != UNKNOWN_HASH_ALG), ret, err);
319*f0865ec9SKyle Evans 	ret = get_hash_by_type(hash_type, &hash); EG(ret, err);
320*f0865ec9SKyle Evans 	MUST_HAVE((hash != NULL), ret, err);
321*f0865ec9SKyle Evans 
322*f0865ec9SKyle Evans 	/* Check real digest size */
323*f0865ec9SKyle Evans 	MUST_HAVE(((*digest_size) >= hash->digest_size), ret, err);
324*f0865ec9SKyle Evans 
325*f0865ec9SKyle Evans 	(*digest_size) = hash->digest_size;
326*f0865ec9SKyle Evans 	ret = nn_export_to_buf(digest, *digest_size, &(in_priv->x));
327*f0865ec9SKyle Evans 
328*f0865ec9SKyle Evans err:
329*f0865ec9SKyle Evans 	return ret;
330*f0865ec9SKyle Evans }
331*f0865ec9SKyle Evans 
332*f0865ec9SKyle Evans /* Encode an Edwards curve affine point in canonical form */
eddsa_encode_point(aff_pt_edwards_src_t in,fp_src_t alpha_edwards,u8 * buf,u16 buflen,ec_alg_type sig_alg)333*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_encode_point(aff_pt_edwards_src_t in,
334*f0865ec9SKyle Evans 							fp_src_t alpha_edwards,
335*f0865ec9SKyle Evans 							u8 *buf, u16 buflen,
336*f0865ec9SKyle Evans 							ec_alg_type sig_alg)
337*f0865ec9SKyle Evans {
338*f0865ec9SKyle Evans 	nn out_reduced;
339*f0865ec9SKyle Evans 	u8 lsb = 0;
340*f0865ec9SKyle Evans 	int ret;
341*f0865ec9SKyle Evans 	out_reduced.magic = WORD(0);
342*f0865ec9SKyle Evans 
343*f0865ec9SKyle Evans 	/* Sanity checks */
344*f0865ec9SKyle Evans 	MUST_HAVE((buf != NULL), ret, err);
345*f0865ec9SKyle Evans 	ret = aff_pt_edwards_check_initialized(in); EG(ret, err);
346*f0865ec9SKyle Evans 	ret = fp_check_initialized(alpha_edwards); EG(ret, err);
347*f0865ec9SKyle Evans 
348*f0865ec9SKyle Evans 	/* Zeroize the buffer */
349*f0865ec9SKyle Evans 	ret = local_memset(buf, 0, buflen); EG(ret, err);
350*f0865ec9SKyle Evans 	ret = nn_init(&out_reduced, 0); EG(ret, err);
351*f0865ec9SKyle Evans 
352*f0865ec9SKyle Evans 	/* Note: we should be reduced modulo Fp for canonical encoding here as
353*f0865ec9SKyle Evans 	 * coordinate elements are in Fp ...
354*f0865ec9SKyle Evans 	 */
355*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
356*f0865ec9SKyle Evans 	if((sig_alg == EDDSA448) || (sig_alg == EDDSA448PH)){
357*f0865ec9SKyle Evans 		/*
358*f0865ec9SKyle Evans 		 * In case of EDDSA448, we apply the 4-isogeny to transfer from
359*f0865ec9SKyle Evans 		 * Ed448 to Edwards448.
360*f0865ec9SKyle Evans 		 * The isogeny maps (x, y) on Ed448 to (x1, y1) on Edwards448
361*f0865ec9SKyle Evans 		 * using:
362*f0865ec9SKyle Evans 		 *      x1 = (4*x*y/c) / (y^2-x^2)
363*f0865ec9SKyle Evans 		 *      y1 = (2-x^2-y^2) / (x^2+y^2) = (2 - (x^2+y^2)) / (x^2 + y^2)
364*f0865ec9SKyle Evans 		 * and (0, 1) as well as (0, -1) are mapped to (0, 1)
365*f0865ec9SKyle Evans 		 * We only need to encode our y1 here, but x1 computation is
366*f0865ec9SKyle Evans 		 * unfortunately needed to get its LSB that is necessary for
367*f0865ec9SKyle Evans 		 * the encoding.
368*f0865ec9SKyle Evans 		 */
369*f0865ec9SKyle Evans 		fp tmp_x, tmp_y, y1;
370*f0865ec9SKyle Evans 		tmp_x.magic = tmp_y.magic = y1.magic = WORD(0);
371*f0865ec9SKyle Evans 		/* Compute x1 to get our LSB */
372*f0865ec9SKyle Evans 		ret = fp_init(&y1, in->y.ctx); EG(ret, err1);
373*f0865ec9SKyle Evans 		ret = fp_copy(&tmp_x, &(in->x)); EG(ret, err1);
374*f0865ec9SKyle Evans 		ret = fp_sqr(&tmp_x, &tmp_x); EG(ret, err1);
375*f0865ec9SKyle Evans 		ret = fp_copy(&tmp_y, &(in->y)); EG(ret, err1);
376*f0865ec9SKyle Evans 		ret = fp_sqr(&tmp_y, &tmp_y); EG(ret, err1);
377*f0865ec9SKyle Evans 		ret = fp_sub(&tmp_y, &tmp_y, &tmp_x); EG(ret, err1);
378*f0865ec9SKyle Evans 		/* NOTE: inversion by zero should be caught by lower layers */
379*f0865ec9SKyle Evans 		ret = fp_inv(&tmp_y, &tmp_y); EG(ret, err1);
380*f0865ec9SKyle Evans 		ret = fp_set_word_value(&tmp_x, WORD(4)); EG(ret, err1);
381*f0865ec9SKyle Evans 		ret = fp_mul(&tmp_x, &tmp_x, &(in->x)); EG(ret, err1);
382*f0865ec9SKyle Evans 		ret = fp_mul(&tmp_x, &tmp_x, &(in->y)); EG(ret, err1);
383*f0865ec9SKyle Evans 		ret = fp_mul(&tmp_x, &tmp_x, &tmp_y); EG(ret, err1);
384*f0865ec9SKyle Evans 		ret = fp_inv(&tmp_y, alpha_edwards); EG(ret, err1);
385*f0865ec9SKyle Evans 		ret = fp_mul(&tmp_x, &tmp_x, &tmp_y); EG(ret, err1);
386*f0865ec9SKyle Evans 		ret = nn_getbit(&(tmp_x.fp_val), 0, &lsb); EG(ret, err1);
387*f0865ec9SKyle Evans 		/* Compute y1 */
388*f0865ec9SKyle Evans 		ret = fp_copy(&tmp_x, &(in->x)); EG(ret, err1);
389*f0865ec9SKyle Evans 		ret = fp_sqr(&tmp_x, &tmp_x); EG(ret, err1);
390*f0865ec9SKyle Evans 		ret = fp_copy(&tmp_y, &(in->y)); EG(ret, err1);
391*f0865ec9SKyle Evans 		ret = fp_sqr(&tmp_y, &tmp_y); EG(ret, err1);
392*f0865ec9SKyle Evans 		ret = fp_set_word_value(&y1, WORD(2)); EG(ret, err1);
393*f0865ec9SKyle Evans 		ret = fp_sub(&y1, &y1, &tmp_x); EG(ret, err1);
394*f0865ec9SKyle Evans 		ret = fp_sub(&y1, &y1, &tmp_y); EG(ret, err1);
395*f0865ec9SKyle Evans 		ret = fp_add(&tmp_x, &tmp_x, &tmp_y); EG(ret, err1);
396*f0865ec9SKyle Evans 		/* NOTE: inversion by zero should be caught by lower layers */
397*f0865ec9SKyle Evans 		ret = fp_inv(&tmp_x, &tmp_x); EG(ret, err1);
398*f0865ec9SKyle Evans 		ret = fp_mul(&y1, &y1, &tmp_x); EG(ret, err1);
399*f0865ec9SKyle Evans 		ret = eddsa_encode_integer(&(y1.fp_val), buf, buflen);
400*f0865ec9SKyle Evans err1:
401*f0865ec9SKyle Evans 		fp_uninit(&tmp_x);
402*f0865ec9SKyle Evans 		fp_uninit(&tmp_y);
403*f0865ec9SKyle Evans 		fp_uninit(&y1);
404*f0865ec9SKyle Evans 		EG(ret, err);
405*f0865ec9SKyle Evans 	}
406*f0865ec9SKyle Evans 	else
407*f0865ec9SKyle Evans #endif /* !defined(WITH_SIG_EDDSA448) */
408*f0865ec9SKyle Evans 	{	/* EDDSA25519 and other cases */
409*f0865ec9SKyle Evans 		FORCE_USED_VAR(sig_alg); /* To avoid unused variable error */
410*f0865ec9SKyle Evans 		ret = nn_getbit(&(in->x.fp_val), 0, &lsb); EG(ret, err);
411*f0865ec9SKyle Evans 		ret = eddsa_encode_integer(&(in->y.fp_val), buf, buflen); EG(ret, err);
412*f0865ec9SKyle Evans 	}
413*f0865ec9SKyle Evans 	/*
414*f0865ec9SKyle Evans 	 * Now deal with the sign for the last bit: copy the least significant
415*f0865ec9SKyle Evans 	 * bit of the x coordinate in the MSB of the last octet.
416*f0865ec9SKyle Evans 	 */
417*f0865ec9SKyle Evans 	MUST_HAVE((buflen > 1), ret, err);
418*f0865ec9SKyle Evans 	buf[buflen - 1] |= (u8)(lsb << 7);
419*f0865ec9SKyle Evans 
420*f0865ec9SKyle Evans err:
421*f0865ec9SKyle Evans 	nn_uninit(&out_reduced);
422*f0865ec9SKyle Evans 
423*f0865ec9SKyle Evans 	return ret;
424*f0865ec9SKyle Evans }
425*f0865ec9SKyle Evans 
426*f0865ec9SKyle Evans /* Decode an Edwards curve affine point from canonical form */
eddsa_decode_point(aff_pt_edwards_t out,ec_edwards_crv_src_t edwards_curve,fp_src_t alpha_edwards,const u8 * buf,u16 buflen,ec_alg_type sig_type)427*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_decode_point(aff_pt_edwards_t out, ec_edwards_crv_src_t edwards_curve,
428*f0865ec9SKyle Evans 			      fp_src_t alpha_edwards, const u8 *buf, u16 buflen,
429*f0865ec9SKyle Evans 			      ec_alg_type sig_type)
430*f0865ec9SKyle Evans {
431*f0865ec9SKyle Evans 	fp x, y;
432*f0865ec9SKyle Evans 	fp sqrt1, sqrt2;
433*f0865ec9SKyle Evans 	u8 x_0, lsb;
434*f0865ec9SKyle Evans 	u8 buf_little_endian[MAX_DIGEST_SIZE];
435*f0865ec9SKyle Evans 	u16 i;
436*f0865ec9SKyle Evans 	int ret, iszero;
437*f0865ec9SKyle Evans 
438*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
439*f0865ec9SKyle Evans         fp tmp;
440*f0865ec9SKyle Evans         tmp.magic = WORD(0);
441*f0865ec9SKyle Evans #endif
442*f0865ec9SKyle Evans 	x.magic = y.magic = sqrt1.magic = sqrt2.magic = WORD(0);
443*f0865ec9SKyle Evans 
444*f0865ec9SKyle Evans 	MUST_HAVE((buf != NULL), ret, err);
445*f0865ec9SKyle Evans 
446*f0865ec9SKyle Evans 	ret = ec_edwards_crv_check_initialized(edwards_curve); EG(ret, err);
447*f0865ec9SKyle Evans 
448*f0865ec9SKyle Evans 	ret = fp_check_initialized(alpha_edwards); EG(ret, err);
449*f0865ec9SKyle Evans 
450*f0865ec9SKyle Evans 	/* Extract the sign */
451*f0865ec9SKyle Evans 	x_0 = ((buf[buflen - 1] & 0x80) >> 7);
452*f0865ec9SKyle Evans 	/* Extract the value by reversing endianness */
453*f0865ec9SKyle Evans 	MUST_HAVE((sizeof(buf_little_endian) >= buflen), ret, err);
454*f0865ec9SKyle Evans 
455*f0865ec9SKyle Evans 	/* Inverse endianness of our input buffer and mask the sign bit */
456*f0865ec9SKyle Evans 	MUST_HAVE((buflen > 1), ret, err);
457*f0865ec9SKyle Evans 
458*f0865ec9SKyle Evans 	for(i = 0; i < buflen; i++){
459*f0865ec9SKyle Evans 		buf_little_endian[i] = buf[buflen - 1 - i];
460*f0865ec9SKyle Evans 		if(i == 0){
461*f0865ec9SKyle Evans 			/* Mask the sign bit */
462*f0865ec9SKyle Evans 			buf_little_endian[i] &= 0x7f;
463*f0865ec9SKyle Evans 		}
464*f0865ec9SKyle Evans 	}
465*f0865ec9SKyle Evans 	/* Try to decode the y coordinate */
466*f0865ec9SKyle Evans 	ret = fp_init_from_buf(&y, edwards_curve->a.ctx, buf_little_endian, buflen); EG(ret, err);
467*f0865ec9SKyle Evans 	/*
468*f0865ec9SKyle Evans 	 * If we suceed, try to find our x coordinate that is the square root of
469*f0865ec9SKyle Evans 	 * (y^2 - 1) / (d y^2 + 1) or (y^2 - 1) / (d y^2 - 1) depending on the
470*f0865ec9SKyle Evans 	 * algorithm (EDDSA25519 our EDDSA448).
471*f0865ec9SKyle Evans 	 */
472*f0865ec9SKyle Evans         ret = fp_init(&sqrt1, edwards_curve->a.ctx); EG(ret, err);
473*f0865ec9SKyle Evans         ret = fp_init(&sqrt2, edwards_curve->a.ctx); EG(ret, err);
474*f0865ec9SKyle Evans         ret = fp_init(&x, edwards_curve->a.ctx); EG(ret, err);
475*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
476*f0865ec9SKyle Evans 	if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){
477*f0865ec9SKyle Evans 		const u8 d_edwards448_buff[] = {
478*f0865ec9SKyle Evans 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
479*f0865ec9SKyle Evans 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
480*f0865ec9SKyle Evans 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
481*f0865ec9SKyle Evans 			0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
482*f0865ec9SKyle Evans 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
483*f0865ec9SKyle Evans 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
484*f0865ec9SKyle Evans 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x67, 0x56
485*f0865ec9SKyle Evans 		};
486*f0865ec9SKyle Evans 		ec_edwards_crv edwards_curve_edwards448;
487*f0865ec9SKyle Evans 
488*f0865ec9SKyle Evans 		ret = fp_init(&tmp, edwards_curve->a.ctx); EG(ret, err);
489*f0865ec9SKyle Evans 		/*
490*f0865ec9SKyle Evans 		 * If we deal with EDDSA448 we must handle the point on
491*f0865ec9SKyle Evans 		 * Edwards448 so we use the dedicated d.
492*f0865ec9SKyle Evans 		 */
493*f0865ec9SKyle Evans 		ret = fp_init_from_buf(&tmp, edwards_curve->a.ctx,
494*f0865ec9SKyle Evans 				(const u8*)d_edwards448_buff, sizeof(d_edwards448_buff)); EG(ret, err);
495*f0865ec9SKyle Evans 		ret = ec_edwards_crv_init(&edwards_curve_edwards448, &(edwards_curve->a), &tmp, &(edwards_curve->order)); EG(ret, err);
496*f0865ec9SKyle Evans 		/* Compute x from y using the dedicated primitive */
497*f0865ec9SKyle Evans 		ret = aff_pt_edwards_x_from_y(&sqrt1, &sqrt2, &y, &edwards_curve_edwards448); EG(ret, err); /* Error or no square root found, this should not happen! */
498*f0865ec9SKyle Evans 		ec_edwards_crv_uninit(&edwards_curve_edwards448);
499*f0865ec9SKyle Evans 	}
500*f0865ec9SKyle Evans 	else
501*f0865ec9SKyle Evans #endif
502*f0865ec9SKyle Evans 	{
503*f0865ec9SKyle Evans 		/* Compute x from y using the dedicated primitive */
504*f0865ec9SKyle Evans 		ret = aff_pt_edwards_x_from_y(&sqrt1, &sqrt2, &y, edwards_curve); EG(ret, err); /* Error or no square root found, this should not happen! */
505*f0865ec9SKyle Evans 	}
506*f0865ec9SKyle Evans 	/* Now select the square root of the proper sign */
507*f0865ec9SKyle Evans 	ret = nn_getbit(&(sqrt1.fp_val), 0, &lsb); EG(ret, err);
508*f0865ec9SKyle Evans 	if(lsb == x_0){
509*f0865ec9SKyle Evans 		ret = fp_copy(&x, &sqrt1); EG(ret, err);
510*f0865ec9SKyle Evans 	}
511*f0865ec9SKyle Evans 	else{
512*f0865ec9SKyle Evans 		ret = fp_copy(&x, &sqrt2); EG(ret, err);
513*f0865ec9SKyle Evans 	}
514*f0865ec9SKyle Evans 	/* If x = 0 and the sign bit is 1, this is an error */
515*f0865ec9SKyle Evans 	ret = fp_iszero(&x, &iszero); EG(ret, err);
516*f0865ec9SKyle Evans 	MUST_HAVE(!(iszero && (x_0 == 1)), ret, err);
517*f0865ec9SKyle Evans 	/*
518*f0865ec9SKyle Evans 	 * In case of EDDSA448, we apply the 4-isogeny to transfer from
519*f0865ec9SKyle Evans 	 * Edwards448 to Ed448.
520*f0865ec9SKyle Evans 	 * The isogeny maps (x1, y1) on Edwards448 to (x, y) on Ed448 using:
521*f0865ec9SKyle Evans 	 *	x = alpha_edwards * (x1*y1) / (2-x1^2-y1^2)
522*f0865ec9SKyle Evans 	 *      y = (x1^2+y1^2) / (y1^2-x1^2)
523*f0865ec9SKyle Evans 	 */
524*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
525*f0865ec9SKyle Evans 	if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){
526*f0865ec9SKyle Evans 		/*
527*f0865ec9SKyle Evans 		 * Use sqrt1 and sqrt2 as temporary buffers for x and y, and
528*f0865ec9SKyle Evans 		 * tmp as scratch pad buffer
529*f0865ec9SKyle Evans 		 */
530*f0865ec9SKyle Evans 		ret = fp_copy(&sqrt1, &x); EG(ret, err);
531*f0865ec9SKyle Evans 		ret = fp_copy(&sqrt2, &y); EG(ret, err);
532*f0865ec9SKyle Evans 
533*f0865ec9SKyle Evans 		ret = fp_set_word_value(&x, WORD(2)); EG(ret, err);
534*f0865ec9SKyle Evans 		ret = fp_sqr(&tmp, &sqrt1); EG(ret, err);
535*f0865ec9SKyle Evans 		ret = fp_sub(&x, &x, &tmp); EG(ret, err);
536*f0865ec9SKyle Evans 		ret = fp_sqr(&tmp, &sqrt2); EG(ret, err);
537*f0865ec9SKyle Evans 		ret = fp_sub(&x, &x, &tmp); EG(ret, err);
538*f0865ec9SKyle Evans 		/* NOTE: inversion by zero should be caught by lower layers */
539*f0865ec9SKyle Evans 		ret = fp_inv(&x, &x); EG(ret, err);
540*f0865ec9SKyle Evans 		ret = fp_mul(&x, &x, &sqrt1); EG(ret, err);
541*f0865ec9SKyle Evans 		ret = fp_mul(&x, &x, &sqrt2); EG(ret, err);
542*f0865ec9SKyle Evans 		ret = fp_mul(&x, &x, alpha_edwards); EG(ret, err);
543*f0865ec9SKyle Evans 
544*f0865ec9SKyle Evans 		ret = fp_sqr(&sqrt1, &sqrt1); EG(ret, err);
545*f0865ec9SKyle Evans 		ret = fp_sqr(&sqrt2, &sqrt2); EG(ret, err);
546*f0865ec9SKyle Evans 		ret = fp_sub(&y, &sqrt2, &sqrt1); EG(ret, err);
547*f0865ec9SKyle Evans 		/* NOTE: inversion by zero should be caught by lower layers */
548*f0865ec9SKyle Evans 		ret = fp_inv(&y, &y); EG(ret, err);
549*f0865ec9SKyle Evans 		ret = fp_add(&sqrt1, &sqrt1, &sqrt2); EG(ret, err);
550*f0865ec9SKyle Evans 		ret = fp_mul(&y, &y, &sqrt1); EG(ret, err);
551*f0865ec9SKyle Evans 	}
552*f0865ec9SKyle Evans #endif /* !defined(WITH_SIG_EDDSA448) */
553*f0865ec9SKyle Evans 
554*f0865ec9SKyle Evans 	/* Initialize our point */
555*f0865ec9SKyle Evans 	ret = aff_pt_edwards_init_from_coords(out, edwards_curve, &x, &y);
556*f0865ec9SKyle Evans 
557*f0865ec9SKyle Evans err:
558*f0865ec9SKyle Evans 	fp_uninit(&sqrt1);
559*f0865ec9SKyle Evans 	fp_uninit(&sqrt2);
560*f0865ec9SKyle Evans 	fp_uninit(&x);
561*f0865ec9SKyle Evans 	fp_uninit(&y);
562*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
563*f0865ec9SKyle Evans 	fp_uninit(&tmp);
564*f0865ec9SKyle Evans #endif
565*f0865ec9SKyle Evans 
566*f0865ec9SKyle Evans 	return ret;
567*f0865ec9SKyle Evans }
568*f0865ec9SKyle Evans 
569*f0865ec9SKyle Evans 
570*f0865ec9SKyle Evans /*
571*f0865ec9SKyle Evans  * Derive hash from private key.
572*f0865ec9SKyle Evans  */
eddsa_derive_priv_key_hash(const ec_priv_key * in_priv,u8 * buf,u16 buflen)573*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_derive_priv_key_hash(const ec_priv_key *in_priv,
574*f0865ec9SKyle Evans 								u8 *buf, u16 buflen)
575*f0865ec9SKyle Evans {
576*f0865ec9SKyle Evans 	hash_alg_type hash_type = UNKNOWN_HASH_ALG;
577*f0865ec9SKyle Evans 	const hash_mapping *hash;
578*f0865ec9SKyle Evans 	u8 x_buf[EC_PRIV_KEY_MAX_SIZE];
579*f0865ec9SKyle Evans 	int ret;
580*f0865ec9SKyle Evans 	const u8 *in[2];
581*f0865ec9SKyle Evans 	u32 in_len[2];
582*f0865ec9SKyle Evans 
583*f0865ec9SKyle Evans 	MUST_HAVE((buf != NULL), ret, err);
584*f0865ec9SKyle Evans 	ret = eddsa_priv_key_sanity_check(in_priv); EG(ret, err);
585*f0865ec9SKyle Evans 
586*f0865ec9SKyle Evans 	MUST_HAVE(((hash_type = get_eddsa_hash_type(in_priv->key_type)) != UNKNOWN_HASH_ALG), ret, err);
587*f0865ec9SKyle Evans 	ret = get_hash_by_type(hash_type, &hash); EG(ret, err);
588*f0865ec9SKyle Evans 	MUST_HAVE((hash != NULL), ret, err);
589*f0865ec9SKyle Evans 
590*f0865ec9SKyle Evans 	/* Get the private key as a buffer and hash it */
591*f0865ec9SKyle Evans 	ret = local_memset(x_buf, 0, sizeof(x_buf)); EG(ret, err);
592*f0865ec9SKyle Evans 	MUST_HAVE((sizeof(x_buf) >= (hash->digest_size / 2)), ret, err);
593*f0865ec9SKyle Evans 
594*f0865ec9SKyle Evans 	ret = ec_priv_key_export_to_buf(in_priv, x_buf, (hash->digest_size / 2)); EG(ret, err);
595*f0865ec9SKyle Evans 
596*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(hash); EG(ret, err);
597*f0865ec9SKyle Evans 
598*f0865ec9SKyle Evans 	MUST_HAVE((buflen >= hash->digest_size), ret, err);
599*f0865ec9SKyle Evans 
600*f0865ec9SKyle Evans 	in[0] = x_buf; in[1] = NULL;
601*f0865ec9SKyle Evans 	in_len[0] = (hash->digest_size / 2); in_len[1] = 0;
602*f0865ec9SKyle Evans 	ret = hash->hfunc_scattered(in, in_len, buf);
603*f0865ec9SKyle Evans 
604*f0865ec9SKyle Evans err:
605*f0865ec9SKyle Evans 	PTR_NULLIFY(hash);
606*f0865ec9SKyle Evans 
607*f0865ec9SKyle Evans 	return ret;
608*f0865ec9SKyle Evans }
609*f0865ec9SKyle Evans 
610*f0865ec9SKyle Evans /*
611*f0865ec9SKyle Evans  * Derive an EdDSA private key.
612*f0865ec9SKyle Evans  *
613*f0865ec9SKyle Evans  */
eddsa_derive_priv_key(ec_priv_key * priv_key)614*f0865ec9SKyle Evans int eddsa_derive_priv_key(ec_priv_key *priv_key)
615*f0865ec9SKyle Evans {
616*f0865ec9SKyle Evans 	int ret, cmp;
617*f0865ec9SKyle Evans 	u8 digest_size;
618*f0865ec9SKyle Evans 	u8 digest[MAX_DIGEST_SIZE];
619*f0865ec9SKyle Evans 	hash_alg_type hash_type = UNKNOWN_HASH_ALG;
620*f0865ec9SKyle Evans 	word_t cofactor = WORD(0);
621*f0865ec9SKyle Evans 
622*f0865ec9SKyle Evans 	/* Check if private key is initialized. */
623*f0865ec9SKyle Evans 	ret = eddsa_priv_key_sanity_check(priv_key); EG(ret, err);
624*f0865ec9SKyle Evans 
625*f0865ec9SKyle Evans 	/* Check hash function compatibility:
626*f0865ec9SKyle Evans 	 *   We must have 2**(b-1) > p with (2*b) the size of the hash function.
627*f0865ec9SKyle Evans 	 */
628*f0865ec9SKyle Evans 	MUST_HAVE(((hash_type = get_eddsa_hash_type(priv_key->key_type)) != UNKNOWN_HASH_ALG), ret, err);
629*f0865ec9SKyle Evans 
630*f0865ec9SKyle Evans 	digest_size = 0;
631*f0865ec9SKyle Evans 	ret = get_hash_sizes(hash_type, &digest_size, NULL); EG(ret, err);
632*f0865ec9SKyle Evans 
633*f0865ec9SKyle Evans 	MUST_HAVE(((2 * priv_key->params->ec_fp.p_bitlen) < (8 * (bitcnt_t)digest_size)), ret, err);
634*f0865ec9SKyle Evans 	MUST_HAVE(((digest_size % 2) == 0), ret, err);
635*f0865ec9SKyle Evans 	MUST_HAVE((digest_size <= sizeof(digest)), ret, err);
636*f0865ec9SKyle Evans 
637*f0865ec9SKyle Evans 	/*
638*f0865ec9SKyle Evans 	 * Now that we have our private scalar, derive the hash value of secret
639*f0865ec9SKyle Evans 	 * key
640*f0865ec9SKyle Evans 	 */
641*f0865ec9SKyle Evans 	/* Hash the private key */
642*f0865ec9SKyle Evans 	ret = eddsa_derive_priv_key_hash(priv_key, digest, digest_size); EG(ret, err);
643*f0865ec9SKyle Evans 
644*f0865ec9SKyle Evans 	/* Get the cofactor as an integer */
645*f0865ec9SKyle Evans 	cofactor = priv_key->params->ec_gen_cofactor.val[0];
646*f0865ec9SKyle Evans 	ret = nn_cmp_word(&(priv_key->params->ec_gen_cofactor), cofactor, &cmp); EG(ret, err);
647*f0865ec9SKyle Evans 	MUST_HAVE((cmp == 0), ret, err);
648*f0865ec9SKyle Evans 	/* Cofactor must be 2**2 or 2**3 as per RFC8032 standard */
649*f0865ec9SKyle Evans 	MUST_HAVE((cofactor == (0x1 << 2)) || (cofactor == (0x1 << 3)), ret, err);
650*f0865ec9SKyle Evans 
651*f0865ec9SKyle Evans 	/* Now clear the low bits related to cofactor */
652*f0865ec9SKyle Evans 	digest[0] &= (u8)(~(cofactor - 1));
653*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
654*f0865ec9SKyle Evans 	if ((priv_key->key_type == EDDSA25519) ||
655*f0865ec9SKyle Evans 	    (priv_key->key_type == EDDSA25519CTX) ||
656*f0865ec9SKyle Evans 	    (priv_key->key_type == EDDSA25519PH)){
657*f0865ec9SKyle Evans 		/*
658*f0865ec9SKyle Evans 		 * MSB of highest octet of half must be cleared, second MSB must
659*f0865ec9SKyle Evans 		 * be set
660*f0865ec9SKyle Evans 		 */
661*f0865ec9SKyle Evans 		digest[(digest_size / 2) - 1] &= 0x7f;
662*f0865ec9SKyle Evans 		digest[(digest_size / 2) - 1] |= 0x40;
663*f0865ec9SKyle Evans 	}
664*f0865ec9SKyle Evans #endif
665*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
666*f0865ec9SKyle Evans 	if ((priv_key->key_type == EDDSA448) || (priv_key->key_type == EDDSA448PH)) {
667*f0865ec9SKyle Evans 		MUST_HAVE((digest_size / 2) >= 2, ret, err);
668*f0865ec9SKyle Evans 		/*
669*f0865ec9SKyle Evans 		 * All eight bits of the last octet are cleared, highest bit
670*f0865ec9SKyle Evans 		 * of the second to last octet is set.
671*f0865ec9SKyle Evans 		 */
672*f0865ec9SKyle Evans 		digest[(digest_size / 2) - 1] = 0;
673*f0865ec9SKyle Evans 		digest[(digest_size / 2) - 2] |= 0x80;
674*f0865ec9SKyle Evans 	}
675*f0865ec9SKyle Evans #endif
676*f0865ec9SKyle Evans #if !defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_EDDSA448)
677*f0865ec9SKyle Evans 	ret = -1;
678*f0865ec9SKyle Evans 	goto err;
679*f0865ec9SKyle Evans #endif
680*f0865ec9SKyle Evans 	/*
681*f0865ec9SKyle Evans 	 * Now that we have derived our hash, store it in place of our secret
682*f0865ec9SKyle Evans 	 * value NOTE: we do not need the secret value anymore since only the
683*f0865ec9SKyle Evans 	 * hash is needed.
684*f0865ec9SKyle Evans 	 */
685*f0865ec9SKyle Evans 	ret = nn_init_from_buf(&(priv_key->x), digest, digest_size);
686*f0865ec9SKyle Evans 
687*f0865ec9SKyle Evans err:
688*f0865ec9SKyle Evans 	VAR_ZEROIFY(digest_size);
689*f0865ec9SKyle Evans 
690*f0865ec9SKyle Evans 	return ret;
691*f0865ec9SKyle Evans }
692*f0865ec9SKyle Evans 
693*f0865ec9SKyle Evans /*
694*f0865ec9SKyle Evans  * Generate an EdDSA private key.
695*f0865ec9SKyle Evans  *
696*f0865ec9SKyle Evans  */
eddsa_gen_priv_key(ec_priv_key * priv_key)697*f0865ec9SKyle Evans int eddsa_gen_priv_key(ec_priv_key *priv_key)
698*f0865ec9SKyle Evans {
699*f0865ec9SKyle Evans 	int ret;
700*f0865ec9SKyle Evans 	u8 digest_size;
701*f0865ec9SKyle Evans 	hash_alg_type hash_type = UNKNOWN_HASH_ALG;
702*f0865ec9SKyle Evans 
703*f0865ec9SKyle Evans 	/* Check if private key is initialized. */
704*f0865ec9SKyle Evans 	ret = eddsa_priv_key_sanity_check(priv_key); EG(ret, err);
705*f0865ec9SKyle Evans 
706*f0865ec9SKyle Evans 	/* Check hash function compatibility:
707*f0865ec9SKyle Evans 	 *   We must have 2**(b-1) > p with (2*b) the size of the hash function.
708*f0865ec9SKyle Evans 	 */
709*f0865ec9SKyle Evans 	MUST_HAVE(((hash_type = get_eddsa_hash_type(priv_key->key_type)) != UNKNOWN_HASH_ALG), ret, err);
710*f0865ec9SKyle Evans 
711*f0865ec9SKyle Evans 	digest_size = 0;
712*f0865ec9SKyle Evans 	ret = get_hash_sizes(hash_type, &digest_size, NULL); EG(ret, err);
713*f0865ec9SKyle Evans 
714*f0865ec9SKyle Evans 	MUST_HAVE(((2 * priv_key->params->ec_fp.p_bitlen) < (8 * (bitcnt_t)digest_size)), ret, err);
715*f0865ec9SKyle Evans 	MUST_HAVE(((digest_size % 2) == 0), ret, err);
716*f0865ec9SKyle Evans 
717*f0865ec9SKyle Evans 	/* Generate a random private key
718*f0865ec9SKyle Evans 	 * An EdDSA secret scalar is a b bit string with (2*b) the size of the hash function
719*f0865ec9SKyle Evans 	 */
720*f0865ec9SKyle Evans 	ret = nn_get_random_len(&(priv_key->x), (digest_size / 2)); EG(ret, err);
721*f0865ec9SKyle Evans 
722*f0865ec9SKyle Evans 	/* Derive the private key */
723*f0865ec9SKyle Evans 	ret = eddsa_derive_priv_key(priv_key);
724*f0865ec9SKyle Evans 
725*f0865ec9SKyle Evans err:
726*f0865ec9SKyle Evans 	VAR_ZEROIFY(digest_size);
727*f0865ec9SKyle Evans 
728*f0865ec9SKyle Evans 	return ret;
729*f0865ec9SKyle Evans }
730*f0865ec9SKyle Evans 
731*f0865ec9SKyle Evans 
732*f0865ec9SKyle Evans /* Import an EdDSA private key from a raw buffer.
733*f0865ec9SKyle Evans  * NOTE: the private key must be a big number associated to the curve that
734*f0865ec9SKyle Evans  * depends on the flavor of EdDSA (Ed25519 or Ed448), and the result is a
735*f0865ec9SKyle Evans  * derived private key that can be used by the internal EdDSA functions.
736*f0865ec9SKyle Evans  * The derived key is a hash of the private key: we mainly perform this
737*f0865ec9SKyle Evans  * derivation early to prevent side-channel attacks and other leaks on the
738*f0865ec9SKyle Evans  * "root" private key.
739*f0865ec9SKyle Evans  */
eddsa_import_priv_key(ec_priv_key * priv_key,const u8 * buf,u16 buflen,const ec_params * shortw_curve_params,ec_alg_type sig_type)740*f0865ec9SKyle Evans int eddsa_import_priv_key(ec_priv_key *priv_key, const u8 *buf, u16 buflen,
741*f0865ec9SKyle Evans 			  const ec_params *shortw_curve_params,
742*f0865ec9SKyle Evans 			  ec_alg_type sig_type)
743*f0865ec9SKyle Evans {
744*f0865ec9SKyle Evans 	int ret;
745*f0865ec9SKyle Evans 	hash_alg_type hash_type = UNKNOWN_HASH_ALG;
746*f0865ec9SKyle Evans 	u8 digest_size;
747*f0865ec9SKyle Evans 	bitcnt_t blen;
748*f0865ec9SKyle Evans 
749*f0865ec9SKyle Evans 	/* Some sanity checks */
750*f0865ec9SKyle Evans 	MUST_HAVE((priv_key != NULL) && (buf != NULL) && (shortw_curve_params != NULL), ret, err);
751*f0865ec9SKyle Evans 
752*f0865ec9SKyle Evans 	/* Import the big number from our buffer */
753*f0865ec9SKyle Evans 	ret = nn_init_from_buf(&(priv_key->x), buf, buflen); EG(ret, err);
754*f0865ec9SKyle Evans 	/* The bit length of our big number must be <= b, half the digest size */
755*f0865ec9SKyle Evans 	hash_type = get_eddsa_hash_type(sig_type);
756*f0865ec9SKyle Evans 	MUST_HAVE((hash_type != UNKNOWN_HASH_ALG), ret, err);
757*f0865ec9SKyle Evans 
758*f0865ec9SKyle Evans 	digest_size = 0;
759*f0865ec9SKyle Evans 	ret = get_hash_sizes(hash_type, &digest_size, NULL); EG(ret, err);
760*f0865ec9SKyle Evans 
761*f0865ec9SKyle Evans 	ret = nn_bitlen(&(priv_key->x), &blen); EG(ret, err);
762*f0865ec9SKyle Evans 	MUST_HAVE((blen <= (8 * ((bitcnt_t)digest_size / 2))), ret, err);
763*f0865ec9SKyle Evans 
764*f0865ec9SKyle Evans 	/* Initialize stuff */
765*f0865ec9SKyle Evans 	priv_key->key_type = sig_type;
766*f0865ec9SKyle Evans 	priv_key->params = shortw_curve_params;
767*f0865ec9SKyle Evans 	priv_key->magic = PRIV_KEY_MAGIC;
768*f0865ec9SKyle Evans 
769*f0865ec9SKyle Evans 	/* Now derive the private key.
770*f0865ec9SKyle Evans 	 * NOTE: sanity check on the private key is performed during derivation.
771*f0865ec9SKyle Evans 	 */
772*f0865ec9SKyle Evans 	ret = eddsa_derive_priv_key(priv_key);
773*f0865ec9SKyle Evans 
774*f0865ec9SKyle Evans err:
775*f0865ec9SKyle Evans 	if((priv_key != NULL) && ret){
776*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset(priv_key, 0, sizeof(ec_priv_key)));
777*f0865ec9SKyle Evans 	}
778*f0865ec9SKyle Evans 	VAR_ZEROIFY(digest_size);
779*f0865ec9SKyle Evans 	VAR_ZEROIFY(blen);
780*f0865ec9SKyle Evans 
781*f0865ec9SKyle Evans 	return ret;
782*f0865ec9SKyle Evans }
783*f0865ec9SKyle Evans 
784*f0865ec9SKyle Evans /* NOTE: we perform EDDSA public key computation on the short Weierstrass
785*f0865ec9SKyle Evans  * form of the curve thanks to the birational equivalence of curve
786*f0865ec9SKyle Evans  * models (the isomorphism allows to perform the scalar multiplication
787*f0865ec9SKyle Evans  * on the equivalent curve).
788*f0865ec9SKyle Evans  */
eddsa_init_pub_key(ec_pub_key * out_pub,const ec_priv_key * in_priv)789*f0865ec9SKyle Evans int eddsa_init_pub_key(ec_pub_key *out_pub, const ec_priv_key *in_priv)
790*f0865ec9SKyle Evans {
791*f0865ec9SKyle Evans 	prj_pt_src_t G;
792*f0865ec9SKyle Evans 	u8 digest_size;
793*f0865ec9SKyle Evans 	u8 digest[MAX_DIGEST_SIZE];
794*f0865ec9SKyle Evans 	/* Secret scalar used for public generation */
795*f0865ec9SKyle Evans 	nn s;
796*f0865ec9SKyle Evans 	hash_alg_type hash_type;
797*f0865ec9SKyle Evans 	u8 digest_size_;
798*f0865ec9SKyle Evans 	int ret;
799*f0865ec9SKyle Evans 	s.magic = WORD(0);
800*f0865ec9SKyle Evans 
801*f0865ec9SKyle Evans 	MUST_HAVE(out_pub != NULL, ret, err);
802*f0865ec9SKyle Evans 	ret = eddsa_priv_key_sanity_check(in_priv); EG(ret, err);
803*f0865ec9SKyle Evans 
804*f0865ec9SKyle Evans 	ret = nn_init(&s, 0); EG(ret, err);
805*f0865ec9SKyle Evans 
806*f0865ec9SKyle Evans 	/* Zero init public key to be generated */
807*f0865ec9SKyle Evans 	ret = local_memset(out_pub, 0, sizeof(ec_pub_key)); EG(ret, err);
808*f0865ec9SKyle Evans 
809*f0865ec9SKyle Evans 	/* Get the generator G */
810*f0865ec9SKyle Evans 	G = &(in_priv->params->ec_gen);
811*f0865ec9SKyle Evans 
812*f0865ec9SKyle Evans 	/* Get the digest in proper format */
813*f0865ec9SKyle Evans 	MUST_HAVE(((hash_type = get_eddsa_hash_type(in_priv->key_type)) != UNKNOWN_HASH_ALG), ret, err);
814*f0865ec9SKyle Evans 
815*f0865ec9SKyle Evans 	digest_size_ = 0;
816*f0865ec9SKyle Evans 	ret = get_hash_sizes(hash_type, &digest_size_, NULL); EG(ret, err);
817*f0865ec9SKyle Evans 
818*f0865ec9SKyle Evans 	/* Extract the digest */
819*f0865ec9SKyle Evans 	digest_size = sizeof(digest);
820*f0865ec9SKyle Evans 	ret = eddsa_get_digest_from_priv_key(digest, &digest_size, in_priv); EG(ret, err);
821*f0865ec9SKyle Evans 
822*f0865ec9SKyle Evans 	/* Sanity check */
823*f0865ec9SKyle Evans 	MUST_HAVE((digest_size == digest_size_), ret, err);
824*f0865ec9SKyle Evans 
825*f0865ec9SKyle Evans 	/* Encode the scalar s from the digest */
826*f0865ec9SKyle Evans 	ret = eddsa_compute_s(&s, digest, digest_size); EG(ret, err);
827*f0865ec9SKyle Evans 
828*f0865ec9SKyle Evans 	/* Compute s x G where G is the base point */
829*f0865ec9SKyle Evans 	/*
830*f0865ec9SKyle Evans 	 * Use blinding when computing point scalar multiplication as we
831*f0865ec9SKyle Evans 	 * manipulate a fixed secret.
832*f0865ec9SKyle Evans 	 */
833*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
834*f0865ec9SKyle Evans 	if((in_priv->key_type == EDDSA448) || (in_priv->key_type == EDDSA448PH)){
835*f0865ec9SKyle Evans 		/*
836*f0865ec9SKyle Evans 		 * NOTE: because of the 4-isogeny between Ed448 and Edwards448,
837*f0865ec9SKyle Evans 		 * we actually multiply by (s/4) since the base point of
838*f0865ec9SKyle Evans 		 * Edwards448 is four times the one of Ed448.
839*f0865ec9SKyle Evans 		 * Here, s/4 can be simply computed by right shifting by 2 as
840*f0865ec9SKyle Evans 		 * we are ensured that our scalar is a multiple of 4 by
841*f0865ec9SKyle Evans 		 * construction.
842*f0865ec9SKyle Evans 		 */
843*f0865ec9SKyle Evans 		ret = nn_rshift(&s, &s, 2); EG(ret, err);
844*f0865ec9SKyle Evans 	}
845*f0865ec9SKyle Evans #endif
846*f0865ec9SKyle Evans 	ret = prj_pt_mul_blind(&(out_pub->y), &s, G); EG(ret, err);
847*f0865ec9SKyle Evans 
848*f0865ec9SKyle Evans 	out_pub->key_type = in_priv->key_type;
849*f0865ec9SKyle Evans 	out_pub->params = in_priv->params;
850*f0865ec9SKyle Evans 	out_pub->magic = PUB_KEY_MAGIC;
851*f0865ec9SKyle Evans 
852*f0865ec9SKyle Evans err:
853*f0865ec9SKyle Evans 	PTR_NULLIFY(G);
854*f0865ec9SKyle Evans 	VAR_ZEROIFY(digest_size);
855*f0865ec9SKyle Evans 	nn_uninit(&s);
856*f0865ec9SKyle Evans 
857*f0865ec9SKyle Evans 	return ret;
858*f0865ec9SKyle Evans }
859*f0865ec9SKyle Evans 
860*f0865ec9SKyle Evans /*
861*f0865ec9SKyle Evans  * Import a public key in canonical form.
862*f0865ec9SKyle Evans  * (imports a public key from a buffer and checks its canonical form.)
863*f0865ec9SKyle Evans  *
864*f0865ec9SKyle Evans  */
eddsa_import_pub_key(ec_pub_key * pub_key,const u8 * buf,u16 buflen,const ec_params * shortw_curve_params,ec_alg_type sig_type)865*f0865ec9SKyle Evans int eddsa_import_pub_key(ec_pub_key *pub_key, const u8 *buf, u16 buflen,
866*f0865ec9SKyle Evans 			 const ec_params *shortw_curve_params,
867*f0865ec9SKyle Evans 			 ec_alg_type sig_type)
868*f0865ec9SKyle Evans {
869*f0865ec9SKyle Evans 	aff_pt_edwards _Tmp;
870*f0865ec9SKyle Evans 	ec_edwards_crv edwards_curve;
871*f0865ec9SKyle Evans 	int ret;
872*f0865ec9SKyle Evans 	ec_shortw_crv_src_t shortw_curve;
873*f0865ec9SKyle Evans 	fp_src_t alpha_montgomery;
874*f0865ec9SKyle Evans 	fp_src_t gamma_montgomery;
875*f0865ec9SKyle Evans 	fp_src_t alpha_edwards;
876*f0865ec9SKyle Evans 	prj_pt_t pub_key_y;
877*f0865ec9SKyle Evans 	_Tmp.magic = edwards_curve.magic = WORD(0);
878*f0865ec9SKyle Evans 
879*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_EDDSA448)
880*f0865ec9SKyle Evans 	if((sig_type != EDDSA25519) && (sig_type != EDDSA25519CTX) && (sig_type != EDDSA25519PH) && \
881*f0865ec9SKyle Evans 	   (sig_type != EDDSA448) && (sig_type != EDDSA448PH)){
882*f0865ec9SKyle Evans #endif
883*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_EDDSA448)
884*f0865ec9SKyle Evans 	if((sig_type != EDDSA25519) && (sig_type != EDDSA25519CTX) && (sig_type != EDDSA25519PH)){
885*f0865ec9SKyle Evans #endif
886*f0865ec9SKyle Evans #if !defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_EDDSA448)
887*f0865ec9SKyle Evans 	if((sig_type != EDDSA448) && (sig_type != EDDSA448PH)){
888*f0865ec9SKyle Evans #endif
889*f0865ec9SKyle Evans 		ret = -1;
890*f0865ec9SKyle Evans 		goto err;
891*f0865ec9SKyle Evans 	}
892*f0865ec9SKyle Evans 
893*f0865ec9SKyle Evans 	MUST_HAVE((pub_key != NULL) && (shortw_curve_params != NULL) && (buf != NULL), ret, err);
894*f0865ec9SKyle Evans 
895*f0865ec9SKyle Evans 	/* Check for sizes on the buffer for strict size depending on EdDSA types */
896*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
897*f0865ec9SKyle Evans 	if((sig_type == EDDSA25519) || (sig_type == EDDSA25519CTX) || (sig_type == EDDSA25519PH)){
898*f0865ec9SKyle Evans 		MUST_HAVE((buflen == EDDSA25519_PUB_KEY_ENCODED_LEN), ret, err);
899*f0865ec9SKyle Evans 	}
900*f0865ec9SKyle Evans #endif
901*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
902*f0865ec9SKyle Evans 	if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){
903*f0865ec9SKyle Evans 		MUST_HAVE((buflen == EDDSA448_PUB_KEY_ENCODED_LEN), ret, err);
904*f0865ec9SKyle Evans 	}
905*f0865ec9SKyle Evans #endif
906*f0865ec9SKyle Evans 
907*f0865ec9SKyle Evans 	/* Make things more readable */
908*f0865ec9SKyle Evans 	shortw_curve = &(shortw_curve_params->ec_curve);
909*f0865ec9SKyle Evans 	alpha_montgomery = &(shortw_curve_params->ec_alpha_montgomery);
910*f0865ec9SKyle Evans 	gamma_montgomery = &(shortw_curve_params->ec_gamma_montgomery);
911*f0865ec9SKyle Evans 	alpha_edwards = &(shortw_curve_params->ec_alpha_edwards);
912*f0865ec9SKyle Evans 	pub_key_y = &(pub_key->y);
913*f0865ec9SKyle Evans 
914*f0865ec9SKyle Evans 	/* Get the isogenic Edwards curve */
915*f0865ec9SKyle Evans 	ret = curve_shortw_to_edwards(shortw_curve, &edwards_curve, alpha_montgomery,
916*f0865ec9SKyle Evans 				gamma_montgomery, alpha_edwards); EG(ret, err);
917*f0865ec9SKyle Evans 
918*f0865ec9SKyle Evans 	/* Decode the point in Edwards */
919*f0865ec9SKyle Evans 	ret = eddsa_decode_point(&_Tmp, &edwards_curve, alpha_edwards, buf, buflen,
920*f0865ec9SKyle Evans 			      sig_type); EG(ret, err);
921*f0865ec9SKyle Evans 	/* Then transfer to short Weierstrass in our public key */
922*f0865ec9SKyle Evans 	ret = aff_pt_edwards_to_prj_pt_shortw(&_Tmp, shortw_curve, pub_key_y,
923*f0865ec9SKyle Evans 					alpha_edwards); EG(ret, err);
924*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
925*f0865ec9SKyle Evans 	if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){
926*f0865ec9SKyle Evans 		nn_src_t gen_order = &(shortw_curve_params->ec_gen_order);
927*f0865ec9SKyle Evans 		nn tmp;
928*f0865ec9SKyle Evans 		tmp.magic = WORD(0);
929*f0865ec9SKyle Evans 
930*f0865ec9SKyle Evans 		/*
931*f0865ec9SKyle Evans 		 * NOTE: because of the 4-isogeny between Ed448 and Edwards448,
932*f0865ec9SKyle Evans 		 * we actually multiply by (s/4) since the base point of
933*f0865ec9SKyle Evans 		 * Edwards448 is four times the one of Ed448.
934*f0865ec9SKyle Evans 		 * Here, s/4 is computed by multiplying s by the modular
935*f0865ec9SKyle Evans 		 * inverse of 4.
936*f0865ec9SKyle Evans 		 */
937*f0865ec9SKyle Evans 		ret = nn_init(&tmp, 0); EG(ret, err1);
938*f0865ec9SKyle Evans 		ret = nn_modinv_word(&tmp, WORD(4), gen_order); EG(ret, err1);
939*f0865ec9SKyle Evans 		ret = prj_pt_mul(&(pub_key->y), &tmp, pub_key_y); EG(ret, err1);
940*f0865ec9SKyle Evans err1:
941*f0865ec9SKyle Evans 		nn_uninit(&tmp);
942*f0865ec9SKyle Evans 		PTR_NULLIFY(gen_order);
943*f0865ec9SKyle Evans 		EG(ret, err);
944*f0865ec9SKyle Evans 	}
945*f0865ec9SKyle Evans #endif
946*f0865ec9SKyle Evans 	/* Mark the public key as initialized */
947*f0865ec9SKyle Evans 	pub_key->key_type = sig_type;
948*f0865ec9SKyle Evans 	pub_key->params = shortw_curve_params;
949*f0865ec9SKyle Evans 	pub_key->magic = PUB_KEY_MAGIC;
950*f0865ec9SKyle Evans 
951*f0865ec9SKyle Evans 	/* Now sanity check our public key before validating the import */
952*f0865ec9SKyle Evans 	ret = eddsa_pub_key_sanity_check(pub_key);
953*f0865ec9SKyle Evans 
954*f0865ec9SKyle Evans err:
955*f0865ec9SKyle Evans 	if((pub_key != NULL) && ret){
956*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset(pub_key, 0, sizeof(ec_pub_key)));
957*f0865ec9SKyle Evans 	}
958*f0865ec9SKyle Evans 	PTR_NULLIFY(shortw_curve);
959*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_montgomery);
960*f0865ec9SKyle Evans 	PTR_NULLIFY(gamma_montgomery);
961*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_edwards);
962*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key_y);
963*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&_Tmp);
964*f0865ec9SKyle Evans 	ec_edwards_crv_uninit(&edwards_curve);
965*f0865ec9SKyle Evans 
966*f0865ec9SKyle Evans 	return ret;
967*f0865ec9SKyle Evans }
968*f0865ec9SKyle Evans 
969*f0865ec9SKyle Evans /*
970*f0865ec9SKyle Evans  * Export a public key in canonical form.
971*f0865ec9SKyle Evans  * (exports a public key to a buffer in canonical form.)
972*f0865ec9SKyle Evans  */
973*f0865ec9SKyle Evans int eddsa_export_pub_key(const ec_pub_key *in_pub, u8 *buf, u16 buflen)
974*f0865ec9SKyle Evans {
975*f0865ec9SKyle Evans 	aff_pt_edwards _Tmp;
976*f0865ec9SKyle Evans 	ec_edwards_crv edwards_curve;
977*f0865ec9SKyle Evans 	ec_alg_type sig_type;
978*f0865ec9SKyle Evans 	int ret;
979*f0865ec9SKyle Evans 	ec_shortw_crv_src_t shortw_curve;
980*f0865ec9SKyle Evans 	fp_src_t alpha_montgomery;
981*f0865ec9SKyle Evans 	fp_src_t gamma_montgomery;
982*f0865ec9SKyle Evans 	fp_src_t alpha_edwards;
983*f0865ec9SKyle Evans 	prj_pt_src_t pub_key_y;
984*f0865ec9SKyle Evans 	_Tmp.magic = edwards_curve.magic = WORD(0);
985*f0865ec9SKyle Evans 
986*f0865ec9SKyle Evans 	ret = pub_key_check_initialized(in_pub); EG(ret, err);
987*f0865ec9SKyle Evans 	MUST_HAVE((buf != NULL), ret, err);
988*f0865ec9SKyle Evans 
989*f0865ec9SKyle Evans 	/* Make things more readable */
990*f0865ec9SKyle Evans 	shortw_curve = &(in_pub->params->ec_curve);
991*f0865ec9SKyle Evans 	alpha_montgomery = &(in_pub->params->ec_alpha_montgomery);
992*f0865ec9SKyle Evans 	gamma_montgomery = &(in_pub->params->ec_gamma_montgomery);
993*f0865ec9SKyle Evans 	alpha_edwards = &(in_pub->params->ec_alpha_edwards);
994*f0865ec9SKyle Evans 	pub_key_y = &(in_pub->y);
995*f0865ec9SKyle Evans 	sig_type = in_pub->key_type;
996*f0865ec9SKyle Evans 
997*f0865ec9SKyle Evans 	/* Check for sizes on the buffer for strict size depending on EdDSA types */
998*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
999*f0865ec9SKyle Evans 	if((sig_type == EDDSA25519) || (sig_type == EDDSA25519CTX) || (sig_type == EDDSA25519PH)){
1000*f0865ec9SKyle Evans 		MUST_HAVE((buflen == EDDSA25519_PUB_KEY_ENCODED_LEN), ret, err);
1001*f0865ec9SKyle Evans 	}
1002*f0865ec9SKyle Evans #endif
1003*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1004*f0865ec9SKyle Evans 	if((sig_type == EDDSA448) || (sig_type == EDDSA448PH)){
1005*f0865ec9SKyle Evans 		MUST_HAVE((buflen == EDDSA448_PUB_KEY_ENCODED_LEN), ret, err);
1006*f0865ec9SKyle Evans 	}
1007*f0865ec9SKyle Evans #endif
1008*f0865ec9SKyle Evans 
1009*f0865ec9SKyle Evans 	/* Transfer our short Weierstrass to Edwards representation */
1010*f0865ec9SKyle Evans 	ret = curve_shortw_to_edwards(shortw_curve, &edwards_curve, alpha_montgomery,
1011*f0865ec9SKyle Evans 				gamma_montgomery, alpha_edwards); EG(ret, err);
1012*f0865ec9SKyle Evans 	ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &edwards_curve, &_Tmp,
1013*f0865ec9SKyle Evans 					alpha_edwards); EG(ret, err);
1014*f0865ec9SKyle Evans 	/* Export to buffer canonical form */
1015*f0865ec9SKyle Evans 	ret = eddsa_encode_point(&_Tmp, alpha_edwards, buf,
1016*f0865ec9SKyle Evans 			      buflen, in_pub->key_type);
1017*f0865ec9SKyle Evans 
1018*f0865ec9SKyle Evans err:
1019*f0865ec9SKyle Evans 	PTR_NULLIFY(shortw_curve);
1020*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_montgomery);
1021*f0865ec9SKyle Evans 	PTR_NULLIFY(gamma_montgomery);
1022*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_edwards);
1023*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key_y);
1024*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&_Tmp);
1025*f0865ec9SKyle Evans 	ec_edwards_crv_uninit(&edwards_curve);
1026*f0865ec9SKyle Evans 
1027*f0865ec9SKyle Evans 	return ret;
1028*f0865ec9SKyle Evans }
1029*f0865ec9SKyle Evans 
1030*f0865ec9SKyle Evans /* Import an EdDSA key pair from a private key buffer */
1031*f0865ec9SKyle Evans int eddsa_import_key_pair_from_priv_key_buf(ec_key_pair *kp,
1032*f0865ec9SKyle Evans 					    const u8 *buf, u16 buflen,
1033*f0865ec9SKyle Evans 					    const ec_params *shortw_curve_params,
1034*f0865ec9SKyle Evans 					    ec_alg_type sig_type)
1035*f0865ec9SKyle Evans {
1036*f0865ec9SKyle Evans 	int ret;
1037*f0865ec9SKyle Evans 
1038*f0865ec9SKyle Evans 	MUST_HAVE((kp != NULL), ret, err);
1039*f0865ec9SKyle Evans 
1040*f0865ec9SKyle Evans 	/* Try to import the private key */
1041*f0865ec9SKyle Evans 	ret = eddsa_import_priv_key(&(kp->priv_key), buf, buflen,
1042*f0865ec9SKyle Evans 				 shortw_curve_params, sig_type); EG(ret, err);
1043*f0865ec9SKyle Evans 
1044*f0865ec9SKyle Evans 	/* Now derive the public key */
1045*f0865ec9SKyle Evans 	ret = eddsa_init_pub_key(&(kp->pub_key), &(kp->priv_key));
1046*f0865ec9SKyle Evans 
1047*f0865ec9SKyle Evans err:
1048*f0865ec9SKyle Evans 	return ret;
1049*f0865ec9SKyle Evans }
1050*f0865ec9SKyle Evans 
1051*f0865ec9SKyle Evans /* Compute PH(M) with PH being the hash depending on the key type */
1052*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int eddsa_compute_pre_hash(const u8 *message, u32 message_size,
1053*f0865ec9SKyle Evans 				  u8 *digest, u8 *digest_size,
1054*f0865ec9SKyle Evans 				  ec_alg_type sig_type)
1055*f0865ec9SKyle Evans {
1056*f0865ec9SKyle Evans 	hash_alg_type hash_type;
1057*f0865ec9SKyle Evans 	const hash_mapping *hash;
1058*f0865ec9SKyle Evans 	hash_context hash_ctx;
1059*f0865ec9SKyle Evans 	int ret;
1060*f0865ec9SKyle Evans 
1061*f0865ec9SKyle Evans 	MUST_HAVE((message != NULL) && (digest != NULL) && (digest_size != NULL), ret, err);
1062*f0865ec9SKyle Evans 
1063*f0865ec9SKyle Evans 	MUST_HAVE(((hash_type = get_eddsa_hash_type(sig_type)) != UNKNOWN_HASH_ALG), ret, err);
1064*f0865ec9SKyle Evans 
1065*f0865ec9SKyle Evans 	ret = get_hash_by_type(hash_type, &hash); EG(ret, err);
1066*f0865ec9SKyle Evans 	MUST_HAVE((hash != NULL), ret, err);
1067*f0865ec9SKyle Evans 
1068*f0865ec9SKyle Evans 	/* Sanity check on the size */
1069*f0865ec9SKyle Evans 	MUST_HAVE(((*digest_size) >= hash->digest_size), ret, err);
1070*f0865ec9SKyle Evans 
1071*f0865ec9SKyle Evans 	(*digest_size) = hash->digest_size;
1072*f0865ec9SKyle Evans 	/* Hash the message */
1073*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(hash); EG(ret, err);
1074*f0865ec9SKyle Evans 	ret = hash->hfunc_init(&hash_ctx); EG(ret, err);
1075*f0865ec9SKyle Evans 	ret = hash->hfunc_update(&hash_ctx, message, message_size); EG(ret, err);
1076*f0865ec9SKyle Evans 	ret = hash->hfunc_finalize(&hash_ctx, digest); EG(ret, err);
1077*f0865ec9SKyle Evans 
1078*f0865ec9SKyle Evans err:
1079*f0865ec9SKyle Evans 	return ret;
1080*f0865ec9SKyle Evans }
1081*f0865ec9SKyle Evans 
1082*f0865ec9SKyle Evans /*****************/
1083*f0865ec9SKyle Evans 
1084*f0865ec9SKyle Evans /* EdDSA signature length */
1085*f0865ec9SKyle Evans int eddsa_siglen(u16 p_bit_len, u16 q_bit_len, u8 hsize, u8 blocksize, u8 *siglen)
1086*f0865ec9SKyle Evans {
1087*f0865ec9SKyle Evans 	int ret;
1088*f0865ec9SKyle Evans 
1089*f0865ec9SKyle Evans 	MUST_HAVE((siglen != NULL), ret, err);
1090*f0865ec9SKyle Evans 	MUST_HAVE((p_bit_len <= CURVES_MAX_P_BIT_LEN) &&
1091*f0865ec9SKyle Evans 		  (q_bit_len <= CURVES_MAX_Q_BIT_LEN) &&
1092*f0865ec9SKyle Evans 		  (hsize <= MAX_DIGEST_SIZE) && (blocksize <= MAX_BLOCK_SIZE), ret, err);
1093*f0865ec9SKyle Evans 
1094*f0865ec9SKyle Evans 	(*siglen) = (u8)EDDSA_SIGLEN(hsize);
1095*f0865ec9SKyle Evans 	ret = 0;
1096*f0865ec9SKyle Evans err:
1097*f0865ec9SKyle Evans 	return ret;
1098*f0865ec9SKyle Evans }
1099*f0865ec9SKyle Evans 
1100*f0865ec9SKyle Evans /*
1101*f0865ec9SKyle Evans  * Generic *internal* EdDSA signature functions (init, update and finalize).
1102*f0865ec9SKyle Evans  *
1103*f0865ec9SKyle Evans  * Global EdDSA signature process is as follows (I,U,F provides
1104*f0865ec9SKyle Evans  * information in which function(s) (init(), update() or finalize())
1105*f0865ec9SKyle Evans  * a specific step is performed):
1106*f0865ec9SKyle Evans  *
1107*f0865ec9SKyle Evans  */
1108*f0865ec9SKyle Evans 
1109*f0865ec9SKyle Evans #define EDDSA_SIGN_MAGIC ((word_t)(0x7632542bf630972bULL))
1110*f0865ec9SKyle Evans #define EDDSA_SIGN_CHECK_INITIALIZED(A, ret, err) \
1111*f0865ec9SKyle Evans 	MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == EDDSA_SIGN_MAGIC), ret, err)
1112*f0865ec9SKyle Evans 
1113*f0865ec9SKyle Evans int _eddsa_sign_init_pre_hash(struct ec_sign_context *ctx)
1114*f0865ec9SKyle Evans {
1115*f0865ec9SKyle Evans 	int ret;
1116*f0865ec9SKyle Evans 	bitcnt_t blen;
1117*f0865ec9SKyle Evans 	u8 use_message_pre_hash = 0;
1118*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
1119*f0865ec9SKyle Evans 	const ec_key_pair *key_pair;
1120*f0865ec9SKyle Evans 	const hash_mapping *h;
1121*f0865ec9SKyle Evans 
1122*f0865ec9SKyle Evans 	/* First, verify context has been initialized */
1123*f0865ec9SKyle Evans 	ret = sig_sign_check_initialized(ctx); EG(ret, err);
1124*f0865ec9SKyle Evans 
1125*f0865ec9SKyle Evans 	/* Make things more readable */
1126*f0865ec9SKyle Evans 	key_pair = ctx->key_pair;
1127*f0865ec9SKyle Evans 	h = ctx->h;
1128*f0865ec9SKyle Evans 	key_type = ctx->key_pair->priv_key.key_type;
1129*f0865ec9SKyle Evans 
1130*f0865ec9SKyle Evans 	/* Sanity check: this function is only supported in PH mode */
1131*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1132*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1133*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
1134*f0865ec9SKyle Evans 	}
1135*f0865ec9SKyle Evans #endif
1136*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1137*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1138*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
1139*f0865ec9SKyle Evans 	}
1140*f0865ec9SKyle Evans #endif
1141*f0865ec9SKyle Evans 	MUST_HAVE((use_message_pre_hash == 1), ret, err);
1142*f0865ec9SKyle Evans 
1143*f0865ec9SKyle Evans 	/* Additional sanity checks on input params from context */
1144*f0865ec9SKyle Evans 	ret = eddsa_key_pair_sanity_check(key_pair); EG(ret, err);
1145*f0865ec9SKyle Evans 
1146*f0865ec9SKyle Evans 	MUST_HAVE((h != NULL) && (h->digest_size <= MAX_DIGEST_SIZE) && (h->block_size <= MAX_BLOCK_SIZE), ret, err);
1147*f0865ec9SKyle Evans 
1148*f0865ec9SKyle Evans 	/* Sanity check on hash types */
1149*f0865ec9SKyle Evans 	MUST_HAVE((key_type == key_pair->pub_key.key_type) && (h->type == get_eddsa_hash_type(key_type)), ret, err);
1150*f0865ec9SKyle Evans 
1151*f0865ec9SKyle Evans 	/*
1152*f0865ec9SKyle Evans 	 * Sanity check on hash size versus private key size
1153*f0865ec9SKyle Evans 	 */
1154*f0865ec9SKyle Evans 	ret = nn_bitlen(&(key_pair->priv_key.x), &blen); EG(ret, err);
1155*f0865ec9SKyle Evans 	MUST_HAVE(blen <= (8 * h->digest_size), ret, err);
1156*f0865ec9SKyle Evans 
1157*f0865ec9SKyle Evans 	/*
1158*f0865ec9SKyle Evans 	 * Initialize hash context stored in our private part of context
1159*f0865ec9SKyle Evans 	 * and record data init has been done
1160*f0865ec9SKyle Evans 	 */
1161*f0865ec9SKyle Evans 	/* Since we call a callback, sanity check our mapping */
1162*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
1163*f0865ec9SKyle Evans 	ret = h->hfunc_init(&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err);
1164*f0865ec9SKyle Evans 
1165*f0865ec9SKyle Evans 	/* Initialize other elements in the context */
1166*f0865ec9SKyle Evans 	ctx->sign_data.eddsa.magic = EDDSA_SIGN_MAGIC;
1167*f0865ec9SKyle Evans 
1168*f0865ec9SKyle Evans err:
1169*f0865ec9SKyle Evans 	PTR_NULLIFY(key_pair);
1170*f0865ec9SKyle Evans 	PTR_NULLIFY(h);
1171*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash);
1172*f0865ec9SKyle Evans 
1173*f0865ec9SKyle Evans 	return ret;
1174*f0865ec9SKyle Evans }
1175*f0865ec9SKyle Evans 
1176*f0865ec9SKyle Evans int _eddsa_sign_update_pre_hash(struct ec_sign_context *ctx,
1177*f0865ec9SKyle Evans 		       const u8 *chunk, u32 chunklen)
1178*f0865ec9SKyle Evans {
1179*f0865ec9SKyle Evans 	int ret;
1180*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
1181*f0865ec9SKyle Evans 	u8 use_message_pre_hash = 0;
1182*f0865ec9SKyle Evans 
1183*f0865ec9SKyle Evans 	/*
1184*f0865ec9SKyle Evans 	 * First, verify context has been initialized and public
1185*f0865ec9SKyle Evans 	 * part too. This guarantees the context is an EDDSA
1186*f0865ec9SKyle Evans 	 * verification one and we do not update() or finalize()
1187*f0865ec9SKyle Evans 	 * before init().
1188*f0865ec9SKyle Evans 	 */
1189*f0865ec9SKyle Evans 	ret = sig_sign_check_initialized(ctx); EG(ret, err);
1190*f0865ec9SKyle Evans 	EDDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.eddsa), ret, err);
1191*f0865ec9SKyle Evans 	MUST_HAVE((chunk != NULL), ret, err);
1192*f0865ec9SKyle Evans 
1193*f0865ec9SKyle Evans 	key_type = ctx->key_pair->priv_key.key_type;
1194*f0865ec9SKyle Evans 
1195*f0865ec9SKyle Evans 	/* Sanity check: this function is only supported in PH mode */
1196*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1197*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1198*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
1199*f0865ec9SKyle Evans 	}
1200*f0865ec9SKyle Evans #endif
1201*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1202*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1203*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
1204*f0865ec9SKyle Evans 	}
1205*f0865ec9SKyle Evans #endif
1206*f0865ec9SKyle Evans 	MUST_HAVE(use_message_pre_hash == 1, ret, err);
1207*f0865ec9SKyle Evans 
1208*f0865ec9SKyle Evans 	/* Sanity check on hash types */
1209*f0865ec9SKyle Evans 	MUST_HAVE((ctx->h->type == get_eddsa_hash_type(key_type)), ret, err);
1210*f0865ec9SKyle Evans 
1211*f0865ec9SKyle Evans 	/* 2. Compute h = H(m) */
1212*f0865ec9SKyle Evans 	/* Since we call a callback, sanity check our mapping */
1213*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
1214*f0865ec9SKyle Evans 
1215*f0865ec9SKyle Evans 	ret = ctx->h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), chunk, chunklen);
1216*f0865ec9SKyle Evans 
1217*f0865ec9SKyle Evans err:
1218*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash);
1219*f0865ec9SKyle Evans 
1220*f0865ec9SKyle Evans 	return ret;
1221*f0865ec9SKyle Evans 
1222*f0865ec9SKyle Evans }
1223*f0865ec9SKyle Evans 
1224*f0865ec9SKyle Evans int _eddsa_sign_finalize_pre_hash(struct ec_sign_context *ctx, u8 *sig, u8 siglen)
1225*f0865ec9SKyle Evans {
1226*f0865ec9SKyle Evans 	const ec_priv_key *priv_key;
1227*f0865ec9SKyle Evans 	const ec_pub_key *pub_key;
1228*f0865ec9SKyle Evans 	prj_pt_src_t G;
1229*f0865ec9SKyle Evans 	u8 hash[MAX_DIGEST_SIZE];
1230*f0865ec9SKyle Evans 	u8 ph_hash[MAX_DIGEST_SIZE];
1231*f0865ec9SKyle Evans 	prj_pt R;
1232*f0865ec9SKyle Evans 	ec_edwards_crv crv_edwards;
1233*f0865ec9SKyle Evans 	aff_pt_edwards Tmp_edwards;
1234*f0865ec9SKyle Evans 	nn_src_t q;
1235*f0865ec9SKyle Evans 	u8 hsize, hash_size;
1236*f0865ec9SKyle Evans 	int ret;
1237*f0865ec9SKyle Evans 	ec_shortw_crv_src_t shortw_curve;
1238*f0865ec9SKyle Evans 	fp_src_t alpha_montgomery;
1239*f0865ec9SKyle Evans 	fp_src_t gamma_montgomery;
1240*f0865ec9SKyle Evans 	fp_src_t alpha_edwards;
1241*f0865ec9SKyle Evans 	prj_pt_src_t pub_key_y;
1242*f0865ec9SKyle Evans 	u8 use_message_pre_hash = 0;
1243*f0865ec9SKyle Evans 	u16 use_message_pre_hash_hsize = 0;
1244*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
1245*f0865ec9SKyle Evans 	u8 r_len, s_len;
1246*f0865ec9SKyle Evans 	const hash_mapping *h;
1247*f0865ec9SKyle Evans 
1248*f0865ec9SKyle Evans 	nn r, s, S;
1249*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1250*f0865ec9SKyle Evans 	/* b is the blinding mask */
1251*f0865ec9SKyle Evans 	nn b, binv;
1252*f0865ec9SKyle Evans 	b.magic = binv.magic = WORD(0);
1253*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1254*f0865ec9SKyle Evans 	r.magic = s.magic = S.magic = WORD(0);
1255*f0865ec9SKyle Evans 	R.magic = crv_edwards.magic = Tmp_edwards.magic = WORD(0);
1256*f0865ec9SKyle Evans 
1257*f0865ec9SKyle Evans 	/*
1258*f0865ec9SKyle Evans 	 * First, verify context has been initialized and private
1259*f0865ec9SKyle Evans 	 * part too. This guarantees the context is an EDDSA
1260*f0865ec9SKyle Evans 	 * signature one and we do not update() or finalize()
1261*f0865ec9SKyle Evans 	 * before init().
1262*f0865ec9SKyle Evans 	 */
1263*f0865ec9SKyle Evans 	ret = sig_sign_check_initialized(ctx); EG(ret, err);
1264*f0865ec9SKyle Evans 	EDDSA_SIGN_CHECK_INITIALIZED(&(ctx->sign_data.eddsa), ret, err);
1265*f0865ec9SKyle Evans 	MUST_HAVE((sig != NULL), ret, err);
1266*f0865ec9SKyle Evans 
1267*f0865ec9SKyle Evans 	/* Zero init out points and data */
1268*f0865ec9SKyle Evans 	ret = local_memset(&R, 0, sizeof(prj_pt)); EG(ret, err);
1269*f0865ec9SKyle Evans 	ret = local_memset(&Tmp_edwards, 0, sizeof(aff_pt_edwards)); EG(ret, err);
1270*f0865ec9SKyle Evans 	ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err);
1271*f0865ec9SKyle Evans 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
1272*f0865ec9SKyle Evans 	ret = local_memset(ph_hash, 0, sizeof(ph_hash)); EG(ret, err);
1273*f0865ec9SKyle Evans 
1274*f0865ec9SKyle Evans 	/* Key type */
1275*f0865ec9SKyle Evans 	key_type = ctx->key_pair->priv_key.key_type;
1276*f0865ec9SKyle Evans 	/* Sanity check on hash types */
1277*f0865ec9SKyle Evans 	MUST_HAVE((key_type == ctx->key_pair->pub_key.key_type) && (ctx->h->type == get_eddsa_hash_type(key_type)), ret, err);
1278*f0865ec9SKyle Evans 
1279*f0865ec9SKyle Evans 	/* Make things more readable */
1280*f0865ec9SKyle Evans 	priv_key = &(ctx->key_pair->priv_key);
1281*f0865ec9SKyle Evans 	pub_key = &(ctx->key_pair->pub_key);
1282*f0865ec9SKyle Evans 	q = &(priv_key->params->ec_gen_order);
1283*f0865ec9SKyle Evans 	G = &(priv_key->params->ec_gen);
1284*f0865ec9SKyle Evans 	h = ctx->h;
1285*f0865ec9SKyle Evans 	hsize = h->digest_size;
1286*f0865ec9SKyle Evans 	r_len = EDDSA_R_LEN(hsize);
1287*f0865ec9SKyle Evans 	s_len = EDDSA_S_LEN(hsize);
1288*f0865ec9SKyle Evans 
1289*f0865ec9SKyle Evans 	shortw_curve = &(priv_key->params->ec_curve);
1290*f0865ec9SKyle Evans 	alpha_montgomery = &(priv_key->params->ec_alpha_montgomery);
1291*f0865ec9SKyle Evans 	gamma_montgomery = &(priv_key->params->ec_gamma_montgomery);
1292*f0865ec9SKyle Evans 	alpha_edwards = &(priv_key->params->ec_alpha_edwards);
1293*f0865ec9SKyle Evans 	pub_key_y = &(pub_key->y);
1294*f0865ec9SKyle Evans 
1295*f0865ec9SKyle Evans 	dbg_nn_print("p", &(priv_key->params->ec_fp.p));
1296*f0865ec9SKyle Evans 	dbg_nn_print("q", &(priv_key->params->ec_gen_order));
1297*f0865ec9SKyle Evans 	dbg_priv_key_print("x", priv_key);
1298*f0865ec9SKyle Evans 	dbg_ec_point_print("G", &(priv_key->params->ec_gen));
1299*f0865ec9SKyle Evans 	dbg_pub_key_print("Y", &(ctx->key_pair->pub_key));
1300*f0865ec9SKyle Evans 
1301*f0865ec9SKyle Evans 	/* Check provided signature length */
1302*f0865ec9SKyle Evans 	MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)) && (siglen == (r_len + s_len)), ret, err);
1303*f0865ec9SKyle Evans 
1304*f0865ec9SKyle Evans 	/* Is it indeed a PH version of the algorithm? */
1305*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1306*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1307*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
1308*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = hsize;
1309*f0865ec9SKyle Evans 	}
1310*f0865ec9SKyle Evans #endif
1311*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1312*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1313*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
1314*f0865ec9SKyle Evans 		/* NOTE: as per RFC8032, EDDSA448PH uses
1315*f0865ec9SKyle Evans 		 * SHAKE256 with 64 bytes output.
1316*f0865ec9SKyle Evans 		 */
1317*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = 64;
1318*f0865ec9SKyle Evans 	}
1319*f0865ec9SKyle Evans #endif
1320*f0865ec9SKyle Evans 	/* Sanity check: this function is only supported in PH mode */
1321*f0865ec9SKyle Evans 	MUST_HAVE((use_message_pre_hash == 1), ret, err);
1322*f0865ec9SKyle Evans 
1323*f0865ec9SKyle Evans 	/* Finish the message hash session */
1324*f0865ec9SKyle Evans 	/* Since we call a callback, sanity check our mapping */
1325*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
1326*f0865ec9SKyle Evans 
1327*f0865ec9SKyle Evans 	ret = h->hfunc_finalize(&(ctx->sign_data.eddsa.h_ctx), ph_hash); EG(ret, err);
1328*f0865ec9SKyle Evans 
1329*f0865ec9SKyle Evans 	/* 1. Finish computing the nonce r = H(h256 || ... || h511 || m) */
1330*f0865ec9SKyle Evans 	/* Update our hash context with half of the secret key */
1331*f0865ec9SKyle Evans 	hash_size = sizeof(hash);
1332*f0865ec9SKyle Evans 	ret = eddsa_get_digest_from_priv_key(hash, &hash_size, priv_key); EG(ret, err);
1333*f0865ec9SKyle Evans 
1334*f0865ec9SKyle Evans 	/* Sanity check */
1335*f0865ec9SKyle Evans 	MUST_HAVE((hash_size == hsize), ret, err);
1336*f0865ec9SKyle Evans 
1337*f0865ec9SKyle Evans 	/* Hash half the digest */
1338*f0865ec9SKyle Evans 	ret = h->hfunc_init(&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err);
1339*f0865ec9SKyle Evans 
1340*f0865ec9SKyle Evans 	/* At this point, we are ensured that we have PH versions of the algorithms */
1341*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1342*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1343*f0865ec9SKyle Evans 		ret = dom2(1, ctx->adata, ctx->adata_len, h,
1344*f0865ec9SKyle Evans 			&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err);
1345*f0865ec9SKyle Evans 	}
1346*f0865ec9SKyle Evans #endif
1347*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1348*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1349*f0865ec9SKyle Evans 		ret = dom4(1, ctx->adata, ctx->adata_len, h,
1350*f0865ec9SKyle Evans 			&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err);
1351*f0865ec9SKyle Evans 	}
1352*f0865ec9SKyle Evans #endif
1353*f0865ec9SKyle Evans 	ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), &hash[hsize / 2], hsize / 2); EG(ret, err);
1354*f0865ec9SKyle Evans 
1355*f0865ec9SKyle Evans 	/* Update hash h with message hash PH(m) */
1356*f0865ec9SKyle Evans 	MUST_HAVE((use_message_pre_hash_hsize <= hsize), ret, err);
1357*f0865ec9SKyle Evans 
1358*f0865ec9SKyle Evans 	ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), ph_hash,
1359*f0865ec9SKyle Evans 			use_message_pre_hash_hsize); EG(ret, err);
1360*f0865ec9SKyle Evans 
1361*f0865ec9SKyle Evans 	/* 1. Finish computing the nonce r = H(h256 || ... || h511 || PH(m)) */
1362*f0865ec9SKyle Evans 	ret = h->hfunc_finalize(&(ctx->sign_data.eddsa.h_ctx), hash); EG(ret, err);
1363*f0865ec9SKyle Evans 	dbg_buf_print("h(h || m)", hash, hsize);
1364*f0865ec9SKyle Evans 
1365*f0865ec9SKyle Evans 	/* Import r as the hash scalar */
1366*f0865ec9SKyle Evans 	ret = eddsa_decode_integer(&r, hash, hsize); EG(ret, err);
1367*f0865ec9SKyle Evans 
1368*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1369*f0865ec9SKyle Evans 	/* Get a random b for blinding the r modular operations before the
1370*f0865ec9SKyle Evans 	 * scalar multiplication as we do not want it to leak.
1371*f0865ec9SKyle Evans 	 */
1372*f0865ec9SKyle Evans 	ret = nn_get_random_mod(&b, q); EG(ret, err);
1373*f0865ec9SKyle Evans 	dbg_nn_print("b", &b);
1374*f0865ec9SKyle Evans 	/* NOTE: we use Fermat's little theorem inversion for
1375*f0865ec9SKyle Evans 	 * constant time here. This is possible since q is prime.
1376*f0865ec9SKyle Evans 	 */
1377*f0865ec9SKyle Evans 	ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err);
1378*f0865ec9SKyle Evans 
1379*f0865ec9SKyle Evans 	/* Blind r */
1380*f0865ec9SKyle Evans 	ret = nn_mul(&r, &r, &b); EG(ret, err);
1381*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
1382*f0865ec9SKyle Evans 
1383*f0865ec9SKyle Evans 	/* Reduce r modulo q for the next computation.
1384*f0865ec9SKyle Evans 	 * (this is a blind reduction if USE_SIG_BLINDING).
1385*f0865ec9SKyle Evans 	 */
1386*f0865ec9SKyle Evans 	ret = nn_mod_notrim(&r, &r, q); EG(ret, err);
1387*f0865ec9SKyle Evans 
1388*f0865ec9SKyle Evans 	/* Now perform our scalar multiplication.
1389*f0865ec9SKyle Evans 	 */
1390*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1391*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1392*f0865ec9SKyle Evans 		/*
1393*f0865ec9SKyle Evans 		 * NOTE: in case of EDDSA448, because of the 4-isogeny we must
1394*f0865ec9SKyle Evans 		 * divide our scalar by 4.
1395*f0865ec9SKyle Evans 		 */
1396*f0865ec9SKyle Evans 		nn r_tmp;
1397*f0865ec9SKyle Evans 		r_tmp.magic = WORD(0);
1398*f0865ec9SKyle Evans 
1399*f0865ec9SKyle Evans 		ret = nn_init(&r_tmp, 0); EG(ret, err1);
1400*f0865ec9SKyle Evans 		ret = nn_modinv_word(&r_tmp, WORD(4), q); EG(ret, err1);
1401*f0865ec9SKyle Evans 		ret = nn_mod_mul(&r_tmp, &r_tmp, &r, q); EG(ret, err1);
1402*f0865ec9SKyle Evans 
1403*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1404*f0865ec9SKyle Evans 		/* Unblind r_tmp */
1405*f0865ec9SKyle Evans 		ret = nn_mod_mul(&r_tmp, &r_tmp, &binv, q); EG(ret, err1);
1406*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&R, &r_tmp, G);
1407*f0865ec9SKyle Evans #else
1408*f0865ec9SKyle Evans 		ret = prj_pt_mul(&R, &r_tmp, G);
1409*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1410*f0865ec9SKyle Evans err1:
1411*f0865ec9SKyle Evans 		nn_uninit(&r_tmp);
1412*f0865ec9SKyle Evans 		EG(ret, err);
1413*f0865ec9SKyle Evans 	}
1414*f0865ec9SKyle Evans 	else
1415*f0865ec9SKyle Evans #endif /* !defined(WITH_SIG_EDDSA448) */
1416*f0865ec9SKyle Evans 	{
1417*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1418*f0865ec9SKyle Evans 		nn r_tmp;
1419*f0865ec9SKyle Evans 		r_tmp.magic = WORD(0);
1420*f0865ec9SKyle Evans 
1421*f0865ec9SKyle Evans 		ret = nn_init(&r_tmp, 0); EG(ret, err2);
1422*f0865ec9SKyle Evans 		ret = nn_copy(&r_tmp, &r); EG(ret, err2);
1423*f0865ec9SKyle Evans 
1424*f0865ec9SKyle Evans 		/* Unblind r_tmp */
1425*f0865ec9SKyle Evans 		ret = nn_mod_mul(&r_tmp, &r_tmp, &binv, q); EG(ret, err2);
1426*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&R, &r_tmp, G); EG(ret, err2);
1427*f0865ec9SKyle Evans err2:
1428*f0865ec9SKyle Evans 		nn_uninit(&r_tmp);
1429*f0865ec9SKyle Evans 		EG(ret, err);
1430*f0865ec9SKyle Evans #else
1431*f0865ec9SKyle Evans 		ret = prj_pt_mul(&R, &r, G); EG(ret, err);
1432*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1433*f0865ec9SKyle Evans 	}
1434*f0865ec9SKyle Evans 
1435*f0865ec9SKyle Evans 	/* Now compute S = (r + H(R || PubKey || PH(m)) * secret) mod q */
1436*f0865ec9SKyle Evans 	ret = h->hfunc_init(&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err);
1437*f0865ec9SKyle Evans 	/* Transfer R to Edwards */
1438*f0865ec9SKyle Evans 	ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery,
1439*f0865ec9SKyle Evans 				gamma_montgomery, alpha_edwards); EG(ret, err);
1440*f0865ec9SKyle Evans 	ret = prj_pt_shortw_to_aff_pt_edwards(&R, &crv_edwards, &Tmp_edwards,
1441*f0865ec9SKyle Evans 					alpha_edwards); EG(ret, err);
1442*f0865ec9SKyle Evans 	dbg_ec_edwards_point_print("R", &Tmp_edwards);
1443*f0865ec9SKyle Evans 
1444*f0865ec9SKyle Evans 	MUST_HAVE((r_len <= siglen), ret, err);
1445*f0865ec9SKyle Evans 	/* Encode R and update */
1446*f0865ec9SKyle Evans 	ret = eddsa_encode_point(&Tmp_edwards, alpha_edwards, &sig[0],
1447*f0865ec9SKyle Evans 			      r_len, key_type); EG(ret, err);
1448*f0865ec9SKyle Evans 	/* At this point, we are ensured that we have PH versions of the algorithms */
1449*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1450*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1451*f0865ec9SKyle Evans 		ret = dom2(1, ctx->adata, ctx->adata_len, h,
1452*f0865ec9SKyle Evans 			&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err);
1453*f0865ec9SKyle Evans 	}
1454*f0865ec9SKyle Evans #endif
1455*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1456*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1457*f0865ec9SKyle Evans 		ret = dom4(1, ctx->adata, ctx->adata_len, h,
1458*f0865ec9SKyle Evans 			&(ctx->sign_data.eddsa.h_ctx)); EG(ret, err);
1459*f0865ec9SKyle Evans 	}
1460*f0865ec9SKyle Evans #endif
1461*f0865ec9SKyle Evans 	/* Update the hash with the encoded R point */
1462*f0865ec9SKyle Evans 	ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), &sig[0], r_len); EG(ret, err);
1463*f0865ec9SKyle Evans 	/* Encode the public key */
1464*f0865ec9SKyle Evans 	/* Transfer the public key to Edwards */
1465*f0865ec9SKyle Evans 	ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards,
1466*f0865ec9SKyle Evans 					&Tmp_edwards, alpha_edwards); EG(ret, err);
1467*f0865ec9SKyle Evans 	dbg_ec_edwards_point_print("A", &Tmp_edwards);
1468*f0865ec9SKyle Evans 	MUST_HAVE(r_len <= sizeof(hash), ret, err);
1469*f0865ec9SKyle Evans 
1470*f0865ec9SKyle Evans 	/* NOTE: we use the hash buffer as a temporary buffer */
1471*f0865ec9SKyle Evans 	ret = eddsa_encode_point(&Tmp_edwards, alpha_edwards, hash,
1472*f0865ec9SKyle Evans 			      r_len, key_type); EG(ret, err);
1473*f0865ec9SKyle Evans 
1474*f0865ec9SKyle Evans 	/* Update the hash with the encoded public key point */
1475*f0865ec9SKyle Evans 	ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), hash, r_len); EG(ret, err);
1476*f0865ec9SKyle Evans 	/* Update the hash with PH(m) */
1477*f0865ec9SKyle Evans 	ret = h->hfunc_update(&(ctx->sign_data.eddsa.h_ctx), ph_hash,
1478*f0865ec9SKyle Evans 			use_message_pre_hash_hsize); EG(ret, err);
1479*f0865ec9SKyle Evans 	/* Finalize the hash */
1480*f0865ec9SKyle Evans 	ret = h->hfunc_finalize(&(ctx->sign_data.eddsa.h_ctx), hash); EG(ret, err);
1481*f0865ec9SKyle Evans 	dbg_buf_print("h(R || PubKey || PH(m))", hash, hsize);
1482*f0865ec9SKyle Evans 	/* Import our resulting hash as an integer in S */
1483*f0865ec9SKyle Evans 	ret = eddsa_decode_integer(&S, hash, hsize); EG(ret, err);
1484*f0865ec9SKyle Evans 	ret = nn_mod(&S, &S, q); EG(ret, err);
1485*f0865ec9SKyle Evans 	/* Extract the digest */
1486*f0865ec9SKyle Evans 	hsize = sizeof(hash);
1487*f0865ec9SKyle Evans 	ret = eddsa_get_digest_from_priv_key(hash, &hsize, priv_key); EG(ret, err);
1488*f0865ec9SKyle Evans 	/* Encode the scalar s from the digest */
1489*f0865ec9SKyle Evans 	ret = eddsa_compute_s(&s, hash, hsize); EG(ret, err);
1490*f0865ec9SKyle Evans 	ret = nn_mod(&s, &s, q); EG(ret, err);
1491*f0865ec9SKyle Evans 
1492*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1493*f0865ec9SKyle Evans 	/* If we use blinding, multiply by b */
1494*f0865ec9SKyle Evans 	ret = nn_mod_mul(&S, &S, &b, q); EG(ret, err);
1495*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1496*f0865ec9SKyle Evans 	/* Multiply by the secret */
1497*f0865ec9SKyle Evans 	ret = nn_mod_mul(&S, &S, &s, q); EG(ret, err);
1498*f0865ec9SKyle Evans 	/* The secret is not needed anymore */
1499*f0865ec9SKyle Evans 	nn_uninit(&s);
1500*f0865ec9SKyle Evans 	/* Add to r */
1501*f0865ec9SKyle Evans 	ret = nn_mod_add(&S, &S, &r, q); EG(ret, err);
1502*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1503*f0865ec9SKyle Evans 	/* Unblind the result */
1504*f0865ec9SKyle Evans 	ret = nn_mod_mul(&S, &S, &binv, q); EG(ret, err);
1505*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1506*f0865ec9SKyle Evans 	/* Store our S in the context as an encoded buffer */
1507*f0865ec9SKyle Evans 	MUST_HAVE((s_len <= (siglen - r_len)), ret, err);
1508*f0865ec9SKyle Evans 	ret = eddsa_encode_integer(&S, &sig[r_len], s_len);
1509*f0865ec9SKyle Evans 
1510*f0865ec9SKyle Evans  err:
1511*f0865ec9SKyle Evans 	/* Clean what remains on the stack */
1512*f0865ec9SKyle Evans 	PTR_NULLIFY(h);
1513*f0865ec9SKyle Evans 	PTR_NULLIFY(priv_key);
1514*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key);
1515*f0865ec9SKyle Evans 	PTR_NULLIFY(G);
1516*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
1517*f0865ec9SKyle Evans 	PTR_NULLIFY(shortw_curve);
1518*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_montgomery);
1519*f0865ec9SKyle Evans 	PTR_NULLIFY(gamma_montgomery);
1520*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_edwards);
1521*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key_y);
1522*f0865ec9SKyle Evans 	VAR_ZEROIFY(hsize);
1523*f0865ec9SKyle Evans 	VAR_ZEROIFY(hash_size);
1524*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash);
1525*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash_hsize);
1526*f0865ec9SKyle Evans 	VAR_ZEROIFY(r_len);
1527*f0865ec9SKyle Evans 	VAR_ZEROIFY(s_len);
1528*f0865ec9SKyle Evans 
1529*f0865ec9SKyle Evans 	prj_pt_uninit(&R);
1530*f0865ec9SKyle Evans 	ec_edwards_crv_uninit(&crv_edwards);
1531*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&Tmp_edwards);
1532*f0865ec9SKyle Evans 	nn_uninit(&s);
1533*f0865ec9SKyle Evans 	nn_uninit(&r);
1534*f0865ec9SKyle Evans 	nn_uninit(&S);
1535*f0865ec9SKyle Evans 
1536*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1537*f0865ec9SKyle Evans 	nn_uninit(&b);
1538*f0865ec9SKyle Evans 	nn_uninit(&binv);
1539*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1540*f0865ec9SKyle Evans 
1541*f0865ec9SKyle Evans 	/*
1542*f0865ec9SKyle Evans 	 * We can now clear data part of the context. This will clear
1543*f0865ec9SKyle Evans 	 * magic and avoid further reuse of the whole context.
1544*f0865ec9SKyle Evans 	 */
1545*f0865ec9SKyle Evans 	if(ctx != NULL){
1546*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset(&(ctx->sign_data.eddsa), 0, sizeof(eddsa_sign_data)));
1547*f0865ec9SKyle Evans 	}
1548*f0865ec9SKyle Evans 	IGNORE_RET_VAL(local_memset(ph_hash, 0, sizeof(ph_hash)));
1549*f0865ec9SKyle Evans 
1550*f0865ec9SKyle Evans 	return ret;
1551*f0865ec9SKyle Evans }
1552*f0865ec9SKyle Evans 
1553*f0865ec9SKyle Evans 
1554*f0865ec9SKyle Evans /******** Signature function specific to pure EdDSA where the message
1555*f0865ec9SKyle Evans ********* streaming mode via init/update/finalize is not supported.
1556*f0865ec9SKyle Evans  */
1557*f0865ec9SKyle Evans int _eddsa_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair,
1558*f0865ec9SKyle Evans 		const u8 *m, u32 mlen, int (*rand) (nn_t out, nn_src_t q),
1559*f0865ec9SKyle Evans 		ec_alg_type sig_type, hash_alg_type hash_type,
1560*f0865ec9SKyle Evans 		const u8 *adata, u16 adata_len)
1561*f0865ec9SKyle Evans {
1562*f0865ec9SKyle Evans 	int ret;
1563*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
1564*f0865ec9SKyle Evans 	ec_shortw_crv_src_t shortw_curve;
1565*f0865ec9SKyle Evans 	fp_src_t alpha_montgomery;
1566*f0865ec9SKyle Evans 	fp_src_t gamma_montgomery;
1567*f0865ec9SKyle Evans 	fp_src_t alpha_edwards;
1568*f0865ec9SKyle Evans 	prj_pt_src_t pub_key_y;
1569*f0865ec9SKyle Evans 	u8 use_message_pre_hash = 0;
1570*f0865ec9SKyle Evans 	u16 use_message_pre_hash_hsize = 0;
1571*f0865ec9SKyle Evans 	prj_pt_src_t G;
1572*f0865ec9SKyle Evans 	prj_pt R;
1573*f0865ec9SKyle Evans 	aff_pt_edwards Tmp_edwards;
1574*f0865ec9SKyle Evans 	ec_edwards_crv crv_edwards;
1575*f0865ec9SKyle Evans 	u8 hash[MAX_DIGEST_SIZE];
1576*f0865ec9SKyle Evans 	u8 ph_hash[MAX_DIGEST_SIZE];
1577*f0865ec9SKyle Evans 	const ec_priv_key *priv_key;
1578*f0865ec9SKyle Evans 	const ec_pub_key *pub_key;
1579*f0865ec9SKyle Evans 	nn_src_t q;
1580*f0865ec9SKyle Evans 	u8 hsize, hash_size;
1581*f0865ec9SKyle Evans 	hash_context h_ctx;
1582*f0865ec9SKyle Evans 	u8 r_len, s_len;
1583*f0865ec9SKyle Evans 	bitcnt_t blen;
1584*f0865ec9SKyle Evans 	const hash_mapping *h;
1585*f0865ec9SKyle Evans 
1586*f0865ec9SKyle Evans 	nn r, s, S;
1587*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1588*f0865ec9SKyle Evans 	/* b is the blinding mask */
1589*f0865ec9SKyle Evans 	nn b, binv;
1590*f0865ec9SKyle Evans 	b.magic = binv.magic = WORD(0);
1591*f0865ec9SKyle Evans #endif
1592*f0865ec9SKyle Evans 
1593*f0865ec9SKyle Evans 	r.magic = s.magic = S.magic = WORD(0);
1594*f0865ec9SKyle Evans 	R.magic = Tmp_edwards.magic = crv_edwards.magic = WORD(0);
1595*f0865ec9SKyle Evans 
1596*f0865ec9SKyle Evans 	/*
1597*f0865ec9SKyle Evans 	 * NOTE: EdDSA does not use any notion of random Nonce, so no need
1598*f0865ec9SKyle Evans 	 * to use 'rand' here: we strictly check that NULL is provided.
1599*f0865ec9SKyle Evans 	 */
1600*f0865ec9SKyle Evans 	MUST_HAVE((rand == NULL), ret, err);
1601*f0865ec9SKyle Evans 
1602*f0865ec9SKyle Evans 	/* Zero init out points and data */
1603*f0865ec9SKyle Evans 	ret = local_memset(&R, 0, sizeof(prj_pt)); EG(ret, err);
1604*f0865ec9SKyle Evans 	ret = local_memset(&Tmp_edwards, 0, sizeof(aff_pt_edwards)); EG(ret, err);
1605*f0865ec9SKyle Evans 	ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err);
1606*f0865ec9SKyle Evans 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
1607*f0865ec9SKyle Evans 	ret = local_memset(ph_hash, 0, sizeof(ph_hash)); EG(ret, err);
1608*f0865ec9SKyle Evans 
1609*f0865ec9SKyle Evans 	/* Sanity check on the key pair */
1610*f0865ec9SKyle Evans 	ret = eddsa_key_pair_sanity_check(key_pair); EG(ret, err);
1611*f0865ec9SKyle Evans 
1612*f0865ec9SKyle Evans 	/* Make things more readable */
1613*f0865ec9SKyle Evans 	ret = get_hash_by_type(hash_type, &h); EG(ret, err);
1614*f0865ec9SKyle Evans 	key_type = key_pair->priv_key.key_type;
1615*f0865ec9SKyle Evans 
1616*f0865ec9SKyle Evans 	/* Sanity check on the hash type */
1617*f0865ec9SKyle Evans 	MUST_HAVE((h != NULL), ret, err);
1618*f0865ec9SKyle Evans 	MUST_HAVE((get_eddsa_hash_type(sig_type) == hash_type), ret, err);
1619*f0865ec9SKyle Evans 	/* Sanity check on the key type */
1620*f0865ec9SKyle Evans 	MUST_HAVE(key_type == sig_type, ret, err);
1621*f0865ec9SKyle Evans 	MUST_HAVE((h != NULL) && (h->digest_size <= MAX_DIGEST_SIZE) && (h->block_size <= MAX_BLOCK_SIZE), ret, err);
1622*f0865ec9SKyle Evans 	/*
1623*f0865ec9SKyle Evans 	 * Sanity check on hash size versus private key size
1624*f0865ec9SKyle Evans 	 */
1625*f0865ec9SKyle Evans 	ret = nn_bitlen(&(key_pair->priv_key.x), &blen); EG(ret, err);
1626*f0865ec9SKyle Evans 	MUST_HAVE((blen <= (8 * h->digest_size)), ret, err);
1627*f0865ec9SKyle Evans 
1628*f0865ec9SKyle Evans 	/* Make things more readable */
1629*f0865ec9SKyle Evans 	priv_key = &(key_pair->priv_key);
1630*f0865ec9SKyle Evans 	pub_key = &(key_pair->pub_key);
1631*f0865ec9SKyle Evans 	q = &(priv_key->params->ec_gen_order);
1632*f0865ec9SKyle Evans 	G = &(priv_key->params->ec_gen);
1633*f0865ec9SKyle Evans 	hsize = h->digest_size;
1634*f0865ec9SKyle Evans 	r_len = EDDSA_R_LEN(hsize);
1635*f0865ec9SKyle Evans 	s_len = EDDSA_S_LEN(hsize);
1636*f0865ec9SKyle Evans 
1637*f0865ec9SKyle Evans 	shortw_curve = &(priv_key->params->ec_curve);
1638*f0865ec9SKyle Evans 	alpha_montgomery = &(priv_key->params->ec_alpha_montgomery);
1639*f0865ec9SKyle Evans 	gamma_montgomery = &(priv_key->params->ec_gamma_montgomery);
1640*f0865ec9SKyle Evans 	alpha_edwards = &(priv_key->params->ec_alpha_edwards);
1641*f0865ec9SKyle Evans 	pub_key_y = &(pub_key->y);
1642*f0865ec9SKyle Evans 
1643*f0865ec9SKyle Evans 	dbg_nn_print("p", &(priv_key->params->ec_fp.p));
1644*f0865ec9SKyle Evans 	dbg_nn_print("q", &(priv_key->params->ec_gen_order));
1645*f0865ec9SKyle Evans 	dbg_priv_key_print("x", priv_key);
1646*f0865ec9SKyle Evans 	dbg_ec_point_print("G", &(priv_key->params->ec_gen));
1647*f0865ec9SKyle Evans 	dbg_pub_key_print("Y", pub_key);
1648*f0865ec9SKyle Evans 
1649*f0865ec9SKyle Evans 	/* Check provided signature length */
1650*f0865ec9SKyle Evans 	MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)) && (siglen == (r_len + s_len)), ret, err);
1651*f0865ec9SKyle Evans 
1652*f0865ec9SKyle Evans 	/* Do we use the raw message or its PH(M) hashed version? */
1653*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1654*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1655*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
1656*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = hsize;
1657*f0865ec9SKyle Evans 	}
1658*f0865ec9SKyle Evans #endif
1659*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1660*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1661*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
1662*f0865ec9SKyle Evans 		/* NOTE: as per RFC8032, EDDSA448PH uses
1663*f0865ec9SKyle Evans 		 * SHAKE256 with 64 bytes output.
1664*f0865ec9SKyle Evans 		 */
1665*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = 64;
1666*f0865ec9SKyle Evans 	}
1667*f0865ec9SKyle Evans #endif
1668*f0865ec9SKyle Evans 	/* First of all, compute the message hash if necessary */
1669*f0865ec9SKyle Evans 	if(use_message_pre_hash){
1670*f0865ec9SKyle Evans 		hash_size = sizeof(ph_hash);
1671*f0865ec9SKyle Evans 		ret = eddsa_compute_pre_hash(m, mlen, ph_hash, &hash_size, sig_type); EG(ret, err);
1672*f0865ec9SKyle Evans 		MUST_HAVE(use_message_pre_hash_hsize <= hash_size, ret, err);
1673*f0865ec9SKyle Evans 	}
1674*f0865ec9SKyle Evans 	/* Initialize our hash context */
1675*f0865ec9SKyle Evans 	/* Compute half of the secret key */
1676*f0865ec9SKyle Evans 	hash_size = sizeof(hash);
1677*f0865ec9SKyle Evans 	ret = eddsa_get_digest_from_priv_key(hash, &hash_size, &(key_pair->priv_key)); EG(ret, err);
1678*f0865ec9SKyle Evans 	/* Sanity check */
1679*f0865ec9SKyle Evans 	MUST_HAVE((hash_size == hsize), ret, err);
1680*f0865ec9SKyle Evans 	/* Since we call a callback, sanity check our mapping */
1681*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
1682*f0865ec9SKyle Evans 	ret = h->hfunc_init(&h_ctx); EG(ret, err);
1683*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1684*f0865ec9SKyle Evans 	if(key_type == EDDSA25519CTX){
1685*f0865ec9SKyle Evans 		/* As per RFC8032, for EDDSA25519CTX the context SHOULD NOT be empty */
1686*f0865ec9SKyle Evans 		MUST_HAVE(adata != NULL, ret, err);
1687*f0865ec9SKyle Evans 		ret = dom2(0, adata, adata_len, h, &h_ctx); EG(ret, err);
1688*f0865ec9SKyle Evans 	}
1689*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1690*f0865ec9SKyle Evans 		ret = dom2(1, adata, adata_len, h, &h_ctx); EG(ret, err);
1691*f0865ec9SKyle Evans 	}
1692*f0865ec9SKyle Evans #endif
1693*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1694*f0865ec9SKyle Evans 	if(key_type == EDDSA448){
1695*f0865ec9SKyle Evans 		ret = dom4(0, adata, adata_len, h, &h_ctx); EG(ret, err);
1696*f0865ec9SKyle Evans 	}
1697*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1698*f0865ec9SKyle Evans 		ret = dom4(1, adata, adata_len, h, &h_ctx); EG(ret, err);
1699*f0865ec9SKyle Evans 	}
1700*f0865ec9SKyle Evans #endif
1701*f0865ec9SKyle Evans 	ret = h->hfunc_update(&h_ctx, &hash[hsize / 2], hsize / 2); EG(ret, err);
1702*f0865ec9SKyle Evans 
1703*f0865ec9SKyle Evans 	/* Now finish computing the scalar r */
1704*f0865ec9SKyle Evans 	if(use_message_pre_hash){
1705*f0865ec9SKyle Evans 		ret = h->hfunc_update(&h_ctx, ph_hash, use_message_pre_hash_hsize); EG(ret, err);
1706*f0865ec9SKyle Evans 	}
1707*f0865ec9SKyle Evans 	else{
1708*f0865ec9SKyle Evans 		ret = h->hfunc_update(&h_ctx, m, mlen); EG(ret, err);
1709*f0865ec9SKyle Evans 	}
1710*f0865ec9SKyle Evans 	ret = h->hfunc_finalize(&h_ctx, hash); EG(ret, err);
1711*f0865ec9SKyle Evans 	dbg_buf_print("h(h || PH(m))", hash, hsize);
1712*f0865ec9SKyle Evans 
1713*f0865ec9SKyle Evans 	/* Import r as the hash scalar */
1714*f0865ec9SKyle Evans 	ret = eddsa_decode_integer(&r, hash, hsize); EG(ret, err);
1715*f0865ec9SKyle Evans 
1716*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1717*f0865ec9SKyle Evans 	/* Get a random b for blinding the r modular operations before the
1718*f0865ec9SKyle Evans 	 * scalar multiplication as we do not want it to leak.
1719*f0865ec9SKyle Evans 	 */
1720*f0865ec9SKyle Evans 	ret = nn_get_random_mod(&b, q); EG(ret, err);
1721*f0865ec9SKyle Evans 	dbg_nn_print("b", &b);
1722*f0865ec9SKyle Evans 	/* NOTE: we use Fermat's little theorem inversion for
1723*f0865ec9SKyle Evans 	 * constant time here. This is possible since q is prime.
1724*f0865ec9SKyle Evans 	 */
1725*f0865ec9SKyle Evans 	ret = nn_modinv_fermat(&binv, &b, q); EG(ret, err);
1726*f0865ec9SKyle Evans 
1727*f0865ec9SKyle Evans 	/* Blind r */
1728*f0865ec9SKyle Evans 	ret = nn_mul(&r, &r, &b); EG(ret, err);
1729*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1730*f0865ec9SKyle Evans 
1731*f0865ec9SKyle Evans 	/* Reduce r modulo q for the next computation.
1732*f0865ec9SKyle Evans 	 * (this is a blind reduction if USE_SIG_BLINDING).
1733*f0865ec9SKyle Evans 	 */
1734*f0865ec9SKyle Evans 	ret = nn_mod_notrim(&r, &r, q); EG(ret, err);
1735*f0865ec9SKyle Evans 
1736*f0865ec9SKyle Evans 	/* Now perform our scalar multiplication.
1737*f0865ec9SKyle Evans 	 */
1738*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1739*f0865ec9SKyle Evans 	if((key_type == EDDSA448) || (key_type == EDDSA448PH)){
1740*f0865ec9SKyle Evans 		/*
1741*f0865ec9SKyle Evans 		 * NOTE: in case of EDDSA448, because of the 4-isogeny we must
1742*f0865ec9SKyle Evans 		 * divide our scalar by 4.
1743*f0865ec9SKyle Evans 		 */
1744*f0865ec9SKyle Evans 		nn r_tmp;
1745*f0865ec9SKyle Evans 		r_tmp.magic = WORD(0);
1746*f0865ec9SKyle Evans 
1747*f0865ec9SKyle Evans 		ret = nn_init(&r_tmp, 0); EG(ret, err1);
1748*f0865ec9SKyle Evans 		ret = nn_modinv_word(&r_tmp, WORD(4), q); EG(ret, err1);
1749*f0865ec9SKyle Evans 		ret = nn_mod_mul(&r_tmp, &r_tmp, &r, q); EG(ret, err1);
1750*f0865ec9SKyle Evans 
1751*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1752*f0865ec9SKyle Evans 		/* Unblind r_tmp */
1753*f0865ec9SKyle Evans 		ret = nn_mod_mul(&r_tmp, &r_tmp, &binv, q); EG(ret, err1);
1754*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&R, &r_tmp, G);
1755*f0865ec9SKyle Evans #else
1756*f0865ec9SKyle Evans 		ret = prj_pt_mul(&R, &r_tmp, G);
1757*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1758*f0865ec9SKyle Evans err1:
1759*f0865ec9SKyle Evans 		nn_uninit(&r_tmp);
1760*f0865ec9SKyle Evans 		EG(ret, err);
1761*f0865ec9SKyle Evans 	}
1762*f0865ec9SKyle Evans 	else
1763*f0865ec9SKyle Evans #endif /* !defined(WITH_SIG_EDDSA448) */
1764*f0865ec9SKyle Evans 	{
1765*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1766*f0865ec9SKyle Evans 		nn r_tmp;
1767*f0865ec9SKyle Evans 		r_tmp.magic = WORD(0);
1768*f0865ec9SKyle Evans 
1769*f0865ec9SKyle Evans 		ret = nn_init(&r_tmp, 0); EG(ret, err2);
1770*f0865ec9SKyle Evans 		ret = nn_copy(&r_tmp, &r); EG(ret, err2);
1771*f0865ec9SKyle Evans 
1772*f0865ec9SKyle Evans 		/* Unblind r_tmp */
1773*f0865ec9SKyle Evans 		ret = nn_mod_mul(&r_tmp, &r_tmp, &binv, q); EG(ret, err2);
1774*f0865ec9SKyle Evans 		ret = prj_pt_mul_blind(&R, &r_tmp, G); EG(ret, err2);
1775*f0865ec9SKyle Evans err2:
1776*f0865ec9SKyle Evans 		nn_uninit(&r_tmp);
1777*f0865ec9SKyle Evans 		EG(ret, err);
1778*f0865ec9SKyle Evans #else
1779*f0865ec9SKyle Evans 		ret = prj_pt_mul(&R, &r, G); EG(ret, err);
1780*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1781*f0865ec9SKyle Evans 	}
1782*f0865ec9SKyle Evans 
1783*f0865ec9SKyle Evans 	/* Now compute S = (r + H(R || PubKey || PH(m)) * secret) mod q */
1784*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(h); EG(ret, err);
1785*f0865ec9SKyle Evans 	ret = h->hfunc_init(&h_ctx); EG(ret, err);
1786*f0865ec9SKyle Evans 	/* Transfer R to Edwards */
1787*f0865ec9SKyle Evans 	ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery,
1788*f0865ec9SKyle Evans 				gamma_montgomery, alpha_edwards); EG(ret, err);
1789*f0865ec9SKyle Evans 	ret = prj_pt_shortw_to_aff_pt_edwards(&R, &crv_edwards, &Tmp_edwards,
1790*f0865ec9SKyle Evans 					alpha_edwards); EG(ret, err);
1791*f0865ec9SKyle Evans 	dbg_ec_edwards_point_print("R", &Tmp_edwards);
1792*f0865ec9SKyle Evans 	MUST_HAVE((r_len <= siglen), ret, err);
1793*f0865ec9SKyle Evans 	/* Encode R and update */
1794*f0865ec9SKyle Evans 	ret = eddsa_encode_point(&Tmp_edwards, alpha_edwards, &sig[0],
1795*f0865ec9SKyle Evans 			      r_len, key_type); EG(ret, err);
1796*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1797*f0865ec9SKyle Evans 	if(key_type == EDDSA25519CTX){
1798*f0865ec9SKyle Evans 		/*
1799*f0865ec9SKyle Evans 		 * As per RFC8032, for EDDSA25519CTX the context
1800*f0865ec9SKyle Evans 		 * SHOULD NOT be empty
1801*f0865ec9SKyle Evans 		 */
1802*f0865ec9SKyle Evans 		MUST_HAVE((adata != NULL), ret, err);
1803*f0865ec9SKyle Evans 		ret = dom2(0, adata, adata_len, h, &h_ctx); EG(ret, err);
1804*f0865ec9SKyle Evans 	}
1805*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1806*f0865ec9SKyle Evans 		ret = dom2(1, adata, adata_len, h, &h_ctx); EG(ret, err);
1807*f0865ec9SKyle Evans 	}
1808*f0865ec9SKyle Evans #endif
1809*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1810*f0865ec9SKyle Evans 	if(key_type == EDDSA448){
1811*f0865ec9SKyle Evans 		ret = dom4(0, adata, adata_len, h, &h_ctx); EG(ret, err);
1812*f0865ec9SKyle Evans 	}
1813*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1814*f0865ec9SKyle Evans 		ret = dom4(1, adata, adata_len, h, &h_ctx); EG(ret, err);
1815*f0865ec9SKyle Evans 	}
1816*f0865ec9SKyle Evans #endif
1817*f0865ec9SKyle Evans 	/* Update the hash with the encoded R point */
1818*f0865ec9SKyle Evans 	ret = h->hfunc_update(&h_ctx, &sig[0], r_len); EG(ret, err);
1819*f0865ec9SKyle Evans 	/* Transfer the public key to Edwards */
1820*f0865ec9SKyle Evans 	ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, &Tmp_edwards,
1821*f0865ec9SKyle Evans 					alpha_edwards); EG(ret, err);
1822*f0865ec9SKyle Evans 	dbg_ec_edwards_point_print("A", &Tmp_edwards);
1823*f0865ec9SKyle Evans 	MUST_HAVE((r_len <= sizeof(hash)), ret, err);
1824*f0865ec9SKyle Evans 	/* Encode the public key */
1825*f0865ec9SKyle Evans 	/* NOTE: we use the hash buffer as a temporary buffer */
1826*f0865ec9SKyle Evans 	ret = eddsa_encode_point(&Tmp_edwards, alpha_edwards,
1827*f0865ec9SKyle Evans 			      hash, r_len, key_type); EG(ret, err);
1828*f0865ec9SKyle Evans 	/* Update the hash with the encoded public key point */
1829*f0865ec9SKyle Evans 	ret = h->hfunc_update(&h_ctx, hash, r_len); EG(ret, err);
1830*f0865ec9SKyle Evans 	/* Update the hash with the message or its hash for the PH versions */
1831*f0865ec9SKyle Evans 	if(use_message_pre_hash){
1832*f0865ec9SKyle Evans 		ret = h->hfunc_update(&h_ctx, ph_hash, use_message_pre_hash_hsize); EG(ret, err);
1833*f0865ec9SKyle Evans 	}
1834*f0865ec9SKyle Evans 	else{
1835*f0865ec9SKyle Evans 		ret = h->hfunc_update(&h_ctx, m, mlen); EG(ret, err);
1836*f0865ec9SKyle Evans 	}
1837*f0865ec9SKyle Evans 	/* Finalize the hash */
1838*f0865ec9SKyle Evans 	ret = h->hfunc_finalize(&h_ctx, hash); EG(ret, err);
1839*f0865ec9SKyle Evans 	dbg_buf_print("h(R || PubKey || PH(m))", hash, hsize);
1840*f0865ec9SKyle Evans 	/* Import our resulting hash as an integer in S */
1841*f0865ec9SKyle Evans 	ret = eddsa_decode_integer(&S, hash, hsize); EG(ret, err);
1842*f0865ec9SKyle Evans 	ret = nn_mod(&S, &S, q); EG(ret, err);
1843*f0865ec9SKyle Evans 	/* Extract the digest */
1844*f0865ec9SKyle Evans 	hsize = sizeof(hash);
1845*f0865ec9SKyle Evans 	ret = eddsa_get_digest_from_priv_key(hash, &hsize, priv_key); EG(ret, err);
1846*f0865ec9SKyle Evans 	ret = eddsa_compute_s(&s, hash, hsize); EG(ret, err);
1847*f0865ec9SKyle Evans 	ret = nn_mod(&s, &s, q); EG(ret, err);
1848*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1849*f0865ec9SKyle Evans 	/* If we use blinding, multiply by b */
1850*f0865ec9SKyle Evans 	ret = nn_mod_mul(&S, &S, &b, q); EG(ret, err);
1851*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1852*f0865ec9SKyle Evans 	/* Multiply by the secret */
1853*f0865ec9SKyle Evans 	ret = nn_mod_mul(&S, &S, &s, q); EG(ret, err);
1854*f0865ec9SKyle Evans 	/* The secret is not needed anymore */
1855*f0865ec9SKyle Evans 	nn_uninit(&s);
1856*f0865ec9SKyle Evans 	/* Add to r */
1857*f0865ec9SKyle Evans 	ret = nn_mod_add(&S, &S, &r, q); EG(ret, err);
1858*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1859*f0865ec9SKyle Evans 	/* Unblind the result */
1860*f0865ec9SKyle Evans 	ret = nn_mod_mul(&S, &S, &binv, q); EG(ret, err);
1861*f0865ec9SKyle Evans #endif /* !USE_SIG_BLINDING */
1862*f0865ec9SKyle Evans 	/* Store our S in the context as an encoded buffer */
1863*f0865ec9SKyle Evans 	MUST_HAVE((s_len <= (siglen - r_len)), ret, err);
1864*f0865ec9SKyle Evans 	/* Encode the scalar s from the digest */
1865*f0865ec9SKyle Evans 	ret = eddsa_encode_integer(&S, &sig[r_len], s_len);
1866*f0865ec9SKyle Evans 
1867*f0865ec9SKyle Evans err:
1868*f0865ec9SKyle Evans 	/* Clean what remains on the stack */
1869*f0865ec9SKyle Evans 	PTR_NULLIFY(priv_key);
1870*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key);
1871*f0865ec9SKyle Evans 	PTR_NULLIFY(G);
1872*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
1873*f0865ec9SKyle Evans 	PTR_NULLIFY(shortw_curve);
1874*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_montgomery);
1875*f0865ec9SKyle Evans 	PTR_NULLIFY(gamma_montgomery);
1876*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_edwards);
1877*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key_y);
1878*f0865ec9SKyle Evans 	PTR_NULLIFY(h);
1879*f0865ec9SKyle Evans 	VAR_ZEROIFY(hsize);
1880*f0865ec9SKyle Evans 	VAR_ZEROIFY(hash_size);
1881*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash);
1882*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash_hsize);
1883*f0865ec9SKyle Evans 	VAR_ZEROIFY(r_len);
1884*f0865ec9SKyle Evans 	VAR_ZEROIFY(s_len);
1885*f0865ec9SKyle Evans 	VAR_ZEROIFY(blen);
1886*f0865ec9SKyle Evans 	IGNORE_RET_VAL(local_memset(&h_ctx, 0, sizeof(h_ctx)));
1887*f0865ec9SKyle Evans 	IGNORE_RET_VAL(local_memset(hash, 0, sizeof(hash)));
1888*f0865ec9SKyle Evans 	IGNORE_RET_VAL(local_memset(ph_hash, 0, sizeof(ph_hash)));
1889*f0865ec9SKyle Evans 
1890*f0865ec9SKyle Evans 	prj_pt_uninit(&R);
1891*f0865ec9SKyle Evans 	ec_edwards_crv_uninit(&crv_edwards);
1892*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&Tmp_edwards);
1893*f0865ec9SKyle Evans 	nn_uninit(&s);
1894*f0865ec9SKyle Evans 	nn_uninit(&r);
1895*f0865ec9SKyle Evans 	nn_uninit(&S);
1896*f0865ec9SKyle Evans 
1897*f0865ec9SKyle Evans #ifdef USE_SIG_BLINDING
1898*f0865ec9SKyle Evans 	nn_uninit(&b);
1899*f0865ec9SKyle Evans 	nn_uninit(&binv);
1900*f0865ec9SKyle Evans #endif /* USE_SIG_BLINDING */
1901*f0865ec9SKyle Evans 
1902*f0865ec9SKyle Evans 	return ret;
1903*f0865ec9SKyle Evans }
1904*f0865ec9SKyle Evans 
1905*f0865ec9SKyle Evans /******************************************************************************/
1906*f0865ec9SKyle Evans /*
1907*f0865ec9SKyle Evans  * Generic *internal* EDDSA verification functions (init, update and finalize).
1908*f0865ec9SKyle Evans  *
1909*f0865ec9SKyle Evans  */
1910*f0865ec9SKyle Evans 
1911*f0865ec9SKyle Evans #define EDDSA_VERIFY_MAGIC ((word_t)(0x3298fe87e77151beULL))
1912*f0865ec9SKyle Evans #define EDDSA_VERIFY_CHECK_INITIALIZED(A, ret, err) \
1913*f0865ec9SKyle Evans 	MUST_HAVE((((void *)(A)) != NULL) && ((A)->magic == EDDSA_VERIFY_MAGIC), ret, err)
1914*f0865ec9SKyle Evans 
1915*f0865ec9SKyle Evans int _eddsa_verify_init(struct ec_verify_context *ctx, const u8 *sig, u8 siglen)
1916*f0865ec9SKyle Evans {
1917*f0865ec9SKyle Evans 	nn_src_t q;
1918*f0865ec9SKyle Evans 	ec_edwards_crv crv_edwards;
1919*f0865ec9SKyle Evans 	aff_pt_edwards R;
1920*f0865ec9SKyle Evans 	prj_pt _Tmp;
1921*f0865ec9SKyle Evans 	prj_pt_t _R;
1922*f0865ec9SKyle Evans 	aff_pt_edwards A;
1923*f0865ec9SKyle Evans 	nn *S;
1924*f0865ec9SKyle Evans 	u8 buff[MAX_DIGEST_SIZE];
1925*f0865ec9SKyle Evans 	int ret, iszero, cmp;
1926*f0865ec9SKyle Evans 	u16 hsize;
1927*f0865ec9SKyle Evans 	const ec_pub_key *pub_key;
1928*f0865ec9SKyle Evans 	ec_shortw_crv_src_t shortw_curve;
1929*f0865ec9SKyle Evans 	fp_src_t alpha_montgomery;
1930*f0865ec9SKyle Evans 	fp_src_t gamma_montgomery;
1931*f0865ec9SKyle Evans 	fp_src_t alpha_edwards;
1932*f0865ec9SKyle Evans 	nn_src_t gen_cofactor;
1933*f0865ec9SKyle Evans 	prj_pt_src_t pub_key_y;
1934*f0865ec9SKyle Evans 	hash_context *h_ctx;
1935*f0865ec9SKyle Evans 	hash_context *h_ctx_pre_hash;
1936*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
1937*f0865ec9SKyle Evans 
1938*f0865ec9SKyle Evans 	R.magic = crv_edwards.magic = _Tmp.magic = A.magic = WORD(0);
1939*f0865ec9SKyle Evans 
1940*f0865ec9SKyle Evans 	/* First, verify context has been initialized */
1941*f0865ec9SKyle Evans 	ret = sig_verify_check_initialized(ctx); EG(ret, err);
1942*f0865ec9SKyle Evans 	MUST_HAVE((sig != NULL), ret, err);
1943*f0865ec9SKyle Evans 
1944*f0865ec9SKyle Evans 	/* Zero init our local data */
1945*f0865ec9SKyle Evans 	ret = local_memset(&A, 0, sizeof(aff_pt_edwards)); EG(ret, err);
1946*f0865ec9SKyle Evans 	ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err);
1947*f0865ec9SKyle Evans 	ret = local_memset(buff, 0, sizeof(buff)); EG(ret, err);
1948*f0865ec9SKyle Evans 	ret = local_memset(&R, 0, sizeof(R)); EG(ret, err);
1949*f0865ec9SKyle Evans 	ret = local_memset(&_Tmp, 0, sizeof(_Tmp)); EG(ret, err);
1950*f0865ec9SKyle Evans 
1951*f0865ec9SKyle Evans 	/* Do some sanity checks on input params */
1952*f0865ec9SKyle Evans 	ret = eddsa_pub_key_sanity_check(ctx->pub_key); EG(ret, err);
1953*f0865ec9SKyle Evans 	MUST_HAVE((ctx->h != NULL) && (ctx->h->digest_size <= MAX_DIGEST_SIZE) && (ctx->h->block_size <= MAX_BLOCK_SIZE), ret, err);
1954*f0865ec9SKyle Evans 
1955*f0865ec9SKyle Evans 	/* Make things more readable */
1956*f0865ec9SKyle Evans 	q = &(ctx->pub_key->params->ec_gen_order);
1957*f0865ec9SKyle Evans 	_R = &(ctx->verify_data.eddsa._R);
1958*f0865ec9SKyle Evans 	S = &(ctx->verify_data.eddsa.S);
1959*f0865ec9SKyle Evans 	hsize = ctx->h->digest_size;
1960*f0865ec9SKyle Evans 
1961*f0865ec9SKyle Evans 	pub_key = ctx->pub_key;
1962*f0865ec9SKyle Evans 	shortw_curve = &(pub_key->params->ec_curve);
1963*f0865ec9SKyle Evans 	alpha_montgomery = &(pub_key->params->ec_alpha_montgomery);
1964*f0865ec9SKyle Evans 	gamma_montgomery = &(pub_key->params->ec_gamma_montgomery);
1965*f0865ec9SKyle Evans 	alpha_edwards = &(pub_key->params->ec_alpha_edwards);
1966*f0865ec9SKyle Evans 	gen_cofactor = &(pub_key->params->ec_gen_cofactor);
1967*f0865ec9SKyle Evans 	pub_key_y = &(pub_key->y);
1968*f0865ec9SKyle Evans 	key_type = pub_key->key_type;
1969*f0865ec9SKyle Evans 	h_ctx = &(ctx->verify_data.eddsa.h_ctx);
1970*f0865ec9SKyle Evans 	h_ctx_pre_hash = &(ctx->verify_data.eddsa.h_ctx_pre_hash);
1971*f0865ec9SKyle Evans 
1972*f0865ec9SKyle Evans 	/* Sanity check on hash types */
1973*f0865ec9SKyle Evans 	MUST_HAVE((ctx->h->type == get_eddsa_hash_type(key_type)), ret, err);
1974*f0865ec9SKyle Evans 
1975*f0865ec9SKyle Evans 	/* Check given signature length is the expected one */
1976*f0865ec9SKyle Evans 	MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)), ret, err);
1977*f0865ec9SKyle Evans 	MUST_HAVE((siglen == (EDDSA_R_LEN(hsize) + EDDSA_S_LEN(hsize))), ret, err);
1978*f0865ec9SKyle Evans 
1979*f0865ec9SKyle Evans 	/* Initialize the hash context */
1980*f0865ec9SKyle Evans 	/* Since we call a callback, sanity check our mapping */
1981*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
1982*f0865ec9SKyle Evans 	ret = ctx->h->hfunc_init(h_ctx); EG(ret, err);
1983*f0865ec9SKyle Evans 	ret = ctx->h->hfunc_init(h_ctx_pre_hash); EG(ret, err);
1984*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
1985*f0865ec9SKyle Evans 	if(key_type == EDDSA25519CTX){
1986*f0865ec9SKyle Evans 		/* As per RFC8032, for EDDSA25519CTX the context SHOULD NOT be empty */
1987*f0865ec9SKyle Evans 		MUST_HAVE((ctx->adata != NULL), ret, err);
1988*f0865ec9SKyle Evans 		ret = dom2(0, ctx->adata, ctx->adata_len, ctx->h, h_ctx); EG(ret, err);
1989*f0865ec9SKyle Evans 	}
1990*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
1991*f0865ec9SKyle Evans 		ret = dom2(1, ctx->adata, ctx->adata_len, ctx->h, h_ctx); EG(ret, err);
1992*f0865ec9SKyle Evans 	}
1993*f0865ec9SKyle Evans #endif
1994*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
1995*f0865ec9SKyle Evans 	if(key_type == EDDSA448){
1996*f0865ec9SKyle Evans 		ret = dom4(0, ctx->adata, ctx->adata_len, ctx->h, h_ctx); EG(ret, err);
1997*f0865ec9SKyle Evans 	}
1998*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
1999*f0865ec9SKyle Evans 		ret = dom4(1, ctx->adata, ctx->adata_len, ctx->h, h_ctx); EG(ret, err);
2000*f0865ec9SKyle Evans 	}
2001*f0865ec9SKyle Evans #endif
2002*f0865ec9SKyle Evans 	/* Import R and S values from signature buffer */
2003*f0865ec9SKyle Evans 	/*******************************/
2004*f0865ec9SKyle Evans 	/* Import R as an Edwards point */
2005*f0865ec9SKyle Evans 	ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery,
2006*f0865ec9SKyle Evans 				gamma_montgomery, alpha_edwards); EG(ret, err);
2007*f0865ec9SKyle Evans 	/* NOTE: non canonical R are checked and rejected here */
2008*f0865ec9SKyle Evans 	ret = eddsa_decode_point(&R, &crv_edwards, alpha_edwards, &sig[0],
2009*f0865ec9SKyle Evans 			      EDDSA_R_LEN(hsize), key_type); EG(ret, err);
2010*f0865ec9SKyle Evans 	dbg_ec_edwards_point_print("R", &R);
2011*f0865ec9SKyle Evans 	/* Transfer our public point R to Weierstrass */
2012*f0865ec9SKyle Evans 	ret = aff_pt_edwards_to_prj_pt_shortw(&R, shortw_curve, _R, alpha_edwards); EG(ret, err);
2013*f0865ec9SKyle Evans 	/* Update the hash with the encoded R */
2014*f0865ec9SKyle Evans 	ret = ctx->h->hfunc_update(h_ctx, &sig[0], EDDSA_R_LEN(hsize)); EG(ret, err);
2015*f0865ec9SKyle Evans 
2016*f0865ec9SKyle Evans 	/*******************************/
2017*f0865ec9SKyle Evans 	/* Import S as an integer */
2018*f0865ec9SKyle Evans 	ret = eddsa_decode_integer(S, &sig[EDDSA_R_LEN(hsize)], EDDSA_S_LEN(hsize)); EG(ret, err);
2019*f0865ec9SKyle Evans 	/* Reject S if it is not reduced modulo q */
2020*f0865ec9SKyle Evans 	ret = nn_cmp(S, q, &cmp); EG(ret, err);
2021*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
2022*f0865ec9SKyle Evans 	dbg_nn_print("S", S);
2023*f0865ec9SKyle Evans 
2024*f0865ec9SKyle Evans 	/*******************************/
2025*f0865ec9SKyle Evans 	/* Encode the public key
2026*f0865ec9SKyle Evans 	 * NOTE: since we deal with a public key transfered to Weierstrass,
2027*f0865ec9SKyle Evans 	 * encoding checking has been handled elsewhere.
2028*f0865ec9SKyle Evans 	 */
2029*f0865ec9SKyle Evans 	/* Reject the signature if the public key is one of small order points.
2030*f0865ec9SKyle Evans 	 * We multiply by the cofactor: since this is a public verification,
2031*f0865ec9SKyle Evans 	 * we use a basic double and add algorithm.
2032*f0865ec9SKyle Evans 	 */
2033*f0865ec9SKyle Evans 	ret = _prj_pt_unprotected_mult(&_Tmp, gen_cofactor, pub_key_y); EG(ret, err);
2034*f0865ec9SKyle Evans 	/* Reject the signature if we have point at infinity here as this means
2035*f0865ec9SKyle Evans 	 * that the public key is of small order.
2036*f0865ec9SKyle Evans 	 */
2037*f0865ec9SKyle Evans 	ret = prj_pt_iszero(&_Tmp, &iszero); EG(ret, err);
2038*f0865ec9SKyle Evans 	MUST_HAVE((!iszero), ret, err);
2039*f0865ec9SKyle Evans 
2040*f0865ec9SKyle Evans 	/* Transfer the public key to Edwards */
2041*f0865ec9SKyle Evans 	ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, &A, alpha_edwards); EG(ret, err);
2042*f0865ec9SKyle Evans 	dbg_ec_edwards_point_print("A", &A);
2043*f0865ec9SKyle Evans 	MUST_HAVE((EDDSA_R_LEN(hsize) <= sizeof(buff)), ret, err);
2044*f0865ec9SKyle Evans 	/* NOTE: we use the hash buffer as a temporary buffer */
2045*f0865ec9SKyle Evans 	ret = eddsa_encode_point(&A, alpha_edwards, buff, EDDSA_R_LEN(hsize), key_type); EG(ret, err);
2046*f0865ec9SKyle Evans 
2047*f0865ec9SKyle Evans 	/* Update the hash with the encoded public key */
2048*f0865ec9SKyle Evans 	ret = ctx->h->hfunc_update(h_ctx, buff, EDDSA_R_LEN(hsize)); EG(ret, err);
2049*f0865ec9SKyle Evans 
2050*f0865ec9SKyle Evans 	/* Context magic set */
2051*f0865ec9SKyle Evans 	ctx->verify_data.eddsa.magic = EDDSA_VERIFY_MAGIC;
2052*f0865ec9SKyle Evans 
2053*f0865ec9SKyle Evans  err:
2054*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
2055*f0865ec9SKyle Evans 	PTR_NULLIFY(_R);
2056*f0865ec9SKyle Evans 	PTR_NULLIFY(S);
2057*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key);
2058*f0865ec9SKyle Evans 	PTR_NULLIFY(shortw_curve);
2059*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_montgomery);
2060*f0865ec9SKyle Evans 	PTR_NULLIFY(gamma_montgomery);
2061*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_edwards);
2062*f0865ec9SKyle Evans 	PTR_NULLIFY(gen_cofactor);
2063*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key_y);
2064*f0865ec9SKyle Evans 
2065*f0865ec9SKyle Evans 	ec_edwards_crv_uninit(&crv_edwards);
2066*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&A);
2067*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&R);
2068*f0865ec9SKyle Evans 	prj_pt_uninit(&_Tmp);
2069*f0865ec9SKyle Evans 
2070*f0865ec9SKyle Evans 	return ret;
2071*f0865ec9SKyle Evans }
2072*f0865ec9SKyle Evans 
2073*f0865ec9SKyle Evans int _eddsa_verify_update(struct ec_verify_context *ctx,
2074*f0865ec9SKyle Evans 			 const u8 *chunk, u32 chunklen)
2075*f0865ec9SKyle Evans {
2076*f0865ec9SKyle Evans 	int ret;
2077*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
2078*f0865ec9SKyle Evans 	u8 use_message_pre_hash = 0;
2079*f0865ec9SKyle Evans 	hash_context *h_ctx;
2080*f0865ec9SKyle Evans 	hash_context *h_ctx_pre_hash;
2081*f0865ec9SKyle Evans 
2082*f0865ec9SKyle Evans 	/*
2083*f0865ec9SKyle Evans 	 * First, verify context has been initialized and public
2084*f0865ec9SKyle Evans 	 * part too. This guarantees the context is an EDDSA
2085*f0865ec9SKyle Evans 	 * verification one and we do not update() or finalize()
2086*f0865ec9SKyle Evans 	 * before init().
2087*f0865ec9SKyle Evans 	 */
2088*f0865ec9SKyle Evans 	ret = sig_verify_check_initialized(ctx); EG(ret, err);
2089*f0865ec9SKyle Evans 	EDDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.eddsa), ret, err);
2090*f0865ec9SKyle Evans 
2091*f0865ec9SKyle Evans 	key_type = ctx->pub_key->key_type;
2092*f0865ec9SKyle Evans 	h_ctx = &(ctx->verify_data.eddsa.h_ctx);
2093*f0865ec9SKyle Evans 	h_ctx_pre_hash = &(ctx->verify_data.eddsa.h_ctx_pre_hash);
2094*f0865ec9SKyle Evans 
2095*f0865ec9SKyle Evans 	/* Sanity check on hash types */
2096*f0865ec9SKyle Evans 	MUST_HAVE(ctx->h->type == get_eddsa_hash_type(key_type), ret, err);
2097*f0865ec9SKyle Evans 
2098*f0865ec9SKyle Evans 	/* Do we use the raw message or its PH(M) hashed version? */
2099*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
2100*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
2101*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
2102*f0865ec9SKyle Evans 	}
2103*f0865ec9SKyle Evans #endif
2104*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2105*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
2106*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
2107*f0865ec9SKyle Evans 	}
2108*f0865ec9SKyle Evans #endif
2109*f0865ec9SKyle Evans 	/* 2. Compute h = H(m) */
2110*f0865ec9SKyle Evans 	/* Since we call a callback, sanity check our mapping */
2111*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
2112*f0865ec9SKyle Evans 	if(use_message_pre_hash == 1){
2113*f0865ec9SKyle Evans 		/* In PH mode, update the dedicated hash context */
2114*f0865ec9SKyle Evans 		ret = ctx->h->hfunc_update(h_ctx_pre_hash,
2115*f0865ec9SKyle Evans 				     chunk, chunklen); EG(ret, err);
2116*f0865ec9SKyle Evans 	}
2117*f0865ec9SKyle Evans 	else{
2118*f0865ec9SKyle Evans 		/* In normal mode, update the nominal hash context */
2119*f0865ec9SKyle Evans 		ret = ctx->h->hfunc_update(h_ctx, chunk, chunklen); EG(ret, err);
2120*f0865ec9SKyle Evans 	}
2121*f0865ec9SKyle Evans 
2122*f0865ec9SKyle Evans err:
2123*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash);
2124*f0865ec9SKyle Evans 
2125*f0865ec9SKyle Evans 	return ret;
2126*f0865ec9SKyle Evans }
2127*f0865ec9SKyle Evans 
2128*f0865ec9SKyle Evans int _eddsa_verify_finalize(struct ec_verify_context *ctx)
2129*f0865ec9SKyle Evans {
2130*f0865ec9SKyle Evans 	prj_pt_src_t G, _R, A;
2131*f0865ec9SKyle Evans 	prj_pt _Tmp1, _Tmp2;
2132*f0865ec9SKyle Evans 	nn_src_t q, S;
2133*f0865ec9SKyle Evans 	nn h;
2134*f0865ec9SKyle Evans 	u16 hsize;
2135*f0865ec9SKyle Evans 	u8 hash[MAX_DIGEST_SIZE];
2136*f0865ec9SKyle Evans 	nn_src_t gen_cofactor;
2137*f0865ec9SKyle Evans 	int ret, iszero, cmp;
2138*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
2139*f0865ec9SKyle Evans 	u8 use_message_pre_hash = 0;
2140*f0865ec9SKyle Evans 	u16 use_message_pre_hash_hsize = 0;
2141*f0865ec9SKyle Evans 	hash_context *h_ctx;
2142*f0865ec9SKyle Evans 	hash_context *h_ctx_pre_hash;
2143*f0865ec9SKyle Evans 
2144*f0865ec9SKyle Evans 	_Tmp1.magic = _Tmp2.magic = h.magic = WORD(0);
2145*f0865ec9SKyle Evans 
2146*f0865ec9SKyle Evans 	/*
2147*f0865ec9SKyle Evans 	 * First, verify context has been initialized and public
2148*f0865ec9SKyle Evans 	 * part too. This guarantees the context is an EDDSA
2149*f0865ec9SKyle Evans 	 * verification one and we do not finalize() before init().
2150*f0865ec9SKyle Evans 	 */
2151*f0865ec9SKyle Evans 	ret = sig_verify_check_initialized(ctx); EG(ret, err);
2152*f0865ec9SKyle Evans 	EDDSA_VERIFY_CHECK_INITIALIZED(&(ctx->verify_data.eddsa), ret, err);
2153*f0865ec9SKyle Evans 
2154*f0865ec9SKyle Evans 	/* Zero init points */
2155*f0865ec9SKyle Evans 	ret = local_memset(&_Tmp1, 0, sizeof(prj_pt)); EG(ret, err);
2156*f0865ec9SKyle Evans 	ret = local_memset(&_Tmp2, 0, sizeof(prj_pt)); EG(ret, err);
2157*f0865ec9SKyle Evans 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
2158*f0865ec9SKyle Evans 
2159*f0865ec9SKyle Evans 	/* Make things more readable */
2160*f0865ec9SKyle Evans 	G = &(ctx->pub_key->params->ec_gen);
2161*f0865ec9SKyle Evans 	A = &(ctx->pub_key->y);
2162*f0865ec9SKyle Evans 	q = &(ctx->pub_key->params->ec_gen_order);
2163*f0865ec9SKyle Evans 	hsize = ctx->h->digest_size;
2164*f0865ec9SKyle Evans 	S = &(ctx->verify_data.eddsa.S);
2165*f0865ec9SKyle Evans 	_R = &(ctx->verify_data.eddsa._R);
2166*f0865ec9SKyle Evans 	gen_cofactor = &(ctx->pub_key->params->ec_gen_cofactor);
2167*f0865ec9SKyle Evans 	key_type = ctx->pub_key->key_type;
2168*f0865ec9SKyle Evans 	h_ctx = &(ctx->verify_data.eddsa.h_ctx);
2169*f0865ec9SKyle Evans 	h_ctx_pre_hash = &(ctx->verify_data.eddsa.h_ctx_pre_hash);
2170*f0865ec9SKyle Evans 
2171*f0865ec9SKyle Evans 	/* Sanity check on hash types */
2172*f0865ec9SKyle Evans 	MUST_HAVE((ctx->h->type == get_eddsa_hash_type(key_type)), ret, err);
2173*f0865ec9SKyle Evans 
2174*f0865ec9SKyle Evans 	/* Do we use the raw message or its PH(M) hashed version? */
2175*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
2176*f0865ec9SKyle Evans 	if(key_type == EDDSA25519PH){
2177*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
2178*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = hsize;
2179*f0865ec9SKyle Evans 	}
2180*f0865ec9SKyle Evans #endif
2181*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2182*f0865ec9SKyle Evans 	if(key_type == EDDSA448PH){
2183*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
2184*f0865ec9SKyle Evans 		/* NOTE: as per RFC8032, EDDSA448PH uses
2185*f0865ec9SKyle Evans 		 * SHAKE256 with 64 bytes output.
2186*f0865ec9SKyle Evans 		 */
2187*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = 64;
2188*f0865ec9SKyle Evans 	}
2189*f0865ec9SKyle Evans #endif
2190*f0865ec9SKyle Evans 
2191*f0865ec9SKyle Evans 	/* Reject S if it is not reduced modulo q */
2192*f0865ec9SKyle Evans 	ret = nn_cmp(S, q, &cmp); EG(ret, err);
2193*f0865ec9SKyle Evans 	MUST_HAVE((cmp < 0), ret, err);
2194*f0865ec9SKyle Evans 
2195*f0865ec9SKyle Evans 	MUST_HAVE((hsize <= sizeof(hash)), ret, err);
2196*f0865ec9SKyle Evans 
2197*f0865ec9SKyle Evans 	/* 2. Finish our computation of h = H(R || A || M) */
2198*f0865ec9SKyle Evans 	/* Since we call a callback, sanity check our mapping */
2199*f0865ec9SKyle Evans 	ret = hash_mapping_callbacks_sanity_check(ctx->h); EG(ret, err);
2200*f0865ec9SKyle Evans 	/* Update the hash with the message or its hash for the PH versions */
2201*f0865ec9SKyle Evans 	if(use_message_pre_hash == 1){
2202*f0865ec9SKyle Evans 		ret = ctx->h->hfunc_finalize(h_ctx_pre_hash, hash); EG(ret, err);
2203*f0865ec9SKyle Evans 		MUST_HAVE((use_message_pre_hash_hsize <= hsize), ret, err);
2204*f0865ec9SKyle Evans 		ret = ctx->h->hfunc_update(h_ctx, hash, use_message_pre_hash_hsize); EG(ret, err);
2205*f0865ec9SKyle Evans 	}
2206*f0865ec9SKyle Evans 	ret = ctx->h->hfunc_finalize(h_ctx, hash); EG(ret, err);
2207*f0865ec9SKyle Evans 	dbg_buf_print("hash = H(R || A || PH(M))", hash, hsize);
2208*f0865ec9SKyle Evans 
2209*f0865ec9SKyle Evans 	/* 3. Import our hash as a NN and reduce it modulo q */
2210*f0865ec9SKyle Evans 	ret = eddsa_decode_integer(&h, hash, hsize); EG(ret, err);
2211*f0865ec9SKyle Evans 	ret = nn_mod(&h, &h, q); EG(ret, err);
2212*f0865ec9SKyle Evans 	dbg_nn_print("h = ", &h);
2213*f0865ec9SKyle Evans 
2214*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2215*f0865ec9SKyle Evans 	if((key_type == EDDSA448) || (key_type == EDDSA448PH)){
2216*f0865ec9SKyle Evans 		/* When dealing with EDDSA448, because of our 4-isogeny between Edwars448 and Ed448
2217*f0865ec9SKyle Evans 		 * mapping base point to four times base point, we actually multiply our public key by 4 here
2218*f0865ec9SKyle Evans 		 * to be inline with the other computations (the public key stored in Weierstrass )
2219*f0865ec9SKyle Evans 		 */
2220*f0865ec9SKyle Evans 		ret = nn_lshift(&h, &h, 2); EG(ret, err);
2221*f0865ec9SKyle Evans 		ret = nn_mod(&h, &h, q); EG(ret, err);
2222*f0865ec9SKyle Evans 	}
2223*f0865ec9SKyle Evans #endif
2224*f0865ec9SKyle Evans 	/* 4. Compute (S * G) - R - (h * A)  */
2225*f0865ec9SKyle Evans 	ret = prj_pt_mul(&_Tmp1, S, G); EG(ret, err);
2226*f0865ec9SKyle Evans 	ret = prj_pt_neg(&_Tmp2, _R); EG(ret, err);
2227*f0865ec9SKyle Evans 	ret = prj_pt_add(&_Tmp1, &_Tmp1, &_Tmp2); EG(ret, err);
2228*f0865ec9SKyle Evans 	ret = prj_pt_mul(&_Tmp2, &h, A); EG(ret, err);
2229*f0865ec9SKyle Evans 	ret = prj_pt_neg(&_Tmp2, &_Tmp2); EG(ret, err);
2230*f0865ec9SKyle Evans 	ret = prj_pt_add(&_Tmp1, &_Tmp1, &_Tmp2); EG(ret, err);
2231*f0865ec9SKyle Evans 
2232*f0865ec9SKyle Evans 	/* 5. We use cofactored multiplication, so multiply by the cofactor:
2233*f0865ec9SKyle Evans 	 *    since this is a public verification, we use a basic double and add
2234*f0865ec9SKyle Evans 	 *    algorithm.
2235*f0865ec9SKyle Evans 	 */
2236*f0865ec9SKyle Evans 	ret = _prj_pt_unprotected_mult(&_Tmp2, gen_cofactor, &_Tmp1); EG(ret, err);
2237*f0865ec9SKyle Evans 
2238*f0865ec9SKyle Evans 	/* Reject the signature if we do not have point at infinity here */
2239*f0865ec9SKyle Evans 	ret = prj_pt_iszero(&_Tmp2, &iszero); EG(ret, err);
2240*f0865ec9SKyle Evans 	ret = iszero ? 0 : -1;
2241*f0865ec9SKyle Evans 
2242*f0865ec9SKyle Evans err:
2243*f0865ec9SKyle Evans 	/*
2244*f0865ec9SKyle Evans 	 * We can now clear data part of the context. This will clear
2245*f0865ec9SKyle Evans 	 * magic and avoid further reuse of the whole context.
2246*f0865ec9SKyle Evans 	 */
2247*f0865ec9SKyle Evans 	if(ctx != NULL){
2248*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset(&(ctx->verify_data.eddsa), 0, sizeof(eddsa_verify_data)));
2249*f0865ec9SKyle Evans 	}
2250*f0865ec9SKyle Evans 
2251*f0865ec9SKyle Evans 	/* Clean what remains on the stack */
2252*f0865ec9SKyle Evans 	PTR_NULLIFY(G);
2253*f0865ec9SKyle Evans 	PTR_NULLIFY(A);
2254*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
2255*f0865ec9SKyle Evans 	PTR_NULLIFY(S);
2256*f0865ec9SKyle Evans 	PTR_NULLIFY(_R);
2257*f0865ec9SKyle Evans 	PTR_NULLIFY(gen_cofactor);
2258*f0865ec9SKyle Evans 	VAR_ZEROIFY(hsize);
2259*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash);
2260*f0865ec9SKyle Evans 	VAR_ZEROIFY(use_message_pre_hash_hsize);
2261*f0865ec9SKyle Evans 
2262*f0865ec9SKyle Evans 	nn_uninit(&h);
2263*f0865ec9SKyle Evans 	prj_pt_uninit(&_Tmp1);
2264*f0865ec9SKyle Evans 	prj_pt_uninit(&_Tmp2);
2265*f0865ec9SKyle Evans 
2266*f0865ec9SKyle Evans 	return ret;
2267*f0865ec9SKyle Evans }
2268*f0865ec9SKyle Evans 
2269*f0865ec9SKyle Evans /* Batch verification function:
2270*f0865ec9SKyle Evans  * This function takes multiple signatures/messages/public keys, and
2271*f0865ec9SKyle Evans  * checks all the signatures.
2272*f0865ec9SKyle Evans  *
2273*f0865ec9SKyle Evans  * This returns 0 if *all* the signatures are correct, and -1 if at least
2274*f0865ec9SKyle Evans  * one signature is not correct.
2275*f0865ec9SKyle Evans  *
2276*f0865ec9SKyle Evans  * NOTE: the "no_memory" version is not optimized and straightforwardly
2277*f0865ec9SKyle Evans  * checks for the signature using naive sums. See below for an optimized
2278*f0865ec9SKyle Evans  * Bos-Coster version (but requiring additional memory to work).
2279*f0865ec9SKyle Evans  *
2280*f0865ec9SKyle Evans  */
2281*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _eddsa_verify_batch_no_memory(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys,
2282*f0865ec9SKyle Evans 					 const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type,
2283*f0865ec9SKyle Evans 		                         hash_alg_type hash_type, const u8 **adata, const u16 *adata_len)
2284*f0865ec9SKyle Evans {
2285*f0865ec9SKyle Evans 	nn_src_t q = NULL;
2286*f0865ec9SKyle Evans 	ec_edwards_crv crv_edwards;
2287*f0865ec9SKyle Evans 	aff_pt_edwards R, A;
2288*f0865ec9SKyle Evans 	prj_pt_src_t G = NULL;
2289*f0865ec9SKyle Evans 	prj_pt _Tmp, _R_sum, _A_sum;
2290*f0865ec9SKyle Evans 	nn S, S_sum, z, h;
2291*f0865ec9SKyle Evans 	u8 hash[MAX_DIGEST_SIZE];
2292*f0865ec9SKyle Evans 	int ret, iszero, cmp;
2293*f0865ec9SKyle Evans 	u16 hsize;
2294*f0865ec9SKyle Evans 	const ec_pub_key *pub_key, *pub_key0;
2295*f0865ec9SKyle Evans 	ec_shortw_crv_src_t shortw_curve;
2296*f0865ec9SKyle Evans 	fp_src_t alpha_montgomery;
2297*f0865ec9SKyle Evans 	fp_src_t gamma_montgomery;
2298*f0865ec9SKyle Evans 	fp_src_t alpha_edwards;
2299*f0865ec9SKyle Evans 	nn_src_t gen_cofactor = NULL;
2300*f0865ec9SKyle Evans 	prj_pt_src_t pub_key_y;
2301*f0865ec9SKyle Evans 	hash_context h_ctx;
2302*f0865ec9SKyle Evans 	hash_context h_ctx_pre_hash;
2303*f0865ec9SKyle Evans 	u8 use_message_pre_hash = 0;
2304*f0865ec9SKyle Evans 	u16 use_message_pre_hash_hsize = 0;
2305*f0865ec9SKyle Evans 	const hash_mapping *hm;
2306*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
2307*f0865ec9SKyle Evans 	u32 i;
2308*f0865ec9SKyle Evans 
2309*f0865ec9SKyle Evans 	R.magic = S.magic = S_sum.magic = crv_edwards.magic = WORD(0);
2310*f0865ec9SKyle Evans 	_Tmp.magic = _R_sum.magic = _A_sum.magic = WORD(0);
2311*f0865ec9SKyle Evans 	z.magic = h.magic = WORD(0);
2312*f0865ec9SKyle Evans 
2313*f0865ec9SKyle Evans 	/* First, some sanity checks */
2314*f0865ec9SKyle Evans 	MUST_HAVE((s != NULL) && (pub_keys != NULL) && (m != NULL) && (adata != NULL), ret, err);
2315*f0865ec9SKyle Evans 	/* We need at least one element in our batch data bags */
2316*f0865ec9SKyle Evans 	MUST_HAVE((num > 0), ret, err);
2317*f0865ec9SKyle Evans 
2318*f0865ec9SKyle Evans 
2319*f0865ec9SKyle Evans 	/* Zero init our local data */
2320*f0865ec9SKyle Evans 	ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err);
2321*f0865ec9SKyle Evans 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
2322*f0865ec9SKyle Evans 	ret = local_memset(&A, 0, sizeof(aff_pt_edwards)); EG(ret, err);
2323*f0865ec9SKyle Evans 	ret = local_memset(&R, 0, sizeof(aff_pt_edwards)); EG(ret, err);
2324*f0865ec9SKyle Evans 	ret = local_memset(&_R_sum, 0, sizeof(prj_pt)); EG(ret, err);
2325*f0865ec9SKyle Evans 	ret = local_memset(&_A_sum, 0, sizeof(prj_pt)); EG(ret, err);
2326*f0865ec9SKyle Evans 	ret = local_memset(&_Tmp, 0, sizeof(prj_pt)); EG(ret, err);
2327*f0865ec9SKyle Evans 
2328*f0865ec9SKyle Evans 	pub_key0 = pub_keys[0];
2329*f0865ec9SKyle Evans 	MUST_HAVE((pub_key0 != NULL), ret, err);
2330*f0865ec9SKyle Evans 
2331*f0865ec9SKyle Evans 	/* Get our hash mapping */
2332*f0865ec9SKyle Evans 	ret = get_hash_by_type(hash_type, &hm); EG(ret, err);
2333*f0865ec9SKyle Evans 	hsize = hm->digest_size;
2334*f0865ec9SKyle Evans 	MUST_HAVE((hm != NULL), ret, err);
2335*f0865ec9SKyle Evans 
2336*f0865ec9SKyle Evans 	/* Do we use the raw message or its PH(M) hashed version? */
2337*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
2338*f0865ec9SKyle Evans 	if(sig_type == EDDSA25519PH){
2339*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
2340*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = hsize;
2341*f0865ec9SKyle Evans 	}
2342*f0865ec9SKyle Evans #endif
2343*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2344*f0865ec9SKyle Evans 	if(sig_type == EDDSA448PH){
2345*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
2346*f0865ec9SKyle Evans 		/* NOTE: as per RFC8032, EDDSA448PH uses
2347*f0865ec9SKyle Evans 		 * SHAKE256 with 64 bytes output.
2348*f0865ec9SKyle Evans 		 */
2349*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = 64;
2350*f0865ec9SKyle Evans 	}
2351*f0865ec9SKyle Evans #endif
2352*f0865ec9SKyle Evans 
2353*f0865ec9SKyle Evans 	for(i = 0; i < num; i++){
2354*f0865ec9SKyle Evans 		u8 siglen;
2355*f0865ec9SKyle Evans 		const u8 *sig = NULL;
2356*f0865ec9SKyle Evans 
2357*f0865ec9SKyle Evans 		ret = eddsa_pub_key_sanity_check(pub_keys[i]); EG(ret, err);
2358*f0865ec9SKyle Evans 
2359*f0865ec9SKyle Evans 		/* Make things more readable */
2360*f0865ec9SKyle Evans 		pub_key = pub_keys[i];
2361*f0865ec9SKyle Evans 
2362*f0865ec9SKyle Evans 		/* Sanity check that all our public keys have the same parameters */
2363*f0865ec9SKyle Evans 		MUST_HAVE((pub_key->params) == (pub_key0->params), ret, err);
2364*f0865ec9SKyle Evans 
2365*f0865ec9SKyle Evans 		q = &(pub_key->params->ec_gen_order);
2366*f0865ec9SKyle Evans 		shortw_curve = &(pub_key->params->ec_curve);
2367*f0865ec9SKyle Evans 		alpha_montgomery = &(pub_key->params->ec_alpha_montgomery);
2368*f0865ec9SKyle Evans 		gamma_montgomery = &(pub_key->params->ec_gamma_montgomery);
2369*f0865ec9SKyle Evans 		alpha_edwards = &(pub_key->params->ec_alpha_edwards);
2370*f0865ec9SKyle Evans 		gen_cofactor = &(pub_key->params->ec_gen_cofactor);
2371*f0865ec9SKyle Evans 		pub_key_y = &(pub_key->y);
2372*f0865ec9SKyle Evans 		key_type = pub_key->key_type;
2373*f0865ec9SKyle Evans 		G = &(pub_key->params->ec_gen);
2374*f0865ec9SKyle Evans 
2375*f0865ec9SKyle Evans 		/* Check the key type versus the algorithm */
2376*f0865ec9SKyle Evans 		MUST_HAVE((key_type == sig_type), ret, err);
2377*f0865ec9SKyle Evans 
2378*f0865ec9SKyle Evans 		if(i == 0){
2379*f0865ec9SKyle Evans 			/* Initialize our sums to zero/point at infinity */
2380*f0865ec9SKyle Evans 			ret = nn_init(&S_sum, 0); EG(ret, err);
2381*f0865ec9SKyle Evans 			ret = prj_pt_init(&_R_sum, shortw_curve); EG(ret, err);
2382*f0865ec9SKyle Evans 			ret = prj_pt_zero(&_R_sum); EG(ret, err);
2383*f0865ec9SKyle Evans 			ret = prj_pt_init(&_A_sum, shortw_curve); EG(ret, err);
2384*f0865ec9SKyle Evans 			ret = prj_pt_zero(&_A_sum); EG(ret, err);
2385*f0865ec9SKyle Evans 			ret = nn_init(&z, 0); EG(ret, err);
2386*f0865ec9SKyle Evans 			ret = nn_init(&h, 0); EG(ret, err);
2387*f0865ec9SKyle Evans 		}
2388*f0865ec9SKyle Evans 
2389*f0865ec9SKyle Evans gen_z_again:
2390*f0865ec9SKyle Evans 		/* Get a random z for randomizing the linear combination */
2391*f0865ec9SKyle Evans 		ret = nn_get_random_len(&z, (hsize / 4)); EG(ret, err);
2392*f0865ec9SKyle Evans 		ret = nn_iszero(&z, &iszero); EG(ret, err);
2393*f0865ec9SKyle Evans 		if(iszero){
2394*f0865ec9SKyle Evans 			goto gen_z_again;
2395*f0865ec9SKyle Evans 		}
2396*f0865ec9SKyle Evans 
2397*f0865ec9SKyle Evans 		/* Sanity check on hash types */
2398*f0865ec9SKyle Evans 		MUST_HAVE((hash_type == get_eddsa_hash_type(key_type)), ret, err);
2399*f0865ec9SKyle Evans 
2400*f0865ec9SKyle Evans 		/* Check given signature length is the expected one */
2401*f0865ec9SKyle Evans 		siglen = s_len[i];
2402*f0865ec9SKyle Evans 		sig = s[i];
2403*f0865ec9SKyle Evans 		MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)), ret, err);
2404*f0865ec9SKyle Evans 		MUST_HAVE((siglen == (EDDSA_R_LEN(hsize) + EDDSA_S_LEN(hsize))), ret, err);
2405*f0865ec9SKyle Evans 
2406*f0865ec9SKyle Evans 		/* Initialize the hash context */
2407*f0865ec9SKyle Evans 		/* Since we call a callback, sanity check our mapping */
2408*f0865ec9SKyle Evans 		ret = hash_mapping_callbacks_sanity_check(hm); EG(ret, err);
2409*f0865ec9SKyle Evans 		ret = hm->hfunc_init(&h_ctx); EG(ret, err);
2410*f0865ec9SKyle Evans 		ret = hm->hfunc_init(&h_ctx_pre_hash); EG(ret, err);
2411*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
2412*f0865ec9SKyle Evans 		if(key_type == EDDSA25519CTX){
2413*f0865ec9SKyle Evans 			/* As per RFC8032, for EDDSA25519CTX the context SHOULD NOT be empty */
2414*f0865ec9SKyle Evans 			MUST_HAVE((adata[i] != NULL), ret, err);
2415*f0865ec9SKyle Evans 			ret = dom2(0, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err);
2416*f0865ec9SKyle Evans 		}
2417*f0865ec9SKyle Evans 		if(key_type == EDDSA25519PH){
2418*f0865ec9SKyle Evans 			ret = dom2(1, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err);
2419*f0865ec9SKyle Evans 		}
2420*f0865ec9SKyle Evans #endif
2421*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2422*f0865ec9SKyle Evans 		if(key_type == EDDSA448){
2423*f0865ec9SKyle Evans 			ret = dom4(0, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err);
2424*f0865ec9SKyle Evans 		}
2425*f0865ec9SKyle Evans 		if(key_type == EDDSA448PH){
2426*f0865ec9SKyle Evans 			ret = dom4(1, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err);
2427*f0865ec9SKyle Evans 		}
2428*f0865ec9SKyle Evans #endif
2429*f0865ec9SKyle Evans 		/* Import R and S values from signature buffer */
2430*f0865ec9SKyle Evans 		/*******************************/
2431*f0865ec9SKyle Evans 		/* Import R as an Edwards point */
2432*f0865ec9SKyle Evans 		ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery,
2433*f0865ec9SKyle Evans 					gamma_montgomery, alpha_edwards); EG(ret, err);
2434*f0865ec9SKyle Evans 		/* NOTE: non canonical R are checked and rejected here */
2435*f0865ec9SKyle Evans 		ret = eddsa_decode_point(&R, &crv_edwards, alpha_edwards, &sig[0],
2436*f0865ec9SKyle Evans 				      EDDSA_R_LEN(hsize), key_type); EG(ret, err);
2437*f0865ec9SKyle Evans 		dbg_ec_edwards_point_print("R", &R);
2438*f0865ec9SKyle Evans 		/* Transfer our public point R to Weierstrass */
2439*f0865ec9SKyle Evans 		ret = aff_pt_edwards_to_prj_pt_shortw(&R, shortw_curve, &_Tmp, alpha_edwards); EG(ret, err);
2440*f0865ec9SKyle Evans 		/* Update the hash with the encoded R */
2441*f0865ec9SKyle Evans 		ret = hm->hfunc_update(&h_ctx, &sig[0], EDDSA_R_LEN(hsize)); EG(ret, err);
2442*f0865ec9SKyle Evans 		/* Multiply by z.
2443*f0865ec9SKyle Evans 		 */
2444*f0865ec9SKyle Evans 		ret = _prj_pt_unprotected_mult(&_Tmp, &z, &_Tmp); EG(ret, err);
2445*f0865ec9SKyle Evans 		/* Add to the sum */
2446*f0865ec9SKyle Evans 		ret = prj_pt_add(&_R_sum, &_R_sum, &_Tmp); EG(ret, err);
2447*f0865ec9SKyle Evans 
2448*f0865ec9SKyle Evans 		/*******************************/
2449*f0865ec9SKyle Evans 		/* Import S as an integer */
2450*f0865ec9SKyle Evans 		ret = eddsa_decode_integer(&S, &sig[EDDSA_R_LEN(hsize)], EDDSA_S_LEN(hsize)); EG(ret, err);
2451*f0865ec9SKyle Evans 		/* Reject S if it is not reduced modulo q */
2452*f0865ec9SKyle Evans 		ret = nn_cmp(&S, q, &cmp); EG(ret, err);
2453*f0865ec9SKyle Evans 		MUST_HAVE((cmp < 0), ret, err);
2454*f0865ec9SKyle Evans 		dbg_nn_print("S", &S);
2455*f0865ec9SKyle Evans 
2456*f0865ec9SKyle Evans 		/* Add z S to the sum */
2457*f0865ec9SKyle Evans 		ret = nn_mul(&S, &S, &z); EG(ret, err);
2458*f0865ec9SKyle Evans 		ret = nn_mod(&S, &S, q); EG(ret, err);
2459*f0865ec9SKyle Evans 		ret = nn_mod_add(&S_sum, &S_sum, &S, q); EG(ret, err);
2460*f0865ec9SKyle Evans 
2461*f0865ec9SKyle Evans 		/*******************************/
2462*f0865ec9SKyle Evans 		/* Encode the public key
2463*f0865ec9SKyle Evans 		 * NOTE: since we deal with a public key transfered to Weierstrass,
2464*f0865ec9SKyle Evans 		 * encoding checking has been handled elsewhere.
2465*f0865ec9SKyle Evans 		 */
2466*f0865ec9SKyle Evans 		/* Reject the signature if the public key is one of small order points.
2467*f0865ec9SKyle Evans 		 * We multiply by the cofactor: since this is a public verification,
2468*f0865ec9SKyle Evans 		 * we use a basic double and add algorithm.
2469*f0865ec9SKyle Evans 		 */
2470*f0865ec9SKyle Evans 		ret = _prj_pt_unprotected_mult(&_Tmp, gen_cofactor, pub_key_y); EG(ret, err);
2471*f0865ec9SKyle Evans 		/* Reject the signature if we have point at infinity here as this means
2472*f0865ec9SKyle Evans 		 * that the public key is of small order.
2473*f0865ec9SKyle Evans 		 */
2474*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&_Tmp, &iszero); EG(ret, err);
2475*f0865ec9SKyle Evans 		MUST_HAVE((!iszero), ret, err);
2476*f0865ec9SKyle Evans 
2477*f0865ec9SKyle Evans 		/* Transfer the public key to Edwards */
2478*f0865ec9SKyle Evans 		ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, &A, alpha_edwards); EG(ret, err);
2479*f0865ec9SKyle Evans 		dbg_ec_edwards_point_print("A", &A);
2480*f0865ec9SKyle Evans 		MUST_HAVE((EDDSA_R_LEN(hsize) <= sizeof(hash)), ret, err);
2481*f0865ec9SKyle Evans 		/* NOTE: we use the hash buffer as a temporary buffer */
2482*f0865ec9SKyle Evans 		ret = eddsa_encode_point(&A, alpha_edwards, hash, EDDSA_R_LEN(hsize), key_type); EG(ret, err);
2483*f0865ec9SKyle Evans 
2484*f0865ec9SKyle Evans 		/* Update the hash with the encoded public key */
2485*f0865ec9SKyle Evans 		ret = hm->hfunc_update(&h_ctx, hash, EDDSA_R_LEN(hsize)); EG(ret, err);
2486*f0865ec9SKyle Evans 		/* Finish our computation of h = H(R || A || M) */
2487*f0865ec9SKyle Evans 		/* Update the hash with the message or its hash for the PH versions */
2488*f0865ec9SKyle Evans 		if(use_message_pre_hash == 1){
2489*f0865ec9SKyle Evans 			ret = hm->hfunc_update(&h_ctx_pre_hash, m[i], m_len[i]); EG(ret, err);
2490*f0865ec9SKyle Evans 			ret = hm->hfunc_finalize(&h_ctx_pre_hash, hash); EG(ret, err);
2491*f0865ec9SKyle Evans 			MUST_HAVE((use_message_pre_hash_hsize <= hsize), ret, err);
2492*f0865ec9SKyle Evans 			ret = hm->hfunc_update(&h_ctx, hash, use_message_pre_hash_hsize); EG(ret, err);
2493*f0865ec9SKyle Evans 		}
2494*f0865ec9SKyle Evans 		else{
2495*f0865ec9SKyle Evans 			ret = hm->hfunc_update(&h_ctx, m[i], m_len[i]); EG(ret, err);
2496*f0865ec9SKyle Evans 		}
2497*f0865ec9SKyle Evans 		ret = hm->hfunc_finalize(&h_ctx, hash); EG(ret, err);
2498*f0865ec9SKyle Evans 		dbg_buf_print("hash = H(R || A || PH(M))", hash, hsize);
2499*f0865ec9SKyle Evans 
2500*f0865ec9SKyle Evans 		/* Import our hash as a NN and reduce it modulo q */
2501*f0865ec9SKyle Evans 		ret = eddsa_decode_integer(&h, hash, hsize); EG(ret, err);
2502*f0865ec9SKyle Evans 		ret = nn_mod(&h, &h, q); EG(ret, err);
2503*f0865ec9SKyle Evans 		dbg_nn_print("h = ", &h);
2504*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2505*f0865ec9SKyle Evans 		if((key_type == EDDSA448) || (key_type == EDDSA448PH)){
2506*f0865ec9SKyle Evans 			/* When dealing with EDDSA448, because of our 4-isogeny between Edwars448 and Ed448
2507*f0865ec9SKyle Evans 			 * mapping base point to four times base point, we actually multiply our public key by 4 here
2508*f0865ec9SKyle Evans 			 * to be inline with the other computations (the public key stored in Weierstrass )
2509*f0865ec9SKyle Evans 			 */
2510*f0865ec9SKyle Evans 			ret = nn_lshift(&h, &h, 2); EG(ret, err);
2511*f0865ec9SKyle Evans 			ret = nn_mod(&h, &h, q); EG(ret, err);
2512*f0865ec9SKyle Evans 		}
2513*f0865ec9SKyle Evans #endif
2514*f0865ec9SKyle Evans 
2515*f0865ec9SKyle Evans 		/* Multiply by (z * h) mod q.
2516*f0865ec9SKyle Evans 		 * NOTE: we use unprotected scalar multiplication since this is a
2517*f0865ec9SKyle Evans 		 * public operation.
2518*f0865ec9SKyle Evans 		 */
2519*f0865ec9SKyle Evans 		ret = nn_mul(&z, &z, &h); EG(ret, err);
2520*f0865ec9SKyle Evans 		ret = nn_mod(&z, &z, q); EG(ret, err);
2521*f0865ec9SKyle Evans 		ret = _prj_pt_unprotected_mult(&_Tmp, &z, &_Tmp); EG(ret, err);
2522*f0865ec9SKyle Evans 		/* Add to the sum */
2523*f0865ec9SKyle Evans 		ret = prj_pt_add(&_A_sum, &_A_sum, &_Tmp); EG(ret, err);
2524*f0865ec9SKyle Evans 	}
2525*f0865ec9SKyle Evans 
2526*f0865ec9SKyle Evans 	/* Sanity check */
2527*f0865ec9SKyle Evans 	MUST_HAVE((gen_cofactor != NULL) && (q != NULL) && (G != NULL), ret, err);
2528*f0865ec9SKyle Evans 
2529*f0865ec9SKyle Evans 	/* Multiply the S sum by the cofactor */
2530*f0865ec9SKyle Evans 	ret = nn_mul(&S_sum, &S_sum, gen_cofactor); EG(ret, err);
2531*f0865ec9SKyle Evans 	ret = nn_mod(&S_sum, &S_sum, q); EG(ret, err);
2532*f0865ec9SKyle Evans 	/* Negate it. NOTE: -x mod q is (q - x) mod q, i.e. (q - x) when x is reduced */
2533*f0865ec9SKyle Evans 	ret = nn_mod_neg(&S_sum, &S_sum, q); EG(ret, err);
2534*f0865ec9SKyle Evans 	/* Multiply this by the generator */
2535*f0865ec9SKyle Evans 	ret = _prj_pt_unprotected_mult(&_Tmp, &S_sum, G); EG(ret, err);
2536*f0865ec9SKyle Evans 
2537*f0865ec9SKyle Evans 	/* Multiply the R sum by the cofactor */
2538*f0865ec9SKyle Evans 	ret = _prj_pt_unprotected_mult(&_R_sum, gen_cofactor, &_R_sum); EG(ret, err);
2539*f0865ec9SKyle Evans 
2540*f0865ec9SKyle Evans 	/* Now add the three sums */
2541*f0865ec9SKyle Evans 	ret = prj_pt_add(&_Tmp, &_Tmp, &_A_sum);
2542*f0865ec9SKyle Evans 	ret = prj_pt_add(&_Tmp, &_Tmp, &_R_sum);
2543*f0865ec9SKyle Evans 
2544*f0865ec9SKyle Evans 	/* Reject the signature if we do not have point at infinity here */
2545*f0865ec9SKyle Evans 	ret = prj_pt_iszero(&_Tmp, &iszero); EG(ret, err);
2546*f0865ec9SKyle Evans 	ret = iszero ? 0 : -1;
2547*f0865ec9SKyle Evans 
2548*f0865ec9SKyle Evans err:
2549*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
2550*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key);
2551*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key0);
2552*f0865ec9SKyle Evans 	PTR_NULLIFY(shortw_curve);
2553*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_montgomery);
2554*f0865ec9SKyle Evans 	PTR_NULLIFY(gamma_montgomery);
2555*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_edwards);
2556*f0865ec9SKyle Evans 	PTR_NULLIFY(gen_cofactor);
2557*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key_y);
2558*f0865ec9SKyle Evans 	PTR_NULLIFY(G);
2559*f0865ec9SKyle Evans 
2560*f0865ec9SKyle Evans 	ec_edwards_crv_uninit(&crv_edwards);
2561*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&A);
2562*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&R);
2563*f0865ec9SKyle Evans 	prj_pt_uninit(&_R_sum);
2564*f0865ec9SKyle Evans 	prj_pt_uninit(&_A_sum);
2565*f0865ec9SKyle Evans 	prj_pt_uninit(&_Tmp);
2566*f0865ec9SKyle Evans 	nn_uninit(&S);
2567*f0865ec9SKyle Evans 	nn_uninit(&S_sum);
2568*f0865ec9SKyle Evans 	nn_uninit(&z);
2569*f0865ec9SKyle Evans 	nn_uninit(&h);
2570*f0865ec9SKyle Evans 
2571*f0865ec9SKyle Evans 	return ret;
2572*f0865ec9SKyle Evans 
2573*f0865ec9SKyle Evans }
2574*f0865ec9SKyle Evans 
2575*f0865ec9SKyle Evans /*
2576*f0865ec9SKyle Evans  * The following batch verification uses the Bos-Coster algorithm, presented e.g. in
2577*f0865ec9SKyle Evans  * https://ed25519.cr.yp.to/ed25519-20110705.pdf
2578*f0865ec9SKyle Evans  *
2579*f0865ec9SKyle Evans  * The Bos-Coster algorithm allows to optimize a sum of scalar multiplications using
2580*f0865ec9SKyle Evans  * addition chains.
2581*f0865ec9SKyle Evans  *
2582*f0865ec9SKyle Evans  */
2583*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _eddsa_verify_batch(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys,
2584*f0865ec9SKyle Evans 			       const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type,
2585*f0865ec9SKyle Evans                                hash_alg_type hash_type, const u8 **adata, const u16 *adata_len,
2586*f0865ec9SKyle Evans                                verify_batch_scratch_pad *scratch_pad_area, u32 *scratch_pad_area_len)
2587*f0865ec9SKyle Evans {
2588*f0865ec9SKyle Evans 	nn_src_t q = NULL;
2589*f0865ec9SKyle Evans 	ec_edwards_crv crv_edwards;
2590*f0865ec9SKyle Evans 	aff_pt_edwards R, A;
2591*f0865ec9SKyle Evans 	prj_pt_src_t G = NULL;
2592*f0865ec9SKyle Evans 	nn S, z;
2593*f0865ec9SKyle Evans 	u8 hash[MAX_DIGEST_SIZE];
2594*f0865ec9SKyle Evans 	int ret, iszero, cmp;
2595*f0865ec9SKyle Evans 	u16 hsize;
2596*f0865ec9SKyle Evans 	const ec_pub_key *pub_key, *pub_key0;
2597*f0865ec9SKyle Evans 	ec_shortw_crv_src_t shortw_curve;
2598*f0865ec9SKyle Evans 	fp_src_t alpha_montgomery;
2599*f0865ec9SKyle Evans 	fp_src_t gamma_montgomery;
2600*f0865ec9SKyle Evans 	fp_src_t alpha_edwards;
2601*f0865ec9SKyle Evans 	nn_src_t gen_cofactor = NULL;
2602*f0865ec9SKyle Evans 	prj_pt_src_t pub_key_y;
2603*f0865ec9SKyle Evans 	hash_context h_ctx;
2604*f0865ec9SKyle Evans 	hash_context h_ctx_pre_hash;
2605*f0865ec9SKyle Evans 	u8 use_message_pre_hash = 0;
2606*f0865ec9SKyle Evans 	u16 use_message_pre_hash_hsize = 0;
2607*f0865ec9SKyle Evans 	const hash_mapping *hm;
2608*f0865ec9SKyle Evans 	ec_alg_type key_type = UNKNOWN_ALG;
2609*f0865ec9SKyle Evans 	/* NN numbers and points pointers */
2610*f0865ec9SKyle Evans 	verify_batch_scratch_pad *elements = scratch_pad_area;
2611*f0865ec9SKyle Evans 	u32 i;
2612*f0865ec9SKyle Evans 	u64 expected_len;
2613*f0865ec9SKyle Evans 	bitcnt_t q_bit_len = 0;
2614*f0865ec9SKyle Evans 
2615*f0865ec9SKyle Evans 	S.magic = z.magic = crv_edwards.magic = WORD(0);
2616*f0865ec9SKyle Evans 
2617*f0865ec9SKyle Evans 	/* First, some sanity checks */
2618*f0865ec9SKyle Evans 	MUST_HAVE((s != NULL) && (pub_keys != NULL) && (m != NULL) && (adata != NULL), ret, err);
2619*f0865ec9SKyle Evans 	MUST_HAVE((scratch_pad_area_len != NULL), ret, err);
2620*f0865ec9SKyle Evans 	MUST_HAVE(((2 * num) >= num), ret, err);
2621*f0865ec9SKyle Evans 	MUST_HAVE(((2 * num) + 1) >= num, ret, err);
2622*f0865ec9SKyle Evans 
2623*f0865ec9SKyle Evans 	/* In oder to apply the algorithm, we must have at least two
2624*f0865ec9SKyle Evans 	 * elements to verify. If this is not the case, we fallback to
2625*f0865ec9SKyle Evans 	 * the regular "no memory" version.
2626*f0865ec9SKyle Evans 	 */
2627*f0865ec9SKyle Evans 	if(num <= 1){
2628*f0865ec9SKyle Evans 		if(scratch_pad_area == NULL){
2629*f0865ec9SKyle Evans 			/* We do not require any memory in this case */
2630*f0865ec9SKyle Evans 			(*scratch_pad_area_len) = 0;
2631*f0865ec9SKyle Evans 			ret = 0;
2632*f0865ec9SKyle Evans 			goto err;
2633*f0865ec9SKyle Evans 		}
2634*f0865ec9SKyle Evans 		else{
2635*f0865ec9SKyle Evans 	                ret = _eddsa_verify_batch_no_memory(s, s_len, pub_keys, m, m_len, num, sig_type,
2636*f0865ec9SKyle Evans 		                                            hash_type, adata, adata_len);
2637*f0865ec9SKyle Evans 			goto err;
2638*f0865ec9SKyle Evans 		}
2639*f0865ec9SKyle Evans 	}
2640*f0865ec9SKyle Evans 
2641*f0865ec9SKyle Evans 	expected_len = ((2 * num) + 1) * sizeof(verify_batch_scratch_pad);
2642*f0865ec9SKyle Evans 	MUST_HAVE((expected_len < 0xffffffff), ret, err);
2643*f0865ec9SKyle Evans 
2644*f0865ec9SKyle Evans 	if(scratch_pad_area == NULL){
2645*f0865ec9SKyle Evans 		/* Return the needed size: we need to keep track of (2 * num) + 1 NN numbers
2646*f0865ec9SKyle Evans 		 * and (2 * num) + 1 projective points, plus (2 * num) + 1 indices
2647*f0865ec9SKyle Evans 		 */
2648*f0865ec9SKyle Evans 		(*scratch_pad_area_len) = (u32)expected_len;
2649*f0865ec9SKyle Evans 		ret = 0;
2650*f0865ec9SKyle Evans 		goto err;
2651*f0865ec9SKyle Evans 	}
2652*f0865ec9SKyle Evans 	else{
2653*f0865ec9SKyle Evans 		MUST_HAVE((*scratch_pad_area_len) >= expected_len, ret, err);
2654*f0865ec9SKyle Evans 	}
2655*f0865ec9SKyle Evans 
2656*f0865ec9SKyle Evans 	/********************************************/
2657*f0865ec9SKyle Evans 	/****** Initialize elements *****************/
2658*f0865ec9SKyle Evans 	/* Zero init our local data */
2659*f0865ec9SKyle Evans 	ret = local_memset(&crv_edwards, 0, sizeof(ec_edwards_crv)); EG(ret, err);
2660*f0865ec9SKyle Evans 	ret = local_memset(hash, 0, sizeof(hash)); EG(ret, err);
2661*f0865ec9SKyle Evans 	ret = local_memset(&A, 0, sizeof(aff_pt_edwards)); EG(ret, err);
2662*f0865ec9SKyle Evans 	ret = local_memset(&R, 0, sizeof(aff_pt_edwards)); EG(ret, err);
2663*f0865ec9SKyle Evans 
2664*f0865ec9SKyle Evans 	pub_key0 = pub_keys[0];
2665*f0865ec9SKyle Evans 	MUST_HAVE((pub_key0 != NULL), ret, err);
2666*f0865ec9SKyle Evans 
2667*f0865ec9SKyle Evans 	/* Get our hash mapping */
2668*f0865ec9SKyle Evans 	ret = get_hash_by_type(hash_type, &hm); EG(ret, err);
2669*f0865ec9SKyle Evans 	hsize = hm->digest_size;
2670*f0865ec9SKyle Evans 	MUST_HAVE((hm != NULL), ret, err);
2671*f0865ec9SKyle Evans 
2672*f0865ec9SKyle Evans 	/* Do we use the raw message or its PH(M) hashed version? */
2673*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
2674*f0865ec9SKyle Evans 	if(sig_type == EDDSA25519PH){
2675*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
2676*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = hsize;
2677*f0865ec9SKyle Evans 	}
2678*f0865ec9SKyle Evans #endif
2679*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2680*f0865ec9SKyle Evans 	if(sig_type == EDDSA448PH){
2681*f0865ec9SKyle Evans 		use_message_pre_hash = 1;
2682*f0865ec9SKyle Evans 		/* NOTE: as per RFC8032, EDDSA448PH uses
2683*f0865ec9SKyle Evans 		 * SHAKE256 with 64 bytes output.
2684*f0865ec9SKyle Evans 		 */
2685*f0865ec9SKyle Evans 		use_message_pre_hash_hsize = 64;
2686*f0865ec9SKyle Evans 	}
2687*f0865ec9SKyle Evans #endif
2688*f0865ec9SKyle Evans 
2689*f0865ec9SKyle Evans 	/* Compute our original numbers and points */
2690*f0865ec9SKyle Evans 	MUST_HAVE((num >= 1), ret, err);
2691*f0865ec9SKyle Evans 	for(i = 0; i < num; i++){
2692*f0865ec9SKyle Evans 		u8 siglen;
2693*f0865ec9SKyle Evans 		const u8 *sig = NULL;
2694*f0865ec9SKyle Evans 
2695*f0865ec9SKyle Evans 		ret = eddsa_pub_key_sanity_check(pub_keys[i]); EG(ret, err);
2696*f0865ec9SKyle Evans 
2697*f0865ec9SKyle Evans 		/* Make things more readable */
2698*f0865ec9SKyle Evans 		pub_key = pub_keys[i];
2699*f0865ec9SKyle Evans 
2700*f0865ec9SKyle Evans 		/* Sanity check that all our public keys have the same parameters */
2701*f0865ec9SKyle Evans 		MUST_HAVE((pub_key->params) == (pub_key0->params), ret, err);
2702*f0865ec9SKyle Evans 
2703*f0865ec9SKyle Evans 		q = &(pub_key->params->ec_gen_order);
2704*f0865ec9SKyle Evans 		shortw_curve = &(pub_key->params->ec_curve);
2705*f0865ec9SKyle Evans 		alpha_montgomery = &(pub_key->params->ec_alpha_montgomery);
2706*f0865ec9SKyle Evans 		gamma_montgomery = &(pub_key->params->ec_gamma_montgomery);
2707*f0865ec9SKyle Evans 		alpha_edwards = &(pub_key->params->ec_alpha_edwards);
2708*f0865ec9SKyle Evans 		gen_cofactor = &(pub_key->params->ec_gen_cofactor);
2709*f0865ec9SKyle Evans 		pub_key_y = &(pub_key->y);
2710*f0865ec9SKyle Evans 		key_type = pub_key->key_type;
2711*f0865ec9SKyle Evans 		G = &(pub_key->params->ec_gen);
2712*f0865ec9SKyle Evans 		q_bit_len = pub_key->params->ec_gen_order_bitlen;
2713*f0865ec9SKyle Evans 
2714*f0865ec9SKyle Evans 		/* Check the key type versus the algorithm */
2715*f0865ec9SKyle Evans 		MUST_HAVE((key_type == sig_type), ret, err);
2716*f0865ec9SKyle Evans 
2717*f0865ec9SKyle Evans 		if(i == 0){
2718*f0865ec9SKyle Evans 			/* Initialize our numbers */
2719*f0865ec9SKyle Evans 			ret = nn_init(&z, 0); EG(ret, err);
2720*f0865ec9SKyle Evans 			ret = nn_init(&S, 0); EG(ret, err);
2721*f0865ec9SKyle Evans 			ret = nn_init(&elements[(2 * num)].number, 0); EG(ret, err);
2722*f0865ec9SKyle Evans 			ret = _prj_pt_unprotected_mult(&elements[(2 * num)].point, gen_cofactor, G); EG(ret, err);
2723*f0865ec9SKyle Evans 		}
2724*f0865ec9SKyle Evans 
2725*f0865ec9SKyle Evans gen_z_again:
2726*f0865ec9SKyle Evans 		/* Get a random z for randomizing the linear combination */
2727*f0865ec9SKyle Evans 		ret = nn_get_random_len(&z, (hsize / 4)); EG(ret, err);
2728*f0865ec9SKyle Evans 		ret = nn_iszero(&z, &iszero); EG(ret, err);
2729*f0865ec9SKyle Evans 		if(iszero){
2730*f0865ec9SKyle Evans 			goto gen_z_again;
2731*f0865ec9SKyle Evans 		}
2732*f0865ec9SKyle Evans 
2733*f0865ec9SKyle Evans 		/* Sanity check on hash types */
2734*f0865ec9SKyle Evans 		MUST_HAVE((hash_type == get_eddsa_hash_type(key_type)), ret, err);
2735*f0865ec9SKyle Evans 
2736*f0865ec9SKyle Evans 		/* Check given signature length is the expected one */
2737*f0865ec9SKyle Evans 		siglen = s_len[i];
2738*f0865ec9SKyle Evans 		sig = s[i];
2739*f0865ec9SKyle Evans 		MUST_HAVE((siglen == EDDSA_SIGLEN(hsize)), ret, err);
2740*f0865ec9SKyle Evans 		MUST_HAVE((siglen == (EDDSA_R_LEN(hsize) + EDDSA_S_LEN(hsize))), ret, err);
2741*f0865ec9SKyle Evans 
2742*f0865ec9SKyle Evans 		/* Initialize the hash context */
2743*f0865ec9SKyle Evans 		/* Since we call a callback, sanity check our mapping */
2744*f0865ec9SKyle Evans 		ret = hash_mapping_callbacks_sanity_check(hm); EG(ret, err);
2745*f0865ec9SKyle Evans 		ret = hm->hfunc_init(&h_ctx); EG(ret, err);
2746*f0865ec9SKyle Evans 		ret = hm->hfunc_init(&h_ctx_pre_hash); EG(ret, err);
2747*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA25519)
2748*f0865ec9SKyle Evans 		if(key_type == EDDSA25519CTX){
2749*f0865ec9SKyle Evans 			/* As per RFC8032, for EDDSA25519CTX the context SHOULD NOT be empty */
2750*f0865ec9SKyle Evans 			MUST_HAVE((adata[i] != NULL), ret, err);
2751*f0865ec9SKyle Evans 			ret = dom2(0, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err);
2752*f0865ec9SKyle Evans 		}
2753*f0865ec9SKyle Evans 		if(key_type == EDDSA25519PH){
2754*f0865ec9SKyle Evans 			ret = dom2(1, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err);
2755*f0865ec9SKyle Evans 		}
2756*f0865ec9SKyle Evans #endif
2757*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2758*f0865ec9SKyle Evans 		if(key_type == EDDSA448){
2759*f0865ec9SKyle Evans 			ret = dom4(0, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err);
2760*f0865ec9SKyle Evans 		}
2761*f0865ec9SKyle Evans 		if(key_type == EDDSA448PH){
2762*f0865ec9SKyle Evans 			ret = dom4(1, adata[i], adata_len[i], hm, &h_ctx); EG(ret, err);
2763*f0865ec9SKyle Evans 		}
2764*f0865ec9SKyle Evans #endif
2765*f0865ec9SKyle Evans 		/* Import R and S values from signature buffer */
2766*f0865ec9SKyle Evans 		/*******************************/
2767*f0865ec9SKyle Evans 		/* Import R as an Edwards point */
2768*f0865ec9SKyle Evans 		ret = curve_shortw_to_edwards(shortw_curve, &crv_edwards, alpha_montgomery,
2769*f0865ec9SKyle Evans 					gamma_montgomery, alpha_edwards); EG(ret, err);
2770*f0865ec9SKyle Evans 		/* NOTE: non canonical R are checked and rejected here */
2771*f0865ec9SKyle Evans 		ret = eddsa_decode_point(&R, &crv_edwards, alpha_edwards, &sig[0],
2772*f0865ec9SKyle Evans 				      EDDSA_R_LEN(hsize), key_type); EG(ret, err);
2773*f0865ec9SKyle Evans 		dbg_ec_edwards_point_print("R", &R);
2774*f0865ec9SKyle Evans 		/* Transfer our public point R to Weierstrass */
2775*f0865ec9SKyle Evans 		ret = aff_pt_edwards_to_prj_pt_shortw(&R, shortw_curve, &elements[i].point, alpha_edwards); EG(ret, err);
2776*f0865ec9SKyle Evans 		/* Update the hash with the encoded R */
2777*f0865ec9SKyle Evans 		ret = hm->hfunc_update(&h_ctx, &sig[0], EDDSA_R_LEN(hsize)); EG(ret, err);
2778*f0865ec9SKyle Evans 		/* Store 8 * z in our number to be multiplied with R */
2779*f0865ec9SKyle Evans 		ret = nn_init(&elements[i].number, 0); EG(ret, err);
2780*f0865ec9SKyle Evans 		ret = nn_mul(&elements[i].number, gen_cofactor, &z); EG(ret, err);
2781*f0865ec9SKyle Evans 		ret = nn_mod(&elements[i].number, &elements[i].number, q); EG(ret, err);
2782*f0865ec9SKyle Evans 
2783*f0865ec9SKyle Evans 		/*******************************/
2784*f0865ec9SKyle Evans 		/* Import S as an integer */
2785*f0865ec9SKyle Evans 		ret = eddsa_decode_integer(&S, &sig[EDDSA_R_LEN(hsize)], EDDSA_S_LEN(hsize)); EG(ret, err);
2786*f0865ec9SKyle Evans 		/* Reject S if it is not reduced modulo q */
2787*f0865ec9SKyle Evans 		ret = nn_cmp(&S, q, &cmp); EG(ret, err);
2788*f0865ec9SKyle Evans 		MUST_HAVE((cmp < 0), ret, err);
2789*f0865ec9SKyle Evans 		dbg_nn_print("S", &S);
2790*f0865ec9SKyle Evans 
2791*f0865ec9SKyle Evans 		/* Add (- z S) to the sum */
2792*f0865ec9SKyle Evans 		ret = nn_mul(&S, &S, &z); EG(ret, err);
2793*f0865ec9SKyle Evans 		ret = nn_mod(&S, &S, q); EG(ret, err);
2794*f0865ec9SKyle Evans 		ret = nn_mod_neg(&S, &S, q); EG(ret, err); /* Negate S */
2795*f0865ec9SKyle Evans 		ret = nn_mod_add(&elements[(2 * num)].number, &elements[(2 * num)].number, &S, q); EG(ret, err);
2796*f0865ec9SKyle Evans 
2797*f0865ec9SKyle Evans 		/*******************************/
2798*f0865ec9SKyle Evans 		/* Encode the public key
2799*f0865ec9SKyle Evans 		 * NOTE: since we deal with a public key transfered to Weierstrass,
2800*f0865ec9SKyle Evans 		 * encoding checking has been handled elsewhere.
2801*f0865ec9SKyle Evans 		 */
2802*f0865ec9SKyle Evans 		/* Reject the signature if the public key is one of small order points.
2803*f0865ec9SKyle Evans 		 * We multiply by the cofactor: since this is a public verification,
2804*f0865ec9SKyle Evans 		 * we use a basic double and add algorithm.
2805*f0865ec9SKyle Evans 		 */
2806*f0865ec9SKyle Evans 		ret = _prj_pt_unprotected_mult(&elements[num + i].point, gen_cofactor, pub_key_y); EG(ret, err);
2807*f0865ec9SKyle Evans 		/* Reject the signature if we have point at infinity here as this means
2808*f0865ec9SKyle Evans 		 * that the public key is of small order.
2809*f0865ec9SKyle Evans 		 */
2810*f0865ec9SKyle Evans 		ret = prj_pt_iszero(&elements[num + i].point, &iszero); EG(ret, err);
2811*f0865ec9SKyle Evans 		MUST_HAVE((!iszero), ret, err);
2812*f0865ec9SKyle Evans 
2813*f0865ec9SKyle Evans 		/* Transfer the public key to Edwards */
2814*f0865ec9SKyle Evans 		ret = prj_pt_shortw_to_aff_pt_edwards(pub_key_y, &crv_edwards, &A, alpha_edwards); EG(ret, err);
2815*f0865ec9SKyle Evans 		dbg_ec_edwards_point_print("A", &A);
2816*f0865ec9SKyle Evans 		MUST_HAVE((EDDSA_R_LEN(hsize) <= sizeof(hash)), ret, err);
2817*f0865ec9SKyle Evans 		/* NOTE: we use the hash buffer as a temporary buffer */
2818*f0865ec9SKyle Evans 		ret = eddsa_encode_point(&A, alpha_edwards, hash, EDDSA_R_LEN(hsize), key_type); EG(ret, err);
2819*f0865ec9SKyle Evans 
2820*f0865ec9SKyle Evans 		/* Update the hash with the encoded public key */
2821*f0865ec9SKyle Evans 		ret = hm->hfunc_update(&h_ctx, hash, EDDSA_R_LEN(hsize)); EG(ret, err);
2822*f0865ec9SKyle Evans 		/* Finish our computation of h = H(R || A || M) */
2823*f0865ec9SKyle Evans 		/* Update the hash with the message or its hash for the PH versions */
2824*f0865ec9SKyle Evans 		if(use_message_pre_hash == 1){
2825*f0865ec9SKyle Evans 			ret = hm->hfunc_update(&h_ctx_pre_hash, m[i], m_len[i]); EG(ret, err);
2826*f0865ec9SKyle Evans 			ret = hm->hfunc_finalize(&h_ctx_pre_hash, hash); EG(ret, err);
2827*f0865ec9SKyle Evans 			MUST_HAVE((use_message_pre_hash_hsize <= hsize), ret, err);
2828*f0865ec9SKyle Evans 			ret = hm->hfunc_update(&h_ctx, hash, use_message_pre_hash_hsize); EG(ret, err);
2829*f0865ec9SKyle Evans 		}
2830*f0865ec9SKyle Evans 		else{
2831*f0865ec9SKyle Evans 			ret = hm->hfunc_update(&h_ctx, m[i], m_len[i]); EG(ret, err);
2832*f0865ec9SKyle Evans 		}
2833*f0865ec9SKyle Evans 		ret = hm->hfunc_finalize(&h_ctx, hash); EG(ret, err);
2834*f0865ec9SKyle Evans 		dbg_buf_print("hash = H(R || A || PH(M))", hash, hsize);
2835*f0865ec9SKyle Evans 
2836*f0865ec9SKyle Evans 		/* Import our hash as a NN and reduce it modulo q */
2837*f0865ec9SKyle Evans 		ret = eddsa_decode_integer(&elements[num + i].number, hash, hsize); EG(ret, err);
2838*f0865ec9SKyle Evans 		ret = nn_mod(&elements[num + i].number, &elements[num + i].number, q); EG(ret, err);
2839*f0865ec9SKyle Evans 		dbg_nn_print("h = ", &elements[num + i].number);
2840*f0865ec9SKyle Evans #if defined(WITH_SIG_EDDSA448)
2841*f0865ec9SKyle Evans 		if((key_type == EDDSA448) || (key_type == EDDSA448PH)){
2842*f0865ec9SKyle Evans 			/* When dealing with EDDSA448, because of our 4-isogeny between Edwars448 and Ed448
2843*f0865ec9SKyle Evans 			 * mapping base point to four times base point, we actually multiply our public key by 4 here
2844*f0865ec9SKyle Evans 			 * to be inline with the other computations (the public key stored in Weierstrass )
2845*f0865ec9SKyle Evans 			 */
2846*f0865ec9SKyle Evans 			ret = nn_lshift(&elements[num + i].number, &elements[num + i].number, 2); EG(ret, err);
2847*f0865ec9SKyle Evans 			ret = nn_mod(&elements[num + i].number, &elements[num + i].number, q); EG(ret, err);
2848*f0865ec9SKyle Evans 		}
2849*f0865ec9SKyle Evans #endif
2850*f0865ec9SKyle Evans 		/* Compute by (z * h) mod q.
2851*f0865ec9SKyle Evans 		 */
2852*f0865ec9SKyle Evans 		ret = nn_mul(&elements[num + i].number, &elements[num + i].number, &z); EG(ret, err);
2853*f0865ec9SKyle Evans 		ret = nn_mod(&elements[num + i].number, &elements[num + i].number, q); EG(ret, err);
2854*f0865ec9SKyle Evans 	}
2855*f0865ec9SKyle Evans 
2856*f0865ec9SKyle Evans 	/* Sanity check */
2857*f0865ec9SKyle Evans 	MUST_HAVE((gen_cofactor != NULL) && (q != NULL) && (G != NULL) && (q_bit_len != 0), ret, err);
2858*f0865ec9SKyle Evans 
2859*f0865ec9SKyle Evans 	/********************************************/
2860*f0865ec9SKyle Evans 	/****** Bos-Coster algorithm ****************/
2861*f0865ec9SKyle Evans 	ret = ec_verify_bos_coster(elements, (2 * num) + 1, q_bit_len);
2862*f0865ec9SKyle Evans         if(ret){
2863*f0865ec9SKyle Evans                 if(ret == -2){
2864*f0865ec9SKyle Evans                         /* In case of Bos-Coster time out, we fall back to the
2865*f0865ec9SKyle Evans                          * slower regular batch verification.
2866*f0865ec9SKyle Evans                          */
2867*f0865ec9SKyle Evans                         ret = _eddsa_verify_batch_no_memory(s, s_len, pub_keys, m, m_len, num, sig_type,
2868*f0865ec9SKyle Evans                                                             hash_type, adata, adata_len); EG(ret, err);
2869*f0865ec9SKyle Evans                 }
2870*f0865ec9SKyle Evans                 goto err;
2871*f0865ec9SKyle Evans         }
2872*f0865ec9SKyle Evans 
2873*f0865ec9SKyle Evans 	/* The first element should contain the sum: it should
2874*f0865ec9SKyle Evans 	 * be equal to zero. Reject the signature if this is not
2875*f0865ec9SKyle Evans 	 * the case.
2876*f0865ec9SKyle Evans 	 */
2877*f0865ec9SKyle Evans 	ret = prj_pt_iszero(&elements[elements[0].index].point, &iszero); EG(ret, err);
2878*f0865ec9SKyle Evans 	ret = iszero ? 0 : -1;
2879*f0865ec9SKyle Evans 
2880*f0865ec9SKyle Evans err:
2881*f0865ec9SKyle Evans 	PTR_NULLIFY(q);
2882*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key);
2883*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key0);
2884*f0865ec9SKyle Evans 	PTR_NULLIFY(shortw_curve);
2885*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_montgomery);
2886*f0865ec9SKyle Evans 	PTR_NULLIFY(gamma_montgomery);
2887*f0865ec9SKyle Evans 	PTR_NULLIFY(alpha_edwards);
2888*f0865ec9SKyle Evans 	PTR_NULLIFY(gen_cofactor);
2889*f0865ec9SKyle Evans 	PTR_NULLIFY(pub_key_y);
2890*f0865ec9SKyle Evans 	PTR_NULLIFY(G);
2891*f0865ec9SKyle Evans 	PTR_NULLIFY(elements);
2892*f0865ec9SKyle Evans 
2893*f0865ec9SKyle Evans 	/* Unitialize all our scratch_pad_area */
2894*f0865ec9SKyle Evans 	if((scratch_pad_area != NULL) && (scratch_pad_area_len != NULL)){
2895*f0865ec9SKyle Evans 		IGNORE_RET_VAL(local_memset((u8*)scratch_pad_area, 0, (*scratch_pad_area_len)));
2896*f0865ec9SKyle Evans 	}
2897*f0865ec9SKyle Evans 
2898*f0865ec9SKyle Evans 	ec_edwards_crv_uninit(&crv_edwards);
2899*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&A);
2900*f0865ec9SKyle Evans 	aff_pt_edwards_uninit(&R);
2901*f0865ec9SKyle Evans 	nn_uninit(&S);
2902*f0865ec9SKyle Evans 	nn_uninit(&z);
2903*f0865ec9SKyle Evans 
2904*f0865ec9SKyle Evans 	return ret;
2905*f0865ec9SKyle Evans }
2906*f0865ec9SKyle Evans 
2907*f0865ec9SKyle Evans int eddsa_verify_batch(const u8 **s, const u8 *s_len, const ec_pub_key **pub_keys,
2908*f0865ec9SKyle Evans                        const u8 **m, const u32 *m_len, u32 num, ec_alg_type sig_type,
2909*f0865ec9SKyle Evans                        hash_alg_type hash_type, const u8 **adata, const u16 *adata_len,
2910*f0865ec9SKyle Evans                        verify_batch_scratch_pad *scratch_pad_area, u32 *scratch_pad_area_len)
2911*f0865ec9SKyle Evans {
2912*f0865ec9SKyle Evans         int ret;
2913*f0865ec9SKyle Evans 
2914*f0865ec9SKyle Evans         if(scratch_pad_area != NULL){
2915*f0865ec9SKyle Evans                 MUST_HAVE((scratch_pad_area_len != NULL), ret, err);
2916*f0865ec9SKyle Evans                 ret = _eddsa_verify_batch(s, s_len, pub_keys, m, m_len, num, sig_type,
2917*f0865ec9SKyle Evans                                           hash_type, adata, adata_len,
2918*f0865ec9SKyle Evans                                           scratch_pad_area, scratch_pad_area_len); EG(ret, err);
2919*f0865ec9SKyle Evans         }
2920*f0865ec9SKyle Evans         else{
2921*f0865ec9SKyle Evans                 ret = _eddsa_verify_batch_no_memory(s, s_len, pub_keys, m, m_len, num, sig_type,
2922*f0865ec9SKyle Evans                                                     hash_type, adata, adata_len); EG(ret, err);
2923*f0865ec9SKyle Evans         }
2924*f0865ec9SKyle Evans 
2925*f0865ec9SKyle Evans err:
2926*f0865ec9SKyle Evans         return ret;
2927*f0865ec9SKyle Evans }
2928*f0865ec9SKyle Evans 
2929*f0865ec9SKyle Evans #else /* !(defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448)) */
2930*f0865ec9SKyle Evans 
2931*f0865ec9SKyle Evans /*
2932*f0865ec9SKyle Evans  * Dummy definition to avoid the empty translation unit ISO C warning
2933*f0865ec9SKyle Evans  */
2934*f0865ec9SKyle Evans typedef int dummy;
2935*f0865ec9SKyle Evans #endif /* defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448) */
2936