ciphersuite_test.go raw

   1  package mls
   2  
   3  import (
   4  	"bytes"
   5  	"fmt"
   6  	"testing"
   7  )
   8  
   9  type cryptoBasicsTest struct {
  10  	CipherSuite      CipherSuite          `json:"cipher_suite"`
  11  	RefHash          refHashTest          `json:"ref_hash"`
  12  	ExpandWithLabel  expandWithLabelTest  `json:"expand_with_label"`
  13  	DeriveSecret     deriveSecretTest     `json:"derive_secret"`
  14  	DeriveTreeSecret deriveTreeSecretTest `json:"derive_tree_secret"`
  15  	SignWithLabel    signWithLabelTest    `json:"sign_with_label"`
  16  	EncryptWithLabel encryptWithLabelTest `json:"encrypt_with_label"`
  17  }
  18  
  19  type refHashTest struct {
  20  	Label string    `json:"label"`
  21  	Out   testBytes `json:"out"`
  22  	Value testBytes `json:"value"`
  23  }
  24  
  25  func testRefHash(t *testing.T, cs CipherSuite, tc *refHashTest) {
  26  	out, err := cs.refHash([]byte(tc.Label), []byte(tc.Value))
  27  	if err != nil {
  28  		t.Fatal(err)
  29  	}
  30  	if !bytes.Equal([]byte(tc.Out), out) {
  31  		t.Errorf("got %v, want %v", out, tc.Out)
  32  	}
  33  }
  34  
  35  type expandWithLabelTest struct {
  36  	Secret  testBytes `json:"secret"`
  37  	Label   string    `json:"label"`
  38  	Context testBytes `json:"context"`
  39  	Length  uint16    `json:"length"`
  40  	Out     testBytes `json:"out"`
  41  }
  42  
  43  func testExpandWithLabel(t *testing.T, cs CipherSuite, tc *expandWithLabelTest) {
  44  	out, err := cs.expandWithLabel([]byte(tc.Secret), []byte(tc.Label), []byte(tc.Context), tc.Length)
  45  	if err != nil {
  46  		t.Fatal(err)
  47  	}
  48  	if !bytes.Equal([]byte(tc.Out), out) {
  49  		t.Errorf("got %v, want %v", out, tc.Out)
  50  	}
  51  }
  52  
  53  type deriveSecretTest struct {
  54  	Label  string    `json:"label"`
  55  	Out    testBytes `json:"out"`
  56  	Secret testBytes `json:"secret"`
  57  }
  58  
  59  func testDeriveSecret(t *testing.T, cs CipherSuite, tc *deriveSecretTest) {
  60  	out, err := cs.deriveSecret([]byte(tc.Secret), []byte(tc.Label))
  61  	if err != nil {
  62  		t.Fatal(err)
  63  	}
  64  	if !bytes.Equal([]byte(tc.Out), out) {
  65  		t.Errorf("got %v, want %v", out, tc.Out)
  66  	}
  67  }
  68  
  69  type deriveTreeSecretTest struct {
  70  	Secret     testBytes `json:"secret"`
  71  	Label      string    `json:"label"`
  72  	Generation uint32    `json:"generation"`
  73  	Length     uint16    `json:"length"`
  74  	Out        testBytes `json:"out"`
  75  }
  76  
  77  func testDeriveTreeSecret(t *testing.T, cs CipherSuite, tc *deriveTreeSecretTest) {
  78  	out, err := deriveTreeSecret(cs, []byte(tc.Secret), []byte(tc.Label), tc.Generation, tc.Length)
  79  	if err != nil {
  80  		t.Fatal(err)
  81  	}
  82  	if !bytes.Equal([]byte(tc.Out), out) {
  83  		t.Errorf("got %v, want %v", out, tc.Out)
  84  	}
  85  }
  86  
  87  type signWithLabelTest struct {
  88  	Priv      testBytes `json:"priv"`
  89  	Pub       testBytes `json:"pub"`
  90  	Content   testBytes `json:"content"`
  91  	Label     string    `json:"label"`
  92  	Signature testBytes `json:"signature"`
  93  }
  94  
  95  func testSignWithLabel(t *testing.T, cs CipherSuite, tc *signWithLabelTest) {
  96  	if !cs.verifyWithLabel([]byte(tc.Pub), []byte(tc.Label), []byte(tc.Content), []byte(tc.Signature)) {
  97  		t.Error("reference signature did not verify")
  98  	}
  99  
 100  	signValue, err := cs.signWithLabel([]byte(tc.Priv), []byte(tc.Label), []byte(tc.Content))
 101  	if err != nil {
 102  		t.Fatalf("signWithLabel() = %v", err)
 103  	}
 104  	if !cs.verifyWithLabel([]byte(tc.Pub), []byte(tc.Label), []byte(tc.Content), signValue) {
 105  		t.Error("generated signature did not verify")
 106  	}
 107  }
 108  
 109  type encryptWithLabelTest struct {
 110  	Priv       testBytes `json:"priv"`
 111  	Pub        testBytes `json:"pub"`
 112  	Label      string    `json:"label"`
 113  	Context    testBytes `json:"context"`
 114  	Plaintext  testBytes `json:"plaintext"`
 115  	KEMOutput  testBytes `json:"kem_output"`
 116  	Ciphertext testBytes `json:"ciphertext"`
 117  }
 118  
 119  func testEncryptWithLabel(t *testing.T, cs CipherSuite, tc *encryptWithLabelTest) {
 120  	plaintext, err := cs.decryptWithLabel([]byte(tc.Priv), []byte(tc.Label), []byte(tc.Context), []byte(tc.KEMOutput), []byte(tc.Ciphertext))
 121  	if err != nil {
 122  		t.Fatalf("decryptWithLabel() = %v", err)
 123  	}
 124  	if !bytes.Equal([]byte(tc.Plaintext), plaintext) {
 125  		t.Fatalf("decrypting reference ciphertext: got %v, want %v", plaintext, tc.Plaintext)
 126  	}
 127  
 128  	kemOutput, ciphertext, err := cs.encryptWithLabel([]byte(tc.Pub), []byte(tc.Label), []byte(tc.Context), []byte(tc.Plaintext))
 129  	if err != nil {
 130  		t.Fatalf("encryptWithLabel() = %v", err)
 131  	}
 132  	plaintext, err = cs.decryptWithLabel([]byte(tc.Priv), []byte(tc.Label), []byte(tc.Context), kemOutput, ciphertext)
 133  	if err != nil {
 134  		t.Fatalf("decryptWithLabel() = %v", err)
 135  	}
 136  	if !bytes.Equal([]byte(tc.Plaintext), plaintext) {
 137  		t.Fatalf("decrypting reference ciphertext: got %v, want %v", plaintext, tc.Plaintext)
 138  	}
 139  }
 140  
 141  func TestCryptoBasics(t *testing.T) {
 142  	var tests []cryptoBasicsTest
 143  	loadTestVector(t, "testdata/crypto-basics.json", &tests)
 144  
 145  	for i, tc := range tests {
 146  		t.Run(fmt.Sprintf("[%v]", i), func(t *testing.T) {
 147  			t.Run("ref_hash", func(t *testing.T) {
 148  				testRefHash(t, tc.CipherSuite, &tc.RefHash)
 149  			})
 150  			t.Run("expand_with_label", func(t *testing.T) {
 151  				testExpandWithLabel(t, tc.CipherSuite, &tc.ExpandWithLabel)
 152  			})
 153  			t.Run("derive_secret", func(t *testing.T) {
 154  				testDeriveSecret(t, tc.CipherSuite, &tc.DeriveSecret)
 155  			})
 156  			t.Run("derive_tree_secret", func(t *testing.T) {
 157  				testDeriveTreeSecret(t, tc.CipherSuite, &tc.DeriveTreeSecret)
 158  			})
 159  			t.Run("sign_with_label", func(t *testing.T) {
 160  				testSignWithLabel(t, tc.CipherSuite, &tc.SignWithLabel)
 161  			})
 162  			t.Run("encrypt_with_label", func(t *testing.T) {
 163  				testEncryptWithLabel(t, tc.CipherSuite, &tc.EncryptWithLabel)
 164  			})
 165  		})
 166  	}
 167  }
 168