/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"),
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup TeeTrusted
 * @{
 *
 * @brief TEE(Trusted Excution Environment) API.
 * Provides security capability APIs such as trusted storage, encryption and decryption,
 * and trusted time for trusted application development.
 *
 * @since 20
 */

/**
 * @file tee_arith_api.h
 *
 * @brief Provides APIs for operating big integers.
 *
 * @library NA
 * @kit TEEKit
 * @syscap SystemCapability.Tee.TeeClient
 * @since 20
 */

#ifndef TEE_ARITH_API_H
#define TEE_ARITH_API_H

#include <stdbool.h>
#include "tee_defines.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Defines the handle type representing a big integer.
 *
 * @since 20
 */
typedef uint32_t TEE_BigInt;

/**
 * @brief Defines the handle of a big integer for Fast Modular Multiplication (FMM).
 *
 * @since 20
 */
typedef uint32_t TEE_BigIntFMM;

/**
 * @brief Defines the handle of a context container for FMM operations.
 *
 * @since 20
 */
typedef uint32_t TEE_BigIntFMMContext;

/**
 * @brief Obtains the size of the array of uint32_t values required to represent a <b>BigInt</b>.
 *
 * @param n Indicates the <b>TEE_BigInt</b> type.
 *
 * @return Returns the <b>BigInt</b> size obtained.
 *
 * @since 20
 */
#define TEE_BigIntSizeInU32(n) ((((n) + 31) / 32) + 2)

/**
 * @brief Obtains the size of the array of uint32_t values.
 *
 * @param modulusSizeInBits Indicates the modulus size, in bits.
 *
 * @return Returns the number of bytes required to store a <b>TEE_BigIntFMM</b>,
 * given a modulus of length <b>modSizeInBits</b>.
 *
 * @since 20
 */
size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits);

/**
 * @brief Obtains the size of an array of uint32_t values required to represent a fast modular context.
 *
 * @param modulusSizeInBits Indicates the modulus size, in bits.
 *
 * @return Returns the number of bytes required to store a <b>TEE_BigIntFMMContext</b>,
 * given a modulus of length <b>modSizeInBits</b>.
 *
 * @since 20
 */
size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits);

/**
 * @brief Initializes a <b>TEE_BigInt</b>.
 *
 * @param bigInt Indicates the pointer to the <b>TEE_BigInt</b> to initialize.
 * @param len Indicates the size of the memory pointed to by <b>TEE_BigInt</b>, in uint32_t.
 *
 * @since 20
 */
void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len);

/**
 * @brief Calculates the necessary prerequisites for fast modular multiplication and stores them in a context.
 *
 * @param context Indicates the pointer to the <b>TEE_BigIntFMMContext</b> to initialize.
 * @param len Indicates the size of the memory pointed to by <b>context</b>, in uint32_t.
 * @param modulus Indicates the pointer to the modulus.
 *
 * @since 20
 */
void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, size_t len, const TEE_BigInt *modulus);

/**
 * @brief Calculates the necessary prerequisites for fast modular multiplication and stores them in a context.
 *
 * @param context Indicates the pointer to the <b>TEE_BigIntFMMContext</b> to initialize.
 * @param len Indicates the size of the memory pointed to by <b>context</b>, in uint32_t.
 * @param modulus Indicates the pointer to the modulus.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns other values if the operation fails.
 *
 * @since 20
 */
TEE_Result TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext *context, size_t len, const TEE_BigInt *modulus);

/**
 * @brief Initializes a <b>TEE_BigIntFMM</b> and sets its represented value to zero.
 *
 * @param bigIntFMM Indicates the pointer to the <b>TEE_BigIntFMM</b> to initialize.
 * @param len Indicates the size of the memory pointed to by <b>bigIntFMM</b>, in uint32_t.
 *
 * @since 20
 */
void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, size_t len);

/**
 * @brief Converts an octet string buffer into the <b>TEE_BigInt</b> format.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result.
 * @param buffer Indicates the pointer to the buffer that holds the octet string representation of the integer.
 * @param bufferLen Indicates the buffer length, in bytes.
 * @param sign Indicates the sign of <b>dest</b>, which is set to the sign of <b>sign</b>.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns <b>TEE_ERROR_OVERFLOW</b> if the memory allocated for <b>dest</b> is too small.
 *
 * @since 20
 */
TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, const uint8_t *buffer, size_t bufferLen, int32_t sign);

/**
 * @brief Converts the absolute value of an integer in <b>TEE_BigInt</b> format into an octet string.
 *
 * @param buffer Indicates the pointer to the output buffer that holds the converted octet string representation
 * of the integer.
 * @param bufferLen Indicates the pointer to the buffer length, in bytes.
 * @param bigInt Indicates the pointer to the integer to convert.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns <b>TEE_ERROR_SHORT_BUFFER</b> if the output buffer is too small to hold the octet string.
 *
 * @since 20
 */
TEE_Result TEE_BigIntConvertToOctetString(void *buffer, size_t *bufferLen, const TEE_BigInt *bigInt);

/**
 * @brief Sets <b>dest</b> to the value <b>shortVal</b>.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result.
 * @param shortVal Indicates the value to set.
 *
 * @since 20
 */
void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal);

/**
 * @brief Sets <b>dest</b> to the value of <b>src</b>, including the sign of <b>src</b>.
 *
 * @param dest Indicates the pointer to the <b> int32_t</b> that holds the result.
 * @param src Indicates the pointer to the value to set.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns <b>TEE_ERROR_OVERFLOW</b> if <b>src</b> does not fit within an <b> int32_t</b>.
 *
 * @since 20
 */
TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src);

/**
 * @brief Checks whether op1 > op2, op1 == op2, or op1 < op2.
 *
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 *
 * @return Returns <b>0</b> if op1 == op2.
 *         Returns a positive number if op1 > op2.
 *
 * @since 20
 */
int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief Checks whether op > shortVal, op == shortVal, or op < shortVal.
 *
 * @param op Indicates the pointer to the first operand.
 * @param shortVal Indicates the pointer to the second operand.
 *
 * @return Returns <b>0</b> if op1 == shortVal.
 *         Returns a positive number if op1 > shortVal.
 *
 * @since 20
 */
int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal);

/**
 * @brief Computes |dest| = |op| >> bits.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the shifted result.
 * @param op Indicates the pointer to the operand to be shifted.
 * @param bits Indicates the number of bits to shift.
 *
 * @since 20
 */
void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits);

/**
 * @brief Obtains the <b>bitIndex</b> bit of the natural binary representation of |src|.
 *
 * @param src Indicates the pointer to the integer.
 * @param bitIndex Indicates the offset of the bit to read, starting from offset <b>0</b> of the least significant bit.
 *
 * @return Returns the Boolean value of <b>bitIndexth</b> in |src|. The value <b>true</b> represents a <b>1</b>,
 * and <b>false</b> represents a <b>0</b>.
 *
 * @since 20
 */
bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex);

/**
 * @brief Obtains the number of bits in the natural binary representation of |src|,
 * that is, the magnitude of <b>src</b>.
 *
 * @param src Indicates the pointer to the integer.
 *
 * @return Returns <b>0</b> if <b>src</b> is <b>0</b>.
 *         Returns the number of bits in the natural binary representation of <b>src</b>.
 *
 * @since 20
 */
uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src);

/**
 * @brief Sets the first bit of <b>bitIndex</b> in the natural binary representation of <b>op</b> to
 * <b>1</b> or <b>0</b>.
 *
 * @param op Indicates the pointer to the integer.
 * @param bitIndex Indicates the offset of the bit to set, starting from offset <b>0</b> of the least significant bit.
 * @param value Indicates the bit value to set. The value <b>true</b> represents a <b>1</b>, and the value <b>false</b>
 * represents a <b>0</b>.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns <b>TEE_ERROR_OVERFLOW bitIndexth</b> if the <b>bitIndexth</b> bit is larger than the allocated bit
 * length of <b>op</b>.
 *
 * @since 20
 */
TEE_Result TEE_BigIntSetBit(TEE_BigInt *op, uint32_t bitIndex, bool value);

/**
 * @brief Assigns the value of <b>src</b> to <b>dest</b>.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> to be assigned.
 * @param src Indicates the pointer to the source operand.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns <b>TEE_ERROR_OVERFLOW</b> if the <b>dest</b> operand cannot hold the value of <b>src</b>.
 *
 * @since 20
 */
TEE_Result TEE_BigIntAssign(TEE_BigInt *dest, const TEE_BigInt *src);

/**
 * @brief Assigns the value of <b>src</b> to <b>dest</b>.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> to be assigned.
 * @param src Indicates the pointer to the source operand.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns <b>TEE_ERROR_OVERFLOW</b> if the <b>dest</b> operand cannot hold the value of <b>src</b>.
 *
 * @since 20
 */
TEE_Result TEE_BigIntAbs(TEE_BigInt *dest, const TEE_BigInt *src);

/**
 * @brief Computes dest = op1 + op2.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the sum of <b>op1</b> and <b>op2</b>.
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 *
 * @since 20
 */
void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief Computes dest = op1 – op2.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the difference between <b>op1</b>
 * and <b>op2</b>.
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 *
 * @since 20
 */
void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief Negates an operand: dest = –op.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result –op.
 * @param op Indicates the pointer to the operand to be negated.
 *
 * @since 20
 */
void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *op);

/**
 * @brief Computes dest = op1 * op2.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the product of <b>op1</b> and <b>op2</b>.
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 *
 * @since 20
 */
void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief Computes dest = op * op.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result op * op.
 * @param op Indicates the pointer to the operand to be squared.
 *
 * @since 20
 */
void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op);

/**
 * @brief Computes <b>dest_r</b> and <b>dest_q</b> to make op1 = dest_q* op2 + dest_r.
 *
 * @param dest_q Indicates the pointer to the <b>TEE_BigInt</b> that holds the quotient.
 * @param dest_r Indicates the pointer to the <b>TEE_BigInt</b> that holds the remainder.
 * @param op1 Indicates the pointer to the first operand, which is the dividend.
 * @param op2 Indicates the pointer to the second operand, which is the divisor.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns <b>TEE_ERROR_BAD_PARAMETERS</b> if at least one parameter is null.
 *
 * @since 20
 */
void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief Computes dest = op (mod n) to make 0 <= dest < n.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result op (mod n).
 * @param op Indicates the pointer to the operand to be reduced mod n.
 * @param n [IN] Indicates the pointer to the modulus, which must be greater than 1.
 *
 * @since 20
 */
void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n);

/**
 * @brief Computes dest = (op1 + op2) (mod n).
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result op (op1 + op2)(mod n).
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 * @param n Indicates the pointer to the modulus, which must be greater than 1.
 *
 * @since 20
 */
void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n);

/**
 * @brief Computes dest = (op1 – op2) (mod n).
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result op (op1 – op2)(mod n).
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 * @param n Indicates the pointer to the modulus, which must be greater than 1.
 *
 * @since 20
 */
void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n);

/**
 * @brief Computes dest = (op1* op2)(mod n).
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result op (op1 * op2)(mod n).
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 * @param n Indicates the pointer to the modulus, which must be greater than 1.
 *
 * @since 20
 */
void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n);

/**
 * @brief Computes dest = (op * op) (mod n).
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result op (op * op)(mod n).
 * @param op Indicates the pointer to the operand.
 * @param n [IN] Indicates the pointer to the modulus, which must be greater than 1.
 *
 * @since 20
 */
void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n);

/**
 * @brief Computes <b>dest</b> to make dest* op = 1 (mod n).
 *
 * @param dest Indicates the pointer to the <b>TEE_BigInt</b> that holds the result (op^–1)(mod n).
 * @param op Indicates the pointer to the operand.
 * @param n [IN] Indicates the pointer to the modulus, which must be greater than 1.
 *
 * @since 20
 */
void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n);

/**
 * @brief Checks whether gcd(op1, op2) == 1.
 *
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 *
 * @return Returns <b>true</b> if gcd(op1, op2) == 1.
 *         Returns <b>false</b> if gcd(op1, op2) != 1.
 *
 * @since 20
 */
bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief Computes the greatest common divisor of <b>op1</b> and <b>op2</b>.
 *
 * @param gcd Indicates the pointer to the <b>TEE_BigInt</b> that holds the greatest common divisor of <b>op1</b>
 * and <b>op2</b>.
 * @param u Indicates the pointer to the <b>TEE_BigInt</b> that holds the first coefficient.
 * @param v Indicates the pointer to the <b>TEE_BigInt</b> that holds the second coefficient.
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 *
 * @since 20
 */
void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, TEE_BigInt *v, const TEE_BigInt *op1,
                                  const TEE_BigInt *op2);
/**
 * @brief Performs a probabilistic primality test on <b>op</b>.
 *
 * @param op Indicates the pointer to the candidate number that is tested for primality.
 * @param confidenceLevel Indicates the expected confidence level for a non-conclusive test.
 *
 * @return Returns <b>0</b> if <b>op</b> is a composite number.
 *         Returns <b>1</b> if <b>op</b> is a prime number.
 *         Returns <b>–1</b> if the test is non-conclusive but the probability that <b>op</b> is composite is
 * less than 2^(-confidenceLevel).
 *
 * @since 20
 */
int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, uint32_t confidenceLevel);

/**
 * @brief Converts <b>src</b> into a representation suitable for doing fast modular multiplication.
 *
 * @param dest Indicates the pointer to an initialized <b>TEE_BigIntFMM</b> memory area.
 * @param src Indicates the pointer to the <b>TEE_BigInt</b> to convert.
 * @param n Indicates the pointer to the modulus.
 * @param context Indicates the pointer to the context that is previously initialized using
 * {@link TEE_BigIntInitFMMContext1}.
 *
 * @since 20
 */
void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src, const TEE_BigInt *n,
                            const TEE_BigIntFMMContext *context);

/**
 * @brief Converts <b>src</b> in the fast modular multiplication representation back to a
 * <b>TEE_BigInt</b> representation.
 *
 * @param dest Indicates the pointer to an initialized <b>TEE_BigIntFMM</b> memory area to store the converted result.
 * @param src Indicates the pointer to a <b>TEE_BigIntFMM</b> holding the value in the fast modular multiplication
 * representation.
 * @param n Indicates the pointer to the modulus.
 * @param context Indicates the pointer to the context that is previously initialized using
 * {@link TEE_BigIntInitFMMContext1}.
 *
 * @since 20
 */
void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src, const TEE_BigInt *n,
                              const TEE_BigIntFMMContext *context);

/**
 * @brief Computes dest = op1* op2 in the fast modular multiplication representation.
 *
 * @param dest Indicates the pointer to the <b>TEE_BigIntFMM</b> that holds the result op1* op2.
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 * @param n Indicates the pointer to the modulus.
 * @param context Indicates the pointer to the context that is previously initialized using
 * {@link TEE_BigIntInitFMMContext1}.
 *
 * @since 20
 */
void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1, const TEE_BigIntFMM *op2, const TEE_BigInt *n,
                          const TEE_BigIntFMMContext *context);

/**
 * @brief Computes dest = (op1 ^ op2)(mod n).
 *
 * @param des Indicates the pointer to the <b>TEE_BigInt</b> that holds the result (op1 ^ op2)(mod n).
 * @param op1 Indicates the pointer to the first operand.
 * @param op2 Indicates the pointer to the second operand.
 * @param n Indicates the pointer to the modulus.
 * @param context Indicates the pointer to the context that is previously initialized using
 * {@link TEE_BigIntInitFMMContext1} or initialized to null.
 *
 * @return Returns <b>TEE_SUCCESS</b> if the operation is successful.
 *         Returns <b>TEE_ERROR_NOT_SUPPORTED</b> if the value of <b>n</b> is not supported.
 *
 * @since 20
 */
TEE_Result TEE_BigIntExpMod(TEE_BigInt *des, TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n,
                            TEE_BigIntFMMContext *context);

#ifdef __cplusplus
}
#endif

#endif
/** @} */