1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4package libkb
5
6import (
7	"errors"
8	"fmt"
9	"io"
10	"os"
11	"strings"
12	"time"
13
14	keybase1 "github.com/keybase/client/go/protocol/keybase1"
15	"github.com/keybase/go-crypto/openpgp"
16)
17
18type KeyringFile struct {
19	filename         string
20	Entities         openpgp.EntityList
21	indexID          map[string](*openpgp.Entity) // Map of 64-bit uppercase-hex KeyIds
22	indexFingerprint map[PGPFingerprint](*openpgp.Entity)
23	Contextified
24}
25
26type Keyrings struct {
27	Contextified
28}
29
30func NewKeyrings(g *GlobalContext) *Keyrings {
31	ret := &Keyrings{
32		Contextified: Contextified{g: g},
33	}
34	return ret
35}
36
37//===================================================================
38
39func (g *GlobalContext) SKBFilenameForUser(un NormalizedUsername) string {
40	tmp := g.Env.GetSecretKeyringTemplate()
41	token := "%u"
42	if !strings.Contains(tmp, token) {
43		return tmp
44	}
45
46	return strings.Replace(tmp, token, un.String(), -1)
47}
48
49func LoadSKBKeyring(m MetaContext, un NormalizedUsername) (*SKBKeyringFile, error) {
50	if un.IsNil() {
51		return nil, NewNoUsernameError()
52	}
53
54	skbfile := NewSKBKeyringFile(m.G(), un)
55	err := skbfile.LoadAndIndex(m.Ctx())
56	if err != nil && !os.IsNotExist(err) {
57		return nil, err
58	}
59	return skbfile, nil
60}
61
62func LoadSKBKeyringFromMetaContext(m MetaContext) (*SKBKeyringFile, error) {
63	return LoadSKBKeyring(m, m.CurrentUsername())
64}
65
66func StatSKBKeyringMTime(un NormalizedUsername, g *GlobalContext) (mtime time.Time, err error) {
67	if un.IsNil() {
68		return mtime, NewNoUsernameError()
69	}
70	return NewSKBKeyringFile(g, un).MTime()
71}
72
73func (k *KeyringFile) LoadAndIndex() error {
74	var err error
75	k.G().Log.Debug("+ LoadAndIndex on %s", k.filename)
76	if err = k.Load(); err == nil {
77		err = k.Index()
78	}
79	k.G().Log.Debug("- LoadAndIndex on %s -> %s", k.filename, ErrToOk(err))
80	return err
81}
82
83func (k *KeyringFile) Index() error {
84	k.G().Log.Debug("+ Index on %s", k.filename)
85	k.indexID = make(map[string](*openpgp.Entity))
86	k.indexFingerprint = make(map[PGPFingerprint](*openpgp.Entity))
87	p := 0
88	s := 0
89	for _, entity := range k.Entities {
90		if entity.PrimaryKey != nil {
91			id := entity.PrimaryKey.KeyIdString()
92			k.indexID[id] = entity
93			fp := PGPFingerprint(entity.PrimaryKey.Fingerprint)
94			k.indexFingerprint[fp] = entity
95			p++
96		}
97		for _, subkey := range entity.Subkeys {
98			if subkey.PublicKey != nil {
99				id := subkey.PublicKey.KeyIdString()
100				k.indexID[id] = entity
101				fp := PGPFingerprint(subkey.PublicKey.Fingerprint)
102				k.indexFingerprint[fp] = entity
103				s++
104			}
105		}
106	}
107	k.G().Log.Debug("| Indexed %d primary and %d subkeys", p, s)
108	k.G().Log.Debug("- Index on %s -> %s", k.filename, "OK")
109	return nil
110}
111
112func (k *KeyringFile) Load() error {
113	k.G().Log.Debug(fmt.Sprintf("+ Loading PGP Keyring %s", k.filename))
114	file, err := os.Open(k.filename)
115	if os.IsNotExist(err) {
116		k.G().Log.Warning(fmt.Sprintf("No PGP Keyring found at %s", k.filename))
117	} else if err != nil {
118		k.G().Log.Errorf("Cannot open keyring %s: %s\n", k.filename, err)
119		return err
120	}
121	if file != nil {
122		defer file.Close()
123		k.Entities, err = openpgp.ReadKeyRing(file)
124		if err != nil {
125			k.G().Log.Errorf("Cannot parse keyring %s: %s\n", k.filename, err)
126			return err
127		}
128	}
129	k.G().Log.Debug(fmt.Sprintf("- Successfully loaded PGP Keyring"))
130	return nil
131}
132
133func (k KeyringFile) WriteTo(w io.Writer) (int64, error) {
134	for _, e := range k.Entities {
135		if err := e.Serialize(w); err != nil {
136			return 0, err
137		}
138	}
139	return 0, nil
140}
141
142func (k KeyringFile) GetFilename() string { return k.filename }
143
144func (k KeyringFile) Save(g *GlobalContext) error {
145	return SafeWriteToFile(g.Log, k, 0)
146}
147
148type SecretKeyType int
149
150const (
151	// The current device signing key.
152	DeviceSigningKeyType SecretKeyType = iota
153	// The current device encryption key.
154	DeviceEncryptionKeyType
155	// A PGP key (including the synced PGP key, if there is one).
156	PGPKeyType
157)
158
159func (t SecretKeyType) String() string {
160	switch t {
161	case DeviceSigningKeyType:
162		return "DeviceSigningKeyType"
163	case DeviceEncryptionKeyType:
164		return "DeviceEncryptionKeyType"
165	case PGPKeyType:
166		return "PGPKeyType"
167	default:
168		return "<Unknown secret key type>"
169	}
170}
171
172func (t SecretKeyType) nonDeviceKeyMatches(key GenericKey) bool {
173	if IsPGP(key) && (t == PGPKeyType) {
174		return true
175	}
176
177	return false
178}
179
180type SecretKeyArg struct {
181	// Whose keys to use. Must be non-nil.
182	Me *User
183
184	// The allowed key types.
185	KeyType SecretKeyType
186
187	// For non-device keys, a string that the key has to match. If
188	// empty, any valid key is allowed.
189	KeyQuery   string
190	ExactMatch bool // if set, full equality required
191}
192
193func getDeviceKey(m MetaContext, ckf *ComputedKeyFamily, secretKeyType SecretKeyType, nun NormalizedUsername) (GenericKey, error) {
194	did := m.G().Env.GetDeviceIDForUsername(nun)
195	if did.IsNil() {
196		return nil, errors.New("Could not get device id")
197	}
198
199	switch secretKeyType {
200	case DeviceSigningKeyType:
201		return ckf.GetSibkeyForDevice(did)
202	case DeviceEncryptionKeyType:
203		return ckf.GetEncryptionSubkeyForDevice(did)
204	default:
205		return nil, fmt.Errorf("Invalid type %v", secretKeyType)
206	}
207}
208
209// LockedLocalSecretKey looks in the local keyring to find a key
210// for the given user.  Returns non-nil if one was found, and nil
211// otherwise.
212func LockedLocalSecretKey(m MetaContext, ska SecretKeyArg) (*SKB, error) {
213	var ret *SKB
214	me := ska.Me
215
216	keyring, err := m.Keyring()
217	if err != nil {
218		return nil, err
219	}
220	if keyring == nil {
221		m.Debug("| No secret keyring found: %s", err)
222		return nil, NoKeyringsError{}
223	}
224
225	ckf := me.GetComputedKeyFamily()
226	if ckf == nil {
227		m.Warning("No ComputedKeyFamily found for %s", me.name)
228		return nil, KeyFamilyError{Msg: "not found for " + me.name}
229	}
230
231	if (ska.KeyType == DeviceSigningKeyType) || (ska.KeyType == DeviceEncryptionKeyType) {
232		key, err := getDeviceKey(m, ckf, ska.KeyType, me.GetNormalizedName())
233		if err != nil {
234			m.Debug("| No key for current device: %s", err)
235			return nil, err
236		}
237
238		if key == nil {
239			m.Debug("| Key for current device is nil")
240			return nil, NoKeyError{Msg: "Key for current device is nil"}
241		}
242
243		kid := key.GetKID()
244		m.Debug("| Found KID for current device: %s", kid)
245		ret = keyring.LookupByKid(kid)
246		if ret != nil {
247			m.Debug("| Using device key: %s", kid)
248		}
249	} else {
250		m.Debug("| Looking up secret key in local keychain")
251		blocks := keyring.SearchWithComputedKeyFamily(ckf, ska)
252		if len(blocks) > 0 {
253			ret = blocks[0]
254		}
255	}
256
257	if ret != nil {
258		ret.SetUID(me.GetUID())
259	}
260
261	return ret, nil
262}
263
264// GetSecretKeyLocked gets a secret key for the current user by first
265// looking for keys synced from the server, and if that fails, tries
266// those in the local Keyring that are also active for the user.
267// In any case, the key will be locked.
268func (k *Keyrings) GetSecretKeyLocked(m MetaContext, ska SecretKeyArg) (ret *SKB, err error) {
269	defer m.Trace("Keyrings#GetSecretKeyLocked()", &err)()
270	m.Debug("| LoadMe w/ Secrets on")
271
272	if ska.Me == nil {
273		if ska.Me, err = LoadMe(NewLoadUserArg(k.G())); err != nil {
274			return nil, err
275		}
276	}
277
278	ret, err = LockedLocalSecretKey(m, ska)
279	if err != nil {
280		return nil, err
281	}
282
283	if ret != nil {
284		m.Debug("| Getting local secret key")
285		return ret, nil
286	}
287
288	// Try to get server synced key.
289
290	if ska.KeyType != PGPKeyType {
291		m.Debug("| Skipped Synced PGP key (via options)")
292		err = NoSecretKeyError{}
293		return nil, err
294	}
295
296	if ret, err = ska.Me.SyncedSecretKeyWithSka(m, ska); err != nil {
297		if _, ok := err.(NoSecretKeyError); !ok {
298			m.Warning("Error fetching synced PGP secret key: %s", err)
299		} else {
300			m.Debug("| Can't find synced PGP key matching query %s", ska.KeyQuery)
301		}
302		return nil, err
303	}
304
305	return ret, nil
306}
307
308func (k *Keyrings) cachedSecretKey(m MetaContext, ska SecretKeyArg) GenericKey {
309	key, err := m.G().ActiveDevice.KeyByType(ska.KeyType)
310
311	if key != nil && err == nil {
312		m.Debug("found cached secret key for ska: %+v", ska)
313	} else if err != nil {
314		if _, notFound := err.(NotFoundError); !notFound {
315			m.Debug("error getting cached secret key: %s", err)
316		}
317	}
318
319	return key
320}
321
322func deviceIDFromDevice(m MetaContext, uid keybase1.UID, device *Device) keybase1.DeviceID {
323	if device != nil {
324		return device.ID
325	}
326	return m.G().Env.GetDeviceIDForUID(uid)
327}
328func deviceNameLookup(m MetaContext, device *Device, me *User, key GenericKey) string {
329	if device != nil {
330		if device.Description != nil && *device.Description != "" {
331			m.Debug("deviceNameLookup: using device name from device: %q", *device.Description)
332			return *device.Description
333		}
334	}
335
336	m.Debug("deviceNameLookup: no device name passed in, checking user")
337
338	if me == nil {
339		m.Debug("deviceNameLookup: me is nil, skipping device name lookup")
340		return ""
341	}
342	m.Debug("deviceNameLookup: looking for device name for device signing key")
343	ckf := me.GetComputedKeyFamily()
344	device, err := ckf.GetDeviceForKey(key)
345	if err != nil {
346		// not fatal
347		m.Debug("deviceNameLookup: error getting device for key: %s", err)
348		return ""
349	}
350	if device == nil {
351		m.Debug("deviceNameLookup: device for key is nil")
352		return ""
353	}
354	if device.Description == nil {
355		m.Debug("deviceNameLookup: device description is nil")
356		return ""
357	}
358
359	m.Debug("deviceNameLookup: found device name %q", *device.Description)
360
361	return *device.Description
362}
363
364func setCachedSecretKey(m MetaContext, ska SecretKeyArg, key GenericKey, device *Device) error {
365	if key == nil {
366		return errors.New("cache of nil secret key attempted")
367	}
368
369	uid := ska.Me.GetUID()
370	uv := ska.Me.ToUserVersion()
371	deviceID := deviceIDFromDevice(m, uid, device)
372	if deviceID.IsNil() {
373		m.Debug("SetCachedSecretKey with nil deviceID (%+v)", ska)
374	}
375
376	switch ska.KeyType {
377	case DeviceSigningKeyType:
378		deviceName := deviceNameLookup(m, device, ska.Me, key)
379		m.Debug("caching secret device signing key (%q/%d)", deviceName, deviceID)
380		return m.SetSigningKey(uv, deviceID, key, deviceName)
381	case DeviceEncryptionKeyType:
382		m.Debug("caching secret device encryption key")
383		return m.SetEncryptionKey(uv, deviceID, key)
384	default:
385		return fmt.Errorf("attempt to cache invalid key type: %d", ska.KeyType)
386	}
387}
388
389type SecretKeyPromptArg struct {
390	Ska            SecretKeyArg
391	SecretUI       SecretUI
392	Reason         string
393	UseCancelCache bool /* if true, when user cancels prompt, don't prompt again for 5m */
394}
395
396// TODO: Figure out whether and how to dep-inject the SecretStore.
397func (k *Keyrings) GetSecretKeyWithPrompt(m MetaContext, arg SecretKeyPromptArg) (key GenericKey, err error) {
398	defer m.Trace(fmt.Sprintf("Keyrings#GetSecretKeyWithPrompt(%s)", arg.Reason), &err)()
399
400	key = k.cachedSecretKey(m, arg.Ska)
401	if key != nil {
402		return key, err
403	}
404
405	key, _, err = k.GetSecretKeyAndSKBWithPrompt(m, arg)
406
407	if key != nil && err == nil {
408		err := setCachedSecretKey(m, arg.Ska, key, nil)
409		if err != nil {
410			m.Debug("GetSecretKeyWithPrompt: error setting cached key: %+v", err)
411		}
412	}
413
414	return key, err
415}
416
417func (k *Keyrings) GetSecretKeyAndSKBWithPrompt(m MetaContext, arg SecretKeyPromptArg) (key GenericKey, skb *SKB, err error) {
418	defer m.Trace(fmt.Sprintf("GetSecretKeyAndSKBWithPrompt(%s)", arg.Reason), &err)()
419	if skb, err = k.GetSecretKeyLocked(m, arg.Ska); err != nil {
420		skb = nil
421		return nil, nil, err
422	}
423	var secretStore SecretStore
424	if arg.Ska.Me != nil {
425		skb.SetUID(arg.Ska.Me.GetUID())
426		secretStore = NewSecretStore(m, arg.Ska.Me.GetNormalizedName())
427	}
428	if key, err = skb.PromptAndUnlock(m, arg, secretStore, arg.Ska.Me); err != nil {
429		return nil, nil, err
430	}
431	return key, skb, nil
432}
433
434func (k *Keyrings) GetSecretKeyWithStoredSecret(m MetaContext, ska SecretKeyArg, me *User, secretRetriever SecretRetriever) (key GenericKey, err error) {
435	defer m.Trace("Keyrings#GetSecretKeyWithStoredSecret()", &err)()
436	var skb *SKB
437	skb, err = k.GetSecretKeyLocked(m, ska)
438	if err != nil {
439		return
440	}
441	skb.SetUID(me.GetUID())
442	return skb.UnlockWithStoredSecret(m, secretRetriever)
443}
444
445func (k *Keyrings) GetSecretKeyWithPassphrase(m MetaContext, me *User, passphrase string, secretStorer SecretStorer) (key GenericKey, err error) {
446	defer m.Trace("Keyrings#GetSecretKeyWithPassphrase()", &err)()
447	ska := SecretKeyArg{
448		Me:      me,
449		KeyType: DeviceSigningKeyType,
450	}
451	var skb *SKB
452	skb, err = k.GetSecretKeyLocked(m, ska)
453	if err != nil {
454		return
455	}
456	skb.SetUID(me.GetUID())
457	pps, tsec := m.PassphraseStreamAndTriplesec()
458	return skb.UnlockSecretKey(m, passphrase, tsec, pps, secretStorer)
459}
460
461type EmptyKeyRing struct{}
462
463func (k EmptyKeyRing) KeysById(id uint64, fp []byte) []openpgp.Key {
464	return []openpgp.Key{}
465}
466func (k EmptyKeyRing) KeysByIdUsage(id uint64, fp []byte, usage byte) []openpgp.Key {
467	return []openpgp.Key{}
468}
469func (k EmptyKeyRing) DecryptionKeys() []openpgp.Key {
470	return []openpgp.Key{}
471}
472