├── testdata ├── rootCA.der ├── endEntity.der ├── intermediateCA.der ├── endEntity.key └── testdata.go ├── cots ├── data │ ├── shared_ta.ta │ └── Snobbish Apparel_ta.ta ├── hardware_version_type.go ├── cbor.go ├── cots_test.go └── abbreviated_swid_evidence_test.go ├── coev ├── testcases │ ├── ce-coswid.cbor │ ├── ce-evidence.cbor │ ├── ce-identity.cbor │ ├── regen-from-src.sh │ └── src │ │ ├── ce-evidence.diag │ │ ├── ce-coswid.diag │ │ └── ce-identity.diag ├── tdx │ ├── testcases │ │ ├── ce-pce-evidence.cbor │ │ ├── ce-qe-evidence.cbor │ │ ├── ce-seam-evidence.cbor │ │ ├── regen-from-src.sh │ │ └── src │ │ │ ├── ce-seam-evidence.diag │ │ │ ├── ce-pce-evidence.diag │ │ │ └── ce-qe-evidence.diag │ └── tdx_profile.go ├── extensions.go ├── test_vars.go ├── cbor.go ├── coswidtriple_test.go ├── evidence_id_test.go ├── coswidtriple.go └── coswid_evidence.go ├── comid ├── testcases │ ├── comid-1.cbor │ ├── comid-2.cbor │ ├── comid-3.cbor │ ├── comid-4.cbor │ ├── comid-5.cbor │ ├── comid-design-cd.cbor │ ├── comid-firmware-cd.cbor │ ├── comid-cond-endorse-series.cbor │ ├── regen-from-src.sh │ └── src │ │ ├── comid-3.diag │ │ ├── comid-1.diag │ │ ├── comid-4.diag │ │ ├── comid-5.diag │ │ └── comid-firmware-cd.diag ├── typeandvalue.go ├── tagidentity.go ├── uuid_test.go ├── valuetriple_test.go ├── cryptokeys_test.go ├── ueid_test.go ├── bytes.go ├── keytriple.go ├── psareferencevalue_test.go ├── version.go ├── version_test.go ├── keytriple_test.go ├── cryptokeys.go ├── linkedtag_test.go ├── macaddr.go ├── flagsmap_test.go ├── flagsmap_confidentiality_test.go ├── linkedtag.go ├── ueid.go ├── extensions_test.go ├── ccaplatformconfigid.go ├── ccaplatformconfigid_test.go ├── environment.go ├── cbor.go ├── rawvalue_test.go ├── example_psa_keys_test.go ├── rel.go ├── comid_test.go ├── valuetriple.go └── role.go ├── coserv ├── testvectors │ ├── rv-results.cbor │ ├── rv-class-simple.cbor │ ├── rv-class-stateful.cbor │ ├── example-class-selector.cbor │ ├── example-group-selector.cbor │ ├── example-instance-selector.cbor │ ├── rv-class-simple-results.cbor │ ├── example-class-selector-noindent.cbor │ ├── rv-class-simple-results-source-artifacts.cbor │ ├── example-instance-selector.b64u │ ├── example-group-selector.b64u │ ├── rv-class-simple.b64u │ ├── rv-class-stateful.b64u │ ├── example-class-selector.b64u │ ├── example-class-selector-noindent.b64u │ ├── example-instance-selector.hex │ ├── example-group-selector.hex │ ├── example-class-selector-noindent.diag │ ├── rv-class-simple.hex │ ├── rv-results.b64u │ ├── example-class-selector.hex │ ├── rv-class-stateful.hex │ ├── example-class-selector-noindent.hex │ ├── example-instance-selector.diag │ ├── example-group-selector.diag │ ├── rv-class-simple-results-source-artifacts.b64u │ ├── rv-class-simple-results.b64u │ ├── rv-results.hex │ ├── example-class-selector.diag │ ├── Makefile │ ├── rv-class-simple-results-source-artifacts.hex │ ├── rv-class-simple-results.hex │ ├── rv-class-simple.diag │ ├── rv-class-simple-results-source-artifacts.diag │ ├── rv-class-stateful.diag │ ├── rv-results.diag │ └── rv-class-simple-results.diag ├── quads.go ├── resulttype.go ├── artifacttype.go ├── query_test.go ├── resultset_test.go ├── environmentselector_test.go ├── query.go └── resultset.go ├── extensions ├── corim-map-extensions.png ├── typechoice_test.go ├── cbor.go └── typechoice.go ├── corim ├── testcases │ ├── signed-good-corim.cbor │ ├── signed-example-corim.cbor │ ├── unsigned-good-corim.cbor │ ├── unsigned-example-corim.cbor │ ├── signed-corim-with-extensions.cbor │ ├── unsigned-corim-with-extensions.cbor │ ├── src │ │ ├── meta.yaml │ │ ├── ec-p256.jwk │ │ ├── good-corim.yaml │ │ ├── corim-with-extensions.yaml │ │ └── example-corim.yaml │ ├── corim.json │ ├── corim-ext.json │ ├── regen-from-src.sh │ ├── comid.json │ └── comid-ext.json ├── validity.go ├── extensions.go ├── signer_test.go ├── cbor.go ├── extensions_test.go ├── role_test.go └── meta.go ├── profiles └── tdx │ ├── testcases │ ├── comid_pce_refval.cbor │ ├── comid_qe_refval.cbor │ ├── comid_seam_refval.cbor │ ├── regen-from-src.sh │ └── src │ │ ├── comid_pce_refval.diag │ │ ├── comid_qe_refval.diag │ │ └── comid_seam_refval.diag │ ├── common.go │ ├── types.go │ ├── teepceid.go │ ├── teeattributes.go │ ├── teemiscselect.go │ ├── teepceid_test.go │ ├── teeattributes_test.go │ ├── teemiscselect_test.go │ ├── numeric_expression.go │ ├── cbor.go │ ├── operator.go │ ├── set_expression.go │ ├── teetcbcompsvn_test.go │ ├── teetcbcompsvn.go │ ├── teedigest_test.go │ ├── teetcbstatus_test.go │ ├── numeric_type_test.go │ ├── tee_tcb_eval_num_test.go │ ├── mval_extensions.go │ ├── teeadvisoryids_test.go │ └── teeinstanceid_test.go ├── cocli └── README.md ├── .gitignore ├── scripts ├── licenses.sh └── cov.py ├── .github └── workflows │ ├── linters.yml │ ├── ci.yml │ └── ci-go-cover.yml ├── go.mod ├── encoding └── embedded.go ├── Makefile ├── .golangci.yml └── README.md /testdata/rootCA.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/testdata/rootCA.der -------------------------------------------------------------------------------- /cots/data/shared_ta.ta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/cots/data/shared_ta.ta -------------------------------------------------------------------------------- /testdata/endEntity.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/testdata/endEntity.der -------------------------------------------------------------------------------- /coev/testcases/ce-coswid.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coev/testcases/ce-coswid.cbor -------------------------------------------------------------------------------- /comid/testcases/comid-1.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/comid/testcases/comid-1.cbor -------------------------------------------------------------------------------- /comid/testcases/comid-2.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/comid/testcases/comid-2.cbor -------------------------------------------------------------------------------- /comid/testcases/comid-3.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/comid/testcases/comid-3.cbor -------------------------------------------------------------------------------- /comid/testcases/comid-4.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/comid/testcases/comid-4.cbor -------------------------------------------------------------------------------- /comid/testcases/comid-5.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/comid/testcases/comid-5.cbor -------------------------------------------------------------------------------- /testdata/intermediateCA.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/testdata/intermediateCA.der -------------------------------------------------------------------------------- /coev/testcases/ce-evidence.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coev/testcases/ce-evidence.cbor -------------------------------------------------------------------------------- /coev/testcases/ce-identity.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coev/testcases/ce-identity.cbor -------------------------------------------------------------------------------- /coserv/testvectors/rv-results.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/rv-results.cbor -------------------------------------------------------------------------------- /cots/data/Snobbish Apparel_ta.ta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/cots/data/Snobbish Apparel_ta.ta -------------------------------------------------------------------------------- /comid/testcases/comid-design-cd.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/comid/testcases/comid-design-cd.cbor -------------------------------------------------------------------------------- /extensions/corim-map-extensions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/extensions/corim-map-extensions.png -------------------------------------------------------------------------------- /coev/tdx/testcases/ce-pce-evidence.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coev/tdx/testcases/ce-pce-evidence.cbor -------------------------------------------------------------------------------- /coev/tdx/testcases/ce-qe-evidence.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coev/tdx/testcases/ce-qe-evidence.cbor -------------------------------------------------------------------------------- /comid/testcases/comid-firmware-cd.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/comid/testcases/comid-firmware-cd.cbor -------------------------------------------------------------------------------- /corim/testcases/signed-good-corim.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/corim/testcases/signed-good-corim.cbor -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/rv-class-simple.cbor -------------------------------------------------------------------------------- /coev/tdx/testcases/ce-seam-evidence.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coev/tdx/testcases/ce-seam-evidence.cbor -------------------------------------------------------------------------------- /corim/testcases/signed-example-corim.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/corim/testcases/signed-example-corim.cbor -------------------------------------------------------------------------------- /corim/testcases/unsigned-good-corim.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/corim/testcases/unsigned-good-corim.cbor -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-stateful.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/rv-class-stateful.cbor -------------------------------------------------------------------------------- /corim/testcases/unsigned-example-corim.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/corim/testcases/unsigned-example-corim.cbor -------------------------------------------------------------------------------- /profiles/tdx/testcases/comid_pce_refval.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/profiles/tdx/testcases/comid_pce_refval.cbor -------------------------------------------------------------------------------- /profiles/tdx/testcases/comid_qe_refval.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/profiles/tdx/testcases/comid_qe_refval.cbor -------------------------------------------------------------------------------- /comid/testcases/comid-cond-endorse-series.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/comid/testcases/comid-cond-endorse-series.cbor -------------------------------------------------------------------------------- /coserv/testvectors/example-class-selector.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/example-class-selector.cbor -------------------------------------------------------------------------------- /coserv/testvectors/example-group-selector.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/example-group-selector.cbor -------------------------------------------------------------------------------- /profiles/tdx/testcases/comid_seam_refval.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/profiles/tdx/testcases/comid_seam_refval.cbor -------------------------------------------------------------------------------- /corim/testcases/signed-corim-with-extensions.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/corim/testcases/signed-corim-with-extensions.cbor -------------------------------------------------------------------------------- /coserv/testvectors/example-instance-selector.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/example-instance-selector.cbor -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple-results.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/rv-class-simple-results.cbor -------------------------------------------------------------------------------- /corim/testcases/unsigned-corim-with-extensions.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/corim/testcases/unsigned-corim-with-extensions.cbor -------------------------------------------------------------------------------- /cocli/README.md: -------------------------------------------------------------------------------- 1 | # Corim Command Line Interface 2 | 3 | `cocli` is now available at [https://github.com/veraison/cocli](https://github.com/veraison/cocli) 4 | -------------------------------------------------------------------------------- /coserv/testvectors/example-class-selector-noindent.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/example-class-selector-noindent.cbor -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple-results-source-artifacts.cbor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veraison/corim/HEAD/coserv/testvectors/rv-class-simple-results-source-artifacts.cbor -------------------------------------------------------------------------------- /coserv/testvectors/example-instance-selector.b64u: -------------------------------------------------------------------------------- 1 | ogB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAYKB2QImRwLerb7v3q2B2QIwRYmZeGVWAsB0MjAzMC0xMi0wMVQxODozMDowMVoDAg -------------------------------------------------------------------------------- /coserv/testvectors/example-group-selector.b64u: -------------------------------------------------------------------------------- 1 | ogB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAoKB2QIwRYmZeGVWgdglUDH7Wr8CPkmSqk6V-cFQO_oCwHQyMDMwLTEyLTAxVDE4OjMwOjAxWgMB -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple.b64u: -------------------------------------------------------------------------------- 1 | ogB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAIGBowDZAjBEABEiMwFuRXhhbXBsZSBWZW5kb3ICbUV4YW1wbGUgTW9kZWwCwHQyMDMwLTEyLTAxVDE4OjMwOjAxWgMB -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-stateful.b64u: -------------------------------------------------------------------------------- 1 | ogB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAIGCowDZAjBEABEiMwFuRXhhbXBsZSBWZW5kb3ICbUV4YW1wbGUgTW9kZWyBoQGiC2tDb21wb25lbnQgQQKBggFBqgLAdDIwMzAtMTItMDFUMTg6MzA6MDFaAwE -------------------------------------------------------------------------------- /coserv/testvectors/example-class-selector.b64u: -------------------------------------------------------------------------------- 1 | ogB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAIKBowDZAjBEABEiMwFuRXhhbXBsZSBWZW5kb3ICbUV4YW1wbGUgTW9kZWyBoQDYJVAx-1q_Aj5JkqpOlfnBUDv6AsB0MjAzMC0xMi0wMVQxODozMDowMVoDAA -------------------------------------------------------------------------------- /coserv/testvectors/example-class-selector-noindent.b64u: -------------------------------------------------------------------------------- 1 | ogB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAIKBowDZAjBEABEiMwFuRXhhbXBsZSBWZW5kb3ICbUV4YW1wbGUgTW9kZWyBoQDYJVAx-1q_Aj5JkqpOlfnBUDv6AsB0MjAzMC0xMi0wMVQxODozMDowMVoDAA -------------------------------------------------------------------------------- /profiles/tdx/common.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | func isType[T any](v any) bool { 7 | _, ok := v.(T) 8 | return ok 9 | } 10 | -------------------------------------------------------------------------------- /coserv/testvectors/example-instance-selector.hex: -------------------------------------------------------------------------------- 1 | a20078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1018281d902264702deadbeefdead81d9023045899978655602c074323033302d31322d30315431383a33303a30315a0302 2 | -------------------------------------------------------------------------------- /corim/testcases/src/meta.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 1: 3 | 0: 4 | tag: 1 5 | value: 1640908800 6 | 1: 7 | tag: 1 8 | value: 1767139200 9 | 0: 10 | 1: 11 | tag: 32 12 | value: https://acme.example 13 | 0: ACME Ltd signing key 14 | -------------------------------------------------------------------------------- /coserv/testvectors/example-group-selector.hex: -------------------------------------------------------------------------------- 1 | a20078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1028281d9023045899978655681d8255031fb5abf023e4992aa4e95f9c1503bfa02c074323033302d31322d30315431383a33303a30315a0301 2 | -------------------------------------------------------------------------------- /coserv/testvectors/example-class-selector-noindent.diag: -------------------------------------------------------------------------------- 1 | {0: "tag:example.com,2025:cc-platform#1.0.0", 1: {0: 2, 1: {0: [[{0: 560(h'00112233'), 1: "Example Vendor", 2: "Example Model"}], [{0: 37(h'31fb5abf023e4992aa4e95f9c1503bfa')}]]}, 2: 0("2030-12-01T18:30:01Z"), 3: 0}} -------------------------------------------------------------------------------- /testdata/endEntity.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIFaWg82uhJd5ejmQxb5HmxLveE4NZ9W/CeyYwYjiFximoAoGCCqGSM49 3 | AwEHoUQDQgAECc8hy7bQIFZJBtS1pQW9E0LT56doX04VB/lWX3S0fJCCAQbcwdkv 4 | tBImTgx96mL4ZyZSJo8rKyJ6UgIEUHEHPQ== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple.hex: -------------------------------------------------------------------------------- 1 | a20078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1008181a300d902304400112233016e4578616d706c652056656e646f72026d4578616d706c65204d6f64656c02c074323033302d31322d30315431383a33303a30315a0301 2 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-results.b64u: -------------------------------------------------------------------------------- 1 | owB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAIGBoQDZAjBFiZl4ZVYCwHQyMDMwLTEyLTAxVDE4OjMwOjAxWgMAAqIAgaIBgdkCMEOrze8CgqEAoQDZAjBFiZl4ZVaBogDYJVAx-1q_Aj5JkqpOlfnBUDv6AaIAogBlMS4yLjMBGUAAAdkCKQIKwHQyMDMwLTEyLTEzVDE4OjMwOjAyWg -------------------------------------------------------------------------------- /corim/testcases/src/ec-p256.jwk: -------------------------------------------------------------------------------- 1 | { 2 | "kty": "EC", 3 | "crv": "P-256", 4 | "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", 5 | "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", 6 | "d": "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE", 7 | "use": "enc", 8 | "kid": "1" 9 | } 10 | -------------------------------------------------------------------------------- /cots/hardware_version_type.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package cots 4 | 5 | import "github.com/veraison/swid" 6 | 7 | type HardwareVersionType struct { 8 | Version string 9 | 10 | Scheme swid.VersionScheme 11 | } 12 | -------------------------------------------------------------------------------- /coserv/testvectors/example-class-selector.hex: -------------------------------------------------------------------------------- 1 | a20078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1008281a300d902304400112233016e4578616d706c652056656e646f72026d4578616d706c65204d6f64656c81a100d8255031fb5abf023e4992aa4e95f9c1503bfa02c074323033302d31322d30315431383a33303a30315a0300 2 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-stateful.hex: -------------------------------------------------------------------------------- 1 | a20078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1008182a300d902304400112233016e4578616d706c652056656e646f72026d4578616d706c65204d6f64656c81a101a20b6b436f6d706f6e656e7420410281820141aa02c074323033302d31322d30315431383a33303a30315a0301 2 | -------------------------------------------------------------------------------- /coserv/testvectors/example-class-selector-noindent.hex: -------------------------------------------------------------------------------- 1 | a20078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1008281a300d902304400112233016e4578616d706c652056656e646f72026d4578616d706c65204d6f64656c81a100d8255031fb5abf023e4992aa4e95f9c1503bfa02c074323033302d31322d30315431383a33303a30315a0300 2 | -------------------------------------------------------------------------------- /coserv/testvectors/example-instance-selector.diag: -------------------------------------------------------------------------------- 1 | { 2 | 0: "tag:example.com,2025:cc-platform#1.0.0", 3 | 1: { 4 | 0: 2, 5 | 1: { 6 | 1: [ 7 | [ 550(h'02DEADBEEFDEAD') ], 8 | [ 560(h'8999786556') ] 9 | ] 10 | }, 11 | 2: 0("2030-12-01T18:30:01Z"), 12 | 3: 2 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /coserv/testvectors/example-group-selector.diag: -------------------------------------------------------------------------------- 1 | { 2 | 0: "tag:example.com,2025:cc-platform#1.0.0", 3 | 1: { 4 | 0: 2, 5 | 1:{ 6 | 2: [ 7 | [ 560(h'8999786556') ], 8 | [ 37(h'31FB5ABF023E4992AA4E95F9C1503BFA') ] 9 | ] 10 | }, 11 | 2: 0("2030-12-01T18:30:01Z"), 12 | 3: 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple-results-source-artifacts.b64u: -------------------------------------------------------------------------------- 1 | owB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAIGBowDZAjBEABEiMwFuRXhhbXBsZSBWZW5kb3ICbUV4YW1wbGUgTW9kZWwCwHQyMDMwLTEyLTAxVDE4OjMwOjAxWgMBAqMAgArAdDIwMzAtMTItMTNUMTg6MzA6MDJaC4KCeB9hcHBsaWNhdGlvbi92bmQuZXhhbXBsZS5yZWZ2YWxzRK-urayCeB9hcHBsaWNhdGlvbi92bmQuZXhhbXBsZS5yZWZ2YWxzRK2sq6o -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | mocks/ 18 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple-results.b64u: -------------------------------------------------------------------------------- 1 | owB4JnRhZzpleGFtcGxlLmNvbSwyMDI1OmNjLXBsYXRmb3JtIzEuMC4wAaQAAgGhAIGBowDZAjBEABEiMwFuRXhhbXBsZSBWZW5kb3ICbUV4YW1wbGUgTW9kZWwCwHQyMDMwLTEyLTAxVDE4OjMwOjAxWgMAAqIAgaIBgdkCMEOrze8CgqEAowDZAjBEABEiMwFuRXhhbXBsZSBWZW5kb3ICbUV4YW1wbGUgTW9kZWyCoQGiC2tDb21wb25lbnQgQQKCggFBqoICQbuhAaILa0NvbXBvbmVudCBCAoKCAUHMggJB3QrAdDIwMzAtMTItMTNUMTg6MzA6MDJa -------------------------------------------------------------------------------- /coserv/testvectors/rv-results.hex: -------------------------------------------------------------------------------- 1 | a30078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1008181a100d9023045899978655602c074323033302d31322d30315431383a33303a30315a030002a20081a20181d9023043abcdef0282a100a100d9023045899978655681a200d8255031fb5abf023e4992aa4e95f9c1503bfa01a200a20065312e322e330119400001d90229020ac074323033302d31322d31335431383a33303a30325a 2 | -------------------------------------------------------------------------------- /corim/testcases/corim.json: -------------------------------------------------------------------------------- 1 | { 2 | "corim-id": "5c57e8f4-46cd-421b-91c9-08cf93e13cfc", 3 | "validity": { 4 | "not-before": "2021-12-31T00:00:00Z", 5 | "not-after": "2025-12-31T00:00:00Z" 6 | }, 7 | "entities": [ 8 | { 9 | "name": "ACME Ltd.", 10 | "regid": "acme.example", 11 | "roles": [ 12 | "manifestCreator" 13 | ] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /corim/testcases/corim-ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "corim-id": "5c57e8f4-46cd-421b-91c9-08cf93e13cfc", 3 | "profile": "http://example.com/test-profile", 4 | "ext1": "foo", 5 | "validity": { 6 | "not-before": "2021-12-31T00:00:00Z", 7 | "not-after": "2025-12-31T00:00:00Z" 8 | }, 9 | "entities": [ 10 | { 11 | "name": "ACME Ltd.", 12 | "regid": "acme.example", 13 | "roles": [ 14 | "manifestCreator" 15 | ] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /scripts/licenses.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2024 Contributors to the Veraison project. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | set -e 6 | 7 | type go-licenses &> /dev/null || go get github.com/google/go-licenses 8 | 9 | MODULES+=("github.com/veraison/corim/corim") 10 | MODULES+=("github.com/veraison/corim/comid") 11 | 12 | for module in ${MODULES[@]} 13 | do 14 | echo ">> retrieving licenses [ ${module} ]" 15 | go-licenses csv ${module} 16 | done 17 | -------------------------------------------------------------------------------- /coserv/testvectors/example-class-selector.diag: -------------------------------------------------------------------------------- 1 | { 2 | 0: "tag:example.com,2025:cc-platform#1.0.0", 3 | 1: { 4 | 0: 2, 5 | 1: { 6 | 0: [ 7 | [ { 8 | 0: 560(h'00112233'), 9 | 1: "Example Vendor", 10 | 2: "Example Model" 11 | } ], 12 | [ { 13 | 0: 37(h'31FB5ABF023E4992AA4E95F9C1503BFA') 14 | } ] 15 | ] 16 | }, 17 | 2: 0("2030-12-01T18:30:01Z"), 18 | 3: 0 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /coserv/quads.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coserv 5 | 6 | import "github.com/veraison/corim/comid" 7 | 8 | type RefValQuad struct { 9 | Authorities *comid.CryptoKeys `cbor:"1,keyasint"` 10 | RVTriple *comid.ValueTriple `cbor:"2,keyasint"` 11 | } 12 | 13 | type AKQuad struct { 14 | Authorities *comid.CryptoKeys `cbor:"1,keyasint"` 15 | AKTriple *comid.KeyTriple `cbor:"2,keyasint"` 16 | } 17 | -------------------------------------------------------------------------------- /coserv/testvectors/Makefile: -------------------------------------------------------------------------------- 1 | SRCS := $(wildcard *.diag) 2 | CBOR := $(SRCS:.diag=.cbor) 3 | B64U := $(SRCS:.diag=.b64u) 4 | HEX := $(SRCS:.diag=.hex) 5 | 6 | %.cbor: %.diag ; diag2cbor.rb < $< > $@ 7 | 8 | CLEANFILES += $(CBOR) 9 | 10 | %.b64u: %.cbor ; basenc --base64url --wrap 0 $< | tr -d '=' > $@ 11 | 12 | CLEANFILES += $(B64U) 13 | 14 | %.hex: %.cbor ; xxd -p -c0 $< > $@ 15 | 16 | CLEANFILES += $(HEX) 17 | 18 | all: $(CBOR) $(B64U) $(HEX) 19 | 20 | clean: ; $(RM) -f $(CLEANFILES) 21 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple-results-source-artifacts.hex: -------------------------------------------------------------------------------- 1 | a30078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1008181a300d902304400112233016e4578616d706c652056656e646f72026d4578616d706c65204d6f64656c02c074323033302d31322d30315431383a33303a30315a030102a300800ac074323033302d31322d31335431383a33303a30325a0b8282781f6170706c69636174696f6e2f766e642e6578616d706c652e72656676616c7344afaeadac82781f6170706c69636174696f6e2f766e642e6578616d706c652e72656676616c7344adacabaa 2 | -------------------------------------------------------------------------------- /profiles/tdx/types.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | const ( 7 | UintType = "uint" 8 | IntType = "int" 9 | FloatType = "float" 10 | StringType = "string" 11 | StringExprType = "string-expression" 12 | NumericExprType = "numeric-expression" 13 | BytesType = "bytes" 14 | DigestType = "digest" 15 | DigestExprType = "digest-expression" 16 | ) 17 | 18 | type maskType []byte 19 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple-results.hex: -------------------------------------------------------------------------------- 1 | a30078267461673a6578616d706c652e636f6d2c323032353a63632d706c6174666f726d23312e302e3001a4000201a1008181a300d902304400112233016e4578616d706c652056656e646f72026d4578616d706c65204d6f64656c02c074323033302d31322d30315431383a33303a30315a030002a20081a20181d9023043abcdef0282a100a300d902304400112233016e4578616d706c652056656e646f72026d4578616d706c65204d6f64656c82a101a20b6b436f6d706f6e656e7420410282820141aa820241bba101a20b6b436f6d706f6e656e7420420282820141cc820241dd0ac074323033302d31322d31335431383a33303a30325a 2 | -------------------------------------------------------------------------------- /comid/typeandvalue.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import "encoding/json" 7 | 8 | // tnv (type'n'value) stores a JSON object with two attributes: a string "type" 9 | // and a generic "value" (left undecoded) defined by type. This type is used in 10 | // a few places to implement the choice types that CBOR handles using tags. 11 | type tnv struct { 12 | Type string `json:"type"` 13 | Value json.RawMessage `json:"value"` 14 | } 15 | -------------------------------------------------------------------------------- /coev/extensions.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coev 5 | 6 | import "github.com/veraison/corim/extensions" 7 | 8 | const ( 9 | ExtConciseEvidence extensions.Point = "ConciseEvidence" 10 | ExtEvTriples extensions.Point = "EvTriples" 11 | ExtEvidenceTriples extensions.Point = "EvidenceTriples" 12 | ExtEvidenceTriplesFlags extensions.Point = "EvidenceTriplesFlags" 13 | ) 14 | 15 | type Extensions struct { 16 | extensions.Extensions 17 | } 18 | -------------------------------------------------------------------------------- /comid/tagidentity.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/veraison/swid" 10 | ) 11 | 12 | type TagIdentity struct { 13 | TagID swid.TagID `cbor:"0,keyasint" json:"id"` 14 | TagVersion uint `cbor:"1,keyasint,omitempty" json:"version,omitempty"` 15 | } 16 | 17 | func (o TagIdentity) Valid() error { 18 | if o.TagID == (swid.TagID{}) { 19 | return fmt.Errorf("empty tag-id") 20 | } 21 | 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /profiles/tdx/teepceid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | type TeePCEID string 11 | 12 | func NewTeePCEID(val string) (*TeePCEID, error) { 13 | var pceID TeePCEID 14 | if val == "" { 15 | return nil, fmt.Errorf("null string for TeePCEID") 16 | } 17 | pceID = TeePCEID(val) 18 | return &pceID, nil 19 | } 20 | 21 | func (o TeePCEID) Valid() error { 22 | if o == "" { 23 | return fmt.Errorf("nil TeePCEID") 24 | } 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple.diag: -------------------------------------------------------------------------------- 1 | { 2 | / profile / 0: "tag:example.com,2025:cc-platform#1.0.0", 3 | / query / 1: { 4 | / artifact-type / 0: 2, / reference-values / 5 | / environment-selector / 1: { 6 | / class / 0: [ [ 7 | { 8 | / class-id / 0: 560(h'00112233'), / tagged-bytes / 9 | / vendor / 1: "Example Vendor", 10 | / model / 2: "Example Model" 11 | } 12 | ] ] 13 | }, 14 | / timestamp / 2: 0("2030-12-01T18:30:01Z"), 15 | / result-type / 3: 1 / source-material / 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /comid/testcases/regen-from-src.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # Copyright 2024 Contributors to the Veraison project. 3 | # SPDX-License-Identifier: Apache-2.0 4 | set -e 5 | 6 | THIS_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 7 | 8 | if [[ "$(type -p diag2cbor.rb)" == "" ]]; then 9 | echo "ERROR: please install ruby-cbor-diag package" 10 | exit 1 11 | fi 12 | 13 | for case in "$THIS_DIR"/src/*.diag; do 14 | outfile=$(basename "${case%%.diag}").cbor 15 | 16 | echo "generating $outfile" 17 | 18 | diag2cbor.rb "$case" > "$THIS_DIR/$outfile" 19 | done 20 | 21 | echo "done." 22 | -------------------------------------------------------------------------------- /coev/testcases/regen-from-src.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # Copyright 2024-2025 Contributors to the Veraison project. 3 | # SPDX-License-Identifier: Apache-2.0 4 | set -e 5 | 6 | THIS_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 7 | 8 | if [[ "$(type -p diag2cbor.rb)" == "" ]]; then 9 | echo "ERROR: please install ruby-cbor-diag package" 10 | exit 1 11 | fi 12 | 13 | for case in "$THIS_DIR"/src/*.diag; do 14 | outfile=$(basename "${case%%.diag}").cbor 15 | 16 | echo "generating $outfile" 17 | 18 | diag2cbor.rb "$case" > "$THIS_DIR/$outfile" 19 | done 20 | 21 | echo "done." 22 | -------------------------------------------------------------------------------- /coev/tdx/testcases/regen-from-src.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # Copyright 2024-2025 Contributors to the Veraison project. 3 | # SPDX-License-Identifier: Apache-2.0 4 | set -e 5 | 6 | THIS_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 7 | 8 | if [[ "$(type -p diag2cbor.rb)" == "" ]]; then 9 | echo "ERROR: please install ruby-cbor-diag package" 10 | exit 1 11 | fi 12 | 13 | for case in "$THIS_DIR"/src/*.diag; do 14 | outfile=$(basename "${case%%.diag}").cbor 15 | 16 | echo "generating $outfile" 17 | 18 | diag2cbor.rb "$case" > "$THIS_DIR/$outfile" 19 | done 20 | 21 | echo "done." 22 | -------------------------------------------------------------------------------- /profiles/tdx/testcases/regen-from-src.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # Copyright 2024-2025 Contributors to the Veraison project. 3 | # SPDX-License-Identifier: Apache-2.0 4 | set -e 5 | 6 | THIS_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 7 | 8 | if [[ "$(type -p diag2cbor.rb)" == "" ]]; then 9 | echo "ERROR: please install ruby-cbor-diag package" 10 | exit 1 11 | fi 12 | 13 | for case in "$THIS_DIR"/src/*.diag; do 14 | outfile=$(basename "${case%%.diag}").cbor 15 | 16 | echo "generating $outfile" 17 | 18 | diag2cbor.rb "$case" > "$THIS_DIR/$outfile" 19 | done 20 | 21 | echo "done." 22 | -------------------------------------------------------------------------------- /comid/uuid_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package comid 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestUUID_JSON(t *testing.T) { 14 | val := TaggedUUID(TestUUID) 15 | expected := fmt.Sprintf("%q", val.String()) 16 | 17 | out, err := val.MarshalJSON() 18 | require.NoError(t, err) 19 | assert.Equal(t, expected, string(out)) 20 | 21 | var outUUID TaggedUUID 22 | 23 | err = outUUID.UnmarshalJSON(out) 24 | require.NoError(t, err) 25 | assert.Equal(t, val, outUUID) 26 | } 27 | -------------------------------------------------------------------------------- /coserv/resulttype.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coserv 5 | 6 | type ResultType uint8 7 | 8 | const ( 9 | ResultTypeCollectedArtifacts ResultType = iota 10 | ResultTypeSourceArtifacts 11 | ResultTypeBoth 12 | ) 13 | 14 | // String returns the string representation of the target ResultType 15 | func (a ResultType) String() string { 16 | switch a { 17 | case ResultTypeCollectedArtifacts: 18 | return "collected-artifacts" 19 | case ResultTypeSourceArtifacts: 20 | return "source-artifacts" 21 | case ResultTypeBoth: 22 | return "both" 23 | } 24 | // unreachable 25 | return "" 26 | } 27 | -------------------------------------------------------------------------------- /profiles/tdx/teeattributes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // nolint:dupl 5 | package tdx 6 | 7 | import "fmt" 8 | 9 | type TeeAttributes maskType 10 | 11 | func NewTeeAttributes(val []byte) (*TeeAttributes, error) { 12 | if val == nil { 13 | return nil, fmt.Errorf("nil TeeAttributes") 14 | } 15 | teeAttributes := TeeAttributes(val) 16 | return &teeAttributes, nil 17 | } 18 | 19 | func (o TeeAttributes) Valid() error { 20 | if o == nil { 21 | return fmt.Errorf("nil TeeAttributes") 22 | } 23 | if len(o) == 0 { 24 | return fmt.Errorf("zero len TeeAttributes") 25 | } 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /profiles/tdx/teemiscselect.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import "fmt" 7 | 8 | type TeeMiscSelect maskType 9 | 10 | func NewTeeMiscSelect(val []byte) (*TeeMiscSelect, error) { 11 | var miscSelect TeeMiscSelect 12 | if val == nil { 13 | return nil, fmt.Errorf("nil value for TeeMiscSelect") 14 | } 15 | miscSelect = TeeMiscSelect(val) 16 | return &miscSelect, nil 17 | } 18 | 19 | func (o TeeMiscSelect) Valid() error { 20 | if o == nil { 21 | return fmt.Errorf("nil TeeMiscSelect") 22 | } 23 | if len(o) == 0 { 24 | return fmt.Errorf("zero len TeeMiscSelect") 25 | } 26 | return nil 27 | } 28 | -------------------------------------------------------------------------------- /coserv/artifacttype.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coserv 5 | 6 | type ArtifactType uint8 7 | 8 | const ( 9 | ArtifactTypeEndorsedValues ArtifactType = iota 10 | ArtifactTypeTrustAnchors 11 | ArtifactTypeReferenceValues 12 | ) 13 | 14 | // String returns the string representation of the target ArtifactType 15 | func (a ArtifactType) String() string { 16 | switch a { 17 | case ArtifactTypeEndorsedValues: 18 | return "endorsed-values" 19 | case ArtifactTypeReferenceValues: 20 | return "reference-values" 21 | case ArtifactTypeTrustAnchors: 22 | return "trust-anchors" 23 | } 24 | // unreachable 25 | return "" 26 | } 27 | -------------------------------------------------------------------------------- /testdata/testdata.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package testdata 4 | 5 | import ( 6 | _ "embed" 7 | ) 8 | 9 | var ( 10 | //go:embed endEntity.der 11 | // EndEntityDer is an intermediate CA-signed certificate. 12 | EndEntityDer []byte 13 | 14 | //go:embed endEntity.key 15 | // EndEntityKey is a key used for signing CoRIMs. 16 | EndEntityKey []byte 17 | 18 | //go:embed intermediateCA.der 19 | // IntermediateCA is a root-signed intermediate certificate authority key certificate. 20 | IntermediateCA []byte 21 | 22 | //go:embed rootCA.der 23 | // RootCA is a self-signed root certificate authority key certificate. 24 | RootCA []byte 25 | ) 26 | -------------------------------------------------------------------------------- /comid/valuetriple_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package comid 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/google/uuid" 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func Test_ReferenceValue(t *testing.T) { 14 | rv := ValueTriple{} 15 | err := rv.Valid() 16 | assert.EqualError(t, err, "environment validation failed: environment must not be empty") 17 | 18 | id, err := uuid.NewUUID() 19 | require.NoError(t, err) 20 | rv.Environment.Instance = MustNewUUIDInstance(id) 21 | err = rv.Valid() 22 | assert.EqualError(t, err, "measurements validation failed: no measurement entries") 23 | } 24 | -------------------------------------------------------------------------------- /extensions/typechoice_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package extensions 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | type testTCValue string 12 | 13 | func (o testTCValue) String() string { 14 | return string(o) 15 | } 16 | 17 | func (o testTCValue) Valid() error { 18 | return nil 19 | } 20 | 21 | func (o testTCValue) Type() string { 22 | return "test_type" 23 | } 24 | 25 | func Test_TypeChoiceValueMarshalJSON(t *testing.T) { 26 | buf, err := TypeChoiceValueMarshalJSON(testTCValue("test")) 27 | assert.NoError(t, err) 28 | assert.JSONEq(t, `{"type": "test_type", "value": "test"}`, string(buf)) 29 | } 30 | -------------------------------------------------------------------------------- /comid/cryptokeys_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func Test_CryptoKeys(t *testing.T) { 13 | keys := NewCryptoKeys() 14 | err := keys.Valid() 15 | 16 | assert.EqualError(t, err, "no keys to validate") 17 | 18 | keys.Add(MustNewCOSEKey(TestCOSEKey)). 19 | Add(MustNewPKIXBase64Key(TestECPubKey)). 20 | Add(nil) 21 | 22 | err = keys.Valid() 23 | assert.NoError(t, err) 24 | 25 | badKey := CryptoKey{TaggedPKIXBase64Cert("lol, nope!")} 26 | keys.Add(&badKey) 27 | 28 | err = keys.Valid() 29 | assert.ErrorContains(t, err, "invalid key at index 2") 30 | } 31 | -------------------------------------------------------------------------------- /scripts/cov.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Contributors to the Veraison project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | import os 4 | import re 5 | import sys 6 | 7 | # read output of (potentially many invocations of) "go test -cover -short", 8 | # e.g., "coverage: 65.7% of statements" 9 | cover_report_lines = sys.stdin.read() 10 | 11 | if len(cover_report_lines) == 0: 12 | sys.exit(2) 13 | 14 | # extract min coverage from GITHUB_WORKFLOW, e.g., "60.4%" 15 | min_cover = float(re.findall(r'\d*\.\d+|\d+', os.environ['GITHUB_WORKFLOW'])[0]) 16 | 17 | for l in cover_report_lines.splitlines(): 18 | cover = float(re.findall(r'\d*\.\d+|\d+', l)[0]) 19 | if cover < min_cover: 20 | print("want", min_cover, "got", cover) 21 | sys.exit(1) 22 | 23 | sys.exit(0) 24 | -------------------------------------------------------------------------------- /comid/ueid_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package comid 4 | 5 | import ( 6 | "encoding/base64" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func Test_NewTaggedUEID(t *testing.T) { 14 | ueid := UEID(TestUEID) 15 | tagged := TaggedUEID(TestUEID) 16 | bytes := MustHexDecode(t, TestUEIDString) 17 | 18 | for _, v := range []any{ 19 | TestUEID, 20 | &TestUEID, 21 | ueid, 22 | &ueid, 23 | tagged, 24 | &tagged, 25 | bytes, 26 | base64.StdEncoding.EncodeToString(bytes), 27 | } { 28 | ret, err := NewTaggedUEID(v) 29 | require.NoError(t, err) 30 | assert.Equal(t, []byte(TestUEID), ret.Bytes()) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /coev/test_vars.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coev 5 | 6 | import ( 7 | "time" 8 | 9 | "github.com/google/uuid" 10 | "github.com/veraison/corim/comid" 11 | "github.com/veraison/swid" 12 | ) 13 | 14 | //nolint:lll 15 | var ( 16 | TestUUIDString = "31fb5abf-023e-4992-aa4e-95f9c1503bfa" 17 | TestUUID = comid.UUID(uuid.Must(uuid.Parse(TestUUIDString))) 18 | TestProfile = "https://abc.com" 19 | TestTag = "31fb5abf-023e-4992-aa4e-95f9c1503bfa" 20 | TestDeviceID = "BAD809B1-7032-43D9-8F94-BF128E5D061D" 21 | TestKey = true 22 | TestDate, _ = time.Parse(time.RFC3339, "1970-01-01T00:00:00Z") 23 | TestEvidence = swid.Evidence{Date: TestDate, DeviceID: TestDeviceID} 24 | ) 25 | -------------------------------------------------------------------------------- /corim/testcases/regen-from-src.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # Copyright 2024 Contributors to the Veraison project. 3 | # SPDX-License-Identifier: Apache-2.0 4 | set -e 5 | 6 | GEN_TESTCASE=$(go env GOPATH)/bin/gen-testcase 7 | 8 | if [[ ! -f ${GEN_TESTCASE} ]]; then 9 | echo "installing gen-testcase" 10 | go install github.com/veraison/gen-testcase@v0.0.3 11 | fi 12 | 13 | testcases=( 14 | good-corim 15 | example-corim 16 | corim-with-extensions 17 | ) 18 | 19 | for case in "${testcases[@]}"; do 20 | echo "generating unsigned-${case}.cbor" 21 | 22 | ${GEN_TESTCASE} "src/${case}.yaml" -o "unsigned-${case}.cbor" 23 | 24 | echo "generating signed-${case}.cbor" 25 | 26 | ${GEN_TESTCASE} -s src/ec-p256.jwk -m src/meta.yaml "src/${case}.yaml" \ 27 | -o "signed-${case}.cbor" 28 | done 29 | 30 | echo "done." 31 | -------------------------------------------------------------------------------- /coserv/query_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coserv 5 | 6 | import ( 7 | "testing" 8 | "time" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestQuery_Valid_empty_query(t *testing.T) { 15 | tv := &Query{} 16 | 17 | actual := tv.Valid() 18 | 19 | expected := "invalid environment selector: non-empty<> constraint violation" 20 | 21 | assert.EqualError(t, actual, expected) 22 | } 23 | 24 | func TestQuery_Valid_invalid_timestamp(t *testing.T) { 25 | tv := exampleClassQuery(t) 26 | 27 | require.NotNil(t, tv.SetTimestamp(time.Time{})) 28 | 29 | actual := tv.Valid() 30 | 31 | expected := "timestamp not set" 32 | 33 | assert.EqualError(t, actual, expected) 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/linters.yml: -------------------------------------------------------------------------------- 1 | # Go Linters - GitHub Actions 2 | name: linters 3 | on: [push, pull_request] 4 | jobs: 5 | 6 | # Check linters on latest-ubuntu with default version of Go. 7 | lint: 8 | name: Lint 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/setup-go@v3 12 | with: 13 | go-version: "1.23" 14 | - name: Checkout code 15 | uses: actions/checkout@v2 16 | - name: Install golangci-lint 17 | run: | 18 | go version 19 | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.1.6 20 | - name: Install mockgen 21 | run: | 22 | go install github.com/golang/mock/mockgen@v1.5.0 23 | - name: Run required linters in .golangci.yml plus hard-coded ones here 24 | run: make lint 25 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple-results-source-artifacts.diag: -------------------------------------------------------------------------------- 1 | { 2 | / profile / 0: "tag:example.com,2025:cc-platform#1.0.0", 3 | / query / 1: { 4 | / artifact-type / 0: 2, / reference-values / 5 | / environment-selector / 1: { 6 | / class / 0: [ [ 7 | { 8 | / class-id / 0: 560(h'00112233'), / tagged-bytes / 9 | / vendor / 1: "Example Vendor", 10 | / model / 2: "Example Model" 11 | } 12 | ] ] 13 | }, 14 | / timestamp / 2: 0("2030-12-01T18:30:01Z"), 15 | / result-type / 3: 1 / source-artifacts / 16 | }, 17 | / results / 2: { 18 | / rvq / 0: [ ], 19 | / expiry / 10: 0("2030-12-13T18:30:02Z"), 20 | / source artifacts / 11: [ 21 | [ "application/vnd.example.refvals", h'afaeadac' ], 22 | [ "application/vnd.example.refvals", h'adacabaa' ] 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /extensions/cbor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package extensions 5 | 6 | import ( 7 | cbor "github.com/fxamacker/cbor/v2" 8 | ) 9 | 10 | var ( 11 | em, emError = initCBOREncMode() 12 | dm, dmError = initCBORDecMode() 13 | ) 14 | 15 | func initCBOREncMode() (en cbor.EncMode, err error) { 16 | encOpt := cbor.EncOptions{ 17 | Sort: cbor.SortCoreDeterministic, 18 | IndefLength: cbor.IndefLengthForbidden, 19 | TimeTag: cbor.EncTagRequired, 20 | } 21 | return encOpt.EncMode() 22 | } 23 | 24 | func initCBORDecMode() (dm cbor.DecMode, err error) { 25 | decOpt := cbor.DecOptions{ 26 | IndefLength: cbor.IndefLengthAllowed, 27 | } 28 | return decOpt.DecMode() 29 | } 30 | 31 | func init() { 32 | if emError != nil { 33 | panic(emError) 34 | } 35 | if dmError != nil { 36 | panic(dmError) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-stateful.diag: -------------------------------------------------------------------------------- 1 | { 2 | / profile / 0: "tag:example.com,2025:cc-platform#1.0.0", 3 | / query / 1: { 4 | / artifact-type / 0: 2, / reference-values / 5 | / environment-selector / 1: { 6 | / stateful-class / 0: [ 7 | [ 8 | / class / { 9 | / class-id / 0: 560(h'00112233'), / tagged-bytes / 10 | / vendor / 1: "Example Vendor", 11 | / model / 2: "Example Model" 12 | }, 13 | / measurements / [ 14 | / measurement-map / { 15 | / mval / 1: { 16 | / name / 11: "Component A", 17 | / digests / 2: [ 18 | [ 1, h'aa' ] 19 | ] 20 | } 21 | } 22 | ] 23 | ] 24 | ] 25 | }, 26 | / timestamp / 2: 0("2030-12-01T18:30:01Z"), 27 | / result-type / 3: 1 / source-material / 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # GitHub Actions - CI for Go to build & test. See ci-go-cover.yml and linters.yml for code coverage and linters. 2 | # Taken from: https://github.com/fxamacker/cbor/workflows/ci.yml (thanks!) 3 | name: ci 4 | on: [push, pull_request] 5 | jobs: 6 | 7 | # Test on various OS with specified Go version. 8 | tests: 9 | name: Test on ${{matrix.os}} 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | matrix: 13 | os: [macos-latest, ubuntu-latest] 14 | steps: 15 | - uses: actions/setup-go@v3 16 | with: 17 | go-version: "1.23" 18 | - name: Checkout code 19 | uses: actions/checkout@v2 20 | with: 21 | fetch-depth: 1 22 | - name: Install mockgen 23 | run: | 24 | go install github.com/golang/mock/mockgen@v1.5.0 25 | - name: Build project 26 | run: go build ./... 27 | - name: Run tests 28 | run: | 29 | go version 30 | make test 31 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-results.diag: -------------------------------------------------------------------------------- 1 | { 2 | / profile / 0: "tag:example.com,2025:cc-platform#1.0.0", 3 | / query / 1: { 4 | 0: 2, 5 | 1: { 6 | 0: [ [ 7 | { 8 | 0: 560(h'8999786556') 9 | } 10 | ] ] 11 | }, 12 | 2: 0("2030-12-01T18:30:01Z"), 13 | 3: 0 14 | }, 15 | / results / 2: { 16 | 0: [ 17 | { 18 | 1: [ 560(h'abcdef') ], 19 | 2: [ 20 | { 21 | 0: { 22 | 0: 560(h'8999786556') 23 | } 24 | }, 25 | [ 26 | { 27 | 0: 37(h'31FB5ABF023E4992AA4E95F9C1503BFA'), 28 | 1: { 29 | / version / 0: { 30 | 0: "1.2.3", 31 | 1: 16384 32 | }, 33 | / svn / 1: 553(2) 34 | } 35 | } 36 | ] 37 | ] 38 | } 39 | ], 40 | 10: 0("2030-12-13T18:30:02Z") 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /profiles/tdx/teepceid_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestPCEID_NewTeePCEID_OK(t *testing.T) { 14 | _, err := NewTeePCEID(TestPCEID) 15 | require.NoError(t, err) 16 | } 17 | 18 | func TestPCEID_NewTeePCEID_NOK(t *testing.T) { 19 | expectedErr := "null string for TeePCEID" 20 | _, err := NewTeePCEID("") 21 | assert.EqualError(t, err, expectedErr) 22 | } 23 | 24 | func TestPCEID_Valid_OK(t *testing.T) { 25 | pceID, err := NewTeePCEID(TestPCEID) 26 | require.NoError(t, err) 27 | err = pceID.Valid() 28 | require.NoError(t, err) 29 | } 30 | 31 | func TestPCEID_Valid_NOK(t *testing.T) { 32 | pceID := TeePCEID("") 33 | expectedErr := "nil TeePCEID" 34 | err := pceID.Valid() 35 | assert.EqualError(t, err, expectedErr) 36 | } 37 | -------------------------------------------------------------------------------- /comid/bytes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | const BytesType = "bytes" 11 | 12 | type TaggedBytes []byte 13 | 14 | func NewBytes(val any) (*TaggedBytes, error) { 15 | var ret TaggedBytes 16 | 17 | if val == nil { 18 | return &ret, nil 19 | } 20 | 21 | switch t := val.(type) { 22 | case string: 23 | b := []byte(t) 24 | ret = TaggedBytes(b) 25 | case []byte: 26 | ret = TaggedBytes(t) 27 | case *[]byte: 28 | ret = TaggedBytes(*t) 29 | default: 30 | return nil, fmt.Errorf("unexpected type for bytes: %T", t) 31 | } 32 | return &ret, nil 33 | } 34 | 35 | func (o TaggedBytes) String() string { 36 | return string(o) 37 | } 38 | 39 | func (o TaggedBytes) Valid() error { 40 | return nil 41 | } 42 | 43 | func (o TaggedBytes) Type() string { 44 | return "bytes" 45 | } 46 | 47 | func (o TaggedBytes) Bytes() []byte { 48 | 49 | return o 50 | } 51 | -------------------------------------------------------------------------------- /profiles/tdx/teeattributes_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestNewTeeAttributes_NewTeeAttributes_OK(t *testing.T) { 14 | _, err := NewTeeAttributes(TestTeeAttributes) 15 | require.Nil(t, err) 16 | } 17 | 18 | func TestNewTeeAttributes_NewTeeAttributes_NOK(t *testing.T) { 19 | expectedErr := "nil TeeAttributes" 20 | _, err := NewTeeAttributes(nil) 21 | assert.EqualError(t, err, expectedErr) 22 | } 23 | 24 | func TestNewTeeAttributes_Valid_OK(t *testing.T) { 25 | tA := TeeAttributes(TestTeeAttributes) 26 | err := tA.Valid() 27 | require.Nil(t, err) 28 | } 29 | 30 | func TestNewTeeAttributes_Valid_NOK(t *testing.T) { 31 | tA := TeeAttributes{} 32 | expectedErr := "zero len TeeAttributes" 33 | err := tA.Valid() 34 | assert.EqualError(t, err, expectedErr) 35 | } 36 | -------------------------------------------------------------------------------- /profiles/tdx/teemiscselect_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestTeeMiscSelect_NewTeeMiscSelect_OK(t *testing.T) { 14 | _, err := NewTeeMiscSelect(TestTeeMiscSelect) 15 | require.Nil(t, err) 16 | } 17 | 18 | func TestTeeMiscSelect_NewTeeMiscSelect_NOK(t *testing.T) { 19 | expectedErr := "nil value for TeeMiscSelect" 20 | _, err := NewTeeMiscSelect(nil) 21 | assert.EqualError(t, err, expectedErr) 22 | } 23 | 24 | func TestNewTeeMiscSelect_Valid_OK(t *testing.T) { 25 | tA := TeeMiscSelect(TestTeeMiscSelect) 26 | err := tA.Valid() 27 | require.Nil(t, err) 28 | } 29 | 30 | func TestTeeMiscSelect_Valid_NOK(t *testing.T) { 31 | tA := TeeMiscSelect{} 32 | expectedErr := "zero len TeeMiscSelect" 33 | err := tA.Valid() 34 | assert.EqualError(t, err, expectedErr) 35 | } 36 | -------------------------------------------------------------------------------- /coev/testcases/src/ce-evidence.diag: -------------------------------------------------------------------------------- 1 | / tagged-concise-evidence / 571( { 2 | / ce.ev-triples / 0 : { 3 | / ce.evidence-triples / 0 : [ 4 | [ 5 | / environment-map / { 6 | / comid.class / 0 : { 7 | / comid.class-id / 0 : 8 | / tagged-oid-type / 111(h'6086480186F84D010F046301'), / 2.16.840.1.113741.1.15.4.99.1 / 9 | / comid.vendor / 1 : "xyzinc.example" 10 | } 11 | }, 12 | [ 13 | / measurement-map / { 14 | / comid.mval / 1 : { 15 | / digests / 2 : [ [ 1, h'A314FC2DC663AE7A6B6BC6787594057396E6B3F569CD50FD5DDB4D1BBAFD2B6A'] ] 16 | }, 17 | 2: 554("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFn0taoAwR3PmrKkYLtAsD9o05KSM6mbgfNCgpuL0g6VpTHkZl73wk5BDxoV7n+Oeee0iIqkW3HMZT3ETiniJdg==\n-----END PUBLIC KEY-----") 18 | } 19 | ] 20 | ] 21 | ] 22 | } 23 | } ) -------------------------------------------------------------------------------- /comid/keytriple.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import "fmt" 7 | 8 | // KeyTriple stores a cryptographic key triple record (identity-triple-record 9 | // or attest-key-triple-record) with CBOR and JSON serializations. Note that 10 | // the CBOR serialization packs the structure into an array. Instead, when 11 | // serializing to JSON, the structure is converted into an object. 12 | type KeyTriple struct { 13 | _ struct{} `cbor:",toarray"` 14 | Environment Environment `json:"environment"` 15 | VerifKeys CryptoKeys `json:"verification-keys"` 16 | } 17 | 18 | func (o KeyTriple) Valid() error { 19 | if err := o.Environment.Valid(); err != nil { 20 | return fmt.Errorf("environment validation failed: %w", err) 21 | } 22 | 23 | if err := o.VerifKeys.Valid(); err != nil { 24 | return fmt.Errorf("verification keys validation failed: %w", err) 25 | } 26 | return nil 27 | } 28 | 29 | type KeyTriples []KeyTriple 30 | 31 | func NewKeyTriples() *KeyTriples { 32 | return &KeyTriples{} 33 | } 34 | -------------------------------------------------------------------------------- /comid/psareferencevalue_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestPSARefValID_Valid_SignerID_range(t *testing.T) { 15 | signerID := []byte{} 16 | 17 | for i := 1; i <= 100; i++ { 18 | signerID = append(signerID, byte(0xff)) 19 | 20 | tv, err := NewPSARefValID(signerID) 21 | 22 | switch i { 23 | case 32, 48, 64: 24 | assert.NotNil(t, tv) 25 | assert.Nil(t, tv.Valid()) 26 | default: 27 | assert.Nil(t, tv) 28 | assert.EqualError( 29 | t, 30 | err, 31 | fmt.Sprintf("invalid PSA RefVal ID length: %d", i), 32 | ) 33 | } 34 | } 35 | } 36 | 37 | func TestPSARefValID_String(t *testing.T) { 38 | signerID := MustHexDecode(t, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") 39 | refvalID, err := NewTaggedPSARefValID(signerID) 40 | require.NoError(t, err) 41 | 42 | assert.Equal(t, `{"signer-id":"3q2+796tvu/erb7v3q2+796tvu/erb7v3q2+796tvu8="}`, refvalID.String()) 43 | } 44 | -------------------------------------------------------------------------------- /comid/testcases/src/comid-3.diag: -------------------------------------------------------------------------------- 1 | / concise-mid-tag / { 2 | / comid.tag-identity / 1 : { 3 | / comid.tag-id / 0 : "my-ns:acme-roadrunner-supplement" 4 | }, 5 | / comid.entity / 2 : [ { 6 | / comid.entity-name / 0 : "ACME Inc.", 7 | / comid.reg-id / 1 : 32("https://acme.example"), 8 | / comid.role / 2 : [ 1,0,2 ] / creator, tag-creator, maintainer / 9 | } ], 10 | / comid.triples / 4 : { 11 | / comid.reference-triples / 0 : [ 12 | [ 13 | / environment-map / { 14 | / comid.class / 0 : { 15 | / comid.class-id / 0 : 16 | / tagged-oid-type / 111( 17 | h'5502C000' 18 | ), 19 | / comid.vendor / 1 : "ACME Inc.", 20 | / comid.model / 2 : "ACME RoadRunner Firmware" 21 | } 22 | }, 23 | [ 24 | / measurement-map / { 25 | / comid.mkey / 0: 700, 26 | / comid.mval / 1 : { 27 | / comid.digests / 2 : [[ 28 | / hash-alg-id / 6, / sha-256-32 / 29 | / hash-value / h'ABCDEF00' ]] 30 | } 31 | } 32 | ] 33 | ] 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /corim/validity.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package corim 5 | 6 | import ( 7 | "fmt" 8 | "time" 9 | ) 10 | 11 | type Validity struct { 12 | NotBefore *time.Time `cbor:"0,keyasint,omitempty" json:"not-before,omitempty"` 13 | NotAfter time.Time `cbor:"1,keyasint" json:"not-after"` 14 | } 15 | 16 | func NewValidity() *Validity { 17 | return &Validity{} 18 | } 19 | 20 | // Set instantiates a Validity object (using the supplied time inputs) & checks it been valid 21 | func (o *Validity) Set(notAfter time.Time, notBefore *time.Time) *Validity { 22 | if o != nil { 23 | v := Validity{ 24 | NotBefore: notBefore, 25 | NotAfter: notAfter, 26 | } 27 | 28 | if v.Valid() != nil { 29 | return nil 30 | } 31 | 32 | *o = v 33 | } 34 | return o 35 | } 36 | 37 | // Valid checks for validity of fields inside the Validity object 38 | func (o Validity) Valid() error { 39 | if o.NotBefore != nil { 40 | if delta := o.NotAfter.Sub(*o.NotBefore); delta < 0 { 41 | return fmt.Errorf("invalid not-before / not-after: negative delta (%d)", delta) 42 | } 43 | } 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /extensions/typechoice.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package extensions 4 | 5 | import ( 6 | "encoding/json" 7 | 8 | "github.com/veraison/corim/encoding" 9 | ) 10 | 11 | var StringType = "string" 12 | 13 | // ITypeChoiceValue is the interface that is implemented by all concrete type 14 | // choice value types. Specific type choices define their own value interfaces 15 | // that embed this one (and possibly include additional methods). 16 | type ITypeChoiceValue interface { 17 | // String returns the string representation of the ITypeChoiceValue. 18 | String() string 19 | // Valid returns an error if validation of the ITypeChoiceValue fails, 20 | // or nil if it succeeds. 21 | Valid() error 22 | // Type returns the type name of this ITypeChoiceValue implementation. 23 | Type() string 24 | } 25 | 26 | func TypeChoiceValueMarshalJSON(v ITypeChoiceValue) ([]byte, error) { 27 | valueBytes, err := json.Marshal(v) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | value := encoding.TypeAndValue{ 33 | Type: v.Type(), 34 | Value: valueBytes, 35 | } 36 | 37 | return json.Marshal(value) 38 | } 39 | -------------------------------------------------------------------------------- /corim/testcases/comid.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": "en-GB", 3 | "tag-identity": { 4 | "id": "43BBE37F-2E61-4B33-AED3-53CFF1428B16", 5 | "version": 0 6 | }, 7 | "entities": [ 8 | { 9 | "name": "ACME Ltd.", 10 | "regid": "https://acme.example", 11 | "roles": [ 12 | "tagCreator", 13 | "creator", 14 | "maintainer" 15 | ] 16 | } 17 | ], 18 | "triples": { 19 | "reference-values": [ 20 | { 21 | "environment": { 22 | "class": { 23 | "id": { 24 | "type": "psa.impl-id", 25 | "value": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=" 26 | }, 27 | "vendor": "ACME", 28 | "model": "RoadRunner" 29 | } 30 | }, 31 | "measurements": [ 32 | { 33 | "key": { 34 | "type": "cca.platform-config-id", 35 | "value": "cfg v1.0.0" 36 | }, 37 | "value": { 38 | "raw-value": { 39 | "type": "bytes", 40 | "value": "cmF3dmFsdWUKcmF3dmFsdWUK" 41 | } 42 | } 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /comid/version.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/veraison/swid" 10 | ) 11 | 12 | // Version stores a version-map with JSON and CBOR serializations. 13 | type Version struct { 14 | Version string `cbor:"0,keyasint" json:"value"` 15 | Scheme swid.VersionScheme `cbor:"1,keyasint" json:"scheme"` 16 | } 17 | 18 | func NewVersion() *Version { 19 | return &Version{} 20 | } 21 | 22 | func (o *Version) SetVersion(v string) *Version { 23 | if o != nil { 24 | o.Version = v 25 | } 26 | return o 27 | } 28 | 29 | func (o *Version) SetScheme(v int64) *Version { 30 | if o != nil { 31 | if o.Scheme.SetCode(v) != nil { 32 | return nil 33 | } 34 | } 35 | return o 36 | } 37 | 38 | func (o Version) Valid() error { 39 | if o.Version == "" { 40 | return fmt.Errorf("empty version") 41 | } 42 | return nil 43 | } 44 | 45 | func (o Version) Equal(r Version) bool { 46 | if o.Scheme != r.Scheme || o.Version != r.Version { 47 | return false 48 | } 49 | 50 | return true 51 | } 52 | 53 | func (o Version) CompareAgainstReference(r Version) bool { 54 | return o.Equal(r) 55 | } 56 | -------------------------------------------------------------------------------- /comid/version_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package comid 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/veraison/swid" 10 | ) 11 | 12 | func TestVersion_Valid_OK(t *testing.T) { 13 | v := NewVersion() 14 | 15 | v.SetVersion("1.55.22") 16 | v.SetScheme(swid.VersionSchemeSemVer) 17 | 18 | assert.Nil(t, v.Valid()) 19 | } 20 | 21 | func TestVersion_Valid_NOK(t *testing.T) { 22 | v := NewVersion() 23 | 24 | assert.EqualError(t, v.Valid(), "empty version") 25 | } 26 | 27 | func TestVersion_Equal_True(t *testing.T) { 28 | claim := NewVersion() 29 | claim.SetVersion("1.55.22") 30 | claim.SetScheme(swid.VersionSchemeSemVer) 31 | 32 | ref := NewVersion() 33 | ref.SetVersion("1.55.22") 34 | ref.SetScheme(swid.VersionSchemeSemVer) 35 | 36 | assert.True(t, claim.Equal(*ref)) 37 | } 38 | 39 | func TestVersion_Equal_False(t *testing.T) { 40 | claim := NewVersion() 41 | claim.SetVersion("1.55.22") 42 | claim.SetScheme(swid.VersionSchemeSemVer) 43 | 44 | ref := NewVersion() 45 | ref.SetVersion("1.55.40") 46 | ref.SetScheme(swid.VersionSchemeSemVer) 47 | 48 | assert.False(t, claim.Equal(*ref)) 49 | } 50 | -------------------------------------------------------------------------------- /comid/keytriple_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestVerificationKeys_Valid_empty(t *testing.T) { 13 | invalidKey := CryptoKey{TaggedPKIXBase64Key("")} 14 | 15 | tvs := []struct { 16 | env Environment 17 | verifkey CryptoKeys 18 | testerr string 19 | }{ 20 | { 21 | env: Environment{}, 22 | verifkey: CryptoKeys{}, 23 | testerr: "environment validation failed: environment must not be empty", 24 | }, 25 | { 26 | env: Environment{Instance: MustNewUEIDInstance(TestUEID)}, 27 | verifkey: CryptoKeys{}, 28 | testerr: "verification keys validation failed: no keys to validate", 29 | }, 30 | { 31 | env: Environment{Instance: MustNewUEIDInstance(TestUEID)}, 32 | verifkey: CryptoKeys{&invalidKey}, 33 | testerr: "verification keys validation failed: invalid key at index 0: key value not set", 34 | }, 35 | } 36 | for _, tv := range tvs { 37 | av := KeyTriple{Environment: tv.env, VerifKeys: tv.verifkey} 38 | err := av.Valid() 39 | assert.EqualError(t, err, tv.testerr) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /coserv/resultset_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coserv 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | "github.com/veraison/cmw" 12 | "github.com/veraison/corim/comid" 13 | ) 14 | 15 | func TestResultSet_AddAttestationKeys(t *testing.T) { 16 | authority, err := comid.NewCryptoKeyTaggedBytes(testAuthority) 17 | require.NoError(t, err) 18 | 19 | akq := AKQuad{ 20 | Authorities: comid.NewCryptoKeys().Add(authority), 21 | AKTriple: &comid.KeyTriple{ 22 | Environment: comid.Environment{ 23 | Class: comid.NewClassBytes(testBytes), 24 | }, 25 | VerifKeys: comid.CryptoKeys{ 26 | comid.MustNewPKIXBase64Key(comid.TestECPubKey), 27 | }, 28 | }, 29 | } 30 | 31 | rset := NewResultSet().SetExpiry(testExpiry).AddAttestationKeys(akq) 32 | assert.NotNil(t, rset) 33 | } 34 | 35 | func TestResultSet_AddSourceArtifacts(t *testing.T) { 36 | cmw0, err := cmw.NewMonad("application/vnd.example.refvals", []byte{0x00, 0x01, 0x02, 0x03}) 37 | require.NoError(t, err) 38 | 39 | rset := NewResultSet().SetExpiry(testExpiry).AddSourceArtifacts(*cmw0) 40 | assert.NotNil(t, rset) 41 | } 42 | -------------------------------------------------------------------------------- /corim/testcases/comid-ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": "en-GB", 3 | "tag-identity": { 4 | "id": "43BBE37F-2E61-4B33-AED3-53CFF1428B16", 5 | "version": 0 6 | }, 7 | "entities": [ 8 | { 9 | "name": "ACME Ltd.", 10 | "regid": "https://acme.example", 11 | "address": "123 Fake Street", 12 | "roles": [ 13 | "tagCreator", 14 | "creator", 15 | "maintainer" 16 | ] 17 | } 18 | ], 19 | "triples": { 20 | "reference-values": [ 21 | { 22 | "environment": { 23 | "class": { 24 | "id": { 25 | "type": "psa.impl-id", 26 | "value": "YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=" 27 | }, 28 | "vendor": "ACME", 29 | "model": "RoadRunner" 30 | } 31 | }, 32 | "measurements": [ 33 | { 34 | "key": { 35 | "type": "cca.platform-config-id", 36 | "value": "cfg v1.0.0" 37 | }, 38 | "value": { 39 | "timestamp": 1720782190, 40 | "raw-value": { 41 | "type": "bytes", 42 | "value": "cmF3dmFsdWUKcmF3dmFsdWUK" 43 | } 44 | } 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /comid/cryptokeys.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import "fmt" 7 | 8 | // CryptoKeys is an array of *CryptoKey 9 | type CryptoKeys []*CryptoKey 10 | 11 | // NewCryptoKeys instantiates an empty CryptoKeys 12 | func NewCryptoKeys() *CryptoKeys { 13 | return new(CryptoKeys) 14 | } 15 | 16 | // Add the supplied *CryptoKey to the CryptoKeys 17 | func (o *CryptoKeys) Add(v *CryptoKey) *CryptoKeys { 18 | if o != nil && v != nil { 19 | *o = append(*o, v) 20 | } 21 | return o 22 | } 23 | 24 | // Valid returns an error if any of the contained keys fail to validate, or if 25 | // CryptoKeys is empty 26 | func (o CryptoKeys) Valid() error { 27 | if len(o) == 0 { 28 | return fmt.Errorf("no keys to validate") 29 | } 30 | 31 | for i, vk := range o { 32 | if err := vk.Valid(); err != nil { 33 | return fmt.Errorf("invalid key at index %d: %w", i, err) 34 | } 35 | } 36 | return nil 37 | } 38 | 39 | // String returns a string representation of all CryptoKeys 40 | func (o CryptoKeys) String() string { 41 | if len(o) == 0 { 42 | return "[]" 43 | } 44 | 45 | result := "[" 46 | for i, key := range o { 47 | if i > 0 { 48 | result += ", " 49 | } 50 | result += key.String() 51 | } 52 | result += "]" 53 | return result 54 | } 55 | -------------------------------------------------------------------------------- /comid/testcases/src/comid-1.diag: -------------------------------------------------------------------------------- 1 | / concise-mid-tag / { 2 | / comid.tag-identity / 1 : { 3 | / comid.tag-id / 0 : h'3f06af63a93c11e4979700505690773f' 4 | }, 5 | / comid.entity / 2 : [ { 6 | / comid.entity-name / 0 : "ACME Inc.", 7 | / comid.reg-id / 1 : 32("https://acme.example"), 8 | / comid.role / 2 : [ 0 ] / tag-creator / 9 | } ], 10 | / comid.triples / 4 : { 11 | / comid.reference-triples / 0 : [ [ 12 | / environment-map / { 13 | / comid.class / 0 : { 14 | / comid.class-id / 0 : 15 | / tagged-uuid-type / 37( 16 | h'67b28b6c34cc40a19117ab5b05911e37' 17 | ), 18 | / comid.vendor / 1 : "ACME Inc.", 19 | / comid.model / 2 : "ACME RoadRunner", 20 | / comid.layer / 3 : 1 21 | } 22 | }, 23 | [ 24 | / measurement-map / { 25 | / comid.mval / 1 : { 26 | / comid.ver / 0 : { 27 | / comid.version / 0 : "1.0.0", 28 | / comid.version-scheme / 1 : 16384 / semver / 29 | }, 30 | / comid.digests / 2 : [ [ 31 | / hash-alg-id / 1, / sha256 / 32 | / hash-value / h'44aa336af4cb14a879432e53dd6571c7fa9bccafb75f488259262d6ea3a4d91b' 33 | ]] 34 | } 35 | } 36 | ] 37 | ] ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /profiles/tdx/numeric_expression.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import "fmt" 7 | 8 | type NumericExpression struct { 9 | _ struct{} `cbor:",toarray"` 10 | NumericOperator Operator `json:"numeric-operator"` 11 | NumericType NumericType `json:"numeric-type"` 12 | } 13 | 14 | type TaggedNumericExpression NumericExpression 15 | 16 | func (o NumericExpression) Valid() error { 17 | switch o.NumericOperator { 18 | case GT, GE, LT, LE: 19 | default: 20 | return fmt.Errorf("invalid Operator %d", o.NumericOperator) 21 | } 22 | return nil 23 | } 24 | 25 | // NewTaggedNumericExpression creates a new TaggedNumericExpression from the 26 | // supplied operator and an interface value. Allowed values are int, uint and float 27 | func NewTaggedNumericExpression(op uint, val any) (*TaggedNumericExpression, error) { 28 | var tnum TaggedNumericExpression 29 | switch op { 30 | case GT, GE, LT, LE: 31 | numType, err := NewNumericType(val) 32 | if err != nil { 33 | return nil, fmt.Errorf("invalid NumericType type: %w", err) 34 | } 35 | numeric := NumericExpression{NumericOperator: Operator(op), NumericType: *numType} 36 | tnum = TaggedNumericExpression(numeric) 37 | return &tnum, nil 38 | default: 39 | return nil, fmt.Errorf("invalid numeric operator %d", op) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/veraison/corim 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.24.2 6 | 7 | require ( 8 | fortio.org/safecast v1.0.0 9 | github.com/fxamacker/cbor/v2 v2.8.0 10 | github.com/google/uuid v1.3.0 11 | github.com/lestrrat-go/jwx/v2 v2.0.21 12 | github.com/spf13/cast v1.4.1 13 | github.com/stretchr/testify v1.10.0 14 | github.com/veraison/cmw v0.2.0 15 | github.com/veraison/eat v0.0.0-20210331113810-3da8a4dd42ff 16 | github.com/veraison/go-cose v1.2.1 17 | github.com/veraison/swid v1.1.1-0.20251003121634-fd1f7f1e1897 18 | ) 19 | 20 | require ( 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect 23 | github.com/goccy/go-json v0.10.2 // indirect 24 | github.com/kr/pretty v0.2.0 // indirect 25 | github.com/lestrrat-go/blackmagic v1.0.2 // indirect 26 | github.com/lestrrat-go/httpcc v1.0.1 // indirect 27 | github.com/lestrrat-go/httprc v1.0.5 // indirect 28 | github.com/lestrrat-go/iter v1.0.2 // indirect 29 | github.com/lestrrat-go/option v1.0.1 // indirect 30 | github.com/pmezard/go-difflib v1.0.0 // indirect 31 | github.com/segmentio/asm v1.2.0 // indirect 32 | github.com/x448/float16 v0.8.4 // indirect 33 | golang.org/x/crypto v0.31.0 // indirect 34 | golang.org/x/sys v0.28.0 // indirect 35 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect 36 | gopkg.in/yaml.v3 v3.0.1 // indirect 37 | ) 38 | -------------------------------------------------------------------------------- /coev/tdx/tdx_profile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "github.com/veraison/corim/coev" 8 | "github.com/veraison/corim/extensions" 9 | "github.com/veraison/corim/profiles/tdx" 10 | "github.com/veraison/eat" 11 | ) 12 | 13 | var ProfileID *eat.Profile 14 | 15 | // Registering the profile inside init() in the same file where it is defined 16 | // ensures that the profile will always be available, and you don't need to 17 | // remember to register it when you want to use it. The only potential 18 | // danger with that is if your profile ID clashes with another profile, 19 | // which should not happen if it is a registered PEN or a URL containing a domain 20 | // that you own. 21 | // Note Intel profile is "2.16.840.1.113741.1.16.1", 22 | // which is "joint-iso-itu-t.country.us.organization.intel.intel-comid.profile" 23 | 24 | func init() { 25 | var err error 26 | ProfileID, err = eat.NewProfile("2.16.840.1.113741.1.16.1") 27 | if err != nil { 28 | panic(err) // will not error, as the hard-coded string above is valid 29 | } 30 | 31 | extMap := extensions.NewMap(). 32 | Add(coev.ExtEvidenceTriples, &tdx.MValExtensions{}) 33 | 34 | if err := coev.RegisterProfile(ProfileID, extMap); err != nil { 35 | // will not error, assuming our profile ID is unique, and we've 36 | // correctly set up the extensions Map above 37 | panic(err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cots/cbor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package cots 5 | 6 | import ( 7 | "reflect" 8 | 9 | cbor "github.com/fxamacker/cbor/v2" 10 | "github.com/veraison/corim/comid" 11 | ) 12 | 13 | var ( 14 | em, emError = initCBOREncMode() 15 | dm, dmError = initCBORDecMode() 16 | ) 17 | 18 | var ( 19 | CotsTag uint64 = 507 20 | ) 21 | 22 | func cotsTags() cbor.TagSet { 23 | corimTagsMap := map[uint64]interface{}{ 24 | 32: comid.TaggedURI(""), 25 | } 26 | 27 | opts := cbor.TagOptions{ 28 | EncTag: cbor.EncTagRequired, 29 | DecTag: cbor.DecTagRequired, 30 | } 31 | 32 | tags := cbor.NewTagSet() 33 | 34 | for tag, typ := range corimTagsMap { 35 | if err := tags.Add(opts, reflect.TypeOf(typ), tag); err != nil { 36 | panic(err) 37 | } 38 | } 39 | 40 | return tags 41 | } 42 | 43 | func initCBOREncMode() (en cbor.EncMode, err error) { 44 | encOpt := cbor.EncOptions{ 45 | IndefLength: cbor.IndefLengthForbidden, 46 | TimeTag: cbor.EncTagRequired, 47 | } 48 | return encOpt.EncModeWithTags(cotsTags()) 49 | } 50 | 51 | func initCBORDecMode() (dm cbor.DecMode, err error) { 52 | decOpt := cbor.DecOptions{ 53 | IndefLength: cbor.IndefLengthAllowed, 54 | TimeTag: cbor.DecTagRequired, 55 | } 56 | return decOpt.DecModeWithTags(cotsTags()) 57 | } 58 | 59 | func init() { 60 | if emError != nil { 61 | panic(emError) 62 | } 63 | if dmError != nil { 64 | panic(dmError) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /coev/cbor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coev 5 | 6 | import ( 7 | "reflect" 8 | 9 | cbor "github.com/fxamacker/cbor/v2" 10 | "github.com/veraison/corim/comid" 11 | ) 12 | 13 | var ( 14 | em, emError = initCBOREncMode() 15 | dm, dmError = initCBORDecMode() 16 | ConciseEvidenceTag = []byte{0xd9, 0x02, 0x3B} 17 | coevTagMap = map[uint64]interface{}{ 18 | 37: comid.TaggedUUID{}, 19 | } 20 | ) 21 | 22 | func coevTags() cbor.TagSet { 23 | opts := cbor.TagOptions{ 24 | EncTag: cbor.EncTagRequired, 25 | DecTag: cbor.DecTagRequired, 26 | } 27 | 28 | tags := cbor.NewTagSet() 29 | 30 | for tag, typ := range coevTagMap { 31 | if err := tags.Add(opts, reflect.TypeOf(typ), tag); err != nil { 32 | panic(err) 33 | } 34 | } 35 | 36 | return tags 37 | } 38 | 39 | func initCBOREncMode() (en cbor.EncMode, err error) { 40 | encOpt := cbor.EncOptions{ 41 | Sort: cbor.SortCoreDeterministic, 42 | IndefLength: cbor.IndefLengthForbidden, 43 | TimeTag: cbor.EncTagRequired, 44 | } 45 | return encOpt.EncModeWithTags(coevTags()) 46 | } 47 | 48 | func initCBORDecMode() (dm cbor.DecMode, err error) { 49 | decOpt := cbor.DecOptions{ 50 | IndefLength: cbor.IndefLengthAllowed, 51 | } 52 | return decOpt.DecModeWithTags(coevTags()) 53 | } 54 | 55 | func init() { 56 | if emError != nil { 57 | panic(emError) 58 | } 59 | if dmError != nil { 60 | panic(dmError) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /coev/testcases/src/ce-coswid.diag: -------------------------------------------------------------------------------- 1 | / tagged-concise-evidence / 571({ 2 | / ce.ev-triples / 0 : { 3 | / ce.coswid-triples / 4 : [ 4 | [ /** ev-coswid-triple-record **/ 5 | / environment-map / { 6 | / comid.class / 0 : { 7 | / comid.class-id / 0 : 8 | / tagged-oid-type / 111(h'0607517B010F046308'), / 2.1.123.1.15.4.99.8 / 9 | / comid.vendor / 1 : "xyzinc.example" 10 | } 11 | }, 12 | [ 13 | / ev-coswid-evidence-map / { 14 | / ce.coswid-tag-id / 0 : "com.acme.rrd2013-ce-sp1-v4-1-5-0", 15 | / ce.coswid-evidence / 1 : { / *** evidence-entry in coswid ** / 16 | / directory / 16: { 17 | / fs-name / 24: "rrdetector", 18 | / root / 25: "%programdata%", 19 | / path-elements / 26: { 20 | / file / 17: { 21 | / fs-name / 24: "rrdetector.exe", 22 | / size / 20: 532712, 23 | / hash / 7: [ 24 | / hash-alg-id / 1, 25 | / hash-value / h'A314FC2DC663AE7A6B6BC6787594057396E6B3F569CD50FD5DDB4D1BBAFD2B6A' 26 | ] 27 | } 28 | } 29 | } 30 | }, 31 | / ce.authorized-by / 2 : [ 32 | / tagged-pkix-base64-key-type / 554("base64_key_X") 33 | ] 34 | } 35 | ] 36 | ] 37 | ] 38 | } 39 | }) -------------------------------------------------------------------------------- /profiles/tdx/cbor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "reflect" 8 | 9 | cbor "github.com/fxamacker/cbor/v2" 10 | ) 11 | 12 | var ( 13 | em, emError = initCBOREncMode() 14 | dm, dmError = initCBORDecMode() 15 | 16 | tdxTagsMap = map[uint64]interface{}{ 17 | // TDX tags 18 | 60010: TaggedNumericExpression{}, 19 | 60020: TaggedSetDigestExpression{}, 20 | 60021: TaggedSetStringExpression{}, 21 | } 22 | ) 23 | 24 | func tdxTags() cbor.TagSet { 25 | opts := cbor.TagOptions{ 26 | EncTag: cbor.EncTagRequired, 27 | DecTag: cbor.DecTagRequired, 28 | } 29 | 30 | tags := cbor.NewTagSet() 31 | 32 | for tag, typ := range tdxTagsMap { 33 | if err := tags.Add(opts, reflect.TypeOf(typ), tag); err != nil { 34 | panic(err) 35 | } 36 | } 37 | 38 | return tags 39 | } 40 | 41 | func initCBOREncMode() (en cbor.EncMode, err error) { 42 | encOpt := cbor.EncOptions{ 43 | Sort: cbor.SortCoreDeterministic, 44 | IndefLength: cbor.IndefLengthForbidden, 45 | TimeTag: cbor.EncTagRequired, 46 | } 47 | return encOpt.EncModeWithTags(tdxTags()) 48 | } 49 | 50 | func initCBORDecMode() (dm cbor.DecMode, err error) { 51 | decOpt := cbor.DecOptions{ 52 | IndefLength: cbor.IndefLengthAllowed, 53 | } 54 | return decOpt.DecModeWithTags(tdxTags()) 55 | } 56 | 57 | func init() { 58 | if emError != nil { 59 | panic(emError) 60 | } 61 | if dmError != nil { 62 | panic(dmError) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /comid/linkedtag_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | "github.com/veraison/swid" 12 | ) 13 | 14 | func TestLinkedTag_Valid_default_value(t *testing.T) { 15 | actual := NewLinkedTag() 16 | require.NotNil(t, actual) 17 | 18 | expected := "tag-id must be set in linked-tag" 19 | 20 | assert.EqualError(t, actual.Valid(), expected) 21 | } 22 | 23 | func TestLinkedTag_Valid_no_rel(t *testing.T) { 24 | tagID := swid.NewTagID(TestTagID) 25 | require.NotNil(t, tagID) 26 | 27 | actual := NewLinkedTag().SetLinkedTag(*tagID) 28 | require.NotNil(t, actual) 29 | 30 | expected := "rel validation failed: rel is unset" 31 | 32 | assert.EqualError(t, actual.Valid(), expected) 33 | } 34 | 35 | func TestLinkedTag_Valid_all_set(t *testing.T) { 36 | tagID := swid.NewTagID(TestTagID) 37 | require.NotNil(t, tagID) 38 | 39 | actual := NewLinkedTag(). 40 | SetLinkedTag(*tagID). 41 | SetRel(RelReplaces) 42 | require.NotNil(t, actual) 43 | 44 | assert.Nil(t, actual.Valid()) 45 | } 46 | 47 | func TestLinkedTags_Valid_bad_entry(t *testing.T) { 48 | emptyLT := NewLinkedTag() 49 | require.NotNil(t, emptyLT) 50 | 51 | actual := NewLinkedTags(). 52 | AddLinkedTag(*emptyLT) 53 | require.NotNil(t, actual) 54 | 55 | expected := "invalid linked-tag entry at index 0: tag-id must be set in linked-tag" 56 | 57 | assert.EqualError(t, actual.Valid(), expected) 58 | } 59 | -------------------------------------------------------------------------------- /coev/tdx/testcases/src/ce-seam-evidence.diag: -------------------------------------------------------------------------------- 1 | / tagged-concise-evidence / 571( { 2 | / ce.ev-triples / 0 : { 3 | / ce.evidence-triples / 0 : [ 4 | [ /** uses reference-triple-record schema **/ 5 | / environment-map / { 6 | / comid.class / 0 : { 7 | / comid.class-id / 0 : 8 | / tagged-oid-type / 111( 9 | h'6086480186F84D010F046301' 10 | ), / 2.16.840.1.113741.1.15.4.99.1 / 11 | / comid.vendor / 1 : "Intel Corporation", 12 | / comid.model / 2 : "TDX Seam" 13 | } 14 | }, 15 | [ 16 | / measurement-map / { 17 | / comid.mval / 1 : { 18 | / comid.attributes / -82 : [1, 2], 19 | / comid.isvprodid / -85 : h'ABCD', 20 | / comid.isvsvn / -73 : 6, 21 | / comid.mrtee / -83 : [ 22 | [1, h'E45B72F5C0C0B572DB4D8D3AB7E97F368FF74E62347A824DECB67A84E5224D75'] 23 | ], 24 | / comid.mrsigner / -84 : [ 25 | [1, h'E45B72F5C0C0B572DB4D8D3AB7E97F368FF74E62347A824DECB67A84E5224D75'], 26 | [7, h'E45B72F5C0C0B572DB4D8D3AB7E97F368FF74E62347A824DECB67A84E5224D75E45B72F5C0C0B572DB4D8D3AB7E97F36'] 27 | ], 28 | / tcb-eval-num / -86 : 11 29 | }, 30 | 2 : [554("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFn0taoAwR3PmrKkYLtAsD9o05KSM6mbgfNCgpuL0g6VpTHkZl73wk5BDxoV7n+Oeee0iIqkW3HMZT3ETiniJdg==\n-----END PUBLIC KEY-----")] 31 | } 32 | ] 33 | ] 34 | ] 35 | } 36 | } ) -------------------------------------------------------------------------------- /comid/macaddr.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "encoding/json" 8 | "fmt" 9 | "net" 10 | "reflect" 11 | ) 12 | 13 | // MACaddr is an HW address (e.g., IEEE 802 MAC-48, EUI-48, EUI-64) 14 | // 15 | // Note: Since TextUnmarshal is not defined on net.HardwareAddr 16 | // (see: https://github.com/golang/go/issues/29678) 17 | // we need to create an alias type with a custom decoder. 18 | type MACaddr net.HardwareAddr 19 | 20 | func (o MACaddr) Equal(r MACaddr) bool { 21 | return reflect.DeepEqual(o, r) 22 | } 23 | 24 | func (o MACaddr) CompareAgainstReference(r MACaddr) bool { 25 | return o.Equal(r) 26 | } 27 | 28 | // UnmarshalJSON deserialize a MAC address in textual form into the MACaddr 29 | // target, e.g.: 30 | // 31 | // "mac-addr": "00:00:5e:00:53:01" 32 | // 33 | // or 34 | // 35 | // "mac-addr": "02:00:5e:10:00:00:00:01" 36 | // 37 | // Supported formats are IEEE 802 MAC-48, EUI-48, EUI-64, e.g.: 38 | // 39 | // 00:00:5e:00:53:01 40 | // 00-00-5e-00-53-01 41 | // 02:00:5e:10:00:00:00:01 42 | // 02-00-5e-10-00-00-00-01 43 | func (o *MACaddr) UnmarshalJSON(data []byte) error { 44 | var s string 45 | 46 | if err := json.Unmarshal(data, &s); err != nil { 47 | return err 48 | } 49 | 50 | val, err := net.ParseMAC(s) 51 | if err != nil { 52 | return fmt.Errorf("bad MAC address %w", err) 53 | } 54 | 55 | *o = MACaddr(val) 56 | 57 | return nil 58 | } 59 | 60 | func (o MACaddr) MarshalJSON() ([]byte, error) { 61 | return json.Marshal(net.HardwareAddr(o).String()) 62 | } 63 | -------------------------------------------------------------------------------- /coev/tdx/testcases/src/ce-pce-evidence.diag: -------------------------------------------------------------------------------- 1 | / tagged-concise-evidence / 571( { 2 | / ce.ev-triples / 0 : { 3 | / ce.evidence-triples / 0 : [ 4 | [ /** uses reference-triple-record schema **/ 5 | / environment-map / { 6 | / comid.class / 0 : { 7 | / comid.class-id / 0 : 8 | / tagged-oid-type / 111( 9 | h'6086480186F84D0102030405' / 2.16.840.1.113741.1.2.3.4.5 - / 10 | ), 11 | / comid.vendor / 1 : "Intel Corporation", 12 | / comid.model / 2 : "TDX PCE TCB" 13 | } 14 | }, 15 | [ 16 | / measurement-map / { 17 | / comid.mval / 1 : { 18 | / comid.instanceid / -77 : h'00112233445566778899aabbccddeeff', 19 | / tcb-comp-svn / -125 : [ 20 | 10, 21 | 10, 22 | 2, 23 | 2, 24 | 2, 25 | 1, 26 | 4, 27 | 0, 28 | 0, 29 | 0, 30 | 0, 31 | 0, 32 | 0, 33 | 0, 34 | 0, 35 | 0 36 | ], 37 | / pceid / -80 : "0000" 38 | }, 39 | / authorized-by / 2 : [ 40 | 554("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFn0taoAwR3PmrKkYLtAsD9o05KSM6mbgfNCgpuL0g6VpTHkZl73wk5BDxoV7n+Oeee0iIqkW3HMZT3ETiniJdg==\n-----END PUBLIC KEY-----") 41 | ] 42 | } 43 | ] 44 | ] 45 | ] 46 | } 47 | } ) -------------------------------------------------------------------------------- /corim/extensions.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package corim 4 | 5 | import ( 6 | "github.com/veraison/corim/extensions" 7 | ) 8 | 9 | const ( 10 | ExtUnsignedCorim extensions.Point = "UnsignedCorim" 11 | ExtEntity extensions.Point = "CorimEntity" 12 | ExtSigner extensions.Point = "Signer" 13 | ) 14 | 15 | type IEntityConstrainer interface { 16 | ConstrainEntity(*Entity) error 17 | } 18 | 19 | type ICorimConstrainer interface { 20 | ConstrainCorim(*UnsignedCorim) error 21 | } 22 | 23 | type ISignerConstrainer interface { 24 | ConstrainSigner(*Signer) error 25 | } 26 | 27 | type Extensions struct { 28 | extensions.Extensions 29 | } 30 | 31 | func (o *Extensions) validEntity(entity *Entity) error { 32 | if !o.HaveExtensions() { 33 | return nil 34 | } 35 | 36 | ev, ok := o.IMapValue.(IEntityConstrainer) 37 | if ok { 38 | if err := ev.ConstrainEntity(entity); err != nil { 39 | return err 40 | } 41 | } 42 | 43 | return nil 44 | } 45 | 46 | func (o *Extensions) validCorim(c *UnsignedCorim) error { 47 | if !o.HaveExtensions() { 48 | return nil 49 | } 50 | 51 | ev, ok := o.IMapValue.(ICorimConstrainer) 52 | if ok { 53 | if err := ev.ConstrainCorim(c); err != nil { 54 | return err 55 | } 56 | } 57 | 58 | return nil 59 | } 60 | 61 | func (o *Extensions) validSigner(signer *Signer) error { 62 | if !o.HaveExtensions() { 63 | return nil 64 | } 65 | 66 | ev, ok := o.IMapValue.(ISignerConstrainer) 67 | if ok { 68 | if err := ev.ConstrainSigner(signer); err != nil { 69 | return err 70 | } 71 | } 72 | 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /coev/coswidtriple_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coev 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | "github.com/veraison/corim/comid" 12 | "github.com/veraison/swid" 13 | ) 14 | 15 | func TestCoSWIDTriple_NewCoSWIDTriple(t *testing.T) { 16 | s := NewCoSWIDTriple() 17 | require.NotNil(t, s) 18 | } 19 | 20 | func TestCoSWIDTriple_AddEnvironment(t *testing.T) { 21 | s := &CoSWIDTriple{} 22 | tv := &comid.Environment{ 23 | Class: comid.NewClassUUID(TestUUID), 24 | } 25 | 26 | err := s.AddEnvironment(tv) 27 | require.Nil(t, err) 28 | } 29 | 30 | func TestCoSWIDTriple_AddEnvironment_NOK(t *testing.T) { 31 | expectedErr := "no environment to add" 32 | s := &CoSWIDTriple{} 33 | var tv *comid.Environment 34 | err := s.AddEnvironment(tv) 35 | assert.EqualError(t, err, expectedErr) 36 | expectedErr = "environment is not valid: environment must not be empty" 37 | tv = &comid.Environment{} 38 | err = s.AddEnvironment(tv) 39 | assert.EqualError(t, err, expectedErr) 40 | } 41 | 42 | func TestCoSWIDTriple_AddEvidence(t *testing.T) { 43 | s := &CoSWIDTriple{} 44 | tv := &CoSWIDEvidenceMap{ 45 | TagID: swid.NewTagID(TestTag), 46 | Evidence: swid.Evidence{Date: TestDate, DeviceID: TestDeviceID}, 47 | } 48 | err := s.AddEvidence(tv) 49 | require.Nil(t, err) 50 | } 51 | 52 | func TestCoSWIDTriple_AddEvidence_NOK(t *testing.T) { 53 | expectedErr := "no evidence map to add" 54 | s := &CoSWIDTriple{} 55 | var tv *CoSWIDEvidenceMap 56 | err := s.AddEvidence(tv) 57 | assert.EqualError(t, err, expectedErr) 58 | } 59 | -------------------------------------------------------------------------------- /coserv/testvectors/rv-class-simple-results.diag: -------------------------------------------------------------------------------- 1 | { 2 | / profile / 0: "tag:example.com,2025:cc-platform#1.0.0", 3 | / query / 1: { 4 | / artifact-type / 0: 2, / reference-values / 5 | / environment-selector / 1: { 6 | / class / 0: [ [ 7 | { 8 | / class-id / 0: 560(h'00112233'), / tagged-bytes / 9 | / vendor / 1: "Example Vendor", 10 | / model / 2: "Example Model" 11 | } 12 | ] ] 13 | }, 14 | / timestamp / 2: 0("2030-12-01T18:30:01Z"), 15 | / result-type / 3: 0 / collected-material / 16 | }, 17 | / results / 2: { 18 | / rvq / 0: [ 19 | { 20 | / authorities / 1: [ 560(h'abcdef') ], 21 | / reference-triple / 2: [ 22 | / environment-map / { 23 | / class / 0: { 24 | / class-id / 0: 560(h'00112233'), 25 | / vendor / 1: "Example Vendor", 26 | / model / 2: "Example Model" 27 | } 28 | }, 29 | [ 30 | / measurement-map / { 31 | / mval / 1: { 32 | / name / 11: "Component A", 33 | / digests / 2: [ 34 | [ 1, h'aa' ], 35 | [ 2, h'bb' ] 36 | ] 37 | } 38 | }, 39 | / measurement-map / { 40 | / mval / 1: { 41 | / name / 11: "Component B", 42 | / digests / 2: [ 43 | [ 1, h'cc' ], 44 | [ 2, h'dd' ] 45 | ] 46 | } 47 | } 48 | ] 49 | ] 50 | } 51 | ], 52 | / expiry / 10: 0("2030-12-13T18:30:02Z") 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /coev/tdx/testcases/src/ce-qe-evidence.diag: -------------------------------------------------------------------------------- 1 | / tagged-concise-evidence / 571( { 2 | / ce.ev-triples / 0 : { 3 | / ce.evidence-triples / 0 : [ 4 | [ /** uses reference-triple-record schema **/ 5 | / environment-map / { 6 | / comid.class / 0 : { 7 | / comid.class-id / 0 : 8 | / tagged-oid-type / 111( 9 | h'6086480186F84D010F046301' 10 | ), / 2.16.840.1.113741.1.15.4.99.1 / 11 | / comid.vendor / 1 : "Intel Corporation", 12 | / comid.model / 2 : "TDX QE TCB" 13 | } 14 | }, 15 | [ 16 | / measurement-map / { 17 | / comid.mval / 1 : { 18 | / comid.miscselect / -81 : h'A0B0C0D000000000', 19 | / comid.isvprodid / -85 : 1, 20 | / comid.mrsigner / -84 : [ 21 | [1, h'E45B72F5C0C0B572DB4D8D3AB7E97F368FF74E62347A824DECB67A84E5224D75'], 22 | [8, h'a314fc2dc663ae7a6b6bc6787594057396e6b3f569cd50fd5ddb4d1bbafd2b6aa314fc2dc663ae7a6b6bc6787594057396e6b3f569cd50fd5ddb4d1bbafd2b6a'] 23 | ], 24 | / tcb-eval-num / -86 : 11, 25 | / advisory-ids / -89 : [ 26 | "INTEL-SA-00078", 27 | "INTEL-SA-00079" 28 | ], 29 | / tcbstatus / -88 : [ 30 | "UpToDate" 31 | ] 32 | }, 33 | / authorized-by / 2 : [ 34 | 554("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFn0taoAwR3PmrKkYLtAsD9o05KSM6mbgfNCgpuL0g6VpTHkZl73wk5BDxoV7n+Oeee0iIqkW3HMZT3ETiniJdg==\n-----END PUBLIC KEY-----") 35 | ] 36 | } 37 | ] 38 | ] 39 | ] 40 | } 41 | } ) -------------------------------------------------------------------------------- /comid/flagsmap_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024-2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package comid 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func Test_FlagsMap(t *testing.T) { 12 | fm := NewFlagsMap() 13 | assert.False(t, fm.AnySet()) 14 | 15 | for _, flag := range []Flag{ 16 | FlagIsConfigured, 17 | FlagIsSecure, 18 | FlagIsRecovery, 19 | FlagIsDebug, 20 | FlagIsReplayProtected, 21 | FlagIsIntegrityProtected, 22 | FlagIsRuntimeMeasured, 23 | FlagIsImmutable, 24 | FlagIsTcb, 25 | FlagIsConfidentialityProtected, 26 | } { 27 | fm.SetTrue(flag) 28 | assert.True(t, fm.AnySet()) 29 | assert.Equal(t, true, *fm.Get(flag)) 30 | 31 | fm.SetFalse(flag) 32 | assert.True(t, fm.AnySet()) 33 | assert.Equal(t, false, *fm.Get(flag)) 34 | 35 | fm.Clear(flag) 36 | assert.False(t, fm.AnySet()) 37 | assert.Equal(t, (*bool)(nil), fm.Get(flag)) 38 | } 39 | 40 | fm.SetTrue(Flag(-1)) 41 | fm.SetFalse(Flag(-1)) 42 | assert.False(t, fm.AnySet()) 43 | assert.Equal(t, (*bool)(nil), fm.Get(Flag(-1))) 44 | } 45 | 46 | func Test_FlagsMap_Equal_True(t *testing.T) { 47 | claim := NewFlagsMap() 48 | ref := NewFlagsMap() 49 | 50 | claim.SetTrue(FlagIsSecure) 51 | claim.SetTrue(FlagIsRuntimeMeasured) 52 | 53 | ref.SetTrue(FlagIsSecure) 54 | ref.SetTrue(FlagIsRuntimeMeasured) 55 | 56 | assert.True(t, claim.Equal(*ref)) 57 | } 58 | 59 | func Test_FlagsMap_Equal_False(t *testing.T) { 60 | claim := NewFlagsMap() 61 | ref := NewFlagsMap() 62 | 63 | claim.SetTrue(FlagIsSecure) 64 | claim.SetTrue(FlagIsRuntimeMeasured) 65 | 66 | ref.SetTrue(FlagIsSecure) 67 | 68 | assert.False(t, claim.Equal(*ref)) 69 | } 70 | -------------------------------------------------------------------------------- /coev/evidence_id_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coev 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/google/uuid" 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestEvidenceID_NewEvidenceID(t *testing.T) { 15 | ev, err := NewEvidenceID(TestUUIDString, "uuid") 16 | require.NoError(t, err) 17 | require.NotNil(t, ev) 18 | } 19 | 20 | func TestEvidenceID_SetUUID_OK(t *testing.T) { 21 | ev := &EvidenceID{} 22 | testUUID, err := uuid.Parse(TestUUIDString) 23 | require.NoError(t, err) 24 | i := ev.SetUUID(testUUID) 25 | require.NotNil(t, i) 26 | } 27 | 28 | func TestEvidenceID_GetUUID_OK(t *testing.T) { 29 | ev := MustNewUUIDEvidenceID(TestUUID) 30 | require.NotNil(t, ev) 31 | u, err := ev.GetUUID() 32 | assert.Nil(t, err) 33 | assert.Equal(t, u, TestUUID) 34 | } 35 | 36 | func TestEvidence_GetUUID_NOK(t *testing.T) { 37 | ev := &EvidenceID{} 38 | expectedErr := "evidence-id type is: " 39 | _, err := ev.GetUUID() 40 | assert.EqualError(t, err, expectedErr) 41 | } 42 | 43 | func TestEvidenceID_UnmarshalJSON_OK(t *testing.T) { 44 | for _, tv := range []struct { 45 | Name string 46 | Input string 47 | }{ 48 | { 49 | Name: "valid input test 1", 50 | Input: `{ "type": "uuid", "value": "31fb5abf-023e-4992-aa4e-95f9c1503bfa" }`, 51 | }, 52 | { 53 | Name: "valid input test 2", 54 | Input: `{ "type": "uuid", "value": "31fb5abf-023e-4992-aa4e-95f9c1503bfb"}`, 55 | }, 56 | } { 57 | t.Run(tv.Name, func(t *testing.T) { 58 | var actual EvidenceID 59 | err := actual.UnmarshalJSON([]byte(tv.Input)) 60 | require.NoError(t, err) 61 | }) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /profiles/tdx/operator.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "encoding/json" 8 | "fmt" 9 | ) 10 | 11 | type Operator uint 12 | 13 | const ( 14 | EQ = iota // EQual 15 | GT // greater than 16 | GE // greater than or equal to 17 | LT // less than 18 | LE // less than or equal to 19 | NOP // undefined 20 | MEM // member 21 | NMEM // no member 22 | SUB // sub-set 23 | SUP // super set 24 | DIS // dis-joint 25 | ) 26 | 27 | var ( 28 | StringToNumericOperator = map[string]Operator{ 29 | "equal": EQ, 30 | "greater_than": GT, 31 | "greater_or_equal": GE, 32 | "less_than": LT, 33 | "less_or equal": LE, 34 | "nop": NOP, 35 | "member": MEM, 36 | "non_member": NMEM, 37 | "subset": SUB, 38 | "superset": SUP, 39 | "disjoint": DIS, 40 | } 41 | NumericOperatorToString = map[Operator]string{ 42 | EQ: "equal", 43 | GT: "greater_than", 44 | GE: "greater_or_equal", 45 | LT: "less_than", 46 | LE: "less_or equal", 47 | NOP: "nop", 48 | MEM: "member", 49 | NMEM: "non_member", 50 | SUB: "subset", 51 | SUP: "superset", 52 | DIS: "disjoint", 53 | } 54 | ) 55 | 56 | func (o Operator) MarshalJSON() ([]byte, error) { 57 | return json.Marshal(NumericOperatorToString[o]) 58 | } 59 | 60 | func (o *Operator) UnmarshalJSON(data []byte) error { 61 | var str string 62 | err := json.Unmarshal(data, &str) 63 | if err != nil { 64 | return fmt.Errorf("unable to unmarshal operator: %w", err) 65 | } 66 | *o = StringToNumericOperator[str] 67 | return nil 68 | } 69 | -------------------------------------------------------------------------------- /coev/testcases/src/ce-identity.diag: -------------------------------------------------------------------------------- 1 | / tagged-concise-evidence / 571({ 2 | / ce.ev-triples / 0 : { 3 | / ce.identity-triples / 1 : [ 4 | [ 5 | / environment-map / { 6 | / class / 0 : { 7 | / class-id / 0 : 8 | / tagged-uuid-type / 37( 9 | h'67b28b6c34cc40a19117ab5b05911e37' 10 | ), 11 | / vendor / 1 : "ACME Inc.", 12 | / model / 2 : "ACME RoadRunner", 13 | / layer / 3 : 1 14 | } 15 | }, 16 | [ 17 | / tagged-pkix-base64-key-type / 554("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----"), 18 | / tagged-pkix-base64-cert-type / 555("-----BEGIN CERTIFICATE-----\nMIIB4TCCAYegAwIBAgIUGhrA9M3yQIFqckA2v6nQewmF30IwCgYIKoZIzj0EAwIw\nRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu\ndGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMzA5MDQxMTAxNDhaGA8yMDUxMDEx\nOTExMDE0OFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAf\nBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBZMBMGByqGSM49AgEGCCqG\nSM49AwEHA0IABFtQb6hfv68vAVmu2RDFNcWGBxEPAZS0+DBRzmjviAk7SL6xHhKa\n/7H0wD+uh9oQh3W+RxFyrUSqHekC3DizwNWjUzBRMB0GA1UdDgQWBBQWpNPb6eWD\nSM/+jwpbzoO3iHg4LTAfBgNVHSMEGDAWgBQWpNPb6eWDSM/+jwpbzoO3iHg4LTAP\nBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIAayNIF0eCJDZmcrqRjH\nf9h8GxeIDUnLqldeIvNfa+9SAiEA9ULBTPjnTUhYle226OAjg2sdhkXtb3Mu0E0F\nnuUmsIQ=\n-----END CERTIFICATE-----"), 19 | / tagged-thumbprint-type / 557([ 20 | / alg / 1, / sha256 / 21 | / value / h'44aa336af4cb14a879432e53dd6571c7fa9bccafb75f488259262d6ea3a4d91b' 22 | ]) 23 | ] 24 | ] 25 | ] 26 | } 27 | }) -------------------------------------------------------------------------------- /comid/testcases/src/comid-4.diag: -------------------------------------------------------------------------------- 1 | / concise-mid-tag / { 2 | / comid.tag-identity / 1 : { 3 | / comid.tag-id / 0 : h'3f06af63a93c11e4979700505690773f' 4 | }, 5 | / comid.entity / 2 : [ { 6 | / comid.entity-name / 0 : "ACME Inc.", 7 | / comid.reg-id / 1 : 32("https://acme.example"), 8 | / comid.role / 2 : [ 0 ] / tag-creator / 9 | } ], 10 | / comid.triples / 4 : { 11 | / comid.reference-triples / 0 : [ [ 12 | / environment-map / { 13 | / comid.class / 0 : { 14 | / comid.class-id / 0 : 15 | / tagged-uuid-type / 37( 16 | h'67b28b6c34cc40a19117ab5b05911e37' 17 | ), 18 | / comid.vendor / 1 : "ACME Inc.", 19 | / comid.model / 2 : "ACME RoadRunner", 20 | / comid.layer / 3 : 1 21 | } 22 | }, 23 | [ 24 | / measurement-map A / { 25 | / comid.mval / 1 : { 26 | / comid.ver / 0 : { 27 | / comid.version / 0 : "1.0.0", 28 | / comid.version-scheme / 1 : 16384 / semver / 29 | }, 30 | / comid.digests / 2 : [ [ 31 | / hash-alg-id / 1, / sha256 / 32 | / hash-value / h'44aa336af4cb14a879432e53dd6571c7fa9bccafb75f488259262d6ea3a4d91b' 33 | ] ] 34 | } 35 | }, 36 | / measurement-map B / { 37 | / comid.mval / 1 : { 38 | / comid.ver / 0 : { 39 | / comid.version / 0 : "2.0.0", 40 | / comid.version-scheme / 1 : 16384 / semver / 41 | }, 42 | / comid.digests / 2 : [ [ 43 | / hash-alg-id / 1, / sha256 / 44 | / hash-value / h'FFaa336af4cb14a879432e53dd6571c7fa9bccafb75f488259262d6ea3a4d91b' 45 | ] ] 46 | } 47 | } 48 | ] 49 | ] ] 50 | } 51 | } -------------------------------------------------------------------------------- /coserv/environmentselector_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coserv 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/veraison/corim/comid" 11 | ) 12 | 13 | func TestEnvironmentSelector_Valid_mixed_fail(t *testing.T) { 14 | tv := badExampleMixedSelector(t) 15 | 16 | err := tv.Valid() 17 | assert.EqualError(t, err, "only one selector type is allowed") 18 | } 19 | 20 | func TestEnvironmentSelector_Valid_empty_fail(t *testing.T) { 21 | tv := badExampleEmptySelector(t) 22 | 23 | err := tv.Valid() 24 | assert.EqualError(t, err, "non-empty<> constraint violation") 25 | } 26 | 27 | func TestStatefulClass_MarshalCBOR_invalid_missing_mandatory(t *testing.T) { 28 | tv := StatefulClass{} 29 | _, err := tv.MarshalCBOR() 30 | assert.EqualError(t, err, "mandatory field class not set") 31 | } 32 | 33 | func TestStatefulClass_MarshalCBOR_valid_full(t *testing.T) { 34 | tv := StatefulClass{ 35 | Class: comid.NewClassUUID(comid.TestUUID), 36 | Measurements: comid.NewMeasurements().Add(comid.MustNewUintMeasurement(uint(1))), 37 | } 38 | _, err := tv.MarshalCBOR() 39 | assert.NoError(t, err) 40 | } 41 | 42 | func TestStatefulClass_UnmarshalCBOR_invalid_eof(t *testing.T) { 43 | tv := comid.MustHexDecode(t, "") 44 | var actual StatefulClass 45 | err := actual.UnmarshalCBOR(tv) 46 | assert.EqualError(t, err, "unmarshaling StatefulClass: CBOR decoding: EOF") 47 | } 48 | 49 | func TestStatefulClass_UnmarshalCBOR_invalid_empty_array(t *testing.T) { 50 | tv := comid.MustHexDecode(t, "80") 51 | var actual StatefulClass 52 | err := actual.UnmarshalCBOR(tv) 53 | assert.EqualError(t, err, "unmarshaling StatefulClass: wrong number of entries (0) in the array") 54 | } 55 | -------------------------------------------------------------------------------- /coev/coswidtriple.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coev 5 | 6 | import ( 7 | "errors" 8 | "fmt" 9 | 10 | "github.com/veraison/corim/comid" 11 | ) 12 | 13 | // CoSWIDTriple stores a CoSWID Evidence 14 | // pertaining to an Environment 15 | type CoSWIDTriple struct { 16 | _ struct{} `cbor:",toarray"` 17 | Environment comid.Environment `json:"environment"` 18 | Evidence CoSWIDEvidence `json:"coswid-evidence"` 19 | } 20 | 21 | func NewCoSWIDTriple() *CoSWIDTriple { 22 | return &CoSWIDTriple{} 23 | } 24 | 25 | func (o *CoSWIDTriple) AddEnvironment(e *comid.Environment) error { 26 | if e == nil { 27 | return errors.New("no environment to add") 28 | } 29 | if err := e.Valid(); err != nil { 30 | return fmt.Errorf("environment is not valid: %w", err) 31 | } 32 | 33 | o.Environment = *e 34 | return nil 35 | } 36 | 37 | func (o *CoSWIDTriple) AddEvidence(e *CoSWIDEvidenceMap) error { 38 | 39 | if e == nil { 40 | return errors.New("no evidence map to add") 41 | } 42 | 43 | if len(o.Evidence) == 0 { 44 | o.Evidence = *NewCoSWIDEvidence() 45 | } 46 | 47 | o.Evidence = append(o.Evidence, *e) 48 | return nil 49 | } 50 | 51 | func (o CoSWIDTriple) Valid() error { 52 | if err := o.Environment.Valid(); err != nil { 53 | return fmt.Errorf("environment validation failed: %w", err) 54 | } 55 | 56 | if len(o.Evidence) == 0 { 57 | return errors.New("no evidence entry in the CoSWIDTriple") 58 | } 59 | 60 | // Validate Evidence entries 61 | if err := o.Evidence.Valid(); err != nil { 62 | return fmt.Errorf("evidence validation failed: %w", err) 63 | } 64 | 65 | return nil 66 | } 67 | 68 | type CoSWIDTriples []CoSWIDTriple 69 | 70 | func NewCoSWIDTriples() *CoSWIDTriples { 71 | return &CoSWIDTriples{} 72 | } 73 | -------------------------------------------------------------------------------- /coev/coswid_evidence.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coev 5 | 6 | import ( 7 | "errors" 8 | "fmt" 9 | 10 | "github.com/veraison/corim/comid" 11 | "github.com/veraison/swid" 12 | ) 13 | 14 | // CoSWIDEvidenceMap is the Map to carry CoSWID Evidence 15 | type CoSWIDEvidenceMap struct { 16 | TagID *swid.TagID `cbor:"0,keyasint,omitempty" json:"tagId,omitempty"` 17 | Evidence swid.Evidence `cbor:"1,keyasint,omitempty" json:"evidence,omitempty"` 18 | AuthorizedBy *comid.CryptoKeys `cbor:"2,keyasint,omitempty" json:"authorized-by,omitempty"` 19 | } 20 | 21 | type CoSWIDEvidence []CoSWIDEvidenceMap 22 | 23 | func NewCoSWIDEvidence() *CoSWIDEvidence { 24 | return &CoSWIDEvidence{} 25 | } 26 | 27 | func (o *CoSWIDEvidence) AddCoSWIDEvidenceMap(e *CoSWIDEvidenceMap) *CoSWIDEvidence { 28 | if o == nil { 29 | o = NewCoSWIDEvidence() 30 | } 31 | *o = append(*o, *e) 32 | return o 33 | } 34 | 35 | // Valid validates the CoSWIDEvidenceMap structure 36 | func (o *CoSWIDEvidenceMap) Valid() error { 37 | // Validate TagID if present 38 | if o.TagID != nil { 39 | if err := o.TagID.Valid(); err != nil { 40 | return fmt.Errorf("tagId validation failed: %w", err) 41 | } 42 | } 43 | 44 | // Validate Evidence 45 | if err := o.Evidence.Valid(); err != nil { 46 | return fmt.Errorf("evidence validation failed: %w", err) 47 | } 48 | 49 | return nil 50 | } 51 | 52 | // Valid validates all CoSWIDEvidence entries 53 | func (o CoSWIDEvidence) Valid() error { 54 | if len(o) == 0 { 55 | return errors.New("must contain at least one entry") 56 | } 57 | 58 | for i := range o { 59 | if err := o[i].Valid(); err != nil { 60 | return fmt.Errorf("evidence[%d] validation failed: %w", i, err) 61 | } 62 | } 63 | 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /comid/testcases/src/comid-5.diag: -------------------------------------------------------------------------------- 1 | / concise-mid-tag / { 2 | / comid.tag-identity / 1 : { 3 | / comid.tag-id / 0 : h'3f06af63a93c11e4979700505690773f' 4 | }, 5 | / comid.entity / 2 : [ { 6 | / comid.entity-name / 0 : "ACME Inc.", 7 | / comid.reg-id / 1 : 32("https://acme.example"), 8 | / comid.role / 2 : [ 0 ] / tag-creator / 9 | } ], 10 | / comid.triples / 4 : { 11 | / comid.reference-triples / 0 : [ [ 12 | / environment-map / { 13 | / comid.class / 0 : { 14 | / comid.class-id / 0 : 15 | / tagged-uuid-type / 37( 16 | h'67b28b6c34cc40a19117ab5b05911e37' 17 | ), 18 | / comid.vendor / 1 : "ACME Inc.", 19 | / comid.model / 2 : "ACME RoadRunner", 20 | / comid.layer / 3 : 1 21 | } 22 | }, 23 | [ 24 | / measurement-map A / { 25 | /comid.mkey / 0 : 1, 26 | / comid.mval / 1 : { 27 | / comid.ver / 0 : { 28 | / comid.version / 0 : "1.0.0", 29 | / comid.version-scheme / 1 : 16384 / semver / 30 | }, 31 | / comid.digests / 2 : [ [ 32 | / hash-alg-id / 1, / sha256 / 33 | / hash-value / h'44aa336af4cb14a879432e53dd6571c7fa9bccafb75f488259262d6ea3a4d91b' 34 | ] ] 35 | } 36 | }, 37 | / measurement-map B / { 38 | /comid.mkey / 0 : 2, 39 | / comid.mval / 1 : { 40 | / comid.ver / 0 : { 41 | / comid.version / 0 : "2.0.0", 42 | / comid.version-scheme / 1 : 16384 / semver / 43 | }, 44 | / comid.digests / 2 : [ [ 45 | / hash-alg-id / 1, / sha256 / 46 | / hash-value / h'FFaa336af4cb14a879432e53dd6571c7fa9bccafb75f488259262d6ea3a4d91b' 47 | ] ] 48 | } 49 | } 50 | ] 51 | ] ] 52 | } 53 | } -------------------------------------------------------------------------------- /encoding/embedded.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024-2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package encoding 4 | 5 | import "reflect" 6 | 7 | const omitempty = "omitempty" 8 | 9 | type embedded struct { 10 | Type reflect.Type 11 | Value reflect.Value 12 | } 13 | 14 | // collectEmbedded returns true if the Field is embedded (regardless of 15 | // whether or not it was collected). 16 | func collectEmbedded( 17 | typeField *reflect.StructField, 18 | valField reflect.Value, 19 | embeds *[]embedded, 20 | ) bool { 21 | // embedded fields are alway anonymous:w 22 | if !typeField.Anonymous { 23 | return false 24 | } 25 | 26 | if typeField.Name == typeField.Type.Name() && 27 | (typeField.Type.Kind() == reflect.Struct || 28 | typeField.Type.Kind() == reflect.Interface) { 29 | 30 | var fieldType reflect.Type 31 | var fieldValue reflect.Value 32 | 33 | if typeField.Type.Kind() == reflect.Interface { 34 | fieldValue = valField.Elem() 35 | if fieldValue.Kind() == reflect.Invalid { 36 | // no value underlying the interface 37 | return true 38 | } 39 | // use the interface's underlying value's real type 40 | fieldType = valField.Elem().Type() 41 | } else { 42 | fieldType = typeField.Type 43 | fieldValue = valField 44 | } 45 | 46 | *embeds = append(*embeds, embedded{Type: fieldType, Value: fieldValue}) 47 | return true 48 | } 49 | 50 | return false 51 | } 52 | 53 | // isMapStringAny returns true iff the provided value, v, is of type 54 | // map[string]any. 55 | func isMapStringAny(v reflect.Value) bool { 56 | if v.Kind() != reflect.Map { 57 | return false 58 | } 59 | 60 | if v.Type().Key().Kind() != reflect.String { 61 | return false 62 | } 63 | 64 | if v.Type().Elem().Kind() != reflect.Interface { 65 | return false 66 | } 67 | 68 | return true 69 | } 70 | -------------------------------------------------------------------------------- /comid/flagsmap_confidentiality_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func Test_FlagsMap_IsConfidentialityProtected(t *testing.T) { 13 | fm := NewFlagsMap() 14 | 15 | // Test initial state - should be nil (unset) 16 | assert.Nil(t, fm.Get(FlagIsConfidentialityProtected)) 17 | assert.False(t, fm.AnySet()) 18 | 19 | // Test setting to true 20 | fm.SetTrue(FlagIsConfidentialityProtected) 21 | assert.True(t, fm.AnySet()) 22 | assert.Equal(t, true, *fm.Get(FlagIsConfidentialityProtected)) 23 | 24 | // Test setting to false 25 | fm.SetFalse(FlagIsConfidentialityProtected) 26 | assert.True(t, fm.AnySet()) 27 | assert.Equal(t, false, *fm.Get(FlagIsConfidentialityProtected)) 28 | 29 | // Test clearing 30 | fm.Clear(FlagIsConfidentialityProtected) 31 | assert.False(t, fm.AnySet()) 32 | assert.Nil(t, fm.Get(FlagIsConfidentialityProtected)) 33 | } 34 | 35 | func Test_FlagsMap_IsConfidentialityProtected_Serialization(t *testing.T) { 36 | fm := NewFlagsMap() 37 | fm.SetTrue(FlagIsConfidentialityProtected) 38 | 39 | // Test CBOR serialization 40 | cbor, err := fm.MarshalCBOR() 41 | assert.NoError(t, err) 42 | assert.NotNil(t, cbor) 43 | 44 | var fm2 FlagsMap 45 | err = fm2.UnmarshalCBOR(cbor) 46 | assert.NoError(t, err) 47 | assert.Equal(t, true, *fm2.Get(FlagIsConfidentialityProtected)) 48 | 49 | // Test JSON serialization 50 | json, err := fm.MarshalJSON() 51 | assert.NoError(t, err) 52 | assert.NotNil(t, json) 53 | assert.Contains(t, string(json), "is-confidentiality-protected") 54 | 55 | var fm3 FlagsMap 56 | err = fm3.UnmarshalJSON(json) 57 | assert.NoError(t, err) 58 | assert.Equal(t, true, *fm3.Get(FlagIsConfidentialityProtected)) 59 | } 60 | -------------------------------------------------------------------------------- /corim/signer_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package corim 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/veraison/corim/comid" 10 | "github.com/veraison/corim/extensions" 11 | ) 12 | 13 | type signerExtensions struct { 14 | Address string `cbor:"-1" json:"address"` 15 | } 16 | 17 | func TestSigner_RegisterExtensions(t *testing.T) { 18 | signer := NewSigner() 19 | assert.False(t, signer.HaveExtensions()) 20 | 21 | exts := &signerExtensions{} 22 | extMap := extensions.NewMap().Add(ExtSigner, exts) 23 | 24 | err := signer.RegisterExtensions(extMap) 25 | assert.NoError(t, err) 26 | assert.True(t, signer.HaveExtensions()) 27 | assert.Equal(t, exts, signer.GetExtensions()) 28 | 29 | badMap := extensions.NewMap().Add(extensions.Point("test"), exts) 30 | err = signer.RegisterExtensions(badMap) 31 | assert.EqualError(t, err, `unexpected extension point: "test"`) 32 | } 33 | 34 | func TestSigner_Valid(t *testing.T) { 35 | var signer Signer 36 | 37 | assert.EqualError(t, signer.Valid(), "empty name") 38 | 39 | signer.Name = "test-signer" 40 | uri := comid.TaggedURI("@@@") 41 | signer.URI = &uri 42 | 43 | assert.EqualError(t, signer.Valid(), `invalid URI: "@@@" is not an absolute URI`) 44 | } 45 | 46 | func TestSigner_JSON(t *testing.T) { 47 | signer := NewSigner() 48 | signer.Name = "test-signer" 49 | uri := comid.TaggedURI("https://example.com") 50 | signer.URI = &uri 51 | 52 | buf, err := signer.MarshalJSON() 53 | assert.NoError(t, err) 54 | assert.JSONEq(t, `{"name": "test-signer", "uri": "https://example.com"}`, string(buf)) 55 | 56 | other := NewSigner() 57 | err = other.UnmarshalJSON(buf) 58 | assert.NoError(t, err) 59 | assert.Equal(t, signer.Name, other.Name) 60 | assert.Equal(t, signer.URI, other.URI) 61 | } 62 | -------------------------------------------------------------------------------- /.github/workflows/ci-go-cover.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2020-present Montgomery Edwards⁴⁴⁸ (github.com/x448). 2 | # This file is licensed under the MIT License. See LICENSE at https://github.com/x448/workflows for the full text. 3 | # 4 | # CI Go Cover 2020.1.28. 5 | # This GitHub Actions workflow checks if Go (Golang) code coverage satisfies the required minimum. 6 | # The required minimum is specified in the workflow name to keep badge.svg and verified minimum in sync. 7 | # 8 | # To help protect your privacy, this workflow avoids external services. 9 | # This workflow simply runs `go test -short -cover` --> grep --> python. 10 | # The python script is embedded and readable in this file. 11 | # 12 | # Steps to install and set minimum required coverage: 13 | # 0. Copy this file to github.com/OWNER_NAME/REPO_NAME/.github/workflows/ci-go-cover.yml 14 | # 1. Change workflow name from "cover 100%" to "cover ≥92.5%". Script will automatically use 92.5%. 15 | # 2. Update README.md to use the new path to badge.svg because the path includes the workflow name. 16 | 17 | name: cover ≥84.4% 18 | on: [push, pull_request] 19 | jobs: 20 | 21 | # Verify minimum coverage is reached using `go test -short -cover` on latest-ubuntu with default version of Go. 22 | # The grep expression can't be too strict, it needed to be relaxed to work with different versions of Go. 23 | cover: 24 | name: Coverage 25 | runs-on: ubuntu-latest 26 | steps: 27 | - uses: actions/setup-go@v3 28 | with: 29 | go-version: "1.23" 30 | - name: Checkout code 31 | uses: actions/checkout@v2 32 | - name: Install mockgen 33 | run: | 34 | go install github.com/golang/mock/mockgen@v1.5.0 35 | - name: Go Coverage 36 | run: | 37 | go version 38 | make test-cover | grep -o "coverage:.*of statements$" | python scripts/cov.py 39 | shell: bash 40 | 41 | -------------------------------------------------------------------------------- /cots/cots_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package cots 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/veraison/corim/comid" 11 | ) 12 | 13 | func TestConciseTaStore_Valid_no_environment_groups(t *testing.T) { 14 | cots := ConciseTaStore{} 15 | assert.EqualError(t, cots.Valid(), "environmentGroups must be present") 16 | } 17 | 18 | func TestConciseTaStore_Valid_invalid_environment_groups(t *testing.T) { 19 | cots := ConciseTaStore{} 20 | cots.Environments = EnvironmentGroups{ 21 | EnvironmentGroup{ 22 | Environment: &comid.Environment{}, 23 | }, 24 | } 25 | 26 | assert.EqualError(t, cots.Valid(), "invalid environmentGroups: bad environment group at index 0: environment group validation failed: environment must not be empty") 27 | 28 | } 29 | 30 | func TestConciseTaStore_Valid_empty_keys(t *testing.T) { 31 | cots := ConciseTaStore{} 32 | cots.Environments = EnvironmentGroups{} 33 | cots.Keys = &TasAndCas{} 34 | 35 | assert.EqualError(t, cots.Valid(), "empty Keys") 36 | } 37 | 38 | func TestConciseTaStore_Valid_invalid_tag_identity(t *testing.T) { 39 | cots := ConciseTaStore{} 40 | cots.Environments = EnvironmentGroups{} 41 | cots.Keys = NewTasAndCas().AddTaCert(ta) 42 | cots.TagIdentity = &comid.TagIdentity{} 43 | 44 | assert.EqualError(t, cots.Valid(), "invalid TagIdentity: empty tag-id") 45 | } 46 | 47 | func TestConciseTaStores_Valid_empty_stores(t *testing.T) { 48 | cotsList := ConciseTaStores{} 49 | assert.EqualError(t, cotsList.Valid(), "empty concise-ta-stores") 50 | } 51 | 52 | func TestConciseTaStores_Valid_bad_cots(t *testing.T) { 53 | cotsList := ConciseTaStores{*NewConciseTaStore().AddPurpose("cots")} 54 | assert.EqualError(t, cotsList.Valid(), "bad ConciseTaStore group at index 0: environmentGroups must be present") 55 | } 56 | -------------------------------------------------------------------------------- /comid/linkedtag.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/veraison/swid" 10 | ) 11 | 12 | // LinkedTag stores one link relation of type Rel between the embedding CoMID 13 | // (the link context) and the referenced CoMID (the link target). The link can 14 | // be viewed as a statement of the form: "$link_context $link_relation_type 15 | // $link_target". 16 | type LinkedTag struct { 17 | LinkedTagID swid.TagID `cbor:"0,keyasint" json:"target"` 18 | Rel Rel `cbor:"1,keyasint" json:"rel"` 19 | } 20 | 21 | func NewLinkedTag() *LinkedTag { 22 | return &LinkedTag{ 23 | Rel: *NewRel(), 24 | // LinkedTagID default constructed 25 | } 26 | } 27 | 28 | func (o *LinkedTag) SetLinkedTag(t swid.TagID) *LinkedTag { 29 | if o != nil { 30 | o.LinkedTagID = t 31 | } 32 | return o 33 | } 34 | 35 | func (o *LinkedTag) SetRel(r Rel) *LinkedTag { 36 | if o != nil { 37 | o.Rel.Set(r) 38 | } 39 | return o 40 | } 41 | 42 | func (o LinkedTag) Valid() error { 43 | if o.LinkedTagID == (swid.TagID{}) { 44 | return fmt.Errorf("tag-id must be set in linked-tag") 45 | } 46 | 47 | if err := o.Rel.Valid(); err != nil { 48 | return fmt.Errorf("rel validation failed: %w", err) 49 | } 50 | 51 | return nil 52 | } 53 | 54 | // LinkedTags is an array of LinkedTag 55 | type LinkedTags []LinkedTag 56 | 57 | func NewLinkedTags() *LinkedTags { 58 | return new(LinkedTags) 59 | } 60 | 61 | // AddLinkedTag adds the supplied linked Tag-map to the target Entities 62 | func (o *LinkedTags) AddLinkedTag(lt LinkedTag) *LinkedTags { 63 | if o != nil { 64 | *o = append(*o, lt) 65 | } 66 | return o 67 | } 68 | 69 | func (o LinkedTags) Valid() error { 70 | for i, l := range o { 71 | if err := l.Valid(); err != nil { 72 | return fmt.Errorf("invalid linked-tag entry at index %d: %w", i, err) 73 | } 74 | } 75 | 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := help 2 | 3 | SHELL := /bin/bash 4 | 5 | GO111MODULE := on 6 | 7 | GOPKG := github.com/veraison/corim/corim 8 | GOPKG += github.com/veraison/corim/comid 9 | GOPKG += github.com/veraison/corim/cots 10 | GOPKG += github.com/veraison/corim/encoding 11 | GOPKG += github.com/veraison/corim/extensions 12 | GOPKG += github.com/veraison/corim/coserv 13 | 14 | GOLINT ?= golangci-lint 15 | 16 | GOLINT_ARGS ?= run --timeout=3m -E dupl -E gocritic -E staticcheck -E lll -E prealloc 17 | 18 | .PHONY: lint 19 | lint: 20 | $(GOLINT) $(GOLINT_ARGS) 21 | 22 | ifeq ($(MAKECMDGOALS),test) 23 | GOTEST_ARGS ?= -v -race $(GOPKG) 24 | else 25 | ifeq ($(MAKECMDGOALS),test-cover) 26 | GOTEST_ARGS ?= -short -cover $(GOPKG) 27 | endif 28 | endif 29 | 30 | COVER_THRESHOLD := $(shell grep '^name: cover' .github/workflows/ci-go-cover.yml | cut -c13-) 31 | 32 | .PHONY: test test-cover 33 | test test-cover: 34 | go test $(GOTEST_ARGS) 35 | 36 | realtest: 37 | go test $(GOTEST_ARGS) 38 | .PHONY: realtest 39 | 40 | presubmit: 41 | @echo 42 | @echo ">>> Check that the reported coverage figures are $(COVER_THRESHOLD)" 43 | @echo 44 | $(MAKE) test-cover 45 | @echo 46 | @echo ">>> Fix any lint error" 47 | @echo 48 | $(MAKE) lint 49 | 50 | .PHONY: licenses 51 | licenses: ; @./scripts/licenses.sh 52 | 53 | .PHONY: test-certs 54 | test-certs: 55 | @echo "Regenerating certificate chain..." 56 | @$(SHELL) scripts/gen-certs.sh create 57 | 58 | .PHONY: help 59 | help: 60 | @echo "Available targets:" 61 | @echo " * test: run unit tests for $(GOPKG)" 62 | @echo " * test-cover: run unit tests and measure coverage for $(GOPKG)" 63 | @echo " * lint: lint sources using default configuration and some extra checkers" 64 | @echo " * presubmit: check you are ready to push your local branch to remote" 65 | @echo " * help: print this menu" 66 | @echo " * licenses: check licenses of dependent packages" 67 | @echo " * test-certs: regenerate the certificate chain" 68 | -------------------------------------------------------------------------------- /coserv/query.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coserv 5 | 6 | import ( 7 | "fmt" 8 | "time" 9 | ) 10 | 11 | // Query is the internal representation of a Query data item 12 | type Query struct { 13 | ArtifactType ArtifactType `cbor:"0,keyasint"` 14 | EnvironmentSelector EnvironmentSelector `cbor:"1,keyasint"` 15 | Timestamp time.Time `cbor:"2,keyasint"` 16 | ResultType ResultType `cbor:"3,keyasint"` 17 | } 18 | 19 | // NewQuery creates a new Query instance with the timestamp set to instantiation time. 20 | // (If needed, the timestamp can be changed using SetTimestamp.) 21 | // An error is returned if the supplied environment selector is invalid. 22 | func NewQuery( 23 | artifactType ArtifactType, 24 | envSelector EnvironmentSelector, 25 | resultType ResultType, 26 | ) (*Query, error) { 27 | if err := envSelector.Valid(); err != nil { 28 | return nil, fmt.Errorf("invalid environment selector: %w", err) 29 | } 30 | 31 | return &Query{ 32 | ArtifactType: artifactType, 33 | EnvironmentSelector: envSelector, 34 | Timestamp: time.Now(), 35 | ResultType: resultType, 36 | }, nil 37 | } 38 | 39 | // SetTimestamp allows setting an explicit timestamp for the target Query object 40 | func (o *Query) SetTimestamp(ts time.Time) *Query { 41 | o.Timestamp = ts 42 | return o 43 | } 44 | 45 | // Valid ensures that the Query target is correctly populated 46 | func (o Query) Valid() error { 47 | // TODO(tho) add tests for these two: 48 | // * artifact and result type mismatch should be caught on decoding 49 | // * ditto for profile syntax errors 50 | 51 | if err := o.EnvironmentSelector.Valid(); err != nil { 52 | return fmt.Errorf("invalid environment selector: %w", err) 53 | } 54 | 55 | zeroTime := time.Time{} 56 | if o.Timestamp.Equal(zeroTime) { 57 | return fmt.Errorf("timestamp not set") 58 | } 59 | 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /profiles/tdx/set_expression.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/veraison/corim/comid" 10 | ) 11 | 12 | type SetDigest comid.Digests 13 | 14 | type SetString []string 15 | 16 | type SetStringExpression struct { 17 | _ struct{} `cbor:",toarray"` 18 | SetOperator Operator `json:"set-operator"` 19 | SetString SetString `json:"set-string"` 20 | } 21 | 22 | type SetDigestExpression struct { 23 | _ struct{} `cbor:",toarray"` 24 | SetOperator Operator `json:"set-operator"` 25 | SetDigest SetDigest `json:"set-digest"` 26 | } 27 | 28 | type TaggedSetStringExpression SetStringExpression 29 | 30 | type TaggedSetDigestExpression SetDigestExpression 31 | 32 | // NewTaggedSetStringExpression creates a TaggedSetStringExpression from 33 | // the supplied operator and an array of strings 34 | func NewTaggedSetStringExpression(op uint, val []string) (*TaggedSetStringExpression, error) { 35 | switch op { 36 | case MEM, NMEM: 37 | if len(val) == 0 { 38 | return nil, fmt.Errorf("zero len string array supplied") 39 | } 40 | set := SetStringExpression{SetOperator: Operator(op), SetString: SetString(val)} 41 | tset := TaggedSetStringExpression(set) 42 | return &tset, nil 43 | default: 44 | return nil, fmt.Errorf("invalid set operator %d", op) 45 | } 46 | } 47 | 48 | // NewTaggedSetDigestExpression creates a TaggedSetStringExpression from 49 | // the supplied operator and Digests 50 | func NewTaggedSetDigestExpression(op uint, val comid.Digests) (*TaggedSetDigestExpression, error) { 51 | switch op { 52 | case MEM, NMEM: 53 | if len(val) == 0 { 54 | return nil, fmt.Errorf("no Digests supplied") 55 | } 56 | set := SetDigestExpression{SetOperator: Operator(op), SetDigest: SetDigest(val)} 57 | tset := TaggedSetDigestExpression(set) 58 | return &tset, nil 59 | default: 60 | return nil, fmt.Errorf("invalid set operator %d", op) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /profiles/tdx/teetcbcompsvn_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestTeeTcbCompSvn_NewTeeTcbCompSvnUint_OK(t *testing.T) { 14 | _, err := NewTeeTcbCompSvnUint(TestCompSvn) 15 | require.NoError(t, err) 16 | } 17 | 18 | func TestTeeTcbCompSvn_NewTeeTcbCompSvnUint_NOK(t *testing.T) { 19 | expectedErr := "no value supplied for TeeTcbCompSVN" 20 | var val []uint 21 | _, err := NewTeeTcbCompSvnUint(val) 22 | assert.EqualError(t, err, expectedErr) 23 | expectedErr = "invalid length 18 for TeeTcbCompSVN" 24 | v := make([]uint, 18) 25 | _, err = NewTeeTcbCompSvnUint(v) 26 | assert.EqualError(t, err, expectedErr) 27 | } 28 | 29 | func TestTeeTcbCompSvn_NewTeeTcbCompSvnExpression_OK(t *testing.T) { 30 | _, err := NewTeeTcbCompSvnExpression(TestCompSvn) 31 | require.NoError(t, err) 32 | } 33 | 34 | func TestTeeTcbCompSvn_NewTeeTcbCompSvnExpression_NOK(t *testing.T) { 35 | expectedErr := "no value supplied for TeeTcbCompSVN" 36 | var val []uint 37 | _, err := NewTeeTcbCompSvnExpression(val) 38 | assert.EqualError(t, err, expectedErr) 39 | expectedErr = "invalid length 18 for TeeTcbCompSVN" 40 | v := make([]uint, 18) 41 | _, err = NewTeeTcbCompSvnExpression(v) 42 | assert.EqualError(t, err, expectedErr) 43 | } 44 | 45 | func TestTeeTcbCompSvn_Valid_OK(t *testing.T) { 46 | tc, err := NewTeeTcbCompSvnExpression(TestCompSvn) 47 | require.NoError(t, err) 48 | err = tc.Valid() 49 | require.NoError(t, err) 50 | tc, err = NewTeeTcbCompSvnUint(TestCompSvn) 51 | require.NoError(t, err) 52 | err = tc.Valid() 53 | require.NoError(t, err) 54 | } 55 | 56 | func TestTeeTcbCompSvn_Valid_NOK(t *testing.T) { 57 | expectedErr := "invalid TeeSvn at index 0, unknown type for TeeSVN" 58 | var tc TeeTcbCompSvn 59 | err := tc.Valid() 60 | assert.EqualError(t, err, expectedErr) 61 | } 62 | -------------------------------------------------------------------------------- /corim/cbor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package corim 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | 10 | cbor "github.com/fxamacker/cbor/v2" 11 | "github.com/veraison/corim/comid" 12 | ) 13 | 14 | var ( 15 | em, emError = initCBOREncMode() 16 | dm, dmError = initCBORDecMode() 17 | ) 18 | 19 | var ( 20 | UnsignedCorimTag = []byte{0xd9, 0x01, 0xf5} // 501() 21 | CoswidTag uint64 = 505 22 | ComidTag uint64 = 506 23 | 24 | corimTagsMap = map[uint64]interface{}{ 25 | 32: comid.TaggedURI(""), 26 | } 27 | ) 28 | 29 | func corimTags() cbor.TagSet { 30 | opts := cbor.TagOptions{ 31 | EncTag: cbor.EncTagRequired, 32 | DecTag: cbor.DecTagRequired, 33 | } 34 | 35 | tags := cbor.NewTagSet() 36 | 37 | for tag, typ := range corimTagsMap { 38 | if err := tags.Add(opts, reflect.TypeOf(typ), tag); err != nil { 39 | panic(err) 40 | } 41 | } 42 | 43 | return tags 44 | } 45 | 46 | func initCBOREncMode() (en cbor.EncMode, err error) { 47 | encOpt := cbor.EncOptions{ 48 | IndefLength: cbor.IndefLengthForbidden, 49 | TimeTag: cbor.EncTagRequired, 50 | } 51 | return encOpt.EncModeWithTags(corimTags()) 52 | } 53 | 54 | func initCBORDecMode() (dm cbor.DecMode, err error) { 55 | decOpt := cbor.DecOptions{ 56 | IndefLength: cbor.IndefLengthAllowed, 57 | TimeTag: cbor.DecTagRequired, 58 | } 59 | return decOpt.DecModeWithTags(corimTags()) 60 | } 61 | 62 | func registerCORIMTag(tag uint64, t interface{}) error { 63 | if _, exists := corimTagsMap[tag]; exists { 64 | return fmt.Errorf("tag %d is already registered", tag) 65 | } 66 | 67 | corimTagsMap[tag] = t 68 | 69 | var err error 70 | 71 | em, err = initCBOREncMode() 72 | if err != nil { 73 | return err 74 | } 75 | 76 | dm, err = initCBORDecMode() 77 | if err != nil { 78 | return err 79 | } 80 | 81 | return nil 82 | } 83 | 84 | func init() { 85 | if emError != nil { 86 | panic(emError) 87 | } 88 | if dmError != nil { 89 | panic(dmError) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /profiles/tdx/testcases/src/comid_pce_refval.diag: -------------------------------------------------------------------------------- 1 | / concise-mid-tag / { 2 | / comid.tag-identity / 1 : { 3 | / comid.tag-id / 0 : "Sample Provisioning Certification Enclave reference tag" 4 | }, 5 | / comid.entity / 2 : [ { 6 | / comid.entity-name / 0 : "INTEL", 7 | / comid.reg-id / 1 : 32("https://intel.com"), 8 | / comid.role / 2 : [ 0 ] / tag-creator / 9 | } ], 10 | / comid.triples / 4 : { 11 | / comid.reference-triples / 0 : [ [ 12 | / environment-map / { 13 | / comid.class / 0 : { 14 | / comid.class-id / 0 : 15 | / tagged-oid-type / 111( 16 | h'6086480186F84D0102030405' / 2.16.840.1.113741.1.2.3.4.5 - / 17 | ), 18 | / comid.vendor / 1 : "Intel Corporation", 19 | / comid.model / 2 : "TDX PCE TCB" 20 | } 21 | }, 22 | [ 23 | / measurement-map / { 24 | / comid.mval / 1 : { 25 | / comid.instanceid / -77 : h'00112233445566778899aabbccddeeff', 26 | / tcb-comp-svn / -125 : [ 27 | 60010([2,10]), 28 | 60010([2,10]), 29 | 60010([2,2]), 30 | 60010([2,2]), 31 | 60010([2,2]), 32 | 60010([2,1]), 33 | 60010([2,4]), 34 | 60010([2,0]), 35 | 60010([2,0]), 36 | 60010([2,0]), 37 | 60010([2,0]), 38 | 60010([2,0]), 39 | 60010([2,0]), 40 | 60010([2,0]), 41 | 60010([2,0]), 42 | 60010([2,0]) 43 | ], 44 | / pceid / -80 : "0000" 45 | }, 46 | / authorized-by / 2: [ 47 | 554("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFn0taoAwR3PmrKkYLtAsD9o05KSM6mbgfNCgpuL0g6VpTHkZl73wk5BDxoV7n+Oeee0iIqkW3HMZT3ETiniJdg==\n-----END PUBLIC KEY-----") 48 | ] 49 | } 50 | ] 51 | ] ] 52 | } 53 | } -------------------------------------------------------------------------------- /coserv/resultset.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package coserv 5 | 6 | import ( 7 | "errors" 8 | "time" 9 | 10 | "github.com/veraison/cmw" 11 | ) 12 | 13 | type ResultSet struct { 14 | RVQ *[]RefValQuad `cbor:"0,keyasint,omitempty"` 15 | AKQ *[]AKQuad `cbor:"3,keyasint,omitempty"` 16 | // TODO(tho) add endorsed values 17 | // TODO(tho) add CoTS 18 | Expiry *time.Time `cbor:"10,keyasint"` 19 | SourceArtifacts *[]cmw.CMW `cbor:"11,keyasint,omitempty"` 20 | } 21 | 22 | // NewResultSet instantiates a new ResultSet 23 | func NewResultSet() *ResultSet { 24 | return &ResultSet{} 25 | } 26 | 27 | // AddReferenceValues adds the supplied ref-val quad to the target ResultSet 28 | func (o *ResultSet) AddReferenceValues(v RefValQuad) *ResultSet { 29 | if o.RVQ == nil { 30 | o.RVQ = new([]RefValQuad) 31 | } 32 | 33 | *o.RVQ = append(*o.RVQ, v) 34 | 35 | return o 36 | } 37 | 38 | // AddAttestationKeys adds the supplied ak quad to the target ResultSet 39 | func (o *ResultSet) AddAttestationKeys(v AKQuad) *ResultSet { 40 | if o.AKQ == nil { 41 | o.AKQ = new([]AKQuad) 42 | } 43 | 44 | *o.AKQ = append(*o.AKQ, v) 45 | 46 | return o 47 | } 48 | 49 | // AddSourceArtifacts adds the supplied CMW to the target ResultSet 50 | func (o *ResultSet) AddSourceArtifacts(v cmw.CMW) *ResultSet { // nolint:gocritic 51 | if o.SourceArtifacts == nil { 52 | o.SourceArtifacts = new([]cmw.CMW) 53 | } 54 | 55 | *o.SourceArtifacts = append(*o.SourceArtifacts, v) 56 | 57 | return o 58 | } 59 | 60 | // SetExpiry sets the Expiry attribute of the target ResultSet to the supplied time 61 | func (o *ResultSet) SetExpiry(exp time.Time) *ResultSet { 62 | o.Expiry = &exp 63 | return o 64 | } 65 | 66 | // Valid checks that the supplied ResultSet is syntactically correct 67 | func (o ResultSet) Valid() error { 68 | if o.Expiry == nil { 69 | return errors.New("missing mandatory expiry") 70 | } 71 | // The coherency between query and results must be checked by the Coserv's 72 | // Valid() 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /comid/ueid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "encoding/base64" 8 | "fmt" 9 | 10 | "github.com/veraison/eat" 11 | ) 12 | 13 | const UEIDType = "ueid" 14 | 15 | // UEID is an Unique Entity Identifier 16 | type UEID eat.UEID 17 | 18 | func (o UEID) Empty() bool { 19 | return len(o) == 0 20 | } 21 | 22 | // Valid checks that the target UEID is in one of the defined formats: IMEI, EUI or RAND 23 | func (o UEID) Valid() error { 24 | if err := eat.UEID(o).Validate(); err != nil { 25 | return fmt.Errorf("UEID validation failed: %w", err) 26 | } 27 | return nil 28 | } 29 | 30 | func (o UEID) String() string { 31 | return base64.StdEncoding.EncodeToString(o) 32 | } 33 | 34 | // TaggedUEID is an alias to allow automatic tagging of an UEID type 35 | type TaggedUEID UEID 36 | 37 | func NewTaggedUEID(val any) (*TaggedUEID, error) { 38 | var ret TaggedUEID 39 | 40 | if val == nil { 41 | return &ret, nil 42 | } 43 | 44 | switch t := val.(type) { 45 | case string: 46 | b, err := base64.StdEncoding.DecodeString(t) 47 | if err != nil { 48 | return nil, fmt.Errorf("bad UEID: %w", err) 49 | } 50 | 51 | ret = TaggedUEID(b) 52 | case []byte: 53 | ret = TaggedUEID(t) 54 | case TaggedUEID: 55 | ret = append(ret, t...) 56 | case *TaggedUEID: 57 | ret = append(ret, *t...) 58 | case UEID: 59 | ret = append(ret, t...) 60 | case *UEID: 61 | ret = append(ret, *t...) 62 | case eat.UEID: 63 | ret = append(ret, t...) 64 | case *eat.UEID: 65 | ret = append(ret, *t...) 66 | default: 67 | return nil, fmt.Errorf("unexpeted type for UEID: %T", t) 68 | } 69 | 70 | if err := ret.Valid(); err != nil { 71 | return nil, err 72 | } 73 | 74 | return &ret, nil 75 | } 76 | 77 | func (o TaggedUEID) Valid() error { 78 | return UEID(o).Valid() 79 | } 80 | 81 | func (o TaggedUEID) String() string { 82 | return UEID(o).String() 83 | } 84 | 85 | func (o TaggedUEID) Type() string { 86 | return "ueid" 87 | } 88 | 89 | func (o TaggedUEID) Bytes() []byte { 90 | return []byte(o) 91 | } 92 | -------------------------------------------------------------------------------- /profiles/tdx/teetcbcompsvn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | // MaxSVNCount is the maximum SVN count in TeeTcbCompSvn 11 | const MaxSVNCount = 16 12 | 13 | type TeeTcbCompSvn [MaxSVNCount]TeeSVN 14 | 15 | // NewTeeTcbCompSvnExpression creates a new TeeTcbCompSvn with an array of SVN as Numeric Expression 16 | // from the supplied array of integers 17 | func NewTeeTcbCompSvnExpression(val []uint) (*TeeTcbCompSvn, error) { 18 | if len(val) > MaxSVNCount { 19 | return nil, fmt.Errorf("invalid length %d for TeeTcbCompSVN", len(val)) 20 | } else if len(val) == 0 { 21 | return nil, fmt.Errorf("no value supplied for TeeTcbCompSVN") 22 | } 23 | 24 | TeeTcbCompSVN := make([]TeeSVN, MaxSVNCount) 25 | for i, value := range val { 26 | svn, err := NewSvnExpression(value) 27 | if err != nil { 28 | return nil, fmt.Errorf("unable to get New SVN Numeric: %w", err) 29 | } 30 | TeeTcbCompSVN[i] = *svn 31 | } 32 | return (*TeeTcbCompSvn)(TeeTcbCompSVN), nil 33 | } 34 | 35 | // NewTeeTcbSVNUint creates a new TeeTcbCompSvn with an array of SVN of type unsigned integers 36 | func NewTeeTcbCompSvnUint(val []uint) (*TeeTcbCompSvn, error) { 37 | if len(val) > MaxSVNCount { 38 | return nil, fmt.Errorf("invalid length %d for TeeTcbCompSVN", len(val)) 39 | } else if len(val) == 0 { 40 | return nil, fmt.Errorf("no value supplied for TeeTcbCompSVN") 41 | } 42 | 43 | TeeTcbCompSVN := make([]TeeSVN, MaxSVNCount) 44 | for i, value := range val { 45 | TeeTcbCompSVN[i].val = value 46 | } 47 | return (*TeeTcbCompSvn)(TeeTcbCompSVN), nil 48 | } 49 | 50 | // nolint:gocritic 51 | func (o TeeTcbCompSvn) Valid() error { 52 | if len(o) == 0 { 53 | return fmt.Errorf("empty TeeTcbCompSVN") 54 | } 55 | if len(o) > MaxSVNCount { 56 | return fmt.Errorf("invalid length: %d for TeeTcbCompSVN", len(o)) 57 | } 58 | 59 | for i, svn := range o { 60 | if err := svn.Valid(); err != nil { 61 | return fmt.Errorf("invalid TeeSvn at index %d, %w", i, err) 62 | } 63 | } 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /corim/testcases/src/good-corim.yaml: -------------------------------------------------------------------------------- 1 | # minimalist unsigned-corim that embeds comid.PSARefValJSONTemplate 2 | --- 3 | tag: 501 4 | value: 5 | 0: test corim id 6 | 1: 7 | - tag: 506 8 | value: 9 | encodedCBOR: 10 | 0: en-GB 11 | 1: 12 | 0: !!binary |- 13 | Q7vjfy5hSzOu01PP8UKLFg== 14 | 2: 15 | - 0: ACME Ltd. 16 | 1: 17 | tag: 32 18 | value: https://acme.example 19 | 2: 20 | - 0 21 | - 1 22 | - 2 23 | 4: 24 | 0: 25 | - - 0: 26 | 0: 27 | tag: 600 28 | value: !!binary |- 29 | YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE= 30 | 1: ACME 31 | 2: RoadRunner 32 | - - 0: 33 | tag: 601 34 | value: 35 | 1: BL 36 | 4: 2.1.0 37 | 5: !!binary |- 38 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 39 | 1: 40 | 2: 41 | - - 1 42 | - !!binary |- 43 | h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc= 44 | - 0: 45 | tag: 601 46 | value: 47 | 1: PRoT 48 | 4: 1.3.5 49 | 5: !!binary |- 50 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 51 | 1: 52 | 2: 53 | - - 1 54 | - !!binary |- 55 | AmOCmYm2/ZVPcrqvL8ZLwuLwHWktTecphuqAj26ZgT8= 56 | - 0: 57 | tag: 601 58 | value: 59 | 1: ARoT 60 | 4: 0.1.4 61 | 5: !!binary |- 62 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 63 | 1: 64 | 2: 65 | - - 1 66 | - !!binary |- 67 | o6XnFfDMV0pzw/m+u2vCTzL/1bZ7OHJEwskJ2neaFHg= 68 | 69 | -------------------------------------------------------------------------------- /profiles/tdx/teedigest_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | "github.com/veraison/corim/comid" 12 | "github.com/veraison/swid" 13 | ) 14 | 15 | func getNewDigests() Digests { 16 | d := comid.NewDigests() 17 | d.AddDigest(swid.Sha256, comid.MustHexDecode(nil, "e45b72f5c0c0b572db4d8d3ab7e97f368ff74e62347a824decb67a84e5224d75")) 18 | return *d 19 | } 20 | func TestTeeDigest_NewTeeDigest_OK(t *testing.T) { 21 | d := getNewDigests() 22 | _, err := NewTeeDigest(d) 23 | require.Nil(t, err) 24 | } 25 | 26 | func TestTeeDigest_NewTeeDigestExpr_OK(t *testing.T) { 27 | d := getNewDigests() 28 | _, err := NewTeeDigestExpr(NMEM, d) 29 | require.Nil(t, err) 30 | } 31 | 32 | func TestTeeDigest_NewTeeDigestExpr_NOK(t *testing.T) { 33 | expectedErr := "invalid operator : 1" 34 | d := getNewDigests() 35 | _, err := NewTeeDigestExpr(GT, d) 36 | assert.EqualError(t, err, expectedErr) 37 | } 38 | 39 | func TestTeeDigest_GetTeeDigest_OK(t *testing.T) { 40 | d := getNewDigests() 41 | dg := TeeDigest{val: d} 42 | d1, err := dg.GetDigest() 43 | require.NoError(t, err) 44 | b := d.Equal(d1) 45 | require.True(t, b) 46 | } 47 | 48 | func TestTeeDigest_AddTeeDigest_OK(t *testing.T) { 49 | d := getNewDigests() 50 | dg := TeeDigest{val: d} 51 | _, err := dg.AddTeeDigest(NOP, d) 52 | require.NoError(t, err) 53 | } 54 | 55 | func TestTeeDigest_AddTeeDigest_NOK(t *testing.T) { 56 | expectedErr := "operator mis-match TeeDigest Op: 6, Input Op: 5" 57 | d := getNewDigests() 58 | dg := TeeDigest{TaggedSetDigestExpression{SetOperator: MEM, SetDigest: SetDigest(d)}} 59 | _, err := dg.AddTeeDigest(NOP, d) 60 | assert.EqualError(t, err, expectedErr) 61 | } 62 | 63 | func TestTeeDigest_Marshal_UnMarshal_OK(t *testing.T) { 64 | d := getNewDigests() 65 | dg := TeeDigest{d} 66 | b, err := dg.MarshalCBOR() 67 | require.Nil(t, err) 68 | x := &TeeDigest{} 69 | err = x.UnmarshalCBOR(b) 70 | require.Nil(t, err) 71 | err = x.Valid() 72 | require.Nil(t, err) 73 | } 74 | -------------------------------------------------------------------------------- /profiles/tdx/testcases/src/comid_qe_refval.diag: -------------------------------------------------------------------------------- 1 | / concise-mid-tag / { 2 | / comid.tag-identity / 1 : { 3 | / comid.tag-id / 0 : "Sample SGX QE reference tag" 4 | }, 5 | / comid.entity / 2 : [ { 6 | / comid.entity-name / 0 : "INTEL", 7 | / comid.reg-id / 1 : 32("https://intel.com"), 8 | / comid.role / 2 : [ 0 ] / tag-creator / 9 | } ], 10 | / comid.triples / 4 : { 11 | / comid.reference-triples / 0 : [ [ 12 | / environment-map / { 13 | / comid.class / 0 : { 14 | / comid.class-id / 0 : 15 | / tagged-oid-type / 111( 16 | h'6086480186F84D0102030401' / 2.16.840.1.113741.1.2.3.4.1 - / 17 | ), 18 | / comid.vendor / 1 : "Intel Corporation", 19 | / comid.model / 2 : "SGX QE TCB" 20 | } 21 | }, 22 | [ 23 | / measurement-map / { 24 | / comid.mval / 1 : { 25 | / comid.miscselect / -81 :h'A0B0C0D000000000', 26 | / comid.isvprodid / -85 : 1, 27 | / mrsigner / -84 : 60020([ / op.member / 6, 28 | / digests-type / [ 29 | [ 30 | / alg-id / 1, / sha256 / 31 | / digest / h'A314FC2DC663AE7A6B6BC6787594057396E6B3F569CD50FD5DDB4D1BBAFD2B6A' 32 | ], 33 | [ 34 | / alg-id / 8, / sha384 / 35 | / digest / h'a314fc2dc663ae7a6b6bc6787594057396e6b3f569cd50fd5ddb4d1bbafd2b6aa314fc2dc663ae7a6b6bc6787594057396e6b3f569cd50fd5ddb4d1bbafd2b6a' 36 | ] 37 | ] 38 | ]), 39 | / tcb-eval-num / -86 : 60010([ / op.ge / 2, 11 ]), 40 | / advisory-ids / -89 : 60021([ /member/ 6, [ "INTEL-SA-00078", "INTEL-SA-00079" ]]), 41 | / tcbstatus / -88 : 60021([ /member/ 6, [ "UpToDate" ]]) 42 | }, 43 | / authorized-by / 2: [ 44 | 554("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFn0taoAwR3PmrKkYLtAsD9o05KSM6mbgfNCgpuL0g6VpTHkZl73wk5BDxoV7n+Oeee0iIqkW3HMZT3ETiniJdg==\n-----END PUBLIC KEY-----") 45 | ] 46 | } 47 | ] 48 | ] ] 49 | } 50 | } -------------------------------------------------------------------------------- /profiles/tdx/testcases/src/comid_seam_refval.diag: -------------------------------------------------------------------------------- 1 | / concise-mid-tag / { 2 | / comid.tag-identity / 1 : { 3 | / comid.tag-id / 0 : h'3f06af63a93c11e4979700505690773f' 4 | }, 5 | / comid.entity / 2 : [ { 6 | / comid.entity-name / 0 : "INTEL", 7 | / comid.reg-id / 1 : 32("https://intel.com"), 8 | / comid.role / 2 : [ 0 ] / tag-creator / 9 | } ], 10 | / comid.triples / 4 : { 11 | / comid.reference-triples / 0 : [ [ 12 | / environment-map / { 13 | / comid.class / 0 : { 14 | / comid.class-id / 0 : 15 | / tagged-oid-type / 111( 16 | h'6086480186F84D0102030403' 17 | ), 18 | / comid.vendor / 1 : "Intel Corporation", 19 | / comid.model / 2 : "TDX SEAM" 20 | } 21 | }, 22 | [ 23 | / measurement-map / { 24 | / comid.mval / 1 : { 25 | / comid.attributes / -82 :[ 1, 2], 26 | / comid.isvprodid / -85 : h'ABCD', 27 | / comid.isvsvn / -73 : 60010([ / op.ge / 2, 6 ]), 28 | / comid.mrtee / -83 : 60020([ / op.member / 6, 29 | [ 30 | [ 31 | / alg-id / 1, / sha256 / 32 | / digest / h'A314FC2DC663AE7A6B6BC6787594057396E6B3F569CD50FD5DDB4D1BBAFD2B6A' 33 | ] 34 | ] 35 | ]), 36 | / comid.mrsigner / -84 : 60020([ / op.member / 6, 37 | [ 38 | [ 39 | / alg-id / 1, / sha256 / 40 | / digest / h'A314FC2DC663AE7A6B6BC6787594057396E6B3F569CD50FD5DDB4D1BBAFD2B6A' 41 | ], 42 | [ 43 | / alg-id / 8, / sha384 / 44 | / digest / h'a314fc2dc663ae7a6b6bc6787594057396e6b3f569cd50fd5ddb4d1bbafd2b6aa314fc2dc663ae7a6b6bc6787594057396e6b3f569cd50fd5ddb4d1bbafd2b6a' 45 | ] 46 | ] 47 | ]), 48 | / tcb-eval-num / -86 : 60010([ / op.ge / 2, 11 ]) 49 | }, 50 | 2: [554("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFn0taoAwR3PmrKkYLtAsD9o05KSM6mbgfNCgpuL0g6VpTHkZl73wk5BDxoV7n+Oeee0iIqkW3HMZT3ETiniJdg==\n-----END PUBLIC KEY-----")] 51 | } 52 | ] 53 | ] ] 54 | } 55 | } -------------------------------------------------------------------------------- /comid/extensions_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package comid 4 | 5 | import ( 6 | "errors" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | var FlagTestFlag = Flag(-1) 13 | 14 | type TestExtension struct { 15 | TestFlag *bool 16 | } 17 | 18 | func (o *TestExtension) ConstrainComid(_ *Comid) error { 19 | return errors.New("invalid") 20 | } 21 | 22 | func (o *TestExtension) ValidTriples(_ *Triples) error { 23 | return errors.New("invalid") 24 | } 25 | 26 | func (o *TestExtension) ConstrainMval(_ *Mval) error { 27 | return errors.New("invalid") 28 | } 29 | 30 | func (o *TestExtension) ConstrainFlagsMap(_ *FlagsMap) error { 31 | return errors.New("invalid") 32 | } 33 | 34 | func (o *TestExtension) ConstrainEntity(_ *Entity) error { 35 | return errors.New("invalid") 36 | } 37 | 38 | func (o *TestExtension) SetTrue(flag Flag) { 39 | if flag == FlagTestFlag { 40 | o.TestFlag = &True 41 | } 42 | } 43 | func (o *TestExtension) SetFalse(flag Flag) { 44 | if flag == FlagTestFlag { 45 | o.TestFlag = &False 46 | } 47 | } 48 | 49 | func (o *TestExtension) Clear(flag Flag) { 50 | if flag == FlagTestFlag { 51 | o.TestFlag = nil 52 | } 53 | } 54 | 55 | func (o *TestExtension) Get(flag Flag) *bool { 56 | if flag == FlagTestFlag { 57 | return o.TestFlag 58 | } 59 | 60 | return nil 61 | } 62 | 63 | func (o *TestExtension) AnySet() bool { 64 | return o.TestFlag != nil 65 | } 66 | 67 | func Test_Extensions(t *testing.T) { 68 | exts := Extensions{} 69 | exts.Register(&TestExtension{}) 70 | 71 | err := exts.validComid(nil) 72 | assert.EqualError(t, err, "invalid") 73 | 74 | err = exts.validTriples(nil) 75 | assert.EqualError(t, err, "invalid") 76 | 77 | err = exts.validMval(nil) 78 | assert.EqualError(t, err, "invalid") 79 | 80 | err = exts.validEntity(nil) 81 | assert.EqualError(t, err, "invalid") 82 | 83 | err = exts.validFlagsMap(nil) 84 | assert.EqualError(t, err, "invalid") 85 | 86 | assert.False(t, exts.anySet()) 87 | 88 | exts.setTrue(FlagTestFlag) 89 | 90 | exts.setFalse(FlagTestFlag) 91 | assert.False(t, *exts.get(FlagTestFlag)) 92 | 93 | exts.clear(FlagTestFlag) 94 | assert.Nil(t, exts.get(FlagTestFlag)) 95 | assert.False(t, exts.anySet()) 96 | } 97 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | # Do not delete linter settings. Linters like gocritic can be enabled on the command line. 2 | 3 | formatters: 4 | enable: 5 | - gofmt 6 | - goimports 7 | settings: 8 | gofmt: 9 | simplify: false 10 | 11 | linters: 12 | default: none 13 | enable: 14 | - dupl # style 15 | - errcheck # bugs 16 | - funlen # complexity 17 | - goconst # style 18 | - gocritic # metalinter 19 | - gocyclo # complexity 20 | - gosec # bugs 21 | - govet # bugs 22 | - ineffassign 23 | - lll # style 24 | - misspell # comment 25 | - staticcheck # metalinter 26 | - unconvert # style 27 | - unused # unused 28 | exclusions: 29 | rules: 30 | - path: '(.+)_test\.go' 31 | linters: 32 | - dupl 33 | - funlen 34 | - lll 35 | - goconst 36 | settings: 37 | dupl: 38 | threshold: 100 39 | funlen: 40 | lines: 100 41 | statements: 50 42 | goconst: 43 | min-len: 2 44 | min-occurrences: 3 45 | gocritic: 46 | enabled-tags: 47 | - diagnostic 48 | - experimental 49 | - opinionated 50 | - performance 51 | - style 52 | disabled-checks: 53 | - dupImport # https://github.com/go-critic/go-critic/issues/845 54 | - ifElseChain 55 | - octalLiteral 56 | - paramTypeCombine 57 | - whyNoLint 58 | - wrapperFunc 59 | govet: 60 | enable: 61 | - shadow 62 | lll: 63 | line-length: 140 64 | misspell: 65 | locale: US 66 | 67 | issues: 68 | # max-issues-per-linter default is 50. Set to 0 to disable limit. 69 | max-issues-per-linter: 0 70 | # max-same-issues default is 3. Set to 0 to disable limit. 71 | max-same-issues: 0 72 | # Excluding configuration per-path, per-linter, per-text and per-source 73 | exclude-rules: 74 | - path: _test\.go 75 | linters: 76 | - goconst 77 | - dupl 78 | - gomnd 79 | - lll 80 | - path: doc\.go 81 | linters: 82 | - goimports 83 | - gomnd 84 | - lll 85 | - path: psatoken_fuzz_test.go 86 | linters: 87 | # the Fuzz function is only invoked by go-fuzz, therefore golangci will 88 | # see it as unused 89 | - unused 90 | 91 | version: "2" 92 | -------------------------------------------------------------------------------- /profiles/tdx/teetcbstatus_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestTcbStatus_NewTeeTcbStatusString_OK(t *testing.T) { 14 | s := TestTCBStatus 15 | _, err := NewTeeTcbStatusString(s) 16 | require.NoError(t, err) 17 | } 18 | 19 | func TestTcbStatus_NewTeeTcbStatusExpr_OK(t *testing.T) { 20 | s := TestTCBStatus 21 | _, err := NewTcbStatusExpr(MEM, s) 22 | require.NoError(t, err) 23 | } 24 | 25 | func TestTcbStatus_NewTeeTcbStatusString_NOK(t *testing.T) { 26 | expectedErr := "zero len value for TeeTcbStatus" 27 | s := []string{} 28 | _, err := NewTeeTcbStatusString(s) 29 | assert.EqualError(t, err, expectedErr) 30 | } 31 | 32 | func TestTcbStatus_NewTeeTcbStatusExpr_NOK(t *testing.T) { 33 | expectedErr := "invalid operator : 5" 34 | s := TestTCBStatus 35 | _, err := NewTcbStatusExpr(NOP, s) 36 | assert.EqualError(t, err, expectedErr) 37 | } 38 | 39 | func TestTcbStatus_AddTcbStatus_OK(t *testing.T) { 40 | s := TestTCBStatus 41 | status := TeeTcbStatus{val: []string{"abcd"}} 42 | _, err := status.AddTeeTcbStatus(NOP, s) 43 | require.Nil(t, err) 44 | } 45 | 46 | func TestTcbStatus_AddTcbStatus_NOK(t *testing.T) { 47 | expectedErr := "operator mis-match TeeTcbStatus Op: 6, Input Op: 2" 48 | s := TestTCBStatus 49 | status, err := NewTcbStatusExpr(MEM, s) 50 | require.Nil(t, err) 51 | _, err = status.AddTeeTcbStatus(GE, []string{"abcd"}) 52 | assert.EqualError(t, err, expectedErr) 53 | } 54 | 55 | func TestTcbStatus_Valid_OK(t *testing.T) { 56 | s := TestTCBStatus 57 | status, err := NewTeeTcbStatusString(s) 58 | require.Nil(t, err) 59 | err = status.Valid() 60 | require.Nil(t, err) 61 | } 62 | 63 | func TestTcbStatus_Valid_NOK(t *testing.T) { 64 | expectedErr := "invalid operator in a TeeTcbStatus: 2" 65 | status := TeeTcbStatus{val: TaggedSetStringExpression(SetStringExpression{SetOperator: 2, SetString: []string{"valid"}})} 66 | err := status.Valid() 67 | assert.EqualError(t, err, expectedErr) 68 | expectedErr = "unknown type []int for TeeTcbStatus" 69 | status = TeeTcbStatus{val: TestInvalidTCBStatus} 70 | err = status.Valid() 71 | assert.EqualError(t, err, expectedErr) 72 | } 73 | -------------------------------------------------------------------------------- /cots/abbreviated_swid_evidence_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package cots 5 | 6 | import ( 7 | "testing" 8 | "time" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/veraison/swid" 12 | ) 13 | 14 | func TestAbbreviatedSwidTag_Valid_WithEvidence_Success(t *testing.T) { 15 | validDate := time.Date(2023, time.January, 1, 12, 0, 0, 0, time.UTC) 16 | 17 | tag, err := NewTag("test-tag-id", "Test Software", "1.0.0") 18 | assert.NoError(t, err) 19 | 20 | // Add required entity 21 | entity := swid.Entity{ 22 | EntityName: "Test Inc.", 23 | } 24 | err = entity.SetRoles(swid.RoleTagCreator) 25 | assert.NoError(t, err) 26 | tag.Entities = append(tag.Entities, entity) 27 | 28 | // Add valid Evidence 29 | evidence := &swid.Evidence{ 30 | DeviceID: "test-device-123", 31 | Date: validDate, 32 | } 33 | tag.Evidence = evidence 34 | 35 | err = tag.Valid() 36 | assert.NoError(t, err, "Tag with valid Evidence should pass validation") 37 | } 38 | 39 | func TestAbbreviatedSwidTag_Valid_WithInvalidEvidence(t *testing.T) { 40 | tag, err := NewTag("test-tag-id", "Test Software", "1.0.0") 41 | assert.NoError(t, err) 42 | 43 | // Add required entity 44 | entity := swid.Entity{ 45 | EntityName: "Test Inc.", 46 | } 47 | err = entity.SetRoles(swid.RoleTagCreator) 48 | assert.NoError(t, err) 49 | tag.Entities = append(tag.Entities, entity) 50 | 51 | // Add invalid Evidence (missing required fields) 52 | evidence := &swid.Evidence{ 53 | // Missing DeviceID and Date 54 | } 55 | tag.Evidence = evidence 56 | 57 | err = tag.Valid() 58 | assert.Error(t, err, "Tag with invalid Evidence should fail validation") 59 | assert.Contains(t, err.Error(), "evidence validation failed") 60 | } 61 | 62 | func TestAbbreviatedSwidTag_Valid_WithoutEvidence(t *testing.T) { 63 | tag, err := NewTag("test-tag-id", "Test Software", "1.0.0") 64 | assert.NoError(t, err) 65 | 66 | // Add required entity 67 | entity := swid.Entity{ 68 | EntityName: "Test Inc.", 69 | } 70 | err = entity.SetRoles(swid.RoleTagCreator) 71 | assert.NoError(t, err) 72 | tag.Entities = append(tag.Entities, entity) 73 | 74 | // Evidence is nil - should still pass validation 75 | err = tag.Valid() 76 | assert.NoError(t, err, "Tag without Evidence should pass validation") 77 | } 78 | -------------------------------------------------------------------------------- /comid/ccaplatformconfigid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "encoding/json" 8 | "errors" 9 | "fmt" 10 | "unicode/utf8" 11 | ) 12 | 13 | var CCAPlatformConfigIDType = "cca.platform-config-id" 14 | 15 | type CCAPlatformConfigID string 16 | 17 | func (o CCAPlatformConfigID) Empty() bool { 18 | return o == "" 19 | } 20 | 21 | func (o *CCAPlatformConfigID) Set(v string) error { 22 | if v == "" { 23 | return fmt.Errorf("empty input string") 24 | } 25 | *o = CCAPlatformConfigID(v) 26 | return nil 27 | } 28 | 29 | func (o CCAPlatformConfigID) Get() (CCAPlatformConfigID, error) { 30 | if o == "" { 31 | return "", fmt.Errorf("empty CCA platform config ID") 32 | } 33 | return o, nil 34 | } 35 | 36 | type TaggedCCAPlatformConfigID CCAPlatformConfigID 37 | 38 | func NewTaggedCCAPlatformConfigID(val any) (*TaggedCCAPlatformConfigID, error) { 39 | var ret TaggedCCAPlatformConfigID 40 | 41 | if val == nil { 42 | return &ret, nil 43 | } 44 | 45 | switch t := val.(type) { 46 | case TaggedCCAPlatformConfigID: 47 | ret = t 48 | case *TaggedCCAPlatformConfigID: 49 | ret = *t 50 | case CCAPlatformConfigID: 51 | ret = TaggedCCAPlatformConfigID(t) 52 | case *CCAPlatformConfigID: 53 | ret = TaggedCCAPlatformConfigID(*t) 54 | case string: 55 | ret = TaggedCCAPlatformConfigID(t) 56 | case []byte: 57 | if !utf8.Valid(t) { 58 | return nil, errors.New("bytes do not form a valid UTF-8 string") 59 | } 60 | ret = TaggedCCAPlatformConfigID(t) 61 | default: 62 | return nil, fmt.Errorf("unexpected type for CCA platform-config-id: %T", t) 63 | } 64 | 65 | return &ret, nil 66 | } 67 | 68 | func (o TaggedCCAPlatformConfigID) Valid() error { 69 | if o == "" { 70 | return errors.New("empty value") 71 | } 72 | 73 | return nil 74 | } 75 | 76 | func (o TaggedCCAPlatformConfigID) String() string { 77 | return string(o) 78 | } 79 | 80 | func (o TaggedCCAPlatformConfigID) Type() string { 81 | return CCAPlatformConfigIDType 82 | } 83 | 84 | func (o TaggedCCAPlatformConfigID) IsZero() bool { 85 | return len(o) == 0 86 | } 87 | 88 | func (o *TaggedCCAPlatformConfigID) UnmarshalJSON(data []byte) error { 89 | var temp string 90 | 91 | if err := json.Unmarshal(data, &temp); err != nil { 92 | return err 93 | } 94 | 95 | *o = TaggedCCAPlatformConfigID(temp) 96 | 97 | return nil 98 | } 99 | -------------------------------------------------------------------------------- /comid/ccaplatformconfigid_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestCCAPlatformConfigID_Set_ok(t *testing.T) { 13 | var cca CCAPlatformConfigID 14 | 15 | err := cca.Set(TestCCALabel) 16 | assert.NoError(t, err) 17 | } 18 | 19 | func TestCCAPlatformConfigID_Set_nok(t *testing.T) { 20 | var cca CCAPlatformConfigID 21 | expectedErr := "empty input string" 22 | err := cca.Set("") 23 | assert.EqualError(t, err, expectedErr) 24 | } 25 | 26 | func TestCCAPlatformConfigID_Get_nok(t *testing.T) { 27 | var cca CCAPlatformConfigID 28 | expectedErr := "empty CCA platform config ID" 29 | _, err := cca.Get() 30 | assert.EqualError(t, err, expectedErr) 31 | } 32 | 33 | func TestNewTaggedCCAPlatformConfigID(t *testing.T) { 34 | testID := TaggedCCAPlatformConfigID("test") 35 | untagged := CCAPlatformConfigID("test") 36 | 37 | for _, tv := range []struct { 38 | Name string 39 | Input any 40 | Err string 41 | Expected TaggedCCAPlatformConfigID 42 | }{ 43 | { 44 | Name: "TaggedCCAPlatformConfigID ok", 45 | Input: testID, 46 | Expected: testID, 47 | }, 48 | { 49 | Name: "*TaggedCCAPlatformConfigID ok", 50 | Input: &testID, 51 | Expected: testID, 52 | }, 53 | { 54 | Name: "CCAPlatformConfigID ok", 55 | Input: untagged, 56 | Expected: testID, 57 | }, 58 | { 59 | Name: "*CCAPlatformConfigID ok", 60 | Input: &untagged, 61 | Expected: testID, 62 | }, 63 | { 64 | Name: "string ok", 65 | Input: "test", 66 | Expected: testID, 67 | }, 68 | { 69 | Name: "[]byte ok", 70 | Input: []byte{0x74, 0x65, 0x73, 0x74}, 71 | Expected: testID, 72 | }, 73 | { 74 | Name: "[]byte not ok", 75 | Input: []byte{0x80, 0x65, 0x73, 0x74}, 76 | Err: "bytes do not form a valid UTF-8 string", 77 | }, 78 | { 79 | Name: "bad type", 80 | Input: 7, 81 | Err: "unexpected type for CCA platform-config-id: int", 82 | }, 83 | } { 84 | t.Run(tv.Name, func(t *testing.T) { 85 | out, err := NewTaggedCCAPlatformConfigID(tv.Input) 86 | 87 | if tv.Err != "" { 88 | assert.Nil(t, out) 89 | assert.EqualError(t, err, tv.Err) 90 | } else { 91 | assert.Equal(t, tv.Expected, *out) 92 | } 93 | }) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /comid/environment.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "encoding/json" 8 | "fmt" 9 | ) 10 | 11 | // Environment stores the identifying information about a target or attesting 12 | // environment at the class, instance and group scope. The Environment type 13 | // has JSON and CBOR serializations. 14 | type Environment struct { 15 | Class *Class `cbor:"0,keyasint,omitempty" json:"class,omitempty"` 16 | Instance *Instance `cbor:"1,keyasint,omitempty" json:"instance,omitempty"` 17 | Group *Group `cbor:"2,keyasint,omitempty" json:"group,omitempty"` 18 | } 19 | 20 | // Valid checks the validity (according to the spec) of the target Environment 21 | func (o Environment) Valid() error { 22 | // non-empty<> 23 | if o.Class == nil && o.Instance == nil && o.Group == nil { 24 | return fmt.Errorf("environment must not be empty") 25 | } 26 | 27 | if o.Class != nil { 28 | if err := o.Class.Valid(); err != nil { 29 | return fmt.Errorf("class validation failed: %w", err) 30 | } 31 | } 32 | 33 | if o.Instance != nil { 34 | if err := o.Instance.Valid(); err != nil { 35 | return fmt.Errorf("instance validation failed: %w", err) 36 | } 37 | } 38 | 39 | if o.Group != nil { 40 | if err := o.Group.Valid(); err != nil { 41 | return fmt.Errorf("group validation failed: %w", err) 42 | } 43 | } 44 | 45 | return nil 46 | } 47 | 48 | // ToCBOR serializes the target Environment to CBOR (if the Environment is "valid") 49 | func (o Environment) ToCBOR() ([]byte, error) { 50 | if err := o.Valid(); err != nil { 51 | return nil, err 52 | } 53 | 54 | return em.Marshal(&o) 55 | } 56 | 57 | // FromCBOR deserializes the supplied CBOR data into the target Environment 58 | func (o *Environment) FromCBOR(data []byte) error { 59 | if err := dm.Unmarshal(data, o); err != nil { 60 | return err 61 | } 62 | 63 | return o.Valid() 64 | } 65 | 66 | // FromJSON deserializes the supplied JSON string into the target Environment 67 | func (o *Environment) FromJSON(data []byte) error { 68 | if err := json.Unmarshal(data, o); err != nil { 69 | return err 70 | } 71 | 72 | return o.Valid() 73 | } 74 | 75 | // ToJSON serializes the target Environment to JSON (if the Environment is "valid") 76 | func (o Environment) ToJSON() ([]byte, error) { 77 | if err := o.Valid(); err != nil { 78 | return nil, err 79 | } 80 | 81 | return json.Marshal(&o) 82 | } 83 | -------------------------------------------------------------------------------- /profiles/tdx/numeric_type_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | const TestInt = 10 14 | const TestUint = uint(10) 15 | const TestFloat = 10.123 16 | 17 | func TestNumericType_NewNumericType(t *testing.T) { 18 | _, err := NewNumericType(uint(10)) 19 | require.NoError(t, err) 20 | _, err = NewNumericType(10) 21 | require.NoError(t, err) 22 | _, err = NewNumericType(10.123) 23 | require.NoError(t, err) 24 | } 25 | 26 | func TestNumericType_SetNumericType(t *testing.T) { 27 | o := &NumericType{} 28 | err := o.SetNumericType(uint(10)) 29 | require.NoError(t, err) 30 | err = o.SetNumericType(10) 31 | require.NoError(t, err) 32 | err = o.SetNumericType(10.123) 33 | require.NoError(t, err) 34 | } 35 | 36 | func TestNumericType_IsType(t *testing.T) { 37 | o := &NumericType{val: 10} 38 | b := o.IsInt() 39 | require.True(t, b) 40 | o = &NumericType{val: uint(10)} 41 | b = o.IsUint() 42 | require.True(t, b) 43 | o = &NumericType{val: 10.00} 44 | require.True(t, b) 45 | } 46 | 47 | func TestNumericType_GetType(t *testing.T) { 48 | o := &NumericType{val: 10} 49 | i, err := o.GetInt() 50 | require.NoError(t, err) 51 | assert.Equal(t, TestInt, i) 52 | 53 | o = &NumericType{val: TestUint} 54 | k, err := o.GetUint() 55 | require.NoError(t, err) 56 | assert.Equal(t, TestUint, k) 57 | 58 | o = &NumericType{val: TestFloat} 59 | f, err := o.GetFloat() 60 | require.NoError(t, err) 61 | assert.Equal(t, TestFloat, f) 62 | } 63 | 64 | func TestNumericType_GetType_NOK(t *testing.T) { 65 | o := &NumericType{val: 10} 66 | i, err := o.GetInt() 67 | require.NoError(t, err) 68 | assert.Equal(t, TestInt, i) 69 | 70 | o = &NumericType{val: TestUint} 71 | k, err := o.GetUint() 72 | require.NoError(t, err) 73 | assert.Equal(t, TestUint, k) 74 | 75 | o = &NumericType{val: TestFloat} 76 | f, err := o.GetFloat() 77 | require.NoError(t, err) 78 | assert.Equal(t, TestFloat, f) 79 | } 80 | 81 | func TestNumericType_Valid_OK(t *testing.T) { 82 | o := NumericType{val: 10} 83 | err := o.Valid() 84 | require.NoError(t, err) 85 | } 86 | 87 | func TestNumericType_Valid_NOK(t *testing.T) { 88 | expectedErr := "unsupported NumericType type: string" 89 | o := NumericType{val: "test"} 90 | err := o.Valid() 91 | assert.EqualError(t, err, expectedErr) 92 | } 93 | -------------------------------------------------------------------------------- /corim/testcases/src/corim-with-extensions.yaml: -------------------------------------------------------------------------------- 1 | # minimalist unsigned-corim that embeds comid.PSARefValJSONTemplate 2 | # - profile (claim 3) has been set to "http://example.com/test-profile" 3 | # - extension claim -1 has been added to corim 4 | # - extension claim -1 has been added to comid entity 5 | --- 6 | tag: 501 7 | value: 8 | 0: test corim id 9 | 3: http://example.com/test-profile 10 | -1: foo 11 | 1: 12 | - tag: 506 13 | value: 14 | encodedCBOR: 15 | 0: en-GB 16 | 1: 17 | 0: !!binary |- 18 | Q7vjfy5hSzOu01PP8UKLFg== 19 | 2: 20 | - 0: ACME Ltd. 21 | 1: 22 | tag: 32 23 | value: https://acme.example 24 | 2: 25 | - 0 26 | - 1 27 | - 2 28 | -1: 123 Fake Street 29 | 4: 30 | 0: 31 | - - 0: 32 | 0: 33 | tag: 600 34 | value: !!binary |- 35 | YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE= 36 | 1: ACME 37 | 2: RoadRunner 38 | - - 0: 39 | tag: 601 40 | value: 41 | 1: BL 42 | 4: 2.1.0 43 | 5: !!binary |- 44 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 45 | 1: 46 | 2: 47 | - - 1 48 | - !!binary |- 49 | h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc= 50 | -1: 1720782190 51 | - 0: 52 | tag: 601 53 | value: 54 | 1: PRoT 55 | 4: 1.3.5 56 | 5: !!binary |- 57 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 58 | 1: 59 | 2: 60 | - - 1 61 | - !!binary |- 62 | AmOCmYm2/ZVPcrqvL8ZLwuLwHWktTecphuqAj26ZgT8= 63 | -1: 1720782190 64 | - 0: 65 | tag: 601 66 | value: 67 | 1: ARoT 68 | 4: 0.1.4 69 | 5: !!binary |- 70 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 71 | 1: 72 | 2: 73 | - - 1 74 | - !!binary |- 75 | o6XnFfDMV0pzw/m+u2vCTzL/1bZ7OHJEwskJ2neaFHg= 76 | -1: 1720782190 77 | 78 | -------------------------------------------------------------------------------- /corim/extensions_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package corim 4 | 5 | import ( 6 | "errors" 7 | "testing" 8 | 9 | "github.com/fxamacker/cbor/v2" 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | "github.com/veraison/corim/extensions" 13 | ) 14 | 15 | type TestExtensions struct { 16 | Address string `cbor:"-1,keyasint,omitempty" json:"address,omitempty"` 17 | Size int `cbor:"-2,keyasint,omitempty" json:"size,omitempty"` 18 | } 19 | 20 | func (o TestExtensions) ConstrainEntity(ent *Entity) error { 21 | if ent.Name.String() != "Futurama" { 22 | return errors.New(`EntityName must be "Futurama"`) // nolint:golint 23 | } 24 | 25 | return nil 26 | } 27 | 28 | func (o TestExtensions) ConstrainCorim(_ *UnsignedCorim) error { 29 | return errors.New("invalid") 30 | } 31 | 32 | func (o TestExtensions) ConstrainSigner(_ *Signer) error { 33 | return errors.New("invalid") 34 | } 35 | 36 | func TestEntityExtensions_Valid(t *testing.T) { 37 | ent := NewEntity() 38 | ent.SetName("The Simpsons") 39 | ent.SetRoles(RoleManifestCreator) 40 | 41 | err := ent.Valid() 42 | assert.NoError(t, err) 43 | 44 | extMap := extensions.NewMap().Add(ExtEntity, &TestExtensions{}) 45 | err = ent.RegisterExtensions(extMap) 46 | require.NoError(t, err) 47 | 48 | err = ent.Valid() 49 | assert.EqualError(t, err, `EntityName must be "Futurama"`) 50 | 51 | ent.SetName("Futurama") 52 | err = ent.Valid() 53 | assert.NoError(t, err) 54 | 55 | assert.EqualError(t, ent.validCorim(nil), "invalid") 56 | assert.EqualError(t, ent.validSigner(nil), "invalid") 57 | } 58 | 59 | func TestEntityExtensions_CBOR(t *testing.T) { 60 | data := []byte{ 61 | 0xa4, // map(4) 62 | 63 | 0x00, // key 0 64 | 0x64, // val tstr(4) 65 | 0x61, 0x63, 0x6d, 0x65, // "acme" 66 | 67 | 0x02, // key 2 68 | 0x81, // array(1) 69 | 0x01, // 1 70 | 71 | 0x20, // key -1 72 | 0x63, // val tstr(3) 73 | 0x66, 0x6f, 0x6f, // "foo" 74 | 75 | 0x21, // key -2 76 | 0x06, // val 6 77 | } 78 | 79 | ent := NewEntity() 80 | extMap := extensions.NewMap().Add(ExtEntity, &TestExtensions{}) 81 | err := ent.RegisterExtensions(extMap) 82 | require.NoError(t, err) 83 | 84 | err = cbor.Unmarshal(data, &ent) 85 | assert.NoError(t, err) 86 | 87 | assert.Equal(t, ent.Name.String(), "acme") 88 | 89 | address, err := ent.Get("address") 90 | require.NoError(t, err) 91 | assert.Equal(t, address, "foo") 92 | } 93 | -------------------------------------------------------------------------------- /comid/cbor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | 10 | cbor "github.com/fxamacker/cbor/v2" 11 | ) 12 | 13 | var ( 14 | em, emError = initCBOREncMode() 15 | dm, dmError = initCBORDecMode() 16 | 17 | comidTagsMap = map[uint64]interface{}{ 18 | 32: TaggedURI(""), 19 | 37: TaggedUUID{}, 20 | 111: TaggedOID{}, 21 | // CoMID tags 22 | 550: TaggedUEID{}, 23 | 551: TaggedInt(0), 24 | 552: TaggedSVN(0), 25 | 553: TaggedMinSVN(0), 26 | 554: TaggedPKIXBase64Key(""), 27 | 555: TaggedPKIXBase64Cert(""), 28 | 556: TaggedPKIXBase64CertPath(""), 29 | 557: TaggedThumbprint{}, 30 | 558: TaggedCOSEKey{}, 31 | 559: TaggedCertThumbprint{}, 32 | 560: TaggedBytes{}, 33 | 561: TaggedCertPathThumbprint{}, 34 | 564: TaggedRawIntRange{}, 35 | // PSA profile tags 36 | 600: TaggedImplID{}, 37 | 601: TaggedPSARefValID{}, 38 | 602: TaggedCCAPlatformConfigID(""), 39 | } 40 | ) 41 | 42 | func comidTags() cbor.TagSet { 43 | opts := cbor.TagOptions{ 44 | EncTag: cbor.EncTagRequired, 45 | DecTag: cbor.DecTagRequired, 46 | } 47 | 48 | tags := cbor.NewTagSet() 49 | 50 | for tag, typ := range comidTagsMap { 51 | if err := tags.Add(opts, reflect.TypeOf(typ), tag); err != nil { 52 | panic(err) 53 | } 54 | } 55 | 56 | return tags 57 | } 58 | 59 | func initCBOREncMode() (en cbor.EncMode, err error) { 60 | encOpt := cbor.EncOptions{ 61 | Sort: cbor.SortCoreDeterministic, 62 | IndefLength: cbor.IndefLengthForbidden, 63 | TimeTag: cbor.EncTagRequired, 64 | } 65 | return encOpt.EncModeWithTags(comidTags()) 66 | } 67 | 68 | func initCBORDecMode() (dm cbor.DecMode, err error) { 69 | decOpt := cbor.DecOptions{ 70 | IndefLength: cbor.IndefLengthAllowed, 71 | } 72 | return decOpt.DecModeWithTags(comidTags()) 73 | } 74 | 75 | func registerCOMIDTag(tag uint64, t interface{}) error { 76 | if _, exists := comidTagsMap[tag]; exists { 77 | return fmt.Errorf("tag %d is already registered", tag) 78 | } 79 | 80 | comidTagsMap[tag] = t 81 | 82 | var err error 83 | 84 | em, err = initCBOREncMode() 85 | if err != nil { 86 | return err 87 | } 88 | 89 | dm, err = initCBORDecMode() 90 | if err != nil { 91 | return err 92 | } 93 | 94 | return nil 95 | } 96 | 97 | func init() { 98 | if emError != nil { 99 | panic(emError) 100 | } 101 | if dmError != nil { 102 | panic(dmError) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Concise Reference Integrity Manifest and Module Identifiers 2 | [![ci](https://github.com/veraison/corim/actions/workflows/ci.yml/badge.svg)](https://github.com/veraison/corim/actions/workflows/ci.yml) 3 | [![cover ≥82%](https://github.com/veraison/corim/actions/workflows/ci-go-cover.yml/badge.svg)](https://github.com/veraison/corim/actions/workflows/ci-go-cover.yml) 4 | [![linters](https://github.com/veraison/corim/actions/workflows/linters.yml/badge.svg)](https://github.com/veraison/corim/actions/workflows/linters.yml) 5 | [![Go Reference](https://pkg.go.dev/badge/github.com/veraison/corim.svg)](https://pkg.go.dev/github.com/veraison/corim) 6 | 7 | 8 | The [`corim/corim`](corim) and [`corim/comid`](comid) packages provide a golang API for low-level manipulation of [Concise Reference Integrity Manifest (CoRIM)](https://datatracker.ietf.org/doc/draft-ietf-rats-corim/) and Concise Module Identifier (CoMID) tags respectively. 9 | The [`corim/coev`](coev) package provides a minimal golang implementation of TCG Concise Evidence CDDL as documented [here](https://github.com/TrustedComputingGroup/dice-coev/blob/main/concise-evidence.cddl) 10 | The [`corim/coserv`](coserv) package provides a golang API for working with [Concise Selector for Endorsements and Reference Values](https://datatracker.ietf.org/doc/draft-howard-rats-coserv). 11 | 12 | > [!NOTE] 13 | > These API are still in active development (as is the underlying CoRIM spec). 14 | > They are **subject to change** in the future. 15 | 16 | ## Required Tools 17 | 18 | Ensure you have the following tools installed with the specified versions on your machine to ensure everything works properly: 19 | 20 | - **Go**: Version 1.22 21 | - **golangci-lint**: Version 1.54.2 22 | 23 | ## Developer tips 24 | 25 | Before requesting a PR (and routinely during the dev/test cycle), you are encouraged to run: 26 | ``` 27 | make presubmit 28 | ``` 29 | and check its output to make sure your code coverage figures are in line with the set target and that there are no newly introduced lint problems. 30 | 31 | ## Extending CoRIM/CoMID 32 | 33 | The CoRIM specification provides a mechanism for adding extensions to the base 34 | CoRIM schema. The `corim` and `comid` structs which can be extended, embed an 35 | `Extensions` object that allows registering a wrapper structure defining 36 | extension fields. For field types that can be extended, i.e. `type choice`, 37 | extensions can be implemented by calling an appropriate registration function 38 | and giving it a new type or a value (for enums). 39 | 40 | Please see [extensions documentation](extensions/README.md) for details. 41 | 42 | 43 | -------------------------------------------------------------------------------- /profiles/tdx/tee_tcb_eval_num_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestTeeTcbEvalNumber_NewTeeTcbEvalNumberNumeric_OK(t *testing.T) { 15 | _, err := NewTeeTcbEvalNumberNumeric(TestTCBEvalNum) 16 | require.NoError(t, err) 17 | } 18 | 19 | func TestTeeTcbEvalNumber_NewTeeTcbEvalNumberUint_OK(t *testing.T) { 20 | _, err := NewTeeTcbEvalNumberUint(TestTCBEvalNum) 21 | require.NoError(t, err) 22 | } 23 | 24 | func TestTeeTcbEvalNumber_Valid_OK(t *testing.T) { 25 | tcb := TeeTcbEvalNumber{val: TestTCBEvalNum} 26 | err := tcb.Valid() 27 | require.NoError(t, err) 28 | } 29 | 30 | func TestTeeTcbEvalNumber_Valid_NOK(t *testing.T) { 31 | expectedErr := "unknown type int for TeeTcbEvalNumber" 32 | en := TeeTcbEvalNumber{val: -10} 33 | err := en.Valid() 34 | assert.EqualError(t, err, expectedErr) 35 | } 36 | 37 | func TestTeeTcbEvalNumber_GetUint_OK(t *testing.T) { 38 | tcb := TeeTcbEvalNumber{val: TestTCBEvalNum} 39 | val, err := tcb.GetUint() 40 | require.NoError(t, err) 41 | require.Equal(t, val, TestTCBEvalNum) 42 | } 43 | 44 | func TestTeeTcbEvalNumber_IsUint_OK(t *testing.T) { 45 | tcb := TeeTcbEvalNumber{val: TestTCBEvalNum} 46 | b := tcb.IsUint() 47 | require.True(t, b) 48 | } 49 | 50 | func TestTeeTcbEvalNumber_JSON1(t *testing.T) { 51 | expectedErr := "unknown type int for TeeTcbEvalNumber" 52 | en := TeeTcbEvalNumber{val: -10} 53 | err := en.Valid() 54 | assert.EqualError(t, err, expectedErr) 55 | } 56 | 57 | func TestTeeTcbEvalNumber_JSON(t *testing.T) { 58 | 59 | for _, tv := range []struct { 60 | input interface{} 61 | ExpectedBytes []byte 62 | }{ 63 | { 64 | input: uint(10), 65 | ExpectedBytes: []byte(`{"type":"uint","value":10}`), 66 | }, 67 | 68 | { 69 | input: TaggedNumericExpression{NumericOperator: GE, NumericType: NumericType{val: uint(100)}}, 70 | ExpectedBytes: []byte(`{"type":"numeric-expression","value":{"numeric-operator":"greater_or_equal","numeric-type":{"type":"uint","value":100}}}`), 71 | }, 72 | } { 73 | 74 | t.Run("test", func(t *testing.T) { 75 | tcb := &TeeTcbEvalNumber{val: tv.input} 76 | 77 | data, err := tcb.MarshalJSON() 78 | require.NoError(t, err) 79 | fmt.Printf("received string %s", string(data)) 80 | assert.Equal(t, tv.ExpectedBytes, data) 81 | 82 | out := &TeeTcbEvalNumber{} 83 | err = out.UnmarshalJSON(data) 84 | require.NoError(t, err) 85 | }) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /corim/role_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package corim 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestRoles_ToJSON_ok(t *testing.T) { 14 | tvs := []struct { 15 | roles *Roles 16 | expected string 17 | }{ 18 | { 19 | roles: NewRoles().Add(RoleManifestCreator), 20 | expected: `[ "manifestCreator" ]`, 21 | }, 22 | } 23 | 24 | for _, tv := range tvs { 25 | actual, err := tv.roles.ToJSON() 26 | 27 | assert.NoError(t, err) 28 | assert.JSONEq(t, tv.expected, string(actual)) 29 | } 30 | } 31 | 32 | func TestRoles_ToJSON_fail(t *testing.T) { 33 | tvs := []struct { 34 | roles *Roles 35 | expectedErr string 36 | }{ 37 | { 38 | roles: NewRoles(), 39 | expectedErr: "validation failed: empty roles", 40 | }, 41 | } 42 | 43 | for _, tv := range tvs { 44 | _, err := tv.roles.ToJSON() 45 | 46 | assert.EqualError(t, err, tv.expectedErr) 47 | } 48 | } 49 | 50 | func TestRoles_FromJSON_fail(t *testing.T) { 51 | tvs := []struct { 52 | json string 53 | expectedErr string 54 | }{ 55 | { 56 | json: `[]`, 57 | expectedErr: "validation failed: empty roles", 58 | }, 59 | { 60 | json: `["blabla"]`, 61 | expectedErr: `decoding failed: unknown role "blabla"`, 62 | }, 63 | { 64 | json: `[ "manifestCreator", "xyz" ]`, 65 | expectedErr: `decoding failed: unknown role "xyz"`, 66 | }, 67 | { 68 | json: `"tagCreator"`, 69 | expectedErr: "decoding failed: json: cannot unmarshal string into Go value of type []string", 70 | }, 71 | } 72 | 73 | for _, tv := range tvs { 74 | var actual Roles 75 | 76 | err := actual.FromJSON([]byte(tv.json)) 77 | 78 | assert.EqualError(t, err, tv.expectedErr) 79 | } 80 | } 81 | 82 | func Test_Role_String(t *testing.T) { 83 | assert.Equal(t, "manifestCreator", RoleManifestCreator.String()) 84 | assert.Equal(t, "Role(9999)", Role(9999).String()) 85 | } 86 | 87 | func Test_RegisterRole(t *testing.T) { 88 | err := RegisterRole(1, "owner") 89 | assert.EqualError(t, err, "role with value 1 already exists") 90 | 91 | err = RegisterRole(3, "manifestCreator") 92 | assert.EqualError(t, err, `role with name "manifestCreator" already exists`) 93 | 94 | err = RegisterRole(3, "owner") 95 | assert.NoError(t, err) 96 | 97 | roles := NewRoles().Add(Role(3)) 98 | 99 | out, err := roles.MarshalJSON() 100 | require.NoError(t, err) 101 | assert.Equal(t, `["owner"]`, string(out)) 102 | } 103 | -------------------------------------------------------------------------------- /comid/rawvalue_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024-2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package comid 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestRawValue_NewRawValue_ok(t *testing.T) { 13 | tv := NewRawValue() 14 | require.NotNil(t, tv) 15 | } 16 | 17 | func TestRawValue_Set_Get_Bytes_ok(t *testing.T) { 18 | tv := RawValue{} 19 | expected := []byte{0x01, 0x02, 0x03} 20 | rv := tv.SetBytes([]byte{0x01, 0x02, 0x03}) 21 | require.NotNil(t, rv) 22 | rval, err := rv.GetBytes() 23 | assert.NoError(t, err) 24 | assert.Equal(t, expected, rval) 25 | } 26 | 27 | func TestRawValue_Get_Bytes_nok(t *testing.T) { 28 | rv := RawValue{} 29 | expectedErr := "raw value is not set" 30 | _, err := rv.GetBytes() 31 | assert.EqualError(t, err, expectedErr) 32 | rv = RawValue{"testraw"} 33 | expectedErr = "unknown type string for $raw-value-type-choice" 34 | _, err = rv.GetBytes() 35 | assert.EqualError(t, err, expectedErr) 36 | } 37 | 38 | func TestRawValue_Marshal_UnMarshal_JSON_ok(t *testing.T) { 39 | tv := RawValue{} 40 | rv := tv.SetBytes([]byte{0x01, 0x02, 0x03}) 41 | bytes, err := rv.MarshalJSON() 42 | assert.NoError(t, err) 43 | sv := RawValue{} 44 | err = sv.UnmarshalJSON(bytes) 45 | assert.NoError(t, err) 46 | assert.Equal(t, *rv, sv) 47 | } 48 | 49 | func TestRawValue_Marshal_UnMarshal_CBOR_ok(t *testing.T) { 50 | tv := RawValue{} 51 | rv := tv.SetBytes([]byte{0x01, 0x02, 0x03}) 52 | bytes, err := rv.MarshalCBOR() 53 | assert.NoError(t, err) 54 | sv := RawValue{} 55 | err = sv.UnmarshalCBOR(bytes) 56 | assert.NoError(t, err) 57 | assert.Equal(t, *rv, sv) 58 | } 59 | 60 | func TestRawValue_Equal_True(t *testing.T) { 61 | claim := RawValue{} 62 | claim.SetBytes([]byte{0x01, 0x02, 0x03}) 63 | ref := RawValue{} 64 | ref.SetBytes([]byte{0x01, 0x02, 0x03}) 65 | 66 | assert.True(t, claim.Equal(ref)) 67 | } 68 | 69 | func TestRawValue_Equal_False(t *testing.T) { 70 | claim := RawValue{} 71 | claim.SetBytes([]byte{0x01, 0x02, 0x03}) 72 | ref := RawValue{} 73 | ref.SetBytes([]byte{0x01, 0x02, 0x04}) 74 | 75 | assert.False(t, claim.Equal(ref)) 76 | } 77 | 78 | func TestRawValue_Compare_True(t *testing.T) { 79 | claim := RawValue{} 80 | claim.SetBytes([]byte{0x01, 0x02, 0x03}) 81 | ref := []byte{0x01, 0x00, 0x03} 82 | mask := []byte{0xff, 0x00, 0xff} 83 | 84 | assert.True(t, claim.CompareAgainstReference(ref, &mask)) 85 | } 86 | 87 | func TestRawValue_Compare_False(t *testing.T) { 88 | claim := RawValue{} 89 | claim.SetBytes([]byte{0x01, 0x02, 0x03}) 90 | ref := []byte{0x04, 0x05, 0x06} 91 | 92 | assert.False(t, claim.CompareAgainstReference(ref, nil)) 93 | } 94 | -------------------------------------------------------------------------------- /comid/example_psa_keys_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import "fmt" 7 | 8 | func Example_psa_keys() { 9 | comid := Comid{} 10 | 11 | if err := comid.FromJSON([]byte(PSAKeysJSONTemplate)); err != nil { 12 | panic(err) 13 | } 14 | 15 | if err := comid.Valid(); err != nil { 16 | panic(err) 17 | } 18 | 19 | if err := extractKeys(&comid); err != nil { 20 | panic(err) 21 | } 22 | 23 | // output: 24 | // ImplementationID: 61636d652d696d706c656d656e746174696f6e2d69642d303030303030303031 25 | // InstanceID: 01ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508 26 | // IAK public key: 2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d 27 | // ImplementationID: 61636d652d696d706c656d656e746174696f6e2d69642d303030303030303031 28 | // InstanceID: 014ca3e4f50bf248c39787020d68ffd05c88767751bf2645ca923f57a98becd296 29 | // IAK public key: 2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d 30 | } 31 | 32 | func extractKeys(c *Comid) error { 33 | if c.Triples.AttestVerifKeys == nil { 34 | return fmt.Errorf("no reference values triples") 35 | } 36 | 37 | for i, k := range *c.Triples.AttestVerifKeys { 38 | if err := extractPSAKey(k); err != nil { 39 | return fmt.Errorf("bad PSA verification key value at index %d: %w", i, err) 40 | } 41 | } 42 | 43 | return nil 44 | } 45 | 46 | func extractPSAKey(k KeyTriple) error { 47 | class := k.Environment.Class 48 | 49 | if err := extractImplementationID(class); err != nil { 50 | return fmt.Errorf("extracting impl-id: %w", err) 51 | } 52 | 53 | instance := k.Environment.Instance 54 | 55 | if err := extractInstanceID(instance); err != nil { 56 | return fmt.Errorf("extracting inst-id: %w", err) 57 | } 58 | 59 | if len(k.VerifKeys) != 1 { 60 | return fmt.Errorf("more than one key") 61 | } 62 | 63 | fmt.Printf("IAK public key: %x\n", k.VerifKeys[0]) 64 | 65 | return nil 66 | } 67 | 68 | func extractInstanceID(i *Instance) error { 69 | if i == nil { 70 | return fmt.Errorf("no instance") 71 | } 72 | 73 | fmt.Printf("InstanceID: %x\n", i.Bytes()) 74 | 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /corim/testcases/src/example-corim.yaml: -------------------------------------------------------------------------------- 1 | # minimalist unsigned-corim that embeds comid.PSARefValJSONTemplate 2 | # - profile (claim 3) has been set to "http://example.com/example-profile" 3 | # - extension claim -1 has been added to corim 4 | # - extension claim -1 has been added to comid entity 5 | # NOTE: this is the as corim-with-extensions.yaml, except for the profile 6 | # string, which is differentiated so that the example (which uses init() 7 | # to register the profile) doesn't clash with the tests. 8 | --- 9 | tag: 501 10 | value: 11 | 0: test corim id 12 | 3: http://example.com/example-profile 13 | -1: foo 14 | 1: 15 | - tag: 506 16 | value: 17 | encodedCBOR: 18 | 0: en-GB 19 | 1: 20 | 0: !!binary |- 21 | Q7vjfy5hSzOu01PP8UKLFg== 22 | 2: 23 | - 0: ACME Ltd. 24 | 1: 25 | tag: 32 26 | value: https://acme.example 27 | 2: 28 | - 0 29 | - 1 30 | - 2 31 | -1: 123 Fake Street 32 | 4: 33 | 0: 34 | - - 0: 35 | 0: 36 | tag: 600 37 | value: !!binary |- 38 | YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE= 39 | 1: ACME 40 | 2: RoadRunner 41 | - - 0: 42 | tag: 601 43 | value: 44 | 1: BL 45 | 4: 2.1.0 46 | 5: !!binary |- 47 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 48 | 1: 49 | 2: 50 | - - 1 51 | - !!binary |- 52 | h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc= 53 | -1: 1720782190 54 | - 0: 55 | tag: 601 56 | value: 57 | 1: PRoT 58 | 4: 1.3.5 59 | 5: !!binary |- 60 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 61 | 1: 62 | 2: 63 | - - 1 64 | - !!binary |- 65 | AmOCmYm2/ZVPcrqvL8ZLwuLwHWktTecphuqAj26ZgT8= 66 | -1: 1720782190 67 | - 0: 68 | tag: 601 69 | value: 70 | 1: ARoT 71 | 4: 0.1.4 72 | 5: !!binary |- 73 | rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs= 74 | 1: 75 | 2: 76 | - - 1 77 | - !!binary |- 78 | o6XnFfDMV0pzw/m+u2vCTzL/1bZ7OHJEwskJ2neaFHg= 79 | -1: 1720782190 80 | 81 | -------------------------------------------------------------------------------- /comid/rel.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "encoding/json" 8 | "errors" 9 | "fmt" 10 | ) 11 | 12 | type Rel int64 13 | 14 | const ( 15 | RelSupplements Rel = iota 16 | RelReplaces 17 | 18 | RelUnset = ^Rel(0) 19 | ) 20 | 21 | var ( 22 | relToString = map[Rel]string{ 23 | RelReplaces: "replaces", 24 | RelSupplements: "supplements", 25 | } 26 | 27 | stringToRel = map[string]Rel{ 28 | "replaces": RelReplaces, 29 | "supplements": RelSupplements, 30 | } 31 | ) 32 | 33 | // RegisterRel creates a new Rel association between the provided value and 34 | // name. An error is returned if either clashes with any of the existing roles. 35 | func RegisterRel(val int64, name string) error { 36 | rel := Rel(val) 37 | 38 | if _, ok := relToString[rel]; ok { 39 | return fmt.Errorf("rel with value %d already exists", val) 40 | } 41 | 42 | if _, ok := stringToRel[name]; ok { 43 | return fmt.Errorf("rel with name %q already exists", name) 44 | } 45 | 46 | relToString[rel] = name 47 | stringToRel[name] = rel 48 | 49 | return nil 50 | } 51 | 52 | func NewRel() *Rel { 53 | r := RelUnset 54 | return &r 55 | } 56 | 57 | func (o *Rel) Set(r Rel) *Rel { 58 | if o != nil { 59 | *o = r 60 | } 61 | return o 62 | } 63 | 64 | func (o Rel) Get() Rel { 65 | return o 66 | } 67 | 68 | func (o Rel) Valid() error { 69 | if o == RelUnset { 70 | return errors.New("rel is unset") 71 | } 72 | 73 | return nil 74 | } 75 | 76 | func (o Rel) String() string { 77 | ret, ok := relToString[o] 78 | if ok { 79 | return ret 80 | } 81 | 82 | return fmt.Sprintf("rel(%d)", o) 83 | } 84 | 85 | func (o Rel) ToCBOR() ([]byte, error) { 86 | if err := o.Valid(); err != nil { 87 | return nil, err 88 | } 89 | 90 | data, err := em.Marshal(o) 91 | if err != nil { 92 | return nil, err 93 | } 94 | 95 | return data, nil 96 | } 97 | 98 | func (o *Rel) FromCBOR(data []byte) error { 99 | err := dm.Unmarshal(data, o) 100 | if err != nil { 101 | return err 102 | } 103 | 104 | return o.Valid() 105 | } 106 | 107 | func (o *Rel) UnmarshalJSON(data []byte) error { 108 | var s string 109 | 110 | if err := json.Unmarshal(data, &s); err != nil { 111 | return fmt.Errorf("cannot unmarshal rel: %w", err) 112 | } 113 | 114 | if s == "" { 115 | return fmt.Errorf("empty rel") 116 | } 117 | 118 | switch s { 119 | case "supplements": 120 | *o = RelSupplements 121 | case "replaces": 122 | *o = RelReplaces 123 | default: 124 | return fmt.Errorf("unknown rel '%s'", s) 125 | } 126 | 127 | return nil 128 | } 129 | 130 | func (o Rel) MarshalJSON() ([]byte, error) { 131 | return json.Marshal(o.String()) 132 | } 133 | -------------------------------------------------------------------------------- /comid/comid_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package comid 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | "github.com/veraison/corim/extensions" 11 | "github.com/veraison/swid" 12 | ) 13 | 14 | func Test_Comid_Extensions(t *testing.T) { 15 | c := NewComid() 16 | assert.Nil(t, c.GetExtensions()) 17 | assert.Equal(t, "", c.MustGetString("field-one")) 18 | 19 | err := c.Set("field-one", "foo") 20 | assert.EqualError(t, err, "extension not found: field-one") 21 | 22 | type ComidExt struct { 23 | FieldOne string `cbor:"-1,keyasint" json:"field-one"` 24 | } 25 | 26 | extMap := extensions.NewMap(). 27 | Add(ExtComid, &ComidExt{}). 28 | Add(ExtEntity, &struct{}{}). 29 | Add(ExtReferenceValue, &struct{}{}). 30 | Add(ExtEndorsedValueFlags, &struct{}{}) 31 | err = c.RegisterExtensions(extMap) 32 | require.NoError(t, err) 33 | 34 | err = c.Set("field-one", "foo") 35 | assert.NoError(t, err) 36 | assert.Equal(t, "foo", c.MustGetString("-1")) 37 | } 38 | 39 | func Test_Comid_ToJSONPretty(t *testing.T) { 40 | c := NewComid() 41 | 42 | _, err := c.ToJSONPretty(" ") 43 | assert.EqualError(t, err, "tag-identity validation failed: empty tag-id") 44 | 45 | c.TagIdentity = TagIdentity{TagID: *swid.NewTagID("test"), TagVersion: 1} 46 | c.Triples = Triples{ 47 | ReferenceValues: NewValueTriples().Add(&ValueTriple{ 48 | Environment: Environment{ 49 | Instance: MustNewUUIDInstance(TestUUID), 50 | }, 51 | Measurements: *NewMeasurements().Add(&Measurement{ 52 | Val: Mval{ 53 | RawValue: NewRawValue().SetBytes(MustHexDecode(t, "deadbeef")), 54 | }, 55 | }), 56 | }), 57 | } 58 | 59 | expected := `{ 60 | "tag-identity": { 61 | "id": "test", 62 | "version": 1 63 | }, 64 | "triples": { 65 | "reference-values": [ 66 | { 67 | "environment": { 68 | "instance": { 69 | "type": "uuid", 70 | "value": "31fb5abf-023e-4992-aa4e-95f9c1503bfa" 71 | } 72 | }, 73 | "measurements": [ 74 | { 75 | "value": { 76 | "raw-value": { 77 | "type": "bytes", 78 | "value": "3q2+7w==" 79 | } 80 | } 81 | } 82 | ] 83 | } 84 | ] 85 | } 86 | }` 87 | v, err := c.ToJSONPretty(" ") 88 | require.NoError(t, err) 89 | assert.Equal(t, expected, string(v)) 90 | } 91 | 92 | func Test_String2URI_nok(t *testing.T) { 93 | s := "@@@" 94 | _, err := String2URI(&s) 95 | assert.EqualError(t, err, `expecting an absolute URI: "@@@" is not an absolute URI`) 96 | } 97 | -------------------------------------------------------------------------------- /corim/meta.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package corim 5 | 6 | import ( 7 | "encoding/json" 8 | "fmt" 9 | "time" 10 | 11 | "github.com/veraison/corim/extensions" 12 | ) 13 | 14 | // Meta stores a corim-meta-map with JSON and CBOR serializations. It carries 15 | // information about the CoRIM signer and, optionally, a validity period 16 | // associated with the signed assertion. A corim-meta-map is serialized to CBOR 17 | // and added to the protected header structure in the signed-corim as a byte string 18 | type Meta struct { 19 | Signer Signer `cbor:"0,keyasint" json:"signer"` 20 | Validity *Validity `cbor:"1,keyasint,omitempty" json:"validity,omitempty"` 21 | } 22 | 23 | func NewMeta() *Meta { 24 | return &Meta{} 25 | } 26 | 27 | func (o *Meta) RegisterExtensions(exts extensions.Map) error { 28 | for p, v := range exts { 29 | switch p { 30 | case ExtSigner: 31 | o.Signer.Register(v) 32 | default: 33 | return fmt.Errorf("%w: %q", extensions.ErrUnexpectedPoint, p) 34 | } 35 | } 36 | 37 | return nil 38 | } 39 | 40 | // SetSigner populates the Signer element in the target Meta with the supplied 41 | // name and optional URI 42 | func (o *Meta) SetSigner(name string, uri *string) *Meta { 43 | if o != nil { 44 | s := NewSigner().SetName(name) 45 | 46 | if uri != nil { 47 | s = s.SetURI(*uri) 48 | } 49 | 50 | if s == nil { 51 | return nil 52 | } 53 | 54 | o.Signer = *s 55 | } 56 | return o 57 | } 58 | 59 | // SetValidity sets the validity period of the target Meta to the supplied time 60 | // range 61 | func (o *Meta) SetValidity(notAfter time.Time, notBefore *time.Time) *Meta { 62 | if o != nil { 63 | v := NewValidity().Set(notAfter, notBefore) 64 | if v == nil { 65 | return nil 66 | } 67 | 68 | o.Validity = v 69 | } 70 | return o 71 | } 72 | 73 | // Valid checks for validity of the fields within Meta 74 | func (o Meta) Valid() error { 75 | if err := o.Signer.Valid(); err != nil { 76 | return fmt.Errorf("invalid signer: %w", err) 77 | } 78 | 79 | if o.Validity != nil { 80 | if err := o.Validity.Valid(); err != nil { 81 | return fmt.Errorf("invalid validity: %w", err) 82 | } 83 | } 84 | 85 | return nil 86 | } 87 | 88 | // ToCBOR serializes the target Meta to CBOR 89 | func (o Meta) ToCBOR() ([]byte, error) { 90 | return em.Marshal(&o) 91 | } 92 | 93 | // FromCBOR deserializes the supplied CBOR data into the target Meta 94 | func (o *Meta) FromCBOR(data []byte) error { 95 | return dm.Unmarshal(data, o) 96 | } 97 | 98 | // FromJSON deserializes the supplied JSON data into the target Meta 99 | func (o *Meta) FromJSON(data []byte) error { 100 | return json.Unmarshal(data, o) 101 | } 102 | 103 | // ToJSON serializes the target Meta to JSON 104 | func (o Meta) ToJSON() ([]byte, error) { 105 | return json.Marshal(&o) 106 | } 107 | -------------------------------------------------------------------------------- /profiles/tdx/mval_extensions.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "time" 8 | 9 | "github.com/veraison/corim/comid" 10 | "github.com/veraison/corim/corim" 11 | "github.com/veraison/corim/extensions" 12 | "github.com/veraison/eat" 13 | ) 14 | 15 | // MValExtensions contains the Intel TDX profile extensions which can appear in 16 | // both Reference Values and Endorsed Values 17 | type MValExtensions struct { 18 | TeeTcbDate *time.Time `cbor:"-72,keyasint,omitempty" json:"tcbdate,omitempty"` 19 | TeeISVSVN *TeeSVN `cbor:"-73,keyasint,omitempty" json:"isvsvn,omitempty"` 20 | TeeInstanceID *TeeInstanceID `cbor:"-77,keyasint,omitempty" json:"instanceid,omitempty"` 21 | TeePCEID *TeePCEID `cbor:"-80,keyasint,omitempty" json:"pceid,omitempty"` 22 | TeeMiscSelect *TeeMiscSelect `cbor:"-81,keyasint,omitempty" json:"miscselect,omitempty"` 23 | TeeAttributes *TeeAttributes `cbor:"-82,keyasint,omitempty" json:"attributes,omitempty"` 24 | TeeMrTee *TeeDigest `cbor:"-83,keyasint,omitempty" json:"mrtee,omitempty"` 25 | TeeMrSigner *TeeDigest `cbor:"-84,keyasint,omitempty" json:"mrsigner,omitempty"` 26 | TeeISVProdID *TeeISVProdID `cbor:"-85,keyasint,omitempty" json:"isvprodid,omitempty"` 27 | TeeTcbEvalNum *TeeTcbEvalNumber `cbor:"-86,keyasint,omitempty" json:"tcbevalnum,omitempty"` 28 | TeeTcbStatus *TeeTcbStatus `cbor:"-88,keyasint,omitempty" json:"tcbstatus,omitempty"` 29 | TeeAdvisoryIDs *TeeAdvisoryIDs `cbor:"-89,keyasint,omitempty" json:"advisoryids,omitempty"` 30 | TeeEpoch *time.Time `cbor:"-90, keyasint,omitempty" json:"epoch,omitempty"` 31 | 32 | TeeCryptoKeys *comid.CryptoKeys `cbor:"-91, keyasint,omitempty" json:"teecryptokeys,omitempty"` 33 | TeeTCBCompSvn *TeeTcbCompSvn `cbor:"-125, keyasint,omitempty" json:"tcbcompsvn,omitempty"` 34 | } 35 | 36 | // Registering the profile inside init() in the same file where it is defined 37 | // ensures that the profile will always be available, and you don't need to 38 | // remember to register it when you want to use it. The only potential 39 | // danger with that is if your profile ID clashes with another profile, 40 | // which should not happen if it is a registered PEN or a URL containing a domain 41 | // that you own. 42 | // Note Intel profile is "2.16.840.1.113741.1.16.1", 43 | // which is "joint-iso-itu-t.country.us.organization.intel.intel-comid.profile" 44 | 45 | func init() { 46 | profileID, err := eat.NewProfile("2.16.840.1.113741.1.16.1") 47 | if err != nil { 48 | panic(err) // will not error, as the hard-coded string above is valid 49 | } 50 | 51 | extMap := extensions.NewMap(). 52 | Add(comid.ExtReferenceValue, &MValExtensions{}). 53 | Add(comid.ExtEndorsedValue, &MValExtensions{}) 54 | 55 | if err := corim.RegisterProfile(profileID, extMap); err != nil { 56 | // will not error, assuming our profile ID is unique, and we've 57 | // correctly set up the extensions Map above 58 | panic(err) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /comid/testcases/src/comid-firmware-cd.diag: -------------------------------------------------------------------------------- 1 | 2 | / concise-mid-tag / { 3 | / comid.tag-identity / 1 : { 4 | / comid.tag-id / 0 : h'AF1CD895BE784ADBB7E9ADD44A65ABF3' 5 | }, 6 | / comid.entity / 2 : [ { 7 | / comid.entity-name / 0 : "Firmware MFG Inc.", 8 | / comid.reg-id / 1 : 32("https://fwmfginc.example"), 9 | / comid.role / 2 : [ 0 ] / tag-creator / 10 | } ], 11 | / comid.triples / 4 : { 12 | / comid.reference-triples / 0 : [ 13 | [ 14 | / environment-map / { 15 | / ** Hash of layer 0 firmware ** / 16 | / comid.class / 0 : { 17 | / comid.vendor / 1 : "fwmfginc.example", 18 | / comid.model / 2 : "fwY_n5x", 19 | / comid.layer / 3 : 0, 20 | / comid.index / 4 : 0 21 | } 22 | }, 23 | [ 24 | / measurement-map / 25 | { 26 | / comid.mval / 1 : { 27 | / comid.svn / 1 : 552(1), 28 | / comid.digests / 2 : [ 29 | [ 30 | / hash-alg-id / 7, / SHA384 / 31 | / hash-value / h'15E77D6F133252F1DB7044901313884F2977D2109B33C79F33E079BFC78865255C0FB733C240FDDA544B8215D7B8F815' 32 | ] 33 | ] 34 | } 35 | } 36 | ] 37 | ], 38 | [ 39 | / environment-map / { 40 | / ** Hash of layer 1 firmware ** / 41 | / comid.class / 0 : { 42 | / comid.vendor / 1 : "fwmfginc.example", 43 | / comid.model / 2 : "fwX_n5x", 44 | / comid.layer / 3 : 1, 45 | / comid.index / 4 : 0 46 | } 47 | }, 48 | [ 49 | / measurement-map / 50 | { 51 | / comid.mval / 1 : { 52 | / comid.svn / 1 : 552(1), 53 | / comid.digests / 2 : [ 54 | [ 55 | / hash-alg-id / 7, / SHA384 / 56 | / hash-value / h'3D90B6BF003DA2D94EA5463F97FB3C53DDC51CFBA1E3E38EEF7AF071A67986595D22729131DF9FE80F5451EEF154F85E' 57 | ] 58 | ] 59 | } 60 | } 61 | ] 62 | ] 63 | ], 64 | / comid.endorsed-triples / 1 : [ 65 | [ 66 | / environment-map / { 67 | / comid.class / 0 : { 68 | / ** Firmware is valid (example) ** / 69 | / comid.class-id / 0 : 70 | / tagged-oid-type / 111(h'6086480186F84D010F046301'), / 2.16.840.1.113741.1.15.4.99.1 / 71 | / comid.vendor / 1 : "fwmfginc.example" 72 | } 73 | }, 74 | [ 75 | / measurement-map / { 76 | / comid.mval / 1 : { 77 | / raw-value-group / 78 | / comid.raw-value / 4 : 560(h'0000000000000000'), 79 | / comid.raw-value-mask / 5 : h'FFFFFFFF00000000' 80 | } 81 | } 82 | ] 83 | ] 84 | ] 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /comid/valuetriple.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "errors" 8 | "fmt" 9 | 10 | "github.com/veraison/corim/extensions" 11 | ) 12 | 13 | // ValueTriple relates measurements to a target environment, essentially 14 | // forming a subject-predicate-object triple of "measurements-pertain 15 | // to-environment". This structure is used to represent both 16 | // reference-triple-record and endorsed-triple-record in the CoRIM spec (as of 17 | // rev. 04). 18 | type ValueTriple struct { 19 | _ struct{} `cbor:",toarray"` 20 | Environment Environment `json:"environment"` 21 | Measurements Measurements `json:"measurements"` 22 | } 23 | 24 | func (o *ValueTriple) RegisterExtensions(exts extensions.Map) error { 25 | return o.Measurements.RegisterExtensions(exts) 26 | } 27 | 28 | func (o *ValueTriple) GetExtensions() extensions.IMapValue { 29 | return o.Measurements.GetExtensions() 30 | } 31 | 32 | func (o ValueTriple) Valid() error { 33 | if err := o.Environment.Valid(); err != nil { 34 | return fmt.Errorf("environment validation failed: %w", err) 35 | } 36 | 37 | if o.Measurements.IsEmpty() { 38 | return errors.New("measurements validation failed: no measurement entries") 39 | } 40 | 41 | if err := o.Measurements.Valid(); err != nil { 42 | return fmt.Errorf("measurements validation failed: %w", err) 43 | } 44 | 45 | return nil 46 | } 47 | 48 | // ValueTriples is a container for ValueTriple instances and their extensions. 49 | // It is a thin wrapper around extensions.Collection. 50 | type ValueTriples extensions.Collection[ValueTriple, *ValueTriple] 51 | 52 | func NewValueTriples() *ValueTriples { 53 | return (*ValueTriples)(extensions.NewCollection[ValueTriple]()) 54 | } 55 | 56 | func (o *ValueTriples) RegisterExtensions(exts extensions.Map) error { 57 | return (*extensions.Collection[ValueTriple, *ValueTriple])(o).RegisterExtensions(exts) 58 | } 59 | 60 | func (o *ValueTriples) GetExtensions() extensions.IMapValue { 61 | return (*extensions.Collection[ValueTriple, *ValueTriple])(o).GetExtensions() 62 | } 63 | 64 | func (o ValueTriples) Valid() error { 65 | return (extensions.Collection[ValueTriple, *ValueTriple])(o).Valid() 66 | } 67 | 68 | func (o *ValueTriples) IsEmpty() bool { 69 | return (*extensions.Collection[ValueTriple, *ValueTriple])(o).IsEmpty() 70 | } 71 | 72 | func (o *ValueTriples) Add(val *ValueTriple) *ValueTriples { 73 | ret := (*extensions.Collection[ValueTriple, *ValueTriple])(o).Add(val) 74 | return (*ValueTriples)(ret) 75 | } 76 | 77 | func (o ValueTriples) MarshalCBOR() ([]byte, error) { 78 | return (extensions.Collection[ValueTriple, *ValueTriple])(o).MarshalCBOR() 79 | } 80 | 81 | func (o *ValueTriples) UnmarshalCBOR(data []byte) error { 82 | return (*extensions.Collection[ValueTriple, *ValueTriple])(o).UnmarshalCBOR(data) 83 | } 84 | 85 | func (o ValueTriples) MarshalJSON() ([]byte, error) { 86 | return (extensions.Collection[ValueTriple, *ValueTriple])(o).MarshalJSON() 87 | } 88 | 89 | func (o *ValueTriples) UnmarshalJSON(data []byte) error { 90 | return (*extensions.Collection[ValueTriple, *ValueTriple])(o).UnmarshalJSON(data) 91 | } 92 | -------------------------------------------------------------------------------- /profiles/tdx/teeadvisoryids_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestAdvisoryIDs_NewTeeAvisoryIDsExpr_OK(t *testing.T) { 15 | a := TestAdvisoryIDs 16 | _, err := NewTeeAdvisoryIDsExpr(MEM, a) 17 | require.Nil(t, err) 18 | } 19 | 20 | func TestAdvisoryIDs_NewTeeAvisoryIDsString_OK(t *testing.T) { 21 | a := TestAdvisoryIDs 22 | _, err := NewTeeAdvisoryIDsString(a) 23 | require.Nil(t, err) 24 | } 25 | 26 | func TestAdvisoryIDs_NewTeeAvisoryIDsExpr_NOK(t *testing.T) { 27 | expectedErr := "invalid operator : 5" 28 | a := make([]string, len(TestAdvisoryIDs)) 29 | _, err := NewTeeAdvisoryIDsExpr(NOP, a) 30 | assert.EqualError(t, err, expectedErr) 31 | } 32 | 33 | func TestAdvisoryIDs_AddAdvisoryIDsString_OK(t *testing.T) { 34 | a := TestAdvisoryIDs 35 | adv := &TeeAdvisoryIDs{val: a} 36 | _, err := adv.AddTeeAdvisoryIDs(NOP, []string{"abcd"}) 37 | require.NoError(t, err) 38 | } 39 | 40 | func TestAdvisoryIDs_AddAdvisoryIDsExpr_OK(t *testing.T) { 41 | a := TestAdvisoryIDs 42 | adv := TeeAdvisoryIDs{val: TaggedSetStringExpression{SetOperator: MEM, SetString: a}} 43 | _, err := adv.AddTeeAdvisoryIDs(MEM, []string{"abcd"}) 44 | require.NoError(t, err) 45 | } 46 | 47 | func TestAdvisoryIDs_Valid_OK(t *testing.T) { 48 | a := TestAdvisoryIDs 49 | ta := TeeAdvisoryIDs{val: a} 50 | err := ta.Valid() 51 | require.NoError(t, err) 52 | ta = TeeAdvisoryIDs{val: TaggedSetStringExpression{SetOperator: MEM, SetString: a}} 53 | err = ta.Valid() 54 | require.NoError(t, err) 55 | } 56 | 57 | func TestAdvisoryIDs_Valid_NOK(t *testing.T) { 58 | expectedErr := "TeeAdvisoryID not set" 59 | a := []string{} 60 | ta := TeeAdvisoryIDs{val: a} 61 | err := ta.Valid() 62 | assert.EqualError(t, err, expectedErr) 63 | expectedErr = "unknown type tdx.SetStringExpression for TeeAdvisoryIDs" 64 | ta = TeeAdvisoryIDs{val: SetStringExpression{SetOperator: NOP, SetString: []string{"abc"}}} 65 | err = ta.Valid() 66 | assert.EqualError(t, err, expectedErr) 67 | } 68 | 69 | func TestAdvisoryIDs_JSON(t *testing.T) { 70 | a := TestAdvisoryIDs 71 | 72 | for _, tv := range []struct { 73 | input []string 74 | ExpectedBytes []byte 75 | }{ 76 | { 77 | input: []string{"SA-123"}, 78 | ExpectedBytes: []byte(`{"type":"string","value":["SA-123"]}`), 79 | }, 80 | { 81 | input: a, 82 | ExpectedBytes: []byte(`{"type":"string","value":["SA-00078","SA-00077","SA-00079"]}`), 83 | }, 84 | } { 85 | 86 | t.Run("test", func(t *testing.T) { 87 | ta, err := NewTeeAdvisoryIDsString(tv.input) 88 | require.NoError(t, err) 89 | 90 | data, err := ta.MarshalJSON() 91 | require.NoError(t, err) 92 | fmt.Printf("received string %s", string(data)) 93 | assert.Equal(t, tv.ExpectedBytes, data) 94 | 95 | out := &TeeAdvisoryIDs{} 96 | err = out.UnmarshalJSON(data) 97 | require.NoError(t, err) 98 | assert.Equal(t, tv.input, out.val) 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /comid/role.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2024 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package comid 5 | 6 | import ( 7 | "encoding/json" 8 | "fmt" 9 | ) 10 | 11 | type Role int64 12 | 13 | /* 14 | $comid-role-type-choice /= comid.tag-creator 15 | $comid-role-type-choice /= comid.creator 16 | $comid-role-type-choice /= comid.maintainer 17 | 18 | comid.tag-creator = 0 19 | comid.creator = 1 20 | comid.maintainer = 2 21 | */ 22 | 23 | const ( 24 | RoleTagCreator Role = iota 25 | RoleCreator 26 | RoleMaintainer 27 | ) 28 | 29 | var ( 30 | roleToString = map[Role]string{ 31 | RoleTagCreator: "tagCreator", 32 | RoleCreator: "creator", 33 | RoleMaintainer: "maintainer", 34 | } 35 | 36 | stringToRole = map[string]Role{ 37 | "tagCreator": RoleTagCreator, 38 | "creator": RoleCreator, 39 | "maintainer": RoleMaintainer, 40 | } 41 | ) 42 | 43 | // String returns the string representation of the Role. 44 | func (o Role) String() string { 45 | text, ok := roleToString[o] 46 | if ok { 47 | return text 48 | } 49 | 50 | return fmt.Sprintf("Role(%d)", o) 51 | } 52 | 53 | // RegisterRole creates a new Role association between the provided value and 54 | // name. An error is returned if either clashes with any of the existing roles. 55 | func RegisterRole(val int64, name string) error { 56 | role := Role(val) 57 | 58 | if _, ok := roleToString[role]; ok { 59 | return fmt.Errorf("role with value %d already exists", val) 60 | } 61 | 62 | if _, ok := stringToRole[name]; ok { 63 | return fmt.Errorf("role with name %q already exists", name) 64 | } 65 | 66 | roleToString[role] = name 67 | stringToRole[name] = role 68 | 69 | return nil 70 | } 71 | 72 | type Roles []Role 73 | 74 | func NewRoles() *Roles { 75 | return new(Roles) 76 | } 77 | 78 | func (o *Roles) Add(roles ...Role) *Roles { 79 | if o != nil { 80 | *o = append(*o, roles...) 81 | } 82 | 83 | return o 84 | } 85 | 86 | func (o Roles) Valid() error { 87 | if len(o) == 0 { 88 | return fmt.Errorf("empty roles") 89 | } 90 | 91 | return nil 92 | } 93 | 94 | func (o Roles) ToCBOR() ([]byte, error) { 95 | if err := o.Valid(); err != nil { 96 | return nil, err 97 | } 98 | 99 | data, err := em.Marshal(o) 100 | if err != nil { 101 | return nil, err 102 | } 103 | 104 | return data, nil 105 | } 106 | 107 | func (o *Roles) FromCBOR(data []byte) error { 108 | err := dm.Unmarshal(data, o) 109 | if err != nil { 110 | return err 111 | } 112 | 113 | return o.Valid() 114 | } 115 | 116 | func (o *Roles) UnmarshalJSON(data []byte) error { 117 | var a []string 118 | 119 | if err := json.Unmarshal(data, &a); err != nil { 120 | return err 121 | } 122 | 123 | if len(a) == 0 { 124 | return fmt.Errorf("no roles found") 125 | } 126 | 127 | for _, s := range a { 128 | r, ok := stringToRole[s] 129 | if !ok { 130 | return fmt.Errorf("unknown role %q", s) 131 | } 132 | o = o.Add(r) 133 | } 134 | 135 | return nil 136 | } 137 | 138 | func (o Roles) MarshalJSON() ([]byte, error) { 139 | roles := []string{} 140 | 141 | for _, r := range o { 142 | s, ok := roleToString[r] 143 | if !ok { 144 | return nil, fmt.Errorf("unknown role %d", r) 145 | } 146 | roles = append(roles, s) 147 | } 148 | 149 | return json.Marshal(roles) 150 | } 151 | -------------------------------------------------------------------------------- /profiles/tdx/teeinstanceid_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Contributors to the Veraison project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package tdx 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | 10 | "github.com/stretchr/testify/assert" 11 | "github.com/stretchr/testify/require" 12 | "github.com/veraison/corim/comid" 13 | ) 14 | 15 | func TestTeeInstanceID_NewTeeInstanceID_OK(t *testing.T) { 16 | tvs := []struct { 17 | desc string 18 | input any 19 | }{ 20 | { 21 | desc: "integer", 22 | input: TestUIntInstance, 23 | }, 24 | { 25 | desc: "byte array", 26 | input: TestByteInstance, 27 | }, 28 | { 29 | desc: "unsigned integer 64", 30 | input: uint64(TestUIntInstance), 31 | }, 32 | } 33 | 34 | for _, tv := range tvs { 35 | _, err := NewTeeInstanceID(tv.input) 36 | require.Nil(t, err) 37 | } 38 | } 39 | 40 | func TestTeeInstanceID_SetTeeInstanceID_OK(t *testing.T) { 41 | inst := &TeeInstanceID{} 42 | err := inst.SetTeeInstanceID(TestUIntInstance) 43 | require.NoError(t, err) 44 | err = inst.SetTeeInstanceID(TestByteInstance) 45 | require.NoError(t, err) 46 | err = inst.SetTeeInstanceID(uint64(1000)) 47 | require.NoError(t, err) 48 | } 49 | 50 | func TestTeeInstanceID_SetTeeInstanceID_NOK(t *testing.T) { 51 | inst := &TeeInstanceID{} 52 | expectedErr := "unsupported negative TeeInstanceID: -1" 53 | err := inst.SetTeeInstanceID(-1) 54 | assert.EqualError(t, err, expectedErr) 55 | expectedErr = "unsupported TeeInstanceID type: float64" 56 | err = inst.SetTeeInstanceID(-1.234) 57 | assert.EqualError(t, err, expectedErr) 58 | } 59 | 60 | func TestTeeInstanceID_Valid_OK(t *testing.T) { 61 | inst := &TeeInstanceID{TestUIntInstance} 62 | err := inst.Valid() 63 | require.NoError(t, err) 64 | } 65 | 66 | func TestTeeInstanceID_Valid_NOK(t *testing.T) { 67 | tvs := []struct { 68 | desc string 69 | input interface{} 70 | expectedErr string 71 | }{ 72 | { 73 | desc: "unsupported type negative integer", 74 | input: -1, 75 | expectedErr: "unsupported negative TeeInstanceID: -1", 76 | }, 77 | { 78 | desc: "non existent TeeInstanceID", 79 | input: nil, 80 | expectedErr: "empty TeeInstanceID", 81 | }, 82 | { 83 | desc: "non existent TeeInstanceID", 84 | input: []byte{}, 85 | expectedErr: "empty TeeInstanceID", 86 | }, 87 | { 88 | desc: "unsupported type float64", 89 | input: 1.234, 90 | expectedErr: "unsupported TeeInstanceID type: float64", 91 | }, 92 | } 93 | 94 | for _, tv := range tvs { 95 | inst := &TeeInstanceID{tv.input} 96 | err := inst.Valid() 97 | assert.EqualError(t, err, tv.expectedErr) 98 | } 99 | } 100 | 101 | func TestTeeInstanceID_MarshalCBOR_Bytes(t *testing.T) { 102 | inst, err := NewTeeInstanceID(TestByteInstance) 103 | require.Nil(t, err) 104 | expected := comid.MustHexDecode(t, "43454647") 105 | actual, err := inst.MarshalCBOR() 106 | fmt.Printf("CBOR: %x\n", actual) 107 | assert.Nil(t, err) 108 | assert.Equal(t, expected, actual) 109 | } 110 | 111 | func TestTeeInstanceID_JSON(t *testing.T) { 112 | inst := TeeInstanceID{TestByteInstance} 113 | ji, err := inst.MarshalJSON() 114 | assert.Nil(t, err) 115 | i := &TeeInstanceID{} 116 | err = i.UnmarshalJSON(ji) 117 | assert.Nil(t, err) 118 | } 119 | --------------------------------------------------------------------------------