func TestDatalogSubprin(t *testing.T) { g, _, tmpdir, err := makeDatalogGuard() if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) for _, s := range datalogSubprinProg { if err := g.AddRule(s); err != nil { t.Fatal("Couldn't add rule '", s, "':", err) } } pprin := auth.Prin{ Type: "key", KeyHash: auth.Bytes([]byte{0x70}), Ext: []auth.PrinExt{ auth.PrinExt{ Name: "Hash", Arg: []auth.Term{auth.Bytes([]byte{0x71})}, }, }, } if !g.IsAuthorized(pprin, "Execute", nil) { t.Fatal("Subprin authorization check failed") } }
func makeACLGuard() (*ACLGuard, *Keys, string, error) { tmpDir, err := ioutil.TempDir("", "acl_guard_test") if err != nil { return nil, nil, "", fmt.Errorf("Couldn't get a temp directory for the ACL guard test") } keys, err := NewTemporaryKeys(Signing) if err != nil { return nil, nil, "", err } config := ACLGuardDetails{ SignedAclsPath: proto.String(path.Join(tmpDir, "acls")), } tg := NewACLGuard(keys.VerifyingKey, config) // Add a bogus rule. p := auth.Prin{ Type: "key", Key: auth.Bytes([]byte(`Fake key`)), } if err := tg.Authorize(p, "Write", []string{"filename"}); err != nil { return nil, nil, "", err } return tg.(*ACLGuard), keys, tmpDir, err }
func TestACLGuardDoubleAuthorize(t *testing.T) { s, err := GenerateSigner() if err != nil { t.Fatal("Couldn't generate a signer") } tg, tmpdir := testNewACLGuard(t, s.GetVerifier()) defer os.RemoveAll(tmpdir) p := auth.Prin{ Type: "key", Key: auth.Bytes([]byte(`Fake key`)), } if err := tg.Authorize(p, "Write", []string{"filename"}); err != nil { t.Fatal("Couldn't authorize a simple operation:", err) } // So nice, we authorize it twice. if err := tg.Authorize(p, "Write", []string{"filename"}); err != nil { t.Fatal("Couldn't authorize a simple operation:", err) } if !tg.IsAuthorized(p, "Write", []string{"filename"}) { t.Fatal("A rule that was added to the ACL was not present") } if err := tg.Retract(p, "Write", []string{"filename"}); err != nil { t.Fatal("Couldn't retract an existing double-added rule:", err) } if tg.IsAuthorized(p, "Write", []string{"filename"}) { t.Fatal("A rule was still authorized after it was retracted") } }
func TestRevokeCertificate(t *testing.T) { k, err := tao.NewTemporaryKeys(tao.Signing) if k == nil || err != nil { t.Fatal("Can't generate signing key") } serialNumber := big.NewInt(5) says := auth.Says{ Speaker: k.SigningKey.ToPrincipal(), Message: auth.Pred{ Name: "revoke", Arg: []auth.Term{auth.Bytes(serialNumber.Bytes())}}} att, err := tao.GenerateAttestation(k.SigningKey, nil, says) if err != nil { t.Fatal("Error generating attestation.") } serAtt, err := proto.Marshal(att) if err != nil { t.Fatal("Error serializing attestation.") } revokedCerts := []pkix.RevokedCertificate{} revokedCerts, err = RevokeCertificate(serAtt, revokedCerts, &tao.Domain{Keys: k}) if err != nil { t.Fatal(err) } if num := revokedCerts[0].SerialNumber.Int64(); num != 5 { t.Fatal(fmt.Sprintf("Serial number %v doesnt match expected value 5", num)) } }
func MakeTPMPrin(verifier *rsa.PublicKey, pcrNums []int, pcrVals [][]byte) (auth.Prin, error) { aik, err := x509.MarshalPKIXPublicKey(verifier) if err != nil { return auth.Prin{}, err } name := auth.Prin{ Type: "tpm", Key: auth.Bytes(aik), } asp := auth.PrinExt{ Name: "PCRs", Arg: make([]auth.Term, 2), } var pcrNumStrs []string for _, v := range pcrNums { pcrNumStrs = append(pcrNumStrs, strconv.Itoa(v)) } asp.Arg[0] = auth.Str(strings.Join(pcrNumStrs, ",")) var pcrValStrs []string for _, p := range pcrVals { pcrValStrs = append(pcrValStrs, hex.EncodeToString(p)) } asp.Arg[1] = auth.Str(strings.Join(pcrValStrs, ",")) // The PCRs are the first extension of the name. name.Ext = []auth.PrinExt{asp} return name, nil }
func TestVerifyDirectiveWithBadProtectedObjectId_invalidProtoBuf(t *testing.T) { badBytes := []byte("bad bytes") params := Params{ SerializedObjectId: auth.Bytes(badBytes), } expectError(¶ms, t) }
// FormatProcessSubprin produces a string that represents a subprincipal with // the given ID and hash. func FormatProcessSubprin(id uint, hash []byte) auth.SubPrin { var args []auth.Term if id != 0 { args = append(args, auth.Int(id)) } args = append(args, auth.Bytes(hash)) return auth.SubPrin{auth.PrinExt{Name: "Program", Arg: args}} }
// FormatDockerSubprin produces a string that represents a subprincipal with the // given ID and hash. func FormatDockerSubprin(id uint, hash []byte) auth.SubPrin { var args []auth.Term if id != 0 { args = append(args, auth.Int(id)) } args = append(args, auth.Bytes(hash)) return auth.SubPrin{auth.PrinExt{Name: "Container", Arg: args}} }
// FormatCoreOSLinuxhostSubprin produces a string that represents a subprincipal with the // given ID and hash. func FormatCoreOSLinuxhostSubprin(id uint, hash []byte) auth.SubPrin { var args []auth.Term if id != 0 { args = append(args, auth.Int(id)) } args = append(args, auth.Bytes(hash)) return auth.SubPrin{auth.PrinExt{Name: "CoreOS", Arg: args}} }
// Subprincipal returns subprincipal DatalogGuard, for temporary guards, or // DatalogGuard(<key>) for persistent guards. func (g *DatalogGuard) Subprincipal() auth.SubPrin { e := auth.PrinExt{Name: "DatalogGuard"} if g.Key == nil { ser, err := proto.Marshal(&g.db) if err == nil { hash := sha256.Sum256(ser) e.Arg = append(e.Arg, auth.Bytes(hash[:])) } } else { e.Arg = append(e.Arg, g.Key.ToPrincipal()) } return auth.SubPrin{e} }
// Subprincipal returns a unique subprincipal for this policy. func (a *ACLGuard) Subprincipal() auth.SubPrin { e := auth.PrinExt{Name: "ACLGuard"} if a.Key == nil { ser, err := proto.Marshal(&ACLSet{Entries: a.ACL}) if err == nil { hash := sha256.Sum256(ser) e.Arg = append(e.Arg, auth.Bytes(hash[:])) } } else { e.Arg = append(e.Arg, a.Key.ToPrincipal()) } return auth.SubPrin{e} }
// Subprincipal returns subprincipal DatalogGuard, for temporary guards, or // DatalogGuard(<key>) for persistent guards. func (g *DatalogGuard) Subprincipal() auth.SubPrin { if g.Key == nil { rules, err := proto.Marshal(&g.db) if err != nil { return nil } hash := sha256.Sum256(rules) e := auth.PrinExt{Name: "DatalogGuard", Arg: []auth.Term{auth.Bytes(hash[:])}} return auth.SubPrin{e} } e := auth.PrinExt{Name: "DatalogGuard", Arg: []auth.Term{g.Key.ToPrincipal()}} return auth.SubPrin{e} }
// Subprincipal returns a unique subprincipal for this policy. func (a *ACLGuard) Subprincipal() auth.SubPrin { if a.Key == nil { acls := &ACLSet{Entries: a.ACL} ser, err := proto.Marshal(acls) if err != nil { return nil } hash := sha256.Sum256(ser) e := auth.PrinExt{Name: "ACLGuard", Arg: []auth.Term{auth.Bytes(hash[:])}} return auth.SubPrin{e} } e := auth.PrinExt{Name: "ACLGuard", Arg: []auth.Term{a.Key.ToPrincipal()}} return auth.SubPrin{e} }
func TestDatalogSimpleTranslation(t *testing.T) { g, keys, tmpdir, err := makeDatalogGuard() if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) for _, s := range datalogProg { if err := g.AddRule(s); err != nil { t.Fatal("Couldn't add rule '", s, "':", err) } } kprin := auth.Prin{ Type: "key", KeyHash: auth.Bytes([]byte{0x70}), } if !g.IsAuthorized(kprin, "Execute", nil) { t.Fatal("Simple authorization check failed") } if err := g.Save(keys.SigningKey); err != nil { t.Fatal("Couldn't save the guard:", err) } ok, err := g.Query("MemberProgram(key([70]))") if err != nil { t.Fatal("Couldn't query the guard:", err) } if !ok { t.Fatal("A simple sanity-check query failed") } ok, err = g.Query("Authorized(key([70]), \"Execute\")") if err != nil { t.Fatal("Couldn't query the guard:", err) } if !ok { t.Fatal("A simple authorized query didn't succeed") } }
func TestACLGuardAuthorize(t *testing.T) { s, err := GenerateSigner() if err != nil { t.Fatal("Couldn't generate a signer") } tg, tmpdir := testNewACLGuard(t, s.GetVerifier()) defer os.RemoveAll(tmpdir) p := auth.Prin{ Type: "key", Key: auth.Bytes([]byte(`Fake key`)), } if err := tg.Authorize(p, "Write", []string{"filename"}); err != nil { t.Fatal("Couldn't authorize a simple operation:", err) } if !tg.IsAuthorized(p, "Write", []string{"filename"}) { t.Fatal("A rule that was added to the ACL was not present") } if tg.IsAuthorized(p, "Write", []string{"file"}) { t.Fatal("A rule was authorized even though it has the wrong file name") } if tg.IsAuthorized(p, "Read", []string{"filename"}) { t.Fatal("A rule was authorized even though it has the wrong op") } if tg.IsAuthorized(auth.Prin{}, "Write", []string{"filename"}) { t.Fatal("A rule was authorized even though it has the wrong principal") } if err := tg.Retract(p, "Write", []string{"filename"}); err != nil { t.Fatal("Couldn't retract an existing rule:", err) } if tg.IsAuthorized(p, "Write", []string{"filename"}) { t.Fatal("A rule was still authorized after it was retracted") } }
func TestTPMTaoAttest(t *testing.T) { aikblob, err := ioutil.ReadFile("./aikblob") if err != nil { t.Skip("Skipping tests, since there's no ./aikblob file") } tpmtao, err := NewTPMTao("/dev/tpm0", aikblob, []int{17, 18}) if err != nil { t.Skip("Couldn't create a new TPM Tao:", err) } tt, ok := tpmtao.(*TPMTao) if !ok { t.Fatal("Failed to create the right kind of Tao object from NewTPMTao") } defer cleanUpTPMTao(tt) // Set up a fake key delegation. taoname, err := tpmtao.GetTaoName() if err != nil { t.Fatal("Couldn't get the name of the tao:", err) } stmt := auth.Speaksfor{ Delegate: auth.Prin{Type: "key", Key: auth.Bytes([]byte(`FakeKeyBytes`))}, Delegator: taoname, } // Let the TPMTao set up the issuer and time and expiration. a, err := tpmtao.Attest(nil, nil, nil, stmt) if err != nil { t.Fatal("Couldn't attest to a key delegation:", err) } says, err := a.Validate() if err != nil { t.Fatal("The attestation didn't pass validation:", err) } t.Logf("Got valid statement %s\n", says) }
// 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 }
func TestACLGuardSaveACLs(t *testing.T) { s, err := GenerateSigner() if err != nil { t.Fatal("Couldn't generate a signer") } tg, tmpdir := testNewACLGuard(t, s.GetVerifier()) defer os.RemoveAll(tmpdir) p := auth.Prin{ Type: "key", Key: auth.Bytes([]byte(`Fake key`)), } if err := tg.Authorize(p, "Write", []string{"filename"}); err != nil { t.Fatal("Couldn't authorize a simple operation:", err) } if err := tg.Save(s); err != nil { t.Fatal("Couldn't save the file") } config := ACLGuardDetails{SignedAclsPath: proto.String(path.Join(tmpdir, "acls"))} v := s.GetVerifier() aclg, err := LoadACLGuard(v, config) if err != nil { t.Fatal("Couldn't load the ACLs:", err) } if aclg.RuleCount() != tg.RuleCount() { t.Fatal("Wrong number of rules in loaded ACLGuard") } if aclg.String() != tg.String() { t.Fatal("Wrong string representation of loaded ACLGuard") } }
func generatePolicyKeyAndSignedDirective(params Params) (*tao.Keys, *DirectiveMessage, error) { var programName auth.Term if params.Delegate != nil { programName = params.Delegate } else { programName = Delegate } var serializedObjectId auth.Term if params.SerializedObjectId != nil { serializedObjectId = params.SerializedObjectId } else { bytes, err := proto.Marshal(&ProtectedObjectId) if err != nil { return nil, nil, err } serializedObjectId = auth.Bytes(bytes) } terms := []auth.Term{programName, serializedObjectId} if params.CanReadTerms != nil { terms = params.CanReadTerms } var canRead auth.Form if params.CanRead != nil { canRead = params.CanRead } else { canRead = auth.Pred{ Name: ReadPredicate, Arg: terms, } } policyKey, err := tao.NewTemporaryKeys(tao.Signing) if err != nil { return nil, nil, err } info := x509Info name := policyKey.SigningKey.ToPrincipal().String() info.CommonName = &name subject := tao.NewX509Name(&info) policyKey.Cert, err = policyKey.SigningKey.CreateSelfSignedX509(subject) if err != nil { return nil, nil, err } var says auth.Form if params.Says != nil { says = params.Says } else { says = auth.Says{ Speaker: policyKey.SigningKey.ToPrincipal(), Time: nil, Expiration: nil, Message: canRead, } } serializedSays := auth.Marshal(says) var directiveType *DirectiveMessageDirectiveType if params.DirectiveType != nil { directiveType = params.DirectiveType } else { directiveType = DirectiveMessage_SECRET_DISCLOSURE.Enum() } var signature []byte if params.Signature != nil { signature = params.Signature } else { signature, err = policyKey.SigningKey.Sign(serializedSays, SigningContext) if err != nil { return nil, nil, err } } var signer []byte if params.Signer != nil { signer = params.Signer } else { signer = auth.Marshal(policyKey.SigningKey.ToPrincipal()) } directive := &DirectiveMessage{ Type: directiveType, SerializedStatement: serializedSays, Signature: signature, Signer: signer, } return policyKey, directive, nil }
// Test that a client can correctly verify that the server is allowed to // execute according to the policy. The policy is set up and the policy // key is used to attest to the identity of the server. The attestation // includes an endorsement of the service itself. The client verifies the // endorsement and adds the predicate to the policy before checking it. func TestCachingDatalogValidatePeerAttestation(t *testing.T) { network := "tcp" addr := "localhost:0" ttl := int64(1) tmpDir := "/tmp/domain_test" // Set up the TaoCA. ch := make(chan bool) cal, err := net.Listen(network, addr) if err != nil { t.Fatal(err) } defer cal.Close() addr = cal.Addr().String() // Set up the policy domain and a public, cached version. policy, pub, err := makeTestDomains(tmpDir, network, addr, ttl) if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir + ".pub") // Set up policy. A key being authorized to execute is of course nonsense; // this is only meant to test that ValidatePeerAttestation() properly adds // the endoresement to the policy. rule := "(forall K: TrustedKey(K) implies Authorized(K, \"Execute\"))" if err := policy.Guard.AddRule(rule); err != nil { t.Errorf("could not add rule : %s", err) return } // Generate a set of keys for the Tao-delegated server. k, err := NewTemporaryTaoDelegatedKeys(Signing|Crypting|Deriving, nil) if err != nil { t.Error("failed to generate keys:", err) return } k.dir = tmpDir // Generate an attesation of the statements: "k.VerifyingKey speaks for // key(K)" and "TrustedKey(key(K))" signed by the policy key and set to // k.Delegation. prin := auth.Prin{ Type: "key", Key: auth.Bytes("This is a terrible key."), } pred := auth.Pred{ Name: "TrustedKey", Arg: []auth.Term{prin}, } sf := auth.Speaksfor{ Delegate: k.SigningKey.ToPrincipal(), Delegator: prin, } stmt := auth.Says{ Speaker: policy.Keys.SigningKey.ToPrincipal(), Time: nil, Expiration: nil, Message: sf, } if k.Delegation, err = GenerateAttestation(policy.Keys.SigningKey, nil, stmt); err != nil { t.Error("failed to attest to speaksfor:", err) return } e := auth.Says{ Speaker: policy.Keys.SigningKey.ToPrincipal(), Message: pred, } ea, err := GenerateAttestation(policy.Keys.SigningKey, nil, e) if err != nil { t.Error("failed to attest to endorsement:", err) return } eab, err := proto.Marshal(ea) if err != nil { t.Error("failed to marshal attested endorsement:", err) return } k.Delegation.SerializedEndorsements = [][]byte{eab} // Generate an x509 certificate for the Tao-delegated server. k.Cert, err = k.SigningKey.CreateSelfSignedX509(&pkix.Name{ Organization: []string{"Identity of some Tao service"}}) if err != nil { t.Error("failed to generate x509 certificate:", err) return } // Run the TaoCA. This handles one request and then exits. go runTCCA(t, cal, policy.Keys, policy.Guard, ch) // Add any verified predicates to the policy. This will cause a // policy query to the TaoCA. if err = AddEndorsements(pub.Guard, k.Delegation, pub.Keys.VerifyingKey); err != nil { t.Error("failed to add endorsements:", err) return } <-ch // Finally, the client verifies the Tao-delegated server is allowed to // execute. if err = ValidatePeerAttestation(k.Delegation, k.Cert, pub.Guard); err != nil { t.Error("failed to verity attestation:", err) } }
import ( "bytes" "fmt" "os" "testing" "github.com/golang/protobuf/proto" po "github.com/jlmucb/cloudproxy/go/support_libraries/protected_objects" "github.com/jlmucb/cloudproxy/go/tao" "github.com/jlmucb/cloudproxy/go/tao/auth" ) var Delegate = auth.Prin{ Type: "program", Key: auth.Bytes([]byte(`fake program`)), } var Delegator = auth.Prin{ Type: "program", Key: auth.Bytes([]byte(`speaker program`)), } var ProtectedObjectName = "obj_name" var ProtectedObjectEpoch = int32(0) var ProtectedObjectId = po.ObjectIdMessage{ ObjName: &ProtectedObjectName, ObjEpoch: &ProtectedObjectEpoch, } var us = "US"
// 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 }
package tao import ( "io/ioutil" "os" "path" "testing" "github.com/golang/protobuf/proto" "github.com/jlmucb/cloudproxy/go/tao/auth" ) var testDomainPassword = []byte(`insecure dummy password`) var authPrin = auth.Prin{ Type: "key", Key: auth.Bytes([]byte(`fake key`)), } func testNewACLDomain(t *testing.T) (*Domain, string) { tmpdir, err := ioutil.TempDir("/tmp", "acl_domain_test") if err != nil { t.Fatal("Couldn't get a temp directory for the new ACL guard:", err) } var dcfg DomainConfig dcfg.DomainInfo = &DomainDetails{ Name: proto.String("Test"), PolicyKeysPath: proto.String("keys"), GuardType: proto.String("ACLs"), } dcfg.SetDefaults()
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!") }