diff --git a/tests/api.c b/tests/api.c index 5b51020ece..2bfab87d2a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -19712,6 +19712,104 @@ static int test_wc_RsaPublicKeyDecodeRaw(void) } /* END test_wc_RsaPublicKeyDecodeRaw */ +/* + * Testing wc_RsaPrivateKeyDecodeRaw() + */ +static int test_wc_RsaPrivateKeyDecodeRaw(void) +{ + EXPECT_DECLS; +#if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) \ + && !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + RsaKey key; + const byte n = 33; + const byte e = 3; + const byte d = 7; + const byte u = 2; + const byte p = 3; + const byte q = 11; + const byte dp = 1; + const byte dq = 7; + + ExpectIntEQ(wc_InitRsaKey(&key, HEAP_HINT), 0); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), NULL, 0, + NULL, 0, &key), 0); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + NULL, 0, &key), 0); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), NULL, 0, + &dq, sizeof(dq), &key), 0); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), 0); + + /* Pass in bad args. */ + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(NULL, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, 0, + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + NULL, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, 0, &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), NULL, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, 0, &u, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + NULL, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, 0, &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), NULL, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, sizeof(u), + &p, sizeof(p), &q, 0, &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, 0, + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), NULL, sizeof(u), + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); + ExpectIntEQ(wc_RsaPrivateKeyDecodeRaw(&n, sizeof(n), + &e, sizeof(e), &d, sizeof(d), &u, 0, + &p, sizeof(p), &q, sizeof(q), &dp, sizeof(dp), + &dq, sizeof(dq), &key), BAD_FUNC_ARG); +#endif + + DoExpectIntEQ(wc_FreeRsaKey(&key), 0); +#endif + return EXPECT_RESULT(); +} /* END test_wc_RsaPrivateKeyDecodeRaw */ + + #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) /* In FIPS builds, wc_MakeRsaKey() will return an error if it cannot find * a probable prime in 5*(modLen/2) attempts. In non-FIPS builds, it keeps @@ -72426,6 +72524,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wc_RsaPrivateKeyDecode), TEST_DECL(test_wc_RsaPublicKeyDecode), TEST_DECL(test_wc_RsaPublicKeyDecodeRaw), + TEST_DECL(test_wc_RsaPrivateKeyDecodeRaw), TEST_DECL(test_wc_MakeRsaKey), TEST_DECL(test_wc_CheckProbablePrime), TEST_DECL(test_wc_RsaPSS_Verify), diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 337d652b35..99fb241d0f 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -5148,4 +5148,105 @@ int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, word32 cpuMHz) #endif /* WC_RSA_NONBLOCK_TIME */ #endif /* WC_RSA_NONBLOCK */ +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) +/* + * Calculate y = d mod(x-1) + */ +static int CalcDX(mp_int* y, mp_int* x, mp_int* d) +{ + mp_int m; + int err; + + err = mp_init(&m); + if (err == MP_OKAY) { + err = mp_sub_d(x, 1, &m); + if (err == MP_OKAY) + err = mp_mod(d, &m, y); + mp_forcezero(&m); + } + + return err; +} +#endif + +int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, const byte* d, word32 dSz, + const byte* u, word32 uSz, const byte* p, word32 pSz, + const byte* q, word32 qSz, const byte* dP, word32 dPSz, + const byte* dQ, word32 dQSz, RsaKey* key) +{ + int err = MP_OKAY; + + if (n == NULL || nSz == 0 || e == NULL || eSz == 0 + || d == NULL || dSz == 0 || p == NULL || pSz == 0 + || q == NULL || qSz == 0 || key == NULL) { + err = BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + if (err == MP_OKAY) { + if ((u == NULL || uSz == 0) + || (dP != NULL && dPSz == 0) + || (dQ != NULL && dQSz == 0)) { + err = BAD_FUNC_ARG; + } + } +#else + (void)u; + (void)uSz; + (void)dP; + (void)dPSz; + (void)dQ; + (void)dQSz; +#endif + + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->n, n, nSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->e, e, eSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->d, d, dSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->p, p, pSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->q, q, qSz); +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->u, u, uSz); + if (err == MP_OKAY) { + if (dP != NULL) + err = mp_read_unsigned_bin(&key->dP, dP, dPSz); + else + err = CalcDX(&key->dP, &key->p, &key->d); + } + if (err == MP_OKAY) { + if (dQ != NULL) + err = mp_read_unsigned_bin(&key->dQ, dQ, dQSz); + else + err = CalcDX(&key->dQ, &key->q, &key->d); + } +#endif + + if (err == MP_OKAY) { + key->type = RSA_PRIVATE; + } + else { + mp_clear(&key->n); + mp_clear(&key->e); + mp_clear(&key->d); + mp_clear(&key->p); + mp_clear(&key->q); +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_clear(&key->u); + mp_clear(&key->dP); + mp_clear(&key->dQ); +#endif + } + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + #endif /* NO_RSA */ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 0f31c86054..ae426db28c 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -454,6 +454,12 @@ WOLFSSL_LOCAL int wc_hash2mgf(enum wc_HashType hType); WOLFSSL_LOCAL int RsaFunctionCheckIn(const byte* in, word32 inLen, RsaKey* key, int checkSmallCt); +WOLFSSL_API int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, const byte* d, word32 dSz, + const byte* u, word32 uSz, const byte* p, word32 pSz, + const byte* q, word32 qSz, const byte* dP, word32 dPSz, + const byte* dQ, word32 dQSz, RsaKey* key); + #ifdef __cplusplus } /* extern "C" */ #endif