1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright 2015-2016 Cryptography Research, Inc. 4e1051a39Sopenharmony_ci * 5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 6e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 9e1051a39Sopenharmony_ci * 10e1051a39Sopenharmony_ci * Originally written by Mike Hamburg 11e1051a39Sopenharmony_ci */ 12e1051a39Sopenharmony_ci#include <string.h> 13e1051a39Sopenharmony_ci#include <openssl/crypto.h> 14e1051a39Sopenharmony_ci#include <openssl/evp.h> 15e1051a39Sopenharmony_ci#include "crypto/ecx.h" 16e1051a39Sopenharmony_ci#include "curve448_local.h" 17e1051a39Sopenharmony_ci#include "word.h" 18e1051a39Sopenharmony_ci#include "ed448.h" 19e1051a39Sopenharmony_ci#include "internal/numbers.h" 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_ci#define COFACTOR 4 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_cistatic c448_error_t oneshot_hash(OSSL_LIB_CTX *ctx, uint8_t *out, size_t outlen, 24e1051a39Sopenharmony_ci const uint8_t *in, size_t inlen, 25e1051a39Sopenharmony_ci const char *propq) 26e1051a39Sopenharmony_ci{ 27e1051a39Sopenharmony_ci EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); 28e1051a39Sopenharmony_ci EVP_MD *shake256 = NULL; 29e1051a39Sopenharmony_ci c448_error_t ret = C448_FAILURE; 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ci if (hashctx == NULL) 32e1051a39Sopenharmony_ci return C448_FAILURE; 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ci shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq); 35e1051a39Sopenharmony_ci if (shake256 == NULL) 36e1051a39Sopenharmony_ci goto err; 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_ci if (!EVP_DigestInit_ex(hashctx, shake256, NULL) 39e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, in, inlen) 40e1051a39Sopenharmony_ci || !EVP_DigestFinalXOF(hashctx, out, outlen)) 41e1051a39Sopenharmony_ci goto err; 42e1051a39Sopenharmony_ci 43e1051a39Sopenharmony_ci ret = C448_SUCCESS; 44e1051a39Sopenharmony_ci err: 45e1051a39Sopenharmony_ci EVP_MD_CTX_free(hashctx); 46e1051a39Sopenharmony_ci EVP_MD_free(shake256); 47e1051a39Sopenharmony_ci return ret; 48e1051a39Sopenharmony_ci} 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_cistatic void clamp(uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]) 51e1051a39Sopenharmony_ci{ 52e1051a39Sopenharmony_ci secret_scalar_ser[0] &= -COFACTOR; 53e1051a39Sopenharmony_ci secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 1] = 0; 54e1051a39Sopenharmony_ci secret_scalar_ser[EDDSA_448_PRIVATE_BYTES - 2] |= 0x80; 55e1051a39Sopenharmony_ci} 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_cistatic c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx, 58e1051a39Sopenharmony_ci uint8_t prehashed, 59e1051a39Sopenharmony_ci uint8_t for_prehash, 60e1051a39Sopenharmony_ci const uint8_t *context, 61e1051a39Sopenharmony_ci size_t context_len, 62e1051a39Sopenharmony_ci const char *propq) 63e1051a39Sopenharmony_ci{ 64e1051a39Sopenharmony_ci#ifdef CHARSET_EBCDIC 65e1051a39Sopenharmony_ci const char dom_s[] = {0x53, 0x69, 0x67, 0x45, 66e1051a39Sopenharmony_ci 0x64, 0x34, 0x34, 0x38, 0x00}; 67e1051a39Sopenharmony_ci#else 68e1051a39Sopenharmony_ci const char dom_s[] = "SigEd448"; 69e1051a39Sopenharmony_ci#endif 70e1051a39Sopenharmony_ci uint8_t dom[2]; 71e1051a39Sopenharmony_ci EVP_MD *shake256 = NULL; 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci if (context_len > UINT8_MAX) 74e1051a39Sopenharmony_ci return C448_FAILURE; 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci dom[0] = (uint8_t)(2 - (prehashed == 0 ? 1 : 0) 77e1051a39Sopenharmony_ci - (for_prehash == 0 ? 1 : 0)); 78e1051a39Sopenharmony_ci dom[1] = (uint8_t)context_len; 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ci shake256 = EVP_MD_fetch(ctx, "SHAKE256", propq); 81e1051a39Sopenharmony_ci if (shake256 == NULL) 82e1051a39Sopenharmony_ci return C448_FAILURE; 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci if (!EVP_DigestInit_ex(hashctx, shake256, NULL) 85e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s)) 86e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, dom, sizeof(dom)) 87e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, context, context_len)) { 88e1051a39Sopenharmony_ci EVP_MD_free(shake256); 89e1051a39Sopenharmony_ci return C448_FAILURE; 90e1051a39Sopenharmony_ci } 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_ci EVP_MD_free(shake256); 93e1051a39Sopenharmony_ci return C448_SUCCESS; 94e1051a39Sopenharmony_ci} 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci/* In this file because it uses the hash */ 97e1051a39Sopenharmony_cic448_error_t 98e1051a39Sopenharmony_ciossl_c448_ed448_convert_private_key_to_x448( 99e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, 100e1051a39Sopenharmony_ci uint8_t x[X448_PRIVATE_BYTES], 101e1051a39Sopenharmony_ci const uint8_t ed [EDDSA_448_PRIVATE_BYTES], 102e1051a39Sopenharmony_ci const char *propq) 103e1051a39Sopenharmony_ci{ 104e1051a39Sopenharmony_ci /* pass the private key through oneshot_hash function */ 105e1051a39Sopenharmony_ci /* and keep the first X448_PRIVATE_BYTES bytes */ 106e1051a39Sopenharmony_ci return oneshot_hash(ctx, x, X448_PRIVATE_BYTES, ed, 107e1051a39Sopenharmony_ci EDDSA_448_PRIVATE_BYTES, propq); 108e1051a39Sopenharmony_ci} 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_cic448_error_t 111e1051a39Sopenharmony_ciossl_c448_ed448_derive_public_key( 112e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, 113e1051a39Sopenharmony_ci uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 114e1051a39Sopenharmony_ci const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], 115e1051a39Sopenharmony_ci const char *propq) 116e1051a39Sopenharmony_ci{ 117e1051a39Sopenharmony_ci /* only this much used for keygen */ 118e1051a39Sopenharmony_ci uint8_t secret_scalar_ser[EDDSA_448_PRIVATE_BYTES]; 119e1051a39Sopenharmony_ci curve448_scalar_t secret_scalar; 120e1051a39Sopenharmony_ci unsigned int c; 121e1051a39Sopenharmony_ci curve448_point_t p; 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci if (!oneshot_hash(ctx, secret_scalar_ser, sizeof(secret_scalar_ser), 124e1051a39Sopenharmony_ci privkey, 125e1051a39Sopenharmony_ci EDDSA_448_PRIVATE_BYTES, 126e1051a39Sopenharmony_ci propq)) 127e1051a39Sopenharmony_ci return C448_FAILURE; 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci clamp(secret_scalar_ser); 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ci ossl_curve448_scalar_decode_long(secret_scalar, secret_scalar_ser, 132e1051a39Sopenharmony_ci sizeof(secret_scalar_ser)); 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci /* 135e1051a39Sopenharmony_ci * Since we are going to mul_by_cofactor during encoding, divide by it 136e1051a39Sopenharmony_ci * here. However, the EdDSA base point is not the same as the decaf base 137e1051a39Sopenharmony_ci * point if the sigma isogeny is in use: the EdDSA base point is on 138e1051a39Sopenharmony_ci * Etwist_d/(1-d) and the decaf base point is on Etwist_d, and when 139e1051a39Sopenharmony_ci * converted it effectively picks up a factor of 2 from the isogenies. So 140e1051a39Sopenharmony_ci * we might start at 2 instead of 1. 141e1051a39Sopenharmony_ci */ 142e1051a39Sopenharmony_ci for (c = 1; c < C448_EDDSA_ENCODE_RATIO; c <<= 1) 143e1051a39Sopenharmony_ci ossl_curve448_scalar_halve(secret_scalar, secret_scalar); 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base, 146e1051a39Sopenharmony_ci secret_scalar); 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ci ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(pubkey, p); 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ci /* Cleanup */ 151e1051a39Sopenharmony_ci ossl_curve448_scalar_destroy(secret_scalar); 152e1051a39Sopenharmony_ci ossl_curve448_point_destroy(p); 153e1051a39Sopenharmony_ci OPENSSL_cleanse(secret_scalar_ser, sizeof(secret_scalar_ser)); 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci return C448_SUCCESS; 156e1051a39Sopenharmony_ci} 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_cic448_error_t 159e1051a39Sopenharmony_ciossl_c448_ed448_sign(OSSL_LIB_CTX *ctx, 160e1051a39Sopenharmony_ci uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 161e1051a39Sopenharmony_ci const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], 162e1051a39Sopenharmony_ci const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 163e1051a39Sopenharmony_ci const uint8_t *message, size_t message_len, 164e1051a39Sopenharmony_ci uint8_t prehashed, const uint8_t *context, 165e1051a39Sopenharmony_ci size_t context_len, const char *propq) 166e1051a39Sopenharmony_ci{ 167e1051a39Sopenharmony_ci curve448_scalar_t secret_scalar; 168e1051a39Sopenharmony_ci EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); 169e1051a39Sopenharmony_ci c448_error_t ret = C448_FAILURE; 170e1051a39Sopenharmony_ci curve448_scalar_t nonce_scalar; 171e1051a39Sopenharmony_ci uint8_t nonce_point[EDDSA_448_PUBLIC_BYTES] = { 0 }; 172e1051a39Sopenharmony_ci unsigned int c; 173e1051a39Sopenharmony_ci curve448_scalar_t challenge_scalar; 174e1051a39Sopenharmony_ci 175e1051a39Sopenharmony_ci if (hashctx == NULL) 176e1051a39Sopenharmony_ci return C448_FAILURE; 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci { 179e1051a39Sopenharmony_ci /* 180e1051a39Sopenharmony_ci * Schedule the secret key, First EDDSA_448_PRIVATE_BYTES is serialized 181e1051a39Sopenharmony_ci * secret scalar,next EDDSA_448_PRIVATE_BYTES bytes is the seed. 182e1051a39Sopenharmony_ci */ 183e1051a39Sopenharmony_ci uint8_t expanded[EDDSA_448_PRIVATE_BYTES * 2]; 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci if (!oneshot_hash(ctx, expanded, sizeof(expanded), privkey, 186e1051a39Sopenharmony_ci EDDSA_448_PRIVATE_BYTES, propq)) 187e1051a39Sopenharmony_ci goto err; 188e1051a39Sopenharmony_ci clamp(expanded); 189e1051a39Sopenharmony_ci ossl_curve448_scalar_decode_long(secret_scalar, expanded, 190e1051a39Sopenharmony_ci EDDSA_448_PRIVATE_BYTES); 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ci /* Hash to create the nonce */ 193e1051a39Sopenharmony_ci if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, 194e1051a39Sopenharmony_ci context_len, propq) 195e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, 196e1051a39Sopenharmony_ci expanded + EDDSA_448_PRIVATE_BYTES, 197e1051a39Sopenharmony_ci EDDSA_448_PRIVATE_BYTES) 198e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, message, message_len)) { 199e1051a39Sopenharmony_ci OPENSSL_cleanse(expanded, sizeof(expanded)); 200e1051a39Sopenharmony_ci goto err; 201e1051a39Sopenharmony_ci } 202e1051a39Sopenharmony_ci OPENSSL_cleanse(expanded, sizeof(expanded)); 203e1051a39Sopenharmony_ci } 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ci /* Decode the nonce */ 206e1051a39Sopenharmony_ci { 207e1051a39Sopenharmony_ci uint8_t nonce[2 * EDDSA_448_PRIVATE_BYTES]; 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ci if (!EVP_DigestFinalXOF(hashctx, nonce, sizeof(nonce))) 210e1051a39Sopenharmony_ci goto err; 211e1051a39Sopenharmony_ci ossl_curve448_scalar_decode_long(nonce_scalar, nonce, sizeof(nonce)); 212e1051a39Sopenharmony_ci OPENSSL_cleanse(nonce, sizeof(nonce)); 213e1051a39Sopenharmony_ci } 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_ci { 216e1051a39Sopenharmony_ci /* Scalarmul to create the nonce-point */ 217e1051a39Sopenharmony_ci curve448_scalar_t nonce_scalar_2; 218e1051a39Sopenharmony_ci curve448_point_t p; 219e1051a39Sopenharmony_ci 220e1051a39Sopenharmony_ci ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar); 221e1051a39Sopenharmony_ci for (c = 2; c < C448_EDDSA_ENCODE_RATIO; c <<= 1) 222e1051a39Sopenharmony_ci ossl_curve448_scalar_halve(nonce_scalar_2, nonce_scalar_2); 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ci ossl_curve448_precomputed_scalarmul(p, ossl_curve448_precomputed_base, 225e1051a39Sopenharmony_ci nonce_scalar_2); 226e1051a39Sopenharmony_ci ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa(nonce_point, p); 227e1051a39Sopenharmony_ci ossl_curve448_point_destroy(p); 228e1051a39Sopenharmony_ci ossl_curve448_scalar_destroy(nonce_scalar_2); 229e1051a39Sopenharmony_ci } 230e1051a39Sopenharmony_ci 231e1051a39Sopenharmony_ci { 232e1051a39Sopenharmony_ci uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES]; 233e1051a39Sopenharmony_ci 234e1051a39Sopenharmony_ci /* Compute the challenge */ 235e1051a39Sopenharmony_ci if (!hash_init_with_dom(ctx, hashctx, prehashed, 0, context, context_len, 236e1051a39Sopenharmony_ci propq) 237e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, nonce_point, sizeof(nonce_point)) 238e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) 239e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, message, message_len) 240e1051a39Sopenharmony_ci || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) 241e1051a39Sopenharmony_ci goto err; 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci ossl_curve448_scalar_decode_long(challenge_scalar, challenge, 244e1051a39Sopenharmony_ci sizeof(challenge)); 245e1051a39Sopenharmony_ci OPENSSL_cleanse(challenge, sizeof(challenge)); 246e1051a39Sopenharmony_ci } 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ci ossl_curve448_scalar_mul(challenge_scalar, challenge_scalar, secret_scalar); 249e1051a39Sopenharmony_ci ossl_curve448_scalar_add(challenge_scalar, challenge_scalar, nonce_scalar); 250e1051a39Sopenharmony_ci 251e1051a39Sopenharmony_ci OPENSSL_cleanse(signature, EDDSA_448_SIGNATURE_BYTES); 252e1051a39Sopenharmony_ci memcpy(signature, nonce_point, sizeof(nonce_point)); 253e1051a39Sopenharmony_ci ossl_curve448_scalar_encode(&signature[EDDSA_448_PUBLIC_BYTES], 254e1051a39Sopenharmony_ci challenge_scalar); 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci ossl_curve448_scalar_destroy(secret_scalar); 257e1051a39Sopenharmony_ci ossl_curve448_scalar_destroy(nonce_scalar); 258e1051a39Sopenharmony_ci ossl_curve448_scalar_destroy(challenge_scalar); 259e1051a39Sopenharmony_ci 260e1051a39Sopenharmony_ci ret = C448_SUCCESS; 261e1051a39Sopenharmony_ci err: 262e1051a39Sopenharmony_ci EVP_MD_CTX_free(hashctx); 263e1051a39Sopenharmony_ci return ret; 264e1051a39Sopenharmony_ci} 265e1051a39Sopenharmony_ci 266e1051a39Sopenharmony_cic448_error_t 267e1051a39Sopenharmony_ciossl_c448_ed448_sign_prehash( 268e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, 269e1051a39Sopenharmony_ci uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 270e1051a39Sopenharmony_ci const uint8_t privkey[EDDSA_448_PRIVATE_BYTES], 271e1051a39Sopenharmony_ci const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 272e1051a39Sopenharmony_ci const uint8_t hash[64], const uint8_t *context, 273e1051a39Sopenharmony_ci size_t context_len, const char *propq) 274e1051a39Sopenharmony_ci{ 275e1051a39Sopenharmony_ci return ossl_c448_ed448_sign(ctx, signature, privkey, pubkey, hash, 64, 1, 276e1051a39Sopenharmony_ci context, context_len, propq); 277e1051a39Sopenharmony_ci} 278e1051a39Sopenharmony_ci 279e1051a39Sopenharmony_cic448_error_t 280e1051a39Sopenharmony_ciossl_c448_ed448_verify( 281e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, 282e1051a39Sopenharmony_ci const uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 283e1051a39Sopenharmony_ci const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 284e1051a39Sopenharmony_ci const uint8_t *message, size_t message_len, 285e1051a39Sopenharmony_ci uint8_t prehashed, const uint8_t *context, 286e1051a39Sopenharmony_ci uint8_t context_len, const char *propq) 287e1051a39Sopenharmony_ci{ 288e1051a39Sopenharmony_ci curve448_point_t pk_point, r_point; 289e1051a39Sopenharmony_ci c448_error_t error; 290e1051a39Sopenharmony_ci curve448_scalar_t challenge_scalar; 291e1051a39Sopenharmony_ci curve448_scalar_t response_scalar; 292e1051a39Sopenharmony_ci /* Order in little endian format */ 293e1051a39Sopenharmony_ci static const uint8_t order[] = { 294e1051a39Sopenharmony_ci 0xF3, 0x44, 0x58, 0xAB, 0x92, 0xC2, 0x78, 0x23, 0x55, 0x8F, 0xC5, 0x8D, 295e1051a39Sopenharmony_ci 0x72, 0xC2, 0x6C, 0x21, 0x90, 0x36, 0xD6, 0xAE, 0x49, 0xDB, 0x4E, 0xC4, 296e1051a39Sopenharmony_ci 0xE9, 0x23, 0xCA, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 297e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 298e1051a39Sopenharmony_ci 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00 299e1051a39Sopenharmony_ci }; 300e1051a39Sopenharmony_ci int i; 301e1051a39Sopenharmony_ci 302e1051a39Sopenharmony_ci /* 303e1051a39Sopenharmony_ci * Check that s (second 57 bytes of the sig) is less than the order. Both 304e1051a39Sopenharmony_ci * s and the order are in little-endian format. This can be done in 305e1051a39Sopenharmony_ci * variable time, since if this is not the case the signature if publicly 306e1051a39Sopenharmony_ci * invalid. 307e1051a39Sopenharmony_ci */ 308e1051a39Sopenharmony_ci for (i = EDDSA_448_PUBLIC_BYTES - 1; i >= 0; i--) { 309e1051a39Sopenharmony_ci if (signature[i + EDDSA_448_PUBLIC_BYTES] > order[i]) 310e1051a39Sopenharmony_ci return C448_FAILURE; 311e1051a39Sopenharmony_ci if (signature[i + EDDSA_448_PUBLIC_BYTES] < order[i]) 312e1051a39Sopenharmony_ci break; 313e1051a39Sopenharmony_ci } 314e1051a39Sopenharmony_ci if (i < 0) 315e1051a39Sopenharmony_ci return C448_FAILURE; 316e1051a39Sopenharmony_ci 317e1051a39Sopenharmony_ci error = 318e1051a39Sopenharmony_ci ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey); 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci if (C448_SUCCESS != error) 321e1051a39Sopenharmony_ci return error; 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ci error = 324e1051a39Sopenharmony_ci ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature); 325e1051a39Sopenharmony_ci if (C448_SUCCESS != error) 326e1051a39Sopenharmony_ci return error; 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_ci { 329e1051a39Sopenharmony_ci /* Compute the challenge */ 330e1051a39Sopenharmony_ci EVP_MD_CTX *hashctx = EVP_MD_CTX_new(); 331e1051a39Sopenharmony_ci uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES]; 332e1051a39Sopenharmony_ci 333e1051a39Sopenharmony_ci if (hashctx == NULL 334e1051a39Sopenharmony_ci || !hash_init_with_dom(ctx, hashctx, prehashed, 0, context, 335e1051a39Sopenharmony_ci context_len, propq) 336e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES) 337e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES) 338e1051a39Sopenharmony_ci || !EVP_DigestUpdate(hashctx, message, message_len) 339e1051a39Sopenharmony_ci || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) { 340e1051a39Sopenharmony_ci EVP_MD_CTX_free(hashctx); 341e1051a39Sopenharmony_ci return C448_FAILURE; 342e1051a39Sopenharmony_ci } 343e1051a39Sopenharmony_ci 344e1051a39Sopenharmony_ci EVP_MD_CTX_free(hashctx); 345e1051a39Sopenharmony_ci ossl_curve448_scalar_decode_long(challenge_scalar, challenge, 346e1051a39Sopenharmony_ci sizeof(challenge)); 347e1051a39Sopenharmony_ci OPENSSL_cleanse(challenge, sizeof(challenge)); 348e1051a39Sopenharmony_ci } 349e1051a39Sopenharmony_ci ossl_curve448_scalar_sub(challenge_scalar, ossl_curve448_scalar_zero, 350e1051a39Sopenharmony_ci challenge_scalar); 351e1051a39Sopenharmony_ci 352e1051a39Sopenharmony_ci ossl_curve448_scalar_decode_long(response_scalar, 353e1051a39Sopenharmony_ci &signature[EDDSA_448_PUBLIC_BYTES], 354e1051a39Sopenharmony_ci EDDSA_448_PRIVATE_BYTES); 355e1051a39Sopenharmony_ci 356e1051a39Sopenharmony_ci /* pk_point = -c(x(P)) + (cx + k)G = kG */ 357e1051a39Sopenharmony_ci ossl_curve448_base_double_scalarmul_non_secret(pk_point, 358e1051a39Sopenharmony_ci response_scalar, 359e1051a39Sopenharmony_ci pk_point, challenge_scalar); 360e1051a39Sopenharmony_ci return c448_succeed_if(ossl_curve448_point_eq(pk_point, r_point)); 361e1051a39Sopenharmony_ci} 362e1051a39Sopenharmony_ci 363e1051a39Sopenharmony_cic448_error_t 364e1051a39Sopenharmony_ciossl_c448_ed448_verify_prehash( 365e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, 366e1051a39Sopenharmony_ci const uint8_t signature[EDDSA_448_SIGNATURE_BYTES], 367e1051a39Sopenharmony_ci const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES], 368e1051a39Sopenharmony_ci const uint8_t hash[64], const uint8_t *context, 369e1051a39Sopenharmony_ci uint8_t context_len, const char *propq) 370e1051a39Sopenharmony_ci{ 371e1051a39Sopenharmony_ci return ossl_c448_ed448_verify(ctx, signature, pubkey, hash, 64, 1, context, 372e1051a39Sopenharmony_ci context_len, propq); 373e1051a39Sopenharmony_ci} 374e1051a39Sopenharmony_ci 375e1051a39Sopenharmony_ciint 376e1051a39Sopenharmony_ciossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t *message, 377e1051a39Sopenharmony_ci size_t message_len, const uint8_t public_key[57], 378e1051a39Sopenharmony_ci const uint8_t private_key[57], const uint8_t *context, 379e1051a39Sopenharmony_ci size_t context_len, const char *propq) 380e1051a39Sopenharmony_ci{ 381e1051a39Sopenharmony_ci return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message, 382e1051a39Sopenharmony_ci message_len, 0, context, context_len, 383e1051a39Sopenharmony_ci propq) == C448_SUCCESS; 384e1051a39Sopenharmony_ci} 385e1051a39Sopenharmony_ci 386e1051a39Sopenharmony_ciint 387e1051a39Sopenharmony_ciossl_ed448_verify(OSSL_LIB_CTX *ctx, const uint8_t *message, size_t message_len, 388e1051a39Sopenharmony_ci const uint8_t signature[114], const uint8_t public_key[57], 389e1051a39Sopenharmony_ci const uint8_t *context, size_t context_len, const char *propq) 390e1051a39Sopenharmony_ci{ 391e1051a39Sopenharmony_ci return ossl_c448_ed448_verify(ctx, signature, public_key, message, 392e1051a39Sopenharmony_ci message_len, 0, context, (uint8_t)context_len, 393e1051a39Sopenharmony_ci propq) == C448_SUCCESS; 394e1051a39Sopenharmony_ci} 395e1051a39Sopenharmony_ci 396e1051a39Sopenharmony_ciint 397e1051a39Sopenharmony_ciossl_ed448ph_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64], 398e1051a39Sopenharmony_ci const uint8_t public_key[57], const uint8_t private_key[57], 399e1051a39Sopenharmony_ci const uint8_t *context, size_t context_len, const char *propq) 400e1051a39Sopenharmony_ci{ 401e1051a39Sopenharmony_ci return ossl_c448_ed448_sign_prehash(ctx, out_sig, private_key, public_key, 402e1051a39Sopenharmony_ci hash, context, context_len, 403e1051a39Sopenharmony_ci propq) == C448_SUCCESS; 404e1051a39Sopenharmony_ci} 405e1051a39Sopenharmony_ci 406e1051a39Sopenharmony_ciint 407e1051a39Sopenharmony_ciossl_ed448ph_verify(OSSL_LIB_CTX *ctx, const uint8_t hash[64], 408e1051a39Sopenharmony_ci const uint8_t signature[114], const uint8_t public_key[57], 409e1051a39Sopenharmony_ci const uint8_t *context, size_t context_len, 410e1051a39Sopenharmony_ci const char *propq) 411e1051a39Sopenharmony_ci{ 412e1051a39Sopenharmony_ci return ossl_c448_ed448_verify_prehash(ctx, signature, public_key, hash, 413e1051a39Sopenharmony_ci context, (uint8_t)context_len, 414e1051a39Sopenharmony_ci propq) == C448_SUCCESS; 415e1051a39Sopenharmony_ci} 416e1051a39Sopenharmony_ci 417e1051a39Sopenharmony_ciint 418e1051a39Sopenharmony_ciossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57], 419e1051a39Sopenharmony_ci const uint8_t private_key[57], const char *propq) 420e1051a39Sopenharmony_ci{ 421e1051a39Sopenharmony_ci return ossl_c448_ed448_derive_public_key(ctx, out_public_key, private_key, 422e1051a39Sopenharmony_ci propq) == C448_SUCCESS; 423e1051a39Sopenharmony_ci} 424