func (b *AESGCMBarrier) decryptKeyring(path string, cipher []byte) ([]byte, error) {
	term := binary.BigEndian.Uint32(cipher[:4])
	gcm, err := b.aeadForTerm(term)
	if err != nil {
		return nil, err
	}
	if gcm == nil {
		return nil, fmt.Errorf("no decryption key available for term %d", term)
	}
	nonce := cipher[5 : 5+gcm.NonceSize()]
	raw := cipher[5+gcm.NonceSize():]
	out := make([]byte, 0, len(raw)-gcm.NonceSize())
	switch cipher[4] {
	case AESGCMVersion1:
		return gcm.Open(out, nonce, raw, nil)
	case AESGCMVersion2:
		return gcm.Open(out, nonce, raw, []byte(path))
	default:
		return nil, fmt.Errorf("version bytes mis-match")
	}
}
decryptKeyring is used to decrypt a value using the keyring
package vault
import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/subtle"
	"encoding/binary"
	"fmt"
	"strings"
	"sync"
	"time"
	"github.com/armon/go-metrics"
	"github.com/hashicorp/vault/helper/jsonutil"
	"github.com/hashicorp/vault/physical"
)
const (
	initialKeyTerm = 1
	termSize = 4
)
const (
	AESGCMVersion1 = 0x1
	AESGCMVersion2 = 0x2
)
type barrierInit struct {
	Version int     
	Key     []byte  
}
type AESGCMBarrier struct {
	backend physical.Backend
	l      sync.RWMutex
	sealed bool
	keyring *Keyring
	cache     map[uint32]cipher.AEAD
	cacheLock sync.RWMutex
	currentAESGCMVersionByte byte
}
func NewAESGCMBarrier(physical physical.Backend) (*AESGCMBarrier, error) {
	b := &AESGCMBarrier{
		backend: physical,
		sealed:  true,
		cache:   make(map[uint32]cipher.AEAD),
		currentAESGCMVersionByte: byte(AESGCMVersion2),
	}
	return b, nil
}
func (b *AESGCMBarrier) Initialized() (bool, error) {
	out, err := b.backend.Get(keyringPath)
	if err != nil {
		return false, fmt.Errorf("failed to check for initialization: %v", err)
	}
	if out != nil {
		return true, nil
	}
	out, err = b.backend.Get(barrierInitPath)
	if err != nil {
		return false, fmt.Errorf("failed to check for initialization: %v", err)
	}
	return out != nil, nil
}
func (b *AESGCMBarrier) Initialize(key []byte) error {
	min, max := b.KeyLength()
	if len(key) < min || len(key) > max {
		return fmt.Errorf("Key size must be %d or %d", min, max)
	}
	if alreadyInit, err := b.Initialized(); err != nil {
		return err
	} else if alreadyInit {
		return ErrBarrierAlreadyInit
	}
	encrypt, err := b.GenerateKey()
	if err != nil {
		return fmt.Errorf("failed to generate encryption key: %v", err)
	}
	keyring := NewKeyring()
	keyring = keyring.SetMasterKey(key)
	keyring, err = keyring.AddKey(&Key{
		Term:    1,
		Version: 1,
		Value:   encrypt,
	})
	if err != nil {
		return fmt.Errorf("failed to create keyring: %v", err)
	}
	return b.persistKeyring(keyring)
}
func (b *AESGCMBarrier) persistKeyring(keyring *Keyring) error {
	keyringBuf, err := keyring.Serialize()
	defer memzero(keyringBuf)
	if err != nil {
		return fmt.Errorf("failed to serialize keyring: %v", err)
	}
	gcm, err := b.aeadFromKey(keyring.MasterKey())
	if err != nil {
		return err
	}
	value := b.encrypt(keyringPath, initialKeyTerm, gcm, keyringBuf)
	pe := &physical.Entry{
		Key:   keyringPath,
		Value: value,
	}
	if err := b.backend.Put(pe); err != nil {
		return fmt.Errorf("failed to persist keyring: %v", err)
	}
	key := &Key{
		Term:    1,
		Version: 1,
		Value:   keyring.MasterKey(),
	}
	keyBuf, err := key.Serialize()
	defer memzero(keyBuf)
	if err != nil {
		return fmt.Errorf("failed to serialize master key: %v", err)
	}
	activeKey := keyring.ActiveKey()
	aead, err := b.aeadFromKey(activeKey.Value)
	if err != nil {
		return err
	}
	value = b.encrypt(masterKeyPath, activeKey.Term, aead, keyBuf)
	pe = &physical.Entry{
		Key:   masterKeyPath,
		Value: value,
	}
	if err := b.backend.Put(pe); err != nil {
		return fmt.Errorf("failed to persist master key: %v", err)
	}
	return nil
}
func (b *AESGCMBarrier) GenerateKey() ([]byte, error) {
	buf := make([]byte, 2*aes.BlockSize)
	_, err := rand.Read(buf)
	return buf, err
}
func (b *AESGCMBarrier) KeyLength() (int, int) {
	return aes.BlockSize, 2 * aes.BlockSize
}
func (b *AESGCMBarrier) Sealed() (bool, error) {
	b.l.RLock()
	defer b.l.RUnlock()
	return b.sealed, nil
}
func (b *AESGCMBarrier) VerifyMaster(key []byte) error {
	b.l.RLock()
	defer b.l.RUnlock()
	if b.sealed {
		return ErrBarrierSealed
	}
	if subtle.ConstantTimeCompare(key, b.keyring.MasterKey()) != 1 {
		return ErrBarrierInvalidKey
	}
	return nil
}
func (b *AESGCMBarrier) ReloadKeyring() error {
	b.l.Lock()
	defer b.l.Unlock()
	gcm, err := b.aeadFromKey(b.keyring.MasterKey())
	if err != nil {
		return err
	}
	out, err := b.backend.Get(keyringPath)
	if err != nil {
		return fmt.Errorf("failed to check for keyring: %v", err)
	}
	if out == nil {
		return fmt.Errorf("keyring unexpectedly missing")
	}
	plain, err := b.decrypt(keyringPath, gcm, out.Value)
	defer memzero(plain)
	if err != nil {
		if strings.Contains(err.Error(), "message authentication failed") {
			return ErrBarrierInvalidKey
		}
		return err
	}
	keyring, err := DeserializeKeyring(plain)
	if err != nil {
		return fmt.Errorf("keyring deserialization failed: %v", err)
	}
	b.keyring = keyring
	return nil
}
func (b *AESGCMBarrier) ReloadMasterKey() error {
	out, err := b.Get(masterKeyPath)
	if err != nil {
		return fmt.Errorf("failed to read master key path: %v", err)
	}
	if out == nil {
		return nil
	}
	defer memzero(out.Value)
	key, err := DeserializeKey(out.Value)
	if err != nil {
		return fmt.Errorf("failed to deserialize key: %v", err)
	}
	b.l.Lock()
	defer b.l.Unlock()
	if bytes.Equal(b.keyring.MasterKey(), key.Value) {
		return nil
	}
	oldKeyring := b.keyring
	b.keyring = b.keyring.SetMasterKey(key.Value)
	oldKeyring.Zeroize(false)
	return nil
}
func (b *AESGCMBarrier) Unseal(key []byte) error {
	b.l.Lock()
	defer b.l.Unlock()
	if !b.sealed {
		return nil
	}
	gcm, err := b.aeadFromKey(key)
	if err != nil {
		return err
	}
	out, err := b.backend.Get(keyringPath)
	if err != nil {
		return fmt.Errorf("failed to check for keyring: %v", err)
	}
	if out != nil {
		plain, err := b.decrypt(keyringPath, gcm, out.Value)
		defer memzero(plain)
		if err != nil {
			if strings.Contains(err.Error(), "message authentication failed") {
				return ErrBarrierInvalidKey
			}
			return err
		}
		keyring, err := DeserializeKeyring(plain)
		if err != nil {
			return fmt.Errorf("keyring deserialization failed: %v", err)
		}
		b.keyring = keyring
		b.sealed = false
		return nil
	}
	out, err = b.backend.Get(barrierInitPath)
	if err != nil {
		return fmt.Errorf("failed to check for initialization: %v", err)
	}
	if out == nil {
		return ErrBarrierNotInit
	}
	plain, err := b.decrypt(barrierInitPath, gcm, out.Value)
	if err != nil {
		if strings.Contains(err.Error(), "message authentication failed") {
			return ErrBarrierInvalidKey
		}
		return err
	}
	defer memzero(plain)
	var init barrierInit
	if err := jsonutil.DecodeJSON(plain, &init); err != nil {
		return fmt.Errorf("failed to unmarshal barrier init file")
	}
	keyringNew := NewKeyring()
	keyring := keyringNew.SetMasterKey(key)
	defer keyringNew.Zeroize(false)
	keyring, err = keyring.AddKey(&Key{
		Term:    1,
		Version: 1,
		Value:   init.Key,
	})
	if err != nil {
		return fmt.Errorf("failed to create keyring: %v", err)
	}
	if err := b.persistKeyring(keyring); err != nil {
		return err
	}
	if err := b.backend.Delete(barrierInitPath); err != nil {
		return fmt.Errorf("failed to delete barrier init file: %v", err)
	}
	b.keyring = keyring
	b.sealed = false
	return nil
}
func (b *AESGCMBarrier) Seal() error {
	b.l.Lock()
	defer b.l.Unlock()
	b.cache = make(map[uint32]cipher.AEAD)
	b.keyring.Zeroize(true)
	b.keyring = nil
	b.sealed = true
	return nil
}
func (b *AESGCMBarrier) Rotate() (uint32, error) {
	b.l.Lock()
	defer b.l.Unlock()
	if b.sealed {
		return 0, ErrBarrierSealed
	}
	encrypt, err := b.GenerateKey()
	if err != nil {
		return 0, fmt.Errorf("failed to generate encryption key: %v", err)
	}
	term := b.keyring.ActiveTerm()
	newTerm := term + 1
	newKeyring, err := b.keyring.AddKey(&Key{
		Term:    newTerm,
		Version: 1,
		Value:   encrypt,
	})
	if err != nil {
		return 0, fmt.Errorf("failed to add new encryption key: %v", err)
	}
	if err := b.persistKeyring(newKeyring); err != nil {
		return 0, err
	}
	b.keyring = newKeyring
	return newTerm, nil
}
func (b *AESGCMBarrier) CreateUpgrade(term uint32) error {
	b.l.RLock()
	defer b.l.RUnlock()
	if b.sealed {
		return ErrBarrierSealed
	}
	termKey := b.keyring.TermKey(term)
	buf, err := termKey.Serialize()
	defer memzero(buf)
	if err != nil {
		return err
	}
	prevTerm := term - 1
	primary, err := b.aeadForTerm(prevTerm)
	if err != nil {
		return err
	}
	key := fmt.Sprintf("%s%d", keyringUpgradePrefix, prevTerm)
	value := b.encrypt(key, prevTerm, primary, buf)
	pe := &physical.Entry{
		Key:   key,
		Value: value,
	}
	return b.backend.Put(pe)
}
func (b *AESGCMBarrier) DestroyUpgrade(term uint32) error {
	path := fmt.Sprintf("%s%d", keyringUpgradePrefix, term-1)
	return b.Delete(path)
}
func (b *AESGCMBarrier) CheckUpgrade() (bool, uint32, error) {
	b.l.RLock()
	defer b.l.RUnlock()
	if b.sealed {
		return false, 0, ErrBarrierSealed
	}
	activeTerm := b.keyring.ActiveTerm()
	upgrade := fmt.Sprintf("%s%d", keyringUpgradePrefix, activeTerm)
	entry, err := b.Get(upgrade)
	if err != nil {
		return false, 0, err
	}
	if entry == nil {
		return false, 0, nil
	}
	defer memzero(entry.Value)
	key, err := DeserializeKey(entry.Value)
	if err != nil {
		return false, 0, err
	}
	b.l.RUnlock()
	defer b.l.RLock()
	b.l.Lock()
	defer b.l.Unlock()
	newKeyring, err := b.keyring.AddKey(key)
	if err != nil {
		return false, 0, fmt.Errorf("failed to add new encryption key: %v", err)
	}
	b.keyring = newKeyring
	return true, key.Term, nil
}
func (b *AESGCMBarrier) ActiveKeyInfo() (*KeyInfo, error) {
	b.l.RLock()
	defer b.l.RUnlock()
	if b.sealed {
		return nil, ErrBarrierSealed
	}
	term := b.keyring.ActiveTerm()
	key := b.keyring.TermKey(term)
	info := &KeyInfo{
		Term:        int(term),
		InstallTime: key.InstallTime,
	}
	return info, nil
}
func (b *AESGCMBarrier) Rekey(key []byte) error {
	b.l.Lock()
	defer b.l.Unlock()
	if b.sealed {
		return ErrBarrierSealed
	}
	min, max := b.KeyLength()
	if len(key) < min || len(key) > max {
		return fmt.Errorf("Key size must be %d or %d", min, max)
	}
	newKeyring := b.keyring.SetMasterKey(key)
	if err := b.persistKeyring(newKeyring); err != nil {
		return err
	}
	oldKeyring := b.keyring
	b.keyring = newKeyring
	oldKeyring.Zeroize(false)
	return nil
}
func (b *AESGCMBarrier) Put(entry *Entry) error {
	defer metrics.MeasureSince([]string{"barrier", "put"}, time.Now())
	b.l.RLock()
	defer b.l.RUnlock()
	if b.sealed {
		return ErrBarrierSealed
	}
	term := b.keyring.ActiveTerm()
	primary, err := b.aeadForTerm(term)
	if err != nil {
		return err
	}
	pe := &physical.Entry{
		Key:   entry.Key,
		Value: b.encrypt(entry.Key, term, primary, entry.Value),
	}
	return b.backend.Put(pe)
}
func (b *AESGCMBarrier) Get(key string) (*Entry, error) {
	defer metrics.MeasureSince([]string{"barrier", "get"}, time.Now())
	b.l.RLock()
	defer b.l.RUnlock()
	if b.sealed {
		return nil, ErrBarrierSealed
	}
	pe, err := b.backend.Get(key)
	if err != nil {
		return nil, err
	} else if pe == nil {
		return nil, nil
	}
	plain, err := b.decryptKeyring(key, pe.Value)
	if err != nil {
		return nil, fmt.Errorf("decryption failed: %v", err)
	}
	entry := &Entry{
		Key:   key,
		Value: plain,
	}
	return entry, nil
}
func (b *AESGCMBarrier) Delete(key string) error {
	defer metrics.MeasureSince([]string{"barrier", "delete"}, time.Now())
	b.l.RLock()
	defer b.l.RUnlock()
	if b.sealed {
		return ErrBarrierSealed
	}
	return b.backend.Delete(key)
}
func (b *AESGCMBarrier) List(prefix string) ([]string, error) {
	defer metrics.MeasureSince([]string{"barrier", "list"}, time.Now())
	b.l.RLock()
	defer b.l.RUnlock()
	if b.sealed {
		return nil, ErrBarrierSealed
	}
	return b.backend.List(prefix)
}
func (b *AESGCMBarrier) aeadForTerm(term uint32) (cipher.AEAD, error) {
	keyring := b.keyring
	if keyring == nil {
		return nil, nil
	}
	b.cacheLock.RLock()
	aead, ok := b.cache[term]
	b.cacheLock.RUnlock()
	if ok {
		return aead, nil
	}
	key := keyring.TermKey(term)
	if key == nil {
		return nil, nil
	}
	aead, err := b.aeadFromKey(key.Value)
	if err != nil {
		return nil, err
	}
	b.cacheLock.Lock()
	b.cache[term] = aead
	b.cacheLock.Unlock()
	return aead, nil
}
func (b *AESGCMBarrier) aeadFromKey(key []byte) (cipher.AEAD, error) {
	aesCipher, err := aes.NewCipher(key)
	if err != nil {
		return nil, fmt.Errorf("failed to create cipher: %v", err)
	}
	gcm, err := cipher.NewGCM(aesCipher)
	if err != nil {
		return nil, fmt.Errorf("failed to initialize GCM mode")
	}
	return gcm, nil
}
func (b *AESGCMBarrier) encrypt(path string, term uint32, gcm cipher.AEAD, plain []byte) []byte {
	capacity := termSize + 1 + gcm.NonceSize() + gcm.Overhead() + len(plain)
	size := termSize + 1 + gcm.NonceSize()
	out := make([]byte, size, capacity)
	binary.BigEndian.PutUint32(out[:4], term)
	out[4] = b.currentAESGCMVersionByte
	nonce := out[5 : 5+gcm.NonceSize()]
	rand.Read(nonce)
	switch b.currentAESGCMVersionByte {
	case AESGCMVersion1:
		out = gcm.Seal(out, nonce, plain, nil)
	case AESGCMVersion2:
		out = gcm.Seal(out, nonce, plain, []byte(path))
	default:
		panic("Unknown AESGCM version")
	}
	return out
}
func (b *AESGCMBarrier) decrypt(path string, gcm cipher.AEAD, cipher []byte) ([]byte, error) {
	term := binary.BigEndian.Uint32(cipher[:4])
	if term != initialKeyTerm {
		return nil, fmt.Errorf("term mis-match")
	}
	nonce := cipher[5 : 5+gcm.NonceSize()]
	raw := cipher[5+gcm.NonceSize():]
	out := make([]byte, 0, len(raw)-gcm.NonceSize())
	switch cipher[4] {
	case AESGCMVersion1:
		return gcm.Open(out, nonce, raw, nil)
	case AESGCMVersion2:
		return gcm.Open(out, nonce, raw, []byte(path))
	default:
		return nil, fmt.Errorf("version bytes mis-match")
	}
}