]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/curve448/eddsa.c
Reorganize local header files
[thirdparty/openssl.git] / crypto / ec / curve448 / eddsa.c
CommitLineData
1308e022 1/*
f53c7764 2 * Copyright 2017-2018 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>
706457b7 15#include "curve448_local.h"
7324473f 16#include "word.h"
a2039c87 17#include "ed448.h"
a242839f 18#include "internal/numbers.h"
7324473f 19
7324473f 20#define COFACTOR 4
7324473f 21
a9612d6c 22static c448_error_t oneshot_hash(OPENSSL_CTX *ctx, uint8_t *out, size_t outlen,
aeeef83c 23 const uint8_t *in, size_t inlen)
a242839f
MC
24{
25 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
a9612d6c
MC
26 EVP_MD *shake256 = NULL;
27 c448_error_t ret = C448_FAILURE;
a242839f
MC
28
29 if (hashctx == NULL)
aeeef83c 30 return C448_FAILURE;
a242839f 31
a9612d6c
MC
32 shake256 = EVP_MD_fetch(ctx, "SHAKE256", NULL);
33 if (shake256 == NULL)
34 goto err;
35
36 if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
04ebd4e1 37 || !EVP_DigestUpdate(hashctx, in, inlen)
a9612d6c
MC
38 || !EVP_DigestFinalXOF(hashctx, out, outlen))
39 goto err;
a242839f 40
a9612d6c
MC
41 ret = C448_SUCCESS;
42 err:
a242839f 43 EVP_MD_CTX_free(hashctx);
3fd70262 44 EVP_MD_free(shake256);
a9612d6c 45 return ret;
a242839f
MC
46}
47
db90b274 48static void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES])
205fd638 49{
7324473f 50 secret_scalar_ser[0] &= -COFACTOR;
9c9d6ff4
MC
51 secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 1] = 0;
52 secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80;
7324473f
MC
53}
54
a9612d6c
MC
55static c448_error_t hash_init_with_dom(OPENSSL_CTX *ctx, EVP_MD_CTX *hashctx,
56 uint8_t prehashed,
aeeef83c
MC
57 uint8_t for_prehash,
58 const uint8_t *context,
59 size_t context_len)
205fd638 60{
a242839f 61 const char *dom_s = "SigEd448";
094c071c 62 uint8_t dom[2];
a9612d6c 63 EVP_MD *shake256 = NULL;
094c071c 64
a242839f 65 if (context_len > UINT8_MAX)
aeeef83c 66 return C448_FAILURE;
7324473f 67
a7232276
MC
68 dom[0] = (uint8_t)(2 - (prehashed == 0 ? 1 : 0)
69 - (for_prehash == 0 ? 1 : 0));
53ef3252
MC
70 dom[1] = (uint8_t)context_len;
71
a9612d6c
MC
72 shake256 = EVP_MD_fetch(ctx, "SHAKE256", NULL);
73 if (shake256 == NULL)
74 return C448_FAILURE;
75
76 if (!EVP_DigestInit_ex(hashctx, shake256, NULL)
04ebd4e1
MC
77 || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s))
78 || !EVP_DigestUpdate(hashctx, dom, sizeof(dom))
a9612d6c 79 || !EVP_DigestUpdate(hashctx, context, context_len)) {
3fd70262 80 EVP_MD_free(shake256);
aeeef83c 81 return C448_FAILURE;
a9612d6c 82 }
a242839f 83
3fd70262 84 EVP_MD_free(shake256);
aeeef83c 85 return C448_SUCCESS;
7324473f
MC
86}
87
7324473f 88/* In this file because it uses the hash */
aeeef83c 89c448_error_t c448_ed448_convert_private_key_to_x448(
a9612d6c 90 OPENSSL_CTX *ctx,
db90b274
MC
91 uint8_t x[X448_PRIVATE_BYTES],
92 const uint8_t ed [EDDSA_448_PRIVATE_BYTES])
205fd638 93{
a242839f 94 /* pass the private key through oneshot_hash function */
db90b274 95 /* and keep the first X448_PRIVATE_BYTES bytes */
a9612d6c 96 return oneshot_hash(ctx, x, X448_PRIVATE_BYTES, ed,
db90b274 97 EDDSA_448_PRIVATE_BYTES);
7324473f 98}
205fd638 99
aeeef83c 100c448_error_t c448_ed448_derive_public_key(
a9612d6c 101 OPENSSL_CTX *ctx,
db90b274
MC
102 uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
103 const uint8_t privkey[EDDSA_448_PRIVATE_BYTES])
205fd638 104{
7324473f 105 /* only this much used for keygen */
db90b274 106 uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES];
094c071c
MC
107 curve448_scalar_t secret_scalar;
108 unsigned int c;
109 curve448_point_t p;
110
a9612d6c
MC
111 if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser),
112 privkey,
db90b274 113 EDDSA_448_PRIVATE_BYTES))
aeeef83c 114 return C448_FAILURE;
8d55f844 115
7324473f 116 clamp(secret_scalar_ser);
094c071c 117
205fd638
MC
118 curve448_scalar_decode_long(secret_scalar, secret_scalar_ser,
119 sizeof(secret_scalar_ser));
120
121 /*
122 * Since we are going to mul_by_cofactor during encoding, divide by it
123 * here. However, the EdDSA base point is not the same as the decaf base
124 * point if the sigma isogeny is in use: the EdDSA base point is on
125 * Etwist_d/(1-d) and the decaf base point is on Etwist_d, and when
126 * converted it effectively picks up a factor of 2 from the isogenies. So
127 * we might start at 2 instead of 1.
7324473f 128 */
db90b274 129 for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
205fd638 130 curve448_scalar_halve(secret_scalar, secret_scalar);
205fd638
MC
131
132 curve448_precomputed_scalarmul(p, curve448_precomputed_base, secret_scalar);
133
e7772577 134 curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p);
205fd638 135
7324473f 136 /* Cleanup */
e7772577
MC
137 curve448_scalar_destroy(secret_scalar);
138 curve448_point_destroy(p);
b6e388ba 139 OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser));
a242839f 140
aeeef83c 141 return C448_SUCCESS;
7324473f
MC
142}
143
aeeef83c 144c448_error_t c448_ed448_sign(
a9612d6c 145 OPENSSL_CTX *ctx,
db90b274
MC
146 uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
147 const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
148 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
8d55f844
MC
149 const uint8_t *message, size_t message_len,
150 uint8_t prehashed, const uint8_t *context,
151 size_t context_len)
205fd638 152{
e7772577 153 curve448_scalar_t secret_scalar;
a242839f 154 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
aeeef83c 155 c448_error_t ret = C448_FAILURE;
094c071c 156 curve448_scalar_t nonce_scalar;
db90b274 157 uint8_t nonce_point[EDDSA_448_PUBLIC_BYTES] = { 0 };
094c071c
MC
158 unsigned int c;
159 curve448_scalar_t challenge_scalar;
a242839f
MC
160
161 if (hashctx == NULL)
aeeef83c 162 return C448_FAILURE;
a242839f 163
7324473f 164 {
52a9587c
MC
165 /*
166 * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialised
167 * secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed.
168 */
169 uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2];
a242839f 170
a9612d6c 171 if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey,
db90b274 172 EDDSA_448_PRIVATE_BYTES))
a242839f 173 goto err;
52a9587c
MC
174 clamp(expanded);
175 curve448_scalar_decode_long(secret_scalar, expanded,
176 EDDSA_448_PRIVATE_BYTES);
205fd638 177
7324473f 178 /* Hash to create the nonce */
a9612d6c
MC
179 if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
180 context_len)
04ebd4e1
MC
181 || !EVP_DigestUpdate(hashctx,
182 expanded + EDDSA_448_PRIVATE_BYTES,
183 EDDSA_448_PRIVATE_BYTES)
28c5b7d4 184 || !EVP_DigestUpdate(hashctx, message, message_len)) {
68b20c00 185 OPENSSL_cleanse(expanded, sizeof(expanded));
a242839f
MC
186 goto err;
187 }
52a9587c 188 OPENSSL_cleanse(expanded, sizeof(expanded));
7324473f 189 }
205fd638 190
7324473f 191 /* Decode the nonce */
7324473f 192 {
db90b274 193 uint8_t nonce[2 * EDDSA_448_PRIVATE_BYTES];
a242839f
MC
194
195 if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce)))
196 goto err;
e7772577 197 curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce));
b6e388ba 198 OPENSSL_cleanse(nonce, sizeof(nonce));
7324473f 199 }
094c071c 200
7324473f
MC
201 {
202 /* Scalarmul to create the nonce-point */
e7772577 203 curve448_scalar_t nonce_scalar_2;
094c071c
MC
204 curve448_point_t p;
205
205fd638 206 curve448_scalar_halve(nonce_scalar_2, nonce_scalar);
68b20c00 207 for (c = 2; c < C448_EDDSA_ENCODE_RATIO; c <<= 1)
205fd638 208 curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2);
094c071c 209
205fd638
MC
210 curve448_precomputed_scalarmul(p, curve448_precomputed_base,
211 nonce_scalar_2);
e7772577
MC
212 curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p);
213 curve448_point_destroy(p);
214 curve448_scalar_destroy(nonce_scalar_2);
7324473f 215 }
094c071c 216
7324473f 217 {
db90b274 218 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
a242839f
MC
219
220 /* Compute the challenge */
a9612d6c 221 if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len)
68b20c00
MC
222 || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point))
223 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
28c5b7d4 224 || !EVP_DigestUpdate(hashctx, message, message_len)
68b20c00 225 || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge)))
a242839f
MC
226 goto err;
227
205fd638
MC
228 curve448_scalar_decode_long(challenge_scalar, challenge,
229 sizeof(challenge));
230 OPENSSL_cleanse(challenge, sizeof(challenge));
7324473f 231 }
205fd638
MC
232
233 curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar);
234 curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar);
235
db90b274 236 OPENSSL_cleanse(signature, EDDSA_448_SIGNATURE_BYTES);
205fd638 237 memcpy(signature, nonce_point, sizeof(nonce_point));
db90b274 238 curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES],
205fd638
MC
239 challenge_scalar);
240
e7772577
MC
241 curve448_scalar_destroy(secret_scalar);
242 curve448_scalar_destroy(nonce_scalar);
243 curve448_scalar_destroy(challenge_scalar);
a242839f 244
aeeef83c 245 ret = C448_SUCCESS;
a242839f
MC
246 err:
247 EVP_MD_CTX_free(hashctx);
248 return ret;
7324473f
MC
249}
250
aeeef83c 251c448_error_t c448_ed448_sign_prehash(
a9612d6c 252 OPENSSL_CTX *ctx,
db90b274
MC
253 uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
254 const uint8_t privkey[EDDSA_448_PRIVATE_BYTES],
255 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
aeeef83c
MC
256 const uint8_t hash[64], const uint8_t *context,
257 size_t context_len)
205fd638 258{
a9612d6c
MC
259 return c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1,
260 context, context_len);
7324473f
MC
261}
262
aeeef83c 263c448_error_t c448_ed448_verify(
a9612d6c 264 OPENSSL_CTX *ctx,
db90b274
MC
265 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
266 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
aeeef83c
MC
267 const uint8_t *message, size_t message_len,
268 uint8_t prehashed, const uint8_t *context,
269 uint8_t context_len)
205fd638 270{
e7772577 271 curve448_point_t pk_point, r_point;
08afd2f3 272 c448_error_t error;
094c071c
MC
273 curve448_scalar_t challenge_scalar;
274 curve448_scalar_t response_scalar;
08afd2f3
MC
275 /* Order in little endian format */
276 static const uint8_t order[] = {
277 0xF3, 0x44, 0x58, 0xAB, 0x92, 0xC2, 0x78, 0x23, 0x55, 0x8F, 0xC5, 0x8D,
278 0x72, 0xC2, 0x6C, 0x21, 0x90, 0x36, 0xD6, 0xAE, 0x49, 0xDB, 0x4E, 0xC4,
279 0xE9, 0x23, 0xCA, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
280 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
281 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00
282 };
283 int i;
284
285 /*
286 * Check that s (second 57 bytes of the sig) is less than the order. Both
287 * s and the order are in little-endian format. This can be done in
288 * variable time, since if this is not the case the signature if publicly
289 * invalid.
290 */
291 for (i = EDDSA_448_PUBLIC_BYTES - 1; i >= 0; i--) {
292 if (signature[i + EDDSA_448_PUBLIC_BYTES] > order[i])
293 return C448_FAILURE;
294 if (signature[i + EDDSA_448_PUBLIC_BYTES] < order[i])
295 break;
296 }
297 if (i < 0)
298 return C448_FAILURE;
299
300 error =
301 curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey);
094c071c 302
aeeef83c 303 if (C448_SUCCESS != error)
205fd638 304 return error;
205fd638
MC
305
306 error =
307 curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature);
aeeef83c 308 if (C448_SUCCESS != error)
205fd638 309 return error;
205fd638 310
7324473f
MC
311 {
312 /* Compute the challenge */
a242839f 313 EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
db90b274 314 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];
a242839f
MC
315
316 if (hashctx == NULL
a9612d6c 317 || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context,
e4118223
MC
318 context_len)
319 || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES)
320 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
321 || !EVP_DigestUpdate(hashctx, message, message_len)
322 || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) {
a242839f 323 EVP_MD_CTX_free(hashctx);
aeeef83c 324 return C448_FAILURE;
a242839f
MC
325 }
326
327 EVP_MD_CTX_free(hashctx);
205fd638
MC
328 curve448_scalar_decode_long(challenge_scalar, challenge,
329 sizeof(challenge));
330 OPENSSL_cleanse(challenge, sizeof(challenge));
7324473f 331 }
205fd638
MC
332 curve448_scalar_sub(challenge_scalar, curve448_scalar_zero,
333 challenge_scalar);
334
335 curve448_scalar_decode_long(response_scalar,
db90b274
MC
336 &signature[EDDSA_448_PUBLIC_BYTES],
337 EDDSA_448_PRIVATE_BYTES);
205fd638 338
7324473f 339 /* pk_point = -c(x(P)) + (cx + k)G = kG */
205fd638
MC
340 curve448_base_double_scalarmul_non_secret(pk_point,
341 response_scalar,
342 pk_point, challenge_scalar);
aeeef83c 343 return c448_succeed_if(curve448_point_eq(pk_point, r_point));
7324473f
MC
344}
345
aeeef83c 346c448_error_t c448_ed448_verify_prehash(
a9612d6c 347 OPENSSL_CTX *ctx,
db90b274
MC
348 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
349 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
8d55f844
MC
350 const uint8_t hash[64], const uint8_t *context,
351 uint8_t context_len)
205fd638 352{
a9612d6c 353 return c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context,
68b20c00 354 context_len);
7324473f 355}
4ea41daa 356
a9612d6c
MC
357int ED448_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t *message,
358 size_t message_len, const uint8_t public_key[57],
359 const uint8_t private_key[57], const uint8_t *context,
360 size_t context_len)
6ea71cba 361{
a9612d6c 362 return c448_ed448_sign(ctx, out_sig, private_key, public_key, message,
aeeef83c
MC
363 message_len, 0, context, context_len)
364 == C448_SUCCESS;
4ea41daa
MC
365}
366
a9612d6c 367int ED448_verify(OPENSSL_CTX *ctx, const uint8_t *message, size_t message_len,
22bcc9cb 368 const uint8_t signature[114], const uint8_t public_key[57],
6ea71cba
MC
369 const uint8_t *context, size_t context_len)
370{
a9612d6c
MC
371 return c448_ed448_verify(ctx, signature, public_key, message, message_len,
372 0, context, (uint8_t)context_len) == C448_SUCCESS;
4ea41daa
MC
373}
374
a9612d6c 375int ED448ph_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64],
22bcc9cb 376 const uint8_t public_key[57], const uint8_t private_key[57],
6ea71cba
MC
377 const uint8_t *context, size_t context_len)
378{
a9612d6c 379 return c448_ed448_sign_prehash(ctx, out_sig, private_key, public_key, hash,
aeeef83c 380 context, context_len) == C448_SUCCESS;
4ea41daa 381
6ea71cba 382}
4ea41daa 383
a9612d6c
MC
384int ED448ph_verify(OPENSSL_CTX *ctx, const uint8_t hash[64],
385 const uint8_t signature[114], const uint8_t public_key[57],
386 const uint8_t *context, size_t context_len)
6ea71cba 387{
a9612d6c 388 return c448_ed448_verify_prehash(ctx, signature, public_key, hash, context,
0cdcdacc 389 (uint8_t)context_len) == C448_SUCCESS;
4ea41daa
MC
390}
391
a9612d6c 392int ED448_public_from_private(OPENSSL_CTX *ctx, uint8_t out_public_key[57],
205fd638 393 const uint8_t private_key[57])
6ea71cba 394{
a9612d6c 395 return c448_ed448_derive_public_key(ctx, out_public_key, private_key)
aeeef83c 396 == C448_SUCCESS;
4ea41daa 397}