From 009a5df963e6303babd4cb28ffe71d8b2308c5e9 Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Thu, 22 Apr 2021 17:41:53 +0300 Subject: [PATCH] Added examples to create a remote attestation credential Signed-off-by: Dimitar Tomov --- .gitignore | 2 + examples/attestation/README.md | 50 +++++ examples/attestation/activate_credential.c | 215 +++++++++++++++++++++ examples/attestation/credential.h | 38 ++++ examples/attestation/include.am | 30 +++ examples/attestation/make_credential.c | 184 ++++++++++++++++++ examples/include.am | 1 + examples/keygen/keygen.c | 2 +- 8 files changed, 521 insertions(+), 1 deletion(-) create mode 100644 examples/attestation/README.md create mode 100644 examples/attestation/activate_credential.c create mode 100644 examples/attestation/credential.h create mode 100644 examples/attestation/include.am create mode 100644 examples/attestation/make_credential.c diff --git a/.gitignore b/.gitignore index 8ce3311..dd8ab23 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,8 @@ examples/gpio/gpio_set examples/gpio/gpio_read examples/seal/seal examples/seal/unseal +examples/attestation/make_credential +examples/attestation/activate_credential # Generated Cert Files certs/ca-*.pem diff --git a/examples/attestation/README.md b/examples/attestation/README.md new file mode 100644 index 0000000..c00fd38 --- /dev/null +++ b/examples/attestation/README.md @@ -0,0 +1,50 @@ +# Remote Attestatino Demo + +This folder contains examples for performing remote attestation. You will learn how to perform a challenge-response between an end node and attestation server. + +## List of examples + +The `./examples/attestation/` folder contains examples related specifically to remote attestation. However, the demonstration requires the use of other examples included in wolfTPM. Complete list can be found below: + +* `./examples/attestation/make_credential`: Used +* `./examples/attestation/activate_credential`: Used to +* `./examples/random/get`: Used to generate a random seed for attestation/make_credential +* `./examples/keygen/keygen`: Used to create a primary key(PK) and attestation key(AK) +* `./examples/keygen/keyload`: Used to load the generated keys + +Scripts: + +TODO: * `./examples/attestation/provisioning.sh` - Using the above examples, creates the necessary TPM objects for remote attestation, emulating provisioning between an end node and attestation server. + + +## Technology introduction + +### Make Credential + +TODO: Add explanation + +### Activate Credential + +TODO: Add explanation + +## Example usage + +### Make Credential Example Usage + +``` +TODO +``` + +### Activate Credential Example Usage + +``` +TODO +``` + +### Provisioning + +TODO + +## Typical demo output + +TODO diff --git a/examples/attestation/activate_credential.c b/examples/attestation/activate_credential.c new file mode 100644 index 0000000..952eece --- /dev/null +++ b/examples/attestation/activate_credential.c @@ -0,0 +1,215 @@ +/* activate_credential.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM 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. + * + * wolfTPM 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-1301, USA + */ + +/* This example shows how to decrypt a credential for Remote Attestation + * and extract the secret for challenge response to an attestation server + */ + +#include + +#ifndef WOLFTPM2_NO_WRAPPER + +#include +#include +#include +#include + +#include + + +/******************************************************************************/ +/* --- BEGIN TPM2.0 Activate Credential example tool -- */ +/******************************************************************************/ + +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/attestation/activate_credential [cred.blob]\n"); + printf("* cred.blob is a input file holding the generated credential.\n"); + printf("Demo usage without parameters, uses \"cred.blob\" filename.\n"); +} + +int TPM2_ActivateCredential_Example(void* userCtx, int argc, char *argv[]) +{ + int rc = -1; + WOLFTPM2_DEV dev; + WOLFTPM2_KEY storage; + WOLFTPM2_KEYBLOB akKey; + WOLFTPM2_SESSION tpmSession; + FILE *fp; + const char *input = "cred.blob"; + const char *keyblob = "keyblob.bin"; + int dataSize = 0; + + union { + ActivateCredential_In activCred; + PolicyCommandCode_In policyCommandCode; + byte maxInput[MAX_COMMAND_SIZE]; + } cmdIn; + union { + ActivateCredential_Out activCred; + byte maxOutput[MAX_RESPONSE_SIZE]; + } cmdOut; + + if (argc == 1) { + printf("Using default values\n"); + } + else if (argc == 2) { + if (XSTRNCMP(argv[1], "-?", 2) == 0 || + XSTRNCMP(argv[1], "-h", 2) == 0 || + XSTRNCMP(argv[1], "--help", 6) == 0) { + usage(); + return 0; + } + if (argv[1][0] != '-') { + input = argv[1]; + } + } + else { + printf("Incorrect arguments\n"); + usage(); + goto exit_badargs; + } + + XMEMSET(&storage, 0, sizeof(storage)); + XMEMSET(&akKey, 0, sizeof(akKey)); + + printf("Demo how to create a credential blob for remote attestation\n"); + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_Init: success\n"); + + printf("Credential will be read from %s\n", input); + + /* Load SRK, required to unwrap credential */ + rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA); + if (rc != 0) goto exit; + printf("SRK loaded\n"); + /* Prepare the auth password for the Storage Key */ + storage.handle.auth.size = sizeof(gStorageKeyAuth)-1; + XMEMCPY(storage.handle.auth.buffer, gStorageKeyAuth, + storage.handle.auth.size); + wolfTPM2_SetAuthHandle(&dev, 0, &storage.handle); + + /* Load AK, required to verify the Key Attributes in the credential */ + rc = readKeyBlob(keyblob, &akKey); + if (rc != TPM_RC_SUCCESS) { + printf("Failure to read keyblob.\n"); + } + storage.handle.hndl = TPM2_DEMO_STORAGE_KEY_HANDLE; + rc = wolfTPM2_LoadKey(&dev, &akKey, &storage.handle); + if (rc != TPM_RC_SUCCESS) { + printf("Failure to load the AK and read its Name.\n"); + goto exit; + } + printf("AK loaded at 0x%x\n", (word32)akKey.handle.hndl); + /* Prepare the auth password for the Attestation Key */ + akKey.handle.auth.size = sizeof(gAiKeyAuth)-1; + XMEMCPY(akKey.handle.auth.buffer, gAiKeyAuth, + akKey.handle.auth.size); + wolfTPM2_SetAuthHandle(&dev, 0, &akKey.handle); + + /* Start an authenticated session (salted / unbound) */ + rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL, + TPM_SE_POLICY, TPM_ALG_NULL); + if (rc != 0) goto exit; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", + (word32)tpmSession.handle.hndl); + + /* ADMIN role required for Activate Credential command */ + XMEMSET(&cmdIn.policyCommandCode, 0, sizeof(cmdIn.policyCommandCode)); + cmdIn.policyCommandCode.policySession = tpmSession.handle.hndl; + cmdIn.policyCommandCode.code = TPM_CC_ActivateCredential; + rc = TPM2_PolicyCommandCode(&cmdIn.policyCommandCode); + if (rc != TPM_RC_SUCCESS) { + printf("policyCommandCode failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + printf("TPM2_policyCommandCode success\n"); /* No command response payload */ + + /* Prepare Key Auths in correct order for ActivateCredential */ + wolfTPM2_SetAuthHandle(&dev, 0, &akKey.handle); + wolfTPM2_SetAuthHandle(&dev, 1, &storage.handle); + + /* Prepare the Activate Credential command */ + XMEMSET(&cmdIn.activCred, 0, sizeof(cmdIn.activCred)); + XMEMSET(&cmdOut.activCred, 0, sizeof(cmdOut.activCred)); + cmdIn.activCred.activateHandle = akKey.handle.hndl; + cmdIn.activCred.keyHandle = TPM2_DEMO_STORAGE_KEY_HANDLE; + /* Read credeitnail from the user file */ +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + fp = XFOPEN(input, "rb"); + if (fp != XBADFILE) { + dataSize = (int)XFREAD((BYTE*)&cmdIn.activCred.credentialBlob, 1, + sizeof(cmdIn.activCred.credentialBlob), fp); + dataSize = (int)XFREAD((BYTE*)&cmdIn.activCred.secret, 1, + sizeof(cmdIn.activCred.secret), fp); + XFCLOSE(fp); + } + printf("Read credential blob and secret from %s, %d bytes\n", input, dataSize); +#else + printf("Can not load credential. File support not enabled\n"); + goto exit; +#endif + /* All required data to verify the credential is prepared */ + rc = TPM2_ActivateCredential(&cmdIn.activCred, &cmdOut.activCred); + if (rc != TPM_RC_SUCCESS) { + printf("TPM2_ActivateCredentials failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + printf("TPM2_ActivateCredential success\n"); + +exit: + + wolfTPM2_UnloadHandle(&dev, &tpmSession.handle); + wolfTPM2_UnloadHandle(&dev, &akKey.handle); + wolfTPM2_Cleanup(&dev); + +exit_badargs: + + return rc; +} + +/******************************************************************************/ +/* --- END TPM2.0 Activate Credential example tool -- */ +/******************************************************************************/ +#endif /* !WOLFTPM2_NO_WRAPPER */ + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc = -1; + +#ifndef WOLFTPM2_NO_WRAPPER + rc = TPM2_ActivateCredential_Example(NULL, argc, argv); +#else + printf("Wrapper code not compiled in\n"); + (void)argc; + (void)argv; +#endif /* !WOLFTPM2_NO_WRAPPER */ + + return rc; +} +#endif diff --git a/examples/attestation/credential.h b/examples/attestation/credential.h new file mode 100644 index 0000000..720d23e --- /dev/null +++ b/examples/attestation/credential.h @@ -0,0 +1,38 @@ +/* credential.h + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM 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. + * + * wolfTPM 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-1301, USA + */ + +#ifndef _CREDENTIAL_H_ +#define _CREDENTIAL_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define CRED_SECRET_SIZE 32 + +int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]); +int TPM2_ActivateCredential_Example(void* userCtx, int argc, char *argv[]); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _CREDENTIAL_H_ */ diff --git a/examples/attestation/include.am b/examples/attestation/include.am new file mode 100644 index 0000000..b6ce7eb --- /dev/null +++ b/examples/attestation/include.am @@ -0,0 +1,30 @@ +# vim:ft=automake +# All paths should be given relative to the root + +if BUILD_EXAMPLES +noinst_PROGRAMS += examples/attestation/make_credential \ + examples/attestation/activate_credential + +noinst_HEADERS += examples/attestation/credential.h + +examples_attestation_make_credential_SOURCES = examples/attestation/make_credential.c \ + examples/tpm_io.c \ + examples/tpm_test_keys.c +examples_attestation_make_credential_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_attestation_make_credential_DEPENDENCIES = src/libwolftpm.la + +examples_attestation_activate_credential_SOURCES = examples/attestation/activate_credential.c \ + examples/tpm_io.c \ + examples/tpm_test_keys.c +examples_attestation_activate_credential_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_attestation_activate_credential_DEPENDENCIES = src/libwolftpm.la + +endif + +dist_example_DATA+= examples/attestation/make_credential.c \ + examples/attestation/activate_credential.c + +DISTCLEANFILES+= examples/attestation/.libs/make_credential \ + examples/attestation/.libs/activate_credential + +EXTRA_DIST+= examples/attestation/README.md diff --git a/examples/attestation/make_credential.c b/examples/attestation/make_credential.c new file mode 100644 index 0000000..f934f1e --- /dev/null +++ b/examples/attestation/make_credential.c @@ -0,0 +1,184 @@ +/* make_credential.c + * + * Copyright (C) 2006-2021 wolfSSL Inc. + * + * This file is part of wolfTPM. + * + * wolfTPM 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. + * + * wolfTPM 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-1301, USA + */ + +/* This example shows how to create a challenge for Remote Attestation */ + +#include + +#ifndef WOLFTPM2_NO_WRAPPER + +#include +#include +#include +#include + +#include + + +/******************************************************************************/ +/* --- BEGIN TPM2.0 Make Credential example tool -- */ +/******************************************************************************/ + +static void usage(void) +{ + printf("Expected usage:\n"); + printf("./examples/attestation/make_credential [cred.blob]\n"); + printf("* cred.blob is a output file holding the generated credential.\n"); + printf("Demo usage without parameters, uses \"cred.blob\" filename.\n"); +} + +int TPM2_MakeCredential_Example(void* userCtx, int argc, char *argv[]) +{ + int rc = -1; + WOLFTPM2_DEV dev; + WOLFTPM2_KEY storage; + WOLFTPM2_KEYBLOB akKey; + FILE *fp; + const char *output = "cred.blob"; + const char *keyblob = "keyblob.bin"; + int dataSize = 0; + + union { + MakeCredential_In makeCred; + byte maxInput[MAX_COMMAND_SIZE]; + } cmdIn; + union { + MakeCredential_Out makeCred; + byte maxOutput[MAX_RESPONSE_SIZE]; + } cmdOut; + + if (argc == 1) { + printf("Using default values\n"); + } + else if (argc == 2) { + if (XSTRNCMP(argv[1], "-?", 2) == 0 || + XSTRNCMP(argv[1], "-h", 2) == 0 || + XSTRNCMP(argv[1], "--help", 6) == 0) { + usage(); + return 0; + } + if (argv[1][0] != '-') { + output = argv[1]; + } + } + else { + printf("Incorrect arguments\n"); + usage(); + goto exit_badargs; + } + + XMEMSET(&storage, 0, sizeof(storage)); + XMEMSET(&akKey, 0, sizeof(akKey)); + + printf("Demo how to create a credential blob for remote attestation\n"); + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_Init: success\n"); + + printf("Credential will be stored in %s\n", output); + + /* Prepare the auth password for the storage key */ + storage.handle.auth.size = sizeof(gStorageKeyAuth)-1; + XMEMCPY(storage.handle.auth.buffer, gStorageKeyAuth, + storage.handle.auth.size); + wolfTPM2_SetAuthPassword(&dev, 0, &storage.handle.auth); + + /* Prepare the Make Credential command */ + XMEMSET(&cmdIn.makeCred, 0, sizeof(cmdIn.makeCred)); + XMEMSET(&cmdOut.makeCred, 0, sizeof(cmdOut.makeCred)); + cmdIn.makeCred.handle = TPM2_DEMO_STORAGE_KEY_HANDLE; + /* Create secret for the attestation server - a symmetric key seed */ + cmdIn.makeCred.credential.size = CRED_SECRET_SIZE; + wolfTPM2_GetRandom(&dev, cmdIn.makeCred.credential.buffer, + cmdIn.makeCred.credential.size); + /* Acquire the Name of the Attestation Key */ + rc = readKeyBlob(keyblob, &akKey); + if (rc != TPM_RC_SUCCESS) { + printf("Failure to read keyblob.\n"); + } + storage.handle.hndl = TPM2_DEMO_STORAGE_KEY_HANDLE; + rc = wolfTPM2_LoadKey(&dev, &akKey, &storage.handle); + if (rc != TPM_RC_SUCCESS) { + printf("Failure to load the AK and read its Name.\n"); + goto exit; + } + printf("AK loaded at 0x%x\n", (word32)akKey.handle.hndl); + /* Copy the AK name into the command request */ + cmdIn.makeCred.objectName.size = akKey.handle.name.size; + XMEMCPY(cmdIn.makeCred.objectName.name, akKey.handle.name.name, + cmdIn.makeCred.objectName.size); + /* All required data for a credential is prepared */ + rc = TPM2_MakeCredential(&cmdIn.makeCred, &cmdOut.makeCred); + if (rc != TPM_RC_SUCCESS) { + printf("TPM2_MakeCredentials failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + printf("TPM2_MakeCredential success\n"); + +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + fp = XFOPEN(output, "wb"); + if (fp != XBADFILE) { + dataSize = (int)XFWRITE((BYTE*)&cmdOut.makeCred.credentialBlob, 1, + sizeof(cmdOut.makeCred.credentialBlob), fp); + dataSize = (int)XFWRITE((BYTE*)&cmdOut.makeCred.secret, 1, + sizeof(cmdOut.makeCred.secret), fp); + XFCLOSE(fp); + } + printf("Wrote credential blob and secret to %s, %d bytes\n", output, dataSize); +#else + printf("Can not store credential. File support not enabled\n"); +#endif + +exit: + + wolfTPM2_UnloadHandle(&dev, &akKey.handle); + wolfTPM2_Cleanup(&dev); + +exit_badargs: + + return rc; +} + +/******************************************************************************/ +/* --- END TPM2.0 Make Credential example tool -- */ +/******************************************************************************/ +#endif /* !WOLFTPM2_NO_WRAPPER */ + +#ifndef NO_MAIN_DRIVER +int main(int argc, char *argv[]) +{ + int rc = -1; + +#ifndef WOLFTPM2_NO_WRAPPER + rc = TPM2_MakeCredential_Example(NULL, argc, argv); +#else + printf("Wrapper code not compiled in\n"); + (void)argc; + (void)argv; +#endif /* !WOLFTPM2_NO_WRAPPER */ + + return rc; +} +#endif diff --git a/examples/include.am b/examples/include.am index 1938a00..c58c9f1 100644 --- a/examples/include.am +++ b/examples/include.am @@ -14,6 +14,7 @@ include examples/keygen/include.am include examples/nvram/include.am include examples/gpio/include.am include examples/seal/include.am +include examples/attestation/include.am dist_example_DATA+= examples/README.md \ examples/tpm_io.c \ diff --git a/examples/keygen/keygen.c b/examples/keygen/keygen.c index dcb1496..4501388 100644 --- a/examples/keygen/keygen.c +++ b/examples/keygen/keygen.c @@ -33,7 +33,7 @@ #ifndef WOLFTPM2_NO_WRAPPER -#define SYM_EXTRA_OPTS_LEN 14 /* 5 for "-sym=" and 6 for extra options */ +#define SYM_EXTRA_OPTS_LEN 14 /* 5 chars for "-sym=" and 9 for extra options */ #define SYM_EXTRA_OPTS_POS 4 /* Array pos of the equal sign for extra opts */ #define SYM_EXTRA_OPTS_AES_MODE_POS 8 #define SYM_EXTRA_OPTS_KEY_BITS_POS 11