Add RSA key import methods to handle PEM and DER encoding directly (#252)

pull/256/head
John Bland 2023-01-27 17:17:19 -05:00 committed by GitHub
parent b4e439a595
commit 3a1ece8da1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 236 additions and 15 deletions

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCePbYR1SIZAL/2
8FYbgpxynENgvHACM9LczZnsgVkZYxx3O9DTba2VTxhMN21i/aocJCzZB35qvz+R
ickyvWBqPDXauJEn9icPXgSknqxzw0ZATzL0wbq/Tk5T+oITFFCGJ8/baFoktOKu
iP5H50Dx6X2W1qNHiLkbGq7NbXHA8YG2wzK9kwikowSXQVB7pZ5bgjW2q73vIGSs
eW802f7I/30wbf4oR1vfk4OQursT9sl2CFLNt5bJSw6lFTm4BOgC7Q3bpHPzC/YK
uFYWKGeQL9GCsEZVWHCM6vzek6SNwQ0eoQ0i9IuF0os/0nJDwdXEZX9OoBhFT717
svlxDXpFAgMBAAECggEABYIV6Jx/5ZloVTbr9GSxP+8PDFq61mTJ6fwxJ7Gf8ZmI
1+Cp5fYrJOeeK6cBRIEabwTWV86iOKKEGrOOYJkFdmU2pbCngtnXZbpK1JUeYSAy
vZHULv9gWgDmipdNeE8Md4MCwfspqh3uxw8HNOcIlHMhd0Ls55RLhzVAUO/GliXz
5HIDhohyQAUvPvkwz1yrPNn5BQwMlJBARc2OKSKf+pJrlFw1KJWR9TKzGvRzMbI4
gwrq9BZ5LCX5y6C7BpuzXdySHXofwihPNmi1KU/88cWhas2E0Xz+p+N/ifmkquTN
3EqzqKBW+xobryM6X9JfQ6has211eUaZKNuU2/idKQKBgQC5rymu0UKHuAkr4uPS
NLGmaWb4p+kDNxbVyzS2ENjtoJ6JyEo/pZQrTG4S/kCWFgGsuztCbx+1Kgk0Pgwi
znaGvcfrjiP9XE1oVfMifA2JmH+drjASyjPqNfsf0BKQtlk0nZXwUO/C1FQ5vUU4
lpmpx4EhTnucQ9E7r0+uXnQHTQKBgQDaKh4bBV7dLBF4ZxwCdydMMSZkBgckBiH7
83BvyLW6I0GKXcFTa7KKLgTj41pXeWh6bmM9365+Cr8fxTZop28EfGRYFBMp08/g
wHpmS3NZ4moSgirJ+PhZsH+nBq89W75INR7BqV4SAc3n4lcwv9eBL9q0Q/YJZ1ph
NCKvz79y2QKBgFyDFPVwdQFBg/BFntRARLJwmUkR/1oGvG3QTHbZdfsOp25mR/fl
+yiHb+AupOciF7uDnUbALsAILYXF1C4TR6JiM5T8wJmev0JYcEaiH+yJ+isJehIi
hDMQqglzlYxcDZ3VVbrh2FLtjvklf7Nt9SlNqNx7ScLVVw2xjrWFgbGRAoGBAMjo
Wnsl0fu6Noh74/Z9RmpLJQCd8HuDTk6ZHCVFX91/1D6ZIo0xM+U+hfBbkfnWa5m8
CJaVZDrcqK+YTQfJkVo/N6VJL3Coh9qBRvbnat4OvQI4bzE6n3LxME1fwYeu8ifL
C3zq/R92G+n8rbDOKqbkq/KwV2bHkBrOCVeA6NzZAoGACztyZbS5jCuSlPqk/xoN
EzX9Cev/GipF5tZMeOcQlty+anPg3TC70O06yZ1SIJKLzOOyoPCUDNrM2M5TCaau
vT0vW1GeNAryc+q9aOmFT3AlZ93Tfst+90Q+NJecEEhkO43tU5S1ZK2iVf9XAOV6
ovHegJU35IUeaoyg23HjFWU=
-----END PRIVATE KEY-----

View File

@ -7,4 +7,5 @@ EXTRA_DIST += \
certs/ca-rsa.cnf \
certs/ca-ecc.cnf \
certs/wolf-ca-ecc-cert.pem \
certs/wolf-ca-rsa-cert.pem
certs/wolf-ca-rsa-cert.pem \
certs/example-rsa-key.pem

View File

@ -40,14 +40,16 @@
static void usage(void)
{
printf("Expected usage:\n");
printf("./examples/keygen/keyimport [keyblob.bin] [-ecc/-rsa] [-aes/xor]\n");
printf("./examples/keygen/keyimport [keyblob.bin] [-ecc/-rsa] [-pem/-der] [-aes/xor]\n");
printf("* -ecc: Use RSA or ECC for keys\n");
printf("* -aes/xor: Use Parameter Encryption\n");
printf("* -pem=[keyfile]/der: Key encoding type, none for binary. Optional pem key file defaults to ./certs/example-rsa-key.pem\n");
}
int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[])
{
int rc;
int i;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY storage; /* SRK */
WOLFTPM2_KEYBLOB impKey;
@ -55,6 +57,14 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[])
TPM_ALG_ID paramEncAlg = TPM_ALG_NULL;
WOLFTPM2_SESSION tpmSession;
const char* outputFile = "keyblob.bin";
byte derEncode = 0;
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
byte pemEncode = 0;
FILE* pemFile = NULL;
const char* pemName = "./certs/example-rsa-key.pem";
char pemBuf[WOLFTPM2_MAX_BUFFER];
#endif
if (argc >= 2) {
if (XSTRCMP(argv[1], "-?") == 0 ||
@ -67,20 +77,41 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[])
if (argv[1][0] != '-')
outputFile = argv[1];
}
while (argc > 1) {
if (XSTRCMP(argv[argc-1], "-ecc") == 0) {
/* i = 1 to skip binary */
for (i = 1; i < argc; i++) {
if (XSTRCMP(argv[i], "-ecc") == 0) {
alg = TPM_ALG_ECC;
}
else if (XSTRCMP(argv[argc-1], "-aes") == 0) {
else if (XSTRCMP(argv[i], "-aes") == 0) {
paramEncAlg = TPM_ALG_CFB;
}
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
else if (XSTRCMP(argv[i], "-xor") == 0) {
paramEncAlg = TPM_ALG_XOR;
}
else {
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
else if (XSTRCMP(argv[i], "-der") == 0) {
derEncode = 1;
}
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
else if (XSTRCMP(argv[i], "-pem") == 0) {
pemEncode = 1;
printf("Warning: No pem file specified, using default: %s\n", pemName);
}
else if (XSTRNCMP(argv[i], "-pem=", XSTRLEN("-pem=")) == 0) {
pemEncode = 1;
if (XSTRLEN(argv[i] + XSTRLEN("-pem=")) == 0) {
printf("Warning: No pem file specified, using default: %s\n", pemName);
}
else {
pemName = (const char*)(argv[i] + XSTRLEN("-pem="));
printf("Warning: No pem file specified, using default: %s\n", pemName);
}
}
#endif
/* we already got outfile */
else if (i == 1 && argv[1][0] != '-') {
printf("Warning: Unrecognized option: %s\n", argv[i]);
}
argc--;
}
XMEMSET(&storage, 0, sizeof(storage));
@ -91,6 +122,11 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[])
printf("\tKey Blob: %s\n", outputFile);
printf("\tAlgorithm: %s\n", TPM2_GetAlgName(alg));
printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg));
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
if (pemEncode) {
printf("\tUse Pem Keyfile: %s\n", pemName);
}
#endif
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
if (rc != TPM_RC_SUCCESS) {
@ -121,12 +157,37 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[])
XMEMCPY(impKey.handle.auth.buffer, gKeyAuth, impKey.handle.auth.size);
if (alg == TPM_ALG_RSA) {
/* Import raw RSA private key into TPM */
rc = wolfTPM2_ImportRsaPrivateKey(&dev, &storage, &impKey,
kRsaKeyPubModulus, (word32)sizeof(kRsaKeyPubModulus),
kRsaKeyPubExponent,
kRsaKeyPrivQ, (word32)sizeof(kRsaKeyPrivQ),
TPM_ALG_NULL, TPM_ALG_NULL);
if (derEncode == 1) {
rc = wolfTPM2_RsaPrivateKeyImportDer(&dev, &storage, &impKey,
kRsaKeyPrivDer, sizeof(kRsaKeyPrivDer), TPM_ALG_NULL,
TPM_ALG_NULL);
}
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
else if (pemEncode == 1) {
pemFile = XFOPEN(pemName, "r");
if (pemFile == NULL)
printf("Failed to read pem file %s\n", pemName);
if (rc == 0)
rc = (int)XFREAD(pemBuf, 1, sizeof(pemBuf), pemFile);
if (rc > 0) {
rc = wolfTPM2_RsaPrivateKeyImportPem(&dev, &storage, &impKey,
pemBuf, rc, NULL, TPM_ALG_NULL, TPM_ALG_NULL);
}
XFCLOSE(pemFile);
}
#endif
else {
/* Import raw RSA private key into TPM */
rc = wolfTPM2_ImportRsaPrivateKey(&dev, &storage, &impKey,
kRsaKeyPubModulus, (word32)sizeof(kRsaKeyPubModulus),
kRsaKeyPubExponent,
kRsaKeyPrivQ, (word32)sizeof(kRsaKeyPrivQ),
TPM_ALG_NULL, TPM_ALG_NULL);
}
}
else if (alg == TPM_ALG_ECC) {
/* Import raw ECC private key into TPM */

View File

@ -1903,6 +1903,7 @@ int wolfTPM2_LoadRsaPrivateKey_ex(WOLFTPM2_DEV* dev,
return rc;
}
int wolfTPM2_LoadRsaPrivateKey(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* parentKey,
WOLFTPM2_KEY* key, const byte* rsaPub, word32 rsaPubSz, word32 exponent,
const byte* rsaPriv, word32 rsaPrivSz)
@ -2059,6 +2060,94 @@ int wolfTPM2_ReadPublicKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
#ifndef WOLFTPM2_NO_WOLFCRYPT
#ifndef NO_RSA
int wolfTPM2_RsaPrivateKeyImportDer(WOLFTPM2_DEV* dev,
const WOLFTPM2_KEY* parentKey, WOLFTPM2_KEYBLOB* keyBlob, const byte* input,
word32 inSz, TPMI_ALG_RSA_SCHEME scheme, TPMI_ALG_HASH hashAlg)
{
int rc = 0;
int initRc = -1;
RsaKey key[1];
word32 idx = 0;
word32 e;
byte n[RSA_MAX_SIZE / 8];
byte d[RSA_MAX_SIZE / 8];
byte p[RSA_MAX_SIZE / 8];
byte q[RSA_MAX_SIZE / 8];
word32 eSz = (word32)sizeof(e);
word32 nSz = (word32)sizeof(n);
word32 dSz = (word32)sizeof(d);
word32 pSz = (word32)sizeof(p);
word32 qSz = (word32)sizeof(q);
if (dev == NULL || parentKey == NULL || keyBlob == NULL || input == NULL ||
inSz == 0) {
rc = BAD_FUNC_ARG;
}
if (rc == 0)
rc = initRc = wc_InitRsaKey(key, NULL);
if (rc == 0)
rc = wc_RsaPrivateKeyDecode(input, &idx, key, inSz);
if (rc == 0) {
rc = wc_RsaExportKey(key, (byte*)&e, &eSz, n, &nSz, d, &dSz, p, &pSz, q,
&qSz);
}
if (rc == 0) {
rc = wolfTPM2_ImportRsaPrivateKey(dev, parentKey, keyBlob, n, nSz, e, q,
qSz, scheme, hashAlg);
}
if (initRc == 0)
wc_FreeRsaKey(key);
return rc;
}
#ifndef WOLFTPM2_NO_HEAP
int wolfTPM2_RsaPrivateKeyImportPem(WOLFTPM2_DEV* dev,
const WOLFTPM2_KEY* parentKey, WOLFTPM2_KEYBLOB* keyBlob,
const char* input, word32 inSz, char* pass,
TPMI_ALG_RSA_SCHEME scheme, TPMI_ALG_HASH hashAlg)
{
int rc = 0;
byte* derBuf;
word32 derSz;
if (dev == NULL || parentKey == NULL || keyBlob == NULL || input == NULL ||
inSz == 0) {
return BAD_FUNC_ARG;
}
/* der size is base 64 decode length */
derSz = inSz * 3 / 4 + 1;
derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (derBuf == NULL)
return MEMORY_E;
rc = wc_KeyPemToDer((byte*)input, inSz, derBuf, derSz, pass);
/* returns the number of bytes */
if (rc > 0) {
rc = wolfTPM2_RsaPrivateKeyImportDer(dev, parentKey, keyBlob, derBuf,
(word32)rc, scheme, hashAlg);
}
/* shouldn't be possible to have a 0 length der, check anyways */
else if (rc == 0) {
rc = BAD_FUNC_ARG;
}
XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return rc;
}
#endif /* WOLFTPM2_NO_HEAP */
int wolfTPM2_RsaKey_TpmToWolf(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* tpmKey,
RsaKey* wolfKey)
{

View File

@ -1019,6 +1019,48 @@ WOLFTPM_API int wolfTPM2_SensitiveToPrivate(TPM2B_SENSITIVE* sens, TPM2B_PRIVATE
#ifndef WOLFTPM2_NO_WOLFCRYPT
#ifndef NO_RSA
/*!
\ingroup wolfTPM2_Wrappers
\brief Helper function to import Der rsa key directly
\return TPM_RC_SUCCESS: successful
\return TPM_RC_FAILURE: generic failure (check TPM IO and TPM return code)
\return BAD_FUNC_ARG: check the provided arguments
\param dev pointer to a TPM2_DEV struct
\param parentKey pointer to a WOLFTPM2_KEY struct, pointing to a Primary Key or TPM Hierarchy
\param keyBlob pointer to a struct of WOLFTPM2_KEY type, to import the rsa key to
\param input buffer holding the rsa der
\param inSz length of the input der buffer
\param scheme value of TPMI_ALG_RSA_SCHEME type, specifying the RSA scheme
\param hashAlg value of TPMI_ALG_HASH type, specifying the TPM hashing algorithm
*/
WOLFTPM_API int wolfTPM2_RsaPrivateKeyImportDer(WOLFTPM2_DEV* dev,
const WOLFTPM2_KEY* parentKey, WOLFTPM2_KEYBLOB* keyBlob, const byte* input,
word32 inSz, TPMI_ALG_RSA_SCHEME scheme, TPMI_ALG_HASH hashAlg);
/*!
\ingroup wolfTPM2_Wrappers
\brief Helper function to import Der rsa key directly
\return TPM_RC_SUCCESS: successful
\return TPM_RC_FAILURE: generic failure (check TPM IO and TPM return code)
\return BAD_FUNC_ARG: check the provided arguments
\param dev pointer to a TPM2_DEV struct
\param parentKey pointer to a WOLFTPM2_KEY struct, pointing to a Primary Key or TPM Hierarchy
\param keyBlob pointer to a struct of WOLFTPM2_KEY type, to import the rsa key to
\param input buffer holding the rsa pem
\param inSz length of the input pem buffer
\param pass optional password of the key
\param scheme value of TPMI_ALG_RSA_SCHEME type, specifying the RSA scheme
\param hashAlg value of TPMI_ALG_HASH type, specifying the TPM hashing algorithm
*/
WOLFTPM_API int wolfTPM2_RsaPrivateKeyImportPem(WOLFTPM2_DEV* dev,
const WOLFTPM2_KEY* parentKey, WOLFTPM2_KEYBLOB* keyBlob,
const char* input, word32 inSz, char* pass,
TPMI_ALG_RSA_SCHEME scheme, TPMI_ALG_HASH hashAlg);
/*!
\ingroup wolfTPM2_Wrappers
\brief Extract a RSA TPM key and convert it to a wolfcrypt key