/*
* RELIC is an Efficient LIbrary for Cryptography
* Copyright (c) 2009 RELIC Authors
*
* This file is part of RELIC. RELIC is legal property of its developers,
* whose names are not listed here. Please refer to the COPYRIGHT file
* for contact information.
*
* RELIC is free software; you can redistribute it and/or modify it under the
* terms of the version 2.1 (or later) of the GNU Lesser General Public License
* as published by the Free Software Foundation; or version 2.0 of the Apache
* License as published by the Apache Software Foundation. See the LICENSE files
* for more details.
*
* RELIC is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the LICENSE files for more details.
*
* You should have received a copy of the GNU Lesser General Public or the
* Apache License along with RELIC. If not, see
* or .
*/
/**
* @defgroup ep Elliptic curves over prime fields
*/
/**
* @file
*
* Interface of the module for arithmetic on prime elliptic curves.
*
* The scalar multiplication functions are only guaranteed to work
* in the large prime order subgroup. If you need a generic scalar
* multiplication function, use ep_mul_basic().
*
* @ingroup ep
*/
#ifndef RLC_EP_H
#define RLC_EP_H
#include "relic_fp.h"
#include "relic_bn.h"
#include "relic_types.h"
#include "relic_label.h"
/*============================================================================*/
/* Constant definitions */
/*============================================================================*/
/**
* Prime elliptic curve identifiers.
*/
enum {
/** SECG P-160 prime curve. */
SECG_P160 = 1,
/** SECG K-160 prime curve. */
SECG_K160,
/** NIST P-192 prime curve. */
NIST_P192,
/** SECG K-192 prime curve. */
SECG_K192,
/** Curve22103 prime curve. */
CURVE_22103,
/** NIST P-224 prime curve. */
NIST_P224,
/** SECG K-224 prime curve. */
SECG_K224,
/** Curve4417 prime curve. */
CURVE_4417,
/** Curve1147 prime curve. */
CURVE_1174,
/** Curve25519 prime curve. */
CURVE_25519,
/** Curve Tweedledum given by Daira Hopwoord at https://github.com/daira/tweedle */
TWEEDLEDUM,
/** NIST P-256 prime curve. */
NIST_P256,
/** Brainpool P256r1 curve. */
BSI_P256,
/** SECG K-256 prime curve. */
SECG_K256,
/** Curve67254 prime curve. */
CURVE_67254,
/** Curve383187 prime curve. */
CURVE_383187,
/** NIST P-384 prime curve. */
NIST_P384,
/** Curve 511187 prime curve. */
CURVE_511187,
/** NIST P-521 prime curve. */
NIST_P521,
/** Barreto-Naehrig curve with positive x */
BN_P158,
/** Barreto-Naehrig curve with negative x (found by Nogami et al.). */
BN_P254,
/** Barreto-Naehrig curve with negative x. */
BN_P256,
/** Barreto-Lynn-Scott curve with embedding degree 12 (ZCash curve). */
B12_P381,
/** Barreto-Naehrig curve with negative x. */
BN_P382,
/** Barreto-Naehrig curve with embedding degree 12. */
BN_P446,
/** Barreto-Lynn-Scott curve with embedding degree 12. */
B12_P446,
/** Barreto-Lynn-Scott curve with embedding degree 12. */
B12_P455,
/** Barreto-Lynn-Scott curve with embedding degree 24. */
B24_P477,
/** Kachisa-Schafer-Scott with negative x. */
KSS_P508,
/** Optimal TNFS-secure curve with embedding degree 8. */
OT8_P511,
/** Cocks-pinch curve with embedding degree 8. */
CP8_P544,
/** Kachisa-Scott-Schaefer curve with embedding degree 54. */
K54_P569,
/** Barreto-Lynn-Scott curve with embedding degree 48. */
B48_P575,
/** Barreto-Naehrig curve with positive x. */
BN_P638,
/** Barreto-Lynn-Scott curve with embedding degree 12. */
B12_P638,
/** 1536-bit supersingular curve. */
SS_P1536,
/** 3072-bit supersingular curve. */
SS_P3072,
};
/**
* Pairing-friendly elliptic curve identifiers.
*/
enum {
/** Supersingular curves with embedding degree 1. */
EP_SS1 = 1,
/** Supersingular curves with embedding degree 2. */
EP_SS2,
/** Barreto-Naehrig. */
EP_BN,
/* Optimal TNFS-secure. */
EP_OT8,
/* Cocks-Pinch curve. */
EP_CP8,
/* Barreto-Lynn-Scott with embedding degree 12. */
EP_B12,
/* Kachisa-Schafer-Scott with embedding degree 16. */
EP_K16,
/* Barreto-Lynn-Scott with embedding degree 24. */
EP_B24,
/* Barreto-Lynn-Scott with embedding degree 48. */
EP_B48,
/** Kachisa-Scott-Schaefer curve with embedding degree 54. */
EP_K54,
};
/*============================================================================*/
/* Constant definitions */
/*============================================================================*/
/**
* Denotes a divisive twist.
*/
#define RLC_EP_DTYPE 1
/**
* Denotes a multiplicative twist.
*/
#define RLC_EP_MTYPE 2
/**
* Size of a precomputation table using the binary method.
*/
#define RLC_EP_TABLE_BASIC (RLC_FP_BITS + 1)
/**
* Size of a precomputation table using the single-table comb method.
*/
#define RLC_EP_TABLE_COMBS (1 << EP_DEPTH)
/**
* Size of a precomputation table using the double-table comb method.
*/
#define RLC_EP_TABLE_COMBD (1 << (EP_DEPTH + 1))
/**
* Size of a precomputation table using the w-(T)NAF method.
*/
#define RLC_EP_TABLE_LWNAF (1 << (EP_DEPTH - 2))
/**
* Size of a precomputation table using the chosen algorithm.
*/
#if EP_FIX == BASIC
#define RLC_EP_TABLE RLC_EP_TABLE_BASIC
#elif EP_FIX == COMBS
#define RLC_EP_TABLE RLC_EP_TABLE_COMBS
#elif EP_FIX == COMBD
#define RLC_EP_TABLE RLC_EP_TABLE_COMBD
#elif EP_FIX == LWNAF
#define RLC_EP_TABLE RLC_EP_TABLE_LWNAF
#endif
/**
* Maximum size of a precomputation table.
*/
#ifdef STRIP
#define RLC_EP_TABLE_MAX RLC_EP_TABLE
#else
#define RLC_EP_TABLE_MAX RLC_MAX(RLC_EP_TABLE_BASIC, RLC_EP_TABLE_COMBD)
#endif
/**
* Maximum number of coefficients of an isogeny map polynomial.
* RLC_TERMS of value 16 is sufficient for a degree-11 isogeny polynomial.
*/
#define RLC_EP_CTMAP_MAX 16
/*============================================================================*/
/* Type definitions */
/*============================================================================*/
/**
* Represents an elliptic curve point over a prime field.
*/
typedef struct {
/** The first coordinate. */
fp_st x;
/** The second coordinate. */
fp_st y;
/** The third coordinate (projective representation). */
fp_st z;
/** Flag to indicate the coordinate system of this point. */
int coord;
} ep_st;
/**
* Pointer to an elliptic curve point.
*/
#if ALLOC == AUTO
typedef ep_st ep_t[1];
#else
typedef ep_st *ep_t;
#endif
/**
* Data structure representing an isogeny map.
*/
typedef struct {
/** The a-coefficient of the isogenous curve used for SSWU mapping. */
fp_st a;
/** The b-coefficient of the isogenous curve used for SSWU mapping. */
fp_st b;
/** Degree of x numerator */
int deg_xn;
/** Degree of x denominator */
int deg_xd;
/** Degree of y numerator */
int deg_yn;
/** Degree of y denominator */
int deg_yd;
/** x numerator coefficients */
fp_st xn[RLC_EP_CTMAP_MAX];
/** x denominator coefficients */
fp_st xd[RLC_EP_CTMAP_MAX];
/** y numerator coefficients */
fp_st yn[RLC_EP_CTMAP_MAX];
/** y denominator coefficients */
fp_st yd[RLC_EP_CTMAP_MAX];
} iso_st;
/**
* Pointer to isogeny map coefficients.
*/
typedef iso_st *iso_t;
/*============================================================================*/
/* Macro definitions */
/*============================================================================*/
/**
* Initializes a point on a prime elliptic curve with a null value.
*
* @param[out] A - the point to initialize.
*/
#if ALLOC == AUTO
#define ep_null(A) /* empty */
#else
#define ep_null(A) A = NULL;
#endif
/**
* Calls a function to allocate a point on a prime elliptic curve.
*
* @param[out] A - the new point.
* @throw ERR_NO_MEMORY - if there is no available memory.
*/
#if ALLOC == DYNAMIC
#define ep_new(A) \
A = (ep_t)calloc(1, sizeof(ep_st)); \
if (A == NULL) { \
RLC_THROW(ERR_NO_MEMORY); \
} \
#elif ALLOC == AUTO
#define ep_new(A) /* empty */
#endif
/**
* Calls a function to clean and free a point on a prime elliptic curve.
*
* @param[out] A - the point to free.
*/
#if ALLOC == DYNAMIC
#define ep_free(A) \
if (A != NULL) { \
free(A); \
A = NULL; \
}
#elif ALLOC == AUTO
#define ep_free(A) /* empty */
#endif
/**
* Adds two prime elliptic curve points. Computes R = P + Q.
*
* @param[out] R - the result.
* @param[in] P - the first point to add.
* @param[in] Q - the second point to add.
*/
#if EP_ADD == BASIC
#define ep_add(R, P, Q) ep_add_basic(R, P, Q)
#elif EP_ADD == PROJC
#define ep_add(R, P, Q) ep_add_projc(R, P, Q)
#elif EP_ADD == JACOB
#define ep_add(R, P, Q) ep_add_jacob(R, P, Q)
#endif
/**
* Doubles a prime elliptic curve point. Computes R = 2P.
*
* @param[out] R - the result.
* @param[in] P - the point to double.
*/
#if EP_ADD == BASIC
#define ep_dbl(R, P) ep_dbl_basic(R, P)
#elif EP_ADD == PROJC
#define ep_dbl(R, P) ep_dbl_projc(R, P)
#elif EP_ADD == JACOB
#define ep_dbl(R, P) ep_dbl_jacob(R, P)
#endif
/**
* Multiplies a prime elliptic curve point by an integer. Computes R = [k]P.
*
* @param[out] R - the result.
* @param[in] P - the point to multiply.
* @param[in] K - the integer.
*/
#if EP_MUL == BASIC
#define ep_mul(R, P, K) ep_mul_basic(R, P, K)
#elif EP_MUL == SLIDE
#define ep_mul(R, P, K) ep_mul_slide(R, P, K)
#elif EP_MUL == MONTY
#define ep_mul(R, P, K) ep_mul_monty(R, P, K)
#elif EP_MUL == LWNAF
#define ep_mul(R, P, K) ep_mul_lwnaf(R, P, K)
#elif EP_MUL == LWREG
#define ep_mul(R, P, K) ep_mul_lwreg(R, P, K)
#endif
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point.
*
* @param[out] T - the precomputation table.
* @param[in] P - the point to multiply.
*/
#if EP_FIX == BASIC
#define ep_mul_pre(T, P) ep_mul_pre_basic(T, P)
#elif EP_FIX == COMBS
#define ep_mul_pre(T, P) ep_mul_pre_combs(T, P)
#elif EP_FIX == COMBD
#define ep_mul_pre(T, P) ep_mul_pre_combd(T, P)
#elif EP_FIX == LWNAF
#define ep_mul_pre(T, P) ep_mul_pre_lwnaf(T, P)
#endif
/**
* Multiplies a fixed prime elliptic point using a precomputation table.
* Computes R = [k]P.
*
* @param[out] R - the result.
* @param[in] T - the precomputation table.
* @param[in] K - the integer.
*/
#if EP_FIX == BASIC
#define ep_mul_fix(R, T, K) ep_mul_fix_basic(R, T, K)
#elif EP_FIX == COMBS
#define ep_mul_fix(R, T, K) ep_mul_fix_combs(R, T, K)
#elif EP_FIX == COMBD
#define ep_mul_fix(R, T, K) ep_mul_fix_combd(R, T, K)
#elif EP_FIX == LWNAF
#define ep_mul_fix(R, T, K) ep_mul_fix_lwnaf(R, T, K)
#endif
/**
* Multiplies and adds two prime elliptic curve points simultaneously.
* Computes R = [k]P + [m]Q.
*
* @param[out] R - the result.
* @param[in] P - the first point to multiply.
* @param[in] K - the first integer.
* @param[in] Q - the second point to multiply.
* @param[in] M - the second integer,
*/
#if EP_SIM == BASIC
#define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_basic(R, P, K, Q, M)
#elif EP_SIM == TRICK
#define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_trick(R, P, K, Q, M)
#elif EP_SIM == INTER
#define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_inter(R, P, K, Q, M)
#elif EP_SIM == JOINT
#define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_joint(R, P, K, Q, M)
#endif
/*============================================================================*/
/* Function prototypes */
/*============================================================================*/
/**
* Initializes the prime elliptic curve arithmetic module.
*/
void ep_curve_init(void);
/**
* Finalizes the prime elliptic curve arithmetic module.
*/
void ep_curve_clean(void);
/**
* Returns the a-coefficient of the currently configured prime elliptic curve.
*
* @return the a-coefficient of the elliptic curve.
*/
dig_t *ep_curve_get_a(void);
/**
* Returns the b-coefficient of the currently configured prime elliptic curve.
*
* @return the b-coefficient of the elliptic curve.
*/
dig_t *ep_curve_get_b(void);
/**
* Returns the b3 = 3*b value used in elliptic curve arithmetic.
*
* @return the value b3 used in elliptic curve arithmetic.
*/
dig_t *ep_curve_get_b3(void);
/**
* Returns the efficient endormorphism associated with the prime curve.
*/
dig_t *ep_curve_get_beta(void);
/**
* Returns the parameter V1 of the prime curve.
*/
void ep_curve_get_v1(bn_t v[]);
/**
* Returns the parameter V2 of the prime curve.
*/
void ep_curve_get_v2(bn_t v[]);
/**
* Returns a optimization identifier based on the a-coefficient of the curve.
*
* @return the optimization identifier.
*/
int ep_curve_opt_a(void);
/**
* Returns a optimization identifier based on the b-coefficient of the curve.
*
* @return the optimization identifier.
*/
int ep_curve_opt_b(void);
/**
* Returns a optimization identifier based on the b-coefficient of the curve.
*
* @return the optimization identifier.
*/
int ep_curve_opt_b3(void);
/**
* Multiplies a field element by the a-coefficient of the curve.
*
* @param[out] c - the result.
* @param[in] a - the field element to multiply.
*/
void ep_curve_mul_a(fp_t c, const fp_t a);
/**
* Multiplies a field element by the b-coefficient of the curve.
*
* @param[out] c - the result.
* @param[in] a - the field element to multiply.
*/
void ep_curve_mul_b(fp_t c, const fp_t a);
/**
* Multiplies a field element by the b3 value of the curve.
*
* @param[out] c - the result.
* @param[in] a - the field element to multiply.
*/
void ep_curve_mul_b3(fp_t c, const fp_t a);
/**
* Tests if the configured prime elliptic curve is a Koblitz curve.
*
* @return 1 if the prime elliptic curve is a Koblitz curve, 0 otherwise.
*/
int ep_curve_is_endom(void);
/**
* Tests if the configured prime elliptic curve is supersingular.
*
* @return 1 if the prime elliptic curve is supersingular, 0 otherwise.
*/
int ep_curve_is_super(void);
/**
* Tests if the configured prime elliptic curve is pairing-friendly.
*
* @return 0 if the prime elliptic curve is not pairing-friendly, and the
* family identifier otherwise.
*/
int ep_curve_is_pairf(void);
/**
* Tests if the current curve should use an isogeny map for the SSWU map.
*
* @return 1 if the curve uses an isogeny, and 0 otherwise.
*/
int ep_curve_is_ctmap(void);
/**
* Returns the generator of the group of points in the prime elliptic curve.
*
* @param[out] g - the returned generator.
*/
void ep_curve_get_gen(ep_t g);
/**
* Returns the precomputation table for the generator.
*
* @return the table.
*/
const ep_t *ep_curve_get_tab(void);
/**
* Returns the order of the group of points in the prime elliptic curve.
*
* @param[out] r - the returned order.
*/
void ep_curve_get_ord(bn_t n);
/**
* Returns the cofactor of the binary elliptic curve.
*
* @param[out] n - the returned cofactor.
*/
void ep_curve_get_cof(bn_t h);
/**
* Returns the isogeny map coefficients for use with the SSWU map.
*/
iso_t ep_curve_get_iso(void);
/**
* Configures a prime elliptic curve without endomorphisms by its coefficients
* and generator.
*
* @param[in] a - the a-coefficient of the curve.
* @param[in] b - the b-coefficient of the curve.
* @param[in] g - the generator.
* @param[in] r - the order of the group of points.
* @param[in] h - the cofactor of the group order.
* @param[in] u - the non-square used for hashing to this curve.
* @param[in] ctmap - true if this curve will use an isogeny for mapping.
*/
void ep_curve_set_plain(const fp_t a, const fp_t b, const ep_t g, const bn_t r,
const bn_t h, const fp_t u, int ctmap);
/**
* Configures a supersingular prime elliptic curve by its coefficients and
* generator.
*
* @param[in] a - the a-coefficient of the curve.
* @param[in] b - the b-coefficient of the curve.
* @param[in] g - the generator.
* @param[in] r - the order of the group of points.
* @param[in] h - the cofactor of the group order.
* @param[in] u - the non-square used for hashing to this curve.
* @param[in] ctmap - true if this curve will use an isogeny for mapping.
*/
void ep_curve_set_super(const fp_t a, const fp_t b, const ep_t g, const bn_t r,
const bn_t h, const fp_t u, int ctmap);
/**
* Configures a prime elliptic curve with endomorphisms by its coefficients and
* generator.
*
* @param[in] a - the a-coefficient of the curve.
* @param[in] b - the b-coefficient of the curve.
* @param[in] g - the generator.
* @param[in] r - the order of the group of points.
* @param[in] beta - the constant associated with the endomorphism.
* @param[in] l - the exponent corresponding to the endomorphism.
* @param[in] h - the cofactor of the group order.
* @param[in] u - the non-square used for hashing to this curve.
* @param[in] ctmap - true if this curve will use an isogeny for mapping.
*/
void ep_curve_set_endom(const fp_t a, const fp_t b, const ep_t g, const bn_t r,
const bn_t h, const fp_t beta, const bn_t l, const fp_t u, int ctmap);
/**
* Configures a prime elliptic curve by its parameter identifier.
*
* @param - the parameter identifier.
*/
void ep_param_set(int param);
/**
* Configures some set of curve parameters for the current security level.
*/
int ep_param_set_any(void);
/**
* Configures some set of ordinary curve parameters for the current security
* level.
*
* @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise.
*/
int ep_param_set_any_plain(void);
/**
* Configures some set of Koblitz curve parameters for the current security
* level.
*
* @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise.
*/
int ep_param_set_any_endom(void);
/**
* Configures some set of supersingular curve parameters for the current
* security level.
*
* @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise.
*/
int ep_param_set_any_super(void);
/**
* Configures some set of pairing-friendly curve parameters for the current
* security level.
*
* @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise.
*/
int ep_param_set_any_pairf(void);
/**
* Returns the parameter identifier of the currently configured prime elliptic
* curve.
*
* @return the parameter identifier.
*/
int ep_param_get(void);
/**
* Prints the current configured prime elliptic curve.
*/
void ep_param_print(void);
/**
* Returns the current security level.
*/
int ep_param_level(void);
/**
* Returns the embedding degree of the currently configured elliptic curve.
*/
int ep_param_embed(void);
/**
* Tests if a point on a prime elliptic curve is at the infinity.
*
* @param[in] p - the point to test.
* @return 1 if the point is at infinity, 0 otherise.
*/
int ep_is_infty(const ep_t p);
/**
* Assigns a prime elliptic curve point to the point at infinity.
*
* @param[out] p - the point to assign.
*/
void ep_set_infty(ep_t p);
/**
* Copies the second argument to the first argument.
*
* @param[out] q - the result.
* @param[in] p - the prime elliptic curve point to copy.
*/
void ep_copy(ep_t r, const ep_t p);
/**
* Compares two prime elliptic curve points.
*
* @param[in] p - the first prime elliptic curve point.
* @param[in] q - the second prime elliptic curve point.
* @return RLC_EQ if p == q and RLC_NE if p != q.
*/
int ep_cmp(const ep_t p, const ep_t q);
/**
* Assigns a random value to a prime elliptic curve point.
*
* @param[out] p - the prime elliptic curve point to assign.
*/
void ep_rand(ep_t p);
/**
* Randomizes coordinates of a prime elliptic curve point.
*
* @param[out] r - the blinded prime elliptic curve point.
* @param[in] p - the prime elliptic curve point to blind.
*/
void ep_blind(ep_t r, const ep_t p);
/**
* Computes the right-hand side of the elliptic curve equation at a certain
* prime elliptic curve point.
*
* @param[out] rhs - the result.
* @param[in] p - the point.
*/
void ep_rhs(fp_t rhs, const ep_t p);
/**
* Tests if a point is in the curve.
*
* @param[in] p - the point to test.
*/
int ep_on_curve(const ep_t p);
/**
* Builds a precomputation table for multiplying a random prime elliptic point.
*
* @param[out] t - the precomputation table.
* @param[in] p - the point to multiply.
* @param[in] w - the window width.
*/
void ep_tab(ep_t *t, const ep_t p, int w);
/**
* Prints a prime elliptic curve point.
*
* @param[in] p - the prime elliptic curve point to print.
*/
void ep_print(const ep_t p);
/**
* Returns the number of bytes necessary to store a prime elliptic curve point
* with optional point compression.
*
* @param[in] a - the prime field element.
* @param[in] pack - the flag to indicate compression.
* @return the number of bytes.
*/
int ep_size_bin(const ep_t a, int pack);
/**
* Reads a prime elliptic curve point from a byte vector in big-endian format.
*
* @param[out] a - the result.
* @param[in] bin - the byte vector.
* @param[in] len - the buffer capacity.
* @throw ERR_NO_VALID - if the encoded point is invalid.
* @throw ERR_NO_BUFFER - if the buffer capacity is invalid.
*/
void ep_read_bin(ep_t a, const uint8_t *bin, int len);
/**
* Writes a prime elliptic curve point to a byte vector in big-endian format
* with optional point compression.
*
* @param[out] bin - the byte vector.
* @param[in] len - the buffer capacity.
* @param[in] a - the prime elliptic curve point to write.
* @param[in] pack - the flag to indicate point compression.
* @throw ERR_NO_BUFFER - if the buffer capacity is invalid.
*/
void ep_write_bin(uint8_t *bin, int len, const ep_t a, int pack);
/**
* Negates a prime elliptic curve point.
*
* @param[out] r - the result.
* @param[in] p - the point to negate.
*/
void ep_neg(ep_t r, const ep_t p);
/**
* Adds two prime elliptic curve points represented in affine coordinates.
*
* @param[out] r - the result.
* @param[in] p - the first point to add.
* @param[in] q - the second point to add.
*/
void ep_add_basic(ep_t r, const ep_t p, const ep_t q);
/**
* Adds two prime elliptic curve points represented in affine coordinates and
* returns the computed slope.
*
* @param[out] r - the result.
* @param[out] s - the slope.
* @param[in] p - the first point to add.
* @param[in] q - the second point to add.
*/
void ep_add_slp_basic(ep_t r, fp_t s, const ep_t p, const ep_t q);
/**
* Adds two prime elliptic curve points represented in projective coordinates.
*
* @param[out] r - the result.
* @param[in] p - the first point to add.
* @param[in] q - the second point to add.
*/
void ep_add_projc(ep_t r, const ep_t p, const ep_t q);
/**
* Adds two prime elliptic curve points represented in Jacobian coordinates.
*
* @param[out] r - the result.
* @param[in] p - the first point to add.
* @param[in] q - the second point to add.
*/
void ep_add_jacob(ep_t r, const ep_t p, const ep_t q);
/**
* Subtracts a prime elliptic curve point from another.
*
* @param[out] r - the result.
* @param[in] p - the first point.
* @param[in] q - the second point.
*/
void ep_sub(ep_t r, const ep_t p, const ep_t q);
/**
* Doubles a prime elliptic curve point represented in affine coordinates.
*
* @param[out] r - the result.
* @param[in] p - the point to double.
*/
void ep_dbl_basic(ep_t r, const ep_t p);
/**
* Doubles a prime elliptic curve point represented in affine coordinates and
* returns the computed slope.
*
* @param[out] r - the result.
* @param[out] s - the slope.
* @param[in] p - the point to double.
*/
void ep_dbl_slp_basic(ep_t r, fp_t s, const ep_t p);
/**
* Doubles a prime elliptic curve point represented in projective coordinates.
*
* @param[out] r - the result.
* @param[in] p - the point to double.
*/
void ep_dbl_projc(ep_t r, const ep_t p);
/**
* Doubles a prime elliptic curve point represented in Jacobian projective
* coordinates.
*
* @param[out] r - the result.
* @param[in] p - the point to double.
*/
void ep_dbl_jacob(ep_t r, const ep_t p);
/**
* Computes the endomorphism map of a prime elliptic curve point.
* Computes R = \psi(P).
*
* @param[out] r - the result.
* @param[in] p - the point.
*/
void ep_psi(ep_t r, const ep_t p);
/**
* Multiplies a prime elliptic point by an integer using the binary method.
* There is no restriction on the scalar.
*
* @param[out] r - the result.
* @param[in] p - the point to multiply.
* @param[in] k - the integer.
*/
void ep_mul_basic(ep_t r, const ep_t p, const bn_t k);
/**
* Multiplies a prime elliptic point by an integer using the sliding window
* method.
*
* @param[out] r - the result.
* @param[in] p - the point to multiply.
* @param[in] k - the integer.
*/
void ep_mul_slide(ep_t r, const ep_t p, const bn_t k);
/**
* Multiplies a prime elliptic point by an integer using the constant-time
* Montgomery ladder point multiplication method.
*
* @param[out] r - the result.
* @param[in] p - the point to multiply.
* @param[in] k - the integer.
*/
void ep_mul_monty(ep_t r, const ep_t p, const bn_t k);
/**
* Multiplies a prime elliptic point by an integer using the w-NAF method.
*
* @param[out] r - the result.
* @param[in] p - the point to multiply.
* @param[in] k - the integer.
*/
void ep_mul_lwnaf(ep_t r, const ep_t p, const bn_t k);
/**
* Multiplies a prime elliptic point by an integer using a regular method.
*
* @param[out] r - the result.
* @param[in] p - the point to multiply.
* @param[in] k - the integer.
*/
void ep_mul_lwreg(ep_t r, const ep_t p, const bn_t k);
/**
* Multiplies the generator of a prime elliptic curve by an integer.
*
* @param[out] r - the result.
* @param[in] k - the integer.
*/
void ep_mul_gen(ep_t r, const bn_t k);
/**
* Multiplies a prime elliptic point by a small positive integer.
*
* @param[out] r - the result.
* @param[in] p - the point to multiply.
* @param[in] k - the integer.
*/
void ep_mul_dig(ep_t r, const ep_t p, dig_t k);
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point
* using the binary method.
*
* @param[out] t - the precomputation table.
* @param[in] p - the point to multiply.
*/
void ep_mul_pre_basic(ep_t *t, const ep_t p);
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point
* using Yao's windowing method.
*
* @param[out] t - the precomputation table.
* @param[in] p - the point to multiply.
*/
void ep_mul_pre_yaowi(ep_t *t, const ep_t p);
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point
* using the NAF windowing method.
*
* @param[out] t - the precomputation table.
* @param[in] p - the point to multiply.
*/
void ep_mul_pre_nafwi(ep_t *t, const ep_t p);
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point
* using the single-table comb method.
*
* @param[out] t - the precomputation table.
* @param[in] p - the point to multiply.
*/
void ep_mul_pre_combs(ep_t *t, const ep_t p);
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point
* using the double-table comb method.
*
* @param[out] t - the precomputation table.
* @param[in] p - the point to multiply.
*/
void ep_mul_pre_combd(ep_t *t, const ep_t p);
/**
* Builds a precomputation table for multiplying a fixed prime elliptic point
* using the w-(T)NAF method.
*
* @param[out] t - the precomputation table.
* @param[in] p - the point to multiply.
*/
void ep_mul_pre_lwnaf(ep_t *t, const ep_t p);
/**
* Multiplies a fixed prime elliptic point using a precomputation table and
* the binary method.
*
* @param[out] r - the result.
* @param[in] t - the precomputation table.
* @param[in] k - the integer.
*/
void ep_mul_fix_basic(ep_t r, const ep_t *t, const bn_t k);
/**
* Multiplies a fixed prime elliptic point using a precomputation table and
* Yao's windowing method
*
* @param[out] r - the result.
* @param[in] t - the precomputation table.
* @param[in] k - the integer.
*/
void ep_mul_fix_yaowi(ep_t r, const ep_t *t, const bn_t k);
/**
* Multiplies a fixed prime elliptic point using a precomputation table and
* the w-(T)NAF method.
*
* @param[out] r - the result.
* @param[in] t - the precomputation table.
* @param[in] k - the integer.
*/
void ep_mul_fix_nafwi(ep_t r, const ep_t *t, const bn_t k);
/**
* Multiplies a fixed prime elliptic point using a precomputation table and
* the single-table comb method.
*
* @param[out] r - the result.
* @param[in] t - the precomputation table.
* @param[in] k - the integer.
*/
void ep_mul_fix_combs(ep_t r, const ep_t *t, const bn_t k);
/**
* Multiplies a fixed prime elliptic point using a precomputation table and
* the double-table comb method.
*
* @param[out] r - the result.
* @param[in] t - the precomputation table.
* @param[in] k - the integer.
*/
void ep_mul_fix_combd(ep_t r, const ep_t *t, const bn_t k);
/**
* Multiplies a fixed prime elliptic point using a precomputation table and
* the w-(T)NAF method.
*
* @param[out] r - the result.
* @param[in] t - the precomputation table.
* @param[in] k - the integer.
*/
void ep_mul_fix_lwnaf(ep_t r, const ep_t *t, const bn_t k);
/**
* Multiplies and adds two prime elliptic curve points simultaneously using
* scalar multiplication and point addition.
*
* @param[out] r - the result.
* @param[in] p - the first point to multiply.
* @param[in] k - the first integer.
* @param[in] q - the second point to multiply.
* @param[in] m - the second integer,
*/
void ep_mul_sim_basic(ep_t r, const ep_t p, const bn_t k, const ep_t q,
const bn_t m);
/**
* Multiplies and adds two prime elliptic curve points simultaneously using
* shamir's trick.
*
* @param[out] r - the result.
* @param[in] p - the first point to multiply.
* @param[in] k - the first integer.
* @param[in] q - the second point to multiply.
* @param[in] m - the second integer,
*/
void ep_mul_sim_trick(ep_t r, const ep_t p, const bn_t k, const ep_t q,
const bn_t m);
/**
* Multiplies and adds two prime elliptic curve points simultaneously using
* interleaving of NAFs.
*
* @param[out] r - the result.
* @param[in] p - the first point to multiply.
* @param[in] k - the first integer.
* @param[in] q - the second point to multiply.
* @param[in] m - the second integer,
*/
void ep_mul_sim_inter(ep_t r, const ep_t p, const bn_t k, const ep_t q,
const bn_t m);
/**
* Multiplies and adds two prime elliptic curve points simultaneously using
* Solinas' Joint Sparse Form.
*
* @param[out] r - the result.
* @param[in] p - the first point to multiply.
* @param[in] k - the first integer.
* @param[in] q - the second point to multiply.
* @param[in] m - the second integer,
*/
void ep_mul_sim_joint(ep_t r, const ep_t p, const bn_t k, const ep_t q,
const bn_t m);
/**
* Multiplies simultaneously elements from G_2. Computes R = \Sum_i=0..n k_iP_i.
*
* @param[out] r - the result.
* @param[out] p - the G_2 elements to multiply.
* @param[out] k - the integer scalars.
* @param[out] n - the number of elements to multiply.
*/
void ep_mul_sim_lot(ep_t r, ep_t p[], const bn_t k[], int n);
/**
* Multiplies and adds the generator and a prime elliptic curve point
* simultaneously. Computes R = [k]G + [m]Q.
*
* @param[out] r - the result.
* @param[in] k - the first integer.
* @param[in] q - the second point to multiply.
* @param[in] m - the second integer.
*/
void ep_mul_sim_gen(ep_t r, const bn_t k, const ep_t q, const bn_t m);
/**
* Multiplies prime elliptic curve points by small scalars.
* Computes R = \sum k_iP_i.
*
* @param[out] r - the result.
* @param[in] p - the points to multiply.
* @param[in] k - the small scalars.
* @param[in] len - the number of points to multiply.
*/
void ep_mul_sim_dig(ep_t r, const ep_t p[], const dig_t k[], int len);
/**
* Converts a point to affine coordinates.
*
* @param[out] r - the result.
* @param[in] p - the point to convert.
*/
void ep_norm(ep_t r, const ep_t p);
/**
* Converts multiple points to affine coordinates.
*
* @param[out] r - the result.
* @param[in] t - the points to convert.
* @param[in] n - the number of points.
*/
void ep_norm_sim(ep_t *r, const ep_t *t, int n);
/**
* Maps a byte array to a point in a prime elliptic curve.
*
* @param[out] p - the result.
* @param[in] msg - the byte array to map.
* @param[in] len - the array length in bytes.
*/
void ep_map(ep_t p, const uint8_t *msg, int len);
/**
* Maps a byte array to a point in a prime elliptic curve using
* an explicit domain separation tag.
*
* @param[out] p - the result.
* @param[in] msg - the byte array to map.
* @param[in] len - the array length in bytes.
* @param[in] dst - the domain separation tag.
* @param[in] dst_len - the domain separation tag length in bytes.
*/
void ep_map_dst(ep_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst_len);
/**
* Maps a byte array to a point in a prime elliptic curve with specified
* domain separation tag (aka personalization string).
*
* @param[out] p - the result.
* @param[in] msg - the byte array to map.
* @param[in] len - the array length in bytes.
* @param[in] dst - the domain separation tag.
* @param[in] dst_len - the domain separation tag length in bytes.
*/
void ep_map_dst(ep_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst_len);
/**
* Compresses a point.
*
* @param[out] r - the result.
* @param[in] p - the point to compress.
*/
void ep_pck(ep_t r, const ep_t p);
/**
* Decompresses a point.
*
* @param[out] r - the result.
* @param[in] p - the point to decompress.
* @return a boolean value indicating if the decompression was successful.
*/
int ep_upk(ep_t r, const ep_t p);
#endif /* !RLC_EP_H */