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 }