mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-05 23:07:44 +00:00
tka: make rotation signatures use nested keyID
Duplicating this at each layer doesnt make any sense, and is another invariant where things could go wrong. Signed-off-by: Tom DNetto <tom@tailscale.com>
This commit is contained in:
parent
86c5bddce2
commit
e8a11f6181
21
tka/sig.go
21
tka/sig.go
@ -116,6 +116,27 @@ func (s NodeKeySignature) wrappingPublic() (pub ed25519.PublicKey, ok bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// authorizingKeyID returns the KeyID of the key trusted by network-lock which authorizes
|
||||
// this signature.
|
||||
func (s NodeKeySignature) authorizingKeyID() (tkatype.KeyID, error) {
|
||||
switch s.SigKind {
|
||||
case SigDirect, SigCredential:
|
||||
if len(s.KeyID) == 0 {
|
||||
return tkatype.KeyID{}, errors.New("invalid signature: no keyID present")
|
||||
}
|
||||
return tkatype.KeyID(s.KeyID), nil
|
||||
|
||||
case SigRotation:
|
||||
if s.Nested == nil {
|
||||
return tkatype.KeyID{}, errors.New("invalid signature: rotation signature missing nested signature")
|
||||
}
|
||||
return s.Nested.authorizingKeyID()
|
||||
|
||||
default:
|
||||
return tkatype.KeyID{}, fmt.Errorf("unhandled signature type: %v", s.SigKind)
|
||||
}
|
||||
}
|
||||
|
||||
// SigHash returns the cryptographic digest which a signature
|
||||
// is over.
|
||||
//
|
||||
|
@ -79,7 +79,6 @@ func TestSigNested(t *testing.T) {
|
||||
// rotation key & embedding the original signature.
|
||||
sig := NodeKeySignature{
|
||||
SigKind: SigRotation,
|
||||
KeyID: k.ID(),
|
||||
Pubkey: nodeKeyPub,
|
||||
Nested: &nestedSig,
|
||||
}
|
||||
@ -145,14 +144,13 @@ func TestSigNested_DeepNesting(t *testing.T) {
|
||||
|
||||
outer := nestedSig
|
||||
var lastNodeKey key.NodePrivate
|
||||
for i := 0; i < 100; i++ {
|
||||
for i := 0; i < 15; i++ { // 15 = max nesting level for CBOR
|
||||
lastNodeKey = key.NewNode()
|
||||
nodeKeyPub, _ := lastNodeKey.Public().MarshalBinary()
|
||||
|
||||
tmp := outer
|
||||
sig := NodeKeySignature{
|
||||
SigKind: SigRotation,
|
||||
KeyID: k.ID(),
|
||||
Pubkey: nodeKeyPub,
|
||||
Nested: &tmp,
|
||||
}
|
||||
@ -166,6 +164,16 @@ func TestSigNested_DeepNesting(t *testing.T) {
|
||||
t.Fatalf("verifySignature(lastNodeKey) failed: %v", err)
|
||||
}
|
||||
|
||||
// Test this works with our public API
|
||||
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})},
|
||||
}})).Chonk())
|
||||
if err := a.NodeKeyAuthorized(lastNodeKey.Public(), outer.Serialize()); err != nil {
|
||||
t.Errorf("NodeKeyAuthorized(lastNodeKey) failed: %v", err)
|
||||
}
|
||||
|
||||
// Test verification fails if the inner signature is invalid
|
||||
tmp := make([]byte, ed25519.SignatureSize)
|
||||
copy(tmp, nestedSig.Signature)
|
||||
@ -206,7 +214,6 @@ func TestSigCredential(t *testing.T) {
|
||||
// delegated key & embedding the original signature.
|
||||
sig := NodeKeySignature{
|
||||
SigKind: SigRotation,
|
||||
KeyID: k.ID(),
|
||||
Pubkey: nodeKeyPub,
|
||||
Nested: &nestedSig,
|
||||
}
|
||||
|
@ -686,7 +686,12 @@ func (a *Authority) NodeKeyAuthorized(nodeKey key.NodePublic, nodeKeySignature t
|
||||
return errors.New("credential signatures cannot authorize nodes on their own")
|
||||
}
|
||||
|
||||
key, err := a.state.GetKey(decoded.KeyID)
|
||||
kID, err := decoded.authorizingKeyID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key, err := a.state.GetKey(kID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("key: %v", err)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user