github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/support_libraries/secret_disclosure_support/secret_disclosure_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 secret_disclosure contains functions which create, interpret and verify
    16  // secret disclosure directives of the following form:
    17  // 'policyKey says programName can read protectedObjectId'
    18  
    19  package secret_disclosure
    20  
    21  import (
    22  	"bytes"
    23  	"fmt"
    24  	"os"
    25  	"testing"
    26  
    27  	"github.com/golang/protobuf/proto"
    28  	po "github.com/jlmucb/cloudproxy/go/support_libraries/protected_objects"
    29  	"github.com/jlmucb/cloudproxy/go/tao"
    30  	"github.com/jlmucb/cloudproxy/go/tao/auth"
    31  )
    32  
    33  var Delegate = auth.Prin{
    34  	Type: "program",
    35  	KeyHash:  auth.Bytes([]byte(`fake program`)),
    36  }
    37  
    38  var Delegator = auth.Prin{
    39  	Type: "program",
    40  	KeyHash:  auth.Bytes([]byte(`speaker program`)),
    41  }
    42  
    43  var ProtectedObjectName = "obj_name"
    44  var ProtectedObjectEpoch = int32(0)
    45  var ProtectedObjectId = po.ObjectIdMessage{
    46  	ObjName:  &ProtectedObjectName,
    47  	ObjEpoch: &ProtectedObjectEpoch,
    48  }
    49  
    50  var us = "US"
    51  var google = "Google"
    52  var x509Info = tao.X509Details{
    53  	Country:      &us,
    54  	Organization: &google}
    55  
    56  func TestProcessDirectiveAndUpdateGuard(t *testing.T) {
    57  	domain := setUpDomain(t)
    58  	err := domain.Guard.Authorize(Delegator, OwnPredicate,
    59  		[]string{ProtectedObjectId.String()})
    60  	failOnError(t, err)
    61  
    62  	programKey, err := tao.NewTemporaryKeys(tao.Signing)
    63  	failOnError(t, err)
    64  	info := x509Info
    65  	speakerStr := Delegator.String()
    66  	info.CommonName = &speakerStr
    67  	subject := tao.NewX509Name(&info)
    68  	pkInt := tao.PublicKeyAlgFromSignerAlg(*domain.Keys.SigningKey.Header.KeyType)
    69  	sigInt := tao.SignatureAlgFromSignerAlg(*domain.Keys.SigningKey.Header.KeyType)
    70  	programKey.Cert, err = domain.Keys.SigningKey.CreateSignedX509(
    71  		domain.Keys.Cert, 1, programKey.SigningKey.GetVerifierFromSigner(),
    72  		pkInt, sigInt, subject)
    73  	failOnError(t, err)
    74  	directive, err := CreateSecretDisclosureDirective(programKey, &Delegator,
    75  		&Delegate, ReadPredicate, &ProtectedObjectId)
    76  	failOnError(t, err)
    77  	directive.Cert = programKey.Cert.Raw
    78  
    79  	err = ProcessDirectiveAndUpdateGuard(domain, directive)
    80  	failOnError(t, err)
    81  
    82  	if !domain.Guard.IsAuthorized(Delegate, ReadPredicate,
    83  		[]string{ProtectedObjectId.String()}) {
    84  		t.Fatal("Domain guard not updated as expected.")
    85  	}
    86  
    87  	tearDown(t)
    88  }
    89  
    90  func TestCreateDirective(t *testing.T) {
    91  	policyKey, testDirective, err := generatePolicyKeyAndSignedDirective(Params{})
    92  	failOnError(t, err)
    93  	signer := policyKey.SigningKey.ToPrincipal()
    94  	directive, err := CreateSecretDisclosureDirective(policyKey, &signer, &Delegate,
    95  		ReadPredicate, &ProtectedObjectId)
    96  	failOnError(t, err)
    97  	signatureValid, err := policyKey.SigningKey.GetVerifierFromSigner().Verify(
    98  		directive.SerializedStatement, SigningContext, directive.Signature)
    99  	failOnError(t, err)
   100  	if !signatureValid {
   101  		t.Fatal("Signature on directive not valid")
   102  	}
   103  	if testDirective.GetType() != directive.GetType() ||
   104  		!bytes.Equal(testDirective.GetSerializedStatement(),
   105  			directive.GetSerializedStatement()) ||
   106  		!bytes.Equal(testDirective.GetSigner(), directive.GetSigner()) {
   107  		t.Fatal("Fields in directive do not match expected value")
   108  	}
   109  }
   110  
   111  func TestVerifyDirective(t *testing.T) {
   112  	policyKey, directive, err := generatePolicyKeyAndSignedDirective(Params{})
   113  	failOnError(t, err)
   114  	prin, programName, pred, protectedObjectId, err :=
   115  		VerifySecretDisclosureDirective(policyKey, directive)
   116  	failOnError(t, err)
   117  	if !prin.Identical(policyKey.SigningKey.ToPrincipal()) {
   118  		t.Fatal("Verify returns different speaker principal from expected value.")
   119  	}
   120  	if !Delegate.Identical(programName) {
   121  		t.Fatal("Verify returns different programName from expected value.")
   122  	}
   123  	if *pred != ReadPredicate {
   124  		t.Fatal("Verify returns different predicate name from expected value.")
   125  	}
   126  	if *protectedObjectId.ObjName != *ProtectedObjectId.ObjName ||
   127  		*protectedObjectId.ObjEpoch != *ProtectedObjectId.ObjEpoch {
   128  		t.Fatal("Verify returns different protectedObjectId from expected value.")
   129  	}
   130  }
   131  
   132  func TestCreateAndVerifyDirective(t *testing.T) {
   133  	policyKey, _, err := generatePolicyKeyAndSignedDirective(Params{})
   134  	failOnError(t, err)
   135  	signer := policyKey.SigningKey.ToPrincipal()
   136  	directive, err := CreateSecretDisclosureDirective(policyKey, &signer, &Delegate,
   137  		ReadPredicate, &ProtectedObjectId)
   138  	failOnError(t, err)
   139  	prin, programName, pred, protectedObjectId, err := VerifySecretDisclosureDirective(policyKey,
   140  		directive)
   141  	failOnError(t, err)
   142  	if !prin.Identical(policyKey.SigningKey.ToPrincipal()) {
   143  		t.Fatal("Verify returns different speaker principal from expected value.")
   144  	}
   145  	if !Delegate.Identical(programName) {
   146  		t.Fatal("Verify returns different programName from expected value.")
   147  	}
   148  	if *pred != ReadPredicate {
   149  		t.Fatal("Verify returns different predicate name from expected value.")
   150  	}
   151  	if *protectedObjectId.ObjName != *ProtectedObjectId.ObjName ||
   152  		*protectedObjectId.ObjEpoch != *ProtectedObjectId.ObjEpoch {
   153  		t.Fatal("Verify returns different protectedObjectId from expected value.")
   154  	}
   155  }
   156  
   157  func TestCreateAndVerifyDirectiveSignedByProgram(t *testing.T) {
   158  	policyKey, _, err := generatePolicyKeyAndSignedDirective(Params{})
   159  	programKey, err := tao.NewTemporaryKeys(tao.Signing)
   160  	failOnError(t, err)
   161  	info := x509Info
   162  	speakerStr := Delegator.String()
   163  	info.CommonName = &speakerStr
   164  	subject := tao.NewX509Name(&info)
   165  	pkInt := tao.PublicKeyAlgFromSignerAlg(*policyKey.SigningKey.Header.KeyType)
   166  	sigInt := tao.SignatureAlgFromSignerAlg(*policyKey.SigningKey.Header.KeyType)
   167  	programKey.Cert, err = policyKey.SigningKey.CreateSignedX509(
   168  		policyKey.Cert, 1, programKey.SigningKey.GetVerifierFromSigner(), pkInt, sigInt, subject)
   169  	failOnError(t, err)
   170  	directive, err := CreateSecretDisclosureDirective(programKey, &Delegator,
   171  		&Delegate, ReadPredicate, &ProtectedObjectId)
   172  	failOnError(t, err)
   173  	directive.Cert = programKey.Cert.Raw
   174  
   175  	speaker, prog, pred, pobj, err := VerifySecretDisclosureDirective(policyKey, directive)
   176  	failOnError(t, err)
   177  	if !speaker.Identical(Delegator) {
   178  		t.Fatal(fmt.Sprintf("verify returns Speaker %v different from expected value %v",
   179  			speaker, Delegator))
   180  	}
   181  	if !prog.Identical(Delegate) {
   182  		t.Fatal(fmt.Sprintf("verify returns program  %v different from expected value %v",
   183  			prog, Delegate))
   184  	}
   185  	if *pred != ReadPredicate {
   186  		t.Fatal(fmt.Sprintf("verify returns predicate  %v different from expected value %v",
   187  			pred, ReadPredicate))
   188  	}
   189  	if *pobj.ObjName != *ProtectedObjectId.ObjName ||
   190  		*pobj.ObjEpoch != *ProtectedObjectId.ObjEpoch {
   191  		t.Fatal("Verify returns different protectedObjectId from expected value.")
   192  	}
   193  }
   194  
   195  func TestVerifyDirectiveWithBadType(t *testing.T) {
   196  	policyKey, testDirective, err := generatePolicyKeyAndSignedDirective(Params{})
   197  	failOnError(t, err)
   198  	testDirective.Type = nil
   199  	_, _, _, _, err = VerifySecretDisclosureDirective(policyKey, testDirective)
   200  	if err == nil {
   201  		t.Fatal("Verify output is not an error")
   202  	}
   203  }
   204  
   205  func TestVerifyDirectiveWithDifferentSignerAndPolicyKey(t *testing.T) {
   206  	params := Params{
   207  		Signer: []byte("Bad Signer"),
   208  	}
   209  	expectError(&params, t)
   210  }
   211  
   212  func TestVerifyDirectiveWithBadSignature(t *testing.T) {
   213  	params := Params{
   214  		Signature: []byte("Bad Signature"),
   215  	}
   216  	expectError(&params, t)
   217  }
   218  
   219  func TestVerifyDirectiveWithBadSays(t *testing.T) {
   220  	params := Params{
   221  		Says: auth.Const(true),
   222  	}
   223  	expectError(&params, t)
   224  }
   225  
   226  func TestVerifyDirectiveWithBadPredicate_badName(t *testing.T) {
   227  	params := Params{
   228  		CanRead: auth.Pred{
   229  			Name: "CanNotRead",
   230  		},
   231  	}
   232  	expectError(&params, t)
   233  }
   234  
   235  func TestVerifyDirectiveWithBadPredicate_badTerms(t *testing.T) {
   236  	params := Params{
   237  		CanRead: auth.Pred{
   238  			Name: ReadPredicate,
   239  			Arg:  []auth.Term{auth.Int(0), auth.Str(""), auth.Str("a")},
   240  			// TODO: Note make([]auth.Term, 3) above causes NPE in auth.Marshal(thisPred)
   241  			// Is that a bug?
   242  		},
   243  	}
   244  	expectError(&params, t)
   245  }
   246  
   247  func TestVerifyDirectiveWithBadDelegate(t *testing.T) {
   248  	params := Params{
   249  		Delegate: auth.Str(""),
   250  	}
   251  	expectError(&params, t)
   252  }
   253  
   254  func TestVerifyDirectiveWithBadProtectedObjectId_invalidType(t *testing.T) {
   255  	params := Params{
   256  		SerializedObjectId: auth.Str(""),
   257  	}
   258  	expectError(&params, t)
   259  }
   260  
   261  func TestVerifyDirectiveWithBadProtectedObjectId_invalidProtoBuf(t *testing.T) {
   262  	badBytes := []byte("bad bytes")
   263  	params := Params{
   264  		SerializedObjectId: auth.Bytes(badBytes),
   265  	}
   266  	expectError(&params, t)
   267  }
   268  
   269  func expectError(params *Params, t *testing.T) {
   270  	policyKey, testDirective, err := generatePolicyKeyAndSignedDirective(*params)
   271  	failOnError(t, err)
   272  	testDirective.Type = nil
   273  	_, _, _, _, err = VerifySecretDisclosureDirective(policyKey, testDirective)
   274  	if err == nil {
   275  		t.Fatal("Verify output is not an error")
   276  	}
   277  }
   278  
   279  func failOnError(t *testing.T, err error) {
   280  	if err != nil {
   281  		t.Fatal(err)
   282  	}
   283  }
   284  
   285  type Params struct {
   286  	Delegate           auth.Term
   287  	SerializedObjectId auth.Term
   288  	Says               auth.Form
   289  	CanRead            auth.Form
   290  	CanReadTerms       []auth.Term
   291  	Signer             []byte
   292  	Signature          []byte
   293  	DirectiveType      *DirectiveMessageDirectiveType
   294  }
   295  
   296  func generatePolicyKeyAndSignedDirective(params Params) (*tao.Keys, *DirectiveMessage, error) {
   297  	var programName auth.Term
   298  	if params.Delegate != nil {
   299  		programName = params.Delegate
   300  	} else {
   301  		programName = Delegate
   302  	}
   303  	var serializedObjectId auth.Term
   304  	if params.SerializedObjectId != nil {
   305  		serializedObjectId = params.SerializedObjectId
   306  	} else {
   307  		bytes, err := proto.Marshal(&ProtectedObjectId)
   308  		if err != nil {
   309  			return nil, nil, err
   310  		}
   311  		serializedObjectId = auth.Bytes(bytes)
   312  	}
   313  	terms := []auth.Term{programName, serializedObjectId}
   314  	if params.CanReadTerms != nil {
   315  		terms = params.CanReadTerms
   316  	}
   317  	var canRead auth.Form
   318  	if params.CanRead != nil {
   319  		canRead = params.CanRead
   320  	} else {
   321  		canRead = auth.Pred{
   322  			Name: ReadPredicate,
   323  			Arg:  terms,
   324  		}
   325  	}
   326  	policyKey, err := tao.NewTemporaryKeys(tao.Signing)
   327  	if err != nil {
   328  		return nil, nil, err
   329  	}
   330  	info := x509Info
   331  	name := policyKey.SigningKey.ToPrincipal().String()
   332  	info.CommonName = &name
   333  	subject := tao.NewX509Name(&info)
   334  	pkInt := tao.PublicKeyAlgFromSignerAlg(*policyKey.SigningKey.Header.KeyType)
   335  	sigInt := tao.SignatureAlgFromSignerAlg(*policyKey.SigningKey.Header.KeyType)
   336  	policyKey.Cert, err = policyKey.SigningKey.CreateSelfSignedX509(pkInt, sigInt, int64(1), subject)
   337  	if err != nil {
   338  		return nil, nil, err
   339  	}
   340  	var says auth.Form
   341  	if params.Says != nil {
   342  		says = params.Says
   343  	} else {
   344  		says = auth.Says{
   345  			Speaker:    policyKey.SigningKey.ToPrincipal(),
   346  			Time:       nil,
   347  			Expiration: nil,
   348  			Message:    canRead,
   349  		}
   350  	}
   351  	serializedSays := auth.Marshal(says)
   352  	var directiveType *DirectiveMessageDirectiveType
   353  	if params.DirectiveType != nil {
   354  		directiveType = params.DirectiveType
   355  	} else {
   356  		directiveType = DirectiveMessage_SECRET_DISCLOSURE.Enum()
   357  	}
   358  	var signature []byte
   359  	if params.Signature != nil {
   360  		signature = params.Signature
   361  	} else {
   362  		signature, err = policyKey.SigningKey.Sign(serializedSays, SigningContext)
   363  		if err != nil {
   364  			return nil, nil, err
   365  		}
   366  	}
   367  	var signer []byte
   368  	if params.Signer != nil {
   369  		signer = params.Signer
   370  	} else {
   371  		signer = auth.Marshal(policyKey.SigningKey.ToPrincipal())
   372  	}
   373  	directive := &DirectiveMessage{
   374  		Type:                directiveType,
   375  		SerializedStatement: serializedSays,
   376  		Signature:           signature,
   377  		Signer:              signer,
   378  	}
   379  	return policyKey, directive, nil
   380  }
   381  
   382  func setUpDomain(t *testing.T) *tao.Domain {
   383  	var err error
   384  	if _, err = os.Stat("./tmpdir"); os.IsNotExist(err) {
   385  		err = os.Mkdir("./tmpdir", 0777)
   386  		if err != nil {
   387  			t.Fatal(err)
   388  		}
   389  	}
   390  	aclGuardType := "ACLs"
   391  	aclGuardPath := "acls"
   392  	cfg := tao.DomainConfig{
   393  		DomainInfo: &tao.DomainDetails{
   394  			GuardType: &aclGuardType},
   395  		AclGuardInfo: &tao.ACLGuardDetails{
   396  			SignedAclsPath: &aclGuardPath}}
   397  	domain, err := tao.CreateDomain(cfg, "./tmpdir/domain", []byte("xxx"))
   398  	if err != nil {
   399  		t.Fatal(err)
   400  	}
   401  	return domain
   402  }
   403  
   404  func tearDown(t *testing.T) {
   405  	err := os.RemoveAll("./tmpdir")
   406  	if err != nil {
   407  		t.Fatal(err)
   408  	}
   409  }