Skip to content

Commit 5e173bc

Browse files
authored
Merge pull request #281 from dgarske/tpm_import
Fixes for TPM private key import with custom seed
2 parents 699217b + e646c57 commit 5e173bc

File tree

10 files changed

+874
-198
lines changed

10 files changed

+874
-198
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ examples/keygen/create_primary
6060
examples/keygen/keyload
6161
examples/keygen/keygen
6262
examples/keygen/keyimport
63+
examples/keygen/external_import
6364
examples/nvram/store
6465
examples/nvram/read
6566
examples/nvram/counter

examples/keygen/external_import.c

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
/* external_import.c
2+
*
3+
* Copyright (C) 2006-2023 wolfSSL Inc.
4+
*
5+
* This file is part of wolfTPM.
6+
*
7+
* wolfTPM is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfTPM is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
/* Example for importing an external RSA key with seed and creating a
23+
* child key under it. */
24+
25+
#include <wolftpm/tpm2_wrap.h>
26+
27+
#include <stdio.h>
28+
29+
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT)
30+
31+
#include <examples/keygen/keygen.h>
32+
#include <hal/tpm_io.h>
33+
34+
/* from certs/example-rsa-key.pem */
35+
const char* extRSAPrivatePem =
36+
"-----BEGIN PRIVATE KEY-----\n"
37+
"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCePbYR1SIZAL/2\n"
38+
"8FYbgpxynENgvHACM9LczZnsgVkZYxx3O9DTba2VTxhMN21i/aocJCzZB35qvz+R\n"
39+
"ickyvWBqPDXauJEn9icPXgSknqxzw0ZATzL0wbq/Tk5T+oITFFCGJ8/baFoktOKu\n"
40+
"iP5H50Dx6X2W1qNHiLkbGq7NbXHA8YG2wzK9kwikowSXQVB7pZ5bgjW2q73vIGSs\n"
41+
"eW802f7I/30wbf4oR1vfk4OQursT9sl2CFLNt5bJSw6lFTm4BOgC7Q3bpHPzC/YK\n"
42+
"uFYWKGeQL9GCsEZVWHCM6vzek6SNwQ0eoQ0i9IuF0os/0nJDwdXEZX9OoBhFT717\n"
43+
"svlxDXpFAgMBAAECggEABYIV6Jx/5ZloVTbr9GSxP+8PDFq61mTJ6fwxJ7Gf8ZmI\n"
44+
"1+Cp5fYrJOeeK6cBRIEabwTWV86iOKKEGrOOYJkFdmU2pbCngtnXZbpK1JUeYSAy\n"
45+
"vZHULv9gWgDmipdNeE8Md4MCwfspqh3uxw8HNOcIlHMhd0Ls55RLhzVAUO/GliXz\n"
46+
"5HIDhohyQAUvPvkwz1yrPNn5BQwMlJBARc2OKSKf+pJrlFw1KJWR9TKzGvRzMbI4\n"
47+
"gwrq9BZ5LCX5y6C7BpuzXdySHXofwihPNmi1KU/88cWhas2E0Xz+p+N/ifmkquTN\n"
48+
"3EqzqKBW+xobryM6X9JfQ6has211eUaZKNuU2/idKQKBgQC5rymu0UKHuAkr4uPS\n"
49+
"NLGmaWb4p+kDNxbVyzS2ENjtoJ6JyEo/pZQrTG4S/kCWFgGsuztCbx+1Kgk0Pgwi\n"
50+
"znaGvcfrjiP9XE1oVfMifA2JmH+drjASyjPqNfsf0BKQtlk0nZXwUO/C1FQ5vUU4\n"
51+
"lpmpx4EhTnucQ9E7r0+uXnQHTQKBgQDaKh4bBV7dLBF4ZxwCdydMMSZkBgckBiH7\n"
52+
"83BvyLW6I0GKXcFTa7KKLgTj41pXeWh6bmM9365+Cr8fxTZop28EfGRYFBMp08/g\n"
53+
"wHpmS3NZ4moSgirJ+PhZsH+nBq89W75INR7BqV4SAc3n4lcwv9eBL9q0Q/YJZ1ph\n"
54+
"NCKvz79y2QKBgFyDFPVwdQFBg/BFntRARLJwmUkR/1oGvG3QTHbZdfsOp25mR/fl\n"
55+
"+yiHb+AupOciF7uDnUbALsAILYXF1C4TR6JiM5T8wJmev0JYcEaiH+yJ+isJehIi\n"
56+
"hDMQqglzlYxcDZ3VVbrh2FLtjvklf7Nt9SlNqNx7ScLVVw2xjrWFgbGRAoGBAMjo\n"
57+
"Wnsl0fu6Noh74/Z9RmpLJQCd8HuDTk6ZHCVFX91/1D6ZIo0xM+U+hfBbkfnWa5m8\n"
58+
"CJaVZDrcqK+YTQfJkVo/N6VJL3Coh9qBRvbnat4OvQI4bzE6n3LxME1fwYeu8ifL\n"
59+
"C3zq/R92G+n8rbDOKqbkq/KwV2bHkBrOCVeA6NzZAoGACztyZbS5jCuSlPqk/xoN\n"
60+
"EzX9Cev/GipF5tZMeOcQlty+anPg3TC70O06yZ1SIJKLzOOyoPCUDNrM2M5TCaau\n"
61+
"vT0vW1GeNAryc+q9aOmFT3AlZ93Tfst+90Q+NJecEEhkO43tU5S1ZK2iVf9XAOV6\n"
62+
"ovHegJU35IUeaoyg23HjFWU=\n"
63+
"-----END PRIVATE KEY-----";
64+
65+
static void usage(void)
66+
{
67+
printf("Expected usage:\n");
68+
printf("./examples/keygen/external_import [-ecc/-rsa]\n");
69+
printf("Primary Key Type:\n");
70+
printf("\t-rsa: Use RSA SRK (DEFAULT)\n");
71+
printf("\t-ecc: Use ECC SRK\n");
72+
}
73+
74+
int TPM2_ExternalImport_Example(void* userCtx, int argc, char *argv[])
75+
{
76+
int rc;
77+
WOLFTPM2_DEV dev;
78+
WOLFTPM2_KEY storage; /* SRK */
79+
WOLFTPM2_KEY *primary;
80+
WOLFTPM2_KEYBLOB* key2;
81+
WOLFTPM2_KEYBLOB* rsaKey3;
82+
TPM2B_DIGEST seedValue;
83+
TPMT_PUBLIC publicTemplate3;
84+
TPMA_OBJECT attributes;
85+
TPMI_ALG_PUBLIC alg = TPM_ALG_RSA;
86+
87+
if (argc >= 2) {
88+
if (XSTRCMP(argv[1], "-?") == 0 ||
89+
XSTRCMP(argv[1], "-h") == 0 ||
90+
XSTRCMP(argv[1], "--help") == 0) {
91+
usage();
92+
return 0;
93+
}
94+
}
95+
while (argc > 1) {
96+
if (XSTRCMP(argv[argc-1], "-rsa") == 0) {
97+
alg = TPM_ALG_RSA;
98+
}
99+
else if (XSTRCMP(argv[argc-1], "-ecc") == 0) {
100+
alg = TPM_ALG_ECC;
101+
}
102+
else {
103+
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
104+
}
105+
106+
argc--;
107+
}
108+
109+
key2 = wolfTPM2_NewKeyBlob();
110+
rsaKey3 = wolfTPM2_NewKeyBlob();
111+
primary = &storage;
112+
113+
rc = wolfTPM2_Init(&dev, TPM2_IoCb, NULL);
114+
if (rc != TPM_RC_SUCCESS) {
115+
printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
116+
goto exit;
117+
}
118+
119+
/* RSA or ECC (faster) SRK */
120+
rc = wolfTPM2_CreateSRK(&dev, &storage, alg, NULL, 0);
121+
if (rc != 0) {
122+
printf("Failed to wolfTPM2_CreateSRK\n");
123+
goto exit;
124+
}
125+
126+
/* Second level key */
127+
attributes = (TPMA_OBJECT_restricted |
128+
TPMA_OBJECT_sensitiveDataOrigin |
129+
TPMA_OBJECT_decrypt |
130+
TPMA_OBJECT_userWithAuth |
131+
TPMA_OBJECT_noDA);
132+
133+
/* Generate random seed */
134+
XMEMSET(&seedValue, 0, sizeof(seedValue));
135+
seedValue.size = TPM2_GetHashDigestSize(TPM_ALG_SHA256);
136+
TPM2_GetNonce(seedValue.buffer, seedValue.size);
137+
#ifdef DEBUG_WOLFTPM
138+
printf("Import RSA Seed %d\n", seedValue.size);
139+
TPM2_PrintBin(seedValue.buffer, seedValue.size);
140+
#endif
141+
142+
rc = wolfTPM2_ImportPrivateKeyBuffer(&dev, &storage, TPM_ALG_RSA, key2,
143+
ENCODING_TYPE_PEM, extRSAPrivatePem, (word32)strlen(extRSAPrivatePem),
144+
NULL, attributes, seedValue.buffer, seedValue.size);
145+
if (rc != 0) {
146+
printf("Failed to wolfTPM2_RsaPrivateKeyImportPem\n");
147+
goto exit;
148+
}
149+
150+
rc = wolfTPM2_LoadKey(&dev, key2, &primary->handle);
151+
if (rc != 0) {
152+
printf("Failed to wolfTPM2_LoadKey\n");
153+
goto exit;
154+
}
155+
156+
/* The 3rd level RSA key */
157+
rc = wolfTPM2_GetKeyTemplate_RSA(&publicTemplate3,
158+
TPMA_OBJECT_sensitiveDataOrigin |
159+
TPMA_OBJECT_userWithAuth |
160+
TPMA_OBJECT_sign |
161+
TPMA_OBJECT_noDA);
162+
if (rc != 0) {
163+
printf("Failed to wolfTPM2_GetKeyTemplate_RSA\n");
164+
goto exit;
165+
}
166+
rc = wolfTPM2_CreateKey(&dev, rsaKey3, &key2->handle,
167+
&publicTemplate3, NULL, 0);
168+
if (rc != TPM_RC_SUCCESS) {
169+
printf("wolfTPM2_CreateKey failed for the 3rd level key: %d\n", rc);
170+
goto exit;
171+
}
172+
173+
/* load the rsa key */
174+
rc = wolfTPM2_LoadKey(&dev, rsaKey3, &key2->handle);
175+
176+
if (rc != 0) {
177+
printf("Failed to wolfTPM2_LoadKey %d\n", rc);
178+
goto exit;
179+
}
180+
181+
exit:
182+
wolfTPM2_UnloadHandle(&dev, &rsaKey3->handle);
183+
wolfTPM2_UnloadHandle(&dev, &key2->handle);
184+
wolfTPM2_UnloadHandle(&dev, &primary->handle);
185+
186+
wolfTPM2_FreeKeyBlob(key2);
187+
wolfTPM2_FreeKeyBlob(rsaKey3);
188+
189+
wolfTPM2_Cleanup(&dev);
190+
191+
(void)userCtx;
192+
(void)argc;
193+
194+
195+
return rc;
196+
}
197+
#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT */
198+
199+
#ifndef NO_MAIN_DRIVER
200+
int main(int argc, char *argv[])
201+
{
202+
int rc = NOT_COMPILED_IN;
203+
204+
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT)
205+
rc = TPM2_ExternalImport_Example(NULL, argc, argv);
206+
#else
207+
printf("Example for external import and child key creation (not compiled in)\n");
208+
(void)argc;
209+
(void)argv;
210+
#endif
211+
212+
return rc;
213+
}
214+
#endif

examples/keygen/include.am

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,24 @@ examples_keygen_keyimport_SOURCES = examples/keygen/keyimport.c \
2727
examples/tpm_test_keys.c
2828
examples_keygen_keyimport_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
2929
examples_keygen_keyimport_DEPENDENCIES = src/libwolftpm.la
30+
31+
noinst_PROGRAMS += examples/keygen/external_import
32+
examples_keygen_external_import_SOURCES = examples/keygen/external_import.c \
33+
examples/tpm_test_keys.c
34+
examples_keygen_external_import_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
35+
examples_keygen_external_import_DEPENDENCIES = src/libwolftpm.la
3036
endif
3137

3238
example_keygendir = $(exampledir)/keygen
3339
dist_example_keygen_DATA = \
3440
examples/keygen/create_primary.c \
3541
examples/keygen/keyload.c \
3642
examples/keygen/keygen.c \
37-
examples/keygen/keyimport.c
43+
examples/keygen/keyimport.c \
44+
examples/keygen/external_import.c
3845

3946
DISTCLEANFILES+= examples/keygen/.libs/create_primary
4047
DISTCLEANFILES+= examples/keygen/.libs/keyload
4148
DISTCLEANFILES+= examples/keygen/.libs/keygen
4249
DISTCLEANFILES+= examples/keygen/.libs/keyimport
50+
DISTCLEANFILES+= examples/keygen/.libs/external_import

examples/keygen/keygen.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
138138
const char *pubFilename = NULL;
139139
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM)
140140
const char *nameFile = "ak.name"; /* Name Digest for attestation purposes */
141+
#if !defined(NO_RSA)
141142
const char *pemFilename = NULL;
143+
#endif
142144
FILE *fp;
143145
#endif
144146
size_t len = 0;
@@ -374,7 +376,8 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
374376
#endif
375377

376378
/* Save EK public key as PEM format file to the disk */
377-
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM)
379+
#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) && \
380+
!defined(NO_RSA)
378381
if (pemFiles) {
379382
byte pem[MAX_RSA_KEY_BYTES];
380383
word32 pemSz;

examples/keygen/keygen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ int TPM2_CreatePrimaryKey_Example(void* userCtx, int argc, char *argv[]);
3030
int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[]);
3131
int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[]);
3232
int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[]);
33+
int TPM2_ExternalImport_Example(void* userCtx, int argc, char *argv[]);
3334

3435
#ifdef __cplusplus
3536
} /* extern "C" */

src/tpm2_packet.c

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ void TPM2_Packet_ParsePoint(TPM2_Packet* packet, TPM2B_ECC_POINT* point)
486486
void TPM2_Packet_AppendSensitive(TPM2_Packet* packet, TPM2B_SENSITIVE* sensitive)
487487
{
488488
int tmpSz = 0;
489+
TPMU_SENSITIVE_COMPOSITE* sens = &sensitive->sensitiveArea.sensitive;
489490

490491
TPM2_Packet_MarkU16(packet, &tmpSz);
491492

@@ -499,9 +500,24 @@ void TPM2_Packet_AppendSensitive(TPM2_Packet* packet, TPM2B_SENSITIVE* sensitive
499500
TPM2_Packet_AppendBytes(packet, sensitive->sensitiveArea.seedValue.buffer,
500501
sensitive->sensitiveArea.seedValue.size);
501502

502-
TPM2_Packet_AppendU16(packet, sensitive->sensitiveArea.sensitive.any.size);
503-
TPM2_Packet_AppendBytes(packet, sensitive->sensitiveArea.sensitive.any.buffer,
504-
sensitive->sensitiveArea.sensitive.any.size);
503+
switch (sensitive->sensitiveArea.sensitiveType) {
504+
case TPM_ALG_RSA:
505+
TPM2_Packet_AppendU16(packet, sens->rsa.size);
506+
TPM2_Packet_AppendBytes(packet, sens->rsa.buffer, sens->rsa.size);
507+
break;
508+
case TPM_ALG_ECC:
509+
TPM2_Packet_AppendU16(packet, sens->ecc.size);
510+
TPM2_Packet_AppendBytes(packet, sens->ecc.buffer, sens->ecc.size);
511+
break;
512+
case TPM_ALG_KEYEDHASH:
513+
TPM2_Packet_AppendU16(packet, sens->bits.size);
514+
TPM2_Packet_AppendBytes(packet, sens->bits.buffer, sens->bits.size);
515+
break;
516+
case TPM_ALG_SYMCIPHER:
517+
TPM2_Packet_AppendU16(packet, sens->sym.size);
518+
TPM2_Packet_AppendBytes(packet, sens->sym.buffer, sens->sym.size);
519+
break;
520+
}
505521

506522
TPM2_Packet_PlaceU16(packet, tmpSz);
507523
}
@@ -583,46 +599,48 @@ void TPM2_Packet_ParsePublicParms(TPM2_Packet* packet, TPMI_ALG_PUBLIC type,
583599
}
584600
}
585601

586-
void TPM2_Packet_AppendPublic(TPM2_Packet* packet, TPM2B_PUBLIC* pub)
602+
void TPM2_Packet_AppendPublicArea(TPM2_Packet* packet, TPMT_PUBLIC* publicArea)
587603
{
588-
int tmpSz = 0;
589-
590-
TPM2_Packet_MarkU16(packet, &tmpSz);
604+
TPM2_Packet_AppendU16(packet, publicArea->type);
605+
TPM2_Packet_AppendU16(packet, publicArea->nameAlg);
606+
TPM2_Packet_AppendU32(packet, publicArea->objectAttributes);
607+
TPM2_Packet_AppendU16(packet, publicArea->authPolicy.size);
608+
TPM2_Packet_AppendBytes(packet, publicArea->authPolicy.buffer,
609+
publicArea->authPolicy.size);
591610

592-
TPM2_Packet_AppendU16(packet, pub->publicArea.type);
593-
TPM2_Packet_AppendU16(packet, pub->publicArea.nameAlg);
594-
TPM2_Packet_AppendU32(packet, pub->publicArea.objectAttributes);
595-
TPM2_Packet_AppendU16(packet, pub->publicArea.authPolicy.size);
596-
TPM2_Packet_AppendBytes(packet, pub->publicArea.authPolicy.buffer,
597-
pub->publicArea.authPolicy.size);
611+
TPM2_Packet_AppendPublicParms(packet, publicArea->type,
612+
&publicArea->parameters);
598613

599-
TPM2_Packet_AppendPublicParms(packet, pub->publicArea.type,
600-
&pub->publicArea.parameters);
601-
602-
switch (pub->publicArea.type) {
614+
switch (publicArea->type) {
603615
case TPM_ALG_KEYEDHASH:
604-
TPM2_Packet_AppendU16(packet, pub->publicArea.unique.keyedHash.size);
605-
TPM2_Packet_AppendBytes(packet, pub->publicArea.unique.keyedHash.buffer,
606-
pub->publicArea.unique.keyedHash.size);
616+
TPM2_Packet_AppendU16(packet, publicArea->unique.keyedHash.size);
617+
TPM2_Packet_AppendBytes(packet, publicArea->unique.keyedHash.buffer,
618+
publicArea->unique.keyedHash.size);
607619
break;
608620
case TPM_ALG_SYMCIPHER:
609-
TPM2_Packet_AppendU16(packet, pub->publicArea.unique.sym.size);
610-
TPM2_Packet_AppendBytes(packet, pub->publicArea.unique.sym.buffer,
611-
pub->publicArea.unique.sym.size);
621+
TPM2_Packet_AppendU16(packet, publicArea->unique.sym.size);
622+
TPM2_Packet_AppendBytes(packet, publicArea->unique.sym.buffer,
623+
publicArea->unique.sym.size);
612624
break;
613625
case TPM_ALG_RSA:
614-
TPM2_Packet_AppendU16(packet, pub->publicArea.unique.rsa.size);
615-
TPM2_Packet_AppendBytes(packet, pub->publicArea.unique.rsa.buffer,
616-
pub->publicArea.unique.rsa.size);
626+
TPM2_Packet_AppendU16(packet, publicArea->unique.rsa.size);
627+
TPM2_Packet_AppendBytes(packet, publicArea->unique.rsa.buffer,
628+
publicArea->unique.rsa.size);
617629
break;
618630
case TPM_ALG_ECC:
619-
TPM2_Packet_AppendEccPoint(packet, &pub->publicArea.unique.ecc);
631+
TPM2_Packet_AppendEccPoint(packet, &publicArea->unique.ecc);
620632
break;
621633
default:
622634
/* TPMS_DERIVE derive; ? */
623635
break;
624636
}
637+
}
638+
void TPM2_Packet_AppendPublic(TPM2_Packet* packet, TPM2B_PUBLIC* pub)
639+
{
640+
int tmpSz = 0;
625641

642+
TPM2_Packet_MarkU16(packet, &tmpSz);
643+
TPM2_Packet_AppendPublicArea(packet, &pub->publicArea);
626644
pub->size = TPM2_Packet_PlaceU16(packet, tmpSz);
627645
}
628646
void TPM2_Packet_ParsePublic(TPM2_Packet* packet, TPM2B_PUBLIC* pub)

0 commit comments

Comments
 (0)