1// Copyright 2021 The BoringSSL Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18	"bytes"
19	"crypto/aes"
20	"crypto/rand"
21	"encoding/hex"
22	"testing"
23)
24
25func TestCTSRoundTrip(t *testing.T) {
26	var buf [aes.BlockSize * 8]byte
27	var key, iv [16]byte
28	rand.Reader.Read(buf[:])
29	rand.Reader.Read(key[:])
30	rand.Reader.Read(iv[:])
31
32	for i := aes.BlockSize; i < len(buf); i++ {
33		in := buf[:i]
34		ciphertext := doCTSEncrypt(key[:], in[:], iv[:])
35		if len(ciphertext) != len(in) {
36			t.Errorf("incorrect ciphertext length for input length %d", len(in))
37			continue
38		}
39		out := doCTSDecrypt(key[:], ciphertext, iv[:])
40
41		if !bytes.Equal(in[:], out) {
42			t.Errorf("did not round trip for length %d", len(in))
43		}
44	}
45}
46
47func TestCTSVectors(t *testing.T) {
48	tests := []struct {
49		plaintextHex  string
50		ciphertextHex string
51		ivHex         string
52	}{
53		// Test vectors from OpenSSL.
54		{
55			"4920776f756c64206c696b652074686520",
56			"c6353568f2bf8cb4d8a580362da7ff7f97",
57			"00000000000000000000000000000000",
58		},
59		{
60			"4920776f756c64206c696b65207468652047656e6572616c20476175277320",
61			"fc00783e0efdb2c1d445d4c8eff7ed2297687268d6ecccc0c07b25e25ecfe5",
62			"00000000000000000000000000000000",
63		},
64		{
65			"4920776f756c64206c696b65207468652047656e6572616c2047617527732043",
66			"39312523a78662d5be7fcbcc98ebf5a897687268d6ecccc0c07b25e25ecfe584",
67			"00000000000000000000000000000000",
68		},
69		{
70			"4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c",
71			"97687268d6ecccc0c07b25e25ecfe584b3fffd940c16a18c1b5549d2f838029e39312523a78662d5be7fcbcc98ebf5",
72			"00000000000000000000000000000000",
73		},
74		{
75			"4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c",
76			"5432a630742dee7beb70f9f1400ee6a0426da5c54a9990f5ae0b7825f51f0060b557cfb581949a4bdf3bb67dedd472",
77			"000102030405060708090a0b0c0d0e0f",
78		},
79	}
80
81	key := fromHex("636869636b656e207465726979616b69")
82
83	for i, test := range tests {
84		plaintext := fromHex(test.plaintextHex)
85		iv := fromHex(test.ivHex)
86		ciphertext := doCTSEncrypt(key, plaintext, iv)
87		if got := hex.EncodeToString(ciphertext); got != test.ciphertextHex {
88			t.Errorf("#%d: unexpected ciphertext %s, want %s", i, got, test.ciphertextHex)
89		}
90		plaintextAgain := doCTSDecrypt(key, ciphertext, iv)
91		if !bytes.Equal(plaintext, plaintextAgain) {
92			t.Errorf("#%d: did not round trip", i)
93		}
94	}
95}
96