// Establishes the Tao Channel for a client using the Program Key. // This program does all the standard client side channel negotiation. // After negotiation is complete. ms is the bi-directional confidentiality and // integrity protected channel. OpenTaoChannel returns the stream (ms) for subsequent reads // and writes as well as the server's Tao Principal Name. func OpenTaoChannel(programObject *TaoProgramData, serverAddr *string) ( *util.MessageStream, *string, error) { // Parse policy cert and make it the root of our // hierarchy for verifying Tao Channel peer. policyCert, err := x509.ParseCertificate(programObject.PolicyCert) if err != nil { return nil, nil, errors.New("OpenTaoChannel: Can't ParseCertificate") } pool := x509.NewCertPool() pool.AddCert(policyCert) // Open the Tao Channel using the Program key. tlsc, err := tao.EncodeTLSCert(&programObject.ProgramKey) if err != nil { log.Fatalln("OpenTaoChannel, encode error: ", err) } // TODO(manferdelli): Replace this with tao.Dial conn, err := tls.Dial("tcp", *serverAddr, &tls.Config{ RootCAs: pool, Certificates: []tls.Certificate{*tlsc}, InsecureSkipVerify: false, }) if err != nil { fmt.Printf("OpenTaoChannel: Can't establish channel ", err, "\n") return nil, nil, errors.New("OpenTaoChannel: Can't establish channel") } peerName := policyCert.Subject.OrganizationalUnit[0] // Stream for Tao Channel. ms := util.NewMessageStream(conn) return ms, &peerName, nil }
// This function sends a DomainServiceRequest of the type GET_CRL to the domain service, // and deserializes the response into a pkix.CertificateList containing the revoked certificates. func RequestCrl(network, addr string) (*pkix.CertificateList, error) { reqType := DomainServiceRequest_GET_CRL request := &DomainServiceRequest{ Type: &reqType} conn, err := net.Dial(network, addr) if err != nil { return nil, err } ms := util.NewMessageStream(conn) _, err = ms.WriteMessage(request) if err != nil { return nil, err } log.Printf("Sent crl request to Domain Service using network %s at address %s.", network, addr) var response DomainServiceResponse err = ms.ReadMessage(&response) if err != nil { return nil, err } log.Println("Got response from Domain Service.") if errStr := response.GetErrorMessage(); errStr != "" { return nil, errors.New(errStr) } parsedCrl, err := x509.ParseCRL(response.GetCrl()) return parsedCrl, err }
func HandleQuoteDomainRequest(conn net.Conn, policyKey *ecdsa.PrivateKey, derPolicyCert []byte) (bool, error) { log.Printf("HandleQuoteDomainRequest\n") // Expect a request with attestation from client. ms := util.NewMessageStream(conn) var request AttestCertRequest err := ms.ReadMessage(&request) if err != nil { log.Printf("HandleQuoteDomainRequest: Couldn't read attest request from channel") return false, err } resp, err := ProcessQuoteDomainRequest(request, policyKey, derPolicyCert) if err != nil { return false, err } _, err = ms.WriteMessage(resp) if err != nil { log.Printf("HandleQuoteDomainRequest: Couldn't return the attestation on the channel") log.Printf("\n") return false, err } return false, nil }
// This function packages a certificate revoke request into a DomainServiceRequest of type // REVOKE_CERTIFICATE and sends it to the domain service. It expects att to be an attestation // signed by the domain policy key with a statement of the form: // policyKey says revoke certificateSerialNumber func RequestRevokeCertificate(att *tao.Attestation, network, addr string) error { serAtt, err := proto.Marshal(att) if err != nil { return err } reqType := DomainServiceRequest_REVOKE_CERTIFICATE request := &DomainServiceRequest{ Type: &reqType, SerializedPolicyAttestation: serAtt} conn, err := net.Dial(network, addr) if err != nil { return err } ms := util.NewMessageStream(conn) _, err = ms.WriteMessage(request) if err != nil { return err } log.Printf("Sent cert revoke request to Domain Service using network %s at address %s.", network, addr) var response DomainServiceResponse err = ms.ReadMessage(&response) if err != nil { return err } log.Println("Got response from Domain Service.") if errStr := response.GetErrorMessage(); errStr != "" { return errors.New(errStr) } return nil }
// NewClientCodec returns a new rpc.ClientCodec using protobuf messages on conn. func NewClientCodec(conn io.ReadWriteCloser) rpc.ClientCodec { m, ok := conn.(*util.MessageStream) if !ok { // The given conn lacks framing, so add some. m = util.NewMessageStream(conn) } return &clientCodec{m, sync.Mutex{}} }
func serve(addr, fp string, cert []byte, signingKey *tao.Keys, policy *fileproxy.ProgramPolicy) error { m := fileproxy.NewResourceMaster(fp) policyCert, err := x509.ParseCertificate(cert) if err != nil { return err } conf, err := signingKey.TLSServerConfig(policyCert) if err != nil { return err } log.Println("fileserver listening") sock, err := tls.Listen("tcp", addr, conf) if err != nil { return err } for { // Accept and handle client connections one at a time. conn, err := sock.Accept() if err != nil { return err } var clientName string if err = conn.(*tls.Conn).Handshake(); err != nil { log.Printf("fileserver: couldn't perform handshake: %s\n", err) continue } peerCerts := conn.(*tls.Conn).ConnectionState().PeerCertificates if peerCerts == nil { log.Println("fileserver: couldn't get peer list") continue } peerCert := conn.(*tls.Conn).ConnectionState().PeerCertificates[0] if peerCert.Raw == nil { log.Println("fileserver: couldn't get peer name") continue } if peerCert.Subject.OrganizationalUnit != nil { clientName = peerCert.Subject.OrganizationalUnit[0] } log.Printf("fileserver: peer name: '%s'\n", clientName) ms := util.NewMessageStream(conn) // TODO(tmroeder): support multiple simultaneous clients. This // requires, e.g., adding locking to the ResourceMaster. if err := m.RunMessageLoop(ms, policy); err != nil { log.Printf("fileserver: failed to run message loop: %s\n", err) continue } log.Println("Finished handling the client messages") } }
func serve(serverAddr string, prin string, policyCert []byte, signingKey *tao.Keys, policy *fileproxy.ProgramPolicy, m *fileproxy.RollbackMaster) error { pc, err := x509.ParseCertificate(policyCert) if err != nil { return err } conf, err := signingKey.TLSServerConfig(pc) if err != nil { return err } log.Println("Rollback server listening") sock, err := tls.Listen("tcp", serverAddr, conf) if err != nil { return err } for { conn, err := sock.Accept() if err != nil { return err } var clientName string if err = conn.(*tls.Conn).Handshake(); err != nil { log.Println("TLS handshake failed") continue } peerCerts := conn.(*tls.Conn).ConnectionState().PeerCertificates if peerCerts == nil { log.Println("rollbackserver: can't get peer list") continue } peerCert := conn.(*tls.Conn).ConnectionState().PeerCertificates[0] if peerCert.Raw == nil { log.Println("rollbackserver: can't get peer name") continue } if peerCert.Subject.OrganizationalUnit == nil { log.Println("No OrganizationalUnit name in the peer certificate. Refusing the connection") continue } clientName = peerCert.Subject.OrganizationalUnit[0] ms := util.NewMessageStream(conn) // TODO(tmroeder): support multiple simultaneous clients. // Add this program as a rollback program. log.Printf("Adding a program with name '%s'\n", clientName) _ = m.AddRollbackProgram(clientName) if err := m.RunMessageLoop(ms, policy, clientName); err != nil { log.Printf("rollbackserver: failed to run message loop: %s\n", err) } } }
// Dial connects to a Tao TLS server, performs a TLS handshake, and verifies // the Attestation value of the server, checking that the server is authorized // to execute. If keys are provided (keys!=nil), then it sends an attestation // of its identity to the peer. func Dial(network, addr string, guard Guard, v *Verifier, keys *Keys) (net.Conn, error) { tlsConfig := &tls.Config{ RootCAs: x509.NewCertPool(), InsecureSkipVerify: true, } // Set up certificate for two-way authentication. if keys != nil { if keys.Cert == nil { return nil, fmt.Errorf("client: can't dial with an empty client certificate\n") } tlsCert, err := EncodeTLSCert(keys) if err != nil { return nil, err } tlsConfig.Certificates = []tls.Certificate{*tlsCert} } conn, err := tls.Dial(network, addr, tlsConfig) if err != nil { return nil, err } ms := util.NewMessageStream(conn) // Two-way Tao handshake: send client delegation. if keys != nil { if _, err = ms.WriteMessage(keys.Delegation); err != nil { conn.Close() return nil, err } } // Tao handshake: read server delegation. var a Attestation if err := ms.ReadMessage(&a); err != nil { conn.Close() return nil, err } if err := AddEndorsements(guard, &a, v); err != nil { conn.Close() return nil, err } // Validate the peer certificate according to the guard. peerCert := conn.ConnectionState().PeerCertificates[0] if err := ValidatePeerAttestation(&a, peerCert, guard); err != nil { conn.Close() return nil, err } return conn, nil }
// RequestDomainServiceCert requests the signed Program // Certificate from simpledomainservice. // TODO: This needs to change in a way that is tao supplier dependent. // For tpm2 we need the ekCert and the tao and we need the data // for ActivateCredential. // For tpm1.2, we need the aikCert. func RequestDomainServiceCert(network, addr string, requesting_key *tao.Keys, v *tao.Verifier) (*domain_policy.DomainCertResponse, error) { // Note requesting program key contains a self-signed cert to open channel. if requesting_key.Cert == nil { return nil, errors.New("RequestDomainServiceCert: Can't dial with an empty client certificate") } tlsCert, err := tao.EncodeTLSCert(requesting_key) if err != nil { return nil, err } conn, err := tls.Dial(network, addr, &tls.Config{ RootCAs: x509.NewCertPool(), Certificates: []tls.Certificate{*tlsCert}, InsecureSkipVerify: true, }) if err != nil { return nil, err } defer conn.Close() var request domain_policy.DomainCertRequest request.Attestation, err = proto.Marshal(requesting_key.Delegation) signer := requesting_key.SigningKey.GetSigner() if signer == nil { return nil, err } key_type := "ECDSA" request.KeyType = &key_type request.SubjectPublicKey, err = domain_policy.GetPublicDerFromEcdsaKey(&signer.PublicKey) if err != nil { return nil, err } // Tao handshake: send client delegation. ms := util.NewMessageStream(conn) _, err = ms.WriteMessage(&request) if err != nil { return nil, err } // Read the new cert var response domain_policy.DomainCertResponse err = ms.ReadMessage(&response) if err != nil { return nil, err } return &response, nil }
// Handshake performs a Tao (and TLS) handshake. This occurs only once, before // the first read or write. Users don't usually need to call this directly, // since other functions call this as necessary. func (conn *Conn) Handshake() error { // Tao handshake protocol: // 0. TLS handshake (executed automatically on first message) // 1. Client -> Server: "delgation", Tao delegation for X.509 certificate. // 2. Server: checks for a Tao-authorized program. // 3. Server -> Client: "delgation", Tao delegation for X.509 certificate. // 4. Client: checks for a Tao-authorized program. // // Alternate steps 1 and 2 if client authentication is not needed: // 1'. Client -> Server: "anonymous" // 2'. Server: checks if policy allows anonymous connections // // Alternate steps 3 and 4 if server authentication is not needed: // 3'. Server -> Client: "anonymous" // 4'. Client: checks if policy allows anonymous connections if !conn.handshakeComplete { if conn.T != nil { conn.T.Start() } // Use a new framing stream on the underlying tls to avoid recursing. ms := util.NewMessageStream(conn.Conn) if conn.isServer { conn.sendCredentials(ms) if conn.T != nil { conn.T.Sample("sent tao creds") } conn.recvCredentials(ms) } else { conn.sendCredentials(ms) if conn.T != nil { conn.T.Sample("sent tao creds") } conn.recvCredentials(ms) } conn.handshakeComplete = true conn.handshakeErr = ms.Err() if conn.handshakeErr != nil { conn.Close() conn.SetErr(conn.handshakeErr) } if conn.T != nil { conn.T.Sample("done tao handshake") } } return conn.handshakeErr }
// RequestACLSet requests the policy from a TaoCA running an ACLGuard. Verify // the signature with the public policy key `v`. func RequestACLSet(network, addr string, v *Verifier) (*ACLSet, error) { // Establish connection wtih the CA. conn, err := net.Dial(network, addr) if err != nil { return nil, err } defer conn.Close() // Create a CArequest. req := &CARequest{ Type: CAType_ACL_POLICY.Enum(), } // Send request. ms := util.NewMessageStream(conn) if _, err = ms.WriteMessage(req); err != nil { return nil, err } // Receive response. var resp CAResponse if err := ms.ReadMessage(&resp); err != nil { return nil, err } // Verify signature. ok, err := v.Verify(resp.SignedAclSet.SerializedAclset, ACLGuardSigningContext, resp.SignedAclSet.Signature) if !ok { return nil, errVerifyFailed } else if err != nil { return nil, err } if *resp.Type != CAType_ACL_POLICY { return nil, errInvalidResponse } var db ACLSet if err := proto.Unmarshal(resp.SignedAclSet.SerializedAclset, &db); err != nil { return nil, err } return &db, nil }
// HandleCARequest checks a request from a program and responds with a truncated // delegation signed by the policy key. func HandleCARequest(conn net.Conn, s *Signer, guard Guard) { defer conn.Close() // TODO(cjpatton) This should be managed by calling function. // Get request. ms := util.NewMessageStream(conn) var req CARequest if err := ms.ReadMessage(&req); err != nil { fmt.Fprintln(os.Stderr, "Couldn't read from channel:", err) return } resp := respond(&req, s, guard) if _, err := ms.WriteMessage(resp); err != nil { fmt.Fprintln(os.Stderr, "Couldn't write to the channel:", err) } }
// RequestDomainQuoteCert requests the Quote Cert func RequestDomainQuoteCert(network, addr string, endorsementCert []byte, tpmDevice io.ReadWriter, quoteHandle Handle, endorsementHandle Handle, taoName string, ownerPw string) ([]byte, error) { requestingKey, derChannelCert, err := CreateTemporaryChannelKey() if err != nil || requestingKey == nil { return nil, err } channelCert, err := x509.ParseCertificate(derChannelCert) if err != nil || channelCert == nil { return nil, err } // Contact domain service. conn, err := tls.Dial(network, addr, &tls.Config{ RootCAs: x509.NewCertPool(), // Certificates: []tls.Certificate{tls.Certificate(*channelCert)}, InsecureSkipVerify: true, }) if err != nil { return nil, err } defer conn.Close() // Build request. request, err := BuildAttestCertRequest(tpmDevice, quoteHandle, endorsementHandle, endorsementCert, taoName, ownerPw) if err != nil { return nil, err } // Send request ms := util.NewMessageStream(conn) _, err = ms.WriteMessage(request) if err != nil { return nil, err } // Read the new cert var response AttestCertResponse err = ms.ReadMessage(&response) if err != nil { return nil, err } return GetCertFromAttestResponse(tpmDevice, quoteHandle, endorsementHandle, ownerPw, response) }
// Accept waits for a connect, accepts it using the underlying Conn and checks // the attestations and the statement. func (l *anonymousListener) Accept() (net.Conn, error) { c, err := l.gl.Accept() if err != nil { return nil, err } // One-way Tao handshake Protocol: // 0. TLS handshake (executed automatically on first message) // 1. Server -> Client: Tao delegation for X.509 certificate. // 2. Client: checks for a Tao-authorized program. ms := util.NewMessageStream(c) if _, err := ms.WriteMessage(l.delegation); err != nil { c.Close() return nil, err } return c, nil }
func TestInvalidRequest(t *testing.T) { cal, err := net.Listen("tcp", "127.0.0.1:0") caAddr := cal.Addr() guard, keys, tmpDir, err := makeDatalogGuard() if err != nil { os.RemoveAll(tmpDir) t.Fatal(err) } defer os.RemoveAll(tmpDir) ch := make(chan bool) // Test an invalid request. go runTCCA(t, cal, keys, guard, ch) conn, err := net.Dial("tcp", caAddr.String()) if err != nil { t.Fatal("Failed to connect to TaoCA.") } defer conn.Close() // Bad CArequest, no value for bad_req.Attesation badReq := new(CARequest) badReq.Type = CAType_ATTESTATION.Enum() ms := util.NewMessageStream(conn) if _, err = ms.WriteMessage(badReq); err != nil { t.Logf("Failed to write to message stream: %s", err) } // Receive response. var resp CAResponse if err := ms.ReadMessage(&resp); err != nil { t.Fatalf("Failed to read from message stream: %s", err) } if *resp.Type != CAType_UNDEFINED { t.Fatalf("Response should have been UNDEFINED, got %s", resp.Type.String()) } <-ch }
// RequestAttestation connects to a CA and gets an attestation back from it. // This might be a truncated attestation (in which case, the right next step is // to verify the truncated attesation, as in RequestTruncatedAttestation), or it // might be some other kind of attestation (like a KeyNegoServer attestation, // which provides a policy-key-signed X.509 certificate for the auth name of // this program). func RequestAttestation(network, addr string, keys *Keys, v *Verifier) (*Attestation, error) { // Establish connection wtih the CA. conn, err := net.Dial(network, addr) if err != nil { return nil, err } defer conn.Close() // Create a CARequest. req := &CARequest{ Type: CAType_ATTESTATION.Enum(), Attestation: keys.Delegation, } // Tao handshake: send client delegation. ms := util.NewMessageStream(conn) if _, err = ms.WriteMessage(req); err != nil { return nil, err } // Read the truncated attestation and check it. var resp CAResponse if err := ms.ReadMessage(&resp); err != nil { return nil, err } ok, err := v.Verify(resp.Attestation.SerializedStatement, AttestationSigningContext, resp.Attestation.Signature) if !ok { return nil, errVerifyFailed } else if err != nil { return nil, err } if *resp.Type != CAType_ATTESTATION { return nil, errInvalidResponse } return resp.Attestation, nil }
// This function packages a host attestation into a DomainServiceRequest of the type // DOMAIN_CERT_REQUEST, sends it to the domain service and deserializes the response // into an attestation that contains the domain program certificate. func RequestProgramCert(hostAtt *tao.Attestation, verifier *tao.Verifier, network string, addr string) (*x509.Certificate, error) { serAtt, err := proto.Marshal(hostAtt) if err != nil { return nil, err } reqType := DomainServiceRequest_DOMAIN_CERT_REQUEST request := &DomainServiceRequest{ Type: &reqType, SerializedHostAttestation: serAtt, ProgramKey: verifier.MarshalKey(), } conn, err := net.Dial(network, addr) if err != nil { return nil, err } ms := util.NewMessageStream(conn) _, err = ms.WriteMessage(request) if err != nil { return nil, err } log.Printf("Sent Program cert request to Domain Service using network %s at address %s.", network, addr) var response DomainServiceResponse err = ms.ReadMessage(&response) if err != nil { return nil, err } log.Println("Got response from Domain Service.") if errStr := response.GetErrorMessage(); errStr != "" { return nil, errors.New(errStr) } cert, err := x509.ParseCertificate(response.GetDerProgramCert()) if err != nil { return nil, err } return cert, nil }
// Submit sends a CSR to a certificate authority server. The keys are used to // authenticate to the server. func (server *Server) Submit(keys *tao.Keys, csr *CSR) ([]*x509.Certificate, error) { addr := net.JoinHostPort(server.Host, server.Port) conn, err := tao.Dial("tcp", addr, nil /* guard */, nil /* verifier */, keys, nil) if err != nil { return nil, err } defer conn.Close() ms := util.NewMessageStream(conn) req := &Request{CSR: csr} _, err = ms.WriteMessage(req) if err != nil { return nil, err } var resp Response if err := ms.ReadMessage(&resp); err != nil { return nil, err } if *resp.Status != ResponseStatus_TAOCA_OK { detail := "unknown error" if resp.ErrorDetail != nil { detail = *resp.ErrorDetail } return nil, fmt.Errorf("%s: %s", resp.Status, detail) } if len(resp.Cert) == 0 { return nil, fmt.Errorf("no certificates in CA response") } certs := make([]*x509.Certificate, len(resp.Cert)) for i, c := range resp.Cert { cert, err := x509.ParseCertificate(c.X509Cert) if err != nil { return nil, err } certs[i] = cert } return certs, nil }
// Return attest certificate func (tt *TPM2Tao) Tpm2Certify(network, addr string, keyName string) ([]byte, error) { // Establish connection wtih the CA. conn, err := net.Dial(network, addr) if err != nil { return nil, err } defer conn.Close() rk, err := tt.loadRoot() if err != nil { return nil, err } defer tpm2.FlushContext(tt.rw, rk) qh, err := tt.loadQuote() if err != nil { return nil, err } defer tpm2.FlushContext(tt.rw, qh) ms := util.NewMessageStream(conn) programCertMessage, err := Tpm2ConstructClientRequest(tt.rw, tt.rootCert, tt.pcrs, qh, "", tt.password, keyName) _, err = ms.WriteMessage(programCertMessage) if err != nil { return nil, err } var resp tpm2.ProgramCertResponseMessage err = ms.ReadMessage(&resp) if err != nil { return nil, err } attestCert, err := Tpm2ClientDecodeServerResponse(tt.rw, rk, qh, tt.password, resp) return attestCert, nil }
// Accept waits for a connect, accepts it using the underlying Conn and checks // the attestations and the statement. func (l *listener) Accept() (net.Conn, error) { c, err := l.gl.Accept() if err != nil { return nil, err } // Tao handshake Protocol: // 0. TLS handshake (executed automatically on first message) // 1. Client -> Server: Tao delegation for X.509 certificate. // 2. Server: checks for a Tao-authorized program. // 3. Server -> Client: Tao delegation for X.509 certificate. // 4. Client: checks for a Tao-authorized program. ms := util.NewMessageStream(c) var a Attestation if err := ms.ReadMessage(&a); err != nil { c.Close() return nil, err } if err := AddEndorsements(l.guard, &a, l.verifier); err != nil { return nil, err } peerCert := c.(*tls.Conn).ConnectionState().PeerCertificates[0] if err := ValidatePeerAttestation(&a, peerCert, l.guard); err != nil { c.Close() return nil, err } if _, err := ms.WriteMessage(l.delegation); err != nil { c.Close() return nil, err } return c, nil }
func main() { flag.Parse() var domain *tao.Domain var rootCerts *x509.CertPool var err error if *createDomainFlag { log.Println("Creating new domain...") domain, rootCerts, err = createDomain() } else { log.Println("Loading domain info...") domain, rootCerts, err = loadDomain() } if err != nil { log.Fatalln("domain_server: could not load domain:", err) } ln, err := net.Listen(*network, *addr) if err != nil { log.Fatalln("domain_server: could not listen at port:", err) } for { conn, err := ln.Accept() if err != nil { log.Fatalln("domain_server: could not accept connection:", err) } // switch case ms := util.NewMessageStream(conn) var request domain_service.DomainServiceRequest if err := ms.ReadMessage(&request); err != nil { log.Printf("domain_server: Couldn't read request from channel: %s\n", err) continue } switch *request.Type { case domain_service.DomainServiceRequest_DOMAIN_CERT_REQUEST: _, kPrin, prog, err := domain_service.VerifyHostAttestation( request.GetSerializedHostAttestation(), domain, rootCerts) if err != nil { log.Printf("domain_server: Error verifying host att: %s\n", err) sendError(err, ms) continue } programKeyBytes := request.GetProgramKey() verifier, err := tao.UnmarshalKey(programKeyBytes) if err != nil { log.Printf("domain_server: Error parsing program key: %v\n", err) sendError(err, ms) continue } if !verifier.ToPrincipal().Identical(kPrin) { log.Printf("domain_server: Program key in request does not match key being attested to.") sendError(err, ms) continue } cert, err := domain_service.GenerateProgramCert(domain, serialNumber, prog, verifier, time.Now(), time.Now().AddDate(1, 0, 0)) if err != nil { log.Printf("domain_server: Error generating program cert: %s\n", err) sendError(err, ms) continue } resp := &domain_service.DomainServiceResponse{ DerProgramCert: cert.Raw} if _, err := ms.WriteMessage(resp); err != nil { log.Printf("domain_server: Error sending cert on the channel: %s\n ", err) continue } case domain_service.DomainServiceRequest_MANAGE_POLICY: // TODO(sidtelang) case domain_service.DomainServiceRequest_REVOKE_CERTIFICATE: revokedCertificates, err = domain_service.RevokeCertificate( request.GetSerializedPolicyAttestation(), revokedCertificates, domain) if err != nil { log.Printf("domain_server: Error revoking certificate: %s\n", err) } sendError(err, ms) case domain_service.DomainServiceRequest_GET_CRL: nowTime := time.Now() expireTime := time.Now().AddDate(1, 0, 0) crl, err := domain.Keys.SigningKey.CreateCRL(domain.Keys.Cert, revokedCertificates, nowTime, expireTime) resp := domain_service.DomainServiceResponse{} if err != nil { errStr := err.Error() resp.ErrorMessage = &errStr } else { resp.Crl = crl } if _, err := ms.WriteMessage(&resp); err != nil { log.Printf("domain_server: Error sending response on the channel: %s\n ", err) } } } }
// 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 }
// 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 }
// This is the server. It implements the server Tao Channel negotiation corresponding // to the client's taosupport.OpenTaoChannel. It's possible we should move this into // taosupport/taosupport.go since it should not vary very much from implementation to // implementation. func server(serverAddr string, serverProgramData *taosupport.TaoProgramData) { var sock net.Listener // Set up the single root certificate for channel negotiation which is the // policy key cert. pool := x509.NewCertPool() policyCert, err := x509.ParseCertificate(serverProgramData.PolicyCert) if err != nil { log.Printf("simpleserver, can't parse policyCert: ", err, "\n") return } // Make the policy cert the unique root of the verification chain. pool.AddCert(policyCert) tlsc, err := tao.EncodeTLSCert(&serverProgramData.ProgramKey) if err != nil { log.Printf("simpleserver, encode error: ", err, "\n") return } conf := &tls.Config{ RootCAs: pool, Certificates: []tls.Certificate{*tlsc}, InsecureSkipVerify: false, ClientAuth: tls.RequireAnyClientCert, } // Listen for clients. log.Printf("simpleserver: Listening\n") sock, err = tls.Listen("tcp", serverAddr, conf) if err != nil { log.Printf("simpleserver, listen error: ", err, "\n") return } // Service client connections. for { log.Printf("server: at accept\n") conn, err := sock.Accept() if err != nil { fmt.Printf("simpleserver: can't accept connection: %s\n", err.Error()) log.Printf("server: can't accept connection: %s\n", err.Error()) continue } var clientName string err = conn.(*tls.Conn).Handshake() if err != nil { log.Printf("server: TLS handshake failed\n") continue } peerCerts := conn.(*tls.Conn).ConnectionState().PeerCertificates if peerCerts == nil { log.Printf("server: can't get peer list\n") continue } peerCert := conn.(*tls.Conn).ConnectionState().PeerCertificates[0] if peerCert.Raw == nil { log.Printf("server: can't get peer cert\n") continue } if peerCert.Subject.OrganizationalUnit == nil { log.Printf("server: can't get peer name\n") continue } clientName = peerCert.Subject.OrganizationalUnit[0] log.Printf("server, peer client name: %s\n", clientName) ms := util.NewMessageStream(conn) // At this point the handshake is complete and we fork a service thread // to communicate with this simpleclient. ms is the bi-directional // confidentiality and integrity protected channel corresponding to the // channel opened by OpenTaoChannel. go serviceThead(ms, clientName, serverProgramData) } }
func main() { caAddr := flag.String("caAddr", "localhost:8124", "The address of the CA for setting up a certificate signed by the policy key") hostcfg := flag.String("hostconfig", "tao.config", "path to host tao configuration") serverHost := flag.String("host", "localhost", "address for client/server") serverPort := flag.String("port", "8123", "port for client/server") rollbackServerHost := flag.String("rollbackhost", "localhost", "address for rollback client/server") rollbackServerPort := flag.String("rollbackport", "8129", "port for client/server") fileClientPassword := flag.String("password", "BogusPass", "A password for unlocking the user certificates") fileClientPath := flag.String("fileclient_files", "fileclient_files", "fileclient directory") fileClientFilePath := flag.String("stored_files", "fileclient_files/stored_files", "fileclient file directory") testFile := flag.String("test_file", "originalTestFile", "test file") fileClientKeyPath := flag.String("usercreds", "usercreds", "user keys and certs") country := flag.String("country", "US", "The country for the fileclient certificate") org := flag.String("organization", "Google", "The organization for the fileclient certificate") flag.Parse() serverAddr := net.JoinHostPort(*serverHost, *serverPort) hostDomain, err := tao.LoadDomain(*hostcfg, nil) if err != nil { log.Fatalln("fileclient: Can't load domain") } var derPolicyCert []byte if hostDomain.Keys.Cert["default"] != nil { derPolicyCert = hostDomain.Keys.Cert["default"].Raw } if derPolicyCert == nil { log.Fatalln("fileclient: Can't retrieve policy cert") } parentTao := tao.Parent() if err := hostDomain.ExtendTaoName(parentTao); err != nil { log.Fatalln("fileclient: can't extend the Tao with the policy key") } e := auth.PrinExt{Name: "fileclient_version_1"} if err = parentTao.ExtendTaoName(auth.SubPrin{e}); err != nil { log.Fatalln("fileclient: couldn't extend the tao name with the policy key") } taoName, err := parentTao.GetTaoName() if err != nil { log.Fatalln("fileclient: Can't get tao name") } // Create or read the keys for fileclient. // Set up a temporary cert for communication with keyNegoServer. // TODO(kwalsh) This may no longer be needed. Is there a significance to // this cert? name := tao.NewX509Name(&tao.X509Details{ Country: proto.String(*country), Organization: proto.String(*org), CommonName: proto.String(taoName.String()), }) fcKeys, err := tao.NewOnDiskTaoSealedKeys(tao.Signing|tao.Crypting, name, parentTao, *fileClientPath, tao.SealPolicyDefault) if err != nil { log.Fatalln("fileclient: couldn't set up the Tao-sealed keys:", err) } if err != nil { log.Fatalln("fileclient: couldn't create a self-signed cert for fileclient keys:", err) } // Contact keyNegoServer for the certificate. if err := fileproxy.EstablishCert("tcp", *caAddr, fcKeys, hostDomain.Keys.VerifyingKey); err != nil { log.Fatalf("fileclient: couldn't establish a cert signed by the policy key: %s", err) } // Get the policy cert and set up TLS. conf, err := fcKeys.TLSClientConfig(hostDomain.Keys.Cert["default"]) if err != nil { log.Fatalln("fileclient, encode error: ", err) } conn, err := tls.Dial("tcp", serverAddr, conf) if err != nil { log.Fatalln("fileclient: can't establish channel: ", err) } ms := util.NewMessageStream(conn) // Before doing any tests, create a simple file to send to the server. testContents := ` This is a simple file to test It has some new lines And it doesn't have very much content. ` if _, err := os.Stat(*fileClientFilePath); err != nil { if err := os.MkdirAll(*fileClientFilePath, 0700); err != nil { log.Fatalf("fileclient: couldn't create the file storage path %s: %s", *fileClientFilePath, err) } } sentFileName := *testFile sentFilePath := path.Join(*fileClientFilePath, sentFileName) if err := ioutil.WriteFile(sentFilePath, []byte(testContents), 0600); err != nil { log.Fatalf("fileclient: couldn't create a test file at %s: %s", sentFilePath, err) } // Authenticate user principal(s). if _, err := os.Stat(*fileClientKeyPath); err != nil { log.Fatalf("fileclient: couldn't get user credentials from %s: %s\n", *fileClientKeyPath, err) } // This method won't generate the right certificate in general for // signing, which is why we check first to make sure the right directory // already exists. But it will successfully read the signer and the // certificate. userKeys, err := tao.NewOnDiskPBEKeys(tao.Signing, []byte(*fileClientPassword), *fileClientKeyPath, nil) if err != nil { log.Fatalf("Couldn't read the keys from %s: %s\n", *fileClientKeyPath, err) } userCert := userKeys.Cert["default"].Raw // Authenticate a key to use for requests to the server. if err = fileproxy.AuthenticatePrincipal(ms, userKeys, userCert); err != nil { log.Fatalf("fileclient: can't authenticate principal: %s", err) } // Create a file. if err = fileproxy.CreateFile(ms, userCert, sentFileName); err != nil { log.Fatalln("fileclient: can't create file:", err) } // Send File. if err = fileproxy.WriteFile(ms, userCert, *fileClientFilePath, sentFileName); err != nil { log.Fatalf("fileclient: couldn't write the file %s to the server: %s", sentFileName, err) } // Get file. outputFileName := sentFileName + ".out" if err = fileproxy.ReadFile(ms, userCert, *fileClientFilePath, sentFileName, outputFileName); err != nil { log.Fatalf("fileclient: couldn't get file %s to output file %s: %s", sentFileName, outputFileName, err) } // TODO(tmroeder): compare the received file against the sent file. // Set up a TLS connection to the rollback server, just like the one to // the file server. rollbackServerAddr := net.JoinHostPort(*rollbackServerHost, *rollbackServerPort) rbconn, err := tls.Dial("tcp", rollbackServerAddr, conf) if err != nil { log.Fatalf("fileclient: can't establish rollback channel: %s", err) } newms := util.NewMessageStream(rbconn) // Create a fake hash value, and set this value for an item. hashLen := 32 hash := make([]byte, hashLen) if _, err := rand.Read(hash); err != nil { log.Fatalf("fileclient: failed to read a random value for the hash") } progName := taoName.String() resName := "test_resource" if err := fileproxy.SetHash(newms, resName, hash); err != nil { log.Fatalf("Couldn't set the hash for program '%s', resource '%s', hash % x on the remote server: %s", progName, resName, hash, err) } // Set the counter to 10 and check that we get the same value back. if err := fileproxy.SetCounter(newms, uint64(10)); err != nil { log.Fatalf("fileclient: couldn't set the counter in the file client") } c, err := fileproxy.GetCounter(newms) if err != nil { log.Fatalf("fileclient: couldn't get the value of the counter from the rollback server") } // Get the hash verification value. newHash, err := fileproxy.GetHashedVerifier(newms, resName) if err != nil { log.Fatalf("fileclient: couldn't get the hashed verifier from the rollback server") } // Try to recompute the hashed verifier directly to see if it matches. sh := sha256.New() vi := fileproxy.EncodeCounter(c) sh.Write(vi) sh.Write(hash) sh.Write(vi) computed := sh.Sum(nil) if subtle.ConstantTimeCompare(newHash, computed) != 1 { log.Fatalf("fileclient: the hashed verifier % x returned by the server didn't match the value % x computed locally", newHash, computed) } log.Println("All fileclient tests pass") }