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>
pull/5974/head
Tom DNetto 2 years ago committed by Tom
parent 86c5bddce2
commit e8a11f6181

@ -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…
Cancel
Save