]>
Commit | Line | Data |
---|---|---|
1308e022 | 1 | /* |
3c2bdd7d | 2 | * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. |
1308e022 | 3 | * Copyright 2015-2016 Cryptography Research, Inc. |
7324473f | 4 | * |
a7f182b7 | 5 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
1308e022 MC |
6 | * this file except in compliance with the License. You can obtain a copy |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
7324473f | 9 | * |
1308e022 | 10 | * Originally written by Mike Hamburg |
7324473f MC |
11 | */ |
12 | ||
ae4186b0 DMSP |
13 | #ifndef OSSL_CRYPTO_EC_CURVE448_POINT_448_H |
14 | # define OSSL_CRYPTO_EC_CURVE448_POINT_448_H | |
7324473f | 15 | |
205fd638 MC |
16 | # include "curve448utils.h" |
17 | # include "field.h" | |
7324473f | 18 | |
9fd3c858 MC |
19 | /* Comb config: number of combs, n, t, s. */ |
20 | #define COMBS_N 5 | |
21 | #define COMBS_T 5 | |
22 | #define COMBS_S 18 | |
23 | ||
24 | /* Projective Niels coordinates */ | |
25 | typedef struct { | |
26 | gf a, b, c; | |
27 | } niels_s, niels_t[1]; | |
28 | typedef struct { | |
29 | niels_t n; | |
30 | gf z; | |
2abe3cad | 31 | } pniels_t[1]; |
9fd3c858 MC |
32 | |
33 | /* Precomputed base */ | |
34 | struct curve448_precomputed_s { | |
35 | niels_t table[COMBS_N << (COMBS_T - 1)]; | |
36 | }; | |
7324473f | 37 | |
db90b274 | 38 | # define C448_SCALAR_LIMBS ((446-1)/C448_WORD_BITS+1) |
7324473f | 39 | |
8d55f844 | 40 | /* The number of bits in a scalar */ |
db90b274 | 41 | # define C448_SCALAR_BITS 446 |
7324473f | 42 | |
8d55f844 | 43 | /* Number of bytes in a serialized scalar. */ |
db90b274 | 44 | # define C448_SCALAR_BYTES 56 |
7324473f | 45 | |
8d55f844 | 46 | /* X448 encoding ratio. */ |
db90b274 | 47 | # define X448_ENCODE_RATIO 2 |
7324473f | 48 | |
8d55f844 | 49 | /* Number of bytes in an x448 public key */ |
db90b274 | 50 | # define X448_PUBLIC_BYTES 56 |
7324473f | 51 | |
8d55f844 | 52 | /* Number of bytes in an x448 private key */ |
db90b274 | 53 | # define X448_PRIVATE_BYTES 56 |
7324473f | 54 | |
8d55f844 | 55 | /* Twisted Edwards extended homogeneous coordinates */ |
e7772577 | 56 | typedef struct curve448_point_s { |
35b7c85a | 57 | gf x, y, z, t; |
e7772577 | 58 | } curve448_point_t[1]; |
7324473f | 59 | |
8d55f844 | 60 | /* Precomputed table based on a point. Can be trivial implementation. */ |
e7772577 | 61 | struct curve448_precomputed_s; |
7324473f | 62 | |
8d55f844 | 63 | /* Precomputed table based on a point. Can be trivial implementation. */ |
205fd638 | 64 | typedef struct curve448_precomputed_s curve448_precomputed_s; |
7324473f | 65 | |
8d55f844 | 66 | /* Scalar is stored packed, because we don't need the speed. */ |
e7772577 | 67 | typedef struct curve448_scalar_s { |
db90b274 | 68 | c448_word_t limb[C448_SCALAR_LIMBS]; |
e7772577 | 69 | } curve448_scalar_t[1]; |
7324473f | 70 | |
8d55f844 | 71 | /* A scalar equal to 1. */ |
054d43ff | 72 | extern const curve448_scalar_t ossl_curve448_scalar_one; |
7324473f | 73 | |
8d55f844 | 74 | /* A scalar equal to 0. */ |
054d43ff | 75 | extern const curve448_scalar_t ossl_curve448_scalar_zero; |
7324473f | 76 | |
8d55f844 | 77 | /* The identity point on the curve. */ |
054d43ff | 78 | extern const curve448_point_t ossl_curve448_point_identity; |
7324473f | 79 | |
8d55f844 | 80 | /* Precomputed table for the base point on the curve. */ |
054d43ff SL |
81 | extern const struct curve448_precomputed_s *ossl_curve448_precomputed_base; |
82 | extern const niels_t *ossl_curve448_wnaf_base; | |
7324473f | 83 | |
8d55f844 MC |
84 | /* |
85 | * Read a scalar from wire format or from bytes. | |
7324473f | 86 | * |
8d55f844 MC |
87 | * ser (in): Serialized form of a scalar. |
88 | * out (out): Deserialized form. | |
7324473f | 89 | * |
8d55f844 | 90 | * Returns: |
aeeef83c MC |
91 | * C448_SUCCESS: The scalar was correctly encoded. |
92 | * C448_FAILURE: The scalar was greater than the modulus, and has been reduced | |
8d55f844 | 93 | * modulo that modulus. |
7324473f | 94 | */ |
054d43ff SL |
95 | c448_error_t |
96 | ossl_curve448_scalar_decode(curve448_scalar_t out, | |
97 | const unsigned char ser[C448_SCALAR_BYTES]); | |
8d55f844 MC |
98 | |
99 | /* | |
100 | * Read a scalar from wire format or from bytes. Reduces mod scalar prime. | |
7324473f | 101 | * |
8d55f844 MC |
102 | * ser (in): Serialized form of a scalar. |
103 | * ser_len (in): Length of serialized form. | |
104 | * out (out): Deserialized form. | |
7324473f | 105 | */ |
054d43ff SL |
106 | void |
107 | ossl_curve448_scalar_decode_long(curve448_scalar_t out, | |
205fd638 MC |
108 | const unsigned char *ser, size_t ser_len); |
109 | ||
8d55f844 MC |
110 | /* |
111 | * Serialize a scalar to wire format. | |
7324473f | 112 | * |
8d55f844 MC |
113 | * ser (out): Serialized form of a scalar. |
114 | * s (in): Deserialized scalar. | |
7324473f | 115 | */ |
054d43ff SL |
116 | void |
117 | ossl_curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], | |
205fd638 MC |
118 | const curve448_scalar_t s); |
119 | ||
8d55f844 | 120 | /* |
53ef3252 | 121 | * Add two scalars. |a|, |b| and |out| may alias each other. |
df443918 | 122 | * |
8d55f844 MC |
123 | * a (in): One scalar. |
124 | * b (in): Another scalar. | |
125 | * out (out): a+b. | |
7324473f | 126 | */ |
054d43ff SL |
127 | void |
128 | ossl_curve448_scalar_add(curve448_scalar_t out, | |
205fd638 | 129 | const curve448_scalar_t a, const curve448_scalar_t b); |
7324473f | 130 | |
8d55f844 | 131 | /* |
53ef3252 | 132 | * Subtract two scalars. |a|, |b| and |out| may alias each other. |
8d55f844 MC |
133 | * a (in): One scalar. |
134 | * b (in): Another scalar. | |
135 | * out (out): a-b. | |
205fd638 | 136 | */ |
054d43ff SL |
137 | void |
138 | ossl_curve448_scalar_sub(curve448_scalar_t out, | |
205fd638 | 139 | const curve448_scalar_t a, const curve448_scalar_t b); |
7324473f | 140 | |
8d55f844 | 141 | /* |
53ef3252 | 142 | * Multiply two scalars. |a|, |b| and |out| may alias each other. |
df443918 | 143 | * |
8d55f844 MC |
144 | * a (in): One scalar. |
145 | * b (in): Another scalar. | |
146 | * out (out): a*b. | |
205fd638 | 147 | */ |
054d43ff SL |
148 | void |
149 | ossl_curve448_scalar_mul(curve448_scalar_t out, | |
205fd638 MC |
150 | const curve448_scalar_t a, const curve448_scalar_t b); |
151 | ||
8d55f844 | 152 | /* |
53ef3252 | 153 | * Halve a scalar. |a| and |out| may alias each other. |
df443918 | 154 | * |
8d55f844 MC |
155 | * a (in): A scalar. |
156 | * out (out): a/2. | |
7324473f | 157 | */ |
054d43ff SL |
158 | void |
159 | ossl_curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a); | |
7324473f | 160 | |
8d55f844 | 161 | /* |
a4e6dd81 | 162 | * Copy a scalar. The scalars may alias each other, in which case this |
8d55f844 | 163 | * function does nothing. |
df443918 | 164 | * |
8d55f844 MC |
165 | * a (in): A scalar. |
166 | * out (out): Will become a copy of a. | |
7324473f | 167 | */ |
205fd638 MC |
168 | static ossl_inline void curve448_scalar_copy(curve448_scalar_t out, |
169 | const curve448_scalar_t a) | |
170 | { | |
7324473f MC |
171 | *out = *a; |
172 | } | |
173 | ||
8d55f844 MC |
174 | /* |
175 | * Copy a point. The input and output may alias, in which case this function | |
176 | * does nothing. | |
7324473f | 177 | * |
8d55f844 MC |
178 | * a (out): A copy of the point. |
179 | * b (in): Any point. | |
7324473f | 180 | */ |
205fd638 MC |
181 | static ossl_inline void curve448_point_copy(curve448_point_t a, |
182 | const curve448_point_t b) | |
183 | { | |
184 | *a = *b; | |
7324473f MC |
185 | } |
186 | ||
8d55f844 | 187 | /* |
aeeef83c MC |
188 | * Test whether two points are equal. If yes, return C448_TRUE, else return |
189 | * C448_FALSE. | |
7324473f | 190 | * |
8d55f844 MC |
191 | * a (in): A point. |
192 | * b (in): Another point. | |
df443918 | 193 | * |
8d55f844 | 194 | * Returns: |
aeeef83c MC |
195 | * C448_TRUE: The points are equal. |
196 | * C448_FALSE: The points are not equal. | |
7324473f | 197 | */ |
054d43ff SL |
198 | __owur c448_bool_t |
199 | ossl_curve448_point_eq(const curve448_point_t a, | |
200 | const curve448_point_t b); | |
7324473f | 201 | |
8d55f844 MC |
202 | /* |
203 | * Double a point. Equivalent to curve448_point_add(two_a,a,a), but potentially | |
204 | * faster. | |
7324473f | 205 | * |
8d55f844 MC |
206 | * two_a (out): The sum a+a. |
207 | * a (in): A point. | |
7324473f | 208 | */ |
054d43ff SL |
209 | void |
210 | ossl_curve448_point_double(curve448_point_t two_a, const curve448_point_t a); | |
7324473f | 211 | |
8d55f844 MC |
212 | /* |
213 | * RFC 7748 Diffie-Hellman scalarmul. This function uses a different | |
7324473f MC |
214 | * (non-Decaf) encoding. |
215 | * | |
8d55f844 MC |
216 | * out (out): The scaled point base*scalar |
217 | * base (in): The point to be scaled. | |
218 | * scalar (in): The scalar to multiply by. | |
7324473f | 219 | * |
8d55f844 | 220 | * Returns: |
aeeef83c MC |
221 | * C448_SUCCESS: The scalarmul succeeded. |
222 | * C448_FAILURE: The scalarmul didn't succeed, because the base point is in a | |
8d55f844 | 223 | * small subgroup. |
7324473f | 224 | */ |
054d43ff SL |
225 | __owur c448_error_t |
226 | ossl_x448_int(uint8_t out[X448_PUBLIC_BYTES], | |
227 | const uint8_t base[X448_PUBLIC_BYTES], | |
228 | const uint8_t scalar[X448_PRIVATE_BYTES]); | |
7324473f | 229 | |
8d55f844 | 230 | /* |
db90b274 | 231 | * Multiply a point by X448_ENCODE_RATIO, then encode it like RFC 7748. |
7324473f MC |
232 | * |
233 | * This function is mainly used internally, but is exported in case | |
234 | * it will be useful. | |
235 | * | |
236 | * The ratio is necessary because the internal representation doesn't | |
237 | * track the cofactor information, so on output we must clear the cofactor. | |
aeeef83c MC |
238 | * This would multiply by the cofactor, but in fact internally points are always |
239 | * even, so it multiplies by half the cofactor instead. | |
7324473f MC |
240 | * |
241 | * As it happens, this aligns with the base point definitions; that is, | |
242 | * if you pass the Decaf/Ristretto base point to this function, the result | |
db90b274 | 243 | * will be X448_ENCODE_RATIO times the X448 |
7324473f MC |
244 | * base point. |
245 | * | |
8d55f844 MC |
246 | * out (out): The scaled and encoded point. |
247 | * p (in): The point to be scaled and encoded. | |
7324473f | 248 | */ |
054d43ff SL |
249 | void |
250 | ossl_curve448_point_mul_by_ratio_and_encode_like_x448( | |
db90b274 | 251 | uint8_t out[X448_PUBLIC_BYTES], |
8d55f844 | 252 | const curve448_point_t p); |
7324473f | 253 | |
8d55f844 MC |
254 | /* |
255 | * RFC 7748 Diffie-Hellman base point scalarmul. This function uses a different | |
256 | * (non-Decaf) encoding. | |
df443918 | 257 | * |
8d55f844 MC |
258 | * out (out): The scaled point base*scalar |
259 | * scalar (in): The scalar to multiply by. | |
7324473f | 260 | */ |
054d43ff SL |
261 | void |
262 | ossl_x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES], | |
db90b274 | 263 | const uint8_t scalar[X448_PRIVATE_BYTES]); |
8d55f844 MC |
264 | |
265 | /* | |
266 | * Multiply a precomputed base point by a scalar: out = scalar*base. | |
7324473f | 267 | * |
8d55f844 MC |
268 | * scaled (out): The scaled point base*scalar |
269 | * base (in): The point to be scaled. | |
270 | * scalar (in): The scalar to multiply by. | |
7324473f | 271 | */ |
054d43ff SL |
272 | void |
273 | ossl_curve448_precomputed_scalarmul(curve448_point_t scaled, | |
205fd638 MC |
274 | const curve448_precomputed_s * base, |
275 | const curve448_scalar_t scalar); | |
7324473f | 276 | |
8d55f844 MC |
277 | /* |
278 | * Multiply two base points by two scalars: | |
279 | * combo = scalar1*curve448_point_base + scalar2*base2. | |
7324473f | 280 | * |
e7772577 | 281 | * Otherwise equivalent to curve448_point_double_scalarmul, but may be |
7324473f MC |
282 | * faster at the expense of being variable time. |
283 | * | |
8d55f844 MC |
284 | * combo (out): The linear combination scalar1*base + scalar2*base2. |
285 | * scalar1 (in): A first scalar to multiply by. | |
286 | * base2 (in): A second point to be scaled. | |
287 | * scalar2 (in) A second scalar to multiply by. | |
7324473f | 288 | * |
df443918 | 289 | * Warning: This function takes variable time, and may leak the scalars used. |
8d55f844 | 290 | * It is designed for signature verification. |
7324473f | 291 | */ |
054d43ff SL |
292 | void |
293 | ossl_curve448_base_double_scalarmul_non_secret(curve448_point_t combo, | |
205fd638 MC |
294 | const curve448_scalar_t scalar1, |
295 | const curve448_point_t base2, | |
296 | const curve448_scalar_t scalar2); | |
7324473f | 297 | |
8d55f844 MC |
298 | /* |
299 | * Test that a point is valid, for debugging purposes. | |
7324473f | 300 | * |
8d55f844 MC |
301 | * to_test (in): The point to test. |
302 | * | |
303 | * Returns: | |
aeeef83c MC |
304 | * C448_TRUE The point is valid. |
305 | * C448_FALSE The point is invalid. | |
7324473f | 306 | */ |
054d43ff SL |
307 | __owur c448_bool_t |
308 | ossl_curve448_point_valid(const curve448_point_t to_test); | |
7324473f | 309 | |
8d55f844 | 310 | /* Overwrite scalar with zeros. */ |
054d43ff | 311 | void ossl_curve448_scalar_destroy(curve448_scalar_t scalar); |
7324473f | 312 | |
8d55f844 | 313 | /* Overwrite point with zeros. */ |
054d43ff | 314 | void ossl_curve448_point_destroy(curve448_point_t point); |
7324473f | 315 | |
ae4186b0 | 316 | #endif /* OSSL_CRYPTO_EC_CURVE448_POINT_448_H */ |