Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 1 | // Copyright 2021 The Pigweed Authors |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| 4 | // use this file except in compliance with the License. You may obtain a copy of |
| 5 | // the License at |
| 6 | // |
| 7 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | // License for the specific language governing permissions and limitations under |
| 13 | // the License. |
Ali Zhang | f5eba29 | 2021-08-24 17:26:50 -0700 | [diff] [blame] | 14 | // |
| 15 | // Implementation of metadata formats specified in TUF Specification. |
| 16 | // See https://theupdateframework.github.io/specification/latest/ |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 17 | |
| 18 | syntax = "proto3"; |
| 19 | |
Zihan Chen | 0128d25 | 2021-09-23 00:24:14 -0700 | [diff] [blame] | 20 | package pw.software_update; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 21 | |
| 22 | import "google/protobuf/timestamp.proto"; |
| 23 | |
| 24 | // Metadata for a particular TUF role (e.g. targets metadata). |
| 25 | // Was TufMetadata |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 26 | message SignedRootMetadata { |
| 27 | // Serialized RootMetadata message that is the data portion of the metadata. |
| 28 | bytes serialized_root_metadata = 1; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 29 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 30 | // Signature of the canonical form of the role's serialized metadata |
| 31 | // (serialized_root_metadata). |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 32 | repeated Signature signatures = 2; |
| 33 | } |
| 34 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 35 | message SignedTimestampMetadata { |
| 36 | // Serialized TimestampMetadata message that is the data portion of the |
| 37 | // metadata. |
| 38 | bytes serialized_timestamp_metadata = 1; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 39 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 40 | // Signature of the canonical form of the role's serialized metadata |
| 41 | // (serialized_timestamp_metadata). |
| 42 | repeated Signature signatures = 2; |
| 43 | } |
| 44 | |
| 45 | message SignedSnapshotMetadata { |
| 46 | // Serialized SnapshotMetadata message that is the data portion of the |
| 47 | // metadata. |
| 48 | bytes serialized_snapshot_metadata = 1; |
| 49 | |
| 50 | // Signature of the canonical form of the role's serialized metadata |
| 51 | // (serialized_snapshot_metadata). |
| 52 | repeated Signature signatures = 2; |
| 53 | } |
| 54 | |
| 55 | message SignedTargetsMetadata { |
| 56 | // Serialized TargetsMetadata message that is the data portion of the |
| 57 | // metadata. |
| 58 | bytes serialized_targets_metadata = 1; |
| 59 | |
| 60 | // Signature of the canonical form of the role's serialized metadata |
| 61 | // (serialized_targets_metadata). |
| 62 | repeated Signature signatures = 2; |
| 63 | } |
| 64 | |
| 65 | message CommonMetadata { |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 66 | // Version number of the TUF Specification. |
| 67 | // Follows the Semantic Versioning 2.0.0 (semver) format. Metadata is |
| 68 | // written according to this version, and clients MUST verify that |
| 69 | // "spec_version" matches the expected version number. |
| 70 | // E.g. "1.0.0". |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 71 | string spec_version = 1; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 72 | |
| 73 | // Metadata file version. |
| 74 | // Clients MUST NOT replace a metadata file with a version number less than |
| 75 | // the one currently trusted. |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 76 | uint32 version = 2; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 77 | |
| 78 | // Expiration time for the metadata. |
| 79 | // Indicates when this metadata should be considered expired and no longer |
| 80 | // trusted by clients. Notice the TUF Specification defines this as a JSON |
| 81 | // string following the ISO 8601 standard. The expected format of the date and |
| 82 | // time string is "YYYY-MM-DDTHH:MM:SSZ". Time is always in UTC, and the "Z" |
| 83 | // time zone designator is attached to indicate a zero UTC offset. |
| 84 | // E.g. "2030-08-26T16:48:27Z". |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 85 | optional google.protobuf.Timestamp expires = 3; |
Ali Zhang | d7977a4 | 2021-10-19 16:40:18 -0700 | [diff] [blame] | 86 | |
| 87 | // Role type for the metadata. |
| 88 | // Indicates the type of the metadata. Valid values are 'root', 'targets', |
| 89 | // 'snapshot' and 'timestamp' as defined in the TUF spec, though we don't |
| 90 | // plan to support 'mirrors'. |
| 91 | // |
| 92 | // This field serves as a "magic code" that identifies a particular type of |
| 93 | // a metadata. During verification, the client is expected to check this |
| 94 | // field against the expected role type immediately after verifying the |
| 95 | // signatures of a metadata. This can be considered a "confidence booster" |
| 96 | // in the absence of canonical protobuf -- i.e. it makes the various |
| 97 | // `serialized_x_metadata` fields more tamper resistant. |
| 98 | optional string role = 4; |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 99 | } |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 100 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 101 | // This content is signed. |
| 102 | message RootMetadata { |
| 103 | CommonMetadata common_metadata = 1; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 104 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 105 | // Whether the repo supports consistent snapshots. If the repo has frequent |
| 106 | // updates, you should set this to true. |
| 107 | bool consistent_snapshot = 2; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 108 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 109 | // Map from Keyid to Key. |
| 110 | // Keyid is a unique identifier that identifies a cryptographic key. |
| 111 | // Contains all of cryptographic keys used by this repository. |
| 112 | repeated KeyMapping keys = 3; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 113 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 114 | // KeyConfig is the list of keys use for a particular role and the threshold. |
| 115 | // Threshold is number of keys of that role whose signatures are required in |
| 116 | // order to consider a file as being properly signed by that role. |
| 117 | SignatureRequirement root_signature_requirement = 4; |
| 118 | SignatureRequirement timestamp_signature_requirement = 5; |
| 119 | SignatureRequirement snapshot_signature_requirement = 6; |
Ali Zhang | ad362b1 | 2021-09-23 16:30:28 -0700 | [diff] [blame] | 120 | SignatureRequirement targets_signature_requirement = 7; |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 121 | |
| 122 | // This is NOT a part of the TUF Specification. |
| 123 | reserved 8 to 31; // Reserved for TUF Specification changes. |
| 124 | |
| 125 | reserved 32 to 64; // Reserved for future Pigweed usage. |
| 126 | |
| 127 | reserved 65 to 255; // Reserved for project-specific usage. |
| 128 | } |
| 129 | |
David Rogers | 7b35742 | 2021-09-08 18:32:53 -0700 | [diff] [blame] | 130 | // The timestamp role is used for freshness check of the snapshot. Any |
| 131 | // project-specific update metadata should go in the top-level targets_metadata |
| 132 | // or with the TargetFile information |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 133 | message TimestampMetadata { |
| 134 | CommonMetadata common_metadata = 1; |
| 135 | |
| 136 | // Only one snapshot_metadata is used per timestamp. |
| 137 | MetadataFile snapshot_metadata = 2; |
| 138 | |
| 139 | // This is NOT a part of the TUF Specification. |
| 140 | reserved 3 to 31; // Reserved for TUF Specification changes. |
| 141 | |
| 142 | reserved 32 to 64; // Reserved for future Pigweed usage. |
| 143 | |
| 144 | reserved 65 to 255; // Reserved for project-specific usage. |
| 145 | } |
| 146 | |
David Rogers | 7b35742 | 2021-09-08 18:32:53 -0700 | [diff] [blame] | 147 | // The snapshot role is used to ensure that the collection of targets_metadata |
| 148 | // files is securely consistent (no target metadata mix and match). Any |
| 149 | // project-specific update metadata should go in the top-level targets_metadata |
| 150 | // or with the TargetFile information |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 151 | message SnapshotMetadata { |
| 152 | CommonMetadata common_metadata = 1; |
| 153 | |
| 154 | // Map from Target metadata file name to MetadataFile. |
| 155 | // File name can be an arbitrary name or a full file name with relative path. |
| 156 | // This map should contain an entry for the top level targets role and all |
| 157 | // delegated roles. |
| 158 | repeated MetadataFile targets_metadata = 2; |
| 159 | |
| 160 | // This is NOT a part of the TUF Specification. |
| 161 | reserved 3 to 31; // Reserved for TUF Specification changes. |
| 162 | |
| 163 | reserved 32 to 64; // Reserved for future Pigweed usage. |
| 164 | |
| 165 | reserved 65 to 255; // Reserved for project-specific usage. |
| 166 | } |
| 167 | |
David Rogers | 7b35742 | 2021-09-08 18:32:53 -0700 | [diff] [blame] | 168 | // The targets role describes the target files that comprise the software |
| 169 | // update. Targets metadata is organized in to a top-level targets metadata file |
| 170 | // and optional multiple deligated targets metadata files |
| 171 | // |
| 172 | // The top-level targets metatdata is the correct place to put any |
| 173 | // project-specific build version information, including build ID, hardware rev, |
| 174 | // etc. |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 175 | message TargetsMetadata { |
| 176 | CommonMetadata common_metadata = 1; |
| 177 | |
| 178 | // Collection of target file information |
| 179 | repeated TargetFile target_files = 2; |
| 180 | // Target file name can be an arbitrary name or a path that describes where |
| 181 | // the file lives relative to the base directory of the repository, e.g. |
| 182 | // "path/to/amber_tools/0". |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 183 | |
David Rogers | 7b35742 | 2021-09-08 18:32:53 -0700 | [diff] [blame] | 184 | // TODO: When it is time to support delegation, add delegation information |
| 185 | // here. |
| 186 | |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 187 | // This is NOT a part of the TUF Specification. |
| 188 | reserved 9 to 31; // Reserved for TUF Specification changes. |
| 189 | |
| 190 | reserved 32 to 64; // Reserved for future Pigweed usage. |
| 191 | |
| 192 | reserved 65 to 255; // Reserved for project-specific usage. |
| 193 | } |
| 194 | |
| 195 | message Signature { |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 196 | // Identifier of the key, which is bytes of the SHA-256 hash of the |
| 197 | // canonical form of the key. |
| 198 | bytes key_id = 1; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 199 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 200 | // The signature of the canonical form of the role's serialized metadata |
| 201 | // (serialized_{root,timestamp,snapshot,targets}_metadata). |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 202 | bytes sig = 2; |
| 203 | } |
| 204 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 205 | message KeyMapping { |
| 206 | // Identifier of the key, which is bytes of the SHA-256 hash of the |
| 207 | // canonical form of the key. |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 208 | bytes key_id = 1; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 209 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 210 | // Cryptographic key |
| 211 | Key key = 2; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 212 | } |
| 213 | |
| 214 | // Identifies an asymmetric cryptographic key. |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 215 | message Key { |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 216 | // Denotes a public key signature system, such as RSA or ECDSA. |
| 217 | KeyType key_type = 1; |
| 218 | |
| 219 | // Denotes the signature scheme corresponding to the key type. For example: |
| 220 | // "rsassa-pss-sha256" or "ecdsa-sha2-nistp256". |
| 221 | KeyScheme scheme = 2; |
| 222 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 223 | // Stores the serialized public key for this cryptographic algorithm. |
| 224 | bytes keyval = 3; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 225 | } |
| 226 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 227 | // The set of cryptographic keys used by a specific role. For example, list of |
| 228 | // key_ids used by the top level role "root". |
| 229 | message SignatureRequirement { |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 230 | // Set of Keyid's. |
| 231 | // Keyid is a unique identifier that identifies a cryptographic key. |
| 232 | // E.g. "f2d5020d08aea06a0a9192eb6a4f549e17032ebefa1aa9ac167c1e3e727930d6". |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 233 | repeated bytes key_ids = 1; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 234 | |
| 235 | // Threshold of signatures required to trust given file. |
| 236 | // In other words; the number of keys of that role whose signatures are |
| 237 | // required in order to consider a file as being properly signed by that role. |
| 238 | uint32 threshold = 2; |
| 239 | } |
| 240 | |
| 241 | enum HashFunction { |
| 242 | // Never use this in any TUF metadata. |
| 243 | UNKNOWN_HASH_FUNCTION = 0; |
| 244 | |
| 245 | SHA256 = 1; |
| 246 | } |
| 247 | |
| 248 | message Hash { |
| 249 | HashFunction function = 1; |
| 250 | // Digest of the cryptographic hash function computed on the target file. |
| 251 | bytes hash = 2; |
| 252 | } |
| 253 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 254 | // Descriptor for a file stored in this repository. Linked to from target |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 255 | // metadata. |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 256 | message TargetFile { |
| 257 | // Target file name can be an arbitrary name or a path that describes where |
| 258 | // the file lives relative to the base directory of the repository, e.g. |
| 259 | // "path/to/amber_tools/0". |
| 260 | string file_name = 1; |
| 261 | |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 262 | // Size of the target file (element payload) in bytes. This the size as stored |
| 263 | // in the bundle. The final applied size can be different due to optional |
| 264 | // compression. |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 265 | uint64 length = 2; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 266 | |
| 267 | // Map from algorithm name to Hash. |
| 268 | // Algorithm name is the name of a cryptographic hash function. E.g. "sha256". |
| 269 | // The Hash string is the hex digest of the cryptographic function computed on |
| 270 | // the target file. E.g. |
| 271 | // "65b8c67f51c993d898250f40aa57a317d854900b3a04895464313e48785440da". |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 272 | repeated Hash hashes = 3; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 273 | |
| 274 | // This is NOT a part of the TUF Specification. |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 275 | reserved 4 to 15; // Reserved for TUF Specification changes. |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 276 | |
| 277 | reserved 16 to 31; // Reserved for future Pigweed usage. |
| 278 | |
| 279 | reserved 32 to 255; // Reserved for future project-specific usage. |
| 280 | } |
| 281 | |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 282 | message MetadataFile { |
| 283 | // Target file name can be an arbitrary name or a path that describes where |
| 284 | // the file lives relative to the base directory of the repository, e.g. |
David Rogers | 7b35742 | 2021-09-08 18:32:53 -0700 | [diff] [blame] | 285 | // "path/to/target/0". |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 286 | optional string file_name = 1; |
| 287 | |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 288 | // Metadata file version. E.g. 3. |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 289 | uint32 version = 2; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 290 | |
| 291 | // Size of the target file in bytes. |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 292 | optional uint64 length = 3; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 293 | |
| 294 | // Map from algorithm name to Hash. |
| 295 | // Algorithm name is the name of a cryptographic hash function. E.g. "sha256". |
| 296 | // The Hash is the hex digest of the cryptographic function computed on the |
| 297 | // target file. E.g. |
| 298 | // "65b8c67f51c993d898250f40aa57a317d854900b3a04895464313e48785440da". |
David Rogers | 633d678 | 2021-08-28 12:04:47 -0700 | [diff] [blame] | 299 | repeated Hash hashes = 4; |
Zihan Chen | a6325cd | 2021-08-24 06:23:37 -0700 | [diff] [blame] | 300 | } |
| 301 | |
| 302 | enum KeyType { |
| 303 | // Never use this in any TUF metadata. |
| 304 | UNKNOWN_KEY_TYPE = 0; |
| 305 | |
| 306 | RSA = 1; |
| 307 | |
| 308 | ED25519 = 2; |
| 309 | |
| 310 | ECDSA_SHA2_NISTP256 = 3; |
| 311 | } |
| 312 | |
| 313 | enum KeyScheme { |
| 314 | // Never use this in any TUF metadata. |
| 315 | UNKNOWN_KEY_SCHEME = 0; |
| 316 | |
| 317 | // RSA Probabilistic signature scheme with appendix. |
| 318 | // The underlying hash function is SHA256. |
| 319 | // In TUF Specification, this is referred to as "rsassa-pss-sha256". |
| 320 | RSASSA_PSS_SHA256_SCHEME = 1; |
| 321 | |
| 322 | // Elliptic Curve digital signature algorithm based on Twisted Edwards curves. |
| 323 | // See https://ed25519.cr.yp.to/. |
| 324 | // In TUF Specification, it is referred to as "ed25519". |
| 325 | ED25519_SCHEME = 2; |
| 326 | |
| 327 | // Elliptic Curve Digital Signature Algorithm with NIST P-256 curve signing |
| 328 | // and SHA-256 hashing. See |
| 329 | // https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm In |
| 330 | // TUF Specification, it is referred to as "ecdsa-sha2-nistp256". |
| 331 | ECDSA_SHA2_NISTP256_SCHEME = 3; |
| 332 | } |