github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/support_libraries/protected_objects/protected_obj.go (about)

     1  // Copyright (c) 2014, 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 protected_objects stores, searches and chains protected objects like keys
    16  // and files.
    17  
    18  package protected_objects
    19  
    20  import (
    21  	"container/list"
    22  	"errors"
    23  	"fmt"
    24  	"io/ioutil"
    25  	"time"
    26  
    27  	"github.com/golang/protobuf/proto"
    28  	"github.com/jlmucb/cloudproxy/go/tao"
    29  )
    30  
    31  func PrintObject(obj *ObjectMessage) {
    32  	fmt.Printf("Object %s, epoch %d\n", *obj.ObjId.ObjName, *obj.ObjId.ObjEpoch)
    33  	if obj.ObjType != nil {
    34  		fmt.Printf("\ttype %s\n", *obj.ObjType)
    35  	}
    36  	if obj.ObjStatus != nil {
    37  		fmt.Printf("\tstatus %s\n", *obj.ObjStatus)
    38  	}
    39  	if obj.NotBefore != nil  && obj.NotBefore != nil {
    40  		fmt.Printf("\tnotbefore: %s, notafter: %s\n", *obj.NotBefore, *obj.NotAfter)
    41  	}
    42  	if obj.ObjVal != nil {
    43  		fmt.Printf("Object value: %x\n", obj.ObjVal)
    44  	} else {
    45  		fmt.Printf("Object value: nil\n")
    46  	}
    47  }
    48  
    49  func PrintProtectedObject(obj *ProtectedObjectMessage) {
    50  	fmt.Printf("Object %s, epoch %d protects ", *obj.ProtectorObjId.ObjName, *obj.ProtectorObjId.ObjEpoch)
    51  	fmt.Printf("Object %s, epoch %d\n", *obj.ProtectedObjId.ObjName, *obj.ProtectedObjId.ObjEpoch)
    52  }
    53  
    54  // Generic string matcher
    55  //	if names list is nil, anything matches
    56  //	otherwise name must match one string in names list
    57  func stringMatch(name *string, names []string) bool {
    58  	if names == nil {
    59  		return true
    60  	}
    61  	if name == nil {
    62  		return false
    63  	}
    64  	for _, v := range names {
    65  		if v == *name {
    66  			return true
    67  		}
    68  	}
    69  	return false
    70  }
    71  
    72  // Create the object with the provided data.
    73  func CreateObject(name string, epoch int32, obj_type *string, status *string, notBefore *time.Time,
    74  	notAfter *time.Time, v []byte) (*ObjectMessage, error) {
    75  	obj_id := &ObjectIdMessage{
    76  		ObjName:  &name,
    77  		ObjEpoch: &epoch,
    78  	}
    79  	str_notBefore := notBefore.String()
    80  	str_notAfter := notAfter.String()
    81  	obj := &ObjectMessage{
    82  		ObjId:     obj_id,
    83  		ObjType:   obj_type,
    84  		ObjStatus: status,
    85  		NotBefore: &str_notBefore,
    86  		NotAfter:  &str_notAfter,
    87  		ObjVal:    v,
    88  	}
    89  	return obj, nil
    90  }
    91  
    92  // Add the indicated objectid to the list.
    93  func AddObjectId(l *list.List, obj ObjectIdMessage) error {
    94  	for e := l.Front(); e != nil; e = e.Next() {
    95  		o := e.Value.(ObjectIdMessage)
    96  		if o.ObjName == obj.ObjName && o.ObjEpoch == obj.ObjEpoch {
    97  			return nil
    98  		}
    99  	}
   100  	l.PushFront(interface{}(obj))
   101  	return nil
   102  }
   103  
   104  // Add the indicated protected object to the list.
   105  func AddObject(l *list.List, obj ObjectMessage) error {
   106  	for e := l.Front(); e != nil; e = e.Next() {
   107  		o := e.Value.(ObjectMessage)
   108  		if o.ObjId.ObjName == obj.ObjId.ObjName && o.ObjId.ObjEpoch == obj.ObjId.ObjEpoch {
   109  			return nil
   110  		}
   111  	}
   112  	l.PushFront(interface{}(obj))
   113  	return nil
   114  }
   115  
   116  // Add the indicated protected object to the list.
   117  func AddProtectedObject(l *list.List, obj ProtectedObjectMessage) error {
   118  	for e := l.Front(); e != nil; e = e.Next() {
   119  		o := e.Value.(ProtectedObjectMessage)
   120  		if o.ProtectedObjId.ObjName == obj.ProtectedObjId.ObjName &&
   121  			o.ProtectedObjId.ObjEpoch == obj.ProtectedObjId.ObjEpoch &&
   122  			o.ProtectorObjId.ObjName == obj.ProtectorObjId.ObjName &&
   123  			o.ProtectorObjId.ObjEpoch == obj.ProtectorObjId.ObjEpoch {
   124  			return nil
   125  		}
   126  	}
   127  	l.PushFront(interface{}(obj))
   128  	return nil
   129  }
   130  
   131  // Remove the referenced object from the list.
   132  func DeleteObject(l *list.List, name string, epoch int32) error {
   133  	for e := l.Front(); e != nil; e = e.Next() {
   134  		o := e.Value.(ObjectMessage)
   135  		if *o.ObjId.ObjName == name && *o.ObjId.ObjEpoch == epoch {
   136  			l.Remove(e)
   137  			break
   138  		}
   139  	}
   140  	return nil
   141  }
   142  
   143  // Remove the referenced protected object from the list.
   144  func DeleteProtectedObject(l *list.List, name string, epoch int32) error {
   145  	for e := l.Front(); e != nil; e = e.Next() {
   146  		o := e.Value.(ProtectedObjectMessage)
   147  		if *o.ProtectedObjId.ObjName == name && *o.ProtectedObjId.ObjEpoch == epoch {
   148  			l.Remove(e)
   149  			break
   150  		}
   151  	}
   152  	return nil
   153  }
   154  
   155  // Find objects protected by object with given name and epoch.
   156  func FindProtectedObjects(l *list.List, name string, epoch int32) *list.List {
   157  	r := list.New()
   158  
   159  	for e := l.Front(); e != nil; e = e.Next() {
   160  		o := e.Value.(ProtectedObjectMessage)
   161  		if epoch != 0 && epoch != *o.ProtectorObjId.ObjEpoch {
   162  			continue
   163  		}
   164  		if name == *o.ProtectorObjId.ObjName {
   165  			r.PushFront(o)
   166  		}
   167  	}
   168  	return r
   169  }
   170  
   171  // Find protectors of the object with given name and epoch.
   172  func FindProtectorObjects(l *list.List, name string, epoch int32) *list.List {
   173  	r := list.New()
   174  
   175  	for e := l.Front(); e != nil; e = e.Next() {
   176  		o := e.Value.(ProtectedObjectMessage)
   177  		if epoch != 0 && epoch != *o.ProtectedObjId.ObjEpoch {
   178  			continue
   179  		}
   180  		if name == *o.ProtectedObjId.ObjName {
   181  			r.PushFront(o)
   182  		}
   183  	}
   184  	return r
   185  }
   186  
   187  func FindElementById(l *list.List, name string, epoch int32) *list.Element {
   188  	var elem *list.Element = nil
   189  	for e := l.Front(); e != nil; e = e.Next() {
   190  		o := e.Value.(ProtectedObjectMessage)
   191  		if epoch != 0 && epoch != *o.ProtectedObjId.ObjEpoch {
   192  			continue
   193  		}
   194  		if name == *o.ProtectedObjId.ObjName {
   195  			elem = e
   196  		}
   197  	}
   198  	return elem
   199  }
   200  
   201  // Find object with given name, epoch, with one of the offered types and names.
   202  // A nil types or names list matches anything (even nil)
   203  func FindObject(l *list.List, name string, epoch int32, types []string,
   204  	statuses []string) *ObjectMessage {
   205  	for e := l.Front(); e != nil; e = e.Next() {
   206  		o := e.Value.(ObjectMessage)
   207  		if !stringMatch(o.ObjStatus, statuses) || !stringMatch(o.ObjType, statuses) {
   208  			continue
   209  		}
   210  		if epoch != 0 && epoch != *o.ObjId.ObjEpoch {
   211  			continue
   212  		}
   213  		if name == *o.ObjId.ObjName {
   214  			return &o
   215  		}
   216  	}
   217  	return nil
   218  }
   219  
   220  // Get object with given name and latest epoch.
   221  func GetLatestEpoch(l *list.List, name string, status []string) *ObjectMessage {
   222  	latest := 0
   223  	var result *ObjectMessage
   224  	for e := l.Front(); e != nil; e = e.Next() {
   225  		o := e.Value.(ObjectMessage)
   226  		PrintObject(&o)
   227  		if *o.ObjId.ObjName != name {
   228  			continue
   229  		}
   230  		if o.ObjId.ObjEpoch == nil {
   231  			continue
   232  		}
   233  		if result == nil {
   234  			result = &o
   235  			latest = int(*o.ObjId.ObjEpoch)
   236  			continue
   237  		}
   238  		if int(*o.ObjId.ObjEpoch) > latest {
   239  			latest = int(*o.ObjId.ObjEpoch)
   240  			result = &o
   241  		}
   242  	}
   243  	return result
   244  }
   245  
   246  // Get object with given name and earliest epoch.
   247  func GetEarliestEpoch(l *list.List, name string, status []string) *ObjectMessage {
   248  	earliest := 0
   249  	var result *ObjectMessage
   250  	for e := l.Front(); e != nil; e = e.Next() {
   251  		o := e.Value.(ObjectMessage)
   252  		if *o.ObjId.ObjName != name {
   253  			continue
   254  		}
   255  		if o.ObjId.ObjEpoch == nil {
   256  			continue
   257  		}
   258  		if result == nil {
   259  			result = &o
   260  			earliest = int(*o.ObjId.ObjEpoch)
   261  			continue
   262  		}
   263  		if earliest == 0 || int(*o.ObjId.ObjEpoch) < earliest {
   264  			earliest = int(*o.ObjId.ObjEpoch)
   265  			result = &o
   266  		}
   267  	}
   268  	return result
   269  }
   270  
   271  // Marshal protected objects and save them in a file.
   272  // nil is error return
   273  func SaveProtectedObjects(l *list.List, file string) error {
   274  	var po_store ProtectedObjectStoreMessage
   275  
   276  	for e := l.Front(); e != nil; e = e.Next() {
   277  		o := e.Value.(ProtectedObjectMessage)
   278  		p := new(ProtectedObjectMessage)
   279  		p.ProtectedObjId.ObjName = o.ProtectedObjId.ObjName
   280  		p.ProtectedObjId.ObjEpoch = o.ProtectedObjId.ObjEpoch
   281  		p.ProtectorObjId.ObjName = o.ProtectorObjId.ObjName
   282  		p.ProtectorObjId.ObjEpoch = o.ProtectorObjId.ObjEpoch
   283  		p.Blob = o.Blob
   284  		po_store.ProtectedObjects = append(po_store.ProtectedObjects, p)
   285  	}
   286  	b, err := proto.Marshal(&po_store)
   287  	if err != nil {
   288  		return err
   289  	}
   290  	ioutil.WriteFile(file, b, 0644)
   291  	return nil
   292  }
   293  
   294  // Marshal objects and save them in a file.
   295  // nil is error return
   296  func SaveObjects(l *list.List, file string) error {
   297  	var o_store ObjectStoreMessage
   298  
   299  	for e := l.Front(); e != nil; e = e.Next() {
   300  		o := e.Value.(ObjectMessage)
   301  		p := new(ObjectMessage)
   302  		p.ObjId = new(ObjectIdMessage)
   303  		p.ObjId.ObjName = o.ObjId.ObjName
   304  		p.ObjId.ObjEpoch = o.ObjId.ObjEpoch
   305  		p.ObjType = o.ObjType
   306  		p.ObjStatus = o.ObjStatus
   307  		p.NotBefore = o.NotBefore
   308  		p.NotAfter = o.NotAfter
   309  		p.ObjVal = o.ObjVal
   310  		o_store.Objects = append(o_store.Objects, p)
   311  	}
   312  	b, err := proto.Marshal(&o_store)
   313  	if err != nil {
   314  		return nil
   315  	}
   316  	ioutil.WriteFile(file, b, 0644)
   317  	return nil
   318  }
   319  
   320  // Read and unmarshal an protected object file.
   321  func LoadProtectedObjects(file string) *list.List {
   322  	var po_store ProtectedObjectStoreMessage
   323  
   324  	buf, err := ioutil.ReadFile(file)
   325  	if err != nil {
   326  		return nil
   327  	}
   328  	err = proto.Unmarshal(buf, &po_store)
   329  	if err != nil {
   330  		return nil
   331  	}
   332  	l := list.New()
   333  	for _, v := range po_store.ProtectedObjects {
   334  		o := new(ProtectedObjectMessage)
   335  		o.ProtectorObjId.ObjName = v.ProtectorObjId.ObjName
   336  		o.ProtectorObjId.ObjEpoch = v.ProtectorObjId.ObjEpoch
   337  		o.ProtectedObjId.ObjName = v.ProtectedObjId.ObjName
   338  		o.ProtectedObjId.ObjEpoch = v.ProtectedObjId.ObjEpoch
   339  		o.Blob = v.Blob
   340  		l.PushFront(*o)
   341  	}
   342  	return l
   343  }
   344  
   345  // Read and unmarshal an object file.
   346  func LoadObjects(file string) *list.List {
   347  	var o_store ObjectStoreMessage
   348  
   349  	buf, err := ioutil.ReadFile(file)
   350  	if err != nil {
   351  		return nil
   352  	}
   353  	err = proto.Unmarshal(buf, &o_store)
   354  	if err != nil {
   355  		return nil
   356  	}
   357  	l := list.New()
   358  	for _, v := range o_store.Objects {
   359  		o := new(ObjectMessage)
   360  		o.ObjId = new(ObjectIdMessage)
   361  		o.ObjId.ObjName = v.ObjId.ObjName
   362  		o.ObjId.ObjEpoch = v.ObjId.ObjEpoch
   363  
   364  		o.ObjType = v.ObjType
   365  		o.ObjStatus = v.ObjStatus
   366  		o.NotBefore = v.NotBefore
   367  		o.NotAfter = v.NotAfter
   368  		o.ObjVal = v.ObjVal
   369  		l.PushFront(*o)
   370  	}
   371  	return l
   372  }
   373  
   374  // Create, marshal and encrypt a protected object blob protecting obj.
   375  func MakeProtectedObject(obj ObjectMessage, protectorName string, protectorEpoch int32,
   376  	protectorKeys []byte) (*ProtectedObjectMessage, error) {
   377  	p := new(ProtectedObjectMessage)
   378  	p.ProtectedObjId = new(ObjectIdMessage)
   379  	p.ProtectorObjId = new(ObjectIdMessage)
   380  	p.ProtectedObjId.ObjName = obj.ObjId.ObjName
   381  	p.ProtectedObjId.ObjEpoch = obj.ObjId.ObjEpoch
   382  	p.ProtectorObjId.ObjName = &protectorName
   383  	p.ProtectorObjId.ObjEpoch = &protectorEpoch
   384  	unencrypted, err := proto.Marshal(&obj)
   385  	if err != nil {
   386  		return nil, errors.New("Can't make Protected Object: " + err.Error())
   387  	}
   388  	encrypted, err := tao.Protect(protectorKeys, unencrypted)
   389  	if err != nil {
   390  		return nil, errors.New("Can't Protect Object")
   391  	}
   392  	p.Blob = encrypted
   393  	return p, nil
   394  }
   395  
   396  // Decrypt and unmarshal a protected object blob
   397  func RecoverProtectedObject(obj *ProtectedObjectMessage, protectorKeys []byte) (*ObjectMessage, error) {
   398  	p := new(ObjectMessage)
   399  	unencrypted, err := tao.Unprotect(protectorKeys, obj.Blob)
   400  	if err != nil {
   401  		return nil, errors.New("Can't make Unprotect Object")
   402  	}
   403  	err = proto.Unmarshal(unencrypted, p)
   404  	if err != nil {
   405  		return nil, errors.New("Can't Unmarshal Object")
   406  	}
   407  	return p, nil
   408  }
   409  
   410  // Is object the right type, have the right status and in it's validity period?
   411  func IsValid(obj ObjectMessage, statuses []string, types []string) bool {
   412  	// if object is not active or the dates are wrong, return false
   413  	if !stringMatch(obj.ObjStatus, statuses) {
   414  		return false
   415  	}
   416  	if !stringMatch(obj.ObjType, types) {
   417  		return false
   418  	}
   419  	tb, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", *obj.NotBefore)
   420  	if err != nil {
   421  		return false
   422  	}
   423  	ta, err := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", *obj.NotAfter)
   424  	if err != nil {
   425  		return false
   426  	}
   427  	tn := time.Now()
   428  	if tb.After(tn) || ta.Before(tn) {
   429  		return false
   430  	}
   431  	return true
   432  }
   433  
   434  // Construct chain of protector objects for (nameProtector, epochProtector)
   435  // Stops when there are no protectors for top object
   436  func ConstructProtectorChain(obj_list *list.List, nameProtector string, epochProtector int32,
   437  	nameTop *string, epochTop *int32,
   438  	statuses []string, types []string, seen_list *list.List,
   439  	protected_object_list *list.List) (*list.List, error) {
   440  
   441  	if nameTop != nil && *nameTop == nameProtector {
   442  		if epochTop == nil || *epochTop == epochProtector {
   443  			return seen_list, nil
   444  		}
   445  	}
   446  	pl := FindProtectedObjects(protected_object_list, nameProtector, epochProtector)
   447  	if pl == nil {
   448  		return nil, errors.New("FindProtectedObject error")
   449  	}
   450  	for e := pl.Front(); e != nil; e = e.Next() {
   451  		o := e.Value.(ProtectedObjectMessage)
   452  		t := FindObject(seen_list, *o.ProtectorObjId.ObjName,
   453  			*o.ProtectorObjId.ObjEpoch, statuses, types)
   454  		if t != nil {
   455  			return nil, errors.New("Circular list")
   456  		}
   457  		t = FindObject(obj_list, *o.ProtectorObjId.ObjName,
   458  			*o.ProtectorObjId.ObjEpoch, statuses, types)
   459  		if t == nil {
   460  			return seen_list, nil
   461  		}
   462  		if !IsValid(*t, statuses, types) {
   463  			continue
   464  		}
   465  		AddObject(seen_list, *t)
   466  		return ConstructProtectorChain(obj_list,
   467  			*o.ProtectorObjId.ObjName, *o.ProtectorObjId.ObjEpoch,
   468  			nameTop, epochTop,
   469  			statuses, types, seen_list, protected_object_list)
   470  	}
   471  	return seen_list, nil
   472  }
   473  
   474  // Construct chain of protector objects for (nameProtected, epochProtected)
   475  //	Chain must terminate with an object from the base list
   476  func ConstructProtectorChainFromBase(obj_list *list.List, nameProtected string, epochProtected int32,
   477  	statuses []string, types []string, base_list *list.List,
   478  	seen_list *list.List, protected_object_list *list.List) (*list.List, error) {
   479  
   480  	// if object is in base list, we're done
   481  	for e := base_list.Front(); e != nil; e = e.Next() {
   482  		o := e.Value.(ObjectIdMessage)
   483  		if *o.ObjName == nameProtected {
   484  			if o.ObjEpoch == nil || *o.ObjEpoch == epochProtected {
   485  				return seen_list, nil
   486  			}
   487  		}
   488  	}
   489  
   490  	pl := FindProtectorObjects(protected_object_list, nameProtected, epochProtected)
   491  	if pl == nil {
   492  		return nil, errors.New("FindProtectorobjects error")
   493  	}
   494  	for e := pl.Front(); e != nil; e = e.Next() {
   495  		o := e.Value.(ProtectedObjectMessage)
   496  		t := FindObject(seen_list, *o.ProtectorObjId.ObjName,
   497  			*o.ProtectorObjId.ObjEpoch, statuses, types)
   498  		if t != nil {
   499  			return nil, errors.New("Circular list")
   500  		}
   501  		t = FindObject(obj_list, *o.ProtectorObjId.ObjName,
   502  			*o.ProtectorObjId.ObjEpoch, statuses, types)
   503  		if !IsValid(*t, statuses, types) {
   504  			continue
   505  		}
   506  		AddObject(seen_list, *t)
   507  		return ConstructProtectorChainFromBase(obj_list,
   508  			*o.ProtectorObjId.ObjName, *o.ProtectorObjId.ObjEpoch,
   509  			statuses, types, base_list, seen_list, protected_object_list)
   510  	}
   511  	return nil, errors.New("Can't find any base value")
   512  }