Home | History | Annotate | only in /external/ukey2
Up to higher level directory
NameDateSize
Android.bp22-Oct-2020904
build.gradle22-Oct-2020395
CONTRIBUTING.md22-Oct-20201.1K
LICENSE22-Oct-202011.1K
METADATA22-Oct-2020280
MODULE_LICENSE_APACHE222-Oct-20200
NOTICE22-Oct-202011.1K
README22-Oct-20200
README.md22-Oct-202014.8K
src/22-Oct-2020

README.md

      1 # Ukey2
      2 This is not an officially supported Google product
      3 
      4 **Coathored by:** Alexei Czeskis, Thai Duong, Eduardo' Vela'' \<Nava\>, and Adam Stubblefield.
      5 
      6 **Status:** Implemented in Java (aczeskis (a] google.com)
      7 
      8 **Design reviewers:** Thai Duong, Bruno Blanchet, Martin Abadi, and Bo Wang
      9 
     10 **Implementation reviewer**: Thai Duong
     11 
     12 **Last Updated:** roughly in September 2016
     13 
     14 
     15 
     16 # Overview
     17 
     18 UKEY2 is a Diffie-Hellman based authenticated key exchange protocol.
     19 
     20 At the end of a UKEY2 run, a client and server have a shared master secret that can be used to
     21 derive keys which can be used in a subsequent protocol. UKEY2 only implicitly guarantees that
     22 servers know that clients believe the protocol finished correctly; that is, until a server
     23 receives a message on the next protocol from the client it does not know that the handshake
     24 completed.
     25 
     26 The intended usage of UKEY2 is to establish a secure channel between two user devices,
     27 e.g., laptop with Chromecast, phone with Google Glass, etc. The secure channel then can be used to
     28 transmit passwords or other credentials. It is especially useful when one wants to connect a brand
     29  new device to a password-protected WIFI network.  UKEY2 is also usable over low-bandwidth
     30 transports like Bluetooth Low Energy (see [Performance](#performance)).
     31 
     32 # Message Framing
     33 
     34 Each UKEY2 message is framed inside an outer protobuf message:
     35 
     36 
     37 ```
     38 message Ukey2Message {
     39   enum Type {
     40     UNKNOWN_DO_NOT_USE = 0;
     41     ALERT = 1;
     42     CLIENT_INIT = 2;
     43     SERVER_INIT = 3;
     44     CLIENT_FINISH = 4;
     45   }
     46 
     47   optional Type message_type = 1;   // Identifies message type
     48   optional bytes message_data = 2;  // Actual message, to be parsed according to
     49                                     // message_type
     50 }
     51 ```
     52 
     53 
     54 
     55 # Alerts
     56 
     57 In case an error occurs, the client and server will reply with an Alert:
     58 
     59 
     60 ```
     61 message Ukey2Alert {
     62   enum AlertType {
     63     // Framing errors
     64     BAD_MESSAGE = 1;             // The message could not be deserialized
     65     BAD_MESSAGE_TYPE = 2;        // message_type has an undefined value
     66     INCORRECT_MESSAGE = 3;       // message_type received does not correspond to expected
     67                                  // type at this stage of the protocol
     68     BAD_MESSAGE_DATA = 4;        // Could not deserialize message_data as per value in
     69                                  // message_type
     70 
     71     // ClientInit and ServerInit errors
     72     BAD_VERSION = 100;           // version is invalid; server cannot find suitable version
     73                                  // to speak with client.
     74     BAD_RANDOM = 101;            // Random data is missing or of incorrect length
     75     BAD_HANDSHAKE_CIPHER = 102;  // No suitable handshake ciphers were found
     76     BAD_NEXT_PROTOCOL = 103;     // The next protocol is missing, unknown, or unsupported
     77     BAD_PUBLIC_KEY = 104;        // The public key could not be parsed
     78 
     79     // Other errors
     80     INTERNAL_ERROR = 200;       // An internal error has occurred.  error_message may
     81                                 // contain additional details for logging and debugging.
     82   }
     83 
     84   optional AlertType type = 1;
     85   optional string error_message = 2;
     86 }
     87 ```
     88 
     89 
     90 The type corresponds to the error that caused the `Alert` to be sent. Upon encountering an error,
     91 clients and servers send an Alert of the proper type and close the connection; all alerts are
     92 fatal. Upon receiving an `Alert`, clients and servers must close the connection, even if they
     93 cannot parse the `Alert`.  The `Alert` message may contain an optional `error_message` string
     94 that may be used to describe error details for logging.
     95 
     96 # Handshake Ciphersuites
     97 
     98 UKEY2 supports negotiation of the cryptographic primitives used in the handshake. Two primitives
     99 are required, a Diffie-Hellman function and a cryptographic hash function, which are represented
    100 by a single enum:
    101 
    102 
    103 ```
    104 enum Ukey2HandshakeCipher {
    105   RESERVED = 0;
    106   P256_SHA512 = 100;        // NIST P-256 used for ECDH, SHA512 used for commitment
    107   CURVE25519_SHA512 = 200;  // Curve 25519 used for ECDH, SHA512 used for commitment
    108 }
    109 ```
    110 
    111 
    112 The implementations of all primitives must resist timing side-channel attacks. A summary of
    113 handshake ciphersuite negotiation is (see ClientInit and ServerInit messages for full details):
    114 
    115 *   The client enumerates the primitives it supports and the server choose the highest (by enum value) cipher that it also supports.
    116 *   The server replies with a public key using the chosen cipher and sends its own list of supported handshake cipher suites so that the client can verify that the right selection was made.
    117 
    118 
    119 # Handshake Details
    120 
    121 The UKEY2 handshake consists of three messages. First, the client sends a `ClientInit` message to
    122 the server -- conceptually, this consists of a list of cipher suites and a commitment to an
    123 ephemeral public key for each suite. The server responds with a `ServerInit` -- conceptually,
    124 this is the server's chosen cipher suite and an ephemeral public key for the cipher suites
    125 selected by the server.  Finally, the client responds with a `ClientFinished` -- conceptually,
    126 this consists of an ephemeral public key matching the cipher suite selected by the server.
    127 
    128 After the handshake, both client and server derive authentication strings, which may be shown to
    129 users for visual comparison or sent over some other channel in order to authenticate the handshake.
    130 The client and server also derive session keys for the next protocol.
    131 
    132 ## The `ClientInit` Message
    133 
    134 The `ClientInit` message is defined as follows:
    135 
    136 
    137 ```
    138 message Ukey2ClientInit {
    139   optional int32 version = 1;  // highest supported version for rollback protection
    140   optional bytes random = 2;   // random bytes for replay/reuse protection
    141 
    142   // One commitment (hash of ClientFinished containing public key) per supported cipher
    143   message CipherCommitment {
    144     optional Ukey2HandshakeCipher handshake_cipher = 1;
    145     optional bytes commitment = 2;
    146   }
    147   repeated CipherCommitment cipher_commitments = 3;
    148 
    149   // Next protocol that the client wants to speak.
    150   optional string next_protocol = 4;
    151 }
    152 ```
    153 
    154 
    155 The `version` field is the maximum version that the client supports.  It should be 1 for now. The `random` field is exactly 32 cryptographically secure random bytes.  The `cipher_commitment` field is a protobuf consisting of a handshake cipher and a commitment which is a hash of the `ClientFinished` message that would be sent if the cipher were selected (the serialized, including framing, raw bytes of the last handshake message sent by the client), calculated with the hash function and the Diffie-Hellman function from the handshake cipher. The client includes each commitment in the order of their preference.  Note that only one commitment per `handshake_cipher` is allowed.  The client also includes the `next_protocol` field that specifies that the client wants to use to speak to the server.  Note that this protocol must implicitly imply a key length.  UKEY2, however, does not provide a namespace for the `next_protocol` values in order to provide layers separation between the handshake and the next protocols.
    156 
    157 
    158 ## Interpreting `ClientInit`
    159 
    160 Upon receiving the `ClientInit` message, the server should:
    161 
    162 
    163 
    164 1.  Deserialize the protobuf; send an `Alert.BAD_MESSAGE` message if deserialization fails.
    165 1.  Verify that `message_type == Type.CLIENT_INIT`; send an `Alert.BAD_MESSAGE_TYPE` message if mismatch occurs.
    166 1.  Deserialize `message_data` as a `ClientInit` message; send an `Alert.BAD_MESSAGE_DATA` message if deserialization fails.
    167 1.  Check that `version == 1`; send `Alert.BAD_VERSION` message if mismatch.
    168 1.  Check that `random` is exactly 32 bytes; send `Alert.BAD_RANDOM` message if not.
    169 1.  Check to see if any of the `handshake_cipher` in `cipher_commitment` are acceptable. Servers should select the first `handshake_cipher` that it finds acceptable to support clients signaling deprecated but supported HandshakeCiphers. If no `handshake_cipher` is acceptable (or there are no HandshakeCiphers in the message), the server sends an `Alert.BAD_HANDSHAKE_CIPHER` message.
    170 1.  Checks that `next_protocol` contains a protocol that the server supports.  Send an `Alert.BAD_NEXT_PROTOCOL` message if not.
    171 
    172 If no alerts have been sent, the server replies with the `ServerInit` message.
    173 
    174 
    175 ## The `ServerInit` Message 
    176 
    177 The `ServerInit` message is as follows
    178 
    179 
    180 ```
    181 message Ukey2ServerInit {
    182   optional int32 version = 1;  // highest supported version for rollback protection
    183   optional bytes random = 2;   // random bytes for replay/reuse protection
    184 
    185   // Selected Cipher and corresponding public key
    186   optional Ukey2HandshakeCipher handshake_cipher = 3;
    187   optional bytes public_key = 4;
    188 }
    189 ```
    190 
    191 
    192 For now, `version` must be 1.  The random field is exactly 32 cryptographically secure random
    193 bytes.  The `handshake_cipher` field contains the server-chosen `HandshakeCipher`.  The
    194 `public_key` field contains the server-chosen corresponding public key.
    195 
    196 
    197 ## Interpreting `ServerInit`
    198 
    199 When a client receives a `ServerInit` after having sent a `ClientInit`, it performs the following actions:
    200 
    201 
    202 1.  Deserialize the protobuf; send an `Alert.BAD_MESSAGE` message if deserialization fails.
    203 1.  Verify that `message_type == Type.SERVER_INIT`; send an `Alert.BAD_MESSAGE_TYPE` message if mismatch occurs.
    204 1.  Deserialize `message_data` as a `ServerInit` message; send an `Alert.BAD_MESSAGE_DATA` message if deserialization fails.
    205 1.  Check that `version == 1`; send `Alert.BAD_VERSION` message if mismatch.
    206 1.  Check that `random` is exactly 32 bytes; send `Alert.BAD_RANDOM` message if not.
    207 1.  Check that `handshake_cipher` matches a handshake cipher that was sent in
    208 `ClientInit.cipher_commitments`. If not, send an `Alert.BAD_HANDSHAKECIPHER` message.
    209 1.  Check that `public_key` parses into a correct public key structure.  If not, send an `Alert.BAD_PUBLIC_KEY` message.
    210 
    211 If no alerts have been sent, the client replies with the `ClientFinished` message.  After sending
    212 the `ClientFinished` message, the Client considers the handshake complete.
    213 
    214 
    215 **IMPORTANT:** The client should compute the authentication string `AUTH_STRING` and
    216 the next-protocol secret `NEXT_SECRET` (see below).  The client should use an out-of-band
    217 channel to verify the authentication string before proceeding to the next protocol.
    218 
    219 
    220 ## The ClientFinished Message 
    221 
    222 The `ClientFinished` message is as follows:
    223 
    224 
    225 ```
    226 message Ukey2ClientFinished {
    227   optional bytes public_key = 1;  // public key matching selected handshake cipher
    228 }
    229 ```
    230 
    231 
    232 The `public_key` contains the Client's public key (whose commitment was sent in the `ClientInit`
    233 message) for the server-selected handshake cipher.
    234 
    235 
    236 ## Interpreting ClientFinished 
    237 
    238 When a server receives a `ClientFinished` after having sent a `ServerInit`, it performs the
    239 following actions:
    240 
    241 
    242 1.  Deserialize the protobuf; terminate the connection if deserialization fails.
    243 1.  Verify that `message_type == Type.CLIENT_FINISHED`; terminate the connection if mismatch occurs.
    244 1.  Verify that the hash of the `ClientFinished` matches the expected commitment for the chosen `handshake_cipher` from `ClientInit`.  Terminate the connection if the expected match fails.
    245 1.  Deserialize `message_data` as a `ClientFinished` message; terminate the connection if deserialization fails.
    246 1.  Check that `public_key` parses into a correct public key structure.  If not, terminate the connection.
    247 
    248 Note that because the client is not expecting a response, any error results in connection termination.
    249 
    250 After parsing the `ClientFinished` message, the Server considers the handshake complete.
    251 
    252 
    253 **IMPORTANT:** The server should compute the authentication string `AUTH_STRING` and the
    254 next-protocol secret `NEXT_SECRET` (see below).  The server should use an out-of-band channel to
    255 verify the authentication string before proceeding to the next protocol.
    256 
    257 
    258 # Deriving the Authentication String and the Next-Protocol Secret
    259 
    260 Let `DHS` = the negotiated Diffie-Hellman key derived from the Client and Server public keys.
    261 
    262 Let `M_1` = the serialized (including framing) raw bytes of the first message sent by
    263 the client
    264 
    265 Let `M_2` = the serialized (including framing) raw bytes of the first message sent by
    266 the server
    267 
    268 Let `Hash` = the hash from HandshakeCipher
    269 
    270 Let `L_auth` = length of authentication string in bytes.  Note that this length can
    271 be short (e.g., a 6 digit visual confirmation code).
    272 
    273 Let `L_next` = length of next protocol key
    274 
    275 Let `HKDF-Extract` and `HKDF-Expand` be as defined in [RFC5869](https://tools.ietf.org/html/rfc5869)
    276 instantiated with the hash from the `HandshakeCipher`.
    277 
    278 Let `PRK_AUTH = HKDF-Extract("UKEY2 v1 auth", DHS)`
    279 
    280 Let `PRK_NEXT = HKDF-Extract("UKEY2 v1 next", DHS)`
    281 
    282 Then `AUTH_STRING = HKDF-Expand(PRK_AUTH, M_1|M_2, L_auth)`
    283 
    284 Then `NEXT_SECRET = HKDF-Expand(PRK_NEXT, M_1|M_2, L_next)`
    285 
    286 
    287 # Security Discussion
    288 
    289 If client and server authenticate one-another using the `AUTH_STRING` through an out-of-band
    290 mechanism, we believe that this handshake is resistant to an active man-in-the-middle attacker.
    291 The attacker, whether he/she plays the role of the client or server, is forced to commit to a
    292 public key before seeing the other-party's public key.
    293 
    294 The authentication string and next secret are computed in such a way that knowledge of one does
    295 not allow an attacker to compute the other.  That is, if the attacker observed the `AUTH_STRING`
    296 (if it was shown on a monitor for example), the attacker could not compute `NEXT_SECRET`.
    297 Furthermore, both the authentication string and next secret depend on the full handshake
    298 transcript -- a manipulation of any handshake message by an adversary would change both the
    299  authentication string and the next secret.  Note that although the last message is not directly
    300  included in the HKDF computation, it is included as part of the commitment sent in `M_1.`
    301 
    302 @shabsi pointed out that by having the `HKDF` info field have bits that also go into making the
    303 `PRK`, this violates some security proof.  Those "shared" bits are the public keys that are sent
    304 in `M_2` and `M_3` and are also used to derive the DHS.  Though the "proof" may
    305  not hold in theory, we do believe the security of the handshake is maintained in practice.
    306 
    307 A natural question may be why we didn't use
    308 [Short Authentication Strings](https://www.iacr.org/archive/crypto2005/36210303/36210303.pdf)
    309 (SAS).  The answer is two-fold.  First, traditional SAS does not incorporate a key exchange, only
    310 authentication; UKEY2 provides both.  Second, the paper does not give concrete primitives,
    311 instead describing abstract functions such as `commit() `and `open()`.  One concrete
    312 implementation of these functions would look similar to what UKEY2 does.
    313 
    314 Bruno Blanchet performed a formal proof of a simplified version of UKEY2.
    315 
    316 # Performance
    317 
    318 The messages are fairly compact.  Running a test where the client sent a single commitment for a
    319 `P256_SHA512` cipher and the `next_protocol` was set to "`AES_256_CBC-HMAC_SHA256"`, the total
    320 size of the messages were:
    321 
    322 
    323 | Message        | Length in Bytes |
    324 |:---------------|----------------:|
    325 |`ClientInit`    | 136             |
    326 |`ServerInit`    | 117             |
    327 |`ClientFinished`| 79              |
    328 
    329 
    330