From 12e85f9cf94ad45fe382b29cab56aa748166de22 Mon Sep 17 00:00:00 2001 From: Jordan Hand Date: Mon, 18 Dec 2023 12:29:54 -0800 Subject: [PATCH] Resolve all golint errors and run in CI golint ensures exported values are documented and generally enforces consistent Go style. Fix all the existing issues and run golint in CI to prevent future lint errors. --- .github/workflows/ci.yml | 4 + Cargo.lock | 161 ++++++++++++++++++++++++++++ ci.sh | 1 + verification/abi.go | 117 +++++++++++++------- verification/certifyKey.go | 73 +++++++------ verification/certs.go | 1 + verification/client.go | 7 ++ verification/errors.go | 3 + verification/extendTCI.go | 6 +- verification/getCertificateChain.go | 1 + verification/getProfile.go | 11 +- verification/initializeContext.go | 2 + verification/negativeCases.go | 13 ++- verification/profile.go | 10 +- verification/rotateContextHandle.go | 3 + verification/sign.go | 6 +- verification/simulator.go | 81 ++++++++------ verification/tpm.go | 1 + verification/transport.go | 11 +- verification/verification.go | 45 +++++++- 20 files changed, 437 insertions(+), 120 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5203a31b..32da872b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,10 @@ jobs: run: | echo "Build-Test: release_ref=$(git rev-parse HEAD)" + - name: Install golint + run: | + go install golang.org/x/lint/golint@latest + # The runner image has rustup with stable (with clippy and rustfmt). So we # just need to update to use the most recent stable. - name: Update rustup diff --git a/Cargo.lock b/Cargo.lock index 81df4f30..b9d7d82c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,6 +134,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.21.5" @@ -275,15 +281,33 @@ name = "crypto" version = "0.1.0" dependencies = [ "arrayvec", + "base64ct", + "ecdsa", "hkdf", + "hmac", "openssl", + "p256", + "p384", "rand", + "sec1", "sha2", "strum", "strum_macros", "zeroize", ] +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -364,6 +388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -398,6 +423,41 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "env_logger" version = "0.10.1" @@ -421,6 +481,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "flagset" version = "0.4.4" @@ -450,6 +520,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -463,6 +534,17 @@ dependencies = [ "wasi", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "heck" version = "0.4.1" @@ -656,6 +738,30 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "pem" version = "2.0.1" @@ -675,6 +781,16 @@ dependencies = [ "base64ct", ] +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.27" @@ -685,8 +801,10 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" name = "platform" version = "0.1.0" dependencies = [ + "cfg-if", "openssl", "ufmt", + "x509-cert", ] [[package]] @@ -701,6 +819,15 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro2" version = "1.0.69" @@ -778,6 +905,16 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "rusticata-macros" version = "4.1.0" @@ -806,6 +943,20 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "serde" version = "1.0.192" @@ -837,6 +988,16 @@ dependencies = [ "digest", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "simulator" version = "0.1.0" diff --git a/ci.sh b/ci.sh index 1b97a233..5f4e08a2 100755 --- a/ci.sh +++ b/ci.sh @@ -37,6 +37,7 @@ function format_rust_targets() { function format_go_targets() { ( cd verification test -z "$(gofmt -l .)" + test -z "$(golint)" ) } diff --git a/verification/abi.go b/verification/abi.go index 63f76607..a78ad636 100755 --- a/verification/abi.go +++ b/verification/abi.go @@ -7,18 +7,22 @@ import ( "reflect" ) +// DefaultContextHandle is the default DPE context handle var DefaultContextHandle = ContextHandle{0} +// Profile-defined constants const ( CmdMagic uint32 = 0x44504543 RespMagic uint32 = 0x44504552 - CURRENT_PROFILE_MAJOR_VERSION uint16 = 0 - CURRENT_PROFILE_MINOR_VERSION uint16 = 8 + CurrentProfileMajorVersion uint16 = 0 + CurrentProfileMinorVersion uint16 = 8 ) +// CommandCode is a DPE command code type CommandCode uint32 +// Support is the set of features a DPE supports type Support struct { Simulation bool ExtendTci bool @@ -32,6 +36,7 @@ type Support struct { IsCA bool } +// All DPE profile command codes const ( CommandGetProfile CommandCode = 0x1 CommandInitializeContext CommandCode = 0x7 @@ -44,77 +49,94 @@ const ( CommandExtendTCI CommandCode = 0x81 ) +// CommandHdr is the DPE command header common to all commands type CommandHdr struct { magic uint32 cmd CommandCode profile Profile } +// RespHdr is the DPE response header common to all responses type RespHdr struct { Magic uint32 Status Status Profile Profile } +// InitCtxCmd is the input parameters to InitializeContext type InitCtxCmd struct { flags InitCtxFlags } +// InitCtxFlags is the input flags to InitializeContext type InitCtxFlags uint32 +// Supported flags to InitializeContext const ( InitIsSimulation InitCtxFlags = 1 << 31 InitIsDefault InitCtxFlags = 1 << 30 ) +// ContextHandle is a DPE context handle type ContextHandle [16]byte +// DestroyCtxFlags is input flags to DestroyContext type DestroyCtxFlags uint32 +// Supported flags to DestroyContext const ( DestroyDescendants DestroyCtxFlags = 1 << 31 ) +// DestroyCtxCmd is input parameters to DestroyContext type DestroyCtxCmd struct { handle ContextHandle flags DestroyCtxFlags } -func NewDestroyCtx(handle ContextHandle, destroy_descendants bool) *DestroyCtxCmd { +// NewDestroyCtx creates a new DestroyContext command +func NewDestroyCtx(handle ContextHandle, destroyDescendants bool) *DestroyCtxCmd { flags := DestroyCtxFlags(0) - if destroy_descendants { + if destroyDescendants { flags |= DestroyDescendants } return &DestroyCtxCmd{handle: handle, flags: flags} } +// InitCtxResp is the response parameters from InitializeContext type InitCtxResp struct { Handle ContextHandle } +// GetProfileResp is the response from GetProfile type GetProfileResp struct { Profile Profile MajorVersion uint16 MinorVersion uint16 - VendorId uint32 + VendorID uint32 VendorSku uint32 MaxTciNodes uint32 Flags uint32 } +// CertifyKeyFlags is the input flags to CertifyKey type CertifyKeyFlags uint32 +// Supported flags to CertifyKey const ( CertifyAddIsCA CertifyKeyFlags = 1 << 30 ) +// CertifyKeyFormat is the requested output format of the DPE key certification type CertifyKeyFormat uint32 +// Supported CertifyKey formats const ( CertifyKeyX509 CertifyKeyFormat = 0 CertifyKeyCsr CertifyKeyFormat = 1 ) +// CertifyKeyReq is the input request to CertifyKey type CertifyKeyReq[Digest DigestAlgorithm] struct { ContextHandle ContextHandle Flags CertifyKeyFlags @@ -122,6 +144,7 @@ type CertifyKeyReq[Digest DigestAlgorithm] struct { Format CertifyKeyFormat } +// CertifyKeyResp is the output response from CertifyKey type CertifyKeyResp[CurveParameter Curve, Digest DigestAlgorithm] struct { NewContextHandle ContextHandle DerivedPublicKeyX CurveParameter @@ -129,32 +152,41 @@ type CertifyKeyResp[CurveParameter Curve, Digest DigestAlgorithm] struct { Certificate []byte } +// GetCertificateChainReq is the input request to GetCertificateChain type GetCertificateChainReq struct { Offset uint32 Size uint32 } + +// GetCertificateChainResp is the output response from GetCertificateChain type GetCertificateChainResp struct { CertificateSize uint32 CertificateChain []byte } +// RotateContextHandleFlags is the input flags to RotateContextHandle type RotateContextHandleFlags uint32 +// Supported RotateContextHandle flags const ( TargetIsDefault RotateContextHandleFlags = 1 << 31 ) +// RotateContextHandleCmd is the input command to RotateContextHandle type RotateContextHandleCmd struct { Handle ContextHandle Flags RotateContextHandleFlags } +// RotatedContextHandle is the response from RotateContextHandle type RotatedContextHandle struct { NewContextHandle ContextHandle } +// DeriveChildFlags is the input flags to DeriveChild type DeriveChildFlags uint32 +// Supported flags to DeriveChild const ( InternalInputInfo DeriveChildFlags = 1 << 31 InternalInputDice DeriveChildFlags = 1 << 30 @@ -165,6 +197,7 @@ const ( InputAllowX509 DeriveChildFlags = 1 << 25 ) +// DeriveChildReq is the input request to DeriveChild type DeriveChildReq[Digest DigestAlgorithm] struct { ContextHandle ContextHandle InputData Digest @@ -173,17 +206,21 @@ type DeriveChildReq[Digest DigestAlgorithm] struct { TargetLocality uint32 } +// DeriveChildResp is the output response from DeriveChild type DeriveChildResp struct { NewContextHandle ContextHandle ParentContextHandle ContextHandle } +// 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 Label Digest @@ -191,40 +228,43 @@ type SignReq[Digest DigestAlgorithm] struct { ToBeSigned Digest } +// SignResp is the output response from Sign type SignResp[Digest DigestAlgorithm] struct { NewContextHandle ContextHandle HmacOrSignatureR Digest SignatureS Digest } +// ExtendTCIReq is the input request to ExtendTCI type ExtendTCIReq[Digest DigestAlgorithm] struct { ContextHandle ContextHandle InputData Digest } +// ExtendTCIResp is the output response from ExtendTCI type ExtendTCIResp struct { NewContextHandle ContextHandle } -// dpeABI is a connection to a DPE instance, parameterized by hash algorithm and ECC curve. -type dpeABI[CurveParameter Curve, Digest DigestAlgorithm] struct { +// DPEABI is a connection to a DPE instance, parameterized by hash algorithm and ECC curve. +type DPEABI[CurveParameter Curve, Digest DigestAlgorithm] struct { transport Transport Profile Profile MajorVersion uint16 MinorVersion uint16 - VendorId uint32 + VendorID uint32 VendorSku uint32 MaxTciNodes uint32 Flags uint32 } // DPEABI256 is a client that implements DPE_PROFILE_IROT_P256_SHA256 -type DPEABI256 = dpeABI[NISTP256Parameter, SHA256Digest] +type DPEABI256 = DPEABI[NISTP256Parameter, SHA256Digest] // DPEABI384 is a client that implements DPE_PROFILE_IROT_P384_SHA384 -type DPEABI384 = dpeABI[NISTP384Parameter, SHA384Digest] +type DPEABI384 = DPEABI[NISTP384Parameter, SHA384Digest] -// dpeProfileImplementsTypeConstraints checks that the requested dpeABI type constraints are compatible with the DPE profile. +// dpeProfileImplementsTypeConstraints checks that the requested DPEABI type constraints are compatible with the DPE profile. func dpeProfileImplementsTypeConstraints[C Curve, D DigestAlgorithm](profile Profile) error { // Test that the expected value types produced by each DPE profile can be assigned to variables of type C and D var c C @@ -253,7 +293,7 @@ func dpeProfileImplementsTypeConstraints[C Curve, D DigestAlgorithm](profile Pro } // newDPEABI initializes a new DPE client. -func newDPEABI[C Curve, D DigestAlgorithm](t Transport) (*dpeABI[C, D], error) { +func newDPEABI[C Curve, D DigestAlgorithm](t Transport) (*DPEABI[C, D], error) { rsp, err := getProfile(t) if err != nil { return nil, fmt.Errorf("could not query DPE for profile: %w", err) @@ -263,28 +303,29 @@ func newDPEABI[C Curve, D DigestAlgorithm](t Transport) (*dpeABI[C, D], error) { return nil, err } - return &dpeABI[C, D]{ + return &DPEABI[C, D]{ transport: t, Profile: rsp.Profile, MajorVersion: rsp.MajorVersion, MinorVersion: rsp.MinorVersion, - VendorId: rsp.VendorId, + VendorID: rsp.VendorID, VendorSku: rsp.VendorSku, Flags: rsp.Flags, }, nil } // NewDPEABI256 is a convenience wrapper for NewDPEABI[NISTP256Parameter, SHA256Digest]. -func NewDPEABI256(t Transport) (*dpeABI[NISTP256Parameter, SHA256Digest], error) { +func NewDPEABI256(t Transport) (*DPEABI[NISTP256Parameter, SHA256Digest], error) { return newDPEABI[NISTP256Parameter, SHA256Digest](t) } -// NewDPEABI256 is a convenience wrapper for NewDPEABI[NISTP384Parameter, SHA384Digest]. -func NewDPEABI384(t Transport) (*dpeABI[NISTP384Parameter, SHA384Digest], error) { +// NewDPEABI384 is a convenience wrapper for NewDPEABI[NISTP384Parameter, SHA384Digest]. +func NewDPEABI384(t Transport) (*DPEABI[NISTP384Parameter, SHA384Digest], error) { return newDPEABI[NISTP384Parameter, SHA384Digest](t) } -func (c *dpeABI[_, _]) InitializeContextABI(cmd *InitCtxCmd) (*InitCtxResp, error) { +// InitializeContextABI calls InitializeContext +func (c *DPEABI[_, _]) InitializeContextABI(cmd *InitCtxCmd) (*InitCtxResp, error) { var respStruct InitCtxResp if _, err := execCommand(c.transport, CommandInitializeContext, c.Profile, cmd, &respStruct); err != nil { @@ -294,6 +335,7 @@ func (c *dpeABI[_, _]) InitializeContextABI(cmd *InitCtxCmd) (*InitCtxResp, erro return &respStruct, nil } +// GetTransportProfile gets the profile for transport `t` func GetTransportProfile(t Transport) (Profile, error) { resp, err := getProfile(t) if err != nil { @@ -313,7 +355,7 @@ func getProfile(t Transport) (*GetProfileResp, error) { respStruct := struct { MajorVersion uint16 MinorVersion uint16 - VendorId uint32 + VendorID uint32 VendorSku uint32 MaxTciNodes uint32 Flags uint32 @@ -329,19 +371,19 @@ func getProfile(t Transport) (*GetProfileResp, error) { Profile: respHdr.Profile, MajorVersion: respStruct.MajorVersion, MinorVersion: respStruct.MinorVersion, - VendorId: respStruct.VendorId, + VendorID: respStruct.VendorID, VendorSku: respStruct.VendorSku, MaxTciNodes: respStruct.MaxTciNodes, Flags: respStruct.Flags, }, nil } -func (c *dpeABI[_, _]) GetProfileABI() (*GetProfileResp, error) { +func (c *DPEABI[_, _]) GetProfileABI() (*GetProfileResp, error) { return getProfile(c.transport) } // Send the command to destroy a context. -func (c *dpeABI[_, _]) DestroyContextABI(cmd *DestroyCtxCmd) error { +func (c *DPEABI[_, _]) DestroyContextABI(cmd *DestroyCtxCmd) error { // DestroyContext does not return any parameters. respStruct := struct{}{} @@ -353,7 +395,7 @@ func (c *dpeABI[_, _]) DestroyContextABI(cmd *DestroyCtxCmd) error { } // CertifyKey calls the DPE CertifyKey command. -func (c *dpeABI[CurveParameter, Digest]) CertifyKeyABI(cmd *CertifyKeyReq[Digest]) (*CertifyKeyResp[CurveParameter, Digest], error) { +func (c *DPEABI[CurveParameter, Digest]) CertifyKeyABI(cmd *CertifyKeyReq[Digest]) (*CertifyKeyResp[CurveParameter, Digest], error) { // Define an anonymous struct for the response, because we have to accept the variable-sized certificate. respStruct := struct { NewContextHandle [16]byte @@ -382,7 +424,7 @@ func (c *dpeABI[CurveParameter, Digest]) CertifyKeyABI(cmd *CertifyKeyReq[Digest } // GetCertificateChain calls the DPE GetCertificateChain command. -func (c *dpeABI[_, _]) GetCertificateChainABI() (*GetCertificateChainResp, error) { +func (c *DPEABI[_, _]) GetCertificateChainABI() (*GetCertificateChainResp, error) { var certs GetCertificateChainResp // Initialize request input parameters @@ -421,7 +463,7 @@ func (c *dpeABI[_, _]) GetCertificateChainABI() (*GetCertificateChainResp, error } // DeriveChild calls DPE DeriveChild command. -func (c *dpeABI[_, Digest]) DeriveChildABI(cmd *DeriveChildReq[Digest]) (*DeriveChildResp, error) { +func (c *DPEABI[_, Digest]) DeriveChildABI(cmd *DeriveChildReq[Digest]) (*DeriveChildResp, error) { var respStruct DeriveChildResp _, err := execCommand(c.transport, CommandDeriveChild, c.Profile, cmd, &respStruct) @@ -433,7 +475,7 @@ func (c *dpeABI[_, Digest]) DeriveChildABI(cmd *DeriveChildReq[Digest]) (*Derive } // RotateContextHandle calls DPE RotateContextHandle command. -func (c *dpeABI[_, Digest]) RotateContextABI(cmd *RotateContextHandleCmd) (*RotatedContextHandle, error) { +func (c *DPEABI[_, Digest]) RotateContextABI(cmd *RotateContextHandleCmd) (*RotatedContextHandle, error) { var respStruct RotatedContextHandle _, err := execCommand(c.transport, CommandRotateContextHandle, c.Profile, cmd, &respStruct) @@ -445,7 +487,7 @@ func (c *dpeABI[_, Digest]) RotateContextABI(cmd *RotateContextHandleCmd) (*Rota } // Sign calls the DPE Sign command. -func (c *dpeABI[_, Digest]) SignABI(cmd *SignReq[Digest]) (*SignResp[Digest], error) { +func (c *DPEABI[_, Digest]) SignABI(cmd *SignReq[Digest]) (*SignResp[Digest], error) { var respStruct SignResp[Digest] _, err := execCommand(c.transport, CommandSign, c.Profile, cmd, &respStruct) @@ -457,7 +499,7 @@ func (c *dpeABI[_, Digest]) SignABI(cmd *SignReq[Digest]) (*SignResp[Digest], er } // ExtendTCI calls the DPE ExtendTCI command. -func (c *dpeABI[_, Digest]) ExtendTCIABI(cmd *ExtendTCIReq[Digest]) (*ExtendTCIResp, error) { +func (c *DPEABI[_, Digest]) ExtendTCIABI(cmd *ExtendTCIReq[Digest]) (*ExtendTCIResp, error) { var respStruct ExtendTCIResp _, err := execCommand(c.transport, CommandExtendTCI, c.Profile, cmd, &respStruct) @@ -468,7 +510,7 @@ func (c *dpeABI[_, Digest]) ExtendTCIABI(cmd *ExtendTCIReq[Digest]) (*ExtendTCIR return &respStruct, nil } -func (c *dpeABI[_, _]) InitializeContext(flags InitCtxFlags) (*ContextHandle, error) { +func (c *DPEABI[_, _]) InitializeContext(flags InitCtxFlags) (*ContextHandle, error) { cmd := InitCtxCmd{flags: flags} resp, err := c.InitializeContextABI(&cmd) if err != nil { @@ -478,11 +520,11 @@ func (c *dpeABI[_, _]) InitializeContext(flags InitCtxFlags) (*ContextHandle, er return &resp.Handle, nil } -func (c *dpeABI[_, _]) GetProfile() (*GetProfileResp, error) { +func (c *DPEABI[_, _]) GetProfile() (*GetProfileResp, error) { return c.GetProfileABI() } -func (c *dpeABI[_, Digest]) CertifyKey(handle *ContextHandle, label []byte, format CertifyKeyFormat, flags CertifyKeyFlags) (*CertifiedKey, error) { +func (c *DPEABI[_, Digest]) CertifyKey(handle *ContextHandle, label []byte, format CertifyKeyFormat, flags CertifyKeyFlags) (*CertifiedKey, error) { if len(label) != len(Digest(label)) { return nil, fmt.Errorf("invalid label length") } @@ -511,7 +553,7 @@ func (c *dpeABI[_, Digest]) CertifyKey(handle *ContextHandle, label []byte, form return key, nil } -func (c *dpeABI[_, _]) DestroyContext(handle *ContextHandle, flags DestroyCtxFlags) error { +func (c *DPEABI[_, _]) DestroyContext(handle *ContextHandle, flags DestroyCtxFlags) error { cmd := DestroyCtxCmd{ handle: *handle, flags: flags, @@ -520,7 +562,7 @@ func (c *dpeABI[_, _]) DestroyContext(handle *ContextHandle, flags DestroyCtxFla return c.DestroyContextABI(&cmd) } -func (c *dpeABI[_, _]) GetCertificateChain() ([]byte, error) { +func (c *DPEABI[_, _]) GetCertificateChain() ([]byte, error) { resp, err := c.GetCertificateChainABI() if err != nil { return nil, err @@ -529,7 +571,7 @@ func (c *dpeABI[_, _]) GetCertificateChain() ([]byte, error) { return resp.CertificateChain, nil } -func (c *dpeABI[_, Digest]) DeriveChild(handle *ContextHandle, inputData []byte, flags DeriveChildFlags, tciType uint32, targetLocality uint32) (*DeriveChildResp, error) { +func (c *DPEABI[_, Digest]) DeriveChild(handle *ContextHandle, inputData []byte, flags DeriveChildFlags, tciType uint32, targetLocality uint32) (*DeriveChildResp, error) { if len(inputData) != len(Digest(inputData)) { return nil, fmt.Errorf("invalid digest length") } @@ -549,7 +591,7 @@ func (c *dpeABI[_, Digest]) DeriveChild(handle *ContextHandle, inputData []byte, return resp, nil } -func (c *dpeABI[_, _]) RotateContextHandle(handle *ContextHandle, flags RotateContextHandleFlags) (*ContextHandle, error) { +func (c *DPEABI[_, _]) RotateContextHandle(handle *ContextHandle, flags RotateContextHandleFlags) (*ContextHandle, error) { cmd := RotateContextHandleCmd{ Handle: *handle, Flags: flags, @@ -561,7 +603,7 @@ func (c *dpeABI[_, _]) RotateContextHandle(handle *ContextHandle, flags RotateCo return &resp.NewContextHandle, nil } -func (c *dpeABI[_, Digest]) Sign(handle *ContextHandle, label []byte, flags SignFlags, toBeSigned []byte) (*DPESignedHash, error) { +func (c *DPEABI[_, Digest]) Sign(handle *ContextHandle, label []byte, flags SignFlags, toBeSigned []byte) (*DPESignedHash, error) { if len(label) != len(Digest(label)) { return nil, fmt.Errorf("invalid label length") } @@ -590,7 +632,7 @@ func (c *dpeABI[_, Digest]) Sign(handle *ContextHandle, label []byte, flags Sign return signedResp, nil } -func (c *dpeABI[_, Digest]) ExtendTCI(handle *ContextHandle, inputData []byte) (*ContextHandle, error) { +func (c *DPEABI[_, Digest]) ExtendTCI(handle *ContextHandle, inputData []byte) (*ContextHandle, error) { if len(inputData) != len(Digest(inputData)) { return nil, fmt.Errorf("invalid digest length") @@ -609,6 +651,7 @@ func (c *dpeABI[_, Digest]) ExtendTCI(handle *ContextHandle, inputData []byte) ( return &resp.NewContextHandle, nil } +// ToFlags converts support to the profile-defined support flags format func (s *Support) ToFlags() uint32 { flags := uint32(0) if s.Simulation { diff --git a/verification/certifyKey.go b/verification/certifyKey.go index 99c69999..dacbcf80 100755 --- a/verification/certifyKey.go +++ b/verification/certifyKey.go @@ -26,17 +26,21 @@ import ( "golang.org/x/exp/slices" ) +// TcgDiceCriticalExtensions are the OIDs of DICE extensions which must be +// marked as critical var TcgDiceCriticalExtensions = [...]string{ OidExtensionTcgDiceMultiTcbInfo.String(), OidExtensionTcgDiceUeid.String(), } +// TcgDiceExtendedKeyUsages are the DICE OIDs expected to be present in the DPE +// leaf EKU extension var TcgDiceExtendedKeyUsages = [...]string{ OidExtensionTcgDiceKpIdentityLoc.String(), OidExtensionTcgDiceKpAttestLoc.String(), } -// tcg-dice-Ueid OBJECT IDENTIFIER ::= {tcg-dice 4} +// TcgUeidExtension is tcg-dice-Ueid OBJECT IDENTIFIER ::= {tcg-dice 4} // // TcgUeid ::== SEQUENCE { // ueid OCTET STRING @@ -45,42 +49,44 @@ type TcgUeidExtension struct { Ueid []uint8 `asn1:"ueid,implicit"` } +// Fwid represents a TCG DICE FWID stucture +type Fwid struct { + HashAlg asn1.ObjectIdentifier + Digest []byte +} + +// DiceTcbInfo represents the following ASN.1 structures // tcg-dice-MultiTcbInfo OBJECT IDENTIFIER ::= {tcg-dice 5} // DiceTcbInfoSeq ::= SEQUENCE SIZE (1..MAX) OF DiceTcbInfo // // tcg-dice-TcbInfo OBJECT IDENTIFIER ::= {tcg-dice 1} // -// DiceTcbInfo ::== SEQUENCE { -// vendor [0] IMPLICIT UTF8String OPTIONAL, -// model [1] IMPLICIT UTF8String OPTIONAL, -// version [2] IMPLICIT UTF8String OPTIONAL, -// svn [3] IMPLICIT INTEGER OPTIONAL, -// layer [4] IMPLICIT INTEGER OPTIONAL, -// index [5] IMPLICIT INTEGER OPTIONAL, -// fwids [6] IMPLICIT FWIDLIST OPTIONAL, -// flags [7] IMPLICIT OperationalFlags OPTIONAL, -// vendorInfo [8] IMPLICIT OCTET STRING OPTIONAL, -// type [9] IMPLICIT OCTET STRING OPTIONAL, -// } +// DiceTcbInfo ::== SEQUENCE { +// vendor [0] IMPLICIT UTF8String OPTIONAL, +// model [1] IMPLICIT UTF8String OPTIONAL, +// version [2] IMPLICIT UTF8String OPTIONAL, +// svn [3] IMPLICIT INTEGER OPTIONAL, +// layer [4] IMPLICIT INTEGER OPTIONAL, +// index [5] IMPLICIT INTEGER OPTIONAL, +// fwids [6] IMPLICIT FWIDLIST OPTIONAL, +// flags [7] IMPLICIT OperationalFlags OPTIONAL, +// vendorInfo [8] IMPLICIT OCTET STRING OPTIONAL, +// type [9] IMPLICIT OCTET STRING OPTIONAL, +// } // // FWIDLIST ::== SEQUENCE SIZE (1..MAX) OF FWID -// FWID ::== SEQUENCE { -// hashAlg OBJECT IDENTIFIER, -// digest OCTET STRING -// } // -// OperationalFlags ::= BIT STRING { -// notConfigured (0), -// notSecure (1), -// recovery (2), -// debug (3) -// } - -type Fwid struct { - HashAlg asn1.ObjectIdentifier - Digest []byte -} - +// FWID ::== SEQUENCE { +// hashAlg OBJECT IDENTIFIER, +// digest OCTET STRING +// } +// +// OperationalFlags ::= BIT STRING { +// notConfigured (0), +// notSecure (1), +// recovery (2), +// debug (3) +// } type DiceTcbInfo struct { Vendor string `asn1:"optional,tag:0,utf8"` Model string `asn1:"optional,tag:1,utf8"` @@ -94,8 +100,10 @@ type DiceTcbInfo struct { Type []byte `asn1:"optional,tag:9"` } +// OperationalFlag represents the TCBInfo Operational Flags field type OperationalFlag int +// TCG spec-defined operational flags const ( NotConfigured OperationalFlag = iota NotSecure @@ -103,22 +111,27 @@ const ( Recovery ) +// TcgMultiTcbInfo represents a sequence of TCBInfos type TcgMultiTcbInfo = []DiceTcbInfo +// CertifyKeyParams holds configurable paramters to CertifyKey for test-cases type CertifyKeyParams struct { Label []byte Flags CertifyKeyFlags } +// TestCertifyKey tests calling CertifyKey func TestCertifyKey(d TestDPEInstance, c DPEClient, t *testing.T) { testCertifyKey(d, c, t, false) } +// TestCertifyKeySimulation tests calling CertifyKey on simulation contexts func TestCertifyKeySimulation(d TestDPEInstance, c DPEClient, t *testing.T) { testCertifyKey(d, c, t, true) } -func TestCertifyKey_Csr(d TestDPEInstance, c DPEClient, t *testing.T) { +// TestCertifyKeyCsr tests calling CeritifyKey with type = CSR +func TestCertifyKeyCsr(d TestDPEInstance, c DPEClient, t *testing.T) { ctx := getInitialContextHandle(d, c, t, false) profile, err := GetTransportProfile(d) diff --git a/verification/certs.go b/verification/certs.go index 8a7d3845..c498645f 100644 --- a/verification/certs.go +++ b/verification/certs.go @@ -28,6 +28,7 @@ var ( OidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2} ) +// BasicConstraints represents an X.509 BasicConstraints extension type BasicConstraints struct { IsCA bool `asn1` PathLenConstraint int `asn1:"optional"` diff --git a/verification/client.go b/verification/client.go index 6f6109a1..e4d54fe8 100755 --- a/verification/client.go +++ b/verification/client.go @@ -7,6 +7,7 @@ import ( ) const ( + // MaxChunkSize is the max size of a DPE certificate chunk MaxChunkSize = 2048 ) @@ -16,29 +17,34 @@ type Transport interface { SendCmd(buf []byte) ([]byte, error) } +// DPEPubKey is an ECC public point // TODO: Include curve type DPEPubKey struct { X []byte Y []byte } +// CertifiedKey is a response from DPE CertifyKey type CertifiedKey struct { Handle ContextHandle Pub DPEPubKey Certificate []byte } +// DPETCI holds the current and cumulative measurements for a DPE TCI node type DPETCI struct { CumulativeTCI []byte CurrentTCI []byte } +// DPESignedHash is the response from DPE Sign type DPESignedHash struct { Handle ContextHandle HmacOrSignatureR []byte SignatureS []byte } +// DPEClient is a generic interface to a DPE instance type DPEClient interface { InitializeContext(flags InitCtxFlags) (*ContextHandle, error) GetProfile() (*GetProfileResp, error) @@ -51,6 +57,7 @@ type DPEClient interface { ExtendTCI(handle *ContextHandle, inputData []byte) (*ContextHandle, error) } +// NewClient returns a new DPE client func NewClient(t Transport, p Profile) (DPEClient, error) { switch p { case ProfileP256SHA256: diff --git a/verification/errors.go b/verification/errors.go index c94a138a..3dd0bae6 100644 --- a/verification/errors.go +++ b/verification/errors.go @@ -4,8 +4,10 @@ package verification import "fmt" +// Status is a DPE status code type Status uint32 +// All spec-defined DPE status codes const ( StatusInternalError Status = 1 StatusInvalidCommand Status = 2 @@ -21,6 +23,7 @@ const ( StatusRandError Status = 0x1007 ) +// Error returns an informational string for all DPE error codes func (s Status) Error() string { switch s { case StatusInternalError: diff --git a/verification/extendTCI.go b/verification/extendTCI.go index e46d1cdb..7d8cb6e0 100644 --- a/verification/extendTCI.go +++ b/verification/extendTCI.go @@ -11,7 +11,8 @@ import ( "testing" ) -// Check whether the ExtendTCI command updates the current TCI and cumulative TCI. +// TestExtendTCI checks whether the ExtendTCI command updates the current TCI +// and cumulative TCI. func TestExtendTCI(d TestDPEInstance, c DPEClient, t *testing.T) { var err error useSimulation := false // To indicate that simulation context is not used @@ -61,7 +62,8 @@ func computeExpectedCumulative(lastCumulative []byte, tciValue []byte) []byte { return hasher.Sum(nil) } -// Check whether the ExtendTCI command with derived child context. +// TestExtendTciOnDerivedContexts checks whether the ExtendTCI command with +// derived child context. func TestExtendTciOnDerivedContexts(d TestDPEInstance, c DPEClient, t *testing.T) { useSimulation := false // To indicate that simulation context is not used diff --git a/verification/getCertificateChain.go b/verification/getCertificateChain.go index 362ed85c..56be0420 100644 --- a/verification/getCertificateChain.go +++ b/verification/getCertificateChain.go @@ -13,6 +13,7 @@ import ( "github.com/zmap/zlint/v3/lint" ) +// TestGetCertificateChain tests calling GetCertificateChain func TestGetCertificateChain(d TestDPEInstance, client DPEClient, t *testing.T) { certChain, err := client.GetCertificateChain() if err != nil { diff --git a/verification/getProfile.go b/verification/getProfile.go index f128ea33..71946ae9 100644 --- a/verification/getProfile.go +++ b/verification/getProfile.go @@ -8,8 +8,9 @@ import ( // This file is used to test the get profile command. +// TestGetProfile tests calling GetProfile func TestGetProfile(d TestDPEInstance, client DPEClient, t *testing.T) { - const MIN_TCI_NODES uint32 = 8 + const minTCINodes uint32 = 8 for _, locality := range d.GetSupportedLocalities() { d.SetLocality(locality) @@ -23,8 +24,8 @@ func TestGetProfile(d TestDPEInstance, client DPEClient, t *testing.T) { if rsp.MinorVersion != d.GetProfileMinorVersion() { t.Fatalf("Incorrect version. 0x%08x != 0x%08x", d.GetProfileMinorVersion(), rsp.MinorVersion) } - if rsp.VendorId != d.GetProfileVendorId() { - t.Fatalf("Incorrect version. 0x%08x != 0x%08x", d.GetProfileVendorId(), rsp.VendorId) + if rsp.VendorID != d.GetProfileVendorID() { + t.Fatalf("Incorrect version. 0x%08x != 0x%08x", d.GetProfileVendorID(), rsp.VendorID) } if rsp.VendorSku != d.GetProfileVendorSku() { t.Fatalf("Unexpected SKU. 0x%08x != 0x%08x", d.GetProfileVendorSku(), rsp.VendorSku) @@ -32,8 +33,8 @@ func TestGetProfile(d TestDPEInstance, client DPEClient, t *testing.T) { if rsp.MaxTciNodes != d.GetMaxTciNodes() { t.Fatalf("Incorrect max TCI nodes. 0x%08x != 0x%08x", d.GetMaxTciNodes(), rsp.MaxTciNodes) } - if rsp.MaxTciNodes < MIN_TCI_NODES { - t.Fatalf("DPE instances must be able to support at least %d TCI nodes.", MIN_TCI_NODES) + if rsp.MaxTciNodes < minTCINodes { + t.Fatalf("DPE instances must be able to support at least %d TCI nodes.", minTCINodes) } if rsp.Flags != d.GetSupport().ToFlags() { t.Fatalf("Incorrect support flags. 0x%08x != 0x%08x", d.GetSupport().ToFlags(), rsp.Flags) diff --git a/verification/initializeContext.go b/verification/initializeContext.go index 728c3e47..deabe39b 100644 --- a/verification/initializeContext.go +++ b/verification/initializeContext.go @@ -9,6 +9,7 @@ import ( // This file is used to test the initialize context command. +// TestInitializeContext tests calling InitializeContext func TestInitializeContext(d TestDPEInstance, c DPEClient, t *testing.T) { for _, locality := range d.GetSupportedLocalities() { d.SetLocality(locality) @@ -16,6 +17,7 @@ func TestInitializeContext(d TestDPEInstance, c DPEClient, t *testing.T) { } } +// TestInitializeSimulation tests calling InitializeContext simulation mode func TestInitializeSimulation(d TestDPEInstance, c DPEClient, t *testing.T) { for _, locality := range d.GetSupportedLocalities() { d.SetLocality(locality) diff --git a/verification/negativeCases.go b/verification/negativeCases.go index 24042403..f9da1816 100644 --- a/verification/negativeCases.go +++ b/verification/negativeCases.go @@ -7,9 +7,11 @@ import ( "testing" ) +// InvalidHandle is a sample DPE handle which is very unlikely to be valid var InvalidHandle = ContextHandle{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} -// Checks whether error is reported when non-existent handle is passed as input to DPE commands. +// TestInvalidHandle checks whether error is reported when non-existent handle +// is passed as input to DPE commands. // Exceptions are - GetProfile, InitializeContext, GetCertificateChain, commands // which do not need context handle as input parameter. func TestInvalidHandle(d TestDPEInstance, c DPEClient, t *testing.T) { @@ -65,7 +67,8 @@ func TestInvalidHandle(d TestDPEInstance, c DPEClient, t *testing.T) { } } -// Checks whether error is reported when caller from one locality issues DPE commands in another locality. +// TestWrongLocality checks whether error is reported when caller from one +// locality issues DPE commands in another locality. // Exceptions are - GetProfile, InitializeContext, GetCertificateChain, commands // which do not need context handle as input and hence locality is irrelevant. func TestWrongLocality(d TestDPEInstance, c DPEClient, t *testing.T) { @@ -132,7 +135,8 @@ func TestWrongLocality(d TestDPEInstance, c DPEClient, t *testing.T) { } } -// Checks whether error is reported while using commands that are turned off in DPE. +// TestUnsupportedCommand checks whether error is reported while using commands +// that are turned off in DPE. // DPE commands - RotateContextHandle, ExtendTCI, require support to be enabled in DPE profile // before being called. func TestUnsupportedCommand(d TestDPEInstance, c DPEClient, t *testing.T) { @@ -159,7 +163,8 @@ func TestUnsupportedCommand(d TestDPEInstance, c DPEClient, t *testing.T) { } } -// Checks whether error is reported while enabling command flags that are turned off in DPE. +// TestUnsupportedCommandFlag checks whether error is reported while enabling +// command flags that are turned off in DPE. // The DPE command may be available but some of its flags may not be supported by DPE. // DPE profile supports the below attributes. // Simulation : Allows caller to request for context iniitialization in simulation mode diff --git a/verification/profile.go b/verification/profile.go index fd46ef12..29e5be4f 100644 --- a/verification/profile.go +++ b/verification/profile.go @@ -8,12 +8,13 @@ import "fmt" type Profile uint32 const ( - // NIST P-256, SHA-256 + // ProfileP256SHA256 is NIST P-256, SHA-256 ProfileP256SHA256 Profile = 1 - // NIST P-384, SHA-384 + // ProfileP384SHA384 is NIST P-384, SHA-384 ProfileP384SHA384 Profile = 2 ) +// GetDigestSize gets the digest size of the profile's supported hash algorithm func (p Profile) GetDigestSize() int { switch p { case ProfileP256SHA256: @@ -24,6 +25,7 @@ func (p Profile) GetDigestSize() int { return 0 } +// GetECCIntSize gets the ECC int size of the profile's supported ECC curve func (p Profile) GetECCIntSize() int { switch p { case ProfileP256SHA256: @@ -54,6 +56,7 @@ type Curve interface { // NISTP256Parameter represents a NIST P-256 curve parameter, i.e., an x, y, r, or s value. type NISTP256Parameter [32]byte +// Bytes returns a big-endian byte slice of a P256 int func (p NISTP256Parameter) Bytes() []byte { return p[:] } @@ -61,6 +64,7 @@ func (p NISTP256Parameter) Bytes() []byte { // NISTP384Parameter represents a NIST P-384 curve parameter, i.e., an x, y, r, or s value. type NISTP384Parameter [48]byte +// Bytes returns a big-endian byte slice of a P384 int func (p NISTP384Parameter) Bytes() []byte { return p[:] } @@ -75,6 +79,7 @@ type DigestAlgorithm interface { // SHA256Digest represents a SHA-256 digest value. type SHA256Digest [32]byte +// Bytes returns a byte slice of the SHA256 digest func (d SHA256Digest) Bytes() []byte { return d[:] } @@ -82,6 +87,7 @@ func (d SHA256Digest) Bytes() []byte { // SHA384Digest represents a SHA-384 digest value. type SHA384Digest [48]byte +// Bytes returns a byte slice of the SHA384 digest func (d SHA384Digest) Bytes() []byte { return d[:] } diff --git a/verification/rotateContextHandle.go b/verification/rotateContextHandle.go index 951fcf89..40769e7d 100644 --- a/verification/rotateContextHandle.go +++ b/verification/rotateContextHandle.go @@ -7,6 +7,7 @@ import ( "testing" ) +// TestRotateContextHandle tests the RotateContextHandle command func TestRotateContextHandle(d TestDPEInstance, c DPEClient, t *testing.T) { simulation := false handle := getInitialContextHandle(d, c, t, simulation) @@ -40,6 +41,8 @@ func TestRotateContextHandle(d TestDPEInstance, c DPEClient, t *testing.T) { } } +// TestRotateContextHandleSimulation tests calling RotateContextHandle on +// simulation contexts func TestRotateContextHandleSimulation(d TestDPEInstance, c DPEClient, t *testing.T) { simulation := true handle := getInitialContextHandle(d, c, t, simulation) diff --git a/verification/sign.go b/verification/sign.go index eb127ee4..26748ef8 100644 --- a/verification/sign.go +++ b/verification/sign.go @@ -12,7 +12,7 @@ import ( "testing" ) -// Obtain and validate signature of asymmetric signing. +// TestAsymmetricSigning obtains and validates signature of asymmetric signing. // Check whether the digital signature returned by Sign command can be verified // using public key in signing key certificate returned by CertifyKey command. // Inspite of the DPE profile supporting symmetric key, for symmetric signing it must be enabled @@ -81,7 +81,7 @@ func TestAsymmetricSigning(d TestDPEInstance, c DPEClient, t *testing.T) { } } -// Check command fails in simulated context because this context does not allow signing. +// TestSignSimulation cheks command fails in simulated context because this context does not allow signing. // This is because simulation context does not allow using context's private key. func TestSignSimulation(d TestDPEInstance, c DPEClient, t *testing.T) { useSimulation := true @@ -111,7 +111,7 @@ func TestSignSimulation(d TestDPEInstance, c DPEClient, t *testing.T) { } } -// Obtain HMAC (symmetric signature) generated and compare for varying label inputs. +// TestSymmetricSigning obtains HMAC (symmetric signature) generated and compares for varying label inputs. // Signature created is deterministic and depends on label passed to command. // This is because label is used by DPE in symmetric key derivation. // Invoking Sign command multiple times with same label and same content (TBS) should return same signature diff --git a/verification/simulator.go b/verification/simulator.go index 8307ba27..9280deb7 100644 --- a/verification/simulator.go +++ b/verification/simulator.go @@ -15,22 +15,25 @@ import ( "time" ) +// Constants for configuring expected values from the DPE simulator const ( simulatorSocketPath = "/tmp/dpe-sim.socket" - DPE_SIMULATOR_AUTO_INIT_LOCALITY uint32 = 0 - DPE_SIMULATOR_OTHER_LOCALITY uint32 = 0x4f544852 - DPE_SIMULATOR_MAX_TCI_NODES uint32 = 24 - DPE_SIMULATOR_MAJOR_PROFILE_VERSION uint16 = CURRENT_PROFILE_MAJOR_VERSION - DPE_SIMULATOR_MINOR_PROFILE_VERSION uint16 = CURRENT_PROFILE_MINOR_VERSION - DPE_SIMULATOR_VENDOR_ID uint32 = 0 - DPE_SIMULATOR_VENDOR_SKU uint32 = 0 + DPESimulatorAutoInitLocality uint32 = 0 + DPESimulatorOtherLocality uint32 = 0x4f544852 + DPESimulatorMaxTCINodes uint32 = 24 + DPESimulatorMajorProfileVersion uint16 = CurrentProfileMajorVersion + DPESimulatorMinorProfileVersion uint16 = CurrentProfileMinorVersion + DPESimulatorVendorID uint32 = 0 + DPESimulatorVendorSKU uint32 = 0 ) +// TargetExe is the simulator executable to use for this test target var TargetExe *string +// DpeSimulator is a handle to a DPE simulator instance type DpeSimulator struct { - exe_path string + exePath string cmd *exec.Cmd supports Support currentLocality uint32 @@ -38,12 +41,12 @@ type DpeSimulator struct { Transport } -// Simulator can be started and stopped. +// HasPowerControl returns whether the simulator can be started and stopped. func (s *DpeSimulator) HasPowerControl() bool { return true } -// Start the simulator. +// PowerOn starts the simulator. func (s *DpeSimulator) PowerOn() error { args := []string{} if s.supports.Simulation { @@ -77,7 +80,7 @@ func (s *DpeSimulator) PowerOn() error { args = append(args, "--supports-internal-dice") } - s.cmd = exec.Command(s.exe_path, args...) + s.cmd = exec.Command(s.exePath, args...) s.cmd.Stdout = os.Stdout err := s.cmd.Start() if err != nil { @@ -89,7 +92,7 @@ func (s *DpeSimulator) PowerOn() error { return nil } -// Kill the simulator in a way that it can cleanup before closing. +// PowerOff kills the simulator in a way that it can cleanup before closing. func (s *DpeSimulator) PowerOff() error { if s.cmd != nil { err := s.cmd.Process.Signal(syscall.SIGTERM) @@ -105,15 +108,15 @@ func (s *DpeSimulator) PowerOff() error { // Wait for the simulator to come alive. Timeout at 15 seconds. func (s *DpeSimulator) waitForPower(on bool) bool { - timeout_seconds := 15 - checks_per_sec := 50 + timeoutSeconds := 15 + checksPerSec := 50 - for i := 0; i < checks_per_sec*timeout_seconds; i++ { + for i := 0; i < checksPerSec*timeoutSeconds; i++ { // Check if the socket file has been created. if fileExists(simulatorSocketPath) == on { return true } - time.Sleep(time.Duration(1000/checks_per_sec) * time.Millisecond) + time.Sleep(time.Duration(1000/checksPerSec) * time.Millisecond) } return false } @@ -126,6 +129,7 @@ func fileExists(filename string) bool { return !info.IsDir() } +// SendCmd sends a DPE command to the simulator func (s *DpeSimulator) SendCmd(buf []byte) ([]byte, error) { // Connect to DPE instance. conn, err := net.Dial("unix", simulatorSocketPath) @@ -143,11 +147,11 @@ func (s *DpeSimulator) SendCmd(buf []byte) ([]byte, error) { } // Send the prepended command. - num_sent, err := conn.Write(prepended.Bytes()) + numSent, err := conn.Write(prepended.Bytes()) if err != nil { return nil, err } - if num_sent != len(prepended.Bytes()) { + if numSent != len(prepended.Bytes()) { return nil, errors.New("didn't send the whole command") } @@ -155,73 +159,88 @@ func (s *DpeSimulator) SendCmd(buf []byte) ([]byte, error) { return io.ReadAll(conn) } +// GetSupport gets supported DPE features from the simulator func (s *DpeSimulator) GetSupport() *Support { return &s.supports } +// GetIsInitialized gets whether DPE is initialized func (s *DpeSimulator) GetIsInitialized() bool { return s.supports.AutoInit || s.isInitialized } +// SetIsInitialized sets whether DPE is initialized func (s *DpeSimulator) SetIsInitialized(isInitialized bool) { s.isInitialized = isInitialized } +// GetSupportedLocalities gets the list of localities the simulator supports func (s *DpeSimulator) GetSupportedLocalities() []uint32 { - return []uint32{DPE_SIMULATOR_AUTO_INIT_LOCALITY, DPE_SIMULATOR_OTHER_LOCALITY} + return []uint32{DPESimulatorAutoInitLocality, DPESimulatorOtherLocality} } +// HasLocalityControl returns whehter the simulator can artificially set the +// locality of the caller. The simulator target can always control the locality. func (s *DpeSimulator) HasLocalityControl() bool { return true } +// SetLocality sets the locality of this caller func (s *DpeSimulator) SetLocality(locality uint32) { s.currentLocality = locality } +// GetLocality gets the locality of the current caller func (s *DpeSimulator) GetLocality() uint32 { return s.currentLocality } +// GetMaxTciNodes gets the max number of TCI nodes the DPE supports func (s *DpeSimulator) GetMaxTciNodes() uint32 { - return DPE_SIMULATOR_MAX_TCI_NODES + return DPESimulatorMaxTCINodes } +// GetProfileMajorVersion gets the major profile version supported by this DPE func (s *DpeSimulator) GetProfileMajorVersion() uint16 { - return DPE_SIMULATOR_MAJOR_PROFILE_VERSION + return DPESimulatorMajorProfileVersion } +// GetProfileMinorVersion gets the minor profile version supported by this DPE func (s *DpeSimulator) GetProfileMinorVersion() uint16 { - return DPE_SIMULATOR_MINOR_PROFILE_VERSION + return DPESimulatorMinorProfileVersion } -func (s *DpeSimulator) GetProfileVendorId() uint32 { - return DPE_SIMULATOR_VENDOR_ID +// GetProfileVendorID gets the vendor ID of this DPE +func (s *DpeSimulator) GetProfileVendorID() uint32 { + return DPESimulatorVendorID } +// GetProfileVendorSku gets the vendor SKU of this DPE func (s *DpeSimulator) GetProfileVendorSku() uint32 { - return DPE_SIMULATOR_VENDOR_SKU + return DPESimulatorVendorSKU } -// Get the simulator target -func GetSimulatorTarget(support_needed []string, target_exe string) TestDPEInstance { +// GetSimulatorTarget gets the simulator target +func GetSimulatorTarget(supportNeeded []string, targetExe string) TestDPEInstance { value := reflect.ValueOf(DpeSimulator{}.supports) fields := reflect.Indirect(value) fVal := reflect.New(reflect.TypeOf(DpeSimulator{}.supports)) - for i := 0; i < len(support_needed); i++ { + for i := 0; i < len(supportNeeded); i++ { for j := 0; j < value.NumField(); j++ { - if fields.Type().Field(j).Name == support_needed[i] { + if fields.Type().Field(j).Name == supportNeeded[i] { fVal.Elem().Field(j).SetBool(true) } } } support := fVal.Elem().Interface().(Support) - var instance TestDPEInstance = &DpeSimulator{exe_path: target_exe, supports: support} + var instance TestDPEInstance = &DpeSimulator{exePath: targetExe, supports: support} return instance } +// GetSimulatorTargets gets different simulator targets with different support +// vectors to run the verification tests against func GetSimulatorTargets() []TestTarget { return []TestTarget{ { @@ -315,6 +334,6 @@ func GetSimulatorTargets() []TestTarget { // Get the test target for simulator/emulator func getTestTarget(supportNeeded []string) TestDPEInstance { instance := GetSimulatorTarget(supportNeeded, *TargetExe) - instance.SetLocality(DPE_SIMULATOR_AUTO_INIT_LOCALITY) + instance.SetLocality(DPESimulatorAutoInitLocality) return instance } diff --git a/verification/tpm.go b/verification/tpm.go index 46ec66f2..85b1a252 100644 --- a/verification/tpm.go +++ b/verification/tpm.go @@ -63,6 +63,7 @@ func startTpmSession(t *testing.T, tpm io.ReadWriteCloser, alg tpm2.Algorithm) ( return sessHandle, nonce, nil } +// TestTpmPolicySigning tests using DPE to satisfy TPM PolicySigned func TestTpmPolicySigning(d TestDPEInstance, c DPEClient, t *testing.T) { simulation := false ctx := getInitialContextHandle(d, c, t, simulation) diff --git a/verification/transport.go b/verification/transport.go index 6feded7d..d0a078b9 100644 --- a/verification/transport.go +++ b/verification/transport.go @@ -6,11 +6,12 @@ import ( "reflect" ) -func HasSupportNeeded(d TestDPEInstance, support_needed []string) bool { +// HasSupportNeeded returns whether `d` supports all the features in `support_needed` +func HasSupportNeeded(d TestDPEInstance, supportNeeded []string) bool { support := d.GetSupport() value := reflect.ValueOf(support) - for i := 0; i < len(support_needed); i++ { - support := reflect.Indirect(value).FieldByName(support_needed[i]) + for i := 0; i < len(supportNeeded); i++ { + support := reflect.Indirect(value).FieldByName(supportNeeded[i]) if !support.Bool() { return false } @@ -19,7 +20,7 @@ func HasSupportNeeded(d TestDPEInstance, support_needed []string) bool { return true } -// An extension to the main DPE transport interface with test hooks. +// TestDPEInstance is an extension to the main DPE transport interface with test hooks. type TestDPEInstance interface { Transport // If power control is unavailable for the given device, return false from @@ -54,7 +55,7 @@ type TestDPEInstance interface { // Returns the minor version of the profile the instance implements. GetProfileMinorVersion() uint16 // Returns the Vendor ID of the profile. - GetProfileVendorId() uint32 + GetProfileVendorID() uint32 // Returns the vendor's product SKU. GetProfileVendorSku() uint32 } diff --git a/verification/verification.go b/verification/verification.go index f64eb6f5..8e7ef441 100644 --- a/verification/verification.go +++ b/verification/verification.go @@ -6,78 +6,120 @@ import ( "testing" ) +// DpeTestFunc is the function template that a DPE test case must implement type DpeTestFunc func(d TestDPEInstance, c DPEClient, t *testing.T) +// TestCase is metadata for a DPE test case type TestCase struct { Name string Run DpeTestFunc SupportNeeded []string } +// TestTarget is a TestDPEInstance and corresponding list of test cases to run +// against that target. type TestTarget struct { Name string D TestDPEInstance TestCases []TestCase } +// InitializeContextTestCase tests InitializeContext var InitializeContextTestCase = TestCase{ "InitializeContext", TestInitializeContext, []string{}, } + +// InitializeContextSimulationTestCase tests InitializeContext in simulation mode var InitializeContextSimulationTestCase = TestCase{ "InitializeContextSimulation", TestInitializeSimulation, []string{"Simulation"}, } + +// CertifyKeyTestCase tests CertifyKey var CertifyKeyTestCase = TestCase{ "CertifyKey", TestCertifyKey, []string{"AutoInit", "X509", "IsCA"}, } + +// CertifyKeyCsrTestCase tests CertifyKey with type = CSR var CertifyKeyCsrTestCase = TestCase{ - "CertifyKeyCsr", TestCertifyKey_Csr, []string{"AutoInit", "Csr", "IsCA"}, + "CertifyKeyCsr", TestCertifyKeyCsr, []string{"AutoInit", "Csr", "IsCA"}, } + +// CertifyKeySimulationTestCase tests CertifyKey on Simulation mode contexts var CertifyKeySimulationTestCase = TestCase{ "CertifyKeySimulation", TestCertifyKeySimulation, []string{"AutoInit", "Simulation", "X509", "IsCA"}, } + +// GetCertificateChainTestCase tests GetCertificateChain var GetCertificateChainTestCase = TestCase{ "GetCertificateChain", TestGetCertificateChain, []string{"AutoInit", "X509"}, } + +// ExtendTCITestCase tests ExtendTci var ExtendTCITestCase = TestCase{ "ExtendTCITestCase", TestExtendTCI, []string{"AutoInit", "ExtendTci"}, } + +// ExtendDerivedTciTestCase tests ExtendTci on derived child contexts var ExtendDerivedTciTestCase = TestCase{ "ExtendDerivedTciTestCase", TestExtendTciOnDerivedContexts, []string{"AutoInit", "ExtendTci"}, } + +// GetProfileTestCase tests GetProfile var GetProfileTestCase = TestCase{ "GetProfile", TestGetProfile, []string{}, } + +// InvalidHandleTestCase tests various commands with invalid context handles var InvalidHandleTestCase = TestCase{ "CheckInvalidHandle", TestInvalidHandle, []string{"Simulation", "RotateContext", "ExtendTci"}, } + +// WrongLocalityTestCase tests various commands with invalid localities var WrongLocalityTestCase = TestCase{ "CheckWrongLocality", TestWrongLocality, []string{"AutoInit", "RotateContext", "ExtendTci"}, } + +// UnsupportedCommand tests calling unsupported commands var UnsupportedCommand = TestCase{ "CheckSupportForCommand", TestUnsupportedCommand, []string{"AutoInit"}, } + +// UnsupportedCommandFlag tests calling unsupported commands flags var UnsupportedCommandFlag = TestCase{ "CheckSupportForCommmandFlag", TestUnsupportedCommandFlag, []string{"AutoInit", "RotateContext", "ExtendTci"}, } + +// RotateContextTestCase tests RotateContext var RotateContextTestCase = TestCase{ "RotateContextHandle", TestRotateContextHandle, []string{"AutoInit", "RotateContext"}, } + +// RotateContextSimulationTestCase tests RotateContext with Simulation contexts var RotateContextSimulationTestCase = TestCase{ "RotateContextHandleSimulation", TestRotateContextHandleSimulation, []string{"Simulation", "RotateContext"}, } + +// SignAsymmetricTestCase tests Sign var SignAsymmetricTestCase = TestCase{ "Sign", TestAsymmetricSigning, []string{"AutoInit", "X509"}, } + +// SignSymmetricTestCase tests Sign with is-symmetric = true var SignSymmetricTestCase = TestCase{ "SignSymmetric", TestSymmetricSigning, []string{"AutoInit", "IsSymmetric"}, } + +// SignSimulationTestCase tests Sign with Simulation contexts var SignSimulationTestCase = TestCase{ "SignSimulation", TestSignSimulation, []string{"Simulation"}, } + +// TpmPolicySigningTestCase tests using DPE to satisfy TPM PolicySigned var TpmPolicySigningTestCase = TestCase{ "TPMPolicySigning", TestTpmPolicySigning, []string{"AutoInit", "X509"}, } +// AllTestCases contains all DPE test cases var AllTestCases = []TestCase{ CertifyKeyTestCase, CertifyKeyCsrTestCase, @@ -98,6 +140,7 @@ var AllTestCases = []TestCase{ WrongLocalityTestCase, } +// RunTargetTestCases runs all test cases for target func RunTargetTestCases(target TestTarget, t *testing.T) { // This needs to be in a separate function to make sure it is powered off before running the // next target. This is particularly important for the simulator because it can attach to an