From b7299a23c0d77dc9907017e7eaab0f1e8c4be689 Mon Sep 17 00:00:00 2001 From: Colton Willey Date: Tue, 27 Aug 2024 13:09:23 -0700 Subject: [PATCH 1/4] Add new crypto callback for RSA with padding. --- tests/api.c | 7 ++ wolfcrypt/src/cryptocb.c | 56 +++++++++ wolfcrypt/src/rsa.c | 62 ++++++++++ wolfcrypt/src/wc_pkcs11.c | 211 +++++++++++++++++++++++++++++++++- wolfssl/wolfcrypt/cryptocb.h | 8 ++ wolfssl/wolfcrypt/rsa.h | 14 +++ wolfssl/wolfcrypt/types.h | 3 + wolfssl/wolfcrypt/wc_pkcs11.h | 4 + 8 files changed, 359 insertions(+), 6 deletions(-) diff --git a/tests/api.c b/tests/api.c index 20e109b80..537612c58 100644 --- a/tests/api.c +++ b/tests/api.c @@ -83658,6 +83658,13 @@ static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) info->pk.rsa.type, ret, *info->pk.rsa.outLen); #endif } + #ifdef WOLF_CRYPTO_CB_RSA_PAD + else if (info->pk.type == WC_PK_TYPE_RSA_PKCS || + info->pk.type == WC_PK_TYPE_RSA_PSS || + info->pk.type == WC_PK_TYPE_RSA_OAEP) { + ret = CRYPTOCB_UNAVAILABLE; /* fallback to software */ + } + #endif /* ifdef WOLF_CRYPTO_CB_RSA_PAD */ #endif /* !NO_RSA */ #ifdef HAVE_ECC if (info->pk.type == WC_PK_TYPE_EC_KEYGEN) { diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index e3c62a86f..d510bb438 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -418,6 +418,62 @@ int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, return wc_CryptoCb_TranslateErrorCode(ret); } +#ifdef WOLF_CRYPTO_CB_RSA_PAD +int wc_CryptoCb_RsaPad(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng, + RsaPadding *padding) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + int pk_type; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK); + + if (padding) { + switch(padding->pad_type) { +#ifndef NO_PKCS11_RSA_PKCS + case WC_RSA_PKCSV15_PAD: + pk_type = WC_PK_TYPE_RSA_PKCS; + break; + case WC_RSA_PSS_PAD: + pk_type = WC_PK_TYPE_RSA_PSS; + break; + case WC_RSA_OAEP_PAD: + pk_type = WC_PK_TYPE_RSA_OAEP; + break; +#endif /* NO_PKCS11_RSA_PKCS */ + default: + pk_type = WC_PK_TYPE_RSA; + } + } else { + pk_type = WC_PK_TYPE_RSA; + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = pk_type; + cryptoInfo.pk.rsa.in = in; + cryptoInfo.pk.rsa.inLen = inLen; + cryptoInfo.pk.rsa.out = out; + cryptoInfo.pk.rsa.outLen = outLen; + cryptoInfo.pk.rsa.type = type; + cryptoInfo.pk.rsa.key = key; + cryptoInfo.pk.rsa.rng = rng; + cryptoInfo.pk.rsa.padding = padding; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif + #ifdef WOLFSSL_KEY_GEN int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) { diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 381af8ad9..f1150f6d2 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -3112,6 +3112,9 @@ static int wc_RsaFunction_ex(const byte* in, word32 inLen, byte* out, int ret = 0; (void)rng; (void)checkSmallCt; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) + RsaPadding padding; +#endif if (key == NULL || in == NULL || inLen == 0 || out == NULL || outLen == NULL || *outLen == 0 || type == RSA_TYPE_UNKNOWN) { @@ -3123,7 +3126,18 @@ static int wc_RsaFunction_ex(const byte* in, word32 inLen, byte* out, if (key->devId != INVALID_DEVID) #endif { + #if defined(WOLF_CRYPTO_CB_RSA_PAD) + /* If we are here, either the RSA PAD callback was already called + * and returned that it could not implement for that padding scheme, + * or this is a public verify operation. Either way indicate to the + * callback that this should be a raw RSA operation with no padding.*/ + XMEMSET(&padding, 0, sizeof(RsaPadding)); + padding.pad_type = WC_RSA_NO_PAD; + ret = wc_CryptoCb_RsaPad(in, inLen, out, + outLen, type, key, rng, &padding); + #else ret = wc_CryptoCb_Rsa(in, inLen, out, outLen, type, key, rng); + #endif #ifndef WOLF_CRYPTO_CB_ONLY_RSA if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; @@ -3231,6 +3245,9 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, int ret = 0; int sz; int state; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) + RsaPadding padding; +#endif if (in == NULL || inLen == 0 || out == NULL || key == NULL) { return BAD_FUNC_ARG; @@ -3327,6 +3344,29 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, #endif #endif /* WOLFSSL_SE050 */ + #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) + if (key->devId != INVALID_DEVID) { + XMEMSET(&padding, 0, sizeof(RsaPadding)); + padding.pad_value = pad_value; + padding.pad_type = pad_type; + padding.hash = hash; + padding.mgf = mgf; + padding.label = label; + padding.labelSz = labelSz; + padding.saltLen = saltLen; + ret = wc_CryptoCb_RsaPad(in, inLen, out, &outLen, rsa_type, key, rng, + &padding); + + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + if (ret < 0) { + break; + } + + ret = outLen; + break; + } + } + #endif key->state = RSA_STATE_ENCRYPT_PAD; ret = wc_RsaPad_ex(in, inLen, out, (word32)sz, pad_value, rng, pad_type, hash, mgf, label, labelSz, saltLen, @@ -3406,6 +3446,9 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, { int ret = WC_NO_ERR_TRACE(RSA_WRONG_TYPE_E); byte* pad = NULL; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) + RsaPadding padding; +#endif if (in == NULL || inLen == 0 || out == NULL || key == NULL) { return BAD_FUNC_ARG; @@ -3516,6 +3559,25 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, FALL_THROUGH; case RSA_STATE_DECRYPT_EXPTMOD: +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) + if ((key->devId != INVALID_DEVID) && (rsa_type != RSA_PUBLIC_DECRYPT)) { + /* Everything except verify goes to crypto cb if + * WOLF_CRYPTO_CB_RSA_PAD defined */ + XMEMSET(&padding, 0, sizeof(RsaPadding)); + padding.pad_value = pad_value; + padding.pad_type = pad_type; + padding.hash = hash; + padding.mgf = mgf; + padding.label = label; + padding.labelSz = labelSz; + padding.saltLen = saltLen; + ret = wc_CryptoCb_RsaPad(in, inLen, out, + &outLen, rsa_type, key, rng, &padding); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + break; + } + } +#endif #if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) && \ !defined(WOLFSSL_NO_MALLOC) ret = wc_RsaFunction_ex(key->data, inLen, key->data, &key->dataLen, diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index 78d78dc1a..d85e195e6 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -552,7 +552,7 @@ static int Pkcs11Slot_FindByTokenName(Pkcs11Dev* dev, PKCS11_RV("C_GetTokenInfo", rv); if (rv == CKR_OK && XMEMCMP(tinfo.label, tokenName, tokenNameSz) == 0) { - ret = slot[index]; + ret = (int)slot[index]; break; } } @@ -1809,6 +1809,63 @@ static int Pkcs11RsaPrivateKey(Pkcs11Session* session, RsaKey* rsaKey, return ret; } +int wc_hash2sz(int hType) +{ + switch(hType) { + case WC_HASH_TYPE_SHA: + return 20; + case WC_HASH_TYPE_SHA256: + return 32; + case WC_HASH_TYPE_SHA384: + return 48; + case WC_HASH_TYPE_SHA512: + return 64; + case WC_HASH_TYPE_SHA224: + return 24; + default: + /* unsupported WC_HASH_TYPE_XXXX */ + return -1; + } +} + +CK_MECHANISM_TYPE wc_hash2ckm(int hType) +{ + switch(hType) { + case WC_HASH_TYPE_SHA: + return CKM_SHA_1; + case WC_HASH_TYPE_SHA256: + return CKM_SHA256; + case WC_HASH_TYPE_SHA384: + return CKM_SHA384; + case WC_HASH_TYPE_SHA512: + return CKM_SHA512; + case WC_HASH_TYPE_SHA224: + return CKM_SHA224; + default: + /* unsupported WC_HASH_TYPE_XXXX */ + return 0UL; + } +} + +CK_MECHANISM_TYPE wc_mgf2ckm(int mgf) +{ + switch(mgf) { + case WC_MGF1SHA1: + return CKG_MGF1_SHA1; + case WC_MGF1SHA256: + return CKG_MGF1_SHA256; + case WC_MGF1SHA384: + return CKG_MGF1_SHA384; + case WC_MGF1SHA512: + return CKG_MGF1_SHA512; + case WC_MGF1SHA224: + return CKG_MGF1_SHA224; + default: + /* unsupported WC_MGF1XXXX */ + return 0x0UL; + } +} + /** * Exponentiate the input with the public part of the RSA key. * Used in public encrypt and decrypt. @@ -1822,9 +1879,13 @@ static int Pkcs11RsaEncrypt(Pkcs11Session* session, wc_CryptoInfo* info, CK_OBJECT_HANDLE key) { int ret = 0; + CK_MECHANISM_TYPE mechanism = 0x0UL; CK_RV rv; CK_MECHANISM mech; CK_ULONG outLen; +#ifdef WOLF_CRYPTO_CB_RSA_PAD + CK_RSA_PKCS_OAEP_PARAMS oaepParams; +#endif WOLFSSL_MSG("PKCS#11: RSA Public Key Operation"); @@ -1832,12 +1893,37 @@ static int Pkcs11RsaEncrypt(Pkcs11Session* session, wc_CryptoInfo* info, ret = BAD_FUNC_ARG; } + switch(info->pk.type) { +#ifdef WOLF_CRYPTO_CB_RSA_PAD + case WC_PK_TYPE_RSA_PKCS: + mechanism = CKM_RSA_PKCS; + break; + case WC_PK_TYPE_RSA_OAEP: + mechanism = CKM_RSA_PKCS_OAEP; + break; +#endif + case WC_PK_TYPE_RSA: + mechanism = CKM_RSA_X_509; + break; + } + if (ret == 0) { /* Raw RSA encrypt/decrypt operation. */ - mech.mechanism = CKM_RSA_X_509; + mech.mechanism = mechanism; mech.ulParameterLen = 0; mech.pParameter = NULL; +#ifdef WOLF_CRYPTO_CB_RSA_PAD + if (mechanism == CKM_RSA_PKCS_OAEP) { + XMEMSET(&oaepParams, 0, sizeof(oaepParams)); + mech.ulParameterLen = sizeof(CK_RSA_PKCS_OAEP_PARAMS); + mech.pParameter = &oaepParams; + oaepParams.source = CKZ_DATA_SPECIFIED; + oaepParams.hashAlg = wc_hash2ckm(info->pk.rsa.padding->hash); + oaepParams.mgf = wc_mgf2ckm(info->pk.rsa.padding->mgf); + } +#endif + rv = session->func->C_EncryptInit(session->handle, &mech, key); PKCS11_RV("C_EncryptInit", rv); if (rv != CKR_OK) { @@ -1875,9 +1961,13 @@ static int Pkcs11RsaDecrypt(Pkcs11Session* session, wc_CryptoInfo* info, CK_OBJECT_HANDLE key) { int ret = 0; + CK_MECHANISM_TYPE mechanism = 0x0UL; CK_RV rv; CK_MECHANISM mech; CK_ULONG outLen; +#ifdef WOLF_CRYPTO_CB_RSA_PAD + CK_RSA_PKCS_OAEP_PARAMS oaepParams; +#endif WOLFSSL_MSG("PKCS#11: RSA Private Key Operation"); @@ -1885,12 +1975,37 @@ static int Pkcs11RsaDecrypt(Pkcs11Session* session, wc_CryptoInfo* info, ret = BAD_FUNC_ARG; } + switch(info->pk.type) { +#ifdef WOLF_CRYPTO_CB_RSA_PAD + case WC_PK_TYPE_RSA_PKCS: + mechanism = CKM_RSA_PKCS; + break; + case WC_PK_TYPE_RSA_OAEP: + mechanism = CKM_RSA_PKCS_OAEP; + break; +#endif + case WC_PK_TYPE_RSA: + mechanism = CKM_RSA_X_509; + break; + } + if (ret == 0) { /* Raw RSA encrypt/decrypt operation. */ - mech.mechanism = CKM_RSA_X_509; + mech.mechanism = mechanism; mech.ulParameterLen = 0; mech.pParameter = NULL; +#ifdef WOLF_CRYPTO_CB_RSA_PAD + if (mechanism == CKM_RSA_PKCS_OAEP) { + XMEMSET(&oaepParams, 0, sizeof(oaepParams)); + mech.ulParameterLen = sizeof(CK_RSA_PKCS_OAEP_PARAMS); + mech.pParameter = &oaepParams; + oaepParams.source = CKZ_DATA_SPECIFIED; + oaepParams.hashAlg = wc_hash2ckm(info->pk.rsa.padding->hash); + oaepParams.mgf = wc_mgf2ckm(info->pk.rsa.padding->mgf); + } +#endif + rv = session->func->C_DecryptInit(session->handle, &mech, key); PKCS11_RV("C_DecryptInit", rv); if (rv != CKR_OK) { @@ -1933,6 +2048,12 @@ static int Pkcs11RsaSign(Pkcs11Session* session, wc_CryptoInfo* info, CK_RV rv; CK_MECHANISM mech; CK_ULONG outLen; + CK_MECHANISM_TYPE mechanism; +#ifdef WOLF_CRYPTO_CB_RSA_PAD + CK_RSA_PKCS_PSS_PARAMS pssParams; + int hLen; + int saltLen; +#endif WOLFSSL_MSG("PKCS#11: RSA Private Key Operation"); @@ -1940,12 +2061,67 @@ static int Pkcs11RsaSign(Pkcs11Session* session, wc_CryptoInfo* info, ret = BAD_FUNC_ARG; } + switch(info->pk.type) { +#ifdef WOLF_CRYPTO_CB_RSA_PAD + case WC_PK_TYPE_RSA_PKCS: + mechanism = CKM_RSA_PKCS; + break; + case WC_PK_TYPE_RSA_PSS: + mechanism = CKM_RSA_PKCS_PSS; + break; +#endif /* WOLF_CRYPTO_CB_RSA_PAD */ + default: + mechanism = CKM_RSA_X_509; + break; + } + if (ret == 0) { /* Raw RSA encrypt/decrypt operation. */ - mech.mechanism = CKM_RSA_X_509; + mech.mechanism = mechanism; mech.ulParameterLen = 0; mech.pParameter = NULL; +#ifdef WOLF_CRYPTO_CB_RSA_PAD + if (mechanism == CKM_RSA_PKCS_PSS) { + mech.ulParameterLen = sizeof(CK_RSA_PKCS_PSS_PARAMS); + mech.pParameter = &pssParams; + pssParams.hashAlg = wc_hash2ckm(info->pk.rsa.padding->hash); + pssParams.mgf = wc_mgf2ckm(info->pk.rsa.padding->mgf); + + saltLen = info->pk.rsa.padding->saltLen; + hLen = wc_hash2sz(info->pk.rsa.padding->hash); + + /* Same salt length code as rsa.c */ + if (saltLen == RSA_PSS_SALT_LEN_DEFAULT) + saltLen = hLen; +#ifndef WOLFSSL_PSS_LONG_SALT + else if (saltLen > hLen) { + return PSS_SALTLEN_E; + } +#endif +#ifndef WOLFSSL_PSS_SALT_LEN_DISCOVER + else if (saltLen < RSA_PSS_SALT_LEN_DEFAULT) { + return PSS_SALTLEN_E; + } +#else + else if (saltLen == RSA_PSS_SALT_LEN_DISCOVER) { + saltLen = *(info->pk.rsa.outLen) - hLen - 2; + if (saltLen < 0) { + return PSS_SALTLEN_E; + } + } + else if (saltLen < RSA_PSS_SALT_LEN_DISCOVER) { + return PSS_SALTLEN_E; + } +#endif + if (*(info->pk.rsa.outLen) - hLen < (word32)(saltLen + 2)) { + return PSS_SALTLEN_E; + } + + pssParams.sLen = saltLen; + } +#endif /* WOLF_CRYPTO_CB_RSA_PAD */ + rv = session->func->C_SignInit(session->handle, &mech, key); PKCS11_RV("C_SignInit", rv); if (rv != CKR_OK) { @@ -1984,13 +2160,31 @@ static int Pkcs11Rsa(Pkcs11Session* session, wc_CryptoInfo* info) int ret = 0; CK_RV rv; CK_MECHANISM_INFO mechInfo; + CK_MECHANISM_TYPE mechanism = 0x0UL; int sessionKey = 0; CK_OBJECT_HANDLE key; RsaKey* rsaKey = info->pk.rsa.key; int type = info->pk.rsa.type; + switch(info->pk.type) { +#ifndef NO_PKCS11_RSA_PKCS + case WC_PK_TYPE_RSA_PKCS: + mechanism = CKM_RSA_PKCS; + break; + case WC_PK_TYPE_RSA_PSS: + mechanism = CKM_RSA_PKCS_PSS; + break; + case WC_PK_TYPE_RSA_OAEP: + mechanism = CKM_RSA_PKCS_OAEP; + break; +#endif /* NO_PKCS11_RSA_PKCS */ + case WC_PK_TYPE_RSA: + mechanism = CKM_RSA_X_509; + break; + } + /* Check operation is supported. */ - rv = session->func->C_GetMechanismInfo(session->slotId, CKM_RSA_X_509, + rv = session->func->C_GetMechanismInfo(session->slotId, mechanism, &mechInfo); PKCS11_RV("C_GetMechanismInfo", rv); if (rv != CKR_OK) { @@ -2023,7 +2217,7 @@ static int Pkcs11Rsa(Pkcs11Session* session, wc_CryptoInfo* info) } else if (type == RSA_PUBLIC_DECRYPT) { WOLFSSL_MSG("PKCS#11: Public Decrypt"); - if ((mechInfo.flags & CKF_DECRYPT) != 0) { + if ((mechInfo.flags & CKF_ENCRYPT) != 0) { ret = Pkcs11RsaEncrypt(session, info, key); } else { @@ -3783,6 +3977,11 @@ int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) switch (info->pk.type) { #ifndef NO_RSA case WC_PK_TYPE_RSA: + #ifdef WOLF_CRYPTO_CB_RSA_PAD + case WC_PK_TYPE_RSA_PKCS: + case WC_PK_TYPE_RSA_PSS: + case WC_PK_TYPE_RSA_OAEP: + #endif ret = Pkcs11OpenSession(token, &session, readWrite); if (ret == 0) { ret = Pkcs11Rsa(&session, info); diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 4b53db9d3..19902bfbb 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -118,6 +118,9 @@ typedef struct wc_CryptoInfo { int type; RsaKey* key; WC_RNG* rng; + #ifdef WOLF_CRYPTO_CB_RSA_PAD + RsaPadding *padding; + #endif } rsa; #ifdef WOLFSSL_KEY_GEN struct { @@ -481,6 +484,11 @@ WOLFSSL_API void wc_CryptoCb_InfoString(wc_CryptoInfo* info); WOLFSSL_LOCAL int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng); +#ifdef WOLF_CRYPTO_CB_RSA_PAD +WOLFSSL_LOCAL int wc_CryptoCb_RsaPad(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng, RsaPadding *padding); +#endif + #ifdef WOLFSSL_KEY_GEN WOLFSSL_LOCAL int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 5db1a23c2..1f9f0222a 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -274,6 +274,20 @@ struct RsaKey { #endif /* HAVE_FIPS */ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) +struct RsaPadding { + byte pad_value; + int pad_type; + enum wc_HashType hash; + int mgf; + byte* label; + word32 labelSz; + int saltLen; + int unpadded; +}; +typedef struct RsaPadding RsaPadding; +#endif + WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void* heap); WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 502435658..b33685f29 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1257,6 +1257,9 @@ typedef struct w64wrapper { #undef _WC_PK_TYPE_MAX #define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_SIG_CHECK_PRIV_KEY #endif + WC_PK_TYPE_RSA_PKCS = 25, + WC_PK_TYPE_RSA_PSS = 26, + WC_PK_TYPE_RSA_OAEP = 27, WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX }; diff --git a/wolfssl/wolfcrypt/wc_pkcs11.h b/wolfssl/wolfcrypt/wc_pkcs11.h index 8cdd87e61..0b8942b33 100644 --- a/wolfssl/wolfcrypt/wc_pkcs11.h +++ b/wolfssl/wolfcrypt/wc_pkcs11.h @@ -97,6 +97,10 @@ WOLFSSL_API int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, WOLFSSL_API int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx); +WOLFSSL_LOCAL int wc_hash2sz(int); +WOLFSSL_LOCAL CK_MECHANISM_TYPE wc_hash2ckm(int); +WOLFSSL_LOCAL CK_MECHANISM_TYPE wc_mgf2ckm(int); + #ifdef __cplusplus } /* extern "C" */ #endif From 2bcfff3497ea2699841dbf2ea451a5244c40b8fc Mon Sep 17 00:00:00 2001 From: Colton Willey Date: Fri, 30 Aug 2024 13:41:51 -0700 Subject: [PATCH 2/4] Expand testing to include SW implementation of RSA with padding callback, code cleanup to address review comments. --- tests/api.c | 66 ++++++++++++++++++++++++++++++++++++++- wolfcrypt/src/wc_pkcs11.c | 33 ++++++++++++++++---- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/tests/api.c b/tests/api.c index 537612c58..c64c17aaf 100644 --- a/tests/api.c +++ b/tests/api.c @@ -83662,7 +83662,71 @@ static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) else if (info->pk.type == WC_PK_TYPE_RSA_PKCS || info->pk.type == WC_PK_TYPE_RSA_PSS || info->pk.type == WC_PK_TYPE_RSA_OAEP) { - ret = CRYPTOCB_UNAVAILABLE; /* fallback to software */ + RsaKey key; + + if (info->pk.rsa.type == RSA_PUBLIC_ENCRYPT || + info->pk.rsa.type == RSA_PUBLIC_DECRYPT) { + /* Have all public key ops fall back to SW */ + return CRYPTOCB_UNAVAILABLE; + } + + if (info->pk.rsa.padding == NULL) { + return BAD_FUNC_ARG; + } + + /* Initialize key */ + ret = load_pem_key_file_as_der(privKeyFile, &pDer, + &keyFormat); + if (ret != 0) { + return ret; + } + + ret = wc_InitRsaKey(&key, HEAP_HINT); + if (ret == 0) { + word32 keyIdx = 0; + /* load RSA private key and perform private transform */ + ret = wc_RsaPrivateKeyDecode(pDer->buffer, &keyIdx, + &key, pDer->length); + } + /* Perform RSA operation */ + if ((ret == 0) && (info->pk.type == WC_PK_TYPE_RSA_PKCS)) { + #if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) + ret = wc_RsaSSL_Sign(info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, *info->pk.rsa.outLen, &key, + info->pk.rsa.rng); + #else + ret = CRYPTOCB_UNAVAILABLE; + #endif + } + if ((ret == 0) && (info->pk.type == WC_PK_TYPE_RSA_PSS)) { + #ifdef WC_RSA_PSS + ret = wc_RsaPSS_Sign_ex(info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, *info->pk.rsa.outLen, + info->pk.rsa.padding->hash, info->pk.rsa.padding->mgf, + info->pk.rsa.padding->saltLen, &key, info->pk.rsa.rng); + #else + ret = CRYPTOCB_UNAVAILABLE; + #endif + } + if ((ret == 0) && (info->pk.type == WC_PK_TYPE_RSA_OAEP)) { + #if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING) + ret = wc_RsaPrivateDecrypt_ex( + info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, *info->pk.rsa.outLen, + &key, WC_RSA_OAEP_PAD, info->pk.rsa.padding->hash, + info->pk.rsa.padding->mgf, info->pk.rsa.padding->label, + info->pk.rsa.padding->labelSz); + #else + ret = CRYPTOCB_UNAVAILABLE; + #endif + } + + if (ret > 0) { + *info->pk.rsa.outLen = ret; + } + + wc_FreeRsaKey(&key); + wc_FreeDer(&pDer); pDer = NULL; } #endif /* ifdef WOLF_CRYPTO_CB_RSA_PAD */ #endif /* !NO_RSA */ diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index d85e195e6..885e495ee 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -1809,57 +1809,78 @@ static int Pkcs11RsaPrivateKey(Pkcs11Session* session, RsaKey* rsaKey, return ret; } +/** + * Get the hash length associated with the WolfCrypt hash type. + * + * @param [in] hType Hash Type. + * @return -1 if hash type not recognized. + * @return hash length on success. + */ int wc_hash2sz(int hType) { switch(hType) { case WC_HASH_TYPE_SHA: return 20; + case WC_HASH_TYPE_SHA224: + return 24; case WC_HASH_TYPE_SHA256: return 32; case WC_HASH_TYPE_SHA384: return 48; case WC_HASH_TYPE_SHA512: return 64; - case WC_HASH_TYPE_SHA224: - return 24; default: /* unsupported WC_HASH_TYPE_XXXX */ return -1; } } +/** + * Get PKCS11 hash mechanism associated with the WolfCrypt hash type. + * + * @param [in] hType Hash Type. + * @return 0 if hash type not recognized. + * @return PKCS11 mechanism on success. + */ CK_MECHANISM_TYPE wc_hash2ckm(int hType) { switch(hType) { case WC_HASH_TYPE_SHA: return CKM_SHA_1; + case WC_HASH_TYPE_SHA224: + return CKM_SHA224; case WC_HASH_TYPE_SHA256: return CKM_SHA256; case WC_HASH_TYPE_SHA384: return CKM_SHA384; case WC_HASH_TYPE_SHA512: return CKM_SHA512; - case WC_HASH_TYPE_SHA224: - return CKM_SHA224; default: /* unsupported WC_HASH_TYPE_XXXX */ return 0UL; } } +/** + * Get PKCS11 MGF hash mechanism associated with the WolfCrypt MGF hash type. + * + * @param [in] mgf MGF Type. + * @return 0 if MGF type not recognized. + * @return PKCS11 MGF hash mechanism on success. + */ CK_MECHANISM_TYPE wc_mgf2ckm(int mgf) { switch(mgf) { case WC_MGF1SHA1: return CKG_MGF1_SHA1; + case WC_MGF1SHA224: + return CKG_MGF1_SHA224; case WC_MGF1SHA256: return CKG_MGF1_SHA256; case WC_MGF1SHA384: return CKG_MGF1_SHA384; case WC_MGF1SHA512: return CKG_MGF1_SHA512; - case WC_MGF1SHA224: - return CKG_MGF1_SHA224; default: /* unsupported WC_MGF1XXXX */ return 0x0UL; From f9af463db1508c9542ab172b3efad2a1cd499fe2 Mon Sep 17 00:00:00 2001 From: Colton Willey Date: Wed, 4 Sep 2024 10:13:40 -0700 Subject: [PATCH 3/4] Update RSA verify documentation to specify that the output should be compared with the original plaintext --- doc/dox_comments/header_files/rsa.h | 32 +++++++++++++++++------------ 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/doc/dox_comments/header_files/rsa.h b/doc/dox_comments/header_files/rsa.h index 9f099c1ed..ec001449e 100644 --- a/doc/dox_comments/header_files/rsa.h +++ b/doc/dox_comments/header_files/rsa.h @@ -23,7 +23,7 @@ int ret; ret = wc_InitRsaKey(&enc, NULL); // not using heap hint. No custom memory if ( ret != 0 ) { - // error initializing RSA key + // error initializing RSA key } \endcode @@ -166,7 +166,7 @@ int wc_FreeRsaKey(RsaKey* key); ret = wc_RsaDirect(in, (word32)sizeof(in), out, &outSz, &key, RSA_PRIVATE_ENCRYPT, &rng); if (ret < 0) { - //handle error + //handle error } \endcode @@ -240,7 +240,7 @@ int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, // initialize with received public key parameters ret = wc_RsaPublicEncrypt(msg, sizeof(msg), out, sizeof(out), &pub, &rng); if ( ret != 0 ) { - // error encrypting message + // error encrypting message } \endcode @@ -403,6 +403,12 @@ int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, if (ret < 0) { return -1; } + if (ret != inLen) { + return -1; + } + if (XMEMCMP(in, plain, ret) != 0) { + return -1; + } \endcode \sa wc_RsaSSL_Sign @@ -1037,7 +1043,7 @@ int wc_RsaEncryptSize(RsaKey* key); wc_InitRsaKey(&enc, NULL); // not using heap hint. No custom memory ret = wc_RsaPrivateKeyDecode(der, &idx, &enc, sizeof(der)); if( ret != 0 ) { - // error parsing private key + // error parsing private key } \endcode @@ -1087,7 +1093,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, wc_InitRsaKey(&pub, NULL); // not using heap hint. No custom memory ret = wc_RsaPublicKeyDecode(der, &idx, &pub, sizeof(der)); if( ret != 0 ) { - // error parsing public key + // error parsing public key } \endcode @@ -1132,7 +1138,7 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, wc_InitRsaKey(&pub, NULL); // not using heap hint. No custom memory ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), &pub); if( ret != 0 ) { - // error parsing public key elements + // error parsing public key elements } \endcode @@ -1215,7 +1221,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen); ret = wc_RsaPublicEncrypt_ex(in, sizeof(in), out, sizeof(out), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } \endcode @@ -1262,14 +1268,14 @@ int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, ret = wc_RsaPublicEncrypt_ex(in, sizeof(in), out, sizeof(out), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } … ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } \endcode @@ -1320,14 +1326,14 @@ int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } … ret = wc_RsaPrivateDecryptInline_ex(out, ret, &plain, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } \endcode @@ -1370,7 +1376,7 @@ int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, ... ret = wc_RsaFlattenPublicKey(&key, e, &eSz, n, &nSz); if (ret != 0) { - // Failure case. + // Failure case. } \endcode @@ -1516,7 +1522,7 @@ int wc_RsaKeyToPublicDer_ex(RsaKey* key, byte* output, word32 inLen, // generate 2048 bit long private key ret = wc_MakeRsaKey(&priv, 2048, e, &rng); if( ret != 0 ) { - // error generating private key + // error generating private key } \endcode From 3b5d0aa85ab0d977ad514b05c0338b7f7a17e91a Mon Sep 17 00:00:00 2001 From: Colton Willey Date: Wed, 4 Sep 2024 10:25:20 -0700 Subject: [PATCH 4/4] Fix up whitespace changes from editor autoformat --- doc/dox_comments/header_files/rsa.h | 32 +++++++++++++++++------------ 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/doc/dox_comments/header_files/rsa.h b/doc/dox_comments/header_files/rsa.h index ec001449e..2245052f3 100644 --- a/doc/dox_comments/header_files/rsa.h +++ b/doc/dox_comments/header_files/rsa.h @@ -23,7 +23,7 @@ int ret; ret = wc_InitRsaKey(&enc, NULL); // not using heap hint. No custom memory if ( ret != 0 ) { - // error initializing RSA key + // error initializing RSA key } \endcode @@ -166,7 +166,7 @@ int wc_FreeRsaKey(RsaKey* key); ret = wc_RsaDirect(in, (word32)sizeof(in), out, &outSz, &key, RSA_PRIVATE_ENCRYPT, &rng); if (ret < 0) { - //handle error + //handle error } \endcode @@ -240,7 +240,7 @@ int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, // initialize with received public key parameters ret = wc_RsaPublicEncrypt(msg, sizeof(msg), out, sizeof(out), &pub, &rng); if ( ret != 0 ) { - // error encrypting message + // error encrypting message } \endcode @@ -333,6 +333,12 @@ int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, if (ret < 0) { return -1; } + if (ret != inLen) { + return -1; + } + if (XMEMCMP(in, plain, ret) != 0) { + return -1; + } \endcode \sa wc_RsaPad @@ -1043,7 +1049,7 @@ int wc_RsaEncryptSize(RsaKey* key); wc_InitRsaKey(&enc, NULL); // not using heap hint. No custom memory ret = wc_RsaPrivateKeyDecode(der, &idx, &enc, sizeof(der)); if( ret != 0 ) { - // error parsing private key + // error parsing private key } \endcode @@ -1093,7 +1099,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, wc_InitRsaKey(&pub, NULL); // not using heap hint. No custom memory ret = wc_RsaPublicKeyDecode(der, &idx, &pub, sizeof(der)); if( ret != 0 ) { - // error parsing public key + // error parsing public key } \endcode @@ -1138,7 +1144,7 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, wc_InitRsaKey(&pub, NULL); // not using heap hint. No custom memory ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), &pub); if( ret != 0 ) { - // error parsing public key elements + // error parsing public key elements } \endcode @@ -1221,7 +1227,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen); ret = wc_RsaPublicEncrypt_ex(in, sizeof(in), out, sizeof(out), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } \endcode @@ -1268,14 +1274,14 @@ int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, ret = wc_RsaPublicEncrypt_ex(in, sizeof(in), out, sizeof(out), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } … ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } \endcode @@ -1326,14 +1332,14 @@ int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } … ret = wc_RsaPrivateDecryptInline_ex(out, ret, &plain, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); if (ret < 0) { - //handle error + //handle error } \endcode @@ -1376,7 +1382,7 @@ int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, ... ret = wc_RsaFlattenPublicKey(&key, e, &eSz, n, &nSz); if (ret != 0) { - // Failure case. + // Failure case. } \endcode @@ -1522,7 +1528,7 @@ int wc_RsaKeyToPublicDer_ex(RsaKey* key, byte* output, word32 inLen, // generate 2048 bit long private key ret = wc_MakeRsaKey(&priv, 2048, e, &rng); if( ret != 0 ) { - // error generating private key + // error generating private key } \endcode