summaryrefslogtreecommitdiffstats
path: root/src/tpm2/Attest_spt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tpm2/Attest_spt.c')
-rw-r--r--src/tpm2/Attest_spt.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/tpm2/Attest_spt.c b/src/tpm2/Attest_spt.c
new file mode 100644
index 0000000..0b8d29c
--- /dev/null
+++ b/src/tpm2/Attest_spt.c
@@ -0,0 +1,209 @@
+/********************************************************************************/
+/* */
+/* */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* $Id: Attest_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */
+/* */
+/* Licenses and Notices */
+/* */
+/* 1. Copyright Licenses: */
+/* */
+/* - Trusted Computing Group (TCG) grants to the user of the source code in */
+/* this specification (the "Source Code") a worldwide, irrevocable, */
+/* nonexclusive, royalty free, copyright license to reproduce, create */
+/* derivative works, distribute, display and perform the Source Code and */
+/* derivative works thereof, and to grant others the rights granted herein. */
+/* */
+/* - The TCG grants to the user of the other parts of the specification */
+/* (other than the Source Code) the rights to reproduce, distribute, */
+/* display, and perform the specification solely for the purpose of */
+/* developing products based on such documents. */
+/* */
+/* 2. Source Code Distribution Conditions: */
+/* */
+/* - Redistributions of Source Code must retain the above copyright licenses, */
+/* this list of conditions and the following disclaimers. */
+/* */
+/* - Redistributions in binary form must reproduce the above copyright */
+/* licenses, this list of conditions and the following disclaimers in the */
+/* documentation and/or other materials provided with the distribution. */
+/* */
+/* 3. Disclaimers: */
+/* */
+/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
+/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
+/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
+/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
+/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
+/* information on specification licensing rights available through TCG */
+/* membership agreements. */
+/* */
+/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
+/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
+/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
+/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
+/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
+/* */
+/* - Without limitation, TCG and its members and licensors disclaim all */
+/* liability, including liability for infringement of any proprietary */
+/* rights, relating to use of information in this specification and to the */
+/* implementation of this specification, and TCG disclaims all liability for */
+/* cost of procurement of substitute goods or services, lost profits, loss */
+/* of use, loss of data or any incidental, consequential, direct, indirect, */
+/* or special damages, whether under contract, tort, warranty or otherwise, */
+/* arising in any way out of use or reliance upon this specification or any */
+/* information herein. */
+/* */
+/* (c) Copyright IBM Corp. and others, 2016 - 2018 */
+/* */
+/********************************************************************************/
+
+#include "Tpm.h"
+#include "Attest_spt_fp.h"
+/* 7.2.2 Functions */
+/* 7.2.2.1 FillInAttestInfo() */
+/* Fill in common fields of TPMS_ATTEST structure. */
+void
+FillInAttestInfo(
+ TPMI_DH_OBJECT signHandle, // IN: handle of signing object
+ TPMT_SIG_SCHEME *scheme, // IN/OUT: scheme to be used for signing
+ TPM2B_DATA *data, // IN: qualifying data
+ TPMS_ATTEST *attest // OUT: attest structure
+ )
+{
+ OBJECT *signObject = HandleToObject(signHandle);
+ // Magic number
+ attest->magic = TPM_GENERATED_VALUE;
+ if(signObject == NULL)
+ {
+ // The name for a null handle is TPM_RH_NULL
+ // This is defined because UINT32_TO_BYTE_ARRAY does a cast. If the
+ // size of the cast is smaller than a constant, the compiler warns
+ // about the truncation of a constant value.
+ TPM_HANDLE nullHandle = TPM_RH_NULL;
+ attest->qualifiedSigner.t.size = sizeof(TPM_HANDLE);
+ UINT32_TO_BYTE_ARRAY(nullHandle, attest->qualifiedSigner.t.name);
+ }
+ else
+ {
+ // Certifying object qualified name
+ // if the scheme is anonymous, this is an empty buffer
+ if(CryptIsSchemeAnonymous(scheme->scheme))
+ attest->qualifiedSigner.t.size = 0;
+ else
+ attest->qualifiedSigner = signObject->qualifiedName;
+ }
+ // current clock in plain text
+ TimeFillInfo(&attest->clockInfo);
+ // Firmware version in plain text
+ attest->firmwareVersion = ((UINT64)gp.firmwareV1 << (sizeof(UINT32) * 8));
+ attest->firmwareVersion += gp.firmwareV2;
+ // Check the hierarchy of sign object. For NULL sign handle, the hierarchy
+ // will be TPM_RH_NULL
+ if((signObject == NULL)
+ || (!signObject->attributes.epsHierarchy
+ && !signObject->attributes.ppsHierarchy))
+ {
+ // For signing key that is not in platform or endorsement hierarchy,
+ // obfuscate the reset, restart and firmware version information
+ UINT64 obfuscation[2];
+ CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gp.shProof.b, OBFUSCATE_STRING,
+ &attest->qualifiedSigner.b, NULL, 128,
+ (BYTE *)&obfuscation[0], NULL, FALSE);
+ // Obfuscate data
+ attest->firmwareVersion += obfuscation[0];
+ attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32);
+ attest->clockInfo.restartCount += (UINT32)obfuscation[1];
+ }
+ // External data
+ if(CryptIsSchemeAnonymous(scheme->scheme))
+ attest->extraData.t.size = 0;
+ else
+ {
+ // If we move the data to the attestation structure, then it is not
+ // used in the signing operation except as part of the signed data
+ attest->extraData = *data;
+ data->t.size = 0;
+ }
+}
+/* 7.2.2.2 SignAttestInfo() */
+/* Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature is returned. */
+/* Error Returns Meaning */
+/* TPM_RC_ATTRIBUTES signHandle references not a signing key */
+/* TPM_RC_SCHEME scheme is not compatible with signHandle type */
+/* TPM_RC_VALUE digest generated for the given scheme is greater than the modulus of signHandle (for
+ an RSA key); invalid commit status or failed to generate r value (for an ECC key) */
+TPM_RC
+SignAttestInfo(
+ OBJECT *signKey, // IN: sign object
+ TPMT_SIG_SCHEME *scheme, // IN: sign scheme
+ TPMS_ATTEST *certifyInfo, // IN: the data to be signed
+ TPM2B_DATA *qualifyingData, // IN: extra data for the signing
+ // process
+ TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be
+ // signed
+ TPMT_SIGNATURE *signature // OUT: signature
+ )
+{
+ BYTE *buffer;
+ HASH_STATE hashState;
+ TPM2B_DIGEST digest;
+ TPM_RC result;
+ // Marshal TPMS_ATTEST structure for hash
+ buffer = attest->t.attestationData;
+ attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL);
+ if(signKey == NULL)
+ {
+ signature->sigAlg = TPM_ALG_NULL;
+ result = TPM_RC_SUCCESS;
+ }
+ else
+ {
+ TPMI_ALG_HASH hashAlg;
+ // Compute hash
+ hashAlg = scheme->details.any.hashAlg;
+ // need to set the receive buffer to get something put in it
+ digest.t.size = sizeof(digest.t.buffer);
+ digest.t.size = CryptHashBlock(hashAlg, attest->t.size,
+ attest->t.attestationData,
+ digest.t.size, digest.t.buffer);
+ // If there is qualifying data, need to rehash the data
+ // hash(qualifyingData || hash(attestationData))
+ if(qualifyingData->t.size != 0)
+ {
+ CryptHashStart(&hashState, hashAlg);
+ CryptDigestUpdate2B(&hashState, &qualifyingData->b);
+ CryptDigestUpdate2B(&hashState, &digest.b);
+ CryptHashEnd2B(&hashState, &digest.b);
+ }
+ // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or
+ // TPM_RC_ATTRIBUTES error may be returned at this point
+ result = CryptSign(signKey, scheme, &digest, signature);
+ // Since the clock is used in an attestation, the state in NV is no longer
+ // "orderly" with respect to the data in RAM if the signature is valid
+ if(result == TPM_RC_SUCCESS)
+ {
+ // Command uses the clock so need to clear the orderly state if it is
+ // set.
+ result = NvClearOrderly();
+ }
+ }
+ return result;
+}
+/* 7.2.2.3 IsSigningObject() */
+/* Checks to see if the object is OK for signing. This is here rather than in Object_spt.c because
+ all the attestation commands use this file but not Object_spt.c. */
+/* Return Values Meaning */
+/* TRUE object may sign */
+/* FALSE object may not sign */
+BOOL
+IsSigningObject(
+ OBJECT *object // IN:
+ )
+{
+ return ((object == NULL)
+ || ((IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign)
+ && object->publicArea.type != TPM_ALG_SYMCIPHER)));
+}
+