From 64f5902c27737ec3f99305e493f7639307ef6db7 Mon Sep 17 00:00:00 2001 From: Miguel Young de la Sota <mcyoung@google.com> Date: Mon, 20 Sep 2021 13:30:00 -0400 Subject: [PATCH] Propose an RFC for version negotiation in Cerberus --- 0003-Version_Detection.md | 205 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 0003-Version_Detection.md diff --git a/0003-Version_Detection.md b/0003-Version_Detection.md new file mode 100644 index 0000000..66e361c --- /dev/null +++ b/0003-Version_Detection.md @@ -0,0 +1,205 @@ +* Name: Version_Detection +* Date: 2021-09-20 +* Pull Request: [#23](https://github.com/opencomputeproject/Security/pull/23) + +# Objective + +Cerberus does not currently expose a particularly precise interface for +discovering the version of a remote device being challenged or otherwise +interacted with. However, Cerberus does make reference to these versions as part +of the `CHALLENGE` message. + +Cerberus also has significant "optional" components, though there is no way to +discover whether a remote device supports them. In theory this would be provided +to a PA-RoT via a manifest, but it some cases it may be useful to query this +information dynamically. + +This RFC describes: +- A formal versioning scheme for the overall protocol, as well as its optional + subcomponents. +- A protocol command for querying this version information. +- A way for vendors to allow for unambiguous querying of their vendor + extensions. +- A story for deprecation of commands. + +# Proposal + +Although Cerberus has some minor prior art around version numbers, we will be +starting over from a clean slate. + +## Protocol Version Numbers + +A Cerberus version is a sixteen-bit opaque value, mapped to a commit hash of +this repository. Protocol version N is described by the repository at that +commit. + +Versions are recorded as Git tags with the name `protocol-v{#}`, where +`{#}` is replaced with the version number. There will also be a file, +`PROTOCOL_VERSIONS.md`, which contains a list of all versions, their dates, +and a changelog, in the following format: +``` +# `protocol-v{#}` +Date: YYYY-MM-DD +<changelog> +``` + +To create a new version: +1. Create a commit that adds the new version to `PROTOCOL_VERSIONS.md`. +2. The pull request created from that commit acts as an opportunity to discuss + the new version and changelog. +3. Once approved, the author must ensure the date on the new version matches. +4. A maintainer will merge the PR, and then create a lightweight tag with the + correct name pointing to the merged commit. This can be done via + `git tag protocol-v{#} && git push origin --tags`. This must be a push to + the upstream repository. + +This proposal does not stipulate guidelines under which creating a new version +is recommended; maintainers should create new versions as they deem necessary. + +After this RFC is merged and implemented, a new version, version 0, must be +created immediately. + +## Subcomponents + +A subcomponent is a set of optional Cerberus commands that need to be provided +together, such as the PFM-related commands. Each subcomponent has a byte +associated with it. + +The subcomponents, their identifying bytes, and the list of commands in each +should be listed in a table, just past the list of all commands. All optional +commands must be part of a subcomponent, and a command may be part of multiple +components. + +## The `Protocol Version` Command + +We define a new command, `Protocol Version`, using command byte `0x05`, and +marked as *required*. Its purpose is to negotiate a shared version for the +devices to communicate over. + +A request has the following structure: + +```c +struct ProtocolVersionRequest { + uint8_t reserved; // Must be zero. + + uint16_t min_version; + uint16_t max_version; + + uint8_t bad_versions_len; + uint16_t bad_versions[bad_versions_len]; + + uint8_t extns_len; + struct { + uint8_t len; + uint8_t name[len]; + } extns[extns_len]; +} +``` + +The requester provides the minimum and maximum versions (inclusive) it +understands, as well as a list of versions it refuses to use (for security +or other reasons). It also provides a list of vendor-defined extensions it +knows how to speak. + +Vendor-defined extensions are defined by strings, to +avoid running into the usual "private use area" problems in code-point +allocation. Vendors should choose strings that incorporate their name into them +to avoid chances of collision. Period-separated names are ideal: +- `widgetsinc.unsealing-with-chacha20` +- `acmeco.fancy-pcie-update-scheme` + +The response looks like this: + +```c +struct ProtocolVersionResponse { + uint16_t version; + + uint8_t extns_len; + uint16_t extn_versions[extns_len]; +}; +``` + +This provides the responder-chosen version, and the versions of the requested +vendor-defined extensions. A version of `0xffff` is used as a sentinel to +indicate that the extension was unrecognized. + +All messages that follow must use the chosen version number. This number not +only specifies which messages are supported, but also which format to use for +parsing commands, since that may vary across versions. The `Protocol Version` +command, however, is unversioned. A reserved byte is included at the top of +the command in case we ever need to change it. + +A new error code, "Unnegotiated Version" (code `0x05`), should be returned by +devices if no version has been negotiated yet with the requesting device. +Requesters which had previously negotiated a version, but which recieve this +message, should re-negotiate a version. + +## Updates to `CHALLENGE` + +Because only a single protocol version is negotiated, we can replace the version +range in the `CHALLENGE` with the single negotiated version. This doesn't change +the layout of the `CHALLENGE` in a meaningful way, since we are replacing two +eight-bit fields with one sixteen-bit field. + +## Evolution and Deprecation Process + +This versioning scheme gives us a way to freely evolve the protocol without +fear of subtle incompatibility: because one version is chosen, there is no +ambiguity about different layouts of commands. + +We also get deprecation for free: if we remove a message, devices can, given +sufficiently wide range of advertised versions, select a version both are +can work with. We can even re-use command bytes across versions, if that ever +becomes a problem. + +There is no particular reason to mark messages as deprecated in the spec itself, +although it may be worthwhile to do so to indicate that they will eventually be +removed. Whether to leave messages deprecated for a version or two, or to remove +them immediately, is up to the maintainers. + +This introduces the risk that two devices may refuse to interoperate due to +incompatible versions. It is up to implementers to chose a sufficiently large +range of versions to interoperate with other vendors' devices. + +# Specification Changelist + +The following changes are required: +- The creation of `PROTOCOL_VERSIONS.md` as described above. +- Prose in a section immediately before the `RoT Commands` section that + describes the Cerberus Protocol versioning scheme, including protocol + subcomponents and vendor-defined extensions. +- A table immediately after the table of all commands, which defines the + protocol subcomponents. +- Add the new error code to the error codes table. +- A new message definition, after `Device Information`, for the new `Protocol + Version` command. This shall include prose of the negotiation process. +- The min/max version fields in the `CHALLENGE` should be replaced with the + single negotiated version. + +# Implementation Guidance + +Implementers which support a range of Cerberus versions will need to maintain a +"currently negotiated version" for each bus they can service requests from. +This should not be a significant cost, given they already need to maintain +similar information for sessions. + +Because requesters must know how to re-establish a negotiated version, an +implementer can choose to record only a single version at a time. + +# Alternatives Considered + +An alternative is to have requester-chosen, rather than responder-chosen, +versions. This doesn't have any specific benefits for us, but it does have the +downside that we need to deal with different versions having different layouts +for commands, meaning that the requester still needs to inform the responder +about which protocol version it wishes to use. + +This could be worked around by being careful about how commands are evolved, but +it's likely to be rare enough that command formats change that the complexity +would be worth it. + +# Future Work + +This RFC does not describe norms and practices around when to mint versions nor +when to make the actual decision of deprecation; these are left up to the +maintainers or a potential future RFC.