github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/provision_utils.go (about) 1 package engine 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/keybase/client/go/libkb" 8 keybase1 "github.com/keybase/client/go/protocol/keybase1" 9 ) 10 11 func retryOnEphemeralRace(mctx libkb.MetaContext, fn func(mctx libkb.MetaContext) error) (err error) { 12 for attempt := 0; attempt < 5; attempt++ { 13 if err = fn(mctx); err == nil { 14 return nil 15 } 16 if !libkb.IsEphemeralRetryableError(err) { 17 return err 18 } 19 mctx.Debug("retryOnEphemeralRace found a retryable error on try %d: %v", 20 attempt, err) 21 } 22 return err 23 } 24 25 // ephemeralKeyReboxer will rebox the lastest userEK while provisioning 26 // devices. The provisionee generates a deviceEK seed so that the provisioner 27 // can rebox the latest userEK for the new deviceKID. The provisionee posts 28 // the userEKBox and deviceEKStatement when posting the new device keys. Once 29 // fully provisioned the provisionee saves the new deviceEK to storage, 30 // encrypted by the newly created device. 31 type ephemeralKeyReboxer struct { 32 deviceEKSeed keybase1.Bytes32 33 seedGenerated bool 34 deviceEKStatement keybase1.DeviceEkStatement 35 userEKBox *keybase1.UserEkBoxed 36 } 37 38 func newEphemeralKeyReboxer() *ephemeralKeyReboxer { 39 return &ephemeralKeyReboxer{} 40 } 41 42 func (e *ephemeralKeyReboxer) getDeviceEKSeed(mctx libkb.MetaContext) (err error) { 43 if ekLib := mctx.G().GetEKLib(); ekLib != nil && !e.seedGenerated { 44 e.deviceEKSeed, err = ekLib.NewEphemeralSeed() 45 if err != nil { 46 return err 47 } 48 e.seedGenerated = true 49 } 50 return nil 51 } 52 53 func (e *ephemeralKeyReboxer) getDeviceEKKID(mctx libkb.MetaContext) (kid keybase1.KID, err error) { 54 if !e.seedGenerated { 55 if err := e.getDeviceEKSeed(mctx); err != nil { 56 return "", err 57 } 58 } 59 if ekLib := mctx.G().GetEKLib(); ekLib != nil { 60 ekPair := ekLib.DeriveDeviceDHKey(e.deviceEKSeed) 61 return ekPair.GetKID(), nil 62 } 63 return "", nil 64 } 65 66 func (e *ephemeralKeyReboxer) getReboxArg(mctx libkb.MetaContext, userEKBox *keybase1.UserEkBoxed, 67 deviceID keybase1.DeviceID, signingKey libkb.GenericKey) (userEKReboxArg *keybase1.UserEkReboxArg, err error) { 68 defer mctx.Trace("ephemeralKeyReboxer#getReboxArg", &err)() 69 70 ekLib := mctx.G().GetEKLib() 71 if ekLib == nil { 72 return nil, nil 73 } 74 75 if userEKBox == nil { // We will create EKs after provisioning in the normal way 76 mctx.Debug("userEKBox nil, no ephemeral keys created during provisioning") 77 return nil, nil 78 } 79 80 deviceEKStatement, deviceEKStatementSig, err := ekLib.SignedDeviceEKStatementFromSeed( 81 mctx, userEKBox.DeviceEkGeneration, e.deviceEKSeed, signingKey) 82 if err != nil { 83 return nil, err 84 } 85 86 userEKReboxArg = &keybase1.UserEkReboxArg{ 87 UserEkBoxMetadata: keybase1.UserEkBoxMetadata{ 88 Box: userEKBox.Box, 89 RecipientDeviceID: deviceID, 90 RecipientGeneration: userEKBox.DeviceEkGeneration, 91 }, 92 DeviceID: deviceID, 93 DeviceEkStatementSig: deviceEKStatementSig, 94 } 95 96 e.deviceEKStatement = deviceEKStatement 97 e.userEKBox = userEKBox 98 99 return userEKReboxArg, nil 100 } 101 102 func (e *ephemeralKeyReboxer) storeEKs(mctx libkb.MetaContext) (err error) { 103 defer mctx.Trace("ephemeralKeyReboxer#storeEKs", &err)() 104 if ekLib := mctx.G().GetEKLib(); ekLib == nil { 105 return nil 106 } 107 if e.userEKBox == nil { 108 mctx.Debug("userEKBox nil, no ephemeral keys to store") 109 return nil 110 } 111 112 if !e.seedGenerated { 113 return fmt.Errorf("Unable to store EKs with out generating a seed first") 114 } 115 116 deviceEKStorage := mctx.G().GetDeviceEKStorage() 117 metadata := e.deviceEKStatement.CurrentDeviceEkMetadata 118 if err = deviceEKStorage.Put(mctx, metadata.Generation, keybase1.DeviceEk{ 119 Seed: e.deviceEKSeed, 120 Metadata: metadata, 121 }); err != nil { 122 return err 123 } 124 125 userEKBoxStorage := mctx.G().GetUserEKBoxStorage() 126 return userEKBoxStorage.Put(mctx, e.userEKBox.Metadata.Generation, *e.userEKBox) 127 } 128 129 func makeUserEKBoxForProvisionee(mctx libkb.MetaContext, kid keybase1.KID) (*keybase1.UserEkBoxed, error) { 130 ekLib := mctx.G().GetEKLib() 131 if ekLib == nil { 132 return nil, nil 133 } 134 ekPair, err := libkb.ImportKeypairFromKID(kid) 135 if err != nil { 136 return nil, err 137 } 138 receiverKey, ok := ekPair.(libkb.NaclDHKeyPair) 139 if !ok { 140 return nil, fmt.Errorf("Unexpected receiver key type") 141 } 142 // This is hardcoded to 1 since we're provisioning a new device. 143 deviceEKGeneration := keybase1.EkGeneration(1) 144 return ekLib.BoxLatestUserEK(mctx, receiverKey, deviceEKGeneration) 145 } 146 147 func verifyLocalStorage(m libkb.MetaContext, username string, uid keybase1.UID) { 148 m.Debug("verifying local storage") 149 defer m.Debug("done verifying local storage") 150 normUsername := libkb.NewNormalizedUsername(username) 151 152 // check config.json looks ok 153 verifyRegularFile(m, "config", m.G().Env.GetConfigFilename()) 154 cr := m.G().Env.GetConfig() 155 if cr.GetUsername() != normUsername { 156 m.Debug("config username %q doesn't match engine username %q", cr.GetUsername(), normUsername) 157 } 158 if cr.GetUID().NotEqual(uid) { 159 m.Debug("config uid %q doesn't match engine uid %q", cr.GetUID(), uid) 160 } 161 162 // check keys in secretkeys.mpack 163 verifyRegularFile(m, "secretkeys", m.G().SKBFilenameForUser(normUsername)) 164 165 // check secret stored 166 secret, err := m.G().SecretStore().RetrieveSecret(m, normUsername) 167 if err != nil { 168 m.Debug("failed to retrieve secret for %s: %s", username, err) 169 } 170 if secret.IsNil() || len(secret.Bytes()) == 0 { 171 m.Debug("retrieved nil/empty secret for %s", username) 172 } 173 } 174 175 func verifyRegularFile(m libkb.MetaContext, name, filename string) { 176 info, err := os.Stat(filename) 177 if err != nil { 178 m.Debug("stat %s file %q error: %s", name, filename, err) 179 return 180 } 181 182 m.Debug("%s file %q size: %d", name, filename, info.Size()) 183 if !info.Mode().IsRegular() { 184 m.Debug("%s file %q not regular: %s", name, filename, info.Mode()) 185 } 186 }