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 }