Initial implementation for using PKCS11 to retrieve certificate for SSL CTX

This commit is contained in:
Colton Willey
2024-12-09 12:15:41 -08:00
parent 67fb29a6f6
commit 324b87614e
7 changed files with 233 additions and 2 deletions

View File

@ -4146,6 +4146,84 @@ int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#endif /* WOLF_PRIVATE_KEY_ID */
#if defined(WOLF_CRYPTO_CB) && !defined(NO_CERTS)
static int wolfSSL_CTX_use_certificate_ex(WOLFSSL_CTX* ctx,
const char *label, const unsigned char *id, int idLen, int devId);
static int wolfSSL_CTX_use_certificate_ex(WOLFSSL_CTX* ctx,
const char *label, const unsigned char *id, int idLen, int devId)
{
int ret;
byte *certData = NULL;
word32 certDataLen = 0;
word32 labelLen = 0;
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_label_ex");
if (label != NULL) {
labelLen = (word32)XSTRLEN(label);
}
ret = wc_CryptoCb_GetCert(devId, (const sword8 *)label,
labelLen, id, idLen, &certData, &certDataLen, ctx->heap);
if (ret != 0) {
ret = WOLFSSL_FAILURE;
goto exit;
}
ret = ProcessBuffer(ctx, certData, certDataLen, WOLFSSL_FILETYPE_ASN1,
CERT_TYPE, NULL, NULL, 0, GET_VERIFY_SETTING_CTX(ctx));
exit:
if (certData != NULL) {
XFREE(certData, ctx->heap, DYNAMIC_TYPE_CERT);
}
return ret;
}
/* Load the label name of a certificate into the SSL context.
*
* @param [in, out] ctx SSL context object.
* @param [in] label Buffer holding label.
* @param [in] devId Device identifier.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_certificate_label(WOLFSSL_CTX* ctx,
const char *label, int devId)
{
if ((ctx == NULL) || (label == NULL)) {
WOLFSSL_MSG("Bad Argument");
return WOLFSSL_FAILURE;
}
return wolfSSL_CTX_use_certificate_ex(ctx, label, NULL, 0, devId);
}
/* Load the id of a certificate into SSL context.
*
* @param [in, out] ctx SSL context object.
* @param [in] id Buffer holding id.
* @param [in] idLen Size of data in bytes.
* @param [in] devId Device identifier.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_certificate_id(WOLFSSL_CTX* ctx,
const unsigned char *id, int idLen, int devId)
{
if ((ctx == NULL) || (id == NULL) || (idLen <= 0)) {
WOLFSSL_MSG("Bad Argument");
return WOLFSSL_FAILURE;
}
return wolfSSL_CTX_use_certificate_ex(ctx, NULL, id, idLen, devId);
}
#endif /* if defined(WOLF_CRYPTO_CB) && !defined(NO_CERTS) */
/* Load a certificate chain in a buffer into SSL context.
*
* @param [in, out] ctx SSL context object.

View File

@ -85,6 +85,7 @@ static const char* GetAlgoTypeStr(int algo)
case WC_ALGO_TYPE_SEED: return "Seed";
case WC_ALGO_TYPE_HMAC: return "HMAC";
case WC_ALGO_TYPE_CMAC: return "CMAC";
case WC_ALGO_TYPE_CERT: return "Cert";
}
return NULL;
}
@ -1799,6 +1800,36 @@ int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz)
}
#endif /* !WC_NO_RNG */
#ifndef NO_CERTS
int wc_CryptoCb_GetCert(int devId, const sword8 *label, word32 labelLen,
const byte *id, word32 idLen, byte** out,
word32* outSz, void *heap)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
CryptoCb* dev;
/* locate registered callback */
dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_CERT);
if (dev && dev->cb) {
wc_CryptoInfo cryptoInfo;
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
cryptoInfo.algo_type = WC_ALGO_TYPE_CERT;
cryptoInfo.cert.label = label;
cryptoInfo.cert.labelLen = labelLen;
cryptoInfo.cert.id = id;
cryptoInfo.cert.idLen = idLen;
cryptoInfo.cert.heap = heap;
cryptoInfo.cert.certDataOut = out;
cryptoInfo.cert.certSz = outSz;
cryptoInfo.cert.heap = heap;
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
}
return wc_CryptoCb_TranslateErrorCode(ret);
}
#endif /* ifndef NO_CERTS */
#if defined(WOLFSSL_CMAC)
int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz,
const byte* in, word32 inSz, byte* out, word32* outSz, int type,

View File

@ -108,6 +108,8 @@ static CK_OBJECT_CLASS privKeyClass = CKO_PRIVATE_KEY;
static CK_OBJECT_CLASS secretKeyClass = CKO_SECRET_KEY;
#endif
static CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
#ifdef WOLFSSL_DEBUG_PKCS11
/* Enable logging of PKCS#11 calls and return value. */
#define PKCS11_RV(op, rv) pkcs11_rv(op, rv)
@ -240,6 +242,10 @@ static void pkcs11_dump_template(const char* name, CK_ATTRIBUTE* templ,
XSNPRINTF(line, sizeof(line), "%25s: SECRET", type);
WOLFSSL_MSG(line);
}
else if (keyClass == CKO_CERTIFICATE) {
XSNPRINTF(line, sizeof(line), "%25s: CERTIFICATE", type);
WOLFSSL_MSG(line);
}
else
{
XSNPRINTF(line, sizeof(line), "%25s: UNKNOWN (%p)", type,
@ -1463,7 +1469,8 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key)
}
#if !defined(NO_RSA) || defined(HAVE_ECC) || (!defined(NO_AES) && \
(defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || !defined(NO_HMAC)
(defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || \
!defined(NO_HMAC) || !defined(NO_CERTS)
/**
* Find the PKCS#11 object containing key data using template.
@ -3965,6 +3972,84 @@ static int Pkcs11RandomSeed(Pkcs11Session* session, wc_CryptoInfo* info)
}
#endif
#ifndef NO_CERTS
static int Pkcs11GetCert(Pkcs11Session* session, wc_CryptoInfo* info) {
int ret = 0;
CK_RV rv = 0;
CK_ULONG count = 0;
CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE;
byte *certData = NULL;
CK_ATTRIBUTE certTemplate[2] = {
{ CKA_CLASS, &certClass, sizeof(certClass) }
};
CK_ATTRIBUTE tmpl[] = {
{ CKA_VALUE, NULL_PTR, 0 }
};
CK_ULONG certTmplCnt = sizeof(certTemplate) / sizeof(*certTemplate);
CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl);
WOLFSSL_MSG("PKCS#11: Retrieve certificate");
if (info->cert.labelLen > 0) {
certTemplate[1].type = CKA_LABEL;
certTemplate[1].pValue = (CK_VOID_PTR)info->cert.label;
certTemplate[1].ulValueLen = info->cert.labelLen;
}
else if (info->cert.idLen > 0) {
certTemplate[1].type = CKA_ID;
certTemplate[1].pValue = (CK_VOID_PTR)info->cert.id;
certTemplate[1].ulValueLen = info->cert.idLen;
}
else {
ret = BAD_FUNC_ARG;
goto exit;
}
ret = Pkcs11FindKeyByTemplate(
&certHandle, session, certTemplate, certTmplCnt, &count);
if (ret == 0 && count == 0) {
ret = WC_HW_E;
goto exit;
}
PKCS11_DUMP_TEMPLATE("Get Certificate Length", tmpl, tmplCnt);
rv = session->func->C_GetAttributeValue(
session->handle, certHandle, tmpl, tmplCnt);
PKCS11_RV("C_GetAttributeValue", rv);
if (rv != CKR_OK) {
ret = WC_HW_E;
goto exit;
}
certData = XMALLOC(
(int)tmpl[0].ulValueLen, info->cert.heap, DYNAMIC_TYPE_CERT);
if (certData == NULL) {
ret = MEMORY_E;
goto exit;
}
tmpl[0].pValue = certData;
rv = session->func->C_GetAttributeValue(
session->handle, certHandle, tmpl, tmplCnt);
PKCS11_RV("C_GetAttributeValue", rv);
if (rv != CKR_OK) {
ret = WC_HW_E;
goto exit;
}
*info->cert.certDataOut = certData;
*info->cert.certSz = (word32)tmpl[0].ulValueLen;
certData = NULL;
exit:
if (certData != NULL) {
XFREE(certData, info->cert.heap, DYNAMIC_TYPE_CERT);
}
return ret;
}
#endif /* ifndef NO_CERTS */
/**
* Perform a cryptographic operation using PKCS#11 device.
*
@ -4157,6 +4242,17 @@ int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
}
#else
ret = NOT_COMPILED_IN;
#endif
}
else if (info->algo_type == WC_ALGO_TYPE_CERT) {
#ifndef NO_CERTS
ret = Pkcs11OpenSession(token, &session, readWrite);
if (ret == 0) {
ret = Pkcs11GetCert(&session, info);
Pkcs11CloseSession(token, &session);
}
#else
ret = NOT_COMPILED_IN;
#endif
}
else

View File

@ -3545,6 +3545,12 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* key, unsigned int len,
const unsigned char* in, long sz, int format);
WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz);
#if defined(WOLF_CRYPTO_CB)
WOLFSSL_API int wolfSSL_CTX_use_certificate_label(WOLFSSL_CTX* ctx,
const char *label, int devId);
WOLFSSL_API int wolfSSL_CTX_use_certificate_id(WOLFSSL_CTX* ctx,
const unsigned char *id, int idLen, int devId);
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_buffer(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz, int format);

View File

@ -448,6 +448,17 @@ typedef struct wc_CryptoInfo {
int type;
} cmac;
#endif
#ifndef NO_CERTS
struct {
const byte *id;
word32 idLen;
const sword8 *label;
word32 labelLen;
byte **certDataOut;
word32 *certSz;
void *heap;
} cert;
#endif
#ifdef WOLF_CRYPTO_CB_CMD
struct { /* uses wc_AlgoType=ALGO_NONE */
int type; /* enum wc_CryptoCbCmdType */
@ -657,6 +668,12 @@ WOLFSSL_LOCAL int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz,
void* ctx);
#endif
#ifndef NO_CERTS
WOLFSSL_LOCAL int wc_CryptoCb_GetCert(int devId, const sword8 *label,
word32 labelLen, const byte *id, word32 idLen, byte** out,
word32* outSz, void *heap);
#endif
#endif /* WOLF_CRYPTO_CB */
#ifdef __cplusplus

View File

@ -71,10 +71,12 @@ extern "C" {
#define CKF_RW_SESSION 0x00000002UL
#define CKF_SERIAL_SESSION 0x00000004UL
#define CKO_CERTIFICATE 0x00000001UL
#define CKO_PUBLIC_KEY 0x00000002UL
#define CKO_PRIVATE_KEY 0x00000003UL
#define CKO_SECRET_KEY 0x00000004UL
#define CKK_RSA 0x00000000UL
#define CKK_DH 0x00000002UL
#define CKK_EC 0x00000003UL

View File

@ -1138,8 +1138,9 @@ typedef struct w64wrapper {
WC_ALGO_TYPE_SEED = 5,
WC_ALGO_TYPE_HMAC = 6,
WC_ALGO_TYPE_CMAC = 7,
WC_ALGO_TYPE_CERT = 8,
WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_CMAC
WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_CERT
};
/* hash types */