Merge pull request #376 from dgarske/tls_idevid

Improve the TPM TLS examples for use with `WOLFTPM_MFG_IDENTITY`
pull/368/merge
philljj 2024-09-11 15:35:10 -04:00 committed by GitHub
commit 6020acfe4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 159 additions and 84 deletions

View File

@ -394,7 +394,7 @@ run_tpm_tls_server() { # Usage: run_tpm_tls_server [ecc/rsa] [tpmargs] [tlsversi
if [ $WOLFCRYPT_ENABLE -eq 1 ] && [ $WOLFCRYPT_DEFAULT -eq 0 ] && [ $NO_FILESYSTEM -eq 0 ]; then
if [ $WOLFCRYPT_RSA -eq 1 ]; then
# TLS client/server RSA TLS v1.2 and v1.2 Crypto callbacks
# TLS client/server RSA TLS v1.2 and v1.3 Crypto callbacks
run_tpm_tls_client "rsa" "" "3"
run_tpm_tls_client "rsa" "-aes" "3"
run_tpm_tls_client "rsa" "" "4"
@ -405,7 +405,7 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ] && [ $WOLFCRYPT_DEFAULT -eq 0 ] && [ $NO_FILESYST
run_tpm_tls_server "rsa" "" "4"
run_tpm_tls_server "rsa" "-aes" "4"
# TLS client/server ECC TLS v1.2 and v1.2 PK callbacks
# TLS client/server ECC TLS v1.2 and v1.3 PK callbacks
run_tpm_tls_client "rsa" "-pk" "3"
run_tpm_tls_client "rsa" "-pk -aes" "3"
run_tpm_tls_client "rsa" "-pk" "4"
@ -418,7 +418,7 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ] && [ $WOLFCRYPT_DEFAULT -eq 0 ] && [ $NO_FILESYST
fi
if [ $WOLFCRYPT_ECC -eq 1 ]; then
# TLS client/server ECC TLS v1.2 and v1.2 Crypto callbacks
# TLS client/server ECC TLS v1.2 and v1.3 Crypto callbacks
run_tpm_tls_client "ecc" "" "3"
run_tpm_tls_client "ecc" "-aes" "3"
run_tpm_tls_client "ecc" "" "4"
@ -429,7 +429,7 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ] && [ $WOLFCRYPT_DEFAULT -eq 0 ] && [ $NO_FILESYST
run_tpm_tls_server "ecc" "" "4"
run_tpm_tls_server "ecc" "-aes" "4"
# TLS client/server ECC TLS v1.2 and v1.2 PK callbacks
# TLS client/server ECC TLS v1.2 and v1.3 PK callbacks
run_tpm_tls_client "ecc" "-pk" "3"
run_tpm_tls_client "ecc" "-pk -aes" "3"
run_tpm_tls_client "ecc" "-pk" "4"

View File

@ -65,7 +65,7 @@
* This example client connects to localhost on on port 11111 by default.
* These can be overriden using `TLS_HOST` and `TLS_PORT`.
*
* By default this example will loads RSA keys unless RSA is disabled (NO_RSA)
* By default this example will load RSA keys unless RSA is disabled (NO_RSA)
* or the TLS_USE_ECC build option is used.
*
* You can validate using the wolfSSL example server this like:
@ -75,8 +75,11 @@
* ./examples/server/server -b -p 11111 -g -A ./certs/tpm-ca-rsa-cert.pem
* or
* ./examples/server/server -b -p 11111 -g -A ./certs/tpm-ca-ecc-cert.pem
*
* If using an ECDSA cipher suite add:
* "-l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem"
* "-l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem"
*
* For TLS v1.3 add to server "-v 4"
*/
@ -106,6 +109,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
int rc;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY storageKey;
WOLFTPM2_KEY* bindKey = NULL;
#ifndef NO_RSA
WOLFTPM2_KEY rsaKey;
#endif
@ -235,14 +239,27 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
if (rc != 0) goto exit;
}
#endif
/* See if primary storage key already exists */
rc = getPrimaryStoragekey(&dev, &storageKey,
useECC ? TPM_ALG_ECC : TPM_ALG_RSA);
if (rc != 0) goto exit;
if (rc == 0) {
bindKey = &storageKey;
}
else {
/* error printed in getPrimaryStoragekey */
#ifdef WOLFTPM_MFG_IDENTITY /* not fatal if using mfg identity */
printf("Allowing primary creation failure, since not required "
"when using a pre-provisioned IDevID key\n");
rc = 0;
#else
goto exit;
#endif
}
/* Start an authenticated session (salted / unbound) with parameter encryption */
if (paramEncAlg != TPM_ALG_NULL) {
rc = wolfTPM2_StartSession(&dev, &tpmSession, &storageKey, NULL,
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
if (rc != 0) goto exit;
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
@ -279,7 +296,9 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
/* Attempt to use pre-provisioned identity key */
rc = wolfTPM2_ReadPublicKey(&dev, &eccKey, TPM2_IDEVID_KEY_HANDLE);
if (rc == 0) {
/* TODO: Supply master password (if not TEST_SAMPLE) */
/* Custom should supply their own custom master password used during
* device provisioning. If using a sample TPM supply NULL to use the
* default password. */
wolfTPM2_SetIdentityAuth(&dev, &eccKey.handle, NULL, 0);
}
else
@ -309,6 +328,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
#endif
#endif /* HAVE_ECC */
/* Setup the WOLFSSL context (factory)
* Use highest version, allow downgrade */
if ((ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())) == NULL) {
@ -330,7 +350,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
#endif
/* Server certificate validation */
/* Note: Can use "WOLFSSL_VERIFY_NONE" to skip server cert validation */
/* Note: Can use "WOLFSSL_VERIFY_NONE" to skip peer cert validation */
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify);
#ifdef NO_FILESYSTEM
/* Load CA Certificates from Buffer */
@ -383,7 +403,9 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
if (wolfSSL_CTX_load_verify_locations(ctx, "./certs/ca-ecc-cert.pem",
0) != WOLFSSL_SUCCESS) {
printf("Error loading ca-ecc-cert.pem cert\n");
#ifndef WOLFTPM_MFG_IDENTITY /* not fatal if using mfg identity */
goto exit;
#endif
}
if (wolfSSL_CTX_load_verify_locations(ctx, "./certs/wolf-ca-ecc-cert.pem",
0) != WOLFSSL_SUCCESS) {
@ -420,7 +442,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
rc = wolfTPM2_ExportPublicKeyBuffer(&dev, pkey,
ENCODING_TYPE_ASN1, der, &derSz);
if (rc < 0) {
printf("Failed to export RSA public key!\n");
printf("Failed to export TPM public key!\n");
goto exit;
}
@ -436,7 +458,7 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
/* Client Certificate (Mutual Authentication) */
if (!useECC) {
#ifndef NO_RSA
#ifndef NO_RSA
printf("Loading RSA certificate\n");
#ifdef NO_FILESYSTEM
/* Load "cert" buffer with ASN.1/DER certificate */
@ -452,17 +474,17 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
printf("Error loading RSA client cert\n");
goto exit;
}
#else
printf("Error: ECC not compiled in\n");
#else
printf("Error: RSA not compiled in\n");
rc = -1;
goto exit;
#endif /* !NO_RSA */
#endif /* !NO_RSA */
}
else {
#ifdef HAVE_ECC
#ifdef HAVE_ECC
printf("Loading ECC certificate\n");
#ifdef WOLFTPM_MFG_IDENTITY
uint8_t cert[800];
#ifdef WOLFTPM_MFG_IDENTITY
uint8_t cert[1024];
uint32_t certSz = (uint32_t)sizeof(cert);
rc = wolfTPM2_NVReadCert(&dev, TPM2_IDEVID_CERT_HANDLE, cert, &certSz);
if (rc == 0) {
@ -471,25 +493,25 @@ int TPM2_TLS_ClientArgs(void* userCtx, int argc, char *argv[])
WOLFSSL_FILETYPE_ASN1);
}
#elif defined(NO_FILESYSTEM)
/* Load "cert" buffer with ASN.1/DER certificate */
#elif defined(NO_FILESYSTEM)
/* Example for loading cert using an ASN.1/DER certificate */
#if 0
rc = wolfSSL_CTX_use_certificate_buffer(ctx, cert.buffer, (long)cert.size,
WOLFSSL_FILETYPE_ASN1);
#endif
#else
#else
rc = wolfSSL_CTX_use_certificate_file(ctx, "./certs/client-ecc-cert.pem",
WOLFSSL_FILETYPE_PEM);
#endif
#endif
if (rc != WOLFSSL_SUCCESS) {
printf("Error loading ECC client cert\n");
goto exit;
}
#else
printf("ECC not supported in this build\n");
#else
printf("Error: ECC not compiled in\n");
rc = -1;
goto exit;
#endif /* HAVE_ECC */
#endif /* HAVE_ECC */
}
#endif /* !NO_TLS_MUTUAL_AUTH */

View File

@ -74,6 +74,8 @@ static int mStop = 0;
* With browsers you will get certificate warnings until you load the test CA's
* ./certs/ca-rsa-cert.pem and ./certs/ca-ecc-cert.pem into your OS key store.
* With most browsers you can bypass the certificate warning.
*
* For TLS v1.3 add to client "-v 4"
*/
/******************************************************************************/
@ -104,6 +106,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
int rc;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY storageKey;
WOLFTPM2_KEY* bindKey = NULL;
#ifndef NO_RSA
WOLFTPM2_KEY rsaKey;
#endif
@ -252,14 +255,27 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
if (rc != 0) goto exit;
}
#endif
/* See if primary storage key already exists */
rc = getPrimaryStoragekey(&dev, &storageKey,
useECC ? TPM_ALG_ECC : TPM_ALG_RSA);
if (rc != 0) goto exit;
if (rc == 0) {
bindKey = &storageKey;
}
else {
/* error printed in getPrimaryStoragekey */
#ifdef WOLFTPM_MFG_IDENTITY /* not fatal if using mfg identity */
printf("Allowing primary creation failure, since not required "
"when using a pre-provisioned IDevID key\n");
rc = 0;
#else
goto exit;
#endif
}
/* Start an authenticated session (salted / unbound) with parameter encryption */
if (paramEncAlg != TPM_ALG_NULL) {
rc = wolfTPM2_StartSession(&dev, &tpmSession, &storageKey, NULL,
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
if (rc != 0) goto exit;
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
@ -292,19 +308,33 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
#ifdef HAVE_ECC
if (useECC) {
/* Create/Load ECC key for TLS authentication */
rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_sign | TPMA_OBJECT_noDA,
TPM_ECC_NIST_P256, TPM_ALG_ECDSA);
if (rc != 0) goto exit;
rc = getECCkey(&dev,
&storageKey,
&eccKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
#ifdef WOLFTPM_MFG_IDENTITY
/* Attempt to use pre-provisioned identity key */
rc = wolfTPM2_ReadPublicKey(&dev, &eccKey, TPM2_IDEVID_KEY_HANDLE);
if (rc == 0) {
/* Custom should supply their own custom master password used during
* device provisioning. If using a sample TPM supply NULL to use the
* default password. */
wolfTPM2_SetIdentityAuth(&dev, &eccKey.handle, NULL, 0);
}
else
#endif
{
/* Create/Load ECC key for TLS authentication */
rc = wolfTPM2_GetKeyTemplate_ECC(&publicTemplate,
TPMA_OBJECT_sensitiveDataOrigin | TPMA_OBJECT_userWithAuth |
TPMA_OBJECT_sign | TPMA_OBJECT_noDA,
TPM_ECC_NIST_P256, TPM_ALG_ECDSA);
if (rc == 0) {
rc = getECCkey(&dev,
&storageKey,
&eccKey,
NULL,
tpmDevId,
(byte*)gKeyAuth, sizeof(gKeyAuth)-1,
&publicTemplate);
}
}
if (rc != 0) goto exit;
}
@ -336,10 +366,7 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
#endif
/* Server certificate validation */
#if 0
/* skip server cert validation for this test */
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, myVerify);
#else
/* Note: Can use "WOLFSSL_VERIFY_NONE" to skip peer cert validation */
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, myVerify);
#ifdef NO_FILESYSTEM
/* example loading from buffer */
@ -374,7 +401,9 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
if (wolfSSL_CTX_load_verify_locations(ctx, "./certs/ca-ecc-cert.pem",
0) != WOLFSSL_SUCCESS) {
printf("Error loading ca-ecc-cert.pem cert\n");
#ifndef WOLFTPM_MFG_IDENTITY /* not fatal if using mfg identity */
goto exit;
#endif
}
if (wolfSSL_CTX_load_verify_locations(ctx, "./certs/wolf-ca-ecc-cert.pem",
0) != WOLFSSL_SUCCESS) {
@ -388,18 +417,8 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
#endif /* HAVE_ECC */
}
#endif /* !NO_FILESYSTEM */
#endif
#ifdef NO_FILESYSTEM
/* example loading from buffer */
#if 0
if (wolfSSL_CTX_use_certificate_buffer(ctx, cert.buffer, (long)cert.size,
WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
goto exit;
}
#endif
(void)useSelfSign;
#else
{
/* Export TPM public key as DER */
byte der[1024];
@ -431,47 +450,69 @@ int TPM2_TLS_ServerArgs(void* userCtx, int argc, char *argv[])
}
/* Server certificate */
printf("Loading %s certificate\n", useECC ? "ECC" : "RSA");
if (!useECC) {
#ifndef NO_RSA
#ifndef NO_RSA
printf("Loading RSA certificate\n");
#ifdef NO_FILESYSTEM
/* Load "cert" buffer with ASN.1/DER certificate */
#if 0
rc = wolfSSL_CTX_use_certificate_buffer(ctx, cert.buffer, (long)cert.size,
WOLFSSL_FILETYPE_ASN1);
#endif
#else
const char* useCert = "./certs/server-rsa-cert.pem";
if (useSelfSign) {
useCert = "./certs/tpm-rsa-cert.pem";
}
printf("Loading RSA certificate (%s) and public key\n", useCert);
if ((rc = wolfSSL_CTX_use_certificate_file(ctx, useCert,
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
rc = wolfSSL_CTX_use_certificate_file(ctx, useCert, WOLFSSL_FILETYPE_PEM);
#endif
if (rc != WOLFSSL_SUCCESS) {
printf("Error loading RSA client cert\n");
goto exit;
}
#else
#else
printf("Error: RSA not compiled in\n");
rc = -1;
goto exit;
#endif /* !NO_RSA */
#endif /* !NO_RSA */
(void)useSelfSign;
}
else {
#ifdef HAVE_ECC
#ifdef HAVE_ECC
#ifdef WOLFTPM_MFG_IDENTITY
uint8_t cert[1024];
uint32_t certSz = (uint32_t)sizeof(cert);
rc = wolfTPM2_NVReadCert(&dev, TPM2_IDEVID_CERT_HANDLE, cert, &certSz);
if (rc == 0) {
/* Load "cert" buffer with ASN.1/DER certificate */
rc = wolfSSL_CTX_use_certificate_buffer(ctx, cert, (long)certSz,
WOLFSSL_FILETYPE_ASN1);
}
#elif defined(NO_FILESYSTEM)
/* Example for loading cert using an ASN.1/DER certificate */
#if 0
rc = wolfSSL_CTX_use_certificate_buffer(ctx, cert.buffer, (long)cert.size,
WOLFSSL_FILETYPE_ASN1);
#endif
#else
const char* useCert = "./certs/server-ecc-cert.pem";
if (useSelfSign) {
useCert = "./certs/tpm-ecc-cert.pem";
}
printf("Loading ECC certificate (%s) and public key\n", useCert);
if ((rc = wolfSSL_CTX_use_certificate_file(ctx, useCert,
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
rc = wolfSSL_CTX_use_certificate_file(ctx, useCert, WOLFSSL_FILETYPE_PEM);
#endif
if (rc != WOLFSSL_SUCCESS) {
printf("Error loading ECC client cert\n");
goto exit;
}
#else
#else
printf("Error: ECC not compiled in\n");
rc = -1;
goto exit;
#endif /* HAVE_ECC */
#endif /* HAVE_ECC */
}
#endif /* !NO_FILESYSTEM */
#ifdef TLS_CIPHER_SUITE
/* Optionally choose the cipher suite */

View File

@ -4722,6 +4722,13 @@ int wolfTPM2_NVReadCert(WOLFTPM2_DEV* dev, TPM_HANDLE handle,
/* Perform read of NV without auth password */
nv.handle.hndl = handle;
rc = wolfTPM2_NVReadAuth(dev, &nv, handle, buffer, (word32*)len, 0);
#ifdef DEBUG_WOLFTPM
printf("NV public read certificate 0x%x (%u bytes)\n",
handle, *len);
TPM2_PrintBin(buffer, *len);
#endif
return rc;
}
@ -7596,12 +7603,10 @@ int wolfTPM2_PolicyAuthorizeMake(TPM_ALG_ID pcrAlg,
/* pre-provisioned IAK and IDevID key/cert from TPM vendor */
#ifdef WOLFTPM_MFG_IDENTITY
#ifdef TEST_SAMPLE
static const uint8_t TPM2_IAK_SAMPLE_MASTER_PASSWORD[] = {
0xFE, 0xEF, 0x8C, 0xDF, 0x1B, 0x77, 0xBD, 0x00,
0x30, 0x58, 0x5E, 0x47, 0xB8, 0x21, 0x46, 0x0B
};
#endif
int wolfTPM2_SetIdentityAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* handle,
uint8_t* masterPassword, uint16_t masterPasswordSz)
@ -7621,22 +7626,25 @@ int wolfTPM2_SetIdentityAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* handle,
#endif
return rc;
}
#ifdef DEBUG_WOLFTPM
printf("TPM Serial Number (%d bytes)\n", (int)sizeof(serialNum));
TPM2_PrintBin(serialNum, sizeof(serialNum));
#endif
/* Hash both values */
rc = wc_HashInit(&hash_ctx, hashType);
if (rc == 0) {
rc = wc_HashUpdate(&hash_ctx, hashType, serialNum, sizeof(serialNum));
if (rc == 0) {
#ifdef TEST_SAMPLE
rc = wc_HashUpdate(&hash_ctx, hashType,
TPM2_IAK_SAMPLE_MASTER_PASSWORD,
sizeof(TPM2_IAK_SAMPLE_MASTER_PASSWORD));
(void)masterPassword;
(void)masterPasswordSz;
#else
rc = wc_HashUpdate(&hash_ctx, hashType,
masterPassword, masterPasswordSz);
#endif
if (masterPassword == NULL || masterPasswordSz == 0) {
rc = wc_HashUpdate(&hash_ctx, hashType,
TPM2_IAK_SAMPLE_MASTER_PASSWORD,
sizeof(TPM2_IAK_SAMPLE_MASTER_PASSWORD));
}
else {
rc = wc_HashUpdate(&hash_ctx, hashType,
masterPassword, masterPasswordSz);
}
}
if (rc == 0) {
rc = wc_HashFinal(&hash_ctx, hashType, digest);
@ -7649,6 +7657,10 @@ int wolfTPM2_SetIdentityAuth(WOLFTPM2_DEV* dev, WOLFTPM2_HANDLE* handle,
/* Use 16-byte for auth when accessing key */
handle->auth.size = 16;
XMEMCPY(handle->auth.buffer, &digest[16], 16);
#ifdef DEBUG_WOLFTPM
printf("Handle 0x%x, Auth %d\n", handle->hndl, handle->auth.size);
TPM2_PrintBin(handle->auth.buffer, handle->auth.size);
#endif
(void)dev;