Example #1
0
// TruncateAttestation cuts off a delegation chain at its "Program" subprincipal
// extension and replaces its prefix with the given key principal. It also
// returns the PrinExt that represents exactly the program hash.
func TruncateAttestation(kprin auth.Prin, a *Attestation) (auth.Says, auth.PrinExt, error) {
	// This attestation must have a top-level delegation to a key. Return an
	// authorization for this program rooted in the policy key. I don't like
	// this, since it seems like it's much riskier, since this doesn't say
	// anything about the context in which the program is running. Fortunately,
	// local policy rules: if a peer won't accept this cert, then the other
	// program will have to fall back on the longer attestation.
	stmt, err := auth.UnmarshalForm(a.SerializedStatement)
	if err != nil {
		return auth.Says{}, auth.PrinExt{}, err
	}

	says, ok := stmt.(auth.Says)
	if !ok {
		return auth.Says{}, auth.PrinExt{}, fmt.Errorf("the serialized statement must be a says")
	}
	// Replace the message with one that uses the new principal, taking the last
	// Program subprinicpal, and all its following elements. It should say:
	// policyKey.Program(...)... says key(...) speaksfor
	// policyKey.Program(...)..., signed policyKey.
	sf, ok := says.Message.(auth.Speaksfor)
	if !ok {
		return auth.Says{}, auth.PrinExt{}, fmt.Errorf("the message in the statement must be a speaksfor")
	}

	delegator, ok := sf.Delegator.(auth.Prin)
	if !ok {
		return auth.Says{}, auth.PrinExt{}, fmt.Errorf("the delegator must be a principal")
	}

	var prog auth.PrinExt
	found := false
	for _, sprin := range delegator.Ext {
		if !found && (sprin.Name == "Program") {
			found = true
			prog = sprin
		}

		if found {
			kprin.Ext = append(kprin.Ext, sprin)
		}
	}

	// TODO(tmroeder): make sure that the delegate is a key and is not, e.g.,
	// the policy key.
	truncSpeaksfor := auth.Speaksfor{
		Delegate:  sf.Delegate,
		Delegator: kprin,
	}
	truncSays := auth.Says{
		Speaker:    kprin,
		Time:       says.Time,
		Expiration: says.Expiration,
		Message:    truncSpeaksfor,
	}

	return truncSays, prog, nil
}
Example #2
0
// RuleDebugString returns a debug string for the ith policy rule, if it exists.
func (g *DatalogGuard) RuleDebugString(i int) string {
	if i < 0 || i >= len(g.db.Rules) {
		return ""
	}
	rule := g.db.Rules[i]
	r, err := auth.UnmarshalForm(rule)
	if err != nil {
		return ""
	}
	return r.ShortString()
}
Example #3
0
// ReloadIfModified reads all persistent policy data from disk if the file
// timestamp is more recent than the last time it was read.
func (g *DatalogGuard) ReloadIfModified() error {
	if g.Key == nil {
		return nil
	}
	file, err := os.Open(g.Config.GetSignedRulesPath())
	if err != nil {
		return err
	}
	defer file.Close()

	// before parsing, check the timestamp
	info, err := file.Stat()
	if err != nil {
		return err
	}
	if !info.ModTime().After(g.modTime) {
		return nil
	}

	serialized, err := ioutil.ReadAll(file)
	if err != nil {
		return err
	}
	var sdb SignedDatalogRules
	if err := proto.Unmarshal(serialized, &sdb); err != nil {
		return err
	}
	if ok, err := g.Key.Verify(sdb.SerializedRules, DatalogRulesSigningContext, sdb.Signature); !ok {
		if err != nil {
			return err
		}
		return newError("datalog rule signature did not verify")
	}
	var db DatalogRules
	if err := proto.Unmarshal(sdb.SerializedRules, &db); err != nil {
		return err
	}
	// Only clear the rules set, since g.assert already skips datalog rules that
	// are already present in the engine.
	g.db.Rules = nil
	g.modTime = info.ModTime()
	for _, rule := range db.Rules {
		r, err := auth.UnmarshalForm(rule)
		if err != nil {
			return err
		}
		err = g.assert(r)
		if err != nil {
			return err
		}
	}
	return nil
}
Example #4
0
// AddEndorsements reads the SerializedEndorsements in an attestation and adds
// the ones that are predicates signed by the policy key.
func AddEndorsements(guard Guard, a *Attestation, v *Verifier) error {
	// Before validating against the guard, check to see if there are any
	// predicates endorsed by the policy key. This allows truncated principals
	// to get the Tao CA to sign a statement of the form
	// TrustedHash(ext.Program(...)).
	for _, e := range a.SerializedEndorsements {
		var ea Attestation
		if err := proto.Unmarshal(e, &ea); err != nil {
			return err
		}

		f, err := auth.UnmarshalForm(ea.SerializedStatement)
		if err != nil {
			return err
		}

		says, ok := f.(auth.Says)
		if !ok {
			return fmt.Errorf("a serialized endorsement must be an auth.Says")
		}

		// TODO(tmroeder): check that this endorsement hasn't expired.
		pred, ok := says.Message.(auth.Pred)
		if !ok {
			return fmt.Errorf("the message in an endorsement must be a predicate")
		}

		signerPrin, err := auth.UnmarshalPrin(ea.Signer)
		if err != nil {
			return err
		}

		if !signerPrin.Identical(says.Speaker) {
			return fmt.Errorf("the speaker of an endorsement must be the signer")
		}
		if !v.ToPrincipal().Identical(signerPrin) {
			return fmt.Errorf("the signer of an endorsement must be the policy key")
		}
		if ok, err := v.Verify(ea.SerializedStatement, AttestationSigningContext, ea.Signature); (err != nil) || !ok {
			return fmt.Errorf("the signature on an endorsement didn't pass verification")
		}

		return guard.AddRule(pred.String())
	}

	return nil
}
Example #5
0
// Create a Program Public/Private key.
func CreateSigningKey(t tao.Tao) (*tao.Keys, []byte, error) {

	self, err := t.GetTaoName()
	k, err := tao.NewTemporaryKeys(tao.Signing)
	if k == nil || err != nil {
		return nil, nil, errors.New("Can't generate signing key")
	}

	publicString := strings.Replace(self.String(), "(", "", -1)
	publicString = strings.Replace(publicString, ")", "", -1)

	// publicString is now a canonicalized Tao Principal name
	us := "US"
	google := "Google"
	details := tao.X509Details{
		Country:      &us,
		Organization: &google,
		CommonName:   &publicString}
	subjectname := tao.NewX509Name(&details)

	derCert, err := k.SigningKey.CreateSelfSignedDER(subjectname)
	if err != nil {
		return nil, nil, errors.New("Can't self sign cert\n")
	}
	cert, err := x509.ParseCertificate(derCert)
	if err != nil {
		return nil, nil, err
	}

	// Construct statement: "ProgramKey (new key) speaksfor Principal Name"
	// ToPrincipal retrieves key's Tao Principal Name.
	k.Cert = cert
	s := &auth.Speaksfor{
		Delegate:  k.SigningKey.ToPrincipal(),
		Delegator: self}
	if s == nil {
		return nil, nil, errors.New("Can't produce speaksfor")
	}

	// Sign attestation statement
	k.Delegation, err = t.Attest(&self, nil, nil, s)
	if err != nil {
		return nil, nil, err
	}
	_, _ = auth.UnmarshalForm(k.Delegation.SerializedStatement)
	return k, derCert, nil
}
Example #6
0
func NewMarshalledDatalogGuard(ser []byte) (*DatalogGuard, error) {
	var db DatalogRules
	if err := proto.Unmarshal(ser, &db); err != nil {
		return nil, err
	}
	g := NewTemporaryDatalogGuard().(*DatalogGuard)
	for _, rule := range db.Rules {
		r, err := auth.UnmarshalForm(rule)
		if err != nil {
			return nil, err
		}
		err = g.assert(r)
		if err != nil {
			return nil, err
		}
	}
	return g, nil
}
// Attest is the server stub for Tao.Attest.
func (server linuxHostTaoServerStub) Attest(r *RPCRequest, s *RPCResponse) error {
	stmt, err := auth.UnmarshalForm(r.Data)
	if err != nil {
		return err
	}
	var issuer *auth.Prin
	if r.Issuer != nil {
		p, err := auth.UnmarshalPrin(r.Issuer)
		if err != nil {
			return err
		}
		issuer = &p
	}
	a, err := server.lh.Attest(server.child, issuer, r.Time, r.Expiration, stmt)
	if err != nil {
		return err
	}
	s.Data, err = proto.Marshal(a)
	return err
}
Example #8
0
func (g *DatalogGuard) findRule(f auth.Form) (string, int, error) {
	rule, err := g.formToDatalogRule(f)
	if err != nil {
		return "", -1, err
	}
	for i, ser := range g.db.Rules {
		f2, err := auth.UnmarshalForm(ser)
		if err != nil {
			continue
		}
		rule2, err := g.formToDatalogRule(f2)
		if err != nil {
			continue
		}
		if rule == rule2 {
			return rule, i, nil
		}
	}
	return rule, -1, nil
}
Example #9
0
// RequestTruncatedAttestation connects to a CA instance, sends the attestation
// for an X.509 certificate, and gets back a truncated attestation with a new
// principal name based on the policy key.
func RequestTruncatedAttestation(network, addr string, keys *Keys, v *Verifier) (*Attestation, error) {
	a, err := RequestAttestation(network, addr, keys, v)
	if err != nil {
		return nil, err
	}

	truncStmt, err := auth.UnmarshalForm(a.SerializedStatement)
	if err != nil {
		return nil, err
	}

	says, _, err := TruncateAttestation(v.ToPrincipal(), keys.Delegation)
	if err != nil {
		return nil, err
	}

	if !IdenticalDelegations(says, truncStmt) {
		return nil, fmt.Errorf("the statement returned by the TaoCA was different than what we expected")
	}

	return a, nil
}
Example #10
0
// EstablishCert contacts a CA to get a certificate signed by the policy key. It
// replaces the current delegation and cert on k with the new delegation and
// cert from the response.
func EstablishCert(network, addr string, k *tao.Keys, v *tao.Verifier) error {
	na, err := tao.RequestAttestation(network, addr, k, v)
	if err != nil {
		return err
	}

	k.Delegation = na
	pa, err := auth.UnmarshalForm(na.SerializedStatement)
	if err != nil {
		return err
	}

	// Parse the received statement.
	var saysStatement *auth.Says
	if ptr, ok := pa.(*auth.Says); ok {
		saysStatement = ptr
	} else if val, ok := pa.(auth.Says); ok {
		saysStatement = &val
	}
	sf, ok := saysStatement.Message.(auth.Speaksfor)
	if ok != true {
		return errors.New("says doesn't have speaksfor message")
	}

	kprin, ok := sf.Delegate.(auth.Term)
	if ok != true {
		return errors.New("speaksfor message doesn't have Delegate")
	}
	newCert := auth.Bytes(kprin.(auth.Bytes))
	cert, err := x509.ParseCertificate(newCert)
	if err != nil {
		return err
	}
	k.Cert["default"] = cert

	return nil
}
Example #11
0
// Reload requests the policy from the remote TaoCA and instantiates a
// new guard.
func (cg *CachedGuard) Reload() error {
	switch cg.guardType {
	case Datalog:
		datalogGuard := NewDatalogGuard(cg.verifier)
		db, err := RequestDatalogRules(cg.network, cg.address, cg.verifier)
		if err != nil {
			return err
		}
		datalogGuard.db = *db
		for _, marshaledForm := range db.Rules {
			f, _ := auth.UnmarshalForm(marshaledForm)
			rule, _, err := datalogGuard.findRule(f)
			if err != nil {
				return err
			}
			datalogGuard.dl.Assert(rule)
		}
		cg.guard = datalogGuard
	case ACLs: // TODO(cjpatton)
		return errors.New("CacheGuard: ACL set reload not implemented")
	}
	cg.timeUpdated = time.Now().Unix()
	return nil
}
Example #12
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())
	}
}
// First return is terminate flag.
func DomainRequest(conn net.Conn, policyKey *tao.Keys, guard tao.Guard) (bool, error) {
	fmt.Printf("DomainRequest\n")
	log.Printf("DomainRequest\n")

	// Expect a request with attestation from client.
	ms := util.NewMessageStream(conn)
	var request domain_policy.DomainCertRequest
	err := ms.ReadMessage(&request)
	if err != nil {
		log.Printf("DomainRequest: Couldn't read attestation from channel:", err)
		log.Printf("\n")
		return false, err
	}

	var a tao.Attestation
	err = proto.Unmarshal(request.Attestation, &a)
	if request.KeyType == nil {
		log.Printf("Domain: Empty key type")
		return false, errors.New("Empty key type")
	}
	if *request.KeyType != "ECDSA" {
		log.Printf("Domain: bad key type")
		return false, errors.New("Domain: bad key type")
	}
	subjectPublicKey, err := domain_policy.GetEcdsaKeyFromDer(request.SubjectPublicKey)
	if err != nil {
		log.Printf("DomainRequest: can't get key from der")
		return false, errors.New("DomainRequest: can't get key from der")
	}

	// Get hash of the public key subject.
	serializedKey, err := domain_policy.SerializeEcdsaKeyToInternalName(subjectPublicKey.(*ecdsa.PublicKey))
	if err != nil || serializedKey == nil {
		log.Printf("DomainRequest: Can't serialize key to internal format\n")
		return false, errors.New("DomainRequest: Can't serialize key to internal format")
	}
	subjectKeyHash := domain_policy.GetKeyHash(serializedKey)

	peerCert := conn.(*tls.Conn).ConnectionState().PeerCertificates[0]
	err = tao.ValidatePeerAttestation(&a, peerCert, guard)
	/*
	   	if err != nil {
	   		log.Printf("Domain: RequestCouldn't validate peer attestation:", err)
	   		return false, err
	   	}
	   fmt.Printf("DomainRequest, peerCert: %x\n", peerCert)
	*/

	// Sign cert

	// Get Program name and key info from delegation.
	f, err := auth.UnmarshalForm(a.SerializedStatement)
	if err != nil {
		log.Printf("DomainRequest: Can't unmarshal a.SerializedStatement\n")
		return false, err
	}

	var saysStatement *auth.Says
	if ptr, ok := f.(*auth.Says); ok {
		saysStatement = ptr
	} else if val, ok := f.(auth.Says); ok {
		saysStatement = &val
	}
	sf, ok := saysStatement.Message.(auth.Speaksfor)
	if ok != true {
		log.Printf("DomainRequest: says doesnt have speaksfor message\n")
		return false, err
	}
	// this in the new key principal
	clientKeyPrincipal, ok := sf.Delegate.(auth.Prin)
	if ok != true {
		log.Printf("DomainRequest: speaksfor Delegate is not auth.Prin\n")
		return false, err
	}

	programPrincipal, ok := sf.Delegator.(auth.Prin)
	if ok != true {
		log.Printf("DomainRequest: Can't get subject principal\n")
		return false, errors.New("Can't get principal name from verifier")
	}
	programPrincipalName := programPrincipal.String()
	verified := IsAuthenticationValid(&programPrincipalName)
	if !verified {
		log.Printf("DomainRequest: name verification failed\n")
		return false, err
	}
	fmt.Printf("\nSimpleDomainService: key principal: %s, program principal: %s\n", clientKeyPrincipal, programPrincipalName)

	// Is the delegate the same key as was presented in the name in the request?
	namedHash := clientKeyPrincipal.KeyHash.(auth.Bytes)
	fmt.Printf("\nkeyhash: %x\n", namedHash)
	if bytes.Compare(subjectKeyHash[:], namedHash) != 0 {
		log.Printf("DomainRequest: named hash is wrong\n")
		fmt.Printf("DomainRequest: named hash is wrong, named: %x, computed: %x\n",
			namedHash, subjectKeyHash)
		return false, errors.New("DomainRequest: named hash is wrong")
	}

	// Sign program certificate.

	notBefore := time.Now()
	validFor := 365 * 24 * time.Hour
	notAfter := notBefore.Add(validFor)

	us := "US"
	issuerName := "Google"
	localhost := "localhost"
	x509SubjectName := &pkix.Name{
		Organization:       []string{programPrincipalName},
		OrganizationalUnit: []string{programPrincipalName},
		CommonName:         localhost,
		Country:            []string{us},
	}
	x509IssuerName := &pkix.Name{
		Organization:       []string{issuerName},
		OrganizationalUnit: []string{issuerName},
		CommonName:         localhost,
		Country:            []string{us},
	}

	// issuerName := tao.NewX509Name(&details)
	SerialNumber = SerialNumber + 1
	var sn big.Int
	certificateTemplate := x509.Certificate{
		SerialNumber: &sn,
		Issuer:       *x509IssuerName,
		Subject:      *x509SubjectName,
		NotBefore:    notBefore,
		NotAfter:     notAfter,
		KeyUsage: x509.KeyUsageCertSign |
			x509.KeyUsageKeyAgreement | x509.KeyUsageDigitalSignature,
	}

	clientCert, err := x509.CreateCertificate(rand.Reader, &certificateTemplate,
		policyKey.Cert, subjectPublicKey,
		policyKey.SigningKey.GetSigner())
	if err != nil {
		fmt.Printf("Can't create client certificate: ", err, "\n")
		return false, err
	}

	zero := int32(0)
	var ra domain_policy.DomainCertResponse
	ra.Error = &zero
	ra.SignedCert = clientCert

	// Add cert chain (just policy cert for now).
	ra.CertChain = append(ra.CertChain, policyKey.Cert.Raw)

	_, err = ms.WriteMessage(&ra)
	if err != nil {
		log.Printf("DomainRequest: Couldn't return the attestation on the channel: ", err)
		log.Printf("\n")
		return false, err
	}
	return false, nil
}
Example #14
0
// First return is terminate flag.
func handleRequest(conn net.Conn, policyKey *tao.Keys, guard tao.Guard) error {
	// Expect an attestation from the client.
	ms := util.NewMessageStream(conn)
	var a tao.Attestation
	if err := ms.ReadMessage(&a); err != nil {
		return err
	}

	peerCert := conn.(*tls.Conn).ConnectionState().PeerCertificates[0]
	p, err := tao.ValidatePeerAttestation(&a, peerCert)
	if err != nil {
		return err
	}
	// TODO(kwalsh) most of this duplicates the work of tao.Conn
	if !guard.IsAuthorized(p, "Execute", nil) {
		return fmt.Errorf("peer is not authorized to execute, hence not authorized to connect either")
	}

	// Sign cert and put it in attestation statement
	// a consists of serialized statement, sig and SignerInfo
	// a is a says speaksfor, Delegate of speaksfor is cert and should be DER encoded

	// Get underlying says
	f, err := auth.UnmarshalForm(a.SerializedStatement)
	if err != nil {
		return err
	}

	var saysStatement *auth.Says
	if ptr, ok := f.(*auth.Says); ok {
		saysStatement = ptr
	} else if val, ok := f.(auth.Says); ok {
		saysStatement = &val
	}
	sf, ok := saysStatement.Message.(auth.Speaksfor)
	if ok != true {
		return fmt.Errorf("keynegoserver: says doesn't have a speaksfor message\n")
	}

	kprin, ok := sf.Delegate.(auth.Prin)
	if ok != true {
		return fmt.Errorf("keynegoserver: speaksfor Delegate is not auth.Prin\n")
	}
	subjectPrin, ok := sf.Delegator.(auth.Prin)
	if ok != true {
		return fmt.Errorf("keynegoserver: can't get subject principal\n")
	}
	subjectName := subjectPrin.String()
	details := &tao.X509Details{
		Country:            proto.String("US"),
		Organization:       proto.String("Google"),
		OrganizationalUnit: proto.String(subjectName),
		CommonName:         proto.String("localhost"),
	}
	subjectname := tao.NewX509Name(details)
	SerialNumber = SerialNumber + 1
	verifier, err := tao.FromPrincipal(kprin)
	if err != nil {
		return errors.New("can't get principal from kprin")
	}
	template := policyKey.SigningKey.X509Template(subjectname)
	template.IsCA = false
	clientCert, err := policyKey.CreateSignedX509(verifier, template, "default")
	if err != nil {
		return fmt.Errorf("keynegoserver: can't create client certificate: %s\n", err)
	}
	clientDERCert := clientCert.Raw
	err = ioutil.WriteFile("ClientCert", clientDERCert, os.ModePerm)

	nowTime := time.Now().UnixNano()
	expireTime := time.Now().AddDate(1, 0, 0).UnixNano()
	// Replace self signed cert in attest request
	newSpeaksFor := &auth.Speaksfor{
		Delegate:  auth.Bytes(clientDERCert),
		Delegator: sf.Delegator,
	}
	keyNegoSays := auth.Says{
		Speaker:    policyKey.SigningKey.ToPrincipal(),
		Time:       &nowTime,
		Expiration: &expireTime,
		Message:    newSpeaksFor,
	}

	delegator, ok := sf.Delegator.(auth.Prin)
	if !ok {
		return fmt.Errorf("keynegoserver: the delegator must be a principal")
	}
	found := false
	for _, sprin := range delegator.Ext {
		if !found && (sprin.Name == "Program") {
			found = true
		}
		if found {
			kprin.Ext = append(kprin.Ext, sprin)
		}
	}
	ra, err := tao.GenerateAttestation(policyKey.SigningKey, nil, keyNegoSays)
	if err != nil {
		return fmt.Errorf("Couldn't attest to the new says statement: %s", err)
	}

	if _, err := ms.WriteMessage(ra); err != nil {
		return fmt.Errorf("Couldn't return the attestation on the channel: %s", err)
	}

	return nil
}
Example #15
0
// 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())
	}
}
Example #16
0
// 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
}
Example #17
0
// This function performs the following checks on a secret disclosure directive.
// (1) the directive signature is valid with respect to signerKey of directive
// (2) Either
//       - policyKey matches the signerKey of directive
//       - directive cert is a valid program cert (signed by policyKey) certifying the signerKey
//         of directive as belonging to 'delegator'
// (3) the directive message is a statement of the form:
//         'policyKey/'delegator' says delegate can read protectedObjectId'
//     where delegate is a Tao Principal and protectedObjectId is a (serialized) protected
//     object message id.
func VerifySecretDisclosureDirective(policyKey *tao.Keys, directive *DirectiveMessage) (*auth.Prin,
	*auth.Prin, *string, *po.ObjectIdMessage, error) {

	// Check type of directive
	if directive.Type == nil || *(directive.Type) != DirectiveMessage_SECRET_DISCLOSURE {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: directive not of secret disclosure type.")
	}

	var verifier *tao.Verifier
	var delegatorStr string
	// Check directive signer matches policy key.
	if bytes.Compare(
		auth.Marshal(policyKey.SigningKey.ToPrincipal()), directive.GetSigner()) == 0 {
		verifier = policyKey.SigningKey.GetVerifier()
		delegatorStr = verifier.ToPrincipal().String()

	} else {
		// Check if program cert is valid, signed by policy key,
		// cert public key matches signer and cert name matches speaker
		// of says statement.
		cert, err := x509.ParseCertificate(directive.Cert)
		if err != nil {
			return nil, nil, nil, nil, errors.New(
				"error parsing directive program cert")
		}
		rootCert := x509.NewCertPool()
		rootCert.AddCert(policyKey.Cert)
		verifyOptions := x509.VerifyOptions{Roots: rootCert}
		_, err = cert.Verify(verifyOptions)
		if err != nil {
			return nil, nil, nil, nil, errors.New(
				"program cert not valid")
		}
		verifier, err = tao.FromX509(cert)
		delegatorStr = cert.Subject.CommonName
		if err != nil {
			return nil, nil, nil, nil, err
		}
		if bytes.Compare(auth.Marshal(verifier.ToPrincipal()), directive.GetSigner()) != 0 {
			return nil, nil, nil, nil, errors.New(
				"secret_disclosure: directive signer doesn't match program key.")
		}
	}

	// Verify signature.
	ok, err := verifier.Verify(directive.GetSerializedStatement(), SigningContext,
		directive.GetSignature())
	if err != nil {
		return nil, nil, nil, nil, err
	}
	if !ok {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive signature check failed.")
	}

	// Validate and return statement.
	statement, err := auth.UnmarshalForm(directive.GetSerializedStatement())
	if err != nil {
		return nil, nil, nil, nil, err
	}
	var saysStatement *auth.Says
	if ptr, ok := statement.(*auth.Says); ok {
		saysStatement = ptr
	} else if val, ok := statement.(auth.Says); ok {
		saysStatement = &val
	} else {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive statement not a 'Says'")
	}
	stmtSpeaker, ok := saysStatement.Speaker.(auth.Prin)
	if !ok {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive speaker not a 'Prin'")
	}
	if stmtSpeaker.String() != delegatorStr {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: directive statement speaker does not match signer")
	}
	pred, ok := saysStatement.Message.(auth.Pred)
	if !ok {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive message not a 'Pred'")
	}
	predName := pred.Name
	if predName == "" {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive predicate name is empty")
	}
	if len(pred.Arg) != 2 {
		return nil, nil, nil, nil,
			errors.New("secret_disclosure: directive predicate doesn't have 2 terms")
	}
	delegateName, ok := pred.Arg[0].(auth.Prin)
	if !ok {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: directive delegateName Term not of type auth.Prin.")
	}
	serializedObjId, ok := pred.Arg[1].(auth.Bytes)
	if !ok {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: directive ObjId Term not of type []byte.")
	}
	protectedObjId := po.ObjectIdMessage{}
	err = proto.Unmarshal(serializedObjId, &protectedObjId)
	if err != nil {
		return nil, nil, nil, nil, errors.New(
			"secret_disclosure: error deserializing protected ObjId.")
	}
	return &stmtSpeaker, &delegateName, &predName, &protectedObjId, nil
}