mirror of https://github.com/ARMmbed/mbed-os.git
M467: Support Crypto ECC H/W in full-module replacement
1. Replace ecp.c full-module, and other ec modules dependent on ecp.c (ecdh.c/ecdsa.c/ecjpake.c) will improve followingly. 2. Recover from Crypto ECC H/W failure: (1) Enable timed-out wait to escape from ECC H/W trap (2) On ECC H/W timeout, stop this ECC H/W operation (3) Fall back to S/W implementation on failure 3. Support Short Weierstrass curve 4. Support Montgomery curve Montgomery curve has the form: B y^2 = x^3 + A x^2 + x (1) In S/W impl, A is used as (A + 2) / 4. Figure out its original value for engine.pull/15337/head2eb06e7620/connectivity/mbedtls/include/mbedtls/ecp.h (L219-L220)
(2) In S/W impl, B is unused. Actually, B is 1 for Curve25519/Curve448 and needs to configure to engine.2eb06e7620/connectivity/mbedtls/include/mbedtls/ecp.h (L221-L222)
(3) In S/W impl, y-coord is absent, but engine needs it. Deduce it from x-coord following: https://tools.ietf.org/id/draft-jivsov-ecc-compact-05.html https://www.rieselprime.de/ziki/Modular_square_root NOTE: Fix Curve448 has wrong order value https://github.com/Mbed-TLS/mbedtls/pull/5811
parent
a430d70c0d
commit
087daeacee
|
@ -15,6 +15,10 @@ target_include_directories(mbed-mbedtls
|
|||
target_sources(mbed-mbedtls
|
||||
INTERFACE
|
||||
aes/aes_alt.c
|
||||
ecp/crypto_ecc_hw.c
|
||||
ecp/ecp_alt.c
|
||||
ecp/ecp_curves_alt.c
|
||||
ecp/ecp_helper.c
|
||||
ecp/ecp_internal_alt.c
|
||||
rsa/crypto_rsa_hw.c
|
||||
rsa/rsa_alt.c
|
||||
|
|
|
@ -0,0 +1,668 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mbedtls/common.h"
|
||||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
#if defined(MBEDTLS_ECP_ALT) || defined(MBEDTLS_ECP_INTERNAL_ALT)
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "mbed_assert.h"
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "nu_bitutil.h"
|
||||
#include "nu_timer.h"
|
||||
#include "crypto-misc.h"
|
||||
#include "crypto_ecc_hw.h"
|
||||
#include "ecp_helper.h"
|
||||
|
||||
/* Enable ECC debug */
|
||||
//#define NU_CRYPTO_ECC_ENABLE_DEBUG
|
||||
|
||||
/* Max key size supported */
|
||||
#define NU_ECC_MAXKEYBITS 571
|
||||
/* Max ECC big-number words */
|
||||
#define NU_ECC_BIGNUM_MAXWORD 18
|
||||
/* words in limb */
|
||||
#define wiL (sizeof (mbedtls_mpi_uint) / sizeof (uint32_t))
|
||||
/* Min MPI limbs for ECC big-number */
|
||||
#define NU_ECC_BIGNUM_MINLIMB (NU_ECC_BIGNUM_MAXWORD / wiL)
|
||||
|
||||
/*
|
||||
* Convert between words and number of limbs
|
||||
* Divide first in order to avoid potential overflows
|
||||
*/
|
||||
#define WORDS_TO_LIMBS(i) ( (i) / wiL + ( (i) % wiL != 0 ) )
|
||||
|
||||
/* Notes for Crypto ECC H/W port
|
||||
*
|
||||
* The following point operations are not supported and will cause engine to trap:
|
||||
* 1. P + P. Workaround by 2*P.
|
||||
* 2. m*P with SCAP enabled, esp m = 2 or close to (order - 1). Cannot work around by
|
||||
* fallback to S/W, because following operations are easily to fail with data error.
|
||||
* Disable SCAP temporarily.
|
||||
*/
|
||||
|
||||
int crypto_ecc_capable(const mbedtls_ecp_group *grp)
|
||||
{
|
||||
/* Curve types
|
||||
*
|
||||
* - Short Weierstrass
|
||||
* - Montgomery
|
||||
*/
|
||||
mbedtls_ecp_curve_type curve_type = mbedtls_ecp_get_type(grp);
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
|
||||
return 1;
|
||||
} else if (curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
if (grp->id == MBEDTLS_ECP_DP_CURVE25519 ||
|
||||
grp->id == MBEDTLS_ECP_DP_CURVE448) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int crypto_ecc_init(const mbedtls_ecp_group *grp)
|
||||
{
|
||||
/* Behavior of mbedtls_internal_ecp_init()/mbedtls_internal_ecp_free()
|
||||
*
|
||||
* mbedtls_internal_ecp_init()/mbedtls_internal_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.
|
||||
*/
|
||||
|
||||
/* Acquire ownership of ECC accelerator */
|
||||
crypto_ecc_acquire();
|
||||
|
||||
/* Initialize crypto module */
|
||||
crypto_init();
|
||||
|
||||
/* Release ownership of ECC accelerator */
|
||||
crypto_ecc_release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypto_ecc_free(const mbedtls_ecp_group *grp)
|
||||
{
|
||||
/* Acquire ownership of ECC accelerator */
|
||||
crypto_ecc_acquire();
|
||||
|
||||
/* Uninit crypto module */
|
||||
crypto_uninit();
|
||||
|
||||
/* Release ownership of ECC accelerator */
|
||||
crypto_ecc_release();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* SCAP is applicable only for PM. */
|
||||
blinding = false;
|
||||
|
||||
return crypto_ecc_run_eccop(grp, R, NULL, P, NULL, Q, ECCOP_POINT_ADD, blinding);
|
||||
}
|
||||
|
||||
int crypto_ecc_run_eccop_double(const mbedtls_ecp_group *grp,
|
||||
mbedtls_ecp_point *R,
|
||||
const mbedtls_ecp_point *P,
|
||||
bool blinding)
|
||||
{
|
||||
/* SCAP is applicable only for PM. */
|
||||
blinding = false;
|
||||
|
||||
return crypto_ecc_run_eccop(grp, R, NULL, P, NULL, NULL, ECCOP_POINT_DOUBLE, 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)
|
||||
{
|
||||
/* NOTE: Engine can trap when SCAP is enabled. See above. */
|
||||
blinding = false;
|
||||
return crypto_ecc_run_eccop(grp, R, m, P, NULL, NULL, ECCOP_POINT_MUL, blinding);
|
||||
}
|
||||
|
||||
int crypto_ecc_run_eccop(const mbedtls_ecp_group *grp,
|
||||
mbedtls_ecp_point *R,
|
||||
const mbedtls_mpi *m,
|
||||
const mbedtls_ecp_point *P,
|
||||
MBED_UNUSED const mbedtls_mpi *n,
|
||||
const mbedtls_ecp_point *Q,
|
||||
uint32_t eccop,
|
||||
bool blinding)
|
||||
{
|
||||
/* Check necessary arguments for all ECC operations */
|
||||
if (grp == NULL || R == NULL) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check grp->P is positive */
|
||||
if (mbedtls_mpi_cmp_int(&grp->P, 0) <= 0) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check supported maximum key bits */
|
||||
if (grp->pbits > NU_ECC_MAXKEYBITS) {
|
||||
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* NOTE: Engine doesn't support P + Q when P and Q are the same. Workaround by 2*P */
|
||||
if (mbedtls_ecp_point_cmp(P, Q) == 0) {
|
||||
return crypto_ecc_run_eccop(grp, R, NULL, P, NULL, NULL, ECCOP_POINT_DOUBLE, blinding);
|
||||
}
|
||||
|
||||
/* Acquire ownership of ECC accelerator */
|
||||
crypto_ecc_acquire();
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
bool ecc_done;
|
||||
|
||||
mbedtls_mpi N_;
|
||||
const mbedtls_mpi *Np;
|
||||
|
||||
mbedtls_mpi_init(&N_);
|
||||
|
||||
/* Use ECP_HELPER_MPI_NORM(Np, N1, N_, P) to get normalized MPI
|
||||
*
|
||||
* N_: Holds normalized MPI if the passed-in MPI N1 is not
|
||||
* Np: Pointer to normalized MPI, which could be N1 or N_
|
||||
*/
|
||||
|
||||
/* Check necessary arguments and handle special cases for specified ECC operation
|
||||
*
|
||||
* ECCOP_POINT_MUL R = m*P
|
||||
* ECCOP_POINT_ADD R = P + Q
|
||||
* ECCOP_POINT_DOUBLE R = 2*P
|
||||
*
|
||||
* ECC accelerator doesn't support R = 0, and we need to detect it.
|
||||
*/
|
||||
if (eccop == ECCOP_POINT_MUL) {
|
||||
/* R = m*P */
|
||||
if (m == NULL || P == NULL) {
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 0*P = 0 or R = P = 0 */
|
||||
if (mbedtls_mpi_cmp_int(m, 0) == 0 || mbedtls_mpi_cmp_int(&P->Z, 0) == 0) {
|
||||
ret = mbedtls_ecp_set_zero(R);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 1*P */
|
||||
if (mbedtls_mpi_cmp_int(m, 1) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
|
||||
/* Unnecessary because passed-in P and Q are required to be normalized */
|
||||
//MBEDTLS_MPI_CHK(internal_ecp_normalize(grp, R));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = m*P = (multiple of order)*G = 0 */
|
||||
/* NOTE: If grp->N (order) is a prime, we could detect R = 0 for all m*P cases
|
||||
* by just checking if m is a multiple of grp->N. Otherwise, sigh. */
|
||||
/* TODO: Find an approach to detecting R = 0 for all m*P cases */
|
||||
ECP_HELPER_MPI_NORM(&Np, *m, N_, grp->N);
|
||||
if (mbedtls_mpi_cmp_int(Np, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
|
||||
goto cleanup;
|
||||
}
|
||||
} else if (eccop == ECCOP_POINT_ADD) {
|
||||
/* R = P + Q */
|
||||
if (P == NULL || Q == NULL) {
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 0 + Q = Q */
|
||||
if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, Q));
|
||||
/* Unnecessary because passed-in P and Q are required to be normalized */
|
||||
//MBEDTLS_MPI_CHK(internal_ecp_normalize(grp, R));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = P + 0 = P */
|
||||
if (mbedtls_mpi_cmp_int(&Q->Z, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
|
||||
/* Unnecessary because passed-in P and Q are required to be normalized */
|
||||
//MBEDTLS_MPI_CHK(internal_ecp_normalize(grp, R));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = P + Q = P + (-P) = 0 */
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_run_modop(&N_, &P->Y, &Q->Y, &grp->P, grp->pbits, MODOP_ADD));
|
||||
if (mbedtls_mpi_cmp_int(&N_, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
|
||||
goto cleanup;
|
||||
}
|
||||
} else if (eccop == ECCOP_POINT_DOUBLE) {
|
||||
/* R = 2*P */
|
||||
if (P == NULL) {
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 2*0 = 0 */
|
||||
if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 2*P = P + P = P + (-P) = 0 */
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_run_modop(&N_, &P->Y, &P->Y, &grp->P, grp->pbits, MODOP_ADD));
|
||||
if (mbedtls_mpi_cmp_int(&N_, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* ECC curve type */
|
||||
mbedtls_ecp_curve_type curve_type = mbedtls_ecp_get_type(grp);
|
||||
uint32_t curve_sel = 0;
|
||||
switch (curve_type) {
|
||||
case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS:
|
||||
curve_sel = 0; // Short Weierstrass
|
||||
break;
|
||||
|
||||
case MBEDTLS_ECP_TYPE_MONTGOMERY:
|
||||
curve_sel = CRPT_ECC_CTL_CSEL_Msk; // Montgomery
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Enable ECC interrupt */
|
||||
ECC_ENABLE_INT(CRPT);
|
||||
|
||||
/* For safe, recover from previous failure if ever */
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_abort(5*1000*1000));
|
||||
|
||||
/* Configure ECC curve coefficient A */
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
/*
|
||||
* In S/W impl, A is used as (A + 2) / 4. Figure out its original value for engine.
|
||||
* https://github.com/ARMmbed/mbed-os/blob/2eb06e76208588afc6cb7580a8dd64c5429a10ce/connectivity/mbedtls/include/mbedtls/ecp.h#L219-L220
|
||||
*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&N_, &grp->A, 4));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&N_, &N_, 2));
|
||||
Np = &N_;
|
||||
} else {
|
||||
/* Special case for A = -3 */
|
||||
if (grp->A.p == NULL) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&N_, -3));
|
||||
ECP_HELPER_MPI_NORM(&Np, N_, N_, grp->P);
|
||||
} else {
|
||||
ECP_HELPER_MPI_NORM(&Np, grp->A, N_, grp->P);
|
||||
}
|
||||
}
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_A, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure ECC curve coefficient B */
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
/*
|
||||
* In S/W impl, B is unused. Actually, B is 1 for Curve25519/Curve448.
|
||||
* https://github.com/ARMmbed/mbed-os/blob/2eb06e76208588afc6cb7580a8dd64c5429a10ce/connectivity/mbedtls/include/mbedtls/ecp.h#L221-L222
|
||||
*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&N_, 1));
|
||||
Np = &N_;
|
||||
} else {
|
||||
ECP_HELPER_MPI_NORM(&Np, grp->B, N_, grp->P);
|
||||
}
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_B, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure ECC prime modulus */
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(&grp->P, (uint32_t *) CRPT->ECC_N, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure ECC scalar for point multiplication
|
||||
*
|
||||
* Normalize m to within [1, order - 1] which ECCOP_POINT_MUL supports
|
||||
* Special cases R = 0 should have been detected out above.
|
||||
*/
|
||||
if (eccop == ECCOP_POINT_MUL) {
|
||||
ECP_HELPER_MPI_NORM(&Np, *m, N_, grp->N);
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_K, NU_ECC_BIGNUM_MAXWORD));
|
||||
/* To enable SCAP, must write order of G into X2 */
|
||||
if (blinding) {
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(&grp->N, (uint32_t *) CRPT->ECC_X2, NU_ECC_BIGNUM_MAXWORD));
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure ECC point (X1, Y1) */
|
||||
ECP_HELPER_MPI_NORM(&Np, P->X, N_, grp->P);
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
/* Deduce Y from X for Montgomery curve
|
||||
*
|
||||
* For Montgomery curve, y-coord is absent. Deduce it from x-coord.
|
||||
* https://github.com/ARMmbed/mbed-os/blob/2eb06e76208588afc6cb7580a8dd64c5429a10ce/connectivity/mbedtls/source/ecp_curves.c#L702-L706
|
||||
* https://github.com/ARMmbed/mbed-os/blob/2eb06e76208588afc6cb7580a8dd64c5429a10ce/connectivity/mbedtls/source/ecp_curves.c#L741-L745
|
||||
*
|
||||
* Per real test, y-coord is necessary for engine.
|
||||
*/
|
||||
MBEDTLS_MPI_CHK(ecp_helper_deduce_y(grp, &N_, &P->X));
|
||||
Np = &N_;
|
||||
} else {
|
||||
ECP_HELPER_MPI_NORM(&Np, P->Y, N_, grp->P);
|
||||
}
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_Y1, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure ECC points (X2, Y2) */
|
||||
if (eccop == ECCOP_POINT_ADD) {
|
||||
ECP_HELPER_MPI_NORM(&Np, Q->X, N_, grp->P);
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_X2, NU_ECC_BIGNUM_MAXWORD));
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
/* Deduce Y from X (see above) */
|
||||
MBEDTLS_MPI_CHK(ecp_helper_deduce_y(grp, &N_, &Q->X));
|
||||
Np = &N_;
|
||||
} else {
|
||||
ECP_HELPER_MPI_NORM(&Np, Q->Y, N_, grp->P);
|
||||
}
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_Y2, NU_ECC_BIGNUM_MAXWORD));
|
||||
}
|
||||
|
||||
/* Configure for point operation */
|
||||
uint32_t ecc_ctl = 0 |
|
||||
CRPT_ECC_CTL_START_Msk | // Start
|
||||
CRPT_ECC_CTL_FSEL_Msk | // Prime field (GF(p))
|
||||
eccop | // Point operation
|
||||
curve_sel | // Curve selection
|
||||
(grp->pbits << CRPT_ECC_CTL_CURVEM_Pos) | // Key length of elliptic curve
|
||||
(blinding ? CRPT_ECC_CTL_SCAP_Msk : 0) | // SCAP
|
||||
0;
|
||||
|
||||
crypto_ecc_prestart();
|
||||
#if defined(NU_CRYPTO_ECC_ENABLE_DEBUG) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
|
||||
mbedtls_printf("[CRPT][ECC] Crypto ECC ...\n");
|
||||
#endif
|
||||
CRPT->ECC_CTL = ecc_ctl;
|
||||
ecc_done = crypto_ecc_wait2(1000*1000); // 1s timeout
|
||||
#if defined(NU_CRYPTO_ECC_ENABLE_DEBUG) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
|
||||
mbedtls_printf("[CRPT][ECC] Crypto ECC ... %s\n", ecc_done ? "Done" : "Error");
|
||||
#endif
|
||||
|
||||
/* For safe, recover from current failure */
|
||||
if (!ecc_done) {
|
||||
crypto_ecc_abort(5*1000*1000);
|
||||
}
|
||||
|
||||
/* Disable ECC interrupt */
|
||||
ECC_DISABLE_INT(CRPT);
|
||||
|
||||
MBEDTLS_MPI_CHK(ecc_done ? 0 : MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED);
|
||||
|
||||
/* (X1, Y1) hold the normalized result. */
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_read_eccreg(&R->X, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_read_eccreg(&R->Y, (uint32_t *) CRPT->ECC_Y1, NU_ECC_BIGNUM_MAXWORD));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->Z, 1));
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_mpi_free(&N_);
|
||||
|
||||
/* Release ownership of ECC accelerator */
|
||||
crypto_ecc_release();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (r == NULL ||
|
||||
o1 == NULL ||
|
||||
o2 == NULL ||
|
||||
p == NULL) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check o1/o2 are not negative */
|
||||
if (mbedtls_mpi_cmp_int(o1, 0) < 0 ||
|
||||
mbedtls_mpi_cmp_int(o2, 0) < 0) {
|
||||
return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
|
||||
}
|
||||
|
||||
/* Check p is positive */
|
||||
if (mbedtls_mpi_cmp_int(p, 0) <= 0) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check supported maximum key bits */
|
||||
if (pbits > NU_ECC_MAXKEYBITS) {
|
||||
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Check MODOP operations are legal */
|
||||
if (modop != MODOP_DIV &&
|
||||
modop != MODOP_MUL &&
|
||||
modop != MODOP_ADD &&
|
||||
modop != MODOP_SUB) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check divisor is not zero in MODOP_DIV operation */
|
||||
if (modop == MODOP_DIV && mbedtls_mpi_cmp_int(o2, 0) == 0) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Acquire ownership of ECC accelerator */
|
||||
crypto_ecc_acquire();
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
bool ecc_done;
|
||||
|
||||
mbedtls_mpi N_;
|
||||
const mbedtls_mpi *Np;
|
||||
|
||||
mbedtls_mpi_init(&N_);
|
||||
|
||||
/* Enable ECC interrupt */
|
||||
ECC_ENABLE_INT(CRPT);
|
||||
|
||||
/* For safe, recover from previous failure if ever */
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_abort(5*1000*1000));
|
||||
|
||||
/* Use ECP_HELPER_MPI_NORM(Np, N1, N_, P) to get normalized MPI
|
||||
*
|
||||
* N_: Holds normalized MPI if the passed-in MPI N1 is not
|
||||
* Np: Pointer to normalized MPI, which could be N1 or N_
|
||||
*/
|
||||
|
||||
if (modop == MODOP_MUL ||
|
||||
modop == MODOP_ADD ||
|
||||
modop == MODOP_SUB) {
|
||||
ECP_HELPER_MPI_NORM(&Np, *o1, N_, *p);
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
ECP_HELPER_MPI_NORM(&Np, *o2, N_, *p);
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_Y1, NU_ECC_BIGNUM_MAXWORD));
|
||||
} else if (modop == MODOP_DIV) {
|
||||
ECP_HELPER_MPI_NORM(&Np, *o2, N_, *p);
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
ECP_HELPER_MPI_NORM(&Np, *o1, N_, *p);
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_Y1, NU_ECC_BIGNUM_MAXWORD));
|
||||
} else {
|
||||
MBEDTLS_MPI_CHK(MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_write_eccreg(p, (uint32_t *) CRPT->ECC_N, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure for modulus operation */
|
||||
uint32_t ecc_ctl = 0 |
|
||||
CRPT_ECC_CTL_START_Msk | // Start
|
||||
CRPT_ECC_CTL_FSEL_Msk | // Prime field (GF(p))
|
||||
ECCOP_MODULE | // No point operation
|
||||
modop | // Modulus operation
|
||||
(pbits << CRPT_ECC_CTL_CURVEM_Pos) | // Key length of elliptic curve
|
||||
0;
|
||||
|
||||
crypto_ecc_prestart();
|
||||
#if defined(NU_CRYPTO_ECC_ENABLE_DEBUG) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
|
||||
mbedtls_printf("[CRPT][ECC] Crypto Modulus ...\n");
|
||||
#endif
|
||||
CRPT->ECC_CTL = ecc_ctl;
|
||||
ecc_done = crypto_ecc_wait2(1000*1000); // 1s timeout
|
||||
#if defined(NU_CRYPTO_ECC_ENABLE_DEBUG) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
|
||||
mbedtls_printf("[CRPT][ECC] Crypto Modulus ... %s\n", ecc_done ? "Done" : "Fallback");
|
||||
#endif
|
||||
|
||||
/* For safe, recover from current failure */
|
||||
if (!ecc_done) {
|
||||
crypto_ecc_abort(5*1000*1000);
|
||||
}
|
||||
|
||||
/* Disable ECC interrupt */
|
||||
ECC_DISABLE_INT(CRPT);
|
||||
|
||||
MBEDTLS_MPI_CHK(ecc_done ? 0 : MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED);
|
||||
|
||||
/* X1 holds the result. */
|
||||
MBEDTLS_MPI_CHK(crypto_ecc_mpi_read_eccreg(r, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_mpi_free(&N_);
|
||||
|
||||
/* Release ownership of ECC accelerator */
|
||||
crypto_ecc_release();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int crypto_ecc_mpi_read_eccreg(mbedtls_mpi *x, const volatile uint32_t *eccreg, size_t eccreg_num)
|
||||
{
|
||||
if (x == NULL) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t i, n;
|
||||
|
||||
for (n = eccreg_num; n > 0; n --) {
|
||||
if (eccreg[n - 1] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(x, 0));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(x, WORDS_TO_LIMBS(n)));
|
||||
|
||||
for (i = 0; i < n; i ++) {
|
||||
x->p[i / wiL] |= ((mbedtls_mpi_uint) eccreg[i]) << ((i % wiL) << 5);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int crypto_ecc_mpi_write_eccreg( const mbedtls_mpi *x, volatile uint32_t *eccreg, size_t eccreg_num )
|
||||
{
|
||||
if (x == NULL) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_cmp_int(x, 0) < 0) {
|
||||
return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
|
||||
}
|
||||
|
||||
size_t i, n;
|
||||
|
||||
/* How many words needed? */
|
||||
n = (mbedtls_mpi_size(x) + sizeof (uint32_t) - 1) / sizeof (uint32_t);
|
||||
|
||||
if (eccreg_num < n) {
|
||||
return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Fill non-zero part */
|
||||
for (i = 0; i < n; i ++) {
|
||||
eccreg[i] = (uint32_t) (x->p[i / wiL] >> ((i % wiL) << 5));
|
||||
}
|
||||
|
||||
/* Zeroize remaining part
|
||||
*
|
||||
* crypto_zeroize32() has excluded optimization doubt, so we can safely set H/W registers to 0 via it.
|
||||
*/
|
||||
crypto_zeroize32((uint32_t *) eccreg + n, eccreg_num - n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypto_ecc_abort(uint32_t timeout_us)
|
||||
{
|
||||
/* Acquire ownership of ECC H/W */
|
||||
crypto_ecc_acquire();
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
CRPT->ECC_CTL = CRPT_ECC_CTL_STOP_Msk;
|
||||
struct nu_countdown_ctx_s cd_ctx;
|
||||
nu_countdown_init(&cd_ctx, timeout_us);
|
||||
while (CRPT->ECC_STS & CRPT_ECC_STS_BUSY_Msk) {
|
||||
if (nu_countdown_expired(&cd_ctx)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
nu_countdown_free(&cd_ctx);
|
||||
if (CRPT->ECC_STS & CRPT_ECC_STS_BUSY_Msk) {
|
||||
#if defined(NU_CRYPTO_ECC_ENABLE_DEBUG) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
|
||||
mbedtls_printf("[CRPT][ECC] Crypto ECC ... Busy\n");
|
||||
#endif
|
||||
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Release ownership of ECC accelerator */
|
||||
crypto_ecc_release();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_ECP_ALT || MBEDTLS_ECP_INTERNAL_ALT */
|
||||
#endif /* MBEDTLS_ECP_C */
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,187 @@
|
|||
/**
|
||||
* \file ecp_alt.h
|
||||
*
|
||||
* \brief This file provides an API for Elliptic Curves over GF(P) (ECP).
|
||||
*
|
||||
* The use of ECP in cryptography and TLS is defined in
|
||||
* <em>Standards for Efficient Cryptography Group (SECG): SEC1
|
||||
* Elliptic Curve Cryptography</em> and
|
||||
* <em>RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites
|
||||
* for Transport Layer Security (TLS)</em>.
|
||||
*
|
||||
* <em>RFC-2409: The Internet Key Exchange (IKE)</em> defines ECP
|
||||
* group types.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* 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 MBEDTLS_ECP_ALT_H
|
||||
#define MBEDTLS_ECP_ALT_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "mbedtls/bignum.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ECP_ALT)
|
||||
|
||||
/* Enable Nuvoton's Crypto ECC H/W */
|
||||
#define NU_CRYPTO_ECC_ENABLE
|
||||
|
||||
/*
|
||||
* default mbed TLS elliptic curve arithmetic implementation
|
||||
*
|
||||
* (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an
|
||||
* alternative implementation for the whole module and it will replace this
|
||||
* one.)
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief The ECP group structure.
|
||||
*
|
||||
* We consider two types of curve equations:
|
||||
* <ul><li>Short Weierstrass: <code>y^2 = x^3 + A x + B mod P</code>
|
||||
* (SEC1 + RFC-4492)</li>
|
||||
* <li>Montgomery: <code>y^2 = x^3 + A x^2 + x mod P</code> (Curve25519,
|
||||
* Curve448)</li></ul>
|
||||
* In both cases, the generator (\p G) for a prime-order subgroup is fixed.
|
||||
*
|
||||
* For Short Weierstrass, this subgroup is the whole curve, and its
|
||||
* cardinality is denoted by \p N. Our code requires that \p N is an
|
||||
* odd prime as mbedtls_ecp_mul() requires an odd number, and
|
||||
* mbedtls_ecdsa_sign() requires that it is prime for blinding purposes.
|
||||
*
|
||||
* For Montgomery curves, we do not store \p A, but <code>(A + 2) / 4</code>,
|
||||
* which is the quantity used in the formulas. Additionally, \p nbits is
|
||||
* not the size of \p N but the required size for private keys.
|
||||
*
|
||||
* If \p modp is NULL, reduction modulo \p P is done using a generic algorithm.
|
||||
* Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the
|
||||
* range of <code>0..2^(2*pbits)-1</code>, and transforms it in-place to an integer
|
||||
* which is congruent mod \p P to the given MPI, and is close enough to \p pbits
|
||||
* in size, so that it may be efficiently brought in the 0..P-1 range by a few
|
||||
* additions or subtractions. Therefore, it is only an approximative modular
|
||||
* reduction. It must return 0 on success and non-zero on failure.
|
||||
*
|
||||
* \note Alternative implementations must keep the group IDs distinct. If
|
||||
* two group structures have the same ID, then they must be
|
||||
* identical.
|
||||
*
|
||||
*/
|
||||
typedef struct mbedtls_ecp_group
|
||||
{
|
||||
mbedtls_ecp_group_id id; /*!< An internal group identifier. */
|
||||
mbedtls_mpi P; /*!< The prime modulus of the base field. */
|
||||
mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For
|
||||
Montgomery curves: <code>(A + 2) / 4</code>. */
|
||||
mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation.
|
||||
For Montgomery curves: unused. */
|
||||
mbedtls_ecp_point G; /*!< The generator of the subgroup used. */
|
||||
mbedtls_mpi N; /*!< The order of \p G. */
|
||||
size_t pbits; /*!< The number of bits in \p P.*/
|
||||
size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P.
|
||||
For Montgomery curves: the number of bits in the
|
||||
private keys. */
|
||||
unsigned int h; /*!< \internal 1 if the constants are static. */
|
||||
int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction
|
||||
mod \p P (see above).*/
|
||||
int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */
|
||||
int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */
|
||||
void *t_data; /*!< Unused. */
|
||||
mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */
|
||||
size_t T_size; /*!< The number of pre-computed points. */
|
||||
|
||||
#if defined(NU_CRYPTO_ECC_ENABLE)
|
||||
int hw_init; /*!< Initialized Crypto ECC H/W or not. */
|
||||
#endif
|
||||
}
|
||||
mbedtls_ecp_group;
|
||||
|
||||
/**
|
||||
* \name SECTION: Module settings
|
||||
*
|
||||
* The configuration options you can set for this module are in this section.
|
||||
* Either change them in config.h, or define them using the compiler command line.
|
||||
* \{
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_ECP_MAX_BITS)
|
||||
/**
|
||||
* The maximum size of the groups, that is, of \c N and \c P.
|
||||
*/
|
||||
#define MBEDTLS_ECP_MAX_BITS 521 /**< The maximum size of groups, in bits. */
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 )
|
||||
#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 )
|
||||
|
||||
#if !defined(MBEDTLS_ECP_WINDOW_SIZE)
|
||||
/*
|
||||
* Maximum "window" size used for point multiplication.
|
||||
* Default: 6.
|
||||
* Minimum value: 2. Maximum value: 7.
|
||||
*
|
||||
* Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
|
||||
* points used for point multiplication. This value is directly tied to EC
|
||||
* peak memory usage, so decreasing it by one should roughly cut memory usage
|
||||
* by two (if large curves are in use).
|
||||
*
|
||||
* Reduction in size may reduce speed, but larger curves are impacted first.
|
||||
* Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1):
|
||||
* w-size: 6 5 4 3 2
|
||||
* 521 145 141 135 120 97
|
||||
* 384 214 209 198 177 146
|
||||
* 256 320 320 303 262 226
|
||||
* 224 475 475 453 398 342
|
||||
* 192 640 640 633 587 476
|
||||
*/
|
||||
#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< The maximum window size used. */
|
||||
#endif /* MBEDTLS_ECP_WINDOW_SIZE */
|
||||
|
||||
#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM)
|
||||
/*
|
||||
* Trade memory for speed on fixed-point multiplication.
|
||||
*
|
||||
* This speeds up repeated multiplication of the generator (that is, the
|
||||
* multiplication in ECDSA signatures, and half of the multiplications in
|
||||
* ECDSA verification and ECDHE) by a factor roughly 3 to 4.
|
||||
*
|
||||
* The cost is increasing EC peak memory usage by a factor roughly 2.
|
||||
*
|
||||
* Change this value to 0 to reduce peak memory usage.
|
||||
*/
|
||||
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */
|
||||
#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */
|
||||
|
||||
/* \} name SECTION: Module settings */
|
||||
|
||||
#endif /* MBEDTLS_ECP_ALT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ecp.h */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/threading.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_ECP_ALT)
|
||||
|
||||
int ecp_helper_deduce_y(const mbedtls_ecp_group *grp,
|
||||
mbedtls_mpi *y,
|
||||
const mbedtls_mpi *x)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
mbedtls_mpi A;
|
||||
mbedtls_mpi B;
|
||||
mbedtls_mpi xx; // x^2
|
||||
mbedtls_mpi yy; // y^2
|
||||
mbedtls_mpi T1; // Scratch
|
||||
mbedtls_mpi T2; // Scratch
|
||||
mbedtls_mpi T3; // Scratch
|
||||
mbedtls_mpi T4; // Scratch
|
||||
|
||||
mbedtls_mpi_init(&A);
|
||||
mbedtls_mpi_init(&B);
|
||||
mbedtls_mpi_init(&xx);
|
||||
mbedtls_mpi_init(&yy);
|
||||
mbedtls_mpi_init(&T1);
|
||||
mbedtls_mpi_init(&T2);
|
||||
mbedtls_mpi_init(&T3);
|
||||
mbedtls_mpi_init(&T4);
|
||||
|
||||
/* ECC curve type */
|
||||
mbedtls_ecp_curve_type curve_type = mbedtls_ecp_get_type(grp);
|
||||
|
||||
/* Resolve A */
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
/*
|
||||
* In S/W impl, A is used as (A + 2) / 4. Figure out its original value for engine.
|
||||
* https://github.com/ARMmbed/mbed-os/blob/2eb06e76208588afc6cb7580a8dd64c5429a10ce/connectivity/mbedtls/include/mbedtls/ecp.h#L219-L220
|
||||
*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&A, &grp->A, 4));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&A, &A, 2));
|
||||
} else {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&A, &grp->A));
|
||||
}
|
||||
|
||||
/* Resolve B */
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
/*
|
||||
* In S/W impl, B is unused. Actually, B is 1 for Curve25519/Curve448.
|
||||
* https://github.com/ARMmbed/mbed-os/blob/2eb06e76208588afc6cb7580a8dd64c5429a10ce/connectivity/mbedtls/include/mbedtls/ecp.h#L221-L222
|
||||
*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&B, 1));
|
||||
} else {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&B, &grp->B));
|
||||
}
|
||||
|
||||
/* y^2 = C(x) (mod P) */
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
/* Montgomery curve: B y^2 = x^3 + A x^2 + x (mod P)
|
||||
* For Curve25519/Curve448, B = 1 */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&yy, x)); // yy = x (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&yy, &yy, &grp->P));
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&xx, x, x)); // xx = x^2 (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&xx, &xx, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T1, &A, &xx)); // T1 = A x^2 (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T1, &T1, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&yy, &T1, &yy)); // yy = A x^2 + x (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&yy, &yy, &grp->P));
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T1, &xx, x)); // T1 = x^3 (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T1, &T1, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&yy, &T1, &yy)); // yy = x^3 + A x^2 + x (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&yy, &yy, &grp->P));
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mbedtls_mpi_uint rmn_4 = 0, rmn_8 = 0;
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&rmn_4, &grp->P, 4));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&rmn_8, &grp->P, 8));
|
||||
|
||||
/* y = sqrt(y^2) (mod P) */
|
||||
if (rmn_8 == 5) {
|
||||
/*
|
||||
* Modulus congruent to 5 modulo 8 (Curve25519), apply the formula below:
|
||||
* https://www.rieselprime.de/ziki/Modular_square_root#Modulus_congruent_to_5_modulo_8
|
||||
*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T1, &grp->P, 5)); // T1 = (P - 5) / 8 (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&T1, NULL, &T1, 8));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T1, &T1, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T2, &yy, 2)); // T2 = 2 y^2 (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T2, &T2, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T3, &T2, &T1, &grp->P, NULL)); // T3 = T2^T1 (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T4, &T2, &T3)); // T4 = T2 T3^2 (mod P)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T4, &T4, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T4, &T4, &T3));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T4, &T4, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(y, &T4, 1)); // y = yy T3 (T4 - 1)
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(y, y, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(y, &T3, y));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(y, y, &grp->P));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(y, &yy, y));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(y, y, &grp->P));
|
||||
} else if (rmn_4 == 3) {
|
||||
/*
|
||||
* Modulus congruent to 3 modulo 4 (Curve448), apply the formula below:
|
||||
* https://www.rieselprime.de/ziki/Modular_square_root#Modulus_congruent_to_3_modulo_4
|
||||
*/
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&T1, &grp->P, 1)); // T1 = (P + 1) / 4
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&T1, NULL, &T1, 4));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(y, &yy, &T1, &grp->P, NULL)); // y = yy^T1 (mod P)
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* y = min(y, P - y) */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&T1, &grp->P, y));
|
||||
if (mbedtls_mpi_cmp_mpi(y, &T1) > 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(y, &T1));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_mpi_free(&T4);
|
||||
mbedtls_mpi_free(&T3);
|
||||
mbedtls_mpi_free(&T2);
|
||||
mbedtls_mpi_free(&T1);
|
||||
mbedtls_mpi_free(&yy);
|
||||
mbedtls_mpi_free(&xx);
|
||||
mbedtls_mpi_free(&B);
|
||||
mbedtls_mpi_free(&A);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_ECP_ALT */
|
||||
|
||||
#endif /* MBEDTLS_ECP_C */
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 ECP_HELPER_H
|
||||
#define ECP_HELPER_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "mbedtls/bignum.h"
|
||||
|
||||
/**
|
||||
* \brief Check if MPI has been normalized
|
||||
*
|
||||
* \param N Input MPI which is to check
|
||||
* \param P Prime modulus
|
||||
*
|
||||
* \return 0 if not normalized,
|
||||
* 1 if normalized
|
||||
*/
|
||||
#define ECP_HELPER_MPI_IS_NORM(N, P) \
|
||||
((mbedtls_mpi_cmp_int(&N, 0) >= 0) && (mbedtls_mpi_cmp_mpi(&N, &P) < 0))
|
||||
|
||||
/**
|
||||
* \brief Normalize MPI if it is not normalized yet
|
||||
*
|
||||
* \param R Holds pointer to normalized MPI (N1 or N2)
|
||||
* \param N1 Input MPI which is to normalize
|
||||
* \param N2 Output MPI which holds normalized N1 if N1 is not normalized yet
|
||||
* \param P Prime modulus
|
||||
*/
|
||||
#define ECP_HELPER_MPI_NORM(R, N1, N2, P) \
|
||||
do { \
|
||||
if (ECP_HELPER_MPI_IS_NORM(N1, P)) { \
|
||||
*R = &N1; \
|
||||
} else { \
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&N2, &N1, &P)); \
|
||||
*R = &N2; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief This function deduces y coordinate from x coordinate
|
||||
* for a ECP point expressed in compact representation.
|
||||
*
|
||||
* \param grp The ECP group to be exported.
|
||||
* This must be initialized and have group parameters
|
||||
* set, for example through mbedtls_ecp_group_load().
|
||||
* \param y Deduced y coordinate which is smaller. The other would be
|
||||
* \p grp->P - \p y. \p y must point to an initialized MPI.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not
|
||||
* designate a Curve25519 or Curve448 curve.
|
||||
* \return Another negative error code on other kinds of failure.
|
||||
*/
|
||||
int ecp_helper_deduce_y(const mbedtls_ecp_group *grp,
|
||||
mbedtls_mpi *y,
|
||||
const mbedtls_mpi *x);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ECP_HELPER_H */
|
|
@ -16,11 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
#include "mbedtls/common.h"
|
||||
|
||||
/* Some internal functions are used for Nuvoton internal self-test.
|
||||
* Remove the static modifier for self-test compile. */
|
||||
|
@ -39,17 +35,6 @@
|
|||
#include <string.h>
|
||||
|
||||
#if !defined(MBEDTLS_ECP_ALT)
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#define mbedtls_calloc calloc
|
||||
#define mbedtls_free free
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
|
||||
|
||||
#include "mbedtls/platform.h"
|
||||
|
@ -60,63 +45,8 @@
|
|||
#include "mbed_toolchain.h"
|
||||
#include "nu_bitutil.h"
|
||||
#include "crypto-misc.h"
|
||||
|
||||
/* Max key size supported */
|
||||
#define NU_ECC_MAXKEYBITS 571
|
||||
/* Max ECC big-number words */
|
||||
#define NU_ECC_BIGNUM_MAXWORD 18
|
||||
/* words in limb */
|
||||
#define wiL (sizeof (mbedtls_mpi_uint) / sizeof (uint32_t))
|
||||
/* Min MPI limbs for ECC big-number */
|
||||
#define NU_ECC_BIGNUM_MINLIMB (NU_ECC_BIGNUM_MAXWORD / wiL)
|
||||
|
||||
/*
|
||||
* Convert between words and number of limbs
|
||||
* Divide first in order to avoid potential overflows
|
||||
*/
|
||||
#define WORDS_TO_LIMBS(i) ( (i) / wiL + ( (i) % wiL != 0 ) )
|
||||
|
||||
|
||||
#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)
|
||||
|
||||
#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)
|
||||
|
||||
/**
|
||||
* \brief Check if MPI has been normalized
|
||||
*
|
||||
* \param N Input MPI which is to check
|
||||
* \param P Prime modulus
|
||||
*
|
||||
* \return 0 if not normalized,
|
||||
* 1 if normalized
|
||||
*/
|
||||
#define INTERNAL_MPI_IS_NORM(N, P) \
|
||||
((mbedtls_mpi_cmp_int(&N, 0) >= 0) && (mbedtls_mpi_cmp_mpi(&N, &P) < 0))
|
||||
|
||||
|
||||
/**
|
||||
* \brief Normalize MPI if it is not normalized yet
|
||||
*
|
||||
* \param R Holds pointer to normalized MPI (N1 or N2)
|
||||
* \param N1 Input MPI which is to normalize
|
||||
* \param N2 Output MPI which holds normalized N1 if N1 is not normalized yet
|
||||
* \param P Prime modulus
|
||||
*/
|
||||
#define INTERNAL_MPI_NORM(R, N1, N2, P) \
|
||||
do { \
|
||||
if (INTERNAL_MPI_IS_NORM(N1, P)) { \
|
||||
*R = &N1; \
|
||||
} else { \
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&N2, &N1, &P)); \
|
||||
*R = &N2; \
|
||||
} \
|
||||
} while(0)
|
||||
#include "crypto_ecc_hw.h"
|
||||
#include "ecp_helper.h"
|
||||
|
||||
/**
|
||||
* \brief Normalize Jacobian coordinates or Montgomery x/z coordinates, dependent on curve type.
|
||||
|
@ -132,99 +62,43 @@ NU_STATIC int internal_ecp_normalize(const mbedtls_ecp_group *grp,
|
|||
mbedtls_ecp_point *pt);
|
||||
|
||||
/**
|
||||
* \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
|
||||
* 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 See \c crypto_ecc_run_eccop.
|
||||
*/
|
||||
NU_STATIC int internal_run_eccop(const mbedtls_ecp_group *grp,
|
||||
mbedtls_ecp_point *R,
|
||||
const mbedtls_mpi *m,
|
||||
const mbedtls_ecp_point *P,
|
||||
MBED_UNUSED const mbedtls_mpi *n,
|
||||
const mbedtls_ecp_point *Q,
|
||||
uint32_t eccop);
|
||||
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);
|
||||
|
||||
/**
|
||||
* \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.
|
||||
* \note See \c crypto_ecc_run_modop.
|
||||
*/
|
||||
NU_STATIC int internal_run_modop(mbedtls_mpi *r,
|
||||
const mbedtls_mpi *o1,
|
||||
const mbedtls_mpi *o2,
|
||||
const mbedtls_mpi *p,
|
||||
uint32_t pbits,
|
||||
uint32_t modop);
|
||||
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.
|
||||
* \note See \c crypto_ecc_mpi_read_eccreg.
|
||||
*/
|
||||
NU_STATIC int internal_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.
|
||||
* \note See \c crypto_ecc_mpi_write_eccreg.
|
||||
*/
|
||||
NU_STATIC int internal_mpi_write_eccreg( const mbedtls_mpi *X, volatile uint32_t *eccreg, size_t eccreg_num );
|
||||
|
||||
unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp )
|
||||
{
|
||||
/* Support types
|
||||
* 1. Short Weierstrass
|
||||
* 2. Montgomery */
|
||||
/* Curve types
|
||||
*
|
||||
* - Short Weierstrass
|
||||
* - Montgomery
|
||||
*/
|
||||
mbedtls_ecp_curve_type curve_type = mbedtls_ecp_get_type(grp);
|
||||
if (curve_type == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ||
|
||||
curve_type == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
||||
|
@ -236,38 +110,12 @@ unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp )
|
|||
|
||||
int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )
|
||||
{
|
||||
/* Behavior of mbedtls_internal_ecp_init()/mbedtls_internal_ecp_free()
|
||||
*
|
||||
* mbedtls_internal_ecp_init()/mbedtls_internal_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.
|
||||
*/
|
||||
|
||||
/* Acquire ownership of ECC accelerator */
|
||||
crypto_ecc_acquire();
|
||||
|
||||
/* Initialize crypto module */
|
||||
crypto_init();
|
||||
|
||||
/* Enable ECC interrupt */
|
||||
ECC_ENABLE_INT(CRPT);
|
||||
|
||||
return 0;
|
||||
return crypto_ecc_init( grp );
|
||||
}
|
||||
|
||||
void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp )
|
||||
{
|
||||
/* Disable ECC interrupt */
|
||||
ECC_DISABLE_INT(CRPT);
|
||||
|
||||
/* Uninit crypto module */
|
||||
crypto_uninit();
|
||||
|
||||
/* Release ownership of ECC accelerator */
|
||||
crypto_ecc_release();
|
||||
crypto_ecc_free( grp );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
|
||||
|
@ -482,7 +330,7 @@ int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp,
|
|||
mbedtls_mpi_init(&Zi);
|
||||
mbedtls_mpi_init(&ZZi);
|
||||
|
||||
/* Use INTERNAL_MPI_NORM(Np, N1, N_, P) to get normalized MPI
|
||||
/* Use ECP_HELPER_MPI_NORM(Np, N1, N_, P) to get normalized MPI
|
||||
*
|
||||
* N_: Holds normalized MPI if the passed-in MPI N1 is not
|
||||
* Np: Pointer to normalized MPI, which could be N1 or N_
|
||||
|
@ -490,18 +338,18 @@ int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp,
|
|||
|
||||
/* Zi = 1 / Z */
|
||||
mbedtls_mpi_lset(&Zi, 1);
|
||||
INTERNAL_MPI_NORM(&Np, pt->Z, N, grp->P);
|
||||
ECP_HELPER_MPI_NORM(&Np, pt->Z, N, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&Zi, &Zi, Np, &grp->P, grp->pbits, MODOP_DIV));
|
||||
|
||||
/* ZZi = 1 / Z^2 = Zi * Zi */
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&ZZi, &Zi, &Zi, &grp->P, grp->pbits, MODOP_MUL));
|
||||
|
||||
/* X = X / Z^2 = X * ZZi */
|
||||
INTERNAL_MPI_NORM(&Np, pt->X, N, grp->P);
|
||||
ECP_HELPER_MPI_NORM(&Np, pt->X, N, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&pt->X, Np, &ZZi, &grp->P, grp->pbits, MODOP_MUL));
|
||||
|
||||
/* Y = Y / Z^3 = Y * ZZi * Zi */
|
||||
INTERNAL_MPI_NORM(&Np, pt->Y, N, grp->P);
|
||||
ECP_HELPER_MPI_NORM(&Np, pt->Y, N, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&pt->Y, Np, &ZZi, &grp->P, grp->pbits, MODOP_MUL));
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&pt->Y, &pt->Y, &Zi, &grp->P, grp->pbits, MODOP_MUL));
|
||||
|
||||
|
@ -699,7 +547,7 @@ int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp,
|
|||
mbedtls_mpi_init(&N);
|
||||
mbedtls_mpi_init(&Zi);
|
||||
|
||||
/* Use INTERNAL_MPI_NORM(Np, N1, N_, P) to get normalized MPI
|
||||
/* Use ECP_HELPER_MPI_NORM(Np, N1, N_, P) to get normalized MPI
|
||||
*
|
||||
* N_: Holds normalized MPI if the passed-in MPI N1 is not
|
||||
* Np: Pointer to normalized MPI, which could be N1 or N_
|
||||
|
@ -707,11 +555,11 @@ int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp,
|
|||
|
||||
/* Zi = 1 / Z */
|
||||
mbedtls_mpi_lset(&Zi, 1);
|
||||
INTERNAL_MPI_NORM(&Np, pt->Z, N, grp->P);
|
||||
ECP_HELPER_MPI_NORM(&Np, pt->Z, N, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&Zi, &Zi, Np, &grp->P, grp->pbits, MODOP_DIV));
|
||||
|
||||
/* X = X / Z = X * Zi */
|
||||
INTERNAL_MPI_NORM(&Np, pt->X, N, grp->P);
|
||||
ECP_HELPER_MPI_NORM(&Np, pt->X, N, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&pt->X, Np, &Zi, &grp->P, grp->pbits, MODOP_MUL));
|
||||
|
||||
/* Z = 1 */
|
||||
|
@ -745,208 +593,11 @@ NU_STATIC int internal_run_eccop(const mbedtls_ecp_group *grp,
|
|||
mbedtls_ecp_point *R,
|
||||
const mbedtls_mpi *m,
|
||||
const mbedtls_ecp_point *P,
|
||||
MBED_UNUSED const mbedtls_mpi *n,
|
||||
const mbedtls_mpi *n,
|
||||
const mbedtls_ecp_point *Q,
|
||||
uint32_t eccop)
|
||||
{
|
||||
/* Check necessary arguments for all ECC operations */
|
||||
if (grp == NULL || R == NULL) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check grp->P is positive */
|
||||
if (mbedtls_mpi_cmp_int(&grp->P, 0) <= 0) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check supported maximum key bits */
|
||||
if (grp->pbits > NU_ECC_MAXKEYBITS) {
|
||||
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
bool ecc_done;
|
||||
|
||||
mbedtls_mpi N_;
|
||||
const mbedtls_mpi *Np;
|
||||
|
||||
mbedtls_mpi_init(&N_);
|
||||
|
||||
/* Use INTERNAL_MPI_NORM(Np, N1, N_, P) to get normalized MPI
|
||||
*
|
||||
* N_: Holds normalized MPI if the passed-in MPI N1 is not
|
||||
* Np: Pointer to normalized MPI, which could be N1 or N_
|
||||
*/
|
||||
|
||||
/* Check necessary arguments and handle special cases for specified ECC operation
|
||||
*
|
||||
* ECCOP_POINT_MUL R = m*P
|
||||
* ECCOP_POINT_ADD R = P + Q
|
||||
* ECCOP_POINT_DOUBLE R = 2*P
|
||||
*
|
||||
* ECC accelerator doesn't support R = 0, and we need to detect it.
|
||||
*/
|
||||
if (eccop == ECCOP_POINT_MUL) {
|
||||
/* R = m*P */
|
||||
if (m == NULL || P == NULL) {
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 0*P = 0 or R = P = 0 */
|
||||
if (mbedtls_mpi_cmp_int(m, 0) == 0 || mbedtls_mpi_cmp_int(&P->Z, 0) == 0) {
|
||||
ret = mbedtls_ecp_set_zero(R);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 1*P */
|
||||
if (mbedtls_mpi_cmp_int(m, 1) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
|
||||
MBEDTLS_MPI_CHK(internal_ecp_normalize(grp, R));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = m*P = (multiple of order)*G = 0 */
|
||||
/* NOTE: If grp->N (order) is a prime, we could detect R = 0 for all m*P cases
|
||||
* by just checking if m is a multiple of grp->N. Otherwise, sigh. */
|
||||
/* TODO: Find an approach to detecting R = 0 for all m*P cases */
|
||||
INTERNAL_MPI_NORM(&Np, *m, N_, grp->N);
|
||||
if (mbedtls_mpi_cmp_int(Np, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
|
||||
goto cleanup;
|
||||
}
|
||||
} else if (eccop == ECCOP_POINT_ADD) {
|
||||
/* R = P + Q */
|
||||
if (P == NULL || Q == NULL) {
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 0 + Q = Q */
|
||||
if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, Q));
|
||||
MBEDTLS_MPI_CHK(internal_ecp_normalize(grp, R));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = P + 0 = P */
|
||||
if (mbedtls_mpi_cmp_int(&Q->Z, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
|
||||
MBEDTLS_MPI_CHK(internal_ecp_normalize(grp, R));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = P + Q = P + (-P) = 0 */
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&N_, &P->Y, &Q->Y, &grp->P, grp->pbits, MODOP_ADD));
|
||||
if (mbedtls_mpi_cmp_int(&N_, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
|
||||
goto cleanup;
|
||||
}
|
||||
} else if (eccop == ECCOP_POINT_DOUBLE) {
|
||||
/* R = 2*P */
|
||||
if (P == NULL) {
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 2*0 = 0 */
|
||||
if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* R = 2*P = P + P = P + (-P) = 0 */
|
||||
MBEDTLS_MPI_CHK(internal_run_modop(&N_, &P->Y, &P->Y, &grp->P, grp->pbits, MODOP_ADD));
|
||||
if (mbedtls_mpi_cmp_int(&N_, 0) == 0) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Configure ECC curve coefficients A/B */
|
||||
/* Special case for A = -3 */
|
||||
if (grp->A.p == NULL) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&N_, -3));
|
||||
INTERNAL_MPI_NORM(&Np, N_, N_, grp->P);
|
||||
} else {
|
||||
INTERNAL_MPI_NORM(&Np, grp->A, N_, grp->P);
|
||||
}
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_A, NU_ECC_BIGNUM_MAXWORD));
|
||||
INTERNAL_MPI_NORM(&Np, grp->B, N_, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_B, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure ECC prime modulus */
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(&grp->P, (uint32_t *) CRPT->ECC_N, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure ECC scalar for point multiplication
|
||||
*
|
||||
* Normalize m to within [1, order - 1] which ECCOP_POINT_MUL supports
|
||||
* Special cases R = 0 should have been detected out above.
|
||||
*/
|
||||
if (eccop == ECCOP_POINT_MUL) {
|
||||
INTERNAL_MPI_NORM(&Np, *m, N_, grp->N);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_K, NU_ECC_BIGNUM_MAXWORD));
|
||||
}
|
||||
|
||||
/* Configure ECC point (X1, Y1) */
|
||||
INTERNAL_MPI_NORM(&Np, P->X, N_, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
INTERNAL_MPI_NORM(&Np, P->Y, N_, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_Y1, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure ECC points (X2, Y2) */
|
||||
if (eccop == ECCOP_POINT_ADD) {
|
||||
INTERNAL_MPI_NORM(&Np, Q->X, N_, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_X2, NU_ECC_BIGNUM_MAXWORD));
|
||||
INTERNAL_MPI_NORM(&Np, Q->Y, N_, grp->P);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_Y2, NU_ECC_BIGNUM_MAXWORD));
|
||||
}
|
||||
|
||||
/* ECC curve type */
|
||||
mbedtls_ecp_curve_type curve_type = mbedtls_ecp_get_type(grp);
|
||||
uint32_t curve_sel = 0;
|
||||
switch (curve_type) {
|
||||
case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS:
|
||||
curve_sel = 0; // Short Weierstrass
|
||||
break;
|
||||
|
||||
case MBEDTLS_ECP_TYPE_MONTGOMERY:
|
||||
curve_sel = CRPT_ECC_CTL_CSEL_Msk; // Montgomery
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Configure for point operation */
|
||||
uint32_t ecc_ctl = 0 |
|
||||
CRPT_ECC_CTL_START_Msk | // Start
|
||||
CRPT_ECC_CTL_FSEL_Msk | // Prime field (GF(p))
|
||||
eccop | // Point operation
|
||||
curve_sel | // Curve selection
|
||||
(grp->pbits << CRPT_ECC_CTL_CURVEM_Pos) | // Key length of elliptic curve
|
||||
0;
|
||||
|
||||
crypto_ecc_prestart();
|
||||
CRPT->ECC_CTL = ecc_ctl;
|
||||
ecc_done = crypto_ecc_wait();
|
||||
|
||||
MBEDTLS_MPI_CHK(ecc_done ? 0 : MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED);
|
||||
|
||||
/* (X1, Y1) hold the normalized result. */
|
||||
MBEDTLS_MPI_CHK(internal_mpi_read_eccreg(&R->X, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
MBEDTLS_MPI_CHK(internal_mpi_read_eccreg(&R->Y, (uint32_t *) CRPT->ECC_Y1, NU_ECC_BIGNUM_MAXWORD));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->Z, 1));
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_mpi_free(&N_);
|
||||
|
||||
return ret;
|
||||
return crypto_ecc_run_eccop( grp, R, m, P, n, Q, eccop, false );
|
||||
}
|
||||
|
||||
NU_STATIC int internal_run_modop(mbedtls_mpi *r,
|
||||
|
@ -956,157 +607,17 @@ NU_STATIC int internal_run_modop(mbedtls_mpi *r,
|
|||
uint32_t pbits,
|
||||
uint32_t modop)
|
||||
{
|
||||
if (r == NULL ||
|
||||
o1 == NULL ||
|
||||
o2 == NULL ||
|
||||
p == NULL) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check o1/o2 are not negative */
|
||||
if (mbedtls_mpi_cmp_int(o1, 0) < 0 ||
|
||||
mbedtls_mpi_cmp_int(o2, 0) < 0) {
|
||||
return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
|
||||
}
|
||||
|
||||
/* Check p is positive */
|
||||
if (mbedtls_mpi_cmp_int(p, 0) <= 0) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check supported maximum key bits */
|
||||
if (pbits > NU_ECC_MAXKEYBITS) {
|
||||
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Check MODOP operations are legal */
|
||||
if (modop != MODOP_DIV &&
|
||||
modop != MODOP_MUL &&
|
||||
modop != MODOP_ADD &&
|
||||
modop != MODOP_SUB) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
/* Check divisor is not zero in MODOP_DIV operation */
|
||||
if (modop == MODOP_DIV && mbedtls_mpi_cmp_int(o2, 0) == 0) {
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
bool ecc_done;
|
||||
|
||||
mbedtls_mpi N_;
|
||||
const mbedtls_mpi *Np;
|
||||
|
||||
mbedtls_mpi_init(&N_);
|
||||
|
||||
/* Use INTERNAL_MPI_NORM(Np, N1, N_, P) to get normalized MPI
|
||||
*
|
||||
* N_: Holds normalized MPI if the passed-in MPI N1 is not
|
||||
* Np: Pointer to normalized MPI, which could be N1 or N_
|
||||
*/
|
||||
|
||||
if (modop == MODOP_MUL ||
|
||||
modop == MODOP_ADD ||
|
||||
modop == MODOP_SUB) {
|
||||
INTERNAL_MPI_NORM(&Np, *o1, N_, *p);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
INTERNAL_MPI_NORM(&Np, *o2, N_, *p);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_Y1, NU_ECC_BIGNUM_MAXWORD));
|
||||
} else if (modop == MODOP_DIV) {
|
||||
INTERNAL_MPI_NORM(&Np, *o2, N_, *p);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
INTERNAL_MPI_NORM(&Np, *o1, N_, *p);
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(Np, (uint32_t *) CRPT->ECC_Y1, NU_ECC_BIGNUM_MAXWORD));
|
||||
} else {
|
||||
MBEDTLS_MPI_CHK(MBEDTLS_ERR_ECP_BAD_INPUT_DATA);
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK(internal_mpi_write_eccreg(p, (uint32_t *) CRPT->ECC_N, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
/* Configure for modulus operation */
|
||||
uint32_t ecc_ctl = 0 |
|
||||
CRPT_ECC_CTL_START_Msk | // Start
|
||||
CRPT_ECC_CTL_FSEL_Msk | // Prime field (GF(p))
|
||||
ECCOP_MODULE | // No point operation
|
||||
modop | // Modulus operation
|
||||
(pbits << CRPT_ECC_CTL_CURVEM_Pos) | // Key length of elliptic curve
|
||||
0;
|
||||
|
||||
crypto_ecc_prestart();
|
||||
CRPT->ECC_CTL = ecc_ctl;
|
||||
ecc_done = crypto_ecc_wait();
|
||||
|
||||
MBEDTLS_MPI_CHK(ecc_done ? 0 : MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED);
|
||||
|
||||
/* X1 holds the result. */
|
||||
MBEDTLS_MPI_CHK(internal_mpi_read_eccreg(r, (uint32_t *) CRPT->ECC_X1, NU_ECC_BIGNUM_MAXWORD));
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_mpi_free(&N_);
|
||||
|
||||
return ret;
|
||||
return crypto_ecc_run_modop( r, o1, o2, p, pbits, modop );
|
||||
}
|
||||
|
||||
NU_STATIC int internal_mpi_read_eccreg(mbedtls_mpi *x, const volatile uint32_t *eccreg, size_t eccreg_num)
|
||||
{
|
||||
if (x == NULL) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t i, n;
|
||||
|
||||
for (n = eccreg_num; n > 0; n --) {
|
||||
if (eccreg[n - 1] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(x, 0));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(x, WORDS_TO_LIMBS(n)));
|
||||
|
||||
for (i = 0; i < n; i ++) {
|
||||
x->p[i / wiL] |= ((mbedtls_mpi_uint) eccreg[i]) << ((i % wiL) << 5);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
return ret;
|
||||
return crypto_ecc_mpi_read_eccreg( x, eccreg, eccreg_num);
|
||||
}
|
||||
|
||||
NU_STATIC int internal_mpi_write_eccreg( const mbedtls_mpi *x, volatile uint32_t *eccreg, size_t eccreg_num )
|
||||
{
|
||||
if (x == NULL) {
|
||||
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (mbedtls_mpi_cmp_int(x, 0) < 0) {
|
||||
return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
|
||||
}
|
||||
|
||||
size_t i, n;
|
||||
|
||||
/* How many words needed? */
|
||||
n = (mbedtls_mpi_size(x) + sizeof (uint32_t) - 1) / sizeof (uint32_t);
|
||||
|
||||
if (eccreg_num < n) {
|
||||
return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* Fill non-zero part */
|
||||
for (i = 0; i < n; i ++) {
|
||||
eccreg[i] = (uint32_t) (x->p[i / wiL] >> ((i % wiL) << 5));
|
||||
}
|
||||
|
||||
/* Zeroize remaining part
|
||||
*
|
||||
* crypto_zeroize32() has excluded optimization doubt, so we can safely set H/W registers to 0 via it.
|
||||
*/
|
||||
crypto_zeroize32((uint32_t *) eccreg + n, eccreg_num - n);
|
||||
|
||||
return 0;
|
||||
return crypto_ecc_mpi_write_eccreg( x, eccreg, eccreg_num );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
|
||||
|
|
|
@ -27,18 +27,26 @@
|
|||
#define MBEDTLS_GCM_ALT
|
||||
#define MBEDTLS_CCM_ALT
|
||||
|
||||
#define MBEDTLS_ECP_ALT
|
||||
|
||||
#if !defined(MBEDTLS_ECP_ALT)
|
||||
|
||||
#define MBEDTLS_ECP_INTERNAL_ALT
|
||||
|
||||
/* Support for Weierstrass curves with Jacobi representation */
|
||||
#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
|
||||
#define MBEDTLS_ECP_ADD_MIXED_ALT
|
||||
#define MBEDTLS_ECP_DOUBLE_JAC_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
|
||||
|
||||
/* Support for curves with Montgomery arithmetic */
|
||||
//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT
|
||||
#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT
|
||||
|
||||
#endif /* !MBEDTLS_ECP_ALT */
|
||||
|
||||
#define MBEDTLS_RSA_ALT
|
||||
|
||||
#endif /* MBEDTLS_DEVICE_H */
|
||||
|
|
Loading…
Reference in New Issue