From 5e313458e2de5b7bd67004b5d308706965cf845b Mon Sep 17 00:00:00 2001 From: akwizgran Date: Tue, 12 May 2015 15:34:59 +0000 Subject: [PATCH] Longer rotation periods --- BTP.markdown | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/BTP.markdown b/BTP.markdown index efec9bb..5d7ec7d 100644 --- a/BTP.markdown +++ b/BTP.markdown @@ -36,39 +36,48 @@ How this state is established is outside the scope of BTP. The devices must esta The devices must also agree which of them will play the role of Alice and which will play the role of Bob. The roles are identical except for some key derivation constants. -> Implementation note: Shared secrets for multiple transports may be derived from an initial shared secret established by a separate key agreement protocol. T may be hard-coded or negotiated by the key agreement protocol. D and L may be hard-coded. We propose to use D = 3600 (one hour). +> Implementation note: Shared secrets for multiple transports may be derived from an initial shared secret established by a separate key agreement protocol. T may be hard-coded or negotiated by the key agreement protocol. D and L may be hard-coded. We propose to use D = 86400 (24 hours). ### Key derivation -Each device derives four initial keys from S: +Each device derives four initial keys from S. -* `atk = KDF(S, "ALICE_TAG_KEY")` -* `ahk = KDF(S, "ALICE_HEADER_KEY")` -* `btk = KDF(S, "BOB_TAG_KEY")` -* `bhk = KDF(S, "BOB_HEADER_KEY")` +Alice derives her keys as follows: -Alice initialises her outgoing tag and header keys otk = atk and ohk = ahk, and her incoming tag and header keys itk = btk and ihk = bhk. Bob initialises his outgoing tag and header keys otk = btk and ohk = bhk, and his incoming tag and header keys itk = atk and ihk = ahk. Thus Alice's outgoing keys are Bob's incoming keys and vice versa. Both devices then erase S. +* `outgoing_tag_key = KDF(S, "ALICE_TAG_KEY")` +* `outgoing_header_key = KDF(S, "ALICE_HEADER_KEY")` +* `incoming_tag_key = KDF(S, "BOB_TAG_KEY")` +* `incoming_header_key = KDF(S, "BOB_HEADER_KEY")` + +Bob derives his keys as follows: + +* `outgoing_tag_key = KDF(S, "BOB_TAG_KEY")` +* `outgoing_header_key = KDF(S, "BOB_HEADER_KEY")` +* `incoming_tag_key = KDF(S, "ALICE_TAG_KEY")` +* `incoming_header_key = KDF(S, "ALICE_HEADER_KEY")` + +Thus Alice's outgoing keys are Bob's incoming keys and vice versa. Both devices then erase S. ### Key rotation BTP achieves forward secrecy by rotating keys periodically. The key rotation function is deterministic, so devices that start from the same S will have matching keys in each rotation period. -The length of each rotation period is R = D + L seconds. Rotation periods are aligned with the Unix epoch. The timestamp T falls in rotation period P = floor(T / R). +The length of each rotation period is R = D + L seconds. Rotation periods are aligned with the Unix epoch. -The initial keys derived from S are the keys for period P - 1. The keys for the i^th rotation period are derived from the previous period's keys as follows: +The initial keys derived from S are the keys for rotation period 0. The timestamp T falls in rotation period 1. The keys for the i^th rotation period are derived from the previous period's keys as follows: -* `otk = KDF(otk, "ROTATE_TAG_KEY", int(i))` -* `ock = KDF(ock, "ROTATE_HEADER_KEY", int(i))` -* `itk = KDF(itk, "ROTATE_TAG_KEY", int(i))` -* `ick = KDF(ick, "ROTATE_HEADER_KEY", int(i))` +* `outgoing_tag_key = KDF(outgoing_tag_key, "ROTATE", int(i))` +* `outgoing_header_key = KDF(outgoing_header_key, "ROTATE", int(i))` +* `incoming_tag_key = KDF(incoming_tag_key, "ROTATE", int(i))` +* `incoming_header_key = KDF(incoming_header_key, "ROTATE", int(i))` If the sender starts sending a stream at time t according to the sender's clock, the recipient may start receiving the stream at any time between t - D and t + D + L according to the recipient's clock. Therefore each device must retain the incoming keys for the previous, current and next rotation periods, along with the outgoing keys for the current rotation period. Keys are erased when they are no longer needed. ### Tags -Each stream starts with a pseudo-random tag, which is TAG_LEN bytes long. The recipient calculates the tag in advance and uses it to recognise which sender the stream comes from and which incoming header key should be used. +Each stream starts with a pseudo-random tag, which is TAG_LEN bytes long. The recipient calculates the tag in advance and uses it to recognise which sender the stream comes from and which incoming header key should be used for the stream. -The tag for the i^th stream from the sender to the recipient in a given rotation period is the first TAG_LEN bytes of MAC(k, int(i)), where k is the sender's outgoing tag key. For simplicity we require that TAG_LEN <= MAC_LEN. Streams are counted starting from zero in each rotation period. +The tag for the i^th stream from a given sender to a given recipient in a given rotation period is the first TAG_LEN bytes of MAC(k, int(i)), where k is the sender's outgoing tag key. For simplicity we require that TAG_LEN <= MAC_LEN. Streams are counted from zero in each rotation period. > Implementation note: We propose to use TAG_LEN = 16. @@ -87,11 +96,11 @@ To avoid reusing tags, which would allow the adversary to distinguish BTP traffi ### Stream header -The pseudo-random tag is followed by the stream header, which consists of a random nonce and an ephemeral key encrypted and authenticated with the sender's outgoing header key and the nonce. The stream header is NONCE_LEN + KEY_LEN + AUTH_LEN bytes long. The ephemeral key is used for encrypting and authenticating the rest of the stream. +The pseudo-random tag is followed by the stream header, which consists of a random nonce followed by an ephemeral key encrypted and authenticated with the sender's outgoing header key and the nonce. The stream header is NONCE_LEN + KEY_LEN + AUTH_LEN bytes long. The ephemeral key is used for encrypting and authenticating the rest of the stream. ### Frames -The remainder of the stream consists of one or more frames. Each frame has a fixed-length header and a variable-length body that may contain data, padding, neither or both. The frames are numbered starting from zero. A stream may not contain more than 2^63 frames. +The remainder of the stream consists of one or more frames. Each frame has a fixed-length header and a variable-length body that may contain data, padding, neither or both. The frames are numbered from zero. A stream may not contain more than 2^63 frames. The plaintext frame header is 4 bytes long, with the following format: