Skip to content

Commit

Permalink
wolfPKCS11 support for using TPM 2.0 module as backend. Uses wolfTPM …
Browse files Browse the repository at this point in the history
…and supports RSA and ECC. The keystore will use TPM NV if `WOLFPKCS11_TPM_STORE` is defined.
  • Loading branch information
dgarske committed Nov 13, 2023
1 parent d6f8c0c commit db291fe
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 14 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Build wolfSSL:
git clone https://github.com/wolfSSL/wolfssl.git
cd wolfssl
./autogen.sh
./configure --enable-rsapss --enable-keygen --enable-pwdbased --enable-scrypt C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT"
./configure -enable-aescfb --enable-cryptocb --enable-rsapss --enable-keygen --enable-pwdbased --enable-scrypt C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT"
make
make check
sudo make install
Expand All @@ -35,6 +35,18 @@ make check

### Build options and defines

#### TPM support with wolfTPM

Enables using a TPM for cryptography and keystore.
Tested using `./configure --enable-wolftpm --disable-dh CFLAGS="-DWOLFPKCS11_TPM_STORE" && make`.

Note: The TPM does not support DH, so only RSA and ECC are supported.

##### Define WOLFPKCS11_TPM_STORE

Use `WOLFPKCS11_TPM_STORE` storing objects in TPM NV.


#### Define WOLFPKCS11_NO_STORE

Disables storage of tokens.
Expand All @@ -48,6 +60,7 @@ See wolfpkcs11/store.h for prototypes of functions to implement.

Sets the private key's label against the public key when generating key pairs.


## Environment variables

### WOLFPKCS11_TOKEN_PATH
Expand Down
14 changes: 14 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,20 @@ if test "$enable_shared" = "no"; then
AM_CFLAGS="$AM_CFLAGS -DHAVE_PKCS11_STATIC"
fi


AC_ARG_ENABLE([wolftpm],
[AS_HELP_STRING([--enable-wolftpm],[Enable wolfTPM keystore support (default: disabled)])],
[ ENABLED_TPM=$enableval ],
[ ENABLED_TPM=no ]
)
if test "$ENABLED_TPM" = "yes"
then
LIBS="$LIBS -lwolftpm"
AM_CFLAGS="$AM_CFLAGS -DWOLFPKCS11_TPM"
fi



AM_CONDITIONAL([BUILD_STATIC],[test "x$enable_shared" = "xno"])


Expand Down
136 changes: 127 additions & 9 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@
"--enable-scrypt C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT"`
#endif

#ifdef WOLFPKCS11_TPM
#include <wolftpm/tpm2_wrap.h>

#ifndef WOLFPKCS11_TPM_CUST_IO
#include <hal/tpm_io.h>
#ifndef TPM2_IOCB_CTX
#define TPM2_IOCB_CTX NULL
#endif
#endif
#endif

/* Size of hash calculated from PIN. */
#define PIN_HASH_SZ 32
/* Size of seed used when calculating hash from PIN. */
Expand Down Expand Up @@ -145,6 +156,9 @@ struct WP11_Object {
#endif
WP11_Data symmKey; /* Symmetric key object */
} data;
#ifdef WOLFPKCS11_TPM
WOLFTPM2_KEY tpmKey;
#endif
CK_KEY_TYPE type; /* Key type of this object */
word32 size; /* Size of the key in bits or bytes */
#ifndef WOLFPKCS11_NO_STORE
Expand Down Expand Up @@ -272,6 +286,7 @@ struct WP11_Session {
#endif
} params;

int devId;
WP11_Session* next; /* Next session for slot */
};

Expand Down Expand Up @@ -307,6 +322,14 @@ struct WP11_Slot {
WP11_Token token; /* Token information for slot */
WP11_Session* session; /* Linked list of sessions */
WP11_Lock lock; /* Lock for access to slot info */

int devId;
#ifdef WOLFPKCS11_TPM
WOLFTPM2_DEV tpmDev;
WOLFTPM2_KEY tpmSrk;
WOLFTPM2_SESSION tpmSession;
TpmCryptoDevCtx tpmCtx;
#endif
};


Expand Down Expand Up @@ -501,6 +524,7 @@ static int wp11_Session_New(WP11_Slot* slot, CK_OBJECT_HANDLE handle,
sess->slotId = slot->id;
sess->slot = slot;
sess->handle = handle;
sess->devId = slot->devId;
*session = sess;
}

Expand Down Expand Up @@ -2967,6 +2991,68 @@ static void wp11_Slot_FreeSession(WP11_Slot* slot, WP11_Session* session)
}
}


#ifdef WOLFPKCS11_TPM
static int wp11_TpmInit(WP11_Slot* slot)
{
int ret;
WOLFTPM2_CAPS caps;
TPM_ALG_ID alg;

ret = wolfTPM2_Init(&slot->tpmDev, TPM2_IoCb, TPM2_IOCB_CTX);
if (ret == 0) {
/* Get device capabilities + options */
ret = wolfTPM2_GetCapabilities(&slot->tpmDev, &caps);
}
if (ret == 0) {
printf("Mfg %s (%d), Vendor %s, Fw %u.%u (0x%x), "
"FIPS 140-2 %d, CC-EAL4 %d\n",
caps.mfgStr, caps.mfg, caps.vendorStr, caps.fwVerMajor,
caps.fwVerMinor, caps.fwVerVendor, caps.fips140_2, caps.cc_eal4);
}
if (ret == 0) {
ret = wolfTPM2_SetCryptoDevCb(&slot->tpmDev, wolfTPM2_CryptoDevCb,
&slot->tpmCtx, &slot->devId);
}
if (ret == 0) {
/* Create a primary storage key - no auth needed for param enc to work */
/* Prefer ECC as its faster */
#ifdef HAVE_ECC
alg = TPM_ALG_ECC;
#elif !defined(NO_RSA)
alg = TPM_ALG_RSA;
#else
alg = TPM_ALG_NULL;
#endif
ret = wolfTPM2_CreateSRK(&slot->tpmDev, &slot->tpmSrk, alg, NULL, 0);
if (ret == 0) {
/* set values needed for crypto callback */
slot->tpmCtx.dev = &slot->tpmDev;
slot->tpmCtx.storageKey = &slot->tpmSrk;

/* Setup a TPM session that can be used for parameter encryption */
ret = wolfTPM2_StartSession(&slot->tpmDev, &slot->tpmSession,
&slot->tpmSrk, NULL, TPM_SE_HMAC, TPM_ALG_CFB);
}
if (ret != 0) {
printf("TPM Create SRK or Session error %d (%s)!\n",
ret, wolfTPM2_GetRCString(ret));
}
}

if (ret != 0) {
printf("TPM Init failed! %d (%s)\n", ret, wolfTPM2_GetRCString(ret));
}
return ret;
}

static void wp11_TpmFinal(WP11_Slot* slot)
{
wolfTPM2_Cleanup(&slot->tpmDev);
}
#endif /* WOLFPKCS11_TPM */


/**
* Free dynamic memory associated with the slot.
*
Expand All @@ -2977,6 +3063,9 @@ static void wp11_Slot_Final(WP11_Slot* slot)
while (slot->session != NULL)
wp11_Slot_FreeSession(slot, slot->session);
wp11_Token_Final(&slot->token);
#ifdef WOLFPKCS11_TPM
wp11_TpmFinal(slot);
#endif
WP11_Lock_Free(&slot->lock);
}

Expand All @@ -3001,17 +3090,24 @@ static int wp11_Slot_Init(WP11_Slot* slot, int id)

ret = WP11_Lock_Init(&slot->lock);
if (ret == 0) {
#ifdef WOLFPKCS11_TPM
if (ret == 0) {
ret = wp11_TpmInit(slot);
}
#endif
/* Create the minimum number of unused sessions. */
for (i = 0; ret == 0 && i < WP11_SESSION_CNT_MIN; i++)
for (i = 0; ret == 0 && i < WP11_SESSION_CNT_MIN; i++) {
ret = wp11_Slot_AddSession(slot, &curr);
}

if (ret == 0) {
ret = wp11_Token_Init(&slot->token, label);
slot->token.state = WP11_TOKEN_STATE_UNKNOWN;
}

if (ret != 0)
if (ret != 0) {
wp11_Slot_Final(slot);
}
}

return ret;
Expand Down Expand Up @@ -4544,6 +4640,10 @@ void WP11_Session_FindFinal(WP11_Session* session)
*/
void WP11_Object_Free(WP11_Object* object)
{
#ifdef WOLFPKCS11_TPM
wolfTPM2_UnloadHandle(&object->slot->tpmDev, &object->tpmKey.handle);
#endif

/* Release dynamic memory. */
if (object->label != NULL)
XFREE(object->label, NULL, DYNAMIC_TYPE_TMP_BUFFER);
Expand Down Expand Up @@ -4650,7 +4750,7 @@ int WP11_Object_SetRsaKey(WP11_Object* object, unsigned char** data,
WP11_Lock_LockRW(object->lock);

key = &object->data.rsaKey;
ret = wc_InitRsaKey_ex(key, NULL, INVALID_DEVID);
ret = wc_InitRsaKey_ex(key, NULL, object->slot->devId);
if (ret == 0) {
ret = SetMPI(&key->n, data[0], (int)len[0]);
if (ret == 0)
Expand Down Expand Up @@ -4679,6 +4779,13 @@ int WP11_Object_SetRsaKey(WP11_Object* object, unsigned char** data,
}
else {
key->type = RSA_PRIVATE;

#ifdef WOLFPKCS11_TPM
/* load private key */
object->slot->tpmCtx.rsaKey = &object->tpmKey;
ret = wolfTPM2_RsaKey_WolfToTpm_ex(&object->slot->tpmDev,
&object->slot->tpmSrk, &object->data.rsaKey, &object->tpmKey);
#endif
}
}

Expand Down Expand Up @@ -4723,8 +4830,8 @@ static int ecc_get_curve_id_from_oid(const byte* oid, word32 len)

return ecc_sets[curve_idx].id;
}

#endif

/**
* Set the EC Parameters based on the DER encoding of the OID.
*
Expand Down Expand Up @@ -5960,7 +6067,7 @@ int WP11_Rsa_ParsePrivKey(byte* data, word32 dataLen, WP11_Object* privKey)
int ret = 0;
word32 idx = 0;

ret = wc_InitRsaKey(&privKey->data.rsaKey, NULL);
ret = wc_InitRsaKey_ex(&privKey->data.rsaKey, NULL, privKey->slot->devId);
if (ret == 0) {
ret = wc_RsaPrivateKeyDecode(data, &idx, &privKey->data.rsaKey, dataLen);
}
Expand All @@ -5983,7 +6090,7 @@ int WP11_Rsa_PrivKey2PubKey(WP11_Object* privKey, WP11_Object* pubKey,
int ret;
word32 idx = 0;

ret = wc_InitRsaKey(&pubKey->data.rsaKey, NULL);
ret = wc_InitRsaKey_ex(&pubKey->data.rsaKey, NULL, pubKey->slot->devId);
if (ret == 0) {
ret = wc_RsaKeyToPublicDer(&privKey->data.rsaKey, workbuf, worksz);
if (ret >= 0) {
Expand Down Expand Up @@ -6041,8 +6148,18 @@ int WP11_Rsa_GenerateKeyPair(WP11_Object* pub, WP11_Object* priv,
if (ret == 0) {
ret = Rng_New(&slot->token.rng, &slot->token.rngLock, &rng);
if (ret == 0) {
/* Generate into the private key. */
ret = wc_MakeRsaKey(&priv->data.rsaKey, pub->size, e, &rng);
ret = wc_InitRsaKey_ex(&priv->data.rsaKey, NULL, priv->slot->devId);
if (ret == 0) {
#ifdef WOLFPKCS11_TPM
priv->slot->tpmCtx.rsaKey = &priv->tpmKey;
#endif

/* Generate into the private key. */
ret = wc_MakeRsaKey(&priv->data.rsaKey, pub->size, e, &rng);
if (ret != 0) {
wc_FreeRsaKey(&priv->data.rsaKey);
}
}
Rng_Free(&rng);
}
}
Expand Down Expand Up @@ -6131,8 +6248,9 @@ int WP11_Rsa_PrivateDecrypt(unsigned char* in, word32 inLen, unsigned char* out,
WP11_Lock_LockRO(priv->lock);
ret = Rng_New(&slot->token.rng, &slot->token.rngLock, &rng);
if (ret == 0) {
ret = wc_RsaFunction(in, inLen, out, outLen, RSA_PRIVATE_DECRYPT,
ret = wc_RsaFunction(in, inLen, out, outLen, RSA_PRIVATE_DECRYPT,
&priv->data.rsaKey, &rng);

Rng_Free(&rng);
}
if (priv->onToken)
Expand Down
4 changes: 2 additions & 2 deletions tests/pkcs11mtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -5686,7 +5686,7 @@ static CK_RV test_hmac_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech,
mech->pParameter = data;
ret = funcList->C_SignInit(session, mech, key);
CHECK_CKR_FAIL(ret, CKR_MECHANISM_PARAM_INVALID,
"HMAC Sign Init bad parametere");
"HMAC Sign Init bad parameter");
mech->pParameter = NULL;
}
if (ret == CKR_OK) {
Expand All @@ -5707,7 +5707,7 @@ static CK_RV test_hmac_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech,
mech->pParameter = data;
ret = funcList->C_VerifyInit(session, mech, key);
CHECK_CKR_FAIL(ret, CKR_MECHANISM_PARAM_INVALID,
"HMAC Verify Init bad parametere");
"HMAC Verify Init bad parameter");
mech->pParameter = NULL;
}
if (ret == CKR_OK) {
Expand Down
4 changes: 2 additions & 2 deletions tests/pkcs11test.c
Original file line number Diff line number Diff line change
Expand Up @@ -7120,7 +7120,7 @@ static CK_RV test_hmac_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech,
mech->pParameter = data;
ret = funcList->C_SignInit(session, mech, key);
CHECK_CKR_FAIL(ret, CKR_MECHANISM_PARAM_INVALID,
"HMAC Sign Init bad parametere");
"HMAC Sign Init bad parameter");
mech->pParameter = NULL;
}
if (ret == CKR_OK) {
Expand All @@ -7141,7 +7141,7 @@ static CK_RV test_hmac_fail(CK_SESSION_HANDLE session, CK_MECHANISM* mech,
mech->pParameter = data;
ret = funcList->C_VerifyInit(session, mech, key);
CHECK_CKR_FAIL(ret, CKR_MECHANISM_PARAM_INVALID,
"HMAC Verify Init bad parametere");
"HMAC Verify Init bad parameter");
mech->pParameter = NULL;
}
if (ret == CKR_OK) {
Expand Down

0 comments on commit db291fe

Please sign in to comment.