1 /*
2 * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright 2015-2016 Cryptography Research, Inc.
4 *
5 * Licensed under the Apache License 2.0 (the "License"). You may not use
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
9 *
10 * Originally written by Mike Hamburg
11 */
12 #include <string.h>
13 #include <openssl/crypto.h>
14 #include <openssl/evp.h>
15 #include "crypto/ecx.h"
16 #include "curve448_local.h"
17 #include "word.h"
18 #include "ed448.h"
19 #include "internal/numbers.h"
20
21 #define COFACTOR 4
22
oneshot_hash(OSSL_LIB_CTX * ctx,uint8_t * out,size_t outlen,const uint8_t * in,size_t inlen,const char * propq)23 static c448_error_t oneshot_hash(OSSL_LIB_CTX *ctx, uint8_t *out, size_t outlen,
24 const uint8_t *in, size_t inlen,
25 const char *propq)
26 {
27 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
28 EVP_MD *shake256 = NULL;
29 c448_error_t ret = C448_FAILURE;
30
31 if (hashctx == NULL)
32 return C448_FAILURE;
33
34 shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq);
35 if (shake256 == NULL)
36 goto err;
37
38 if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
39 || !EVP_DigestUpdate(hashctx, in, inlen)
40 || !EVP_DigestFinalXOF(hashctx, out, outlen))
41 goto err;
42
43 ret = C448_SUCCESS;
44 err:
45 EVP_MD_CTX_free(hashctx);
46 EVP_MD_free(shake256);
47 return ret;
48 }
49
clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])50 static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
51 {
52 secret_scalar_ser[0] &= -COFACTOR;
53 secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 1] = 0;
54 secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80;
55 }
56
hash_init_with_dom(OSSL_LIB_CTX * ctx,EVP_MD_CTX * hashctx,uint8_t prehashed,uint8_t for_prehash,const uint8_t * context,size_t context_len,const char * propq)57 static c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx,
58 uint8_t prehashed,
59 uint8_t for_prehash,
60 const uint8_t *context,
61 size_t context_len,
62 const char *propq)
63 {
64 /* ASCII: "SigEd448", in hex for EBCDIC compatibility */
65 const char dom_s[] = "\x53\x69\x67\x45\x64\x34\x34\x38";
66 uint8_t dom[2];
67 EVP_MD *shake256 = NULL;
68
69 if (context_len > UINT8_MAX)
70 return C448_FAILURE;
71
72 dom[0] = (uint8_t)(2 - (prehashed == 0 ? 1 : 0)
73 - (for_prehash == 0 ? 1 : 0));
74 dom[1] = (uint8_t)context_len;
75
76 shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq);
77 if (shake256 == NULL)
78 return C448_FAILURE;
79
80 if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
81 || !EVP_DigestUpdate(hashctx, dom_s, sizeof(dom_s)-1)
82 || !EVP_DigestUpdate(hashctx, dom, sizeof(dom))
83 || !EVP_DigestUpdate(hashctx, context, context_len)) {
84 EVP_MD_free(shake256);
85 return C448_FAILURE;
86 }
87
88 EVP_MD_free(shake256);
89 return C448_SUCCESS;
90 }
91
92 /* In this file because it uses the hash */
93 c448_error_t
ossl_c448_ed448_convert_private_key_to_x448(OSSL_LIB_CTX * ctx,uint8_t x[X448_PRIVATE_BYTES],const uint8_t ed[EDDSA_448_PRIVATE_BYTES],const char * propq)94 ossl_c448_ed448_convert_private_key_to_x448(
95 OSSL_LIB_CTX *ctx,
96 uint8_t x[X448_PRIVATE_BYTES],
97 const uint8_t ed [EDDSA_448_PRIVATE_BYTES],
98 const char *propq)
99 {
100 /* pass the private key through oneshot_hash function */
101 /* and keep the first X448_PRIVATE_BYTES bytes */
102 return oneshot_hash(ctx, x, X448_PRIVATE_BYTES, ed,
103 EDDSA_448_PRIVATE_BYTES, propq);
104 }
105
106 c448_error_t
ossl_c448_ed448_derive_public_key(OSSL_LIB_CTX * ctx,uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],const char * propq)107 ossl_c448_ed448_derive_public_key(
108 OSSL_LIB_CTX *ctx,
109 uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
110 const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
111 const char *propq)
112 {
113 /* only this much used for keygen */
114 uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES];
115 curve448_scalar_t secret_scalar;
116 unsigned int c;
117 curve448_point_t p;
118
119 if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser),
120 privkey,
121 EDDSA_448_PRIVATE_BYTES,
122 propq))
123 return C448_FAILURE;
124
125 clamp(secret_scalar_ser);
126
127 ossl_curve448_scalar_decode_long(secret_scalar, secret_scalar_ser,
128 sizeof(secret_scalar_ser));
129
130 /*
131 * Since we are going to mul_by_cofactor during encoding, divide by it
132 * here. However, the EdDSA base point is not the same as the decaf base
133 * point if the sigma isogeny is in use: the EdDSA base point is on
134 * Etwist_d/(1-d) and the decaf base point is on Etwist_d, and when
135 * converted it effectively picks up a factor of 2 from the isogenies. So
136 * we might start at 2 instead of 1.
137 */
138 for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
139 ossl_curve448_scalar_halve(secret_scalar, secret_scalar);
140
141 ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base,
142 secret_scalar);
143
144 ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p);
145
146 /* Cleanup */
147 ossl_curve448_scalar_destroy(secret_scalar);
148 ossl_curve448_point_destroy(p);
149 OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser));
150
151 return C448_SUCCESS;
152 }
153
154 c448_error_t
ossl_c448_ed448_sign(OSSL_LIB_CTX * ctx,uint8_t signature[EDDSA_448_SIGNATURE_BYTES],const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],const uint8_t * message,size_t message_len,uint8_t prehashed,const uint8_t * context,size_t context_len,const char * propq)155 ossl_c448_ed448_sign(OSSL_LIB_CTX *ctx,
156 uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
157 const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
158 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
159 const uint8_t *message, size_t message_len,
160 uint8_t prehashed, const uint8_t *context,
161 size_t context_len, const char *propq)
162 {
163 curve448_scalar_t secret_scalar;
164 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
165 c448_error_t ret = C448_FAILURE;
166 curve448_scalar_t nonce_scalar;
167 uint8_t nonce_point[EDDSA_448_PUBLIC_BYTES] = { 0 };
168 unsigned int c;
169 curve448_scalar_t challenge_scalar;
170
171 if (hashctx == NULL)
172 return C448_FAILURE;
173
174 {
175 /*
176 * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialized
177 * secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed.
178 */
179 uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2];
180
181 if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey,
182 EDDSA_448_PRIVATE_BYTES, propq))
183 goto err;
184 clamp(expanded);
185 ossl_curve448_scalar_decode_long(secret_scalar, expanded,
186 EDDSA_448_PRIVATE_BYTES);
187
188 /* Hash to create the nonce */
189 if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
190 context_len, propq)
191 || !EVP_DigestUpdate(hashctx,
192 expanded + EDDSA_448_PRIVATE_BYTES,
193 EDDSA_448_PRIVATE_BYTES)
194 || !EVP_DigestUpdate(hashctx, message, message_len)) {
195 OPENSSL_cleanse(expanded, sizeof(expanded));
196 goto err;
197 }
198 OPENSSL_cleanse(expanded, sizeof(expanded));
199 }
200
201 /* Decode the nonce */
202 {
203 uint8_t nonce[2 * EDDSA_448_PRIVATE_BYTES];
204
205 if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce)))
206 goto err;
207 ossl_curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce));
208 OPENSSL_cleanse(nonce, sizeof(nonce));
209 }
210
211 {
212 /* Scalarmul to create the nonce-point */
213 curve448_scalar_t nonce_scalar_2;
214 curve448_point_t p;
215
216 ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar);
217 for (c = 2; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
218 ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2);
219
220 ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base,
221 nonce_scalar_2);
222 ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p);
223 ossl_curve448_point_destroy(p);
224 ossl_curve448_scalar_destroy(nonce_scalar_2);
225 }
226
227 {
228 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
229
230 /* Compute the challenge */
231 if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len,
232 propq)
233 || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point))
234 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
235 || !EVP_DigestUpdate(hashctx, message, message_len)
236 || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge)))
237 goto err;
238
239 ossl_curve448_scalar_decode_long(challenge_scalar, challenge,
240 sizeof(challenge));
241 OPENSSL_cleanse(challenge, sizeof(challenge));
242 }
243
244 ossl_curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar);
245 ossl_curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar);
246
247 OPENSSL_cleanse(signature, EDDSA_448_SIGNATURE_BYTES);
248 memcpy(signature, nonce_point, sizeof(nonce_point));
249 ossl_curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES],
250 challenge_scalar);
251
252 ossl_curve448_scalar_destroy(secret_scalar);
253 ossl_curve448_scalar_destroy(nonce_scalar);
254 ossl_curve448_scalar_destroy(challenge_scalar);
255
256 ret = C448_SUCCESS;
257 err:
258 EVP_MD_CTX_free(hashctx);
259 return ret;
260 }
261
262 c448_error_t
ossl_c448_ed448_sign_prehash(OSSL_LIB_CTX * ctx,uint8_t signature[EDDSA_448_SIGNATURE_BYTES],const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],const uint8_t hash[64],const uint8_t * context,size_t context_len,const char * propq)263 ossl_c448_ed448_sign_prehash(
264 OSSL_LIB_CTX *ctx,
265 uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
266 const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
267 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
268 const uint8_t hash[64], const uint8_t *context,
269 size_t context_len, const char *propq)
270 {
271 return ossl_c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1,
272 context, context_len, propq);
273 }
274
275 static c448_error_t
c448_ed448_pubkey_verify(const uint8_t * pub,size_t pub_len)276 c448_ed448_pubkey_verify(const uint8_t *pub, size_t pub_len)
277 {
278 curve448_point_t pk_point;
279
280 if (pub_len != EDDSA_448_PUBLIC_BYTES)
281 return C448_FAILURE;
282
283 return ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pub);
284 }
285
286 c448_error_t
ossl_c448_ed448_verify(OSSL_LIB_CTX * ctx,const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],const uint8_t * message,size_t message_len,uint8_t prehashed,const uint8_t * context,uint8_t context_len,const char * propq)287 ossl_c448_ed448_verify(
288 OSSL_LIB_CTX *ctx,
289 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
290 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
291 const uint8_t *message, size_t message_len,
292 uint8_t prehashed, const uint8_t *context,
293 uint8_t context_len, const char *propq)
294 {
295 curve448_point_t pk_point, r_point;
296 c448_error_t error;
297 curve448_scalar_t challenge_scalar;
298 curve448_scalar_t response_scalar;
299 /* Order in little endian format */
300 static const uint8_t order[] = {
301 0xF3, 0x44, 0x58, 0xAB, 0x92, 0xC2, 0x78, 0x23, 0x55, 0x8F, 0xC5, 0x8D,
302 0x72, 0xC2, 0x6C, 0x21, 0x90, 0x36, 0xD6, 0xAE, 0x49, 0xDB, 0x4E, 0xC4,
303 0xE9, 0x23, 0xCA, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
304 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
305 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00
306 };
307 int i;
308
309 /*
310 * Check that s (second 57 bytes of the sig) is less than the order. Both
311 * s and the order are in little-endian format. This can be done in
312 * variable time, since if this is not the case the signature if publicly
313 * invalid.
314 */
315 for (i = EDDSA_448_PUBLIC_BYTES - 1; i >= 0; i--) {
316 if (signature[i + EDDSA_448_PUBLIC_BYTES] > order[i])
317 return C448_FAILURE;
318 if (signature[i + EDDSA_448_PUBLIC_BYTES] < order[i])
319 break;
320 }
321 if (i < 0)
322 return C448_FAILURE;
323
324 error =
325 ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey);
326
327 if (C448_SUCCESS != error)
328 return error;
329
330 error =
331 ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature);
332 if (C448_SUCCESS != error)
333 return error;
334
335 {
336 /* Compute the challenge */
337 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
338 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
339
340 if (hashctx == NULL
341 || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
342 context_len, propq)
343 || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES)
344 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
345 || !EVP_DigestUpdate(hashctx, message, message_len)
346 || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) {
347 EVP_MD_CTX_free(hashctx);
348 return C448_FAILURE;
349 }
350
351 EVP_MD_CTX_free(hashctx);
352 ossl_curve448_scalar_decode_long(challenge_scalar, challenge,
353 sizeof(challenge));
354 OPENSSL_cleanse(challenge, sizeof(challenge));
355 }
356 ossl_curve448_scalar_sub(challenge_scalar, ossl_curve448_scalar_zero,
357 challenge_scalar);
358
359 ossl_curve448_scalar_decode_long(response_scalar,
360 &signature[EDDSA_448_PUBLIC_BYTES],
361 EDDSA_448_PRIVATE_BYTES);
362
363 /* pk_point = -c(x(P)) + (cx + k)G = kG */
364 ossl_curve448_base_double_scalarmul_non_secret(pk_point,
365 response_scalar,
366 pk_point, challenge_scalar);
367 return c448_succeed_if(ossl_curve448_point_eq(pk_point, r_point));
368 }
369
370 c448_error_t
ossl_c448_ed448_verify_prehash(OSSL_LIB_CTX * ctx,const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],const uint8_t hash[64],const uint8_t * context,uint8_t context_len,const char * propq)371 ossl_c448_ed448_verify_prehash(
372 OSSL_LIB_CTX *ctx,
373 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
374 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
375 const uint8_t hash[64], const uint8_t *context,
376 uint8_t context_len, const char *propq)
377 {
378 return ossl_c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context,
379 context_len, propq);
380 }
381
382 int
ossl_ed448_sign(OSSL_LIB_CTX * ctx,uint8_t * out_sig,const uint8_t * message,size_t message_len,const uint8_t public_key[57],const uint8_t private_key[57],const uint8_t * context,size_t context_len,const uint8_t phflag,const char * propq)383 ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig,
384 const uint8_t *message, size_t message_len,
385 const uint8_t public_key[57], const uint8_t private_key[57],
386 const uint8_t *context, size_t context_len,
387 const uint8_t phflag, const char *propq)
388 {
389 return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message,
390 message_len, phflag, context, context_len,
391 propq) == C448_SUCCESS;
392 }
393
394 /*
395 * This function should not be necessary since ossl_ed448_verify() already
396 * does this check internally.
397 * For some reason the FIPS ACVP requires a EDDSA KeyVer test.
398 */
399 int
ossl_ed448_pubkey_verify(const uint8_t * pub,size_t pub_len)400 ossl_ed448_pubkey_verify(const uint8_t *pub, size_t pub_len)
401 {
402 return c448_ed448_pubkey_verify(pub, pub_len);
403 }
404
405 int
ossl_ed448_verify(OSSL_LIB_CTX * ctx,const uint8_t * message,size_t message_len,const uint8_t signature[114],const uint8_t public_key[57],const uint8_t * context,size_t context_len,const uint8_t phflag,const char * propq)406 ossl_ed448_verify(OSSL_LIB_CTX *ctx,
407 const uint8_t *message, size_t message_len,
408 const uint8_t signature[114], const uint8_t public_key[57],
409 const uint8_t *context, size_t context_len,
410 const uint8_t phflag, const char *propq)
411 {
412 return ossl_c448_ed448_verify(ctx, signature, public_key, message,
413 message_len, phflag, context, (uint8_t)context_len,
414 propq) == C448_SUCCESS;
415 }
416
417 int
ossl_ed448_public_from_private(OSSL_LIB_CTX * ctx,uint8_t out_public_key[57],const uint8_t private_key[57],const char * propq)418 ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57],
419 const uint8_t private_key[57], const char *propq)
420 {
421 return ossl_c448_ed448_derive_public_key(ctx, out_public_key, private_key,
422 propq) == C448_SUCCESS;
423 }
424