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