From a021c420748540c5285bf46049620e1d3eaca403 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Sat, 1 Jun 2024 16:41:07 -0700 Subject: [PATCH] Using Decode Raw RSA Private Key 1. If wc_RsaPrivateKeyDecodeRaw() is available, use it to load the private key from GetOpenSshKeyRsa(). If unavailable, process the key the original way. 2. Check for wolfSSL version and if greater than v5.7.0, the new function is available. 3. When loading an OpenSSH format RSA key, if wolfSSL's RSA_LOW_MEM is set, skip the u value, and do not calculate dP and dQ. 4. Rename RsaCalcInverses() to RsaCalcDX(). --- src/internal.c | 77 +++++++++++++++++++++++++++++++++++++++++----- wolfssh/internal.h | 4 +++ 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/internal.c b/src/internal.c index ca57e6579..0b876317b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #ifndef WOLFSSH_NO_DH #include @@ -45,7 +46,6 @@ #include #include #include -#include #include #ifdef WOLFSSH_HAVE_LIBOQS @@ -1353,10 +1353,57 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap) #ifndef WOLFSSH_NO_RSA + +#if LIBWOLFSSL_VERSION_HEX > WOLFSSL_V5_7_0 +/* + * The function wc_RsaPrivateKeyDecodeRaw() is available + * from wolfSSL after v5.7.0. + */ + +/* + * Utility for GetOpenSshKey() to read in RSA keys. + */ +static int GetOpenSshKeyRsa(RsaKey* key, + const byte* buf, word32 len, word32* idx) +{ + const byte *n, *e, *d, *u, *p, *q; + word32 nSz, eSz, dSz, uSz, pSz, qSz; + int ret; + + ret = wc_InitRsaKey(key, NULL); + if (ret == WS_SUCCESS) + ret = GetMpint(&nSz, &n, buf, len, idx); + if (ret == WS_SUCCESS) + ret = GetMpint(&eSz, &e, buf, len, idx); + if (ret == WS_SUCCESS) + ret = GetMpint(&dSz, &d, buf, len, idx); + if (ret == WS_SUCCESS) + ret = GetMpint(&uSz, &u, buf, len, idx); + if (ret == WS_SUCCESS) + ret = GetMpint(&pSz, &p, buf, len, idx); + if (ret == WS_SUCCESS) + ret = GetMpint(&qSz, &q, buf, len, idx); + if (ret == WS_SUCCESS) + ret = wc_RsaPrivateKeyDecodeRaw(n, nSz, e, eSz, d, dSz, + u, uSz, p, pSz, q, qSz, NULL, 0, NULL, 0, key); + + if (ret != WS_SUCCESS) + ret = WS_RSA_E; + + return ret; +} + +#else /* LIBWOLFSSL_VERSION_HEX > WOLFSSL_V5_7_0 */ + +#include + /* * Utility function to read an Mpint from the stream directly into a mp_int. + * The RsaKey members u, dP, and dQ do not exist when wolfCrypt is built + * with RSA_LOW_MEM. (That mode of wolfCrypt isn't using the extra values + * for the Chinese Remainder Theorem.) */ -static INLINE int GetMpintToMp(mp_int* mp, +static int GetMpintToMp(mp_int* mp, const byte* buf, word32 len, word32* idx) { const byte* val = NULL; @@ -1371,12 +1418,13 @@ static INLINE int GetMpintToMp(mp_int* mp, } +#ifndef RSA_LOW_MEM /* - * For the given RSA key, calculate p^-1 and q^-1. wolfCrypt's RSA - * code expects them, but the OpenSSH format key doesn't store them. - * TODO: Add a RSA read function to wolfCrypt to handle this condition. + * For the given RSA key, calculate d mod(p-1) and d mod(q-1). + * wolfCrypt's RSA code expects them, but the OpenSSH format key + * doesn't store them. */ -static INLINE int CalcRsaInverses(RsaKey* key) +static int CalcRsaDX(RsaKey* key) { mp_int m; int ret; @@ -1395,6 +1443,7 @@ static INLINE int CalcRsaInverses(RsaKey* key) return ret; } +#endif /* * Utility for GetOpenSshKey() to read in RSA keys. @@ -1411,23 +1460,35 @@ static int GetOpenSshKeyRsa(RsaKey* key, ret = GetMpintToMp(&key->e, buf, len, idx); if (ret == WS_SUCCESS) ret = GetMpintToMp(&key->d, buf, len, idx); +#ifndef RSA_LOW_MEM if (ret == WS_SUCCESS) ret = GetMpintToMp(&key->u, buf, len, idx); +#else + /* Skipping the u value in the key. */ + if (ret == WS_SUCCESS) + ret = GetSkip(buf, len, idx); +#endif if (ret == WS_SUCCESS) ret = GetMpintToMp(&key->p, buf, len, idx); if (ret == WS_SUCCESS) ret = GetMpintToMp(&key->q, buf, len, idx); +#ifndef RSA_LOW_MEM /* Calculate dP and dQ for wolfCrypt. */ if (ret == WS_SUCCESS) - ret = CalcRsaInverses(key); + ret = CalcRsaDX(key); +#endif if (ret != WS_SUCCESS) ret = WS_RSA_E; return ret; } -#endif + +#endif /* LIBWOLFSSL_VERSION_HEX > WOLFSSL_V5_7_0 */ + +#endif /* WOLFSSH_NO_RSA */ + #ifndef WOLFSSH_NO_ECDSA /* diff --git a/wolfssh/internal.h b/wolfssh/internal.h index f99bbe1a3..0ed5db5c4 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -1331,6 +1331,10 @@ enum TerminalModes { }; #endif /* WOLFSSH_TERM */ + +#define WOLFSSL_V5_7_0 0x05007000 + + #ifdef __cplusplus } #endif