1// Copyright 2015 Keybase, Inc. All rights reserved. Use of 2// this source code is governed by the included BSD license. 3 4package engine 5 6import ( 7 "errors" 8 "fmt" 9 10 "github.com/keybase/client/go/kbcrypto" 11 "github.com/keybase/client/go/libkb" 12 keybase1 "github.com/keybase/client/go/protocol/keybase1" 13) 14 15type DeviceKeygenArgs struct { 16 Me *libkb.User 17 DeviceID keybase1.DeviceID 18 DeviceName string 19 DeviceType keybase1.DeviceTypeV2 20 Lks *libkb.LKSec 21 IsEldest bool 22 IsSelfProvision bool 23 PerUserKeyring *libkb.PerUserKeyring 24 EkReboxer *ephemeralKeyReboxer 25 26 // Used in tests for reproducible key generation 27 naclSigningKeyPair libkb.NaclKeyPair 28 naclEncryptionKeyPair libkb.NaclKeyPair 29} 30 31// DeviceKeygenPushArgs determines how the push will run. There are 32// currently three different paths it can take: 33// 34// 1. this device is the eldest device: pushes eldest signing 35// key, encryption subkey. (IsEldest => true) 36// 37// 2. this device is a sibling (but we're not in a key exchange 38// scenario): pushes sibkey signing key, encryption subkey. 39// (IsEldest => False, SkipSignerPush => false, Signer != nil, 40// EldestKID != nil) 41// 42// 3. this device is a sibling, but another device pushed 43// the signing key, so skip that part. 44// (IsEldest => False, SkipSignerPush => true, Signer != nil, 45// EldestKID != nil) 46// 47// The User argument is optional, but it is necessary if the 48// user's sigchain changes between key generation and key push. 49// 50type DeviceKeygenPushArgs struct { 51 SkipSignerPush bool 52 Signer libkb.GenericKey 53 EldestKID keybase1.KID 54 User *libkb.User // optional 55} 56 57type DeviceKeygen struct { 58 args *DeviceKeygenArgs 59 60 runErr error 61 pushErr error 62 63 naclSignGen *libkb.NaclKeyGen 64 naclEncGen *libkb.NaclKeyGen 65 66 // can be nil 67 perUserKeySeed *libkb.PerUserKeySeed 68 69 libkb.Contextified 70} 71 72// NewDeviceKeygen creates a DeviceKeygen engine. 73func NewDeviceKeygen(g *libkb.GlobalContext, args *DeviceKeygenArgs) *DeviceKeygen { 74 return &DeviceKeygen{ 75 args: args, 76 Contextified: libkb.NewContextified(g), 77 } 78} 79 80// Name is the unique engine name. 81func (e *DeviceKeygen) Name() string { 82 return "DeviceKeygen" 83} 84 85// GetPrereqs returns the engine prereqs. 86func (e *DeviceKeygen) Prereqs() Prereqs { 87 return Prereqs{TemporarySession: true} 88} 89 90// RequiredUIs returns the required UIs. 91func (e *DeviceKeygen) RequiredUIs() []libkb.UIKind { 92 return []libkb.UIKind{ 93 libkb.LogUIKind, 94 } 95} 96 97// SubConsumers returns the other UI consumers for this engine. 98func (e *DeviceKeygen) SubConsumers() []libkb.UIConsumer { 99 return nil 100} 101 102// Run starts the engine. 103func (e *DeviceKeygen) Run(m libkb.MetaContext) (err error) { 104 defer m.Trace("DeviceKeygen#Run", &err)() 105 106 e.setup(m) 107 e.generate(m) 108 e.localSave(m) 109 return e.runErr 110} 111 112func (e *DeviceKeygen) SigningKeyPublic() (kbcrypto.NaclSigningKeyPublic, error) { 113 s, ok := e.naclSignGen.GetKeyPair().(libkb.NaclSigningKeyPair) 114 if !ok { 115 return kbcrypto.NaclSigningKeyPublic{}, kbcrypto.BadKeyError{Msg: fmt.Sprintf("invalid key type %T", e.naclSignGen.GetKeyPair())} 116 } 117 return s.Public, nil 118 119} 120 121func (e *DeviceKeygen) SigningKey() libkb.NaclKeyPair { 122 return e.naclSignGen.GetKeyPair() 123} 124 125func (e *DeviceKeygen) EncryptionKey() libkb.NaclDHKeyPair { 126 return e.naclEncGen.GetKeyPair().(libkb.NaclDHKeyPair) 127} 128 129// Push pushes the generated keys to the api server and stores the 130// local key security server half on the api server as well. 131func (e *DeviceKeygen) Push(m libkb.MetaContext, pargs *DeviceKeygenPushArgs) (err error) { 132 var encSigner libkb.GenericKey 133 eldestKID := pargs.EldestKID 134 135 ds := []libkb.Delegator{} 136 137 m.Debug("DeviceKeygen#Push PUK(upgrade:%v)", m.G().Env.GetUpgradePerUserKey()) 138 139 var pukBoxes = []keybase1.PerUserKeyBox{} 140 if e.G().Env.GetUpgradePerUserKey() && e.args.IsEldest { 141 if e.perUserKeySeed == nil { 142 return errors.New("missing new per user key") 143 } 144 // Encrypt the new per-user-key for this eldest device. 145 pukBox, err := libkb.NewPerUserKeyBox( 146 *e.perUserKeySeed, // inner key to be encrypted 147 e.EncryptionKey(), // receiver key (device enc key) 148 e.EncryptionKey(), // sender key (device enc key) 149 keybase1.PerUserKeyGeneration(1)) 150 if err != nil { 151 return err 152 } 153 pukBoxes = append(pukBoxes, pukBox) 154 } 155 if !e.args.IsEldest || e.args.IsSelfProvision { 156 boxes, err := e.preparePerUserKeyBoxFromProvisioningKey(m) 157 if err != nil { 158 return err 159 } 160 pukBoxes = append(pukBoxes, boxes...) 161 } 162 163 // append the signing key 164 if e.args.IsEldest { 165 ds = e.appendEldest(m, ds, pargs) 166 encSigner = e.naclSignGen.GetKeyPair() 167 eldestKID = encSigner.GetKID() 168 } else if !pargs.SkipSignerPush { 169 ds = e.appendSibkey(m, ds, pargs) 170 encSigner = e.naclSignGen.GetKeyPair() 171 } else { 172 encSigner = pargs.Signer 173 } 174 175 ds = e.appendEncKey(m, ds, encSigner, eldestKID, pargs.User) 176 177 var userEKReboxArg *keybase1.UserEkReboxArg 178 if e.args.IsSelfProvision { 179 userEKReboxArg, err = e.reboxUserEK(m, encSigner) 180 if err != nil { 181 return err 182 } 183 } 184 185 var pukSigProducer libkb.AggSigProducer // = nil 186 // PerUserKey does not use Delegator. 187 if e.G().Env.GetUpgradePerUserKey() && e.args.IsEldest { 188 // Sign in the new per-user-key 189 if e.perUserKeySeed == nil { 190 return errors.New("missing new per user key") 191 } 192 193 pukSigProducer = func() (libkb.JSONPayload, keybase1.Seqno, libkb.LinkID, error) { 194 gen := keybase1.PerUserKeyGeneration(1) 195 rev, err := libkb.PerUserKeyProofReverseSigned(m, e.args.Me, *e.perUserKeySeed, gen, encSigner) 196 if err != nil { 197 return nil, 0, nil, err 198 } 199 return rev.Payload, rev.Seqno, rev.LinkID, nil 200 } 201 } 202 203 e.pushErr = libkb.DelegatorAggregator(m, ds, pukSigProducer, pukBoxes, nil, userEKReboxArg) 204 205 // push the LKS server half 206 e.pushLKS(m) 207 208 return e.pushErr 209} 210 211func (e *DeviceKeygen) setup(m libkb.MetaContext) { 212 defer m.Trace("DeviceKeygen#setup", &e.runErr)() 213 if e.runErr != nil { 214 return 215 } 216 217 e.naclSignGen = e.newNaclKeyGen(m, func() (libkb.NaclKeyPair, error) { 218 if e.args.naclSigningKeyPair != nil { 219 return e.args.naclSigningKeyPair, nil 220 } 221 kp, err := libkb.GenerateNaclSigningKeyPair() 222 if err != nil { 223 return nil, err 224 } 225 return kp, nil 226 }, e.device(), libkb.NaclEdDSAExpireIn) 227 228 e.naclEncGen = e.newNaclKeyGen(m, func() (libkb.NaclKeyPair, error) { 229 if e.args.naclEncryptionKeyPair != nil { 230 return e.args.naclEncryptionKeyPair, nil 231 } 232 kp, err := libkb.GenerateNaclDHKeyPair() 233 if err != nil { 234 return nil, err 235 } 236 return kp, nil 237 }, e.device(), libkb.NaclDHExpireIn) 238} 239 240func (e *DeviceKeygen) generate(m libkb.MetaContext) { 241 defer m.Trace("DeviceKeygen#generate", &e.runErr)() 242 if e.runErr != nil { 243 return 244 } 245 246 if e.runErr = e.naclSignGen.Generate(); e.runErr != nil { 247 return 248 } 249 250 if e.runErr = e.naclEncGen.Generate(); e.runErr != nil { 251 return 252 } 253 254 if e.G().Env.GetUpgradePerUserKey() && e.args.IsEldest { 255 seed, err := libkb.GeneratePerUserKeySeed() 256 if err != nil { 257 e.runErr = err 258 return 259 } 260 e.perUserKeySeed = &seed 261 } 262 263} 264 265func (e *DeviceKeygen) localSave(m libkb.MetaContext) { 266 defer m.Trace("DeviceKeygen#localSave", &e.runErr)() 267 if e.runErr != nil { 268 return 269 } 270 if e.args.DeviceType == keybase1.DeviceTypeV2_PAPER { 271 m.Debug("Not writing out paper key to local storage") 272 return 273 } 274 if e.runErr = e.naclSignGen.SaveLKS(m, e.args.Lks); e.runErr != nil { 275 return 276 } 277 if e.runErr = e.naclEncGen.SaveLKS(m, e.args.Lks); e.runErr != nil { 278 return 279 } 280} 281 282func (e *DeviceKeygen) reboxUserEK(m libkb.MetaContext, signingKey libkb.GenericKey) (reboxArg *keybase1.UserEkReboxArg, err error) { 283 defer m.Trace("DeviceKeygen#reboxUserEK", &err)() 284 ekKID, err := e.args.EkReboxer.getDeviceEKKID(m) 285 if err != nil { 286 return nil, err 287 } 288 userEKBox, err := makeUserEKBoxForProvisionee(m, ekKID) 289 if err != nil { 290 return nil, err 291 } 292 return e.args.EkReboxer.getReboxArg(m, userEKBox, e.args.DeviceID, signingKey) 293} 294 295func (e *DeviceKeygen) appendEldest(m libkb.MetaContext, ds []libkb.Delegator, pargs *DeviceKeygenPushArgs) []libkb.Delegator { 296 defer m.Trace("DeviceKeygen#appendEldest", &e.pushErr)() 297 if e.pushErr != nil { 298 return ds 299 } 300 301 var d libkb.Delegator 302 d, e.pushErr = e.naclSignGen.Push(m, true) 303 if e.pushErr == nil { 304 return append(ds, d) 305 } 306 307 return ds 308} 309 310func (e *DeviceKeygen) appendSibkey(m libkb.MetaContext, ds []libkb.Delegator, pargs *DeviceKeygenPushArgs) []libkb.Delegator { 311 defer m.Trace("DeviceKeygen#appendSibkey", &e.pushErr)() 312 if e.pushErr != nil { 313 return ds 314 } 315 316 var d libkb.Delegator 317 318 e.naclSignGen.UpdateArg(pargs.Signer, pargs.EldestKID, libkb.DelegationTypeSibkey, pargs.User) 319 d, e.pushErr = e.naclSignGen.Push(m, true) 320 if e.pushErr == nil { 321 return append(ds, d) 322 } 323 324 return ds 325} 326 327func (e *DeviceKeygen) appendEncKey(m libkb.MetaContext, ds []libkb.Delegator, signer libkb.GenericKey, eldestKID keybase1.KID, user *libkb.User) []libkb.Delegator { 328 defer m.Trace("DeviceKeygen#appendEncKey", &e.pushErr)() 329 if e.pushErr != nil { 330 return ds 331 } 332 333 e.naclEncGen.UpdateArg(signer, eldestKID, libkb.DelegationTypeSubkey, user) 334 335 var d libkb.Delegator 336 d, e.pushErr = e.naclEncGen.Push(m, true) 337 if e.pushErr == nil { 338 return append(ds, d) 339 } 340 341 return ds 342} 343 344func (e *DeviceKeygen) generateClientHalfRecovery(m libkb.MetaContext) (ctext string, kid keybase1.KID, err error) { 345 defer m.Trace("DeviceKeygen#generateClientHalfRecovery", &err)() 346 key := e.naclEncGen.GetKeyPair() 347 kid = key.GetKID() 348 ctext, err = e.args.Lks.EncryptClientHalfRecovery(key) 349 return ctext, kid, err 350} 351 352func (e *DeviceKeygen) pushLKS(m libkb.MetaContext) { 353 defer m.Trace("DeviceKeygen#pushLKS", &e.pushErr)() 354 355 if e.pushErr != nil { 356 return 357 } 358 359 if e.args.Lks == nil { 360 e.pushErr = errors.New("no local key security set") 361 return 362 } 363 364 serverHalf := e.args.Lks.GetServerHalf() 365 if serverHalf.IsNil() { 366 e.pushErr = errors.New("LKS server half is empty, and should not be") 367 return 368 } 369 370 var chr string 371 var chrk keybase1.KID 372 if chr, chrk, e.pushErr = e.generateClientHalfRecovery(m); e.pushErr != nil { 373 return 374 } 375 376 e.pushErr = libkb.PostDeviceLKS(m, e.args.DeviceID, e.args.DeviceType, serverHalf, e.args.Lks.Generation(), chr, chrk) 377 if e.pushErr != nil { 378 return 379 } 380} 381 382func (e *DeviceKeygen) newNaclKeyGen(m libkb.MetaContext, gen libkb.NaclGenerator, device *libkb.Device, expire int) *libkb.NaclKeyGen { 383 return libkb.NewNaclKeyGen(libkb.NaclKeyGenArg{ 384 Generator: gen, 385 Device: device, 386 Me: e.args.Me, 387 ExpireIn: expire, 388 }) 389} 390 391func (e *DeviceKeygen) device() *libkb.Device { 392 s := libkb.DeviceStatusActive 393 return &libkb.Device{ 394 ID: e.args.DeviceID, 395 Description: &e.args.DeviceName, 396 Type: e.args.DeviceType, 397 Status: &s, 398 } 399} 400 401// Can return no boxes if there are no per-user-keys. 402func (e *DeviceKeygen) preparePerUserKeyBoxFromProvisioningKey(m libkb.MetaContext) ([]keybase1.PerUserKeyBox, error) { 403 // Assuming this is a paperkey or self provision. 404 405 upak := e.args.Me.ExportToUserPlusAllKeys() 406 if len(upak.Base.PerUserKeys) == 0 { 407 m.Debug("DeviceKeygen skipping per-user-keys, none exist") 408 return nil, nil 409 } 410 411 pukring := e.args.PerUserKeyring 412 if pukring == nil { 413 return nil, errors.New("missing PerUserKeyring") 414 } 415 416 provisioningKey := m.ActiveDevice().ProvisioningKey(m) 417 var provisioningSigKey, provisioningEncKeyGeneric libkb.GenericKey 418 if provisioningKey != nil { 419 provisioningSigKey = provisioningKey.SigningKey() 420 provisioningEncKeyGeneric = provisioningKey.EncryptionKey() 421 } 422 423 if provisioningSigKey == nil && provisioningEncKeyGeneric == nil { 424 // GPG provisioning is not supported when the user has per-user-keys. 425 // This is the error that manifests. See CORE-4960 426 return nil, errors.New("missing provisioning key in login context") 427 } 428 if provisioningSigKey == nil { 429 return nil, errors.New("missing provisioning sig key") 430 } 431 if provisioningEncKeyGeneric == nil { 432 return nil, errors.New("missing provisioning enc key") 433 } 434 provisioningEncKey, ok := provisioningEncKeyGeneric.(libkb.NaclDHKeyPair) 435 if !ok { 436 return nil, errors.New("Unexpected encryption key type") 437 } 438 439 provisioningDeviceID, err := upak.GetDeviceID(provisioningSigKey.GetKID()) 440 if err != nil { 441 return nil, err 442 } 443 err = pukring.SyncAsProvisioningKey(m, &upak, provisioningDeviceID, provisioningEncKey) 444 if err != nil { 445 return nil, err 446 } 447 if !pukring.HasAnyKeys() { 448 return nil, nil 449 } 450 pukBox, err := pukring.PrepareBoxForNewDevice(m, 451 e.EncryptionKey(), // receiver key: provisionee enc 452 provisioningEncKey, // sender key: provisioning key enc 453 ) 454 return []keybase1.PerUserKeyBox{pukBox}, err 455} 456