secret_tree_test.go raw

   1  package mls
   2  
   3  import (
   4  	"bytes"
   5  	"fmt"
   6  	"testing"
   7  )
   8  
   9  type secretTreeTest struct {
  10  	CipherSuite CipherSuite `json:"cipher_suite"`
  11  
  12  	SenderData struct {
  13  		SenderDataSecret testBytes `json:"sender_data_secret"`
  14  		Ciphertext       testBytes `json:"ciphertext"`
  15  		Key              testBytes `json:"key"`
  16  		Nonce            testBytes `json:"nonce"`
  17  	} `json:"sender_data"`
  18  
  19  	EncryptionSecret testBytes             `json:"encryption_secret"`
  20  	Leaves           [][]secretTreeTestGen `json:"leaves"`
  21  }
  22  
  23  type secretTreeTestGen struct {
  24  	Generation       uint32    `json:"generation"`
  25  	HandshakeKey     testBytes `json:"handshake_key"`
  26  	HandshakeNonce   testBytes `json:"handshake_nonce"`
  27  	ApplicationKey   testBytes `json:"application_key"`
  28  	ApplicationNonce testBytes `json:"application_nonce"`
  29  }
  30  
  31  func testSecretTree(t *testing.T, tc *secretTreeTest) {
  32  	senderDataSecret := []byte(tc.SenderData.SenderDataSecret)
  33  	ciphertext := []byte(tc.SenderData.Ciphertext)
  34  
  35  	key, err := expandSenderDataKey(tc.CipherSuite, senderDataSecret, ciphertext)
  36  	if err != nil {
  37  		t.Errorf("expandSenderDataKey() = %v", err)
  38  	} else if !bytes.Equal(key, []byte(tc.SenderData.Key)) {
  39  		t.Errorf("expandSenderDataKey() = %v, want %v", key, tc.SenderData.Key)
  40  	}
  41  
  42  	nonce, err := expandSenderDataNonce(tc.CipherSuite, senderDataSecret, ciphertext)
  43  	if err != nil {
  44  		t.Errorf("expandSenderDataNonce() = %v", err)
  45  	} else if !bytes.Equal(nonce, []byte(tc.SenderData.Nonce)) {
  46  		t.Errorf("expandSenderDataNonce() = %v, want %v", nonce, tc.SenderData.Nonce)
  47  	}
  48  
  49  	tree, err := deriveSecretTree(tc.CipherSuite, numLeaves(len(tc.Leaves)), []byte(tc.EncryptionSecret))
  50  	if err != nil {
  51  		t.Fatalf("generateSecretTree() = %v", err)
  52  	}
  53  
  54  	for i, gens := range tc.Leaves {
  55  		li := leafIndex(i)
  56  		t.Run(fmt.Sprintf("leaf-%v/handshake", li), func(t *testing.T) {
  57  			testRatchetSecret(t, tc.CipherSuite, tree, li, ratchetLabelHandshake, gens)
  58  		})
  59  		t.Run(fmt.Sprintf("leaf-%v/application", li), func(t *testing.T) {
  60  			testRatchetSecret(t, tc.CipherSuite, tree, li, ratchetLabelApplication, gens)
  61  		})
  62  	}
  63  }
  64  
  65  func testRatchetSecret(t *testing.T, cs CipherSuite, tree secretTree, li leafIndex, label ratchetLabel, gens []secretTreeTestGen) {
  66  	secret, err := tree.deriveRatchetRoot(cs, li.nodeIndex(), label)
  67  	if err != nil {
  68  		t.Fatalf("deriveRatchetRoot() = %v", err)
  69  	}
  70  
  71  	for _, gen := range gens {
  72  		if gen.Generation < secret.generation {
  73  			panic("unreachable")
  74  		}
  75  
  76  		for secret.generation != gen.Generation {
  77  			secret, err = secret.deriveNext(cs)
  78  			if err != nil {
  79  				t.Fatalf("deriveNext() = %v", err)
  80  			}
  81  		}
  82  
  83  		var wantKey, wantNonce testBytes
  84  		switch string(label) {
  85  		case string(ratchetLabelHandshake):
  86  			wantKey, wantNonce = gen.HandshakeKey, gen.HandshakeNonce
  87  		case string(ratchetLabelApplication):
  88  			wantKey, wantNonce = gen.ApplicationKey, gen.ApplicationNonce
  89  		default:
  90  			panic("unreachable")
  91  		}
  92  
  93  		key, err := secret.deriveKey(cs)
  94  		if err != nil {
  95  			t.Fatalf("deriveKey() = %v", err)
  96  		} else if !bytes.Equal(key, []byte(wantKey)) {
  97  			t.Errorf("deriveKey() = %v, want %v", key, wantKey)
  98  		}
  99  
 100  		nonce, err := secret.deriveNonce(cs)
 101  		if err != nil {
 102  			t.Fatalf("deriveNonce() = %v", err)
 103  		} else if !bytes.Equal(nonce, []byte(wantNonce)) {
 104  			t.Errorf("deriveNonce() = %v, want %v", nonce, wantNonce)
 105  		}
 106  	}
 107  }
 108  
 109  func TestSecretTree(t *testing.T) {
 110  	var tests []secretTreeTest
 111  	loadTestVector(t, "testdata/secret-tree.json", &tests)
 112  
 113  	for i, tc := range tests {
 114  		t.Run(fmt.Sprintf("[%v]", i), func(t *testing.T) {
 115  			testSecretTree(t, &tc)
 116  		})
 117  	}
 118  }
 119