xref: /freebsd/crypto/libecc/include/libecc/nn/nn_config.h (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
1 /*
2  *  Copyright (C) 2017 - This file is part of libecc project
3  *
4  *  Authors:
5  *      Ryad BENADJILA <ryadbenadjila@gmail.com>
6  *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7  *      Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8  *
9  *  Contributors:
10  *      Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11  *      Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12  *
13  *  This software is licensed under a dual BSD and GPL v2 license.
14  *  See LICENSE file at the root folder of the project.
15  */
16 #ifndef __NN_CONFIG_H__
17 #define __NN_CONFIG_H__
18 #include <libecc/words/words.h>
19 /*
20  * We include the curves list to adapt the maximum NN size to P and Q
21  * (prime and order of the curve).
22  */
23 #include <libecc/curves/curves_list.h>
24 /*
25  * We also include the hash layer to adapt the maximum NN size to the
26  * maximum digest size as we have to import full digests as NN when dealing
27  * with some signature algorithms.
28  *
29  */
30 #include <libecc/hash/hash_algs.h>
31 
32 /*
33  * All the big num used in the lib are statically allocated. This constant
34  * must be defined (here or during build) to provide an upper limit on the
35  * size in bits of the numbers the instance of the lib you will build will
36  * handle. Note that this value does not prevent the declaration and use
37  * of smaller numbers.
38  *
39  * Rationale for the default value: the main purpose of the lirary is to
40  * support for an ECC implementation. ATM, a forseeable upper limit for the
41  * numbers that will be dealt with is 521 bits.
42  *
43  * However, the user is allowed to overload the maximum bit length of the
44  * numbers through the USER_NN_BIT_LEN macro definition (see below). A
45  * hard limit 'nn_max' for this size depends on the word size and verifies
46  * the following equation (with w being the word size):
47  *
48  *             floor((nn_max + w - 1) / w) * 3 = 255
49  *
50  * This equation is explained by elements given below, and by the fact that
51  * the length in words of our big numbers are encoded on an u8. This yields
52  * in max sizes of around 5300 bits for 64-bit words, around 2650 bits for
53  * 32-bit words, and around 1300 bits for 16-bit words.
54  *
55  * Among all the functions we have, some need to handle something which
56  * can be seen as a double, so we need twice the amount of bit above.
57  * This is typically the case when two numbers are multiplied.
58  * But then you usually want to divide this product by another number
59  * of the initial size which generically requires shifting by the
60  * original sized, whence the factor 3 below.
61  *
62  * Additionally, all numbers we handled are expected to have a length which
63  * is a multiple of the word size we support, i.e. 64/32/16 bits. Hence the
64  * rounding.
65  */
66 
67 /* Macro to round a bit length size to a word size */
68 #define BIT_LEN_ROUNDING(x, w) ((((x) + (w) - 1) / (w)) * (w))
69 
70 /*
71  * Macro to round a bit length size of a NN value to a word size, and
72  * to a size compatible with the arithmetic operations of the library
73  * (usually 3 times the size of the input numbers, see explanations above).
74  */
75 #define MAX_BIT_LEN_ROUNDING(x, w) (((((x) + (w) - 1) / (w)) * (w)) * 3)
76 
77 #ifndef USER_NN_BIT_LEN
78 /*
79  * The user has not defined a specific bit length: we can infer our maximum
80  * NN bit size from our curves.
81  */
82 #ifndef NN_MAX_BIT_LEN
83 #if CURVES_MAX_P_BIT_LEN >= CURVES_MAX_CURVE_ORDER_BIT_LEN
84 #define NN_MAX_BIT_LEN MAX_BIT_LEN_ROUNDING(CURVES_MAX_P_BIT_LEN, WORD_BITS)
85 #define NN_MAX_BASE CURVES_MAX_P_BIT_LEN
86 #else
87 #define NN_MAX_BIT_LEN MAX_BIT_LEN_ROUNDING(CURVES_MAX_CURVE_ORDER_BIT_LEN, WORD_BITS)
88 #define NN_MAX_BASE CURVES_MAX_CURVE_ORDER_BIT_LEN
89 #endif
90 #endif
91 /****************/
92 #else
93 /*
94  * If the USER_NN_BIT_LEN flag is defined by the user, we want to be sure that
95  * we can also handle our curves, and we also want to round the size to the
96  * words we have.
97  */
98 #if CURVES_MAX_P_BIT_LEN >= CURVES_MAX_CURVE_ORDER_BIT_LEN
99 #if USER_NN_BIT_LEN >= CURVES_MAX_P_BIT_LEN
100 #define NN_MAX_BIT_LEN MAX_BIT_LEN_ROUNDING(USER_NN_BIT_LEN, WORD_BITS)
101 #define NN_MAX_BASE USER_NN_BIT_LEN
102 #else
103 #define NN_MAX_BIT_LEN MAX_BIT_LEN_ROUNDING(CURVES_MAX_P_BIT_LEN, WORD_BITS)
104 #define NN_MAX_BASE CURVES_MAX_P_BIT_LEN
105 #endif
106 #else
107 #if USER_NN_BIT_LEN >= CURVES_MAX_CURVE_ORDER_BIT_LEN
108 #define NN_MAX_BIT_LEN MAX_BIT_LEN_ROUNDING(USER_NN_BIT_LEN, WORD_BITS)
109 #define NN_MAX_BASE USER_NN_BIT_LEN
110 #else
111 #define NN_MAX_BIT_LEN MAX_BIT_LEN_ROUNDING(CURVES_MAX_CURVE_ORDER_BIT_LEN, WORD_BITS)
112 #define NN_MAX_BASE CURVES_MAX_CURVE_ORDER_BIT_LEN
113 #endif
114 #endif
115 #endif
116 
117 /* Now adjust the maximum length with our maximum digest size as we
118  * have to import full digests as big numbers in some signature algorithms.
119  *
120  * The division by 2 here is related to the fact that we usually import hash values
121  * without performing much NN operations on them (immediately reducing them modulo q), so
122  * it is safe to remove some additional space left for multiplications.
123  */
124 #if NN_MAX_BIT_LEN < MAX_BIT_LEN_ROUNDING(((8 * MAX_DIGEST_SIZE) / 2), WORD_BITS)
125 #undef NN_MAX_BIT_LEN
126 #define NN_MAX_BIT_LEN MAX_BIT_LEN_ROUNDING(((8 * MAX_DIGEST_SIZE) / 2), WORD_BITS)
127 #undef NN_MAX_BASE
128 #define NN_MAX_BASE MAX_DIGEST_SIZE_BITS
129 #endif
130 /*
131  * NOTE: the only exception to the rule above (i.e. immediately reducing hash sized
132  * values modulo q) is when we use blinding and EdDSA and there might be not enough
133  * room for our computations. This is actually *specific to EdDSA 25519* as EdDSA 448
134  * always uses SHAKE256 digest with 114 bytes hash output that has enough room for
135  * computation when compared to the 448-bit size order of the curve.
136  *
137  * This is kind of ugly to have this specific case here, but
138  * being too conservative always using the maximum size adapated to MAX_DIGEST_SIZE
139  * sacrifices *ALL* the sognature performance only for the specific case of EdDSA 25519!
140  *
141  */
142 #if defined(WITH_SIG_EDDSA25519) && defined(USE_SIG_BLINDING)
143 #if NN_MAX_BIT_LEN < MAX_BIT_LEN_ROUNDING((8 * SHA512_DIGEST_SIZE), WORD_BITS)
144 #undef NN_MAX_BIT_LEN
145 #define NN_MAX_BIT_LEN MAX_BIT_LEN_ROUNDING((8 * SHA512_DIGEST_SIZE), WORD_BITS)
146 #undef NN_MAX_BASE
147 #define NN_MAX_BASE MAX_DIGEST_SIZE_BITS
148 #endif
149 #endif /* defined(WITH_SIG_EDDSA25519) && defined(USE_SIG_BLINDING) */
150 
151 /************/
152 /* NN maximum internal lengths to be "safe" in our computations */
153 #define NN_MAX_BYTE_LEN (NN_MAX_BIT_LEN / 8)
154 #define NN_MAX_WORD_LEN (NN_MAX_BYTE_LEN / WORD_BYTES)
155 /* Usable maximum sizes, to be used by the end user to be "safe" in
156  * all the computations.
157  */
158 #define NN_USABLE_MAX_BIT_LEN  (NN_MAX_BASE)
159 #define NN_USABLE_MAX_BYTE_LEN ((BIT_LEN_ROUNDING(NN_USABLE_MAX_BIT_LEN, 8)) / 8)
160 #define NN_USABLE_MAX_WORD_LEN ((BIT_LEN_ROUNDING(NN_USABLE_MAX_BIT_LEN, WORD_BITS)) / WORD_BITS)
161 
162 /* Sanity checks */
163 #if (NN_USABLE_MAX_BIT_LEN > NN_MAX_BIT_LEN) || (NN_USABLE_MAX_BYTE_LEN > NN_MAX_BYTE_LEN) || (NN_USABLE_MAX_WORD_LEN > NN_MAX_WORD_LEN)
164 #error "usable maximum length > internal maximum length, this should not happen!"
165 #endif
166 
167 #if (NN_MAX_WORD_LEN > 255)
168 #error "nn.wlen is encoded on an u8. NN_MAX_WORD_LEN cannot be larger than 255!"
169 #endif
170 
171 /* Add a (somehow 'dirty' but working and useful!) way to detect when our .a
172  * library has been compiled with options (WORDSIZE and NN_MAX_BIT_LEN)
173  * inconsistent with the 'final' binary we want to compile linking to the .a
174  * archive. The 'magic' lies in the definition in nn.c of a function (symbol)
175  * in our .a archive, consisting in a concatenation of WORDSIZE and
176  * NN_MAX_BIT_LEN preprocessed values. On the other side, we force the use
177  * of this symbol in other NN .c modules, yielding in a compile time error
178  * if WORDSIZE or NN_MAX_BIT_LEN differ.
179  * Update: we also check here the consistency of using complete formulas
180  * or not.
181  */
182 #ifdef NO_USE_COMPLETE_FORMULAS
183 #define _LIBECC_CONCATENATE(a, b, c, d, e) a##_##b##_##c##_##d##_##e
184 #define LIBECC_CONCATENATE(a, b, c, d, e) _LIBECC_CONCATENATE(a, b, c, d, e)
185 void LIBECC_CONCATENATE(nn_consistency_check_maxbitlen, NN_MAX_BASE, wordsize,
186 		 WORDSIZE, MAX_DIGEST_SIZE) (void);
187 #ifdef NN_CONSISTENCY_CHECK
LIBECC_CONCATENATE(nn_consistency_check_maxbitlen,NN_MAX_BASE,wordsize,WORDSIZE,MAX_DIGEST_SIZE)188 ATTRIBUTE_USED void LIBECC_CONCATENATE(nn_consistency_check_maxbitlen, NN_MAX_BASE,
189 				wordsize, WORDSIZE, MAX_DIGEST_SIZE) (void) {
190 	return;
191 }
192 #else
nn_check_libconsistency(void)193 ATTRIBUTE_USED static inline void nn_check_libconsistency(void)
194 {
195 	LIBECC_CONCATENATE(nn_consistency_check_maxbitlen, NN_MAX_BASE, wordsize,
196 		    WORDSIZE, MAX_DIGEST_SIZE) ();
197 	return;
198 }
199 #endif
200 #else /* NO_USE_COMPLETE_FORMULAS */
201 #define _LIBECC_CONCATENATE(a, b, c, d, e, f) a##_##b##_##c##_##d##_##e##_##f
202 #define LIBECC_CONCATENATE(a, b, c, d, e, f) _LIBECC_CONCATENATE(a, b, c, d, e, f)
203 void LIBECC_CONCATENATE(nn_consistency_check_maxbitlen, NN_MAX_BASE, wordsize,
204 		 WORDSIZE, complete_formulas, MAX_DIGEST_SIZE) (void);
205 #ifdef NN_CONSISTENCY_CHECK
LIBECC_CONCATENATE(nn_consistency_check_maxbitlen,NN_MAX_BASE,wordsize,WORDSIZE,complete_formulas,MAX_DIGEST_SIZE)206 ATTRIBUTE_USED void LIBECC_CONCATENATE(nn_consistency_check_maxbitlen, NN_MAX_BASE,
207 				wordsize, WORDSIZE, complete_formulas, MAX_DIGEST_SIZE) (void) {
208 	return;
209 }
210 #else
nn_check_libconsistency(void)211 ATTRIBUTE_USED static inline void nn_check_libconsistency(void)
212 {
213 	LIBECC_CONCATENATE(nn_consistency_check_maxbitlen, NN_MAX_BASE, wordsize,
214 		    WORDSIZE, complete_formulas, MAX_DIGEST_SIZE) ();
215 	return;
216 }
217 #endif
218 #endif /* NO_USE_COMPLETE_FORMULAS */
219 
220 #endif /* __NN_CONFIG_H__ */
221