github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/device_wrap.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 engine 5 6 import ( 7 "github.com/keybase/client/go/libkb" 8 keybase1 "github.com/keybase/client/go/protocol/keybase1" 9 ) 10 11 // DeviceWrap is an engine that wraps DeviceRegister and 12 // DeviceKeygen. 13 type DeviceWrap struct { 14 libkb.Contextified 15 16 args *DeviceWrapArgs 17 18 signingKey libkb.GenericKey 19 encryptionKey libkb.NaclDHKeyPair 20 deviceID keybase1.DeviceID 21 } 22 23 type DeviceWrapArgs struct { 24 Me *libkb.User 25 DeviceName string 26 DeviceType keybase1.DeviceTypeV2 27 Lks *libkb.LKSec 28 IsEldest bool 29 IsSelfProvision bool 30 Signer libkb.GenericKey 31 EldestKID keybase1.KID 32 PerUserKeyring *libkb.PerUserKeyring 33 EkReboxer *ephemeralKeyReboxer 34 DeviceID keybase1.DeviceID 35 36 // Used in tests for reproducible key generation 37 naclSigningKeyPair libkb.NaclKeyPair 38 naclEncryptionKeyPair libkb.NaclKeyPair 39 } 40 41 // NewDeviceWrap creates a DeviceWrap engine. 42 func NewDeviceWrap(g *libkb.GlobalContext, args *DeviceWrapArgs) *DeviceWrap { 43 return &DeviceWrap{ 44 args: args, 45 Contextified: libkb.NewContextified(g), 46 } 47 } 48 49 // Name is the unique engine name. 50 func (e *DeviceWrap) Name() string { 51 return "DeviceWrap" 52 } 53 54 // GetPrereqs returns the engine prereqs. 55 func (e *DeviceWrap) Prereqs() Prereqs { 56 return Prereqs{} 57 } 58 59 // RequiredUIs returns the required UIs. 60 func (e *DeviceWrap) RequiredUIs() []libkb.UIKind { 61 return []libkb.UIKind{} 62 } 63 64 // SubConsumers returns the other UI consumers for this engine. 65 func (e *DeviceWrap) SubConsumers() []libkb.UIConsumer { 66 return []libkb.UIConsumer{ 67 &DeviceKeygen{}, 68 } 69 } 70 71 func (e *DeviceWrap) registerDevice(m libkb.MetaContext) (err error) { 72 defer m.Trace("DeviceWrap#registerDevice", &err)() 73 74 if e.args.Me.HasCurrentDeviceInCurrentInstall() && !e.args.IsSelfProvision { 75 return libkb.DeviceAlreadyProvisionedError{} 76 } 77 78 if e.deviceID, err = libkb.NewDeviceID(); err != nil { 79 return err 80 } 81 m.Debug("Device name: %s", e.args.DeviceName) 82 m.Debug("Device ID: %s", e.deviceID) 83 return e.args.Lks.GenerateServerHalf() 84 } 85 86 func (e *DeviceWrap) genKeys(m libkb.MetaContext) (err error) { 87 defer m.Trace("DeviceWrap#genKeys", &err)() 88 89 kgArgs := &DeviceKeygenArgs{ 90 Me: e.args.Me, 91 DeviceID: e.deviceID, 92 DeviceName: e.args.DeviceName, 93 DeviceType: e.args.DeviceType, 94 Lks: e.args.Lks, 95 IsEldest: e.args.IsEldest, 96 IsSelfProvision: e.args.IsSelfProvision, 97 PerUserKeyring: e.args.PerUserKeyring, 98 EkReboxer: e.args.EkReboxer, 99 naclSigningKeyPair: e.args.naclSigningKeyPair, 100 naclEncryptionKeyPair: e.args.naclEncryptionKeyPair, 101 } 102 kgEng := NewDeviceKeygen(m.G(), kgArgs) 103 if err = RunEngine2(m, kgEng); err != nil { 104 return err 105 } 106 107 pargs := &DeviceKeygenPushArgs{ 108 Signer: e.args.Signer, 109 EldestKID: e.args.EldestKID, 110 } 111 112 if err = kgEng.Push(m, pargs); err != nil { 113 return err 114 } 115 116 e.signingKey = kgEng.SigningKey() 117 e.encryptionKey = kgEng.EncryptionKey() 118 return nil 119 } 120 121 func (e *DeviceWrap) refreshMe(m libkb.MetaContext) (err error) { 122 defer m.Trace("DeviceWrap#refreshMe", &err)() 123 if !(e.args.IsEldest || e.args.IsSelfProvision) { 124 return nil 125 } 126 m.Debug("reloading Me because we just bumped eldest seqno or self provisioned") 127 me, err := libkb.LoadMe(libkb.NewLoadUserArgWithMetaContext(m)) 128 if err != nil { 129 return err 130 } 131 e.args.Me = me 132 return nil 133 } 134 135 func (e *DeviceWrap) deviceWithKeys(m libkb.MetaContext, mode libkb.KeychainMode) *libkb.DeviceWithKeys { 136 return libkb.NewDeviceWithKeys(e.signingKey, e.encryptionKey, e.deviceID, e.args.DeviceName, mode) 137 } 138 139 // SwitchConfigAndActiveDevice changes active device to the one 140 // generated by DeviceWrap. It switches UserConfig and sets global 141 // ActiveDevice. 142 func (e *DeviceWrap) SwitchConfigAndActiveDevice(m libkb.MetaContext) (err error) { 143 defer m.Trace("DeviceWrap#SwitchConfigAndActiveDevice", &err)() 144 145 if err = e.refreshMe(m); err != nil { 146 return err 147 } 148 149 salt, err := e.args.Me.GetSalt() 150 if err != nil { 151 return err 152 } 153 me := e.args.Me 154 155 // Atomically swap to the new config and active device 156 if e.args.DeviceType == keybase1.DeviceTypeV2_PAPER { 157 err = m.SwitchUserToActiveOneshotDevice(me.ToUserVersion(), me.GetNormalizedName(), e.deviceWithKeys(m, libkb.KeychainModeNone)) 158 } else { 159 err = m.SwitchUserNewConfigActiveDevice(me.ToUserVersion(), me.GetNormalizedName(), salt, 160 e.deviceID, e.signingKey, e.encryptionKey, e.args.DeviceName, libkb.KeychainModeOS) 161 } 162 if err != nil { 163 return err 164 } 165 166 // Sync down secrets for future offline login attempts to work. 167 // This will largely just download what we just uploaded, but it's 168 // easy to do this way. 169 _, w := m.ActiveDevice().SyncSecrets(m) 170 if w != nil { 171 m.Warning("Error sync secrets: %s", w.Error()) 172 } 173 return nil 174 } 175 176 // Run starts the engine. 177 func (e *DeviceWrap) Run(m libkb.MetaContext) (err error) { 178 179 defer m.Trace("DeviceWrap#Run", &err)() 180 181 if err = e.registerDevice(m); err != nil { 182 return err 183 } 184 185 return e.genKeys(m) 186 } 187 188 func (e *DeviceWrap) SigningKey() libkb.GenericKey { 189 return e.signingKey 190 } 191 192 func (e *DeviceWrap) EncryptionKey() libkb.NaclDHKeyPair { 193 return e.encryptionKey 194 } 195 196 func (e *DeviceWrap) DeviceID() keybase1.DeviceID { 197 return e.deviceID 198 }