"veyron/security": Make principal serializaiton backwards compatible

CL 6820 changed the serialization format for BlessingStores, as a result
of which principals serialized in the old format could no longer be
deserialized.

This turned out to be huge inconvenience as it required re-generating
credentials for all envyor binaries (pis, identity server, etc).

This CL restores support for the old serialization format. In
particular,
* Principals serialized according to the old format can be deserialized
* However, subsequent updates to the principal's state get saved in the
new format.

Once everyone has switched to the new serialization format, we will
remove support for the old one.

Change-Id: Icd1204c27e93fbb3cd710b072dbc7b621a47f2c8
diff --git a/security/blessingstore.go b/security/blessingstore.go
index 1a7540d..57ef450 100644
--- a/security/blessingstore.go
+++ b/security/blessingstore.go
@@ -175,18 +175,75 @@
 	}
 }
 
+// TODO(ataly, ashankar): Get rid of this struct once we have switched all credentials
+// directories to the new serialization format.
+type oldState struct {
+	Store   map[security.BlessingPattern]security.WireBlessings
+	Default security.WireBlessings
+}
+
+// TODO(ataly, ashankar): Get rid of this method once we have switched all
+// credentials directories to the new serialization format.
+func (bs *blessingStore) tryOldFormat() bool {
+	var empty security.WireBlessings
+	if len(bs.state.Store) == 0 {
+		return bs.state.Default == nil || reflect.DeepEqual(bs.state.Default.Value, empty)
+	}
+	for _, wb := range bs.state.Store {
+		if len(wb.Value.CertificateChains) == 0 {
+			return true
+		}
+	}
+	return false
+}
+
+// TODO(ataly, ashankar): Get rid of this method once we have switched all
+// credentials directories to the new serialization format.
+func (bs *blessingStore) deserializeOld() error {
+	data, signature, err := bs.serializer.Readers()
+	if err != nil {
+		return err
+	}
+	if data == nil && signature == nil {
+		return nil
+	}
+	var old oldState
+	if err := decodeFromStorage(&old, data, signature, bs.signer.PublicKey()); err != nil {
+		return err
+	}
+	for p, wire := range old.Store {
+		bs.state.Store[p] = &blessings{Value: wire}
+	}
+	bs.state.Default = &blessings{Value: old.Default}
+	return nil
+}
+
+func (bs *blessingStore) deserialize() error {
+	data, signature, err := bs.serializer.Readers()
+	if err != nil {
+		return err
+	}
+	if data == nil && signature == nil {
+		return nil
+	}
+	if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err == nil && !bs.tryOldFormat() {
+		return nil
+	}
+	if err := bs.deserializeOld(); err != nil {
+		return err
+	}
+	return nil
+}
+
 // newPersistingBlessingStore returns a security.BlessingStore for a principal
 // that is initialized with the persisted data. The returned security.BlessingStore
 // also persists any updates to its state.
 func newPersistingBlessingStore(serializer SerializerReaderWriter, signer serialization.Signer) (security.BlessingStore, error) {
 	verifyBlessings := func(wb *blessings, key security.PublicKey) error {
-		if wb == nil {
-			return nil
-		}
 		if err := wb.Verify(); err != nil {
 			return err
 		}
-		if b := wb.Blessings(); !reflect.DeepEqual(b.PublicKey(), key) {
+		if b := wb.Blessings(); b != nil && !reflect.DeepEqual(b.PublicKey(), key) {
 			return fmt.Errorf("read Blessings: %v that are not for provided PublicKey: %v", b, key)
 		}
 		return nil
@@ -200,21 +257,25 @@
 		serializer: serializer,
 		signer:     signer,
 	}
-	data, signature, err := bs.serializer.Readers()
-	if err != nil {
+	if err := bs.deserialize(); err != nil {
 		return nil, err
 	}
-	if data != nil && signature != nil {
-		if err := decodeFromStorage(&bs.state, data, signature, bs.signer.PublicKey()); err != nil {
-			return nil, err
-		}
-	}
 	for _, wb := range bs.state.Store {
 		if err := verifyBlessings(wb, bs.publicKey); err != nil {
 			return nil, err
 		}
 	}
-	if err := verifyBlessings(bs.state.Default, bs.publicKey); err != nil {
+	if bs.state.Default != nil {
+		if err := verifyBlessings(bs.state.Default, bs.publicKey); err != nil {
+			return nil, err
+		}
+	}
+	// Save the blessingstore in the new serialization format. This will ensure
+	// that all credentials directories in the old format will switch to the new
+	// format.
+	// TODO(ataly, ashankar): Get rid of this  once we have switched all
+	// credentials directories to the new serialization format.
+	if err := bs.save(); err != nil {
 		return nil, err
 	}
 	return bs, nil