2 * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright 2015-2016 Cryptography Research, Inc.
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
10 * Originally written by Mike Hamburg
13 #include <openssl/crypto.h>
14 #include <openssl/evp.h>
15 #include "crypto/ecx.h"
16 #include "curve448_local.h"
19 #include "internal/numbers.h"
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,
27 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
28 EVP_MD *shake256 = NULL;
29 c448_error_t ret = C448_FAILURE;
34 shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq);
38 if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
39 || !EVP_DigestUpdate(hashctx, in, inlen)
40 || !EVP_DigestFinalXOF(hashctx, out, outlen))
45 EVP_MD_CTX_free(hashctx);
46 EVP_MD_free(shake256);
50 static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
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;
57 static c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx,
60 const uint8_t *context,
64 /* ASCII: "SigEd448", in hex for EBCDIC compatibility */
65 const char dom_s[] = "\x53\x69\x67\x45\x64\x34\x34\x38";
67 EVP_MD *shake256 = NULL;
69 if (context_len > UINT8_MAX)
72 dom[0] = (uint8_t)(2 - (prehashed == 0 ? 1 : 0)
73 - (for_prehash == 0 ? 1 : 0));
74 dom[1] = (uint8_t)context_len;
76 shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq);
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);
88 EVP_MD_free(shake256);
92 /* In this file because it uses the hash */
94 ossl_c448_ed448_convert_private_key_to_x448(
96 uint8_t x[X448_PRIVATE_BYTES],
97 const uint8_t ed [EDDSA_448_PRIVATE_BYTES],
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);
107 ossl_c448_ed448_derive_public_key(
109 uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
110 const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
113 /* only this much used for keygen */
114 uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES];
115 curve448_scalar_t secret_scalar;
119 if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser),
121 EDDSA_448_PRIVATE_BYTES,
125 clamp(secret_scalar_ser);
127 ossl_curve448_scalar_decode_long(secret_scalar, secret_scalar_ser,
128 sizeof(secret_scalar_ser));
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.
138 for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
139 ossl_curve448_scalar_halve(secret_scalar, secret_scalar);
141 ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base,
144 ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p);
147 ossl_curve448_scalar_destroy(secret_scalar);
148 ossl_curve448_point_destroy(p);
149 OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser));
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)
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 };
169 curve448_scalar_t challenge_scalar;
176 * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialized
177 * secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed.
179 uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2];
181 if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey,
182 EDDSA_448_PRIVATE_BYTES, propq))
185 ossl_curve448_scalar_decode_long(secret_scalar, expanded,
186 EDDSA_448_PRIVATE_BYTES);
188 /* Hash to create the nonce */
189 if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
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));
198 OPENSSL_cleanse(expanded, sizeof(expanded));
201 /* Decode the nonce */
203 uint8_t nonce[2 * EDDSA_448_PRIVATE_BYTES];
205 if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce)))
207 ossl_curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce));
208 OPENSSL_cleanse(nonce, sizeof(nonce));
212 /* Scalarmul to create the nonce-point */
213 curve448_scalar_t nonce_scalar_2;
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);
220 ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base,
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);
228 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
230 /* Compute the challenge */
231 if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len,
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)))
239 ossl_curve448_scalar_decode_long(challenge_scalar, challenge,
241 OPENSSL_cleanse(challenge, sizeof(challenge));
244 ossl_curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar);
245 ossl_curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar);
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],
252 ossl_curve448_scalar_destroy(secret_scalar);
253 ossl_curve448_scalar_destroy(nonce_scalar);
254 ossl_curve448_scalar_destroy(challenge_scalar);
258 EVP_MD_CTX_free(hashctx);
263 ossl_c448_ed448_sign_prehash(
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)
271 return ossl_c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1,
272 context, context_len, propq);
276 ossl_c448_ed448_verify(
278 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
279 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
280 const uint8_t *message, size_t message_len,
281 uint8_t prehashed, const uint8_t *context,
282 uint8_t context_len, const char *propq)
284 curve448_point_t pk_point, r_point;
286 curve448_scalar_t challenge_scalar;
287 curve448_scalar_t response_scalar;
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
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
304 for (i = EDDSA_448_PUBLIC_BYTES - 1; i >= 0; i--) {
305 if (signature[i + EDDSA_448_PUBLIC_BYTES] > order[i])
307 if (signature[i + EDDSA_448_PUBLIC_BYTES] < order[i])
314 ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey);
316 if (C448_SUCCESS != error)
320 ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature);
321 if (C448_SUCCESS != error)
325 /* Compute the challenge */
326 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
327 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
330 || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
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))) {
336 EVP_MD_CTX_free(hashctx);
340 EVP_MD_CTX_free(hashctx);
341 ossl_curve448_scalar_decode_long(challenge_scalar, challenge,
343 OPENSSL_cleanse(challenge, sizeof(challenge));
345 ossl_curve448_scalar_sub(challenge_scalar, ossl_curve448_scalar_zero,
348 ossl_curve448_scalar_decode_long(response_scalar,
349 &signature[EDDSA_448_PUBLIC_BYTES],
350 EDDSA_448_PRIVATE_BYTES);
352 /* pk_point = -c(x(P)) + (cx + k)G = kG */
353 ossl_curve448_base_double_scalarmul_non_secret(pk_point,
355 pk_point, challenge_scalar);
356 return c448_succeed_if(ossl_curve448_point_eq(pk_point, r_point));
360 ossl_c448_ed448_verify_prehash(
362 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
363 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
364 const uint8_t hash[64], const uint8_t *context,
365 uint8_t context_len, const char *propq)
367 return ossl_c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context,
372 ossl_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)
378 return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message,
379 message_len, phflag, context, context_len,
380 propq) == C448_SUCCESS;
384 ossl_ed448_verify(OSSL_LIB_CTX *ctx,
385 const uint8_t *message, size_t message_len,
386 const uint8_t signature[114], const uint8_t public_key[57],
387 const uint8_t *context, size_t context_len,
388 const uint8_t phflag, const char *propq)
390 return ossl_c448_ed448_verify(ctx, signature, public_key, message,
391 message_len, phflag, context, (uint8_t)context_len,
392 propq) == C448_SUCCESS;
396 ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57],
397 const uint8_t private_key[57], const char *propq)
399 return ossl_c448_ed448_derive_public_key(ctx, out_public_key, private_key,
400 propq) == C448_SUCCESS;