/* * Copyright 2018 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #include "mbedtls/threading.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #include "ksdk_mbedtls.h" #endif #if defined(MBEDTLS_ECP_ALT) /******************************************************************************* * Definitions ******************************************************************************/ /******************************************************************************* * Prototypes ******************************************************************************/ /******************************************************************************* * Variables ******************************************************************************/ /******************************************************************************* * Codes ******************************************************************************/ #if defined(MBEDTLS_MCUX_CASPER_ECC) #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) #error "CASPER hw acceleration currently supported only for SECP256R1 , SECP384R1 and SECP521R1." #endif /* CASPER driver allows usage of 256, 384 and 521 ECC */ #define CASPER_MAX_ECC_SIZE_BITS (521) #define CASPER_MAX_ECC_SIZE_BYTES (72) /* 32 for 256 bits, 48 for 384 bits and 72 for 521 bits*/ /* Parameter validation macros based on platform_util.h */ #define ECP_VALIDATE_RET(cond) MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA) #define ECP_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond) static void reverse_array(uint8_t *src, size_t src_len) { int i; for (i = 0; i < src_len / 2; i++) { uint8_t tmp; tmp = src[i]; src[i] = src[src_len - 1 - i]; src[src_len - 1 - i] = tmp; } } #if defined(MBEDTLS_ECP_MUL_COMB_ALT) int ecp_mul_comb(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, // result const mbedtls_mpi *m, // scalar const mbedtls_ecp_point *P, // X & Y int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) /* TBD: rs_ctx is not used MBEDTLS_ECP_RESTARTABLE is not supported */ { size_t size; int ret = 0; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&mbedtls_threading_hwcrypto_casper_mutex)) != 0) return (ret); #endif size = mbedtls_mpi_size(&grp->P); uint32_t M[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; uint32_t X[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; uint32_t Y[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; //* Write MbedTLS mpi coordinates into binary buffer */ mbedtls_mpi_write_binary(&P->X, (unsigned char *)&X[0], size); mbedtls_mpi_write_binary(&P->Y, (unsigned char *)&Y[0], size); /* Reverse endianness for CASPER */ reverse_array((uint8_t *)X, size); reverse_array((uint8_t *)Y, size); /* Init CASPER */ if (size == 32) { CASPER_ecc_init(kCASPER_ECC_P256); } if (size == 48) { CASPER_ecc_init(kCASPER_ECC_P384); } if (size == 66) { CASPER_ecc_init(kCASPER_ECC_P521); } if (mbedtls_mpi_size(m) > sizeof(M)) { __BKPT(0); #if defined(MBEDTLS_THREADING_C) ret = mbedtls_mutex_unlock(&mbedtls_threading_hwcrypto_casper_mutex); #endif /* (MBEDTLS_THREADING_C) */ ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; return (ret); } mbedtls_mpi_write_binary(m, (void *)M, size); reverse_array((void *)M, size); if (size == 32) { CASPER_ECC_SECP256R1_Mul(CASPER, &X[0], &Y[0], &X[0], &Y[0], (void *)M); } if (size == 48) { CASPER_ECC_SECP384R1_Mul(CASPER, &X[0], &Y[0], &X[0], &Y[0], (void *)M); } if (size == 66) { CASPER_ECC_SECP521R1_Mul(CASPER, &X[0], &Y[0], &X[0], &Y[0], (void *)M); } /* Reverse results back to MbedTLS format */ reverse_array((uint8_t *)X, size); reverse_array((uint8_t *)Y, size); /* Write results into R MPI */ mbedtls_mpi_read_binary(&R->X, (void *)&X[0], size); mbedtls_mpi_read_binary(&R->Y, (void *)&Y[0], size); mbedtls_mpi_lset(&R->Z, 1); #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_unlock(&mbedtls_threading_hwcrypto_casper_mutex)) != 0) return (ret); #endif return (ret); } #endif /* MBEDTLS_ECP_MUL_COMB_ALT */ #if defined(MBEDTLS_ECP_MULADD_ALT) /* * Restartable linear combination * NOT constant-time */ int mbedtls_ecp_muladd_restartable(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, mbedtls_ecp_restart_ctx *rs_ctx) /* TBD restartable is not implemented */ { uint32_t X1[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; uint32_t Y1[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; uint32_t X2[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; uint32_t Y2[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; uint32_t M[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; uint32_t N[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = {0}; size_t size; int ret = 0; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&mbedtls_threading_hwcrypto_casper_mutex)) != 0) return (ret); #endif /* shortcut for (m == 1) && (n == 1). this case is point addition. */ /* this shortcut follows original mbedtls_ecp_muladd() implementation */ /* and is required for ecjpake_ecp_add3(). */ if ((mbedtls_mpi_cmp_int(m, 1) == 0) && (mbedtls_mpi_cmp_int(n, 1) == 0)) { return ecp_add(grp, R, P, Q); } /* Write MbedTLS mpi coordinates into binary buffer */ size = mbedtls_mpi_size(&grp->P); mbedtls_mpi_write_binary(&P->X, (unsigned char *)&X1[0], size); mbedtls_mpi_write_binary(&P->Y, (unsigned char *)&Y1[0], size); reverse_array((uint8_t *)X1, size); reverse_array((uint8_t *)Y1, size); /* Init CASPER */ if (size == 32) { CASPER_ecc_init(kCASPER_ECC_P256); } if (size == 48) { CASPER_ecc_init(kCASPER_ECC_P384); } if (size == 66) { CASPER_ecc_init(kCASPER_ECC_P521); } if (mbedtls_mpi_size(m) > sizeof(M)) { __BKPT(0); #if defined(MBEDTLS_THREADING_C) ret = mbedtls_mutex_unlock(&mbedtls_threading_hwcrypto_casper_mutex); #endif /* (MBEDTLS_THREADING_C) */ ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; return (ret); } mbedtls_mpi_write_binary(m, (void *)M, size); reverse_array((void *)M, size); /* Write MbedTLS mpi coordinates into binary bufer */ mbedtls_mpi_write_binary(&Q->X, (unsigned char *)&X2[0], size); mbedtls_mpi_write_binary(&Q->Y, (unsigned char *)&Y2[0], size); reverse_array((uint8_t *)X2, size); reverse_array((uint8_t *)Y2, size); if (mbedtls_mpi_size(n) > sizeof(N)) { __BKPT(0); ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; return (ret); } mbedtls_mpi_write_binary(n, (void *)N, size); reverse_array((void *)N, size); if (size == 32) { CASPER_ECC_SECP256R1_MulAdd(CASPER, &X1[0], &Y1[0], &X1[0], &Y1[0], (void *)M, &X2[0], &Y2[0], (void *)N); } if (size == 48) { CASPER_ECC_SECP384R1_MulAdd(CASPER, &X1[0], &Y1[0], &X1[0], &Y1[0], (void *)M, &X2[0], &Y2[0], (void *)N); } if (size == 66) { CASPER_ECC_SECP521R1_MulAdd(CASPER, &X1[0], &Y1[0], &X1[0], &Y1[0], (void *)M, &X2[0], &Y2[0], (void *)N); } /* Reverse results back to MbedTLS format */ reverse_array((uint8_t *)X1, size); reverse_array((uint8_t *)Y1, size); /* Write results into R MPI */ mbedtls_mpi_read_binary(&R->X, (void *)&X1[0], size); mbedtls_mpi_read_binary(&R->Y, (void *)&Y1[0], size); mbedtls_mpi_lset(&R->Z, 1); #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_unlock(&mbedtls_threading_hwcrypto_casper_mutex)) != 0) return (ret); #endif return ret; } /* * Linear combination * NOT constant-time */ int mbedtls_ecp_muladd(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) { ECP_VALIDATE_RET(grp != NULL); ECP_VALIDATE_RET(R != NULL); ECP_VALIDATE_RET(m != NULL); ECP_VALIDATE_RET(P != NULL); ECP_VALIDATE_RET(n != NULL); ECP_VALIDATE_RET(Q != NULL); return (mbedtls_ecp_muladd_restartable(grp, R, m, P, n, Q, NULL)); } #endif /* MBEDTLS_ECP_MULADD_ALT */ #endif /* MBEDTLS_MCUX_CASPER_ECC */ #endif /* MBEDTLS_ECP_ALT */ #endif /* MBEDTLS_ECP_C */