/* Copyright (c) (2014,2015,2016,2017,2018,2019) Apple Inc. All rights reserved.
 *
 * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
 * is contained in the License.txt file distributed with corecrypto) and only to 
 * people who accept that license. IMPORTANT:  Any license rights granted to you by 
 * Apple Inc. (if any) are limited to internal use within your organization only on 
 * devices and computers you own or control, for the sole purpose of verifying the 
 * security characteristics and correct functioning of the Apple Software.  You may 
 * not, directly or indirectly, redistribute the Apple Software or any portions thereof.
 */

/*
    Based on reference code from <http://ed25519.cr.yp.to/> and <http://bench.cr.yp.to/supercop.html>.
*/

#ifndef _CORECRYPTO_CCED25519_PRIV_H_
#define _CORECRYPTO_CCED25519_PRIV_H_

#include <corecrypto/ccec25519.h>

/*!
    @function cced25519_sign_deterministic
    @abstract Produces a deterministic Ed25519 signature.

    @param  di          A valid descriptor for a 512 bit hash function for the platform
    @param  sig         Receives the 64-byte signature.
    @param  msg_len     Number of bytes to sign.
    @param  msg         Data to sign.
    @param  pk          32-byte public key as generated by cced25519_make_key_pair().
    @param  sk          32-byte secret key as generated by cced25519_make_key_pair().
    @param  rng         RNG for masking.
*/
CC_NONNULL_ALL
int cced25519_sign_deterministic(const struct ccdigest_info *di,
                                 ccec25519signature sig,
                                 size_t msg_len,
                                 const void *msg,
                                 const ccec25519pubkey pk,
                                 const ccec25519secretkey sk,
                                 struct ccrng_state *rng);

//===========================================================================================================================
//	Internals
//===========================================================================================================================

// Compatibility

typedef int32_t crypto_int32;
typedef uint32_t crypto_uint32;
typedef int64_t crypto_int64;
typedef uint64_t crypto_uint64;

// fe

typedef crypto_int32 fe[10];

void fe_mul(fe h, const fe f, const fe g);
void fe_sq(fe h, const fe f);
void fe_tobytes(unsigned char *s, const fe h);

// ge

// ge_p2: (X:Y:Z) satisfying x=X/Z, y=Y/Z
typedef struct {
    fe X;
    fe Y;
    fe Z;
} ge_p2;

// ge_p3: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
typedef struct {
    fe X;
    fe Y;
    fe Z;
    fe T;
} ge_p3;

// ge_p1p1: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
typedef struct {
    fe X;
    fe Y;
    fe Z;
    fe T;
} ge_p1p1;

// ge_precomp: (y+x,y-x,2dxy)
typedef struct {
    fe yplusx;
    fe yminusx;
    fe xy2d;
} ge_precomp;

typedef struct {
    fe YplusX;
    fe YminusX;
    fe Z;
    fe T2d;
} ge_cached;

int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); /* USED */
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s);
int ge_frombytes_vartime(ge_p3 *h, const unsigned char *s);
void ge_from_uniform(unsigned char s[32], const unsigned char r[32]);
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); /* USED */
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); /* USED */
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h); /* USED */
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); /* USED */
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a); /* USED */
int ge_scalarmult_base_masked(ge_p3 *h, const unsigned char *a, struct ccrng_state *rng); /* USED */
void ge_scalarmult_cofactor(ge_p3 *point); /* USED */
int ge_has_small_order(const unsigned char s[32]); /* USED */
void ge_scalarmult(ge_p3 *h, const unsigned char *a, const ge_p3 *p); /* USED */
void ge_tobytes(unsigned char *s, const ge_p2 *h); /* USED */
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p);
void fe_frombytes(fe h, const unsigned char *s);
void fe_0(fe h);
void fe_1(fe h);
void fe_mul(fe h, const fe f, const fe g);
void fe_sub(fe h, const fe f, const fe g);
void fe_add(fe h, const fe f, const fe g);
void fe_pow22523(fe out, const fe z);
int fe_isnonzero(const fe f);
int fe_isnegative(const fe f);
void fe_neg(fe h, const fe f);
void fe_sq2(fe h, const fe f);
void fe_invert(fe out, const fe z);
void fe_cmov(fe f, const fe g, unsigned int b);
void fe_copy(fe h, const fe f);
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
void ge_p3_0(ge_p3 *h);
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p);
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p);

// constants

extern const fe d;
extern const fe sqrtm1;

// sc

void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); /* USED */
void sc_reduce(unsigned char *s);                                                                         /* USED */

// misc

int crypto_verify_32(const unsigned char *x, const unsigned char *y); /* USED only in verify */

#define ASSERT_DIGEST_SIZE(_DI_) cc_assert((_DI_)->output_size == 64)

#endif // _CORECRYPTO_CCED25519_PRIV_H_
