mirror of https://github.com/wolfSSL/wolfTPM.git
commit
0d6bb389ed
|
|
@ -1,3 +1,6 @@
|
|||
*~
|
||||
patch/
|
||||
*.swp
|
||||
.metadata
|
||||
language.settings.xml
|
||||
src/config.h.in
|
||||
|
|
@ -35,9 +38,11 @@ examples/tls/tls_client
|
|||
examples/pkcs7/pkcs7
|
||||
examples/timestamp/signed_timestamp
|
||||
examples/pcr/quote
|
||||
examples/pcr/quote_paramenc
|
||||
examples/pcr/extend
|
||||
examples/pcr/reset
|
||||
examples/timestamp/clock_set
|
||||
examples/management/flush
|
||||
pkcs7tpmsigned.p7s
|
||||
pkcs7tpmsignedex.p7s
|
||||
examples/tls/tls_server
|
||||
|
|
|
|||
|
|
@ -631,7 +631,6 @@ Connection: close
|
|||
|
||||
## Todo
|
||||
|
||||
* Add support for encrypting / decrypting parameters.
|
||||
* Add support for SensitiveToPrivate inner and outer.
|
||||
* Add runtime support for detecting module type ST33, SLB9670 or ATTPM20.
|
||||
* Update to v1.59 of specification.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,26 @@ More information about how to test and use PCR attestation can be found in the i
|
|||
`./examples/pcr/extend`
|
||||
`./examples/pcr/reset`
|
||||
|
||||
## Parameter Encryption
|
||||
|
||||
### TPM2.0 Quote with encrypted user data
|
||||
|
||||
Example for demonstrating how to use parameter encryption to protect the user data between the Host and the TPM.
|
||||
|
||||
In this example the qualifying data that can be supplied by the user for a Quote operation is protected. Qualifying data is arbitrary data incorporated into the signed Quote structure. Using parameter encryption, wolfTPM enables the Host to transfer that user data in encrypted form to the TPM and vice versa. Thus, protecting the data from man-in-the-middle attacks.
|
||||
|
||||
Only the first parameter of a TPM command can be encrypted and the parameter must be of type `TPM2B_DATA`. For example, the password auth of a TPM key or the qualifying data of a TPM2.0 Quote.
|
||||
|
||||
The encryption of command request and response can be performed together or separate. There can be a communication exchange between the TPM and a client program where only the parameter in the request command is encrypted.
|
||||
|
||||
This behavior depends on the `sessionAttributes`:
|
||||
|
||||
- `TPMA_SESSION_encrypt` for command request
|
||||
- `TPMA_SESSION_decrypt` for command response
|
||||
|
||||
Either one can be set separately or both can be set in one authorization session. This is up to the user (developer).
|
||||
|
||||
`./examples/pcr/quote_paramenc`
|
||||
|
||||
## CSR
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ include examples/csr/include.am
|
|||
include examples/pkcs7/include.am
|
||||
include examples/timestamp/include.am
|
||||
include examples/pcr/include.am
|
||||
include examples/management/include.am
|
||||
|
||||
dist_example_DATA+= examples/README.md \
|
||||
examples/tpm_io.c \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
/* flush.c
|
||||
*
|
||||
* Copyright (C) 2006-2020 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfTPM.
|
||||
*
|
||||
* wolfTPM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfTPM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* This is a helper tool for reseting the value of a TPM2.0 PCR */
|
||||
|
||||
#include <wolftpm/tpm2_wrap.h>
|
||||
|
||||
#include <examples/management/flush.h>
|
||||
#include <examples/tpm_io.h>
|
||||
#include <examples/tpm_test.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* atoi */
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* --- BEGIN TPM2.0 Flush tool -- */
|
||||
/******************************************************************************/
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Expected usage:\n");
|
||||
printf("./tool/management/flush [handle]\n");
|
||||
printf("* handle is a valid TPM2.0 handle index\n");
|
||||
printf("Note: Default behavior, without parameters, the tool flushes"
|
||||
" all transient TPM2.0 objects (0x8000000x, 0x300000x)\n");
|
||||
}
|
||||
|
||||
int TPM2_Flush_Tool(void* userCtx, int argc, char *argv[])
|
||||
{
|
||||
int rc = TPM_RC_FAILURE;
|
||||
int allTransientObjects = 0, handle = 0;
|
||||
WOLFTPM2_DEV dev;
|
||||
FlushContext_In flushCtx;
|
||||
|
||||
if (argc == 2) {
|
||||
/* TODO: Parse input parameter as 8 digit hex value */
|
||||
(void)argv;
|
||||
if(1) {
|
||||
printf("Input value does not look like a TPM handle\n");
|
||||
usage();
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
else if (argc == 1) {
|
||||
allTransientObjects = 1;
|
||||
}
|
||||
else {
|
||||
printf("Incorrect arguments\n");
|
||||
usage();
|
||||
goto exit;
|
||||
}
|
||||
|
||||
printf("Preparing to free TPM2.0 Resources\n");
|
||||
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
printf("wolfTPM2_Init: success\n");
|
||||
|
||||
if (allTransientObjects) {
|
||||
/* Flush key objects */
|
||||
for(handle=0x80000000; handle < (int)0x8000000A; handle+=4) {
|
||||
flushCtx.flushHandle = handle;
|
||||
printf("Freeing %X object\n", handle);
|
||||
TPM2_FlushContext(&flushCtx);
|
||||
}
|
||||
/* Flush auth sessions */
|
||||
for(handle=0x3000000; handle < (int)0x3000004; handle++) {
|
||||
flushCtx.flushHandle = handle;
|
||||
printf("Freeing %X object\n", handle);
|
||||
TPM2_FlushContext(&flushCtx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
flushCtx.flushHandle = handle;
|
||||
printf("Freeing %X object\n", handle);
|
||||
TPM2_FlushContext(&flushCtx);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
wolfTPM2_Cleanup(&dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* --- END TPM2.0 PCR Reset example tool -- */
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
#ifndef NO_MAIN_DRIVER
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = TPM2_Flush_Tool(NULL, argc, argv);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* flush.h
|
||||
*
|
||||
* Copyright (C) 2006-2020 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfTPM.
|
||||
*
|
||||
* wolfTPM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfTPM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUSH_H_
|
||||
#define _FLUSH_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int TPM2_Flush_Tool(void* userCtx, int argc, char *argv[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _FLUSH_H_ */
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# vim:ft=automake
|
||||
# All paths should be given relative to the root
|
||||
|
||||
if BUILD_EXAMPLES
|
||||
noinst_PROGRAMS += examples/management/flush
|
||||
|
||||
noinst_HEADERS += examples/management/flush.h
|
||||
|
||||
examples_management_flush_SOURCES = examples/management/flush.c \
|
||||
examples/tpm_io.c
|
||||
examples_management_flush_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
|
||||
examples_management_flush_DEPENDENCIES = src/libwolftpm.la
|
||||
endif
|
||||
|
||||
dist_example_DATA+= examples/management/flush.c
|
||||
|
||||
DISTCLEANFILES+= examples/management/.libs/flush
|
||||
|
|
@ -32,4 +32,4 @@ int TPM2_Extend_Test(void* userCtx, int argc, char *argv[]);
|
|||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _quote_H_ */
|
||||
#endif /* _EXTEND_H_ */
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@
|
|||
|
||||
if BUILD_EXAMPLES
|
||||
noinst_PROGRAMS += examples/pcr/quote \
|
||||
examples/pcr/quote_paramenc \
|
||||
examples/pcr/extend \
|
||||
examples/pcr/reset
|
||||
|
||||
noinst_HEADERS += examples/pcr/quote.h \
|
||||
examples/pcr/quote_paramenc.h \
|
||||
examples/pcr/extend.h \
|
||||
examples/pcr/reset.h
|
||||
|
||||
|
|
@ -15,6 +17,11 @@ examples_pcr_quote_SOURCES = examples/pcr/quote.c \
|
|||
examples_pcr_quote_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
|
||||
examples_pcr_quote_DEPENDENCIES = src/libwolftpm.la
|
||||
|
||||
examples_pcr_quote_paramenc_SOURCES = examples/pcr/quote_paramenc.c \
|
||||
examples/tpm_io.c
|
||||
examples_pcr_quote_paramenc_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
|
||||
examples_pcr_quote_paramenc_DEPENDENCIES = src/libwolftpm.la
|
||||
|
||||
examples_pcr_extend_SOURCES = examples/pcr/extend.c \
|
||||
examples/tpm_io.c
|
||||
examples_pcr_extend_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
|
||||
|
|
@ -27,10 +34,12 @@ examples_pcr_reset_DEPENDENCIES = src/libwolftpm.la
|
|||
endif
|
||||
|
||||
dist_example_DATA+= examples/pcr/quote.c \
|
||||
examples/pcr/quote_paramenc.c \
|
||||
examples/pcr/extend.c \
|
||||
examples/pcr/reset.c
|
||||
|
||||
DISTCLEANFILES+= examples/pcr/.libs/quote \
|
||||
examples/pcr/.libs/quote_paramenc \
|
||||
examples/pcr/.libs/extend \
|
||||
examples/pcr/.libs/reset
|
||||
|
||||
|
|
|
|||
|
|
@ -32,4 +32,4 @@ int TPM2_Quote_Test(void* userCtx, int argc, char *argv[]);
|
|||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _quote_H_ */
|
||||
#endif /* _QUOTE_H_ */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,300 @@
|
|||
/* quote_paramenc.c
|
||||
*
|
||||
* Copyright (C) 2006-2020 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfTPM.
|
||||
*
|
||||
* wolfTPM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfTPM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* This example shows how to generate a TPM2.0 Quote that holds a signed
|
||||
* PCR measurement. PCR values are used as basis for system integrity.
|
||||
*/
|
||||
|
||||
#include <wolftpm/tpm2_wrap.h>
|
||||
|
||||
#include <examples/pcr/quote.h>
|
||||
#include <examples/tpm_io.h>
|
||||
#include <examples/tpm_test.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* atoi */
|
||||
|
||||
const char defaultFilename[] = "quote.blob\0";
|
||||
const char userData[] = "ThisIsData";
|
||||
|
||||
/******************************************************************************/
|
||||
/* --- BEGIN TPM2.0 Quote Test with Parameter Encryption over user data --- */
|
||||
/******************************************************************************/
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Expected usage:\n");
|
||||
printf("./examples/pcr/quote [pcr] [filename]\n");
|
||||
printf("* pcr is a PCR index between 0-23 (default %d)\n", TPM2_TEST_PCR);
|
||||
printf("* filename for saving the TPMS_ATTEST structure to a file\n");
|
||||
printf("Demo usage without parameters, generates quote over PCR%d and\n"
|
||||
"saves the output TPMS_ATTEST structure to \"quote.blob\" file.\n",
|
||||
TPM2_TEST_PCR);
|
||||
}
|
||||
|
||||
int TPM2_Quote_Test(void* userCtx, int argc, char *argv[])
|
||||
{
|
||||
int pcrIndex, rc = -1;
|
||||
const char *filename = NULL;
|
||||
BYTE *data = NULL;
|
||||
FILE *quoteBlob = NULL;
|
||||
WOLFTPM2_DEV dev;
|
||||
TPMS_ATTEST attestedData;
|
||||
|
||||
WOLFTPM2_KEY storage; /* SRK */
|
||||
WOLFTPM2_KEY rsaKey; /* AIK */
|
||||
|
||||
TPMS_AUTH_COMMAND session[MAX_SESSION_NUM];
|
||||
TPM_HANDLE sessionHandle = TPM_RH_NULL;
|
||||
|
||||
union {
|
||||
Quote_In quoteAsk;
|
||||
StartAuthSession_In authSes;
|
||||
FlushContext_In flushCtx;
|
||||
byte maxInput[MAX_COMMAND_SIZE];
|
||||
} cmdIn;
|
||||
union {
|
||||
Quote_Out quoteResult;
|
||||
StartAuthSession_Out authSes;
|
||||
byte maxOutput[MAX_RESPONSE_SIZE];
|
||||
} cmdOut;
|
||||
|
||||
XMEMSET(&storage, 0, sizeof(storage));
|
||||
XMEMSET(&rsaKey, 0, sizeof(rsaKey));
|
||||
|
||||
|
||||
if (argc == 1) {
|
||||
/* Demo usage */
|
||||
pcrIndex = TPM2_TEST_PCR;
|
||||
filename = defaultFilename;
|
||||
}
|
||||
else if (argc == 3) {
|
||||
/* Advanced usage */
|
||||
pcrIndex = atoi(argv[1]);
|
||||
if (pcrIndex < 0 || pcrIndex > 23 || *argv[1] < '0' || *argv[1] > '9') {
|
||||
printf("PCR index is out of range (0-23)\n");
|
||||
usage();
|
||||
goto exit_badargs;
|
||||
}
|
||||
filename = argv[2];
|
||||
}
|
||||
else {
|
||||
printf("Incorrect arguments\n");
|
||||
usage();
|
||||
goto exit_badargs;
|
||||
}
|
||||
|
||||
quoteBlob = fopen(filename, "wb");
|
||||
if (quoteBlob == NULL) {
|
||||
printf("Error opening file %s\n", filename);
|
||||
usage();
|
||||
goto exit_badargs;
|
||||
}
|
||||
|
||||
printf("Demo of TPM2.0 Quote with parameter encryption over user data\n");
|
||||
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
printf("wolfTPM2_Init: success\n");
|
||||
|
||||
|
||||
/* Define the default session auth that has NULL password */
|
||||
XMEMSET(session, 0, sizeof(session));
|
||||
session[0].sessionHandle = TPM_RS_PW;
|
||||
session[0].auth.size = 0; /* NULL Password */
|
||||
TPM2_SetSessionAuth(session);
|
||||
|
||||
|
||||
/* Create RSA Storage Key, also called SRK */
|
||||
rc = wolfTPM2_CreateSRK(&dev, &storage, TPM_ALG_RSA,
|
||||
(byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
printf("wolfTPM2_CreateSRK: Storage failed 0x%x: %s\n", rc,
|
||||
TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
printf("wolfTPM2_CreateSRK: Storage 0x%x (%d bytes)\n",
|
||||
(word32)storage.handle.hndl, storage.pub.size);
|
||||
|
||||
|
||||
/* set session auth for storage key */
|
||||
session[0].auth.size = sizeof(gStorageKeyAuth)-1;
|
||||
XMEMCPY(session[0].auth.buffer, gStorageKeyAuth, session[0].auth.size);
|
||||
|
||||
|
||||
/* Create an RSA key for Attestation purposes */
|
||||
rc = wolfTPM2_CreateAndLoadAIK(&dev, &rsaKey, TPM_ALG_RSA, &storage,
|
||||
(const byte*)gUsageAuth, sizeof(gUsageAuth)-1);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
printf("wolfTPM2_CreateAndLoadAIK failed 0x%x: %s\n", rc,
|
||||
TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
printf("wolfTPM2_CreateAndLoadAIK: AIK 0x%x (%d bytes)\n",
|
||||
(word32)rsaKey.handle.hndl, rsaKey.pub.size);
|
||||
|
||||
|
||||
/* Start Auth Session - Unbounded, Unsalted */
|
||||
XMEMSET(&cmdIn.authSes, 0, sizeof(cmdIn.authSes));
|
||||
cmdIn.authSes.sessionType = TPM_SE_POLICY;
|
||||
cmdIn.authSes.tpmKey = TPM_RH_NULL;
|
||||
cmdIn.authSes.bind = TPM_RH_NULL;
|
||||
cmdIn.authSes.symmetric.algorithm = TPM_ALG_XOR;
|
||||
cmdIn.authSes.symmetric.keyBits.xorr = TPM_ALG_SHA256;
|
||||
cmdIn.authSes.symmetric.mode.sym = TPM_ALG_NULL;
|
||||
cmdIn.authSes.encryptedSalt.size = 0;
|
||||
cmdIn.authSes.authHash = TPM_ALG_SHA256;
|
||||
cmdIn.authSes.nonceCaller.size = TPM_SHA256_DIGEST_SIZE;
|
||||
rc = TPM2_GetNonce(cmdIn.authSes.nonceCaller.buffer,
|
||||
cmdIn.authSes.nonceCaller.size);
|
||||
if (rc < 0) {
|
||||
printf("TPM2_GetNonce failed 0x%x: %s\n", rc,
|
||||
TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
rc = TPM2_StartAuthSession(&cmdIn.authSes, &cmdOut.authSes);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
printf("\nTPM2_StartAuthSession failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
sessionHandle = cmdOut.authSes.sessionHandle;
|
||||
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", (word32)sessionHandle);
|
||||
|
||||
|
||||
/* set auth for using the AIK */
|
||||
session[0].auth.size = sizeof(gUsageAuth)-1;
|
||||
XMEMCPY(session[0].auth.buffer, gUsageAuth, session[0].auth.size);
|
||||
|
||||
/* set session for XOR parameter encryption of the TPM Command */
|
||||
session[1].sessionHandle = sessionHandle;
|
||||
session[1].sessionAttributes = TPMA_SESSION_decrypt |
|
||||
TPMA_SESSION_encrypt |
|
||||
TPMA_SESSION_continueSession;
|
||||
session[1].symmetric.algorithm = TPM_ALG_XOR;
|
||||
session[1].symmetric.keyBits.xorr = TPM_ALG_SHA256;
|
||||
session[1].authHash = TPM_ALG_SHA256;
|
||||
session[1].auth.size = sizeof(gXorAuth)-1;
|
||||
XMEMCPY(session[1].auth.buffer, gXorAuth, session[1].auth.size);
|
||||
session[1].nonce.size = TPM_SHA256_DIGEST_SIZE;
|
||||
rc = TPM2_GetNonce(session[1].nonce.buffer,
|
||||
session[1].nonce.size);
|
||||
if (rc < 0) {
|
||||
printf("TPM2_GetNonce failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Prepare Quote request */
|
||||
XMEMSET(&cmdIn.quoteAsk, 0, sizeof(cmdIn.quoteAsk));
|
||||
XMEMSET(&cmdOut.quoteResult, 0, sizeof(cmdOut.quoteResult));
|
||||
cmdIn.quoteAsk.signHandle = rsaKey.handle.hndl;
|
||||
cmdIn.quoteAsk.inScheme.scheme = TPM_ALG_RSASSA;
|
||||
cmdIn.quoteAsk.inScheme.details.rsassa.hashAlg = TPM_ALG_SHA256;
|
||||
/* This specifies the size of the parameter that will be encrypted */
|
||||
cmdIn.quoteAsk.qualifyingData.size = sizeof(userData);
|
||||
/* This is the data that will be encrypted */
|
||||
XMEMCPY(cmdIn.quoteAsk.qualifyingData.buffer, userData,
|
||||
cmdIn.quoteAsk.qualifyingData.size);
|
||||
/* Choose PCR for signing */
|
||||
TPM2_SetupPCRSel(&cmdIn.quoteAsk.PCRselect, TPM_ALG_SHA256, pcrIndex);
|
||||
|
||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||
printf("\n\tCommand with ParamEnc\n");
|
||||
#endif
|
||||
|
||||
/* Get the PCR measurement signed by the TPM using the AIK key */
|
||||
rc = TPM2_Quote(&cmdIn.quoteAsk, &cmdOut.quoteResult);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
printf("TPM2_Quote failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
printf("TPM2_Quote: success\n");
|
||||
|
||||
rc = TPM2_ParseAttest(&cmdOut.quoteResult.quoted, &attestedData);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
printf("TPM2_Packet_ParseAttest failed 0x%x: %s\n", rc,
|
||||
TPM2_GetRCString(rc));
|
||||
goto exit;
|
||||
}
|
||||
if (attestedData.magic != TPM_GENERATED_VALUE) {
|
||||
printf("\tError, attested data not generated by the TPM = 0x%X\n",
|
||||
attestedData.magic);
|
||||
}
|
||||
|
||||
if(quoteBlob) {
|
||||
data = (UINT8*)&cmdOut.quoteResult.quoted;
|
||||
data += 2; /* skip the size field of TPMS_ATTEST */
|
||||
if(fwrite(data, sizeof(TPMS_ATTEST)-2, 1, quoteBlob) != 1) {
|
||||
printf("Error while writing to a %s file\n", filename);
|
||||
}
|
||||
}
|
||||
|
||||
printf("TPM with signature attests (type 0x%x):\n", attestedData.type);
|
||||
printf("\tTPM signed %lu count of PCRs\n",
|
||||
(unsigned long)attestedData.attested.quote.pcrSelect.count);
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("\tPCR digest:\n");
|
||||
TPM2_PrintBin(attestedData.attested.quote.pcrDigest.buffer,
|
||||
attestedData.attested.quote.pcrDigest.size);
|
||||
printf("\tTPM generated signature:\n");
|
||||
TPM2_PrintBin(cmdOut.quoteResult.signature.signature.rsassa.sig.buffer,
|
||||
cmdOut.quoteResult.signature.signature.rsassa.sig.size);
|
||||
#endif
|
||||
|
||||
exit:
|
||||
|
||||
/* Close key handles */
|
||||
wolfTPM2_UnloadHandle(&dev, &rsaKey.handle);
|
||||
wolfTPM2_UnloadHandle(&dev, &storage.handle);
|
||||
|
||||
/* Close session */
|
||||
if (sessionHandle != TPM_RH_NULL) {
|
||||
cmdIn.flushCtx.flushHandle = sessionHandle;
|
||||
TPM2_FlushContext(&cmdIn.flushCtx);
|
||||
}
|
||||
|
||||
wolfTPM2_Cleanup(&dev);
|
||||
|
||||
exit_badargs:
|
||||
|
||||
if (quoteBlob != NULL) {
|
||||
fclose(quoteBlob);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* --- END TPM2.0 Quote Test -- */
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
#ifndef NO_MAIN_DRIVER
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = TPM2_Quote_Test(NULL, argc, argv);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* quote_paramenc.h
|
||||
*
|
||||
* Copyright (C) 2006-2020 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfTPM.
|
||||
*
|
||||
* wolfTPM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfTPM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _QUOTE_PARAMENC_H_
|
||||
#define _QUOTE_PARAMENC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int TPM2_Quote_Test(void* userCtx, int argc, char *argv[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _QUOTE_PARAMENC_H_ */
|
||||
|
|
@ -32,4 +32,4 @@ int TPM2_Reset_Test(void* userCtx, int argc, char *argv[]);
|
|||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _clear_H_ */
|
||||
#endif /* _CLEAR_H_ */
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ static const char gKeyAuth[] = "ThisIsMyKeyAuth";
|
|||
static const char gKeyAuthAlt[] = "ThisIsMyKeyAltAuth";
|
||||
static const char gUsageAuth[] = "ThisIsASecretUsageAuth";
|
||||
static const char gNvAuth[] = "ThisIsMyNvAuth";
|
||||
static const char gXorAuth[] = "ThisIsMyXorAuth";
|
||||
|
||||
/* Default Test PCR */
|
||||
/* PCR16 is for DEBUG purposes, thus safe to use */
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ src_libwolftpm_la_SOURCES = \
|
|||
src/tpm2.c \
|
||||
src/tpm2_packet.c \
|
||||
src/tpm2_tis.c \
|
||||
src/tpm2_wrap.c
|
||||
src/tpm2_wrap.c \
|
||||
src/tpm2_param_enc.c
|
||||
|
||||
if BUILD_DEVTPM
|
||||
src_libwolftpm_la_SOURCES += src/tpm2_linux.c
|
||||
|
|
|
|||
218
src/tpm2.c
218
src/tpm2.c
|
|
@ -25,6 +25,7 @@
|
|||
#include <wolftpm/tpm2_tis.h>
|
||||
#include <wolftpm/tpm2_linux.h>
|
||||
#include <wolftpm/tpm2_swtpm.h>
|
||||
#include <wolftpm/tpm2_param_enc.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/* --- Local Variables -- */
|
||||
|
|
@ -77,162 +78,128 @@ static void TPM2_ReleaseLock(TPM2_CTX* ctx)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int TPM2_Parameter_EncryptDecrypt(int modeMask,
|
||||
TPMT_SYM_DEF* symmetric, TPMI_ALG_HASH authHash,
|
||||
const BYTE* keyBuf, int keySz,
|
||||
const BYTE* nonceBuf, int nonceSz,
|
||||
BYTE* dataBuf, int dataSz)
|
||||
{
|
||||
/* TODO: Perform symmetric encrypt or decrypt */
|
||||
if (modeMask & TPMA_SESSION_encrypt) {
|
||||
/* encrypt */
|
||||
}
|
||||
else {
|
||||
/* decrypt */
|
||||
}
|
||||
|
||||
(void)symmetric;
|
||||
(void)authHash;
|
||||
(void)keyBuf;
|
||||
(void)keySz;
|
||||
(void)nonceBuf;
|
||||
(void)nonceSz;
|
||||
(void)dataBuf;
|
||||
(void)dataSz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Send Command Wrapper */
|
||||
static TPM_RC TPM2_SendCommandAuth(TPM2_CTX* ctx, TPM2_Packet* packet,
|
||||
int authCnt, int inHandleCnt, int outHandleCnt)
|
||||
{
|
||||
TPM_RC rc = TPM_RC_FAILURE;
|
||||
TPMS_AUTH_COMMAND* auth;
|
||||
TPM_ST* tag;
|
||||
TPM2B_SYM_KEY key;
|
||||
TPM_ST tag;
|
||||
BYTE *cmd, *param;
|
||||
UINT32 paramSz;
|
||||
int i;
|
||||
UINT32 cmdSz, authSz;
|
||||
UINT16 requestParamSz;
|
||||
UINT32 responseParamSz;
|
||||
TPM2B_MAX_BUFFER encryptedParameter;
|
||||
int sessionParamEnc;
|
||||
|
||||
if (ctx == NULL || packet == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
cmd = packet->buf;
|
||||
tag = (TPM_ST*)cmd;
|
||||
cmdSz = packet->pos;
|
||||
|
||||
if (*tag == TPM_ST_SESSIONS && (authCnt < 1 || ctx->authCmd == NULL))
|
||||
return TPM_RC_AUTH_MISSING;
|
||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||
printf("Request command (size=%d):\n", cmdSz);
|
||||
TPM2_PrintBin(cmd, cmdSz);
|
||||
#endif
|
||||
|
||||
/* parameter encryption */
|
||||
if (*tag == TPM_ST_SESSIONS) {
|
||||
/* tag = (TPM_ST*)cmd; Can not be processed correctly due to Marshaling */
|
||||
packet->pos = 0;
|
||||
TPM2_Packet_ParseU16(packet, &tag);
|
||||
|
||||
/* Is auth session required for this TPM command? */
|
||||
if (tag == TPM_ST_SESSIONS) {
|
||||
/* Is there at least one auth session present? */
|
||||
if (authCnt < 1 || ctx->authCmd == NULL)
|
||||
return TPM_RC_AUTH_MISSING;
|
||||
|
||||
/* Pass the TPM header and Handles area */
|
||||
param = cmd + TPM2_HEADER_SIZE + (inHandleCnt * sizeof(TPM_HANDLE));
|
||||
|
||||
paramSz = *(UINT32*)param;
|
||||
param += sizeof(UINT32); /* skip the param size */
|
||||
|
||||
for (i=0; i<authCnt; i++) {
|
||||
auth = &ctx->authCmd[i];
|
||||
|
||||
/* check if encrypting parameters */
|
||||
if (auth->sessionAttributes & TPMA_SESSION_decrypt) {
|
||||
/* get new nonce if required */
|
||||
if (ctx->authCmd->sessionHandle !=
|
||||
TPM_RS_PW && auth->nonce.size > 0) {
|
||||
rc = TPM2_GetNonce(auth->nonce.buffer, auth->nonce.size);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* build key */
|
||||
XMEMCPY(key.buffer, auth->auth.buffer, auth->auth.size);
|
||||
key.size = auth->auth.size;
|
||||
|
||||
/* check for object handle auth and append to key */
|
||||
if (i < inHandleCnt) {
|
||||
TPM_HANDLE* objHandle = (TPM_HANDLE*)(cmd +
|
||||
TPM2_HEADER_SIZE + (i * sizeof(TPM_HANDLE)));
|
||||
if (*objHandle == auth->objHandle) {
|
||||
/* append to key */
|
||||
XMEMCPY(key.buffer + key.size, auth->objAuth.buffer,
|
||||
auth->objAuth.size);
|
||||
key.size += auth->objAuth.size;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform parameter encryption (inline) */
|
||||
rc = TPM2_Parameter_EncryptDecrypt(TPMA_SESSION_encrypt,
|
||||
&auth->symmetric,
|
||||
auth->authHash,
|
||||
key.buffer, key.size,
|
||||
auth->nonce.buffer, auth->nonce.size,
|
||||
param, paramSz);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
packet->pos = TPM2_HEADER_SIZE + (inHandleCnt * sizeof(TPM_HANDLE));
|
||||
/* Extract the size of the Authorization Area to skip */
|
||||
TPM2_Packet_ParseU32(packet, &authSz);
|
||||
/* Pass the Auth Session area, size field already passed by ParseU32 */
|
||||
packet->pos += authSz;
|
||||
/* Extract the size of the first parameter */
|
||||
TPM2_Packet_ParseU16(packet, &requestParamSz);
|
||||
/* Index the beginning of the parameter data */
|
||||
param += sizeof(authSz) + authSz + sizeof(requestParamSz);
|
||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||
printf("Request parameter (size=%d):\n", requestParamSz);
|
||||
TPM2_PrintBin(param, requestParamSz);
|
||||
#endif
|
||||
/* Do encryption of the first parameter in the command request */
|
||||
sessionParamEnc = TPM2_ParamEnc_FindDecryptSession(ctx);
|
||||
if (sessionParamEnc < MAX_SESSION_NUM) {
|
||||
rc = TPM2_ParamEnc_CmdRequest(&ctx->authCmd[sessionParamEnc],
|
||||
&encryptedParameter,
|
||||
param, requestParamSz);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("Request parameter encryption failed\n");
|
||||
#endif
|
||||
return TPM_RC_FAILURE;
|
||||
}
|
||||
/* packet->pos already points at the first command parameter */
|
||||
TPM2_Packet_AppendBytes(packet, encryptedParameter.buffer,
|
||||
encryptedParameter.size);
|
||||
}
|
||||
}
|
||||
/* reset packet->pos */
|
||||
packet->pos = cmdSz;
|
||||
|
||||
/* submit command and wait for response */
|
||||
rc = (TPM_RC)INTERNAL_SEND_COMMAND(ctx, packet);
|
||||
|
||||
/* parse response */
|
||||
cmd = packet->buf;
|
||||
rc = TPM2_Packet_Parse(rc, packet);
|
||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||
cmdSz = packet->size;
|
||||
printf("Response command (size=%d)\n", cmdSz);
|
||||
TPM2_PrintBin(cmd, cmdSz);
|
||||
#endif
|
||||
/* Extract tag */
|
||||
packet->pos = 0;
|
||||
TPM2_Packet_ParseU16(packet, &tag);
|
||||
|
||||
/* parameter decryption */
|
||||
if (rc == TPM_RC_SUCCESS && *tag == TPM_ST_SESSIONS) {
|
||||
TPMS_AUTH_RESPONSE authResp;
|
||||
TPM2_Packet tmpPacket = *packet; /* make copy of packet parse info */
|
||||
/* Is auth session required for this TPM command? */
|
||||
if (rc == TPM_RC_SUCCESS && tag == TPM_ST_SESSIONS) {
|
||||
/* Pass the TPM header and Handles area */
|
||||
param = cmd + TPM2_HEADER_SIZE + (outHandleCnt * sizeof(TPM_HANDLE));
|
||||
packet->pos = TPM2_HEADER_SIZE + (outHandleCnt * sizeof(TPM_HANDLE));
|
||||
/* Extract the size of the first parameter */
|
||||
TPM2_Packet_ParseU32(packet, &responseParamSz);
|
||||
param += sizeof(responseParamSz);
|
||||
|
||||
/* skip handles */
|
||||
i = outHandleCnt * sizeof(TPM_HANDLE);
|
||||
tmpPacket.buf += i; tmpPacket.pos += i;
|
||||
|
||||
/* get parameter size and buffer */
|
||||
TPM2_Packet_ParseU32(&tmpPacket, ¶mSz);
|
||||
param = tmpPacket.buf;
|
||||
|
||||
/* get auth response */
|
||||
tmpPacket.buf += paramSz; tmpPacket.pos += paramSz;
|
||||
TPM2_Packet_ParseAuth(&tmpPacket, &authResp);
|
||||
|
||||
for (i=0; i<authCnt; i++) {
|
||||
auth = &ctx->authCmd[i];
|
||||
|
||||
/* check if encrypting parameters */
|
||||
if (auth->sessionAttributes & TPMA_SESSION_encrypt) {
|
||||
/* build key */
|
||||
XMEMCPY(key.buffer, auth->auth.buffer, auth->auth.size);
|
||||
key.size = auth->auth.size;
|
||||
|
||||
/* check for object handle auth and append to key */
|
||||
if (i < outHandleCnt) {
|
||||
TPM_HANDLE* objHandle = (TPM_HANDLE*)(cmd +
|
||||
TPM2_HEADER_SIZE + (i * sizeof(TPM_HANDLE)));
|
||||
if (*objHandle == auth->objHandle) {
|
||||
/* append to key */
|
||||
XMEMCPY(key.buffer + key.size, auth->objAuth.buffer,
|
||||
auth->objAuth.size);
|
||||
key.size += auth->objAuth.size;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform parameter decryption (inline) */
|
||||
rc = TPM2_Parameter_EncryptDecrypt(TPMA_SESSION_decrypt,
|
||||
&auth->symmetric,
|
||||
auth->authHash,
|
||||
key.buffer, key.size,
|
||||
auth->nonce.buffer, auth->nonce.size,
|
||||
param, paramSz);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||
printf("Response parameter (size=%d):\n", responseParamSz);
|
||||
TPM2_PrintBin(param, responseParamSz);
|
||||
#endif
|
||||
/* Should the first parameter in the command response be decrypted */
|
||||
sessionParamEnc = TPM2_ParamEnc_FindEncryptSession(ctx);
|
||||
if (sessionParamEnc < MAX_SESSION_NUM) {
|
||||
rc = TPM2_ParamEnc_CmdResponse(&ctx->authCmd[sessionParamEnc],
|
||||
&encryptedParameter,
|
||||
param, responseParamSz);
|
||||
if (rc != TPM_RC_SUCCESS) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("Response parameter encryption failed\n");
|
||||
#endif
|
||||
return TPM_RC_FAILURE;
|
||||
}
|
||||
/* packet->pos already points at the parameter, copy the decrypted data */
|
||||
TPM2_Packet_ParseBytes(packet, encryptedParameter.buffer,
|
||||
encryptedParameter.size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: Backward compatibility after Parameter Encryption changes
|
||||
* Before returning to caller, set packet to expected position.
|
||||
*/
|
||||
packet->pos = TPM2_HEADER_SIZE;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static TPM_RC TPM2_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
|
||||
{
|
||||
TPM_RC rc;
|
||||
|
|
@ -249,6 +216,7 @@ static TPM_RC TPM2_SendCommand(TPM2_CTX* ctx, TPM2_Packet* packet)
|
|||
static TPM_ST TPM2_GetTag(TPM2_CTX* ctx)
|
||||
{
|
||||
TPM_ST st = TPM_ST_NO_SESSIONS;
|
||||
/* TODO: Fix bug, ST_SESSION shows need of auth Session, not paramEnc */
|
||||
if (ctx && ctx->authCmd &&
|
||||
(ctx->authCmd->sessionAttributes &
|
||||
(TPMA_SESSION_decrypt | TPMA_SESSION_encrypt))) {
|
||||
|
|
|
|||
|
|
@ -101,10 +101,35 @@
|
|||
#define be64_to_cpu(d) (d)
|
||||
#endif
|
||||
|
||||
/* convert 16 bit integer to opaque */
|
||||
static inline void c16toa(word16 wc_u16, byte* c)
|
||||
{
|
||||
c[0] = (wc_u16 >> 8) & 0xff;
|
||||
c[1] = wc_u16 & 0xff;
|
||||
}
|
||||
/* convert 32 bit integer to opaque */
|
||||
static inline void c32toa(word32 wc_u32, byte* c)
|
||||
{
|
||||
c[0] = (wc_u32 >> 24) & 0xff;
|
||||
c[1] = (wc_u32 >> 16) & 0xff;
|
||||
c[2] = (wc_u32 >> 8) & 0xff;
|
||||
c[3] = wc_u32 & 0xff;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* --- BEGIN TPM Packet Assembly / Parsing -- */
|
||||
/******************************************************************************/
|
||||
void TPM2_Packet_U16ToByteArray(UINT16 val, BYTE* b)
|
||||
{
|
||||
if (b)
|
||||
c16toa(val, b);
|
||||
}
|
||||
void TPM2_Packet_U32ToByteArray(UINT32 val, BYTE* b)
|
||||
{
|
||||
if (b)
|
||||
c32toa(val, b);
|
||||
}
|
||||
|
||||
UINT16 TPM2_Packet_SwapU16(UINT16 data) {
|
||||
return cpu_to_be16(data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,336 @@
|
|||
/* tpm2_param_enc.c
|
||||
*
|
||||
* Copyright (C) 2006-2020 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfTPM.
|
||||
*
|
||||
* wolfTPM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfTPM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#include <wolftpm/tpm2_param_enc.h>
|
||||
#include <wolftpm/tpm2_packet.h>
|
||||
|
||||
#ifndef WOLFTPM2_NO_WOLFCRYPT
|
||||
#include <wolfssl/wolfcrypt/hmac.h>
|
||||
#endif
|
||||
|
||||
/* Routines for performing TPM Parameter Encryption
|
||||
*
|
||||
* NB: Only TPM2B_DATA parameters can be encrypted
|
||||
*
|
||||
* Only the first parameter of a TPM command can be encrypted.
|
||||
* For example, the password auth of a TPM key. The encryption
|
||||
* of command response and request are separate. There can be a
|
||||
* communication exchange between the TPM and a client program
|
||||
* where only the parameter in the request command is encrypted.
|
||||
*
|
||||
* This behavior depends on the sessionAttributes:
|
||||
* - TPMA_SESSION_encrypt for command request
|
||||
* - TPMA_SESSION_decrypt for command response
|
||||
* Either one can be set separately or both can be set in one
|
||||
* authorization session. This is up to the user(developer).
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
||||
/* --- Local Functions -- */
|
||||
/******************************************************************************/
|
||||
|
||||
/* This function performs key generation according to Part 1 of the TPM spec
|
||||
* and returns the number of bytes generated, which may be zero.
|
||||
*
|
||||
* 'key' or 'authValue' are used to generate the session key.
|
||||
* - either 'key' or 'authValue' must be provided.
|
||||
*
|
||||
* 'keyStream' points to the buffer storing the generated session key
|
||||
* - 'keyStream' can not be NULL.
|
||||
*
|
||||
* 'sizeInBits' must be no larger than (2^18)-1 = 256K bits (32385 bytes).
|
||||
*
|
||||
* Note: The "once" parameter is set to allow incremental generation of a large
|
||||
* value. If this flag is TRUE, "sizeInBits" is used in the HMAC computation
|
||||
* but only one iteration of the KDF is performed. This would be used for
|
||||
* XOR obfuscation so that the mask value can be generated in digest-sized
|
||||
* chunks rather than having to be generated all at once in an arbitrarily
|
||||
* large buffer and then XORed into the result. If "once" is TRUE, then
|
||||
* "sizeInBits" must be a multiple of 8.
|
||||
*
|
||||
* Any error in the processing of this command is considered fatal.
|
||||
*
|
||||
* Return values:
|
||||
* 0 hash algorithm is not supported or is TPM_ALG_NULL
|
||||
* >0 the number of bytes in the 'keyStream' buffer
|
||||
*
|
||||
*/
|
||||
static int TPM2_KDFa(
|
||||
TPM_ALG_ID hashAlg, /* IN: hash algorithm used in HMAC */
|
||||
TPM2B_DATA *key, /* IN: key, can also be used as authValue buffer */
|
||||
TPM2B_AUTH *authValue, /* IN: authValue for unbounded, unsalted session */
|
||||
const char *label, /* IN: a 0-byte terminated label used in KDF */
|
||||
TPM2B_NONCE *contextU, /* IN: context U */
|
||||
TPM2B_NONCE *contextV, /* IN: context V */
|
||||
UINT32 sizeInBits, /* IN: size of generated key in bits */
|
||||
BYTE *keyStream, /* OUT: key buffer */
|
||||
UINT32 *counterInc,/* IN/OUT: See Note for incremental operations */
|
||||
int doOnce /* IN: TRUE if only one iteration is performed */
|
||||
)
|
||||
{
|
||||
#ifndef WOLFTPM2_NO_WOLFCRYPT
|
||||
int ret, hashType;
|
||||
Hmac hmac;
|
||||
word32 counter = 0;
|
||||
int hLen, outLen, lLen = 0;
|
||||
byte *outStream;
|
||||
byte uint32Buf[sizeof(UINT32)];
|
||||
|
||||
if ((key == NULL && authValue == NULL) || keyStream == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (doOnce != 0 && (sizeInBits & 7) != 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
hashType = TPM2_GetHashType(hashAlg);
|
||||
if (hashType == WC_HASH_TYPE_NONE)
|
||||
return NOT_COMPILED_IN;
|
||||
|
||||
hLen = TPM2_GetHashDigestSize(hashAlg);
|
||||
if (hLen <= 0)
|
||||
return NOT_COMPILED_IN;
|
||||
|
||||
ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* setup counter */
|
||||
counter = (counterInc != NULL) ? *counterInc : 0;
|
||||
|
||||
/* get label length if provided */
|
||||
if (label != NULL)
|
||||
lLen = (int)XSTRLEN(label);
|
||||
|
||||
/* generate required bytes */
|
||||
outLen = doOnce ? hLen : (((int)sizeInBits + 7) / 8);
|
||||
outStream = keyStream;
|
||||
|
||||
/* Do we have unbounded, unsalted session? */
|
||||
if (key == NULL) {
|
||||
/* Then, use the authValue to gen session key */
|
||||
key = (TPM2B_DATA *)authValue;
|
||||
}
|
||||
|
||||
for (; outLen > 0; outLen -= hLen) {
|
||||
if (hLen > outLen)
|
||||
hLen = outLen;
|
||||
|
||||
counter++;
|
||||
|
||||
/* start HMAC */
|
||||
ret = wc_HmacSetKey(&hmac, hashType, &key->buffer[0], key->size);
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
||||
/* add counter */
|
||||
TPM2_Packet_U32ToByteArray(counter, uint32Buf);
|
||||
ret = wc_HmacUpdate(&hmac, uint32Buf, (word32)sizeof(uint32Buf));
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
||||
/* add label */
|
||||
if (label != NULL) {
|
||||
ret = wc_HmacUpdate(&hmac, (byte*)label, lLen);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* add contextU */
|
||||
if (contextU != NULL) {
|
||||
ret = wc_HmacUpdate(&hmac, contextU->buffer, contextU->size);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* add contextV */
|
||||
if (contextV != NULL) {
|
||||
ret = wc_HmacUpdate(&hmac, contextV->buffer, contextV->size);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* add size in bits */
|
||||
TPM2_Packet_U32ToByteArray(sizeInBits, (byte*)&uint32Buf);
|
||||
ret = wc_HmacUpdate(&hmac, uint32Buf, (word32)sizeof(uint32Buf));
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
||||
/* get result */
|
||||
ret = wc_HmacFinal(&hmac, outStream);
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
||||
outStream = &outStream[hLen];
|
||||
}
|
||||
|
||||
wc_HmacFree(&hmac);
|
||||
|
||||
/* mask off bits if not a multiple of byte size */
|
||||
if ((sizeInBits % 8) != 0)
|
||||
keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
|
||||
|
||||
/* return counter if provided */
|
||||
if (counterInc != NULL)
|
||||
*counterInc = counter;
|
||||
|
||||
/* return length rounded up to nearest 8 multiple */
|
||||
return ((sizeInBits + 7) / 8);
|
||||
#else
|
||||
(void)hashAlg;
|
||||
(void)key;
|
||||
(void)authValue;
|
||||
(void)label;
|
||||
(void)contextU;
|
||||
(void)contextV;
|
||||
(void)sizeInBits;
|
||||
(void)keyStream;
|
||||
(void)counterInc;
|
||||
(void)doOnce;
|
||||
|
||||
return NOT_COMPILED_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Perform XOR encryption over the first parameter of a TPM packet */
|
||||
static TPM_RC TPM2_ParamEnc_XOR(TPMS_AUTH_COMMAND *session,
|
||||
TPM2B_MAX_BUFFER *encryptedData,
|
||||
BYTE *paramData, UINT32 paramSz)
|
||||
{
|
||||
TPM_RC rc = TPM_RC_FAILURE;
|
||||
TPM2B_MAX_BUFFER mask;
|
||||
/* authValueKDF used for unbounded, unsalted session */
|
||||
TPM2B_AUTH authValueKDF;
|
||||
TPM2B_NONCE nonceNewer, nonceOlder;
|
||||
UINT32 bits = paramSz * 8;
|
||||
UINT32 i, encryptedBytes;
|
||||
|
||||
if (session->auth.size <= sizeof(authValueKDF.buffer)) {
|
||||
authValueKDF.size = session->auth.size;
|
||||
XMEMCPY(authValueKDF.buffer, session->auth.buffer, authValueKDF.size);
|
||||
}
|
||||
if (session->nonce.size <= sizeof(nonceNewer.buffer)) {
|
||||
nonceNewer.size = session->nonce.size;
|
||||
XMEMCPY(nonceNewer.buffer, session->nonce.buffer, nonceNewer.size);
|
||||
}
|
||||
if (session->nonce.size <= sizeof(nonceOlder.buffer)) {
|
||||
nonceOlder.size = nonceNewer.size;
|
||||
XMEMCPY(nonceOlder.buffer, nonceNewer.buffer, nonceOlder.size);
|
||||
}
|
||||
|
||||
XMEMSET(mask.buffer, 0, sizeof(mask.buffer));
|
||||
|
||||
encryptedBytes = TPM2_KDFa(session->authHash, NULL, &authValueKDF, "XOR",
|
||||
&nonceOlder, &nonceNewer, bits, mask.buffer,
|
||||
NULL, 1);
|
||||
if (encryptedBytes == paramSz) {
|
||||
for(i = 0; i < paramSz; i++) {
|
||||
encryptedData->buffer[i] = paramData[i] ^ mask.buffer[i];
|
||||
}
|
||||
encryptedData->size = encryptedBytes;
|
||||
/* Data size matched and data encryption completed at this point */
|
||||
rc = TPM_RC_SUCCESS;
|
||||
}
|
||||
#ifdef WOLFTPM_DEBUG_VERBOSE
|
||||
else {
|
||||
printf("Encrypted data differs in size = %d\n", encryptedBytes);
|
||||
printf("Parameter data original size is = %d\n", paramSz);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* --- Public Functions -- */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Returns MAX_SESSION_NUM if no session is found, otherwise session index */
|
||||
int TPM2_ParamEnc_FindDecryptSession(TPM2_CTX *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_SESSION_NUM; i++) {
|
||||
if ((ctx->authCmd[i].sessionAttributes & TPMA_SESSION_decrypt) &&
|
||||
ctx->authCmd[i].sessionHandle != TPM_RS_PW) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Returns MAX_SESSION_NUM if no session is found, otherwise session index */
|
||||
int TPM2_ParamEnc_FindEncryptSession(TPM2_CTX *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_SESSION_NUM; i++) {
|
||||
if ((ctx->authCmd[i].sessionAttributes & TPMA_SESSION_encrypt) &&
|
||||
ctx->authCmd[i].sessionHandle != TPM_RS_PW) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
TPM_RC TPM2_ParamEnc_CmdRequest(TPMS_AUTH_COMMAND *session,
|
||||
TPM2B_MAX_BUFFER *encryptedParameter,
|
||||
BYTE *paramData, UINT32 paramSz)
|
||||
{
|
||||
TPM_RC rc = TPM_RC_FAILURE;
|
||||
|
||||
if (session->symmetric.algorithm == TPM_ALG_XOR) {
|
||||
rc = TPM2_ParamEnc_XOR(session, encryptedParameter, paramData, paramSz);
|
||||
}
|
||||
else {
|
||||
/* TODO: Add CFB mode
|
||||
rc = TPM2_ParamEnc_CFB_Request(sessionParamEnc, encryptedParameter,
|
||||
paramData, paramSz);
|
||||
*/
|
||||
rc = TPM_RC_FAILURE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
TPM_RC TPM2_ParamEnc_CmdResponse(TPMS_AUTH_COMMAND *session,
|
||||
TPM2B_MAX_BUFFER *encryptedParameter,
|
||||
BYTE *paramData, UINT32 paramSz)
|
||||
{
|
||||
TPM_RC rc = TPM_RC_FAILURE;
|
||||
|
||||
if (session->symmetric.algorithm == TPM_ALG_XOR) {
|
||||
rc = TPM2_ParamEnc_XOR(session, encryptedParameter, paramData, paramSz);
|
||||
}
|
||||
else {
|
||||
/* TODO: Handling CFB mode for response parameter differs
|
||||
rc = TPM2_ParamEnc_CFB_Response(sessionParamEnc, encryptedParameter,
|
||||
paramData, paramSz);
|
||||
*/
|
||||
rc = TPM_RC_FAILURE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ nobase_include_HEADERS+= \
|
|||
wolftpm/tpm2_wrap.h \
|
||||
wolftpm/tpm2_linux.h \
|
||||
wolftpm/tpm2_swtpm.h \
|
||||
wolftpm/tpm2_param_enc.h \
|
||||
wolftpm/version.h \
|
||||
wolftpm/visibility.h \
|
||||
wolftpm/options.h
|
||||
|
|
|
|||
|
|
@ -1570,7 +1570,8 @@ typedef struct TPMS_AUTH_COMMAND {
|
|||
TPMI_SH_AUTH_SESSION sessionHandle;
|
||||
TPM2B_NONCE nonce;
|
||||
TPMA_SESSION sessionAttributes;
|
||||
TPM2B_AUTH auth;
|
||||
TPM2B_AUTH auth; /* TCG Spec Part 2 calls this field hmac */
|
||||
/* TPM2B_AUTH can be an HMAC, a password or an Empty Auth */
|
||||
|
||||
/* Implementation specific */
|
||||
/* These are used for parameter encrypt/decrypt */
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ typedef struct TPM2_Packet {
|
|||
int size;
|
||||
} TPM2_Packet;
|
||||
|
||||
WOLFTPM_LOCAL void TPM2_Packet_U16ToByteArray(UINT16 val, BYTE* b);
|
||||
WOLFTPM_LOCAL void TPM2_Packet_U32ToByteArray(UINT32 val, BYTE* b);
|
||||
|
||||
WOLFTPM_LOCAL UINT16 TPM2_Packet_SwapU16(UINT16 data);
|
||||
WOLFTPM_LOCAL UINT32 TPM2_Packet_SwapU32(UINT32 data);
|
||||
WOLFTPM_LOCAL UINT64 TPM2_Packet_SwapU64(UINT64 data);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
/* tpm2_param_enc.h
|
||||
*
|
||||
* Copyright (C) 2006-2020 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfTPM.
|
||||
*
|
||||
* wolfTPM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfTPM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _TPM2_PARAM_ENC_H_
|
||||
#define _TPM2_PARAM_ENC_H_
|
||||
|
||||
#include <wolftpm/tpm2.h>
|
||||
#include <wolftpm/tpm2_packet.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WOLFTPM_LOCAL int TPM2_ParamEnc_FindDecryptSession(TPM2_CTX *ctx);
|
||||
WOLFTPM_LOCAL int TPM2_ParamEnc_FindEncryptSession(TPM2_CTX *ctx);
|
||||
/* Perform encryption over the first parameter of a TPM packet */
|
||||
WOLFTPM_LOCAL TPM_RC TPM2_ParamEnc_CmdRequest(TPMS_AUTH_COMMAND *session,
|
||||
TPM2B_MAX_BUFFER *encryptedParameter,
|
||||
BYTE *paramData, UINT32 paramSz);
|
||||
WOLFTPM_LOCAL TPM_RC TPM2_ParamEnc_CmdResponse(TPMS_AUTH_COMMAND *session,
|
||||
TPM2B_MAX_BUFFER *encryptedParameter,
|
||||
BYTE *paramData, UINT32 paramSz);
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _TPM2_PARAM_ENC_H_ */
|
||||
Loading…
Reference in New Issue