---
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