mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 12:14:38 +02:00
Merge pull request #9002 from holtrop/aes-key-wrap-callbacks
Add callback functions for custom AES key wrap/unwrap operations
This commit is contained in:
@@ -1,3 +1,23 @@
|
|||||||
|
/*!
|
||||||
|
\ingroup PKCS7
|
||||||
|
|
||||||
|
\brief Callback used for a custom AES key wrap/unwrap operation.
|
||||||
|
|
||||||
|
\return The size of the wrapped/unwrapped key written to the output buffer
|
||||||
|
should be returned on success. A 0 return value or error code (< 0)
|
||||||
|
indicates a failure.
|
||||||
|
|
||||||
|
\param[in] key Specify the key to use.
|
||||||
|
\param[in] keySz Size of the key to use.
|
||||||
|
\param[in] in Specify the input data to wrap/unwrap.
|
||||||
|
\param[in] inSz Size of the input data.
|
||||||
|
\param[in] wrap 1 if the requested operation is a key wrap, 0 for unwrap.
|
||||||
|
\param[out] out Specify the output buffer.
|
||||||
|
\param[out] outSz Size of the output buffer.
|
||||||
|
*/
|
||||||
|
typedef int (*CallbackAESKeyWrapUnwrap)(const byte* key, word32 keySz,
|
||||||
|
const byte* in, word32 inSz, int wrap, byte* out, word32 outSz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\ingroup PKCS7
|
\ingroup PKCS7
|
||||||
|
|
||||||
@@ -477,6 +497,21 @@ int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf,
|
|||||||
word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot,
|
word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot,
|
||||||
word32 pkiMsgFootSz);
|
word32 pkiMsgFootSz);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\ingroup PKCS7
|
||||||
|
|
||||||
|
\brief Set the callback function to be used to perform a custom AES key
|
||||||
|
wrap/unwrap operation.
|
||||||
|
|
||||||
|
\retval 0 Callback function was set successfully
|
||||||
|
\retval BAD_FUNC_ARG Parameter pkcs7 is NULL
|
||||||
|
|
||||||
|
\param pkcs7 pointer to the PKCS7 structure
|
||||||
|
\param aesKeyWrapCb pointer to custom AES key wrap/unwrap function
|
||||||
|
*/
|
||||||
|
int wc_PKCS7_SetAESKeyWrapUnwrapCb(wc_PKCS7* pkcs7,
|
||||||
|
CallbackAESKeyWrapUnwrap aesKeyWrapCb);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\ingroup PKCS7
|
\ingroup PKCS7
|
||||||
|
|
||||||
|
126
tests/api.c
126
tests/api.c
@@ -18179,6 +18179,131 @@ static int test_wc_PKCS7_EncodeDecodeEnvelopedData(void)
|
|||||||
} /* END test_wc_PKCS7_EncodeDecodeEnvelopedData() */
|
} /* END test_wc_PKCS7_EncodeDecodeEnvelopedData() */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(HAVE_PKCS7) && defined(HAVE_ECC) && !defined(NO_SHA256) && defined(WOLFSSL_AES_256)
|
||||||
|
static int wasAESKeyWrapCbCalled = 0;
|
||||||
|
static int wasAESKeyUnwrapCbCalled = 0;
|
||||||
|
|
||||||
|
static int testAESKeyWrapUnwrapCb(const byte* key, word32 keySz,
|
||||||
|
const byte* in, word32 inSz, int wrap, byte* out, word32 outSz)
|
||||||
|
{
|
||||||
|
(void)key;
|
||||||
|
(void)keySz;
|
||||||
|
(void)wrap;
|
||||||
|
if (wrap)
|
||||||
|
wasAESKeyWrapCbCalled = 1;
|
||||||
|
else
|
||||||
|
wasAESKeyUnwrapCbCalled = 1;
|
||||||
|
XMEMSET(out, 0xEE, outSz);
|
||||||
|
if (inSz <= outSz) {
|
||||||
|
XMEMCPY(out, in, inSz);
|
||||||
|
}
|
||||||
|
return inSz;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test custom AES key wrap/unwrap callback
|
||||||
|
*/
|
||||||
|
static int test_wc_PKCS7_SetAESKeyWrapUnwrapCb(void)
|
||||||
|
{
|
||||||
|
EXPECT_DECLS;
|
||||||
|
#if defined(HAVE_PKCS7) && defined(HAVE_ECC) && !defined(NO_SHA256) && defined(WOLFSSL_AES_256)
|
||||||
|
static const char input[] = "Test input for AES key wrapping";
|
||||||
|
PKCS7 * pkcs7 = NULL;
|
||||||
|
byte * eccCert = NULL;
|
||||||
|
byte * eccPrivKey = NULL;
|
||||||
|
word32 eccCertSz = 0;
|
||||||
|
word32 eccPrivKeySz = 0;
|
||||||
|
byte output[ONEK_BUF];
|
||||||
|
byte decoded[sizeof(input)/sizeof(char)];
|
||||||
|
int decodedSz = 0;
|
||||||
|
#ifdef ECC_TIMING_RESISTANT
|
||||||
|
WC_RNG rng;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Load test certs */
|
||||||
|
#ifdef USE_CERT_BUFFERS_256
|
||||||
|
ExpectNotNull(eccCert = (byte*)XMALLOC(TWOK_BUF, HEAP_HINT,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER));
|
||||||
|
/* Init buffer. */
|
||||||
|
eccCertSz = (word32)sizeof_cliecc_cert_der_256;
|
||||||
|
if (eccCert != NULL) {
|
||||||
|
XMEMCPY(eccCert, cliecc_cert_der_256, eccCertSz);
|
||||||
|
}
|
||||||
|
ExpectNotNull(eccPrivKey = (byte*)XMALLOC(TWOK_BUF, HEAP_HINT,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER));
|
||||||
|
eccPrivKeySz = (word32)sizeof_ecc_clikey_der_256;
|
||||||
|
if (eccPrivKey != NULL) {
|
||||||
|
XMEMCPY(eccPrivKey, ecc_clikey_der_256, eccPrivKeySz);
|
||||||
|
}
|
||||||
|
#else /* File system. */
|
||||||
|
ExpectTrue((certFile = XFOPEN(eccClientCert, "rb")) != XBADFILE);
|
||||||
|
eccCertSz = (word32)FOURK_BUF;
|
||||||
|
ExpectNotNull(eccCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER));
|
||||||
|
ExpectTrue((eccCertSz = (word32)XFREAD(eccCert, 1, eccCertSz,
|
||||||
|
certFile)) > 0);
|
||||||
|
if (certFile != XBADFILE) {
|
||||||
|
XFCLOSE(certFile);
|
||||||
|
}
|
||||||
|
ExpectTrue((keyFile = XFOPEN(eccClientKey, "rb")) != XBADFILE);
|
||||||
|
eccPrivKeySz = (word32)FOURK_BUF;
|
||||||
|
ExpectNotNull(eccPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER));
|
||||||
|
ExpectTrue((eccPrivKeySz = (word32)XFREAD(eccPrivKey, 1, eccPrivKeySz,
|
||||||
|
keyFile)) > 0);
|
||||||
|
if (keyFile != XBADFILE) {
|
||||||
|
XFCLOSE(keyFile);
|
||||||
|
}
|
||||||
|
#endif /* USE_CERT_BUFFERS_256 */
|
||||||
|
|
||||||
|
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
|
||||||
|
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, eccCert, eccCertSz), 0);
|
||||||
|
if (pkcs7 != NULL) {
|
||||||
|
pkcs7->content = (byte*)input;
|
||||||
|
pkcs7->contentSz = sizeof(input);
|
||||||
|
pkcs7->contentOID = DATA;
|
||||||
|
pkcs7->encryptOID = AES256CBCb;
|
||||||
|
pkcs7->keyWrapOID = AES256_WRAP;
|
||||||
|
pkcs7->keyAgreeOID = dhSinglePass_stdDH_sha256kdf_scheme;
|
||||||
|
pkcs7->privateKey = eccPrivKey;
|
||||||
|
pkcs7->privateKeySz = eccPrivKeySz;
|
||||||
|
pkcs7->singleCert = eccCert;
|
||||||
|
pkcs7->singleCertSz = (word32)eccCertSz;
|
||||||
|
#ifdef ECC_TIMING_RESISTANT
|
||||||
|
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
||||||
|
ExpectIntEQ(wc_InitRng(&rng), 0);
|
||||||
|
pkcs7->rng = &rng;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test custom AES key wrap/unwrap callback */
|
||||||
|
ExpectIntEQ(wc_PKCS7_SetAESKeyWrapUnwrapCb(pkcs7, testAESKeyWrapUnwrapCb), 0);
|
||||||
|
|
||||||
|
ExpectIntGE(wc_PKCS7_EncodeEnvelopedData(pkcs7, output,
|
||||||
|
(word32)sizeof(output)), 0);
|
||||||
|
|
||||||
|
decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output,
|
||||||
|
(word32)sizeof(output), decoded, (word32)sizeof(decoded));
|
||||||
|
ExpectIntGE(decodedSz, 0);
|
||||||
|
/* Verify the size of each buffer. */
|
||||||
|
ExpectIntEQ((word32)sizeof(input)/sizeof(char), decodedSz);
|
||||||
|
|
||||||
|
ExpectIntEQ(wasAESKeyWrapCbCalled, 1);
|
||||||
|
ExpectIntEQ(wasAESKeyUnwrapCbCalled, 1);
|
||||||
|
|
||||||
|
wc_PKCS7_Free(pkcs7);
|
||||||
|
pkcs7 = NULL;
|
||||||
|
XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
#ifdef ECC_TIMING_RESISTANT
|
||||||
|
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return EXPECT_RESULT();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Testing wc_PKCS7_EncodeEncryptedData()
|
* Testing wc_PKCS7_EncodeEncryptedData()
|
||||||
*/
|
*/
|
||||||
@@ -68016,6 +68141,7 @@ TEST_CASE testCases[] = {
|
|||||||
TEST_DECL(test_wc_PKCS7_VerifySignedData_ECC),
|
TEST_DECL(test_wc_PKCS7_VerifySignedData_ECC),
|
||||||
TEST_DECL(test_wc_PKCS7_DecodeEnvelopedData_stream),
|
TEST_DECL(test_wc_PKCS7_DecodeEnvelopedData_stream),
|
||||||
TEST_DECL(test_wc_PKCS7_EncodeDecodeEnvelopedData),
|
TEST_DECL(test_wc_PKCS7_EncodeDecodeEnvelopedData),
|
||||||
|
TEST_DECL(test_wc_PKCS7_SetAESKeyWrapUnwrapCb),
|
||||||
TEST_DECL(test_wc_PKCS7_EncodeEncryptedData),
|
TEST_DECL(test_wc_PKCS7_EncodeEncryptedData),
|
||||||
TEST_DECL(test_wc_PKCS7_DecodeEncryptedKeyPackage),
|
TEST_DECL(test_wc_PKCS7_DecodeEncryptedKeyPackage),
|
||||||
TEST_DECL(test_wc_PKCS7_Degenerate),
|
TEST_DECL(test_wc_PKCS7_Degenerate),
|
||||||
|
@@ -6814,14 +6814,15 @@ static int PKCS7_GenerateContentEncryptionKey(wc_PKCS7* pkcs7, word32 len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */
|
/* wrap CEK (content encryption key) with KEK, returns output size (> 0) on
|
||||||
static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek,
|
* success, < 0 on error */
|
||||||
word32 kekSz, byte* out, word32 outSz,
|
static int wc_PKCS7_KeyWrap(const wc_PKCS7 * pkcs7, const byte * cek,
|
||||||
int keyWrapAlgo, int direction)
|
word32 cekSz, const byte * kek, word32 kekSz, byte * out, word32 outSz,
|
||||||
|
int keyWrapAlgo, int direction)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (cek == NULL || kek == NULL || out == NULL)
|
if (pkcs7 == NULL || cek == NULL || kek == NULL || out == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
switch (keyWrapAlgo) {
|
switch (keyWrapAlgo) {
|
||||||
@@ -6837,14 +6838,24 @@ static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (direction == AES_ENCRYPTION) {
|
if (direction == AES_ENCRYPTION) {
|
||||||
|
if (pkcs7->aesKeyWrapUnwrapCb != NULL) {
|
||||||
ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz,
|
ret = pkcs7->aesKeyWrapUnwrapCb(kek, kekSz, cek, cekSz, 1,
|
||||||
out, outSz, NULL);
|
out, outSz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz,
|
||||||
|
out, outSz, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (direction == AES_DECRYPTION) {
|
} else if (direction == AES_DECRYPTION) {
|
||||||
|
if (pkcs7->aesKeyWrapUnwrapCb != NULL) {
|
||||||
ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz,
|
ret = pkcs7->aesKeyWrapUnwrapCb(kek, kekSz, cek, cekSz, 0,
|
||||||
out, outSz, NULL);
|
out, outSz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz,
|
||||||
|
out, outSz, NULL);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
WOLFSSL_MSG("Bad key un/wrap direction");
|
WOLFSSL_MSG("Bad key un/wrap direction");
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
@@ -7548,7 +7559,7 @@ int wc_PKCS7_AddRecipient_KARI(wc_PKCS7* pkcs7, const byte* cert, word32 certSz,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* encrypt CEK with KEK */
|
/* encrypt CEK with KEK */
|
||||||
keySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kari->kek,
|
keySz = wc_PKCS7_KeyWrap(pkcs7, pkcs7->cek, pkcs7->cekSz, kari->kek,
|
||||||
kari->kekSz, encryptedKey, encryptedKeySz,
|
kari->kekSz, encryptedKey, encryptedKeySz,
|
||||||
keyWrapOID, direction);
|
keyWrapOID, direction);
|
||||||
if (keySz <= 0) {
|
if (keySz <= 0) {
|
||||||
@@ -9630,9 +9641,8 @@ int wc_PKCS7_AddRecipient_KEKRI(wc_PKCS7* pkcs7, int keyWrapOID, byte* kek,
|
|||||||
direction = DES_ENCRYPTION;
|
direction = DES_ENCRYPTION;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kek, kekSz,
|
encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7, pkcs7->cek, pkcs7->cekSz, kek,
|
||||||
encryptedKey, (word32)encryptedKeySz, keyWrapOID,
|
kekSz, encryptedKey, (word32)encryptedKeySz, keyWrapOID, direction);
|
||||||
direction);
|
|
||||||
if (encryptedKeySz < 0) {
|
if (encryptedKeySz < 0) {
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||||
@@ -11082,6 +11092,19 @@ int wc_PKCS7_SetWrapCEKCb(wc_PKCS7* pkcs7, CallbackWrapCEK cb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* return 0 on success */
|
||||||
|
int wc_PKCS7_SetAESKeyWrapUnwrapCb(wc_PKCS7* pkcs7, CallbackAESKeyWrapUnwrap aesKeyWrapUnwrapCb)
|
||||||
|
{
|
||||||
|
if (pkcs7 == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
pkcs7->aesKeyWrapUnwrapCb = aesKeyWrapUnwrapCb;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Decrypt ASN.1 OtherRecipientInfo (ori), as defined by:
|
/* Decrypt ASN.1 OtherRecipientInfo (ori), as defined by:
|
||||||
*
|
*
|
||||||
* OtherRecipientInfo ::= SEQUENCE {
|
* OtherRecipientInfo ::= SEQUENCE {
|
||||||
@@ -11529,10 +11552,9 @@ static int wc_PKCS7_DecryptKekri(wc_PKCS7* pkcs7, byte* in, word32 inSz,
|
|||||||
(int)PKCS7_KEKRI, direction);
|
(int)PKCS7_KEKRI, direction);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, (word32)length,
|
keySz = wc_PKCS7_KeyWrap(pkcs7, pkiMsg + *idx, (word32)length,
|
||||||
pkcs7->privateKey, pkcs7->privateKeySz,
|
pkcs7->privateKey, pkcs7->privateKeySz, decryptedKey,
|
||||||
decryptedKey, *decryptedKeySz,
|
*decryptedKeySz, (int)keyWrapOID, direction);
|
||||||
(int)keyWrapOID, direction);
|
|
||||||
}
|
}
|
||||||
if (keySz <= 0)
|
if (keySz <= 0)
|
||||||
return keySz;
|
return keySz;
|
||||||
@@ -11795,9 +11817,10 @@ static int wc_PKCS7_DecryptKari(wc_PKCS7* pkcs7, byte* in, word32 inSz,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* decrypt CEK with KEK */
|
/* decrypt CEK with KEK */
|
||||||
keySz = wc_PKCS7_KeyWrap(encryptedKey, (word32)encryptedKeySz,
|
keySz = wc_PKCS7_KeyWrap(pkcs7, encryptedKey,
|
||||||
kari->kek, kari->kekSz, decryptedKey, *decryptedKeySz,
|
(word32)encryptedKeySz, kari->kek, kari->kekSz,
|
||||||
(int)keyWrapOID, direction);
|
decryptedKey, *decryptedKeySz, (int)keyWrapOID,
|
||||||
|
direction);
|
||||||
}
|
}
|
||||||
if (keySz <= 0) {
|
if (keySz <= 0) {
|
||||||
wc_PKCS7_KariFree(kari);
|
wc_PKCS7_KariFree(kari);
|
||||||
|
@@ -213,6 +213,8 @@ typedef int (*CallbackWrapCEK)(wc_PKCS7* pkcs7, byte* cek, word32 cekSz,
|
|||||||
byte* originKey, word32 originKeySz,
|
byte* originKey, word32 originKeySz,
|
||||||
byte* out, word32 outSz,
|
byte* out, word32 outSz,
|
||||||
int keyWrapAlgo, int type, int dir);
|
int keyWrapAlgo, int type, int dir);
|
||||||
|
typedef int (*CallbackAESKeyWrapUnwrap)(const byte* key, word32 keySz,
|
||||||
|
const byte* in, word32 inSz, int wrap, byte* out, word32 outSz);
|
||||||
|
|
||||||
/* Callbacks for supporting different stream cases */
|
/* Callbacks for supporting different stream cases */
|
||||||
typedef int (*CallbackGetContent)(wc_PKCS7* pkcs7, byte** content, void* ctx);
|
typedef int (*CallbackGetContent)(wc_PKCS7* pkcs7, byte** content, void* ctx);
|
||||||
@@ -371,6 +373,8 @@ struct wc_PKCS7 {
|
|||||||
} decryptKey;
|
} decryptKey;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CallbackAESKeyWrapUnwrap aesKeyWrapUnwrapCb;
|
||||||
|
|
||||||
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
|
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -498,6 +502,8 @@ WOLFSSL_API int wc_PKCS7_AddRecipient_ORI(wc_PKCS7* pkcs7, CallbackOriEncrypt c
|
|||||||
int options);
|
int options);
|
||||||
WOLFSSL_API int wc_PKCS7_SetWrapCEKCb(wc_PKCS7* pkcs7,
|
WOLFSSL_API int wc_PKCS7_SetWrapCEKCb(wc_PKCS7* pkcs7,
|
||||||
CallbackWrapCEK wrapCEKCb);
|
CallbackWrapCEK wrapCEKCb);
|
||||||
|
WOLFSSL_API int wc_PKCS7_SetAESKeyWrapUnwrapCb(wc_PKCS7* pkcs7,
|
||||||
|
CallbackAESKeyWrapUnwrap aesKeyWrapUnwrapCb);
|
||||||
|
|
||||||
#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)
|
#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)
|
||||||
WOLFSSL_API int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7,
|
WOLFSSL_API int wc_PKCS7_SetRsaSignRawDigestCb(wc_PKCS7* pkcs7,
|
||||||
|
Reference in New Issue
Block a user