"sxops" interface for Weierstrass elliptic curve computations.
Simpler functions to perform public key crypto operations. Included directly in some interfaces (like sxbuf or OpenSSL engine). The functions take input operands (large integers) and output operands which will get the computed results.
Operands have the "sx_op" type. The specific interfaces (like sxbuf) define the "sx_op" type.
@file
ECCWEIERSTRASS_HEADER_FILE Macro
C
#define ECCWEIERSTRASS_HEADER_FILE
/ Copyright (c) 2018-2020 Silex Insight sa Copyright (c) 2018-2020 Beerten Engineering scs SPDX-License-Identifier: BSD-3-Clause
Make sure the application is compatible with SilexPK API version **/
SX_PK_API_ASSERT_COMPATIBLE(1, 3);
struct sx_pk_ecurve;
inline
Function
C
static inline
@addtogroup SX_PK_SXOPS_ECC
@{
Curve generator point for sx_ecp_ptmult() or sx_async_ecp_mult_go() */
SX_PTMULT_CURVE_GENERATOR Macro
C
#define SX_PTMULT_CURVE_GENERATOR NULL
inline
Function
C
static inline
@addtogroup SX_PK_SXOPS_ECDSA
@{
Asynchronous ECDSA signature generation
Start an ECDSA signature generation on the accelerator and return immediately.
@remark When the operation finishes on the accelerator, call sx_async_ecdsa_generate_end()
Parameters
curve Elliptic curve on which to perform ECDSA signature
Parameters
d Private key
Parameters
k Random value
Parameters
h Formatted hash digest of message to be signed. Truncation or padding should be done by user application @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_ecdsa_generate_go( const struct sx_pk_ecurve curve, const sx_op d, const sx_op k, const sx_op h) { struct sx_pk_dreq pkreq; struct sx_pk_inops_ecdsa_generate inputs; pkreq = SX_PK_ACQUIRE_REQ(curve->cnx, SX_PK_CMD_ECDSA_GEN); if (pkreq.status) return pkreq; // convert and transfer operands pkreq.status = SX_PK_LIST_ECC_INSLOTS(pkreq.req, curve, 0, (struct sx_pk_slot)&inputs); if (pkreq.status) return pkreq; int opsz = SX_PK_GET_OPSIZE(pkreq.req); SX_PK_OP2MEM(d, inputs.d.addr, opsz); SX_PK_OP2MEM(k, inputs.k.addr, opsz); SX_PK_OP2MEM(h, inputs.h.addr, opsz); SX_PK_RUN(pkreq.req); return pkreq; }
Finish asynchronous (non-blocking) ECDSA generation.
Get the output operands of the ECDSA signature generation and release the reserved resources. @pre The operation on the accelerator must be finished before calling this function.
Parameters
req The previously acquired acceleration request for this operation
Parameters
r First part of signature
Parameters
s Second part of signature static inline void sx_async_ecdsa_generate_end(sx_pk_accel req, sx_op r, sx_op s) { sx_async_finish_pair(req, r, s); }
Generate an ECDSA signature on an elliptic curve
The signature generation has the following steps : 1. P(x1, y1) = k G 2. r = x1 mod n 3. if r == 0 then report failure 4. w = k -1 mod n 5. s = k -1 (h + d r) mod n 6. if s == 0 then report failure 7. signature is the r and s
Parameters
curve Elliptic curve on which to perform ECDSA signature
Parameters
d Private key
Parameters
k Random value
Parameters
h Digest of message to be signed Truncation or padding should be done by user application
Parameters
r First part of signature
Parameters
s Second part of signature @return ::SX_OK @return ::SX_ERR_INVALID_PARAM @return ::SX_ERR_NOT_INVERTIBLE @return ::SX_ERR_INVALID_SIGNATURE @return ::SX_ERR_OUT_OF_RANGE @return ::SX_ERR_UNKNOWN_ERROR @return ::SX_ERR_BUSY @return ::SX_ERR_NOT_IMPLEMENTED @return ::SX_ERR_OPERAND_TOO_LARGE @return ::SX_ERR_PLATFORM_ERROR @return ::SX_ERR_EXPIRED @see sx_async_ecdsa_generate_go(), sx_async_ecdsa_generate_end() for an asynchronous version static inline int sx_ecdsa_generate( const struct sx_pk_ecurve curve, const sx_op d, const sx_op k, const sx_op h, sx_op r, sx_op s) { uint32_t status; struct sx_pk_dreq pkreq; pkreq = sx_async_ecdsa_generate_go(curve, d, k, h); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_ecdsa_generate_end(pkreq.req, r, s); return status; }
Asynchronous (non-blocking) ECDSA verification.
Start an ECDSA signature verification on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call SX_PK_RELEASE_REQ()
Parameters
curve Elliptic curve on which to perform ECDSA verification
Parameters
qx x-coordinate of public key. Point (qx, qy) should be on the curve
Parameters
qy y-coordinate of public key. Point (qx, qy) should be on the curve
Parameters
r First part of signature to verify
Parameters
s Second part of signature to verify
Parameters
h Digest of message to be signed @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_ecdsa_verify_go( const struct sx_pk_ecurve curve, const sx_op qx, const sx_op qy, const sx_op r, const sx_op s, const sx_op h) { struct sx_pk_dreq pkreq; struct sx_pk_inops_ecdsa_verify inputs; pkreq = SX_PK_ACQUIRE_REQ(curve->cnx, SX_PK_CMD_ECDSA_VER); if (pkreq.status) return pkreq; // convert and transfer operands pkreq.status = SX_PK_LIST_ECC_INSLOTS(pkreq.req, curve, 0, (struct sx_pk_slot)&inputs); if (pkreq.status) return pkreq; int opsz = SX_PK_GET_OPSIZE(pkreq.req); SX_PK_OP2MEM(qx, inputs.qx.addr, opsz); SX_PK_OP2MEM(qy, inputs.qy.addr, opsz); SX_PK_OP2MEM(r, inputs.r.addr, opsz); SX_PK_OP2MEM(s, inputs.s.addr, opsz); SX_PK_OP2MEM(h, inputs.h.addr, opsz); SX_PK_RUN(pkreq.req); return pkreq; }
Verify ECDSA signature on an elliptic curve
The verification has the following steps: 1. check qx and qy are smaller than q from the domain 2. Check that Q lies on the elliptic curve from the domain 3. Check that r and s are smaller than n 4. w = s ^ -1 mod n 5. u1 = h w mod n 6. u2 = r w mod n 7. X(x1, y1) = u1 G + u2 Q 8. If X is invalid, then the signature is invalid 9. v = x1 mod n 10. Accept signature if and only if v == r
Parameters
curve Elliptic curve on which to perform ECDSA verification
Parameters
qx x-coordinate of public key. Point (qx, qy) should be on the curve
Parameters
qy y-coordinate of public key. Point (qx, qy) should be on the curve
Parameters
r First part of signature to verify
Parameters
s Second part of signature to verify
Parameters
h Digest of message to be signed @return ::SX_OK @return ::SX_ERR_INVALID_PARAM @return ::SX_ERR_NOT_INVERTIBLE @return ::SX_ERR_INVALID_SIGNATURE @return ::SX_ERR_OUT_OF_RANGE @return ::SX_ERR_UNKNOWN_ERROR @return ::SX_ERR_BUSY @return ::SX_ERR_NOT_IMPLEMENTED @return ::SX_ERR_OPERAND_TOO_LARGE @return ::SX_ERR_PLATFORM_ERROR @return ::SX_ERR_EXPIRED @see sx_async_ecdsa_verify_go() for an asynchronous version static inline int sx_ecdsa_verify( const struct sx_pk_ecurve curve, const sx_op qx, const sx_op qy, const sx_op r, const sx_op s, const sx_op h) { uint32_t status; struct sx_pk_dreq pkreq; pkreq = sx_async_ecdsa_verify_go(curve, qx, qy, r, s, h); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); SX_PK_RELEASE_REQ(pkreq.req); return status; }
@} */
inline
Function
C
static inline
@addtogroup SX_PK_SXOPS_ECOPS @{
Asynchronous EC point multiplication.
Starts an EC point multiplication on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_ecp_mult_end()
Parameters
curve Elliptic curve used to perform point multiplication
Parameters
k Scalar that multiplies point P
Parameters
Py x-coordinate of point P
Parameters
Px y-coordinate of point P @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_ecp_mult_go( const struct sx_pk_ecurve curve, const sx_op k, const sx_op Px, const sx_op Py) { struct sx_pk_dreq pkreq; pkreq = SX_PK_ACQUIRE_REQ(curve->cnx, SX_PK_CMD_ECC_PTMUL); if (pkreq.status) return pkreq; struct sx_pk_inops_ecp_mult inputs; pkreq.status = SX_PK_LIST_ECC_INSLOTS(pkreq.req, curve, 0, (struct sx_pk_slot)&inputs); if (pkreq.status) return pkreq; int opsz = SX_PK_GET_OPSIZE(pkreq.req); SX_PK_OP2MEM(k, inputs.k.addr, opsz); if (Px == SX_PTMULT_CURVE_GENERATOR) { SX_PK_WRITE_CURVE_GEN(pkreq.req, curve, inputs.px, inputs.py); } else { SX_PK_OP2MEM(Px, inputs.px.addr, opsz); SX_PK_OP2MEM(Py, inputs.py.addr, opsz); } SX_PK_RUN(pkreq.req); return pkreq; }
Finish asynchronous EC point multiplication.
Get the output operands of the EC point multiplication and release the reserved resources. @pre The operation on the accelerator must be finished before calling this function.
Parameters
req The previously acquired acceleration request for this operation
Parameters
Rx x-coordinate of resulting point R
Parameters
Ry y-coordinate of resulting point R static inline void sx_async_ecp_mult_end( sx_pk_accel req, sx_op Rx, sx_op Ry) { sx_async_finish_pair(req, Rx, Ry); }
Compute point multiplication on an elliptic curve
(Rx, Ry) = k (Px, Py)
Parameters
curve Elliptic curve used to perform point multiplication
Parameters
k Scalar that multiplies point P
Parameters
Py x-coordinate of point P
Parameters
Px y-coordinate of point P
Parameters
Rx x-coordinate of resulting point R
Parameters
Ry y-coordinate of resulting point R @return ::SX_OK @return ::SX_ERR_NOT_INVERTIBLE @return ::SX_ERR_OUT_OF_RANGE @return ::SX_ERR_POINT_NOT_ON_CURVE @return ::SX_ERR_INVALID_PARAM @return ::SX_ERR_UNKNOWN_ERROR @return ::SX_ERR_BUSY @return ::SX_ERR_NOT_IMPLEMENTED @return ::SX_ERR_OPERAND_TOO_LARGE @return ::SX_ERR_PLATFORM_ERROR @return ::SX_ERR_EXPIRED @see sx_async_ecp_mult_go(), sx_async_ecp_mult_end() for an asynchronous versions static inline int sx_ecp_ptmult( const struct sx_pk_ecurve curve, const sx_op k, const sx_op Px, const sx_op Py, sx_op Rx, sx_op Ry) { int status; struct sx_pk_dreq pkreq; pkreq = sx_async_ecp_mult_go(curve, k, Px, Py); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_ecp_mult_end(pkreq.req, Rx, Ry); return status; }
Asynchronous EC point doubling.
Starts an EC point doubling on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_ecp_double_end()
Parameters
curve Elliptic curve used to perform point doubling
Parameters
py x-coordinate of point P
Parameters
px y-coordinate of point P @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_ecp_double_go( const struct sx_pk_ecurve curve, const sx_op px, const sx_op py) { struct sx_pk_dreq pkreq; pkreq = SX_PK_ACQUIRE_REQ(curve->cnx, SX_PK_CMD_ECC_PT_DOUBLE); if (pkreq.status) return pkreq; struct sx_pk_inops_ecp_double inputs; pkreq.status = SX_PK_LIST_ECC_INSLOTS(pkreq.req, curve, 0, (struct sx_pk_slot)&inputs); if (pkreq.status) return pkreq; int opsz = SX_PK_GET_OPSIZE(pkreq.req); SX_PK_OP2MEM(px, inputs.px.addr, opsz); SX_PK_OP2MEM(py, inputs.py.addr, opsz); SX_PK_RUN(pkreq.req); return pkreq; }
Finish asynchronous EC point doubling.
Get the output operands of the EC point doubling and release the reserved resources. @pre The operation on the accelerator must be finished before calling this function
Parameters
req The previously acquired acceleration request for this operation
Parameters
rx x-coordinate of resulting point R
Parameters
ry y-coordinate of resulting point R static inline void sx_async_ecp_double_end( sx_pk_accel req, sx_op rx, sx_op ry) { sx_async_finish_pair(req, rx, ry); }
Compute point doubling on an elliptic curve
(Rx, Ry) = 2 (Px, Py)
Parameters
curve Elliptic curve used to perform point doubling
Parameters
py x-coordinate of point P
Parameters
px y-coordinate of point P
Parameters
rx x-coordinate of resulting point R
Parameters
ry y-coordinate of resulting point R @return ::SX_OK @return ::SX_ERR_NOT_INVERTIBLE @return ::SX_ERR_OUT_OF_RANGE @return ::SX_ERR_POINT_NOT_ON_CURVE @return ::SX_ERR_INVALID_PARAM @return ::SX_ERR_UNKNOWN_ERROR @return ::SX_ERR_BUSY @return ::SX_ERR_NOT_IMPLEMENTED @return ::SX_ERR_OPERAND_TOO_LARGE @return ::SX_ERR_PLATFORM_ERROR @return ::SX_ERR_EXPIRED @see sx_async_ecp_double_go(), sx_async_ecp_double_end() for an asynchronous verion static inline int sx_ecp_double( const struct sx_pk_ecurve curve, const sx_op px, const sx_op py, sx_op rx, sx_op ry) { int status; struct sx_pk_dreq pkreq; pkreq = sx_async_ecp_double_go(curve, px, py); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_ecp_double_end(pkreq.req, rx, ry); return status; }
Asynchronous (non-blocking) EC point on curve check.
Starts an EC point on curve check on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call SX_PK_RELEASE_REQ()
Parameters
curve Elliptic curve used to validate point
Parameters
px x-coordinate of point P
Parameters
py y-coordinate of point P @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_ec_ptoncurve_go( const struct sx_pk_ecurve curve, const sx_op px, const sx_op py) { struct sx_pk_dreq pkreq; pkreq = SX_PK_ACQUIRE_REQ(curve->cnx, SX_PK_CMD_ECC_PTONCURVE); if (pkreq.status) return pkreq; struct sx_pk_inops_ec_ptoncurve inputs; pkreq.status = SX_PK_LIST_ECC_INSLOTS(pkreq.req, curve, 0, (struct sx_pk_slot)&inputs); if (pkreq.status) return pkreq; int opsz = SX_PK_GET_OPSIZE(pkreq.req); SX_PK_OP2MEM(px, inputs.px.addr, opsz); SX_PK_OP2MEM(py, inputs.py.addr, opsz); SX_PK_RUN(pkreq.req); return pkreq; }
Check if the given point is on the given elliptic curve
It succeeds if the following checks pass: For GF(p): 1. px < p 2. py < p 3. py2 == px3 + a px + b mod p For GF(2m), where q = 2m 1. px < q 2. py < q 3. py2 + px py == px3 + a px^2 + b mod q
Parameters
curve Elliptic curve used to validate point
Parameters
px x-coordinate of point P
Parameters
py y-coordinate of point P @return ::SX_OK @return ::SX_ERR_NOT_INVERTIBLE @return ::SX_ERR_OUT_OF_RANGE @return ::SX_ERR_POINT_NOT_ON_CURVE @return ::SX_ERR_INVALID_PARAM @return ::SX_ERR_UNKNOWN_ERROR @return ::SX_ERR_BUSY @return ::SX_ERR_NOT_IMPLEMENTED @return ::SX_ERR_OPERAND_TOO_LARGE @return ::SX_ERR_PLATFORM_ERROR @return ::SX_ERR_EXPIRED static inline int sx_ec_ptoncurve( const struct sx_pk_ecurve curve, const sx_op px, const sx_op py) { int status; struct sx_pk_dreq pkreq; pkreq = sx_async_ec_ptoncurve_go(curve, px, py); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); SX_PK_RELEASE_REQ(pkreq.req); return status; }
Asynchronous (non-blocking) EC point decompression.
Starts an EC point decompression on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_ec_pt_decompression_end()
Parameters
curve Elliptic curve used to validate point
Parameters
x x-coordinate of point to decompress
Parameters
y_lsb Least Significant Bit of y-coordinate @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_ec_pt_decompression_go( const struct sx_pk_ecurve curve, const sx_op x, const int y_lsb) { struct sx_pk_dreq pkreq; pkreq = SX_PK_ACQUIRE_REQ(curve->cnx, SX_PK_CMD_ECC_PT_DECOMP); if (pkreq.status) return pkreq; struct sx_pk_inops_ec_pt_decompression inputs; pkreq.status = SX_PK_LIST_ECC_INSLOTS(pkreq.req, curve, ((y_lsb & 1) << 29), (struct sx_pk_slot)&inputs); if (pkreq.status) return pkreq; int opsz = SX_PK_GET_OPSIZE(pkreq.req); SX_PK_OP2MEM(x, inputs.x.addr, opsz); SX_PK_RUN(pkreq.req); return pkreq; }
Finish asynchronous (non-blocking) EC point decompression.
Get the output operand of the EC point decompression and release the reserved resources. @pre The operation on the accelerator must be finished before calling this function.
Parameters
req The previously acquired acceleration request for this operation
Parameters
y y-coordinate of decompressed point static inline void sx_async_ec_pt_decompression_end( sx_pk_accel req, sx_op y) { sx_async_finish_single(req, y); }
ECC point decompression
Recover the y coordinate of a point using x value and LSB of y: 1. y = sqrt(x^3 + a x + b) | Param | Description | |:----- |:----------- |
| 2. if (y & 1) != y_lsb then y = p | y with a and p the curve parameters 3. else return ::SX_ERR_NOT_QUADRATIC_RESIDUE @remark: Point decompression is supported for GF(p) only
Parameters
curve Elliptic curve used to validate point
Parameters
x x-coordinate of point to decompress
Parameters
y_lsb Least Significant Bit of y-coordinate
Parameters
y y-coordinate of decompressed point @return ::SX_OK @return ::SX_ERR_NOT_QUADRATIC_RESIDUE @return ::SX_ERR_INVALID_PARAM @return ::SX_ERR_UNKNOWN_ERROR @return ::SX_ERR_BUSY @return ::SX_ERR_NOT_IMPLEMENTED @return ::SX_ERR_OPERAND_TOO_LARGE @return ::SX_ERR_PLATFORM_ERROR @return ::SX_ERR_EXPIRED static inline int sx_ec_pt_decompression( const struct sx_pk_ecurve curve, const sx_op x, const int y_lsb, sx_op y) { int status; struct sx_pk_dreq pkreq; pkreq = sx_async_ec_pt_decompression_go(curve, x, y_lsb); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_ec_pt_decompression_end(pkreq.req, y); return status; }
@addtogroup SX_PK_SXOPS_ECOPS
@{
Asynchronous (non-blocking) EC point addition.
Start an EC point addition on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_ecp_add_end()
Parameters
curve Elliptic curve to perform EC point addition
Parameters
p1x x-coordinate of first point
Parameters
p1y y-coordinate of first point
Parameters
p2x x-coordinate of second point
Parameters
p2y y-coordinate of second point @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_ecp_add_go( const struct sx_pk_ecurve curve, const sx_op p1x, const sx_op p1y, const sx_op p2x, const sx_op p2y) { struct sx_pk_dreq pkreq; pkreq = SX_PK_ACQUIRE_REQ(curve->cnx, SX_PK_CMD_ECC_PT_ADD); if (pkreq.status) return pkreq; struct sx_pk_inops_ecp_add inputs; pkreq.status = SX_PK_LIST_ECC_INSLOTS(pkreq.req, curve, 0, (struct sx_pk_slot)&inputs); if (pkreq.status) return pkreq; int opsz = SX_PK_GET_OPSIZE(pkreq.req); SX_PK_OP2MEM(p1x, inputs.p1x.addr, opsz); SX_PK_OP2MEM(p1y, inputs.p1y.addr, opsz); SX_PK_OP2MEM(p2x, inputs.p2x.addr, opsz); SX_PK_OP2MEM(p2y, inputs.p2y.addr, opsz); SX_PK_RUN(pkreq.req); return pkreq; }
Finish asynchronous (non-blocking) EC point addition.
Get the output operands of the EC point addition and release the reserved resources. @pre The operation on the accelerator must be finished before calling this function.
Parameters
req The previously acquired acceleration request for this operation
Parameters
rx x-coordinate of resulting addition point
Parameters
ry y-coordinate of resulting addition point static inline void sx_async_ecp_add_end( sx_pk_accel req, sx_op rx, sx_op ry) { sx_async_finish_pair(req, rx, ry); }
Compute point addition on an elliptic curve
(Rx, Ry) = P1 + P2 If P1 == P2 returns an SX_ERR_NOT_INVERTIBLE error @remark Use point doubling operation for the addition of equal points
Parameters
curve Elliptic curve to do point addition
Parameters
p1x x-coordinate of point P1
Parameters
p1y y-coordinate of point P1
Parameters
p2x x-coordinate of point P2
Parameters
p2y y-coordinate of point P2
Parameters
rx x-coordinate of resulting point R
Parameters
ry y-coordinate of resulting point R @return ::SX_OK @return ::SX_ERR_NOT_INVERTIBLE @return ::SX_ERR_OUT_OF_RANGE @return ::SX_ERR_POINT_NOT_ON_CURVE @return ::SX_ERR_INVALID_PARAM @return ::SX_ERR_UNKNOWN_ERROR @return ::SX_ERR_BUSY @return ::SX_ERR_NOT_IMPLEMENTED @return ::SX_ERR_OPERAND_TOO_LARGE @return ::SX_ERR_PLATFORM_ERROR @return ::SX_ERR_EXPIRED @remark Use point doubling operation for the addition of equal points @see sx_ecp_double() static inline int sx_ecp_ptadd( const struct sx_pk_ecurve curve, const sx_op p1x, const sx_op p1y, const sx_op p2x, const sx_op p2y, sx_op rx, sx_op ry) { int status; struct sx_pk_dreq pkreq; pkreq = sx_async_ecp_add_go(curve, p1x, p1y, p2x, p2y); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_ecp_add_end(pkreq.req, rx, ry); return status; }
}