diff --git a/specs/plugin-extensibility.md b/specs/plugin-extensibility.md index 0cde8d6..c30c2d8 100644 --- a/specs/plugin-extensibility.md +++ b/specs/plugin-extensibility.md @@ -232,7 +232,7 @@ This interface targets plugins that integrate with providers of basic cryptograp 1. Check if `response.signingAlgorithm` is one of [supported signing algorithms](./signature-specification.md#algorithm-selection). 2. Check that the plugin did not modify `request.payload` before generating the signature, and the signature is valid for the given payload. Verify the hash of the `request.payload` against `response.signature`, using the public key of signing certificate (leaf certificate) in `response.certificateChain` along with the `response.signingAlgorithm`. This step does not include certificate chain validation (certificate chain leads to a trusted root configured in Notation's Trust Store), or revocation check. 3. Check that the `response.certificateChain` conforms to [Certificate Requirements](./signature-specification.md#certificate-requirements). - 5. Assemble the JWS Signature envelope using `response.signature`, `response.signingAlgorithm` and `response.certificateChain`. Notation may also generate and include timestamp signature in this step. + 5. Assemble the signature envelope using `response.signature`, `response.signingAlgorithm` and `response.certificateChain`. If the signing scheme is [`notary.x509`](./signing-scheme.md/#notaryx509), implementations SHOULD also request and include TSA timestamp countersignature in this step. The `certReq` field in the [timestamping request](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.1) MUST be set to true. 6. Generate a signature manifest for the given signature envelope. 2. Else if, plugin supports capability `SIGNATURE_GENERATOR.ENVELOPE` *(covered in next section)* 3. Return an error @@ -355,7 +355,7 @@ All response attributes are required. ### Signature Envelope Generator -This interface targets plugins that in addition to signature generation want to generate the complete signature envelope. This interface allows plugins to have full control over the generated signature envelope, and can append additional signed and unsigned metadata, including timestamp signatures. The plugin must be signature envelope format aware, and implement new formats when Notary Project adopts new formats. +This interface targets plugins that in addition to signature generation want to generate the complete signature envelope. This interface allows plugins to have full control over the generated signature envelope, and can append additional signed and unsigned metadata, including timestamp countersignatures. The plugin must be signature envelope format aware, and implement new formats when Notary Project adopts new formats. #### Signing workflow using plugin @@ -366,14 +366,15 @@ This interface targets plugins that in addition to signature generation want to 1. Execute the plugin with `get-plugin-metadata` command 1. If plugin supports capability `SIGNATURE_GENERATOR.ENVELOPE` 1. Execute the plugin with `generate-envelope` command. Set `request.keyId` and the optional `request.pluginConfig` to corresponding values associated with signing key `keyName` in `config.json`. Set `request.payload` to base64 encoded the [Notary Project signature Payload](./signature-specification.md#payload), `request.payloadType` to `application/vnd.cncf.notary.payload.v1+json` and `request.signatureEnvelopeType` to a pre-defined type (`application/jose+json` for JWS). - 2. `response.signatureEnvelope` contains the base64 encoded signature envelope, value of `response.signatureEnvelopeType` MUST match `request.signatureEnvelopeType`. - 3. Validate the generated signature, return an error if of the checks fails. + 2. If plugin supports timestamping under signing scheme [`notary.x509`](./signing-scheme.md/#notaryx509), the plugin SHOULD request and include TSA timestamp countersignature in the signature envelope at this step. The timestamp countersignature MUST be [RFC 3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2) compliant. The `certReq` field in the [timestamping request](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.1) MUST be set to true. + 3. `response.signatureEnvelope` contains the base64 encoded signature envelope, value of `response.signatureEnvelopeType` MUST match `request.signatureEnvelopeType`. + 4. Validate the generated signature envelope, return an error if any of the checks fails. 1. Check if `response.signatureEnvelopeType` is a supported envelope type and `response.signatureEnvelope`'s format matches `response.signatureEnvelopeType`. 2. Check if the signing algorithm in the signature envelope is one of [supported signing algorithms](./signature-specification.md#algorithm-selection). 3. Check that the [`targetArtifact` descriptor](./signature-specification.md#payload) in JWSPayload in `response.signatureEnvelope` matches `request.payload`. Plugins MAY append additional annotations but MUST NOT replace/override existing descriptor attributes and annotations. - 4. Check that `response.signatureEnvelope` can be verified using the public key and signing algorithm specified in the signing certificate, which is embedded as part of certificate chain in `response.signatureEnvelope` . This step does not include certificate chain validation (certificate chain leads to a trusted root configure in Notation), or revocation check. - 5. Check that the certificate chain in `response.signatureEnvelope` confirm to [Certificate Requirements]. - 4. Generate a signature manifest for the given signature envelope, and append `response.annotations` to manifest annotations. + 4. Check that `response.signatureEnvelope` can be verified using the public key and signing algorithm specified in the signing certificate, which is embedded as part of certificate chain in `response.signatureEnvelope`. This step does not include certificate chain validation (certificate chain leads to a trusted root configured in Notation), or revocation check. + 5. Check that the certificate chain in `response.signatureEnvelope` and [timestamp countersignature](./signature-specification.md#unsigned-attributes) confirm to [certificate requirements](./signature-specification.md#certificate-requirements). + 5. Generate a signature manifest for the given signature envelope, and append `response.annotations` to manifest annotations. 2. Else if plugin supports capability `SIGNATURE_GENERATOR.RAW` *(covered in previous section)* 3. Return an error @@ -510,11 +511,11 @@ This allows implementations of the [Notary Project signature specification](./si "criticalAttributes" : { "contentType" : "application/vnd.cncf.notary.payload.v1+json", - // One of notary.default.x509 or notary.signingAuthority.x509 - "signingScheme" : "notary.default.x509" | "notary.signingAuthority.x509", + // One of notary.x509 or notary.x509.signingAuthority + "signingScheme" : "notary.x509" | "notary.x509.signingAuthority", // Value is always RFC 3339 formatted date time string "expiry": "2022-10-06T07:01:20Z", - // if signingScheme is notary.signingAuthority.x509. + // if signingScheme is notary.x509.signingAuthority "authenticSigningTime": "2022-04-06T07:01:20Z", // Name of the verification plugin "verificationPlugin": "com.example.nv2plugin", @@ -604,6 +605,6 @@ All response attributes are required. ## FAQ -**Q: Will Notation generate timestamp signature for Signature Envelope Generator plugin or its responsibility of plugin publisher?** +**Q: Will Notation generate timestamp countersignature for Signature Envelope Generator plugin or its responsibility of plugin publisher?** -**A :** If the envelope generated by a Signature Envelope Generator plugin contains timestamp signature, Notation will not append additional timestamp signature, else it will generate the timestamp signature and append it to the envelope as an unsigned attribute. +**A :** The Signature Envelope Generator plugin has full control over the generated signature envelope including any timestamp countersignature. Notation will NOT add/update/delete any timestamp countersignature in an envelope that's generated by a Signature Envelope Generator plugin. \ No newline at end of file diff --git a/specs/signature-envelope-cose.md b/specs/signature-envelope-cose.md index c126a43..6df10e5 100644 --- a/specs/signature-envelope-cose.md +++ b/specs/signature-envelope-cose.md @@ -128,7 +128,7 @@ Note: The above examples are represented using the [extended CBOR diagnostic not - **[`content type`](https://datatracker.ietf.org/doc/html/rfc8152#section-3.1)** (*tstr*): The REQUIRED parameter content type (label `3`) is used to declare the media type of the secured content (the payload). The supported value is `application/vnd.cncf.notary.payload.v1+json`. - **`io.cncf.notary.signingScheme`** (*tstr*, critical): This REQUIRED header specifies the [Notary Project signing scheme](./signing-scheme.md) used by the signature. Supported values are `notary.x509` and `notary.x509.signingAuthority`. - **`io.cncf.notary.signingTime`** (*date/time*): This header specifies the time at which the signature was generated. This is an untrusted date/time, and therefore not used in trust decisions. Its value is an Epoch-Based Date/Time defined in [RFC 8949](https://datatracker.ietf.org/doc/html/rfc8949#section-3.4.2). The optional fractional seconds SHOULD NOT be used. This claim is REQUIRED and only valid when signing scheme is `notary.x509`. -- **`io.cncf.notary.authenticSigningTime`** (*date/time*, critical): This header specifies the authenticated time at which the signature was generated. Its value is an Epoch-Based Date/Time defined in [RFC 8949](https://datatracker.ietf.org/doc/html/rfc8949#section-3.4.2). The optional fractional seconds SHOULD NOT be used. This claim is REQUIRED and only valid when signing scheme is `notary.x509.signingAuthority` . +- **`io.cncf.notary.authenticSigningTime`** (*date/time*, critical): This header specifies the authenticated time at which the signature was generated. Its value is an Epoch-Based Date/Time defined in [RFC 8949](https://datatracker.ietf.org/doc/html/rfc8949#section-3.4.2). The optional fractional seconds SHOULD NOT be used. This claim is REQUIRED and only valid when signing scheme is `notary.x509.signingAuthority`. - **`io.cncf.notary.expiry`** (*date/time*, critical): This OPTIONAL header provides a "best by use" time for the artifact, as defined by the signer. Its value is an Epoch-Based Date/Time defined in [RFC 8949](https://datatracker.ietf.org/doc/html/rfc8949#section-3.4.2). The optional fractional seconds SHOULD NOT be used. ## Unprotected Headers @@ -154,8 +154,7 @@ The Notary Project signature supports the following unprotected header parameter Note: `<<` and `>>` are used to notate the CBOR byte string resulting from encoding the data item. - **[`x5chain`](https://datatracker.ietf.org/doc/html/draft-ietf-cose-x509-08#section-2)** (*array of bstr*): This REQUIRED parameter (label `33` by [IANA](https://www.iana.org/assignments/cose/cose.xhtml#header-parameters)) contains the ordered list of X.509 certificate or certificate chain ([RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)) corresponding to the key used to digitally sign the COSE. The certificate chain is represented as an array of certificate, each certificate in the array is DER encoded and then wrapped in a CBOR byte string. The certificate containing the public key corresponding to the key used to digitally sign the COSE MUST be the first certificate, followed by the intermediate and root certificates in the correct order. Refer [*Certificate Chain* unsigned attribute](signature-specification.md#unsigned-attributes) for more details. Optionally, this header can be presented in the protected header. -- **`io.cncf.notary.timestampSignature`** (*bstr*): This OPTIONAL header is used to store countersignature that provides authentic signing time. Only [RFC3161]([rfc3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2)) compliant `TimeStampToken` are supported. - - **TODO** Define the opaque datum (hash of envelope) that is sent to TSA, and how TSA response (time stamp token) is represented in this header. +- **`io.cncf.notary.timestampSignature`** (*bstr*): This OPTIONAL header is used to store a countersignature that proves the signature was generated before the timestamp. Only [RFC 3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2) compliant `TimeStampToken` are supported. If present, this header is validated and used solely under the [`notary.x509`](./signing-scheme.md/#notaryx509) signing scheme. Refer [*Timestamp Signature* unsigned attribute](signature-specification.md#unsigned-attributes) for more details. - **`io.cncf.notary.signingAgent`** (*tstr*): This OPTIONAL header provides the identifier of a client (e.g. Notation) that produced the signature. E.g. `notation/1.0.0`. Refer [*Signing Agent* unsigned attribute](signature-specification.md#unsigned-attributes) for more details. ## Signature diff --git a/specs/signature-envelope-jws.md b/specs/signature-envelope-jws.md index dfb8756..e50a0cd 100644 --- a/specs/signature-envelope-jws.md +++ b/specs/signature-envelope-jws.md @@ -120,7 +120,7 @@ Example with Signing Scheme `notary.x509.signingAuthority` - **[`cty`](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.10)**(*string*): The REQUIRED header content-type is used to declare the media type of the secured content (the payload). The supported value is `application/vnd.cncf.notary.payload.v1+json`. - **`io.cncf.notary.signingScheme`**(*string*)(critical): This REQUIRED header specifies the [Notary Project signing scheme](./signing-scheme.md) used by the signature. Supported values are `notary.x509` and `notary.x509.signingAuthority`. - **`io.cncf.notary.signingTime`**(*string*): This header specifies the time at which the signature was generated. This is an untrusted timestamp, and therefore not used in trust decisions. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used. This claim is REQUIRED and only valid when signing scheme is `notary.x509`. -- **`io.cncf.notary.authenticSigningTime`**(*string*)(critical): This header specifies the authenticated time at which the signature was generated. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used. This claim is REQUIRED and only valid when signing scheme is `notary.x509.signingAuthority` . +- **`io.cncf.notary.authenticSigningTime`**(*string*)(critical): This header specifies the authenticated time at which the signature was generated. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used. This claim is REQUIRED and only valid when signing scheme is `notary.x509.signingAuthority`. - **`io.cncf.notary.expiry`**(*string*)(critical): This OPTIONAL header provides a “best by use” time for the artifact, as defined by the signer. Its value is a [RFC 3339][rfc3339] formatted date time, the optional fractional second ([time-secfrac][rfc3339][[1](https://datatracker.ietf.org/doc/html/rfc3339#section-5.3)]) SHOULD NOT be used. - **[`crit`](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.11)**(*array of strings*): This REQUIRED (optional as per JWS spec, but required in Notary Project JWS signature) header lists the headers that implementation MUST understand and process. It MUST only contain headers apart from registered headers (e.g. `alg`, `cty`) in JWS specification. This header MUST contain `io.cncf.notary.signingScheme` which is a required critical header, and optionally contain `io.cncf.notary.authenticSigningTime` and `io.cncf.notary.expiry` if these critical headers are present in the signature. @@ -144,8 +144,7 @@ The Notary Project signature supports following unprotected headers: `timestamp` ``` - **[`x5c`](https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.6)** (*array of strings*): This REQUIRED header contains the ordered list of X.509 certificate or certificate chain([RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)) corresponding to the key used to digitally sign the JWS. The certificate chain is represented as a JSON array of certificate value strings, each string in the array is a base64-encoded DER certificate value. The certificate containing the public key corresponding to the key used to digitally sign the JWS MUST be the first certificate, followed by the intermediate and root certificates in the correct order. Refer [*Certificate Chain* unsigned attribute](signature-specification.md#unsigned-attributes) for more details. -- **`io.cncf.notary.timestampSignature`** (*string*): This OPTIONAL header is used to store countersignature that provides authentic signing time. Only [RFC3161]([rfc3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2)) compliant `TimeStampToken` are supported. - - **TODO** Define the opaque datum (hash of envelope) that is sent to TSA, and how TSA response (time stamp token) is represented in this header. +- **`io.cncf.notary.timestampSignature`** (*string*): This OPTIONAL header is used to store a base64-encoded countersignature that proves the signature was generated before the timestamp. Only [RFC 3161](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.2) compliant `TimeStampToken` are supported. If present, this header is validated and used solely under the [`notary.x509`](./signing-scheme.md/#notaryx509) signing scheme. Refer [*Timestamp Signature* unsigned attribute](signature-specification.md#unsigned-attributes) for more details. - **`io.cncf.notary.signingAgent`**(*string*): This OPTIONAL header provides the identifier of a client (e.g. Notation) that produced the signature. E.g. “notation/1.0.0”. Refer [*Signing Agent* unsigned attribute](signature-specification.md#unsigned-attributes) for more details. ## Signature diff --git a/specs/signature-specification.md b/specs/signature-specification.md index ce06c66..bd619c1 100644 --- a/specs/signature-specification.md +++ b/specs/signature-specification.md @@ -13,8 +13,8 @@ A signature envelope consists of the following components: - Payload/Message `m`: The data that is integrity protected - e.g. descriptor of the artifact being signed. - Signed attributes `v`: The signature metadata that is integrity protected - e.g. signature expiration time, creation time, etc. -- Unsigned attributes `u`: These attributes are not signed by the signing key that generates the signature. We anticipate unsigned attributes contain content that may be signed by an different party e.g. Certificate chain signed by a CA, or TSA countersignature signed by the TSA. -- Cryptographic signatures `s`: The digital signatures computed on payload and signed attributes. +- Unsigned attributes `u`: These attributes are not signed by the signing key that generates the signature. We anticipate unsigned attributes contain content that may be signed by a different party e.g. certificate chain signed by a CA, or timestamping countersignature signed by a TSA. +- Primitive signature `s`: The digital signature computed on payload and signed attributes. A signature envelope is `e = {m, v, u, s}` where `s` is signature. @@ -113,8 +113,8 @@ The Notary Project signature specification requires the signature envelope to su #### Standard attributes - **Signing Scheme** (critical): A REQUIRED claim that defines the [Notary Project Signing Scheme](./signing-scheme.md) used by the signature. This attribute dictates the rest of signature schema - the set of signed and unsigned attributes to be included in the signature. Supported values are `notary.x509` and `notary.x509.signingAuthority`. -- **Signing Time**: A claim that indicates the time at which the signature was generated. Though this claim is signed by the signing key, it's considered unauthenticated as a signer can modify local time and manipulate this claim. More details [here](#signing-time). This claim is REQUIRED and only valid when signing scheme is `notary.x509`. -- **Authentic Signing Time** (critical): The authenticated time at which the signature was generated. This claim allows a verifier to determine if the signature was generated when the certificate was valid. This claim is REQUIRED and only valid when signing scheme is `notary.x509.signingAuthority`. More details [here](#signing-time). +- **Signing Time**: A claim that indicates the time at which the signature was generated. Though this claim is signed by the signing key, it's considered unauthenticated as a signer can modify local time and manipulate this claim. More details [here](#signing-time--authentic-signing-time). This claim is REQUIRED and only valid when signing scheme is `notary.x509`. +- **Authentic Signing Time** (critical): The authenticated time at which the signature was generated. This claim allows a verifier to determine if the signature was generated when the certificate was valid. This claim is REQUIRED and only valid when signing scheme is `notary.x509.signingAuthority`. More details [here](#signing-time--authentic-signing-time). - **Expiry** (critical): An OPTIONAL claim that provides a "best by use" time for the artifact, as defined by the signer. More details [here](#expiry). - **Content Type** (critical): A REQUIRED claim that indicates the content type of the [payload](#payload). The supported value is `application/vnd.cncf.notary.payload.v1+json`. Other payload types MAY be supported in future. @@ -149,7 +149,7 @@ See [Guidelines for implementations of the Notary Project signature specificatio These attributes are considered unsigned with respect to the signing key that generates the signature. - **Certificate Chain**: This is a REQUIRED attribute that contains the ordered list of X.509 public certificates associated with the signing key used to generate the signature. The ordered list starts with the signing certificate, any intermediate certificates and ends with the root certificate. The certificate chain MUST be authenticated against a trust store as part of signature validation. Specific requirements for the certificates in the chain are provided [here](#certificate-requirements). -- **Timestamp signature** : An OPTIONAL counter signature which provides [authentic timestamp](#signing-time)e.g. Time Stamp Authority (TSA) generated timestamp signature. Only [RFC3161][ietf-rfc3161] compliant TimeStampToken are currently supported. +- **Timestamp Signature**: An OPTIONAL countersignature generated by a trusted third party, such as a Timestamp Authority (TSA). Its purpose is to demonstrate that the primitive signature, computed on payload and signed attributes, was generated before the timestamp. Only [RFC 3161][ietf-rfc3161] compliant timestamp signatures are supported. If present, this claim is validated and used solely under the [`notary.x509`](./signing-scheme.md/#notaryx509) signing scheme. - **Signing Agent**: An OPTIONAL claim that provides the identifier of the software (e.g. Notation) that produced the signature on behalf of the user. It is an opaque string set by the software that produces the signature. It's intended primarily for diagnostic and troubleshooting purposes, this attribute is unsigned, the verifier MUST NOT validate formatting, or fail validation based on the content of this claim. The suggested format is one or more tokens of the form `{id}/{version}` containing identifier and version of the software, separated by spaces. E.g. "notation/1.0.0", "notation/1.0.0 myplugin/0.8". ## OCI Signatures @@ -258,17 +258,20 @@ The signing certificate's public key algorithm and size MUST be used to determin ### Certificate Requirements -The codesigning and timestamping certificates MUST meet the following requirements. These requirements are validated both at signature generation time and signature verification time, and are applied to the certificate chain in the signature envelope. These validations are independent of certificate chain validation against a trust store. +The **codesigning** and **timestamping** certificates MUST meet the following requirements. These requirements are validated both at signature generation time and signature verification time, and are applied to the certificate chain in the signature envelope and timestamp countersignature respectively. These validations are independent of certificate chain validation against a trust store. #### Root and Intermediate CA Certificates The CA certificates MUST meet the following requirements 1. **[Basic Constraints:](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9)** -The `basicConstraints` extension MUST be present and MUST be marked as critical. The `cA` field MUST be set `true`. +The `basicConstraints` extension MUST be present and MUST be marked as critical. The `cA` field MUST be set to `true`. The [`pathLenConstraint`](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9) field is OPTIONAL. If present, it MUST be verified against the depth of the chain below that CA certificate. (If value is null consider it as not present) 1. **[Key Usage:](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3)** -The `keyUsage` extension MUST be present and MUST be marked critical. Bit positions for `keyCertSign` MUST be set. + - **For codesigning certificate:** the `keyUsage` extension MUST be present and MUST be marked critical. + - **For timestamping certificate:** the `keyUsage` extension MUST be present and SHOULD be marked critical. + + Bit positions for `keyCertSign` MUST be set. #### Leaf Certificates @@ -277,10 +280,13 @@ The leaf or end certificates MUST meet the following requirements 1. **[Basic Constraints:](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9)** The `basicConstraints` extension is OPTIONAL and can OPTIONALLY be marked as critical. If present, the `cA` field MUST be set to `false`. 1. **[Key Usage:](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3)** -The `keyUsage` extension MUST be present and MUST be marked critical. Bit positions for `digitalSignature` MUST be set. The Bit positions for `keyEncipherment`, `dataEncipherment`, `keyAgreement`, `keyCertSign`, `encipherOnly`, `decipherOnly` and `cRLSign` MUST NOT be set. -1. **[Extended Key Usage:](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)** The `extendedKeyUsage` extension is OPTIONAL and can OPTIONALLY be marked as critical. - - **For signing certificate:** If present, the value MAY contain `id-kp-codeSigning` and MUST NOT contain `anyExtendedKeyUsage`, `serverAuth`, `clientAuth`, `emailProtection` and `timeStamping`. - - **For timestamping certificate:** If present, the value MUST contain `id-kp-timeStamping` and MUST NOT contain `anyExtendedKeyUsage`, `serverAuth`, `clientAuth`, `emailProtection` and `codeSigning`. + - **For codesigning certificate:** the `keyUsage` extension MUST be present and MUST be marked critical. + - **For timestamping certificate:** the `keyUsage` extension MUST be present and SHOULD be marked critical. + + Bit positions for `digitalSignature` MUST be set. The Bit positions for `keyEncipherment`, `dataEncipherment`, `keyAgreement`, `keyCertSign`, `encipherOnly`, `decipherOnly` and `cRLSign` MUST NOT be set. +1. **[Extended Key Usage:](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12)** + - **For codesigning certificate:** The `extendedKeyUsage` extension is OPTIONAL and can OPTIONALLY be marked as critical. If present, the value MAY contain `id-kp-codeSigning` and MUST NOT contain `anyExtendedKeyUsage`, `serverAuth`, `clientAuth`, `emailProtection` and `timeStamping`. + - **For timestamping certificate:** According to [RFC 3161 2.3](https://datatracker.ietf.org/doc/html/rfc3161#section-2.3), the `extendedKeyUsage` extension MUST be present and MUST be marked as critical. The value MUST contain `id-kp-timeStamping` only. 1. **Key Length** The certificate MUST abide by the following key length restrictions: - For RSA public key, the key length MUST be 2048 bits or higher. - For ECDSA public key, the key length MUST be 256 bits or higher. @@ -294,7 +300,7 @@ The `keyUsage` extension MUST be present and MUST be marked critical. Bit positi 1. Any certificate in the certificate chain MUST NOT use SHA1WithRSA and ECDSAWithSHA1 signatures. 2. Only Basic Constraints, Key Usage, and Extended Key Usage extensions of X.509 certificates are honored. For rest of the extensions, implementations of the Notary Project signature specification MUST fail open i.e. rest of the extensions MUST NOT be evaluated or honored. 3. The certificates in the certificate chain MUST be valid at signing time. Implementations of the Notary Project signature specification MUST NOT enforce validity period nesting, i.e the validity period for a given certificate may not fall entirely within the validity period of that certificate's issuer certificate. -4. In the absence of an Authentic Timestamp, each and every certificate in the certificate chain i.e. signing certificate, intermediate certificates, and the root certificate must be valid i.e. not expired at the time of signature verification. +4. For codesigning certificates, in the absence of an Authentic Timestamp, each and every certificate in the certificate chain i.e. signing certificate, intermediate certificates, and the root certificate must be valid i.e. not expired at the time of verification. ## FAQ @@ -312,9 +318,14 @@ The client implementation can use the aforementioned `mediaType` to parse the si ## Appendix -### Signing time +### Signing time & Authentic Signing time + +A `signing time` denotes the time at which the signature was generated. An X509 certificate has a defined [validity](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.5) during which it can be used to generate signatures. The signing time must be greater than or equal to certificate's `notBefore` attribute, and the signing time must be less than or equal to certificate's `notAfter` attribute. Signatures generated outside the certificate's validity are considered invalid. + +An `authentic signing time` is a signing time authenticated by a `Signing Authority (SA)`. It allows a verifier to determine if the signature was generated within the certificate's validity. `Authentic signing time` is only used with signing scheme [`notary.x509.signingAuthority`](./signing-scheme.md/#notaryx509signingauthority). It is REQUIRED and MUST be present under the *Authentic Signing Time* signed attribute of the signature envelope. -The signing time denotes the time at which the signature was generated. A X509 certificate has a defined [validity](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.5) during which it can be used to generate signatures. The signing time must be greater than or equal to certificate's `notBefore` attribute, and signing time must be less than or equal to certificate's `notAfter` attribute. Signatures generated after the certificate expires are considered invalid. An authentic timestamp, like TSA countersignature, allows a verifier to determine if the signature was generated when the certificate was valid. It also allows a verifier to determine if a signature be treated as valid when a certificate is revoked, if the certificate was revoked after the signature was generated. In the absence of an authentic timestamp, signatures are considered invalid after certificate expires, and all signatures are considered revoked when a certificate is revoked. +> [!NOTE] +> The *Timestamp Signature* unsigned attribute MUST NOT be used as an `authentic signing time`. Successful verification of the timestamp countersignature only implies that the `primitive signature` in the signature envelope was generated before the time point been stamped. The phrase `time point been stamped` refers to the specific time point at which the *Timestamp Authority (TSA)* receives the timestamping request. ### Expiry diff --git a/specs/signing-and-verification-workflow.md b/specs/signing-and-verification-workflow.md index bd9353a..216a7be 100644 --- a/specs/signing-and-verification-workflow.md +++ b/specs/signing-and-verification-workflow.md @@ -8,7 +8,7 @@ The user wants to sign an OCI artifact and push the signature to a repository. ### Signing Prerequisites -- User has access to the signing certificate and private key or a remote signing service through a notation plug-in. +- User has access to the signing certificate and private key or a remote signing service through a notation plugin. ### Signing Steps @@ -16,11 +16,11 @@ The user wants to sign an OCI artifact and push the signature to a repository. 1. Verify that the signing certificate is valid and satisfies [certificate requirements](./signature-specification.md#certificate-requirements). 1. Verify that the signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). 1. Generate signature. - 1. Generate signature using signature formats specified in [supported signature envelopes](./signature-specification.md#supported-signature-envelopes). Also, as part of this step, the user-defined/supplied custom attributes should be added to the annotations of the signature's descriptor. - 1. If the user wants to timestamp the signature, obtain an [RFC-3161](https://datatracker.ietf.org/doc/html/rfc3161.html) compliant timestamp for the signature generated in the previous step. Otherwise, continue to the next step. + 1. Generate signature envelope using signature formats specified in [supported signature envelopes](./signature-specification.md#supported-signature-envelopes). Also, as part of this step, the user-defined/supplied custom attributes should be added to the annotations of the signature's descriptor. + 1. If signing scheme is [`notary.x509`](./signing-scheme.md#notaryx509) and timestamp countersignature is demanded, extract the [primitive signature](./signature-specification.md#signature-envelope) (the digital signature computed on payload and signed attributes) from the signature envelope generated in the previous step. Compute hash of the signature (the hash algorithm MUST be deduced from signing certificate's public key. See [algorithm requirements](./signature-specification.md#signature-algorithm-requirements)) and send it to a [RFC 3161](https://datatracker.ietf.org/doc/html/rfc3161.html) compliant *Timestamp Authority (TSA)* for timestamping. The `certReq` field in the [timestamping request](https://datatracker.ietf.org/doc/html/rfc3161#section-2.4.1) MUST be set to true. Otherwise, continue to the next step. 1. Verify that the timestamp signing certificate satisfies [certificate requirements](./signature-specification.md#certificate-requirements). 1. Verify that the timestamp signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). - 1. Embed timestamp to the signature envelope. + 1. On success, embed the timestamp countersignature into the *Timestamp Signature* unsigned attribute of the signature envelope. If any of the above timestamping step failed, implementations MUST fail the signing process. 1. **Push the signature envelope:** Push the signature envelope generated in the previous step to the repository. 1. **Generate signature artifact manifest:** As described in [signature specification](./signature-specification.md#storage) create the Notary Project signature manifest for the signature envelope generated in step 1. 1. **Push signature artifact manifest:** Push the Notary Project signature manifest to the repository. @@ -61,7 +61,7 @@ The user wants to pull an OCI artifact only if they are signed by a trusted publ If all signature artifact descriptors have already been processed, fail the signature verification and exit. 1. **Get and verify signatures:** On the filtered manifest of the Notary Project signature, perform the following steps: 1. Download the signature envelope. - 1. Verify the signature envelope using trust-store and trust-policy as mentioned in [signature evaluation](./trust-store-trust-policy.md#signature-evaluation) section. + 1. Verify the signature envelope using trust-store and trust-policy as mentioned in [signature verification](./trust-store-trust-policy.md#signature-verification) section. 1. If the signature verification fails, skip the below steps and move to the next signature artifact descriptor(step 3.1). If all signature artifact descriptors have already been processed, fail the signature verification and exit. 1. If signature verification succeeds, compare the digest derived from the given OCI artifact reference with the signed digest present in the signature envelope's payload. Also, if there are any user-defined/supplied custom annotations, match them as well. @@ -77,7 +77,7 @@ The user wants to sign an arbitrary blob with a detached signature. ### Signing Prerequisites -- User has access to the signing certificate and private key or a remote signing service through a notation plug-in. +- User has access to the signing certificate and private key or a remote signing service through a notation plugin. ### Signing Steps @@ -87,10 +87,10 @@ The user wants to sign an arbitrary blob with a detached signature. 1. Verify that the signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). 1. Generate signature. 1. Generate signature using a signature format specified in [supported signature envelopes](./signature-specification.md#supported-signature-envelopes). Also, as part of this step, the user-defined/supplied custom attributes should be added to the annotations of the signature payload. - 1. If the user wants to timestamp the signature, obtain an [RFC-3161](https://datatracker.ietf.org/doc/html/rfc3161.html) compliant timestamp for the signature generated in the previous step. Otherwise, continue to the next step. + 1. If signing scheme is [`notary.x509`](./signing-scheme.md/#notaryx509) and timestamp countersignature is demanded, extract the [primitive signature](./signature-specification.md#signature-envelope) (the digital signature computed on payload and signed attributes) from the signature envelope generated in the previous step. Compute hash of the signature (the hash algorithm SHOULD be deduced from signing certificate's public key) and send it to a [RFC 3161](https://datatracker.ietf.org/doc/html/rfc3161.html) compliant *Timestamp Authority (TSA)* for timestamping. Otherwise, continue to the next step. 1. Verify that the timestamp signing certificate satisfies [certificate requirements](./signature-specification.md#certificate-requirements). 1. Verify that the timestamp signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). - 1. Embed timestamp to the signature envelope. + 1. On success, embed the timestamp countersignature into the *Timestamp Signature* unsigned attribute of the signature envelope. If any of the above timestamping step failed, implementations MUST fail the signing process. 1. **Save the signature envelope:** Save the signature envelope generated in the previous step to a file. File extension should be the original blob file name plus `.sig.jws` for JWS signatures and `.sig.cose` for COSE signatures. ## Arbitrary blob verification workflow diff --git a/specs/signing-scheme.md b/specs/signing-scheme.md index 31fbccd..a2976f7 100644 --- a/specs/signing-scheme.md +++ b/specs/signing-scheme.md @@ -22,24 +22,27 @@ Generally it covers the following aspects, but can be extended to other aspects 1. Mechanism to establish trust in end users and other entities (like CAs). 1. Set of guarantees available to the verifier apart from integrity and authenticity. -## Signing Scheme +> [!IMPORTANT] +> A signature envelope is restricted to one signing scheme. -Notary Project currently defines the following Signing Schemes. +When the Notary Project incorporates support for a new Signing Scheme + * For signatures generated using the new signing scheme, it is imperative to update existing signature verification software to newer versions. Failed to so will result in these signatures verification failure. However, signatures generated using older signing schemes will continue to be verified correctly. + * The language of the [Notary Project trust policy](./trust-store-trust-policy.md) in *trustpolicy.json* MAY have breaking changes to support newer concepts/configuration elements introduced by the new signing scheme. + The breaking changes are addressed by introducing new major version in the versioned *trustpolicy.json*. -`notary.x509` - Defines a signing scheme that uses the traditional signing workflow in which an end user generates signatures using X.509 certificates. +## Supported Signing Scheme -`notary.x509.signingAuthority` - Defines a signing scheme in which a `signing authority` generates signatures on behalf of an end user (the signature requestor) using X.509 certificates. -A trusted signing authority is defined as a third party service that is trusted both by the end user (the signature requestor) and verifying entity to generate signatures. -Authorities trusted by users should have mechanisms for validating, logging, monitoring, and auditing access to their systems and publish incidence response plans. -A certificate authority (CA) will need to demonstrate only validated entities were issued an X.509 certificate that chains to their root, and a time stamp authority (TSA) will need to demonstrate the time-stamp signing keys were only used within their service. -Similarly, a signing authority (SA) will need to demonstrate signing keys were only used within their service and only validated entities were allowed to generate signatures using the service. +Notary Project currently defines the following Signing Schemes: + +### `notary.x509` + +Defines a signing scheme that uses the traditional signing workflow in which an end user generates signatures using X.509 certificates. -* A signature envelope can only specify one Signing Scheme -* When Notary Project supports an additional Signing Scheme - * Existing signed artifacts MUST be re-signed if they need to be verified using the new signing scheme defined verification process. - * Existing clients used by verifying entity MUST be updated to newer versions that support verifying signatures that use the new signing scheme, otherwise the signatures with newer signing schemes which are unknown to existing clients will fail signature verification. Signatures that use older signing schemes which are known to existing clients will continue to verify correctly. - * The language of the [Notary Project verification policy](./trust-store-trust-policy.md) in *trustpolicy.json* MAY have breaking changes to support newer concepts/configuration elements introduced by the new signing scheme. - The breaking changes are addressed by introducing new major version in the versioned *trustpolicy.json* . +### `notary.x509.signingAuthority` + +Defines a signing scheme in which a `Signing Authority (SA)` generates signatures on behalf of an end user (the signature requestor) using X.509 certificates. A trusted Signing Authority is defined as a third party service that is trusted both by the end user (the signature requestor) and verifying entity to generate signatures. +Authorities trusted by users should have mechanisms for validating, logging, monitoring, and auditing access to their systems and publish incidence response plans. +A trusted Signing Authority will need to demonstrate signing keys were only used within their service and only validated entities were allowed to generate signatures using the service. ## Signature Creation @@ -48,35 +51,35 @@ This attribute dictates the rest of signature schema - the set of signed and uns Both `notary.x509` and `notary.x509.signingAuthority` signing schemes use the similar signature schema (set of signed and unsigned attributes) with the following differences. -* `notary.x509` MUST use a countersignature from trusted source to determine authentic signing time (timestamp). -This is supported through the Timestamp signature unsigned attribute in the signature envelope. Currently Notary Project uses a [RFC3161](ietf-rfc3161) compliant TSA signature for this purpose. +* `notary.x509` can use a timestamp countersignature to prove that the signature was generated before the time point been stamped by the *Timestamp Authority (TSA)*. +This is supported through the OPTIONAL *Timestamp Signature* unsigned attribute in the signature envelope. Currently the Notary Project only supports a [RFC 3161][ietf-rfc3161] compliant Timestamp for this purpose. When not provided, every certificate in the certificate chain MUST be within its validity period at the time of verification. -* `notary.x509.signingAuthority` MUST use a timestamp attribute that is generated by a signing service as part of the original signature itself to determine authenticated signing time (timestamp). -This is supported through the *Authentic Signing time* attribute in the signature envelope. +* `notary.x509.signingAuthority` MUST use a timestamp attribute that is generated by the signing service as part of the original signature to determine `authentic signing time`. +This is supported through the REQUIRED *Authentic Signing Time* signed attribute in the signature envelope. ## Signature Verification Signature verification requires that a `Signing Scheme` attribute is present in the signature and it’s treated as critical i.e. the attribute MUST be understood and processed by the verifier. -For the JWS signature format, the attribute name is `io.cncf.notary.signingScheme`, with supported values `notary.x509` and `notary.x509.signingAuthority`. +The attribute name is `io.cncf.notary.signingScheme`, with supported values `notary.x509` and `notary.x509.signingAuthority`. Any other value will fail signature verification i.e when Notary Project supports an additional Signing Scheme, clients (like *Notation CLI*) MUST be updated to a version that supports the new signing scheme. ### Trust Stores -Each *Signing Scheme* defines the set of trust store types (e.g. CA) that it uses for signature verification. +Each *Signing Scheme* defines the set of trust store types (e.g. CA) that is used for signature verification. `notary.x509` -* Uses trusts store types Certificate Authority (CA) and Timestamping Authority (TSA) during signature verification. -The signature is verified against the trust store of type CA, and the *Timestamp signature* is verified against the trust store of type TSA (to determine the signing time). +* Uses trust store types Certificate Authority (CA) and Timestamping Authority (TSA) during signature verification. +The signature is verified against the trust store of type CA, and the *Timestamp Signature* unsigned attribute in the signature envelope is verified against the trust store of type TSA. * For signature verification to be successful - * The verifying entity’s trust store MUST contain the trusted root certificates under named trust stores of type CA (`{CONFIG}/notation/truststore/x509/ca`) and TSA(`{CONFIG}/notation/truststore/x509/tsa`) + * The verifying entity’s trust store MUST contain the trusted root certificates under named trust stores of type CA (`{CONFIG}/notation/truststore/x509/ca`) and TSA (`{CONFIG}/notation/truststore/x509/tsa`) * The named trust stores MUST be specified in *trustpolicy.json*. E.g. *trustPolicy.trustStores* with value of `ca:acme-rockets,tsa:acme-tsa`. `notary.x509.signingAuthority` * Uses trusts store type Signing Authority during signature verification. The signature is verified against the trust store of type Signing Authority. -The signing time is determined using the *Authentic Signing time* attribute in the signature envelope, and does not rely on a separate TSA generated Timestamp signature. +The authentic signing time is determined using the *Authentic Signing Time* signed attribute in the signature envelope, and does not rely on a separate TSA generated timestamp countersignature. * For signature verification to be successful * The verifying entity’s trust store MUST contain the trusted root certificates under named trust stores of type signingAuthority (`{CONFIG}/notation/truststore/x509/signingAuthority`). * The named trust stores MUST be specified in *trustpolicy.json*. E.g. *trustPolicy.trustStores* with value of `signingAuthority:foobar` . @@ -92,7 +95,7 @@ A given signing scheme can be implemented through any signature envelope format *A:* Signing Authority is a different type of trusted entity as compared to Certificate Authority (CA) or Timestamping Authority (TSA). A CA is trusted for verifying the identity of a signing entity (end user) and issuing it a certificate, whereas a TSA is trusted to generate authentic timestamp. -In contrast, an SA is trusted to generate signatures on behalf of an end user (signature requestor) and also to generate authentic timestamp as part of the signature. +In contrast, an SA is trusted to generate signatures on behalf of an end user (signature requestor) and also to generate authentic signing time as part of the signature. If we use a shared trust store for CA and SA, a verifying entity does not have the ability to differentiate between CA and SA when the verifying entity configures trusted roots in the trust store. This has implication such as an end user with CA issued certificate can masquerade themselves as an SA by generating a signature with signing scheme `notary.x509.signingAuthority`. diff --git a/specs/trust-store-trust-policy.md b/specs/trust-store-trust-policy.md index 9978579..53a446e 100644 --- a/specs/trust-store-trust-policy.md +++ b/specs/trust-store-trust-policy.md @@ -25,7 +25,7 @@ Contains a set of trusted identities through which trust is derived for the rest - Following certificate formats are supported - Files with extension .pem, .crt and .cer, the files are expected to contain certificate(s) in DER (binary) format or PEM format (base-64 encoded DER). - The trust store is a directory location, under which each sub directory is considered a named store, that contains zero or more certificates. The name of this sub directory is used to reference the specific store in trust policy. - Symlinks are not supported for the named store directories or certificate files. Implementation MUST validate that the named store directory or certificate files are not symlinks, and fail if it does not meet this condition. -- Certificates in a trust store are root certificates. Placing intermediate certificates in the trust store is not recommended this is a form of certificate pinning that can break signature verification unexpectedly anytime the intermediate certificate is rotated. +- Certificates in a trust store are root certificates. Placing intermediate certificates in the trust store is not recommended as this is a form of certificate pinning that can break signature verification unexpectedly anytime the intermediate certificate is rotated. The Notary Project uses following directory structure to represent the trust store. The example shows named stores `acme-rockets` and `wabbit-networks`, which are subsequently references in the trust policy. Without this reference, presence of a named store and certificates in it does not confer trust automatically to the named store. The trust store is configured ahead of verification time, by an out of band mechanism that is beyond the scope of this document. Different entities and organizations have their own processes and policies to configure and distribute trust stores. @@ -47,14 +47,14 @@ $XDG_CONFIG_HOME/notation/trust-store cert10.pem /tsa /publicly-trusted-tsa - tsa-cert1.pem + tsa-root.pem ``` -The Trust store currently supports three kinds of identities, additional identities may be supported in future : +The Trust store currently supports three kinds of identities, additional identities may be supported in future: - **Certificates**: The `x509/ca` trust store contains named stores that contain Certificate Authority (CA) root certificates. - **SigningAuthority Certificate**: The `x509/signingAuthority` trust store contains named stores that contain Signing Authority's root certificates. -- **Timestamping Certificates**: The `x509/tsa` trust store contains named stores with Time Stamping Authority (TSA) root certificates. +- **Timestamping Certificates**: The `x509/tsa` trust store contains named stores that contain Timestamping Authority (TSA) root certificates. Any additional sub directories under a named store and certificates in it are ignored. **NOTE**: Implementation SHOULD warn if it finds sub directories with certificates under a named store, to help diagnose misconfigured store. @@ -81,9 +81,10 @@ Users who consume signed artifacts from OCI registries, or signed arbitrary blob An *object* that specifies a predefined verification level, with an option to override the Notary Project trust policy defined verification level if user wants to specify a [custom verification level](#custom-verification-level). - **`level`**(*string*): A REQUIRED property that specifies the verification level, supported values are `strict`, `permissive`, `audit` and `skip`. Detailed explanation of each level is present [here](#signatureverification-details). - **`override`**(*map of string-string*): This OPTIONAL map is used to specify a [custom verification level](#custom-verification-level). - - **`trustStores`**(*array of string*): This REQUIRED property specifies a set of one or more named trust stores, each of which contain the trusted roots against which signatures are verified. Each named trust store uses the format `{trust-store-type}:{named-store}`. Currently supported values for `trust-store-type` are `ca`, `signingAuthority` and `tsa`. For publicly trusted TSA, `tsa:publicly-trusted-tsa` is the default value, and implied without explicitly specifying it. If a custom TSA is used the format `ca:acme-rockets,tsa:acme-tsa` is supported to specify it. - - **`trustedIdentities`**(*array of strings*): This REQUIRED property specifies a set of identities that the user trusts. For X.509 PKI, it supports list of elements/attributes of the signing certificate's subject. For more information, see [identities constraints](#trusted-identities-constraints) section. A value `*` is supported if user trusts any identity (signing certificate) issued by the CA(s) in `trustStore`. - + - **`verifyTimestamp`**(*string*): An OPTIONAL property that specifies timestamp verification configuration. Supported values are `always` and `afterCertExpiry`. The default value is `always`, which means always verify timestamp countersignature. `afterCertExpiry` means only verify timestamp countersignature if at least one certificate in the signing certificate chain has expired at the time of verification. + - **`trustStores`**(*array of string*): This REQUIRED property specifies a set of one or more named trust stores, each of which contain the trusted roots against which signatures are verified. Each named trust store uses the format `{trust-store-type}:{named-store}`. Currently supported values for `trust-store-type` are `ca`, `signingAuthority` and `tsa`. To enable timestamp verification, type `tsa` MUST be configured. + - **`trustedIdentities`**(*array of strings*): This REQUIRED property specifies a set of identities that the user trusts. For X.509 PKI, it supports list of elements/attributes of the signing certificate's subject. For more information, see [identities constraints](#trusted-identities-constraints) section. A value `*` is supported if user trusts any identity (signing certificate) issued by the CA(s) in `trustStore`. This field only contains trusted identities issued by CA(s) or Signing Authorities. + #### Blob Trust Policy ##### Version 1.0 @@ -95,9 +96,10 @@ Users who consume signed artifacts from OCI registries, or signed arbitrary blob An *object* that specifies a predefined verification level, with an option to override the Notary Project trust policy defined verification level if user wants to specify a [custom verification level](#custom-verification-level). - **`level`**(*string*): A REQUIRED property that specifies the verification level, supported values are `strict`, `permissive`, `audit` and `skip`. Detailed explanation of each level is present [here](#signatureverification-details). - **`override`**(*map of string-string*): This OPTIONAL map is used to specify a [custom verification level](#custom-verification-level). + - **`verifyTimestamp`**(*string*): An OPTIONAL property that specifies timestamp verification configuration. Supported values are `always` and `afterCertExpiry`. The default value is `always`, which means always verify timestamp countersignature. `afterCertExpiry` means only verify timestamp countersignature if at least one certificate in the signing certificate chain has expired at the time of verification. - **`globalPolicy`**(*boolean*): This OPTIONAL property flags the policy as the global trust policy if set to `true`. This policy will be used for verification if the user does not select any policy by its name during verification. - - **`trustStores`**(*array of string*): This REQUIRED property specifies a set of one or more named trust stores, each of which contain the trusted roots against which signatures are verified. Each named trust store uses the format `{trust-store-type}:{named-store}`. Currently supported values for `trust-store-type` are `ca`, `signingAuthority` and `tsa`. For publicly trusted TSA, `tsa:publicly-trusted-tsa` is the default value, and implied without explicitly specifying it. If a custom TSA is used the format `ca:acme-rockets,tsa:acme-tsa` is supported to specify it. - - **`trustedIdentities`**(*array of strings*): This REQUIRED property specifies a set of identities that the user trusts. For X.509 PKI, it supports list of elements/attributes of the signing certificate's subject. For more information, see [identities constraints](#trusted-identities-constraints) section. A value `*` is supported if user trusts any identity (signing certificate) issued by the CA(s) in `trustStore`. + - **`trustStores`**(*array of string*): This REQUIRED property specifies a set of one or more named trust stores, each of which contain the trusted roots against which signatures are verified. Each named trust store uses the format `{trust-store-type}:{named-store}`. Currently supported values for `trust-store-type` are `ca`, `signingAuthority` and `tsa`. To enable timestamp verification, type `tsa` MUST be configured. + - **`trustedIdentities`**(*array of strings*): This REQUIRED property specifies a set of identities that the user trusts. For X.509 PKI, it supports list of elements/attributes of the signing certificate's subject. For more information, see [identities constraints](#trusted-identities-constraints) section. A value `*` is supported if user trusts any identity (signing certificate) issued by the CA(s) in `trustStore`. This field only contains trusted identities issued by CA(s) or Signing Authorities. ### Trust Policy Examples @@ -142,7 +144,7 @@ Users who consume signed artifacts from OCI registries, or signed arbitrary blob "signatureVerification": { "level" : "strict" }, - "trustStores": ["wabbit-networks"], + "trustStores": ["ca:wabbit-networks"], "trustedIdentities": [ "x509.subject: C=US, ST=WA, L=Seattle, O=wabbit-networks.io, OU=Security Tools" ] @@ -188,6 +190,28 @@ Users who consume signed artifacts from OCI registries, or signed arbitrary blob } ``` +3. Trust policy for a scenario where ACME Rockets consumes some OCI artifacts signed by Wabbit Networks with timestamp countersignature. + +```jsonc +{ + "version": "1.0", + "trustPolicies": [ + { + "name": "wabbit-networks-images", + "registryScopes": [ "*" ], + "signatureVerification": { + "level" : "strict", + "verifyTimestamp": "afterCertExpiry" // Only verify any timestamp countersignature when codesigning certificate chain has expired + }, + "trustStores": ["ca:acme-rockets", "tsa:trusted-tsa"], // The trust store type `tsa` MUST be configured to enable timestamp verification. + "trustedIdentities": [ + "x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder" + ] + } + ] +} +``` + #### Trust Policy for Blobs 1. Trust policy for the scenario where ACME Rockets consumes arbitrary blobs signed by Wabbit Networks and some signed by ACME Rockets. @@ -237,12 +261,33 @@ Users who consume signed artifacts from OCI registries, or signed arbitrary blob } ``` +2. Trust policy for the scenario where ACME Rockets consumes arbitrary blobs signed by Wabbit Networks with timestamp countersignature. + +```jsonc +{ + "version": "1.0", + "trustPolicies": [ + { + "name": "wabbit-networks-blobs", + "signatureVerification": { + "level" : "strict", + "verifyTimestamp": "afterCertExpiry" // Only verify any timestamp countersignature when codesigning certificate chain has expired + }, + "trustStores": ["ca:acme-rockets", "tsa:trusted-tsa"], // The trust store type `tsa` MUST be configured to enable timestamp verification. + "trustedIdentities": [ + "x509.subject: C=US, ST=WA, L=Seattle, O=acme-rockets.io, OU=Finance, CN=SecureBuilder" + ] + } + ] +} +``` + #### Signature Verification details - Signature verification is a multi step process performs the following validations - integrity (artifact is unaltered, signature is not corrupted) - authenticity (the signature is really from the identity that claims to have signed it) - - trusted timestamping (the signature was generated when the key/certificate were unexpired) + - authentic timestamp (the signature was generated when the certificate was unexpired) - expiry (an optional check if the artifact specifies an expiry time) - revocation check (is the signing identity still trusted at the present time). - Based on the signature verification level, each of these validations is *enforced* or *logged*. @@ -273,19 +318,17 @@ The following table shows the resultant validation action, either *enforced* (ve **Authentic timestamp** : Guarantees that the signature was generated when the certificate was valid. It also allows a verifier to determine if a signature must be treated as valid or invalid based on whether the signature was generated before or after the certificate revocation. In the absence of an Authentic Timestamp, a signature is considered invalid if the signing certificate or chain is either expired or revoked. -- **NOTE**: `notation` RC1 will generate trusted timestamp using a TSA when the signature is generated, but will not support verification of TSA countersignatures. Related issue - [#59](https://github.com/notaryproject/roadmap/issues/59). - **Expiry** : This is an optional feature that guarantees that artifact is within “best by use” date indicated in the signature. Notary Project allows users to include an optional expiry time when they generate a signature. The expiry time is not set by default and requires explicit configuration by users at the time of signature generation. The artifact is considered expired when the current time is greater than or equal to expiry time, users performing verification can either configure their trust policies to fail the verification or even accept the artifact with expiry date in the past using policy. This is an advanced feature that allows implementing controls for user defined semantics like deprecation for older artifacts, or block older artifacts in a production environment. Users should only include an expiry time in the signed artifact after considering the behavior they expect for consumers of the artifact after it expires. Users can choose to consume an artifact even after the expiry time based on their specific needs. **Revocation check** : Guarantees that the signing identity is still trusted at signature verification time. Events such as key or system compromise can make a signing identity that was previously trusted, to be subsequently untrusted. This guarantee typically requires a verification-time call to an external system, which may not be consistently reliable. The `permissive` verification level only logs failures of revocation check and does not enforce it. If a particular revocation mechanism is reliable, use `strict` verification level instead. -#### Custom Verification Level +##### Custom Verification Level Signature verification levels provide defined behavior for each validation e.g. `strict` will always *enforce* authenticity validation. For fine grained control over validations that occur during signature verification, users can define a custom level which overrides the behavior of an existing verification level. - To use this feature, the `level` property MUST be specified along with an OPTIONAL `override` map. - Supported values for `level` are - `strict`, `permissive` and `audit`. A `skip` level cannot be customized. -- Supported keys for `override` map and their supported values are as follows. +- Supported keys for `override` map and their supported values are as follows: - `integrity` validation cannot be overriden, and therefore cannot be specified as a key. - `authenticity` - Supported values are `enforce` and `log`. - `authenticTimestamp` - Supported values are `enforce` and `log`. @@ -301,6 +344,51 @@ Signature verification levels provide defined behavior for each validation e.g. } ``` +#### Timestamp Countersignature Verification details + +Sufficient and necessary conditions to trigger timestamp countersignature verification: + - As the overall switch, `authenticTimestamp` under `signatureVerification` of trust policy is NOT marked as `skip`. + - The signing scheme is [`notary.x509`](./signing-scheme.md/#notaryx509). + - `tsa` trust store type is configured under `trustStores` field of the corresponding trust policy statement. + - `verifyTimestamp` under `signatureVerification` of trust policy is not set or set to `always`; OR it's set to `afterCertExpiry` and at least one certificate in the signing certificate chain has expired at the time of verification. + +See the flow chart below for a better understanding: +```mermaid +flowchart TD; + A{Authentic timestamp}; + B{Signing scheme}; + C{`tsa` trust store configured}; + D{`verifyTimestamp`}; + E{Signing cert chain expired}; + R1[Trigger timestamp verification]; + R2[No timestamp verification]; + + A --> |Not skip| B + A --> |Skip| R2 + B --> |notary.x509| C + B --> |notary.x509.signingAuthority| R2 + C --> |Yes| D + C --> |No| R2 + D --> |Not set or `always`| R1 + D --> |`afterCertExpiry`| E + E --> |Yes| R1 + E --> |No| R2 +``` + +Timestamp countersignature verification is a multi step process performs the following validations + - existence (timestamp token is present in the signature envelope) + - integrity (timestamp token is unaltered, countersignature is not corrupted) + - authenticity (the timestamp token is really from the TSA that claims to have signed it) + - revocation check (is the TSA still trusted at the time of verification) + + **Existence** : Guarantees that the timestamp token exists in the signature envelope. It is always enforced when timestamp countersignature verification is triggered. + + **Integrity** : Guarantees that the timestamp token wasn't altered after it was signed, or the countersignature isn't corrupted. It is always enforced when timestamp countersignature verification is triggered. + + **Authenticity** : Guarantees that the timestamp was issued by a trusted TSA identity. Its definition does not include revocation, which is when a trusted TSA is subsequently untrusted because of a compromise. It is always enforced when timestamp countersignature verification is triggered. + + **Revocation check** : Guarantees that the TSA identity is still trusted at verification time. Events such as key or system compromise can cause a previously trusted TSA identity to become untrusted. It is always enforced when timestamp countersignature verification is triggered. + #### Trust Policy Constraints ##### OCI Trust Policy Constraints @@ -393,7 +481,7 @@ Notary Project allows user to execute custom validations during verification usi 1. `enforced` - validation failures are treated as critical, causes the overall signature verification to fail and exit. Subsequent validations are not processed. 1. `logged` - validation failure is logged and the next validation step is processed. 1. A signature verification is considered successful when all validation steps are completed without critical failure. -1. **Validate Integrity.** +1. **Validate Integrity:** 1. Validate signature envelope 1. For OCI artifacts, validate that signature envelope can be parsed successfully based on the signature envelope type specified in the `blobs[0].mediaType` attribute of the signature artifact manifest. 1. For Blob artifacts, validate that signature envelope can be parsed successfully based on the signature envelope type specified in the detached signature file extension. If no file extension is available, parse the envelope type by trying each of the [supported signature envelopes](./signature-specification.md#supported-signature-envelopes). Fail integrity check if unsuccessful. @@ -414,25 +502,32 @@ Notary Project allows user to execute custom validations during verification usi 1. Else validate if the X.509 subject (`x509.subject`) in the `trustedIdentities` list matches with the value of corresponding attributes in the signing certificate’s subject, refer [this section](#trusted-identities-constraints) for details. If a match is not found, fail this step. 1. **Validate Expiry:** 1. If an `expiry time` signed attribute is present in the signature envelope, check if the local machine’s current time(in UTC) is greater than `expiry time`. If yes, fail this step. -1. **Validate Trusted Timestamp:** - 1. Check for the timestamp signature in the signature envelope. - 1. If the timestamp exists, continue with the next step. - Otherwise, store the local machine's current time(in UTC) in variables `timeStampLowerLimit` and `timeStampUpperLimit` and continue with step 6.2. - 1. Validate that the timestamp hash in `TSTInfo.messageImprint` matches the hash of the signature to which the timestamp was applied. - 1. Validate that the timestamp signing certificate satisfies [certificate requirements](./signature-specification.md#certificate-requirements). - 1. Validate that the timestamp signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). - 1. Validate the `signing-certificate`([RFC-2634](https://tools.ietf.org/html/rfc2634)) or `signing-certificate-v2`([RFC-5126](https://tools.ietf.org/html/rfc5126#section-5.7.3.2)) attribute of timestamp CMS. - 1. Validate that timestamp certificate and certificate chain leads to a trusted TSA certificate as per value configured in `trustStore`. - 1. Validate timestamp certificate and certificate chain revocation status using [certificate revocation evaluation](#certificate-revocation-evaluation) section. - 1. Retrieve the timestamp's time from `TSTInfo.genTime`. - 1. Retrieve the timestamp's accuracy. - If the accuracy is explicitly specified in `TSTInfo.accuracy`, use that value. - If the accuracy is not explicitly specified and `TSTInfo.policy` is the baseline time-stamp policy([RFC-3628](https://tools.ietf.org/html/rfc3628#section-5.2)), use accuracy of 1 second. - Otherwise, use an accuracy of 0. - 1. Calculate the timestamp range using the lower and upper limits per [RFC-3161 section 2.4.2](https://tools.ietf.org/html/rfc3161#section-2.4.2) and store the limits as `timeStampLowerLimit` and `timeStampUpperLimit` variables respectively. - 1. Validate that the time range from `timeStampLowerLimit` to `timeStampUpperLimit` timestamp is entirely within the signing certificate and certificate chain's validity period. If the validation passes, continue to the next step. Else fail this step. +1. **Validate Authentic Timestamp:** + 1. If under signing scheme [`notary.x509`](./signing-scheme.md/#notaryx509): + 1. If [`sufficient and necessary conditions to trigger timestamp countersignature verification`](./trust-store-trust-policy.md/#timestamp-countersignature-verification-details) are satisfied, perform timestamp countersignature verification: + 1. Check the unsigned attribute `Timestamp Signature`, if not present or empty, fail this step. + 1. Verify the timestamp countersignature and validate the `TSTInfo` based on [RFC 3161](https://datatracker.ietf.org/doc/html/rfc3161) and [RFC-5816](https://datatracker.ietf.org/doc/html/rfc5816). + 1. Validate that the timestamp hash in `TSTInfo.messageImprint` matches the hash of the signature to which the timestamp was applied. + 1. Validate that the timestamp signing certificate satisfies [certificate requirements](./signature-specification.md#certificate-requirements). + 1. Validate that the timestamp signing algorithm satisfies [algorithm requirements](./signature-specification.md#signature-algorithm-requirements). + 1. Validate the `signing-certificate-v2` ([RFC-5126](https://tools.ietf.org/html/rfc5126#section-5.7.3.2)) attribute of timestamp CMS. When missing, fail this step. + 1. Validate that the timestamp certificate chain leads to a trusted root certificate as per setting in `trustStore` with trust store type `tsa` in trust policy. + 1. Validate timestamp certificate chain revocation status using [certificate revocation evaluation](#certificate-revocation-evaluation) section. + 1. Retrieve the timestamp's time from `TSTInfo.genTime`. + 1. Retrieve the timestamp's accuracy. + If the accuracy is explicitly specified in `TSTInfo.accuracy`, use that value. + If the accuracy is not explicitly specified and `TSTInfo.policy` is the baseline time-stamp policy([RFC-3628](https://tools.ietf.org/html/rfc3628#section-5.2)), use accuracy of 1 second. + Otherwise, use an accuracy of 0. + 1. Calculate the timestamp range using the lower and upper limits per [RFC 3161 section 2.4.2](https://tools.ietf.org/html/rfc3161#section-2.4.2) and store the limits as `timeStampLowerLimit` and `timeStampUpperLimit` variables respectively. + 1. Validate that the time range from `timeStampLowerLimit` to `timeStampUpperLimit` is entirely within the signing certificate chain's validity period. If the validation passes, continue to the next validation (Validate Revocation Status). Else fail this step. + 1. If step 6.i.a is not performed. Validate that the local machine's current time (in UTC) is within the signing certificate chain's validity period. If the validation passes, continue to the next validation (Validate Revocation Status). Else fail this step. + + 1. If under signing scheme [`notary.x509.signingAuthority`](./signing-scheme.md/#notaryx509signingauthority): + 1. Check for the `Authentic Signing Time` signed attribute. If it does not exist, fail this step. + 1. Validate that the `Authentic Signing Time` is within the signing certificate chain's validity period. If the validation passes, continue to the next validation (Validate Revocation Status). Else fail this step. + 1. **Validate Revocation Status:** - 1. Validate signing identity(certificate and certificate chain) revocation status using [certificate revocation evaluation](#certificate-revocation-evaluation) section as per `signingIdentityRevocation` setting in trust-policy. + 1. Validate signing identity(certificate and certificate chain) revocation status using [certificate revocation evaluation](#certificate-revocation-evaluation) section as per `revocation` setting in trust policy. 1. Perform extended validation using the applicable (if any) plugin. 1. If present, verify the user provided metadata/custom annotations match the signed attributes present in the signature envelope. 1. If all the steps are completed without critical failures then the signatures is successfully verified. @@ -523,7 +618,7 @@ To check the revocation status of a certificate using OCSP, the following steps Response is considered expired if the current date is after the `NextUpdate` field in the response. 1. Verify that the OCSP response indicates that the certificate is not revoked i.e `CertStatus` is `good`. 1. If the certificate is revoked i.e `CertStatus` is `revoked`, look for `InvalidityDate`. - 1. If the invalidity date is present and timestamp signature is also present then if the invalidity date is before the timestamping date, the certificate is considered revoked. + 1. If the invalidity date is present and the authentic signing time is also present then if the invalidity date is before the authentic signing time, the certificate is considered revoked. 1. If the invalidity date is not present in OCSP response, the certificate is considered revoked. 1. If the certificate status is `unknown`, the revocation status is considered `revocation unavailable`. 1. If `id-pkix-ocsp-nocheck`(1.3.6.1.5.5.7.48.1.5) extension is not present on the OCSP signing certificate then revocation checking must be performed using CRLs for the OCSP signing certificate.