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