Skip to content

Commit d07cffa

Browse files
committed
Support import export TPM private keys
Signed-off-by: Silas Steinhauser <silas.steinhauser@gapfruit.com>
1 parent f4b9ade commit d07cffa

6 files changed

Lines changed: 143 additions & 7 deletions

Makefile.am

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ TESTS_SHELL = test/list.sh \
103103
test/rsa_createak_sign_handle.sh \
104104
test/rsa_create_decrypt_pkcs1.sh \
105105
test/rsa_create_decrypt_oaep.sh \
106+
test/rsa_export_import_private_key.sh \
106107
test/rsa_genpkey_x509_cert.sh \
107108
test/rsa_genpkey_x509_cmp.sh \
108109
test/rsa_genpkey_x509_cms.sh \
@@ -111,8 +112,10 @@ TESTS_SHELL = test/list.sh \
111112
test/rsa_createak_x509_csr.sh \
112113
test/rsapss_genpkey_sign_rawin.sh \
113114
test/rsapss_createak_tls_server.sh \
115+
test/rsapss_export_import_private_key.sh \
114116
test/rsa_pki/rsa_pki.sh \
115117
test/ec_genpkey_check.sh \
118+
test/ec_export_import_private_key.sh \
116119
test/ec_genpkey_parameters.sh \
117120
test/ec_genpkey_x509_cms.sh \
118121
test/ecdsa_genpkey_sign_auth.sh \

src/tpm2-provider-pkey.c

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@ typedef struct {
1515
ASN1_INTEGER *parent;
1616
ASN1_OCTET_STRING *pubkey;
1717
ASN1_OCTET_STRING *privkey;
18+
ASN1_INTEGER *privkeyType;
19+
ASN1_INTEGER *privkeyHandle;
1820
} TSSPRIVKEY;
1921

2022
ASN1_SEQUENCE(TSSPRIVKEY) = {
2123
ASN1_SIMPLE(TSSPRIVKEY, type, ASN1_OBJECT),
2224
ASN1_EXP_OPT(TSSPRIVKEY, emptyAuth, ASN1_BOOLEAN, 0),
2325
ASN1_SIMPLE(TSSPRIVKEY, parent, ASN1_INTEGER),
2426
ASN1_SIMPLE(TSSPRIVKEY, pubkey, ASN1_OCTET_STRING),
25-
ASN1_SIMPLE(TSSPRIVKEY, privkey, ASN1_OCTET_STRING)
27+
ASN1_SIMPLE(TSSPRIVKEY, privkey, ASN1_OCTET_STRING),
28+
ASN1_EXP_OPT(TSSPRIVKEY, privkeyType, ASN1_INTEGER, 1),
29+
ASN1_EXP_OPT(TSSPRIVKEY, privkeyHandle, ASN1_INTEGER, 2),
2630
} ASN1_SEQUENCE_END(TSSPRIVKEY)
2731

2832
#define OID_loadableKey "2.23.133.10.1.3"
@@ -62,10 +66,33 @@ tpm2_keydata_write(const TPM2_KEYDATA *keydata, BIO *bout, TPM2_PKEY_FORMAT form
6266
if (!tpk)
6367
return 0;
6468

65-
if (Tss2_MU_TPM2B_PRIVATE_Marshal(&keydata->priv, &privbuf[0],
66-
sizeof(privbuf), &privbuf_len))
69+
if (tpk->privkeyType == NULL) {
70+
tpk->privkeyType = ASN1_INTEGER_new();
71+
if (tpk->privkeyType == NULL)
72+
goto error;
73+
};
74+
if (!ASN1_INTEGER_set_uint64(tpk->privkeyType, keydata->privatetype))
6775
goto error;
6876

77+
switch (keydata->privatetype) {
78+
case KEY_TYPE_HANDLE:
79+
if (tpk->privkeyHandle == NULL) {
80+
tpk->privkeyHandle = ASN1_INTEGER_new();
81+
if (tpk->privkeyHandle == NULL)
82+
goto error;
83+
}
84+
if (!ASN1_INTEGER_set_uint64(tpk->privkeyHandle, keydata->handle))
85+
goto error;
86+
break;
87+
case KEY_TYPE_BLOB:
88+
if (Tss2_MU_TPM2B_PRIVATE_Marshal(&keydata->priv, &privbuf[0],
89+
sizeof(privbuf), &privbuf_len))
90+
goto error;
91+
break;
92+
default:
93+
goto error;
94+
}
95+
6996
if (Tss2_MU_TPM2B_PUBLIC_Marshal(&keydata->pub, &pubbuf[0],
7097
sizeof(pubbuf), &pubbuf_len))
7198
goto error;
@@ -131,7 +158,6 @@ tpm2_keydata_read(BIO *bin, TPM2_KEYDATA *keydata, TPM2_PKEY_FORMAT format)
131158
if (tpk == NULL)
132159
return 0;
133160

134-
keydata->privatetype = KEY_TYPE_BLOB;
135161
keydata->emptyAuth = (tpk->emptyAuth != V_ASN1_UNDEF && tpk->emptyAuth);
136162

137163
// the ASN1_INTEGER_get on a 32-bit machine will fail for numbers of UINT32_MAX
@@ -149,10 +175,30 @@ tpm2_keydata_read(BIO *bin, TPM2_KEYDATA *keydata, TPM2_PKEY_FORMAT format)
149175
strcmp(type_oid, OID_loadableKey))
150176
goto error;
151177

152-
if (Tss2_MU_TPM2B_PRIVATE_Unmarshal(tpk->privkey->data,
153-
tpk->privkey->length, NULL,
154-
&keydata->priv))
178+
uint64_t privkeyType;
179+
if (tpk->privkeyType != NULL) {
180+
if(!ASN1_INTEGER_get_uint64(&privkeyType, tpk->privkeyType))
181+
goto error;
182+
} else {
183+
privkeyType = KEY_TYPE_BLOB;
184+
}
185+
keydata->privatetype = privkeyType;
186+
187+
switch (keydata->privatetype) {
188+
case KEY_TYPE_HANDLE:
189+
if (tpk->privkeyType != NULL
190+
&& !ASN1_INTEGER_get_uint64((uint64_t *)&keydata->handle, tpk->privkeyHandle))
191+
goto error;
192+
break;
193+
case KEY_TYPE_BLOB:
194+
if (Tss2_MU_TPM2B_PRIVATE_Unmarshal(tpk->privkey->data,
195+
tpk->privkey->length, NULL,
196+
&keydata->priv))
197+
goto error;
198+
break;
199+
default:
155200
goto error;
201+
}
156202

157203
if (Tss2_MU_TPM2B_PUBLIC_Unmarshal(tpk->pubkey->data,
158204
tpk->pubkey->length, NULL,

src/tpm2-provider.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,16 @@ static const OSSL_ALGORITHM tpm2_encoders[] = {
207207
/* private key */
208208
{ "RSA", "provider=tpm2,output=der,structure=PrivateKeyInfo", tpm2_tss_encoder_PrivateKeyInfo_der_functions },
209209
{ "RSA", "provider=tpm2,output=pem,structure=PrivateKeyInfo", tpm2_tss_encoder_PrivateKeyInfo_pem_functions },
210+
{ "RSA", "provider=tpm2,output=der,structure=type-specific", tpm2_tss_encoder_PrivateKeyInfo_der_functions },
211+
{ "RSA", "provider=tpm2,output=pem,structure=type-specific", tpm2_tss_encoder_PrivateKeyInfo_pem_functions },
210212
{ "RSA-PSS", "provider=tpm2,output=der,structure=PrivateKeyInfo", tpm2_tss_encoder_PrivateKeyInfo_der_functions },
211213
{ "RSA-PSS", "provider=tpm2,output=pem,structure=PrivateKeyInfo", tpm2_tss_encoder_PrivateKeyInfo_pem_functions },
214+
{ "RSA-PSS", "provider=tpm2,output=der,structure=type-specific", tpm2_tss_encoder_PrivateKeyInfo_der_functions },
215+
{ "RSA-PSS", "provider=tpm2,output=pem,structure=type-specific", tpm2_tss_encoder_PrivateKeyInfo_pem_functions },
212216
{ "EC", "provider=tpm2,output=der,structure=PrivateKeyInfo", tpm2_tss_encoder_PrivateKeyInfo_der_functions },
213217
{ "EC", "provider=tpm2,output=pem,structure=PrivateKeyInfo", tpm2_tss_encoder_PrivateKeyInfo_pem_functions },
218+
{ "EC", "provider=tpm2,output=der,structure=type-specific", tpm2_tss_encoder_PrivateKeyInfo_der_functions },
219+
{ "EC", "provider=tpm2,output=pem,structure=type-specific", tpm2_tss_encoder_PrivateKeyInfo_pem_functions },
214220
/* public key */
215221
{ "RSA", "provider=tpm2,output=der,structure=pkcs1", tpm2_rsa_encoder_pkcs1_der_functions },
216222
{ "RSA", "provider=tpm2,output=pem,structure=pkcs1", tpm2_rsa_encoder_pkcs1_pem_functions },
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: BSD-3-Clause
3+
set -eufx
4+
5+
EXPECTED=expected_params.pem
6+
COMPUTED=params.pem
7+
8+
cat > ${EXPECTED} <<EOF
9+
-----BEGIN EC PARAMETERS-----
10+
BggqhkjOPQMBBw==
11+
-----END EC PARAMETERS-----
12+
EOF
13+
14+
# create primary
15+
tpm2_createprimary -G ecc -g sha256 -c primary.ctx
16+
17+
# make the primary persistent
18+
HANDLE=$(tpm2_evictcontrol -c primary.ctx | cut -d ' ' -f 2 | head -n 1)
19+
20+
# Export the private key through the specified handle
21+
openssl ec -provider tpm2 -provider default -in "handle:${HANDLE}" -out primary_key.pem
22+
23+
# Import the private key and export the parameters
24+
openssl ec -provider tpm2 -provider default -in primary_key.pem -param_out -out ${COMPUTED}
25+
26+
# Simple test, check if the parameter is equals
27+
if cmp -s "${EXPECTED}" "${COMPUTED}" ;
28+
then
29+
echo "Expected params are equals!"
30+
else
31+
echo "Expected params differ. Expected:"
32+
cat ${EXPECTED}
33+
echo "Got: "
34+
cat ${COMPUTED}
35+
exit 1
36+
fi
37+
38+
# release the persistent key
39+
tpm2_evictcontrol -c ${HANDLE}
40+
41+
rm primary.ctx primary_key.pem ${EXPECTED} ${COMPUTED}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: BSD-3-Clause
3+
set -eufx
4+
5+
# create primary
6+
tpm2_createprimary -G rsa -g sha256 -c primary.ctx
7+
8+
# make the primary persistent
9+
HANDLE=$(tpm2_evictcontrol -c primary.ctx | cut -d ' ' -f 2 | head -n 1)
10+
11+
# Export the private key through the specified handle
12+
openssl rsa -provider tpm2 -provider default -in "handle:${HANDLE}" -out primary_key.pem
13+
14+
# Import the private key and print the modulus
15+
openssl rsa -provider tpm2 -provider default -in primary_key.pem -modulus -noout
16+
17+
# release the persistent key
18+
tpm2_evictcontrol -c ${HANDLE}
19+
20+
rm primary.ctx primary_key.pem
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: BSD-3-Clause
3+
set -eufx
4+
5+
# create primary
6+
tpm2_createprimary -G rsa2048:rsapss-sha256:null -c primary.ctx -a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|sign|restricted'
7+
8+
# make the primary persistent
9+
HANDLE=$(tpm2_evictcontrol -c primary.ctx | cut -d ' ' -f 2 | head -n 1)
10+
11+
# Export the private key through the specified handle
12+
openssl rsa -provider tpm2 -provider default -in "handle:${HANDLE}" -out primary_key.pem
13+
14+
# Import the private key and export
15+
openssl rsa -provider tpm2 -provider default -in primary_key.pem -modulus -noout
16+
17+
# release the persistent key
18+
tpm2_evictcontrol -c ${HANDLE}
19+
20+
rm primary.ctx primary_key.pem

0 commit comments

Comments
 (0)