1package vault
2
3import (
4	"bytes"
5	"encoding/json"
6	"fmt"
7	"time"
8
9	"github.com/hashicorp/errwrap"
10	"github.com/hashicorp/vault/sdk/helper/jsonutil"
11)
12
13// Keyring is used to manage multiple encryption keys used by
14// the barrier. New keys can be installed and each has a sequential term.
15// The term used to encrypt a key is prefixed to the key written out.
16// All data is encrypted with the latest key, but storing the old keys
17// allows for decryption of keys written previously. Along with the encryption
18// keys, the keyring also tracks the master key. This is necessary so that
19// when a new key is added to the keyring, we can encrypt with the master key
20// and write out the new keyring.
21type Keyring struct {
22	masterKey  []byte
23	keys       map[uint32]*Key
24	activeTerm uint32
25}
26
27// EncodedKeyring is used for serialization of the keyring
28type EncodedKeyring struct {
29	MasterKey []byte
30	Keys      []*Key
31}
32
33// Key represents a single term, along with the key used.
34type Key struct {
35	Term        uint32
36	Version     int
37	Value       []byte
38	InstallTime time.Time
39}
40
41// Serialize is used to create a byte encoded key
42func (k *Key) Serialize() ([]byte, error) {
43	return json.Marshal(k)
44}
45
46// DeserializeKey is used to deserialize and return a new key
47func DeserializeKey(buf []byte) (*Key, error) {
48	k := new(Key)
49	if err := jsonutil.DecodeJSON(buf, k); err != nil {
50		return nil, errwrap.Wrapf("deserialization failed: {{err}}", err)
51	}
52	return k, nil
53}
54
55// NewKeyring creates a new keyring
56func NewKeyring() *Keyring {
57	k := &Keyring{
58		keys:       make(map[uint32]*Key),
59		activeTerm: 0,
60	}
61	return k
62}
63
64// Clone returns a new copy of the keyring
65func (k *Keyring) Clone() *Keyring {
66	clone := &Keyring{
67		masterKey:  k.masterKey,
68		keys:       make(map[uint32]*Key, len(k.keys)),
69		activeTerm: k.activeTerm,
70	}
71	for idx, key := range k.keys {
72		clone.keys[idx] = key
73	}
74	return clone
75}
76
77// AddKey adds a new key to the keyring
78func (k *Keyring) AddKey(key *Key) (*Keyring, error) {
79	// Ensure there is no conflict
80	if exist, ok := k.keys[key.Term]; ok {
81		if !bytes.Equal(key.Value, exist.Value) {
82			return nil, fmt.Errorf("conflicting key for term %d already installed", key.Term)
83		}
84		return k, nil
85	}
86
87	// Add a time if none
88	if key.InstallTime.IsZero() {
89		key.InstallTime = time.Now()
90	}
91
92	// Make a new keyring
93	clone := k.Clone()
94
95	// Install the new key
96	clone.keys[key.Term] = key
97
98	// Update the active term if newer
99	if key.Term > clone.activeTerm {
100		clone.activeTerm = key.Term
101	}
102	return clone, nil
103}
104
105// RemoveKey removes a key from the keyring
106func (k *Keyring) RemoveKey(term uint32) (*Keyring, error) {
107	// Ensure this is not the active key
108	if term == k.activeTerm {
109		return nil, fmt.Errorf("cannot remove active key")
110	}
111
112	// Check if this term does not exist
113	if _, ok := k.keys[term]; !ok {
114		return k, nil
115	}
116
117	// Delete the key
118	clone := k.Clone()
119	delete(clone.keys, term)
120	return clone, nil
121}
122
123// ActiveTerm returns the currently active term
124func (k *Keyring) ActiveTerm() uint32 {
125	return k.activeTerm
126}
127
128// ActiveKey returns the active encryption key, or nil
129func (k *Keyring) ActiveKey() *Key {
130	return k.keys[k.activeTerm]
131}
132
133// TermKey returns the key for the given term, or nil
134func (k *Keyring) TermKey(term uint32) *Key {
135	return k.keys[term]
136}
137
138// SetMasterKey is used to update the master key
139func (k *Keyring) SetMasterKey(val []byte) *Keyring {
140	valCopy := make([]byte, len(val))
141	copy(valCopy, val)
142	clone := k.Clone()
143	clone.masterKey = valCopy
144	return clone
145}
146
147// MasterKey returns the master key
148func (k *Keyring) MasterKey() []byte {
149	return k.masterKey
150}
151
152// Serialize is used to create a byte encoded keyring
153func (k *Keyring) Serialize() ([]byte, error) {
154	// Create the encoded entry
155	enc := EncodedKeyring{
156		MasterKey: k.masterKey,
157	}
158	for _, key := range k.keys {
159		enc.Keys = append(enc.Keys, key)
160	}
161
162	// JSON encode the keyring
163	buf, err := json.Marshal(enc)
164	return buf, err
165}
166
167// DeserializeKeyring is used to deserialize and return a new keyring
168func DeserializeKeyring(buf []byte) (*Keyring, error) {
169	// Deserialize the keyring
170	var enc EncodedKeyring
171	if err := jsonutil.DecodeJSON(buf, &enc); err != nil {
172		return nil, errwrap.Wrapf("deserialization failed: {{err}}", err)
173	}
174
175	// Create a new keyring
176	k := NewKeyring()
177	k.masterKey = enc.MasterKey
178	for _, key := range enc.Keys {
179		k.keys[key.Term] = key
180		if key.Term > k.activeTerm {
181			k.activeTerm = key.Term
182		}
183	}
184	return k, nil
185}
186
187// N.B.:
188// Since Go 1.5 these are not reliable; see the documentation around the memzero
189// function. These are best-effort.
190func (k *Keyring) Zeroize(keysToo bool) {
191	if k == nil {
192		return
193	}
194	if k.masterKey != nil {
195		memzero(k.masterKey)
196	}
197	if !keysToo || k.keys == nil {
198		return
199	}
200	for _, key := range k.keys {
201		memzero(key.Value)
202	}
203}
204