func main() { domain, err := tao.LoadDomain(*configPath, []byte(*domainPass)) if domain == nil { log.Printf("domainserver: no domain path - %s, pass - %s, err - %s\n", *configPath, *domainPass, err) } else if err != nil { log.Printf("domainserver: Couldn't load the config path %s: %s\n", *configPath, err) } policyKey, policyCert := domain.Keys, domain.Keys.Cert if policyCert == nil { log.Fatalln("Policy cert not found") } hostKey, hostAtt := generateAttestation(policyKey, hostName) programKey, programAtt := generateAttestation(hostKey, programName) rawEnd1, err := proto.Marshal(hostAtt) if err != nil { log.Fatalln("Error serializing attestation.") } programAtt.SerializedEndorsements = [][]byte{rawEnd1} cert, err := domain_service.RequestProgramCert(programAtt, programKey.VerifyingKey, *network, *addr) if err != nil { log.Fatalln("Error:", err) } rootCerts := x509.NewCertPool() rootCerts.AddCert(domain.Keys.Cert) options := x509.VerifyOptions{Roots: rootCerts} _, err = cert.Verify(options) if err != nil { log.Fatalln("Program cert fails verification check.", err) } ver, err := tao.FromX509(cert) if err != nil { log.Fatalln("Error getting verifier from Program cert", err) } if v := programKey.VerifyingKey; !v.Equals(cert) { log.Fatalf("Key in Program cert %v differs from expected value %v.", ver, v) } // Test Certificate Revocation. serialNumber := cert.SerialNumber says := auth.Says{ Speaker: domain.Keys.SigningKey.ToPrincipal(), Message: auth.Pred{ Name: "revoke", Arg: []auth.Term{auth.Bytes(serialNumber.Bytes())}}} att, err := tao.GenerateAttestation(domain.Keys.SigningKey, nil, says) if err != nil { log.Fatalln("Error generating attestation for certificate revocation.") } err = domain_service.RequestRevokeCertificate(att, *network, *addr) if err != nil { log.Fatalln("Error revoking certificate: ", err) } crl, err := domain_service.RequestCrl(*network, *addr) if err != nil { log.Fatalln("Error getting CRL: ", err) } revokedCerts := crl.TBSCertList.RevokedCertificates if len(revokedCerts) != 1 { log.Fatalf("Revoked 1 cert and got back CRL with %v revoked certs", len(revokedCerts)) } if num := revokedCerts[0].SerialNumber.Int64(); num != serialNumber.Int64() { log.Fatalf("Serial number %v doesnt match expected value %v", num, serialNumber) } log.Println("YAY!") }
// AuthenticatePrincipal runs a synchronous protocol to authenticate a single // principal on a single channel. In this toy implementation, it is assumed that // there are no other principals on the channel and that there are no other // simultaneous channels. func (m *ResourceMaster) AuthenticatePrincipal(ms util.MessageStream, msg *Message, programPolicy *ProgramPolicy) ([]byte, error) { // The certificate message is passed in by the caller as the first // message. // Process the certificate. For AUTH_CERT, the data is just the // certificate. cert, err := x509.ParseCertificate([]byte(msg.Data)) if err != nil { log.Printf("couldn't Parse Certificate in AuthenticatePrincipal\n") return nil, err } // Set up a nonce challenge for the reply. For NONCE_CHALL, the data is // also just the message itself. reply := &Message{ Type: MessageType_NONCE_CHALL.Enum(), Data: make([]byte, NonceSize), } if _, err = rand.Read(reply.Data); err != nil { return nil, err } // Step 1: Send a nonce to the principal. if _, err := ms.WriteMessage(reply); err != nil { return nil, err } // Step 2: Wait for the signed response. var s Message if err := ms.ReadMessage(&s); err != nil { return nil, err } if *s.Type != MessageType_SIGNED_NONCE { return nil, fmt.Errorf("received message was not SIGNED_NONCE") } // Verify the certificate against the root. // TODO(tmroeder): move the VerifyOptions up into the ResourceMaster. var opts x509.VerifyOptions roots := x509.NewCertPool() policyCert, err := x509.ParseCertificate(programPolicy.PolicyCert) if err != nil || policyCert == nil { return nil, err } roots.AddCert(policyCert) opts.Roots = roots chains, err := cert.Verify(opts) if chains == nil || err != nil { return nil, err } v, err := tao.FromX509(cert) if err != nil { return nil, err } ok, err := v.Verify(reply.Data, ChallengeContext, s.Data) if err != nil { return nil, err } if err := sendResult(ms, ok); err != nil { return nil, fmt.Errorf("failed to return a result to the client") } if !ok { return nil, fmt.Errorf("the nonce signature did not pass verification") } return msg.Data, nil }
// 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 }