github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/kex2_test.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 "crypto/rand" 8 "fmt" 9 "sync" 10 "testing" 11 12 "github.com/keybase/client/go/kex2" 13 "github.com/keybase/client/go/libkb" 14 keybase1 "github.com/keybase/client/go/protocol/keybase1" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestKex2Provision(t *testing.T) { 19 subTestKex2Provision(t, false) 20 } 21 22 func TestKex2ProvisionPUK(t *testing.T) { 23 subTestKex2Provision(t, true) 24 } 25 26 func subTestKex2Provision(t *testing.T, upgradePerUserKey bool) { 27 // device X (provisioner) context: 28 tcX := SetupEngineTest(t, "kex2provision") 29 defer tcX.Cleanup() 30 31 tcX.Tp.DisableUpgradePerUserKey = !upgradePerUserKey 32 33 // provisioner needs to be logged in 34 userX := CreateAndSignupFakeUser(tcX, "login") 35 36 // device Y (provisionee) context: 37 tcY := SetupEngineTest(t, "kex2provision") 38 defer tcY.Cleanup() 39 40 tcY.Tp.DisableUpgradePerUserKey = !upgradePerUserKey 41 42 var secretX kex2.Secret 43 if _, err := rand.Read(secretX[:]); err != nil { 44 t.Fatal(err) 45 } 46 47 var secretY kex2.Secret 48 if _, err := rand.Read(secretY[:]); err != nil { 49 t.Fatal(err) 50 } 51 52 var wg sync.WaitGroup 53 54 // start provisionee 55 wg.Add(1) 56 go func() { 57 defer wg.Done() 58 err := (func() error { 59 uis := libkb.UIs{ 60 ProvisionUI: &testProvisionUI{secretCh: make(chan kex2.Secret, 1)}, 61 } 62 m := NewMetaContextForTest(tcY).WithUIs(uis).WithNewProvisionalLoginContext() 63 deviceID, err := libkb.NewDeviceID() 64 if err != nil { 65 return err 66 } 67 suffix, err := libkb.RandBytes(5) 68 if err != nil { 69 return err 70 } 71 dname := fmt.Sprintf("device_%x", suffix) 72 device := &libkb.Device{ 73 ID: deviceID, 74 Description: &dname, 75 Type: keybase1.DeviceTypeV2_DESKTOP, 76 } 77 provisionee := NewKex2Provisionee(tcY.G, device, secretY, userX.UID(), fakeSalt()) 78 return RunEngine2(m, provisionee) 79 })() 80 require.NoError(t, err, "no kex2 provisionee error") 81 }() 82 83 // start provisioner 84 wg.Add(1) 85 go func() { 86 defer wg.Done() 87 uis := libkb.UIs{ 88 SecretUI: userX.NewSecretUI(), 89 ProvisionUI: &testProvisionUI{}, 90 } 91 provisioner := NewKex2Provisioner(tcX.G, secretX, nil) 92 m := NewMetaContextForTest(tcX).WithUIs(uis) 93 go provisioner.AddSecret(secretY) 94 if err := RunEngine2(m, provisioner); err != nil { 95 t.Errorf("provisioner error: %s", err) 96 return 97 } 98 }() 99 100 wg.Wait() 101 } 102 103 // Get a new device, test context and all, by provisioning it from an existing test context. 104 // This was copied from subTestKex2Provision 105 // Note that it uses Errorf in goroutines, so if it fails 106 // the test will not fail until later. 107 // Returns (tcY, CleanupFunction) 108 func provisionNewDeviceKex(tcX *libkb.TestContext, userX *FakeUser) (*libkb.TestContext, func()) { 109 // tcX is the device X (provisioner) context: 110 // tcX should already have been logged in. 111 112 t := tcX.T 113 114 // device Y (provisionee) context: 115 tcY := SetupEngineTest(t, "kex2provision") 116 cleanup := func() { tcY.Cleanup() } 117 118 var secretX kex2.Secret 119 if _, err := rand.Read(secretX[:]); err != nil { 120 t.Fatal(err) 121 } 122 123 var secretY kex2.Secret 124 if _, err := rand.Read(secretY[:]); err != nil { 125 t.Fatal(err) 126 } 127 128 var wg sync.WaitGroup 129 130 // start provisionee 131 wg.Add(1) 132 go func() { 133 defer wg.Done() 134 err := (func() error { 135 uis := libkb.UIs{ 136 ProvisionUI: &testProvisionUI{secretCh: make(chan kex2.Secret, 1)}, 137 } 138 m := NewMetaContextForTest(tcY).WithUIs(uis).WithNewProvisionalLoginContext() 139 deviceID, err := libkb.NewDeviceID() 140 if err != nil { 141 return err 142 } 143 suffix, err := libkb.RandBytes(5) 144 if err != nil { 145 return err 146 } 147 dname := fmt.Sprintf("device_%x", suffix) 148 device := &libkb.Device{ 149 ID: deviceID, 150 Description: &dname, 151 Type: keybase1.DeviceTypeV2_DESKTOP, 152 } 153 provisionee := NewKex2Provisionee(tcY.G, device, secretY, userX.UID(), fakeSalt()) 154 return RunEngine2(m, provisionee) 155 })() 156 require.NoError(t, err, "kex2 provisionee") 157 }() 158 159 // start provisioner 160 wg.Add(1) 161 go func() { 162 defer wg.Done() 163 uis := libkb.UIs{ 164 SecretUI: userX.NewSecretUI(), 165 ProvisionUI: &testProvisionUI{}, 166 } 167 provisioner := NewKex2Provisioner(tcX.G, secretX, nil) 168 go provisioner.AddSecret(secretY) 169 m := NewMetaContextForTest(*tcX).WithUIs(uis) 170 if err := RunEngine2(m, provisioner); err != nil { 171 t.Errorf("provisioner error: %s", err) 172 return 173 } 174 }() 175 176 wg.Wait() 177 178 return &tcY, cleanup 179 }