mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 00:00:49 +02:00
deb668ca4b
Add full RSA-PSS (RSASSA-PSS) support to PKCS#7 SignedData encoding and verification. This change enables SignerInfo.signatureAlgorithm to use id-RSASSA-PSS with explicit RSASSA-PSS-params (hash, MGF1, salt length), as required by RFC 4055 and CMS profiles. Key changes: - Add RSA-PSS encode and verify paths for PKCS7 SignedData - Encode full RSASSA-PSS AlgorithmIdentifier parameters - Decode RSA-PSS parameters from SignerInfo for verification - Treat RSA-PSS like ECDSA (sign raw digest, not DigestInfo) - Fix certificate signatureAlgorithm parameter length handling - Add API test coverage for RSA-PSS SignedData This resolves failures when using RSA-PSS signer certificates (e.g. -173 invalid signature algorithm) and maintains backward compatibility with RSA PKCS#1 v1.5 and ECDSA. Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
254 lines
8.3 KiB
C
254 lines
8.3 KiB
C
/*!
|
|
\ingroup CryptoCb
|
|
|
|
\brief This function registers a unique device identifier (devID) and
|
|
callback function for offloading crypto operations to external
|
|
hardware such as Key Store, Secure Element, HSM, PKCS11 or TPM.
|
|
|
|
For STSAFE with Crypto Callbacks example see
|
|
wolfcrypt/src/port/st/stsafe.c and the wolfSSL_STSAFE_CryptoDevCb function.
|
|
|
|
For TPM based crypto callbacks example see the wolfTPM2_CryptoDevCb
|
|
function in wolfTPM src/tpm2_wrap.c
|
|
|
|
\return CRYPTOCB_UNAVAILABLE to fallback to using software crypto
|
|
\return 0 for success
|
|
\return negative value for failure
|
|
|
|
\param devId any unique value, not -2 (INVALID_DEVID)
|
|
\param cb a callback function with prototype:
|
|
typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx);
|
|
|
|
_Example_
|
|
\code
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
#include <wolfssl/wolfcrypt/cryptocb.h>
|
|
static int myCryptoCb_Func(int devId, wc_CryptoInfo* info, void* ctx)
|
|
{
|
|
int ret = CRYPTOCB_UNAVAILABLE;
|
|
|
|
if (info->algo_type == WC_ALGO_TYPE_PK) {
|
|
#ifndef NO_RSA
|
|
if (info->pk.type == WC_PK_TYPE_RSA) {
|
|
switch (info->pk.rsa.type) {
|
|
case RSA_PUBLIC_ENCRYPT:
|
|
case RSA_PUBLIC_DECRYPT:
|
|
// RSA public op
|
|
ret = wc_RsaFunction(
|
|
info->pk.rsa.in, info->pk.rsa.inLen,
|
|
info->pk.rsa.out, info->pk.rsa.outLen,
|
|
info->pk.rsa.type, info->pk.rsa.key,
|
|
info->pk.rsa.rng);
|
|
break;
|
|
case RSA_PRIVATE_ENCRYPT:
|
|
case RSA_PRIVATE_DECRYPT:
|
|
// RSA private op
|
|
ret = wc_RsaFunction(
|
|
info->pk.rsa.in, info->pk.rsa.inLen,
|
|
info->pk.rsa.out, info->pk.rsa.outLen,
|
|
info->pk.rsa.type, info->pk.rsa.key,
|
|
info->pk.rsa.rng);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
|
|
if (info->pk.type == WC_PK_TYPE_RSA_PSS) {
|
|
// RSA-PSS sign/verify
|
|
ret = wc_RsaPSS_Sign_ex(
|
|
info->pk.rsa.in, info->pk.rsa.inLen,
|
|
info->pk.rsa.out, *info->pk.rsa.outLen,
|
|
WC_HASH_TYPE_SHA256, WC_MGF1SHA256,
|
|
RSA_PSS_SALT_LEN_DEFAULT,
|
|
info->pk.rsa.key, info->pk.rsa.rng);
|
|
}
|
|
#endif
|
|
#ifdef HAVE_ECC
|
|
if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
|
|
// ECDSA
|
|
ret = wc_ecc_sign_hash(
|
|
info->pk.eccsign.in, info->pk.eccsign.inlen,
|
|
info->pk.eccsign.out, info->pk.eccsign.outlen,
|
|
info->pk.eccsign.rng, info->pk.eccsign.key);
|
|
}
|
|
#endif
|
|
#ifdef HAVE_ED25519
|
|
if (info->pk.type == WC_PK_TYPE_ED25519_SIGN) {
|
|
// ED25519 sign
|
|
ret = wc_ed25519_sign_msg_ex(
|
|
info->pk.ed25519sign.in, info->pk.ed25519sign.inLen,
|
|
info->pk.ed25519sign.out, info->pk.ed25519sign.outLen,
|
|
info->pk.ed25519sign.key, info->pk.ed25519sign.type,
|
|
info->pk.ed25519sign.context,
|
|
info->pk.ed25519sign.contextLen);
|
|
}
|
|
#endif
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int devId = 1;
|
|
wc_CryptoCb_RegisterDevice(devId, myCryptoCb_Func, &myCtx);
|
|
wolfSSL_CTX_SetDevId(ctx, devId);
|
|
\endcode
|
|
|
|
\sa wc_CryptoCb_UnRegisterDevice
|
|
\sa wolfSSL_SetDevId
|
|
\sa wolfSSL_CTX_SetDevId
|
|
*/
|
|
int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx);
|
|
|
|
/*!
|
|
\ingroup CryptoCb
|
|
|
|
\brief This function un-registers a unique device identifier (devID)
|
|
callback function.
|
|
|
|
\return none No returns.
|
|
|
|
\param devId any unique value, not -2 (INVALID_DEVID)
|
|
|
|
_Example_
|
|
\code
|
|
wc_CryptoCb_UnRegisterDevice(devId);
|
|
devId = INVALID_DEVID;
|
|
wolfSSL_CTX_SetDevId(ctx, devId);
|
|
\endcode
|
|
|
|
\sa wc_CryptoCb_RegisterDevice
|
|
\sa wolfSSL_SetDevId
|
|
\sa wolfSSL_CTX_SetDevId
|
|
*/
|
|
void wc_CryptoCb_UnRegisterDevice(int devId);
|
|
|
|
/*!
|
|
\ingroup CryptoCb
|
|
\brief This function returns the default device ID for crypto
|
|
callbacks. This is useful when you want to get the device ID that
|
|
was set as the default for the library.
|
|
|
|
\return The default device ID, or INVALID_DEVID if no default is set.
|
|
|
|
_Example_
|
|
\code
|
|
int devId = wc_CryptoCb_DefaultDevID();
|
|
if (devId != INVALID_DEVID) {
|
|
// default device ID is set
|
|
}
|
|
\endcode
|
|
|
|
\sa wc_CryptoCb_RegisterDevice
|
|
\sa wc_CryptoCb_UnRegisterDevice
|
|
*/
|
|
int wc_CryptoCb_DefaultDevID(void);
|
|
|
|
/*!
|
|
\ingroup CryptoCb
|
|
\brief This function sets a callback for finding crypto devices.
|
|
The callback is invoked when a device ID needs to be resolved to
|
|
a device context. This is useful for dynamic device management.
|
|
|
|
\return none No returns.
|
|
|
|
\param cb callback function with prototype:
|
|
typedef void* (*CryptoDevCallbackFind)(int devId);
|
|
|
|
_Example_
|
|
\code
|
|
void* myDeviceFindCb(int devId) {
|
|
// lookup device context by ID
|
|
return deviceContext;
|
|
}
|
|
|
|
wc_CryptoCb_SetDeviceFindCb(myDeviceFindCb);
|
|
\endcode
|
|
|
|
\sa wc_CryptoCb_RegisterDevice
|
|
*/
|
|
void wc_CryptoCb_SetDeviceFindCb(CryptoDevCallbackFind cb);
|
|
|
|
/*!
|
|
\ingroup CryptoCb
|
|
\brief This function converts a wc_CryptoInfo structure to a
|
|
human-readable string for debugging purposes. The string is printed
|
|
to stdout and describes the cryptographic operation being performed.
|
|
|
|
\return none No returns.
|
|
|
|
\param info pointer to the wc_CryptoInfo structure to convert
|
|
|
|
_Example_
|
|
\code
|
|
int myCryptoCb(int devId, wc_CryptoInfo* info, void* ctx) {
|
|
// print debug info about the operation
|
|
wc_CryptoCb_InfoString(info);
|
|
|
|
// handle the operation
|
|
return CRYPTOCB_UNAVAILABLE;
|
|
}
|
|
\endcode
|
|
|
|
\sa wc_CryptoCb_RegisterDevice
|
|
*/
|
|
void wc_CryptoCb_InfoString(wc_CryptoInfo* info);
|
|
|
|
/*!
|
|
\ingroup CryptoCb
|
|
|
|
\brief Import an AES key into a CryptoCB device for hardware offload.
|
|
|
|
This function allows AES keys to be handled by an external device
|
|
(e.g. Secure Element or HSM). When supported, the device callback stores
|
|
the key internally and sets an opaque handle in aes->devCtx.
|
|
|
|
When CryptoCB AES SetKey support is enabled
|
|
(WOLF_CRYPTO_CB_AES_SETKEY), wolfCrypt routes AES-GCM operations
|
|
through the CryptoCB interface.
|
|
|
|
**TLS Builds (Default):**
|
|
- Key bytes ARE stored in wolfCrypt memory (devKey) for fallback
|
|
- GCM tables ARE generated for software fallback
|
|
- Provides hardware acceleration with automatic fallback
|
|
|
|
**Crypto-Only Builds (--disable-tls):**
|
|
- Key bytes NOT stored in wolfCrypt memory (true key isolation)
|
|
- GCM tables skipped (true hardware offload)
|
|
- Callback must handle all GCM operations (SetKey, Encrypt, Decrypt, Free)
|
|
|
|
If the callback returns success (0), full AES-GCM offload is assumed.
|
|
The callback must handle SetKey, Encrypt, Decrypt, and Free operations.
|
|
|
|
\param aes AES context
|
|
\param key Pointer to raw AES key material
|
|
\param keySz Size of key in bytes
|
|
|
|
\return 0 on success
|
|
\return CRYPTOCB_UNAVAILABLE if device does not support this operation
|
|
\return BAD_FUNC_ARG on invalid parameters
|
|
|
|
_Example_
|
|
\code
|
|
#include <wolfssl/wolfcrypt/cryptocb.h>
|
|
#include <wolfssl/wolfcrypt/aes.h>
|
|
|
|
Aes aes;
|
|
byte key[32] = { /* 256-bit key */ };
|
|
int devId = 1;
|
|
|
|
/* Register your CryptoCB callback first */
|
|
wc_CryptoCb_RegisterDevice(devId, myCryptoCallback, NULL);
|
|
|
|
wc_AesInit(&aes, NULL, devId);
|
|
/* wc_AesGcmSetKey internally calls wc_CryptoCb_AesSetKey */
|
|
if (wc_CryptoCb_AesSetKey(&aes, key, sizeof(key)) == 0) {
|
|
/* Key successfully imported to device via callback */
|
|
/* aes.devCtx now contains device handle */
|
|
/* Full GCM offload is assumed - callback must handle all operations */
|
|
}
|
|
\endcode
|
|
|
|
\sa wc_CryptoCb_RegisterDevice
|
|
\sa wc_AesInit
|
|
*/
|
|
int wc_CryptoCb_AesSetKey(Aes* aes, const byte* key, word32 keySz);
|