func TestLocalKeySecurity(t *testing.T) { tc := SetupEngineTest(t, "signup") defer tc.Cleanup() fu := NewFakeUserOrBust(t, "se") arg := MakeTestSignupEngineRunArg(fu) s := NewSignupEngine(&arg, tc.G) ctx := &Context{ LogUI: tc.G.UI.GetLogUI(), GPGUI: &gpgtestui{}, SecretUI: fu.NewSecretUI(), LoginUI: &libkb.TestLoginUI{Username: fu.Username}, } if err := RunEngine(s, ctx); err != nil { t.Fatal(err) } lks := libkb.NewLKSec(s.ppStream, s.uid, nil) if err := lks.Load(nil); err != nil { t.Fatal(err) } text := "the people on the bus go up and down, up and down, up and down" enc, err := lks.Encrypt([]byte(text)) if err != nil { t.Fatal(err) } dec, _, err := lks.Decrypt(nil, enc) if err != nil { t.Fatal(err) } if string(dec) != text { t.Errorf("decrypt: %q, expected %q", string(dec), text) } }
func (e *Kex2Provisionee) pushLKSServerHalf() error { // make new lks ppstream := libkb.NewPassphraseStream(e.pps.PassphraseStream) ppstream.SetGeneration(libkb.PassphraseGeneration(e.pps.Generation)) e.lks = libkb.NewLKSec(ppstream, e.uid, e.G()) e.lks.GenerateServerHalf() // make client half recovery chrKID := e.dh.GetKID() chrText, err := e.lks.EncryptClientHalfRecovery(e.dh) if err != nil { return err } err = libkb.PostDeviceLKS(e, e.device.ID, e.device.Type, e.lks.GetServerHalf(), e.lks.Generation(), chrText, chrKID) if err != nil { return err } // Sync the LKS stuff back from the server, so that subsequent // attempts to use public key login will work. /* err = e.G().LoginState().RunSecretSyncer(e.uid) if err != nil { return err } */ return nil }
// To add a device key as the eldest key, signer and eldestKID // should be nil. func (d *Locksmith) addDeviceKeyWithSigner(ctx *Context, signer libkb.GenericKey, eldestKID keybase1.KID) error { devname, err := d.deviceName(ctx) if err != nil { return err } pps, err := d.ppStream(ctx) if err != nil { return err } d.lks = libkb.NewLKSec(pps, d.arg.User.GetUID(), d.G()) args := &DeviceWrapArgs{ Me: d.arg.User, DeviceName: devname, DeviceType: libkb.DeviceTypeDesktop, Lks: d.lks, IsEldest: false, Signer: signer, EldestKID: eldestKID, } if signer == nil && eldestKID.IsNil() { args.IsEldest = true } eng := NewDeviceWrap(args, d.G()) if err := RunEngine(eng, ctx); err != nil { return err } d.signingKey = eng.SigningKey() return nil }
func (e *Kex2Provisionee) pushLKSServerHalf() error { // make new lks ppstream := libkb.NewPassphraseStream(e.pps.PassphraseStream) ppstream.SetGeneration(libkb.PassphraseGeneration(e.pps.Generation)) e.lks = libkb.NewLKSec(ppstream, e.uid, e.G()) e.lks.GenerateServerHalf() // make client half recovery chrKID := e.dh.GetKID() chrText, err := e.lks.EncryptClientHalfRecovery(e.dh) if err != nil { return err } err = libkb.PostDeviceLKS(e, e.device.ID, e.device.Type, e.lks.GetServerHalf(), e.lks.Generation(), chrText, chrKID) if err != nil { return err } // Sync the LKS stuff back from the server, so that subsequent // attempts to use public key login will work. err = e.ctx.LoginContext.RunSecretSyncer(e.uid) if err != nil { return err } // Cache the passphrase stream. Note that we don't have the triplesec // portion of the stream cache, and that the only bytes in ppstream // are the lksec portion (no pwhash, eddsa, dh). Currently passes // all tests with this situation and code that uses those portions // looks to be ok. e.ctx.LoginContext.CreateStreamCache(nil, ppstream) return nil }
// NewKexNewDevice creates a KexNewDevice engine. func NewKexNewDevice(pps *libkb.PassphraseStream, args *KexNewDeviceArgs, gc *libkb.GlobalContext) *KexNewDevice { kc := newKexCommon(gc) kf := &KexNewDevice{KexCommon: *kc, args: args} kf.debugName = "KexNewDevice" if pps != nil { kf.lks = libkb.NewLKSec(pps, kf.args.User.GetUID(), gc) } return kf }
// ensureLKSec ensures we have LKSec for saving device keys. func (e *loginProvision) ensureLKSec(ctx *Context) error { if e.lks != nil { return nil } pps, err := e.ppStream(ctx) if err != nil { return err } e.lks = libkb.NewLKSec(pps, e.arg.User.GetUID(), e.G()) return nil }
func (s *SignupEngine) registerDevice(a libkb.LoginContext, ctx *Context, deviceName string) error { s.lks = libkb.NewLKSec(s.ppStream, s.uid, s.G()) args := &DeviceWrapArgs{ Me: s.me, DeviceName: deviceName, DeviceType: libkb.DeviceTypeDesktop, Lks: s.lks, IsEldest: true, } eng := NewDeviceWrap(args, s.G()) ctx.LoginContext = a if err := RunEngine(eng, ctx); err != nil { return err } s.signingKey = eng.SigningKey() s.encryptionKey = eng.EncryptionKey() if err := ctx.LoginContext.LocalSession().SetDeviceProvisioned(s.G().Env.GetDeviceID()); err != nil { // this isn't a fatal error, session will stay in memory... s.G().Log.Warning("error saving session file: %s", err) } if s.arg.StoreSecret { // Create the secret store as late as possible here // (instead of when we first get the value of // StoreSecret) as the username may change during the // signup process. secretStore := libkb.NewSecretStore(s.G(), s.me.GetNormalizedName()) secret, err := s.lks.GetSecret(a) if err != nil { return err } // Ignore any errors storing the secret. storeSecretErr := secretStore.StoreSecret(secret) if storeSecretErr != nil { s.G().Log.Warning("StoreSecret error: %s", storeSecretErr) } } // is there any reason *not* to do this? ctx.LoginContext.SetCachedSecretKey(libkb.SecretKeyArg{KeyType: libkb.DeviceSigningKeyType}, s.signingKey) ctx.LoginContext.SetCachedSecretKey(libkb.SecretKeyArg{KeyType: libkb.DeviceEncryptionKeyType}, eng.EncryptionKey()) s.G().Log.Debug("registered new device: %s", s.G().Env.GetDeviceID()) s.G().Log.Debug("eldest kid: %s", s.me.GetEldestKID()) return nil }
// makeDeviceWrapArgs creates a base set of args for DeviceWrap. func (e *PGPProvision) makeDeviceWrapArgs(ctx *Context) (*DeviceWrapArgs, error) { // generate lks salt, err := ctx.LoginContext.LoginSession().Salt() if err != nil { return nil, err } _, pps, err := libkb.StretchPassphrase(e.G(), e.passphrase, salt) if err != nil { return nil, err } // since this is just for testing, ok to set this explicitly pps.SetGeneration(1) lks := libkb.NewLKSec(pps, e.user.GetUID(), e.G()) return &DeviceWrapArgs{ Me: e.user, DeviceName: e.deviceName, DeviceType: libkb.DeviceTypeDesktop, Lks: lks, }, nil }
// fakeLKS is used to create a lks that has the server half when // creating a fake user that doesn't have a device. func (s *SignupEngine) fakeLKS() error { s.lks = libkb.NewLKSec(s.ppStream, s.uid, s.G()) return s.lks.GenerateServerHalf() }