1/*-
2 * Copyright 2014 Square Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package jose
18
19import (
20	"bytes"
21	"crypto/cipher"
22	"crypto/rand"
23	"crypto/sha256"
24	"io"
25	"testing"
26
27	"golang.org/x/crypto/pbkdf2"
28)
29
30func TestInvalidSymmetricAlgorithms(t *testing.T) {
31	_, err := newSymmetricRecipient("XYZ", []byte{})
32	if err != ErrUnsupportedAlgorithm {
33		t.Error("should not accept invalid algorithm")
34	}
35
36	enc := &symmetricKeyCipher{}
37	_, err = enc.encryptKey([]byte{}, "XYZ")
38	if err != ErrUnsupportedAlgorithm {
39		t.Error("should not accept invalid algorithm")
40	}
41}
42
43func TestAeadErrors(t *testing.T) {
44	aead := &aeadContentCipher{
45		keyBytes:     16,
46		authtagBytes: 16,
47		getAead: func(key []byte) (cipher.AEAD, error) {
48			return nil, ErrCryptoFailure
49		},
50	}
51
52	parts, err := aead.encrypt([]byte{}, []byte{}, []byte{})
53	if err != ErrCryptoFailure {
54		t.Error("should handle aead failure")
55	}
56
57	_, err = aead.decrypt([]byte{}, []byte{}, parts)
58	if err != ErrCryptoFailure {
59		t.Error("should handle aead failure")
60	}
61}
62
63func TestInvalidKey(t *testing.T) {
64	gcm := newAESGCM(16).(*aeadContentCipher)
65	_, err := gcm.getAead([]byte{})
66	if err == nil {
67		t.Error("should not accept invalid key")
68	}
69}
70
71func TestStaticKeyGen(t *testing.T) {
72	key := make([]byte, 32)
73	io.ReadFull(rand.Reader, key)
74
75	gen := &staticKeyGenerator{key: key}
76	if gen.keySize() != len(key) {
77		t.Error("static key generator reports incorrect size")
78	}
79
80	generated, _, err := gen.genKey()
81	if err != nil {
82		t.Error("static key generator should always succeed", err)
83	}
84	if !bytes.Equal(generated, key) {
85		t.Error("static key generator returns different data")
86	}
87}
88
89func TestAeadInvalidInput(t *testing.T) {
90	sample := []byte("1234567890123456")
91	tt := []aeadParts{
92		{},
93		{iv: sample, tag: sample},
94	}
95	for _, tc := range tt {
96		aead := newAESGCM(16).(*aeadContentCipher)
97		_, err := aead.decrypt(sample, []byte{}, &tc)
98		if err != ErrCryptoFailure {
99			t.Error("should handle aead failure")
100		}
101	}
102}
103
104func TestVectorsAESGCM(t *testing.T) {
105	// Source: http://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-29#appendix-A.1
106	plaintext := []byte{
107		84, 104, 101, 32, 116, 114, 117, 101, 32, 115, 105, 103, 110, 32,
108		111, 102, 32, 105, 110, 116, 101, 108, 108, 105, 103, 101, 110, 99,
109		101, 32, 105, 115, 32, 110, 111, 116, 32, 107, 110, 111, 119, 108,
110		101, 100, 103, 101, 32, 98, 117, 116, 32, 105, 109, 97, 103, 105,
111		110, 97, 116, 105, 111, 110, 46}
112
113	aad := []byte{
114		101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 48, 69,
115		116, 84, 48, 70, 70, 85, 67, 73, 115, 73, 109, 86, 117, 89, 121, 73,
116		54, 73, 107, 69, 121, 78, 84, 90, 72, 81, 48, 48, 105, 102, 81}
117
118	expectedCiphertext := []byte{
119		229, 236, 166, 241, 53, 191, 115, 196, 174, 43, 73, 109, 39, 122,
120		233, 96, 140, 206, 120, 52, 51, 237, 48, 11, 190, 219, 186, 80, 111,
121		104, 50, 142, 47, 167, 59, 61, 181, 127, 196, 21, 40, 82, 242, 32,
122		123, 143, 168, 226, 73, 216, 176, 144, 138, 247, 106, 60, 16, 205,
123		160, 109, 64, 63, 192}
124
125	expectedAuthtag := []byte{
126		92, 80, 104, 49, 133, 25, 161, 215, 173, 101, 219, 211, 136, 91, 210, 145}
127
128	// Mock random reader
129	RandReader = bytes.NewReader([]byte{
130		177, 161, 244, 128, 84, 143, 225, 115, 63, 180, 3, 255, 107, 154,
131		212, 246, 138, 7, 110, 91, 112, 46, 34, 105, 47, 130, 203, 46, 122,
132		234, 64, 252, 227, 197, 117, 252, 2, 219, 233, 68, 180, 225, 77, 219})
133	defer resetRandReader()
134
135	enc := newAESGCM(32)
136	key, _, _ := randomKeyGenerator{size: 32}.genKey()
137	out, err := enc.encrypt(key, aad, plaintext)
138	if err != nil {
139		t.Error("Unable to encrypt:", err)
140		return
141	}
142
143	if bytes.Compare(out.ciphertext, expectedCiphertext) != 0 {
144		t.Error("Ciphertext did not match")
145	}
146	if bytes.Compare(out.tag, expectedAuthtag) != 0 {
147		t.Error("Auth tag did not match")
148	}
149}
150
151func TestVectorPBES2_HS256A_128KW(t *testing.T) {
152	cipher := &symmetricKeyCipher{
153		key: []byte("Thus from my lips, by yours, my sin is purged."),
154		p2c: 4096,
155		p2s: []byte{
156			217, 96, 147, 112, 150, 117, 70,
157			247, 127, 8, 155, 137, 174, 42, 80, 215,
158		},
159	}
160
161	cek := []byte{
162		111, 27, 25, 52, 66, 29, 20, 78, 92, 176, 56, 240, 65, 208, 82, 112,
163		161, 131, 36, 55, 202, 236, 185, 172, 129, 23, 153, 194, 195, 48,
164		253, 182,
165	}
166
167	// PBES2-HS256+A128KW || 0x00 || p2s
168	salt := []byte{
169		80, 66, 69, 83, 50, 45, 72, 83, 50, 53, 54, 43, 65, 49, 50, 56, 75,
170		87, 0, 217, 96, 147, 112, 150, 117, 70, 247, 127, 8, 155, 137, 174,
171		42, 80, 215,
172	}
173
174	expectedDerivedKey := []byte{
175		110, 171, 169, 92, 129, 92, 109, 117, 233, 242, 116, 233, 170, 14,
176		24, 75}
177
178	expectedEncryptedKey := []byte{
179		78, 186, 151, 59, 11, 141, 81, 240, 213, 245, 83, 211, 53, 188, 134,
180		188, 66, 125, 36, 200, 222, 124, 5, 103, 249, 52, 117, 184, 140, 81,
181		246, 158, 161, 177, 20, 33, 245, 57, 59, 4}
182
183	derivedKey := pbkdf2.Key(cipher.key, salt, cipher.p2c, 16, sha256.New)
184	if bytes.Compare(derivedKey, expectedDerivedKey) != 0 {
185		t.Error("Derived key did not match")
186	}
187
188	encryptedKey, err := cipher.encryptKey(cek, PBES2_HS256_A128KW)
189	if err != nil {
190		t.Fatal("Unable to encrypt:", err)
191	}
192
193	if bytes.Compare(encryptedKey.encryptedKey, expectedEncryptedKey) != 0 {
194		t.Error("Encrypted key did not match")
195	}
196}
197