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