From 64ae0a827cfd05bd0b3b85639e39ad8c4cf06eb1 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 16 Apr 2021 11:29:03 -0700 Subject: [PATCH] Fixes for RSA with NXP LTC. The invmod function must reduce if A > B. Added RSA Key Generation acceleration. --- wolfcrypt/src/integer.c | 2 +- wolfcrypt/src/port/nxp/ksdk_port.c | 178 +++++++++++++++++++++-------- wolfcrypt/src/rsa.c | 4 +- wolfcrypt/src/tfm.c | 15 ++- wolfcrypt/test/test.c | 3 +- 5 files changed, 151 insertions(+), 51 deletions(-) diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 5dd9e15fc..852ff5969 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -1450,7 +1450,7 @@ int mp_is_bit_set (mp_int *a, mp_digit b) mp_digit s = b % DIGIT_BIT; /* bit index */ if ((mp_digit)a->used <= i) { - /* no words avaialable at that bit count */ + /* no words available at that bit count */ return 0; } diff --git a/wolfcrypt/src/port/nxp/ksdk_port.c b/wolfcrypt/src/port/nxp/ksdk_port.c index be8cbe1de..4daf3d92f 100644 --- a/wolfcrypt/src/port/nxp/ksdk_port.c +++ b/wolfcrypt/src/port/nxp/ksdk_port.c @@ -129,9 +129,9 @@ int mp_mul(mp_int *A, mp_int *B, mp_int *C) #endif /* unsigned multiply */ - 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); + 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; @@ -142,9 +142,10 @@ int mp_mul(mp_int *A, mp_int *B, mp_int *C) if (res == MP_OKAY) { XMEMSET(ptrC, 0xFF, LTC_MAX_INT_BYTES); - LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, LTC_MAX_INT_BYTES, ptrB, &sizeB, - kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, - kLTC_PKHA_TimingEqualized); + LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, + LTC_MAX_INT_BYTES, ptrB, &sizeB, kLTC_PKHA_IntegerArith, + kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); ltc_reverse_array(ptrB, sizeB); res = mp_read_unsigned_bin(C, ptrB, sizeB); @@ -185,9 +186,9 @@ int mp_mod(mp_int *a, mp_int *b, mp_int *c) if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { int neg = 0; - 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); + 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); #ifndef WOLFSSL_SP_MATH /* get sign for the result */ @@ -203,7 +204,8 @@ int mp_mod(mp_int *a, mp_int *b, mp_int *c) 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_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); @@ -251,9 +253,9 @@ int mp_invmod(mp_int *a, mp_int *b, mp_int *c) 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); + 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; @@ -261,10 +263,18 @@ int mp_invmod(mp_int *a, mp_int *b, mp_int *c) 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 a >= b then reduce */ + 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 (kStatus_Success == - LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) - { + 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); } @@ -308,13 +318,15 @@ int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) szA = mp_unsigned_bin_size(a); szB = mp_unsigned_bin_size(b); szC = mp_unsigned_bin_size(c); - if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { + if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && + (szC <= LTC_MAX_INT_BYTES)) + { mp_int t; - 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); - uint8_t *ptrD = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + 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); + uint8_t *ptrD = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); /* if A or B is negative, subtract abs(A) or abs(B) from modulus to get * positive integer representation of the same number */ @@ -344,7 +356,8 @@ int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) res = ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC); /* (A*B)mod C = ((A mod C) * (B mod C)) mod C */ - if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, sizeC) >= 0) { + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, + sizeC) >= 0) { if (kStatus_Success != LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrC, sizeC, ptrA, &sizeA, kLTC_PKHA_IntegerArith)) @@ -352,8 +365,8 @@ int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) res = MP_VAL; } } - if (res == MP_OKAY && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, sizeC) >= 0)) - { + if (res == MP_OKAY && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, + sizeC) >= 0)) { if (kStatus_Success != LTC_PKHA_ModRed(LTC_BASE, ptrB, sizeB, ptrC, sizeC, ptrB, &sizeB, kLTC_PKHA_IntegerArith)) @@ -413,7 +426,9 @@ int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) { int res = MP_OKAY; int szA, szB, szC; +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) mp_int tmp; +#endif /* if G cannot fit into LTC_PKHA, reduce it */ szA = mp_unsigned_bin_size(G); @@ -432,15 +447,16 @@ int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) szB = mp_unsigned_bin_size(X); szC = mp_unsigned_bin_size(P); - if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && + if ((szA <= LTC_MAX_INT_BYTES) && + (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { mp_int t; uint16_t sizeG, sizeX, sizeP; - uint8_t *ptrG = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrX = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); - uint8_t *ptrP = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + uint8_t *ptrG = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + uint8_t *ptrX = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); + uint8_t *ptrP = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); /* if G is negative, add modulus to convert to positive number for LTC */ res = mp_init(&t); @@ -460,29 +476,27 @@ int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) if (res == MP_OKAY) res = ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP); - /* if number if greater that modulo, we must first reduce due to - LTC requirement on modular exponentiation */ + /* if number if greater that modulo, we must first reduce due to LTC + requirement on modular exponentiation */ /* it needs number less than modulus. */ - /* we can take advantage of modular arithmetic rule that: A^B mod C = ( (A mod C)^B ) mod C - and so we do first (A mod N) : LTC does not give size requirement on A versus N, - and then the modular exponentiation. + /* we can take advantage of modular arithmetic rule that: + A^B mod C = ( (A mod C)^B ) mod C + and so we do first (A mod N) : LTC does not give size requirement + on A versus N, and then the modular exponentiation. */ - /* if G >= P then */ - if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { - res = (int)LTC_PKHA_ModRed(LTC_BASE, ptrG, sizeG, ptrP, sizeP, - ptrG, &sizeG, kLTC_PKHA_IntegerArith); - - if (res != kStatus_Success) { + /* if G >= P then reduce */ + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, + sizeP) >= 0) { + if (LTC_PKHA_ModRed(LTC_BASE, ptrG, sizeG, ptrP, sizeP, + ptrG, &sizeG, kLTC_PKHA_IntegerArith) != kStatus_Success) { res = MP_VAL; } } if (res == MP_OKAY) { - res = (int)LTC_PKHA_ModExp(LTC_BASE, ptrG, sizeG, ptrP, sizeP, - ptrX, sizeX, ptrP, &sizeP, kLTC_PKHA_IntegerArith, - kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); - - if (res != kStatus_Success) { + if (LTC_PKHA_ModExp(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrX, sizeX, + ptrP, &sizeP, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized) != kStatus_Success) { res = MP_VAL; } else { @@ -524,6 +538,79 @@ int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) return res; } +int mp_exptmod_nct (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + /* use hardware implementation even for non-constant time operations */ + return mp_exptmod(G, X, P, Y); +} + +#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; + + 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); + /* The base size is the number of bits / 8. One is added if the number + * of bits isn't an even 8. */ + 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; + } + + #ifndef WC_NO_RNG + if (res == MP_OKAY && rng != NULL) { + 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, /* seed */ + (uint8_t*)&t, sizeof(t), /* trials */ + ptrA, sizeA, /* candidate */ + (bool*)result) != kStatus_Success) { + res = MP_MEM; + } + } + + if (ptrB) { + XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT); + } + if (ptrA) { + XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT); + } + } + else { +#if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) + res = mp_prime_is_prime_ex(a, t, result, rng); +#else + res = NOT_COMPILED_IN; +#endif + } + return res; +} + +int mp_prime_is_prime(mp_int* a, int t, int* result) +{ + return mp_prime_is_prime_ex(a, t, result, NULL); +} +#endif /* !NO_RSA || !NO_DSA || !NO_DH || WOLFSSL_KEY_GEN */ + #endif /* FREESCALE_LTC_TFM */ @@ -567,7 +654,8 @@ static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) return res; } -/* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA driver functions */ +/* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA + * driver functions */ #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #define ECC192 #endif diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 87ba82770..76f84dfa3 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -397,7 +397,7 @@ int wc_InitRsaKey_Label(RsaKey* key, const char* label, void* heap, int devId) */ int wc_InitRsaHw(RsaKey* key) { - unsigned char* m; /* RSA modulous */ + unsigned char* m; /* RSA modulus */ word32 e = 0; /* RSA public exponent */ int mSz; int eSz; @@ -673,7 +673,7 @@ int wc_CheckRsaKey(RsaKey* key) break; #endif /* WOLFSSL_SP_4096 */ default: - /* If using only single precsision math then issue key size + /* If using only single precision math then issue key size * error, otherwise fall-back to multi-precision math * calculation */ #if defined(WOLFSSL_SP_MATH) diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 300b777ba..f30957088 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -4275,7 +4275,11 @@ int mp_exptmod_ex (mp_int * G, mp_int * X, int digits, mp_int * P, mp_int * Y) return fp_exptmod_ex(G, X, digits, P, Y); } +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod_nct (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else int mp_exptmod_nct (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif { return fp_exptmod_nct(G, X, P, Y); } @@ -4724,8 +4728,11 @@ int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c) static int fp_isprime_ex(fp_int *a, int t, int* result); - +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_prime_is_prime(mp_int* a, int t, int* result) +#else int mp_prime_is_prime(mp_int* a, int t, int* result) +#endif { return fp_isprime_ex(a, t, result); } @@ -4960,7 +4967,11 @@ int fp_isprime_ex(fp_int *a, int t, int* result) } +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) +#else int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) +#endif { int ret = FP_YES; fp_digit d; @@ -5370,7 +5381,7 @@ int mp_add_d(fp_int *a, fp_digit b, fp_int *c) /* chars used in radix conversions */ static wcchar fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz+/"; + "abcdefghijklmnopqrstuvwxyz+/"; #endif #if !defined(NO_DSA) || defined(HAVE_ECC) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index efa3c430f..94d0e93d8 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -14705,7 +14705,8 @@ static int rsa_keygen_test(WC_RNG* rng) #if !defined(HAVE_FAST_RSA) && !defined(HAVE_USER_RSA) && \ (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) && \ - !defined(HAVE_SELFTEST) && !defined(HAVE_INTEL_QA) + !defined(HAVE_SELFTEST) && !defined(HAVE_INTEL_QA) \ + && !defined(WOLFSSL_NO_RSA_KEY_CHECK) ret = wc_CheckRsaKey(genKey); if (ret != 0) { ERROR_OUT(-7872, exit_rsa);