1
2
3 package ocb
4
5 import (
6 "bytes"
7 "crypto/aes"
8 "crypto/cipher"
9 "crypto/rand"
10 "encoding/binary"
11 "encoding/hex"
12 mathrand "math/rand"
13 "testing"
14 "time"
15 )
16
17 const (
18 blockLength = 16
19 maxLength = 1 << 12
20 )
21
22 func TestOCBImplementsAEADInterface(t *testing.T) {
23 var ocbInstance ocb
24 var aux interface{} = &ocbInstance
25 _, ok := aux.(cipher.AEAD)
26 if !ok {
27 t.Errorf("Error: OCB can't implement AEAD interface")
28 }
29 }
30
31 func TestZeroHash(t *testing.T) {
32
33 aesCipher, err := aes.NewCipher(testKey)
34 if err != nil {
35 t.Fatal(err)
36 }
37 o := ocb{
38 block: aesCipher,
39 tagSize: defaultTagSize,
40 nonceSize: defaultNonceSize,
41 }
42
43 blockSize := o.block.BlockSize()
44 if !bytes.Equal(o.hash(make([]byte, 0)), make([]byte, blockSize)) {
45 t.Errorf("Error: Hash() did not return a correct amount of zero bytes")
46 }
47 }
48
49 func TestNewOCBIncorrectNonceLength(t *testing.T) {
50 aesCipher, err := aes.NewCipher(make([]byte, 16))
51 if err != nil {
52 t.Fatal(err)
53 }
54 e, err := NewOCBWithNonceAndTagSize(aesCipher, 0, 16)
55 if err == nil || e != nil {
56 t.Errorf("OCB with nonceLength 0 was not rejected")
57 }
58 }
59
60 func TestSealIncorrectNonceLength(t *testing.T) {
61 aesCipher, err := aes.NewCipher(make([]byte, 16))
62 if err != nil {
63 t.Fatal(err)
64 }
65 o, err := NewOCBWithNonceAndTagSize(aesCipher, 15, 16)
66 if err != nil {
67 t.Fatal(err)
68 }
69 defer func() {
70 if r := recover(); r == nil {
71 t.Errorf("Ocb.Seal didn't panic on exceedingly long nonce")
72 }
73 }()
74 longNonce := make([]byte, o.NonceSize()+1)
75 o.Seal(nil, longNonce, nil, nil)
76 }
77
78 func TestOpenIncorrectNonceLength(t *testing.T) {
79 aesCipher, err := aes.NewCipher(make([]byte, 16))
80 if err != nil {
81 t.Fatal(err)
82 }
83 o, err := NewOCBWithNonceAndTagSize(aesCipher, 15, 16)
84 if err != nil {
85 t.Fatal(err)
86 }
87 defer func() {
88 if r := recover(); r == nil {
89 t.Errorf("Ocb.Open didn't panic on exceedingly long nonce")
90 }
91 }()
92 longNonce := make([]byte, o.NonceSize()+1)
93 _, err = o.Open(nil, longNonce, nil, nil)
94
95 if err != nil {
96 }
97 }
98
99 func TestOpenShortCiphertext(t *testing.T) {
100 aesCipher, err := aes.NewCipher(make([]byte, 16))
101 if err != nil {
102 t.Fatal(err)
103 }
104 o, err := NewOCBWithNonceAndTagSize(aesCipher, 15, 16)
105 if err != nil {
106 t.Fatal(err)
107 }
108 shortCt := make([]byte, o.Overhead()-1)
109 pt, err := o.Open(nil, nil, nil, shortCt)
110 if pt != nil || err == nil {
111 t.Errorf("Ocb.Open processed an exceedingly short ciphertext")
112 }
113 }
114
115 func TestEncryptDecryptRFC7253TestVectors(t *testing.T) {
116
117 aesCipher, err := aes.NewCipher(testKey)
118 if err != nil {
119 t.Fatal(err)
120 }
121 ocbInstance, errO := NewOCB(aesCipher)
122 if errO != nil {
123 t.Fatal(err)
124 }
125 for _, test := range rfc7253testVectors {
126 nonce, _ := hex.DecodeString(test.nonce)
127 adata, _ := hex.DecodeString(test.header)
128 targetPt, _ := hex.DecodeString(test.plaintext)
129 targetCt, _ := hex.DecodeString(test.ciphertext)
130 ct := ocbInstance.Seal(nil, nonce, targetPt, adata)
131
132 if !bytes.Equal(ct, targetCt) {
133 t.Errorf(
134 `RFC7253 Test vectors Encrypt error (ciphertexts don't match):
135 Got:
136 %X
137 Want:
138 %X`, ct, targetCt)
139 }
140
141 pt, err := ocbInstance.Open(nil, nonce, targetCt, adata)
142 if err != nil {
143 t.Errorf(
144 `RFC7253 Valid ciphertext was refused decryption:
145 plaintext %X
146 nonce %X
147 header %X
148 ciphertext %X`, targetPt, nonce, adata, targetCt)
149 }
150 if !bytes.Equal(pt, targetPt) {
151 t.Errorf(
152 `RFC7253 test vectors Decrypt error (plaintexts don't match):
153 Got:
154 %X
155 Want:
156 %X`, pt, targetPt)
157 }
158 }
159 }
160
161 func TestEncryptDecryptRFC7253TagLen96(t *testing.T) {
162 test := rfc7253TestVectorTaglen96
163 key, _ := hex.DecodeString(test.key)
164 nonce, _ := hex.DecodeString(test.nonce)
165 adata, _ := hex.DecodeString(test.header)
166 targetPt, _ := hex.DecodeString(test.plaintext)
167 targetCt, _ := hex.DecodeString(test.ciphertext)
168 aesCipher, err := aes.NewCipher(key)
169 if err != nil {
170 t.Fatal(err)
171 }
172 ocbInstance, err := NewOCBWithNonceAndTagSize(aesCipher, len(nonce), 96/8)
173 if err != nil {
174 t.Fatal(err)
175 }
176 ct := ocbInstance.Seal(nil, nonce, targetPt, adata)
177 if !bytes.Equal(ct, targetCt) {
178 t.Errorf(
179 `RFC7253 test tagLen96 error (ciphertexts don't match):
180 Got:
181 %X
182 Want:
183 %X`, ct, targetCt)
184 }
185 pt, err := ocbInstance.Open(nil, nonce, targetCt, adata)
186 if err != nil {
187 t.Errorf(`RFC7253 test tagLen96 was refused decryption`)
188 }
189 if !bytes.Equal(pt, targetPt) {
190 t.Errorf(
191 `RFC7253 test tagLen96 error (plaintexts don't match):
192 Got:
193 %X
194 Want:
195 %X`, pt, targetPt)
196 }
197 }
198
199
200 func TestEncryptDecryptRFC7253DifferentKeySizes(t *testing.T) {
201 for _, testCase := range rfc7253AlgorithmTest {
202 keyLen := testCase.KEYLEN
203 tagLen := testCase.TAGLEN
204 key := make([]byte, keyLen/8)
205 key[len(key)-1] = byte(tagLen)
206
207 aesCipher, err := aes.NewCipher(key)
208 if err != nil {
209 t.Fatal(err)
210 }
211 ocbInstance, err := NewOCBWithNonceAndTagSize(aesCipher, 12, tagLen/8)
212 if err != nil {
213 t.Fatal(err)
214 }
215 C := make([]byte, 0)
216 ending := make([]byte, 4)
217 var N, S []byte
218 for i := 0; i < 128; i++ {
219 S = make([]byte, i)
220 binary.BigEndian.PutUint32(ending, uint32(3*i+1))
221 N = append(make([]byte, 8), ending...)
222
223 C = append(C, ocbInstance.Seal(nil, N, S, S)...)
224 binary.BigEndian.PutUint32(ending, uint32(3*i+2))
225 N = append(make([]byte, 8), ending...)
226
227 C = append(C, ocbInstance.Seal(nil, N, S, make([]byte, 0))...)
228 binary.BigEndian.PutUint32(ending, uint32(3*i+3))
229 N = append(make([]byte, 8), ending...)
230
231 C = append(C, ocbInstance.Seal(nil, N, make([]byte, 0), S)...)
232 }
233 binary.BigEndian.PutUint32(ending, uint32(385))
234 N = append(make([]byte, 8), ending...)
235
236 output := ocbInstance.Seal(nil, N, make([]byte, 0), C)
237 targetOutput, _ := hex.DecodeString(testCase.OUTPUT)
238 if !bytes.Equal(output, targetOutput) {
239 t.Errorf(
240 `RFC7253 Test algorithm error (outputs do not match):
241 AES_%d_OCB_TAGLEN%d
242 Got:
243 %X
244 Want:
245 %X`, keyLen, tagLen, output, targetOutput)
246 }
247 }
248 }
249
250 func TestEncryptDecryptGoTestVectors(t *testing.T) {
251 for _, test := range randomVectors {
252 key, _ := hex.DecodeString(test.key)
253 aesCipher, err := aes.NewCipher(key)
254 if err != nil {
255 t.Fatal(err)
256 }
257 nonce, _ := hex.DecodeString(test.nonce)
258 adata, _ := hex.DecodeString(test.header)
259 targetPt, _ := hex.DecodeString(test.plaintext)
260 targetCt, _ := hex.DecodeString(test.ciphertext)
261 tagSize := len(targetCt) - len(targetPt)
262 ocbInstance, err := NewOCBWithNonceAndTagSize(aesCipher, len(nonce), tagSize)
263 if err != nil {
264 t.Fatal(err)
265 }
266
267 ct := ocbInstance.Seal(nil, nonce, targetPt, adata)
268 if !bytes.Equal(ct, targetCt) {
269 t.Errorf(
270 `Go Test vectors Encrypt error (ciphertexts don't match):
271 Got:
272 %X
273 Want:
274 %X`, ct, targetCt)
275 }
276
277
278 pt, err := ocbInstance.Open(nil, nonce, targetCt, adata)
279 if err != nil {
280 t.Errorf(
281 `Valid Go ciphertext was refused decryption:
282 plaintext %X
283 nonce %X
284 header %X
285 ciphertext %X`, targetPt, nonce, adata, targetCt)
286 }
287 if !bytes.Equal(pt, targetPt) {
288 t.Errorf(
289 `Go Test vectors Decrypt error (plaintexts don't match):
290 Got:
291 %X
292 Want:
293 %X`, pt, targetPt)
294 }
295 }
296 }
297
298 func TestEncryptDecryptVectorsWithPreviousDataRandomizeSlow(t *testing.T) {
299 mathrand.Seed(time.Now().UnixNano())
300 allowedKeyLengths := []int{16, 24, 32}
301 for _, keyLength := range allowedKeyLengths {
302 pt := make([]byte, mathrand.Intn(maxLength))
303 header := make([]byte, mathrand.Intn(maxLength))
304 key := make([]byte, keyLength)
305
306 nonce := make([]byte, 1+mathrand.Intn(blockLength-1))
307 previousData := make([]byte, mathrand.Intn(maxLength))
308
309 itemsToPopulate := [][]byte{pt, header, key, nonce, previousData}
310 for _, item := range itemsToPopulate {
311 _, err := rand.Read(item)
312 if err != nil {
313 }
314 }
315 aesCipher, err := aes.NewCipher(key)
316 if err != nil {
317 t.Fatal(err)
318 }
319 ocb, err := NewOCB(aesCipher)
320 if err != nil {
321 t.Fatal(err)
322 }
323 newData := ocb.Seal(previousData, nonce, pt, header)
324 ct := newData[len(previousData):]
325 decrypted, err := ocb.Open(nil, nonce, ct, header)
326 if err != nil {
327 t.Errorf(
328 `Decrypt refused valid tag (not displaying long output)`)
329 break
330 }
331 if !bytes.Equal(pt, decrypted) {
332 t.Errorf(
333 `Random Encrypt/Decrypt error (plaintexts don't match)`)
334 break
335 }
336 }
337 }
338
339 func TestRejectTamperedCiphertextRandomizeSlow(t *testing.T) {
340 pt := make([]byte, mathrand.Intn(maxLength))
341 header := make([]byte, mathrand.Intn(maxLength))
342 key := make([]byte, blockLength)
343
344 nonce := make([]byte, blockLength-1)
345 itemsToPopulate := [][]byte{pt, header, key, nonce}
346 for _, item := range itemsToPopulate {
347 _, err := rand.Read(item)
348 if err != nil {
349 }
350 }
351 aesCipher, err := aes.NewCipher(key)
352 if err != nil {
353 t.Fatal(err)
354 }
355 ocb, errO := NewOCB(aesCipher)
356 if errO != nil {
357 t.Fatal(err)
358 }
359 ct := ocb.Seal(nil, nonce, pt, header)
360
361 tampered := make([]byte, len(ct))
362 copy(tampered, ct)
363 for bytes.Equal(tampered, ct) {
364 tampered[mathrand.Intn(len(ct))] = byte(mathrand.Intn(len(ct)))
365 }
366 _, err = ocb.Open(nil, nonce, tampered, header)
367 if err == nil {
368 t.Errorf(
369 "Tampered ciphertext was not refused decryption (OCB did not return an error)")
370 return
371 }
372 }
373
374 func TestParameters(t *testing.T) {
375 blockLength := 16
376 key := make([]byte, blockLength)
377 aesCipher, err := aes.NewCipher(key)
378 if err != nil {
379 t.Fatal(err)
380 }
381 t.Run("Should return error on too long tagSize", func(st *testing.T) {
382 tagSize := blockLength + 1 + mathrand.Intn(12)
383 nonceSize := 1 + mathrand.Intn(16)
384 _, err := NewOCBWithNonceAndTagSize(aesCipher, nonceSize, tagSize)
385 if err == nil {
386 st.Errorf("No error was returned")
387 }
388 })
389 t.Run("Should return error on too long nonceSize", func(st *testing.T) {
390 tagSize := 12
391 nonceSize := blockLength + mathrand.Intn(16)
392 _, err := NewOCBWithNonceAndTagSize(aesCipher, nonceSize, tagSize)
393 if err == nil {
394 st.Errorf("No error was returned")
395 }
396 })
397 t.Run(
398 "Should not give error with allowed parameters", func(st *testing.T) {
399
400
401 nonceSize := 12 + mathrand.Intn(blockLength-12)
402 tagSize := 12 + mathrand.Intn(blockLength-11)
403 _, err := NewOCBWithNonceAndTagSize(aesCipher, nonceSize, tagSize)
404 if err != nil {
405 st.Errorf("An error was returned")
406 }
407 })
408 }
409
410 func BenchmarkEncrypt(b *testing.B) {
411 plaintextLength := maxLength
412 headerLength := 16
413 pt := make([]byte, plaintextLength)
414 header := make([]byte, headerLength)
415 key := make([]byte, blockLength)
416 nonce := make([]byte, blockLength-1)
417 itemsToPopulate := [][]byte{pt, header, key, nonce}
418 for _, item := range itemsToPopulate {
419 _, err := rand.Read(item)
420 if err != nil {
421 }
422 }
423 aesCipher, err := aes.NewCipher(key)
424 if err != nil {
425 b.Fatal(err)
426 }
427 ocb, err := NewOCB(aesCipher)
428 if err != nil {
429 b.Fatal(err)
430 }
431 for i := 0; i < b.N; i++ {
432 ocb.Seal(nil, nonce, pt, header)
433 }
434 }
435
436 func BenchmarkDecrypt(b *testing.B) {
437 plaintextLength := maxLength
438 headerLength := 16
439 pt := make([]byte, plaintextLength)
440 header := make([]byte, headerLength)
441 key := make([]byte, blockLength)
442 nonce := make([]byte, blockLength-1)
443 itemsToPopulate := [][]byte{pt, header, key, nonce}
444 for _, item := range itemsToPopulate {
445 _, err := rand.Read(item)
446 if err != nil {
447 }
448 }
449 aesCipher, err := aes.NewCipher(key)
450 if err != nil {
451 b.Fatal(err)
452 }
453 ocb, errO := NewOCB(aesCipher)
454 if errO != nil {
455 b.Fatal(err)
456 }
457 ct := ocb.Seal(nil, nonce, pt, header)
458 for i := 0; i < b.N; i++ {
459 _, err := ocb.Open(nil, nonce, ct, header)
460 if err != nil {
461 b.Fatal(err)
462 }
463 }
464 }
465
View as plain text