aboutsummaryrefslogtreecommitdiff
path: root/spec/tor-spec/setting-circuit-keys.md
blob: 200862f1958d5e499468fa5aadd029a4db9f067b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<a id="tor-spec.txt-5.2"></a>

# Setting circuit keys{#setting-circuit-keys}

<a id="tor-spec.txt-5.2.1"></a>

## KDF-TOR{#kdf-tor}

This key derivation function is used by the TAP and CREATE_FAST
handshakes, and in the current hidden service protocol. It shouldn't
be used for new functionality.

If the TAP handshake is used to extend a circuit, both parties
base their key material on K0=g^xy, represented as a big-endian unsigned
integer.

If CREATE_FAST is used, both parties base their key material on
K0=X|Y.

From the base key material K0, they compute KEY_LEN*2+HASH_LEN*3 bytes of
derivative key data as

K = H(K0 | \[00\]) | H(K0 | \[01\]) | H(K0 | \[02\]) | ...

The first HASH_LEN bytes of K form KH; the next HASH_LEN form the forward
digest Df; the next HASH_LEN 41-60 form the backward digest Db; the next
KEY_LEN 61-76 form Kf, and the final KEY_LEN form Kb.  Excess bytes from K
are discarded.

KH is used in the handshake response to demonstrate knowledge of the
computed shared key. Df is used to seed the integrity-checking hash
for the stream of data going from the OP to the OR, and Db seeds the
integrity-checking hash for the data stream from the OR to the OP. Kf
is used to encrypt the stream of data going from the OP to the OR, and
Kb is used to encrypt the stream of data going from the OR to the OP.

<a id="tor-spec.txt-5.2.2"></a>

## KDF-RFC5869{#kdf-rfc5869}

For newer KDF needs, Tor uses the key derivation function HKDF from
RFC5869, instantiated with SHA256.  (This is due to a construction
from Krawczyk.)  The generated key material is:

K = K_1 | K_2 | K_3 | ...

```text
       Where H(x,t) is HMAC_SHA256 with value x and key t
         and K_1     = H(m_expand | INT8(1) , KEY_SEED )
         and K_(i+1) = H(K_i | m_expand | INT8(i+1) , KEY_SEED )
         and m_expand is an arbitrarily chosen value,
         and INT8(i) is a octet with the value "i".
```

In RFC5869's vocabulary, this is HKDF-SHA256 with info == m_expand,
salt == t_key, and IKM == secret_input.

When used in the ntor handshake, the first HASH_LEN bytes form the
forward digest Df; the next HASH_LEN form the backward digest Db; the
next KEY_LEN form Kf, the next KEY_LEN form Kb, and the final
DIGEST_LEN bytes are taken as a nonce to use in the place of KH in the
hidden service protocol.  Excess bytes from K are discarded.