Skip to content

Commit 2cf03da

Browse files
committed
Add wc_SignCert_cb API for external signing callbacks
1 parent ff28a11 commit 2cf03da

File tree

4 files changed

+586
-139
lines changed

4 files changed

+586
-139
lines changed

configure.ac

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4591,6 +4591,19 @@ then
45914591
fi
45924592

45934593

4594+
# CERT SIGN CALLBACK
4595+
AC_ARG_ENABLE([certsigncb],
4596+
[AS_HELP_STRING([--enable-certsigncb],[Enable cert signing callback API for TPM/HSM (default: disabled)])],
4597+
[ ENABLED_CERTSIGNCB=$enableval ],
4598+
[ ENABLED_CERTSIGNCB=no ]
4599+
)
4600+
4601+
if test "$ENABLED_CERTSIGNCB" = "yes"
4602+
then
4603+
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_SIGN_CB"
4604+
fi
4605+
4606+
45944607
# SEP
45954608
AC_ARG_ENABLE([sep],
45964609
[AS_HELP_STRING([--enable-sep],[Enable sep extensions (default: disabled)])],

tests/api.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19987,6 +19987,125 @@ static int test_MakeCertWithCaFalse(void)
1998719987
return EXPECT_RESULT();
1998819988
}
1998919989

19990+
/* Mock callback for testing wc_SignCert_cb */
19991+
#if defined(WOLFSSL_CERT_SIGN_CB) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ))
19992+
/* Context structure for mock signing callback */
19993+
typedef struct {
19994+
void* key; /* Pointer to RSA or ECC key */
19995+
WC_RNG* rng; /* Random number generator (required for ECC) */
19996+
} MockSignCtx;
19997+
19998+
static int mockSignCb(const byte* in, word32 inLen, byte* out, word32* outLen,
19999+
int sigAlgo, int keyType, void* ctx)
20000+
{
20001+
int ret = 0;
20002+
MockSignCtx* signCtx = (MockSignCtx*)ctx;
20003+
20004+
if (signCtx == NULL || signCtx->key == NULL || in == NULL ||
20005+
out == NULL || outLen == NULL) {
20006+
return BAD_FUNC_ARG;
20007+
}
20008+
20009+
(void)sigAlgo;
20010+
20011+
#ifndef NO_RSA
20012+
if (keyType == RSA_TYPE) {
20013+
RsaKey* rsaKey = (RsaKey*)signCtx->key;
20014+
word32 outSz = *outLen;
20015+
20016+
/* For RSA, input is DER-encoded digest (DigestInfo structure) */
20017+
ret = wc_RsaSSL_Sign(in, inLen, out, outSz, rsaKey, signCtx->rng);
20018+
if (ret > 0) {
20019+
*outLen = (word32)ret;
20020+
ret = 0;
20021+
}
20022+
}
20023+
else
20024+
#endif
20025+
#ifdef HAVE_ECC
20026+
if (keyType == ECC_TYPE) {
20027+
ecc_key* eccKey = (ecc_key*)signCtx->key;
20028+
word32 outSz = *outLen;
20029+
20030+
/* For ECC, input is raw hash, sign it (RNG required for ECDSA k value) */
20031+
ret = wc_ecc_sign_hash(in, inLen, out, &outSz, signCtx->rng, eccKey);
20032+
if (ret == 0) {
20033+
*outLen = outSz;
20034+
}
20035+
}
20036+
else
20037+
#endif
20038+
{
20039+
ret = BAD_FUNC_ARG;
20040+
}
20041+
20042+
return ret;
20043+
}
20044+
#endif
20045+
20046+
#ifdef WOLFSSL_CERT_SIGN_CB
20047+
static int test_wc_SignCert_cb(void)
20048+
{
20049+
EXPECT_DECLS;
20050+
#if defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && !defined(NO_ASN_TIME)
20051+
Cert cert;
20052+
byte der[FOURK_BUF];
20053+
int derSize = 0;
20054+
WC_RNG rng;
20055+
ecc_key key;
20056+
MockSignCtx signCtx;
20057+
int ret;
20058+
20059+
XMEMSET(&rng, 0, sizeof(WC_RNG));
20060+
XMEMSET(&key, 0, sizeof(ecc_key));
20061+
XMEMSET(&cert, 0, sizeof(Cert));
20062+
XMEMSET(&signCtx, 0, sizeof(MockSignCtx));
20063+
20064+
ExpectIntEQ(wc_InitRng(&rng), 0);
20065+
ExpectIntEQ(wc_ecc_init(&key), 0);
20066+
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &key), 0);
20067+
ExpectIntEQ(wc_InitCert(&cert), 0);
20068+
20069+
(void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
20070+
(void)XSTRNCPY(cert.subject.state, "state", CTC_NAME_SIZE);
20071+
(void)XSTRNCPY(cert.subject.locality, "locality", CTC_NAME_SIZE);
20072+
(void)XSTRNCPY(cert.subject.org, "org", CTC_NAME_SIZE);
20073+
(void)XSTRNCPY(cert.subject.unit, "unit", CTC_NAME_SIZE);
20074+
(void)XSTRNCPY(cert.subject.commonName, "www.example.com",
20075+
CTC_NAME_SIZE);
20076+
(void)XSTRNCPY(cert.subject.email, "[email protected]", CTC_NAME_SIZE);
20077+
20078+
cert.selfSigned = 1;
20079+
cert.isCA = 0;
20080+
cert.sigType = CTC_SHA256wECDSA;
20081+
20082+
/* Make cert body */
20083+
ExpectIntGT(wc_MakeCert(&cert, der, FOURK_BUF, NULL, &key, &rng), 0);
20084+
20085+
/* Setup signing context with key and RNG */
20086+
signCtx.key = &key;
20087+
signCtx.rng = &rng;
20088+
20089+
/* Sign using callback API */
20090+
ExpectIntGT(derSize = wc_SignCert_cb(cert.bodySz, cert.sigType, der,
20091+
FOURK_BUF, ECC_TYPE, mockSignCb, &signCtx, &rng), 0);
20092+
20093+
/* Verify the certificate was created properly */
20094+
ExpectIntGT(derSize, 0);
20095+
20096+
/* Test error cases */
20097+
ExpectIntEQ(wc_SignCert_cb(cert.bodySz, cert.sigType, der,
20098+
FOURK_BUF, ECC_TYPE, NULL, &signCtx, &rng), BAD_FUNC_ARG);
20099+
20100+
ret = wc_ecc_free(&key);
20101+
ExpectIntEQ(ret, 0);
20102+
ret = wc_FreeRng(&rng);
20103+
ExpectIntEQ(ret, 0);
20104+
#endif
20105+
return EXPECT_RESULT();
20106+
}
20107+
#endif /* WOLFSSL_CERT_SIGN_CB */
20108+
1999020109
static int test_ERR_load_crypto_strings(void)
1999120110
{
1999220111
#if defined(OPENSSL_ALL)
@@ -31467,6 +31586,9 @@ TEST_CASE testCases[] = {
3146731586
TEST_DECL(test_MakeCertWithPathLen),
3146831587
TEST_DECL(test_MakeCertWith0Ser),
3146931588
TEST_DECL(test_MakeCertWithCaFalse),
31589+
#ifdef WOLFSSL_CERT_SIGN_CB
31590+
TEST_DECL(test_wc_SignCert_cb),
31591+
#endif
3147031592
TEST_DECL(test_wc_SetKeyUsage),
3147131593
TEST_DECL(test_wc_SetAuthKeyIdFromPublicKey_ex),
3147231594
TEST_DECL(test_wc_SetSubjectBuffer),

0 commit comments

Comments
 (0)