mirror of https://github.com/ARMmbed/mbed-os.git
1726 lines
52 KiB
C
1726 lines
52 KiB
C
/*
|
|
* Elliptic curves over GF(p): CRYPTO hw acceleration functions
|
|
*
|
|
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
|
* 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.
|
|
*/
|
|
/*
|
|
* This file includes alternative plugin implementations of various
|
|
* functions in ecp.c using the CRYPTO hardware accelerator incorporated
|
|
* in MCU devices from Silicon Laboratories.
|
|
*/
|
|
/*
|
|
* References:
|
|
*
|
|
* SEC1 http://www.secg.org/index.php?action=secg,docs_secg
|
|
* GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
|
|
* FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
|
|
* RFC 4492 for the related TLS structures and constants
|
|
*
|
|
* [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
|
|
*
|
|
* [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
|
|
* for elliptic curve cryptosystems. In : Cryptographic Hardware and
|
|
* Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
|
|
* <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
|
|
*
|
|
* [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
|
|
* render ECC resistant against Side Channel Attacks. IACR Cryptology
|
|
* ePrint Archive, 2004, vol. 2004, p. 342.
|
|
* <http://eprint.iacr.org/2004/342.pdf>
|
|
*/
|
|
|
|
#if !defined(MBEDTLS_CONFIG_FILE)
|
|
#include "mbedtls/config.h"
|
|
#else
|
|
#include MBEDTLS_CONFIG_FILE
|
|
#endif
|
|
|
|
#include "em_device.h"
|
|
|
|
#if defined( CRYPTO_PRESENT )
|
|
|
|
#if defined( MBEDTLS_ECP_C )
|
|
#if defined( MBEDTLS_ECP_INTERNAL_ALT )
|
|
|
|
#include "mbedtls/ecp.h"
|
|
#include "mbedtls/ecp_internal.h"
|
|
#include "mbedtls/platform.h"
|
|
#include "em_crypto.h"
|
|
#include "em_core.h"
|
|
#include "crypto_management.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
/** ECC big integer type. */
|
|
#define ECC_BIGINT_SIZE_IN_BITS (256)
|
|
#define ECC_BIGINT_SIZE_IN_BYTES (ECC_BIGINT_SIZE_IN_BITS/8)
|
|
#define ECC_BIGINT_SIZE_IN_32BIT_WORDS (ECC_BIGINT_SIZE_IN_BYTES/sizeof(uint32_t))
|
|
#define EC_BIGINT_COPY(X, Y) memcpy((X), (Y), sizeof(ecc_bigint_t));
|
|
typedef uint32_t ecc_bigint_t[ECC_BIGINT_SIZE_IN_32BIT_WORDS];
|
|
|
|
#define SLCL_ECP_CHK(f) do { if( ( ret = (f) ) != 0 ) goto cleanup; } while( 0 )
|
|
|
|
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) || defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
|
|
#define MPI_TO_BIGINT(bigint, mpi) mpitobigint((bigint), (mpi));
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Convert an mpi number representation to a 32bit word array used by crypto.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void mpitobigint( ecc_bigint_t bigint, const mbedtls_mpi* mpi )
|
|
{
|
|
uint32_t* bi = bigint;
|
|
|
|
if ( mpi->n < ECC_BIGINT_SIZE_IN_32BIT_WORDS )
|
|
{
|
|
memcpy(bigint, mpi->p, mpi->n * sizeof(uint32_t));
|
|
memset(&bi[mpi->n],
|
|
0,
|
|
ECC_BIGINT_SIZE_IN_BYTES - ( mpi->n * sizeof(uint32_t) ) );
|
|
}
|
|
else
|
|
{
|
|
/* mpi has more room than bigint, so only store up to sizeof(bigint) */
|
|
memcpy(bigint, mpi->p, ECC_BIGINT_SIZE_IN_BYTES);
|
|
}
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Returns true if the value of the DDATA0 register is equal to zero.
|
|
******************************************************************************/
|
|
__STATIC_INLINE bool crypto_ddata0_is_zero(CRYPTO_TypeDef* crypto,
|
|
uint32_t* status_reg)
|
|
{
|
|
CORE_DECLARE_IRQ_STATE;
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_EXECUTE_3(crypto,
|
|
CRYPTO_CMD_INSTR_CCLR,
|
|
CRYPTO_CMD_INSTR_DEC, /* Decrement by one which will set
|
|
carry bit if DDATA0 is zero. */
|
|
CRYPTO_CMD_INSTR_INC /* Increment in order to restore
|
|
original value. */
|
|
);
|
|
|
|
*status_reg = crypto->DSTATUS;
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
return (*status_reg & CRYPTO_DSTATUS_CARRY) == CRYPTO_DSTATUS_CARRY;
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Modular division using CRYPTO hardware acceleration.
|
|
*
|
|
* @details
|
|
* This function computes R = X/Y mod(N) using CRYPTO hardware acceleration.
|
|
* The implementation is not a direct replacement plugin, i.e. alternative
|
|
* implementation, of an existing mbedtls function. This function is used
|
|
* internally in other CRYPTO plugin functions indirectly replacing
|
|
* mbedtls_mpi_inv_mod.
|
|
*
|
|
* @param[in] X Dividend of modular division operation
|
|
* @param[in] Y Divisor of modular division operation
|
|
* @param[in] N Modulus
|
|
* @param[out] R The destination of the result
|
|
*
|
|
* @return N/A
|
|
******************************************************************************/
|
|
static void crypto_mpi_div_mod(CRYPTO_TypeDef *crypto,
|
|
ecc_bigint_t X,
|
|
ecc_bigint_t Y,
|
|
ecc_bigint_t N,
|
|
ecc_bigint_t R)
|
|
{
|
|
uint32_t D[9];
|
|
uint32_t status_reg;
|
|
uint8_t rdata;
|
|
uint8_t lsb_C;
|
|
uint8_t lsb_D;
|
|
uint8_t lsb_U;
|
|
int t;
|
|
int k;
|
|
CORE_DECLARE_IRQ_STATE;
|
|
|
|
/************** Initialize and organize data in crypto module **************/
|
|
|
|
/*
|
|
** Register usage:
|
|
**
|
|
** DDATA0 - holds temporary results and loads 260 bit variables in/out
|
|
** DDATA1 - variable referred to as 'C' in the following algorithm
|
|
** DDATA2 - variable referred to as 'U' in the following algorithm
|
|
** DDATA3 - variable referred to as 'D' in the following algorithm
|
|
** DDATA4 - variable referred to as 'W' in the following algorithm
|
|
*/
|
|
|
|
EC_BIGINT_COPY(D, N); /* D will hold the modulus (n) initially */
|
|
D[8]=0; /* Set MSWord of D to 0. */
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataWrite(&crypto->DDATA1, Y); /* Set C to Y (divisor) initially */
|
|
CRYPTO_DDataWrite(&crypto->DDATA2, X); /* Set U to X (dividend)initially */
|
|
CRYPTO_DDataWrite(&crypto->DDATA3, N); /* Set D to modulus p initially */
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_3(crypto,
|
|
CRYPTO_CMD_INSTR_CLR, /* DDATA0 = 0 */
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA4, /* Set W to zero initially*/
|
|
CRYPTO_CMD_INSTR_DDATA1TODDATA0);/* DDATA0 = C initially */
|
|
|
|
t = 0;
|
|
k = 1;
|
|
|
|
/******************* Run main loop while 'C' is non-zero ********************/
|
|
|
|
/* while (C != 1024'd0) */
|
|
while ( !crypto_ddata0_is_zero(crypto, &status_reg) )
|
|
{
|
|
|
|
lsb_C = (status_reg & _CRYPTO_DSTATUS_DDATA0LSBS_MASK) >> _CRYPTO_DSTATUS_DDATA0LSBS_SHIFT;
|
|
if ((lsb_C & 0x1) == 0)
|
|
{
|
|
CRYPTO_EXECUTE_3(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA1,
|
|
CRYPTO_CMD_INSTR_SHRA,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1
|
|
);
|
|
t = t-1;
|
|
}
|
|
else
|
|
{
|
|
if (t<0)
|
|
{
|
|
CRYPTO_EXECUTE_6(crypto,
|
|
CRYPTO_CMD_INSTR_DDATA2TODDATA0,
|
|
CRYPTO_CMD_INSTR_DDATA4TODDATA2,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA4,
|
|
CRYPTO_CMD_INSTR_DDATA1TODDATA0,
|
|
CRYPTO_CMD_INSTR_DDATA3TODDATA1,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3);
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDATA0_260_BITS_READ(crypto, D);
|
|
CORE_EXIT_CRITICAL();
|
|
t = -t;
|
|
}
|
|
|
|
k = 1;
|
|
|
|
CRYPTO_EXECUTE_2(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_ADD);
|
|
|
|
rdata = CRYPTO_DData0_4LSBitsRead(crypto);
|
|
|
|
if((rdata & 0x3) != 0x0)
|
|
k = -1;
|
|
else
|
|
t = t-1;
|
|
|
|
/* R1 = C >> 1 */
|
|
crypto->CMD = CRYPTO_CMD_INSTR_DDATA1TODDATA0; /* to get the lsb of C */
|
|
|
|
lsb_C = CRYPTO_DData0_4LSBitsRead(crypto);
|
|
CRYPTO_EXECUTE_4(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA1,
|
|
CRYPTO_CMD_INSTR_SHRA,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_DDATA3TODDATA0); /* to get the lsb of D(R3) */
|
|
|
|
/* R3 = D >> 1 */
|
|
lsb_D = CRYPTO_DData0_4LSBitsRead(crypto);
|
|
|
|
CRYPTO_EXECUTE_2(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA3DDATA3,
|
|
CRYPTO_CMD_INSTR_SHRA);
|
|
|
|
if(k == 1)
|
|
{
|
|
if (((lsb_C & 0x1)==0x1) && ((lsb_D & 0x1)==0x1))
|
|
{
|
|
CRYPTO_EXECUTE_7(crypto,
|
|
/* C = R1+R3+1 */
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA1,
|
|
CRYPTO_CMD_INSTR_CSET,
|
|
CRYPTO_CMD_INSTR_ADDC,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
/* U = mod(R2+R4,n) */
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA4,
|
|
CRYPTO_CMD_INSTR_MADD,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2
|
|
);
|
|
}
|
|
else
|
|
{
|
|
CRYPTO_EXECUTE_6(crypto,
|
|
/* C = R1+R3 */
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA1,
|
|
CRYPTO_CMD_INSTR_ADD,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
/* U = mod(R2+R4,n) */
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA4,
|
|
CRYPTO_CMD_INSTR_MADD,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (k == -1)
|
|
{
|
|
if (((lsb_C & 0x1)==0x0) && ((lsb_D & 0x1)==0x1))
|
|
{
|
|
CRYPTO_EXECUTE_8(crypto,
|
|
/* C = R1-R3-1 */
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_CSET,
|
|
CRYPTO_CMD_INSTR_SUBC,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
/* U = mod(R2-R4,p) */
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA4,
|
|
CRYPTO_CMD_INSTR_MSUB,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2
|
|
);
|
|
}
|
|
else
|
|
{
|
|
CRYPTO_EXECUTE_7(crypto,
|
|
/* C = R1+R3 */
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_SUB,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
/* U = mod(R2-R4,p) */
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA4,
|
|
CRYPTO_CMD_INSTR_MSUB,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2
|
|
);
|
|
}
|
|
|
|
CRYPTO_DDATA0_260_BITS_WRITE(crypto, D);
|
|
crypto->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA3;
|
|
|
|
} /* if (k == -1) */
|
|
}
|
|
} /* else: !if((C[31:0] & 0x1) == 0x0) */
|
|
|
|
crypto->CMD = CRYPTO_CMD_INSTR_DDATA2TODDATA0;
|
|
|
|
lsb_U = CRYPTO_DData0_4LSBitsRead(crypto);
|
|
|
|
/* if ((U[31:0] & 0x1) == 0x1) */
|
|
if((lsb_U & 0x1) == 0x1)
|
|
{
|
|
CRYPTO_EXECUTE_3( crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA2,
|
|
CRYPTO_CMD_INSTR_SHRA,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataWrite(&crypto->DDATA0, N);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_6( crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA0,
|
|
CRYPTO_CMD_INSTR_SHR,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA2,
|
|
CRYPTO_CMD_INSTR_CSET,
|
|
CRYPTO_CMD_INSTR_ADDC,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2);
|
|
}
|
|
else
|
|
{
|
|
CRYPTO_EXECUTE_3(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA2,
|
|
CRYPTO_CMD_INSTR_SHRA,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2);
|
|
}
|
|
|
|
/* DDATA0 = C */
|
|
crypto->CMD = CRYPTO_CMD_INSTR_DDATA1TODDATA0;
|
|
|
|
} /* End of main loop: while (C != 0) */
|
|
|
|
/* if (D == 1): */
|
|
/* Decrement D by 1 and test if zero. */
|
|
CRYPTO_EXECUTE_2(crypto,
|
|
CRYPTO_CMD_INSTR_DDATA3TODDATA0,
|
|
CRYPTO_CMD_INSTR_DEC);
|
|
|
|
if (crypto_ddata0_is_zero(crypto, &status_reg))
|
|
{
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataRead(&crypto->DDATA4, R);
|
|
CORE_EXIT_CRITICAL();
|
|
}
|
|
else
|
|
{
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataWrite(&crypto->DDATA0, N);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_2(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA4,
|
|
CRYPTO_CMD_INSTR_SUB
|
|
);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataRead(&crypto->DDATA0, R);
|
|
CORE_EXIT_CRITICAL();
|
|
}
|
|
return;
|
|
} /* crypto_mpi_div_mod */
|
|
#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT || MBEDTLS_ECP_NORMALIZE_JAC_ALT */
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Enable CRYPTO by setting up control registers for given ecc curve.
|
|
******************************************************************************/
|
|
static int crypto_device_init( CRYPTO_TypeDef *device, const mbedtls_ecp_group *grp)
|
|
{
|
|
int ret = 0;
|
|
|
|
/* Setup CRYPTO registers for ECC operation */
|
|
device->CTRL = 0;
|
|
device->SEQCTRL = CRYPTO_SEQCTRL_BLOCKSIZE_32BYTES | 32;
|
|
device->SEQCTRLB = 0;
|
|
|
|
switch( grp->id )
|
|
{
|
|
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
|
|
case MBEDTLS_ECP_DP_SECP192R1:
|
|
CRYPTO_ModulusSet( device, cryptoModulusEccP192 );
|
|
CRYPTO_MulOperandWidthSet( device, cryptoMulOperandModulusBits );
|
|
CRYPTO_ResultWidthSet( device, cryptoResult256Bits );
|
|
break;
|
|
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
|
|
|
|
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
|
|
case MBEDTLS_ECP_DP_SECP224R1:
|
|
CRYPTO_ModulusSet( device, cryptoModulusEccP224 );
|
|
CRYPTO_MulOperandWidthSet( device, cryptoMulOperandModulusBits );
|
|
CRYPTO_ResultWidthSet( device, cryptoResult256Bits );
|
|
break;
|
|
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
|
|
|
|
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
|
|
case MBEDTLS_ECP_DP_SECP256R1:
|
|
CRYPTO_ModulusSet( device, cryptoModulusEccP256 );
|
|
CRYPTO_MulOperandWidthSet( device, cryptoMulOperandModulusBits );
|
|
CRYPTO_ResultWidthSet( device, cryptoResult260Bits );
|
|
break;
|
|
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
|
|
|
|
default:
|
|
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
|
|
break;
|
|
}
|
|
|
|
return( ret );
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Write 256 bits of data to a DDATAX register in the CRYPTO module.
|
|
*
|
|
* @details
|
|
* Write 256 bits of data into a DDATAX (Double Data) register in the crypto
|
|
* module.
|
|
*
|
|
* @param[in] ddataReg Data register identifier
|
|
* @param[in] val Value of the data to write to the DDATA register.
|
|
******************************************************************************/
|
|
__STATIC_INLINE void ecp_crypto_ddata_write(CRYPTO_DDataReg_TypeDef ddataReg,
|
|
const mbedtls_mpi* mpi)
|
|
{
|
|
uint32_t volatile* regPtr = (volatile uint32_t *) ddataReg;
|
|
uint32_t* pVal = mpi->p;
|
|
register uint32_t v0;
|
|
register uint32_t v1;
|
|
register uint32_t v2;
|
|
register uint32_t v3;
|
|
int i;
|
|
|
|
if (mpi->n <4)
|
|
{
|
|
/* Non optimal write of data. */
|
|
for (i=0; i<(int)mpi->n; i++)
|
|
*regPtr = *pVal++;
|
|
for (; i<8; i++)
|
|
*regPtr = 0;
|
|
}
|
|
else
|
|
{
|
|
if (mpi->n < 8)
|
|
{
|
|
/* Optimal write of first 4 words. */
|
|
v0 = *pVal++;
|
|
v1 = *pVal++;
|
|
v2 = *pVal++;
|
|
v3 = *pVal++;
|
|
*regPtr = v0;
|
|
*regPtr = v1;
|
|
*regPtr = v2;
|
|
*regPtr = v3;
|
|
|
|
/* Non optimal write of remaining words */
|
|
for (i=4; i<(int)mpi->n; i++)
|
|
*regPtr = *pVal++;
|
|
for (; i<8; i++)
|
|
*regPtr = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Optimal write of all data. */
|
|
v0 = *pVal++;
|
|
v1 = *pVal++;
|
|
v2 = *pVal++;
|
|
v3 = *pVal++;
|
|
*regPtr = v0;
|
|
*regPtr = v1;
|
|
*regPtr = v2;
|
|
*regPtr = v3;
|
|
|
|
v0 = *pVal++;
|
|
v1 = *pVal++;
|
|
v2 = *pVal++;
|
|
v3 = *pVal++;
|
|
*regPtr = v0;
|
|
*regPtr = v1;
|
|
*regPtr = v2;
|
|
*regPtr = v3;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief
|
|
* Read 256 bits of data from a DDATAX register in the CRYPTO module.
|
|
*
|
|
* @details
|
|
* Read 256 bits of data from a DDATAX (Double Data) register in the crypto
|
|
* module.
|
|
*
|
|
* @param[in] ddataReg Data register identifier
|
|
* @param[out] val Location where to store the value in memory.
|
|
******************************************************************************/
|
|
|
|
__STATIC_INLINE int ecp_crypto_ddata_read(CRYPTO_DDataReg_TypeDef ddataReg,
|
|
mbedtls_mpi* mpi)
|
|
{
|
|
CRYPTO_DData_TypeDef ddata;
|
|
uint32_t val32;
|
|
int i;
|
|
int used;
|
|
int ret = 0;
|
|
CORE_DECLARE_IRQ_STATE;
|
|
|
|
if (mpi->n == 8)
|
|
{
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataRead(ddataReg, mpi->p);
|
|
CORE_EXIT_CRITICAL();
|
|
}
|
|
else
|
|
{
|
|
if (mpi->n > 8)
|
|
{
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataRead(ddataReg, mpi->p);
|
|
CORE_EXIT_CRITICAL();
|
|
memset(&mpi->p[8], 0, sizeof(uint32_t)*(mpi->n-8));
|
|
}
|
|
else
|
|
{
|
|
uint32_t volatile* regPtr = (volatile uint32_t*) ddataReg;
|
|
used = 0;
|
|
for (i=0; i<8; i++)
|
|
{
|
|
ddata[i] = val32 = *regPtr;
|
|
if (val32)
|
|
used = i+1;
|
|
}
|
|
if (used > (int)mpi->n)
|
|
{
|
|
SLCL_ECP_CHK( mbedtls_mpi_grow(mpi, used) );
|
|
memcpy(mpi->p, ddata, used*sizeof(uint32_t));
|
|
mpi->s = 1;
|
|
}
|
|
else
|
|
{
|
|
memcpy(mpi->p, ddata, mpi->n*sizeof(uint32_t));
|
|
}
|
|
}
|
|
}
|
|
cleanup:
|
|
return( ret );
|
|
}
|
|
|
|
/**
|
|
* \brief Indicate if the Elliptic Curve Point module extension can
|
|
* handle the group.
|
|
*
|
|
* \param grp The pointer to the elliptic curve group that will be the
|
|
* basis of the cryptographic computations.
|
|
*
|
|
* \return Non-zero if successful.
|
|
*/
|
|
unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp )
|
|
{
|
|
switch( grp->id )
|
|
{
|
|
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
|
|
case MBEDTLS_ECP_DP_SECP192R1:
|
|
return( true );
|
|
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
|
|
|
|
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
|
|
case MBEDTLS_ECP_DP_SECP224R1:
|
|
return( true );
|
|
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
|
|
|
|
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
|
|
case MBEDTLS_ECP_DP_SECP256R1:
|
|
return( true );
|
|
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
|
|
|
|
default:
|
|
return( false );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Initialise the Elliptic Curve Point module extension.
|
|
*
|
|
* If mbedtls_internal_ecp_grp_capable returns true for a
|
|
* group, this function has to be able to initialise the
|
|
* module for it.
|
|
*
|
|
* This module can be a driver to a crypto hardware
|
|
* accelerator, for which this could be an initialise function.
|
|
*
|
|
* \param grp The pointer to the group the module needs to be
|
|
* initialised for.
|
|
*
|
|
* \return 0 if successful.
|
|
*/
|
|
int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )
|
|
{
|
|
/* Crypto operations are atomic, so no need to setup any context here */
|
|
(void) grp;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Frees and deallocates the Elliptic Curve Point module
|
|
* extension.
|
|
*
|
|
* \param grp The pointer to the group the module was initialised for.
|
|
*/
|
|
void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp )
|
|
{
|
|
/* Crypto operations are atomic, so no need to free any context here */
|
|
(void) grp;
|
|
}
|
|
|
|
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
|
|
/**
|
|
* \brief Randomize jacobian coordinates:
|
|
* (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l.
|
|
*
|
|
* \param grp Pointer to the group representing the curve.
|
|
*
|
|
* \param pt The point on the curve to be randomised, given with Jacobian
|
|
* coordinates.
|
|
*
|
|
* \param f_rng A function pointer to the random number generator.
|
|
*
|
|
* \param p_rng A pointer to the random number generator state.
|
|
*
|
|
* \return 0 if successful.
|
|
*/
|
|
int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp,
|
|
mbedtls_ecp_point *pt,
|
|
int (*f_rng)(void *, unsigned char *, size_t),
|
|
void *p_rng )
|
|
{
|
|
int ret;
|
|
ecc_bigint_t l;
|
|
CORE_DECLARE_IRQ_STATE;
|
|
CRYPTO_TypeDef *crypto;
|
|
|
|
/* Strategy:
|
|
* 1) Generate l such that 1 < l < p
|
|
* 2) Z = l (R1) * Z (R4)
|
|
* 3) ll (R1) = l (R4) * l
|
|
* 4) X = ll (R1) * X (R2)
|
|
* 5) lll (R1) = ll (R1) * l (R4)
|
|
* 6) Y = lll (R1) * Y (R3)
|
|
*/
|
|
|
|
/* Acquire entropy before grabbing crypto, since the entropy function might use crypto */
|
|
/* Generate l such that 1 < l < p */
|
|
ret = f_rng(p_rng, (unsigned char *)l, sizeof(l));
|
|
if ( ret != 0 ) {
|
|
return( ret );
|
|
}
|
|
|
|
crypto = crypto_management_acquire();
|
|
crypto_device_init(crypto, grp);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataWrite(&crypto->DDATA1, l);
|
|
ecp_crypto_ddata_write(&crypto->DDATA2, &pt->X);
|
|
ecp_crypto_ddata_write(&crypto->DDATA3, &pt->Y);
|
|
ecp_crypto_ddata_write(&crypto->DDATA4, &pt->Z);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
/* Z = l * Z */
|
|
CRYPTO_EXECUTE_2 ( crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL );
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
MBEDTLS_MPI_CHK( ecp_crypto_ddata_read(&crypto->DDATA0, &pt->Z) );
|
|
|
|
/* X = l^2 * X */
|
|
CRYPTO_EXECUTE_6 ( crypto,
|
|
CRYPTO_CMD_INSTR_DDATA1TODDATA4,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL );
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
MBEDTLS_MPI_CHK( ecp_crypto_ddata_read(&crypto->DDATA0, &pt->X) );
|
|
|
|
/* Y = l^3 * Y */
|
|
CRYPTO_EXECUTE_5 ( crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_MMUL );
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
MBEDTLS_MPI_CHK( ecp_crypto_ddata_read(&crypto->DDATA0, &pt->Y) );
|
|
|
|
cleanup:
|
|
crypto_management_release( crypto );
|
|
return( ret );
|
|
}
|
|
#endif
|
|
|
|
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
|
|
/**
|
|
* \brief Addition: R = P + Q, mixed affine-Jacobian coordinates.
|
|
*
|
|
* The coordinates of Q must be normalized (= affine),
|
|
* but those of P don't need to. R is not normalized.
|
|
*
|
|
* This function is used only as a subrutine of
|
|
* ecp_mul_comb().
|
|
*
|
|
* Special cases: (1) P or Q is zero, (2) R is zero,
|
|
* (3) P == Q.
|
|
* None of these cases can happen as intermediate step in
|
|
* ecp_mul_comb():
|
|
* - at each step, P, Q and R are multiples of the base
|
|
* point, the factor being less than its order, so none of
|
|
* them is zero;
|
|
* - Q is an odd multiple of the base point, P an even
|
|
* multiple, due to the choice of precomputed points in the
|
|
* modified comb method.
|
|
* So branches for these cases do not leak secret information.
|
|
*
|
|
* We accept Q->Z being unset (saving memory in tables) as
|
|
* meaning 1.
|
|
*
|
|
* Cost in field operations if done by [5] 3.22:
|
|
* 1A := 8M + 3S
|
|
*
|
|
* \param grp Pointer to the group representing the curve.
|
|
*
|
|
* \param R Pointer to a point structure to hold the result.
|
|
*
|
|
* \param P Pointer to the first summand, given with Jacobian
|
|
* coordinates
|
|
*
|
|
* \param Q Pointer to the second summand, given with affine
|
|
* coordinates.
|
|
*
|
|
* \return 0 if successful.
|
|
*/
|
|
int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp,
|
|
mbedtls_ecp_point *R,
|
|
const mbedtls_ecp_point *P,
|
|
const mbedtls_ecp_point *Q )
|
|
{
|
|
int ret;
|
|
CORE_DECLARE_IRQ_STATE;
|
|
CRYPTO_TypeDef *crypto = crypto_management_acquire();
|
|
|
|
crypto_device_init(crypto, grp);
|
|
|
|
/*
|
|
STEP 1:
|
|
|
|
Goals:
|
|
A = Qx*Pz^2
|
|
B = Qy*Pz^3
|
|
|
|
Write Operations:
|
|
|
|
R0 = Pz
|
|
R0 = Qx
|
|
R0 = Qy
|
|
|
|
Instructions to be executed:
|
|
|
|
1. R0 = DMA = Pz
|
|
2. R1 = R0 = Pz
|
|
3. R2 = R0 = Pz
|
|
4. Select R1, R2
|
|
5. R0 = R1 * R2 = Pz^2
|
|
6. R1 = R0 = Pz^2
|
|
|
|
7. R0 = DMA = Qx
|
|
8. R3 = R0 = Qx
|
|
9. Select R1, R3
|
|
10. R0 = R1 * R3 = Qx * Pz^2
|
|
11. R3 = R0 = Qx * Pz^2
|
|
|
|
12. Select R1, R2
|
|
13. R0 = R1 * R2 = Pz^3
|
|
14. R1 = R0 = Pz^3
|
|
|
|
15. R0 = DMA = Qy
|
|
16. R4 = R0 = Qx
|
|
17. Select R1, R4
|
|
18. R0 = R1 * R4 = Qy * Pz^3
|
|
19. Select R0, R1 (for MSUB in step 2)
|
|
|
|
Output State:
|
|
R0 = B
|
|
R1 = FREE
|
|
R2 = FREE
|
|
R3 = A
|
|
R4 = Pz
|
|
|
|
STEP 1:
|
|
*/
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA0, &P->Z);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_5(crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA4,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA0, &Q->X);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_4 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA0, &Q->Y);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL
|
|
);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
/*
|
|
STEP 2:
|
|
|
|
Goals:
|
|
C = A - Px
|
|
D = B - Py
|
|
R->Z = Pz * C
|
|
|
|
Write Operations:
|
|
|
|
R1 = Py
|
|
R0 = Px (via DMA)
|
|
|
|
Input State:
|
|
R0 = B
|
|
R1 = Py
|
|
R2 = FREE
|
|
R3 = A
|
|
R4 = Pz
|
|
|
|
Instructions to be executed:
|
|
|
|
0. Select R0, R1
|
|
1. R0 = R0 - R1 = B - Py = D
|
|
2. R2 = R0 = D
|
|
3. R1 = R3 = A
|
|
4. R0 = DMA = Px
|
|
5. R3 = R0 = Px
|
|
6. Select R1, R3
|
|
7. R0 = R1 - R3 = A - Px = C
|
|
8. R1 = R0 = C
|
|
9. Select R1, R4
|
|
10. R0 = R1 * R4 = Pz * C = R->Z
|
|
|
|
Read Operations:
|
|
|
|
R->Z = R0 = Pz * C
|
|
|
|
Output State:
|
|
R0 = FREE
|
|
R1 = C
|
|
R2 = D
|
|
R3 = Px
|
|
R4 = FREE
|
|
|
|
STEP 2:
|
|
*/
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA1, &P->Y);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA1,
|
|
CRYPTO_CMD_INSTR_MSUB,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2); /* R2 = D */
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA0, &P->X);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_7 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA3TODDATA1,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_MSUB,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1, /* R1 = C */
|
|
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL
|
|
);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->Z);
|
|
|
|
if (ret != 0) goto cleanup;
|
|
|
|
/*
|
|
STEP 3:
|
|
|
|
Goals:
|
|
X1C2 = Px * C^2
|
|
C3 = C^3
|
|
D2 = D^2
|
|
|
|
Input State:
|
|
R0 = FREE
|
|
R1 = C
|
|
R2 = D
|
|
R3 = Px
|
|
R4 = FREE
|
|
|
|
Instructions to be executed:
|
|
|
|
1. R4 = R1 = C
|
|
2. Select R1, R4
|
|
3. R0 = R1 * R4 = C^2
|
|
4. R1 = R0 = C^2
|
|
5. R0 = R1 * R4 = C^3
|
|
6. R4 = R0 = C^3
|
|
7. Select R1, R3
|
|
8. R0 = R1 * R3 = Px * C^2
|
|
9. R3 = R0 = Px * C^2
|
|
10. R1 = R2 = D
|
|
11. Select R1, R1
|
|
12. R0 = R1 * R1 = D^2
|
|
13. Select R0, R4
|
|
14. R0 = R0 - R4 = D2 - C3
|
|
|
|
Output state:
|
|
|
|
R0 = D2 - C3
|
|
R1 = FREE
|
|
R2 = D
|
|
R3 = X1C2 = Px * C^2
|
|
R4 = C3 = C^3
|
|
|
|
STEP 3:
|
|
*/
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA1TODDATA4,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA4);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CRYPTO_EXECUTE_5 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA2TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA4,
|
|
CRYPTO_CMD_INSTR_MSUB
|
|
);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
/*
|
|
STEP 3:
|
|
|
|
Goals:
|
|
R->X = D2 - (C3 + 2 * X1C2) = D2 - C3 - X1C2- X1C2
|
|
Y1C3 = Py * C3
|
|
R->Y = D * (X1C2 - R->X) - Y1C3
|
|
|
|
Write Operations:
|
|
R1 = Py
|
|
|
|
Input State:
|
|
R0 = D2 - C3
|
|
R1 = FREE
|
|
R2 = D
|
|
R3 = X1C2
|
|
R4 = C3
|
|
|
|
Instructions to be executed:
|
|
|
|
1. Select R0, R3
|
|
2. R0 = R0 - R3 = D2 - C3 - X1C2
|
|
3. R0 = R0 - R3 = D2 - C3 - X1C2 - X1C2 = R->X
|
|
4. DMA = R0 = R->X
|
|
5. R1 = R0 = R->X
|
|
|
|
6. Select R3, R1
|
|
7. R0 = R3 - R1 = X1C2 - R->X
|
|
8. R1 = R0 = X1C2 - R->X
|
|
9. Select R1, R2
|
|
10. R0 = R1 * R2 = D *(X1C2 - R->X)
|
|
11. R2 = R0
|
|
|
|
12. R0 = DMA = Py
|
|
13. R1 = R0 = Py
|
|
14. Select R1, R4
|
|
15. R0 = R1 * R4 = Py * C3 = Y1C3
|
|
16. R4 = R0 = Y1C3
|
|
|
|
17. Select R2, R4
|
|
18. R0 = R2 - R4
|
|
|
|
Read Operations:
|
|
|
|
R->X = R2 = D2 - (C3 + 2 * X1C2)
|
|
R->Y = R0 = D * (X1C2 - R->X) - Y1C3
|
|
|
|
STEP 4:
|
|
*/
|
|
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA3,
|
|
CRYPTO_CMD_INSTR_MSUB,
|
|
CRYPTO_CMD_INSTR_MSUB);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->X);
|
|
if ( ret != 0 ) goto cleanup;
|
|
|
|
CRYPTO_EXECUTE_7 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
|
|
CRYPTO_CMD_INSTR_SELDDATA3DDATA1,
|
|
CRYPTO_CMD_INSTR_MSUB,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA0, &P->Y);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_6 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA4,
|
|
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA4,
|
|
CRYPTO_CMD_INSTR_MSUB
|
|
);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->Y);
|
|
if ( ret != 0 ) goto cleanup;
|
|
|
|
cleanup:
|
|
crypto_management_release( crypto );
|
|
return ( ret );
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* \brief Point doubling R = 2 P, Jacobian coordinates.
|
|
*
|
|
* Cost: 1D := 3M + 4S (A == 0)
|
|
* 4M + 4S (A == -3)
|
|
* 3M + 6S + 1a otherwise
|
|
* when the implementation is based on the "dbl-1998-cmo-2"
|
|
* doubling formulas in [8] and standard optimizations are
|
|
* applied when curve parameter A is one of { 0, -3 }.
|
|
*
|
|
* \param grp Pointer to the group representing the curve.
|
|
*
|
|
* \param R Pointer to a point structure to hold the result.
|
|
*
|
|
* \param P Pointer to the point that has to be doubled, given with
|
|
* Jacobian coordinates.
|
|
*
|
|
* \return 0 if successful.
|
|
*/
|
|
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
|
|
int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp,
|
|
mbedtls_ecp_point *R,
|
|
const mbedtls_ecp_point *P )
|
|
{
|
|
int ret;
|
|
CORE_DECLARE_IRQ_STATE;
|
|
CRYPTO_TypeDef *crypto = crypto_management_acquire();
|
|
|
|
crypto_device_init(crypto, grp);
|
|
|
|
ecc_bigint_t _2YY;
|
|
/*
|
|
STEP 1:
|
|
|
|
Goals:
|
|
ZZ = Z^2
|
|
R->Z = 2 * Y * Z
|
|
YY = Y^2
|
|
4YY = 4 * Y^2
|
|
|
|
Write Operations:
|
|
|
|
R2 = Y
|
|
R3 = Z
|
|
|
|
Instructions to be executed:
|
|
|
|
1. R0 = DMA = Z
|
|
2. R1 = R0 = Z
|
|
3. R2 = R0 = Z
|
|
4. Select R1, R2
|
|
5. R0 = R1 * R2 = Z^2 = ZZ
|
|
6. R3 = R0 = ZZ
|
|
|
|
7. R0 = DMA = Y
|
|
8. R2 = R0 = Y
|
|
9. R0 = R1 * R2 = Y * Z
|
|
10. Select R0, R0
|
|
11. R0 = R0 + R0 = 2 * Y * Z = R->Z
|
|
|
|
12. DMA = R0 = R->Z
|
|
|
|
13. R1 = R2 = Y
|
|
14. Select R1, R2
|
|
15. R0 = R1 * R2 = Y^2 = YY
|
|
16. Select R0, R0
|
|
17. R0 = R0 + R0 = 2YY
|
|
|
|
Read Operations:
|
|
|
|
R->Z = R0 = 2 * Y * Z
|
|
2YY = R0
|
|
|
|
Output State:
|
|
R0 = 2YY
|
|
R1 = FREE
|
|
R2 = FREE
|
|
R3 = ZZ
|
|
R4 = FREE
|
|
|
|
STEP 1:
|
|
*/
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA0, &P->Z);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_5 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA0, &P->Y);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_4 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA0,
|
|
CRYPTO_CMD_INSTR_MADD);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->Z);
|
|
if ( ret != 0 ) goto cleanup;
|
|
|
|
CRYPTO_EXECUTE_5 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA2TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA0,
|
|
CRYPTO_CMD_INSTR_MADD
|
|
);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA4, &P->X);
|
|
CRYPTO_DDataRead(&crypto->DDATA0, _2YY);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
/*
|
|
STEP 2:
|
|
|
|
Goals:
|
|
A = 4YY * X
|
|
C = 3(X - ZZ)(X + ZZ)
|
|
|
|
Write Operations:
|
|
|
|
R4 = X
|
|
|
|
Input State:
|
|
R0 = 2YY
|
|
R1 = FREE
|
|
R2 = FREE
|
|
R3 = ZZ
|
|
R4 = X
|
|
|
|
Instructions to be executed:
|
|
|
|
1. R0 = R0 + R0 = 4YY
|
|
2. R1 = R0 = 4YY
|
|
3. Select R1, R4
|
|
4. R0 = R1 * R4 = 4YY * X = A
|
|
5. R2 = R0 = A
|
|
6. Select R4, R3
|
|
7. R0 = R4 + R3 = X + ZZ
|
|
8. R1 = R0 = X + ZZ
|
|
9. R0 = R4 - R3 = X - ZZ
|
|
0. R2 = R0 = X - ZZ
|
|
11. Select R1, R2
|
|
12. R0 = R1 * R2 = (X + ZZ)(X - ZZ)
|
|
13. R1 = R0 = (X + ZZ)(X - ZZ)
|
|
14. Select R0, R1
|
|
15. R0 = R0 + R1 = 2(X + ZZ)(X - ZZ)
|
|
16. R0 = R0 + R1 = 3(X + ZZ)(X - ZZ) = C
|
|
17. R1 = R0 = C
|
|
|
|
Output State:
|
|
R0 = FREE
|
|
R1 = C
|
|
R2 = A
|
|
R3 = FREE
|
|
R4 = FREE
|
|
|
|
STEP 2:
|
|
*/
|
|
CRYPTO_EXECUTE_11(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA0,
|
|
CRYPTO_CMD_INSTR_MADD,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2,
|
|
CRYPTO_CMD_INSTR_SELDDATA4DDATA3,
|
|
CRYPTO_CMD_INSTR_MADD,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_MSUB,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA4);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_7 (crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA1,
|
|
CRYPTO_CMD_INSTR_MADD,
|
|
CRYPTO_CMD_INSTR_MADD,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1
|
|
);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
/*
|
|
STEP 3:
|
|
|
|
Goals:
|
|
R->X = C^2 - 2A
|
|
D = C(A - R->X)
|
|
|
|
Input State:
|
|
R0 = FREE
|
|
R1 = C
|
|
R2 = A
|
|
R3 = FREE
|
|
R4 = FREE
|
|
|
|
Instructions to be executed:
|
|
|
|
1. R4 = R1 = C
|
|
2. Select R1, R4
|
|
3. R0 = R1 * R4 = C^2
|
|
4. Select R0, R2
|
|
5. R0 = R0 - R2 = C^2 - 2A = R->X
|
|
6. R4 = R0 = R->X
|
|
7. Select R3, R4
|
|
8. R0 = R3 - R4 = A - R->X
|
|
9. R2 = R0 = A - R->X
|
|
10 Select R1, R2
|
|
11. R0 = R1 * R2 = C(A - R->X) = D
|
|
|
|
Read Operations:
|
|
|
|
R->X = R4 = C^2 - 2A
|
|
|
|
Output State:
|
|
R0 = FREE
|
|
R1 = FREE
|
|
R2 = FREE
|
|
R3 = D
|
|
R4 = FREE
|
|
|
|
STEP 3:
|
|
*/
|
|
|
|
CRYPTO_EXECUTE_8 (crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA2,
|
|
CRYPTO_CMD_INSTR_MADD,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA4,
|
|
|
|
CRYPTO_CMD_INSTR_DDATA1TODDATA3,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA4,
|
|
CRYPTO_CMD_INSTR_MSUB);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->X);
|
|
if ( ret != 0 ) goto cleanup;
|
|
|
|
CRYPTO_EXECUTE_7 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA4,
|
|
|
|
CRYPTO_CMD_INSTR_SELDDATA2DDATA4,
|
|
CRYPTO_CMD_INSTR_MSUB,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3
|
|
);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
|
|
/*
|
|
STEP 4:
|
|
|
|
Goals:
|
|
B = 8 * Y^4
|
|
R->Y = D - B
|
|
|
|
Write Operations:
|
|
|
|
R1 = YY
|
|
|
|
Input State:
|
|
R0 = FREE
|
|
R1 = YY
|
|
R2 = FREE
|
|
R3 = D
|
|
R4 = FREE
|
|
|
|
Instructions to be executed:
|
|
|
|
2. R0 = DMA0
|
|
3. R1 = R0 = Y^2
|
|
4. R2 = R0 = Y^2
|
|
5. Select R1, R2
|
|
6. R0 = R1 * R2 = Y^4
|
|
7. Select R0, R0
|
|
8. R0 = R0 + R0 = 2 * Y^4
|
|
9. R0 = R0 + R0 = 4 * Y^4
|
|
10. R0 = R0 + R0 = 8 * Y^4
|
|
11. R2 = R0
|
|
12. Select R3, R2
|
|
13. R0 = R3 - R2 = D - B = R->Y
|
|
|
|
Read Operations:
|
|
|
|
R->Y = R0 = D - B
|
|
|
|
STEP 4:
|
|
*/
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataWrite(&crypto->DDATA0, _2YY);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_9 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
|
|
CRYPTO_CMD_INSTR_SELDDATA0DDATA0,
|
|
CRYPTO_CMD_INSTR_MADD,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2,
|
|
|
|
CRYPTO_CMD_INSTR_SELDDATA3DDATA2,
|
|
CRYPTO_CMD_INSTR_MSUB
|
|
);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->Y);
|
|
if ( ret != 0 ) goto cleanup;
|
|
|
|
cleanup:
|
|
crypto_management_release( crypto );
|
|
|
|
return ( ret );
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* \brief Normalize jacobian coordinates of an array of (pointers to)
|
|
* points.
|
|
*
|
|
* Using Montgomery's trick to perform only one inversion mod P
|
|
* the cost is:
|
|
* 1N(t) := 1I + (6t - 3)M + 1S
|
|
* (See for example Algorithm 10.3.4. in [9])
|
|
*
|
|
* This function is used only as a subrutine of
|
|
* ecp_mul_comb().
|
|
*
|
|
* Warning: fails (returning an error) if one of the points is
|
|
* zero!
|
|
* This should never happen, see choice of w in ecp_mul_comb().
|
|
*
|
|
* \param grp Pointer to the group representing the curve.
|
|
*
|
|
* \param T Array of pointers to the points to normalise.
|
|
*
|
|
* \param t_len Number of elements in the array.
|
|
*
|
|
* \return 0 if successful,
|
|
* an error if one of the points is zero.
|
|
*/
|
|
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
|
|
int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
|
|
mbedtls_ecp_point *T[],
|
|
size_t t_len )
|
|
{
|
|
int ret = 0;
|
|
size_t i;
|
|
ecc_bigint_t* cc;
|
|
ecc_bigint_t uu;
|
|
ecc_bigint_t one;
|
|
ecc_bigint_t modulus;
|
|
CORE_DECLARE_IRQ_STATE;
|
|
|
|
if( t_len < 2 )
|
|
return( mbedtls_internal_ecp_normalize_jac( grp, *T ) );
|
|
|
|
if( ( cc = mbedtls_calloc( t_len, sizeof( ecc_bigint_t ) ) ) == NULL )
|
|
return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
|
|
|
|
/*
|
|
* c[i] = Z_0 * ... * Z_i
|
|
*/
|
|
MPI_TO_BIGINT( cc[0], &T[0]->Z );
|
|
|
|
CRYPTO_TypeDef *crypto = crypto_management_acquire();
|
|
crypto_device_init(crypto, grp);
|
|
|
|
for( i = 1; i < t_len; i++ )
|
|
{
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write( &crypto->DDATA1, &T[i]->Z );
|
|
CRYPTO_DDataWrite( &crypto->DDATA2, cc[i-1] );
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_2(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataRead( &crypto->DDATA0, cc[i] );
|
|
CORE_EXIT_CRITICAL();
|
|
}
|
|
|
|
memset(one, 0, sizeof(one));
|
|
one[0]=1;
|
|
MPI_TO_BIGINT( modulus, &grp->P );
|
|
|
|
/*
|
|
* u = 1 / (Z_0 * ... * Z_n) mod P
|
|
*/
|
|
crypto_mpi_div_mod(crypto, one, cc[t_len-1], modulus, uu);
|
|
|
|
for( i = t_len - 1; ; i-- )
|
|
{
|
|
/*
|
|
* Zi = 1 / Z_i mod p
|
|
* u = 1 / (Z_0 * ... * Z_i) mod P
|
|
*/
|
|
if( i == 0 )
|
|
{
|
|
/* Z_inv (DDATA2) = uu */
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataWrite(&crypto->DDATA2, uu);
|
|
CORE_EXIT_CRITICAL();
|
|
}
|
|
else
|
|
{
|
|
/* Z_inv (DDATA1) = uu x cc[i-1] modulo p */
|
|
/* uu = uu x T[i]->Z modulo p */
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataWrite(&crypto->DDATA1, uu);
|
|
CRYPTO_DDataWrite(&crypto->DDATA2, cc[i-1]);
|
|
ecp_crypto_ddata_write( &crypto->DDATA3, &T[i]->Z );
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_3(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA2); /* Z_inv (DDATA2) */
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_2(crypto,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataRead(&crypto->DDATA0, uu);
|
|
CORE_EXIT_CRITICAL();
|
|
}
|
|
|
|
/*
|
|
* proceed as in normalize()
|
|
*/
|
|
CORE_ENTER_CRITICAL();
|
|
ecp_crypto_ddata_write(&crypto->DDATA3, &T[i]->X);
|
|
ecp_crypto_ddata_write(&crypto->DDATA4, &T[i]->Y);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
/* Z_inv already in DDATA2 */
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA2TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
ecp_crypto_ddata_read(&crypto->DDATA0, &T[i]->Y);
|
|
ecp_crypto_ddata_read(&crypto->DDATA3, &T[i]->X);
|
|
|
|
/*
|
|
* Post-precessing: reclaim some memory by shrinking coordinates
|
|
* - not storing Z (always 1)
|
|
* - shrinking other coordinates, but still keeping the same number of
|
|
* limbs as P, as otherwise it will too likely be regrown too fast.
|
|
*/
|
|
SLCL_ECP_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
|
|
SLCL_ECP_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
|
|
mbedtls_mpi_free( &T[i]->Z );
|
|
|
|
if( i == 0 )
|
|
break;
|
|
}
|
|
|
|
cleanup:
|
|
crypto_management_release( crypto );
|
|
mbedtls_free( cc );
|
|
|
|
return( ret );
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* \brief Normalize jacobian coordinates so that Z == 0 || Z == 1.
|
|
*
|
|
* Cost in field operations if done by [5] 3.2.1:
|
|
* 1N := 1I + 3M + 1S
|
|
*
|
|
* \param grp Pointer to the group representing the curve.
|
|
*
|
|
* \param pt pointer to the point to be normalised. This is an
|
|
* input/output parameter.
|
|
*
|
|
* \return 0 if successful.
|
|
*/
|
|
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
|
|
int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp,
|
|
mbedtls_ecp_point *pt )
|
|
{
|
|
int ret = 0;
|
|
CORE_DECLARE_IRQ_STATE;
|
|
CRYPTO_TypeDef *crypto = crypto_management_acquire();
|
|
|
|
crypto_device_init(crypto, grp);
|
|
|
|
ecc_bigint_t one;
|
|
ecc_bigint_t Z;
|
|
ecc_bigint_t modulus;
|
|
ecc_bigint_t Z_inv;
|
|
|
|
memset(one, 0, sizeof(one));
|
|
one[0]=1;
|
|
|
|
MPI_TO_BIGINT( Z, &pt->Z );
|
|
MPI_TO_BIGINT( modulus, &grp->P );
|
|
|
|
crypto_mpi_div_mod(crypto, one, Z, modulus, Z_inv);
|
|
|
|
/*
|
|
|
|
Goals:
|
|
R->X = P->X * Z_inv ^2
|
|
R->Y = P->Y * Z_inv ^3
|
|
|
|
Write Operations:
|
|
|
|
R1 = Z_inv
|
|
R3 = P->X
|
|
R4 = P->Y
|
|
|
|
Instructions to be executed:
|
|
|
|
1. R2 = R1 = Z_inv
|
|
2. Select R1, R2
|
|
3. R0 = R1 * R2 = Z_inv^2
|
|
4. R1 = R0 = Z_inv^2
|
|
5. Select R1, R3
|
|
6. R0 = R1 * R3 = P->X * Z_inv^2 = R->X
|
|
7. R3 = R0
|
|
8. Select R1, R2
|
|
9. R0 = R1 * R2 = Z_inv^3
|
|
10. R1 = R0 = Z_inv^3
|
|
11. Select R1, R4
|
|
12. R0 = R1 * R4 = P->Y * Z_inv^3 = R->Y
|
|
|
|
Read Operations:
|
|
|
|
R->Y = R0 = P->Y * P->Z_inv^3
|
|
R->X = R3 = P->X * P->Z_inv^2
|
|
|
|
*/
|
|
CORE_ENTER_CRITICAL();
|
|
CRYPTO_DDataWrite(&crypto->DDATA1, Z_inv);
|
|
ecp_crypto_ddata_write(&crypto->DDATA3, &pt->X);
|
|
ecp_crypto_ddata_write(&crypto->DDATA4, &pt->Y);
|
|
CORE_EXIT_CRITICAL();
|
|
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA1TODDATA2,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA3,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA3,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA2,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
CRYPTO_EXECUTE_3 (crypto,
|
|
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
|
CRYPTO_CMD_INSTR_SELDDATA1DDATA4,
|
|
CRYPTO_CMD_INSTR_MMUL);
|
|
CRYPTO_InstructionSequenceWait(crypto);
|
|
|
|
ecp_crypto_ddata_read(&crypto->DDATA0, &pt->Y);
|
|
ecp_crypto_ddata_read(&crypto->DDATA3, &pt->X);
|
|
|
|
crypto_management_release( crypto );
|
|
|
|
/*
|
|
* Z = 1
|
|
*/
|
|
SLCL_ECP_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
|
|
|
|
cleanup:
|
|
return( ret );
|
|
}
|
|
#endif
|
|
|
|
#endif /* #if defined( MBEDTLS_ECP_INTERNAL_ALT ) */
|
|
|
|
#endif /* #if defined( MBEDTLS_ECP_C ) */
|
|
|
|
#endif /* #if defined( CRYPTO_PRESENT ) */
|