secret_tree_crypto.mx raw
1 package mls
2
3 // MLS secret tree crypto operations (RFC 9420 ยง9).
4
5 func deriveSecretTree(cs CipherSuite, n numLeaves, encryptionSecret []byte) (v [][]byte, err2 error) {
6 tree := [][]byte{:int32(n.width())}
7 secretTreeSet(tree, n.root(), encryptionSecret)
8 err := secretTreeDeriveChildren(cs, tree, n.root())
9 return tree, err
10 }
11
12 func secretTreeDeriveChildren(cs CipherSuite, tree [][]byte, x nodeIndex) (err error) {
13 l, r, ok := x.children()
14 if !ok {
15 return nil
16 }
17
18 parentSecret := secretTreeGet(tree, x)
19 nh := uint16(cs.ExtractSize())
20 leftSecret, err := cs.expandWithLabel(parentSecret, []byte("tree"), []byte("left"), nh)
21 if err != nil {
22 return err
23 }
24 rightSecret, err := cs.expandWithLabel(parentSecret, []byte("tree"), []byte("right"), nh)
25 if err != nil {
26 return err
27 }
28
29 secretTreeSet(tree, l, leftSecret)
30 secretTreeSet(tree, r, rightSecret)
31
32 if e := secretTreeDeriveChildren(cs, tree, l); e != nil {
33 return e
34 }
35 return secretTreeDeriveChildren(cs, tree, r)
36 }
37
38 func secretTreeDeriveRatchetRoot(tree [][]byte, cs CipherSuite, ni nodeIndex, label []byte) (v ratchetSecret, err2 error) {
39 nh := uint16(cs.ExtractSize())
40 root, err := cs.expandWithLabel(secretTreeGet(tree, ni), label, nil, nh)
41 return ratchetSecret{root, 0}, err
42 }
43
44 func (secret *ratchetSecret) deriveNonce(cs CipherSuite) (out []byte, err error) {
45 return deriveTreeSecret(cs, secret.secret, []byte("nonce"), secret.generation, uint16(cs.AEADNonceSize()))
46 }
47
48 func (secret *ratchetSecret) deriveKey(cs CipherSuite) (out []byte, err error) {
49 return deriveTreeSecret(cs, secret.secret, []byte("key"), secret.generation, uint16(cs.AEADKeySize()))
50 }
51
52 func (secret *ratchetSecret) deriveNext(cs CipherSuite) (v ratchetSecret, err2 error) {
53 nh := uint16(cs.ExtractSize())
54 next, err := deriveTreeSecret(cs, secret.secret, []byte("secret"), secret.generation, nh)
55 return ratchetSecret{next, secret.generation + 1}, err
56 }
57
58 func deriveTreeSecret(cs CipherSuite, secret, label []byte, generation uint32, length uint16) (out []byte, err error) {
59 // context = I2OSP(generation, 4)
60 context := []byte{byte(generation >> 24), byte(generation >> 16), byte(generation >> 8), byte(generation)}
61 return cs.expandWithLabel(secret, label, context, length)
62 }
63