2021-03-08 20:27:00 +00:00
|
|
|
// Copyright 2021 Google Inc.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
|
|
// use this file except in compliance with the License. You may obtain a copy of
|
|
|
|
// the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
// License for the specific language governing permissions and limitations under
|
|
|
|
// the License.
|
|
|
|
|
2021-12-09 00:43:38 +00:00
|
|
|
//go:build (!localtest || !tpm12) && linux && cgo
|
|
|
|
// +build !localtest !tpm12
|
|
|
|
// +build linux
|
|
|
|
// +build cgo
|
|
|
|
|
2021-03-08 20:27:00 +00:00
|
|
|
package attest
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto"
|
|
|
|
"crypto/rand"
|
|
|
|
"crypto/rsa"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
|
|
"github.com/google/go-tpm/tpm2"
|
|
|
|
)
|
|
|
|
|
2021-05-20 18:15:09 +00:00
|
|
|
func TestSimTPM20CertificationParameters(t *testing.T) {
|
|
|
|
sim, tpm := setupSimulatedTPM(t)
|
|
|
|
defer sim.Close()
|
|
|
|
testCertificationParameters(t, tpm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTPM20CertificationParameters(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)
|
|
|
|
}
|
2021-03-08 20:27:00 +00:00
|
|
|
|
2021-05-20 18:15:09 +00:00
|
|
|
func testCertificationParameters(t *testing.T, tpm *TPM) {
|
2021-03-08 20:27:00 +00:00
|
|
|
ak, err := tpm.NewAK(nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
akAttestParams := ak.AttestationParameters()
|
|
|
|
pub, err := tpm2.DecodePublic(akAttestParams.Public)
|
|
|
|
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()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
correctOpts := VerifyOpts{
|
|
|
|
Public: pk,
|
|
|
|
Hash: hash,
|
|
|
|
}
|
|
|
|
|
|
|
|
wrongKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
wrongHash := crypto.SHA512_256
|
|
|
|
if wrongHash == correctOpts.Hash {
|
|
|
|
wrongHash = crypto.SHA256
|
|
|
|
}
|
|
|
|
|
|
|
|
sk, err := tpm.NewKey(ak, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
skCertParams := sk.CertificationParameters()
|
|
|
|
|
|
|
|
for _, test := range []struct {
|
|
|
|
name string
|
|
|
|
p *CertificationParameters
|
|
|
|
opts VerifyOpts
|
|
|
|
err error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "OK",
|
|
|
|
p: &skCertParams,
|
|
|
|
opts: correctOpts,
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "wrong public key",
|
|
|
|
p: &skCertParams,
|
|
|
|
opts: VerifyOpts{
|
|
|
|
Public: wrongKey.Public,
|
|
|
|
Hash: correctOpts.Hash,
|
|
|
|
},
|
|
|
|
err: cmpopts.AnyError,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "wrong hash function",
|
|
|
|
p: &skCertParams,
|
|
|
|
opts: VerifyOpts{
|
|
|
|
Public: correctOpts.Public,
|
|
|
|
Hash: wrongHash,
|
|
|
|
},
|
|
|
|
err: cmpopts.AnyError,
|
|
|
|
},
|
2021-03-09 17:30:11 +00:00
|
|
|
{
|
|
|
|
name: "unavailable hash function",
|
|
|
|
p: &skCertParams,
|
|
|
|
opts: VerifyOpts{
|
|
|
|
Public: correctOpts.Public,
|
|
|
|
Hash: crypto.BLAKE2b_384,
|
|
|
|
},
|
|
|
|
err: cmpopts.AnyError,
|
|
|
|
},
|
2021-03-08 20:27:00 +00:00
|
|
|
{
|
|
|
|
name: "modified Public",
|
|
|
|
p: &CertificationParameters{
|
|
|
|
Public: akAttestParams.Public,
|
|
|
|
CreateAttestation: skCertParams.CreateAttestation,
|
|
|
|
CreateSignature: skCertParams.CreateSignature,
|
|
|
|
},
|
|
|
|
opts: correctOpts,
|
|
|
|
err: cmpopts.AnyError,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "modified CreateAttestation",
|
|
|
|
p: &CertificationParameters{
|
|
|
|
Public: skCertParams.Public,
|
|
|
|
CreateAttestation: akAttestParams.CreateAttestation,
|
|
|
|
CreateSignature: skCertParams.CreateSignature,
|
|
|
|
},
|
|
|
|
opts: correctOpts,
|
|
|
|
err: cmpopts.AnyError,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "modified CreateSignature",
|
|
|
|
p: &CertificationParameters{
|
|
|
|
Public: skCertParams.Public,
|
|
|
|
CreateAttestation: skCertParams.CreateAttestation,
|
|
|
|
CreateSignature: akAttestParams.CreateSignature,
|
|
|
|
},
|
|
|
|
opts: correctOpts,
|
|
|
|
err: cmpopts.AnyError,
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
err := test.p.Verify(test.opts)
|
|
|
|
if test.err == nil && err == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if got, want := err, test.err; !cmp.Equal(got, want, cmpopts.EquateErrors()) {
|
|
|
|
t.Errorf("p.Verify() err = %v, want = %v", got, want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2021-05-20 18:15:09 +00:00
|
|
|
|
|
|
|
func TestSimTPM20KeyCertification(t *testing.T) {
|
|
|
|
sim, tpm := setupSimulatedTPM(t)
|
|
|
|
defer sim.Close()
|
|
|
|
testKeyCertification(t, tpm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTPM20KeyCertification(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)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testKeyCertification(t *testing.T, tpm *TPM) {
|
|
|
|
ak, err := tpm.NewAK(nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("NewAK() failed: %v", err)
|
|
|
|
}
|
|
|
|
akAttestParams := ak.AttestationParameters()
|
|
|
|
pub, err := tpm2.DecodePublic(akAttestParams.Public)
|
|
|
|
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()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("cannot access AK's hash function: %v", err)
|
|
|
|
}
|
|
|
|
verifyOpts := VerifyOpts{
|
|
|
|
Public: pk,
|
|
|
|
Hash: hash,
|
|
|
|
}
|
|
|
|
for _, test := range []struct {
|
|
|
|
name string
|
|
|
|
opts *KeyConfig
|
|
|
|
err error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "default",
|
|
|
|
opts: nil,
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ECDSAP256-SHA256",
|
|
|
|
opts: &KeyConfig{
|
|
|
|
Algorithm: ECDSA,
|
|
|
|
Size: 256,
|
|
|
|
},
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ECDSAP384-SHA384",
|
|
|
|
opts: &KeyConfig{
|
|
|
|
Algorithm: ECDSA,
|
|
|
|
Size: 384,
|
|
|
|
},
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ECDSAP521-SHA512",
|
|
|
|
opts: &KeyConfig{
|
|
|
|
Algorithm: ECDSA,
|
|
|
|
Size: 521,
|
|
|
|
},
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "RSA-1024, key too short",
|
|
|
|
opts: &KeyConfig{
|
|
|
|
Algorithm: RSA,
|
|
|
|
Size: 1024,
|
|
|
|
},
|
|
|
|
err: cmpopts.AnyError,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "RSA-2048",
|
|
|
|
opts: &KeyConfig{
|
|
|
|
Algorithm: RSA,
|
|
|
|
Size: 2048,
|
|
|
|
},
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
sk, err := tpm.NewKey(ak, test.opts)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("NewKey() failed: %v", err)
|
|
|
|
}
|
|
|
|
defer sk.Close()
|
|
|
|
p := sk.CertificationParameters()
|
|
|
|
err = p.Verify(verifyOpts)
|
|
|
|
if test.err == nil && err == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if got, want := err, test.err; !cmp.Equal(got, want, cmpopts.EquateErrors()) {
|
|
|
|
t.Errorf("p.Verify() err = %v, want = %v", got, want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|