@@ -32112,46 +32112,46 @@ static int InternalSignCb(const byte* in, word32 inLen,
3211232112 ret = 0;
3211332113 }
3211432114 }
32115+ else
3211532116#endif /* !NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY && !WOLFSSL_RSA_VERIFY_ONLY */
32116-
3211732117#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)
3211832118 if (keyType == ECC_TYPE && signCtx->key) {
3211932119 /* For ECC, input is the raw hash */
3212032120 ret = wc_ecc_sign_hash(in, inLen, out, outLen,
3212132121 signCtx->rng, (ecc_key*)signCtx->key);
3212232122 }
32123+ else
3212332124#endif /* HAVE_ECC && HAVE_ECC_SIGN */
32124-
3212532125#if defined(HAVE_ED25519) && defined(HAVE_ED25519_SIGN)
3212632126 if (keyType == ED25519_TYPE && signCtx->key) {
3212732127 /* Ed25519 signs messages, not hashes - cannot use callback path */
3212832128 ret = SIG_TYPE_E;
3212932129 }
32130+ else
3213032131#endif /* HAVE_ED25519 && HAVE_ED25519_SIGN */
32131-
3213232132#if defined(HAVE_ED448) && defined(HAVE_ED448_SIGN)
3213332133 if (keyType == ED448_TYPE && signCtx->key) {
3213432134 /* Ed448 signs messages, not hashes - cannot use callback path */
3213532135 ret = SIG_TYPE_E;
3213632136 }
32137+ else
3213732138#endif /* HAVE_ED448 && HAVE_ED448_SIGN */
32138-
3213932139#if defined(HAVE_FALCON)
3214032140 if ((keyType == FALCON_LEVEL1_TYPE || keyType == FALCON_LEVEL5_TYPE) &&
3214132141 signCtx->key) {
3214232142 /* Falcon signs messages, not hashes - cannot use callback path */
3214332143 ret = SIG_TYPE_E;
3214432144 }
32145+ else
3214532146#endif /* HAVE_FALCON */
32146-
3214732147#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN)
3214832148 if ((keyType == DILITHIUM_LEVEL2_TYPE || keyType == DILITHIUM_LEVEL3_TYPE ||
3214932149 keyType == DILITHIUM_LEVEL5_TYPE) && signCtx->key) {
3215032150 /* Dilithium signs messages, not hashes - cannot use callback path */
3215132151 ret = SIG_TYPE_E;
3215232152 }
32153+ else
3215332154#endif /* HAVE_DILITHIUM && !WOLFSSL_DILITHIUM_NO_SIGN */
32154-
3215532155#if defined(HAVE_SPHINCS)
3215632156 if ((keyType == SPHINCS_FAST_LEVEL1_TYPE || keyType == SPHINCS_FAST_LEVEL3_TYPE ||
3215732157 keyType == SPHINCS_FAST_LEVEL5_TYPE || keyType == SPHINCS_SMALL_LEVEL1_TYPE ||
@@ -32160,7 +32160,17 @@ static int InternalSignCb(const byte* in, word32 inLen,
3216032160 /* Sphincs signs messages, not hashes - cannot use callback path */
3216132161 ret = SIG_TYPE_E;
3216232162 }
32163+ else
3216332164#endif /* HAVE_SPHINCS */
32165+ {
32166+ /* Unhandled key type */
32167+ (void)in;
32168+ (void)inLen;
32169+ (void)out;
32170+ (void)outLen;
32171+ (void)keyType;
32172+ (void)signCtx;
32173+ }
3216432174
3216532175 return ret;
3216632176}
@@ -34004,14 +34014,34 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
3400434014 word32 sz, byte* sig, word32 sigSz, int sigAlgoType, int keyType,
3400534015 wc_SignCertCb signCb, void* signCtx, WC_RNG* rng, void* heap)
3400634016{
34007- int digestSz = 0, typeH = 0, ret = 0;
34017+ int ret = 0;
3400834018 word32 outLen;
3400934019
3401034020 (void)rng;
3401134021#ifdef WOLFSSL_NO_MALLOC
3401234022 (void)heap;
3401334023#endif
3401434024
34025+ /* Validate keyType - only RSA and ECC are supported for callback signing.
34026+ * Ed25519, Ed448, and post-quantum algorithms sign messages directly,
34027+ * not hashes, so they cannot use the callback path. */
34028+ #if !defined(NO_RSA) && defined(HAVE_ECC)
34029+ if (keyType != RSA_TYPE && keyType != ECC_TYPE) {
34030+ return BAD_FUNC_ARG;
34031+ }
34032+ #elif !defined(NO_RSA)
34033+ if (keyType != RSA_TYPE) {
34034+ return BAD_FUNC_ARG;
34035+ }
34036+ #elif defined(HAVE_ECC)
34037+ if (keyType != ECC_TYPE) {
34038+ return BAD_FUNC_ARG;
34039+ }
34040+ #else
34041+ (void)keyType;
34042+ return NOT_COMPILED_IN;
34043+ #endif
34044+
3401534045 switch (certSignCtx->state) {
3401634046 case CERTSIGN_STATE_BEGIN:
3401734047 case CERTSIGN_STATE_DIGEST:
@@ -34025,7 +34055,8 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
3402534055 }
3402634056#endif
3402734057 ret = HashForSignature(buf, sz, (word32)sigAlgoType, certSignCtx->digest,
34028- &typeH, &digestSz, 0, NULL, INVALID_DEVID);
34058+ &certSignCtx->typeH, &certSignCtx->digestSz, 0,
34059+ NULL, INVALID_DEVID);
3402934060 certSignCtx->state = CERTSIGN_STATE_ENCODE;
3403034061 if (ret != 0) {
3403134062 goto exit_ms;
@@ -34044,8 +34075,10 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
3404434075 goto exit_ms;
3404534076 }
3404634077#endif
34078+ /* typeH was stored in certSignCtx by HashForSignature */
3404734079 certSignCtx->encSigSz = (int)wc_EncodeSignature(certSignCtx->encSig,
34048- certSignCtx->digest, (word32)digestSz, typeH);
34080+ certSignCtx->digest, (word32)certSignCtx->digestSz,
34081+ certSignCtx->typeH);
3404934082 }
3405034083#endif /* !NO_RSA */
3405134084 FALL_THROUGH;
@@ -34065,10 +34098,17 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
3406534098#endif /* !NO_RSA */
3406634099 {
3406734100 /* ECC: pass raw hash */
34068- ret = signCb(certSignCtx->digest, (word32)digestSz,
34101+ ret = signCb(certSignCtx->digest, (word32)certSignCtx-> digestSz,
3406934102 sig, &outLen, sigAlgoType, keyType, signCtx);
3407034103 }
3407134104
34105+ #ifdef WOLFSSL_ASYNC_CRYPT
34106+ /* If callback returns WC_PENDING_E, preserve state for re-entry */
34107+ if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
34108+ return ret;
34109+ }
34110+ #endif
34111+
3407234112 if (ret == 0) {
3407334113 ret = (int)outLen;
3407434114 }
@@ -34089,6 +34129,8 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf,
3408934129
3409034130 /* reset state */
3409134131 certSignCtx->state = CERTSIGN_STATE_BEGIN;
34132+ certSignCtx->digestSz = 0;
34133+ certSignCtx->typeH = 0;
3409234134
3409334135 if (ret < 0) {
3409434136 WOLFSSL_ERROR_VERBOSE(ret);
@@ -34402,16 +34444,22 @@ int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
3440234444 * This allows external signing implementations (e.g., TPM, HSM)
3440334445 * without requiring the crypto callback infrastructure.
3440434446 *
34447+ * NOTE: This function does NOT support async crypto (WOLFSSL_ASYNC_CRYPT).
34448+ * The certSignCtx is local to this function and cannot persist across
34449+ * async re-entry. Use wc_SignCert or wc_SignCert_ex for async operations.
34450+ *
3440534451 * @param [in] requestSz Size of certificate body to sign.
3440634452 * @param [in] sType The signature type.
3440734453 * @param [in,out] buf Der buffer to sign.
3440834454 * @param [in] buffSz Der buffer size.
34409- * @param [in] keyType The type of key.
34455+ * @param [in] keyType The type of key (RSA_TYPE or ECC_TYPE only) .
3441034456 * @param [in] signCb User signing callback.
3441134457 * @param [in] signCtx Context passed to callback.
3441234458 * @param [in] rng Random number generator (may be NULL).
3441334459 *
3441434460 * @return Size of signature on success.
34461+ * @return BAD_FUNC_ARG if signCb or buf is NULL, buffSz is 0, or invalid
34462+ * keyType.
3441534463 * @return < 0 on error
3441634464 */
3441734465#ifdef WOLFSSL_CERT_SIGN_CB
@@ -34423,10 +34471,29 @@ int wc_SignCert_cb(int requestSz, int sType, byte* buf, word32 buffSz,
3442334471 CertSignCtx certSignCtx_lcl;
3442434472 CertSignCtx* certSignCtx = &certSignCtx_lcl;
3442534473
34426- if (signCb == NULL || buf == NULL) {
34474+ /* Validate parameters */
34475+ if (signCb == NULL || buf == NULL || buffSz == 0) {
3442734476 return BAD_FUNC_ARG;
3442834477 }
3442934478
34479+ /* Validate keyType - only RSA and ECC supported */
34480+ #if !defined(NO_RSA) && defined(HAVE_ECC)
34481+ if (keyType != RSA_TYPE && keyType != ECC_TYPE) {
34482+ return BAD_FUNC_ARG;
34483+ }
34484+ #elif !defined(NO_RSA)
34485+ if (keyType != RSA_TYPE) {
34486+ return BAD_FUNC_ARG;
34487+ }
34488+ #elif defined(HAVE_ECC)
34489+ if (keyType != ECC_TYPE) {
34490+ return BAD_FUNC_ARG;
34491+ }
34492+ #else
34493+ (void)keyType;
34494+ return NOT_COMPILED_IN;
34495+ #endif
34496+
3443034497 XMEMSET(certSignCtx, 0, sizeof(*certSignCtx));
3443134498
3443234499 if (requestSz < 0) {
@@ -34447,13 +34514,23 @@ int wc_SignCert_cb(int requestSz, int sType, byte* buf, word32 buffSz,
3444734514
3444834515#ifdef WOLFSSL_ASYNC_CRYPT
3444934516 if (sigSz == WC_NO_ERR_TRACE(WC_PENDING_E)) {
34450- /* Not free'ing certSignCtx->sig here because it could still be in use
34451- * with async operations. */
34452- return sigSz;
34517+ /* Async crypto not supported with wc_SignCert_cb because certSignCtx
34518+ * is local and cannot persist across re-entry. Clean up and return
34519+ * error. */
34520+ #ifndef WOLFSSL_NO_MALLOC
34521+ XFREE(certSignCtx->sig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
34522+ certSignCtx->sig = NULL;
34523+ #endif
34524+ return NOT_COMPILED_IN;
3445334525 }
3445434526#endif
3445534527
3445634528 if (sigSz >= 0) {
34529+ /* Check buffer has room for signature structure. This is an estimate
34530+ * using MAX_SEQ_SZ * 2 to account for sequence headers and algorithm
34531+ * identifier overhead. For precise sizing, call AddSignature with
34532+ * NULL buffer first, but this estimate matches the existing pattern
34533+ * used in SignCert. */
3445734534 if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz) {
3445834535 sigSz = BUFFER_E;
3445934536 }
0 commit comments