Home | History | Annotate | Line # | Download | only in curve448
      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