Skip to content
13 changes: 13 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -4534,6 +4534,19 @@ then
fi


# CERT SIGN CALLBACK
AC_ARG_ENABLE([certsigncb],
[AS_HELP_STRING([--enable-certsigncb],[Enable cert signing callback API for TPM/HSM (default: disabled)])],
[ ENABLED_CERTSIGNCB=$enableval ],
[ ENABLED_CERTSIGNCB=no ]
)

if test "$ENABLED_CERTSIGNCB" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_SIGN_CB"
fi


# SEP
AC_ARG_ENABLE([sep],
[AS_HELP_STRING([--enable-sep],[Enable sep extensions (default: disabled)])],
Expand Down
123 changes: 123 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -26920,6 +26920,126 @@ static int test_MakeCertWithCaFalse(void)
return EXPECT_RESULT();
}

/* Mock callback for testing wc_SignCert_cb */
#if defined(WOLFSSL_CERT_SIGN_CB) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ))
/* Context structure for mock signing callback */
typedef struct {
void* key; /* Pointer to RSA or ECC key */
WC_RNG* rng; /* Random number generator (required for ECC) */
} MockSignCtx;

static int mockSignCb(const byte* in, word32 inLen, byte* out, word32* outLen,
int sigAlgo, int keyType, void* ctx)
{
int ret = 0;
MockSignCtx* signCtx = (MockSignCtx*)ctx;

if (signCtx == NULL || signCtx->key == NULL || in == NULL ||
out == NULL || outLen == NULL) {
return BAD_FUNC_ARG;
}

(void)sigAlgo;

#ifndef NO_RSA
if (keyType == RSA_TYPE) {
RsaKey* rsaKey = (RsaKey*)signCtx->key;
word32 outSz = *outLen;

/* For RSA, input is DER-encoded digest (DigestInfo structure) */
ret = wc_RsaSSL_Sign(in, inLen, out, outSz, rsaKey, signCtx->rng);
if (ret > 0) {
*outLen = (word32)ret;
ret = 0;
}
}
else
#endif
#ifdef HAVE_ECC
if (keyType == ECC_TYPE) {
ecc_key* eccKey = (ecc_key*)signCtx->key;
word32 outSz = *outLen;

/* For ECC, input is raw hash, sign it (RNG required for ECDSA k value) */
ret = wc_ecc_sign_hash(in, inLen, out, &outSz, signCtx->rng, eccKey);
if (ret == 0) {
*outLen = outSz;
}
}
else
#endif
{
ret = BAD_FUNC_ARG;
}

return ret;
}
#endif

#ifdef WOLFSSL_CERT_SIGN_CB
static int test_wc_SignCert_cb(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && !defined(NO_ASN_TIME)
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only covers ECC key types, but the API and implementation support both RSA and ECC. Consider adding a test case for RSA to ensure the RSA code path (wc_RsaSSL_Sign in the callback) is also tested and works correctly with the new API.

Copilot uses AI. Check for mistakes.
Cert cert;
byte der[FOURK_BUF];
int derSize = 0;
WC_RNG rng;
ecc_key key;
MockSignCtx signCtx;
int ret;

XMEMSET(&rng, 0, sizeof(WC_RNG));
XMEMSET(&key, 0, sizeof(ecc_key));
XMEMSET(&cert, 0, sizeof(Cert));
XMEMSET(&signCtx, 0, sizeof(MockSignCtx));

ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_ecc_init(&key), 0);
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &key), 0);
ExpectIntEQ(wc_InitCert(&cert), 0);

(void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
(void)XSTRNCPY(cert.subject.state, "state", CTC_NAME_SIZE);
(void)XSTRNCPY(cert.subject.locality, "locality", CTC_NAME_SIZE);
(void)XSTRNCPY(cert.subject.org, "org", CTC_NAME_SIZE);
(void)XSTRNCPY(cert.subject.unit, "unit", CTC_NAME_SIZE);
(void)XSTRNCPY(cert.subject.commonName, "www.example.com",
CTC_NAME_SIZE);
(void)XSTRNCPY(cert.subject.email, "[email protected]", CTC_NAME_SIZE);

cert.selfSigned = 1;
cert.isCA = 0;
cert.sigType = CTC_SHA256wECDSA;

/* Make cert body */
ExpectIntGT(wc_MakeCert(&cert, der, FOURK_BUF, NULL, &key, &rng), 0);

/* Setup signing context with key and RNG */
signCtx.key = &key;
signCtx.rng = &rng;

/* Sign using callback API */
ExpectIntGT(derSize = wc_SignCert_cb(cert.bodySz, cert.sigType, der,
FOURK_BUF, ECC_TYPE, mockSignCb, &signCtx, &rng), 0);
Comment on lines +26980 to +27024
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only exercises the ECC code path. The mockSignCb function includes RSA support, but test_wc_SignCert_cb only tests with ECC keys. Consider adding a separate test case or expanding this test to also verify RSA certificate signing via the callback to ensure complete test coverage.

Copilot uses AI. Check for mistakes.

/* Verify the certificate was created properly */
ExpectIntGT(derSize, 0);

/* Test error cases */
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
FOURK_BUF, ECC_TYPE, NULL, &signCtx, &rng), BAD_FUNC_ARG);

ret = wc_ecc_free(&key);
ExpectIntEQ(ret, 0);
ret = wc_FreeRng(&rng);
ExpectIntEQ(ret, 0);
#endif
return EXPECT_RESULT();
}
#endif /* WOLFSSL_CERT_SIGN_CB */


static int test_wolfSSL_EVP_PKEY_encrypt(void)
{
EXPECT_DECLS;
Expand Down Expand Up @@ -41535,6 +41655,9 @@ TEST_CASE testCases[] = {
TEST_DECL(test_MakeCertWithPathLen),
TEST_DECL(test_MakeCertWith0Ser),
TEST_DECL(test_MakeCertWithCaFalse),
#ifdef WOLFSSL_CERT_SIGN_CB
TEST_DECL(test_wc_SignCert_cb),
#endif
TEST_DECL(test_wc_SetKeyUsage),
TEST_DECL(test_wc_SetAuthKeyIdFromPublicKey_ex),
TEST_DECL(test_wc_SetSubjectBuffer),
Expand Down
Loading