github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/keyring.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     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  
    18  type 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  
    26  type Keyrings struct {
    27  	Contextified
    28  }
    29  
    30  func NewKeyrings(g *GlobalContext) *Keyrings {
    31  	ret := &Keyrings{
    32  		Contextified: Contextified{g: g},
    33  	}
    34  	return ret
    35  }
    36  
    37  // ===================================================================
    38  
    39  func (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.ReplaceAll(tmp, token, un.String())
    47  }
    48  
    49  func 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  
    62  func LoadSKBKeyringFromMetaContext(m MetaContext) (*SKBKeyringFile, error) {
    63  	return LoadSKBKeyring(m, m.CurrentUsername())
    64  }
    65  
    66  func 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  
    73  func (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  
    83  func (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  
   112  func (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("- Successfully loaded PGP Keyring")
   130  	return nil
   131  }
   132  
   133  func (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  
   142  func (k KeyringFile) GetFilename() string { return k.filename }
   143  
   144  func (k KeyringFile) Save(g *GlobalContext) error {
   145  	return SafeWriteToFile(g.Log, k, 0)
   146  }
   147  
   148  type SecretKeyType int
   149  
   150  const (
   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  
   159  func (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  
   172  func (t SecretKeyType) nonDeviceKeyMatches(key GenericKey) bool {
   173  	if IsPGP(key) && (t == PGPKeyType) {
   174  		return true
   175  	}
   176  
   177  	return false
   178  }
   179  
   180  type 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  
   193  func 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.
   212  func 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.
   268  func (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  
   308  func (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  
   322  func 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  }
   328  func 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  
   364  func 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  
   389  type 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.
   397  func (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  
   417  func (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  		return nil, nil, err
   421  	}
   422  	var secretStore SecretStore
   423  	if arg.Ska.Me != nil {
   424  		skb.SetUID(arg.Ska.Me.GetUID())
   425  		secretStore = NewSecretStore(m, arg.Ska.Me.GetNormalizedName())
   426  	}
   427  	if key, err = skb.PromptAndUnlock(m, arg, secretStore, arg.Ska.Me); err != nil {
   428  		return nil, nil, err
   429  	}
   430  	return key, skb, nil
   431  }
   432  
   433  func (k *Keyrings) GetSecretKeyWithStoredSecret(m MetaContext, ska SecretKeyArg, me *User, secretRetriever SecretRetriever) (key GenericKey, err error) {
   434  	defer m.Trace("Keyrings#GetSecretKeyWithStoredSecret()", &err)()
   435  	var skb *SKB
   436  	skb, err = k.GetSecretKeyLocked(m, ska)
   437  	if err != nil {
   438  		return
   439  	}
   440  	skb.SetUID(me.GetUID())
   441  	return skb.UnlockWithStoredSecret(m, secretRetriever)
   442  }
   443  
   444  func (k *Keyrings) GetSecretKeyWithPassphrase(m MetaContext, me *User, passphrase string, secretStorer SecretStorer) (key GenericKey, err error) {
   445  	defer m.Trace("Keyrings#GetSecretKeyWithPassphrase()", &err)()
   446  	ska := SecretKeyArg{
   447  		Me:      me,
   448  		KeyType: DeviceSigningKeyType,
   449  	}
   450  	var skb *SKB
   451  	skb, err = k.GetSecretKeyLocked(m, ska)
   452  	if err != nil {
   453  		return
   454  	}
   455  	skb.SetUID(me.GetUID())
   456  	pps, tsec := m.PassphraseStreamAndTriplesec()
   457  	return skb.UnlockSecretKey(m, passphrase, tsec, pps, secretStorer)
   458  }
   459  
   460  type EmptyKeyRing struct{}
   461  
   462  func (k EmptyKeyRing) KeysById(id uint64, fp []byte) []openpgp.Key {
   463  	return []openpgp.Key{}
   464  }
   465  func (k EmptyKeyRing) KeysByIdUsage(id uint64, fp []byte, usage byte) []openpgp.Key {
   466  	return []openpgp.Key{}
   467  }
   468  func (k EmptyKeyRing) DecryptionKeys() []openpgp.Key {
   469  	return []openpgp.Key{}
   470  }