documentation: Add CUP documentation.
Bug: 1053773 Change-Id: I466d21f7e384a1c68d178bddb9b87f7e87e1575a Fixed: 1053773 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2323583 Reviewed-by: Sorin Jianu <sorin@chromium.org> Commit-Queue: Sorin Jianu <sorin@chromium.org> Auto-Submit: Joshua Pawlicki <waffles@chromium.org> Cr-Commit-Position: refs/heads/master@{#792882}
This commit is contained in:

committed by
Commit Bot

parent
0062f525e7
commit
32ec7d8e9d
docs/updater
134
docs/updater/cup.md
Normal file
134
docs/updater/cup.md
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
# Client Update Protocol (CUP)
|
||||||
|
|
||||||
|
CUP is an HTTP protocol extension used to secure communication with CUP-capable
|
||||||
|
servers when TLS is untrustworthy or impractical for other reasons.
|
||||||
|
|
||||||
|
CUP provides:
|
||||||
|
* Integrity of the client's request body.
|
||||||
|
* Integrity of the server's response body.
|
||||||
|
* Freshness of the server's response body.
|
||||||
|
|
||||||
|
CUP does not provide:
|
||||||
|
* Integrity of the client's request headers or request line.
|
||||||
|
* Integrity of the server's response headers.
|
||||||
|
* Confidentiality of the client's request.
|
||||||
|
* Confidentiality of the server's response.
|
||||||
|
* Freshness of the client's request.
|
||||||
|
|
||||||
|
CUP requires:
|
||||||
|
* Control of both the client and server.
|
||||||
|
|
||||||
|
Current CUP communications are secured by an ECDSA key pair. The client has the
|
||||||
|
public key hardcoded into the application binary. The server signs
|
||||||
|
request-response pairs with the private key, and the client verifies using the
|
||||||
|
public key.
|
||||||
|
|
||||||
|
In Chromium, CUP keys are rotated annually. Each key pair has a corresponding
|
||||||
|
version number. To interoperate with old clients, the server must keep all
|
||||||
|
historical versions of the key, and be prepared to sign with any of them. The
|
||||||
|
client should only keep a single version (whichever was most recent at compile
|
||||||
|
time).
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
### Description
|
||||||
|
The server publishes an elliptic curve field/equation and a public key curve
|
||||||
|
point to be used by the client. In practice, these values are hardcoded into
|
||||||
|
each client at compile time.
|
||||||
|
|
||||||
|
For each request, the client assembles three components:
|
||||||
|
1. The message body (the request body to be sent to the server).
|
||||||
|
2. A small random number to be used as a client nonce for freshness (at least
|
||||||
|
32 bits).
|
||||||
|
3. A code to identify the public key the client will use to verify this
|
||||||
|
request. The client converts the public key id and nonce to a string: the
|
||||||
|
public key is converted to decimal, and the nonce to hexadecimal (lowercase
|
||||||
|
a-f).
|
||||||
|
|
||||||
|
The client stores the request body in a buffer, in UTF-8 format; it
|
||||||
|
appends the keyid/nonce string to this buffer. It calculates a SHA-256 hash of
|
||||||
|
this combined buffer, which it stores for validation later. It sends the
|
||||||
|
request and the keyid/nonce string to the server.
|
||||||
|
|
||||||
|
The server receives the request body, public key id, and nonce; it performs
|
||||||
|
the same appending operation, and computes the SHA-256 hash of the received data
|
||||||
|
buffer.
|
||||||
|
|
||||||
|
The server attempts to find a matching ECDSA private key for the specified
|
||||||
|
public key id, returning an HTTP error if no such private key exists. Finally,
|
||||||
|
it assembles the response body.
|
||||||
|
|
||||||
|
Before sending, the server stores the response body (also in UTF-8) in a
|
||||||
|
buffer. It appends the computed SHA-256 hash of the request body+keyid+nonce to
|
||||||
|
the buffer. It then calculates an ECDSA signature over that combined buffer,
|
||||||
|
using the server’s private key. It sends the ECDSA signature and the response
|
||||||
|
body + client hash back to the user.
|
||||||
|
|
||||||
|
The client receives the response body, observed client hash, and ECDSA signature.
|
||||||
|
The client compares the observed client hash to its stored request hash. If
|
||||||
|
there is a mismatch, then either the request or response have been tampered with
|
||||||
|
and the response is rejected.
|
||||||
|
|
||||||
|
The client concatenates the request hash to the response body, and verifies the
|
||||||
|
signature using its public key. If verification fails, then either the request
|
||||||
|
or response have been tampered with and the response is rejected.
|
||||||
|
|
||||||
|
### HTTP Implementation
|
||||||
|
The request body is a POST body. The key ID and nonce, are transmitted in a
|
||||||
|
query parameter appended to the requested URL, using the format `&cup2key=%d:%u`
|
||||||
|
where the first parameter is the key ID, the second is the freshness nonce.
|
||||||
|
|
||||||
|
For debugging purposes, the request hash is sent to the server using a query
|
||||||
|
parameter appended to the requested URL, using the format `&cup2hreq=%s` where
|
||||||
|
%s is the lowercase hexadecimal value of the hash (in big-endian format).
|
||||||
|
|
||||||
|
The server returns the ECDSA signature and the request hash it computed in at
|
||||||
|
least one of three forms:
|
||||||
|
1. The `X-Cup-Server-Proof` HTTP header, with the value in the format
|
||||||
|
`signature:hash`.
|
||||||
|
2. The `ETag` HTTP header, with the value in the format of
|
||||||
|
`W/"signature:hash"`.
|
||||||
|
3. The `ETag` HTTP header, with the value in the format of `signature:hash`.
|
||||||
|
|
||||||
|
If multiple forms are present in the response, clients should prefer form 1,
|
||||||
|
falling back to form 2 only if form 1 is not present, and falling back to form 3
|
||||||
|
only if form 1 and 2 are not present.
|
||||||
|
|
||||||
|
In practice, multiple forms allow the communication to navigate different types
|
||||||
|
of proxies that mutate request headers.
|
||||||
|
|
||||||
|
In all forms, `signature` is a DER-encoded ASN.1 sequence of "R" and "S",
|
||||||
|
rendered in lowercase hexadecimal representation.
|
||||||
|
|
||||||
|
In all forms, `hash` is a 256-bit value rendered in lowercase hexadecimal
|
||||||
|
representation (big-endian).
|
||||||
|
|
||||||
|
### K-Repetition
|
||||||
|
A grave danger in any system involving ECDSA is the danger of K repetition.
|
||||||
|
|
||||||
|
Computing an ECDSA signature starts with selecting a random 256-bit integer,
|
||||||
|
called K. The combination of K and the public key are used to produce the first
|
||||||
|
half of the signature, called R; the values of R, K, the private key, and the
|
||||||
|
message digest are used to compute the other half of the signature, called S.
|
||||||
|
|
||||||
|
Because of this process, if the same value of K is chosen for two signatures,
|
||||||
|
both signatures will have the same value for R. If a malicious user can acquire
|
||||||
|
two messages that have different bodies but identical R values, a
|
||||||
|
straightforward computation yields the server's private key.
|
||||||
|
|
||||||
|
Assuming that a good PRNG is used, and properly seeded, the probability of a
|
||||||
|
collision is small even across a large number of signatures. However, regular
|
||||||
|
key rotation is still recommended:
|
||||||
|
1. Key material may be disclosed due to server compromise, and organizations
|
||||||
|
should be prepared to remediate by performing a key rotation. Regularly
|
||||||
|
exercising a key rotation process is important preparation.
|
||||||
|
2. PRNGs are not always perfectly secure or properly seeded.
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
Previous documents describing CUP can be found at:
|
||||||
|
* [Original Public Design](https://github.com/google/omaha/blob/master/doc/ClientUpdateProtocol.md)
|
||||||
|
* [ECDSA Extension](https://github.com/google/omaha/blob/master/doc/ClientUpdateProtocolEcdsa.md)
|
||||||
|
|
||||||
|
Chromium's implementation of CUP can be found in
|
||||||
|
[components/client\_update\_protocol](https://source.chromium.org/chromium/chromium/src/+/master:components/client_update_protocol/).
|
||||||
|
|
@@ -1,8 +1,8 @@
|
|||||||
# Omaha Protocol (V3.1)
|
# Omaha Protocol (V3.1)
|
||||||
This document describes version 3.1 of the Omaha Client-Server Protocol.
|
This document describes version 3.1 of the Omaha Client-Server Protocol.
|
||||||
Previous versions are described at:
|
Previous versions are described at:
|
||||||
* (Version 3)[https://github.com/google/omaha/blob/master/doc/ServerProtocolV3.md]
|
* [Version 3](https://github.com/google/omaha/blob/master/doc/ServerProtocolV3.md)
|
||||||
* (Version 2)[https://github.com/google/omaha/blob/master/doc/ServerProtocolV2.md]
|
* [Version 2](https://github.com/google/omaha/blob/master/doc/ServerProtocolV2.md)
|
||||||
* Version 1 of the protocol was never publicly deployed.
|
* Version 1 of the protocol was never publicly deployed.
|
||||||
|
|
||||||
[TOC]
|
[TOC]
|
||||||
|
Reference in New Issue
Block a user