// Attest requests the Tao host sign a statement on behalf of the caller. func (t *StackedHost) Attest(childSubprin auth.SubPrin, issuer *auth.Prin, time, expiration *int64, message auth.Form) (*Attestation, error) { child := t.taoHostName.MakeSubprincipal(childSubprin) if issuer != nil { if !auth.SubprinOrIdentical(*issuer, child) { return nil, newError("invalid issuer in statement") } } else { issuer = &child } if t.keys == nil || t.keys.SigningKey == nil { return t.hostTao.Attest(issuer, time, expiration, message) } stmt := auth.Says{Speaker: *issuer, Time: time, Expiration: expiration, Message: message} var d []byte if t.keys.Delegation != nil { var err error d, err = proto.Marshal(t.keys.Delegation) if err != nil { return nil, err } } return GenerateAttestation(t.keys.SigningKey, d, stmt) }
// Attest requests the Tao host sign a statement on behalf of the caller. The // optional issuer, time and expiration will be given default values if nil. func (tt *TPMTao) Attest(issuer *auth.Prin, start, expiration *int64, message auth.Form) (*Attestation, error) { if issuer == nil { issuer = &tt.name } else if !auth.SubprinOrIdentical(*issuer, tt.name) { return nil, errors.New("invalid issuer in statement") } // TODO(tmroeder): we assume here that the PCRs haven't changed (e.g., been // extended) since this TPMTao was created. If they have, then the PCRs will // be wrong when we extend the principal here with them as the first // component. This doesn't matter at the moment, since we don't currently // support extending the PCRs or clearing them, but it will need to be // changed when we do. stmt := auth.Says{ Speaker: *issuer, Time: start, Expiration: expiration, Message: message, } // This is done in GenerateAttestation, but the TPM attestation is signed // differently, so we do the time calculations here. t := time.Now() if stmt.Time == nil { i := t.UnixNano() stmt.Time = &i } if stmt.Expiration == nil { i := t.Add(365 * 24 * time.Hour).UnixNano() stmt.Expiration = &i } ser := auth.Marshal(stmt) // TODO(tmroeder): check the pcrVals for sanity once we support extending or // clearing the PCRs. sig, _, err := tpm.Quote(tt.tpmfile, tt.aikHandle, ser, tt.pcrNums, tt.srkAuth[:]) if err != nil { return nil, err } // Pull off the extensions from the name to get the bare TPM key for the // signer. signer := auth.Prin{ Type: tt.name.Type, Key: tt.name.Key, } a := &Attestation{ SerializedStatement: ser, Signature: sig, Signer: auth.Marshal(signer), } return a, nil }
// Attest requests the Tao host sign a statement on behalf of the caller. func (t *RootHost) Attest(childSubprin auth.SubPrin, issuer *auth.Prin, time, expiration *int64, message auth.Form) (*Attestation, error) { child := t.taoHostName.MakeSubprincipal(childSubprin) if issuer != nil { if !auth.SubprinOrIdentical(*issuer, child) { return nil, newError("invalid issuer in statement") } } else { issuer = &child } stmt := auth.Says{Speaker: *issuer, Time: time, Expiration: expiration, Message: message} return GenerateAttestation(t.keys.SigningKey, nil /* delegation */, stmt) }
// Attest requests that the Tao host sign a statement on behalf of the caller. func (s *SoftTao) Attest(issuer *auth.Prin, time, expiration *int64, message auth.Form) (*Attestation, error) { child := s.name.MakeSubprincipal(s.nameExtension) if issuer == nil { issuer = &child } else if !auth.SubprinOrIdentical(issuer, child) { return nil, newError("Invalid issuer in statement: %s may not speak for %s", child, issuer) } stmt := auth.Says{Speaker: *issuer, Time: time, Expiration: expiration, Message: message} var delegation []byte if s.keys.Delegation != nil { var err error delegation, err = proto.Marshal(s.keys.Delegation) if err != nil { return nil, err } } return GenerateAttestation(s.keys.SigningKey, delegation, stmt) }
// SignsForPrincipal returns true when prin is (or is a subprincipal of) this verifier key. func (v *Verifier) SignsForPrincipal(prin auth.Prin) bool { return auth.SubprinOrIdentical(prin, v.ToPrincipal()) }
// Validate checks whether an attestation is valid and, if so, it returns the // statement conveyed by the attestation. func (a *Attestation) Validate() (auth.Says, error) { signer, err := a.ValidSigner() if err != nil { return auth.Says{}, err } f, err := auth.UnmarshalForm(a.SerializedStatement) if err != nil { return auth.Says{}, err } var stmt *auth.Says if ptr, ok := f.(*auth.Says); ok { stmt = ptr } else if val, ok := f.(auth.Says); ok { stmt = &val } else { return auth.Says{}, newError("tao: attestation statement has wrong type: %T", f) } if a.SerializedDelegation == nil { // Case (1), no delegation present. // Require that stmt.Speaker be a subprincipal of (or identical to) a.signer. if !auth.SubprinOrIdentical(stmt.Speaker, signer) { return auth.Says{}, newError("tao: attestation statement signer (%v) does not evidently speak for issuer (%v)", signer, stmt.Speaker) } } else { // Case (2), delegation present. // Require that: // - delegation conveys delegator says delegate speaksfor delegator, // - a.signer speaks for delegate // - and delegator speaks for s.Speaker var da Attestation if err := proto.Unmarshal(a.SerializedDelegation, &da); err != nil { return auth.Says{}, err } delegationStatement, err := da.Validate() if err != nil { return auth.Says{}, err } var delegation *auth.Speaksfor if ptr, ok := delegationStatement.Message.(*auth.Speaksfor); ok { delegation = ptr } else if val, ok := delegationStatement.Message.(auth.Speaksfor); ok { delegation = &val } else { return auth.Says{}, newError("tao: attestation delegation is wrong type") } if !delegationStatement.Speaker.Identical(delegation.Delegator) { return auth.Says{}, newError("tao: attestation delegation is invalid") } if !auth.SubprinOrIdentical(delegation.Delegate, signer) { return auth.Says{}, newError("tao: attestation delegation irrelevant to signer") } if !auth.SubprinOrIdentical(stmt.Speaker, delegation.Delegator) { return auth.Says{}, newError("tao: attestation delegation irrelevant to issuer") } if stmt.Time == nil { stmt.Time = delegationStatement.Time } else if delegationStatement.Time != nil && *stmt.Time < *delegationStatement.Time { stmt.Time = delegationStatement.Time } if stmt.Expiration == nil { stmt.Expiration = delegationStatement.Expiration } else if delegationStatement.Expiration != nil && *stmt.Expiration > *delegationStatement.Expiration { stmt.Expiration = delegationStatement.Expiration } } return *stmt, nil }
// Attest requests the Tao host seal a statement on behalf of the caller. The // optional issuer, time and expiration will be given default values if nil. func (tt *TPM2Tao) Attest(issuer *auth.Prin, start, expiration *int64, message auth.Form) (*Attestation, error) { fmt.Fprintf(os.Stderr, "About to load the quote key in attest\n") qh, err := tt.loadQuote() if err != nil { return nil, err } defer tpm2.FlushContext(tt.rw, qh) if issuer == nil { issuer = &tt.name } else if !auth.SubprinOrIdentical(*issuer, tt.name) { return nil, errors.New("invalid issuer in statement") } // TODO(tmroeder): we assume here that the PCRs haven't changed (e.g., been // extended) since this TPM2Tao was created. If they have, then the PCRs will // be wrong when we extend the principal here with them as the first // component. This doesn't matter at the moment, since we don't currently // support extending the PCRs or clearing them, but it will need to be // changed when we do. stmt := auth.Says{ Speaker: *issuer, Time: start, Expiration: expiration, Message: message, } // This is done in GenerateAttestation, but the TPM attestation is sealed // differently, so we do the time calculations here. t := time.Now() if stmt.Time == nil { i := t.UnixNano() stmt.Time = &i } if stmt.Expiration == nil { i := t.Add(365 * 24 * time.Hour).UnixNano() stmt.Expiration = &i } ser := auth.Marshal(stmt) var pcrVals [][]byte toQuote, err := tpm2.FormatTpm2Quote(ser, tt.pcrs, pcrVals) if err != nil { return nil, errors.New("Can't format tpm2 Quote") } // TODO(tmroeder): check the pcrVals for sanity once we support extending or // clearing the PCRs. quote_struct, sig, err := tpm2.Quote(tt.rw, qh, "", tt.password, toQuote, tt.pcrs, uint16(tpm2.AlgTPM_ALG_NULL)) if err != nil { return nil, err } fmt.Printf("toQuote: %x\n", toQuote) fmt.Printf("Quote: %x\n", quote_struct) fmt.Printf("sig: %x\n", sig) quoteKey, err := x509.MarshalPKIXPublicKey(tt.verifier) if err != nil { return nil, err } // TODO(kwalsh) remove Tpm2QuoteStructure from Attestation structure a := &Attestation{ SerializedStatement: ser, Signature: sig, SignerType: proto.String("tpm2"), SignerKey: quoteKey, Tpm2QuoteStructure: quote_struct, } return a, nil }