mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 12:10:51 +02:00
Address copilot feedback
This commit is contained in:
@@ -253,18 +253,29 @@ int wc_DhPublicKeyDecode(const byte* input, word32* inOutIdx, DhKey* key,
|
||||
3. Calls the user-provided callback to perform the actual signing
|
||||
4. Encodes the signature into the certificate/CSR DER structure
|
||||
|
||||
NOTE: Only RSA and ECC key types are supported. Ed25519, Ed448, and
|
||||
post-quantum algorithms (Falcon, Dilithium, SPHINCS+) sign messages
|
||||
directly rather than hashes, so they cannot use this callback-based API.
|
||||
Use wc_SignCert_ex for those algorithms.
|
||||
|
||||
NOTE: This function does NOT support async crypto (WOLFSSL_ASYNC_CRYPT).
|
||||
The internal context is local to this function and cannot persist across
|
||||
async re-entry.
|
||||
|
||||
\param requestSz Size of the certificate body to sign (from Cert.bodySz).
|
||||
\param sType Signature algorithm type (e.g., CTC_SHA256wRSA,
|
||||
CTC_SHA256wECDSA).
|
||||
\param buf Buffer containing the certificate/CSR DER data to sign.
|
||||
\param buffSz Total size of the buffer (must be large enough for signature).
|
||||
\param keyType Type of key used for signing (RSA_TYPE, ECC_TYPE, etc.).
|
||||
\param keyType Type of key used for signing. Only RSA_TYPE and ECC_TYPE
|
||||
are supported.
|
||||
\param signCb User-provided signing callback function.
|
||||
\param signCtx Context pointer passed to the signing callback.
|
||||
\param rng Random number generator (may be NULL if not needed).
|
||||
|
||||
\return Size of the signed certificate/CSR on success.
|
||||
\return BAD_FUNC_ARG if signCb is NULL or other parameters are invalid.
|
||||
\return BAD_FUNC_ARG if signCb or buf is NULL, buffSz is 0, or keyType
|
||||
is not RSA_TYPE or ECC_TYPE.
|
||||
\return BUFFER_E if the buffer is too small for the signed certificate.
|
||||
\return MEMORY_E if memory allocation fails.
|
||||
\return Negative error code on other failures.
|
||||
|
||||
+72
-1
@@ -20041,6 +20041,20 @@ static int mockSignCb(const byte* in, word32 inLen, byte* out, word32* outLen,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Mock callback that always returns an error for testing */
|
||||
static int mockSignCbError(const byte* in, word32 inLen, byte* out,
|
||||
word32* outLen, int sigAlgo, int keyType, void* ctx)
|
||||
{
|
||||
(void)in;
|
||||
(void)inLen;
|
||||
(void)out;
|
||||
(void)outLen;
|
||||
(void)sigAlgo;
|
||||
(void)keyType;
|
||||
(void)ctx;
|
||||
return BAD_STATE_E; /* Return an error */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_CERT_SIGN_CB
|
||||
@@ -20058,12 +20072,14 @@ static int test_wc_SignCert_cb(void)
|
||||
WC_RNG rng;
|
||||
ecc_key key;
|
||||
MockSignCtx signCtx;
|
||||
DecodedCert decodedCert;
|
||||
int ret;
|
||||
|
||||
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
||||
XMEMSET(&key, 0, sizeof(ecc_key));
|
||||
XMEMSET(&cert, 0, sizeof(Cert));
|
||||
XMEMSET(&signCtx, 0, sizeof(MockSignCtx));
|
||||
XMEMSET(&decodedCert, 0, sizeof(DecodedCert));
|
||||
|
||||
ExpectIntEQ(wc_InitRng(&rng), 0);
|
||||
ExpectIntEQ(wc_ecc_init(&key), 0);
|
||||
@@ -20097,9 +20113,37 @@ static int test_wc_SignCert_cb(void)
|
||||
/* Verify the certificate was created properly */
|
||||
ExpectIntGT(derSize, 0);
|
||||
|
||||
/* Parse the certificate and verify it's well-formed */
|
||||
if (EXPECT_SUCCESS()) {
|
||||
wc_InitDecodedCert(&decodedCert, der, (word32)derSize, NULL);
|
||||
ExpectIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL),
|
||||
0);
|
||||
/* Verify signature algorithm matches what we set */
|
||||
ExpectIntEQ(decodedCert.signatureOID, CTC_SHA256wECDSA);
|
||||
wc_FreeDecodedCert(&decodedCert);
|
||||
}
|
||||
|
||||
/* Test error cases */
|
||||
/* NULL callback */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
|
||||
FOURK_BUF, ECC_TYPE, NULL, &signCtx, &rng), BAD_FUNC_ARG);
|
||||
/* NULL buffer */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, NULL,
|
||||
FOURK_BUF, ECC_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG);
|
||||
/* Zero buffer size */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
|
||||
0, ECC_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG);
|
||||
/* Negative requestSz - should return the negative value */
|
||||
ExpectIntLT(wc_SignCert_cb(-1, cert.sigType, der,
|
||||
FOURK_BUF, ECC_TYPE, mockSignCb, &signCtx, &rng), 0);
|
||||
/* Callback returning error */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
|
||||
FOURK_BUF, ECC_TYPE, mockSignCbError, &signCtx, &rng), BAD_STATE_E);
|
||||
#ifndef NO_RSA
|
||||
/* Invalid keyType for ECC signature */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
|
||||
FOURK_BUF, ED25519_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG);
|
||||
#endif
|
||||
|
||||
ret = wc_ecc_free(&key);
|
||||
ExpectIntEQ(ret, 0);
|
||||
@@ -20117,12 +20161,14 @@ static int test_wc_SignCert_cb(void)
|
||||
WC_RNG rng;
|
||||
RsaKey key;
|
||||
MockSignCtx signCtx;
|
||||
DecodedCert decodedCert;
|
||||
int ret;
|
||||
|
||||
XMEMSET(&rng, 0, sizeof(WC_RNG));
|
||||
XMEMSET(&key, 0, sizeof(RsaKey));
|
||||
XMEMSET(&cert, 0, sizeof(Cert));
|
||||
XMEMSET(&signCtx, 0, sizeof(MockSignCtx));
|
||||
XMEMSET(&decodedCert, 0, sizeof(DecodedCert));
|
||||
|
||||
ExpectIntEQ(wc_InitRng(&rng), 0);
|
||||
ExpectIntEQ(wc_InitRsaKey(&key, NULL), 0);
|
||||
@@ -20156,9 +20202,34 @@ static int test_wc_SignCert_cb(void)
|
||||
/* Verify the certificate was created properly */
|
||||
ExpectIntGT(derSize, 0);
|
||||
|
||||
/* Test error case - NULL callback */
|
||||
/* Parse the certificate and verify it's well-formed */
|
||||
if (EXPECT_SUCCESS()) {
|
||||
wc_InitDecodedCert(&decodedCert, der, (word32)derSize, NULL);
|
||||
ExpectIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL),
|
||||
0);
|
||||
/* Verify signature algorithm matches what we set */
|
||||
ExpectIntEQ(decodedCert.signatureOID, CTC_SHA256wRSA);
|
||||
wc_FreeDecodedCert(&decodedCert);
|
||||
}
|
||||
|
||||
/* Test error cases */
|
||||
/* NULL callback */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
|
||||
FOURK_BUF, RSA_TYPE, NULL, &signCtx, &rng), BAD_FUNC_ARG);
|
||||
/* NULL buffer */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, NULL,
|
||||
FOURK_BUF, RSA_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG);
|
||||
/* Zero buffer size */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
|
||||
0, RSA_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG);
|
||||
/* Callback returning error */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
|
||||
FOURK_BUF, RSA_TYPE, mockSignCbError, &signCtx, &rng), BAD_STATE_E);
|
||||
#ifdef HAVE_ECC
|
||||
/* Invalid keyType */
|
||||
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
|
||||
FOURK_BUF, ED448_TYPE, mockSignCb, &signCtx, &rng), BAD_FUNC_ARG);
|
||||
#endif
|
||||
|
||||
ret = wc_FreeRsaKey(&key);
|
||||
ExpectIntEQ(ret, 0);
|
||||
|
||||
+92
-15
@@ -32112,46 +32112,46 @@ static int InternalSignCb(const byte* in, word32 inLen,
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* !NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY && !WOLFSSL_RSA_VERIFY_ONLY */
|
||||
|
||||
#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)
|
||||
if (keyType == ECC_TYPE && signCtx->key) {
|
||||
/* For ECC, input is the raw hash */
|
||||
ret = wc_ecc_sign_hash(in, inLen, out, outLen,
|
||||
signCtx->rng, (ecc_key*)signCtx->key);
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_ECC && HAVE_ECC_SIGN */
|
||||
|
||||
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_SIGN)
|
||||
if (keyType == ED25519_TYPE && signCtx->key) {
|
||||
/* Ed25519 signs messages, not hashes - cannot use callback path */
|
||||
ret = SIG_TYPE_E;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_ED25519 && HAVE_ED25519_SIGN */
|
||||
|
||||
#if defined(HAVE_ED448) && defined(HAVE_ED448_SIGN)
|
||||
if (keyType == ED448_TYPE && signCtx->key) {
|
||||
/* Ed448 signs messages, not hashes - cannot use callback path */
|
||||
ret = SIG_TYPE_E;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_ED448 && HAVE_ED448_SIGN */
|
||||
|
||||
#if defined(HAVE_FALCON)
|
||||
if ((keyType == FALCON_LEVEL1_TYPE || keyType == FALCON_LEVEL5_TYPE) &&
|
||||
signCtx->key) {
|
||||
/* Falcon signs messages, not hashes - cannot use callback path */
|
||||
ret = SIG_TYPE_E;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_FALCON */
|
||||
|
||||
#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN)
|
||||
if ((keyType == DILITHIUM_LEVEL2_TYPE || keyType == DILITHIUM_LEVEL3_TYPE ||
|
||||
keyType == DILITHIUM_LEVEL5_TYPE) && signCtx->key) {
|
||||
/* Dilithium signs messages, not hashes - cannot use callback path */
|
||||
ret = SIG_TYPE_E;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_DILITHIUM && !WOLFSSL_DILITHIUM_NO_SIGN */
|
||||
|
||||
#if defined(HAVE_SPHINCS)
|
||||
if ((keyType == SPHINCS_FAST_LEVEL1_TYPE || keyType == SPHINCS_FAST_LEVEL3_TYPE ||
|
||||
keyType == SPHINCS_FAST_LEVEL5_TYPE || keyType == SPHINCS_SMALL_LEVEL1_TYPE ||
|
||||
@@ -32160,7 +32160,17 @@ static int InternalSignCb(const byte* in, word32 inLen,
|
||||
/* Sphincs signs messages, not hashes - cannot use callback path */
|
||||
ret = SIG_TYPE_E;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_SPHINCS */
|
||||
{
|
||||
/* Unhandled key type */
|
||||
(void)in;
|
||||
(void)inLen;
|
||||
(void)out;
|
||||
(void)outLen;
|
||||
(void)keyType;
|
||||
(void)signCtx;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -34004,7 +34014,7 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
|
||||
word32 sz, byte* sig, word32 sigSz, int sigAlgoType, int keyType,
|
||||
wc_SignCertCb signCb, void* signCtx, WC_RNG* rng, void* heap)
|
||||
{
|
||||
int digestSz = 0, typeH = 0, ret = 0;
|
||||
int ret = 0;
|
||||
word32 outLen;
|
||||
|
||||
(void)rng;
|
||||
@@ -34012,6 +34022,26 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
|
||||
(void)heap;
|
||||
#endif
|
||||
|
||||
/* Validate keyType - only RSA and ECC are supported for callback signing.
|
||||
* Ed25519, Ed448, and post-quantum algorithms sign messages directly,
|
||||
* not hashes, so they cannot use the callback path. */
|
||||
#if !defined(NO_RSA) && defined(HAVE_ECC)
|
||||
if (keyType != RSA_TYPE && keyType != ECC_TYPE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
#elif !defined(NO_RSA)
|
||||
if (keyType != RSA_TYPE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
#elif defined(HAVE_ECC)
|
||||
if (keyType != ECC_TYPE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
#else
|
||||
(void)keyType;
|
||||
return NOT_COMPILED_IN;
|
||||
#endif
|
||||
|
||||
switch (certSignCtx->state) {
|
||||
case CERTSIGN_STATE_BEGIN:
|
||||
case CERTSIGN_STATE_DIGEST:
|
||||
@@ -34025,7 +34055,8 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
|
||||
}
|
||||
#endif
|
||||
ret = HashForSignature(buf, sz, (word32)sigAlgoType, certSignCtx->digest,
|
||||
&typeH, &digestSz, 0, NULL, INVALID_DEVID);
|
||||
&certSignCtx->typeH, &certSignCtx->digestSz, 0,
|
||||
NULL, INVALID_DEVID);
|
||||
certSignCtx->state = CERTSIGN_STATE_ENCODE;
|
||||
if (ret != 0) {
|
||||
goto exit_ms;
|
||||
@@ -34044,8 +34075,10 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
|
||||
goto exit_ms;
|
||||
}
|
||||
#endif
|
||||
/* typeH was stored in certSignCtx by HashForSignature */
|
||||
certSignCtx->encSigSz = (int)wc_EncodeSignature(certSignCtx->encSig,
|
||||
certSignCtx->digest, (word32)digestSz, typeH);
|
||||
certSignCtx->digest, (word32)certSignCtx->digestSz,
|
||||
certSignCtx->typeH);
|
||||
}
|
||||
#endif /* !NO_RSA */
|
||||
FALL_THROUGH;
|
||||
@@ -34065,10 +34098,17 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
|
||||
#endif /* !NO_RSA */
|
||||
{
|
||||
/* ECC: pass raw hash */
|
||||
ret = signCb(certSignCtx->digest, (word32)digestSz,
|
||||
ret = signCb(certSignCtx->digest, (word32)certSignCtx->digestSz,
|
||||
sig, &outLen, sigAlgoType, keyType, signCtx);
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* If callback returns WC_PENDING_E, preserve state for re-entry */
|
||||
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == 0) {
|
||||
ret = (int)outLen;
|
||||
}
|
||||
@@ -34089,6 +34129,8 @@ exit_ms:
|
||||
|
||||
/* reset state */
|
||||
certSignCtx->state = CERTSIGN_STATE_BEGIN;
|
||||
certSignCtx->digestSz = 0;
|
||||
certSignCtx->typeH = 0;
|
||||
|
||||
if (ret < 0) {
|
||||
WOLFSSL_ERROR_VERBOSE(ret);
|
||||
@@ -34402,16 +34444,22 @@ int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
|
||||
* This allows external signing implementations (e.g., TPM, HSM)
|
||||
* without requiring the crypto callback infrastructure.
|
||||
*
|
||||
* NOTE: This function does NOT support async crypto (WOLFSSL_ASYNC_CRYPT).
|
||||
* The certSignCtx is local to this function and cannot persist across
|
||||
* async re-entry. Use wc_SignCert or wc_SignCert_ex for async operations.
|
||||
*
|
||||
* @param [in] requestSz Size of certificate body to sign.
|
||||
* @param [in] sType The signature type.
|
||||
* @param [in,out] buf Der buffer to sign.
|
||||
* @param [in] buffSz Der buffer size.
|
||||
* @param [in] keyType The type of key.
|
||||
* @param [in] keyType The type of key (RSA_TYPE or ECC_TYPE only).
|
||||
* @param [in] signCb User signing callback.
|
||||
* @param [in] signCtx Context passed to callback.
|
||||
* @param [in] rng Random number generator (may be NULL).
|
||||
*
|
||||
* @return Size of signature on success.
|
||||
* @return BAD_FUNC_ARG if signCb or buf is NULL, buffSz is 0, or invalid
|
||||
* keyType.
|
||||
* @return < 0 on error
|
||||
*/
|
||||
#ifdef WOLFSSL_CERT_SIGN_CB
|
||||
@@ -34423,10 +34471,29 @@ int wc_SignCert_cb(int requestSz, int sType, byte* buf, word32 buffSz,
|
||||
CertSignCtx certSignCtx_lcl;
|
||||
CertSignCtx* certSignCtx = &certSignCtx_lcl;
|
||||
|
||||
if (signCb == NULL || buf == NULL) {
|
||||
/* Validate parameters */
|
||||
if (signCb == NULL || buf == NULL || buffSz == 0) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Validate keyType - only RSA and ECC supported */
|
||||
#if !defined(NO_RSA) && defined(HAVE_ECC)
|
||||
if (keyType != RSA_TYPE && keyType != ECC_TYPE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
#elif !defined(NO_RSA)
|
||||
if (keyType != RSA_TYPE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
#elif defined(HAVE_ECC)
|
||||
if (keyType != ECC_TYPE) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
#else
|
||||
(void)keyType;
|
||||
return NOT_COMPILED_IN;
|
||||
#endif
|
||||
|
||||
XMEMSET(certSignCtx, 0, sizeof(*certSignCtx));
|
||||
|
||||
if (requestSz < 0) {
|
||||
@@ -34447,13 +34514,23 @@ int wc_SignCert_cb(int requestSz, int sType, byte* buf, word32 buffSz,
|
||||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
if (sigSz == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
/* Not free'ing certSignCtx->sig here because it could still be in use
|
||||
* with async operations. */
|
||||
return sigSz;
|
||||
/* Async crypto not supported with wc_SignCert_cb because certSignCtx
|
||||
* is local and cannot persist across re-entry. Clean up and return
|
||||
* error. */
|
||||
#ifndef WOLFSSL_NO_MALLOC
|
||||
XFREE(certSignCtx->sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
certSignCtx->sig = NULL;
|
||||
#endif
|
||||
return NOT_COMPILED_IN;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sigSz >= 0) {
|
||||
/* Check buffer has room for signature structure. This is an estimate
|
||||
* using MAX_SEQ_SZ * 2 to account for sequence headers and algorithm
|
||||
* identifier overhead. For precise sizing, call AddSignature with
|
||||
* NULL buffer first, but this estimate matches the existing pattern
|
||||
* used in SignCert. */
|
||||
if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz) {
|
||||
sigSz = BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ typedef int (wc_pem_password_cb)(char* passwd, int sz, int rw, void* userdata);
|
||||
\param outLen Input: size of output buffer. Output: actual signature size.
|
||||
\param sigAlgo Signature algorithm identifier (e.g., CTC_SHA256wRSA,
|
||||
CTC_SHA256wECDSA).
|
||||
\param keyType Key type (RSA_TYPE, ECC_TYPE, etc.).
|
||||
\param keyType Key type (RSA_TYPE or ECC_TYPE only).
|
||||
\param ctx User-provided context pointer for callback state.
|
||||
|
||||
\return 0 on success.
|
||||
|
||||
@@ -2397,6 +2397,8 @@ enum Max_ASN {
|
||||
#ifndef NO_RSA
|
||||
int encSigSz;
|
||||
#endif
|
||||
int digestSz;
|
||||
int typeH; /* Hash algorithm type for encoding */
|
||||
int state; /* enum CertSignState */
|
||||
} CertSignCtx;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user