]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/curve448/eddsa.c
threads_pthread.c: change inline to ossl_inline
[thirdparty/openssl.git] / crypto / ec / curve448 / eddsa.c
CommitLineData
1308e022 1/*
da1c088f 2 * Copyright 2017-2023 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 11 */
53ef3252 12#include <string.h>
b6e388ba 13#include <openssl/crypto.h>
a242839f 14#include <openssl/evp.h>
3965480c 15#include "crypto/ecx.h"
706457b7 16#include "curve448_local.h"
7324473f 17#include "word.h"
a2039c87 18#include "ed448.h"
a242839f 19#include "internal/numbers.h"
7324473f 20
7324473f 21#define COFACTOR 4
7324473f 22
b4250010 23static c448_error_t oneshot_hash(OSSL_LIB_CTX *ctx, uint8_t *out, size_t outlen,
8dbef010
SL
24 const uint8_t *in, size_t inlen,
25 const char *propq)
a242839f
MC
26{
27 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
a9612d6c
MC
28 EVP_MD *shake256 = NULL;
29 c448_error_t ret = C448_FAILURE;
a242839f
MC
30
31 if (hashctx == NULL)
aeeef83c 32 return C448_FAILURE;
a242839f 33
8dbef010 34 shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq);
a9612d6c
MC
35 if (shake256 == NULL)
36 goto err;
37
38 if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
04ebd4e1 39 || !EVP_DigestUpdate(hashctx, in, inlen)
a9612d6c
MC
40 || !EVP_DigestFinalXOF(hashctx, out, outlen))
41 goto err;
a242839f 42
a9612d6c
MC
43 ret = C448_SUCCESS;
44 err:
a242839f 45 EVP_MD_CTX_free(hashctx);
3fd70262 46 EVP_MD_free(shake256);
a9612d6c 47 return ret;
a242839f
MC
48}
49
db90b274 50static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
205fd638 51{
7324473f 52 secret_scalar_ser[0] &= -COFACTOR;
9c9d6ff4
MC
53 secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 1] = 0;
54 secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80;
7324473f
MC
55}
56
b4250010 57static c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx,
a9612d6c 58 uint8_t prehashed,
aeeef83c
MC
59 uint8_t for_prehash,
60 const uint8_t *context,
8dbef010
SL
61 size_t context_len,
62 const char *propq)
205fd638 63{
836080a8
JM
64 /* ASCII: "SigEd448", in hex for EBCDIC compatibility */
65 const char dom_s[] = "\x53\x69\x67\x45\x64\x34\x34\x38";
094c071c 66 uint8_t dom[2];
a9612d6c 67 EVP_MD *shake256 = NULL;
094c071c 68
a242839f 69 if (context_len > UINT8_MAX)
aeeef83c 70 return C448_FAILURE;
7324473f 71
a7232276
MC
72 dom[0] = (uint8_t)(2 - (prehashed == 0 ? 1 : 0)
73 - (for_prehash == 0 ? 1 : 0));
53ef3252
MC
74 dom[1] = (uint8_t)context_len;
75
8dbef010 76 shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq);
a9612d6c
MC
77 if (shake256 == NULL)
78 return C448_FAILURE;
79
80 if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
836080a8 81 || !EVP_DigestUpdate(hashctx, dom_s, sizeof(dom_s)-1)
04ebd4e1 82 || !EVP_DigestUpdate(hashctx, dom, sizeof(dom))
a9612d6c 83 || !EVP_DigestUpdate(hashctx, context, context_len)) {
3fd70262 84 EVP_MD_free(shake256);
aeeef83c 85 return C448_FAILURE;
a9612d6c 86 }
a242839f 87
3fd70262 88 EVP_MD_free(shake256);
aeeef83c 89 return C448_SUCCESS;
7324473f
MC
90}
91
7324473f 92/* In this file because it uses the hash */
054d43ff
SL
93c448_error_t
94ossl_c448_ed448_convert_private_key_to_x448(
b4250010 95 OSSL_LIB_CTX *ctx,
db90b274 96 uint8_t x[X448_PRIVATE_BYTES],
8dbef010
SL
97 const uint8_t ed [EDDSA_448_PRIVATE_BYTES],
98 const char *propq)
205fd638 99{
a242839f 100 /* pass the private key through oneshot_hash function */
db90b274 101 /* and keep the first X448_PRIVATE_BYTES bytes */
a9612d6c 102 return oneshot_hash(ctx, x, X448_PRIVATE_BYTES, ed,
8dbef010 103 EDDSA_448_PRIVATE_BYTES, propq);
7324473f 104}
205fd638 105
054d43ff
SL
106c448_error_t
107ossl_c448_ed448_derive_public_key(
b4250010 108 OSSL_LIB_CTX *ctx,
db90b274 109 uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
8dbef010
SL
110 const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
111 const char *propq)
205fd638 112{
7324473f 113 /* only this much used for keygen */
db90b274 114 uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES];
094c071c
MC
115 curve448_scalar_t secret_scalar;
116 unsigned int c;
117 curve448_point_t p;
118
a9612d6c
MC
119 if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser),
120 privkey,
8dbef010
SL
121 EDDSA_448_PRIVATE_BYTES,
122 propq))
aeeef83c 123 return C448_FAILURE;
8d55f844 124
7324473f 125 clamp(secret_scalar_ser);
094c071c 126
054d43ff
SL
127 ossl_curve448_scalar_decode_long(secret_scalar, secret_scalar_ser,
128 sizeof(secret_scalar_ser));
205fd638
MC
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.
7324473f 137 */
db90b274 138 for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
054d43ff 139 ossl_curve448_scalar_halve(secret_scalar, secret_scalar);
205fd638 140
054d43ff
SL
141 ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base,
142 secret_scalar);
205fd638 143
054d43ff 144 ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p);
205fd638 145
7324473f 146 /* Cleanup */
054d43ff
SL
147 ossl_curve448_scalar_destroy(secret_scalar);
148 ossl_curve448_point_destroy(p);
b6e388ba 149 OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser));
a242839f 150
aeeef83c 151 return C448_SUCCESS;
7324473f
MC
152}
153
054d43ff
SL
154c448_error_t
155ossl_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)
205fd638 162{
e7772577 163 curve448_scalar_t secret_scalar;
a242839f 164 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
aeeef83c 165 c448_error_t ret = C448_FAILURE;
094c071c 166 curve448_scalar_t nonce_scalar;
db90b274 167 uint8_t nonce_point[EDDSA_448_PUBLIC_BYTES] = { 0 };
094c071c
MC
168 unsigned int c;
169 curve448_scalar_t challenge_scalar;
a242839f
MC
170
171 if (hashctx == NULL)
aeeef83c 172 return C448_FAILURE;
a242839f 173
7324473f 174 {
52a9587c 175 /*
aa97970c 176 * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialized
52a9587c
MC
177 * secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed.
178 */
179 uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2];
a242839f 180
a9612d6c 181 if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey,
8dbef010 182 EDDSA_448_PRIVATE_BYTES, propq))
a242839f 183 goto err;
52a9587c 184 clamp(expanded);
054d43ff
SL
185 ossl_curve448_scalar_decode_long(secret_scalar, expanded,
186 EDDSA_448_PRIVATE_BYTES);
205fd638 187
7324473f 188 /* Hash to create the nonce */
a9612d6c 189 if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
8dbef010 190 context_len, propq)
04ebd4e1
MC
191 || !EVP_DigestUpdate(hashctx,
192 expanded + EDDSA_448_PRIVATE_BYTES,
193 EDDSA_448_PRIVATE_BYTES)
28c5b7d4 194 || !EVP_DigestUpdate(hashctx, message, message_len)) {
68b20c00 195 OPENSSL_cleanse(expanded, sizeof(expanded));
a242839f
MC
196 goto err;
197 }
52a9587c 198 OPENSSL_cleanse(expanded, sizeof(expanded));
7324473f 199 }
205fd638 200
7324473f 201 /* Decode the nonce */
7324473f 202 {
db90b274 203 uint8_t nonce[2 * EDDSA_448_PRIVATE_BYTES];
a242839f
MC
204
205 if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce)))
206 goto err;
054d43ff 207 ossl_curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce));
b6e388ba 208 OPENSSL_cleanse(nonce, sizeof(nonce));
7324473f 209 }
094c071c 210
7324473f
MC
211 {
212 /* Scalarmul to create the nonce-point */
e7772577 213 curve448_scalar_t nonce_scalar_2;
094c071c
MC
214 curve448_point_t p;
215
054d43ff 216 ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar);
68b20c00 217 for (c = 2; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
054d43ff 218 ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2);
094c071c 219
054d43ff
SL
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);
7324473f 225 }
094c071c 226
7324473f 227 {
db90b274 228 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
a242839f
MC
229
230 /* Compute the challenge */
8dbef010
SL
231 if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len,
232 propq)
68b20c00
MC
233 || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point))
234 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
28c5b7d4 235 || !EVP_DigestUpdate(hashctx, message, message_len)
68b20c00 236 || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge)))
a242839f
MC
237 goto err;
238
054d43ff
SL
239 ossl_curve448_scalar_decode_long(challenge_scalar, challenge,
240 sizeof(challenge));
205fd638 241 OPENSSL_cleanse(challenge, sizeof(challenge));
7324473f 242 }
205fd638 243
054d43ff
SL
244 ossl_curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar);
245 ossl_curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar);
205fd638 246
db90b274 247 OPENSSL_cleanse(signature, EDDSA_448_SIGNATURE_BYTES);
205fd638 248 memcpy(signature, nonce_point, sizeof(nonce_point));
054d43ff
SL
249 ossl_curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES],
250 challenge_scalar);
205fd638 251
054d43ff
SL
252 ossl_curve448_scalar_destroy(secret_scalar);
253 ossl_curve448_scalar_destroy(nonce_scalar);
254 ossl_curve448_scalar_destroy(challenge_scalar);
a242839f 255
aeeef83c 256 ret = C448_SUCCESS;
a242839f
MC
257 err:
258 EVP_MD_CTX_free(hashctx);
259 return ret;
7324473f
MC
260}
261
054d43ff
SL
262c448_error_t
263ossl_c448_ed448_sign_prehash(
b4250010 264 OSSL_LIB_CTX *ctx,
db90b274
MC
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],
aeeef83c 268 const uint8_t hash[64], const uint8_t *context,
8dbef010 269 size_t context_len, const char *propq)
205fd638 270{
054d43ff
SL
271 return ossl_c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1,
272 context, context_len, propq);
7324473f
MC
273}
274
054d43ff
SL
275c448_error_t
276ossl_c448_ed448_verify(
b4250010 277 OSSL_LIB_CTX *ctx,
db90b274
MC
278 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
279 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
aeeef83c
MC
280 const uint8_t *message, size_t message_len,
281 uint8_t prehashed, const uint8_t *context,
8dbef010 282 uint8_t context_len, const char *propq)
205fd638 283{
e7772577 284 curve448_point_t pk_point, r_point;
08afd2f3 285 c448_error_t error;
094c071c
MC
286 curve448_scalar_t challenge_scalar;
287 curve448_scalar_t response_scalar;
08afd2f3
MC
288 /* Order in little endian format */
289 static const uint8_t order[] = {
290 0xF3, 0x44, 0x58, 0xAB, 0x92, 0xC2, 0x78, 0x23, 0x55, 0x8F, 0xC5, 0x8D,
291 0x72, 0xC2, 0x6C, 0x21, 0x90, 0x36, 0xD6, 0xAE, 0x49, 0xDB, 0x4E, 0xC4,
292 0xE9, 0x23, 0xCA, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
293 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
294 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00
295 };
296 int i;
297
298 /*
299 * Check that s (second 57 bytes of the sig) is less than the order. Both
300 * s and the order are in little-endian format. This can be done in
301 * variable time, since if this is not the case the signature if publicly
302 * invalid.
303 */
304 for (i = EDDSA_448_PUBLIC_BYTES - 1; i >= 0; i--) {
305 if (signature[i + EDDSA_448_PUBLIC_BYTES] > order[i])
306 return C448_FAILURE;
307 if (signature[i + EDDSA_448_PUBLIC_BYTES] < order[i])
308 break;
309 }
310 if (i < 0)
311 return C448_FAILURE;
312
313 error =
054d43ff 314 ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey);
094c071c 315
aeeef83c 316 if (C448_SUCCESS != error)
205fd638 317 return error;
205fd638
MC
318
319 error =
054d43ff 320 ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature);
aeeef83c 321 if (C448_SUCCESS != error)
205fd638 322 return error;
205fd638 323
7324473f
MC
324 {
325 /* Compute the challenge */
a242839f 326 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
db90b274 327 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
a242839f
MC
328
329 if (hashctx == NULL
a9612d6c 330 || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
8dbef010 331 context_len, propq)
e4118223
MC
332 || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES)
333 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
334 || !EVP_DigestUpdate(hashctx, message, message_len)
335 || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) {
a242839f 336 EVP_MD_CTX_free(hashctx);
aeeef83c 337 return C448_FAILURE;
a242839f
MC
338 }
339
340 EVP_MD_CTX_free(hashctx);
054d43ff
SL
341 ossl_curve448_scalar_decode_long(challenge_scalar, challenge,
342 sizeof(challenge));
205fd638 343 OPENSSL_cleanse(challenge, sizeof(challenge));
7324473f 344 }
054d43ff
SL
345 ossl_curve448_scalar_sub(challenge_scalar, ossl_curve448_scalar_zero,
346 challenge_scalar);
205fd638 347
054d43ff
SL
348 ossl_curve448_scalar_decode_long(response_scalar,
349 &signature[EDDSA_448_PUBLIC_BYTES],
350 EDDSA_448_PRIVATE_BYTES);
205fd638 351
7324473f 352 /* pk_point = -c(x(P)) + (cx + k)G = kG */
054d43ff
SL
353 ossl_curve448_base_double_scalarmul_non_secret(pk_point,
354 response_scalar,
355 pk_point, challenge_scalar);
356 return c448_succeed_if(ossl_curve448_point_eq(pk_point, r_point));
7324473f
MC
357}
358
054d43ff
SL
359c448_error_t
360ossl_c448_ed448_verify_prehash(
b4250010 361 OSSL_LIB_CTX *ctx,
db90b274
MC
362 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
363 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
8d55f844 364 const uint8_t hash[64], const uint8_t *context,
8dbef010 365 uint8_t context_len, const char *propq)
205fd638 366{
054d43ff
SL
367 return ossl_c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context,
368 context_len, propq);
7324473f 369}
4ea41daa 370
054d43ff 371int
836080a8
JM
372ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig,
373 const uint8_t *message, size_t message_len,
374 const uint8_t public_key[57], const uint8_t private_key[57],
375 const uint8_t *context, size_t context_len,
376 const uint8_t phflag, const char *propq)
6ea71cba 377{
054d43ff 378 return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message,
836080a8 379 message_len, phflag, context, context_len,
054d43ff 380 propq) == C448_SUCCESS;
4ea41daa
MC
381}
382
054d43ff 383int
836080a8
JM
384ossl_ed448_verify(OSSL_LIB_CTX *ctx,
385 const uint8_t *message, size_t message_len,
054d43ff 386 const uint8_t signature[114], const uint8_t public_key[57],
836080a8
JM
387 const uint8_t *context, size_t context_len,
388 const uint8_t phflag, const char *propq)
6ea71cba 389{
054d43ff 390 return ossl_c448_ed448_verify(ctx, signature, public_key, message,
836080a8 391 message_len, phflag, context, (uint8_t)context_len,
054d43ff 392 propq) == C448_SUCCESS;
4ea41daa
MC
393}
394
054d43ff
SL
395int
396ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57],
397 const uint8_t private_key[57], const char *propq)
6ea71cba 398{
054d43ff
SL
399 return ossl_c448_ed448_derive_public_key(ctx, out_public_key, private_key,
400 propq) == C448_SUCCESS;
4ea41daa 401}