1package vault
2
3import (
4	"context"
5	"crypto/aes"
6	"crypto/cipher"
7	"crypto/rand"
8	"crypto/subtle"
9	"encoding/binary"
10	"errors"
11	"fmt"
12	"io"
13	"strconv"
14	"strings"
15	"sync"
16	"time"
17
18	"github.com/armon/go-metrics"
19	"github.com/hashicorp/vault/sdk/helper/jsonutil"
20	"github.com/hashicorp/vault/sdk/helper/strutil"
21	"github.com/hashicorp/vault/sdk/logical"
22	"github.com/hashicorp/vault/sdk/physical"
23	"go.uber.org/atomic"
24)
25
26const (
27	// initialKeyTerm is the hard coded initial key term. This is
28	// used only for values that are not encrypted with the keyring.
29	initialKeyTerm = 1
30
31	// termSize the number of bytes used for the key term.
32	termSize = 4
33
34	autoRotateCheckInterval = 5 * time.Minute
35	legacyRotateReason      = "legacy rotation"
36)
37
38// Versions of the AESGCM storage methodology
39const (
40	AESGCMVersion1 = 0x1
41	AESGCMVersion2 = 0x2
42)
43
44// barrierInit is the JSON encoded value stored
45type barrierInit struct {
46	Version int    // Version is the current format version
47	Key     []byte // Key is the primary encryption key
48}
49
50// Validate AESGCMBarrier satisfies SecurityBarrier interface
51var (
52	_                      SecurityBarrier = &AESGCMBarrier{}
53	barrierEncryptsMetric                  = []string{"barrier", "estimated_encryptions"}
54	barrierRotationsMetric                 = []string{"barrier", "auto_rotation"}
55)
56
57// AESGCMBarrier is a SecurityBarrier implementation that uses the AES
58// cipher core and the Galois Counter Mode block mode. It defaults to
59// the golang NONCE default value of 12 and a key size of 256
60// bit. AES-GCM is high performance, and provides both confidentiality
61// and integrity.
62type AESGCMBarrier struct {
63	backend physical.Backend
64
65	l      sync.RWMutex
66	sealed bool
67
68	// keyring is used to maintain all of the encryption keys, including
69	// the active key used for encryption, but also prior keys to allow
70	// decryption of keys encrypted under previous terms.
71	keyring *Keyring
72
73	// cache is used to reduce the number of AEAD constructions we do
74	cache     map[uint32]cipher.AEAD
75	cacheLock sync.RWMutex
76
77	// currentAESGCMVersionByte is prefixed to a message to allow for
78	// future versioning of barrier implementations. It's var instead
79	// of const to allow for testing
80	currentAESGCMVersionByte byte
81
82	initialized atomic.Bool
83
84	UnaccountedEncryptions *atomic.Int64
85	// Used only for testing
86	RemoteEncryptions     *atomic.Int64
87	totalLocalEncryptions *atomic.Int64
88}
89
90func (b *AESGCMBarrier) RotationConfig() (kc KeyRotationConfig, err error) {
91	if b.keyring == nil {
92		return kc, errors.New("keyring not yet present")
93	}
94	return b.keyring.rotationConfig.Clone(), nil
95}
96
97func (b *AESGCMBarrier) SetRotationConfig(ctx context.Context, rotConfig KeyRotationConfig) error {
98	b.l.Lock()
99	defer b.l.Unlock()
100	rotConfig.Sanitize()
101	if !rotConfig.Equals(b.keyring.rotationConfig) {
102		b.keyring.rotationConfig = rotConfig
103
104		return b.persistKeyring(ctx, b.keyring)
105	}
106	return nil
107}
108
109// NewAESGCMBarrier is used to construct a new barrier that uses
110// the provided physical backend for storage.
111func NewAESGCMBarrier(physical physical.Backend) (*AESGCMBarrier, error) {
112	b := &AESGCMBarrier{
113		backend:                  physical,
114		sealed:                   true,
115		cache:                    make(map[uint32]cipher.AEAD),
116		currentAESGCMVersionByte: byte(AESGCMVersion2),
117		UnaccountedEncryptions:   atomic.NewInt64(0),
118		RemoteEncryptions:        atomic.NewInt64(0),
119		totalLocalEncryptions:    atomic.NewInt64(0),
120	}
121	return b, nil
122}
123
124// Initialized checks if the barrier has been initialized
125// and has a master key set.
126func (b *AESGCMBarrier) Initialized(ctx context.Context) (bool, error) {
127	if b.initialized.Load() {
128		return true, nil
129	}
130
131	// Read the keyring file
132	keys, err := b.backend.List(ctx, keyringPrefix)
133	if err != nil {
134		return false, fmt.Errorf("failed to check for initialization: %w", err)
135	}
136	if strutil.StrListContains(keys, "keyring") {
137		b.initialized.Store(true)
138		return true, nil
139	}
140
141	// Fallback, check for the old sentinel file
142	out, err := b.backend.Get(ctx, barrierInitPath)
143	if err != nil {
144		return false, fmt.Errorf("failed to check for initialization: %w", err)
145	}
146	b.initialized.Store(out != nil)
147	return out != nil, nil
148}
149
150// Initialize works only if the barrier has not been initialized
151// and makes use of the given master key.
152func (b *AESGCMBarrier) Initialize(ctx context.Context, key, sealKey []byte, reader io.Reader) error {
153	// Verify the key size
154	min, max := b.KeyLength()
155	if len(key) < min || len(key) > max {
156		return fmt.Errorf("key size must be %d or %d", min, max)
157	}
158
159	// Check if already initialized
160	if alreadyInit, err := b.Initialized(ctx); err != nil {
161		return err
162	} else if alreadyInit {
163		return ErrBarrierAlreadyInit
164	}
165
166	// Generate encryption key
167	encrypt, err := b.GenerateKey(reader)
168	if err != nil {
169		return fmt.Errorf("failed to generate encryption key: %w", err)
170	}
171
172	// Create a new keyring, install the keys
173	keyring := NewKeyring()
174	keyring = keyring.SetMasterKey(key)
175	keyring, err = keyring.AddKey(&Key{
176		Term:    1,
177		Version: 1,
178		Value:   encrypt,
179	})
180	if err != nil {
181		return fmt.Errorf("failed to create keyring: %w", err)
182	}
183
184	err = b.persistKeyring(ctx, keyring)
185	if err != nil {
186		return err
187	}
188
189	if len(sealKey) > 0 {
190		primary, err := b.aeadFromKey(encrypt)
191		if err != nil {
192			return err
193		}
194
195		err = b.putInternal(ctx, 1, primary, &logical.StorageEntry{
196			Key:   shamirKekPath,
197			Value: sealKey,
198		})
199		if err != nil {
200			return fmt.Errorf("failed to store new seal key: %w", err)
201		}
202	}
203
204	return nil
205}
206
207// persistKeyring is used to write out the keyring using the
208// master key to encrypt it.
209func (b *AESGCMBarrier) persistKeyring(ctx context.Context, keyring *Keyring) error {
210	// Create the keyring entry
211	keyringBuf, err := keyring.Serialize()
212	defer memzero(keyringBuf)
213	if err != nil {
214		return fmt.Errorf("failed to serialize keyring: %w", err)
215	}
216
217	// Create the AES-GCM
218	gcm, err := b.aeadFromKey(keyring.MasterKey())
219	if err != nil {
220		return err
221	}
222
223	// Encrypt the barrier init value
224	value, err := b.encrypt(keyringPath, initialKeyTerm, gcm, keyringBuf)
225	if err != nil {
226		return err
227	}
228
229	// Create the keyring physical entry
230	pe := &physical.Entry{
231		Key:   keyringPath,
232		Value: value,
233	}
234	if err := b.backend.Put(ctx, pe); err != nil {
235		return fmt.Errorf("failed to persist keyring: %w", err)
236	}
237
238	// Serialize the master key value
239	key := &Key{
240		Term:    1,
241		Version: 1,
242		Value:   keyring.MasterKey(),
243	}
244	keyBuf, err := key.Serialize()
245	defer memzero(keyBuf)
246	if err != nil {
247		return fmt.Errorf("failed to serialize master key: %w", err)
248	}
249
250	// Encrypt the master key
251	activeKey := keyring.ActiveKey()
252	aead, err := b.aeadFromKey(activeKey.Value)
253	if err != nil {
254		return err
255	}
256	value, err = b.encryptTracked(masterKeyPath, activeKey.Term, aead, keyBuf)
257	if err != nil {
258		return err
259	}
260
261	// Update the masterKeyPath for standby instances
262	pe = &physical.Entry{
263		Key:   masterKeyPath,
264		Value: value,
265	}
266	if err := b.backend.Put(ctx, pe); err != nil {
267		return fmt.Errorf("failed to persist master key: %w", err)
268	}
269	return nil
270}
271
272// GenerateKey is used to generate a new key
273func (b *AESGCMBarrier) GenerateKey(reader io.Reader) ([]byte, error) {
274	// Generate a 256bit key
275	buf := make([]byte, 2*aes.BlockSize)
276	_, err := reader.Read(buf)
277
278	return buf, err
279}
280
281// KeyLength is used to sanity check a key
282func (b *AESGCMBarrier) KeyLength() (int, int) {
283	return aes.BlockSize, 2 * aes.BlockSize
284}
285
286// Sealed checks if the barrier has been unlocked yet. The Barrier
287// is not expected to be able to perform any CRUD until it is unsealed.
288func (b *AESGCMBarrier) Sealed() (bool, error) {
289	b.l.RLock()
290	sealed := b.sealed
291	b.l.RUnlock()
292	return sealed, nil
293}
294
295// VerifyMaster is used to check if the given key matches the master key
296func (b *AESGCMBarrier) VerifyMaster(key []byte) error {
297	b.l.RLock()
298	defer b.l.RUnlock()
299	if b.sealed {
300		return ErrBarrierSealed
301	}
302	if subtle.ConstantTimeCompare(key, b.keyring.MasterKey()) != 1 {
303		return ErrBarrierInvalidKey
304	}
305	return nil
306}
307
308// ReloadKeyring is used to re-read the underlying keyring.
309// This is used for HA deployments to ensure the latest keyring
310// is present in the leader.
311func (b *AESGCMBarrier) ReloadKeyring(ctx context.Context) error {
312	b.l.Lock()
313	defer b.l.Unlock()
314
315	// Create the AES-GCM
316	gcm, err := b.aeadFromKey(b.keyring.MasterKey())
317	if err != nil {
318		return err
319	}
320
321	// Read in the keyring
322	out, err := b.backend.Get(ctx, keyringPath)
323	if err != nil {
324		return fmt.Errorf("failed to check for keyring: %w", err)
325	}
326
327	// Ensure that the keyring exists. This should never happen,
328	// and indicates something really bad has happened.
329	if out == nil {
330		return errors.New("keyring unexpectedly missing")
331	}
332
333	// Verify the term is always just one
334	term := binary.BigEndian.Uint32(out.Value[:4])
335	if term != initialKeyTerm {
336		return errors.New("term mis-match")
337	}
338
339	// Decrypt the barrier init key
340	plain, err := b.decrypt(keyringPath, gcm, out.Value)
341	defer memzero(plain)
342	if err != nil {
343		if strings.Contains(err.Error(), "message authentication failed") {
344			return ErrBarrierInvalidKey
345		}
346		return err
347	}
348
349	// Reset enc. counters, this may be a leadership change
350	b.totalLocalEncryptions.Store(0)
351	b.totalLocalEncryptions.Store(0)
352	b.UnaccountedEncryptions.Store(0)
353	b.RemoteEncryptions.Store(0)
354
355	return b.recoverKeyring(plain)
356}
357
358func (b *AESGCMBarrier) recoverKeyring(plaintext []byte) error {
359	keyring, err := DeserializeKeyring(plaintext)
360	if err != nil {
361		return fmt.Errorf("keyring deserialization failed: %w", err)
362	}
363
364	// Setup the keyring and finish
365	b.cache = make(map[uint32]cipher.AEAD)
366	b.keyring = keyring
367	return nil
368}
369
370// ReloadMasterKey is used to re-read the underlying masterkey.
371// This is used for HA deployments to ensure the latest master key
372// is available for keyring reloading.
373func (b *AESGCMBarrier) ReloadMasterKey(ctx context.Context) error {
374	// Read the masterKeyPath upgrade
375	out, err := b.Get(ctx, masterKeyPath)
376	if err != nil {
377		return fmt.Errorf("failed to read master key path: %w", err)
378	}
379
380	// The masterKeyPath could be missing (backwards incompatible),
381	// we can ignore this and attempt to make progress with the current
382	// master key.
383	if out == nil {
384		return nil
385	}
386
387	// Grab write lock and refetch
388	b.l.Lock()
389	defer b.l.Unlock()
390
391	out, err = b.lockSwitchedGet(ctx, masterKeyPath, false)
392	if err != nil {
393		return fmt.Errorf("failed to read master key path: %w", err)
394	}
395
396	if out == nil {
397		return nil
398	}
399
400	// Deserialize the master key
401	key, err := DeserializeKey(out.Value)
402	memzero(out.Value)
403	if err != nil {
404		return fmt.Errorf("failed to deserialize key: %w", err)
405	}
406
407	// Check if the master key is the same
408	if subtle.ConstantTimeCompare(b.keyring.MasterKey(), key.Value) == 1 {
409		return nil
410	}
411
412	// Update the master key
413	oldKeyring := b.keyring
414	b.keyring = b.keyring.SetMasterKey(key.Value)
415	oldKeyring.Zeroize(false)
416	return nil
417}
418
419// Unseal is used to provide the master key which permits the barrier
420// to be unsealed. If the key is not correct, the barrier remains sealed.
421func (b *AESGCMBarrier) Unseal(ctx context.Context, key []byte) error {
422	b.l.Lock()
423	defer b.l.Unlock()
424
425	// Do nothing if already unsealed
426	if !b.sealed {
427		return nil
428	}
429
430	// Create the AES-GCM
431	gcm, err := b.aeadFromKey(key)
432	if err != nil {
433		return err
434	}
435
436	// Read in the keyring
437	out, err := b.backend.Get(ctx, keyringPath)
438	if err != nil {
439		return fmt.Errorf("failed to check for keyring: %w", err)
440	}
441	if out != nil {
442		// Verify the term is always just one
443		term := binary.BigEndian.Uint32(out.Value[:4])
444		if term != initialKeyTerm {
445			return errors.New("term mis-match")
446		}
447
448		// Decrypt the barrier init key
449		plain, err := b.decrypt(keyringPath, gcm, out.Value)
450		defer memzero(plain)
451		if err != nil {
452			if strings.Contains(err.Error(), "message authentication failed") {
453				return ErrBarrierInvalidKey
454			}
455			return err
456		}
457
458		// Recover the keyring
459		err = b.recoverKeyring(plain)
460		if err != nil {
461			return fmt.Errorf("keyring deserialization failed: %w", err)
462		}
463
464		b.sealed = false
465
466		return nil
467	}
468
469	// Read the barrier initialization key
470	out, err = b.backend.Get(ctx, barrierInitPath)
471	if err != nil {
472		return fmt.Errorf("failed to check for initialization: %w", err)
473	}
474	if out == nil {
475		return ErrBarrierNotInit
476	}
477
478	// Verify the term is always just one
479	term := binary.BigEndian.Uint32(out.Value[:4])
480	if term != initialKeyTerm {
481		return errors.New("term mis-match")
482	}
483
484	// Decrypt the barrier init key
485	plain, err := b.decrypt(barrierInitPath, gcm, out.Value)
486	if err != nil {
487		if strings.Contains(err.Error(), "message authentication failed") {
488			return ErrBarrierInvalidKey
489		}
490		return err
491	}
492	defer memzero(plain)
493
494	// Unmarshal the barrier init
495	var init barrierInit
496	if err := jsonutil.DecodeJSON(plain, &init); err != nil {
497		return fmt.Errorf("failed to unmarshal barrier init file")
498	}
499
500	// Setup a new keyring, this is for backwards compatibility
501	keyringNew := NewKeyring()
502	keyring := keyringNew.SetMasterKey(key)
503
504	// AddKey reuses the master, so we are only zeroizing after this call
505	defer keyringNew.Zeroize(false)
506
507	keyring, err = keyring.AddKey(&Key{
508		Term:    1,
509		Version: 1,
510		Value:   init.Key,
511	})
512	if err != nil {
513		return fmt.Errorf("failed to create keyring: %w", err)
514	}
515	if err := b.persistKeyring(ctx, keyring); err != nil {
516		return err
517	}
518
519	// Delete the old barrier entry
520	if err := b.backend.Delete(ctx, barrierInitPath); err != nil {
521		return fmt.Errorf("failed to delete barrier init file: %w", err)
522	}
523
524	// Set the vault as unsealed
525	b.keyring = keyring
526	b.sealed = false
527
528	return nil
529}
530
531// Seal is used to re-seal the barrier. This requires the barrier to
532// be unsealed again to perform any further operations.
533func (b *AESGCMBarrier) Seal() error {
534	b.l.Lock()
535	defer b.l.Unlock()
536
537	// Remove the primary key, and seal the vault
538	b.cache = make(map[uint32]cipher.AEAD)
539	b.keyring.Zeroize(true)
540	b.keyring = nil
541	b.sealed = true
542	return nil
543}
544
545// Rotate is used to create a new encryption key. All future writes
546// should use the new key, while old values should still be decryptable.
547func (b *AESGCMBarrier) Rotate(ctx context.Context, randomSource io.Reader) (uint32, error) {
548	b.l.Lock()
549	defer b.l.Unlock()
550	if b.sealed {
551		return 0, ErrBarrierSealed
552	}
553
554	// Generate a new key
555	encrypt, err := b.GenerateKey(randomSource)
556	if err != nil {
557		return 0, fmt.Errorf("failed to generate encryption key: %w", err)
558	}
559
560	// Get the next term
561	term := b.keyring.ActiveTerm()
562	newTerm := term + 1
563
564	// Add a new encryption key
565	newKeyring, err := b.keyring.AddKey(&Key{
566		Term:    newTerm,
567		Version: 1,
568		Value:   encrypt,
569	})
570	if err != nil {
571		return 0, fmt.Errorf("failed to add new encryption key: %w", err)
572	}
573
574	// Persist the new keyring
575	if err := b.persistKeyring(ctx, newKeyring); err != nil {
576		return 0, err
577	}
578
579	// Clear encryption tracking
580	b.RemoteEncryptions.Store(0)
581	b.totalLocalEncryptions.Store(0)
582	b.UnaccountedEncryptions.Store(0)
583
584	// Swap the keyrings
585	b.keyring = newKeyring
586
587	return newTerm, nil
588}
589
590// CreateUpgrade creates an upgrade path key to the given term from the previous term
591func (b *AESGCMBarrier) CreateUpgrade(ctx context.Context, term uint32) error {
592	b.l.RLock()
593	if b.sealed {
594		b.l.RUnlock()
595		return ErrBarrierSealed
596	}
597
598	// Get the key for this term
599	termKey := b.keyring.TermKey(term)
600	buf, err := termKey.Serialize()
601	defer memzero(buf)
602	if err != nil {
603		b.l.RUnlock()
604		return err
605	}
606
607	// Get the AEAD for the previous term
608	prevTerm := term - 1
609	primary, err := b.aeadForTerm(prevTerm)
610	if err != nil {
611		b.l.RUnlock()
612		return err
613	}
614
615	key := fmt.Sprintf("%s%d", keyringUpgradePrefix, prevTerm)
616	value, err := b.encryptTracked(key, prevTerm, primary, buf)
617	b.l.RUnlock()
618	if err != nil {
619		return err
620	}
621	// Create upgrade key
622	pe := &physical.Entry{
623		Key:   key,
624		Value: value,
625	}
626	return b.backend.Put(ctx, pe)
627}
628
629// DestroyUpgrade destroys the upgrade path key to the given term
630func (b *AESGCMBarrier) DestroyUpgrade(ctx context.Context, term uint32) error {
631	path := fmt.Sprintf("%s%d", keyringUpgradePrefix, term-1)
632	return b.Delete(ctx, path)
633}
634
635// CheckUpgrade looks for an upgrade to the current term and installs it
636func (b *AESGCMBarrier) CheckUpgrade(ctx context.Context) (bool, uint32, error) {
637	b.l.RLock()
638	if b.sealed {
639		b.l.RUnlock()
640		return false, 0, ErrBarrierSealed
641	}
642
643	// Get the current term
644	activeTerm := b.keyring.ActiveTerm()
645
646	// Check for an upgrade key
647	upgrade := fmt.Sprintf("%s%d", keyringUpgradePrefix, activeTerm)
648	entry, err := b.lockSwitchedGet(ctx, upgrade, false)
649	if err != nil {
650		b.l.RUnlock()
651		return false, 0, err
652	}
653
654	// Nothing to do if no upgrade
655	if entry == nil {
656		b.l.RUnlock()
657		return false, 0, nil
658	}
659
660	// Upgrade from read lock to write lock
661	b.l.RUnlock()
662	b.l.Lock()
663	defer b.l.Unlock()
664
665	// Validate base cases and refetch values again
666
667	if b.sealed {
668		return false, 0, ErrBarrierSealed
669	}
670
671	activeTerm = b.keyring.ActiveTerm()
672
673	upgrade = fmt.Sprintf("%s%d", keyringUpgradePrefix, activeTerm)
674	entry, err = b.lockSwitchedGet(ctx, upgrade, false)
675	if err != nil {
676		return false, 0, err
677	}
678
679	if entry == nil {
680		return false, 0, nil
681	}
682
683	// Deserialize the key
684	key, err := DeserializeKey(entry.Value)
685	memzero(entry.Value)
686	if err != nil {
687		return false, 0, err
688	}
689
690	// Update the keyring
691	newKeyring, err := b.keyring.AddKey(key)
692	if err != nil {
693		return false, 0, fmt.Errorf("failed to add new encryption key: %w", err)
694	}
695	b.keyring = newKeyring
696
697	// Done!
698	return true, key.Term, nil
699}
700
701// ActiveKeyInfo is used to inform details about the active key
702func (b *AESGCMBarrier) ActiveKeyInfo() (*KeyInfo, error) {
703	b.l.RLock()
704	defer b.l.RUnlock()
705	if b.sealed {
706		return nil, ErrBarrierSealed
707	}
708
709	// Determine the key install time
710	term := b.keyring.ActiveTerm()
711	key := b.keyring.TermKey(term)
712
713	// Return the key info
714	info := &KeyInfo{
715		Term:        int(term),
716		InstallTime: key.InstallTime,
717		Encryptions: b.encryptions(),
718	}
719	return info, nil
720}
721
722// Rekey is used to change the master key used to protect the keyring
723func (b *AESGCMBarrier) Rekey(ctx context.Context, key []byte) error {
724	b.l.Lock()
725	defer b.l.Unlock()
726
727	newKeyring, err := b.updateMasterKeyCommon(key)
728	if err != nil {
729		return err
730	}
731
732	// Persist the new keyring
733	if err := b.persistKeyring(ctx, newKeyring); err != nil {
734		return err
735	}
736
737	// Swap the keyrings
738	oldKeyring := b.keyring
739	b.keyring = newKeyring
740	oldKeyring.Zeroize(false)
741	return nil
742}
743
744// SetMasterKey updates the keyring's in-memory master key but does not persist
745// anything to storage
746func (b *AESGCMBarrier) SetMasterKey(key []byte) error {
747	b.l.Lock()
748	defer b.l.Unlock()
749
750	newKeyring, err := b.updateMasterKeyCommon(key)
751	if err != nil {
752		return err
753	}
754
755	// Swap the keyrings
756	oldKeyring := b.keyring
757	b.keyring = newKeyring
758	oldKeyring.Zeroize(false)
759	return nil
760}
761
762// Performs common tasks related to updating the master key; note that the lock
763// must be held before calling this function
764func (b *AESGCMBarrier) updateMasterKeyCommon(key []byte) (*Keyring, error) {
765	if b.sealed {
766		return nil, ErrBarrierSealed
767	}
768
769	// Verify the key size
770	min, max := b.KeyLength()
771	if len(key) < min || len(key) > max {
772		return nil, fmt.Errorf("key size must be %d or %d", min, max)
773	}
774
775	return b.keyring.SetMasterKey(key), nil
776}
777
778// Put is used to insert or update an entry
779func (b *AESGCMBarrier) Put(ctx context.Context, entry *logical.StorageEntry) error {
780	defer metrics.MeasureSince([]string{"barrier", "put"}, time.Now())
781	b.l.RLock()
782	if b.sealed {
783		b.l.RUnlock()
784		return ErrBarrierSealed
785	}
786
787	term := b.keyring.ActiveTerm()
788	primary, err := b.aeadForTerm(term)
789	b.l.RUnlock()
790	if err != nil {
791		return err
792	}
793
794	return b.putInternal(ctx, term, primary, entry)
795}
796
797func (b *AESGCMBarrier) putInternal(ctx context.Context, term uint32, primary cipher.AEAD, entry *logical.StorageEntry) error {
798	value, err := b.encryptTracked(entry.Key, term, primary, entry.Value)
799	if err != nil {
800		return err
801	}
802	pe := &physical.Entry{
803		Key:      entry.Key,
804		Value:    value,
805		SealWrap: entry.SealWrap,
806	}
807	return b.backend.Put(ctx, pe)
808}
809
810// Get is used to fetch an entry
811func (b *AESGCMBarrier) Get(ctx context.Context, key string) (*logical.StorageEntry, error) {
812	return b.lockSwitchedGet(ctx, key, true)
813}
814
815func (b *AESGCMBarrier) lockSwitchedGet(ctx context.Context, key string, getLock bool) (*logical.StorageEntry, error) {
816	defer metrics.MeasureSince([]string{"barrier", "get"}, time.Now())
817	if getLock {
818		b.l.RLock()
819	}
820	if b.sealed {
821		if getLock {
822			b.l.RUnlock()
823		}
824		return nil, ErrBarrierSealed
825	}
826
827	// Read the key from the backend
828	pe, err := b.backend.Get(ctx, key)
829	if err != nil {
830		if getLock {
831			b.l.RUnlock()
832		}
833		return nil, err
834	} else if pe == nil {
835		if getLock {
836			b.l.RUnlock()
837		}
838		return nil, nil
839	}
840
841	if len(pe.Value) < 4 {
842		if getLock {
843			b.l.RUnlock()
844		}
845		return nil, errors.New("invalid value")
846	}
847
848	// Verify the term
849	term := binary.BigEndian.Uint32(pe.Value[:4])
850
851	// Get the GCM by term
852	// It is expensive to do this first but it is not a
853	// normal case that this won't match
854	gcm, err := b.aeadForTerm(term)
855	if getLock {
856		b.l.RUnlock()
857	}
858	if err != nil {
859		return nil, err
860	}
861	if gcm == nil {
862		return nil, fmt.Errorf("no decryption key available for term %d", term)
863	}
864
865	// Decrypt the ciphertext
866	plain, err := b.decrypt(key, gcm, pe.Value)
867	if err != nil {
868		return nil, fmt.Errorf("decryption failed: %w", err)
869	}
870
871	// Wrap in a logical entry
872	entry := &logical.StorageEntry{
873		Key:      key,
874		Value:    plain,
875		SealWrap: pe.SealWrap,
876	}
877	return entry, nil
878}
879
880// Delete is used to permanently delete an entry
881func (b *AESGCMBarrier) Delete(ctx context.Context, key string) error {
882	defer metrics.MeasureSince([]string{"barrier", "delete"}, time.Now())
883	b.l.RLock()
884	sealed := b.sealed
885	b.l.RUnlock()
886	if sealed {
887		return ErrBarrierSealed
888	}
889
890	return b.backend.Delete(ctx, key)
891}
892
893// List is used ot list all the keys under a given
894// prefix, up to the next prefix.
895func (b *AESGCMBarrier) List(ctx context.Context, prefix string) ([]string, error) {
896	defer metrics.MeasureSince([]string{"barrier", "list"}, time.Now())
897	b.l.RLock()
898	sealed := b.sealed
899	b.l.RUnlock()
900	if sealed {
901		return nil, ErrBarrierSealed
902	}
903
904	return b.backend.List(ctx, prefix)
905}
906
907// aeadForTerm returns the AES-GCM AEAD for the given term
908func (b *AESGCMBarrier) aeadForTerm(term uint32) (cipher.AEAD, error) {
909	// Check for the keyring
910	keyring := b.keyring
911	if keyring == nil {
912		return nil, nil
913	}
914
915	// Check the cache for the aead
916	b.cacheLock.RLock()
917	aead, ok := b.cache[term]
918	b.cacheLock.RUnlock()
919	if ok {
920		return aead, nil
921	}
922
923	// Read the underlying key
924	key := keyring.TermKey(term)
925	if key == nil {
926		return nil, nil
927	}
928
929	// Create a new aead
930	aead, err := b.aeadFromKey(key.Value)
931	if err != nil {
932		return nil, err
933	}
934
935	// Update the cache
936	b.cacheLock.Lock()
937	b.cache[term] = aead
938	b.cacheLock.Unlock()
939	return aead, nil
940}
941
942// aeadFromKey returns an AES-GCM AEAD using the given key.
943func (b *AESGCMBarrier) aeadFromKey(key []byte) (cipher.AEAD, error) {
944	// Create the AES cipher
945	aesCipher, err := aes.NewCipher(key)
946	if err != nil {
947		return nil, fmt.Errorf("failed to create cipher: %w", err)
948	}
949
950	// Create the GCM mode AEAD
951	gcm, err := cipher.NewGCM(aesCipher)
952	if err != nil {
953		return nil, fmt.Errorf("failed to initialize GCM mode")
954	}
955	return gcm, nil
956}
957
958// encrypt is used to encrypt a value
959func (b *AESGCMBarrier) encrypt(path string, term uint32, gcm cipher.AEAD, plain []byte) ([]byte, error) {
960	// Allocate the output buffer with room for tern, version byte,
961	// nonce, GCM tag and the plaintext
962	capacity := termSize + 1 + gcm.NonceSize() + gcm.Overhead() + len(plain)
963	if capacity < 0 {
964		return nil, ErrPlaintextTooLarge
965	}
966	size := termSize + 1 + gcm.NonceSize()
967	out := make([]byte, size, capacity)
968
969	// Set the key term
970	binary.BigEndian.PutUint32(out[:4], term)
971
972	// Set the version byte
973	out[4] = b.currentAESGCMVersionByte
974
975	// Generate a random nonce
976	nonce := out[5 : 5+gcm.NonceSize()]
977	n, err := rand.Read(nonce)
978	if err != nil {
979		return nil, err
980	}
981	if n != len(nonce) {
982		return nil, errors.New("unable to read enough random bytes to fill gcm nonce")
983	}
984
985	// Seal the output
986	switch b.currentAESGCMVersionByte {
987	case AESGCMVersion1:
988		out = gcm.Seal(out, nonce, plain, nil)
989	case AESGCMVersion2:
990		aad := []byte(nil)
991		if path != "" {
992			aad = []byte(path)
993		}
994		out = gcm.Seal(out, nonce, plain, aad)
995	default:
996		panic("Unknown AESGCM version")
997	}
998
999	return out, nil
1000}
1001
1002func termLabel(term uint32) []metrics.Label {
1003	return []metrics.Label{
1004		{
1005			Name:  "term",
1006			Value: strconv.FormatUint(uint64(term), 10),
1007		},
1008	}
1009}
1010
1011// decrypt is used to decrypt a value using the keyring
1012func (b *AESGCMBarrier) decrypt(path string, gcm cipher.AEAD, cipher []byte) ([]byte, error) {
1013	// Capture the parts
1014	nonce := cipher[5 : 5+gcm.NonceSize()]
1015	raw := cipher[5+gcm.NonceSize():]
1016	out := make([]byte, 0, len(raw)-gcm.NonceSize())
1017
1018	// Attempt to open
1019	switch cipher[4] {
1020	case AESGCMVersion1:
1021		return gcm.Open(out, nonce, raw, nil)
1022	case AESGCMVersion2:
1023		aad := []byte(nil)
1024		if path != "" {
1025			aad = []byte(path)
1026		}
1027		return gcm.Open(out, nonce, raw, aad)
1028	default:
1029		return nil, fmt.Errorf("version bytes mis-match")
1030	}
1031}
1032
1033// Encrypt is used to encrypt in-memory for the BarrierEncryptor interface
1034func (b *AESGCMBarrier) Encrypt(ctx context.Context, key string, plaintext []byte) ([]byte, error) {
1035	b.l.RLock()
1036	if b.sealed {
1037		b.l.RUnlock()
1038		return nil, ErrBarrierSealed
1039	}
1040
1041	term := b.keyring.ActiveTerm()
1042	primary, err := b.aeadForTerm(term)
1043	b.l.RUnlock()
1044	if err != nil {
1045		return nil, err
1046	}
1047
1048	ciphertext, err := b.encryptTracked(key, term, primary, plaintext)
1049	if err != nil {
1050		return nil, err
1051	}
1052
1053	return ciphertext, nil
1054}
1055
1056// Decrypt is used to decrypt in-memory for the BarrierEncryptor interface
1057func (b *AESGCMBarrier) Decrypt(_ context.Context, key string, ciphertext []byte) ([]byte, error) {
1058	b.l.RLock()
1059	if b.sealed {
1060		b.l.RUnlock()
1061		return nil, ErrBarrierSealed
1062	}
1063
1064	// Verify the term
1065	term := binary.BigEndian.Uint32(ciphertext[:4])
1066
1067	// Get the GCM by term
1068	// It is expensive to do this first but it is not a
1069	// normal case that this won't match
1070	gcm, err := b.aeadForTerm(term)
1071	b.l.RUnlock()
1072	if err != nil {
1073		return nil, err
1074	}
1075	if gcm == nil {
1076		return nil, fmt.Errorf("no decryption key available for term %d", term)
1077	}
1078
1079	// Decrypt the ciphertext
1080	plain, err := b.decrypt(key, gcm, ciphertext)
1081	if err != nil {
1082		return nil, fmt.Errorf("decryption failed: %w", err)
1083	}
1084
1085	return plain, nil
1086}
1087
1088func (b *AESGCMBarrier) Keyring() (*Keyring, error) {
1089	b.l.RLock()
1090	defer b.l.RUnlock()
1091	if b.sealed {
1092		return nil, ErrBarrierSealed
1093	}
1094
1095	return b.keyring.Clone(), nil
1096}
1097
1098func (b *AESGCMBarrier) ConsumeEncryptionCount(consumer func(int64) error) error {
1099	if b.keyring != nil {
1100		// Lock to prevent replacement of the key while we consume the encryptions
1101		b.l.RLock()
1102		defer b.l.RUnlock()
1103
1104		c := b.UnaccountedEncryptions.Load()
1105		err := consumer(c)
1106		if err == nil && c > 0 {
1107			// Consumer succeeded, remove those from local encryptions
1108			b.UnaccountedEncryptions.Sub(c)
1109		}
1110		return err
1111	}
1112	return nil
1113}
1114
1115func (b *AESGCMBarrier) AddRemoteEncryptions(encryptions int64) {
1116	// For rollup and persistence
1117	b.UnaccountedEncryptions.Add(encryptions)
1118	// For testing
1119	b.RemoteEncryptions.Add(encryptions)
1120}
1121
1122func (b *AESGCMBarrier) encryptTracked(path string, term uint32, gcm cipher.AEAD, buf []byte) ([]byte, error) {
1123	ct, err := b.encrypt(path, term, gcm, buf)
1124	if err != nil {
1125		return nil, err
1126	}
1127	// Increment the local encryption count, and track metrics
1128	b.UnaccountedEncryptions.Add(1)
1129	b.totalLocalEncryptions.Add(1)
1130	metrics.IncrCounterWithLabels(barrierEncryptsMetric, 1, termLabel(term))
1131
1132	return ct, nil
1133}
1134
1135// UnaccountedEncryptions returns the number of encryptions made on the local instance only for the current key term
1136func (b *AESGCMBarrier) TotalLocalEncryptions() int64 {
1137	return b.totalLocalEncryptions.Load()
1138}
1139
1140func (b *AESGCMBarrier) CheckBarrierAutoRotate(ctx context.Context) (string, error) {
1141	const oneYear = 24 * 365 * time.Hour
1142	reason, err := func() (string, error) {
1143		b.l.RLock()
1144		defer b.l.RUnlock()
1145		if b.keyring != nil {
1146			// Rotation Checks
1147			var reason string
1148
1149			rc, err := b.RotationConfig()
1150			if err != nil {
1151				return "", err
1152			}
1153
1154			if !rc.Disabled {
1155				activeKey := b.keyring.ActiveKey()
1156				ops := b.encryptions()
1157				switch {
1158				case activeKey.Encryptions == 0 && !activeKey.InstallTime.IsZero() && time.Since(activeKey.InstallTime) > oneYear:
1159					reason = legacyRotateReason
1160				case ops > rc.MaxOperations:
1161					reason = "reached max operations"
1162				case rc.Interval > 0 && time.Since(activeKey.InstallTime) > rc.Interval:
1163					reason = "rotation interval reached"
1164				}
1165			}
1166			return reason, nil
1167		}
1168		return "", nil
1169	}()
1170	if err != nil {
1171		return "", err
1172	}
1173	if reason != "" {
1174		return reason, nil
1175	}
1176
1177	b.l.Lock()
1178	defer b.l.Unlock()
1179	if b.keyring != nil {
1180		err := b.persistEncryptions(ctx)
1181		if err != nil {
1182			return "", err
1183		}
1184	}
1185	return reason, nil
1186}
1187
1188// Must be called with lock held
1189func (b *AESGCMBarrier) persistEncryptions(ctx context.Context) error {
1190	if !b.sealed {
1191		// Encryption count persistence
1192		upe := b.UnaccountedEncryptions.Load()
1193		if upe > 0 {
1194			activeKey := b.keyring.ActiveKey()
1195			// Move local (unpersisted) encryptions to the key and persist.  This prevents us from needing to persist if
1196			// there has been no activity. Since persistence performs an encryption, perversely we zero out after
1197			// persistence and add 1 to the count to avoid this operation guaranteeing we need another
1198			// autoRotateCheckInterval later.
1199			newEncs := upe + 1
1200			activeKey.Encryptions += uint64(newEncs)
1201			newKeyring := b.keyring.Clone()
1202			err := b.persistKeyring(ctx, newKeyring)
1203			if err != nil {
1204				return err
1205			}
1206			b.UnaccountedEncryptions.Sub(newEncs)
1207		}
1208	}
1209	return nil
1210}
1211
1212// Mostly for testing, returns the total number of encryption operations performed on the active term
1213func (b *AESGCMBarrier) encryptions() int64 {
1214	if b.keyring != nil {
1215		activeKey := b.keyring.ActiveKey()
1216		if activeKey != nil {
1217			return b.UnaccountedEncryptions.Load() + int64(activeKey.Encryptions)
1218		}
1219	}
1220	return 0
1221}
1222