/* casper_port.c * * Copyright (C) 2006-2026 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #include #ifdef WOLFSSL_NXP_CASPER #if defined(WOLFSSL_CRYPT_HW_MUTEX) && WOLFSSL_CRYPT_HW_MUTEX > 0 #error WOLFSSL_CRYPT_HW_MUTEX=1 not supported yet #endif #include #include #include "fsl_casper.h" int wc_casper_init(void) { CASPER_Init(CASPER); return 0; } #if !defined(NO_RSA) && defined(WOLFSSL_NXP_CASPER_RSA_PUB_EXPTMOD) #define CASPER_MAX_BUF_SZ 512 static uint8_t key_buf[CASPER_MAX_BUF_SZ]; static uint8_t sig_buf[CASPER_MAX_BUF_SZ]; static uint8_t out_buf[CASPER_MAX_BUF_SZ]; int casper_rsa_public_exptmod( const byte* in, word32 inLen, byte* out, word32* outLen, RsaKey* key ) { int res; int sig_sz = inLen; int key_sz = mp_unsigned_bin_size(&key->n); int exp_sz = mp_unsigned_bin_size(&key->e); uint8_t exp_buf[sizeof(uint32_t)]; uint32_t exp = 0; if (inLen > CASPER_MAX_BUF_SZ || *outLen > CASPER_MAX_BUF_SZ) return BAD_FUNC_ARG; /* casper only accepts a 32-bit public exponent */ if (exp_sz <= 0 || exp_sz > (int)sizeof(exp_buf)) return BAD_FUNC_ARG; /* casper requires little endian format for inputs/outputs */ XMEMCPY(sig_buf, in, sig_sz); mp_reverse(sig_buf, sig_sz); if ((res = mp_to_unsigned_bin(&key->n, key_buf)) != MP_OKAY) return res; mp_reverse(key_buf, key_sz); XMEMSET(exp_buf, 0, sizeof(exp_buf)); if ((res = mp_to_unsigned_bin(&key->e, exp_buf + sizeof(exp_buf) - exp_sz)) != MP_OKAY) return res; exp = ((uint32_t)exp_buf[0] << 24) | ((uint32_t)exp_buf[1] << 16) | ((uint32_t)exp_buf[2] << 8) | ((uint32_t)exp_buf[3]); CASPER_ModExp(CASPER, (void *)sig_buf, (void *)key_buf, key_sz / sizeof(uint32_t), exp, out_buf); mp_reverse(out_buf, sig_sz); XMEMCPY(out, out_buf, sig_sz); *outLen = inLen; return 0; } #endif /* !NO_RSA && WOLFSSL_NXP_CASPER_RSA_PUB_EXPTMOD */ /* 32 for 256 bits, 48 for 384 bits and 72 for 521 bits... */ #define CASPER_MAX_ECC_SIZE_BYTES (72) #if defined(HAVE_ECC) && defined(WOLFSSL_NXP_CASPER_ECC_MULMOD) /* calculates R = m*P[X, Y] */ int casper_ecc_mulmod( const mp_int *m, ecc_point *P, ecc_point *R, int curve_id ) { 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 }; int size; if (!m || !P || !R) return BAD_FUNC_ARG; if (curve_id == ECC_SECP256R1) { size = 32; CASPER_ecc_init(kCASPER_ECC_P256); } else if (curve_id == ECC_SECP384R1) { size = 48; CASPER_ecc_init(kCASPER_ECC_P384); } else if (curve_id == ECC_SECP521R1) { size = 66; CASPER_ecc_init(kCASPER_ECC_P521); } else return BAD_FUNC_ARG; /* scalar */ if (mp_to_unsigned_bin(m, (unsigned char *)&M[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&M[0], size); /* point */ if (mp_to_unsigned_bin(P->x, (unsigned char *)&X[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&X[0], size); if (mp_to_unsigned_bin(P->y, (unsigned char *)&Y[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&Y[0], size); if (curve_id == ECC_SECP256R1) { CASPER_ECC_SECP256R1_Mul(CASPER, X, Y, X, Y, (void *)M); } else if (curve_id == ECC_SECP384R1) { CASPER_ECC_SECP384R1_Mul(CASPER, X, Y, X, Y, (void *)M); } else if (curve_id == ECC_SECP521R1) { CASPER_ECC_SECP521R1_Mul(CASPER, X, Y, X, Y, (void *)M); } /* result */ mp_reverse((unsigned char *)&X[0], size); if (mp_read_unsigned_bin(R->x, (unsigned char *)&X[0], size) != MP_OKAY) return MP_READ_E; mp_reverse((unsigned char *)&Y[0], size); if (mp_read_unsigned_bin(R->y, (unsigned char *)&Y[0], size) != MP_OKAY) return MP_READ_E; mp_set(R->z, 1); return 0; } #endif /* HAVE_ECC && WOLFSSL_NXP_CASPER_ECC_MULMOD */ #if defined(HAVE_ECC) && defined(WOLFSSL_NXP_CASPER_ECC_MUL2ADD) /* calculates R = m*P[X, Y] + n*Q[X, Y] */ int casper_ecc_mul2add( const mp_int *m, ecc_point *P, const mp_int *n, ecc_point *Q, ecc_point *R, int curve_id ) { uint32_t M[CASPER_MAX_ECC_SIZE_BYTES / sizeof(uint32_t)] = { 0 }; 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 N[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 }; int size; if (!m || !P || !n || !Q || !R) return BAD_FUNC_ARG; if (curve_id == ECC_SECP256R1) { size = 32; CASPER_ecc_init(kCASPER_ECC_P256); } else if (curve_id == ECC_SECP384R1) { size = 48; CASPER_ecc_init(kCASPER_ECC_P384); } else if (curve_id == ECC_SECP521R1) { size = 66; CASPER_ecc_init(kCASPER_ECC_P521); } else return BAD_FUNC_ARG; /* first scalar */ if (mp_to_unsigned_bin(m, (unsigned char *)&M[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&M[0], size); /* first point */ if (mp_to_unsigned_bin(P->x, (unsigned char *)&X1[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&X1[0], size); if (mp_to_unsigned_bin(P->y, (unsigned char *)&Y1[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&Y1[0], size); /* second scalar */ if (mp_to_unsigned_bin(n, (unsigned char *)&N[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&N[0], size); /* second point */ if (mp_to_unsigned_bin(Q->x, (unsigned char *)&X2[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&X2[0], size); if (mp_to_unsigned_bin(Q->y, (unsigned char *)&Y2[0]) != MP_OKAY) return MP_TO_E; mp_reverse((unsigned char *)&Y2[0], size); if (curve_id == ECC_SECP256R1) { CASPER_ECC_SECP256R1_MulAdd(CASPER, &X1[0], &Y1[0], &X1[0], &Y1[0], (void *)M, &X2[0], &Y2[0], (void *)N); } else if (curve_id == ECC_SECP384R1) { CASPER_ECC_SECP384R1_MulAdd(CASPER, &X1[0], &Y1[0], &X1[0], &Y1[0], (void *)M, &X2[0], &Y2[0], (void *)N); } else if (curve_id == ECC_SECP521R1) { CASPER_ECC_SECP521R1_MulAdd(CASPER, &X1[0], &Y1[0], &X1[0], &Y1[0], (void *)M, &X2[0], &Y2[0], (void *)N); } /* result */ mp_reverse((unsigned char *)&X1[0], size); if (mp_read_unsigned_bin(R->x, (unsigned char *)&X1[0], size) != MP_OKAY) return MP_READ_E; mp_reverse((unsigned char *)&Y1[0], size); if (mp_read_unsigned_bin(R->y, (unsigned char *)&Y1[0], size) != MP_OKAY) return MP_READ_E; mp_set(R->z, 1); return 0; } #endif /* HAVE_ECC && WOLFSSL_NXP_CASPER_ECC_MUL2ADD */ #endif /* WOLFSSL_NXP_CASPER */