func Load(path string) (tao.Guard, error) { s, err := NewScanner(path) if err != nil { return nil, err } t := s.NextLine() var g tao.Guard switch t { case "acl": g = tao.NewACLGuard() case "datalog": g = tao.NewTemporaryDatalogGuard() case "": return nil, fmt.Errorf("%s: first line must specify 'datalog' or 'acl'\n", path) default: return nil, fmt.Errorf("%s: expected 'datalog' or 'acl', found %q\n", path, t) } for line := s.NextLine(); line != ""; line = s.NextLine() { err = g.AddRule(line) if err != nil { return nil, fmt.Errorf("%s: %s; processing this line:\n> %s\n", path, err, line) } } return g, nil }
// Checks the following: // (1) cert is valid according to one of the rootCerts. // (2) the subject key of cert corresponds to kPrin. // (3) the subject CommonName of cert is allowed by guard. func validateEndorsementCertificate(cert *x509.Certificate, guard tao.Guard, kPrin *auth.Prin, rootCerts *x509.CertPool) error { verifyOptions := x509.VerifyOptions{Roots: rootCerts} _, err := cert.Verify(verifyOptions) if err != nil { return err } var hwPublicKey *rsa.PublicKey hwPublicKey, ok := cert.PublicKey.(*rsa.PublicKey) if !ok { key, ok := cert.PublicKey.(rsa.PublicKey) if !ok { return errors.New("endorsement cert does not contain a valid RSA public key") } hwPublicKey = &key } ek, err := x509.MarshalPKIXPublicKey(hwPublicKey) if err != nil { return err } hashedCertKey := sha256.Sum256(ek) if kPrin.Type != "tpm" && kPrin.Type != "tpm2" { return errors.New("key principal to be endorsed is not a TPM key, but it's expected to be") } hashedBytes, ok := kPrin.KeyHash.(auth.Bytes) if !ok { return errors.New("key principal to be endorsed does not have bytes as its auth.Term") } if !bytes.Equal(hashedBytes, hashedCertKey[:]) { return errors.New(fmt.Sprintf( "endorsement cert endorses %v but needs to endorse %v", hashedCertKey, hashedBytes)) } machinePrin := auth.Prin{ Type: "MachineInfo", KeyHash: auth.Str(cert.Subject.CommonName), } if !guard.IsAuthorized(machinePrin, "Root", []string{}) { return errors.New( "machine endorsed by certificate is not authorized by policy") } return nil }
// Checks the following: // (1) the endorsement attestation is valid // (2) the key being endorsed is kPrin // (3) the subject being endorsed is a trusted host // Finally the function returns the key principal signing the endorsement func validateEndorsementAttestation(attestation *tao.Attestation, guard tao.Guard, kPrin *auth.Prin) (*auth.Prin, error) { saysStatement, err := attestation.Validate() if err != nil { return nil, err } _, key, host, err := parseSaysStatement(&saysStatement) if err != nil { return nil, err } if !key.Identical(kPrin) { return nil, errors.New("endorsement does not endorse signer of (previous) attestaton") } if !guard.IsAuthorized(*host, "Host", []string{}) { return nil, errors.New("endorsement host not authorized to run in this domain") } signerType := attestation.SignerType if signerType == nil { return nil, errors.New("endorsement chain has attestation with missing SignerType") } signerPrin := auth.NewPrin(*signerType, attestation.SignerKey) return &signerPrin, nil }
// 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 }