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  }