Skip to content

Commit 64faaae

Browse files
committed
[FAB-6462] Enforce PEM types for gossip identities
The MSP support for gossip (MessageCryptoService) takes into account The entire PEM of an x509 based identity, which is too lenient. Instead of enforcing explicit sanitation of input for GetPKIidOfCert(), We will just make identities that have the wrong PEM type - invalid. This is much more efficient because the GetPKIidOfCert is called many times in the code, and sanitizing its input is therefore costly, while if we just make identities that have the wrong type - invalid, it would implicitly force sanitation of identities. Another argument for doing so, would be that the Validate() is costly anyway and is rarely performed in the peer's life cycle, therefore - adding an additional slight overhead to it doesn't affect much the cost of validating an identity. The BCCSP-MSP Serialize() method already puts the right PEM type as of an earlier commit that is targeted for v1.1 and isn't in v1.0.x This change set makes the MessageCryptoService consider x509 based identities valid only if they have a PEM type of either CERTIFICATE or a blank one. Change-Id: Ic332f592cf2ebfe364f6c99ae762b2789d9c2b51 Signed-off-by: yacovm <yacovm@il.ibm.com>
1 parent 8a52d63 commit 64faaae

File tree

16 files changed

+217
-22
lines changed

16 files changed

+217
-22
lines changed

common/cauthdsl/cauthdsl_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ type mockDeserializer struct {
8686
fail error
8787
}
8888

89+
func (md *mockDeserializer) IsWellFormed(_ *mb.SerializedIdentity) error {
90+
return nil
91+
}
92+
8993
func (md *mockDeserializer) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) {
9094
if md.fail != nil {
9195
return nil, md.fail

common/mocks/msp/noopmsp.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ func (msp *noopmsp) SatisfiesPrincipal(id m.Identity, principal *msp.MSPPrincipa
8686
return nil
8787
}
8888

89+
// IsWellFormed checks if the given identity can be deserialized into its provider-specific form
90+
func (msp *noopmsp) IsWellFormed(_ *msp.SerializedIdentity) error {
91+
return nil
92+
}
93+
8994
type noopidentity struct {
9095
}
9196

core/common/privdata/simplecollection_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ func (md *mockDeserializer) DeserializeIdentity(serializedIdentity []byte) (msp.
8282
return &mockIdentity{idBytes: serializedIdentity}, nil
8383
}
8484

85+
func (md *mockDeserializer) IsWellFormed(_ *mb.SerializedIdentity) error {
86+
return nil
87+
}
88+
8589
func TestSetupBadConfig(t *testing.T) {
8690
// set up simple collection with invalid data
8791
var sc SimpleCollection

core/policy/mocks/mocks.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ func (d *MockIdentityDeserializer) DeserializeIdentity(serializedIdentity []byte
7878
return nil, errors.New("Invalid Identity")
7979
}
8080

81+
func (d *MockIdentityDeserializer) IsWellFormed(_ *mspproto.SerializedIdentity) error {
82+
return nil
83+
}
84+
8185
type MockIdentity struct {
8286
identity []byte
8387
msg []byte

msp/idemixmsp.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,18 @@ func (msp *idemixmsp) SatisfiesPrincipal(id Identity, principal *m.MSPPrincipal)
328328
}
329329
}
330330

331+
// IsWellFormed checks if the given identity can be deserialized into its provider-specific .
332+
// In this MSP implementation, an identity is considered well formed if it contains a
333+
// marshaled SerializedIdemixIdentity protobuf message.
334+
func (id *idemixmsp) IsWellFormed(identity *m.SerializedIdentity) error {
335+
sId := new(m.SerializedIdemixIdentity)
336+
err := proto.Unmarshal(identity.IdBytes, sId)
337+
if err != nil {
338+
return errors.Wrap(err, "not an idemix identity")
339+
}
340+
return nil
341+
}
342+
331343
func (msp *idemixmsp) GetTLSRootCerts() [][]byte {
332344
// TODO
333345
return nil

msp/idemixmsp_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,26 @@ func TestPrincipalIdentityBadIdentity(t *testing.T) {
285285
}
286286
}
287287

288+
func TestIdemixIsWellFormed(t *testing.T) {
289+
idemixMSP, err := setup("testdata/idemix/MSP1OU1")
290+
assert.NoError(t, err)
291+
292+
id, err := getDefaultSigner(idemixMSP)
293+
assert.NoError(t, err)
294+
rawId, err := id.Serialize()
295+
assert.NoError(t, err)
296+
sId := &msp.SerializedIdentity{}
297+
err = proto.Unmarshal(rawId, sId)
298+
assert.NoError(t, err)
299+
err = idemixMSP.IsWellFormed(sId)
300+
assert.NoError(t, err)
301+
// Corrupt the identity bytes
302+
sId.IdBytes = append(sId.IdBytes, 1)
303+
err = idemixMSP.IsWellFormed(sId)
304+
assert.Error(t, err)
305+
assert.Contains(t, err.Error(), "not an idemix identity")
306+
}
307+
288308
func TestPrincipalOU(t *testing.T) {
289309
msp1, err := setup("testdata/idemix/MSP1OU1")
290310
assert.NoError(t, err)

msp/mgmt/deserializer.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import (
2626
// DeserializersManager is a support interface to
2727
// access the local and channel deserializers
2828
type DeserializersManager interface {
29+
30+
// Deserialize receives SerializedIdentity bytes and returns the unmarshaled form
31+
// of the SerializedIdentity, or error on failure
2932
Deserialize(raw []byte) (*mspproto.SerializedIdentity, error)
3033

3134
// GetLocalMSPIdentifier returns the local MSP identifier

msp/mocks/mocks.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ type MockMSP struct {
1818
mock.Mock
1919
}
2020

21+
func (m *MockMSP) IsWellFormed(_ *pmsp.SerializedIdentity) error {
22+
return nil
23+
}
24+
2125
func (m *MockMSP) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) {
2226
args := m.Called(serializedIdentity)
2327
return args.Get(0).(msp.Identity), args.Error(1)

msp/msp.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ type IdentityDeserializer interface {
1919
// an msp that is different from this one that is performing
2020
// the deserialization.
2121
DeserializeIdentity(serializedIdentity []byte) (Identity, error)
22+
23+
// IsWellFormed checks if the given identity can be deserialized into its provider-specific form
24+
IsWellFormed(identity *msp.SerializedIdentity) error
2225
}
2326

2427
// Membership service provider APIs for Hyperledger Fabric:

msp/msp_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,64 @@ func TestSerializeIdentities(t *testing.T) {
258258
}
259259
}
260260

261+
func TestIsWellFormed(t *testing.T) {
262+
mspMgr := NewMSPManager()
263+
264+
id, err := localMsp.GetDefaultSigningIdentity()
265+
if err != nil {
266+
t.Fatalf("GetSigningIdentity should have succeeded, got err %s", err)
267+
return
268+
}
269+
270+
serializedID, err := id.Serialize()
271+
if err != nil {
272+
t.Fatalf("Serialize should have succeeded, got err %s", err)
273+
return
274+
}
275+
276+
sId := &msp.SerializedIdentity{}
277+
err = proto.Unmarshal(serializedID, sId)
278+
assert.NoError(t, err)
279+
280+
// An MSP Manager without any MSPs should not recognize the identity since
281+
// not providers are registered
282+
err = mspMgr.IsWellFormed(sId)
283+
assert.Error(t, err)
284+
assert.Equal(t, "no MSP provider recognizes the identity", err.Error())
285+
286+
// Add the MSP to the MSP Manager
287+
mspMgr.Setup([]MSP{localMsp})
288+
289+
err = localMsp.IsWellFormed(sId)
290+
assert.NoError(t, err)
291+
err = mspMgr.IsWellFormed(sId)
292+
assert.NoError(t, err)
293+
294+
bl, _ := pem.Decode(sId.IdBytes)
295+
assert.Equal(t, "CERTIFICATE", bl.Type)
296+
297+
// Now, strip off the type from the PEM block. It should still be valid
298+
bl.Type = ""
299+
sId.IdBytes = pem.EncodeToMemory(bl)
300+
301+
err = localMsp.IsWellFormed(sId)
302+
assert.NoError(t, err)
303+
304+
// Now, corrupt the type of the PEM block.
305+
// make sure it isn't considered well formed by both an MSP and an MSP Manager
306+
bl.Type = "foo"
307+
sId.IdBytes = pem.EncodeToMemory(bl)
308+
err = localMsp.IsWellFormed(sId)
309+
310+
assert.Error(t, err)
311+
assert.Contains(t, err.Error(), "pem type is")
312+
assert.Contains(t, err.Error(), "should be 'CERTIFICATE' or missing")
313+
314+
err = mspMgr.IsWellFormed(sId)
315+
assert.Error(t, err)
316+
assert.Equal(t, "no MSP provider recognizes the identity", err.Error())
317+
}
318+
261319
func TestValidateCAIdentity(t *testing.T) {
262320
caID := getIdentity(t, cacerts)
263321

0 commit comments

Comments
 (0)