diff --git a/docs/tuf-spec.txt b/docs/tuf-spec.txt index c10e9563..37653350 100644 --- a/docs/tuf-spec.txt +++ b/docs/tuf-spec.txt @@ -1,6 +1,6 @@ The Update Framework Specification -7 October 2016 +23 May 2017 Version 1.0 (Draft) 1. Introduction @@ -9,6 +9,10 @@ Version 1.0 (Draft) This document describes a framework for securing software update systems. + The keywords "MUST," "MUST NOT," "REQUIRED," "SHALL," "SHALL NOT," "SHOULD," + "SHOULD NOT," "RECOMMENDED," "MAY," and "OPTIONAL" in this document are to be + interpreted as described in RFC 2119. + 1.2. Motivation Software is commonly updated through software update systems. These systems @@ -74,7 +78,7 @@ Version 1.0 (Draft) The framework will not have the responsibility of deciding on the correct course of action in all error situations, such as those that can occur when - certain attacks are being performed. Instead, the framework will provide + certain attacks are being performed. Instead, the framework will provide the software update system the relevant information about any errors that require security decisions which are situation-specific. How those errors are handled is up to the software update system. @@ -134,31 +138,31 @@ Version 1.0 (Draft) the client system. That is, an attacker can provide arbitrary files in response to download requests and the files will not be detected as illegitimate. - + Endless data attacks. Attackers should not be able to respond to client requests with huge amounts of data (extremely large files) that interfere with the client's system. - + Extraneous dependencies attacks. Attackers should not be able to cause clients to download or install software dependencies that are not the intended dependencies. - + Fast-forward attacks. An attacker arbitrarily increases the version numbers - of project metadata files in the snapshot metadata well beyond the current + of project metadata files in the snapshot metadata well beyond the current value, thus tricking a software update system into thinking any subsequent updates are trying to rollback the package to a previous, out-of-date version. In some situations, such as those where there is a maximum possible version number, the perpetrator could use a number so high that the system would never be able to match it with the one in the snapshot metadata, and thus new updates could never be downloaded. - + Indefinite freeze attacks. Attackers should not be able to respond to client requests with the same, outdated metadata without the client being aware of the problem. - + Malicious mirrors preventing updates. Repository mirrors should be unable to prevent updates from good mirrors. - + Mix-and-match attacks. Attackers should not be able to trick clients into using a combination of metadata that never existed together on the repository at the same time. @@ -170,7 +174,7 @@ Version 1.0 (Draft) Slow retrieval attacks. Attackers should not be able to prevent clients from being aware of interference with receiving updates by responding to client requests so slowly that automated updates never complete. - + Vulnerability to key compromises. An attacker who is able to compromise a single key or less than a given threshold of keys can compromise clients. This includes relying on a single online key (such as only being protected @@ -207,7 +211,7 @@ Version 1.0 (Draft) the file. As providing additional information about target files may be important to some software update systems using the framework, additional arbitrary information can be provided with any target - file. This information will be included in signed metadata that describes + file. This information will be included in signed metadata that describes the target files. The following are the high-level steps of using the framework from the @@ -277,7 +281,7 @@ Version 1.0 (Draft) (that is, another set of keys and the threshold required for trust) is trusted to sign target file metadata. Partial trust delegation is when the delegated role is only trusted for some of the target files that the - delegating role is trusted for. + delegating role is trusted for. Delegated developer roles can further delegate trust to other delegated roles. This provides for multiple levels of trust delegation where each @@ -415,7 +419,7 @@ Version 1.0 (Draft) provides one signed metadata file. As is the case with the directory structure of top-level metadata, the delegated files are relative to the base URL of metadata available from a given repository mirror. - + A delegated role file is located at: /DELEGATED_ROLE.json @@ -425,7 +429,7 @@ Version 1.0 (Draft) named ANOTHER_ROLE, that role's signed metadata file is made available at: /ANOTHER_ROLE.json - + 4. Document formats All of the formats described below include the ability to add more @@ -443,7 +447,7 @@ Version 1.0 (Draft) 4.2. File formats: general principles All signed metadata objects have the format: - + { "signed" : ROLE, "signatures" : [ { "keyid" : KEYID, @@ -460,18 +464,18 @@ Version 1.0 (Draft) The current reference implementation of TUF defines two signing methods, although TUF is not restricted to any particular key signing method, key type, or cryptographic library: - + "RSASSA-PSS" : RSA Probabilistic signature scheme with appendix. The underlying hash function is SHA256. - + "ed25519" : Elliptic curve digital signature algorithm based on Twisted Edwards curves. - - RSASSA-PSS: https://tools.ietf.org/html/rfc3447#page-29 + + RSASSA-PSS: https://tools.ietf.org/html/rfc3447#page-29 ed25519: https://ed25519.cr.yp.to/ - + All keys have the format: - + { "keytype" : KEYTYPE, "keyval" : KEYVAL } @@ -480,9 +484,9 @@ Version 1.0 (Draft) KEYVAL. We define two keytypes at present: 'rsa' and 'ed25519'. - + The 'rsa' format is: - + { "keytype" : "rsa", "keyval" : { "public" : PUBLIC} } @@ -491,16 +495,16 @@ Version 1.0 (Draft) must be at least 2048 bits. The 'ed25519' format is: - + { "keytype" : "ed25519", "keyval" : { "public" : PUBLIC} } where PUBLIC is a 32-byte string. - + The KEYID of a key is the hexdigest of the SHA-256 hash of the canonical JSON form of the key. - + Metadata date-time data follows the ISO 8601 standard. The expected format of the combined date and time string is "YYYY-MM-DDTHH:MM:SSZ". Time is always in UTC, and the "Z" time zone designator is attached to indicate a @@ -556,68 +560,68 @@ Version 1.0 (Draft) { "signatures": [ { - "keyid": "f2d5020d08aea06a0a9192eb6a4f549e17032ebefa1aa9ac167c1e3e727930d6", - "method": "ed25519", + "keyid": "f2d5020d08aea06a0a9192eb6a4f549e17032ebefa1aa9ac167c1e3e727930d6", + "method": "ed25519", "sig": "a312b9c3cb4a1b693e8ebac5ee1ca9cc01f2661c14391917dcb111517f72370809 f32c890c6b801e30158ac4efe0d4d87317223077784c7a378834249d048306" } - ], + ], "signed": { - "_type": "Root", - "consistent_snapshot": false, - "expires": "2030-01-01T00:00:00Z", + "_type": "Root", + "consistent_snapshot": false, + "expires": "2030-01-01T00:00:00Z", "keys": { "1a2b4110927d4cba257262f614896179ff85ca1f1353a41b5224ac474ca71cb4": { - "keytype": "ed25519", + "keytype": "ed25519", "keyval": { "public": "72378e5bc588793e58f81c8533da64a2e8f1565c1fcc7f253496394ffc52542c" } - }, + }, "93ec2c3dec7cc08922179320ccd8c346234bf7f21705268b93e990d5273a2a3b": { - "keytype": "ed25519", + "keytype": "ed25519", "keyval": { "public": "68ead6e54a43f8f36f9717b10669d1ef0ebb38cee6b05317669341309f1069cb" } - }, + }, "f2d5020d08aea06a0a9192eb6a4f549e17032ebefa1aa9ac167c1e3e727930d6": { - "keytype": "ed25519", + "keytype": "ed25519", "keyval": { "public": "66dd78c5c2a78abc6fc6b267ff1a8017ba0e8bfc853dd97af351949bba021275" } - }, + }, "fce9cf1cc86b0945d6a042f334026f31ed8e4ee1510218f198e8d3f191d15309": { - "keytype": "ed25519", + "keytype": "ed25519", "keyval": { "public": "01c61f8dc7d77fcef973f4267927541e355e8ceda757e2c402818dad850f856e" } } - }, + }, "roles": { "root": { "keyids": [ "f2d5020d08aea06a0a9192eb6a4f549e17032ebefa1aa9ac167c1e3e727930d6" - ], + ], "threshold": 1 - }, + }, "snapshot": { "keyids": [ "fce9cf1cc86b0945d6a042f334026f31ed8e4ee1510218f198e8d3f191d15309" - ], + ], "threshold": 1 - }, + }, "targets": { "keyids": [ "93ec2c3dec7cc08922179320ccd8c346234bf7f21705268b93e990d5273a2a3b" - ], + ], "threshold": 1 - }, + }, "timestamp": { "keyids": [ "1a2b4110927d4cba257262f614896179ff85ca1f1353a41b5224ac474ca71cb4" - ], + ], "threshold": 1 } - }, + }, "version": 1 } } @@ -648,7 +652,7 @@ Version 1.0 (Draft) METAPATH is the the metadata file's path on the repository relative to the metadata base URL. - + The HASHES and LENGTH are the hashes and length of the file, both of which are only specified for the root file. VERSION is listed for the root file and all other roles available on the repository. LENGTH is an integer. @@ -660,31 +664,31 @@ Version 1.0 (Draft) { "signatures": [ { - "keyid": "fce9cf1cc86b0945d6a042f334026f31ed8e4ee1510218f198e8d3f191d15309", - "method": "ed25519", + "keyid": "fce9cf1cc86b0945d6a042f334026f31ed8e4ee1510218f198e8d3f191d15309", + "method": "ed25519", "sig": "f7f03b13e3f4a78a23561419fc0dd741a637e49ee671251be9f8f3fceedfc112e4 4ee3aaff2278fad9164ab039118d4dc53f22f94900dae9a147aa4d35dcfc0f" } - ], + ], "signed": { - "_type": "Snapshot", - "expires": "2030-01-01T00:00:00Z", + "_type": "Snapshot", + "expires": "2030-01-01T00:00:00Z", "meta": { "root.json": { "hashes": { "sha256": "52bbb30f683d166fae5c366e4582cfe8212aacbe1b21ae2026dae58ec55d3701" - }, + }, "length": 1831, "version": 1 - }, + }, "targets.json": { "version": 1 - }, + }, "project.json": { "version": 1 - }, + }, } - }, + }, "version": 1 } @@ -734,7 +738,7 @@ Version 1.0 (Draft) "paths" : [ PATHPATTERN, ... ]) }, ... ] } - + ROLENAME is the full name of the delegated role. For example, "targets/projects" @@ -788,51 +792,51 @@ Version 1.0 (Draft) { "signatures": [ { - "keyid": "93ec2c3dec7cc08922179320ccd8c346234bf7f21705268b93e990d5273a2a3b", - "method": "ed25519", + "keyid": "93ec2c3dec7cc08922179320ccd8c346234bf7f21705268b93e990d5273a2a3b", + "method": "ed25519", "sig": "e9fd40008fba263758a3ff1dc59f93e42a4910a282749af915fbbea1401178e5a0 12090c228f06db1deb75ad8ddd7e40635ac51d4b04301fce0fd720074e0209" } - ], + ], "signed": { - "_type": "Targets", + "_type": "Targets", "delegations": { "keys": { "ce3e02e72980b09ca6f5efa68197130b381921e5d0675e2e0c8f3c47e0626bba": { - "keytype": "ed25519", + "keytype": "ed25519", "keyval": { "public": "b6e40fb71a6041212a3d84331336ecaa1f48a0c523f80ccc762a034c727606fa" } } - }, + }, "roles": [ { "keyids": [ "ce3e02e72980b09ca6f5efa68197130b381921e5d0675e2e0c8f3c47e0626bba" - ], - "name": "targets/project", + ], + "name": "targets/project", "paths": [ "/project/file3.txt" - ], + ], "threshold": 1 } ] - }, - "expires": "2030-01-01T00:00:00Z", + }, + "expires": "2030-01-01T00:00:00Z", "targets": { "/file1.txt": { "hashes": { "sha256": "65b8c67f51c993d898250f40aa57a317d854900b3a04895464313e48785440da" - }, + }, "length": 31 - }, + }, "/file2.txt": { "hashes": { "sha256": "452ce8308500d83ef44248d8e6062359211992fd837ea9e370e561efb1a4ca99" - }, + }, "length": 39 } - }, + }, "version": 1 } } @@ -864,24 +868,24 @@ Version 1.0 (Draft) { "signatures": [ { - "keyid": "1a2b4110927d4cba257262f614896179ff85ca1f1353a41b5224ac474ca71cb4", - "method": "ed25519", + "keyid": "1a2b4110927d4cba257262f614896179ff85ca1f1353a41b5224ac474ca71cb4", + "method": "ed25519", "sig": "90d2a06c7a6c2a6a93a9f5771eb2e5ce0c93dd580bebc2080d10894623cfd6eaed f4df84891d5aa37ace3ae3736a698e082e12c300dfe5aee92ea33a8f461f02" } - ], + ], "signed": { - "_type": "Timestamp", - "expires": "2030-01-01T00:00:00Z", + "_type": "Timestamp", + "expires": "2030-01-01T00:00:00Z", "meta": { "snapshot.json": { "hashes": { "sha256": "c14aeb4ac9f4a8fc0d83d12482b9197452f6adf3eb710e3b1e2b79e8d14cb681" - }, + }, "length": 1007, "version": 1 } - }, + }, "version": 1 } } @@ -928,61 +932,187 @@ Version 1.0 (Draft) 5.1. The client application - 1. The client application first instructs TUF to check for updates. + 0. **Load the previous root metadata file.** We assume that a good, trusted + copy of this file was shipped with the package manager / software updater + using an out-of-band process. - 2. TUF downloads and verifies timestamp.json. + 0.1. **Check signatures.** The previous root metadata file MUST have been + signed by a threshold of keys specified in the previous root metadata file. - 3. If timestamp.json indicates that snapshot.json has changed, TUF downloads - and verifies snapshot.json. + 0.2. Note that the expiration of the previous root metadata file does not + matter, because we will attempt to update it in the next step. - 4. TUF determines which metadata files listed in snapshot.json differ from - those described in the last snapshot.json that TUF has seen. If root.json - has changed, the update process starts over using the new root.json. + 1. **Update the root metadata file.** Since it may now be signed using + entirely different keys, the client must somehow be able to establish a + trusted line of continuity to the latest set of keys (see Section 6.1). To + do so, the client MUST download intermediate root metadata files, until the + latest available one is reached. - 5. TUF provides the software update system with a list of available files - according to targets.json. + 1.1. Let N denote the version number of the previous root metadata file. - 6. The software update system instructs TUF to download a specific target file. + 1.2. **Try downloading version N+1 of the root metadata file**, up to some + X number of bytes (because the size is unknown). The value for X is set by + the authors of the application using TUF. For example, X may be tens of + kilobytes. The filename used to download the root metadata file is of the + fixed form VERSION.FILENAME.EXT (e.g., 42.root.json). If this file is not + available, then go to step 1.8. - 7. TUF downloads and verifies the file and then makes the file available to the - software update system. + 1.3. **Check signatures.** Version N+1 of the root metadata file MUST have + been signed by: (1) a threshold of keys specified in the previous root + metadata file (version N), and (2) a threshold of keys specified in the + current root metadata file (version N+1). - Note: If at any point in the above procedure there is a problem (i.e., if - unexpired, signed, valid metadata cannot be retrieved from the repository), - the Root file is downloaded and the process is retried once more (and only - once to avoid an infinite loop). Optionally, the software update system - using the framework can decide how to proceed rather than automatically - downloading a new Root file. + 1.4. **Check for a rollback attack.** The version number of the previous + root metadata file must be less than or equal to the version number of this + root metadata file. Effectively, this means checking that the version + number signed in the current root metadata file is indeed N+1. + 1.5. **Check for a freeze attack.** The latest known time should be lower + than the expiration timestamp in the current root metadata file. - The client code instructs the framework to check for updates. The framework - downloads the timestamp.json file from a mirror and checks that the file is - properly signed by the timestamp role, is not expired, and is not older than - the last timestamp.json file retrieved. If the timestamp file lists the same - snapshot.json file as was previously seen, the client code is informed that no - updates are available and the update checking process stops. + 1.6. Set the previous to the current root metadata file. - If the snapshot.json file has changed, the framework downloads the file and - verifies that it is properly signed by the snapshot role, is not expired, has - a newer timestamp than the last snapshot.json file seen, and matches the - description (hashes and size) in the timestamp.json file. The framework then - checks which metadata files listed in snapshot.json differ from those - described in the last snapshot.json file the framework had seen. If the - root.json file has changed, the framework updates this (following the same - security measures as with the other files) and starts the process over. If - any other metadata files have changed, the framework downloads and checks - those. + 1.7. Repeat steps 1.1 to 1.6. - By comparing the trusted targets from the old trusted metadata with the new - metadata, the framework is able to determine which target files have - changed. The framework ensures that any targets described in delegated - targets files are allowed to be provided by the delegated role. + 1.8. **If the the timestamp and / or snapshot keys have been rotated, then + delete the previous timestamp and snapshot metadata files.** This is done + in order to recover from fast-forward attacks after the repository has been + compromised and recovered. A _fast-forward attack_ happens when attackers + arbitrarily increase the version numbers of: (1) the timestamp metadata, + (2) the snapshot metadata, and / or (3) the targets, or a delegated + targets, metadata file in the snapshot metadata. Please see [the submitted + Mercury + draft](https://ssl.engineering.nyu.edu/papers/kuppusamy_usenix_17.pdf) for + more details. - When the client code asks the framework to download a target file, the - framework downloads the file from (potentially trying multiple mirrors), - checks the downloaded file to ensure that it matches the information - described in the targets files, and then makes the file available to the - client code. + 2. **Download the timestamp metadata file**, up to Y number of bytes + (because the size is unknown.) The value for Y is set by the authors of the + application using TUF. For example, Y may be tens of kilobytes. The + filename used to download the timestamp metadata file is of the fixed form + FILENAME.EXT (e.g., timestamp.json). + + 2.1. **Check signatures.** The timestamp metadata file must have been + signed by a threshold of keys specified in the root metadata file. + + 2.2. **Check for a rollback attack.** The version number of the previous + timestamp metadata file, if any, must be less than or equal to the version + number of this timestamp metadata file. + + 2.3. **Check for a freeze attack.** The latest known time should be lower + than the expiration timestamp in this metadata file. + + 3. **Download and check the snapshot metadata file**, up to the number of + bytes specified in the timestamp metadata file. + If consistent snapshots are not used (see Section 7), then the filename + used to download the snapshot metadata file is of the fixed form + FILENAME.EXT (e.g., snapshot.json). + Otherwise, the filename is of the form VERSION.FILENAME.EXT (e.g., + 42.snapshot.json), where HASH is one of the hashes of the snapshot metadata + file listed in the timestamp metadata file. + In either case, the client MUST write the file to non-volatile storage as + FILENAME.EXT. + + 3.1. **Check against timestamp metadata.** The hashes, and version number + of this metadata file MUST match the timestamp metadata. + + 3.2. **Check signatures.** The snapshot metadata file MUST have been signed + by a threshold of keys specified in the previous root metadata file. + + 3.3. **Check for a rollback attack.** + + 3.3.1. Note that the previous snapshot metadata file may be checked for + authenticity, but its expiration does not matter for the following + purposes. + + 3.3.2. The version number of the previous snapshot metadata file, if any, + MUST be less than or equal to the version number of this snapshot metadata + file. + + 3.3.3. The version number of the targets metadata file, and all delegated + targets metadata files (if any), in the previous snapshot metadata file, if + any, MUST be less than or equal to its version number in this snapshot + metadata file. Furthermore, any targets metadata filename that was listed + in the previous snapshot metadata file, if any, MUST continue to be listed + in this snapshot metadata file. + + 3.4. **Check for a freeze attack.** The latest downloaded time should be + lower than the expiration timestamp in this metadata file. + + 4. **Download and check the top-level targets metadata file**, up to either + the number of bytes specified in the snapshot metadata file, or some + Z number of bytes. The value for Z is set by the authors of the application + using TUF. For example, Z may be tens of kilobytes. + If consistent snapshots are not used (see Section 7), then the filename + used to download the targets metadata file is of the fixed form + FILENAME.EXT (e.g., targets.json). + Otherwise, the filename is of the form VERSION.FILENAME.EXT (e.g., + 42.targets.json), where VERSION is the version number of the targets + metadata file listed in the snapshot metadata file. + In either case, the client MUST write the file to non-volatile storage as + FILENAME.EXT. + + 4.1. **Check against snapshot metadata.** The hashes (if any), and version + number of this metadata file MUST match the snapshot metadata. This is + done, in part, to prevent a mix-and-match attack by man-in-the-middle + attackers. + + 4.2. **Check for an arbitrary software attack.** This metadata file MUST + have been signed by a threshold of keys specified in the latest root + metadata file. + + 4.3. **Check for a rollback attack.** The version number of the previous + targets metadata file, if any, MUST be less than or equal to the version + number of this targets metadata file. + + 4.4. **Check for a freeze attack.** The latest downloaded time should be + lower than the expiration timestamp in this metadata file. + + 4.5. **Perform a preorder depth-first search for metadata about the desired + target, beginning with the top-level targets role.** + + 4.5.1. If this role has been visited before, then skip this role (so that + cycles in the delegation graph are avoided). + Otherwise, if an application-specific maximum number of roles have been + visited, then go to step 5 (so that attackers cannot cause the client to + waste excessive bandwidth or time). + Otherwise, if this role contains metadata about the desired target, then go + to step 5. + + 4.5.2. Otherwise, recursively search the list of delegations in order of + appearance. + + 4.5.2.1. If the current delegation is a multi-role delegation, recursively + visit each role, and check that each has signed exactly the same non-custom + metadata (i.e., length and hashes) about the target (or the lack of any + such metadata). + + 4.5.2.2. If the current delegation is a terminating delegation, then jump + to step 5. + + 4.5.2.3. Otherwise, if the current delegation is a non-terminating + delegation, continue processing the next delegation, if any. Stop the + search, and jump to step 5 as soon as a delegation returns a result. + + 5. **Verify the desired target against its targets metadata.** + + 5.1. If there is no targets metadata about this target, then report that + there is no such target. + + 5.2. Otherwise, download the target (up to the number of bytes specified in + the targets metadata), and verify that its hashes match the targets + metadata. (We download up to this number of bytes, because in some cases, + the exact number is unknown. This may happen, for example, if an external + program is used to compute the root hash of a tree of targets files, and + this program does not provide the total size of all of these files.) + If consistent snapshots are not used (see Section 7), then the filename + used to download the target file is of the fixed form FILENAME.EXT (e.g., + foobar.tar.gz). + Otherwise, the filename is of the form HASH.FILENAME.EXT (e.g., + c14aeb4ac9f4a8fc0d83d12482b9197452f6adf3eb710e3b1e2b79e8d14cb681.foobar.tar.gz), + where HASH is one of the hashes of the targets file listed in the targets + metadata file found earlier in step 4. + In either case, the client MUST write the file to non-volatile storage as + FILENAME.EXT. 6. Usage @@ -995,7 +1125,7 @@ Version 1.0 (Draft) stored securely offline (e.g. encrypted and on a separate machine, in special-purpose hardware, etc.). This document does not prescribe how keys should be encrypted and stored, and so it is left to implementers of - this document to decide how best to secure them. + this document to decide how best to secure them. To replace a compromised root key or any other top-level role key, the root role signs a new root.json file that lists the updated trusted keys for the @@ -1016,8 +1146,9 @@ Version 1.0 (Draft) clients will (correctly) not validate the new root.json file. For example, if there is a 1.root.json that has threshold 2 and a 2.root.json that has threshold 3, 2.root.json MUST be signed by at least 2 keys defined in - 1.root.json and at least 3 keys defined in 2.root.json. - + 1.root.json and at least 3 keys defined in 2.root.json. See step 1 in + Section 5.1 for more details. + To replace a delegated developer key, the role that delegated to that key just replaces that key with another in the signed metadata where the delegation is done. @@ -1046,21 +1177,22 @@ Version 1.0 (Draft) Simply put, TUF should write every metadata file as such: if the file had the original name of filename.ext, then it should be written to - disk as version_number.filename.ext, where version_number is an integer. - - On the other hand, consistent target files should be written to disk as - digest.filename.ext. This means that if the referrer metadata lists N - cryptographic hashes of the referred file, then there must be N identical - copies of the referred file, where each file will be distinguished only by - the value of the digest in its filename. The modified filename need not - include the name of the cryptographic hash function used to produce the - digest because, on a read, the choice of function follows from the - selection of a digest (which includes the name of the cryptographic - function) from all digests in the referred file. + non-volatile storage as version_number.filename.ext, where version_number + is an integer. + + On the other hand, consistent target files should be written to + non-volatile storage as digest.filename.ext. This means that if the + referrer metadata lists N cryptographic hashes of the referred file, then + there must be N identical copies of the referred file, where each file will + be distinguished only by the value of the digest in its filename. The + modified filename need not include the name of the cryptographic hash + function used to produce the digest because, on a read, the choice of + function follows from the selection of a digest (which includes the name of + the cryptographic function) from all digests in the referred file. Additionally, the timestamp metadata (timestamp.json) should also be - written to disk whenever it is updated. It is optional for an - implementation to write identical copies at digest.timestamp.json for + written to non-volatile storage whenever it is updated. It is optional for + an implementation to write identical copies at digest.timestamp.json for record-keeping purposes, because a cryptographic hash of the timestamp metadata is usually not known in advance. The same step applies to the root metadata (root.json), although an implementation must write both root.json @@ -1088,32 +1220,7 @@ Version 1.0 (Draft) 7.2. Reading consistent snapshots - We now explain how a client should read a self-contained consistent - snapshot. - - If the root metadata (root.json) is either missing the Boolean - "consistent_snapshot" attribute or the attribute is set to False, then the - client should do nothing different from the workflow in Section 5.1. - - Otherwise, the client must perform as follows: - 1. It must first retrieve the timestamp metadata (timestamp.json) from the - repository. - 2. If a threshold number of signatures of the timestamp or snapshot - metadata are not valid, then the client must download the root metadata - (root.json) from the repository and return to step 1. - 3. Otherwise, the client must download every subsequent metadata or - target file as follows: if the metadata or target file has the name - filename.ext, then the client must actually retrieve the file with the - name digest.filename.ext, where digest is the hex digest of a - cryptographic hash of the referred file as listed by its referrer file. - Even though the modified filename does not include the name of the - cryptographic hash function used to produce the chosen digest value, the - choice of function follows from the selection of the digest (which - includes the name of the cryptographic function) from all digests in the - referred file. - 4. Finally, the client must be careful to rename every metadata or target - file retrieved with the name digest.filename.ext to the name - filename.ext. + See Section 5.1 for more details. F. Future directions and open questions @@ -1122,4 +1229,3 @@ F.1. Support for bogus clocks. The framework may need to offer an application-enablable "no, my clock is _supposed_ to be wrong" mode, since others have noticed that many users seem to have incorrect clocks. -