1package vault
2
3import (
4	"bytes"
5	"context"
6	"encoding/json"
7	"testing"
8
9	log "github.com/hashicorp/go-hclog"
10	"github.com/hashicorp/vault/sdk/helper/logging"
11	"github.com/hashicorp/vault/sdk/logical"
12	"github.com/hashicorp/vault/sdk/physical"
13	"github.com/hashicorp/vault/sdk/physical/inmem"
14)
15
16var (
17	logger = logging.NewVaultLogger(log.Trace)
18)
19
20// mockBarrier returns a physical backend, security barrier, and master key
21func mockBarrier(t testing.TB) (physical.Backend, SecurityBarrier, []byte) {
22	inm, err := inmem.NewInmem(nil, logger)
23	if err != nil {
24		t.Fatalf("err: %v", err)
25	}
26	b, err := NewAESGCMBarrier(inm)
27	if err != nil {
28		t.Fatalf("err: %v", err)
29	}
30
31	// Initialize and unseal
32	key, _ := b.GenerateKey()
33	b.Initialize(context.Background(), key)
34	b.Unseal(context.Background(), key)
35	return inm, b, key
36}
37
38func TestAESGCMBarrier_Basic(t *testing.T) {
39	inm, err := inmem.NewInmem(nil, logger)
40	if err != nil {
41		t.Fatalf("err: %v", err)
42	}
43	b, err := NewAESGCMBarrier(inm)
44	if err != nil {
45		t.Fatalf("err: %v", err)
46	}
47	testBarrier(t, b)
48}
49
50func TestAESGCMBarrier_Rotate(t *testing.T) {
51	inm, err := inmem.NewInmem(nil, logger)
52	if err != nil {
53		t.Fatalf("err: %v", err)
54	}
55	b, err := NewAESGCMBarrier(inm)
56	if err != nil {
57		t.Fatalf("err: %v", err)
58	}
59	testBarrier_Rotate(t, b)
60}
61
62func TestAESGCMBarrier_Upgrade(t *testing.T) {
63	inm, err := inmem.NewInmem(nil, logger)
64	if err != nil {
65		t.Fatalf("err: %v", err)
66	}
67	b1, err := NewAESGCMBarrier(inm)
68	if err != nil {
69		t.Fatalf("err: %v", err)
70	}
71	b2, err := NewAESGCMBarrier(inm)
72	if err != nil {
73		t.Fatalf("err: %v", err)
74	}
75	testBarrier_Upgrade(t, b1, b2)
76}
77
78func TestAESGCMBarrier_Upgrade_Rekey(t *testing.T) {
79	inm, err := inmem.NewInmem(nil, logger)
80	if err != nil {
81		t.Fatalf("err: %v", err)
82	}
83	b1, err := NewAESGCMBarrier(inm)
84	if err != nil {
85		t.Fatalf("err: %v", err)
86	}
87	b2, err := NewAESGCMBarrier(inm)
88	if err != nil {
89		t.Fatalf("err: %v", err)
90	}
91	testBarrier_Upgrade_Rekey(t, b1, b2)
92}
93
94func TestAESGCMBarrier_Rekey(t *testing.T) {
95	inm, err := inmem.NewInmem(nil, logger)
96	if err != nil {
97		t.Fatalf("err: %v", err)
98	}
99	b, err := NewAESGCMBarrier(inm)
100	if err != nil {
101		t.Fatalf("err: %v", err)
102	}
103	testBarrier_Rekey(t, b)
104}
105
106// Test an upgrade from the old (0.1) barrier/init to the new
107// core/keyring style
108func TestAESGCMBarrier_BackwardsCompatible(t *testing.T) {
109	inm, err := inmem.NewInmem(nil, logger)
110	if err != nil {
111		t.Fatalf("err: %v", err)
112	}
113	b, err := NewAESGCMBarrier(inm)
114	if err != nil {
115		t.Fatalf("err: %v", err)
116	}
117
118	// Generate a barrier/init entry
119	encrypt, _ := b.GenerateKey()
120	init := &barrierInit{
121		Version: 1,
122		Key:     encrypt,
123	}
124	buf, _ := json.Marshal(init)
125
126	// Protect with master key
127	master, _ := b.GenerateKey()
128	gcm, _ := b.aeadFromKey(master)
129	value, err := b.encrypt(barrierInitPath, initialKeyTerm, gcm, buf)
130	if err != nil {
131		t.Fatal(err)
132	}
133
134	// Write to the physical backend
135	pe := &physical.Entry{
136		Key:   barrierInitPath,
137		Value: value,
138	}
139	inm.Put(context.Background(), pe)
140
141	// Create a fake key
142	gcm, _ = b.aeadFromKey(encrypt)
143	value, err = b.encrypt("test/foo", initialKeyTerm, gcm, []byte("test"))
144	if err != nil {
145		t.Fatal(err)
146	}
147	pe = &physical.Entry{
148		Key:   "test/foo",
149		Value: value,
150	}
151	inm.Put(context.Background(), pe)
152
153	// Should still be initialized
154	isInit, err := b.Initialized(context.Background())
155	if err != nil {
156		t.Fatalf("err: %v", err)
157	}
158	if !isInit {
159		t.Fatalf("should be initialized")
160	}
161
162	// Unseal should work and migrate online
163	err = b.Unseal(context.Background(), master)
164	if err != nil {
165		t.Fatalf("err: %v", err)
166	}
167
168	// Check for migration
169	out, err := inm.Get(context.Background(), barrierInitPath)
170	if err != nil {
171		t.Fatalf("err: %v", err)
172	}
173	if out != nil {
174		t.Fatalf("should delete old barrier init")
175	}
176
177	// Should have keyring
178	out, err = inm.Get(context.Background(), keyringPath)
179	if err != nil {
180		t.Fatalf("err: %v", err)
181	}
182	if out == nil {
183		t.Fatalf("should have keyring file")
184	}
185
186	// Attempt to read encrypted key
187	entry, err := b.Get(context.Background(), "test/foo")
188	if err != nil {
189		t.Fatalf("err: %v", err)
190	}
191	if string(entry.Value) != "test" {
192		t.Fatalf("bad: %#v", entry)
193	}
194}
195
196// Verify data sent through is encrypted
197func TestAESGCMBarrier_Confidential(t *testing.T) {
198	inm, err := inmem.NewInmem(nil, logger)
199	if err != nil {
200		t.Fatalf("err: %v", err)
201	}
202	b, err := NewAESGCMBarrier(inm)
203	if err != nil {
204		t.Fatalf("err: %v", err)
205	}
206
207	// Initialize and unseal
208	key, _ := b.GenerateKey()
209	b.Initialize(context.Background(), key)
210	b.Unseal(context.Background(), key)
211
212	// Put a logical entry
213	entry := &logical.StorageEntry{Key: "test", Value: []byte("test")}
214	err = b.Put(context.Background(), entry)
215	if err != nil {
216		t.Fatalf("err: %v", err)
217	}
218
219	// Check the physical entry
220	pe, err := inm.Get(context.Background(), "test")
221	if err != nil {
222		t.Fatalf("err: %v", err)
223	}
224	if pe == nil {
225		t.Fatalf("missing physical entry")
226	}
227
228	if pe.Key != "test" {
229		t.Fatalf("bad: %#v", pe)
230	}
231	if bytes.Equal(pe.Value, entry.Value) {
232		t.Fatalf("bad: %#v", pe)
233	}
234}
235
236// Verify data sent through cannot be tampered with
237func TestAESGCMBarrier_Integrity(t *testing.T) {
238	inm, err := inmem.NewInmem(nil, logger)
239	if err != nil {
240		t.Fatalf("err: %v", err)
241	}
242	b, err := NewAESGCMBarrier(inm)
243	if err != nil {
244		t.Fatalf("err: %v", err)
245	}
246
247	// Initialize and unseal
248	key, _ := b.GenerateKey()
249	b.Initialize(context.Background(), key)
250	b.Unseal(context.Background(), key)
251
252	// Put a logical entry
253	entry := &logical.StorageEntry{Key: "test", Value: []byte("test")}
254	err = b.Put(context.Background(), entry)
255	if err != nil {
256		t.Fatalf("err: %v", err)
257	}
258
259	// Change a byte in the underlying physical entry
260	pe, _ := inm.Get(context.Background(), "test")
261	pe.Value[15]++
262	err = inm.Put(context.Background(), pe)
263	if err != nil {
264		t.Fatalf("err: %v", err)
265	}
266
267	// Read from the barrier
268	_, err = b.Get(context.Background(), "test")
269	if err == nil {
270		t.Fatalf("should fail!")
271	}
272}
273
274// Verify data sent through cannot be moved
275func TestAESGCMBarrier_MoveIntegrityV1(t *testing.T) {
276	inm, err := inmem.NewInmem(nil, logger)
277	if err != nil {
278		t.Fatalf("err: %v", err)
279	}
280	b, err := NewAESGCMBarrier(inm)
281	if err != nil {
282		t.Fatalf("err: %v", err)
283	}
284	b.currentAESGCMVersionByte = AESGCMVersion1
285
286	// Initialize and unseal
287	key, _ := b.GenerateKey()
288	err = b.Initialize(context.Background(), key)
289	if err != nil {
290		t.Fatalf("err: %v", err)
291	}
292	err = b.Unseal(context.Background(), key)
293	if err != nil {
294		t.Fatalf("err: %v", err)
295	}
296
297	// Put a logical entry
298	entry := &logical.StorageEntry{Key: "test", Value: []byte("test")}
299	err = b.Put(context.Background(), entry)
300	if err != nil {
301		t.Fatalf("err: %v", err)
302	}
303
304	// Change the location of the underlying physical entry
305	pe, _ := inm.Get(context.Background(), "test")
306	pe.Key = "moved"
307	err = inm.Put(context.Background(), pe)
308	if err != nil {
309		t.Fatalf("err: %v", err)
310	}
311
312	// Read from the barrier
313	_, err = b.Get(context.Background(), "moved")
314	if err != nil {
315		t.Fatalf("should succeed with version 1!")
316	}
317}
318
319func TestAESGCMBarrier_MoveIntegrityV2(t *testing.T) {
320	inm, err := inmem.NewInmem(nil, logger)
321	if err != nil {
322		t.Fatalf("err: %v", err)
323	}
324	b, err := NewAESGCMBarrier(inm)
325	if err != nil {
326		t.Fatalf("err: %v", err)
327	}
328	b.currentAESGCMVersionByte = AESGCMVersion2
329
330	// Initialize and unseal
331	key, _ := b.GenerateKey()
332	err = b.Initialize(context.Background(), key)
333	if err != nil {
334		t.Fatalf("err: %v", err)
335	}
336	err = b.Unseal(context.Background(), key)
337	if err != nil {
338		t.Fatalf("err: %v", err)
339	}
340
341	// Put a logical entry
342	entry := &logical.StorageEntry{Key: "test", Value: []byte("test")}
343	err = b.Put(context.Background(), entry)
344	if err != nil {
345		t.Fatalf("err: %v", err)
346	}
347
348	// Change the location of the underlying physical entry
349	pe, _ := inm.Get(context.Background(), "test")
350	pe.Key = "moved"
351	err = inm.Put(context.Background(), pe)
352	if err != nil {
353		t.Fatalf("err: %v", err)
354	}
355
356	// Read from the barrier
357	_, err = b.Get(context.Background(), "moved")
358	if err == nil {
359		t.Fatalf("should fail with version 2!")
360	}
361}
362
363func TestAESGCMBarrier_UpgradeV1toV2(t *testing.T) {
364	inm, err := inmem.NewInmem(nil, logger)
365	if err != nil {
366		t.Fatalf("err: %v", err)
367	}
368	b, err := NewAESGCMBarrier(inm)
369	if err != nil {
370		t.Fatalf("err: %v", err)
371	}
372	b.currentAESGCMVersionByte = AESGCMVersion1
373
374	// Initialize and unseal
375	key, _ := b.GenerateKey()
376	err = b.Initialize(context.Background(), key)
377	if err != nil {
378		t.Fatalf("err: %v", err)
379	}
380	err = b.Unseal(context.Background(), key)
381	if err != nil {
382		t.Fatalf("err: %v", err)
383	}
384
385	// Put a logical entry
386	entry := &logical.StorageEntry{Key: "test", Value: []byte("test")}
387	err = b.Put(context.Background(), entry)
388	if err != nil {
389		t.Fatalf("err: %v", err)
390	}
391
392	// Seal
393	err = b.Seal()
394	if err != nil {
395		t.Fatalf("err: %v", err)
396	}
397
398	// Open again as version 2
399	b, err = NewAESGCMBarrier(inm)
400	if err != nil {
401		t.Fatalf("err: %v", err)
402	}
403	b.currentAESGCMVersionByte = AESGCMVersion2
404
405	// Unseal
406	err = b.Unseal(context.Background(), key)
407	if err != nil {
408		t.Fatalf("err: %v", err)
409	}
410
411	// Check successful decryption
412	_, err = b.Get(context.Background(), "test")
413	if err != nil {
414		t.Fatalf("Upgrade unsuccessful")
415	}
416}
417
418func TestEncrypt_Unique(t *testing.T) {
419	inm, err := inmem.NewInmem(nil, logger)
420	if err != nil {
421		t.Fatalf("err: %v", err)
422	}
423	b, err := NewAESGCMBarrier(inm)
424	if err != nil {
425		t.Fatalf("err: %v", err)
426	}
427
428	key, _ := b.GenerateKey()
429	b.Initialize(context.Background(), key)
430	b.Unseal(context.Background(), key)
431
432	if b.keyring == nil {
433		t.Fatalf("barrier is sealed")
434	}
435
436	entry := &logical.StorageEntry{Key: "test", Value: []byte("test")}
437	term := b.keyring.ActiveTerm()
438	primary, _ := b.aeadForTerm(term)
439
440	first, err := b.encrypt("test", term, primary, entry.Value)
441	if err != nil {
442		t.Fatal(err)
443	}
444	second, err := b.encrypt("test", term, primary, entry.Value)
445	if err != nil {
446		t.Fatal(err)
447	}
448
449	if bytes.Equal(first, second) == true {
450		t.Fatalf("improper random seeding detected")
451	}
452}
453
454func TestInitialize_KeyLength(t *testing.T) {
455	inm, err := inmem.NewInmem(nil, logger)
456	if err != nil {
457		t.Fatalf("err: %v", err)
458	}
459	b, err := NewAESGCMBarrier(inm)
460	if err != nil {
461		t.Fatalf("err: %v", err)
462	}
463
464	long := []byte("ThisKeyDoesNotHaveTheRightLength!")
465	middle := []byte("ThisIsASecretKeyAndMore")
466	short := []byte("Key")
467
468	err = b.Initialize(context.Background(), long)
469
470	if err == nil {
471		t.Fatalf("key length protection failed")
472	}
473
474	err = b.Initialize(context.Background(), middle)
475
476	if err == nil {
477		t.Fatalf("key length protection failed")
478	}
479
480	err = b.Initialize(context.Background(), short)
481
482	if err == nil {
483		t.Fatalf("key length protection failed")
484	}
485}
486
487func TestEncrypt_BarrierEncryptor(t *testing.T) {
488	inm, err := inmem.NewInmem(nil, logger)
489	if err != nil {
490		t.Fatalf("err: %v", err)
491	}
492	if err != nil {
493		t.Fatalf("err: %v", err)
494	}
495	b, err := NewAESGCMBarrier(inm)
496	if err != nil {
497		t.Fatalf("err: %v", err)
498	}
499
500	// Initialize and unseal
501	key, _ := b.GenerateKey()
502	b.Initialize(context.Background(), key)
503	b.Unseal(context.Background(), key)
504
505	cipher, err := b.Encrypt(context.Background(), "foo", []byte("quick brown fox"))
506	if err != nil {
507		t.Fatalf("err: %v", err)
508	}
509
510	plain, err := b.Decrypt(context.Background(), "foo", cipher)
511	if err != nil {
512		t.Fatalf("err: %v", err)
513	}
514
515	if string(plain) != "quick brown fox" {
516		t.Fatalf("bad: %s", plain)
517	}
518}
519
520func TestAESGCMBarrier_ReloadKeyring(t *testing.T) {
521	inm, err := inmem.NewInmem(nil, logger)
522	if err != nil {
523		t.Fatalf("err: %v", err)
524	}
525	b, err := NewAESGCMBarrier(inm)
526	if err != nil {
527		t.Fatalf("err: %v", err)
528	}
529
530	// Initialize and unseal
531	key, _ := b.GenerateKey()
532	b.Initialize(context.Background(), key)
533	b.Unseal(context.Background(), key)
534
535	keyringRaw, err := inm.Get(context.Background(), keyringPath)
536	if err != nil {
537		t.Fatalf("err: %v", err)
538	}
539
540	// Encrypt something to test cache invalidation
541	_, err = b.Encrypt(context.Background(), "foo", []byte("quick brown fox"))
542	if err != nil {
543		t.Fatalf("err: %v", err)
544	}
545
546	{
547		// Create a second barrier and rotate the keyring
548		b2, err := NewAESGCMBarrier(inm)
549		if err != nil {
550			t.Fatalf("err: %v", err)
551		}
552		b2.Unseal(context.Background(), key)
553		_, err = b2.Rotate(context.Background())
554		if err != nil {
555			t.Fatalf("err: %v", err)
556		}
557	}
558
559	// Reload the keyring on the first
560	err = b.ReloadKeyring(context.Background())
561	if err != nil {
562		t.Fatalf("err: %v", err)
563	}
564
565	if b.keyring.ActiveTerm() != 2 {
566		t.Fatal("failed to reload keyring")
567	}
568	if len(b.cache) != 0 {
569		t.Fatal("failed to clear cache")
570	}
571
572	// Encrypt something to test cache invalidation
573	_, err = b.Encrypt(context.Background(), "foo", []byte("quick brown fox"))
574	if err != nil {
575		t.Fatalf("err: %v", err)
576	}
577
578	// Restore old keyring to test rolling back
579	err = inm.Put(context.Background(), keyringRaw)
580	if err != nil {
581		t.Fatalf("err: %v", err)
582	}
583
584	// Reload the keyring on the first
585	err = b.ReloadKeyring(context.Background())
586	if err != nil {
587		t.Fatalf("err: %v", err)
588	}
589
590	if b.keyring.ActiveTerm() != 1 {
591		t.Fatal("failed to reload keyring")
592	}
593	if len(b.cache) != 0 {
594		t.Fatal("failed to clear cache")
595	}
596
597}
598