"sxops" interface for RSA and GF(p) cryptographic 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

RSA_HEADER_FILE Macro

C

#define RSA_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, 0);

struct sx_pk_cmd_def;

inline

Function

C

static inline

@addtogroup SX_PK_SXOPS_MOD

@{

Asynchronous (non-blocking) Primitive modular operation with 1 operand

Start a primitive modular operation with 1 operand on the accelerator and return immediately.

@remark When the operation finishes on the accelerator, call sx_async_finish_single()

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

cmd Command definition. Should be a primitive modular operation with 1 operands. For example: ::SX_PK_CMD_ODD_MOD_INV, ::SX_PK_CMD_ODD_MOD_REDUCE, ::SX_PK_CMD_EVEN_MOD_INV, ::SX_PK_CMD_EVEN_MOD_REDUCE

Parameters

modulo Modulus operand. Must be odd if using ::SX_PK_CMD_ODD_MOD_INV or ::SX_PK_CMD_ODD_MOD_REDUCE command and even when using ::SX_PK_CMD_EVEN_MOD_INV or ::SX_PK_CMD_EVEN_MOD_REDUCE command

Parameters

b Operand of modular operation @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_mod_single_op_cmd_go( struct sx_pk_cnx cnx, const struct sx_pk_cmd_def cmd, const sx_op modulo, const sx_op b) { struct sx_pk_dreq pkreq; struct sx_pk_inops_mod_single_op_cmd inputs; pkreq = SX_PK_ACQUIRE_REQ(cnx, cmd); if (pkreq.status) return pkreq; // convert and transfer operands int sizes = { SX_OP_SIZE(modulo), SX_OP_SIZE(b), }; pkreq.status = SX_PK_LIST_GFP_INSLOTS(pkreq.req, sizes, (struct sx_pk_slot )&inputs); if (pkreq.status) return pkreq; SX_PK_OP2VMEM(modulo, inputs.n.addr); SX_PK_OP2VMEM(b, inputs.b.addr); SX_PK_RUN(pkreq.req); return pkreq; }

Compute single operand modular operation

ParamDescription
result = b mod modulo for ::SX_PK_CMD_ODD_MOD_REDUCE, ::SX_PK_CMD_EVEN_MOD_REDUCE
result = 1 / b mod modulo for ::SX_PK_CMD_ODD_MOD_INV, ::SX_PK_CMD_EVEN_MOD_INV

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

cmd Command definition. Should be a primitive modular operation with 1 operand. For example: ::SX_PK_CMD_ODD_MOD_REDUCE, ::SX_PK_CMD_ODD_MOD_INV, ::SX_PK_CMD_EVEN_MOD_REDUCE, ::SX_PK_CMD_EVEN_MOD_INV

Parameters

modulo Modulus operand. Must be odd if using ::SX_PK_CMD_ODD_MOD_INV or ::SX_PK_CMD_ODD_MOD_REDUCE command and even when using ::SX_PK_CMD_EVEN_MOD_INV or ::SX_PK_CMD_EVEN_MOD_REDUCE command

Parameters

b Operand

Parameters

result Result operand @return ::SX_OK @return ::SX_ERR_INVALID_PARAM @return ::SX_ERR_NOT_INVERTIBLE @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 It is up to the user to use the corresponding command w.r.t. the parity of the modulus @see sx_async_mod_single_op_cmd_go() and sx_async_finish_single() for an asynchronous version static inline int sx_mod_single_op_cmd( struct sx_pk_cnx cnx, const struct sx_pk_cmd_def cmd, const sx_op modulo, const sx_op b, sx_op result) { struct sx_pk_dreq pkreq; int status; pkreq = sx_async_mod_single_op_cmd_go(cnx, cmd, modulo, b); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_finish_single(pkreq.req, result); return status; }

Asynchronous (non-blocking) Primitive modular operation with 2 operands

Start a primitive modular operation with 2 operands on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_finish_single()

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

cmd Command definition. Should be a primitive modular operation with 2 operands. For example: ::SX_PK_CMD_MOD_ADD, ::SX_PK_CMD_MOD_SUB, ::SX_PK_CMD_ODD_MOD_MULT, ::SX_PK_CMD_ODD_MOD_DIV

Parameters

modulo Modulus operand for the modular operantion

Parameters

a First operand of modular operation

Parameters

b Second operand of modular operation @return Acquired acceleration request for this operation @see sx_mod_primitive_cmd() for a synchronous version static inline struct sx_pk_dreq sx_async_mod_cmd_go( struct sx_pk_cnx cnx, const struct sx_pk_cmd_def cmd, const sx_op modulo, const sx_op a, const sx_op b) { struct sx_pk_dreq pkreq; struct sx_pk_inops_mod_cmd inputs; pkreq = SX_PK_ACQUIRE_REQ(cnx, cmd); if (pkreq.status) return pkreq; // convert and transfer operands int sizes = { SX_OP_SIZE(modulo), SX_OP_SIZE(a), SX_OP_SIZE(b), }; pkreq.status = SX_PK_LIST_GFP_INSLOTS(pkreq.req, sizes, (struct sx_pk_slot )&inputs); if (pkreq.status) return pkreq; SX_PK_OP2VMEM(modulo, inputs.n.addr); SX_PK_OP2VMEM(a, inputs.a.addr); SX_PK_OP2VMEM(b, inputs.b.addr); SX_PK_RUN(pkreq.req); return pkreq; }

Primitive modular operation with 2 operands

ParamDescription
result = a + b mod modulo for ::SX_PK_CMD_MOD_ADD
result = a
result = a b mod modulo for ::SX_PK_CMD_ODD_MOD_MULT with odd modulus
result = a / b mod modulo for ::SX_PK_CMD_ODD_MOD_DIV with odd modulus Perform a modular addition or subtraction or odd modular multiplication or odd modular division.

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

cmd Command definition. Should be a primitive modular operation with 2 operands. See description

Parameters

modulo Modulus operand for the modular operantion

Parameters

a First operand of modular operation

Parameters

b Second operand of modular operation

Parameters

result Result operand of the modular operation @return ::SX_OK @return ::SX_ERR_NOT_INVERTIBLE @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_mod_cmd_go() and sx_async_finish_single() for an asynchronous version static inline int sx_mod_primitive_cmd( struct sx_pk_cnx cnx, const struct sx_pk_cmd_def cmd, const sx_op modulo, const sx_op a, const sx_op b, sx_op result) { struct sx_pk_dreq pkreq; int status; pkreq = sx_async_mod_cmd_go(cnx, cmd, modulo, a, b); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_finish_single(pkreq.req, result); return status; }

Asynchronous (non-blocking) mod inversion.

Start a modular inversion on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_finish_single()

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

modulo Modulus operand

Parameters

b Operand to inverse @return Acquired acceleration request for this operation @see sx_async_finish_single(), sx_mod_inv() static inline struct sx_pk_dreq sx_async_mod_inv_go( struct sx_pk_cnx cnx, const sx_op modulo, const sx_op b) { return sx_async_mod_single_op_cmd_go(cnx, SX_PK_CMD_ODD_MOD_INV, modulo, b); }

Compute modular inversion

result = 1/b mod modulo

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

modulo Modulus operand

Parameters

b Operand to inverse

Parameters

result Result operand of the modular inversion @return ::SX_OK @return ::SX_ERR_NOT_INVERTIBLE @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_mod_inv_go() for an asynchronous verion static inline int sx_mod_inv( struct sx_pk_cnx cnx, const sx_op modulo, const sx_op b, sx_op result) { struct sx_pk_dreq pkreq; int status; pkreq = sx_async_mod_inv_go(cnx, modulo, b); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_finish_single(pkreq.req, result); return status; }

Asynchronous (non-blocking) modular exponentiation.

Start a modular exponentiation on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_mod_exp_end()

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

input Base operand for modular exponentiation

Parameters

exp Exponent operand

Parameters

m Modulus operand @return Acquired acceleration request for this operation @see sx_mod_exp() for the synchronous version static inline struct sx_pk_dreq sx_async_mod_exp_go( struct sx_pk_cnx cnx, const sx_op input, const sx_op exp, const sx_op m) { return sx_async_mod_cmd_go(cnx, SX_PK_CMD_MOD_EXP, m, input, exp); }

Finish asynchronous (non-blocking) modular exponentiation.

Get the output operand of the modular exponentiation and release the accelerator. @pre The operation on the accelerator must be finished before calling this function.

Parameters

req The previously acquired acceleration request for this operation

Parameters

result Result operand @see sx_async_mod_exp_go() and sx_mod_exp() static inline void sx_async_mod_exp_end( sx_pk_accel req, sx_op result) { sx_async_finish_single(req, result); }

Compute modular exponentiation.

result = input ^ exp mod m

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

input Base operand

Parameters

exp Exponent operand

Parameters

m Modulus operand

Parameters

result Result operand @return ::SX_OK @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_mod_exp_go(), sx_async_mod_exp_end() for an asynchronous version static inline int sx_mod_exp( struct sx_pk_cnx cnx, const sx_op input, const sx_op exp, const sx_op m, sx_op result) { struct sx_pk_dreq pkreq; int status; pkreq = sx_async_mod_exp_go(cnx, input, exp, m); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_mod_exp_end(pkreq.req, result); return status; }

@} */

inline

Function

C

static inline

@addtogroup SX_PK_SXOPS_RSA @{

Asynchronous (non-blocking) modular exponentiation with CRT.

Start a modular exponentiation with CRT on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_crt_mod_exp_end()

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

in Input

Parameters

p Prime number p

Parameters

q Prime number q

Parameters

dp d mod (p-1), with d the private key

Parameters

dq d mod (q-1), with d the private key

Parameters

qinv q^(-1) mod p @return Acquired acceleration request for this operation @see sx_async_crt_mod_exp_end() static inline struct sx_pk_dreq sx_async_crt_mod_exp_go( struct sx_pk_cnx cnx, const sx_op in, const sx_op p, const sx_op q, const sx_op dp, const sx_op dq, const sx_op qinv) { struct sx_pk_dreq pkreq; struct sx_pk_inops_crt_mod_exp inputs; pkreq = SX_PK_ACQUIRE_REQ(cnx, SX_PK_CMD_MOD_EXP_CRT); if (pkreq.status) return pkreq; // convert and transfer operands int sizes = { SX_OP_SIZE(p), SX_OP_SIZE(q), SX_OP_SIZE(in), SX_OP_SIZE(dp), SX_OP_SIZE(dq), SX_OP_SIZE(qinv) }; pkreq.status = SX_PK_LIST_GFP_INSLOTS(pkreq.req, sizes, (struct sx_pk_slot )&inputs); if (pkreq.status) return pkreq; SX_PK_OP2VMEM(in, inputs.in.addr); SX_PK_OP2VMEM(p, inputs.p.addr); SX_PK_OP2VMEM(q, inputs.q.addr); SX_PK_OP2VMEM(dp, inputs.dp.addr); SX_PK_OP2VMEM(dq, inputs.dq.addr); SX_PK_OP2VMEM(qinv, inputs.qinv.addr); SX_PK_RUN(pkreq.req); return pkreq; }

Finish asynchronous (non-blocking) modular exponentiation with CRT.

Get the output operand of the modular exponentiation with CRT 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

result @see sx_async_crt_mod_exp_go() static inline void sx_async_crt_mod_exp_end( sx_pk_accel req, sx_op result) { sx_async_finish_single(req, result); }

Compute modular exponentiation with CRT

Compute (result = in db mod m) with those steps: vp = in dp mod p vq = in ^ dq mod q u = (vp -vq) qinv mod p result = vq + u q

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

in Input

Parameters

p Prime number p

Parameters

q Prime number q

Parameters

dp d mod (p-1), with d the private key

Parameters

dq d mod (q-1), with d the private key

Parameters

qinv q^(-1) mod p

Parameters

result Result of modular exponentiation with CRT @return ::SX_OK @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_crt_mod_exp_go(), sx_async_crt_mod_exp_end() for an asynchronous version static inline int sx_crt_mod_exp( struct sx_pk_cnx cnx, const sx_op in, const sx_op p, const sx_op q, const sx_op dp, const sx_op dq, const sx_op qinv, sx_op result) { struct sx_pk_dreq pkreq; int status; pkreq = sx_async_crt_mod_exp_go(cnx, in, p, q, dp, dq, qinv); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_crt_mod_exp_end(pkreq.req, result); return status; }

Asynchronous (non-blocking) RSA private key generation.

Start an RSA private key generation on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_rsa_keygen_end()

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

p Prime value p

Parameters

q Prime value q

Parameters

public_expo Public exponent operand @return Acquired acceleration request for this operation static inline struct sx_pk_dreq sx_async_rsa_keygen_go(struct sx_pk_cnx cnx, const sx_op p, const sx_op q, const sx_op public_expo) { struct sx_pk_dreq pkreq; struct sx_pk_inops_rsa_keygen inputs; pkreq = SX_PK_ACQUIRE_REQ(cnx, SX_PK_CMD_RSA_KEYGEN); if (pkreq.status) return pkreq; // convert and transfer operands int sizes = { SX_OP_SIZE(p), SX_OP_SIZE(q), SX_OP_SIZE(public_expo) }; pkreq.status = SX_PK_LIST_GFP_INSLOTS(pkreq.req, sizes, (struct sx_pk_slot )&inputs); if (pkreq.status) return pkreq; SX_PK_OP2VMEM(p, inputs.p.addr); SX_PK_OP2VMEM(q, inputs.q.addr); SX_PK_OP2VMEM(public_expo, inputs.e.addr); SX_PK_RUN(pkreq.req); return pkreq; }

Finish asynchronous (non-blocking) RSA private key generation.

Get the output operands of the RSA private key 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

n Multiple of 2 primes p and q

Parameters

lambda_n Least common multiple of p-1 and q-1

Parameters

privkey Private key static inline void sx_async_rsa_keygen_end(sx_pk_accel req, sx_op n, sx_op lambda_n, sx_op privkey) { const char outputs = SX_PK_GET_OUTPUT_OPS(req); const int opsz = SX_PK_GET_OPSIZE(req); SX_PK_MEM2OP(outputs, opsz, n); SX_PK_MEM2OP(outputs, opsz, lambda_n); SX_PK_MEM2OP(outputs, opsz, privkey); SX_PK_RELEASE_REQ(req); }

Compute RSA private key and lambda_n from primes p and q.

The private key is generated with the following steps: 1. n = p q 2. lambda_n = lcm(p-1,q-1) 3. d = e^-1 % lambda_n Where d is the private key (privkey).

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

p Prime value p

Parameters

q Prime value q

Parameters

public_expo Public exponent operand

Parameters

n Resulting n operand

Parameters

lambda_n Resulting lambda_n operand

Parameters

privkey Resulting rivate key operand @return ::SX_OK @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_rsa_keygen_go(), sx_async_rsa_keygen_end() for an asynchronous version static inline int sx_rsa_keygen(struct sx_pk_cnx cnx, const sx_op p, const sx_op q, const sx_op public_expo, sx_op n, sx_op lambda_n, sx_op privkey) { struct sx_pk_dreq pkreq; int status; pkreq = sx_async_rsa_keygen_go(cnx, p, q, public_expo); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_rsa_keygen_end(pkreq.req, n, lambda_n, privkey); return status; }

Asynchronous (non-blocking) RSA CRT private key parameters.

Start a RSA CRT private key generation on the accelerator and return immediately. @remark When the operation finishes on the accelerator, call sx_async_rsa_crt_keyparams_end()

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

p Prime operand p

Parameters

q Prime operand q

Parameters

privkey Private key @return Acquired acceleration request for this operation @see sx_async_rsa_crt_keyparams_end() and sx_async_rsa_crt_keyparams() static inline struct sx_pk_dreq sx_async_rsa_crt_keyparams_go( struct sx_pk_cnx cnx, const sx_op p, const sx_op q, const sx_op privkey) { struct sx_pk_dreq pkreq; struct sx_pk_inops_rsa_crt_keyparams inputs; pkreq = SX_PK_ACQUIRE_REQ(cnx, SX_PK_CMD_RSA_CRT_KEYPARAMS); if (pkreq.status) return pkreq; // convert and transfer operands int sizes = { SX_OP_SIZE(p), SX_OP_SIZE(q), SX_OP_SIZE(privkey) }; pkreq.status = SX_PK_LIST_GFP_INSLOTS(pkreq.req, sizes, (struct sx_pk_slot )&inputs); if (pkreq.status) return pkreq; SX_PK_OP2VMEM(p, inputs.p.addr); SX_PK_OP2VMEM(q, inputs.q.addr); SX_PK_OP2VMEM(privkey, inputs.privkey.addr); SX_PK_RUN(pkreq.req); return pkreq; }

Finish asynchronous (non-blocking) RSA CRT private key parameters.

Get the output operands of the RSA CRT private key parameters 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

ParamDescription
dp d mod (p1)

Parameters

ParamDescription
dq d mod (q1)

Parameters

qinv q ^ -1 mod p @see sx_async_rsa_crt_keyparams_go() and sx_rsa_crt_keyparams() static inline void sx_async_rsa_crt_keyparams_end(sx_pk_accel req, sx_op dp, sx_op dq, sx_op qinv) { const char outputs = SX_PK_GET_OUTPUT_OPS(req); const int opsz = SX_PK_GET_OPSIZE(req); SX_PK_MEM2OP(outputs, opsz, dp); SX_PK_MEM2OP(outputs, opsz, dq); SX_PK_MEM2OP(outputs, opsz, qinv); SX_PK_RELEASE_REQ(req); }

Compute RSA CRT private key parameters.

Computes the following parameters: | Param | Description | |:----- |:----------- |

| dp = d mod (p | 1) | | dq = d mod (q | 1) qinv = q ^ -1 mod p where d is the private key and the pair p and q are the secret primes used to create the RSA private key.

Parameters

cnx Connection structure obtained through SX_PK_OPEN() at startup

Parameters

p Prime value p

Parameters

q Prime value q

Parameters

privkey Private key operand

Parameters

ParamDescription
dp d mod (p1)

Parameters

ParamDescription
dq d mod (q1)

Parameters

qinv q ^ -1 mod p @return ::SX_OK @return ::SX_ERR_NOT_INVERTIBLE @return ::SX_ERR_OUT_OF_RANGE @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_rsa_crt_keyparams_go(), sx_async_rsa_crt_keyparams_end() for an asynchronous version static inline int sx_rsa_crt_keyparams(struct sx_pk_cnx cnx, const sx_op p, const sx_op q, const sx_op privkey, sx_op dp, sx_op dq, sx_op qinv) { struct sx_pk_dreq pkreq; int status; pkreq = sx_async_rsa_crt_keyparams_go(cnx, p, q, privkey); if (pkreq.status) return pkreq.status; status = SX_PK_WAIT(pkreq.req); sx_async_rsa_crt_keyparams_end(pkreq.req, dp, dq, qinv); return status; }}