diff --git a/certs/example-ecc256-key-pub.der b/certs/example-ecc256-key-pub.der new file mode 100644 index 0000000..91aa79b Binary files /dev/null and b/certs/example-ecc256-key-pub.der differ diff --git a/certs/example-ecc256-key-pub.pem b/certs/example-ecc256-key-pub.pem new file mode 100644 index 0000000..30363ef --- /dev/null +++ b/certs/example-ecc256-key-pub.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U +6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ihf/DPGNqREQI0huggWDMLgDSJ2A== +-----END PUBLIC KEY----- diff --git a/certs/example-ecc256-key.der b/certs/example-ecc256-key.der new file mode 100644 index 0000000..a88d141 Binary files /dev/null and b/certs/example-ecc256-key.der differ diff --git a/certs/example-ecc256-key.pem b/certs/example-ecc256-key.pem new file mode 100644 index 0000000..03e7a61 --- /dev/null +++ b/certs/example-ecc256-key.pem @@ -0,0 +1,9 @@ +ASN1 OID: prime256v1 +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIEW2aQJznGyFoThbcujox6zEA41TNQT6bCjcNI3hqAmMoAoGCCqGSM49 +AwEHoUQDQgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC6a9N0wKT +mjFbl5Ihf/DPGNqREQI0huggWDMLgDSJ2A== +-----END EC PRIVATE KEY----- diff --git a/certs/example-ecc384-key-pub.der b/certs/example-ecc384-key-pub.der new file mode 100644 index 0000000..d48e9ed Binary files /dev/null and b/certs/example-ecc384-key-pub.der differ diff --git a/certs/example-ecc384-key-pub.pem b/certs/example-ecc384-key-pub.pem new file mode 100644 index 0000000..c5a33a5 --- /dev/null +++ b/certs/example-ecc384-key-pub.pem @@ -0,0 +1,5 @@ +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE6s+TTywJuzkUD1Zkw0C03w5jruVxSwDM +BJf/4ek4lrtfkbJqzLU5X49wWfEB9lorAWxoC89VJa9tmEgKqHTJqRegDMP70yNo +/gQ8Y1CIO7lPfGc09zupc+cbw1FeIhjs +-----END PUBLIC KEY----- diff --git a/certs/example-ecc384-key.der b/certs/example-ecc384-key.der new file mode 100644 index 0000000..9dde676 Binary files /dev/null and b/certs/example-ecc384-key.der differ diff --git a/certs/example-ecc384-key.pem b/certs/example-ecc384-key.pem new file mode 100644 index 0000000..5d3d61d --- /dev/null +++ b/certs/example-ecc384-key.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCk5QboBhY+q4n4YEPA +YCXbunv+GTUIVWV24tzgAYtraN/Pb4ASznk36yuce8RoHHShZANiAATqz5NPLAm7 +ORQPVmTDQLTfDmOu5XFLAMwEl//h6TiWu1+RsmrMtTlfj3BZ8QH2WisBbGgLz1Ul +r22YSAqodMmpF6AMw/vTI2j+BDxjUIg7uU98ZzT3O6lz5xvDUV4iGOw= +-----END PRIVATE KEY----- diff --git a/certs/example-rsa-key-pub.der b/certs/example-rsa2048-key-pub.der similarity index 100% rename from certs/example-rsa-key-pub.der rename to certs/example-rsa2048-key-pub.der diff --git a/certs/example-rsa-key-pub.pem b/certs/example-rsa2048-key-pub.pem similarity index 100% rename from certs/example-rsa-key-pub.pem rename to certs/example-rsa2048-key-pub.pem diff --git a/certs/example-rsa-key.der b/certs/example-rsa2048-key.der similarity index 100% rename from certs/example-rsa-key.der rename to certs/example-rsa2048-key.der diff --git a/certs/example-rsa-key.pem b/certs/example-rsa2048-key.pem similarity index 100% rename from certs/example-rsa-key.pem rename to certs/example-rsa2048-key.pem diff --git a/certs/include.am b/certs/include.am index e8ce201..4157d46 100644 --- a/certs/include.am +++ b/certs/include.am @@ -3,12 +3,20 @@ # EXTRA_DIST += \ - certs/certreq.sh \ - certs/ca-rsa.cnf \ - certs/ca-ecc.cnf \ - certs/wolf-ca-ecc-cert.pem \ - certs/wolf-ca-rsa-cert.pem \ - certs/example-rsa-key.pem \ - certs/example-rsa-key.der \ - certs/example-rsa-key-pub.pem \ - certs/example-rsa-key-pub.der + certs/certreq.sh \ + certs/ca-rsa.cnf \ + certs/ca-ecc.cnf \ + certs/wolf-ca-ecc-cert.pem \ + certs/wolf-ca-rsa-cert.pem \ + certs/example-rsa2048-key.pem \ + certs/example-rsa2048-key.der \ + certs/example-rsa2048-key-pub.pem \ + certs/example-rsa2048-key-pub.der \ + certs/example-ecc256-key.pem \ + certs/example-ecc256-key.der \ + certs/example-ecc256-key-pub.pem \ + certs/example-ecc256-key-pub.der \ + certs/example-ecc384-key.pem \ + certs/example-ecc384-key.der \ + certs/example-ecc384-key-pub.pem \ + certs/example-ecc384-key-pub.der diff --git a/examples/keygen/keyimport.c b/examples/keygen/keyimport.c index 11a2fe7..f17e3c3 100644 --- a/examples/keygen/keyimport.c +++ b/examples/keygen/keyimport.c @@ -39,16 +39,29 @@ static void usage(void) { printf("Expected usage:\n"); - printf("./examples/keygen/keyimport [keyblob.bin] [-ecc/-rsa] [-pem/-der] [-aes/xor]\n"); - printf("* -ecc: Use RSA or ECC for keys\n"); + printf("./examples/keygen/keyimport [keyblob.bin] [-ecc/-rsa] [-pem/-der] [-aes/xor] [-password] [-public]\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"); + printf("* -rsa/-ecc: Use RSA or ECC key\n"); + printf("* -public: Input file is public key only\n"); + printf("* -password=[password]: Optional password for private key\n"); + printf("* -pem=[keyfile]: PEM (Base64 Encoded) key file\n"); + printf("* -der=[keyfile]: DER (ASN.1) binary key file\n"); + printf("Examples:\n"); + printf("\t./examples/keygen/keyimport -ecc\n"); + printf("\t./examples/keygen/keyimport -rsa\n"); + printf("\t./examples/keygen/keyimport -ecc -pem=./certs/example-ecc256-key.pem -aes\n"); + printf("\t./examples/keygen/keyimport -rsa -pem=./certs/example-rsa2048-key.pem -aes\n"); + printf("\t./examples/keygen/keyimport -ecc -der=./certs/example-ecc256-key.der -aes\n"); + printf("\t./examples/keygen/keyimport -rsa -der=./certs/example-rsa2048-key.der -aes\n"); + printf("\t./examples/keygen/keyimport -ecc -pem=../wolfssl/certs/ecc-keyPkcs8Enc.pem -password=yassl123 -aes\n"); + printf("\t./examples/keygen/keyimport -rsa -pem=../wolfssl/certs/server-keyPkcs8Enc.pem -password=yassl123 -aes\n"); + printf("\t./examples/keygen/keyimport -ecc -der=./certs/example-ecc256-key-pub.der -public\n"); + printf("\t./examples/keygen/keyimport -rsa -der=./certs/example-rsa2048-key-pub.der -public\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; @@ -56,16 +69,13 @@ 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; - const char* pemName = "./certs/example-rsa-key.pem"; - #if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_RSA) - FILE* pemFile = NULL; - char pemBuf[WOLFTPM2_MAX_BUFFER]; - #endif -#endif + const char* impFile = NULL; + int encType = ENCODING_TYPE_ASN1; + const char* password = NULL; + TPMA_OBJECT attributes; + byte* buf = NULL; + size_t bufSz = 0; + int isPublicKey = 0; if (argc >= 2) { if (XSTRCMP(argv[1], "-?") == 0 || @@ -75,44 +85,53 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[]) return 0; } - if (argv[1][0] != '-') + if (argv[1][0] != '-') { outputFile = argv[1]; + } } - /* i = 1 to skip binary */ - for (i = 1; i < argc; i++) { - if (XSTRCMP(argv[i], "-ecc") == 0) { + while (argc > 1) { + if (XSTRCMP(argv[argc-1], "-ecc") == 0) { alg = TPM_ALG_ECC; } - else if (XSTRCMP(argv[i], "-aes") == 0) { + else if (XSTRCMP(argv[argc-1], "-aes") == 0) { paramEncAlg = TPM_ALG_CFB; } - else if (XSTRCMP(argv[i], "-xor") == 0) { + else if (XSTRCMP(argv[argc-1], "-xor") == 0) { paramEncAlg = TPM_ALG_XOR; } - else if (XSTRCMP(argv[i], "-der") == 0) { - derEncode = 1; + else if (XSTRCMP(argv[argc-1], "-public") == 0) { + isPublicKey = 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[argc-1], "-password=", XSTRLEN("-password=")) == 0) { + password = (const char*)(argv[argc-1] + XSTRLEN("-password=")); + } + else if (XSTRCMP(argv[argc-1], "-der") == 0) { + encType = ENCODING_TYPE_ASN1; + } + else if (XSTRNCMP(argv[argc-1], "-der=", XSTRLEN("-der=")) == 0) { + encType = ENCODING_TYPE_ASN1; + impFile = (const char*)(argv[argc-1] + XSTRLEN("-der=")); + } + else if (XSTRCMP(argv[argc-1], "-pem") == 0) { + encType = ENCODING_TYPE_PEM; + } + else if (XSTRNCMP(argv[argc-1], "-pem=", XSTRLEN("-pem=")) == 0) { + encType = ENCODING_TYPE_PEM; + impFile = (const char*)(argv[argc-1] + XSTRLEN("-pem=")); + } + else { + printf("Warning: Unrecognized option: %s\n", argv[argc-1]); } - 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--; + } + + /* setup default import file */ + if (impFile == NULL) { + if (alg == TPM_ALG_RSA) + impFile = "./certs/example-rsa2048-key.der"; + else if (alg == TPM_ALG_ECC) + impFile = "./certs/example-ecc256-key.der"; } XMEMSET(&storage, 0, sizeof(storage)); @@ -123,11 +142,7 @@ 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 + printf("\tpassword: %s\n", password); rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); if (rc != TPM_RC_SUCCESS) { @@ -136,7 +151,7 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[]) } /* get SRK */ - rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA); + rc = getPrimaryStoragekey(&dev, &storage, alg); if (rc != 0) goto exit; if (paramEncAlg != TPM_ALG_NULL) { @@ -154,51 +169,61 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[]) } /* setup an auth value */ - impKey.handle.auth.size = (int)sizeof(gKeyAuth)-1; - XMEMCPY(impKey.handle.auth.buffer, gKeyAuth, impKey.handle.auth.size); + if (password != NULL) { + impKey.handle.auth.size = (int)XSTRLEN(password); + XMEMCPY(impKey.handle.auth.buffer, password, impKey.handle.auth.size); + } - if (alg == TPM_ALG_RSA) { - if (derEncode == 1) { - #if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_RSA) && \ - !defined(NO_ASN) - rc = wolfTPM2_RsaPrivateKeyImportDer(&dev, &storage, &impKey, - kRsaKeyPrivDer, sizeof(kRsaKeyPrivDer), TPM_ALG_NULL, - TPM_ALG_NULL); - #else - rc = NOT_COMPILED_IN; - #endif - } - #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) - else if (pemEncode == 1) { - #if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_RSA) - pemFile = XFOPEN(pemName, "r"); - if (pemFile != XBADFILE) { - 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); + attributes = (TPMA_OBJECT_restricted | + TPMA_OBJECT_sensitiveDataOrigin | + TPMA_OBJECT_decrypt | + TPMA_OBJECT_userWithAuth | + TPMA_OBJECT_noDA); + +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) + if (impFile != NULL) { + printf("Loading %s%s key file: %s\n", + encType == ENCODING_TYPE_PEM ? "PEM" : "DER", + isPublicKey ? " public" : "", + impFile); + rc = loadFile(impFile, &buf, &bufSz); + if (rc == 0) { + if (isPublicKey) { + rc = wolfTPM2_ImportPublicKeyBuffer(&dev, + alg, + (WOLFTPM2_KEY*)&impKey, + encType, + (const char*)buf, (word32)bufSz, + attributes + ); } - else { - printf("Failed to read pem file %s\n", pemName); - rc = BUFFER_E; + else { /* private key */ + rc = wolfTPM2_ImportPrivateKeyBuffer(&dev, &storage, + alg, + &impKey, + encType, + (const char*)buf, (word32)bufSz, + password, + attributes, NULL, 0 + ); } - #else - rc = NOT_COMPILED_IN; - #endif - } - #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 +#endif + if (alg == TPM_ALG_RSA) { + printf("Loading example RSA key (see kRsaKeyPrivQ)\n"); + + /* 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) { + printf("Loading example ECC key (see kEccKeyPrivD)\n"); + /* Import raw ECC private key into TPM */ rc = wolfTPM2_ImportEccPrivateKey(&dev, &storage, &impKey, TPM_ECC_NIST_P256, @@ -212,7 +237,7 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[]) TPM2_GetAlgName(alg), impKey.pub.size, impKey.priv.size); /* Save key as encrypted blob to the disk */ -#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) rc = writeKeyBlob(outputFile, &impKey); #else printf("Key Public Blob %d\n", impKey.pub.size); diff --git a/examples/keygen/keyload.c b/examples/keygen/keyload.c index 6ccb19e..8c667e3 100644 --- a/examples/keygen/keyload.c +++ b/examples/keygen/keyload.c @@ -79,12 +79,12 @@ int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[]) if (argv[1][0] != '-') { inputFile = argv[1]; } - if (XSTRCMP(argv[1], "-eh") == 0) { - endorseKey = 1; - } } while (argc > 1) { - if (XSTRCMP(argv[argc-1], "-aes") == 0) { + if (XSTRCMP(argv[argc-1], "-eh") == 0) { + endorseKey = 1; + } + else if (XSTRCMP(argv[argc-1], "-aes") == 0) { paramEncAlg = TPM_ALG_CFB; } else if (XSTRCMP(argv[argc-1], "-xor") == 0) { @@ -160,9 +160,14 @@ int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[]) goto exit; #endif - rc = wolfTPM2_LoadKey(&dev, &newKey, &primary->handle); + if (newKey.priv.size == 0) { + rc = wolfTPM2_LoadPublicKey(&dev, (WOLFTPM2_KEY*)&newKey, &newKey.pub); + } + else { + rc = wolfTPM2_LoadKey(&dev, &newKey, &primary->handle); + } if (rc != TPM_RC_SUCCESS) { - printf("wolfTPM2_LoadKey failed\n"); + printf("Load Key failed!\n"); goto exit; } printf("Loaded key to 0x%x\n", diff --git a/examples/tpm_test_keys.c b/examples/tpm_test_keys.c index d8ba762..d544b54 100644 --- a/examples/tpm_test_keys.c +++ b/examples/tpm_test_keys.c @@ -165,6 +165,9 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key) } rc = 0; /* success */ } + if (key->priv.size == 0) { + printf("No private key loaded\n"); + } /* sanity check the sizes */ if (pubAreaSize != (key->pub.size + (int)sizeof(key->pub.size)) || @@ -391,4 +394,57 @@ int getECCkey(WOLFTPM2_DEV* pDev, return rc; } +int loadFile(const char* fname, byte** buf, size_t* bufLen) +{ + int ret; +#if !defined(WOLFTPM2_NO_WOLFCRYPT) && !defined(NO_FILESYSTEM) && \ + !defined(WOLFTPM2_NO_HEAP) + long int fileSz; + XFILE lFile; + + if (fname == NULL || buf == NULL || bufLen == NULL) + return BAD_FUNC_ARG; + + /* set defaults */ + *buf = NULL; + *bufLen = 0; + + /* open file (read-only binary) */ + lFile = XFOPEN(fname, "rb"); + if (!lFile) { + fprintf(stderr, "Error loading %s\n", fname); + return BUFFER_E; + } + + XFSEEK(lFile, 0, XSEEK_END); + fileSz = (int)ftell(lFile); + XFSEEK(lFile, 0, XSEEK_SET); + if (fileSz > 0) { + *bufLen = (size_t)fileSz; + *buf = (byte*)XMALLOC(*bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (*buf == NULL) { + ret = MEMORY_E; + fprintf(stderr, + "Error allocating %lu bytes\n", (unsigned long)*bufLen); + } + else { + size_t readLen = fread(*buf, *bufLen, 1, lFile); + + /* check response code */ + ret = (readLen > 0) ? 0 : -1; + } + } + else { + ret = BUFFER_E; + } + fclose(lFile); +#else + (void)fname; + (void)buf; + (void)bufLen; + ret = NOT_COMPILED_IN; +#endif /* !WOLFTPM2_NO_WOLFCRYPT && !NO_FILESYSTEM && !WOLFTPM2_NO_HEAP */ + return ret; +} + #endif /* !WOLFTPM2_NO_WRAPPER */ diff --git a/examples/tpm_test_keys.h b/examples/tpm_test_keys.h index 8d2813b..03b8e27 100644 --- a/examples/tpm_test_keys.h +++ b/examples/tpm_test_keys.h @@ -66,6 +66,8 @@ WOLFTPM_LOCAL int getECCkey(WOLFTPM2_DEV* pDev, const byte* auth, int authSz, TPMT_PUBLIC* publicTemplate); +WOLFTPM_LOCAL int loadFile(const char* fname, byte** buf, size_t* bufLen); + #endif /* !WOLFTPM2_NO_WRAPPER */ #endif /* _TPM_TEST_KEYS_H_ */ diff --git a/src/tpm2_wrap.c b/src/tpm2_wrap.c index 18bc6ba..aabba9b 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -2470,7 +2470,7 @@ int wolfTPM2_ReadPublicKey(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key, #ifndef NO_ASN #ifndef NO_RSA -static int DecodeRsaPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, +static int DecodeRsaDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, const byte* input, word32 inSz, TPMA_OBJECT attributes) { int rc = 0; @@ -2486,6 +2486,7 @@ static int DecodeRsaPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, word32 dSz = (word32)sizeof(d); word32 pSz = (word32)sizeof(p); word32 qSz = (word32)sizeof(q); + int isPrivateKey = 0; XMEMSET(n, 0, sizeof(n)); XMEMSET(d, 0, sizeof(d)); @@ -2494,15 +2495,26 @@ static int DecodeRsaPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, rc = wc_InitRsaKey(key, NULL); if (rc == 0) { + idx = 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); + isPrivateKey = 1; + } + else { + idx = 0; + rc = wc_RsaPublicKeyDecode(input, &idx, key, inSz); + } + if (rc == 0) { + if (isPrivateKey) + rc = wc_RsaExportKey(key, (byte*)&e, &eSz, n, &nSz, d, &dSz, + p, &pSz, q, &qSz); + else + rc = wc_RsaFlattenPublicKey(key, (byte*)&e, &eSz, n, &nSz); } if (rc == 0 && nSz > sizeof(pub->publicArea.unique.rsa.buffer)) rc = BUFFER_E; - if (rc == 0 && qSz > sizeof(sens->sensitiveArea.sensitive.rsa.buffer)) + if (rc == 0 && sens != NULL && isPrivateKey && + qSz > sizeof(sens->sensitiveArea.sensitive.rsa.buffer)) rc = BUFFER_E; if (rc == 0) { /* Set up public key */ @@ -2529,9 +2541,11 @@ static int DecodeRsaPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, } /* Set up private key */ - sens->sensitiveArea.sensitiveType = TPM_ALG_RSA; - sens->sensitiveArea.sensitive.rsa.size = qSz; - XMEMCPY(sens->sensitiveArea.sensitive.rsa.buffer, q, qSz); + if (sens != NULL && isPrivateKey) { + sens->sensitiveArea.sensitiveType = TPM_ALG_RSA; + sens->sensitiveArea.sensitive.rsa.size = qSz; + XMEMCPY(sens->sensitiveArea.sensitive.rsa.buffer, q, qSz); + } } wc_FreeRsaKey(key); } @@ -2540,12 +2554,12 @@ static int DecodeRsaPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, } #endif #ifdef HAVE_ECC -static int DecodeEccPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, +static int DecodeEccDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, const byte* input, word32 inSz, TPMA_OBJECT attributes) { int rc; int curveId = 0; - word32 idx = 0; + word32 idx; ecc_key key[1]; byte d[WOLFTPM2_WRAP_ECC_KEY_BITS / 8]; byte qx[WOLFTPM2_WRAP_ECC_KEY_BITS / 8]; @@ -2553,6 +2567,7 @@ static int DecodeEccPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, word32 dSz = sizeof(d); word32 qxSz = sizeof(qx); word32 qySz = sizeof(qy); + int isPrivateKey = 0; XMEMSET(d, 0, sizeof(d)); XMEMSET(qx, 0, sizeof(qx)); @@ -2560,17 +2575,29 @@ static int DecodeEccPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, rc = wc_ecc_init(key); if (rc == 0) { + idx = 0; rc = wc_EccPrivateKeyDecode(input, &idx, key, inSz); + if (rc == 0) { + isPrivateKey = 1; + } + else { + idx = 0; + rc = wc_EccPublicKeyDecode(input, &idx, key, inSz); + } if (rc == 0) { curveId = TPM2_GetTpmCurve(key->dp->id); - rc = wc_ecc_export_private_raw(key, qx, &qxSz, qy, &qySz, d, &dSz); + if (isPrivateKey) + rc = wc_ecc_export_private_raw(key, qx, &qxSz, qy, &qySz, d, &dSz); + else + rc = wc_ecc_export_public_raw(key, qx, &qxSz, qy, &qySz); } if (rc == 0 && qxSz > sizeof(pub->publicArea.unique.ecc.x.buffer)) rc = BUFFER_E; if (rc == 0 && qySz > sizeof(pub->publicArea.unique.ecc.y.buffer)) rc = BUFFER_E; - if (rc == 0 && dSz > sizeof(sens->sensitiveArea.sensitive.ecc.buffer)) + if (rc == 0 && sens != NULL && isPrivateKey && + dSz > sizeof(sens->sensitiveArea.sensitive.ecc.buffer)) rc = BUFFER_E; if (rc == 0) { /* Set up public key */ @@ -2601,9 +2628,11 @@ static int DecodeEccPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, } /* Set up private key */ - sens->sensitiveArea.sensitiveType = TPM_ALG_ECC; - sens->sensitiveArea.sensitive.ecc.size = dSz; - XMEMCPY(sens->sensitiveArea.sensitive.ecc.buffer, d, dSz); + if (sens != NULL && isPrivateKey) { + sens->sensitiveArea.sensitiveType = TPM_ALG_ECC; + sens->sensitiveArea.sensitive.ecc.size = dSz; + XMEMCPY(sens->sensitiveArea.sensitive.ecc.buffer, d, dSz); + } } wc_ecc_free(key); @@ -2613,9 +2642,68 @@ static int DecodeEccPrivateDer(TPM2B_PUBLIC* pub, TPM2B_SENSITIVE* sens, } #endif /* HAVE_ECC */ +int wolfTPM2_ImportPublicKeyBuffer(WOLFTPM2_DEV* dev, int keyType, + WOLFTPM2_KEY* key, int encodingType, const char* input, word32 inSz, + TPMA_OBJECT objectAttributes) +{ + int rc = 0; + byte* derBuf; + word32 derSz; + + if (dev == NULL || key == NULL || input == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + if (encodingType == ENCODING_TYPE_PEM) { + #if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) + /* 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_PubKeyPemToDer((byte*)input, inSz, derBuf, derSz); + if (rc >= 0) { + derSz = rc; + rc = 0; + } + #else + (void)pass; + return NOT_COMPILED_IN; + #endif + } + else { /* ASN.1 (DER) */ + derBuf = (byte*)input; + derSz = inSz; + } + + /* Handle DER Import */ + if (keyType == TPM_ALG_RSA) { + #ifndef NO_RSA + rc = DecodeRsaDer(&key->pub, NULL, derBuf, derSz, objectAttributes); + #else + rc = NOT_COMPILED_IN; + #endif + } + else if (keyType == TPM_ALG_ECC) { + #ifdef HAVE_ECC + rc = DecodeEccDer(&key->pub, NULL, derBuf, derSz, objectAttributes); + #else + rc = NOT_COMPILED_IN; + #endif + } + +#if !defined(WOLFTPM2_NO_HEAP) && defined(WOLFSSL_PEM_TO_DER) + if (derBuf != (byte*)input) { + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + return rc; +} + int wolfTPM2_ImportPrivateKeyBuffer(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* parentKey, int keyType, WOLFTPM2_KEYBLOB* keyBlob, - int encodingType, const char* input, word32 inSz, char* pass, + int encodingType, const char* input, word32 inSz, const char* pass, TPMA_OBJECT objectAttributes, byte* seed, word32 seedSz) { int rc = 0; @@ -2658,14 +2746,14 @@ int wolfTPM2_ImportPrivateKeyBuffer(WOLFTPM2_DEV* dev, /* Handle DER Import */ if (keyType == TPM_ALG_RSA) { #ifndef NO_RSA - rc = DecodeRsaPrivateDer(&pub, &sens, derBuf, derSz, objectAttributes); + rc = DecodeRsaDer(&pub, &sens, derBuf, derSz, objectAttributes); #else rc = NOT_COMPILED_IN; #endif } else if (keyType == TPM_ALG_ECC) { #ifdef HAVE_ECC - rc = DecodeEccPrivateDer(&pub, &sens, derBuf, derSz, objectAttributes); + rc = DecodeEccDer(&pub, &sens, derBuf, derSz, objectAttributes); #else rc = NOT_COMPILED_IN; #endif @@ -3120,10 +3208,17 @@ int wolfTPM2_NVStoreKey(WOLFTPM2_DEV* dev, TPM_HANDLE primaryHandle, int rc; EvictControl_In in; - if (dev == NULL || key == NULL || - (primaryHandle != TPM_RH_OWNER && primaryHandle != TPM_RH_PLATFORM) || - persistentHandle < PERSISTENT_FIRST || - persistentHandle > PERSISTENT_LAST) { + if (dev == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + if (primaryHandle == TPM_RH_OWNER && + (persistentHandle < PERSISTENT_FIRST || + persistentHandle > PERSISTENT_LAST)) { + return BAD_FUNC_ARG; + } + if (primaryHandle == TPM_RH_PLATFORM && + (persistentHandle < PLATFORM_PERSISTENT || + persistentHandle > PERSISTENT_LAST)) { return BAD_FUNC_ARG; } diff --git a/wolftpm/tpm2_wrap.h b/wolftpm/tpm2_wrap.h index e6b530d..0f31e0b 100644 --- a/wolftpm/tpm2_wrap.h +++ b/wolftpm/tpm2_wrap.h @@ -1128,8 +1128,9 @@ WOLFTPM_API int wolfTPM2_SensitiveToPrivate(TPM2B_SENSITIVE* sens, TPM2B_PRIVATE \return BAD_FUNC_ARG: check the provided arguments \param dev pointer to a TPM2_DEV struct + \param keyType The type of key (TPM_ALG_RSA or TPM_ALG_ECC) \param parentKey pointer to a WOLFTPM2_KEY struct, pointing to a Primary Key or TPM Hierarchy - \param keyBlob pointer to a struct of WOLFTPM2_KEYBLOB type, to import the rsa key to + \param keyBlob pointer to a struct of WOLFTPM2_KEYBLOB type, to import the private key to \param encodingType ENCODING_TYPE_PEM or ENCODING_TYPE_ASN1 (DER) \param input buffer holding the rsa pem \param inSz length of the input pem buffer @@ -1140,9 +1141,29 @@ WOLFTPM_API int wolfTPM2_SensitiveToPrivate(TPM2B_SENSITIVE* sens, TPM2B_PRIVATE */ WOLFTPM_API int wolfTPM2_ImportPrivateKeyBuffer(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* parentKey, int keyType, WOLFTPM2_KEYBLOB* keyBlob, - int encodingType, const char* input, word32 inSz, char* pass, + int encodingType, const char* input, word32 inSz, const char* pass, TPMA_OBJECT objectAttributes, byte* seed, word32 seedSz); +/*! + \ingroup wolfTPM2_Wrappers + \brief Helper function to import PEM/DER formatted RSA/ECC public key + + \return TPM_RC_SUCCESS: successful - populates key->pub + \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 keyType The type of key (TPM_ALG_RSA or TPM_ALG_ECC) + \param key pointer to a struct of WOLFTPM2_KEY type, to import the public key to + \param encodingType ENCODING_TYPE_PEM or ENCODING_TYPE_ASN1 (DER) + \param input buffer holding the rsa pem + \param inSz length of the input pem buffer + \param objectAttributes integer value of OR'd TPMA_OBJECT_* types +*/ +WOLFTPM_API int wolfTPM2_ImportPublicKeyBuffer(WOLFTPM2_DEV* dev, int keyType, + WOLFTPM2_KEY* key, int encodingType, const char* input, word32 inSz, + TPMA_OBJECT objectAttributes); + #ifndef NO_RSA /*! \ingroup wolfTPM2_Wrappers