diff --git a/draft-ietf-httpbis-http2-secondary-certs.md b/draft-ietf-httpbis-http2-secondary-certs.md index 929139e1d..bb9ea079a 100644 --- a/draft-ietf-httpbis-http2-secondary-certs.md +++ b/draft-ietf-httpbis-http2-secondary-certs.md @@ -253,13 +253,16 @@ This could be done in a naive manner by replicating the TLS messages as HTTP/2 frames on each stream. However, this would create needless redundancy between streams and require frequent expensive signing operations. Instead, TLS Exported Authenticators [I-D.ietf-tls-exported-authenticator] are exchanged on stream -zero and the on-stream frames incorporate them by reference as needed. +zero and other frames incorporate them to particular requests by reference as +needed. TLS Exported Authenticators are structured messages that can be exported by -either party of a TLS connection and validated by the other party. An -authenticator message can be constructed by either the client or the server -given an established TLS connection, a certificate, and a corresponding private -key. Exported Authenticators use the message structures from section 4.4 of +either party of a TLS connection and validated by the other party. Given an +established TLS connection, a request can be constructed which describes the +desired certificate and an authenticator message can be constructed proving +possession of a certificate and a corresponding private key. Both requests and +authenticators can be generated by either the client or the server. Exported +Authenticators use the message structures from sections 4.3.2 and 4.4 of [I-D.ietf-tls-tls13], but different parameters. Each Authenticator is computed using a Handshake Context and Finished MAC Key @@ -270,9 +273,7 @@ whether the Authenticator is created by the client or the server. Successfully verified Authenticators result in certificate chains, with verified possession of the corresponding private key, which can be supplied into a collection of available certificates. Likewise, descriptions of desired -certificates can be supplied into these collections. These pre-supplied elements -are then available for automatic use (in some situations) or for reference by -individual streams. +certificates can be supplied into these collections. {{discovery}} describes how the feature is employed, defining means to detect support in peers ({{setting}}), make certificates and requests available @@ -293,22 +294,23 @@ when, and only when, they appear in all capitals, as shown here. # Discovering Additional Certificates at the HTTP/2 Layer {#discovery} A certificate chain with proof of possession of the private key corresponding to -the end-entity certificate is sent as a single `CERTIFICATE` frame (see +the end-entity certificate is sent as a sequence of `CERTIFICATE` frames (see {{http-cert}}) on stream zero. Once the holder of a certificate has sent the chain and proof, this certificate chain is cached by the recipient and available -for future use. If the certificate is marked as `AUTOMATIC_USE`, the certificate -may be used by the recipient to authorize any current or future request. -Otherwise, the recipient requests the required certificate on each stream, but -the previously-supplied certificates are available for reference without having +for future use. Clients can proactively indicate the certificate they intend to +use on each request using an unsolicited `USE_CERTIFICATE` frame, if desired. +The previously-supplied certificates are available for reference without having to resend them. -Likewise, the details of a request are sent on stream zero and stored by the -recipient. These details will be referenced by subsequent `CERTIFICATE_NEEDED` -frames. +Otherwise, the server uses a `CERTIFICATE_REQUEST` frame to describe a class of +certificates on stream zero, then uses `CERTIFICATE_NEEDED` frames to associate +these with individual requests. The client responds with a `USE_CERTIFICATE` +frame indicating the certificate which should be used to satisfy the request. Data sent by each peer is correlated by the ID given in each frame. This ID is unrelated to values used by the other peer, even if each uses the same ID in -certain cases. +certain cases. `USE_CERTIFICATE` frames indicate whether they are sent +proactively or are in response to a `CERTIFICATE_NEEDED` frame. ## Indicating support for HTTP-layer certificate authentication {#setting} @@ -322,21 +324,21 @@ does support HTTP-layer certificate authentication, the value is 1. ## Making certificates or requests available {#cert-available} -When a peer has advertised support for HTTP-layer certificates as in +When both peers have advertised support for HTTP-layer certificates as in {{setting}}, either party can supply additional certificates into the connection -at any time. These certificates then become available for the peer to consider -when deciding whether a connection is suitable to transport a particular -request. +at any time. This means that clients or servers which predict a certificate will +be required could supply the certificate before being asked. These +certificates are available for reference by future `USE_CERTIFICATE` frames. -Available certificates which have the `AUTOMATIC_USE` flag set MAY be used by -the recipient without further notice. This means that clients or servers which -predict a certificate will be required could pre-supply the certificate without -being asked. Regardless of whether `AUTOMATIC_USE` is set, these certificates -are available for reference by future `USE_CERTIFICATE` frames. +Certificates supplied by servers can be considered by clients without further +action by the server. A server SHOULD NOT send certificates which do not cover +origins which it is prepared to service on the current connection, but MAY use +the ORIGIN frame {{?RFC8336}} to indicate that not all covered origins will be +served. ~~~ Client Server - <-------- (stream 0) CERTIFICATE (AU flag) -- + <------------------ (stream 0) CERTIFICATE -- ... -- (stream N) GET /from-new-origin ---------> <----------------------- (stream N) 200 OK -- @@ -346,7 +348,9 @@ Client Server ~~~ Client Server - -- (stream 0) CERTIFICATE (AU flag) --------> + -- (stream 0) CERTIFICATE ------------------> + -- (stream 0) USE_CERTIFICATE (S=1) --------> + -- (stream 0) USE_CERTIFICATE (S=3) --------> -- (streams 1,3) GET /protected ------------> <-------------------- (streams 1,3) 200 OK -- @@ -354,13 +358,15 @@ Client Server {: #ex-http2-client-proactive title="Proactive Client Certificate"} Likewise, either party can supply a `CERTIFICATE_REQUEST` that outlines -parameters of a certificate they might request in the future. It is important -to note that this does not currently request such a certificate, but makes the -contents of the request available for reference by a future `CERTIFICATE_NEEDED` -frame. +parameters of a certificate they might request in the future. Upon receipt of a +`CERTIFICATE_REQUEST`, servers SHOULD provide a corresponding certificate. +Clients MAY wait for a `CERTIFICATE_NEEDED` frame to assist in associating the +certificate request with a particular HTTP transition. ## Requiring certificate authentication {#cert-challenge} +### Requiring additional server certificates + As defined in [RFC7540], when a client finds that a https:// origin (or Alternative Service [RFC7838]) to which it needs to make a request has the same IP address as a server to which it is already connected, it MAY check whether @@ -370,72 +376,54 @@ the connection. If the TLS certificate does not contain the new origin, but the server has claimed support for that origin (with an ORIGIN frame, see [I-D.ietf-httpbis-origin-frame]) and advertised support for HTTP-layer -certificates (see {{setting}}), it MAY send a `CERTIFICATE_NEEDED` frame on the -stream it will use to make the request. (If the request parameters have not -already been made available using a `CERTIFICATE_REQUEST` frame, the client will -need to send the `CERTIFICATE_REQUEST` in order to generate the -`CERTIFICATE_NEEDED` frame.) The stream represents a pending request to that -origin which is blocked until a valid certificate is processed. - -The request is blocked until the server has responded with a `USE_CERTIFICATE` -frame pointing to a certificate for that origin. If the certificate is already -available, the server SHOULD immediately respond with the appropriate -`USE_CERTIFICATE` frame. (If the certificate has not already been transmitted, -the server will need to make the certificate available as described in -{{cert-available}} before completing the exchange.) - -If the server does not have the desired certificate, it MUST respond with an -empty `USE_CERTIFICATE` frame. In this case, or if the server has not advertised -support for HTTP-layer certificates, the client MUST NOT send any requests for -resources in that origin on the current connection. +certificates (see {{setting}}), the client MAY send a `CERTIFICATE_REQUEST` +frame describing the desired origin. Servers SHOULD provide a corresponding +certificate if one is available. + +If the server does not have the desired certificate, it MUST \[see issue #564]. +In this case, or if the server has not advertised support for HTTP-layer +certificates, the client MUST NOT send any requests for resources in that origin +on the current connection. ~~~ Client Server <----------------------- (stream 0) ORIGIN -- -- (stream 0) CERTIFICATE_REQUEST ----------> - ... - -- (stream N) CERTIFICATE_NEEDED -----------> <------------------ (stream 0) CERTIFICATE -- - <-------------- (stream N) USE_CERTIFICATE -- -- (stream N) GET /from-new-origin ---------> <----------------------- (stream N) 200 OK -- - ~~~ {: #ex-http2-server-requested title="Client-Requested Certificate"} -Likewise, on each stream where certificate authentication is required, the -server sends a `CERTIFICATE_NEEDED` frame, which the client answers with a -`USE_CERTIFICATE` frame indicating the certificate to use. If the request -parameters or the responding certificate are not already available, they will -need to be sent as described in {{cert-available}} as part of this exchange. +Likewise, the server sends a `CERTIFICATE_NEEDED` frame for each stream where +certificate authentication is required. The client answers with a +`USE_CERTIFICATE` frame indicating the certificate to use on that stream. If the +request parameters or the responding certificate are not already available, they +will need to be sent as described in {{cert-available}} as part of this +exchange. ~~~ Client Server <---------- (stream 0) CERTIFICATE_REQUEST -- ... -- (stream N) GET /protected ---------------> - <----------- (stream N) CERTIFICATE_NEEDED -- + <----- (stream 0) CERTIFICATE_NEEDED (S=N) -- -- (stream 0) CERTIFICATE ------------------> - -- (stream N) USE_CERTIFICATE --------------> + -- (stream 0) USE_CERTIFICATE (S=N) --------> <----------------------- (stream N) 200 OK -- - ~~~ {: #ex-http2-client-requested title="Reactive Certificate Authentication"} -A server SHOULD provide certificates for an origin before pushing resources from -it or supplying content referencing the origin. If a client receives a -`PUSH_PROMISE` referencing an origin for which it has not yet received the -server's certificate, the client MUST verify the server's possession of an -appropriate certificate by sending a `CERTIFICATE_NEEDED` frame on the pushed -stream to inform the server that progress is blocked until the request is -satisfied. The client MUST NOT use the pushed resource until an appropriate -certificate has been received and validated. +If a client receives a `PUSH_PROMISE` referencing an origin for which it has not +yet received the server's certificate, this is a fatal connection error (see +section 8.2 of [RFC7540]). To avoid this, servers MUST supply the associated +certificates before pushing resources from a different origin. # Certificates Frames for HTTP/2 {#certs-http2} The `CERTIFICATE_REQUEST` and `CERTIFICATE_NEEDED` frames are correlated by their `Request-ID` field. Subsequent `CERTIFICATE_NEEDED` frames with the same -`Request-ID` value MAY be sent on other streams where the sender is expecting a +`Request-ID` value MAY be sent for other streams where the sender is expecting a certificate with the same parameters. The `CERTIFICATE`, and `USE_CERTIFICATE` frames are correlated by their @@ -443,70 +431,133 @@ The `CERTIFICATE`, and `USE_CERTIFICATE` frames are correlated by their be sent in response to other `CERTIFICATE_NEEDED` frames and refer to the same certificate. -`Request-ID` and `Cert-ID` are sender-local, and the use of the same value by -the other peer does not imply any correlation between their frames. These values -MUST be unique per sender over the lifetime of the connection. +`CERTIFICATE_NEEDED` and `USE_CERTIFICATE` frames are correlated by the Stream +ID they reference. Unsolicited `USE_CERTIFICATE` frames are not responses to +`CERTIFICATE_NEEDED` frames; otherwise, each `USE_CERTIFICATE` frame for a +stream is considered to respond to a `CERTIFICATE_NEEDED` frame for the same +stream in sequence. + +~~~ drawing + +---------+ +---------+ + | REQUEST | | CERT | + +---------+ +---------+ + | | + | Request-ID | Cert-ID + | | + v v + +---------+ Stream ID +---------+ + | NEEDED |---------->| USE | + +---------+ +---------+ +~~~ +{: #frame-relationships title="Frame correlation"} + +`Request-ID` and `Cert-ID` are independent and sender-local. The use of the +same value by the other peer or in the other context does not imply any +correlation between these frames. These values MUST be unique per sender for +each space over the lifetime of the connection. ## The CERTIFICATE_NEEDED frame {#http-cert-needed} -The `CERTIFICATE_NEEDED` frame (0xFRAME-TBD1) is sent to indicate that the HTTP -request on the current stream is blocked pending certificate authentication. The -frame includes a request identifier which can be used to correlate the stream -with a previous `CERTIFICATE_REQUEST` frame sent on stream zero. The -`CERTIFICATE_REQUEST` describes the certificate the sender requires to make -progress on the stream in question. +The `CERTIFICATE_NEEDED` frame (0xFRAME-TBD1) is sent on stream zero to indicate +that the HTTP request on the indicated stream is blocked pending certificate +authentication. The frame includes stream ID and a request identifier which can +be used to correlate the stream with a previous `CERTIFICATE_REQUEST` frame sent +on stream zero. The `CERTIFICATE_REQUEST` describes the certificate the sender +requires to make progress on the stream in question. + +~~~~~~~~~~~~~~~ + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +---------------------------------------------------------------+ + |R| Stream ID (31) | + +-------------------------------+-------------------------------+ + | Request-ID (16) | + +-------------------------------+ +~~~~~~~~~~~~~~~ +{: #fig-cert-needed title="CERTIFICATE_NEEDED frame payload"} -The `CERTIFICATE_NEEDED` frame contains 2 octets, which is the authentication -request identifier, `Request-ID`. A peer that receives a `CERTIFICATE_NEEDED` of -any other length MUST treat this as a stream error of type `PROTOCOL_ERROR`. -Frames with identical request identifiers refer to the same -`CERTIFICATE_REQUEST`. +The `CERTIFICATE_NEEDED` frame contains 6 octets. The first four octets +indicate the Stream ID of the affected stream. The following two octets are the +authentication request identifier, `Request-ID`. A peer that receives a +`CERTIFICATE_NEEDED` of any other length MUST treat this as a stream error of +type `PROTOCOL_ERROR`. Frames with identical request identifiers refer to the +same `CERTIFICATE_REQUEST`. -A server MAY send multiple `CERTIFICATE_NEEDED` frames on the same stream. If a +A server MAY send multiple `CERTIFICATE_NEEDED` frames for the same stream. If a server requires that a client provide multiple certificates before authorizing a single request, each required certificate MUST be indicated with a separate `CERTIFICATE_NEEDED` frame, each of which MUST have a different request identifier (referencing different `CERTIFICATE_REQUEST` frames describing each required certificate). To reduce the risk of client confusion, servers SHOULD -NOT have multiple outstanding `CERTIFICATE_NEEDED` frames on the same stream at +NOT have multiple outstanding `CERTIFICATE_NEEDED` frames for the same stream at any given time. -Clients MUST NOT send multiple `CERTIFICATE_NEEDED` frames on the same stream. +Clients MUST NOT send multiple `CERTIFICATE_NEEDED` frames for the same stream. The `CERTIFICATE_NEEDED` frame MUST NOT be sent to a peer which has not advertised support for HTTP-layer certificate authentication. -The `CERTIFICATE_NEEDED` frame MUST NOT be sent on stream zero, and MUST NOT be -sent on a stream in the "half-closed (local)" state [RFC7540]. A client that -receives a `CERTIFICATE_NEEDED` frame on a stream which is not in a valid state -SHOULD treat this as a stream error of type `PROTOCOL_ERROR`. +The `CERTIFICATE_NEEDED` frame MUST NOT reference a stream in the "half-closed +(local)" or "closed" states [RFC7540]. A client that receives a +`CERTIFICATE_NEEDED` frame for a stream which is not in a valid state SHOULD +treat this as a stream error of type `PROTOCOL_ERROR`. ## The USE_CERTIFICATE Frame {#http-use-certificate} -The `USE_CERTIFICATE` frame (0xFRAME-TBD4) is sent in response to a -`CERTIFICATE_NEEDED` frame to indicate which certificate is being used to -satisfy the requirement. +The `USE_CERTIFICATE` frame (0xFRAME-TBD4) is sent on stream zero to indicate +which certificate is being used on a particular request stream. + +The `USE_CERTIFICATE` frame defines a single flag: -A `USE_CERTIFICATE` frame with no payload refers to the certificate provided at -the TLS layer, if any. If no certificate was provided at the TLS layer, the -stream should be processed with no authentication, likely returning an -authentication-related error at the HTTP level (e.g. 403) for servers or routing -the request to a new connection for clients. +UNSOLICITED (0x01): +: Indicates that no `CERTIFICATE_NEEDED` frame has yet been received for this + stream. -Otherwise, the `USE_CERTIFICATE` frame contains the two-octet `Cert-ID` of the +The payload of the `USE_CERTIFICATE` frame is as follows: + +~~~~~~~~~~~~~~~ + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +---------------------------------------------------------------+ + |R| Stream ID (31) | + +-------------------------------+-------------------------------+ + | [Cert-ID (16)] | + +-------------------------------+ +~~~~~~~~~~~~~~~ +{: #fig-use-cert title="USE_CERTIFICATE frame payload"} + +The first four octets indicate the Stream ID of the affected stream. The +following two octets, if present, contain the two-octet `Cert-ID` of the certificate the sender wishes to use. This MUST be the ID of a certificate for which proof of possession has been presented in a `CERTIFICATE` frame. Recipients of a `USE_CERTIFICATE` frame of any other length MUST treat this as a stream error of type `PROTOCOL_ERROR`. Frames with identical certificate identifiers refer to the same certificate chain. -The `USE_CERTIFICATE` frame MUST NOT be sent on stream zero or a stream on which -a `CERTIFICATE_NEEDED` frame has not been received. Receipt of a -`USE_CERTIFICATE` frame in these circumstances SHOULD be treated as a stream -error of type `PROTOCOL_ERROR`. Each `USE_CERTIFICATE` frame should reference a -preceding `CERTIFICATE` frame. Receipt of a `USE_CERTIFICATE` frame before the -necessary frames have been received on stream zero MUST also result in a stream -error of type `PROTOCOL_ERROR`. +A `USE_CERTIFICATE` frame which omits the Cert-ID refers to the certificate +provided at the TLS layer, if any. If no certificate was provided at the TLS +layer, the stream should be processed with no authentication, likely returning +an authentication-related error at the HTTP level (e.g. 403) for servers or +routing the request to a new connection for clients. + +The `UNSOLICITED` flag MAY be set by clients on the first `USE_CERTIFICATE` +frame referring to a given stream. This permits a client to proactively indicate +which certificate should be used when processing a new request. When such an +unsolicited indication refers to a request that has not yet been received, +servers SHOULD cache the indication briefly in anticipation of the request. + +Receipt of more than one unsolicited `USE_CERTIFICATE` frames or an unsolicited +`USE_CERTIFICATE` frame which is not the first in reference to a given stream +MUST be treated as a stream error of type `CERTIFICATE_OVERUSED`. + +Each `USE_CERTIFICATE` frame which is not marked as unsolicited is considered to +respond in order to the `CERTIFICATE_NEEDED` frames for the same stream. If a +`USE_CERTIFICATE` frame is received for which a `CERTIFICATE_NEEDED` frame has +not been sent, this MUST be treated as a stream error of type +`CERTIFICATE_OVERUSED`. + +Receipt of a `USE_CERTIFICATE` frame with an unknown `Cert-ID` MUST result in a +stream error of type `PROTOCOL_ERROR`. The referenced certificate chain needs to conform to the requirements expressed in the `CERTIFICATE_REQUEST` to the best of the sender's ability, or the @@ -575,10 +626,7 @@ end-entity certificate. The `CERTIFICATE` frame defines two flags: -AUTOMATIC_USE (0x01): -: Indicates that the certificate can be used automatically on future requests. - -TO_BE_CONTINUED (0x02): +TO_BE_CONTINUED (0x01): : Indicates that the exported authenticator spans more than one frame. ~~~~~~~~~~~~ @@ -602,16 +650,6 @@ field, permitting them to be associated with each other. Receipt of any `CERTIFICATE` frame with `TO_BE_CONTINUED` unset MUST be treated as a connection error of type `PROTOCOL_ERROR`. -If the `AUTOMATIC_USE` flag is set, the recipient MAY omit sending -`CERTIFICATE_NEEDED` frames on future streams which would require a similar -certificate and use the referenced certificate for authentication without -further notice to the holder. This behavior is optional, and receipt of a -`CERTIFICATE_NEEDED` frame does not imply that previously-presented certificates -were unacceptable, even if `AUTOMATIC_USE` was set. Servers MUST set the -`AUTOMATIC_USE` flag when sending a `CERTIFICATE` frame. A server MUST NOT send -certificates for origins which it is not prepared to service on the current -connection. - Upon receiving a complete series of `CERTIFICATE` frames, the receiver may validate the Exported Authenticator value by using the exported authenticator API. This returns either an error indicating that the message was invalid, or @@ -664,6 +702,9 @@ CERTIFICATE_EXPIRED (0xERROR-TBD4): CERTIFICATE_GENERAL (0xERROR-TBD5): : Any other certificate-related error +CERTIFICATE_OVERUSED (0xERROR-TBD6): +: More certificates were used on a request than were requested + As described in [RFC7540], implementations MAY choose to treat a stream error as a connection error at any time. Of particular note, a stream error cannot occur on stream 0, which means that implementations cannot send non-session errors in @@ -791,7 +832,7 @@ this document. ## New HTTP/2 Error Codes {#iana-errors} -Five new error codes are registered in the "HTTP/2 Error Code" registry +Six new error codes are registered in the "HTTP/2 Error Code" registry established in [RFC7540]. The entries in the following table are registered by this document. @@ -803,6 +844,7 @@ this document. | CERTIFICATE_REVOKED | 0xERROR-TBD3 | {{errors}} | | CERTIFICATE_EXPIRED | 0xERROR-TBD4 | {{errors}} | | CERTIFICATE_GENERAL | 0xERROR-TBD5 | {{errors}} | +| CERTIFICATE_OVERUSED | 0xERROR-TBD6 | {{errors}} | |-------------------------|--------------|-------------------------| --- back @@ -814,7 +856,8 @@ this document. ## Since draft-ietf-httpbis-http2-secondary-certs-00: -Nothing yet. +- All frames sent on stream zero; replaced `AUTOMATIC_USE` on `CERTIFICATE` with + `UNSOLICITED` on `USE_CERTIFICATE`. (#482,#566) ## Since draft-bishop-httpbis-http2-additional-certs-05: