Skip to content

Commit d086eba

Browse files
author
elms
authored
Merge pull request #143 from tomoveu/add-sym-keygen
2 parents 314e96b + 8ee41a3 commit d086eba

11 files changed

Lines changed: 611 additions & 103 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ tests/unit.test
5050
examples/keygen/keyload
5151
examples/keygen/keygen
5252
examples/keygen/keyimport
53+
examples/nvram/store
54+
examples/nvram/read
5355

5456
# Generated Cert Files
5557
certs/ca-*.pem

README.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,23 @@ Portable TPM 2.0 project designed for embedded use.
1212
* wolfTPM can also use the Linux TPM kernel interface (/dev/tpmX) to talk with any physical TPM on SPI, I2C and even LPC bus.
1313
* Platform support for Raspberry Pi, STM32 with CubeMX, Atmel ASF and Barebox.
1414
* The design allows for easy portability to different platforms:
15-
* Native C code designed for embedded use.
16-
* Single IO callback for hardware SPI interface.
17-
* No external dependencies.
18-
* Compact code size and minimal memory use.
15+
* Native C code designed for embedded use.
16+
* Single IO callback for hardware SPI interface.
17+
* No external dependencies.
18+
* Compact code size and minimal memory use.
1919
* Includes example code for:
2020
* Most TPM2 native API’s
2121
* All TPM2 wrapper API's
22-
* PKCS 7
23-
* Certificate Signing Request (CSR)
24-
* TLS Client
25-
* TLS Server
26-
* Benchmarking TPM algorithms and TLS
27-
* Parameter encryption support using AES-CFB or XOR. Supports salted unbound authenticated sessions.
22+
* PKCS 7
23+
* Certificate Signing Request (CSR)
24+
* TLS Client
25+
* TLS Server
26+
* Use of the TPM's Non-volatile memory
27+
* Attestation (TPM2_Quote and TPM2_GetTime)
28+
* Benchmarking TPM algorithms and TLS
29+
* Parameter encryption support using AES-CFB or XOR.
30+
* Support for salted unbound authenticated sessions.
31+
* Support for HMAC Sessions.
2832

2933
Note: See [examples/README.md](examples/README.md) for details on using the examples.
3034

examples/README.md

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,35 @@ TPM2.0 Key load example
236236
Loading SRK: Storage 0x81000200 (282 bytes)
237237
Reading 744 bytes from keyblob.bin
238238
Loaded key to 0x80000001
239+
240+
./examples/keygen/keygen -sym=aescfb128
241+
TPM2.0 Key generation example
242+
Key Blob: keyblob.bin
243+
Algorithm: SYMCIPHER
244+
aescfb mode, 128 keybits
245+
Template: Default
246+
Use Parameter Encryption: NULL
247+
Loading SRK: Storage 0x81000200 (282 bytes)
248+
Symmetric template
249+
Creating new SYMCIPHER key...
250+
Created new key (pub 50, priv 142 bytes)
251+
Wrote 198 bytes to keyblob.bin
252+
253+
$ ./examples/keygen/keyload
254+
TPM2.0 Key load example
255+
Key Blob: keyblob.bin
256+
Use Parameter Encryption: NULL
257+
Loading SRK: Storage 0x81000200 (282 bytes)
258+
Reading 198 bytes from keyblob.bin
259+
Reading the private part of the key
260+
Loaded key to 0x80000001
261+
239262
```
240263

264+
When filename is not supplied, a default filename "keyblob.bin" is used, therefore `keyload` and `keygen` can be used without additional parameters for quick TPM 2.0 key generation demonstration.
265+
266+
To see the complete list of supported cryptographic algorithms and options by the `keygen` example, use one of the `--help` switches.
267+
241268
Example for importing a private key as TPM key blob and storing to disk, then loading from disk and loading into temporary TPM handle.
242269

243270
```
@@ -271,26 +298,79 @@ The `keyload` tool takes only one argument, the filename of the stored key. Beca
271298

272299
## Storing keys into the TPM's NVRAM
273300

274-
These examples demonstrates how to use the TPM as secure vault for keys. There are two programs, one to store a TPM key into the TPM's NVRAM and another to extract the key from the TPM's NVRAM. Both examples can use parameter encryption to protect from MITM attacks. The Non-volatile memory location is protected with a password authorization that is passed in encrypted form, when "-aes" or "-xor" is given on the commmand line.
301+
These examples demonstrates how to use the TPM as a secure vault for keys. There are two programs, one to store a TPM key into the TPM's NVRAM and another to extract the key from the TPM's NVRAM. Both examples can use parameter encryption to protect from MITM attacks. The Non-volatile memory location is protected with a password authorization that is passed in encrypted form, when "-aes" is given on the command line.
275302

276303
Before running the examples, make sure there is a keyblob.bin generated using the keygen tool. The key can be of any type, RSA, ECC or symmetric. The example will store the private and public part. In case of a symmetric key the public part is meta data from the TPM. How to generate a key you can see above, in the description of the keygen example.
277304

278-
Typical output for storing and then reading an RSA key using parameter encryption:
305+
Typical output for storing and then reading an RSA key with parameter encryption enabled:
279306

280307
```
308+
281309
$ ./examples/nvram/store -aes
310+
Parameter Encryption: Enabled (AES CFB).
311+
282312
TPM2_StartAuthSession: sessionHandle 0x2000000
283313
Reading 840 bytes from keyblob.bin
284314
Storing key at TPM NV index 0x1800202 with password protection
315+
285316
Public part = 616 bytes
317+
NV write of public part succeeded
318+
286319
Private part = 222 bytes
287-
NV write succeeded
320+
Stored 2-byte size marker before the private part
321+
NV write of private part succeeded
322+
323+
324+
$ ./examples/nvram/read -aes
325+
Parameter Encryption: Enabled (AES CFB).
288326
289-
$ ./examples/nvram/read 616 222 -aes
290327
TPM2_StartAuthSession: sessionHandle 0x2000000
291328
Trying to read 616 bytes of public key part from NV
329+
Successfully read public key part from NV
330+
331+
Trying to read size marker of the private key part from NV
332+
Successfully read size marker from NV
333+
334+
Trying to read 222 bytes of private key part from NV
335+
Successfully read private key part from NV
336+
337+
Extraction of key from NVRAM at index 0x1800202 succeeded
338+
Loading SRK: Storage 0x81000200 (282 bytes)
339+
Trying to load the key extracted from NVRAM
340+
Loaded key to 0x80000001
341+
342+
```
343+
344+
The "read" example will try to load the extracted key, if both the public and private part of the key were stored in NVRAM. The "-aes" switches triggers the use of parameter encryption.
345+
346+
The examples can work with partial key material - private or public. This is achieved by using the "-priv" and "-pub" options.
347+
348+
Typical output of storing only the private key of RSA asymmetric key pair in NVRAM and without parameter encryption enabled.
349+
350+
```
351+
352+
$ ./examples/nvram/store -priv
353+
Parameter Encryption: Not enabled (try -aes or -xor).
354+
355+
Reading 506 bytes from keyblob.bin
356+
Reading the private part of the key
357+
Storing key at TPM NV index 0x1800202 with password protection
358+
359+
Private part = 222 bytes
360+
Stored 2-byte size marker before the private part
361+
NV write of private part succeeded
362+
363+
$ ./examples/nvram/read -priv
364+
Parameter Encryption: Not enabled (try -aes or -xor).
365+
366+
Trying to read size marker of the private key part from NV
367+
Successfully read size marker from NV
368+
292369
Trying to read 222 bytes of private key part from NV
370+
Successfully read private key part from NV
371+
293372
Extraction of key from NVRAM at index 0x1800202 succeeded
373+
294374
```
295375

296-
The read example takes as first argument the size of the public part and as second argument the private part. This information is given from the store example. The "-aes" swiches triggers the use of parameter encryption.
376+
After successful key extraction using "read", the NV Index is destroyed. Therefore, to use "read" again, the "store" example must be run again as well.

examples/keygen/keygen.c

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* keygen.c
22
*
3-
* Copyright (C) 2006-2020 wolfSSL Inc.
3+
* Copyright (C) 2006-2021 wolfSSL Inc.
44
*
55
* This file is part of wolfTPM.
66
*
@@ -29,34 +29,99 @@
2929
#include <examples/tpm_test_keys.h>
3030

3131
#include <stdio.h>
32+
#include <stdlib.h> /* atoi */
3233

3334
#ifndef WOLFTPM2_NO_WRAPPER
3435

36+
#define SYM_EXTRA_OPTS_LEN 14 /* 5 for "-sym=" and 6 for extra options */
37+
#define SYM_EXTRA_OPTS_POS 4 /* Array pos of the equal sign for extra opts */
38+
#define SYM_EXTRA_OPTS_AES_MODE_POS 8
39+
#define SYM_EXTRA_OPTS_KEY_BITS_POS 11
40+
41+
42+
3543
/******************************************************************************/
3644
/* --- BEGIN TPM Keygen Example -- */
3745
/******************************************************************************/
3846
static void usage(void)
3947
{
4048
printf("Expected usage:\n");
41-
printf("./examples/keygen/keygen [keyblob.bin] [-ecc/-rsa] [-t] [-aes/xor]\n");
42-
printf("* -ecc: Use RSA or ECC for keys\n");
49+
printf("./examples/keygen/keygen [keyblob.bin] [-ecc/-rsa/-sym] [-t] [-aes/xor]\n");
50+
printf("* -rsa: Use RSA for asymmetric key generation (DEFAULT)\n");
51+
printf("* -ecc: Use ECC for asymmetric key generation \n");
52+
printf("* -sym: Use Symmetric Cypher for key generation\n");
53+
printf("\tDefault Symmetric Cypher is AES CTR with 256 bits\n");
4354
printf("* -t: Use default template (otherwise AIK)\n");
4455
printf("* -aes/xor: Use Parameter Encryption\n");
56+
printf("Example usage:\n");
57+
printf("\t* RSA, default template\n");
58+
printf("\t\t keygen -t\n");
59+
printf("\t* ECC, Attestation Key template "\
60+
"with AES CFB parameter encryption\n");
61+
printf("\t\t keygen -ecc -aes\n");
62+
printf("\t* Symmetric key, AES, CTR mode, 128 bits\n");
63+
printf("\t\t keygen -sym=aesctr128\n");
64+
printf("\t* Symmetric key, AES, CFB mode, 256 bits\n");
65+
printf("\t\t keygen -sym=aescfb256\n");
66+
printf("\t* Symmetric key, AES, CBC mode, 128 bits, "\
67+
"with XOR parameter encryption\n");
68+
printf("\t\t keygen -sym=aescbc256 -xor\n");
69+
}
70+
71+
static int symChoice(const char* arg, TPM_ALG_ID* algSym, int* keyBits,
72+
char* symMode)
73+
{
74+
size_t len = XSTRLEN(arg);
75+
76+
if (len != SYM_EXTRA_OPTS_LEN) {
77+
return TPM_RC_FAILURE;
78+
}
79+
if (XSTRNCMP(&arg[SYM_EXTRA_OPTS_POS+1], "aes", 3)) {
80+
return TPM_RC_FAILURE;
81+
}
82+
83+
/* Copy string for user information later */
84+
XMEMCPY(symMode, &arg[SYM_EXTRA_OPTS_POS+1], 6);
85+
86+
if (XSTRNCMP(&arg[SYM_EXTRA_OPTS_AES_MODE_POS], "cfb", 3) == 0) {
87+
*algSym = TPM_ALG_CFB;
88+
}
89+
else if (XSTRNCMP(&arg[SYM_EXTRA_OPTS_AES_MODE_POS], "ctr", 3) == 0) {
90+
*algSym = TPM_ALG_CTR;
91+
}
92+
else if (XSTRNCMP(&arg[SYM_EXTRA_OPTS_AES_MODE_POS], "cbc", 3) == 0) {
93+
*algSym = TPM_ALG_CBC;
94+
}
95+
else {
96+
return TPM_RC_FAILURE;
97+
}
98+
99+
*keyBits = atoi(&arg[SYM_EXTRA_OPTS_KEY_BITS_POS]);
100+
if(*keyBits != 128 && *keyBits != 192 && *keyBits != 256) {
101+
return TPM_RC_FAILURE;
102+
}
103+
104+
return TPM_RC_SUCCESS;
45105
}
46106

47107
int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
48108
{
49109
int rc;
50110
WOLFTPM2_DEV dev;
51111
WOLFTPM2_KEY storage; /* SRK */
112+
WOLFTPM2_KEY aesKey; /* Symmetric key */
52113
WOLFTPM2_KEYBLOB newKey;
53114
TPMT_PUBLIC publicTemplate;
54-
TPMI_ALG_PUBLIC alg = TPM_ALG_RSA; /* TPM_ALG_ECC */
115+
TPMI_ALG_PUBLIC alg = TPM_ALG_RSA; /* default, see usage() for options */
116+
TPM_ALG_ID algSym = TPM_ALG_CTR; /* default Symmetric Cypher, see usage */
55117
TPM_ALG_ID paramEncAlg = TPM_ALG_NULL;
56118
WOLFTPM2_SESSION tpmSession;
57119
TPM2B_AUTH auth;
58120
int bAIK = 1;
121+
int keyBits = 256;
59122
const char* outputFile = "keyblob.bin";
123+
size_t len = 0;
124+
char symMode[] = "aesctr";
60125

61126
if (argc >= 2) {
62127
if (XSTRNCMP(argv[1], "-?", 2) == 0 ||
@@ -69,9 +134,29 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
69134
outputFile = argv[1];
70135
}
71136
while (argc > 1) {
137+
if (XSTRNCMP(argv[argc-1], "-rsa", 4) == 0) {
138+
alg = TPM_ALG_RSA;
139+
}
72140
if (XSTRNCMP(argv[argc-1], "-ecc", 4) == 0) {
73141
alg = TPM_ALG_ECC;
74142
}
143+
if (XSTRNCMP(argv[argc-1], "-sym", 4) == 0) {
144+
len = XSTRLEN(argv[argc-1]);
145+
if (len >= SYM_EXTRA_OPTS_LEN) {
146+
/* Did the user provide specific options? */
147+
if (argv[argc-1][SYM_EXTRA_OPTS_POS] == '=') {
148+
rc = symChoice(argv[argc-1], &algSym, &keyBits, symMode);
149+
}
150+
/* In case of incorrect extra options, abort execution */
151+
if (rc != TPM_RC_SUCCESS) {
152+
usage();
153+
return 0;
154+
}
155+
/* Otherwise, defaults are used: AES CTR, 256 key bits */
156+
}
157+
alg = TPM_ALG_SYMCIPHER;
158+
bAIK = 0;
159+
}
75160
if (XSTRNCMP(argv[argc-1], "-t", 2) == 0) {
76161
bAIK = 0;
77162
}
@@ -86,12 +171,16 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
86171

87172
XMEMSET(&storage, 0, sizeof(storage));
88173
XMEMSET(&newKey, 0, sizeof(newKey));
174+
XMEMSET(&aesKey, 0, sizeof(aesKey));
89175
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
90176
XMEMSET(&auth, 0, sizeof(auth));
91177

92178
printf("TPM2.0 Key generation example\n");
93179
printf("\tKey Blob: %s\n", outputFile);
94180
printf("\tAlgorithm: %s\n", TPM2_GetAlgName(alg));
181+
if(alg == TPM_ALG_SYMCIPHER) {
182+
printf("\t\t %s mode, %d keybits\n", symMode, keyBits);
183+
}
95184
printf("\tTemplate: %s\n", bAIK ? "AIK" : "Default");
96185
printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg));
97186

@@ -129,6 +218,10 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
129218
printf("ECC AIK template\n");
130219
rc = wolfTPM2_GetKeyTemplate_ECC_AIK(&publicTemplate);
131220
}
221+
else if (alg == TPM_ALG_SYMCIPHER) {
222+
printf("AIK are expected to be RSA or ECC, not symmetric keys.\n");
223+
rc = BAD_FUNC_ARG;
224+
}
132225
else {
133226
rc = BAD_FUNC_ARG;
134227
}
@@ -152,6 +245,11 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
152245
TPMA_OBJECT_sign | TPMA_OBJECT_noDA,
153246
TPM_ECC_NIST_P256, TPM_ALG_ECDSA);
154247
}
248+
else if (alg == TPM_ALG_SYMCIPHER) {
249+
printf("Symmetric template\n");
250+
rc = wolfTPM2_GetKeyTemplate_Symmetric(&publicTemplate, keyBits,
251+
algSym, YES, YES);
252+
}
155253
else {
156254
rc = BAD_FUNC_ARG;
157255
}
@@ -176,6 +274,9 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
176274
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM)
177275
rc = writeKeyBlob(outputFile, &newKey);
178276
#else
277+
if(alg == TPM_ALG_SYMCIPHER) {
278+
printf("The Public Part of a symmetric key contains only meta data\n");
279+
}
179280
printf("Key Public Blob %d\n", newKey.pub.size);
180281
TPM2_PrintBin((const byte*)&newKey.pub.publicArea, newKey.pub.size);
181282
printf("Key Private Blob %d\n", newKey.priv.size);

0 commit comments

Comments
 (0)