Skip to content

Commit

Permalink
attest: Support certification by ECC AKs.
Browse files Browse the repository at this point in the history
  • Loading branch information
zhsh authored and brandonweeks committed Jan 22, 2025
1 parent 1b202b1 commit c7aee80
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 29 deletions.
19 changes: 12 additions & 7 deletions attest/certification.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package attest
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"errors"
Expand Down Expand Up @@ -164,11 +165,6 @@ func (p *CertificationParameters) Verify(opts VerifyOpts) error {
}

// Check the signature over the attestation data verifies correctly.
// TODO: Support ECC certifying keys
pk, ok := opts.Public.(*rsa.PublicKey)
if !ok {
return fmt.Errorf("only RSA verification keys are supported")
}
if !opts.Hash.Available() {
return fmt.Errorf("hash function is unavailable")
}
Expand All @@ -184,8 +180,17 @@ func (p *CertificationParameters) Verify(opts VerifyOpts) error {
return fmt.Errorf("DecodeSignature() failed: %v", err)
}

if err := rsa.VerifyPKCS1v15(pk, opts.Hash, hsh.Sum(nil), sig.RSA.Signature); err != nil {
return fmt.Errorf("could not verify attestation: %v", err)
switch pk := opts.Public.(type) {
case *rsa.PublicKey:
if err := rsa.VerifyPKCS1v15(pk, opts.Hash, hsh.Sum(nil), sig.RSA.Signature); err != nil {
return fmt.Errorf("could not verify attestation: %v", err)
}
case *ecdsa.PublicKey:
if ok := ecdsa.Verify(pk, hsh.Sum(nil), sig.ECC.R, sig.ECC.S); !ok {
return fmt.Errorf("could not verify ECC attestation")
}
default:
return fmt.Errorf("unsupported public key type: %T", pub)
}

return nil
Expand Down
77 changes: 58 additions & 19 deletions attest/certification_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,19 @@ import (
"github.com/google/go-tpm/legacy/tpm2"
)

func TestSimTPM20CertificationParameters(t *testing.T) {
func TestSimTPM20CertificationParametersRSA(t *testing.T) {
sim, tpm := setupSimulatedTPM(t)
defer sim.Close()
testCertificationParameters(t, tpm)
testCertificationParameters(t, tpm, RSA)
}

func TestTPM20CertificationParameters(t *testing.T) {
func TestSimTPM20CertificationParametersECC(t *testing.T) {
sim, tpm := setupSimulatedTPM(t)
defer sim.Close()
testCertificationParameters(t, tpm, ECDSA)
}

func TestTPM20CertificationParametersRSA(t *testing.T) {
if !*testLocal {
t.SkipNow()
}
Expand All @@ -46,11 +52,23 @@ func TestTPM20CertificationParameters(t *testing.T) {
t.Fatalf("OpenTPM() failed: %v", err)
}
defer tpm.Close()
testCertificationParameters(t, tpm)
testCertificationParameters(t, tpm, RSA)
}

func testCertificationParameters(t *testing.T, tpm *TPM) {
ak, err := tpm.NewAK(nil)
func TestTPM20CertificationParametersECC(t *testing.T) {
if !*testLocal {
t.SkipNow()
}
tpm, err := OpenTPM(nil)
if err != nil {
t.Fatalf("OpenTPM() failed: %v", err)
}
defer tpm.Close()
testCertificationParameters(t, tpm, ECDSA)
}

func testCertificationParameters(t *testing.T, tpm *TPM, akAlg Algorithm) {
ak, err := tpm.NewAK(&AKConfig{Algorithm: akAlg})
if err != nil {
t.Fatal(err)
}
Expand All @@ -59,12 +77,12 @@ func testCertificationParameters(t *testing.T, tpm *TPM) {
if err != nil {
t.Fatal(err)
}
if pub.Type != tpm2.AlgRSA {
t.Fatal("non-RSA verifying key")
}

pk := &rsa.PublicKey{E: int(pub.RSAParameters.Exponent()), N: pub.RSAParameters.Modulus()}
hash, err := pub.RSAParameters.Sign.Hash.Hash()
pk, err := pub.Key()
if err != nil {
t.Fatal(err)
}
hash, err := pub.NameAlg.Hash()
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -170,13 +188,19 @@ func testCertificationParameters(t *testing.T, tpm *TPM) {
}
}

func TestSimTPM20KeyCertification(t *testing.T) {
func TestSimTPM20KeyCertificationRSA(t *testing.T) {
sim, tpm := setupSimulatedTPM(t)
defer sim.Close()
testKeyCertification(t, tpm, RSA)
}

func TestSimTPM20KeyCertificationECC(t *testing.T) {
sim, tpm := setupSimulatedTPM(t)
defer sim.Close()
testKeyCertification(t, tpm)
testKeyCertification(t, tpm, ECDSA)
}

func TestTPM20KeyCertification(t *testing.T) {
func TestTPM20KeyCertificationRSA(t *testing.T) {
if !*testLocal {
t.SkipNow()
}
Expand All @@ -185,11 +209,23 @@ func TestTPM20KeyCertification(t *testing.T) {
t.Fatalf("OpenTPM() failed: %v", err)
}
defer tpm.Close()
testKeyCertification(t, tpm)
testKeyCertification(t, tpm, RSA)
}

func testKeyCertification(t *testing.T, tpm *TPM) {
ak, err := tpm.NewAK(nil)
func TestTPM20KeyCertificationECC(t *testing.T) {
if !*testLocal {
t.SkipNow()
}
tpm, err := OpenTPM(nil)
if err != nil {
t.Fatalf("OpenTPM() failed: %v", err)
}
defer tpm.Close()
testKeyCertification(t, tpm, ECDSA)
}

func testKeyCertification(t *testing.T, tpm *TPM, akAlg Algorithm) {
ak, err := tpm.NewAK(&AKConfig{Algorithm: akAlg})
if err != nil {
t.Fatalf("NewAK() failed: %v", err)
}
Expand All @@ -198,8 +234,11 @@ func testKeyCertification(t *testing.T, tpm *TPM) {
if err != nil {
t.Fatalf("DecodePublic() failed: %v", err)
}
pk := &rsa.PublicKey{E: int(pub.RSAParameters.Exponent()), N: pub.RSAParameters.Modulus()}
hash, err := pub.RSAParameters.Sign.Hash.Hash()
pk, err := pub.Key()
if err != nil {
t.Fatalf("pub.Key() failed: %v", err)
}
hash, err := pub.NameAlg.Hash()
if err != nil {
t.Fatalf("cannot access AK's hash function: %v", err)
}
Expand Down
27 changes: 24 additions & 3 deletions attest/wrapped_tpm20.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,27 @@ func (k *wrappedKey20) activateCredential(tb tpmBase, in EncryptedCredential, ek
}, k.hnd, ekHnd, credential, secret)
}

func sigSchemeFromPublicKey(pub []byte) (tpm2.SigScheme, error) {
tpmPub, err := tpm2.DecodePublic(pub)
if err != nil {
return tpm2.SigScheme{}, fmt.Errorf("decode public key: %v", err)
}
switch tpmPub.Type {
case tpm2.AlgRSA:
return tpm2.SigScheme{
Alg: tpm2.AlgRSASSA,
Hash: tpm2.AlgSHA256,
}, nil
case tpm2.AlgECC:
return tpm2.SigScheme{
Alg: tpm2.AlgECDSA,
Hash: tpm2.AlgSHA256,
}, nil
default:
return tpm2.SigScheme{}, fmt.Errorf("public key of alg 0x%x not supported", tpmPub.Type)
}
}

func (k *wrappedKey20) certify(tb tpmBase, handle interface{}) (*CertificationParameters, error) {
t, ok := tb.(*wrappedTPM20)
if !ok {
Expand All @@ -575,9 +596,9 @@ func (k *wrappedKey20) certify(tb tpmBase, handle interface{}) (*CertificationPa
if !ok {
return nil, fmt.Errorf("expected tpmutil.Handle, got %T", handle)
}
scheme := tpm2.SigScheme{
Alg: tpm2.AlgRSASSA,
Hash: tpm2.AlgSHA256,
scheme, err := sigSchemeFromPublicKey(k.public)
if err != nil {
return nil, fmt.Errorf("get signature scheme: %v", err)
}
return certify(t.rwc, hnd, k.hnd, scheme)
}
Expand Down

0 comments on commit c7aee80

Please sign in to comment.