// ValidSigner checks the signature on an attestation and, if so, returns the signer. func (a *Attestation) ValidSigner() (auth.Prin, error) { signer, err := auth.UnmarshalPrin(a.Signer) if err != nil { return auth.Prin{}, err } if len(signer.Ext) != 0 { return auth.Prin{}, newError("tao: attestation signer principal malformed: %s", signer) } switch signer.Type { 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 PCRs from the signer: %s", err) } pk, err := ExtractAIK(speaker) if err != nil { return auth.Prin{}, newError("tao: couldn't extract the AIK from the signer: %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 "key": // Signer is ECDSA key, use Tao signature verification. v, err := FromPrincipal(signer) 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()) } }
// 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()) } }