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 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 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 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 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 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 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 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 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 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 = ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey); 325 326 if (C448_SUCCESS != error) 327 return error; 328 329 error = ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature); 330 if (C448_SUCCESS != error) 331 return error; 332 333 { 334 /* Compute the challenge */ 335 EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); 336 uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES]; 337 338 if (hashctx == NULL 339 || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context, 340 context_len, propq) 341 || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES) 342 || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) 343 || !EVP_DigestUpdate(hashctx, message, message_len) 344 || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) { 345 EVP_MD_CTX_free(hashctx); 346 return C448_FAILURE; 347 } 348 349 EVP_MD_CTX_free(hashctx); 350 ossl_curve448_scalar_decode_long(challenge_scalar, challenge, 351 sizeof(challenge)); 352 OPENSSL_cleanse(challenge, sizeof(challenge)); 353 } 354 ossl_curve448_scalar_sub(challenge_scalar, ossl_curve448_scalar_zero, 355 challenge_scalar); 356 357 ossl_curve448_scalar_decode_long(response_scalar, 358 &signature[EDDSA_448_PUBLIC_BYTES], 359 EDDSA_448_PRIVATE_BYTES); 360 361 /* pk_point = -c(x(P)) + (cx + k)G = kG */ 362 ossl_curve448_base_double_scalarmul_non_secret(pk_point, 363 response_scalar, 364 pk_point, challenge_scalar); 365 return c448_succeed_if(ossl_curve448_point_eq(pk_point, r_point)); 366 } 367 368 c448_error_t 369 ossl_c448_ed448_verify_prehash( 370 OSSL_LIB_CTX *ctx, 371 const uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 372 const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 373 const uint8_t hash[64], const uint8_t *context, 374 uint8_t context_len, const char *propq) 375 { 376 return ossl_c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context, 377 context_len, propq); 378 } 379 380 int ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, 381 const uint8_t *message, size_t message_len, 382 const uint8_t public_key[57], const uint8_t private_key[57], 383 const uint8_t *context, size_t context_len, 384 const uint8_t phflag, const char *propq) 385 { 386 return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message, 387 message_len, phflag, context, context_len, 388 propq) 389 == C448_SUCCESS; 390 } 391 392 /* 393 * This function should not be necessary since ossl_ed448_verify() already 394 * does this check internally. 395 * For some reason the FIPS ACVP requires a EDDSA KeyVer test. 396 */ 397 int ossl_ed448_pubkey_verify(const uint8_t *pub, size_t pub_len) 398 { 399 return c448_ed448_pubkey_verify(pub, pub_len); 400 } 401 402 int ossl_ed448_verify(OSSL_LIB_CTX *ctx, 403 const uint8_t *message, size_t message_len, 404 const uint8_t signature[114], const uint8_t public_key[57], 405 const uint8_t *context, size_t context_len, 406 const uint8_t phflag, const char *propq) 407 { 408 return ossl_c448_ed448_verify(ctx, signature, public_key, message, 409 message_len, phflag, context, (uint8_t)context_len, 410 propq) 411 == C448_SUCCESS; 412 } 413 414 int ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57], 415 const uint8_t private_key[57], const char *propq) 416 { 417 return ossl_c448_ed448_derive_public_key(ctx, out_public_key, private_key, 418 propq) 419 == C448_SUCCESS; 420 } 421