From d67fb24ae1cf9ddd4be8fa7372710dda81845edb Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Wed, 22 Jan 2025 10:43:53 -0800 Subject: [PATCH] Add verification tests for the "export-cdi" DeriveContext feature --- simulator/src/main.rs | 5 +++ verification/client/abi.go | 59 +++++++++++++++++++++------ verification/sim/transport.go | 3 ++ verification/testing/deriveContext.go | 39 ++++++++++++++++++ verification/testing/simulator.go | 5 +++ verification/testing/verification.go | 5 +++ 6 files changed, 104 insertions(+), 12 deletions(-) diff --git a/simulator/src/main.rs b/simulator/src/main.rs index d12ae05c..015ef899 100644 --- a/simulator/src/main.rs +++ b/simulator/src/main.rs @@ -112,6 +112,10 @@ struct Args { /// Supports the RETAIN_PARENT_CONTEXT extension to DeriveContext #[arg(long)] supports_retain_parent_context: bool, + + /// Supports the CDI_EXPORT extension to DeriveContext + #[arg(long)] + supports_cdi_export: bool, } struct SimTypes {} @@ -156,6 +160,7 @@ fn main() -> std::io::Result<()> { Support::RETAIN_PARENT_CONTEXT, args.supports_retain_parent_context, ); + support.set(Support::CDI_EXPORT, args.supports_cdi_export); let mut env = DpeEnv:: { crypto: ::Crypto::new(), diff --git a/verification/client/abi.go b/verification/client/abi.go index 2ba12073..47421767 100644 --- a/verification/client/abi.go +++ b/verification/client/abi.go @@ -35,6 +35,7 @@ type Support struct { InternalDice bool IsCA bool RetainParentContext bool + CdiExport bool } // profileCommandCodes holds command codes for a specific revision of the @@ -125,6 +126,9 @@ const ( // ContextHandle is a DPE context handle type ContextHandle [16]byte +// ExportedCdi is a handle to an exported CDI +type ExportedCdi [32]byte + // DestroyCtxCmd is input parameters to DestroyContext type DestroyCtxCmd struct { handle ContextHandle @@ -223,6 +227,8 @@ const ( InputAllowCA DeriveContextFlags = 1 << 26 InputAllowX509 DeriveContextFlags = 1 << 25 Recursive DeriveContextFlags = 1 << 24 + CdiExport DeriveContextFlags = 1 << 23 + CreateCertificate DeriveContextFlags = 1 << 22 ) // DeriveContextReq is the input request to DeriveContext @@ -238,16 +244,14 @@ type DeriveContextReq[Digest DigestAlgorithm] struct { type DeriveContextResp struct { NewContextHandle ContextHandle ParentContextHandle ContextHandle + ExportedCdi ExportedCdi + CertificateSize uint32 + NewCertificate []byte } // SignFlags is the input flags to Sign type SignFlags uint32 -// Supported Sign flags -const ( - IsSymmetric SignFlags = 1 << 30 -) - // SignReq is the input request to Sign type SignReq[Digest DigestAlgorithm] struct { ContextHandle ContextHandle @@ -517,15 +521,43 @@ func (c *DPEABI[_, _, _]) GetCertificateChainABI() (*GetCertificateChainResp, er } // DeriveContextABI calls DPE DeriveContext command. -func (c *DPEABI[_, Digest, _]) DeriveContextABI(cmd *DeriveContextReq[Digest]) (*DeriveContextResp, error) { - var respStruct DeriveContextResp +func (c *DPEABI[_, Digest, DPECertificate]) DeriveContextABI(cmd *DeriveContextReq[Digest]) (*DeriveContextResp, error) { + // Define an anonymous struct for the response, because the shape changes if exportCdi is set. + if cmd.Flags&CdiExport == CdiExport { + respStruct := struct { + NewContextHandle [16]byte + ParentContextHandle [16]byte + ExportedCdi [32]byte + CertificateSize uint32 + Certificate DPECertificate + }{} + _, err := execCommand(c.transport, c.constants.Codes.DeriveContext, c.Profile, cmd, &respStruct) + if err != nil { + return nil, err + } - _, err := execCommand(c.transport, c.constants.Codes.DeriveContext, c.Profile, cmd, &respStruct) - if err != nil { - return nil, err - } + return &DeriveContextResp{ + NewContextHandle: respStruct.NewContextHandle, + ParentContextHandle: respStruct.ParentContextHandle, + ExportedCdi: respStruct.ExportedCdi, + CertificateSize: respStruct.CertificateSize, + NewCertificate: respStruct.Certificate.Bytes()[:respStruct.CertificateSize], + }, nil + } else { + respStruct := struct { + NewContextHandle [16]byte + ParentContextHandle [16]byte + }{} + _, err := execCommand(c.transport, c.constants.Codes.DeriveContext, c.Profile, cmd, &respStruct) + if err != nil { + return nil, err + } - return &respStruct, err + return &DeriveContextResp{ + NewContextHandle: respStruct.NewContextHandle, + ParentContextHandle: respStruct.ParentContextHandle, + }, nil + } } // RotateContextHandleABI calls DPE RotateContextHandle command. @@ -738,5 +770,8 @@ func (s *Support) ToFlags() uint32 { if s.RetainParentContext { flags |= (1 << 19) } + if s.CdiExport { + flags |= (1 << 18) + } return flags } diff --git a/verification/sim/transport.go b/verification/sim/transport.go index 19518b7a..3aaf51a5 100644 --- a/verification/sim/transport.go +++ b/verification/sim/transport.go @@ -82,6 +82,9 @@ func (s *DpeSimulator) PowerOn() error { if s.supports.RetainParentContext { args = append(args, "--supports-retain-parent-context") } + if s.supports.CdiExport { + args = append(args, "--supports-cdi-export") + } s.cmd = exec.Command(s.exePath, args...) s.cmd.Stdout = os.Stdout diff --git a/verification/testing/deriveContext.go b/verification/testing/deriveContext.go index 0623d4e8..0ec42931 100644 --- a/verification/testing/deriveContext.go +++ b/verification/testing/deriveContext.go @@ -73,6 +73,45 @@ func TestDeriveContext(d client.TestDPEInstance, c client.DPEClient, t *testing. handle = &resp.NewContextHandle } +func TestDeriveContextCdiExport(d client.TestDPEInstance, c client.DPEClient, t *testing.T) { + var resp *client.DeriveContextResp + + simulation := false + handle := getInitialContextHandle(d, c, t, simulation) + defer func() { + c.DestroyContext(handle) + }() + + profile, err := client.GetTransportProfile(d) + if err != nil { + t.Fatalf("Could not get profile: %v", err) + } + digestLen := profile.GetDigestSize() + + resp, err = c.DeriveContext(handle, make([]byte, digestLen), client.CdiExport|client.CreateCertificate, 0, 0) + if err != nil { + t.Fatalf("[ERROR]: Error while exporting CdiExport: %s", err) + } + + if resp.ExportedCdi == client.ExportedCdi(bytes.Repeat([]byte{0x0}, 32)) { + t.Fatalf("[FATAL]: Expected ExportedCdi field to be set but was %v", resp.ExportedCdi) + } + if resp.NewContextHandle != client.ContextHandle(bytes.Repeat([]byte{0xFF}, 16)) { + t.Fatalf("[FATAL]: Expected invalid NewContextHandle field but it was set to %v", resp.NewContextHandle) + } + if resp.ParentContextHandle != client.ContextHandle(bytes.Repeat([]byte{0xFF}, 16)) { + t.Fatalf("[FATAL]: Expected invalid ParentContextHandle field but it was set to %v", resp.ParentContextHandle) + } + if resp.CertificateSize == 0 { + t.Fatalf("[FATAL]: Expected CertificateSize to be set but was set to %v", resp.CertificateSize) + } + + // Check whether certificate is correctly encoded. + if _, err := x509.ParseCertificate(resp.NewCertificate); err != nil { + t.Fatalf("[FATAL]: Could not parse certificate using crypto/x509: %v", err) + } +} + // Validates DerivedChild command with ChangeLocality flag. func TestChangeLocality(d client.TestDPEInstance, c client.DPEClient, t *testing.T) { if !d.HasLocalityControl() { diff --git a/verification/testing/simulator.go b/verification/testing/simulator.go index 5001eccb..82b7b02e 100644 --- a/verification/testing/simulator.go +++ b/verification/testing/simulator.go @@ -120,6 +120,11 @@ func GetSimulatorTargets() []TestTarget { getTestTarget([]string{"AutoInit", "X509", "RetainParentContext"}), []TestCase{DeriveContextTestCase}, }, + { + "TestDeriveContextCdiExport", + getTestTarget([]string{"AutoInit", "CdiExport"}), + []TestCase{TestDeriveContextCdiExportTestCase}, + }, { "DeriveContext_Simulation", getTestTarget([]string{"AutoInit", "Simulation", "X509", "RetainParentContext"}), diff --git a/verification/testing/verification.go b/verification/testing/verification.go index 65ee6dcb..4f7d0a6b 100644 --- a/verification/testing/verification.go +++ b/verification/testing/verification.go @@ -112,6 +112,11 @@ var DeriveContextTestCase = TestCase{ "DeriveContext", TestDeriveContext, []string{"AutoInit", "RetainParentContext"}, } +// TestDeriveContextCdiExport tests DeriveContext +var TestDeriveContextCdiExportTestCase = TestCase{ + "DeriveContextCdiExport", TestDeriveContextCdiExport, []string{"CdiExport"}, +} + // DeriveContextSimulationTestCase tests DeriveContext with Simulation contexts var DeriveContextSimulationTestCase = TestCase{ "DeriveContextSimulation", TestDeriveContextSimulation, []string{"AutoInit", "Simulation", "X509", "InternalDice", "InternalInfo", "RetainParentContext"},