#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC)
#include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <stdint.h>
#define ERROR_OUT(res) { ret = (res); goto done; }
#ifdef ENABLE_NXPLTC_TESTS
static int doLtcTest = 0;
#endif
int ksdk_port_init(void)
{
#if defined(FREESCALE_LTC_TFM)
LTC_Init(LTC0);
#endif
return 0;
}
static void ltc_reverse_array(uint8_t *src, size_t src_len)
{
unsigned 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;
}
}
#ifndef WOLFSSL_SP_MATH
static int mp_to_unsigned_lsb_bin(mp_int *a, unsigned char *b)
{
int res;
mp_int t;
res = mp_init_copy(&t, a);
if (res == MP_OKAY) {
res = mp_to_unsigned_bin_at_pos(0, &t, b);
if (res >= 0)
res = 0;
#ifndef USE_FAST_MATH
mp_clear(&t);
#endif
}
return res;
}
#endif
static int ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz)
{
int res;
uint16_t sz;
sz = mp_unsigned_bin_size(A);
#ifndef WOLFSSL_SP_MATH
res = mp_to_unsigned_lsb_bin(A, dst);
#else
res = mp_to_unsigned_bin(A, dst);
if (res == MP_OKAY) {
ltc_reverse_array(dst, sz);
}
#endif
*psz = sz;
return res;
}
#if defined(FREESCALE_LTC_TFM)
int mp_mul(mp_int *A, mp_int *B, mp_int *C)
{
int res = MP_OKAY;
status_t status;
int szA, szB;
#ifdef ENABLE_NXPLTC_TESTS
mp_int t;
mp_init(&t);
if (doLtcTest)
wolfcrypt_mp_mul(A, B, &t);
#endif
szA = mp_unsigned_bin_size(A);
szB = mp_unsigned_bin_size(B);
if ((szA <= LTC_MAX_INT_BYTES / 2) && (szB <= LTC_MAX_INT_BYTES / 2)) {
uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
uint8_t *ptrN = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
defined(WOLFSSL_SP_INT_NEGATIVE)
int neg = (A->sign == B->sign) ? MP_ZPOS : MP_NEG;
#endif
if (ptrA && ptrB && ptrN && ptrC) {
uint16_t sizeA, sizeB, sizeN, sizeC = 0;
res = ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA);
if (res == MP_OKAY)
res = ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB);
if (res == MP_OKAY) {
sizeN = sizeA + sizeB;
XMEMSET(ptrN, 0xFF, sizeN);
XMEMSET(ptrC, 0, LTC_MAX_INT_BYTES);
status = LTC_PKHA_ModMul(LTC_BASE,
ptrA, sizeA,
ptrB, sizeB,
ptrN, sizeN,
ptrC, &sizeC,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
if (status == kStatus_Success) {
ltc_reverse_array(ptrC, sizeC);
res = mp_read_unsigned_bin(C, ptrC, sizeC);
#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
defined(WOLFSSL_SP_INT_NEGATIVE)
C->sign = neg;
#endif
}
else {
res = MP_VAL;
}
}
}
else {
res = MP_MEM;
}
XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrN, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT);
}
else {
#ifdef WOLFSSL_SP_MATH
res = sp_mul(A, B, C);
#else
res = wolfcrypt_mp_mul(A, B, C);
#endif
}
#ifdef ENABLE_NXPLTC_TESTS
if (doLtcTest && mp_cmp(&t, C) != MP_EQ) {
printf("mp_mul test fail!\n");
mp_dump("C", C, 0);
mp_dump("C soft", &t, 0);
}
mp_clear(&t);
#endif
return res;
}
int mp_mod(mp_int *a, mp_int *b, mp_int *c)
{
int res = MP_OKAY;
int szA, szB;
#ifdef ENABLE_NXPLTC_TESTS
mp_int t;
mp_init(&t);
if (doLtcTest)
wolfcrypt_mp_mod(a, b, &t);
#endif
szA = mp_unsigned_bin_size(a);
szB = mp_unsigned_bin_size(b);
if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) {
uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
defined(WOLFSSL_SP_INT_NEGATIVE)
int neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
#endif
if (ptrA && ptrB && ptrC) {
uint16_t sizeA, sizeB, sizeC;
res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA);
if (res == MP_OKAY)
res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB);
if (res == MP_OKAY) {
if (kStatus_Success ==
LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC,
&sizeC, kLTC_PKHA_IntegerArith))
{
ltc_reverse_array(ptrC, sizeC);
res = mp_read_unsigned_bin(c, ptrC, sizeC);
#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
defined(WOLFSSL_SP_INT_NEGATIVE)
c->sign = neg;
#endif
}
else {
res = MP_VAL;
}
}
}
else {
res = MP_MEM;
}
XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT);
}
else {
#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
res = wolfcrypt_mp_mod(a, b, c);
#else
res = NOT_COMPILED_IN;
#endif
}
#ifdef ENABLE_NXPLTC_TESTS
if (doLtcTest && mp_cmp(&t, c) != MP_EQ) {
printf("mp_mod test fail!\n");
mp_dump("C", c, 0);
mp_dump("C soft", &t, 0);
}
mp_clear(&t);
#endif
return res;
}
int mp_invmod(mp_int *a, mp_int *b, mp_int *c)
{
int res = MP_OKAY;
int szA, szB;
#ifdef ENABLE_NXPLTC_TESTS
mp_int t;
mp_init(&t);
if (doLtcTest)
wolfcrypt_mp_invmod(a, b, &t);
#endif
szA = mp_unsigned_bin_size(a);
szB = mp_unsigned_bin_size(b);
if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) {
uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
DYNAMIC_TYPE_BIGINT);
if (ptrA && ptrB && ptrC) {
uint16_t sizeA, sizeB, sizeC;
res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA);
if (res == MP_OKAY)
res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB);
if (res == MP_OKAY &&
LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrB, sizeB) >= 0) {
if (LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB,
ptrA, &sizeA, kLTC_PKHA_IntegerArith) != kStatus_Success) {
res = MP_VAL;
}
}
if (res == MP_OKAY) {
if (LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC,
&sizeC, kLTC_PKHA_IntegerArith) == kStatus_Success) {
ltc_reverse_array(ptrC, sizeC);
res = mp_read_unsigned_bin(c, ptrC, sizeC);
#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
defined(WOLFSSL_SP_INT_NEGATIVE)
c->sign = a->sign;
#endif
}
else {
res = MP_VAL;
}
}
}
else {
res = MP_MEM;
}
XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT);
}
else {
#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
res = wolfcrypt_mp_invmod(a, b, c);
#else
res = NOT_COMPILED_IN;
#endif
}
#ifdef ENABLE_NXPLTC_TESTS
if (doLtcTest && mp_cmp(&t, c) != MP_EQ) {
printf("mp_invmod test fail!\n");
mp_dump("C", c, 0);
mp_dump("C soft", &t, 0);
}
mp_clear(&t);
#endif
return res;
}
int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
{
int res = MP_OKAY;
status_t status;
int szA, szB, szC;
#ifdef ENABLE_NXPLTC_TESTS
mp_int t;
mp_init(&t);
if (doLtcTest)
wolfcrypt_mp_mulmod(a, b, c, &t);
#endif
szA = mp_unsigned_bin_size(a);
szB = mp_unsigned_bin_size(b);
szC = mp_unsigned_bin_size(c);
if ((szA + szB < LTC_MAX_INT_BYTES-1) && (szC <= LTC_MAX_INT_BYTES))
{
uint8_t *ptrA, *ptrB, *ptrC, *ptrD;
ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
ptrD = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
if (ptrA && ptrB && ptrC && ptrD) {
uint16_t sizeA, sizeB, sizeC, sizeD = 0;
#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
defined(WOLFSSL_SP_INT_NEGATIVE)
int neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
#endif
res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA);
if (res == MP_OKAY)
res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB);
if (res == MP_OKAY) {
sizeC = sizeA + sizeB;
XMEMSET(ptrC, 0xFF, sizeC);
XMEMSET(ptrD, 0, LTC_MAX_INT_BYTES);
status = LTC_PKHA_ModMul(LTC_BASE,
ptrA, sizeA,
ptrB, sizeB,
ptrC, sizeC,
ptrD, &sizeD,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
if (status != kStatus_Success)
res = MP_VAL;
}
if (res == MP_OKAY)
res = ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC);
if (res == MP_OKAY) {
status = LTC_PKHA_ModRed(LTC_BASE,
ptrD, sizeD,
ptrC, sizeC,
ptrD, &sizeD,
kLTC_PKHA_IntegerArith);
if (status != kStatus_Success)
res = MP_VAL;
}
if (res == MP_OKAY) {
ltc_reverse_array(ptrD, sizeD);
res = mp_read_unsigned_bin(d, ptrD, sizeD);
#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
defined(WOLFSSL_SP_INT_NEGATIVE)
d->sign = neg;
#endif
}
}
else {
res = MP_MEM;
}
XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrD, NULL, DYNAMIC_TYPE_BIGINT);
}
else {
#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
res = wolfcrypt_mp_mulmod(a, b, c, d);
#else
res = NOT_COMPILED_IN;
#endif
}
#ifdef ENABLE_NXPLTC_TESTS
if (doLtcTest && mp_cmp(&t, d) != MP_EQ) {
printf("mp_mulmod test fail!\n");
mp_dump("D", d, 0);
mp_dump("D soft", &t, 0);
}
mp_clear(&t);
#endif
return res;
}
int ltc_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int useConstTime)
{
int res = MP_OKAY;
int szG, szX, szP;
#ifdef ENABLE_NXPLTC_TESTS
mp_int t;
mp_init(&t);
if (doLtcTest)
wolfcrypt_mp_exptmod(G, X, P, &t);
#endif
szG = mp_unsigned_bin_size(G);
szX = mp_unsigned_bin_size(X);
szP = mp_unsigned_bin_size(P);
if ((szG <= LTC_MAX_INT_BYTES) &&
(szX <= LTC_MAX_INT_BYTES) &&
(szP <= LTC_MAX_INT_BYTES))
{
uint16_t sizeG, sizeX, sizeP, sizeY;
uint8_t *ptrG, *ptrX, *ptrP, *ptrY;
ptrG = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
ptrX = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
ptrP = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
ptrY = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
if (ptrG && ptrX && ptrP && ptrY) {
res = ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG);
if (res == MP_OKAY)
res = ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX);
if (res == MP_OKAY)
res = ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP);
if (res == MP_OKAY &&
LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) {
res = LTC_PKHA_ModRed(LTC_BASE,
ptrG, sizeG,
ptrP, sizeP,
ptrG, &sizeG, kLTC_PKHA_IntegerArith);
res = (res == kStatus_Success) ? MP_OKAY: MP_VAL;
}
if (res == MP_OKAY) {
res = LTC_PKHA_ModExp(LTC_BASE,
ptrG, sizeG,
ptrP, sizeP,
ptrX, sizeX,
ptrY, &sizeY,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
useConstTime ? kLTC_PKHA_TimingEqualized :
kLTC_PKHA_NoTimingEqualized);
res = (res == kStatus_Success) ? MP_OKAY: MP_VAL;
}
if (res == MP_OKAY) {
ltc_reverse_array(ptrY, sizeY);
res = mp_read_unsigned_bin(Y, ptrY, sizeY);
}
}
else {
res = MP_MEM;
}
XFREE(ptrY, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrP, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrX, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrG, NULL, DYNAMIC_TYPE_BIGINT);
}
else {
#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
res = wolfcrypt_mp_exptmod(G, X, P, Y);
#else
res = NOT_COMPILED_IN;
#endif
}
#ifdef ENABLE_NXPLTC_TESTS
if (doLtcTest && mp_cmp(&t, Y) != MP_EQ) {
printf("mp_exptmod test fail!\n");
mp_dump("Y", Y, 0);
mp_dump("Y soft", &t, 0);
}
mp_clear(&t);
#endif
return res;
}
int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y)
{
return ltc_mp_exptmod(G, X, P, Y, 1);
}
int mp_exptmod_nct(mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{
return ltc_mp_exptmod(G, X, P, Y, 0);
}
#if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || \
defined(WOLFSSL_KEY_GEN)
int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
{
int res = MP_OKAY;
int szA;
#ifdef ENABLE_NXPLTC_TESTS
int result_soft = 0;
if (doLtcTest)
mp_prime_is_prime_ex(a, t, &result_soft, rng);
#endif
szA = mp_unsigned_bin_size(a);
if (szA <= LTC_MAX_INT_BYTES) {
uint16_t sizeA, sizeB;
uint8_t *ptrA, *ptrB;
sizeB = mp_count_bits(a);
sizeB = (sizeB / 8) + ((sizeB % 8) ? 1 : 0);
ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
ptrB = (uint8_t*)XMALLOC(sizeB, NULL, DYNAMIC_TYPE_BIGINT);
if (ptrA == NULL || ptrB == NULL) {
res = MEMORY_E;
}
if (res == MP_OKAY) {
#ifndef WC_NO_RNG
res = wc_RNG_GenerateBlock(rng, ptrB, sizeB);
#else
res = NOT_COMPILED_IN;
#endif
}
if (res == MP_OKAY) {
res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA);
}
if (res == MP_OKAY) {
if (LTC_PKHA_PrimalityTest(LTC_BASE,
ptrB, sizeB,
(uint8_t*)&t, sizeof(t),
ptrA, sizeA,
(bool*)result) != kStatus_Success) {
res = MP_MEM;
}
}
XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
}
else {
#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
res = wolfcrypt_mp_prime_is_prime_ex(a, t, result, rng);
#else
res = NOT_COMPILED_IN;
#endif
}
#ifdef ENABLE_NXPLTC_TESTS
if (doLtcTest && *result != result_soft) {
printf("Fail! mp_prime_is_prime_ex %d != %d\n", *result, result_soft);
}
#endif
return res;
}
int mp_prime_is_prime(mp_int* a, int t, int* result)
{
return wolfcrypt_mp_prime_is_prime_ex(a, t, result, NULL);
}
#endif
#endif
#if defined(HAVE_ECC) && defined(FREESCALE_LTC_ECC)
static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz)
{
int res;
int szbin;
int offset;
szbin = mp_unsigned_bin_size(a);
offset = sz - szbin;
if (offset < 0)
offset = 0;
if (offset > sz)
offset = sz;
if (offset)
XMEMSET(dst, 0, offset);
res = mp_to_unsigned_bin(a, dst + offset);
if (res == MP_OKAY) {
ltc_reverse_array(dst, sz);
}
return res;
}
#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
#define ECC192
#endif
#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
#define ECC224
#endif
#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
#define ECC256
#endif
#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
#define ECC384
#endif
#ifdef ECC192
#ifndef NO_ECC_SECP
static const uint8_t ltc_secp192r1_modulus[24] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp192r1_r2modn[24] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp192r1_aCurveParam[24] = {
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp192r1_bCurveParam[24] = {
0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE, 0x49, 0x30, 0x24, 0x72,
0xAB, 0xE9, 0xA7, 0x0F, 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64};
#endif
#ifdef HAVE_ECC_KOBLITZ
static const uint8_t ltc_secp192k1_modulus[24] = {
0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp192k1_r2modn[24] = {
0xD1, 0x4F, 0x3C, 0x01, 0x92, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp192k1_aCurveParam[24] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp192k1_bCurveParam[24] = {
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
#endif
#ifdef ECC224
#ifndef NO_ECC_SECP
static const uint8_t ltc_secp224r1_modulus[28] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp224r1_r2modn[28] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp224r1_aCurveParam[28] = {
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp224r1_bCurveParam[28] = {
0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27, 0xBA, 0xD8,
0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50, 0x56, 0x32, 0x41, 0xF5,
0xAB, 0xB3, 0x04, 0x0C, 0x85, 0x0A, 0x05, 0xB4};
#endif
#ifdef HAVE_ECC_KOBLITZ
static const uint8_t ltc_secp224k1_modulus[28] = {
0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp224k1_r2modn[28] = {
0x69, 0x30, 0xC2, 0x02, 0x26, 0x35, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp224k1_aCurveParam[28] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp224k1_bCurveParam[28] = {
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
#endif
#ifdef ECC256
#ifndef NO_ECC_SECP
static const uint8_t ltc_secp256r1_modulus[32] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp256r1_r2modn[32] = {
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp256r1_aCurveParam[32] = {
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp256r1_bCurveParam[32] = {
0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B, 0xF6, 0xB0, 0x53,
0xCC, 0xB0, 0x06, 0x1D, 0x65, 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD,
0xEB, 0xB3, 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A};
#endif
#ifdef HAVE_ECC_KOBLITZ
static const uint8_t ltc_secp256k1_modulus[32] = {
0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const uint8_t ltc_secp256k1_r2modn[32] = {
0xA1, 0x90, 0x0E, 0x00, 0xA2, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp256k1_aCurveParam[32] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp256k1_bCurveParam[32] = {
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
#endif
#ifdef ECC384
#ifndef NO_ECC_SECP
static const uint8_t ltc_secp384r1_modulus[48] = {
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const uint8_t ltc_secp384r1_r2modn[48] = {
0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t ltc_secp384r1_aCurveParam[48] = {
0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const uint8_t ltc_secp384r1_bCurveParam[48] = {
0xef, 0x2a, 0xec, 0xd3, 0xed, 0xc8, 0x85, 0x2a, 0x9d, 0xd1, 0x2e, 0x8a,
0x8d, 0x39, 0x56, 0xc6, 0x5a, 0x87, 0x13, 0x50, 0x8f, 0x08, 0x14, 0x03,
0x12, 0x41, 0x81, 0xfe, 0x6e, 0x9c, 0x1d, 0x18, 0x19, 0x2d, 0xf8, 0xe3,
0x6b, 0x05, 0x8e, 0x98, 0xe4, 0xe7, 0x3e, 0xe2, 0xa7, 0x2f, 0x31, 0xb3};
#endif
#endif
static int ltc_get_ecc_specs(const uint8_t **modulus, const uint8_t **r2modn,
const uint8_t **aCurveParam, const uint8_t **bCurveParam, const uint8_t *prime,
int size)
{
switch (size) {
#ifdef ECC256
case 32:
#ifndef NO_ECC_SECP
if (XMEMCMP(prime, ltc_secp256r1_modulus, size) == 0) {
*modulus = ltc_secp256r1_modulus;
*r2modn = ltc_secp256r1_r2modn;
*aCurveParam = ltc_secp256r1_aCurveParam;
*bCurveParam = ltc_secp256r1_bCurveParam;
return 0;
}
#endif
#ifdef HAVE_ECC_KOBLITZ
if (XMEMCMP(prime, ltc_secp256k1_modulus, size) == 0) {
*modulus = ltc_secp256k1_modulus;
*r2modn = ltc_secp256k1_r2modn;
*aCurveParam = ltc_secp256k1_aCurveParam;
*bCurveParam = ltc_secp256k1_bCurveParam;
return 0;
}
#endif
break;
#endif
#ifdef ECC224
case 28:
#ifndef NO_ECC_SECP
if (XMEMCMP(prime, ltc_secp224r1_modulus, size) == 0) {
*modulus = ltc_secp224r1_modulus;
*r2modn = ltc_secp224r1_r2modn;
*aCurveParam = ltc_secp224r1_aCurveParam;
*bCurveParam = ltc_secp224r1_bCurveParam;
return 0;
}
#endif
#ifdef HAVE_ECC_KOBLITZ
if (XMEMCMP(prime, ltc_secp224k1_modulus, size) == 0) {
*modulus = ltc_secp224k1_modulus;
*r2modn = ltc_secp224k1_r2modn;
*aCurveParam = ltc_secp224k1_aCurveParam;
*bCurveParam = ltc_secp224k1_bCurveParam;
return 0;
}
#endif
break;
#endif
#ifdef ECC192
case 24:
#ifndef NO_ECC_SECP
if (XMEMCMP(prime, ltc_secp192r1_modulus, size) == 0) {
*modulus = ltc_secp192r1_modulus;
*r2modn = ltc_secp192r1_r2modn;
*aCurveParam = ltc_secp192r1_aCurveParam;
*bCurveParam = ltc_secp192r1_bCurveParam;
return 0;
}
#endif
#ifdef HAVE_ECC_KOBLITZ
if (XMEMCMP(prime, ltc_secp192k1_modulus, size) == 0) {
*modulus = ltc_secp192k1_modulus;
*r2modn = ltc_secp192k1_r2modn;
*aCurveParam = ltc_secp192k1_aCurveParam;
*bCurveParam = ltc_secp192k1_bCurveParam;
return 0;
}
#endif
break;
#endif
#ifdef ECC384
case 48:
#ifndef NO_ECC_SECP
if (XMEMCMP(prime, ltc_secp384r1_modulus, size) == 0) {
*modulus = ltc_secp384r1_modulus;
*r2modn = ltc_secp384r1_r2modn;
*aCurveParam = ltc_secp384r1_aCurveParam;
*bCurveParam = ltc_secp384r1_bCurveParam;
return 0;
}
#endif
break;
#endif
default:
break;
}
return -1;
}
int wc_ecc_mulmod_ex(const mp_int *k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int *modulus, int map, void* heap)
{
ltc_pkha_ecc_point_t B;
uint8_t size;
int szModulus;
int szkbin;
bool point_of_infinity;
status_t status;
int res;
uint8_t Gxbin[LTC_MAX_ECC_BITS / 8];
uint8_t Gybin[LTC_MAX_ECC_BITS / 8];
uint8_t kbin[LTC_MAX_INT_BYTES];
const uint8_t *modbin;
const uint8_t *aCurveParam;
const uint8_t *bCurveParam;
const uint8_t *r2modn;
(void)a;
(void)heap;
if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
return ECC_BAD_ARG_E;
}
szModulus = mp_unsigned_bin_size(modulus);
szkbin = mp_unsigned_bin_size(k);
if (szModulus > LTC_MAX_INT_BYTES / 2) {
return MP_MEM;
}
res = ltc_get_from_mp_int(kbin, (mp_int*)k, szkbin);
if (res == MP_OKAY)
res = ltc_get_from_mp_int(Gxbin, G->x, szModulus);
if (res == MP_OKAY)
res = ltc_get_from_mp_int(Gybin, G->y, szModulus);
if (res != MP_OKAY)
return res;
size = szModulus;
if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam,
(const uint8_t *)modulus->dp, size) != 0) {
return ECC_BAD_ARG_E;
}
B.X = &Gxbin[0];
B.Y = &Gybin[0];
status = LTC_PKHA_ECC_PointMul(LTC_BASE, &B, kbin, szkbin, modbin, r2modn,
aCurveParam, bCurveParam, size, kLTC_PKHA_TimingEqualized,
kLTC_PKHA_IntegerArith, &B, &point_of_infinity);
if (status != kStatus_Success) {
return MP_VAL;
}
ltc_reverse_array(Gxbin, size);
ltc_reverse_array(Gybin, size);
res = mp_read_unsigned_bin(R->x, Gxbin, size);
if (res == MP_OKAY) {
res = mp_read_unsigned_bin(R->y, Gybin, size);
#if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
defined(WOLFSSL_SP_INT_NEGATIVE)
R->y->sign = k->sign;
#endif
}
if (res == MP_OKAY)
res = mp_set(R->z, 1);
return res;
}
int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int* modulus, mp_int* order, WC_RNG* rng, int map,
void* heap)
{
(void)order;
(void)rng;
return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, heap);
}
int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
{
(void)P;
(void)modulus;
(void)mp;
(void)ct;
return MP_OKAY;
}
int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m)
{
int res;
ltc_pkha_ecc_point_t A, B;
int size;
status_t status;
uint8_t Gxbin[LTC_MAX_ECC_BITS / 8];
uint8_t Gybin[LTC_MAX_ECC_BITS / 8];
uint8_t Qxbin[LTC_MAX_ECC_BITS / 8];
uint8_t Qybin[LTC_MAX_ECC_BITS / 8];
const uint8_t *modbin;
const uint8_t *aCurveParam;
const uint8_t *bCurveParam;
const uint8_t *r2modn;
size = mp_unsigned_bin_size(m);
if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam,
(const uint8_t *)m->dp, size) != 0) {
res = ECC_BAD_ARG_E;
}
else {
res = ltc_get_from_mp_int(Gxbin, mG->x, size);
if (res == MP_OKAY)
res = ltc_get_from_mp_int(Gybin, mG->y, size);
if (res == MP_OKAY)
res = ltc_get_from_mp_int(Qxbin, mQ->x, size);
if (res == MP_OKAY)
res = ltc_get_from_mp_int(Qybin, mQ->y, size);
if (res != MP_OKAY)
return res;
A.X = Gxbin;
A.Y = Gybin;
B.X = Qxbin;
B.Y = Qybin;
status = LTC_PKHA_ECC_PointAdd(LTC_BASE, &A, &B, modbin, r2modn,
aCurveParam, bCurveParam, size, kLTC_PKHA_IntegerArith, &A);
if (status != kStatus_Success) {
res = MP_VAL;
}
else {
ltc_reverse_array(Gxbin, size);
ltc_reverse_array(Gybin, size);
res = mp_read_unsigned_bin(mR->x, Gxbin, size);
if (res == MP_OKAY)
res = mp_read_unsigned_bin(mR->y, Gybin, size);
if (res == MP_OKAY)
res = mp_set(mR->z, 1);
}
}
return res;
}
#if defined(HAVE_ED25519) || defined(HAVE_CURVE25519)
static const uint8_t curve25519_modbin[32] = {
0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
static const uint8_t r2mod[32] = {
0xa4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t invThree[32] = {
0x49, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
status_t LTC_PKHA_Prime25519SquareRootMod(const uint8_t *A, size_t sizeA,
uint8_t *res, size_t *szRes, int sign)
{
status_t status;
const uint8_t curve25519_param[] = {
0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f};
uint8_t twoA[sizeof(curve25519_modbin)] = {0};
uint8_t V[sizeof(curve25519_modbin)] = {0};
uint8_t I[sizeof(curve25519_modbin)] = {0};
uint8_t VV[sizeof(curve25519_modbin)] = {0};
uint16_t szTwoA = 0;
uint16_t szV = 0;
uint16_t szVV = 0;
uint16_t szI = 0;
uint16_t szRes16 = 0;
uint8_t one = 1;
status = LTC_PKHA_ModAdd(LTC_BASE, A, sizeA, A, sizeA, curve25519_modbin,
sizeof(curve25519_modbin), twoA, &szTwoA, kLTC_PKHA_IntegerArith);
if (status == kStatus_Success) {
status =
LTC_PKHA_ModExp(LTC_BASE, twoA, szTwoA, curve25519_modbin,
sizeof(curve25519_modbin), curve25519_param,
sizeof(curve25519_param), V, &szV, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, V, szV, V, szV, curve25519_modbin,
sizeof(curve25519_modbin), VV, &szVV, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, twoA, szTwoA, VV, szVV,
curve25519_modbin, sizeof(curve25519_modbin), I, &szI,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
XMEMSET(VV, 0xff, sizeof(VV));
if (LTC_PKHA_CompareBigNum(I, szI, &one, sizeof(one)) >= 0) {
if (status == kStatus_Success) {
status = LTC_PKHA_ModSub1(LTC_BASE, I, szI, &one, sizeof(one),
VV, sizeof(VV), I, &szI);
}
}
else {
if (status == kStatus_Success) {
status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin,
sizeof(curve25519_modbin), &one, sizeof(one), VV, sizeof(VV), I,
&szI);
}
}
status = LTC_PKHA_ModMul(LTC_BASE, A, sizeA, V, szV, curve25519_modbin,
sizeof(curve25519_modbin), res, &szRes16, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, res, szRes16, I, szI,
curve25519_modbin, sizeof(curve25519_modbin), res, &szRes16,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if ((status == kStatus_Success) &&
((bool)sign != (bool)(res[0] & 0x01u)))
{
status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin,
sizeof(curve25519_modbin), res, szRes16, VV, sizeof(VV), res,
&szRes16);
}
if (status == kStatus_Success) {
*szRes = szRes16;
}
return status;
}
#endif
#ifdef HAVE_CURVE25519
static const ECPoint ecBasePoint = {
{0x5a, 0x24, 0xad, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a},
{0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c,
0x6d, 0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd,
0x1e, 0xe0, 0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20},
};
const ECPoint *nxp_ltc_curve25519_GetBasePoint(void)
{
return &ecBasePoint;
}
static const uint8_t curve25519_aCurveParam[CURVE25519_KEYSIZE] = {
0x44, 0xa1, 0x14, 0x49, 0x98, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0x2a};
static const uint8_t curve25519_bCurveParam[CURVE25519_KEYSIZE] = {
0x64, 0xc8, 0x10, 0x77, 0x9c, 0x5e, 0x0b, 0x26, 0xb4, 0x97, 0xd0,
0x5e, 0x42, 0x7b, 0x09, 0xed,
0x25, 0xb4, 0x97, 0xd0, 0x5e, 0x42, 0x7b, 0x09, 0xed, 0x25, 0xb4,
0x97, 0xd0, 0x5e, 0x42, 0x7b};
status_t LTC_PKHA_Curve25519ToWeierstrass(
const ltc_pkha_ecc_point_t *ltcPointIn,ltc_pkha_ecc_point_t *ltcPointOut)
{
const uint8_t offset[] = {
0x51, 0x24, 0xad, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a};
uint16_t sizeRes = 0;
status_t status;
status = LTC_PKHA_ModAdd(LTC_BASE, ltcPointIn->X, CURVE25519_KEYSIZE,
offset, sizeof(offset), curve25519_modbin, CURVE25519_KEYSIZE,
ltcPointOut->X, &sizeRes, kLTC_PKHA_IntegerArith);
if (status == kStatus_Success) {
if (ltcPointOut->Y != ltcPointIn->Y) {
XMEMCPY(ltcPointOut->Y, ltcPointIn->Y, CURVE25519_KEYSIZE);
}
}
return status;
}
status_t LTC_PKHA_WeierstrassToCurve25519(
const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut)
{
status_t status;
uint16_t resultSize = 0;
const uint8_t three = 0x03;
status = LTC_PKHA_ModMul(LTC_BASE, &three, sizeof(three), ltcPointIn->X,
CURVE25519_KEYSIZE, curve25519_modbin, CURVE25519_KEYSIZE,
ltcPointOut->X, &resultSize, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
if (status == kStatus_Success) {
const uint8_t A[] = {0x06, 0x6d, 0x07};
if (LTC_PKHA_CompareBigNum(ltcPointOut->X, resultSize, A, sizeof(A))) {
status = LTC_PKHA_ModSub1(LTC_BASE, ltcPointOut->X, resultSize, A,
sizeof(A), curve25519_modbin, CURVE25519_KEYSIZE,
ltcPointOut->X, &resultSize);
}
else {
status = LTC_PKHA_ModSub2(LTC_BASE, ltcPointOut->X, resultSize, A,
sizeof(A), curve25519_modbin, CURVE25519_KEYSIZE,
ltcPointOut->X, &resultSize);
}
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, invThree, CURVE25519_KEYSIZE,
ltcPointOut->X, resultSize, curve25519_modbin, CURVE25519_KEYSIZE,
ltcPointOut->X, &resultSize, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
if (ltcPointOut->Y != ltcPointIn->Y) {
XMEMCPY(ltcPointOut->Y, ltcPointIn->Y, CURVE25519_KEYSIZE);
}
}
return status;
}
status_t LTC_PKHA_Curve25519ComputeY(ltc_pkha_ecc_point_t *ltcPoint)
{
uint8_t three = 3;
const uint8_t A[] = {0x06, 0x6d, 0x07};
uint8_t U[CURVE25519_KEYSIZE] = {0};
uint8_t X2[CURVE25519_KEYSIZE] = {0};
uint16_t sizeU = 0;
uint16_t sizeX2 = 0;
size_t szRes = 0;
status_t status;
status = LTC_PKHA_ModExp(LTC_BASE, ltcPoint->X, CURVE25519_KEYSIZE,
curve25519_modbin, CURVE25519_KEYSIZE, &three, 1, U, &sizeU,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, ltcPoint->X, CURVE25519_KEYSIZE,
ltcPoint->X, CURVE25519_KEYSIZE, curve25519_modbin,
CURVE25519_KEYSIZE, X2, &sizeX2, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, A, sizeof(A), X2, sizeX2,
curve25519_modbin, CURVE25519_KEYSIZE, X2, &sizeX2,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModAdd(LTC_BASE, U, sizeU, X2, sizeX2,
curve25519_modbin, CURVE25519_KEYSIZE, U, &sizeU,
kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModAdd(LTC_BASE, U, sizeU, ltcPoint->X,
CURVE25519_KEYSIZE, curve25519_modbin, CURVE25519_KEYSIZE, U,
&sizeU, kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_Prime25519SquareRootMod(U, sizeU, ltcPoint->Y,
&szRes, 1);
}
return status;
}
int nxp_ltc_curve25519(ECPoint *q, const byte *n, const ECPoint *p,
fsl_ltc_ecc_coordinate_system_t type)
{
status_t status;
ltc_pkha_ecc_point_t ltcPoint;
ltc_pkha_ecc_point_t ltcPointOut;
ECPoint pIn = {{0}};
XMEMCPY(&pIn, p, sizeof(*p));
ltcPoint.X = &pIn.point[0];
ltcPoint.Y = &pIn.pointY[0];
if (type == kLTC_Curve25519) {
LTC_PKHA_Curve25519ToWeierstrass(<cPoint, <cPoint);
}
ltcPointOut.X = &q->point[0];
ltcPointOut.Y = &q->pointY[0];
status = LTC_PKHA_ECC_PointMul(LTC_BASE, <cPoint, n, CURVE25519_KEYSIZE,
curve25519_modbin, r2mod, curve25519_aCurveParam,
curve25519_bCurveParam, CURVE25519_KEYSIZE, kLTC_PKHA_TimingEqualized,
kLTC_PKHA_IntegerArith, <cPointOut, NULL);
if (status == kStatus_Success) {
status = LTC_PKHA_WeierstrassToCurve25519(<cPointOut, <cPointOut);
}
return (status == kStatus_Success) ? 0 : IS_POINT_E;
}
#endif
#ifdef HAVE_ED25519
static const uint8_t d_coefEd25519[] = {
0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, 0xab, 0xd8, 0x41,
0x41, 0x4d, 0x0a, 0x70, 0x00, 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40,
0xc7, 0x8c, 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52};
static const uint8_t A_coefEd25519[] = {
0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const uint8_t B_coefEd25519[] = {
0xe5, 0x92, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
static const uint8_t threeB_coefEd25519[] = {
0xd5, 0xb8, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
static const uint8_t minus_A_coefEd25519[] = {
0xe7, 0x92, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
static const uint8_t invB_coefEd25519[] = {
0xc4, 0xa1, 0x29, 0x7b, 0x8d, 0x2c, 0x85, 0x22, 0xd5, 0x89, 0xaf,
0xaf, 0x6c, 0xfd, 0xe3, 0xff, 0xd9, 0x85, 0x21, 0xa2, 0xe1, 0x2f,
0xce, 0x1c, 0x63, 0x00, 0x24, 0x75, 0xc4, 0x24, 0x7f, 0x6b};
static const uint8_t A_mul_invThreeB_coefEd25519[] = {
0xb9, 0x3e, 0xe4, 0xad, 0xa1, 0x37, 0xa7, 0x93, 0x1c, 0xa4, 0x35,
0xe0, 0x0c, 0x57, 0xbd, 0xaa, 0x6e, 0x51, 0x94, 0x3e, 0x14, 0xe0,
0xcb, 0xec, 0xbd, 0xff, 0xe7, 0xb1, 0x27, 0x92, 0x00, 0x63};
static const uint8_t a_coefEd25519[] = {
0x2d, 0x17, 0xbc, 0xf8, 0x8e, 0xe1, 0x71, 0xac, 0xf7, 0x2a, 0xa5,
0x0c, 0x5d, 0xb6, 0xb8, 0x6b, 0xd6, 0x3d, 0x7b, 0x61, 0x0d, 0xe1,
0x97, 0x31, 0xe6, 0xbe, 0xb9, 0xa5, 0xd3, 0xac, 0x4e, 0x5d};
static const uint8_t b_coefEd25519[] = {
0xa4, 0xb2, 0x64, 0xf3, 0xc1, 0xeb, 0x04, 0x90, 0x32, 0xbc, 0x9f,
0x6b, 0x97, 0x31, 0x48, 0xf5, 0xd5, 0x80, 0x57, 0x10, 0x06, 0xdb,
0x0d, 0x55, 0xe0, 0xb3, 0xd0, 0xcf, 0x9b, 0xb2, 0x11, 0x1d};
static uint8_t Wx_Ed25519[ED25519_KEY_SIZE] = {
0x35, 0xef, 0x5a, 0x02, 0x9b, 0xc8, 0x55, 0xca, 0x9a, 0x7c, 0x61,
0x0d, 0xdf, 0x3f, 0xc1, 0xa9, 0x18, 0x06, 0xc2, 0xf1, 0x02, 0x8f,
0x0b, 0xf0, 0x39, 0x03, 0x2c, 0xd0, 0x0f, 0xdd, 0x78, 0x2a};
static uint8_t Wy_Ed25519[ED25519_KEY_SIZE] = {
0x14, 0x1d, 0x2c, 0xf6, 0xf3, 0x30, 0x78, 0x9b, 0x65, 0x31, 0x71,
0x80, 0x61, 0xd0, 0x6f, 0xcf, 0x23, 0x83, 0x79, 0x63, 0xa5, 0x3b,
0x48, 0xbe, 0x2e, 0xa2, 0x1d, 0xc7, 0xa5, 0x44, 0xc6, 0x29};
static const ltc_pkha_ecc_point_t basepointEd25519 = {
Wx_Ed25519, Wy_Ed25519,
};
const ltc_pkha_ecc_point_t *LTC_PKHA_Ed25519_BasePoint(void)
{
return &basepointEd25519;
}
status_t LTC_PKHA_Ed25519_PointMul(const ltc_pkha_ecc_point_t *ltcPointIn,
const uint8_t *N,
size_t sizeN,
ltc_pkha_ecc_point_t *ltcPointOut,
fsl_ltc_ecc_coordinate_system_t typeOut)
{
uint16_t szN = (uint16_t)sizeN;
status_t status;
status = LTC_PKHA_ECC_PointMul(LTC_BASE, ltcPointIn, N, szN,
curve25519_modbin, r2mod, a_coefEd25519, b_coefEd25519,
ED25519_KEY_SIZE, kLTC_PKHA_TimingEqualized, kLTC_PKHA_IntegerArith,
ltcPointOut, NULL);
if ((status == kStatus_Success) && (typeOut == kLTC_Ed25519)) {
status = LTC_PKHA_WeierstrassToEd25519(ltcPointOut, ltcPointOut);
}
return status;
}
status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn,
ltc_pkha_ecc_point_t *ltcPointOut)
{
status_t status;
uint8_t Mx[ED25519_KEY_SIZE] = {0};
uint8_t My[ED25519_KEY_SIZE] = {0};
uint8_t temp[ED25519_KEY_SIZE] = {0};
uint8_t temp2[ED25519_KEY_SIZE] = {0};
const uint8_t max[32] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const uint8_t *Ex;
const uint8_t *Ey;
uint8_t *Gx;
uint8_t *Gy;
uint16_t szMx = 0;
uint16_t szGx = 0;
uint16_t szMy = 0;
uint16_t szGy = 0;
uint16_t szTemp = 0;
uint16_t szTemp2 = 0;
uint8_t one = 1;
Ex = ltcPointIn->X;
Ey = ltcPointIn->Y;
Gx = ltcPointOut->X;
Gy = ltcPointOut->Y;
status = LTC_PKHA_ModAdd(LTC_BASE, Ey, ED25519_KEY_SIZE, &one, sizeof(one),
curve25519_modbin, sizeof(curve25519_modbin), temp, &szTemp,
kLTC_PKHA_IntegerArith);
if (status == kStatus_Success) {
status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin,
sizeof(curve25519_modbin), Ey, ED25519_KEY_SIZE, max, sizeof(max),
temp2, &szTemp2);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModAdd(LTC_BASE, temp2, szTemp2, &one, sizeof(one),
curve25519_modbin, sizeof(curve25519_modbin), temp2, &szTemp2,
kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModInv(LTC_BASE, temp2, szTemp2, curve25519_modbin,
sizeof(curve25519_modbin), Mx, &szMx, kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, Mx, szMx, temp, szTemp,
curve25519_modbin, ED25519_KEY_SIZE, Mx, &szMx,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, Ex, ED25519_KEY_SIZE, temp2,
szTemp2, curve25519_modbin, ED25519_KEY_SIZE, My, &szMy,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModInv(LTC_BASE, My, szMy, curve25519_modbin,
sizeof(curve25519_modbin), My, &szMy, kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, My, szMy, temp, szTemp,
curve25519_modbin, ED25519_KEY_SIZE, My, &szMy,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, Mx, szMx, invB_coefEd25519,
sizeof(invB_coefEd25519), curve25519_modbin, ED25519_KEY_SIZE, Gx,
&szGx, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModAdd(LTC_BASE, Gx, szGx,
A_mul_invThreeB_coefEd25519, sizeof(A_mul_invThreeB_coefEd25519),
curve25519_modbin, sizeof(curve25519_modbin), Gx, &szGx,
kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, My, szMy, invB_coefEd25519,
sizeof(invB_coefEd25519), curve25519_modbin, ED25519_KEY_SIZE, Gy,
&szGy, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
return status;
}
status_t LTC_PKHA_WeierstrassToEd25519(const ltc_pkha_ecc_point_t *ltcPointIn,
ltc_pkha_ecc_point_t *ltcPointOut)
{
status_t status;
uint8_t Mx[ED25519_KEY_SIZE] = {0};
uint8_t My[ED25519_KEY_SIZE] = {0};
uint8_t temp[ED25519_KEY_SIZE] = {0};
const uint8_t *Gx;
const uint8_t *Gy;
uint8_t *Ex;
uint8_t *Ey;
uint16_t szMx = 0;
uint16_t szEx = 0;
uint16_t szMy = 0;
uint16_t szEy = 0;
uint16_t szTemp = 0;
uint8_t one = 1;
Gx = ltcPointIn->X;
Gy = ltcPointIn->Y;
Ex = ltcPointOut->X;
Ey = ltcPointOut->Y;
status = LTC_PKHA_ModMul(LTC_BASE, B_coefEd25519, sizeof(B_coefEd25519),
Gy, ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, My, &szMy,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, threeB_coefEd25519,
sizeof(threeB_coefEd25519), Gx, ED25519_KEY_SIZE, curve25519_modbin,
ED25519_KEY_SIZE, temp, &szTemp, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModAdd(LTC_BASE, temp, szTemp, minus_A_coefEd25519,
sizeof(minus_A_coefEd25519), curve25519_modbin,
sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, invThree,
sizeof(invThree), curve25519_modbin, sizeof(curve25519_modbin), Mx,
&szMx, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModInv(LTC_BASE, My, szMy, curve25519_modbin,
sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, Mx, szMx,
curve25519_modbin, sizeof(curve25519_modbin), Ex, &szEx,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModAdd(LTC_BASE, Mx, szMx, &one, sizeof(one),
curve25519_modbin, sizeof(curve25519_modbin), temp, &szTemp,
kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModInv(LTC_BASE, temp, szTemp, curve25519_modbin,
sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
if (LTC_PKHA_CompareBigNum(Mx, szMx, &one, sizeof(one)) >= 0) {
status = LTC_PKHA_ModSub1(LTC_BASE, Mx, szMx, &one, sizeof(one),
curve25519_modbin, sizeof(curve25519_modbin), Mx, &szMx);
}
else {
XMEMCPY(Mx, curve25519_modbin, sizeof(curve25519_modbin));
Mx[0]--;
}
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, Mx, szMx,
curve25519_modbin, sizeof(curve25519_modbin), Ey, &szEy,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
return status;
}
status_t LTC_PKHA_Ed25519_PointDecompress(const uint8_t *pubkey,
size_t pubKeySize, ltc_pkha_ecc_point_t *ltcPointOut)
{
status_t status;
const uint8_t one = 1;
XMEMCPY(ltcPointOut->Y, pubkey, pubKeySize);
ltcPointOut->Y[pubKeySize - 1] &= ~0x80u;
int sign = (int)(bool)(pubkey[pubKeySize - 1] & 0x80u);
uint8_t U[ED25519_KEY_SIZE] = {0};
uint8_t V[ED25519_KEY_SIZE] = {0};
uint8_t *X = ltcPointOut->X;
uint8_t *Y = ltcPointOut->Y;
uint16_t szU = 0;
uint16_t szV = 0;
size_t szRes = 0;
status = LTC_PKHA_ModMul(LTC_BASE, Y, ED25519_KEY_SIZE, Y,
ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, U, &szU,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
XMEMCPY(V, U, szU);
szV = szU;
if (status == kStatus_Success) {
if (LTC_PKHA_CompareBigNum(U, szU, &one, sizeof(one)) >= 0) {
status = LTC_PKHA_ModSub1(LTC_BASE, U, szU, &one, sizeof(one),
curve25519_modbin, sizeof(curve25519_modbin), U, &szU);
}
else {
XMEMCPY(U, curve25519_modbin, sizeof(curve25519_modbin));
U[0]--;
}
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, V, szV, d_coefEd25519,
ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, V, &szV,
kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModAdd(LTC_BASE, V, szV, &one, sizeof(one),
curve25519_modbin, sizeof(curve25519_modbin), V, &szV,
kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModInv(LTC_BASE, V, szV, curve25519_modbin,
sizeof(curve25519_modbin), V, &szV, kLTC_PKHA_IntegerArith);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, V, szV, U, szU, curve25519_modbin,
ED25519_KEY_SIZE, U, &szU, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_Prime25519SquareRootMod(U, szU, X, &szRes, sign);
}
return status;
}
static const uint8_t l_coefEdDSA[] = {
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
status_t LTC_PKHA_sc_reduce(uint8_t *a)
{
uint16_t szA = 0;
return LTC_PKHA_ModRed(LTC_BASE, a, 64, l_coefEdDSA, sizeof(l_coefEdDSA),
a, &szA, kLTC_PKHA_IntegerArith);
}
status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a,
const uint8_t *b, const uint8_t *c)
{
uint16_t szS = 0;
uint16_t szB = 0;
uint8_t tempB[32] = {0};
status_t status;
status = LTC_PKHA_ModRed(LTC_BASE, b, 32, l_coefEdDSA, sizeof(l_coefEdDSA),
tempB, &szB, kLTC_PKHA_IntegerArith);
if (status == kStatus_Success) {
status = LTC_PKHA_ModMul(LTC_BASE, a, 32, tempB, szB, l_coefEdDSA,
sizeof(l_coefEdDSA), s, &szS, kLTC_PKHA_IntegerArith,
kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
kLTC_PKHA_TimingEqualized);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModAdd(LTC_BASE, s, szS, c, 32, l_coefEdDSA, 32, s,
&szS, kLTC_PKHA_IntegerArith);
}
return status;
}
status_t LTC_PKHA_SignatureForVerify(uint8_t *rcheck, const unsigned char *a,
const unsigned char *b, ed25519_key *key)
{
uint8_t X0[ED25519_PUB_KEY_SIZE] = {0};
uint8_t X1[ED25519_PUB_KEY_SIZE] = {0};
uint8_t Y0[ED25519_PUB_KEY_SIZE] = {0};
uint8_t Y1[ED25519_PUB_KEY_SIZE] = {0};
const uint8_t max[32] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
ltc_pkha_ecc_point_t ltc0;
ltc_pkha_ecc_point_t ltc1;
ltc_pkha_ecc_point_t pubKey;
status_t status;
uint16_t szY = 32;
ltc0.X = X0;
ltc1.X = X1;
ltc0.Y = Y0;
ltc1.Y = Y1;
pubKey.X = key->pointX;
pubKey.Y = key->pointY;
status = LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), b,
ED25519_KEY_SIZE, <c0, kLTC_Weierstrass );
if (status == kStatus_Success) {
status = LTC_PKHA_Ed25519ToWeierstrass(&pubKey, <c1);
}
if (status == kStatus_Success) {
status = LTC_PKHA_Ed25519_PointMul(<c1, a, ED25519_KEY_SIZE, <c1,
kLTC_Weierstrass );
}
if (status == kStatus_Success) {
status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin,
sizeof(curve25519_modbin), ltc1.Y, szY, max, sizeof(max), ltc1.Y,
&szY);
}
if (status == kStatus_Success) {
status = LTC_PKHA_ECC_PointAdd(LTC_BASE, <c0, <c1,
curve25519_modbin, r2mod, a_coefEd25519, b_coefEd25519,
ED25519_KEY_SIZE, kLTC_PKHA_IntegerArith, <c0);
}
if (status == kStatus_Success) {
status = LTC_PKHA_WeierstrassToEd25519(<c0, <c0);
}
if (status == kStatus_Success) {
if (((uint32_t)ltc0.X[0]) & 0x01u) {
ltc0.Y[ED25519_KEY_SIZE - 1] |= 0x80u;
}
XMEMCPY(rcheck, ltc0.Y, ED25519_KEY_SIZE);
}
return status;
}
status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn,
uint8_t *p)
{
XMEMCPY(p, ltcPointIn->Y, ED25519_KEY_SIZE);
if (((uint32_t)ltcPointIn->X[0]) & 0x01u) {
p[ED25519_KEY_SIZE - 1] |= 0x80u;
}
return kStatus_Success;
}
#endif
#endif
#undef ERROR_OUT
#endif