control/controlclient,ipn/ipnlocal: wire tka enable/disable

Signed-off-by: Tom DNetto <tom@tailscale.com>
This commit is contained in:
Tom DNetto
2022-09-06 16:34:16 -07:00
committed by Tom
parent b9b0bf65a0
commit e9b98dd2e1
16 changed files with 469 additions and 17 deletions

View File

@@ -45,6 +45,12 @@ func (h AUMHash) MarshalText() ([]byte, error) {
return b, nil
}
// IsZero returns true if the hash is the empty value.
func (h AUMHash) IsZero() bool {
return h == (AUMHash{})
}
// AUMKind describes valid AUM types.
type AUMKind uint8

View File

@@ -31,7 +31,7 @@ func TestAuthorityBuilderAddKey(t *testing.T) {
storage := &Mem{}
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
@@ -68,7 +68,7 @@ func TestAuthorityBuilderRemoveKey(t *testing.T) {
storage := &Mem{}
a, _, err := Create(storage, State{
Keys: []Key{key, key2},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
@@ -100,7 +100,7 @@ func TestAuthorityBuilderSetKeyVote(t *testing.T) {
storage := &Mem{}
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
@@ -136,7 +136,7 @@ func TestAuthorityBuilderSetKeyMeta(t *testing.T) {
storage := &Mem{}
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
@@ -172,7 +172,7 @@ func TestAuthorityBuilderMultiple(t *testing.T) {
storage := &Mem{}
a, _, err := Create(storage, State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)

View File

@@ -169,7 +169,7 @@ func testScenario(t *testing.T, sharedChain string, sharedOptions ...testchainOp
sharedOptions = append(sharedOptions,
optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}}),
optKey("key", key, priv),
optSignAllUsing("key"))

View File

@@ -226,7 +226,7 @@ func TestSigCredential(t *testing.T) {
a, _ := Open(newTestchain(t, "G1\nG1.template = genesis",
optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &State{
Keys: []Key{k},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}})).Chonk())
if err := a.NodeKeyAuthorized(node.Public(), nestedSig.Serialize()); err == nil {
t.Error("NodeKeyAuthorized(SigCredential, node) did not fail")

View File

@@ -93,7 +93,13 @@ const disablementLength = 32
var disablementSalt = []byte("tailscale network-lock disablement salt")
func disablementKDF(secret []byte) []byte {
// DisablementKDF computes a public value which can be stored in a
// key authority, but cannot be reversed to find the input secret.
//
// When the output of this function is stored in tka state (i.e. in
// tka.State.DisablementSecrets) a call to Authority.ValidDisablement()
// with the input of this function as the argument will return true.
func DisablementKDF(secret []byte) []byte {
// time = 4 (3 recommended, booped to 4 to compensate for less memory)
// memory = 16 (32 recommended)
// threads = 4
@@ -103,7 +109,7 @@ func disablementKDF(secret []byte) []byte {
// checkDisablement returns true for a valid disablement secret.
func (s State) checkDisablement(secret []byte) bool {
derived := disablementKDF(secret)
derived := DisablementKDF(secret)
for _, candidate := range s.DisablementSecrets {
if bytes.Equal(derived, candidate) {
return true

View File

@@ -342,7 +342,7 @@ func TestSyncSimpleE2E(t *testing.T) {
`,
optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}}),
optKey("key", key, priv),
optSignAllUsing("key"))

View File

@@ -305,7 +305,7 @@ func TestAuthorityValidDisablement(t *testing.T) {
`,
optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}}),
)
@@ -321,7 +321,7 @@ func TestCreateBootstrapAuthority(t *testing.T) {
a1, genesisAUM, err := Create(&Mem{}, State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}, signer25519(priv))
if err != nil {
t.Fatalf("Create() failed: %v", err)
@@ -361,7 +361,7 @@ func TestAuthorityInformNonLinear(t *testing.T) {
`,
optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}}),
optKey("key", key, priv),
optSignAllUsing("key"))
@@ -406,7 +406,7 @@ func TestAuthorityInformLinear(t *testing.T) {
`,
optTemplate("genesis", AUM{MessageKind: AUMCheckpoint, State: &State{
Keys: []Key{key},
DisablementSecrets: [][]byte{disablementKDF([]byte{1, 2, 3})},
DisablementSecrets: [][]byte{DisablementKDF([]byte{1, 2, 3})},
}}),
optKey("key", key, priv),
optSignAllUsing("key"))