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