veyron2/security: Remove PrivateKey accessor from PrivateID interface.

We imagine that private keys are stored in secure storage - like a TPM
or some other simpler factotum service like an ssh-agent. Not keeping
the private keys in memory of the process makes attacks to reveal the
private key significantly harder.

This change modifies the interface so that only a "Sign" method
is exposed. Subsequent changes that introduce the TPM/ssh-agent etc.
will provide identity implementations that do not store the private key
in memory at all but defer to the TPM/agent for signatures.

Change-Id: I1a02694a819177d934590b66854e4ad0253772e0
diff --git a/runtimes/google/ipc/stream/vc/auth.go b/runtimes/google/ipc/stream/vc/auth.go
index 6afec46..0378b31 100644
--- a/runtimes/google/ipc/stream/vc/auth.go
+++ b/runtimes/google/ipc/stream/vc/auth.go
@@ -3,7 +3,6 @@
 import (
 	"bytes"
 	"crypto/ecdsa"
-	"crypto/rand"
 	"errors"
 	"fmt"
 	"io"
@@ -85,17 +84,16 @@
 	defer eid.Release()
 
 	// Sign the channel ID
-	r, s, err := ecdsa.Sign(rand.Reader, id.PrivateKey(), chid.Contents)
+	signature, err := id.Sign(chid.Contents)
 	if err != nil {
 		return err
 	}
-	// Encrypt the signature
-	er, err := enc.Encrypt(iobuf.NewSlice(r.Bytes()))
+	er, err := enc.Encrypt(iobuf.NewSlice(signature.R.Bytes()))
 	if err != nil {
 		return err
 	}
 	defer er.Release()
-	es, err := enc.Encrypt(iobuf.NewSlice(s.Bytes()))
+	es, err := enc.Encrypt(iobuf.NewSlice(signature.S.Bytes()))
 	if err != nil {
 		return err
 	}
diff --git a/runtimes/google/security/caveat/public_key_caveat.go b/runtimes/google/security/caveat/public_key_caveat.go
index be80c12..f142359 100644
--- a/runtimes/google/security/caveat/public_key_caveat.go
+++ b/runtimes/google/security/caveat/public_key_caveat.go
@@ -131,15 +131,13 @@
 	return wire.DecodeThirdPartyCaveats(d.Caveats)
 }
 
-// sign uses the provided private key to sign the contents of the discharge. The private
-// key typically belongs to the principal that minted the discharge.
-func (d *publicKeyDischarge) sign(key *ecdsa.PrivateKey) error {
-	r, s, err := ecdsa.Sign(rand.Reader, key, d.contentHash())
+// sign uses the provided identity to sign the contents of the discharge.
+func (d *publicKeyDischarge) sign(discharger security.PrivateID) error {
+	signature, err := discharger.Sign(d.contentHash())
 	if err != nil {
 		return err
 	}
-	d.Signature.R = r.Bytes()
-	d.Signature.S = s.Bytes()
+	d.Signature.Set(signature)
 	return nil
 }
 
@@ -185,7 +183,7 @@
 // the discharge includes the provided service caveats along with a universal
 // expiry caveat for the provided duration. The discharge also includes a
 // signature over its contents obtained from the provided private key.
-func NewPublicKeyDischarge(caveat security.ThirdPartyCaveat, ctx security.Context, dischargingKey *ecdsa.PrivateKey, duration time.Duration, caveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
+func NewPublicKeyDischarge(discharger security.PrivateID, caveat security.ThirdPartyCaveat, ctx security.Context, duration time.Duration, caveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
 	cav, ok := caveat.(*publicKeyCaveat)
 	if !ok {
 		return nil, fmt.Errorf("cannot mint discharges for %T", caveat)
@@ -198,23 +196,22 @@
 	if err := mintingCaveat.Validate(ctx); err != nil {
 		return nil, fmt.Errorf("failed to validate DischargeMintingCaveat: %s", err)
 	}
-
-	discharge := &publicKeyDischarge{ThirdPartyCaveatID: caveat.ID()}
-
 	now := time.Now()
 	expiryCaveat := &vcaveat.Expiry{IssueTime: now, ExpiryTime: now.Add(duration)}
 	caveats = append(caveats, security.UniversalCaveat(expiryCaveat))
-
 	encodedCaveats, err := wire.EncodeCaveats(caveats)
 	if err != nil {
+		return nil, fmt.Errorf("failed to encode caveats in discharge: %v", err)
+	}
+	discharge := &publicKeyDischarge{
+		ThirdPartyCaveatID: caveat.ID(),
+		Caveats:            encodedCaveats,
+	}
+	// TODO(ashankar,ataly): Should discharger necessarily be the same as ctx.LocalID()?
+	// If so, need the PrivateID object corresponding to ctx.LocalID.
+	if err := discharge.sign(discharger); err != nil {
 		return nil, err
 	}
-	discharge.Caveats = encodedCaveats
-
-	if err := discharge.sign(dischargingKey); err != nil {
-		return nil, err
-	}
-
 	return discharge, nil
 }
 
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
index 52f2147..ca6ca3d 100644
--- a/runtimes/google/security/identity_chain.go
+++ b/runtimes/google/security/identity_chain.go
@@ -120,11 +120,12 @@
 	privateKey *ecdsa.PrivateKey
 }
 
-// PublicID returns the PublicID associated with the PrivateID.
 func (id *chainPrivateID) PublicID() security.PublicID { return id.publicID }
 
-// PrivateKey returns the private key associated with the PrivateID.
-func (id *chainPrivateID) PrivateKey() *ecdsa.PrivateKey { return id.privateKey }
+func (id *chainPrivateID) Sign(message []byte) (signature security.Signature, err error) {
+	signature.R, signature.S, err = ecdsa.Sign(rand.Reader, id.privateKey, message)
+	return
+}
 
 func (id *chainPrivateID) String() string { return fmt.Sprintf("PrivateID:%v", id.publicID) }
 
@@ -210,7 +211,7 @@
 }
 
 func (id *chainPrivateID) MintDischarge(cav security.ThirdPartyCaveat, ctx security.Context, duration time.Duration, dischargeCaveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
-	return icaveat.NewPublicKeyDischarge(cav, ctx, id.privateKey, duration, dischargeCaveats)
+	return icaveat.NewPublicKeyDischarge(id, cav, ctx, duration, dischargeCaveats)
 }
 
 // newChainPrivateID returns a new PrivateID containing a freshly generated
diff --git a/runtimes/google/security/identity_set.go b/runtimes/google/security/identity_set.go
index 85bdbad..0b2bd89 100644
--- a/runtimes/google/security/identity_set.go
+++ b/runtimes/google/security/identity_set.go
@@ -146,8 +146,9 @@
 	case 1:
 		return ids[0], nil
 	default:
+		pub := ids[0].PublicID().PublicKey()
 		for i := 1; i < len(ids); i++ {
-			if !reflect.DeepEqual(ids[0].PrivateKey(), ids[i].PrivateKey()) {
+			if !reflect.DeepEqual(pub, ids[i].PublicID().PublicKey()) {
 				return nil, errMismatchedKeys
 			}
 		}
@@ -164,7 +165,7 @@
 	return &set
 }
 
-func (s setPrivateID) PrivateKey() *ecdsa.PrivateKey { return s[0].PrivateKey() }
+func (s setPrivateID) Sign(message []byte) (security.Signature, error) { return s[0].Sign(message) }
 
 func (s setPrivateID) Bless(blessee security.PublicID, blessingName string, duration time.Duration, caveats []security.ServiceCaveat) (security.PublicID, error) {
 	pubs := make([]security.PublicID, len(s))
@@ -178,15 +179,12 @@
 }
 
 func (s setPrivateID) Derive(pub security.PublicID) (security.PrivateID, error) {
-	if !reflect.DeepEqual(pub.PublicKey(), &s.PrivateKey().PublicKey) {
-		return nil, errDeriveMismatch
-	}
-	var err error
 	switch p := pub.(type) {
 	case *chainPublicID:
 		return s[0].Derive(p)
 	case *setPublicID:
 		privs := make([]security.PrivateID, len(*p))
+		var err error
 		for ix, ip := range *p {
 			if privs[ix], err = s.Derive(ip); err != nil {
 				return nil, fmt.Errorf("Derive failed for %d of %d id in set", ix, len(*p))
diff --git a/runtimes/google/security/identity_test.go b/runtimes/google/security/identity_test.go
index 1d772ad..55ebf89 100644
--- a/runtimes/google/security/identity_test.go
+++ b/runtimes/google/security/identity_test.go
@@ -705,7 +705,7 @@
 	for _, d := range testdata {
 		derivedID, err := d.priv.Derive(d.pub)
 		if reflect.TypeOf(derivedID) != d.typ {
-			t.Errorf("%T=%q.Derive(%T=%q) yielded %T, want %v", d.priv, d.priv, d.pub, d.pub, derivedID, d.typ)
+			t.Errorf("%T=%q.Derive(%T=%q) yielded (%T, %v), want %v", d.priv, d.priv, d.pub, d.pub, derivedID, err, d.typ)
 			continue
 		}
 		if err != nil {
@@ -716,9 +716,6 @@
 		if !reflect.DeepEqual(derivedID.PublicID(), d.pub) {
 			t.Errorf("%q.Derive(%q) returned: %q. PublicID mismatch", d.priv, d.pub, derivedID)
 		}
-		if !reflect.DeepEqual(derivedID.PrivateKey(), d.priv.PrivateKey()) {
-			t.Errorf("%q.Derive(%q) returned: %q. PrivateKey mismatch", d.priv, d.pub, derivedID)
-		}
 		if _, err := roundTrip(derivedID.PublicID()); err != nil {
 			t.Errorf("roundTrip(%q=%q.Derive(%q)) failed: %v", derivedID, d.priv, d.pub, err)
 		}
diff --git a/tools/identity/main.go b/tools/identity/main.go
index 0ef0771..d440ffd 100644
--- a/tools/identity/main.go
+++ b/tools/identity/main.go
@@ -80,12 +80,11 @@
 
 	if len(*interpret) > 0 {
 		id := load(*interpret)
-		fmt.Println("Name   : ", id.PublicID())
-		fmt.Printf("Go Type: %T\n", id)
-		fmt.Println("Key    : <Cannot print the elliptic curve>")
-		fmt.Println("      X: ", id.PrivateKey().X)
-		fmt.Println("      Y: ", id.PrivateKey().Y)
-		fmt.Println("      D: ", id.PrivateKey().D)
+		fmt.Println("Name     : ", id.PublicID())
+		fmt.Printf("Go Type  : %T\n", id)
+		fmt.Println("PublicKey: <Cannot print the elliptic curve>")
+		fmt.Println("        X: ", id.PublicID().PublicKey().X)
+		fmt.Println("        Y: ", id.PublicID().PublicKey().Y)
 		fmt.Println("Any caveats in the identity are not printed")
 	}
 }