|
| 1 | +* Name: Version_Detection |
| 2 | +* Date: 2021-09-20 |
| 3 | +* Pull Request: [#NNNN](https://github.com/opencomputeproject/Security/pull/NNNN) |
| 4 | + |
| 5 | +# Objective |
| 6 | + |
| 7 | +Cerberus does not currently expose a particularly precise interface for |
| 8 | +discovering the version of a remote device being challenged or otherwise |
| 9 | +interacted with. However, Cerberus does make reference to these versions as part |
| 10 | +of the `CHALLENGE` message. |
| 11 | + |
| 12 | +Cerberus also has significant "optional" components, though there is no way to |
| 13 | +discover whether a remote device supports them. In theory this would be provided |
| 14 | +to a PA-RoT via a manifest, but it some cases it may be useful to query this |
| 15 | +information dynamically. |
| 16 | + |
| 17 | +This RFC describes: |
| 18 | +- A formal versioning scheme for the overall protocol, as well as its optional |
| 19 | + subcomponents. |
| 20 | +- A protocol command for querying this version information. |
| 21 | +- A way for vendors to allow for unambiguous querying of their vendor |
| 22 | + extensions. |
| 23 | +- A story for deprecation of commands. |
| 24 | + |
| 25 | +# Proposal |
| 26 | + |
| 27 | +Although Cerberus has some minor prior art around version numbers, we will be |
| 28 | +starting over from a clean slate. |
| 29 | + |
| 30 | +## Protocol Version Numbers |
| 31 | + |
| 32 | +A Cerberus version is a sixteen-bit opaque value, mapped to a commit hash of |
| 33 | +this repository. Protocol version N is described by the repository at that |
| 34 | +commit. |
| 35 | + |
| 36 | +Versions are recorded as Git tags with the name `protocol-v{#}`, where |
| 37 | +`{#}` is replaced with the version number. There will also be a file, |
| 38 | +`PROTOCOL_VERSIONS.md`, which contains a list of all versions, their dates, |
| 39 | +and a changelog, in the following format: |
| 40 | +``` |
| 41 | +# `protocol-v{#}` |
| 42 | +Date: YYYY-MM-DD |
| 43 | +<changelog> |
| 44 | +``` |
| 45 | + |
| 46 | +To create a new version: |
| 47 | +1. Create a commit that adds the new version to `PROTOCOL_VERSIONS.md`. |
| 48 | +2. The pull request created from that commit acts as an opportunity to discuss |
| 49 | + the new version and changelog. |
| 50 | +3. Once approved, the author must ensure the date on the new version matches. |
| 51 | +4. A maintainer will merge the PR, and then create a lightweight tag with the |
| 52 | + correct name pointing to the merged commit. This can be done via |
| 53 | + `git tag protocol-v{#} && git push origin --tags`. This must be a push to |
| 54 | + the upstream repository. |
| 55 | + |
| 56 | +This proposal does not stipulate guidelines under which creating a new version |
| 57 | +is recommended; maintainers should create new versions as they deem necessary. |
| 58 | + |
| 59 | +After this RFC is merged and implemented, a new version, version 0, must be |
| 60 | +created immediately. |
| 61 | + |
| 62 | +## Subcomponents |
| 63 | + |
| 64 | +A subcomponent is a set of optional Cerberus commands that need to be provided |
| 65 | +together, such as the PFM-related commands. Each subcomponent has a byte |
| 66 | +associated with it. |
| 67 | + |
| 68 | +The subcomponents, their identifying bytes, and the list of commands in each |
| 69 | +should be listed in a table, just past the list of all commands. All optional |
| 70 | +commands must be part of a subcomponent, and a command may be part of multiple |
| 71 | +components. |
| 72 | + |
| 73 | +## The `Protocol Version` Command |
| 74 | + |
| 75 | +We define a new command, `Protocol Version`, using command byte `0x05`, and |
| 76 | +marked as *required*. Its purpose is to negotiate a shared version for the |
| 77 | +devices to communicate over. |
| 78 | + |
| 79 | +A request has the following structure: |
| 80 | + |
| 81 | +```c |
| 82 | +struct ProtocolVersionRequest { |
| 83 | + uint8_t reserved; // Must be zero. |
| 84 | + |
| 85 | + uint16_t min_version; |
| 86 | + uint16_t max_version; |
| 87 | + |
| 88 | + uint8_t bad_versions_len; |
| 89 | + uint16_t bad_versions[bad_versions_len]; |
| 90 | + |
| 91 | + uint8_t extns_len; |
| 92 | + struct { |
| 93 | + uint8_t len; |
| 94 | + uint8_t name[len]; |
| 95 | + } extns[extns_len]; |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +The requester provides the minimum and maximum versions (inclusive) it |
| 100 | +understands, as well as a list of versions it refuses to use (for security |
| 101 | +or other reasons). It also provides a list of vendor-defined extensions it |
| 102 | +knows how to speak. |
| 103 | + |
| 104 | +Vendor-defined extensions are defined by strings, to |
| 105 | +avoid running into the usual "private use area" problems in code-point |
| 106 | +allocation. Vendors should choose strings that incorporate their name into them |
| 107 | +to avoid chances of collision. Period-separated names are ideal: |
| 108 | +- `widgetsinc.unsealing-with-chacha20` |
| 109 | +- `acmeco.fancy-pcie-update-scheme` |
| 110 | + |
| 111 | +The response looks like this: |
| 112 | + |
| 113 | +```c |
| 114 | +struct ProtocolVersionResponse { |
| 115 | + uint16_t version; |
| 116 | + |
| 117 | + uint8_t extns_len; |
| 118 | + uint16_t extn_versions[extns_len]; |
| 119 | +}; |
| 120 | +``` |
| 121 | + |
| 122 | +This provides the responder-chosen version, and the versions of the requested |
| 123 | +vendor-defined extensions. A version of `0xffff` is used as a sentinel to |
| 124 | +indicate that the extension was unrecognized. |
| 125 | + |
| 126 | +All messages that follow must use the chosen version number. This number not |
| 127 | +only specifies which messages are supported, but also which format to use for |
| 128 | +parsing commands, since that may vary across versions. The `Protocol Version` |
| 129 | +command, however, is unversioned. A reserved byte is included at the top of |
| 130 | +the command in case we ever need to change it. |
| 131 | + |
| 132 | +A new error code, "Unnegotiated Version" (code `0x05`), should be returned by |
| 133 | +devices if no version has been negotiated yet with the requesting device. |
| 134 | +Requesters which had previously negotiated a version, but which recieve this |
| 135 | +message, should re-negotiate a version. |
| 136 | + |
| 137 | +## Updates to `CHALLENGE` |
| 138 | + |
| 139 | +Because only a single protocol version is negotiated, we can replace the version |
| 140 | +range in the `CHALLENGE` with the single negotiated version. This doesn't change |
| 141 | +the layout of the `CHALLENGE` in a meaningful way, since we are replacing two |
| 142 | +eight-bit fields with one sixteen-bit field. |
| 143 | + |
| 144 | +## Evolution and Deprecation Process |
| 145 | + |
| 146 | +This versioning scheme gives us a way to freely evolve the protocol without |
| 147 | +fear of subtle incompatibility: because one version is chosen, there is no |
| 148 | +ambiguity about different layouts of commands. |
| 149 | + |
| 150 | +We also get deprecation for free: if we remove a message, devices can, given |
| 151 | +sufficiently wide range of advertised versions, select a version both are |
| 152 | +can work with. We can even re-use command bytes across versions, if that ever |
| 153 | +becomes a problem. |
| 154 | + |
| 155 | +There is no particular reason to mark messages as deprecated in the spec itself, |
| 156 | +although it may be worthwhile to do so to indicate that they will eventually be |
| 157 | +removed. Whether to leave messages deprecated for a version or two, or to remove |
| 158 | +them immediately, is up to the maintainers. |
| 159 | + |
| 160 | +This introduces the risk that two devices may refuse to interoperate due to |
| 161 | +incompatible versions. It is up to implementers to chose a sufficiently large |
| 162 | +range of versions to interoperate with other vendors' devices. |
| 163 | + |
| 164 | +# Specification Changelist |
| 165 | + |
| 166 | +The following changes are required: |
| 167 | +- The creation of `PROTOCOL_VERSIONS.md` as described above. |
| 168 | +- Prose in a section immediately before the `RoT Commands` section that |
| 169 | + describes the Cerberus Protocol versioning scheme, including protocol |
| 170 | + subcomponents and vendor-defined extensions. |
| 171 | +- A table immediately after the table of all commands, which defines the |
| 172 | + protocol subcomponents. |
| 173 | +- Add the new error code to the error codes table. |
| 174 | +- A new message definition, after `Device Information`, for the new `Protocol |
| 175 | + Version` command. This shall include prose of the negotiation process. |
| 176 | +- The min/max version fields in the `CHALLENGE` should be replaced with the |
| 177 | + single negotiated version. |
| 178 | + |
| 179 | +# Implementation Guidance |
| 180 | + |
| 181 | +Implementers which support a range of Cerberus versions will need to maintain a |
| 182 | +"currently negotiated version" for each bus they can service requests from. |
| 183 | +This should not be a significant cost, given they already need to maintain |
| 184 | +similar information for sessions. |
| 185 | + |
| 186 | +Because requesters must know how to re-establish a negotiated version, an |
| 187 | +implementer can choose to record only a single version at a time. |
| 188 | + |
| 189 | +# Alternatives Considered |
| 190 | + |
| 191 | +An alternative is to have requester-chosen, rather than responder-chosen, |
| 192 | +versions. This doesn't have any specific benefits for us, but it does have the |
| 193 | +downside that we need to deal with different versions having different layouts |
| 194 | +for commands, meaning that the requester still needs to inform the responder |
| 195 | +about which protocol version it wishes to use. |
| 196 | + |
| 197 | +This could be worked around by being careful about how commands are evolved, but |
| 198 | +it's likely to be rare enough that command formats change that the complexity |
| 199 | +would be worth it. |
| 200 | + |
| 201 | +# Future Work |
| 202 | + |
| 203 | +This RFC does not describe norms and practices around when to mint versions nor |
| 204 | +when to make the actual decision of deprecation; these are left up to the |
| 205 | +maintainers or a potential future RFC. |
0 commit comments