diff --git a/certs/example-ecc256-key-pub.der b/certs/example-ecc256-key-pub.der new file mode 100644 index 00000000..91aa79be 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 00000000..30363efa --- /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 00000000..a88d141e 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 00000000..03e7a617 --- /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 00000000..d48e9ed9 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 00000000..c5a33a5b --- /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 00000000..9dde6764 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 00000000..5d3d61d0 --- /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 e8ce2012..4157d466 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 11a2fe74..8f1b511e 100644 --- a/examples/keygen/keyimport.c +++ b/examples/keygen/keyimport.c @@ -1,6 +1,6 @@ /* keyimport.c * - * Copyright (C) 2006-2022 wolfSSL Inc. + * Copyright (C) 2006-2023 wolfSSL Inc. * * This file is part of wolfTPM. * @@ -39,33 +39,44 @@ 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; - TPMI_ALG_PUBLIC alg = TPM_ALG_RSA; /* TPM_ALG_ECC */ + TPMI_ALG_PUBLIC alg = TPM_ALG_RSA, srkAlg; /* TPM_ALG_ECC */ 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 +86,54 @@ 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 (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); - } + else if (XSTRCMP(argv[argc-1], "-der") == 0) { + encType = ENCODING_TYPE_ASN1; } -#endif - /* we already got outfile */ - else if (i == 1 && argv[1][0] != '-') { - printf("Warning: Unrecognized option: %s\n", argv[i]); + 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]); + } + + 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 +144,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) { @@ -135,12 +152,23 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[]) goto exit; } + srkAlg = alg; +#if defined(HAVE_ECC) && !defined(WOLFSSL_PUBLIC_MP) + if (srkAlg == TPM_ALG_ECC && paramEncAlg != TPM_ALG_NULL) { + /* ECC encrypt requires mp_ API's */ + printf("Parameter encryption with ECC SRK support not available, " + "using RSA SRK\n"); + srkAlg = TPM_ALG_RSA; + } +#endif + /* get SRK */ - rc = getPrimaryStoragekey(&dev, &storage, TPM_ALG_RSA); + rc = getPrimaryStoragekey(&dev, &storage, srkAlg); if (rc != 0) goto exit; if (paramEncAlg != TPM_ALG_NULL) { - /* Start an authenticated session (salted / unbound) with parameter encryption */ + /* Start an authenticated session (salted / unbound) with parameter + * encryption */ rc = wolfTPM2_StartSession(&dev, &tpmSession, &storage, NULL, TPM_SE_HMAC, paramEncAlg); if (rc != 0) goto exit; @@ -149,56 +177,67 @@ int TPM2_Keyimport_Example(void* userCtx, int argc, char *argv[]) /* set session for authorization of the storage key */ rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession, - (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession)); + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); if (rc != 0) goto exit; } /* 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 +251,8 @@ 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 6ccb19ee..391983d9 100644 --- a/examples/keygen/keyload.c +++ b/examples/keygen/keyload.c @@ -1,6 +1,6 @@ /* keyload.c * - * Copyright (C) 2006-2022 wolfSSL Inc. + * Copyright (C) 2006-2023 wolfSSL Inc. * * This file is part of wolfTPM. * @@ -47,7 +47,8 @@ static void usage(void) { printf("Expected usage:\n"); - printf("./examples/keygen/keyload [keyblob.bin] [-aes/xor] [-persistent] [-eh]\n"); + printf("./examples/keygen/keyload [keyblob.bin] [-aes/xor] [-persistent]" + " [-eh]\n"); printf("* -eh: Key is from the Endorsement Hierarchy, requires EK\n"); printf("* -aes/xor: Use Parameter Encryption\n"); printf("* -persistent: Load the TPM key as persistent\n"); @@ -79,12 +80,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) { @@ -137,7 +138,8 @@ int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[]) } if (paramEncAlg != TPM_ALG_NULL) { - /* Start an authenticated session (salted / unbound) with parameter encryption */ + /* Start an authenticated session (salted / unbound) with parameter + * encryption */ rc = wolfTPM2_StartSession(&dev, &tpmSession, &storage, NULL, TPM_SE_HMAC, paramEncAlg); if (rc != 0) goto exit; @@ -146,7 +148,8 @@ int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[]) /* set session for authorization of the storage key */ rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession, - (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession)); + (TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | + TPMA_SESSION_continueSession)); if (rc != 0) goto exit; } @@ -160,9 +163,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", @@ -172,7 +180,8 @@ int TPM2_Keyload_Example(void* userCtx, int argc, char *argv[]) if (persistent) { /* Prepare key in the format expected by the wolfTPM wrapper */ persistKey.handle.hndl = newKey.handle.hndl; - XMEMCPY((BYTE*)&persistKey.pub, (BYTE*)&newKey.pub, sizeof(persistKey.pub)); + XMEMCPY((BYTE*)&persistKey.pub, (BYTE*)&newKey.pub, + sizeof(persistKey.pub)); /* Make key persistent */ rc = wolfTPM2_NVStoreKey(&dev, TPM_RH_OWNER, &persistKey, TPM2_DEMO_PERSISTENT_KEY_HANDLE); diff --git a/examples/tpm_test_keys.c b/examples/tpm_test_keys.c index d8ba762e..7e0c54c1 100644 --- a/examples/tpm_test_keys.c +++ b/examples/tpm_test_keys.c @@ -1,6 +1,6 @@ /* tpm_test_keys.c * - * Copyright (C) 2006-2022 wolfSSL Inc. + * Copyright (C) 2006-2023 wolfSSL Inc. * * This file is part of wolfTPM. * @@ -80,7 +80,8 @@ int writeKeyBlob(const char* filename, fp = XFOPEN(filename, "wb"); if (fp != XBADFILE) { - /* Make publicArea in encoded format to eliminate empty fields, save space */ + /* Make publicArea in encoded format to eliminate empty fields, + * save space */ rc = TPM2_AppendPublic(pubAreaBuffer, (word32)sizeof(pubAreaBuffer), &pubAreaSize, &key->pub); if (rc != TPM_RC_SUCCESS) @@ -139,7 +140,8 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key) } fileSz -= bytes_read; - bytes_read = XFREAD(pubAreaBuffer, 1, sizeof(UINT16) + key->pub.size, fp); + bytes_read = XFREAD(pubAreaBuffer, 1, + sizeof(UINT16) + key->pub.size, fp); if (bytes_read != sizeof(UINT16) + key->pub.size) { printf("Read %zu, expected public blob %zu bytes\n", bytes_read, sizeof(UINT16) + key->pub.size); @@ -165,6 +167,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)) || @@ -192,13 +197,9 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key) return rc; } -int createAndLoadKey(WOLFTPM2_DEV* pDev, - WOLFTPM2_KEY* key, - WOLFTPM2_HANDLE* parent, - const char* filename, - const byte* auth, - int authSz, - TPMT_PUBLIC* publicTemplate) +int createAndLoadKey(WOLFTPM2_DEV* pDev, WOLFTPM2_KEY* key, + WOLFTPM2_HANDLE* parent, const char* filename, const byte* auth, int authSz, + TPMT_PUBLIC* publicTemplate) { int rc; WOLFTPM2_KEYBLOB keyblob; @@ -250,12 +251,8 @@ int createAndLoadKey(WOLFTPM2_DEV* pDev, return rc; } -int readAndLoadKey(WOLFTPM2_DEV* pDev, - WOLFTPM2_KEY* key, - WOLFTPM2_HANDLE* parent, - const char* filename, - const byte* auth, - int authSz) +int readAndLoadKey(WOLFTPM2_DEV* pDev, WOLFTPM2_KEY* key, + WOLFTPM2_HANDLE* parent, const char* filename, const byte* auth, int authSz) { int rc; WOLFTPM2_KEYBLOB keyblob; @@ -286,14 +283,23 @@ int readAndLoadKey(WOLFTPM2_DEV* pDev, return rc; } -int getPrimaryStoragekey(WOLFTPM2_DEV* pDev, - WOLFTPM2_KEY* pStorageKey, - TPM_ALG_ID alg) +int getPrimaryStoragekey(WOLFTPM2_DEV* pDev, WOLFTPM2_KEY* pStorageKey, + TPM_ALG_ID alg) { int rc; + TPM_HANDLE handle; + + if (alg == TPM_ALG_RSA) + handle = TPM2_DEMO_STORAGE_KEY_HANDLE; + else if (alg == TPM_ALG_ECC) + handle = TPM2_DEMO_STORAGE_EC_KEY_HANDLE; + else { + printf("Invalid SRK alg %x\n", alg); + return BAD_FUNC_ARG; + } /* See if SRK already exists */ - rc = wolfTPM2_ReadPublicKey(pDev, pStorageKey, TPM2_DEMO_STORAGE_KEY_HANDLE); + rc = wolfTPM2_ReadPublicKey(pDev, pStorageKey, handle); if (rc != 0) { /* Create primary storage key */ rc = wolfTPM2_CreateSRK(pDev, pStorageKey, alg, @@ -301,8 +307,7 @@ int getPrimaryStoragekey(WOLFTPM2_DEV* pDev, #ifndef WOLFTPM_WINAPI if (rc == TPM_RC_SUCCESS) { /* Move storage key into persistent NV */ - rc = wolfTPM2_NVStoreKey(pDev, TPM_RH_OWNER, pStorageKey, - TPM2_DEMO_STORAGE_KEY_HANDLE); + rc = wolfTPM2_NVStoreKey(pDev, TPM_RH_OWNER, pStorageKey, handle); } #endif } @@ -322,13 +327,9 @@ int getPrimaryStoragekey(WOLFTPM2_DEV* pDev, return rc; } -int getRSAkey(WOLFTPM2_DEV* pDev, - WOLFTPM2_KEY* pStorageKey, - WOLFTPM2_KEY* key, - void* pWolfRsaKey, - int tpmDevId, - const byte* auth, int authSz, - TPMT_PUBLIC* publicTemplate) +int getRSAkey(WOLFTPM2_DEV* pDev, WOLFTPM2_KEY* pStorageKey, WOLFTPM2_KEY* key, + void* pWolfRsaKey, int tpmDevId, const byte* auth, int authSz, + TPMT_PUBLIC* publicTemplate) { int rc = 0; @@ -357,13 +358,9 @@ int getRSAkey(WOLFTPM2_DEV* pDev, return rc; } -int getECCkey(WOLFTPM2_DEV* pDev, - WOLFTPM2_KEY* pStorageKey, - WOLFTPM2_KEY* key, - void* pWolfEccKey, - int tpmDevId, - const byte* auth, int authSz, - TPMT_PUBLIC* publicTemplate) +int getECCkey(WOLFTPM2_DEV* pDev, WOLFTPM2_KEY* pStorageKey, WOLFTPM2_KEY* key, + void* pWolfEccKey, int tpmDevId, const byte* auth, int authSz, + TPMT_PUBLIC* publicTemplate) { int rc = 0; @@ -391,4 +388,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 8d2813b3..03b8e271 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 18bc6baf..d43bb483 100644 --- a/src/tpm2_wrap.c +++ b/src/tpm2_wrap.c @@ -1,6 +1,6 @@ /* tpm2_wrap.c * - * Copyright (C) 2006-2022 wolfSSL Inc. + * Copyright (C) 2006-2023 wolfSSL Inc. * * This file is part of wolfTPM. * @@ -1243,6 +1243,11 @@ int wolfTPM2_EncryptSecret(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpmKey, return TPM_RC_SUCCESS; } +#ifdef DEBUG_WOLFTPM + printf("Encrypt secret: Alg %s, Label %s\n", + TPM2_GetAlgName(tpmKey->pub.publicArea.type), label); +#endif + #ifndef WOLFTPM2_NO_WOLFCRYPT switch (tpmKey->pub.publicArea.type) { #if defined(HAVE_ECC) && !defined(WC_NO_RNG) && defined(WOLFSSL_PUBLIC_MP) @@ -1261,7 +1266,7 @@ int wolfTPM2_EncryptSecret(WOLFTPM2_DEV* dev, const WOLFTPM2_KEY* tpmKey, } #ifdef WOLFTPM_DEBUG_VERBOSE - printf("Secret %d\n", data->size); + printf("Encrypt Secret %d: %d bytes\n", data->size); TPM2_PrintBin(data->buffer, data->size); #endif #endif /* !WOLFTPM2_NO_WOLFCRYPT */ @@ -2470,7 +2475,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 +2491,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 +2500,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 +2546,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 +2559,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 +2572,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 +2580,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 +2633,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 +2647,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 +2751,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 +3213,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 e6b530d7..0f31e0b6 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