Example using the EVP compatibility layer with the crypto callbacks and TPM.

pull/267/head
David Garske 2021-08-24 12:43:54 -07:00
parent 59e50a6a09
commit 621b801338
4 changed files with 372 additions and 0 deletions

2
.gitignore vendored
View File

@ -219,3 +219,5 @@ hash/sha256-hash
sslkeylog.log
server-tls13
client-tls13
tpm/evp_tpm

14
tpm/Makefile 100644
View File

@ -0,0 +1,14 @@
CC=gcc
WOLF_INSTALL_DIR=/usr/local
CFLAGS=-I$(WOLF_INSTALL_DIR)/include -Wall
LIBS=-L$(WOLF_INSTALL_DIR)/lib -lwolfssl -lwolftpm
all:evp_tpm
evp_tpm:evp_tpm.o
$(CC) -o $@ $^ $(CFLAGS) $(CPPFLAGS) $(LIBS)
.PHONY: clean all
clean:
rm -f *.o evp_tpm

61
tpm/README.md 100644
View File

@ -0,0 +1,61 @@
# TPM Examples
## EVP with TPM Example (evp_tpm.c)
This example shows use of the EVP compatibility layer with the crypto callbacks and TPM.
Note: Requires PR https://github.com/wolfSSL/wolfssl/pull/4333
### Building wolfSSL
```
% ./configure --enable-opensslextra --enable-wolftpm --enable-cryptocb [--enable-debug] [--prefix=DIR]
% make
% make install
```
### Building wolfTPM
```
% ./configure [--enable-swtpm] [--enable-debug] [--prefix=DIR]
% make
% make install
```
### Building evp_tpm example
```sh
% make
gcc -I/usr/local/include -Wall -c -o evp_tpm.o evp_tpm.c
gcc -o evp_tpm evp_tpm.o -I/usr/local/include -Wall -L/usr/local/lib -lwolfssl -lwolftpm
```
### Example Output
```sh
% ./evp_tpm
wolfSSL Entering wolfCrypt_Init
TPM2: Caps 0x00000000, Did 0x0000, Vid 0x0000, Rid 0x 0
TPM2_Startup pass
TPM2_SelfTest pass
TPM2_ReadPublic Handle 0x81000201: pub 90, name 34, qualifiedName 34
Loading SRK: Storage 0x81000201 (90 bytes)
TPM2_Create key: pub 88, priv 126
Public Area (size 88):
Type: ECC (0x23), name: SHA256 (0xB), objAttr: 0x40460, authPolicy sz: 0
ECC: sym algorithm: NULL (0x10), sym keyBits: 0, sym mode: Unknown (0x0)
scheme: ECDSA (0x18), scheme hash: SHA256 (0xB), curveID: size 32, 0x3
KDF scheme: NULL (0x10), KDF alg: Unknown (0x0), unique X/Y size 32/32
TPM2_Load Key Handle 0x80000002
Create/Load ECC Key: Handle 0x80000002 (88 bytes)
EVP_MD_ecc_signing()
CryptoCbFunc Pk: Type 4
TPM2_Sign: ECDSA 64
EVP_DigestSignFinal sz 72
EVP_DigestVerifyFinal success
Result: success (0)
TPM2_FlushContext: Closed handle 0x80000002
```
## Support
For questions please email support@wolfssl.com

295
tpm/evp_tpm.c 100644
View File

@ -0,0 +1,295 @@
/* evp_tpm.c
*
* Copyright (C) 2006-2021 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#include <wolftpm/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/cryptocb.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/openssl/ssl.h>
#include <wolfssl/openssl/evp.h>
#include <wolftpm/tpm2_wrap.h>
#include <wolftpm/tpm2_tis.h>
/* Storage Key Parameters */
#define TPM2_DEMO_STORAGE_EC_KEY_HANDLE 0x81000201 /* Persistent Storage Key Handle (ECC) */
static const char gStorageKeyAuth[] = "ThisIsMyStorageKeyAuth";
static const char gKeyAuth[] = "ThisIsMyKeyAuth";
typedef struct TpmCryptoCbCtx {
WOLFTPM2_DEV* dev;
WOLFTPM2_KEY* eccKey;
} TpmCryptoCbCtx;
static int CreateLoadExportTpmKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
WOLFTPM2_KEY* storageKey, byte* pubKeyDer, word32* pubKeyDerSz)
{
int ret;
TPMT_PUBLIC publicTemplate;
ecc_key* wolfEccKey;
wolfTPM2_GetKeyTemplate_ECC(&publicTemplate,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_sign | TPMA_OBJECT_noDA,
TPM_ECC_NIST_P256, TPM_ALG_ECDSA);
ret = wolfTPM2_CreateAndLoadKey(dev, tpmKey, &storageKey->handle,
&publicTemplate, (byte*)gKeyAuth, sizeof(gKeyAuth)-1);
if (ret == 0) {
wolfEccKey = wc_ecc_key_new(NULL);
if (wolfEccKey != NULL) {
/* extract public key der */
/* load public portion of key into wolf ECC Key */
ret = wolfTPM2_EccKey_TpmToWolf(dev, tpmKey, wolfEccKey);
if (ret == 0) {
ret = wc_EccPublicKeyToDer(wolfEccKey,
pubKeyDer, *pubKeyDerSz, 1);
if (ret >= 0) {
*pubKeyDerSz = ret;
ret = 0;
}
}
wc_ecc_key_free(wolfEccKey);
}
}
if (ret == 0) {
printf("Create/Load ECC Key: Handle 0x%x (%d bytes)\n",
(word32)tpmKey->handle.hndl, tpmKey->pub.size);
}
else {
printf("Create/Load ECC Key: failed 0x%x: %s\n", ret,
TPM2_GetRCString(ret));
}
return ret;
}
static int LoadPrimaryStoragekey(WOLFTPM2_DEV* pDev, WOLFTPM2_KEY* pStorageKey,
TPM_ALG_ID alg)
{
int ret;
/* See if SRK already exists */
ret = wolfTPM2_ReadPublicKey(pDev, pStorageKey,
TPM2_DEMO_STORAGE_EC_KEY_HANDLE);
if (ret != 0) {
/* Create primary storage key */
ret = wolfTPM2_CreateSRK(pDev, pStorageKey, alg,
(byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1);
if (ret == TPM_RC_SUCCESS) {
/* Move storage key into persistent NV */
ret = wolfTPM2_NVStoreKey(pDev, TPM_RH_OWNER, pStorageKey,
TPM2_DEMO_STORAGE_EC_KEY_HANDLE);
}
}
else {
/* specify auth password for storage key */
pStorageKey->handle.auth.size = sizeof(gStorageKeyAuth)-1;
XMEMCPY(pStorageKey->handle.auth.buffer, gStorageKeyAuth,
pStorageKey->handle.auth.size);
}
if (ret == 0) {
printf("Loading SRK: Storage 0x%x (%d bytes)\n",
(word32)pStorageKey->handle.hndl, pStorageKey->pub.size);
}
else {
printf("Loading SRK: Storage failed 0x%x: %s\n", ret,
TPM2_GetRCString(ret));
}
return ret;
}
int CryptoCbFunc(int devId, wc_CryptoInfo* info, void* ctx)
{
int ret = CRYPTOCB_UNAVAILABLE;
TpmCryptoCbCtx* tlsCtx = (TpmCryptoCbCtx*)ctx;
if (info == NULL || ctx == NULL || tlsCtx->dev == NULL) {
return BAD_FUNC_ARG;
}
(void)devId;
if (info->algo_type == WC_ALGO_TYPE_PK) {
printf("CryptoCbFunc Pk: Type %d\n", info->pk.type);
if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
byte sigRS[MAX_ECC_BYTES*2];
byte *r = sigRS, *s;
word32 rsLen = sizeof(sigRS), rLen, sLen;
word32 inlen = info->pk.eccsign.inlen;
/* truncate input to match key size */
rLen = wc_ecc_size(info->pk.eccsign.key);
if (inlen > rLen)
inlen = rLen;
ret = wolfTPM2_SignHash(tlsCtx->dev, tlsCtx->eccKey,
info->pk.eccsign.in, inlen, sigRS, (int*)&rsLen);
if (ret == 0) {
/* Encode ECDSA Header */
rLen = sLen = rsLen / 2;
s = &sigRS[rLen];
ret = wc_ecc_rs_raw_to_sig(r, rLen, s, sLen,
info->pk.eccsign.out, info->pk.eccsign.outlen);
}
}
}
/* need to return negative here for error */
if (ret != TPM_RC_SUCCESS && ret != CRYPTOCB_UNAVAILABLE) {
printf("CryptoCbFunc failed ret = %d\n", ret);
ret = WC_HW_E;
}
return ret;
}
static int test_EVP_MD_ecc_signing(int devId, const byte* pubKeyBuf, word32 pubKeySz)
{
int ret = 0;
#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
EVP_MD_CTX mdCtx;
EVP_PKEY* privKey;
EVP_PKEY* pubKey = NULL;
const char testData[] = "Hi There";
unsigned int testDataSz = (unsigned int)XSTRLEN(testData);
unsigned char check[ECC_MAX_SIG_SIZE];
size_t checkSz = ECC_MAX_SIG_SIZE;
const unsigned char *p;
printf("EVP_MD_ecc_signing()\n");
privKey = wolfSSL_d2i_PrivateKey_id(EVP_PKEY_EC, NULL, NULL, devId);
if (privKey == NULL) {
ret = MEMORY_E;
}
if (ret == 0) {
p = pubKeyBuf;
pubKey = d2i_PUBKEY(NULL, &p, pubKeySz);
if (pubKey == NULL) {
ret = MEMORY_E;
}
}
if (ret == 0) {
EVP_MD_CTX_init(&mdCtx);
ret = EVP_DigestSignInit(&mdCtx, NULL, EVP_sha256(), NULL, privKey);
if (ret == WOLFSSL_SUCCESS)
ret = EVP_DigestSignUpdate(&mdCtx, testData, testDataSz);
if (ret == WOLFSSL_SUCCESS)
ret = EVP_DigestSignFinal(&mdCtx, check, &checkSz);
EVP_MD_CTX_cleanup(&mdCtx);
if (ret == WOLFSSL_SUCCESS) {
printf("EVP_DigestSignFinal sz %d\n", (int)checkSz);
ret = 0;
}
else {
ret = -1; /* failure */
}
}
if (ret == 0) {
EVP_MD_CTX_init(&mdCtx);
ret = EVP_DigestVerifyInit(&mdCtx, NULL, EVP_sha256(), NULL, pubKey);
if (ret == WOLFSSL_SUCCESS)
ret = EVP_DigestVerifyUpdate(&mdCtx, testData, testDataSz);
if (ret == WOLFSSL_SUCCESS)
ret = EVP_DigestVerifyFinal(&mdCtx, check, checkSz);
EVP_MD_CTX_cleanup(&mdCtx);
if (ret == WOLFSSL_SUCCESS) {
printf("EVP_DigestVerifyFinal success\n");
ret = 0;
}
else {
ret = -1; /* failure */
}
}
EVP_PKEY_free(pubKey);
EVP_PKEY_free(privKey);
#else
ret = NOT_COMPILED_IN;
#endif
return ret;
}
int main(void)
{
int ret;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY tpmKey;
WOLFTPM2_KEY storageKey;
TpmCryptoCbCtx tpmCtx;
int devId = INVALID_DEVID;
byte pubKeyDer[1024];
word32 pubKeyDerSz = 1024;
XMEMSET(&tpmCtx, 0, sizeof(tpmCtx));
XMEMSET(&tpmKey, 0, sizeof(tpmKey));
XMEMSET(&storageKey, 0, sizeof(storageKey));
XMEMSET(pubKeyDer, 0, sizeof(pubKeyDer));
tpmCtx.eccKey = &tpmKey;
ret = wolfTPM2_Init(&dev, NULL, NULL);
if (ret == 0) {
wolfSSL_Debugging_OFF();
ret = wolfTPM2_GetTpmDevId(&dev);
if (ret >= 0) {
devId = ret;
tpmCtx.dev = &dev;
ret = wc_CryptoDev_RegisterDevice(devId, CryptoCbFunc, &tpmCtx);
}
}
if (ret == 0) {
ret = LoadPrimaryStoragekey(&dev, &storageKey, TPM_ALG_ECC);
}
if (ret == 0) {
ret = CreateLoadExportTpmKey(&dev, &tpmKey, &storageKey,
pubKeyDer, &pubKeyDerSz);
}
if (ret == 0) {
ret = test_EVP_MD_ecc_signing(devId, pubKeyDer, pubKeyDerSz);
}
printf("Result: %s (%d)\n", ret == 0 ? "success" :
wolfSSL_ERR_reason_error_string(ret), ret);
wolfTPM2_UnloadHandle(&dev, &tpmKey.handle);
wolfTPM2_Cleanup(&dev);
return ret;
}