/* Copyright (c) (2014,2015,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.
 */

#ifndef _CORECRYPTO_CCEC25519_H_
#define _CORECRYPTO_CCEC25519_H_

#include <corecrypto/cc.h>
#include <corecrypto/ccrng.h>
#include <corecrypto/ccdigest.h>

typedef uint8_t ccec25519key[32];
typedef ccec25519key ccec25519secretkey;
typedef ccec25519key ccec25519pubkey;
typedef ccec25519key ccec25519base;

typedef uint8_t ccec25519signature[64];

/*!
    @function		cccurve25519
    @abstract		Perform Curve25519 Diffie-Hellman.
                    http://cr.yp.to/ecdh.html

    @param      out  Output shared secret or public key.
    @param      sk   Input secret key.
    @param      base Input basepoint (for computing a shared secret)
                     or NULL (for computing a public key).
 */

void cccurve25519(ccec25519key out, const ccec25519secretkey sk, const ccec25519base base);

/*!
    @function	cccurve25519_make_priv
    @abstract	Generates a random, montgomery curve 25519 private key.

    @param      rng  An initialized random number generator
    @param      sk	 Receives 32-byte secret key.
 */

CC_INLINE void cccurve25519_make_priv(struct ccrng_state *rng, ccec25519secretkey sk)
{
    ccrng_generate(rng, 32, sk);
    sk[0] &= 248;
    sk[31] &= 127;
    sk[31] |= 64;
}

/*!
    @function	cccurve25519_make_pub
    @abstract	Creates a montgomery curve 25519 public key from a private key.

    @param      pk	Receives 32-byte public key.
    @param      sk	Receives 32-byte secret key.
 */

CC_INLINE void cccurve25519_make_pub(ccec25519pubkey pk, const ccec25519secretkey sk)
{
    cccurve25519(pk, sk, NULL);
}

/*!
    @function	cccurve25519_make_key_pair
    @abstract	Generates a random, montgomery curve 25519 key pair.

    @param      rng  An initialized random number generator
    @param      pk	Receives 32-byte public key.
    @param      sk	Receives 32-byte secret key.
 */

CC_INLINE void cccurve25519_make_key_pair(struct ccrng_state *rng, ccec25519pubkey pk, ccec25519secretkey sk)
{
    cccurve25519_make_priv(rng, sk);
    cccurve25519_make_pub(pk, sk);
}

/*!
    @function	cced25519_make_key_pair
    @abstract	Generates a random, Ed25519 key pair.

    @param      di   A valid descriptor for a 512 bit hash function for the platform
    @param      rng  An initialized random number generator
    @param      pk	Receives 32-byte public key.
    @param      sk	Receives 32-byte secret key.
 */
void cced25519_make_key_pair(const struct ccdigest_info *di, struct ccrng_state *rng, ccec25519pubkey pk, ccec25519secretkey sk);

/*!
    @function	cced25519_sign
    @abstract	Signs a message using a secret key.

    @param      di      A valid descriptor for a 512 bit hash function for the platform
    @param		sig		Receives the 64-byte signature.
    @param		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().
*/
void cced25519_sign(const struct ccdigest_info *di,
                    ccec25519signature sig,
                    size_t len,
                    const void *msg,
                    const ccec25519pubkey pk,
                    const ccec25519secretkey sk);

/*!
    @function	cced25519_verify
    @abstract	Verifies a signed message using a public key.

    @param      di      A valid descriptor for a 512 bit hash function for the platform
    @param		len		Number of bytes of data to verify.
    @param		msg		Data to verify.
    @param		sig		64-byte signature to verify data against.
    @param		pk		32-byte public key. Should have been generated by the peer using
                        cced25519_make_key_pair().

    @result		0=Signed message is valid. Non-zero=Bad message.
*/
int cced25519_verify(const struct ccdigest_info *di,
                     size_t len,
                     const void *msg,
                     const ccec25519signature sig,
                     const ccec25519pubkey pk);

#endif /* _CORECRYPTO_CCEC25519_H_ */
