예제 #1
0
// ValidSigner checks the signature on an attestation and, if so, returns the
// principal name for the signer.
func (a *Attestation) ValidSigner() (auth.Prin, error) {
	signer := auth.NewPrin(*a.SignerType, a.SignerKey)
	switch *a.SignerType {
	case "tpm":
		// The PCRs are contained in the Speaker of an auth.Says statement that
		// makes up the a.SerializedStatement.
		f, err := auth.UnmarshalForm(a.SerializedStatement)
		if err != nil {
			return auth.Prin{}, newError("tao: couldn't unmarshal the statement: %s", err)
		}

		// A TPM attestation must be an auth.Says.
		says, ok := f.(auth.Says)
		if !ok {
			return auth.Prin{}, newError("tao: the attestation statement was not an auth.Says statement")
		}

		// Signer is tpm; use tpm-specific signature verification. Extract the
		// PCRs from the issuer name, unmarshal the key as an RSA key, and call
		// tpm.VerifyQuote().
		speaker, ok := says.Speaker.(auth.Prin)
		if !ok {
			return auth.Prin{}, newError("tao: the speaker of an attestation must be an auth.Prin")
		}
		pcrNums, pcrVals, err := extractPCRs(speaker)
		if err != nil {
			return auth.Prin{}, newError("tao: couldn't extract TPM PCRs from attestation: %s", err)
		}

		pk, err := extractTPMKey(a.SignerKey)
		if err != nil {
			return auth.Prin{}, newError("tao: couldn't extract TPM key from attestation: %s", err)
		}
		if err := tpm.VerifyQuote(pk, a.SerializedStatement, a.Signature, pcrNums, pcrVals); err != nil {
			return auth.Prin{}, newError("tao: TPM quote failed verification: %s", err)
		}

		return signer, nil
	case "tpm2":
		// TODO -- tpm2
		// The PCRs are contained in the Speaker of an auth.Says statement that
		// makes up the a.SerializedStatement.
		f, err := auth.UnmarshalForm(a.SerializedStatement)
		if err != nil {
			return auth.Prin{}, newError("tao: couldn't unmarshal the statement: %s", err)
		}

		// put this back in
		// A TPM attestation must be an auth.Says.
		says, ok := f.(auth.Says)
		if !ok {
			return auth.Prin{}, newError("tao: the attestation statement was not an auth.Says statement")
		}

		// Signer is tpm; use tpm-specific signature verification. Extract the
		// PCRs from the issuer name, unmarshal the key as an RSA key, and call
		// tpm2.VerifyQuote().
		speaker, ok := says.Speaker.(auth.Prin)
		if !ok {
			return auth.Prin{}, newError("tao: the speaker of an attestation must be an auth.Prin")
		}

		key, err := extractTPM2Key(a.SignerKey)
		if err != nil {
			return auth.Prin{}, newError("tao: couldn't extract TPM key from attestation: %s", err)
		}
		pcrNums, pcrVal, err := extractTpm2PCRs(speaker)
		if err != nil {
			return auth.Prin{}, newError("tao: couldn't extract TPM PCRs from attestation: %s", err)
		}

		ok, err = tpm2.VerifyTpm2Quote(a.SerializedStatement,
			pcrNums, pcrVal, a.Tpm2QuoteStructure, a.Signature,
			key)
		if err != nil {
			return auth.Prin{}, newError("tao: TPM quote verification error")
		}
		if !ok {
			return auth.Prin{}, newError("tao: TPM quote failed verification")
		}
		return signer, nil
	case "key":
		// Signer is ECDSA key, use Tao signature verification.
		v, err := UnmarshalKey(a.SignerKey)
		if err != nil {
			return auth.Prin{}, err
		}
		ok, err := v.Verify(a.SerializedStatement, AttestationSigningContext, a.Signature)
		if err != nil {
			return auth.Prin{}, err
		}
		if !ok {
			return auth.Prin{}, newError("tao: attestation signature invalid")
		}
		return signer, nil
	default:
		return auth.Prin{}, newError("tao: attestation signer principal unrecognized: %s", signer.String())
	}
}
예제 #2
0
func TestTPM2TaoAttest(t *testing.T) {

	// Fix
	hash_alg_id := uint16(tpm2.AlgTPM_ALG_SHA1)

	tpmtao, err := NewTPM2Tao("/dev/tpm0", "../tpm2/tmptest", []int{17, 18})
	if err != nil {
		t.Skip("Couldn't create a new TPM Tao:", err)
	}
	tt, ok := tpmtao.(*TPM2Tao)
	if !ok {
		t.Fatal("Failed to create the right kind of Tao object from NewTPM2Tao")
	}
	defer cleanUpTPM2Tao(tt)

	// Set up a fake key delegation.
	taoname, err := tpmtao.GetTaoName()
	if err != nil {
		t.Fatal("Couldn't get the name of the tao:", err)
	}
	stmt := auth.Speaksfor{
		Delegate:  auth.NewKeyPrin([]byte(`FakeKeyBytes`)),
		Delegator: taoname,
	}

	// Let the TPMTao set up the issuer and time and expiration.
	a, err := tpmtao.Attest(nil, nil, nil, stmt)
	if err != nil {
		t.Fatal("Couldn't attest to a key delegation:", err)
	}

	digests, err := tt.ReadPcrs([]int{17, 18}) // tt.pcrs
	if err != nil {
		t.Fatal("ReadPcrs failed\n")
	}
	var allDigests []byte
	for i := 0; i < len(digests); i++ {
		allDigests = append(allDigests, digests[i]...)
	}
	computedDigest, err := tpm2.ComputeHashValue(hash_alg_id, allDigests)
	if err != nil {
		t.Fatal("Can't compute combined quote digest")
	}
	fmt.Printf("Pcr combined digest: %x\n", computedDigest)

	pms, err := tpm2.UnmarshalCertifyInfo(a.Tpm2QuoteStructure)
	if err != nil {
		fmt.Printf("a.Tpm2QuoteStructure: %x\n", a.Tpm2QuoteStructure)
		t.Fatal("Can't unmarshal quote structure\n")
	}
	tpm2.PrintAttestData(pms)
	key, _ := tt.GetRsaQuoteKey()
	ok, err = tpm2.VerifyTpm2Quote(a.SerializedStatement, tt.GetPcrNums(),
		computedDigest, a.Tpm2QuoteStructure, a.Signature, key)
	if err != nil {
		t.Fatal("VerifyQuote error")
	}
	if !ok {
		t.Fatal("VerifyQuote succeeds")
	}
}