Files
netbird/client/internal/tpm/signer_test.go
T
riccardom a7f183c87c [client] Read TSS2 key files on go-tpm, checked against the library it replaces
The TSS2 parser was the only reason this repository depended on a crypto suite
whose own build tooling it inherits. The replacement sits on go-tpm, which was
already a direct dependency and is in fact what that suite calls underneath, so
this removes a wrapper rather than porting onto a different library: the load,
the derived storage root key and the signing commands are the same calls.

Swapping a parser on the one path a customer actually runs is not something to
assert, so the two are held side by side for this commit. One test feeds the
replacement bytes the old library wrote and requires the same key type, empty
auth flag, parent handle, blobs and decoded public key; the other feeds both the
fixtures the tests are built on, so those are the shape the format calls for and
not merely the shape the new parser reads. The scaffolding goes away with the
dependency in the commit that follows.

The encoder behind the fixtures is written out separately from the parser under
test, so an encoder bug and a decoder bug cannot cancel each other out.
2026-10-02 16:21:04 +02:00

62 lines
1.7 KiB
Go

package tpm
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"encoding/pem"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/netbirdio/netbird/client/internal/tpm/tpmtest"
)
func TestParseKey_ReportsPublicKeyWithoutTouchingTPM(t *testing.T) {
key := newP256Key(t)
signer, err := ParseKey(decodePEM(t, tpmtest.KeyPEM(t, &key.PublicKey)))
require.NoError(t, err)
assert.True(t, key.PublicKey.Equal(signer.Public()), "signer must expose the key the TPM holds")
}
func TestParseKey_RejectsKeyWithAuthorization(t *testing.T) {
key := newP256Key(t)
_, err := ParseKey(decodePEM(t, tpmtest.KeyPEM(t, &key.PublicKey, tpmtest.WithAuth())))
assert.ErrorIs(t, err, ErrKeyNeedsAuth)
}
func TestParseKey_RejectsMalformedKey(t *testing.T) {
_, err := ParseKey([]byte("not a TSS2 key"))
assert.Error(t, err)
}
func TestSign_FailsWhenTPMIsUnreachable(t *testing.T) {
t.Setenv(DeviceEnv, filepath.Join(t.TempDir(), "missing"))
signer, err := ParseKey(decodePEM(t, tpmtest.KeyPEM(t, &newP256Key(t).PublicKey)))
require.NoError(t, err)
digest := sha256.Sum256([]byte("challenge"))
_, err = signer.Sign(rand.Reader, digest[:], crypto.SHA256)
assert.Error(t, err, "signing must not fall back to software when the TPM is missing")
}
func newP256Key(t *testing.T) *ecdsa.PrivateKey {
t.Helper()
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)
return key
}
func decodePEM(t *testing.T, pemData string) []byte {
t.Helper()
block, _ := pem.Decode([]byte(pemData))
require.NotNil(t, block)
require.Equal(t, KeyPEMType, block.Type)
return block.Bytes
}