control/controlclient: update machine certificate signature version

This iterates on the original signature format.

Signed-off-by: Adrian Dewhurst <adrian@tailscale.com>
This commit is contained in:
Adrian Dewhurst 2021-09-17 13:17:57 -04:00 committed by Adrian Dewhurst
parent a722e48cef
commit 4da559d7cc
3 changed files with 35 additions and 10 deletions

View File

@ -10,22 +10,34 @@
"fmt"
"time"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
)
var (
errNoCertStore = errors.New("no certificate store")
errCertificateNotConfigured = errors.New("no certificate subject configured")
errUnsupportedSignatureVersion = errors.New("unsupported signature version")
)
// HashRegisterRequest generates the hash required sign or verify a
// tailcfg.RegisterRequest with tailcfg.SignatureV1.
func HashRegisterRequest(ts time.Time, serverURL string, deviceCert []byte, serverPubKey, machinePubKey key.MachinePublic) []byte {
// tailcfg.RegisterRequest.
func HashRegisterRequest(
version tailcfg.SignatureType, ts time.Time, serverURL string, deviceCert []byte,
serverPubKey, machinePubKey key.MachinePublic) ([]byte, error) {
h := crypto.SHA256.New()
// hash.Hash.Write never returns an error, so we don't check for one here.
switch version {
case tailcfg.SignatureV1:
fmt.Fprintf(h, "%s%s%s%s%s",
ts.UTC().Format(time.RFC3339), serverURL, deviceCert, serverPubKey.ShortString(), machinePubKey.ShortString())
case tailcfg.SignatureV2:
fmt.Fprintf(h, "%s%s%s%s%s",
ts.UTC().Format(time.RFC3339), serverURL, deviceCert, serverPubKey, machinePubKey)
return h.Sum(nil)
default:
return nil, errUnsupportedSignatureVersion
}
return h.Sum(nil), nil
}

View File

@ -167,7 +167,11 @@ func signRegisterRequest(req *tailcfg.RegisterRequest, serverURL string, serverP
req.DeviceCert = append(req.DeviceCert, c.Raw...)
}
h := HashRegisterRequest(req.Timestamp.UTC(), serverURL, req.DeviceCert, serverPubKey, machinePubKey)
req.SignatureType = tailcfg.SignatureV2
h, err := HashRegisterRequest(req.SignatureType, req.Timestamp.UTC(), serverURL, req.DeviceCert, serverPubKey, machinePubKey)
if err != nil {
return fmt.Errorf("hash: %w", err)
}
req.Signature, err = signer.Sign(nil, h, &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthEqualsHash,
@ -176,7 +180,6 @@ func signRegisterRequest(req *tailcfg.RegisterRequest, serverURL string, serverP
if err != nil {
return fmt.Errorf("sign: %w", err)
}
req.SignatureType = tailcfg.SignatureV1
return nil
}

View File

@ -558,10 +558,16 @@ func (h *Hostinfo) Equal(h2 *Hostinfo) bool {
// be considered an error if seen.
SignatureUnknown
// SignatureV1 is computed as RSA-PSS-Sign(privateKeyForDeviceCert,
// SHA256(Timestamp || ServerIdentity || DeviceCert || ServerShortPubKey ||
// MachineShortPubKey)). The PSS salt length is equal to hash length
// (rsa.PSSSaltLengthEqualsHash). Device cert is required.
// Deprecated: uses old key serialization format.
SignatureV1
// SignatureV2 is computed as RSA-PSS-Sign(privateKeyForDeviceCert,
// SHA256(Timestamp || ServerIdentity || DeviceCert || ServerPubKey ||
// MachinePubKey)). The PSS salt length is equal to hash length
// (rsa.PSSSaltLengthEqualsHash). Device cert is required.
SignatureV1
SignatureV2
)
func (st SignatureType) MarshalText() ([]byte, error) {
@ -574,6 +580,8 @@ func (st *SignatureType) UnmarshalText(b []byte) error {
*st = SignatureNone
case "signature-v1":
*st = SignatureV1
case "signature-v2":
*st = SignatureV2
default:
var val int
if _, err := fmt.Sscanf(string(b), "signature-unknown(%d)", &val); err != nil {
@ -593,6 +601,8 @@ func (st SignatureType) String() string {
return "signature-unknown"
case SignatureV1:
return "signature-v1"
case SignatureV2:
return "signature-v2"
default:
return fmt.Sprintf("signature-unknown(%d)", int(st))
}