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

Multi tcb info fields validation with derived context #269

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

hpya93
Copy link
Contributor

@hpya93 hpya93 commented Nov 25, 2023

Hi @jhand2
This commit has :

  • MultiTcb information has field-wise validation (apart from checking structure)

  • Verify by deriving more child contexts in non-simulation mode and simulation mode.

    • Check VendorInfo by validating against target locality
    • Check Type by passing Tci type to derived child context
    • Check Fwids[n].hashAlg by validating against expected hash alg OID SHA384/ SHA256 based on DPE profile
    • Check Fwid[0].Digest by passing a TCI value to child context and checking if reflected in TCI_CURRENT of child TCB info
    • Check Fwid[1].Digest by calculating cumulative TCI and cross verification
  • Aside from above checks, have moved helper functions that operate of certificate and cert extensions to certs.go for better readabilty of certifyKey.go. The helper functions will just return errors and caller must handle/log errors using t.Error()

  • Check if multitcb info fwidarray length is 1 when extendtci is not supported by DPE profile.
    Specification contents

{
	Vendor: "",              // Optional and VendorDefined
	Model: "",               // Optional and VendorDefined
	Version: "",             // Omitted
	SVN: 0,                  // Omitted
	Layer: 0,                // Omitted
	Index: 0,                // Omitted
	Fwids: [ 
		{{Digest : [], HashAlg:OID},   // TCI_CURRENT 
                {Digest : [], HashAlg:OID}],   // TCI_CUMULATIVE  omitted when extend_tci is not supported
	]
	Flags: NotConfigured (0), 	// Omitted
	VendorInfo: [0,0,0,0], 		// TARGET_LOCALITY parameter
	Type: [0,0,0,0]}	       // Vendor defined / input (tci_type) provided by a client to DeriveChild
}

@@ -3,11 +3,116 @@
package verification
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functions that validate various fields are moved here from certifyKey.go. This is an effort to keep helper functions that are independent of DPEClient instance in certs.go
This was done to reduce the bloating in CertifyKey.go

@@ -455,6 +54,7 @@ func testCertifyKey(d TestDPEInstance, c DPEClient, t *testing.T, simulation boo

certifyKeyParams := []CertifyKeyParams{
{Label: make([]byte, digestLen), Flags: CertifyKeyFlags(0)},
{Label: make([]byte, digestLen), Flags: CertifyKeyFlags(CertifyAddIsCA)},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new test case to check if IS_CA is set.

checkWithDerivedChildContextSimulation(d, c, t, handle)
} else {
checkWithDerivedChildContext(d, c, t, handle)
}
Copy link
Contributor Author

@hpya93 hpya93 Nov 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommended to have two separate methods to test derived child contexts as clubbing together lead to confusing if-elses.
The simulation mode varies in locality, Derivechild flags, not needing restoration of parent handle etc...

// - the "fwid" field must contain cumulative TCI measurement.
func checkWithDerivedChildContext(d TestDPEInstance, c DPEClient, t *testing.T, handle *ContextHandle) {
profile, err := GetTransportProfile(d)
if err != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New method after adding DeriveContext support.
Derives child contexzt, preserves & rotates back default handle, focusses on multi tcb info fields validation.

keyUsageNames := []string{}
// Checks Multi Tcb Info for context derived from simulation mode
func checkWithDerivedChildContextSimulation(d TestDPEInstance, c DPEClient, t *testing.T, handle *ContextHandle) {
profile, err := GetTransportProfile(d)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New method after adding DeriveContext support.
Derives child context from simulated context, there is no need to preserve & rotate back parent handle, focusses on multi tcb info fields validation.

// FWID at index 1 has the TCI_CUMULATIVE as digest
// The length of FWID array in each DICE TCB information block is 2.
func validateDiceTcbFwids(leafCertBytes []byte, expectedCurrentTci []byte) error {
var leafCert *x509.Certificate
Copy link
Contributor Author

@hpya93 hpya93 Nov 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function cycles through all multi TCB info blocks and validates cumulative measurement, it gets the current TCI values from caller - the most recend node's current TCI value will be added first in this input list.

verification/certs.go Outdated Show resolved Hide resolved
verification/certs.go Outdated Show resolved Hide resolved
verification/certs.go Outdated Show resolved Hide resolved
verification/certs.go Outdated Show resolved Hide resolved
@@ -18,12 +123,12 @@ func getMultiTcbInfo(c *x509.Certificate) (TcgMultiTcbInfo, error) {
for _, ext := range c.Extensions {
if ext.Id.Equal(OidExtensionTcgDiceMultiTcbInfo) { // OID for Tcg Dice MultiTcbInfo
if !ext.Critical {
return multiTcbInfo, fmt.Errorf("[ERROR]: TCG DICE MultiTcbInfo extension is not marked as CRITICAL")
return multiTcbInfo, fmt.Errorf("multiTcbInfo extension is not marked as CRITICAL")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to smallcase as IDE kept complaining that error message should not start with Upper case, have new lines and have punctuation at the end.

)

type TcgMultiTcbInfo = []DiceTcbInfo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some required structs and constants

binary.Write(flagsBuf, binary.LittleEndian, flags)
// Checks whether FWID array omits index-1 when extend TCI is not supported in DPE profile.
func TestCertifyKeyWithoutExtendTciSupport(d TestDPEInstance, c DPEClient, t *testing.T) {
simulation := false
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New test case to check if FWID[1] is omitted when no extendTCI support in DPE profile

Comment on lines 578 to 520
for i, tcbinfo := range multiTcbInfo {
currentTci := tcbinfo.Fwids[0].Digest
cumulativeTci := tcbinfo.Fwids[1].Digest
hasher.Reset()
hasher.Write(lastCumulativeTCI)
hasher.Write(currentTci)
expectedCumulativeValue := hasher.Sum(nil)
if !bytes.Equal(cumulativeTci, expectedCumulativeValue) {
return fmt.Errorf("cumulative TCI value for TCB block-%d, want %v but got %v", i, expectedCumulativeValue, cumulativeTci)
}
lastCumulativeTCI = cumulativeTci
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TCI_CUMULATIVE isn't a hash of all the currents from TcbInfos in the cert. TCI_CUMULATIVE gets extended whenever the ExtendTCI command is called on a node so for a given TCI Node X, TCI_CUMULATIVE is calculated using all the values input for each call to ExtendTCI(handle=X, input_data=input).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rectified the issue

if !d.GetSupport().ExtendTci {
t.Errorf("ExtendTCI is unsupported by profile, unable to run tests to verify TCI_CUMULATIVE measurement")
return
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because extendTCI when not supported cumulative hash will be omitted from FWID array

for i := range childTCI2 {
childTCI2[i] = byte(i + 2)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to try TCB validation for multiple TCI nodes with different TCI inputs

return opts
childHandle = &certifiedKey.Handle
leafCertBytes := certifiedKey.Certificate

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update child handle for cleanup.


// Build list of tci_current for validation and use it for validating TCI measurements
currentTCIs := [][]byte{childTCI2, childTCI1}
if err = validateDiceTcbFwids(leafCertBytes, currentTCIs, digestLen); err != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rectified the issue pointed out.

// Check cumulative, current TCI of other indices if any
lastCumulativeTCI := defaultTci
multiTcbInfo = multiTcbInfo[:lastIndex]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate validation for the last index as the TCI_CURRENT = TCI_CUMULATIVE = Default TCI.

wantCurrentTci := currentTcis[i]
verifyDiceTcbDigest(tcbinfo, wantCurrentTci, lastCumulativeTCI)
}
return err
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cross verify the TCI_CUMULATIVE with TCI_CURRENT value passed.

@hpya93 hpya93 reopened this Dec 12, 2023
@hpya93 hpya93 closed this Dec 16, 2023
@hpya93 hpya93 reopened this Dec 19, 2023
"CertifyKey_TcbValidation",
getTestTarget([]string{"AutoInit", "Simulation", "X509", "Csr", "IsCA", "RotateContext", "ExtendTci"}),
[]TestCase{DiceTcbValidationTestCase, DiceTcbValidationSimulationTestCase},
},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have added this as separate test target.
As per a comment in #PR250, it was mentioned to move tests that modify DPE tree out of basic testcases.
I addressed it in this PR because it is relevant to CertifyKey command.
If i had to include these tests in "AllTestCases" list, I had to use RetainParent, ChangeLocality(for Sim mode), so that the parent context wouyld be available for further tests.

"CheckDiceTcbInfo", TestDiceTcbInfo, []string{"AutoInit", "X509", "IsCA", "RotateContext", "ExtendTci"},
}
var DiceTcbValidationSimulationTestCase = TestCase{
"CheckDiceTcbInfoInSimulationMode", TestDiceTcbInfoSimulation, []string{"AutoInit", "Simulation", "X509", "IsCA", "RotateContext", "ExtendTci"},
Copy link
Contributor Author

@hpya93 hpya93 Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having DiceTcb Validation as separate test from CertifyKey as it uses DeriveChild command and due to aforementioned reason.

)

type TcgMultiTcbInfo = []DiceTcbInfo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to certs.go

func TestDiceTcbInfoSimulation(d TestDPEInstance, c DPEClient, t *testing.T) {
testDiceTcbInfo(d, c, t, true)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate test case to validate DiceTcb with derived contexts in normal mode and Sim mode.

// unknownExtnMap collects extensions unknown to both x509 and the DICE certificate profiles spec.
// positive case expects the unknownExtnMap to be empty.
func removeTcgDiceCriticalExtensions(t *testing.T, certs []*x509.Certificate) {
t.Helper()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the utility function to certs.go

// unknownKeyUsagesMap collects keyusages unknown to both x509 and the DICE certificate profiles spec.
// positive case expects the unknownKeyUsagesMap to be empty.
func removeTcgDiceExtendedKeyUsages(t *testing.T, certs []*x509.Certificate) {
t.Helper()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the utility function to certs.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants