1package libkb 2 3import ( 4 "sync" 5 "time" 6 7 keybase1 "github.com/keybase/client/go/protocol/keybase1" 8) 9 10type KeychainMode int 11 12const ( 13 KeychainModeNone KeychainMode = 0 14 KeychainModeOS KeychainMode = 1 15 KeychainModeMemory KeychainMode = 2 16) 17 18type DeviceWithKeys struct { 19 signingKey GenericKey 20 encryptionKey GenericKey 21 deviceID keybase1.DeviceID 22 deviceName string 23 deviceCtime keybase1.Time 24 keychainMode KeychainMode 25} 26 27func NewDeviceWithKeys(signingKey, encryptionKey GenericKey, deviceID keybase1.DeviceID, deviceName string, keychainMode KeychainMode) *DeviceWithKeys { 28 return &DeviceWithKeys{ 29 signingKey: signingKey, 30 encryptionKey: encryptionKey, 31 deviceID: deviceID, 32 deviceName: deviceName, 33 keychainMode: keychainMode, 34 } 35} 36func NewDeviceWithKeysOnly(signingKey, encryptionKey GenericKey, keychainMode KeychainMode) *DeviceWithKeys { 37 return &DeviceWithKeys{ 38 signingKey: signingKey, 39 encryptionKey: encryptionKey, 40 keychainMode: keychainMode, 41 } 42} 43func (d DeviceWithKeys) EncryptionKey() GenericKey { 44 return d.encryptionKey 45} 46func (d DeviceWithKeys) SigningKey() GenericKey { 47 return d.signingKey 48} 49func (d DeviceWithKeys) DeviceID() keybase1.DeviceID { 50 return d.deviceID 51} 52func (d DeviceWithKeys) DeviceName() string { 53 return d.deviceName 54} 55func (d DeviceWithKeys) DeviceCtime() keybase1.Time { 56 return d.deviceCtime 57} 58func (d *DeviceWithKeys) SetDeviceInfo(i keybase1.DeviceID, n string) { 59 d.deviceID = i 60 d.deviceName = n 61} 62 63func (d DeviceWithKeys) HasBothKeys() bool { 64 return d.signingKey != nil && d.encryptionKey != nil 65} 66 67type SelfDestructingDeviceWithKeys struct { 68 sync.Mutex 69 deviceWithKeys *DeviceWithKeys 70 testPostCleanHook func() 71} 72 73func NewSelfDestructingDeviceWithKeys(m MetaContext, k *DeviceWithKeys, d time.Duration) *SelfDestructingDeviceWithKeys { 74 ret := &SelfDestructingDeviceWithKeys{ 75 deviceWithKeys: k, 76 } 77 go ret.setFuse(m, d) 78 return ret 79} 80 81func (s *SelfDestructingDeviceWithKeys) setFuse(m MetaContext, d time.Duration) { 82 <-m.G().Clock().After(d) 83 s.Lock() 84 defer s.Unlock() 85 s.deviceWithKeys = nil 86 if s.testPostCleanHook != nil { 87 s.testPostCleanHook() 88 } 89} 90 91func (s *SelfDestructingDeviceWithKeys) SetTestPostCleanHook(f func()) { 92 s.Lock() 93 defer s.Unlock() 94 s.testPostCleanHook = f 95} 96 97func (s *SelfDestructingDeviceWithKeys) DeviceWithKeys() *DeviceWithKeys { 98 s.Lock() 99 defer s.Unlock() 100 if s.deviceWithKeys == nil { 101 return nil 102 } 103 ret := *s.deviceWithKeys 104 return &ret 105} 106 107type ownerDeviceReply struct { 108 Status AppStatus `json:"status"` 109 UID keybase1.UID `json:"uid"` 110 DeviceID keybase1.DeviceID `json:"device_id"` 111 DeviceName string `json:"device_name"` 112 DeviceCtime keybase1.Time `json:"device_ctime"` 113} 114 115func (o *ownerDeviceReply) GetAppStatus() *AppStatus { 116 return &o.Status 117} 118 119func (d *DeviceWithKeys) Populate(m MetaContext) (uid keybase1.UID, err error) { 120 arg := APIArg{ 121 Endpoint: "key/owner/device", 122 SessionType: APISessionTypeNONE, 123 Args: HTTPArgs{"kid": S{Val: d.signingKey.GetKID().String()}}, 124 } 125 var res ownerDeviceReply 126 if err = m.G().API.GetDecode(m, arg, &res); err != nil { 127 return uid, err 128 } 129 d.deviceID = res.DeviceID 130 d.deviceName = res.DeviceName 131 d.deviceCtime = res.DeviceCtime 132 return res.UID, nil 133} 134 135func (d *DeviceWithKeys) ToProvisioningKeyActiveDevice(m MetaContext, uv keybase1.UserVersion) *ActiveDevice { 136 return NewProvisioningKeyActiveDevice(m, uv, d) 137} 138