Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add support for enabling the SVN-limited hierarchy #470

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
2 changes: 2 additions & 0 deletions include/libtpms/tpm_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ TPM_RESULT TPMLIB_SetProfile(const char *profile);

TPM_BOOL TPMLIB_WasManufactured(void);

TPM_RESULT TPMLIB_RecreateSvnBaseSecret(void);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions include/libtpms/tpm_library.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ TPM_RESULT TPMLIB_SetProfile(const char *profile);

TPM_BOOL TPMLIB_WasManufactured(void);

TPM_RESULT TPMLIB_RecreateSvnBaseSecret(void);

#ifdef __cplusplus
}
#endif
Expand Down
1 change: 1 addition & 0 deletions man/man3/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ man3_PODS = \
TPMLIB_GetVersion.pod \
TPMLIB_MainInit.pod \
TPMLIB_Process.pod \
TPMLIB_RecreateSvnBaseSecret.pod \
TPMLIB_RegisterCallbacks.pod \
TPMLIB_SetBufferSize.pod \
TPMLIB_SetDebugFD.pod \
Expand Down
37 changes: 37 additions & 0 deletions man/man3/TPMLIB_RecreateSvnBaseSecret.pod
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
=head1 NAME

TPMLIB_RecreateSvnBaseSecret - Recreate a TPM 2's SVN-limited hierarchy base secret

=head1 LIBRARY

TPM library (libtpms, -ltpms)

=head1 SYNOPSIS

B<#include <libtpms/tpm_types.h>>

B<#include <libtpms/tpm_library.h>>

B<#include <libtpms/tpm_error.h>>

B<TPM_RESULT TPMLIB_RecreateSvnBaseSecret(void);>

=head1 DESCRIPTION

B<TPMLIB_RecreateSvnBaseSecret()> is used to recreate the internal base SVN
secret that is used for by the SVN-limited hierachy to derive its secret
from by adding the 16bit SVN number to it. Since the SVN base secret is part
of the permanent/persistent state of a TPM 2, this function should be called
after loading the state or before processing the first command. This can for
example be done right after I<TPMLIB_MainInit()> or as late as just before
I<TPMLIB_Process()>.

The side effect of recreating the base SVN secret is that previous firmware
SVN secrets cannot be created anymore and objects (keys) associated with the
SVN-limited hierachy cannot be used anymore.

=head1 SEE ALSO

B<TPMLIB_MainInit>, B<TPMLIB_Process>(3)

=cut
12 changes: 12 additions & 0 deletions man/man3/TPMLIB_SetProfile.pod
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ This I<StateFormatLevel> enabled the following profile attributes:

=back

=item 8: (since v0.10)

This I<StateFormatLevel> enabled the I<svn-limited-hierarchy> attribute.

=back

A user may specify the I<StateFormatLevel> when using the I<custom> profile.
Expand Down Expand Up @@ -304,6 +308,14 @@ keys

=back

=item B<svn-limited-hierarchy>: (since v0.10)

=over 2

=item * Enable the SVN-limited hierarchy

=back

=back

=head1 FIPS mode on the host
Expand Down
6 changes: 6 additions & 0 deletions src/disabled_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ static TPM_BOOL Disabled_WasManufactured(void)
return FALSE;
}

static TPM_RESULT Disabled_RecreateSvnBaseSecret(void)
{
return TPM_FAIL;
}

const struct tpm_interface DisabledInterface = {
.MainInit = Disabled_MainInit,
.Terminate = Disabled_Terminate,
Expand All @@ -128,4 +133,5 @@ const struct tpm_interface DisabledInterface = {
.SetState = Disabled_SetState,
.GetState = Disabled_GetState,
.WasManufactured = Disabled_WasManufactured,
.RecreateSvnBaseSecret = Disabled_RecreateSvnBaseSecret,
};
1 change: 1 addition & 0 deletions src/libtpms.syms
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ LIBTPMS_0.10.0 {
global:
TPMLIB_SetProfile;
TPMLIB_WasManufactured;
TPMLIB_RecreateSvnBaseSecret;
local:
*;
} LIBTPMS_0.6.0;
4 changes: 4 additions & 0 deletions src/tpm2/Global.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ TPM2B_TYPE(PROOF, PROOF_SIZE);
// Definition for a Primary Seed value
TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE);

// Definition for Svn base secret
TPM2B_TYPE(SVN_BASE_SECRET, 16);
extern TPM2B_SVN_BASE_SECRET g_SvnBaseSecret;

// A CLOCK_NONCE is used to tag the time value in the authorization session and
// in the ticket computation so that the ticket expires when there is a time
// discontinuity. When the clock stops during normal operation, the nonce is
Expand Down
13 changes: 12 additions & 1 deletion src/tpm2/Handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ NextPermanentHandle(TPM_HANDLE inHandle // IN: the handle to check
case TPM_RH_FW_PLATFORM:
case TPM_RH_FW_NULL:
#endif
#if SVN_LIMITED_SUPPORT
#if 0 //SVN_LIMITED_SUPPORT // libtpms changed
case TPM_RH_SVN_OWNER_BASE:
case TPM_RH_SVN_ENDORSEMENT_BASE:
case TPM_RH_SVN_PLATFORM_BASE:
Expand All @@ -135,6 +135,17 @@ NextPermanentHandle(TPM_HANDLE inHandle // IN: the handle to check

return inHandle;
break;
#if SVN_LIMITED_SUPPORT // libtpms added begin
case TPM_RH_SVN_OWNER_BASE:
case TPM_RH_SVN_ENDORSEMENT_BASE:
case TPM_RH_SVN_PLATFORM_BASE:
case TPM_RH_SVN_NULL_BASE:
if(RuntimeProfileHasAttributeFlags(&g_RuntimeProfile,
RUNTIME_ATTRIBUTE_SVN_LIMITED_HIERARCHY))
return inHandle;

break;
#endif // libtpms added end
default:
break;
}
Expand Down
6 changes: 6 additions & 0 deletions src/tpm2/Hierarchy.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ static TPM_RC GetAdditionalSecret(const HIERARCHY_MODIFIER* modifier, // I
case HM_SVN_LIMITED:
{
#if SVN_LIMITED_SUPPORT
if(!RuntimeProfileHasAttributeFlags(&g_RuntimeProfile, // libtpms added begin
RUNTIME_ATTRIBUTE_SVN_LIMITED_HIERARCHY))
return TPM_RC_SVN_LIMITED; // libtpms added end
if(_plat__GetTpmFirmwareSvnSecret(modifier->min_svn,
sizeof(secret_buffer->t.buffer),
secret_buffer->t.buffer,
Expand Down Expand Up @@ -514,6 +517,9 @@ TPM_RC ValidateHierarchy(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy
case HM_SVN_LIMITED:
{
#if SVN_LIMITED_SUPPORT
if(!RuntimeProfileHasAttributeFlags(&g_RuntimeProfile, // libtpms added begin
RUNTIME_ATTRIBUTE_SVN_LIMITED_HIERARCHY))
return TPM_RC_SVN_LIMITED; // libtpms added end
// SVN-limited hierarchies are only enabled for SVNs less than or
// equal to the current firmware's SVN.
if(modifier.min_svn > _plat__GetTpmFirmwareSvn())
Expand Down
5 changes: 4 additions & 1 deletion src/tpm2/Manufacture.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ TPM_Manufacture(
IsTestStateSet(ENTROPY),
IsDrbgTested());
return -1;
} // libtpms added end
}
if (firstTime && _plat__SvnBaseSecretGenerate() < 0)
return -1;
// libtpms added end
// default configuration for PCR
PCRManufacture();

Expand Down
17 changes: 15 additions & 2 deletions src/tpm2/NVMarshal.c
Original file line number Diff line number Diff line change
Expand Up @@ -5060,7 +5060,7 @@ USER_NVRAM_Unmarshal(BYTE **buffer, INT32 *size)
* - indexOrderlyRAM (NV_INDEX_RAM_DATA)
* - NVRAM locations (NV_USER_DYNAMIC)
*/
#define PERSISTENT_ALL_VERSION 4
#define PERSISTENT_ALL_VERSION 5
#define PERSISTENT_ALL_MAGIC 0xab364723
UINT32
PERSISTENT_ALL_Marshal(BYTE **buffer, INT32 *size)
Expand Down Expand Up @@ -5094,8 +5094,11 @@ PERSISTENT_ALL_Marshal(BYTE **buffer, INT32 *size)
case 1:
blob_version = 3;
break;
case 2 ... 7:
blob_version = 4;
break;
default:
blob_version = 4; /* since stateFormatLevel 2 */
blob_version = 5; /* since stateFormatLevel 8 */
break;
}

Expand All @@ -5112,6 +5115,10 @@ PERSISTENT_ALL_Marshal(BYTE **buffer, INT32 *size)
assert(profileJSON);
written += String_Marshal(profileJSON, buffer, size); // since v4
}
if (blob_version >= 5) {
written += TPM2B_Marshal(&g_SvnBaseSecret.b, sizeof(g_SvnBaseSecret.t.buffer),
buffer, size);
}
written += PACompileConstants_Marshal(buffer, size);
written += PERSISTENT_DATA_Marshal(&pd, buffer, size, RuntimeProfile);
written += ORDERLY_DATA_Marshal(&od, buffer, size);
Expand Down Expand Up @@ -5168,6 +5175,12 @@ PERSISTENT_ALL_Unmarshal(BYTE **buffer, INT32 *size)
rc = String_Unmarshal(&profileJSON, buffer, size);
}
}
if (rc == TPM_RC_SUCCESS) {
if (hdr.version >= 5) {
rc = TPM2B_Unmarshal(&g_SvnBaseSecret.b, sizeof(g_SvnBaseSecret.t.buffer),
buffer, size);
}
}
if (rc == TPM_RC_SUCCESS) {
/* set the profile read from the state */
rc = RuntimeProfileSet(&g_RuntimeProfile, profileJSON, false);
Expand Down
7 changes: 6 additions & 1 deletion src/tpm2/Object_spt.c
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,12 @@ PublicAttributesValidation(
}
if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, svnLimited))
{
#if SVN_LIMITED_SUPPORT // libtpms added
#if SVN_LIMITED_SUPPORT // libtpms added begin
if(!RuntimeProfileHasAttributeFlags(&g_RuntimeProfile,
RUNTIME_ATTRIBUTE_SVN_LIMITED_HIERARCHY))
{
return TPM_RCS_ATTRIBUTES;
} // libtpms added end
if(parentObject != NULL)
{
// For an ordinary object, svnLimited can only be set if its
Expand Down
2 changes: 2 additions & 0 deletions src/tpm2/RuntimeAttributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ static const struct {
7),
ATTRIBUTE("no-ecc-key-derivation", RUNTIME_ATTRIBUTE_NO_ECC_KEY_DERIVATION,
7),
ATTRIBUTE("svn-limited-hierarchy", RUNTIME_ATTRIBUTE_SVN_LIMITED_HIERARCHY,
8),
};

LIB_EXPORT void
Expand Down
3 changes: 2 additions & 1 deletion src/tpm2/RuntimeAttributes_fp.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
#ifndef RUNTIME_ATTRIBUTES_H
#define RUNTIME_ATTRIBUTES_H

#define NUM_ENTRIES_ATTRIBUTE_PROPERTIES 10
#define NUM_ENTRIES_ATTRIBUTE_PROPERTIES 11

#define RUNTIME_ATTRIBUTE_NO_UNPADDED_ENCRYPTION (1 << 0)
#define RUNTIME_ATTRIBUTE_NO_SHA1_SIGNING (1 << 1)
Expand All @@ -52,6 +52,7 @@
#define RUNTIME_ATTRIBUTE_DRBG_CONTINOUS_TEST (1 << 5)
#define RUNTIME_ATTRIBUTE_PAIRWISE_CONSISTENCY_TEST (1 << 6)
#define RUNTIME_ATTRIBUTE_NO_ECC_KEY_DERIVATION (1 << 7)
#define RUNTIME_ATTRIBUTE_SVN_LIMITED_HIERARCHY (1 << 8)

struct RuntimeAttributes {
/* */
Expand Down
11 changes: 8 additions & 3 deletions src/tpm2/RuntimeProfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ const char defaultAlgorithmsProfile[] =
"ecc-bn,ecc-sm2-p256,symcipher,camellia,camellia-min-size=128,cmac,"
"ctr,ofb,cbc,cfb,ecb";

const char defaultAttributesProfile[] =
"svn-limited-hierarchy";

static const struct RuntimeProfileDesc {
const char *name;
#define MAX_PROFILE_NAME_LEN 32
Expand All @@ -78,7 +81,7 @@ static const struct RuntimeProfileDesc {
* This basically locks the name of the profile to the stateFormatLevel.
*/
unsigned int stateFormatLevel;
#define STATE_FORMAT_LEVEL_CURRENT 7
#define STATE_FORMAT_LEVEL_CURRENT 8
#define STATE_FORMAT_LEVEL_UNKNOWN 0 /* JSON didn't provide StateFormatLevel; this is only
allowed for the 'default' profile or when user
passed JSON via SetProfile() */
Expand All @@ -105,6 +108,7 @@ static const struct RuntimeProfileDesc {
* - drbg-continous-test
* - pct
* - no-ecc-key-derivation
* 8 : Attribute 'svn-limited-hierarchy' was added
*/
const char *description;
#define DESCRIPTION_MAX_SIZE 250
Expand All @@ -118,6 +122,7 @@ static const struct RuntimeProfileDesc {
.name = DEFAULT_PROFILE_NAME,
.commandsProfile = defaultCommandsProfile,
.algorithmsProfile = defaultAlgorithmsProfile,
.attributesProfile = defaultAttributesProfile,
.stateFormatLevel = STATE_FORMAT_LEVEL_CURRENT, /* should always be the latest */
.description = "This profile enables all libtpms v0.10-supported commands and "
"algorithms. This profile is compatible with libtpms >= v0.10.",
Expand Down Expand Up @@ -965,8 +970,8 @@ RuntimeProfileGetSeedCompatLevel(void)
case 1: /* profile runs on v0.9 */
return SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX;

case 2 ... 7: /* profile runs on v0.10 */ {
MUST_BE(STATE_FORMAT_LEVEL_CURRENT == 7); // force update when this changes
case 2 ... 8: /* profile runs on v0.10 */ {
MUST_BE(STATE_FORMAT_LEVEL_CURRENT == 8); // force update when this changes
return SEED_COMPAT_LEVEL_LAST;
}

Expand Down
7 changes: 7 additions & 0 deletions src/tpm2/RuntimeProfile_fp.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,12 @@ SEED_COMPAT_LEVEL RuntimeProfileGetSeedCompatLevel(void);
BOOL
RuntimeProfileRequiresAttributeFlags(struct RuntimeProfile *RuntimeProfile,
unsigned int attributeFlags);
static inline BOOL
RuntimeProfileHasAttributeFlags(struct RuntimeProfile *RuntimeProfile,
unsigned int attributeFlags)
{
return RuntimeProfileRequiresAttributeFlags(RuntimeProfile,
attributeFlags);
}

#endif /* RUNTIME_PROFILE_H */
2 changes: 1 addition & 1 deletion src/tpm2/TpmProfile_Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@
// Defines controlling Firmware- and SVN-limited objects
//***********************************************
#define FW_LIMITED_SUPPORT NO // libtpms: NO
#define SVN_LIMITED_SUPPORT NO // libtpms: NO
#define SVN_LIMITED_SUPPORT YES // libtpms: YES (StateFormatLevel 8)

//***********************************************
// Defines controlling External NV
Expand Down
Loading