// Input: Der encoded endorsement cert and handles // quote key is certified key unlike in the tpm2.go library // Returns ProgramCertRequestMessage func Tpm2ConstructClientRequest(rw io.ReadWriter, derEkCert []byte, pcrs []int, qh tpm2.Handle, parentPassword string, ownerPassword string, keyName string) (*tpm2.ProgramCertRequestMessage, error) { // Generate Request request := new(tpm2.ProgramCertRequestMessage) request.ProgramKey = new(tpm2.ProgramKeyParameters) request.EndorsementCertBlob = derEkCert req_id := "001" request.RequestId = &req_id // Quote key keyBlob, tpm2QuoteName, _, err := tpm2.ReadPublic(rw, qh) if err != nil { return nil, err } rsaQuoteParams, err := tpm2.DecodeRsaBuf(keyBlob) if err != nil { return nil, err } modSize := int32(rsaQuoteParams.Mod_sz) keyType := "rsa" request.ProgramKey.ProgramName = &keyName request.ProgramKey.ProgramKeyType = &keyType request.ProgramKey.ProgramBitModulusSize = &modSize request.ProgramKey.ProgramKeyExponent = []byte{0, 1, 0, 1} request.ProgramKey.ProgramKeyModulus = rsaQuoteParams.Modulus serializedProgramKey := proto.CompactTextString(request.ProgramKey) sha1Hash := sha1.New() sha1Hash.Write([]byte(serializedProgramKey)) hashProgramKey := sha1Hash.Sum(nil) sigAlg := uint16(tpm2.AlgTPM_ALG_NULL) attest, sig, err := tpm2.Quote(rw, qh, parentPassword, ownerPassword, hashProgramKey, pcrs, sigAlg) if err != nil { return nil, err } // Quote key info. request.QuoteKeyInfo = new(tpm2.QuoteKeyInfoMessage) request.QuoteKeyInfo.Name = tpm2QuoteName request.QuoteKeyInfo.PublicKey = new(tpm2.PublicKeyMessage) request.QuoteKeyInfo.PublicKey.RsaKey = new(tpm2.RsaPublicKeyMessage) request.QuoteKeyInfo.PublicKey.RsaKey.KeyName = &keyName var encAlg string var hashAlg string if rsaQuoteParams.Enc_alg == tpm2.AlgTPM_ALG_RSA { encAlg = "rsa" } else { return nil, err } if rsaQuoteParams.Hash_alg == tpm2.AlgTPM_ALG_SHA1 { hashAlg = "sha1" } else if rsaQuoteParams.Hash_alg == tpm2.AlgTPM_ALG_SHA256 { hashAlg = "sha256" } else { return nil, err } request.QuoteKeyInfo.PublicKey.KeyType = &encAlg request.QuoteKeyInfo.PublicKey.RsaKey.BitModulusSize = &modSize request.QuoteKeyInfo.PublicKey.RsaKey.Modulus = rsaQuoteParams.Modulus request.QuoteSignAlg = &encAlg request.QuoteSignHashAlg = &hashAlg request.ProgramKey = new(tpm2.ProgramKeyParameters) request.ProgramKey.ProgramName = &keyName request.ProgramKey.ProgramKeyType = &encAlg request.ProgramKey.ProgramBitModulusSize = &modSize request.ProgramKey.ProgramKeyModulus = rsaQuoteParams.Modulus request.QuotedBlob = attest request.QuoteSignature = sig return request, 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 }