Skip to content

Commit

Permalink
[FAB-3677] Identity validation
Browse files Browse the repository at this point in the history
This change-set addressed FAB-3677 in the following way:
At MSP setup time, a certification tree T is constructed based
on the root CA and Intermediate CA certificates (after their
sanitization). The MSP instance then stores the number of
children each node in T has. An identity is valid only if
its corresponding certificates had been signed by a leaf of T.
Specific tests haves been added.

Change-Id: Ie7d07c2faadc76890eec151267172ed92db0af34
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed May 12, 2017
1 parent b2cce35 commit 2f02dc3
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 8 deletions.
49 changes: 41 additions & 8 deletions msp/mspimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ type bccspmsp struct {
// list of intermediate certs we trust
intermediateCerts []Identity

// certificationTreeInternalNodesMap whose keys correspond to the raw material
// (DER representation) of a certificate casted to a string, and whose values
// are boolean. True means that the certificate is an internal node of the certification tree.
// False means that the certificate corresponds to a leaf of the certification tree.
certificationTreeInternalNodesMap map[string]bool

// list of signing identities
signer SigningIdentity

Expand Down Expand Up @@ -311,26 +317,24 @@ func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error {
return errors.New("Expected at least one CA certificate")
}

// pre-create the verify options with roots and intermediates
// this is needed to make certificate sanitation working.
msp.opts = &x509.VerifyOptions{
Roots: x509.NewCertPool(),
Intermediates: x509.NewCertPool(),
}
// pre-create the verify options with roots and intermediates.
// This is needed to make certificate sanitation working.
// Recall that sanitization is applied also to root CA and intermediate
// CA certificates. After their sanitization is done, the opts
// will be recreated using the sanitized certs.
msp.opts = &x509.VerifyOptions{Roots: x509.NewCertPool(), Intermediates: x509.NewCertPool()}
for _, v := range conf.RootCerts {
cert, err := msp.getCertFromPem(v)
if err != nil {
return err
}

msp.opts.Roots.AddCert(cert)
}
for _, v := range conf.IntermediateCerts {
cert, err := msp.getCertFromPem(v)
if err != nil {
return err
}

msp.opts.Intermediates.AddCert(cert)
}

Expand All @@ -357,6 +361,15 @@ func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error {
msp.intermediateCerts[i] = id
}

// root CA and intermediate CA certificates are sanitized, they can be reimported
msp.opts = &x509.VerifyOptions{Roots: x509.NewCertPool(), Intermediates: x509.NewCertPool()}
for _, id := range msp.rootCerts {
msp.opts.Roots.AddCert(id.(*identity).cert)
}
for _, id := range msp.intermediateCerts {
msp.opts.Intermediates.AddCert(id.(*identity).cert)
}

// make and fill the set of admin certs (if present)
msp.admins = make([]Identity, len(conf.Admins))
for i, admCert := range conf.Admins {
Expand Down Expand Up @@ -395,6 +408,21 @@ func (msp *bccspmsp) Setup(conf1 *m.MSPConfig) error {
}
}

// populate certificationTreeInternalNodesMap to mark the internal nodes of the
// certification tree
msp.certificationTreeInternalNodesMap = make(map[string]bool)
for _, cert := range append([]Identity{}, msp.intermediateCerts...) {
chain, err := msp.getUniqueValidationChain(cert.(*identity).cert)
if err != nil {
return fmt.Errorf("Failed getting validation chain, (SN: %s)", cert.(*identity).cert.SerialNumber)
}

// Recall chain[0] is cert.(*identity).cert so it does not count as a parent
for i := 1; i < len(chain); i++ {
msp.certificationTreeInternalNodesMap[string(chain[i].Raw)] = true
}
}

// setup the signer (if present)
if conf.SigningIdentity != nil {
sid, err := msp.getSigningIdentityFromConf(conf.SigningIdentity)
Expand Down Expand Up @@ -683,6 +711,11 @@ func (msp *bccspmsp) getValidationChain(cert *x509.Certificate) ([]*x509.Certifi
return nil, fmt.Errorf("Expected a chain of length at least 2, got %d", len(validationChain))
}

// check that the parent is a leaf of the certification tree
if msp.certificationTreeInternalNodesMap[string(validationChain[1].Raw)] {
return nil, fmt.Errorf("Invalid validation chain. Parent certificate should be a leaf of the certification tree [%v].", cert.Raw)
}

return validationChain, nil
}

Expand Down
28 changes: 28 additions & 0 deletions msp/mspwithintermediatecas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package msp

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -63,3 +64,30 @@ func TestIntermediateCAIdentityValidity(t *testing.T) {
id := thisMSP.(*bccspmsp).intermediateCerts[0]
assert.Error(t, id.Validate())
}

func TestMSPWithIntermediateCAs2(t *testing.T) {
// testdata/intermediate2 contains the credentials for a test MSP setup that has
// 1) a key and a signcert (used to populate the default signing identity);
// signcert is not signed by a CA directly but by an intermediate CA
// 2) intermediatecert is an intermediate CA, signed by the CA
// 3) cacert is the CA that signed the intermediate
// 4) user2-cert is the certificate of an identity signed directly by the CA
// therefore validation should fail.
thisMSP := getLocalMSP(t, filepath.Join("testdata", "intermediate2"))

// the default signing identity is signed by the intermediate CA,
// the validation should return no error
id, err := thisMSP.GetDefaultSigningIdentity()
assert.NoError(t, err)
err = thisMSP.Validate(id.GetPublicVersion())
assert.NoError(t, err)

// user2-cert has been signed by the root CA, validation must fail
pem, err := readPemFile(filepath.Join("testdata", "intermediate2", "users", "user2-cert.pem"))
assert.NoError(t, err)
id2, _, err := thisMSP.(*bccspmsp).getIdentityFromConf(pem)
assert.NoError(t, err)
err = thisMSP.Validate(id2)
assert.Error(t, err)
assert.Contains(t, err.Error(), "Invalid validation chain. Parent certificate should be a leaf of the certification tree ")
}
14 changes: 14 additions & 0 deletions msp/testdata/intermediate2/admincerts/admin.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICLzCCAdagAwIBAgIQLcb0TM7r3ga3Z+o4nBRSFjAKBggqhkjOPQQDAjBJMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzENMAsGA1UEAxMEaWNhMTAeFw0xNzA1MTAxNjIxNDhaFw0yNzA1MDgx
NjIxNDhaMEoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYD
VQQHEw1TYW4gRnJhbmNpc2NvMQ4wDAYDVQQDEwV1c2VyMTBZMBMGByqGSM49AgEG
CCqGSM49AwEHA0IABPdaoTrPLuSB0Ns3gRy/7UhMSMWc6knnaiLmWsF9eEW34XXa
oupK5izQSokvRW9u0pkyR1cCSBAHbqJ8AC+q1OejgZ4wgZswDgYDVR0PAQH/BAQD
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwZgYDVR0jBF8w
XYBbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB2id4RLBxhAE+TrhgE/cd/yk
5fe8TKgeJUKHDoKbcRUeYSz1lR1uYR2+ucGvRPP1qmYOKA0HdPKbVLBE0fAhOTAK
BggqhkjOPQQDAgNHADBEAiAdeTm6jnLCVEKfNCnrYcOLkB2lUFaNr8hLtQXCOlnD
swIgMdTefeOqQvpKY1VrCR3VUE3zOMKF5k2kruyr7gGdU3E=
-----END CERTIFICATE-----
14 changes: 14 additions & 0 deletions msp/testdata/intermediate2/cacerts/cacert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICEDCCAbegAwIBAgIQKy5yRZcslB/rn4imlQYAkzAKBggqhkjOPQQDAjBVMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzEMMAoGA1UEChMDb3JnMQswCQYDVQQDEwJjYTAeFw0xNzA1MTAxNjIx
NDhaFw0yNzA1MDgxNjIxNDhaMFUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp
Zm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMQwwCgYDVQQKEwNvcmcxCzAJ
BgNVBAMTAmNhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdYa6mGu7DbwLl9ax
kfDWe5irUfO/NF/ISxBBZuN2QaxV0IWsL66Bbr1hGWDbrQjrsrfWHO/73d1xrlbT
wmcOQ6NpMGcwDgYDVR0PAQH/BAQDAgGmMBkGA1UdJQQSMBAGBFUdJQAGCCsGAQUF
BwMBMA8GA1UdEwEB/wQFMAMBAf8wKQYDVR0OBCIEIF7PPyL7Fc9WILdySDYZIJ+u
JR7wDRyZN5OKrEQVECAHMAoGCCqGSM49BAMCA0cAMEQCIGKJRDsVIHMioqTUevBp
dRnXZnKUFiPJb2t00NGh6oKuAiAs5vlQ+6izRviSO7ujTNdsqjfs5WlCcesy5reV
8F7esg==
-----END CERTIFICATE-----
16 changes: 16 additions & 0 deletions msp/testdata/intermediate2/intermediatecerts/intermediatecert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICbzCCAhWgAwIBAgIQKA9DhIj8YDJpbP7wFsmuSDAKBggqhkjOPQQDAjBVMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzEMMAoGA1UEChMDb3JnMQswCQYDVQQDEwJjYTAeFw0xNzA1MTAxNjIx
NDhaFw0yNzA1MDgxNjIxNDhaMEkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxp
Zm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQDEwRpY2ExMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB2id4RLBxhAE+TrhgE/cd/yk5fe8TKge
JUKHDoKbcRUeYSz1lR1uYR2+ucGvRPP1qmYOKA0HdPKbVLBE0fAhOaOB0jCBzzAO
BgNVHQ8BAf8EBAMCAaYwGQYDVR0lBBIwEAYEVR0lAAYIKwYBBQUHAwEwDwYDVR0T
AQH/BAUwAwEB/zBkBgNVHQ4EXQRbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
B2id4RLBxhAE+TrhgE/cd/yk5fe8TKgeJUKHDoKbcRUeYSz1lR1uYR2+ucGvRPP1
qmYOKA0HdPKbVLBE0fAhOTArBgNVHSMEJDAigCBezz8i+xXPViC3ckg2GSCfriUe
8A0cmTeTiqxEFRAgBzAKBggqhkjOPQQDAgNIADBFAiEAjt/IU7E9fBIXG8WzKxIz
Jmbfjm/qCOmLvt53HPa/B0ICIB2q1TE21KK68fxO6C92AhNuTmGHmumLB8yTBG7j
QsQL
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions msp/testdata/intermediate2/keystore/key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgTNlF7jY6jBKQGLqs
AgllL7utSIRxZdxy4fexQaNX7JKhRANCAAT3WqE6zy7kgdDbN4Ecv+1ITEjFnOpJ
52oi5lrBfXhFt+F12qLqSuYs0EqJL0VvbtKZMkdXAkgQB26ifAAvqtTn
-----END PRIVATE KEY-----
14 changes: 14 additions & 0 deletions msp/testdata/intermediate2/signcerts/signcert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICLzCCAdagAwIBAgIQLcb0TM7r3ga3Z+o4nBRSFjAKBggqhkjOPQQDAjBJMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzENMAsGA1UEAxMEaWNhMTAeFw0xNzA1MTAxNjIxNDhaFw0yNzA1MDgx
NjIxNDhaMEoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYD
VQQHEw1TYW4gRnJhbmNpc2NvMQ4wDAYDVQQDEwV1c2VyMTBZMBMGByqGSM49AgEG
CCqGSM49AwEHA0IABPdaoTrPLuSB0Ns3gRy/7UhMSMWc6knnaiLmWsF9eEW34XXa
oupK5izQSokvRW9u0pkyR1cCSBAHbqJ8AC+q1OejgZ4wgZswDgYDVR0PAQH/BAQD
AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwZgYDVR0jBF8w
XYBbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB2id4RLBxhAE+TrhgE/cd/yk
5fe8TKgeJUKHDoKbcRUeYSz1lR1uYR2+ucGvRPP1qmYOKA0HdPKbVLBE0fAhOTAK
BggqhkjOPQQDAgNHADBEAiAdeTm6jnLCVEKfNCnrYcOLkB2lUFaNr8hLtQXCOlnD
swIgMdTefeOqQvpKY1VrCR3VUE3zOMKF5k2kruyr7gGdU3E=
-----END CERTIFICATE-----
13 changes: 13 additions & 0 deletions msp/testdata/intermediate2/users/user2-cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB/zCCAaagAwIBAgIRAO7SLOYTMXE76j8HsQvesuswCgYIKoZIzj0EAwIwVTEL
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG
cmFuY2lzY28xDDAKBgNVBAoTA29yZzELMAkGA1UEAxMCY2EwHhcNMTcwNTEwMTYy
MTQ4WhcNMjcwNTA4MTYyMTQ4WjBKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
aWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEOMAwGA1UEAxMFdXNlcjIw
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT+6mBEtOvply3HopfMlDN1CrpY3lNj
A/Kfyh+5HUhcFY+shi7NP1qCAvQ3rId57Zm2ii7GhQip6g9pJzbHoRWbo2IwYDAO
BgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIw
ADArBgNVHSMEJDAigCBezz8i+xXPViC3ckg2GSCfriUe8A0cmTeTiqxEFRAgBzAK
BggqhkjOPQQDAgNHADBEAiApy6JAi5mEkaRknmvuRFQykqsJ1WJ3YxhEP2GrX95x
9gIgH5lA0xykOrvVyARyCO1u+6NebJsv2aUMdXJ7eJMjREE=
-----END CERTIFICATE-----

0 comments on commit 2f02dc3

Please sign in to comment.