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  }