github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/support_infrastructure/domain_service/domain_service_test.go (about)

     1  // Copyright (c) 2016, Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package domain_service
    16  
    17  import (
    18  	"crypto/rand"
    19  	"crypto/rsa"
    20  	"crypto/x509"
    21  	"crypto/x509/pkix"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"os"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/golang/protobuf/proto"
    30  	"github.com/google/go-tpm/tpm"
    31  	"github.com/jlmucb/cloudproxy/go/tao"
    32  	"github.com/jlmucb/cloudproxy/go/tao/auth"
    33  )
    34  
    35  var machineName = "Encode Machine Information"
    36  
    37  var hostName = &auth.Prin{
    38  	Type:    "program",
    39  	KeyHash: auth.Str("hostHash")}
    40  
    41  var programName = &auth.Prin{
    42  	Type:    "program",
    43  	KeyHash: auth.Str("programHash")}
    44  
    45  var us = "US"
    46  var google = "Google"
    47  var x509Info = &tao.X509Details{
    48  	Country:      &us,
    49  	Organization: &google}
    50  
    51  func TestVerifyHostAttestation_stackedHost(t *testing.T) {
    52  	aikblob, err := ioutil.ReadFile("./aikblob")
    53  	if err != nil {
    54  		t.Skip("Skipping tests, since there's no ./aikblob file")
    55  	}
    56  	tpmtao, err := tao.NewTPMTao("/dev/tpm0", aikblob, []int{17, 18}, nil)
    57  	if err != nil {
    58  		t.Skip("Couldn't create a new TPM Tao:", err)
    59  	}
    60  	tt, ok := tpmtao.(*tao.TPMTao)
    61  	if !ok {
    62  		t.Fatal("Failed to create the right kind of Tao object from NewTPMTao")
    63  	}
    64  	defer tao.CleanUpTPMTao(tt)
    65  	hwPublicKey, err := tpm.UnmarshalRSAPublicKey(aikblob)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	domain := generateDomain(t)
    71  	policyKey, policyCert := domain.Keys, domain.Keys.Cert
    72  	hwCert := generateEndorsementCertficate(t, policyKey, hwPublicKey, policyCert)
    73  	hostKey, hostAtt := generateTpmAttestation(t, tt, hostName)
    74  	programKey, programAtt := generateAttestation(t, hostKey, programName)
    75  	rawEnd1, err := proto.Marshal(hostAtt)
    76  	if err != nil {
    77  		t.Fatal("Error serializing attestation.")
    78  	}
    79  	rawEnd2 := hwCert.Raw
    80  	programAtt.SerializedEndorsements = [][]byte{rawEnd1, rawEnd2}
    81  	rawAtt, err := proto.Marshal(programAtt)
    82  	if err != nil {
    83  		t.Fatal("Error serializing attestation.")
    84  	}
    85  	certPool := x509.NewCertPool()
    86  	certPool.AddCert(policyCert)
    87  	speaker, key, prog, err := VerifyHostAttestation(rawAtt, domain, certPool)
    88  	if err != nil {
    89  		t.Fatal("Test attesation failed verification checks.", err)
    90  	}
    91  	if !programName.Identical(prog) {
    92  		t.Fatal("Attestation program name not identical to expected program name.")
    93  	}
    94  	if !programKey.SigningKey.ToPrincipal().Identical(key) {
    95  		t.Fatal("Attestation program key not identical to expected program key.")
    96  	}
    97  	if !hostKey.SigningKey.ToPrincipal().Identical(speaker) {
    98  		t.Fatal("Attestation host key not identical to expected host key.")
    99  	}
   100  }
   101  
   102  func TestVerifyHostAttestation_rootHost(t *testing.T) {
   103  	domain := generateDomain(t)
   104  	policyKey, policyCert := domain.Keys, domain.Keys.Cert
   105  	hostKey, hostAtt := generateAttestation(t, policyKey, hostName)
   106  	programKey, programAtt := generateAttestation(t, hostKey, programName)
   107  	rawEnd, err := proto.Marshal(hostAtt)
   108  	if err != nil {
   109  		t.Fatal("Error serializing attestation.")
   110  	}
   111  	programAtt.SerializedEndorsements = [][]byte{rawEnd}
   112  	rawAtt, err := proto.Marshal(programAtt)
   113  	if err != nil {
   114  		t.Fatal("Error serializing attestation.")
   115  	}
   116  	certPool := x509.NewCertPool()
   117  	certPool.AddCert(policyCert)
   118  	speaker, key, prog, err := VerifyHostAttestation(rawAtt, domain, certPool)
   119  	if err != nil {
   120  		t.Fatal("Test attesation failed verification checks.", err)
   121  	}
   122  	if !programName.Identical(prog) {
   123  		t.Fatal("Attestation program name not identical to expected program name.")
   124  	}
   125  	if !programKey.SigningKey.ToPrincipal().Identical(key) {
   126  		t.Fatal("Attestation program key not identical to expected program key.")
   127  	}
   128  	if !hostKey.SigningKey.ToPrincipal().Identical(speaker) {
   129  		t.Fatal("Attestation host key not identical to expected host key.")
   130  	}
   131  }
   132  
   133  func TestGenerateProgramCert(t *testing.T) {
   134  	domain := generateDomain(t)
   135  	programKey, err := tao.NewTemporaryKeys(tao.Signing)
   136  	if err != nil {
   137  		t.Fatal("Error generating keys.", err)
   138  	}
   139  	cert, err := GenerateProgramCert(domain, 0, programName, programKey.VerifyingKey,
   140  		time.Now(), time.Now().AddDate(1, 0, 0))
   141  	rootCerts := x509.NewCertPool()
   142  	rootCerts.AddCert(domain.Keys.Cert)
   143  	options := x509.VerifyOptions{Roots: rootCerts}
   144  	_, err = cert.Verify(options)
   145  	if err != nil {
   146  		t.Fatal("Program cert fails verification check.", err)
   147  	}
   148  }
   149  
   150  func TestValidateEndorsementCert(t *testing.T) {
   151  	aikblob, err := ioutil.ReadFile("./aikblob")
   152  	if err != nil {
   153  		t.Skip("Skipping tests, since there's no ./aikblob file")
   154  	}
   155  	tpmtao, err := tao.NewTPMTao("/dev/tpm0", aikblob, []int{17, 18}, nil)
   156  	if err != nil {
   157  		t.Skip("Couldn't create a new TPM Tao:", err)
   158  	}
   159  	tt, ok := tpmtao.(*tao.TPMTao)
   160  	if !ok {
   161  		t.Fatal("Failed to create the right kind of Tao object from NewTPMTao")
   162  	}
   163  	defer tao.CleanUpTPMTao(tt)
   164  	hwPublicKey, err := tpm.UnmarshalRSAPublicKey(aikblob)
   165  	if err != nil {
   166  		t.Fatal(err)
   167  	}
   168  
   169  	domain := generateDomain(t)
   170  	policyKey, policyCert := domain.Keys, domain.Keys.Cert
   171  	hwCert := generateEndorsementCertficate(t, policyKey, hwPublicKey, policyCert)
   172  	rootCerts := x509.NewCertPool()
   173  	rootCerts.AddCert(policyCert)
   174  	taoname, err := tt.GetTaoName()
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	err = validateEndorsementCertificate(hwCert, *generateGuard(t), &taoname, rootCerts)
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  }
   183  
   184  func TestInitAcls(t *testing.T) {
   185  	if _, err := os.Stat("./tmpdir"); os.IsNotExist(err) {
   186  		err = os.Mkdir("./tmpdir", 0777)
   187  		if err != nil {
   188  			t.Fatal(err)
   189  		}
   190  	}
   191  	trustedEntities := TrustedEntities{
   192  		TrustedProgramTaoNames: []string{fmt.Sprintf("%v", programName)},
   193  		TrustedHostTaoNames:    []string{fmt.Sprintf("%v", hostName)},
   194  		TrustedMachineInfos:    []string{machineName}}
   195  	f, err := os.Create("./tmpdir/TrustedEntities")
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	err = proto.MarshalText(f, &trustedEntities)
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  	err = f.Close()
   204  	if err != nil {
   205  		t.Fatal(err)
   206  	}
   207  	aclGuardType := "ACLs"
   208  	aclGuardPath := "acls"
   209  	cfg := tao.DomainConfig{
   210  		DomainInfo: &tao.DomainDetails{
   211  			GuardType: &aclGuardType},
   212  		AclGuardInfo: &tao.ACLGuardDetails{
   213  			SignedAclsPath: &aclGuardPath}}
   214  	domain, err := tao.CreateDomain(cfg, "./tmpdir/domain", []byte("xxx"))
   215  	if err != nil {
   216  		t.Fatal(err)
   217  	}
   218  	err = InitAcls(domain, "./tmpdir/TrustedEntities")
   219  	if err != nil {
   220  		t.Fatal(err)
   221  	}
   222  	machinePrin := auth.Prin{
   223  		Type:    "MachineInfo",
   224  		KeyHash: auth.Str(machineName),
   225  	}
   226  	if !domain.Guard.IsAuthorized(*programName, "Execute", []string{}) ||
   227  		!domain.Guard.IsAuthorized(*hostName, "Host", []string{}) ||
   228  		!domain.Guard.IsAuthorized(machinePrin, "Root", []string{}) {
   229  		t.Fatal("Authorization checks fail")
   230  	}
   231  	err = os.RemoveAll("./tmpdir")
   232  	if err != nil {
   233  		t.Fatal(err)
   234  	}
   235  }
   236  
   237  func TestRevokeCertificate(t *testing.T) {
   238  	k, err := tao.NewTemporaryKeys(tao.Signing)
   239  	if k == nil || err != nil {
   240  		t.Fatal("Can't generate signing key")
   241  	}
   242  	serialNumber := big.NewInt(5)
   243  	says := auth.Says{
   244  		Speaker: k.SigningKey.ToPrincipal(),
   245  		Message: auth.Pred{
   246  			Name: "revoke",
   247  			Arg:  []auth.Term{auth.Bytes(serialNumber.Bytes())}}}
   248  
   249  	att, err := tao.GenerateAttestation(k.SigningKey, nil, says)
   250  	if err != nil {
   251  		t.Fatal("Error generating attestation.")
   252  	}
   253  	serAtt, err := proto.Marshal(att)
   254  	if err != nil {
   255  		t.Fatal("Error serializing attestation.")
   256  	}
   257  	revokedCerts := []pkix.RevokedCertificate{}
   258  	revokedCerts, err = RevokeCertificate(serAtt, revokedCerts, &tao.Domain{Keys: k})
   259  	if err != nil {
   260  		t.Fatal(err)
   261  	}
   262  	if num := revokedCerts[0].SerialNumber.Int64(); num != 5 {
   263  		t.Fatal(fmt.Sprintf("Serial number %v doesnt match expected value 5", num))
   264  	}
   265  }
   266  
   267  func generateDomain(t *testing.T) *tao.Domain {
   268  	domain := tao.Domain{}
   269  	domain.Keys, domain.Keys.Cert = generatePolicyKey(t)
   270  	domain.Guard = *generateGuard(t)
   271  	domain.Config = tao.DomainConfig{X509Info: x509Info}
   272  	return &domain
   273  }
   274  
   275  func generatePolicyKey(t *testing.T) (*tao.Keys, *x509.Certificate) {
   276  	k, err := tao.NewTemporaryKeys(tao.Signing)
   277  	if k == nil || err != nil {
   278  		t.Fatal("Can't generate signing key")
   279  	}
   280  	us := "US"
   281  	google := "Google"
   282  	subjectName := "Policy"
   283  	details := tao.X509Details{
   284  		Country:      &us,
   285  		Organization: &google,
   286  		CommonName:   &subjectName}
   287  	subjectname := tao.NewX509Name(&details)
   288  	pkInt := tao.PublicKeyAlgFromSignerAlg(*k.SigningKey.Header.KeyType)
   289  	sigInt := tao.SignatureAlgFromSignerAlg(*k.SigningKey.Header.KeyType)
   290  	cert, err := k.SigningKey.CreateSelfSignedX509(pkInt, sigInt, int64(1), subjectname)
   291  	if err != nil {
   292  		t.Fatal("Can't self sign cert\n")
   293  	}
   294  	return k, cert
   295  }
   296  
   297  func generateEndorsementCertficate(t *testing.T, policyKey *tao.Keys, hwPublicKey *rsa.PublicKey,
   298  	policyCert *x509.Certificate) *x509.Certificate {
   299  	us := "US"
   300  	google := "Google"
   301  	details := tao.X509Details{
   302  		Country:      &us,
   303  		Organization: &google,
   304  		CommonName:   &machineName}
   305  	subject := tao.NewX509Name(&details)
   306  	pkInt := tao.PublicKeyAlgFromSignerAlg(*policyKey.SigningKey.Header.KeyType)
   307  	sigInt := tao.SignatureAlgFromSignerAlg(*policyKey.SigningKey.Header.KeyType)
   308  	signTemplate := tao.PrepareX509Template(pkInt, sigInt, int64(1), subject)
   309  	derSignedCert, err := x509.CreateCertificate(rand.Reader, signTemplate, policyCert,
   310  		hwPublicKey, policyKey.SigningKey)
   311  	if err != nil {
   312  		t.Fatal(err)
   313  	}
   314  	cert, err := x509.ParseCertificate(derSignedCert)
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  	return cert
   319  }
   320  
   321  func generateTpmAttestation(t *testing.T, tpmtao *tao.TPMTao, delegator *auth.Prin) (*tao.Keys,
   322  	*tao.Attestation) {
   323  	k, err := tao.NewTemporaryKeys(tao.Signing)
   324  	if k == nil || err != nil {
   325  		t.Fatal("Can't generate signing key")
   326  	}
   327  	speaksFor := &auth.Speaksfor{
   328  		Delegate:  k.SigningKey.ToPrincipal(),
   329  		Delegator: delegator,
   330  	}
   331  	taoname, err := tpmtao.GetTaoName()
   332  	if err != nil {
   333  		t.Fatal("Couldn't get the name of the tao:", err)
   334  	}
   335  	says := &auth.Says{
   336  		Speaker:    taoname,
   337  		Time:       nil,
   338  		Expiration: nil,
   339  		Message:    speaksFor,
   340  	}
   341  
   342  	att, err := tpmtao.Attest(&taoname, nil, nil, says)
   343  	if err != nil {
   344  		t.Fatal("TPM couldn't attest:", err)
   345  	}
   346  	return k, att
   347  }
   348  
   349  func generateAttestation(t *testing.T, signingKey *tao.Keys, delegator *auth.Prin) (*tao.Keys,
   350  	*tao.Attestation) {
   351  	k, err := tao.NewTemporaryKeys(tao.Signing)
   352  	if k == nil || err != nil {
   353  		t.Fatal("Can't generate signing key")
   354  	}
   355  	speaksFor := &auth.Speaksfor{
   356  		Delegate:  k.SigningKey.ToPrincipal(),
   357  		Delegator: delegator,
   358  	}
   359  	says := &auth.Says{
   360  		Speaker:    signingKey.SigningKey.ToPrincipal(),
   361  		Time:       nil,
   362  		Expiration: nil,
   363  		Message:    speaksFor,
   364  	}
   365  
   366  	att, err := tao.GenerateAttestation(signingKey.SigningKey, nil, *says)
   367  	if err != nil {
   368  		t.Fatal("Error generating attestation:", err)
   369  	}
   370  	return k, att
   371  }
   372  
   373  func generateGuard(t *testing.T) *tao.Guard {
   374  	guard := tao.NewACLGuard(nil, tao.ACLGuardDetails{})
   375  	err := guard.Authorize(*hostName, "Host", []string{})
   376  	if err != nil {
   377  		t.Fatal("Error adding a rule to the guard", err)
   378  	}
   379  	err = guard.Authorize(*programName, "Execute", []string{})
   380  	if err != nil {
   381  		t.Fatal("Error adding a rule to the guard", err)
   382  	}
   383  	machinePrin := auth.Prin{Type: "MachineInfo", KeyHash: auth.Str(machineName)}
   384  	err = guard.Authorize(machinePrin, "Root", []string{})
   385  	if err != nil {
   386  		t.Fatal("Error adding a rule to the guard", err)
   387  	}
   388  	return &guard
   389  }