1289177Speter/* 2289177Speter * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. 3289177Speter * Copyright 2015-2016 Cryptography Research, Inc. 4289177Speter * 5289177Speter * Licensed under the Apache License 2.0 (the "License"). You may not use 6289177Speter * this file except in compliance with the License. You can obtain a copy 7289177Speter * in the file LICENSE in the source distribution or at 8289177Speter * https://www.openssl.org/source/license.html 9289177Speter * 10289177Speter * Originally written by Mike Hamburg 11289177Speter */ 12289177Speter#include <string.h> 13289177Speter#include <openssl/crypto.h> 14289177Speter#include <openssl/evp.h> 15289177Speter#include "crypto/ecx.h" 16289177Speter#include "curve448_local.h" 17289177Speter#include "word.h" 18289177Speter#include "ed448.h" 19289177Speter#include "internal/numbers.h" 20289177Speter 21289177Speter#define COFACTOR 4 22289177Speter 23289177Speterstatic c448_error_t oneshot_hash(OSSL_LIB_CTX *ctx, uint8_t *out, size_t outlen, 24289177Speter const uint8_t *in, size_t inlen, 25289177Speter const char *propq) 26289177Speter{ 27289177Speter EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); 28289177Speter EVP_MD *shake256 = NULL; 29289177Speter c448_error_t ret = C448_FAILURE; 30289177Speter 31289177Speter if (hashctx == NULL) 32289177Speter return C448_FAILURE; 33289177Speter 34289177Speter shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq); 35289177Speter if (shake256 == NULL) 36289177Speter goto err; 37289177Speter 38289177Speter if (!EVP_DigestInit_ex(hashctx, shake256, NULL) 39289177Speter || !EVP_DigestUpdate(hashctx, in, inlen) 40289177Speter || !EVP_DigestFinalXOF(hashctx, out, outlen)) 41289177Speter goto err; 42289177Speter 43289177Speter ret = C448_SUCCESS; 44289177Speter err: 45289177Speter EVP_MD_CTX_free(hashctx); 46289177Speter EVP_MD_free(shake256); 47289177Speter return ret; 48289177Speter} 49289177Speter 50289177Speterstatic void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]) 51289177Speter{ 52289177Speter secret_scalar_ser[0] &= -COFACTOR; 53289177Speter secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 1] = 0; 54289177Speter secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80; 55289177Speter} 56289177Speter 57289177Speterstatic c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx, 58289177Speter uint8_t prehashed, 59289177Speter uint8_t for_prehash, 60289177Speter const uint8_t *context, 61289177Speter size_t context_len, 62289177Speter const char *propq) 63289177Speter{ 64289177Speter#ifdef CHARSET_EBCDIC 65289177Speter const char dom_s[] = {0x53, 0x69, 0x67, 0x45, 66289177Speter 0x64, 0x34, 0x34, 0x38, 0x00}; 67289177Speter#else 68289177Speter const char dom_s[] = "SigEd448"; 69289177Speter#endif 70289177Speter uint8_t dom[2]; 71289177Speter EVP_MD *shake256 = NULL; 72289177Speter 73289177Speter if (context_len > UINT8_MAX) 74289177Speter return C448_FAILURE; 75289177Speter 76289177Speter dom[0] = (uint8_t)(2 - (prehashed == 0 ? 1 : 0) 77289177Speter - (for_prehash == 0 ? 1 : 0)); 78289177Speter dom[1] = (uint8_t)context_len; 79289177Speter 80289177Speter shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq); 81289177Speter if (shake256 == NULL) 82289177Speter return C448_FAILURE; 83289177Speter 84289177Speter if (!EVP_DigestInit_ex(hashctx, shake256, NULL) 85289177Speter || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s)) 86289177Speter || !EVP_DigestUpdate(hashctx, dom, sizeof(dom)) 87289177Speter || !EVP_DigestUpdate(hashctx, context, context_len)) { 88289177Speter EVP_MD_free(shake256); 89289177Speter return C448_FAILURE; 90289177Speter } 91289177Speter 92289177Speter EVP_MD_free(shake256); 93289177Speter return C448_SUCCESS; 94289177Speter} 95289177Speter 96289177Speter/* In this file because it uses the hash */ 97289177Speterc448_error_t 98289177Speterossl_c448_ed448_convert_private_key_to_x448( 99289177Speter OSSL_LIB_CTX *ctx, 100289177Speter uint8_t x[X448_PRIVATE_BYTES], 101289177Speter const uint8_t ed [EDDSA_448_PRIVATE_BYTES], 102289177Speter const char *propq) 103289177Speter{ 104289177Speter /* pass the private key through oneshot_hash function */ 105289177Speter /* and keep the first X448_PRIVATE_BYTES bytes */ 106289177Speter return oneshot_hash(ctx, x, X448_PRIVATE_BYTES, ed, 107289177Speter EDDSA_448_PRIVATE_BYTES, propq); 108289177Speter} 109289177Speter 110289177Speterc448_error_t 111289177Speterossl_c448_ed448_derive_public_key( 112289177Speter OSSL_LIB_CTX *ctx, 113289177Speter uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 114289177Speter const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], 115289177Speter const char *propq) 116289177Speter{ 117289177Speter /* only this much used for keygen */ 118289177Speter uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]; 119289177Speter curve448_scalar_t secret_scalar; 120289177Speter unsigned int c; 121289177Speter curve448_point_t p; 122289177Speter 123289177Speter if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser), 124289177Speter privkey, 125289177Speter EDDSA_448_PRIVATE_BYTES, 126289177Speter propq)) 127289177Speter return C448_FAILURE; 128289177Speter 129289177Speter clamp(secret_scalar_ser); 130289177Speter 131289177Speter ossl_curve448_scalar_decode_long(secret_scalar, secret_scalar_ser, 132289177Speter sizeof(secret_scalar_ser)); 133289177Speter 134289177Speter /* 135289177Speter * Since we are going to mul_by_cofactor during encoding, divide by it 136289177Speter * here. However, the EdDSA base point is not the same as the decaf base 137289177Speter * point if the sigma isogeny is in use: the EdDSA base point is on 138289177Speter * Etwist_d/(1-d) and the decaf base point is on Etwist_d, and when 139289177Speter * converted it effectively picks up a factor of 2 from the isogenies. So 140289177Speter * we might start at 2 instead of 1. 141289177Speter */ 142289177Speter for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1) 143289177Speter ossl_curve448_scalar_halve(secret_scalar, secret_scalar); 144289177Speter 145289177Speter ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base, 146289177Speter secret_scalar); 147289177Speter 148289177Speter ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p); 149289177Speter 150289177Speter /* Cleanup */ 151289177Speter ossl_curve448_scalar_destroy(secret_scalar); 152289177Speter ossl_curve448_point_destroy(p); 153289177Speter OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser)); 154289177Speter 155289177Speter return C448_SUCCESS; 156289177Speter} 157289177Speter 158289177Speterc448_error_t 159289177Speterossl_c448_ed448_sign(OSSL_LIB_CTX *ctx, 160289177Speter uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 161289177Speter const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], 162289177Speter const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 163289177Speter const uint8_t *message, size_t message_len, 164289177Speter uint8_t prehashed, const uint8_t *context, 165289177Speter size_t context_len, const char *propq) 166289177Speter{ 167289177Speter curve448_scalar_t secret_scalar; 168289177Speter EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); 169289177Speter c448_error_t ret = C448_FAILURE; 170289177Speter curve448_scalar_t nonce_scalar; 171289177Speter uint8_t nonce_point[EDDSA_448_PUBLIC_BYTES] = { 0 }; 172289177Speter unsigned int c; 173289177Speter curve448_scalar_t challenge_scalar; 174289177Speter 175289177Speter if (hashctx == NULL) 176289177Speter return C448_FAILURE; 177289177Speter 178289177Speter { 179289177Speter /* 180289177Speter * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialized 181289177Speter * secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed. 182289177Speter */ 183289177Speter uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2]; 184289177Speter 185289177Speter if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey, 186289177Speter EDDSA_448_PRIVATE_BYTES, propq)) 187289177Speter goto err; 188289177Speter clamp(expanded); 189289177Speter ossl_curve448_scalar_decode_long(secret_scalar, expanded, 190289177Speter EDDSA_448_PRIVATE_BYTES); 191289177Speter 192289177Speter /* Hash to create the nonce */ 193289177Speter if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, 194289177Speter context_len, propq) 195289177Speter || !EVP_DigestUpdate(hashctx, 196289177Speter expanded + EDDSA_448_PRIVATE_BYTES, 197289177Speter EDDSA_448_PRIVATE_BYTES) 198289177Speter || !EVP_DigestUpdate(hashctx, message, message_len)) { 199289177Speter OPENSSL_cleanse(expanded, sizeof(expanded)); 200289177Speter goto err; 201289177Speter } 202289177Speter OPENSSL_cleanse(expanded, sizeof(expanded)); 203289177Speter } 204289177Speter 205289177Speter /* Decode the nonce */ 206289177Speter { 207289177Speter uint8_t nonce[2 * EDDSA_448_PRIVATE_BYTES]; 208289177Speter 209289177Speter if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce))) 210289177Speter goto err; 211289177Speter ossl_curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce)); 212289177Speter OPENSSL_cleanse(nonce, sizeof(nonce)); 213289177Speter } 214289177Speter 215289177Speter { 216289177Speter /* Scalarmul to create the nonce-point */ 217289177Speter curve448_scalar_t nonce_scalar_2; 218289177Speter curve448_point_t p; 219289177Speter 220289177Speter ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar); 221289177Speter for (c = 2; c < C448_EDDSA_ENCODE_RATIO; c <<= 1) 222289177Speter ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2); 223289177Speter 224289177Speter ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base, 225289177Speter nonce_scalar_2); 226289177Speter ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p); 227289177Speter ossl_curve448_point_destroy(p); 228289177Speter ossl_curve448_scalar_destroy(nonce_scalar_2); 229289177Speter } 230289177Speter 231289177Speter { 232289177Speter uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES]; 233289177Speter 234289177Speter /* Compute the challenge */ 235289177Speter if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len, 236289177Speter propq) 237289177Speter || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point)) 238289177Speter || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) 239289177Speter || !EVP_DigestUpdate(hashctx, message, message_len) 240289177Speter || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) 241289177Speter goto err; 242289177Speter 243289177Speter ossl_curve448_scalar_decode_long(challenge_scalar, challenge, 244289177Speter sizeof(challenge)); 245289177Speter OPENSSL_cleanse(challenge, sizeof(challenge)); 246289177Speter } 247289177Speter 248289177Speter ossl_curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar); 249289177Speter ossl_curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar); 250289177Speter 251289177Speter OPENSSL_cleanse(signature, EDDSA_448_SIGNATURE_BYTES); 252289177Speter memcpy(signature, nonce_point, sizeof(nonce_point)); 253289177Speter ossl_curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES], 254289177Speter challenge_scalar); 255289177Speter 256289177Speter ossl_curve448_scalar_destroy(secret_scalar); 257289177Speter ossl_curve448_scalar_destroy(nonce_scalar); 258289177Speter ossl_curve448_scalar_destroy(challenge_scalar); 259289177Speter 260289177Speter ret = C448_SUCCESS; 261289177Speter err: 262289177Speter EVP_MD_CTX_free(hashctx); 263289177Speter return ret; 264289177Speter} 265289177Speter 266289177Speterc448_error_t 267289177Speterossl_c448_ed448_sign_prehash( 268289177Speter OSSL_LIB_CTX *ctx, 269289177Speter uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 270289177Speter const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], 271289177Speter const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 272289177Speter const uint8_t hash[64], const uint8_t *context, 273289177Speter size_t context_len, const char *propq) 274289177Speter{ 275289177Speter return ossl_c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1, 276289177Speter context, context_len, propq); 277289177Speter} 278289177Speter 279289177Speterc448_error_t 280289177Speterossl_c448_ed448_verify( 281289177Speter OSSL_LIB_CTX *ctx, 282289177Speter const uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 283289177Speter const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 284289177Speter const uint8_t *message, size_t message_len, 285289177Speter uint8_t prehashed, const uint8_t *context, 286289177Speter uint8_t context_len, const char *propq) 287289177Speter{ 288289177Speter curve448_point_t pk_point, r_point; 289289177Speter c448_error_t error; 290289177Speter curve448_scalar_t challenge_scalar; 291289177Speter curve448_scalar_t response_scalar; 292289177Speter /* Order in little endian format */ 293289177Speter static const uint8_t order[] = { 294289177Speter 0xF3, 0x44, 0x58, 0xAB, 0x92, 0xC2, 0x78, 0x23, 0x55, 0x8F, 0xC5, 0x8D, 295289177Speter 0x72, 0xC2, 0x6C, 0x21, 0x90, 0x36, 0xD6, 0xAE, 0x49, 0xDB, 0x4E, 0xC4, 296289177Speter 0xE9, 0x23, 0xCA, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 297289177Speter 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 298289177Speter 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00 299289177Speter }; 300289177Speter int i; 301289177Speter 302289177Speter /* 303289177Speter * Check that s (second 57 bytes of the sig) is less than the order. Both 304289177Speter * s and the order are in little-endian format. This can be done in 305289177Speter * variable time, since if this is not the case the signature if publicly 306289177Speter * invalid. 307289177Speter */ 308289177Speter for (i = EDDSA_448_PUBLIC_BYTES - 1; i >= 0; i--) { 309289177Speter if (signature[i + EDDSA_448_PUBLIC_BYTES] > order[i]) 310289177Speter return C448_FAILURE; 311289177Speter if (signature[i + EDDSA_448_PUBLIC_BYTES] < order[i]) 312289177Speter break; 313289177Speter } 314289177Speter if (i < 0) 315289177Speter return C448_FAILURE; 316 317 error = 318 ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey); 319 320 if (C448_SUCCESS != error) 321 return error; 322 323 error = 324 ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature); 325 if (C448_SUCCESS != error) 326 return error; 327 328 { 329 /* Compute the challenge */ 330 EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); 331 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES]; 332 333 if (hashctx == NULL 334 || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context, 335 context_len, propq) 336 || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES) 337 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) 338 || !EVP_DigestUpdate(hashctx, message, message_len) 339 || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) { 340 EVP_MD_CTX_free(hashctx); 341 return C448_FAILURE; 342 } 343 344 EVP_MD_CTX_free(hashctx); 345 ossl_curve448_scalar_decode_long(challenge_scalar, challenge, 346 sizeof(challenge)); 347 OPENSSL_cleanse(challenge, sizeof(challenge)); 348 } 349 ossl_curve448_scalar_sub(challenge_scalar, ossl_curve448_scalar_zero, 350 challenge_scalar); 351 352 ossl_curve448_scalar_decode_long(response_scalar, 353 &signature[EDDSA_448_PUBLIC_BYTES], 354 EDDSA_448_PRIVATE_BYTES); 355 356 /* pk_point = -c(x(P)) + (cx + k)G = kG */ 357 ossl_curve448_base_double_scalarmul_non_secret(pk_point, 358 response_scalar, 359 pk_point, challenge_scalar); 360 return c448_succeed_if(ossl_curve448_point_eq(pk_point, r_point)); 361} 362 363c448_error_t 364ossl_c448_ed448_verify_prehash( 365 OSSL_LIB_CTX *ctx, 366 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 367 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 368 const uint8_t hash[64], const uint8_t *context, 369 uint8_t context_len, const char *propq) 370{ 371 return ossl_c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context, 372 context_len, propq); 373} 374 375int 376ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t *message, 377 size_t message_len, const uint8_t public_key[57], 378 const uint8_t private_key[57], const uint8_t *context, 379 size_t context_len, const char *propq) 380{ 381 return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message, 382 message_len, 0, context, context_len, 383 propq) == C448_SUCCESS; 384} 385 386int 387ossl_ed448_verify(OSSL_LIB_CTX *ctx, const uint8_t *message, size_t message_len, 388 const uint8_t signature[114], const uint8_t public_key[57], 389 const uint8_t *context, size_t context_len, const char *propq) 390{ 391 return ossl_c448_ed448_verify(ctx, signature, public_key, message, 392 message_len, 0, context, (uint8_t)context_len, 393 propq) == C448_SUCCESS; 394} 395 396int 397ossl_ed448ph_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64], 398 const uint8_t public_key[57], const uint8_t private_key[57], 399 const uint8_t *context, size_t context_len, const char *propq) 400{ 401 return ossl_c448_ed448_sign_prehash(ctx, out_sig, private_key, public_key, 402 hash, context, context_len, 403 propq) == C448_SUCCESS; 404} 405 406int 407ossl_ed448ph_verify(OSSL_LIB_CTX *ctx, const uint8_t hash[64], 408 const uint8_t signature[114], const uint8_t public_key[57], 409 const uint8_t *context, size_t context_len, 410 const char *propq) 411{ 412 return ossl_c448_ed448_verify_prehash(ctx, signature, public_key, hash, 413 context, (uint8_t)context_len, 414 propq) == C448_SUCCESS; 415} 416 417int 418ossl_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