Newer
Older
mbed-os / connectivity / drivers / mbedtls / TARGET_NUVOTON / TARGET_M460 / ecp / crypto_ecc_hw.h
@Jay Sridharan Jay Sridharan on 31 Dec 2022 7 KB Merge upstream changes into mbed-ce (#117)
/*
 * Copyright (c) 2022, Nuvoton Technology Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */

#ifndef CRYPTO_ECC_HW_H
#define CRYPTO_ECC_HW_H

#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif

#if defined(MBEDTLS_ECP_ALT) || defined(MBEDTLS_ECP_INTERNAL_ALT)

#include "mbedtls/ecp.h"
#include <stdbool.h>

/* Crypto ECC H/W point operations */
#define ECCOP_POINT_MUL     (0x0UL << CRPT_ECC_CTL_ECCOP_Pos)
#define ECCOP_MODULE        (0x1UL << CRPT_ECC_CTL_ECCOP_Pos)
#define ECCOP_POINT_ADD     (0x2UL << CRPT_ECC_CTL_ECCOP_Pos)
#define ECCOP_POINT_DOUBLE  (0x3UL << CRPT_ECC_CTL_ECCOP_Pos)

/* Crypto ECC H/W modulus operations */
#define MODOP_DIV           (0x0UL << CRPT_ECC_CTL_MODOP_Pos)
#define MODOP_MUL           (0x1UL << CRPT_ECC_CTL_MODOP_Pos)
#define MODOP_ADD           (0x2UL << CRPT_ECC_CTL_MODOP_Pos)
#define MODOP_SUB           (0x3UL << CRPT_ECC_CTL_MODOP_Pos)

#ifdef __cplusplus
extern "C" {
#endif

/**
 * \brief           This function checks whether a given group can be used
 *                  for Crypto ECC H/W.
 *
 * \param grp       ECP group
 *
 * \return          \c 1 if the group can be used, \c 0 otherwise
 */
int crypto_ecc_capable(const mbedtls_ecp_group *grp);

/**
 * \brief           Initialize/Free Crypto ECC H/W
 *
 * \return          \c 0 on success.
 * \return          A non-zero error code on failure.
 *
 * \note            crypto_ecp_init()/crypto_ecp_free() are like pre-op/post-op calls
 *                  and they guarantee:
 *
 *                  1. Paired
 *                  2. No overlapping
 *                  3. Upper public function cannot return when ECP alter. is still activated.
 */
int crypto_ecc_init(const mbedtls_ecp_group *grp);
void crypto_ecc_free(const mbedtls_ecp_group *grp);
/**
 * \brief           Configure ECCOP operation, start it, and wait for its completion
 *
 * \param grp       ECP group
 * \param R         Destination point
 * \param m         Integer by which to multiply P
 * \param P         Point to multiply by m
 * \param n         Integer by which to multiply Q
 * \param Q         Point to be multiplied by n
 * \param eccop     ECCOP code. Could be ECCOP_POINT_MUL/ADD/DOUBLE
 * \param blinding  Blinding (SCAP) or not.
 *                  Dependent on passed-in eccop, only partial parameters among m/P/n/Q are needed and checked.
 *                  ECCOP_POINT_MUL     R = m*P
 *                  ECCOP_POINT_ADD     R = P + Q
 *                  ECCOP_POINT_DOUBLE  R = 2*P
 *
 * \return          0 if successful
 *
 * \note            P/Q must be normalized (= affine). R would be normalized.
 *
 * \note            m/n could be negative.
 *
 * \note            ECC accelerator doesn't support R = 0, and we need to detect it additionally.
 *                  For R = P + Q or R = 2*P, we can detect all R = 0 cases.
 *                  For R = m*P, we can detect all R = 0 cases only if grp->N (order) is a prime.
 *
 * \note            According to ECCOP operation, n is unnecessary. But to be consistent with R = m*P + n*Q,
 *                  n is kept with unused modifier.
 *
 * \note            Blinding (SCAP) is applicable only for point multiplication. But for future extension,
 *                  blinding is kept with all point operations.
 *                  
 */
int crypto_ecc_run_eccop_add(const mbedtls_ecp_group *grp,
                             mbedtls_ecp_point *R,
                             const mbedtls_ecp_point *P,
                             const mbedtls_ecp_point *Q,
                             bool blinding);
int crypto_ecc_run_eccop_double(const mbedtls_ecp_group *grp,
                                mbedtls_ecp_point *R,
                                const mbedtls_ecp_point *P,
                                bool blinding);
int crypto_ecc_run_eccop_mul(const mbedtls_ecp_group *grp,
                             mbedtls_ecp_point *R,
                             const mbedtls_mpi *m,
                             const mbedtls_ecp_point *P,
                             bool blinding);
int crypto_ecc_run_eccop(const mbedtls_ecp_group *grp,
                         mbedtls_ecp_point *R,
                         const mbedtls_mpi *m,
                         const mbedtls_ecp_point *P,
                         const mbedtls_mpi *n,
                         const mbedtls_ecp_point *Q,
                         uint32_t eccop,
                         bool blinding);

/**
 * \brief           Configure MODOP operation and wait for its completion
 *
 * \param r         Destination MPI
 * \param o1        Input MPI for first operand of MODOP
 * \param o2        Input MPI for second operand of MODOP
 * \param p         Prime modulus
 * \param pbits     Bit number of p
 * \param modop     ECCOP code. Could be MODOP_ADD/SUB/MUL/DIV
 *                  MODOP_ADD       r = o1 + o2 mod p
 *                  MODOP_SUB       r = o1 - o2 mod p
 *                  MODOP_MUL       r = o1 * o2 mod p
 *                  MODOP_DIV       r = o1 / o2 mod p
 *
 * \return          0 if successful
 *
 * \note            o1/o2 must be normalized (within [0, p - 1]). r would be normalized.
 */
int crypto_ecc_run_modop(mbedtls_mpi *r,
                         const mbedtls_mpi *o1,
                         const mbedtls_mpi *o2,
                         const mbedtls_mpi *p,
                         uint32_t pbits,
                         uint32_t modop);

/**
 * \brief               Import X from ECC registers, little endian
 *
 * \param X             Destination MPI
 * \param eccreg        Start of input ECC register
 * \param eccreg_num    Number of input ECC register
 *
 * \return              0 if successful
 *
 * \note                Destination MPI is always non-negative.
 */
int crypto_ecc_mpi_read_eccreg( mbedtls_mpi *X, const volatile uint32_t *eccreg, size_t eccreg_num );

/**
 * \brief               Export X into ECC registers, little endian
 *
 * \param X             Source MPI
 * \param eccreg        Start of ECC output registers
 * \param eccreg_num    Number of ECC output registers
 *
 * \return              0 if successful
 *
 * \note                Source MPI cannot be negative.
 * \note                Fills the remaining MSB ECC registers with zeros if X doesn't cover all.
 */
int crypto_ecc_mpi_write_eccreg( const mbedtls_mpi *X, volatile uint32_t *eccreg, size_t eccreg_num );

/**
 * \brief           Abort Crypto ECC H/W
 *
 * \param timeout_us    Timeout in microseconds.
 *
 * \return          \c 0 on success.
 * \return          A non-zero error code on failure.
 */
int crypto_ecc_abort(uint32_t timeout_us);

#ifdef __cplusplus
}
#endif

#endif /* MBEDTLS_ECP_ALT || MBEDTLS_ECP_INTERNAL_ALT */
#endif /* CRYPTO_ECC_HW_H */