--- title: Supply Chain Integrity Model abbrev: SCIM docname: draft-birkholz-scim-latest stand_alone: true ipr: trust200902 area: Security wg: RATS Working Group kw: Internet-Draft cat: std pi: toc: yes sortrefs: yes symrefs: yes author: - ins: J. Doe name: John Doe org: ACME Inc. abbrev: ACME Inc. email: john.doe@loopback street: Loop Back 127 code: '12712' city: Loopback country: Germany normative: RFC2119: RFC8174: I-D.ietf-sacm-coswid: coswid informative: --- abstract Abstract --- middle [TOC] # Introduction This document describes a generic model, the Supply Chain Integrity Model (SCIM) for managing data about the security, quality, and integrity of assets (physical, digital, and human) across end-to-end supply chains. # References Distributed Identity (DID) - https://www.w3.org/TR/did-core/ Confidential Consortium Framework (CCF) - https://microsoft.github.io/CCF/ Note: Later generalize to not reference DID or CCF specifically. # Terminology Actors: : Agent - (W3C:PROV-O) An agent is something that bears some form of responsibility for an activity taking place, for the existence of an entity, or for another agent's activity. : Person - Person agents are people. : Organization - An organization is a social or legal institution such as a company, society, etc. : Software Agent - A software agent is running software. Roles: : Issuing Authority - Agent that issues Signed Claims, e.g. Microsoft. : Auditor - An Issuing Authority that issues signed audit claims about artifacts that are, for example, other claims, or software packages, or activities conducted by a role, or other resources. : Claim Generator - Software Agent that generates Claims, e.g. Office build system. : Claim Signer - Software Agent that accepts unsigned Claims and signs them using protected capabilities endorsed by an Issuing Authority, e.g. Microsoft signing service including an endorsed RoT. : Ledger Service - Software Agent that accepts and logs Signed Claims based on Trust Anchors, making them Registered Claims. : Ledger Authority - Agent that governs a Ledger Service, e.g. 'Microsoft', 'Global Supply Chain Consortium'. Governance includes managing Trust Anchors. : Claims Registration Requestor - Software Agent that submits Signed Claims to a Ledger Service for registration. : Claims Index Service - Software Agent that supports querying of Registered Claims. Duties: : Timestamping an activity (e.g. an essential duty of the Ledger Services) Documents (data at rest): : Claims * Anonymous statements produced by a human or tool, e.g. evidence, endorsements, and policy * Arbitrary format, but with defined media type * Comes without guarantees * Process: Statements produced by human or tool * Guarantees: None * Analogy: Real world document/letter : Signed Claims - claims wrapped with a header and signed. * Header contains media type of claims and signing key details * No restriction on media type of claims * Process: Signed * Guarantees: Proof of possession of private key * Analogy: Signed document or letter : Registered Claims - signed claims wrapped in a ledger receipt. * Process: * Signed claims are submitted (via REST) * The ledger either: * Has a cached DID document for the issuer, or * Resolves the DID document for the issuer * The ledger makes collateral used to resolve the DID document transparent * e.g., TLS certificate (with OCSP) for did:web * The ledger validates the claims signature based on the public key contained (at the specified keyid) in the DID document * The signed claims are made transparent by reaching consensus * Note that the media type of the claims and the claims themselves are considered opaque * Guarantees: * The Signed Claims are transparant * The process by which the Signed Claims are registered is transparant * The signature is valid. * The DID verification material was valid when the Signed Claims were validated by the ledger. * Deciding if DID verification material is valid is DID method specific. * The DID document corresponding to the DID referenced in the signed claims header contained the public key corresponding to the private key at a specific keyid (the DID document can have multiple keyids) * The Ledger contains the DID document that was used to validate the public key * The "rules of the system" at the time the Signed Claims were made transparent are themselves transparent * Hardware attestation reports indicating that the system was valid at the time it executed are transparent * The history of all Ledger governance that could affect the registering of Signed Claims is itself transparent ## Media types Claims are represented as a document with a media type. Examples are SBOMs, policies, audits, freshness information, and others. Signed Claims are claims embedded in a signing envelope where the media type of the claims is included in the envelope. The signing envelope itself has a media type as well, currently fixed to application/cose. Registered claims are Signed Claims embedded in a Claims Registration Receipt where the media type of the signing envelope is included in the receipt. In this document, the media type of the claims is also called content type. ### SCIM-defined content types Generally, SCIM is agnostic to claims content types. However, to aid interoperability this specification recommends and/or defines certain content types. * freshness claims? * default fall-back? maybe even MTI? Part of SCIM [FIXME] ## Claims Index Service Capabilites MAIK: I'm not sure we can realistically define an interface for such a service as it will depend on the use case. We could define a very generic interface but this may be less valuable. * content-types? * Encoding by Hash, URL, and description of _access method_ [FIXME] * requirement: The *query engine* (Claims Index Service) is the thing which has to know about the media-type decoding. common (media?) types to filter by: - vulnerabilities - ## Mirroring / Bulk retrieval REST API interface to allow bulk-fetching of registered claims according to some filter criteria: - required: start txid - optional: end txid, may be higher than actual (if missing, until latest) - optional: content type(s) - optional: issuer(s) Result: - cbor list of receipts - actual end txid of given range - pagination Notes: - tx ids in ledger must be increasing, not guids, otherwise range query does not make sense basis for developing a query engine, where (a subset of) data is continually mirrored whether part of the ledger or not, it should be part of SCIM ### Vital SCIM Metadata * "EO metadata" -> ?? ## Messages (data in flight) for End-User Interface Claims Registration Request: : Operation: HTTP message to enter Signed Claims in a Ledger Service. : From: Claims Registration Requestor : To: Ledger Service Claims Registration Response: : Operation: HTTP message returned by a Ledger Service in response to a Claims Registration Request, confirming whether the Signed Claims have been accepted for registration, pending consensus. : From: Ledger Service : To: Claims Registration Requestor Claims Registration Receipt Request: : Operation: HTTP message to request a receipt for a successful claims registration. : From: Claims Registration Requestor : To: Ledger Service Claims Registration Receipt Response: : Operation: HTTP message returned by a Ledger Service in response to a Claims Registration Receipt Request, containing either the receipt or error details. : From: Ledger Service : To: Claims Registration Requestor Questions: * **Maik:** How are Duties different from Roles? * How do we handle policy and verification in the model? Ledger: : tbd ## Messages "internal to the Ledger" **MAIK:** That seems like a lot. I don't want to paste the CCF REST API in here. It's implementation-specific. ## Policy Evaluation Phases 1. Verify Claims_Registration_Receipt -> walking thourgh hash tree, "check the proof" * one or more trsuted services key roots (as the included signature is over the root cert only) * then you walk the proof (check existence of tree nodes in ledger according to path in receipt) * public key in the receipt is the basis for trust decisions based on your policies -> actually trusted trust anchors in trust anchor store * this is probably very well-defined and simple to follow (integrity & trust decision based on HRoT) * not part of your policy engine, just code that does signature validation * Trust Anchor management might be "out-of-band" 2. Look at content that might be part of the payload or around it (freshnes/expire/version) * where does Claims that enable this go? * could be content, could be in the wrapper * is the DID issuer in my list of trusted DID issuers? * root policy? how to identify, how to trust? * e.g., one trusted issuer for DID * if that content from that issuer, I can trust that policy * "list of all the other claims that are attributes of the first claims" 2nd claims -> metadata 3. Process signed_claims to arraive at a certain conclusion * here ## Requirements Notation {::boilerplate bcp14-tagged} {: #mybody} # SCIM ## The SCIM Diagram ~~~~ .---------------------. .---------------------. | SoftwareAgent: | | Message: | | SCIM Assertion-Set | generates | SCIM Assertion Set | | Generator +----------------->| | | RATS Claims Generator | | RATS Claim | '---------------------' '---------------------' ^ ^ | owns | consumes | | .----------+----------. .----------+----------. | Agent: | | SoftwareAgent: | | SCIM Issuer | generates + | SCIM Header Adder & | | +----------------->| Signer | | RATS RP Owner | header-claims | RATS Claim Collector | '----------+----------' '----------+----------' | | | owns | generates v v .---------------------. .---------------------. | SoftwareAgent: | | Message: | | SCIM ReceiptRequester | consumes | (COSE) Signed SCIM | | RATS Attester +----------------->| Claims Set | | RATS Relying Party | | RATS Claim | '----------+-----+----' '---------------------' | | | '----------------. v generates | consumes .---------------------. | .---------------------. | Message: | | | Message: | | SCIM ReceiptRequest | '--->| SCIM Receipt | | | .--->| RATS AR-augmented | | RATS Evidence | | | Evidence | '----------+----------' | '---------------------' ^ consumes | generates | .----------------' | | .----------+-----+----. .---------------------. | SoftwareAgent: | | Agent: | | SCIM Ledger Service | consumes | SCIM Ledger Authority | | +----------------->| | | RATS Endorsed Verifier| | RATS Verifier Owner | '----------+----------' '----------+----------' | | | generates | owns v v .---------------------. .---------------------. | Messages: | | SoftwareAgent: | | Receipt Ledger | consumes | "Store" | | |<-----------------| | | RATS Evidence | | RATS Verifier | '---------------------' '---------------------' ~~~~ # Trust Anchor Model * DID specifica * TLS cert verfiication can happen inside a TEE * Ledger HRoT # SCIM Roles and Messages ## Roles ### Claim-Set Generator ### Issuer ## Messages This section describes the HTTP messages sent to and received from the Ledger Service. TODO: probably should define URL paths as well, not just verb, headers, body ### Claims Registration Request A Claims Registration Request is an HTTP `POST` message sent to the Ledger Service with the `Content-Type: application/cose` header and the body being the Signed Claims to register. Signed Claims are represented as a tagged `COSE_Sign1` message. The COSE protected header must contain the following parameters: - alg (label: `1`): Asymmetric signature algorithm as integer, for example `-35` for ECDSA with SHA-384, see [COSE Algorithms registry](https://www.iana.org/assignments/cose/cose.xhtml) - payload type (label: `3`): Media type of claims as string, for example `application/spdx+cbor` - issuer (label: `258`, to be registered): DID of the signer as string, for example `did:web:example.com` Depending on the DID method the protected header must contain one or more of the following parameters: - kid (label: `4`): Key identifier as a UTF-8 string encoded as a byte string, required for `did:web` In CDDL notation, the Signed Claims message is defined as follows: ``` Signed_Claims = COSE_Sign1_Tagged COSE_Sign1_Tagged = #6.18(COSE_Sign1) COSE_Sign1 = [ protected : bstr .cbor Protected_Header, unprotected : {}, ; not used, hence an empty map payload : bstr, signature : bstr ] Protected_Header = { ; mandatory 1 => int ; algorithm identifier 3 => tstr ; payload type 258 => tstr ; DID of issuer ; mandatory depending on DID method ? 4 => bstr ; key identifier ? 33 => COSE_X509 ; X.509 certificate chain, excluding Root CA certificate } COSE_X509 = bstr / [ 2*certs: bstr ] ``` ### Claims Registration Response A Claims Registration Response is an HTTP message returned by the Ledger Service in response to a Claims Registration Request. There are multiple cases: - HTTP Status `201` - Registration was tentatively successful pending service consensus. - HTTP Status `400` - Registration was unsuccessful. - Error code `AwaitingDIDResolutionTryLater` - Error code `InvalidInput` The `201` response contains the `Location` HTTP header to request the Claims Registration Receipt at the given URL. The `400` response has a `Content-Type: application/json` header and a body containing details about the error: ```json { "error": { "code": "<error code>", "message": "<message>" } } ``` `AwaitingDIDResolutionTryLater` means the service does not have an up-to-date DID document of the DID referenced in the Signed Claims but is performing or will perform a DID resolution after which the client may retry the request. The response may contain the HTTP header `Retry-After` to inform the client about the expected wait time. `InvalidInput` means either the Signed Claims message is syntactically malformed, violates the signing profile (e.g. signing algorithm), or has an invalid signature relative to the currently resolved DID document. ### Claims Registration Receipt Request A Claims Registration Receipt Request is an HTTP `GET` message sent to the Ledger Service. The request URL contains a transaction identifier and is returned in the Claims Registration Response. ### Claims Registration Receipt Response A Claims Registration Receipt Response is an HTTP message returned by the Ledger Service in response to a Claims Registration Receipt Request. There are multiple cases: - HTTP Status `200` - Registration was successful and the receipt is returned. - HTTP Status `400` - Transaction exists but does not correspond to a Registration Request. - Error code `TransactionMismatch` - HTTP Status `404` - Transaction is pending, unknown, or invalid. - Error code `TransactionPendingOrUnknown` - Error code `TransactionInvalid` The `200` response contains the Claims Registration Receipt in the body. The `400` and `404` responses return the error details as described earlier. The Claims Registration Receipt represents Registered Claims and is a CBOR document with the following elements: - version: Receipt format version as integer, currently `1`, maximum `23` - transaction id: Transaction ID corresponding to the receipt as string, informational - service key: Public key of the Ledger Service identity as a DER-encoded `SubjectPublicKeyInfo` structure ([RFC 5280 sec. 4.1](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1), [RFC 3279 sec. 2.3](https://datatracker.ietf.org/doc/html/rfc3279#section-2.3)) - signature: ECDSA with SHA-256 signature over the Merkle tree root hash, DER-encoded as described in [RFC 3279 sec. 2.2.3](https://datatracker.ietf.org/doc/html/rfc3279.html#section-2.2.3) - proof: Inclusion proof as an array of pairs (two-element array) where a pair contains the direction as boolean (`true` for left, `false` for right) and the SHA-256 hash as byte string - leaf: SHA-256 Merkle tree leaf hash as byte string - writeset: SHA-256 hash of the transaction write set as byte string (part of leaf data) - signed claims type: Media type of the Signed Claims envelope as string, currently always `application/cose` (part of leaf data) - signed claims: Signed Claims submitted to the Ledger Service as a byte string (part of leaf data) The CDDL of a Claims Registration Receipt is as follows: ``` Claims_Registration_Receipt = [ version : Version, transaction_id : tstr, service_key : bstr, signature : bstr, leaf : SHA_256, proof : bstr .cbor [+ ProofElement], writeset : SHA_256, signed_claims_type : tstr, ; always "application/cose" signed_claims : bstr ] Version = 1..23 ; represented as single byte in CBOR ProofElement = [ left : bool, hash : SHA_256 ] SHA_256 = bstr .size 32 ``` TODO: The receipt format relies on features that are quite CCF-specific, in particular a concept called "custom transaction claims" (covers `writeset` and the following custom fields). We could define that and propose it as a standard for other types of ledgers, but it may not be straight-forward. # Issuers and Guaranteed Properties ## Component Properties and End-to-End Properties You need sets of component properties to arrive at end-to-end properties. ### Integrity of the Ledger * Role of Confidential Compute * Roots of trusts * Redundant Byzantine Fault Tolerance * what does it mean to be faithful? * what does it mean to be slow? * what does it mean to be malicious? # CDDL See {{-coswid}}. ~~~~ CDDL <CODE BEGINS> ;{::include some.cddl} <CODE ENDS> ~~~~ # Privacy Considerations Privacy Considerations # Security Considerations Security Considerations # IANA Considerations See Body {{mybody}}. --- back # Mapping to RATS ~~~~ {::include scim-rats.ascii} ~~~~ Update