Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TPM sealing cleanups #375

Merged
merged 1 commit into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions docs/TPM.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ NOTE: The TPM's RSA verify requires ASN.1 encoding, so use SIGN=RSA2048ENC
% ./tools/tpm/pcr_extend 0 aaa.bin
% ./tools/tpm/policy_create -pcr=0
# if ROT enabled
% ./tools/tpm/rot -write
% ./tools/tpm/rot -write [-auth=TestAuth]
% make clean && make POLICY_FILE=policy.bin

% ./wolfboot.elf get_version
Expand Down Expand Up @@ -168,7 +168,31 @@ Building firmware with the policy digest to sign:
% make POLICY_FILE=policy.bin
```

OR manually using:
OR manually sign the policy using the `tools/tpm/policy_sign` or `tools/keytools/sign` tools.
These tools do not need access to a TPM, they are signing a policy digest. The result is a 32-bit PCR mask + signature.

Sign with policy_sign tool:

```sh
% ./tools/tpm/policy_sign -pcr=0 -pcrdigest=eca4e8eda468b8667244ae972b8240d3244ea72341b2bf2383e79c66643bbecc
Sign PCR Policy Tool
Signing Algorithm: ECC256
PCR Index(s) (SHA256): 0
Policy Signing Key: wolfboot_signing_private_key.der
PCR Digest (32 bytes):
eca4e8eda468b8667244ae972b8240d3244ea72341b2bf2383e79c66643bbecc
PCR Policy Digest (32 bytes):
2d401eb05f45ba2b15c35f628b5896cc7de9745bb6e722363e2dbee804e0500f
PCR Policy Digest (w/PolicyRef) (32 bytes):
749b3139ece21449a7828f11ee05303b0473ff1a26cf41d6f9ff28b24c717f02
PCR Mask (0x1) and Policy Signature (68 bytes):
01000000
5b5f875b3f7ce78b5935abe4fc5a4d8a6e87c4b4ac0836fbab909e232b6d7ca2
3ecfc6be723b695b951ba2886d3c7b83ab2f8cc0e96d766bc84276eaf3f213ee
Wrote PCR Mask + Signature (68 bytes) to policy.bin.sig
```

Sign using the signing key tool:

```sh
% ./tools/keytools/sign --ecc256 --policy policy.bin test-app/image.elf wolfboot_signing_private_key.der 1
Expand All @@ -186,5 +210,6 @@ Calculating SHA256 digest...
Signing the digest...
Opening policy file policy.bin
Signing the policy digest...
Saving policy signature to policy.bin.sig
Output image(s) successfully created.
```
8 changes: 8 additions & 0 deletions src/tpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,10 @@ int wolfBoot_seal_blob(const uint8_t* pubkey_hint, const uint8_t* policy, uint16
/* get public key for policy authorization */
rc = wolfBoot_load_pubkey(pubkey_hint, &authKey, &alg);

#ifdef WOLFBOOT_DEBUG_TPM
wolfBoot_printf("Seal: Pub Key %d\n", alg);
#endif

/* The handle for the public key if not needed, so unload it.
* For seal only a populated TPM2B_PUBLIC is required */
wolfTPM2_UnloadHandle(&wolftpm_dev, &authKey.handle);
Expand Down Expand Up @@ -885,6 +889,10 @@ int wolfBoot_unseal_blob(const uint8_t* pubkey_hint,
memset(pcrArray, 0, sizeof(pcrArray));
pcrArraySz = wolfBoot_tpm_pcrmask_sel(pcrMask, pcrArray, sizeof(pcrArray));

#ifdef WOLFBOOT_DEBUG_TPM
wolfBoot_printf("Unseal: PCR mask 0x%x (sz %d)\n", pcrMask, pcrArraySz);
#endif

/* skip to signature */
policy += sizeof(pcrMask);
policySz -= sizeof(pcrMask);
Expand Down
5 changes: 3 additions & 2 deletions src/update_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@ int wolfBoot_unlock_disk(void)


/* Extend a PCR from the mask to prevent future unsealing */
#if !defined(ARCH_SIM) && !defined(WOLFBOOT_NO_UNSEAL_PCR_EXTEND)
{
uint32_t pcrMask;
uint32_t pcrArraySz;
Expand All @@ -670,8 +671,8 @@ int wolfBoot_unlock_disk(void)
pcrArraySz = wolfBoot_tpm_pcrmask_sel(pcrMask,
pcrArray, sizeof(pcrArray)); /* get first PCR from mask */
wolfBoot_tpm2_extend(pcrArray[0], (uint8_t*)digest, __LINE__);
}

}
#endif
}
else {
wolfBoot_printf("unlock disk failed! %d (%s)\n",
Expand Down
120 changes: 65 additions & 55 deletions tools/tpm/policy_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,31 @@
*/


#include "wolfssl/wolfcrypt/types.h"
#include <wolftpm/tpm2.h>
#include <wolftpm/tpm2_wrap.h>

#include <stdio.h>

#include <hal/tpm_io.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/hash.h>
#include <wolftpm/tpm2_wrap.h>
#include "tpm.h"

/* Default PCR (test) */
#define DEFAULT_PCR 16

/* Prefer SHA2-256 for PCR's, and all TPM 2.0 devices support it */
#define USE_PCR_ALG TPM_ALG_SHA256
enum sign_alg {
ECC256 = 0,
};

static void usage(void)
{
printf("Expected usage:\n");
printf("./examples/pcr/policy_sign [-ecc256] [-key=pem/der] [-pcr] [-pcrdisgest] [-outpolicy=] policy_file\n");
printf("* -ecc256: Use ECC256P1 key\n");
printf("* -key=keyfile: Private key to sign PCR policy (PEM or DER)\n");
printf("* -pcr=index: PCR index < 24 (multiple can be supplied) (default 0)\n");
printf("./examples/pcr/policy_sign [-ecc256/-ecc384] [-key=pem/der] [-pcr=] [-pcrdigest=] [-policydigest=][-outpolicy=]\n");
printf("* -ecc256/-ecc384: Key type (currently only ECC) (default SECP256R1)\n");
printf("* -key=keyfile: Private key to sign PCR policy (PEM or DER) (default wolfboot_signing_private_key.der)\n");
printf("* -pcr=index: PCR index < 24 (multiple can be supplied) (default %d)\n", DEFAULT_PCR);
printf("* -pcrdigest=hexstr: PCR Digest (default=Read actual PCR's)\n");
printf("* -out=file: Signature file (default policy.bin.sig)\n");
printf("* -policydigest=hexstr: Policy Digest (policy based on PCR digest and PCR(s)\n");
printf("* -outpolicy=file: Signature file (default policy.bin.sig)\n");
printf("Example:\n");
printf("\t./tools/tpm/policy_sign -ecc256 -pcr=0 -pcrdigest=eca4e8eda468b8667244ae972b8240d3244ea72341b2bf2383e79c66643bbecc\n");
}


Expand Down Expand Up @@ -98,8 +99,8 @@ static int loadFile(const char* fname, byte** buf, size_t* bufLen)
}

/* Function to sign policy with external key */
static int PolicySign(enum sign_alg alg, const char* keyFile, byte* hash,
word32 hashSz, byte* sig, word32* sigSz)
static int PolicySign(int alg, const char* keyFile, byte* hash, word32 hashSz,
byte* sig, word32* sigSz)
{
int rc = 0;
byte* buf = NULL;
Expand All @@ -114,8 +115,8 @@ static int PolicySign(enum sign_alg alg, const char* keyFile, byte* hash,
#endif
} key;

XMEMSET(&key, 0, sizeof(key));
XMEMSET(&rng, 0, sizeof(rng));
memset(&key, 0, sizeof(key));
memset(&rng, 0, sizeof(rng));

rc = wc_InitRng(&rng);
if (rc != 0) {
Expand All @@ -124,20 +125,21 @@ static int PolicySign(enum sign_alg alg, const char* keyFile, byte* hash,
}

rc = loadFile(keyFile, &buf, &bufSz);
if (rc == 0 && alg == ECC256) {
if (rc == 0 && (alg == ECC_SECP256R1 || alg == ECC_SECP384R1)) {
word32 keySz = 32;
if (alg == ECC_SECP384R1)
keySz = 48;
rc = wc_ecc_init(&key.ecc);
if (rc == 0) {
rc = wc_ecc_import_unsigned(&key.ecc, buf,
(buf) + 32, buf + 64,
ECC_SECP256R1);
(buf) + keySz, buf + (keySz*2), alg);
if (rc == 0) {
mp_int r, s;
rc = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL);
if (rc == 0) {
rc = wc_ecc_sign_hash_ex(hash, hashSz, &rng, &key.ecc, &r, &s);
}
if (rc == 0) {
word32 keySz = key.ecc.dp->size;
mp_to_unsigned_bin(&r, sig);
mp_to_unsigned_bin(&s, sig + keySz);
mp_clear(&r);
Expand Down Expand Up @@ -231,10 +233,10 @@ int policy_sign(int argc, char *argv[])
int i;
int rc = -1;
TPM_ALG_ID pcrAlg = USE_PCR_ALG;
enum sign_alg alg;
int alg = ECC_SECP256R1;
byte pcrArray[PCR_SELECT_MAX*2];
word32 pcrArraySz = 0;
const char* keyFile = NULL;
const char* keyFile = "wolfboot_signing_private_key.der";
const char* outPolicyFile = "policy.bin.sig";
byte pcrDigest[WC_MAX_DIGEST_SIZE];
word32 pcrDigestSz = 0;
Expand All @@ -257,7 +259,10 @@ int policy_sign(int argc, char *argv[])
}
while (argc > 1) {
if (XSTRCMP(argv[argc-1], "-ecc256") == 0) {
alg = ECC256;
alg = ECC_SECP256R1;
}
else if (XSTRCMP(argv[argc-1], "-ecc384") == 0) {
alg = ECC_SECP384R1;
}
else if (strncmp(argv[argc-1], "-pcr=", strlen("-pcr=")) == 0) {
const char* pcrStr = argv[argc-1] + strlen("-pcr=");
Expand Down Expand Up @@ -310,7 +315,18 @@ int policy_sign(int argc, char *argv[])
argc--;
}

printf("Sign PCR Policy Example\n");
printf("Sign PCR Policy Tool\n");

if (pcrArraySz == 0) {
pcrArray[pcrArraySz] = DEFAULT_PCR;
pcrArraySz++;
}

printf("Signing Algorithm: %s\n",
(alg == ECC_SECP256R1) ? "ECC256" :
(alg == ECC_SECP384R1) ? "ECC384" :
"Unknown"
);

printf("PCR Index(s) (%s): ", TPM2_GetAlgName(pcrAlg));
for (i = 0; i < (int)pcrArraySz; i++) {
Expand All @@ -327,20 +343,18 @@ int policy_sign(int argc, char *argv[])
printf("Policy Signing Key: %s\n", keyFile);
}

/* PCR Hash - Use provided hash or read PCR's and get hash */
/* PCR Hash - Use provided PCR digest or Policy digest */
if (pcrDigestSz == 0 && digestSz == 0) {
printf("Error: Specificy PCR's or Policy hash!\n");
goto exit;
}

if (pcrDigestSz > 0) {
printf("PCR Digest (%d bytes):\n", pcrDigestSz);
printHexString(pcrDigest, pcrDigestSz, pcrDigestSz);
printf("Error: Must supply either PCR or Policy digest!\n");
usage();
return -1;
}
printf("PCR Digest (%d bytes):\n", pcrDigestSz);
printHexString(pcrDigest, pcrDigestSz, pcrDigestSz);

if (digestSz == 0) {
/* Build PCR Policy to Sign */
XMEMSET(digest, 0, sizeof(digest));
/* If not supplied, build PCR Policy to Sign */
memset(digest, 0, sizeof(digest));
digestSz = TPM2_GetHashDigestSize(pcrAlg);
rc = wolfTPM2_PolicyPCRMake(pcrAlg, pcrArray, pcrArraySz,
pcrDigest, pcrDigestSz, digest, &digestSz);
Expand All @@ -358,28 +372,24 @@ int policy_sign(int argc, char *argv[])
printHexString(digest, digestSz, digestSz);

/* Sign the PCR policy (use private key provided or do externally) */
if (keyFile != NULL) {
rc = PolicySign(alg, keyFile, digest, digestSz, sig, &sigSz);
rc = PolicySign(alg, keyFile, digest, digestSz, sig, &sigSz);
if (rc == 0) {
pcrMask = 0;
for (i = 0; i < (int)pcrArraySz; i++)
pcrMask |= (1 << pcrArray[i]);

memcpy(policy, &pcrMask, sizeof(pcrMask));
memcpy(policy + sizeof(pcrMask), sig, sigSz);
printf("PCR Mask (0x%x) and Policy Signature (%d bytes):\n",
(int)pcrMask, (int)(sigSz + sizeof(pcrMask)));
printHexString(policy, sizeof(pcrMask), 0);
printHexString(policy + sizeof(pcrMask), sigSz, 32);
rc = writeBin(outPolicyFile, policy, sigSz+sizeof(pcrMask));
if (rc == 0) {
pcrMask = 0;
for (i = 0; i < (int)pcrArraySz; i++)
pcrMask |= (1 << pcrArray[i]);

memcpy(policy, &pcrMask, sizeof(pcrMask));
memcpy(policy + sizeof(pcrMask), sig, sigSz);
printf("PCR Mask (0x%x) and Policy Signature (%d bytes):\n", (int)pcrMask,
(int)(sigSz + sizeof(pcrMask)));
printHexString(policy, sigSz+sizeof(pcrMask), 32);
rc = writeBin(outPolicyFile, policy, sigSz+sizeof(pcrMask));
printf("Wrote PCR Mask + Signature (%d bytes) to %s\n",
(int)(sigSz + sizeof(pcrMask)), outPolicyFile);
}
}
else {
/* Print policy hash to sign externally and exit early */
printf("No private key to sign policy!\n");
printf("Externally sign the PCR Policy digest\n");
rc = 0;
goto exit;
}

exit:
if (rc != 0) {
Expand Down
Loading