From 75db97d88011050f86c1567bab09e889b0a9e562 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Fri, 21 Apr 2017 17:11:03 +0200 Subject: [PATCH] Improved test coverage for bccsp/utils This change-set improves the test coverage of the bccsp/utils package Change-Id: Iccef021c18e227abd14b7e7aa88928d11aff0903 Signed-off-by: Angelo De Caro --- bccsp/utils/errs_test.go | 31 ++++++++++++ bccsp/utils/io.go | 2 +- bccsp/utils/io_test.go | 74 ++++++++++++++++++++++++++++ bccsp/utils/keys.go | 28 ++++++++--- bccsp/utils/keys_test.go | 97 ++++++++++++++++++++++++++++++++++++ bccsp/utils/slice_test.go | 29 +++++++++++ bccsp/utils/x509_test.go | 101 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 355 insertions(+), 7 deletions(-) create mode 100644 bccsp/utils/errs_test.go create mode 100644 bccsp/utils/io_test.go create mode 100644 bccsp/utils/slice_test.go create mode 100644 bccsp/utils/x509_test.go diff --git a/bccsp/utils/errs_test.go b/bccsp/utils/errs_test.go new file mode 100644 index 00000000000..09961839986 --- /dev/null +++ b/bccsp/utils/errs_test.go @@ -0,0 +1,31 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestErrToString(t *testing.T) { + assert.Equal(t, ErrToString(errors.New("error")), "error") + + assert.Equal(t, ErrToString(nil), "") + +} diff --git a/bccsp/utils/io.go b/bccsp/utils/io.go index bf61ce19570..95e0cee3fff 100644 --- a/bccsp/utils/io.go +++ b/bccsp/utils/io.go @@ -1,5 +1,5 @@ /* -Copyright IBM Corp. 2016 All Rights Reserved. +Copyright IBM Corp. 2017 All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/bccsp/utils/io_test.go b/bccsp/utils/io_test.go new file mode 100644 index 00000000000..0c02f59b56a --- /dev/null +++ b/bccsp/utils/io_test.go @@ -0,0 +1,74 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDirExists(t *testing.T) { + r, err := DirExists("") + assert.False(t, r) + assert.NoError(t, err) + + r, err = DirExists(os.TempDir()) + assert.NoError(t, err) + assert.Equal(t, true, r) + + r, err = DirExists(filepath.Join(os.TempDir(), "7rhf90239vhev90")) + assert.NoError(t, err) + assert.Equal(t, false, r) +} + +func TestDirMissingOrEmpty(t *testing.T) { + r, err := DirMissingOrEmpty("") + assert.NoError(t, err) + assert.True(t, r) + + r, err = DirMissingOrEmpty(filepath.Join(os.TempDir(), "7rhf90239vhev90")) + assert.NoError(t, err) + assert.Equal(t, true, r) +} + +func TestDirEmpty(t *testing.T) { + _, err := DirEmpty("") + assert.Error(t, err) + + path := filepath.Join(os.TempDir(), "7rhf90239vhev90") + defer os.Remove(path) + os.Mkdir(path, os.ModePerm) + + r, err := DirEmpty(path) + assert.NoError(t, err) + assert.Equal(t, true, r) + + r, err = DirEmpty(os.TempDir()) + assert.NoError(t, err) + assert.Equal(t, false, r) + + r, err = DirMissingOrEmpty(os.TempDir()) + assert.NoError(t, err) + assert.Equal(t, false, r) + + r, err = DirMissingOrEmpty(path) + assert.NoError(t, err) + assert.Equal(t, true, r) +} diff --git a/bccsp/utils/keys.go b/bccsp/utils/keys.go index 4dda12acf27..59bac0fdcdc 100644 --- a/bccsp/utils/keys.go +++ b/bccsp/utils/keys.go @@ -82,6 +82,9 @@ func PrivateKeyToPEM(privateKey interface{}, pwd []byte) ([]byte, error) { if len(pwd) != 0 { return PrivateKeyToEncryptedPEM(privateKey, pwd) } + if privateKey == nil { + return nil, errors.New("Invalid key. It must be different from nil.") + } switch k := privateKey.(type) { case *ecdsa.PrivateKey: @@ -131,7 +134,6 @@ func PrivateKeyToPEM(privateKey interface{}, pwd []byte) ([]byte, error) { if k == nil { return nil, errors.New("Invalid rsa private key. It must be different from nil.") } - raw := x509.MarshalPKCS1PrivateKey(k) return pem.EncodeToMemory( @@ -147,12 +149,15 @@ func PrivateKeyToPEM(privateKey interface{}, pwd []byte) ([]byte, error) { // PrivateKeyToEncryptedPEM converts a private key to an encrypted PEM func PrivateKeyToEncryptedPEM(privateKey interface{}, pwd []byte) ([]byte, error) { + if privateKey == nil { + return nil, errors.New("Invalid private key. It must be different from nil.") + } + switch k := privateKey.(type) { case *ecdsa.PrivateKey: if k == nil { return nil, errors.New("Invalid ecdsa private key. It must be different from nil.") } - raw, err := x509.MarshalECPrivateKey(k) if err != nil { @@ -295,12 +300,15 @@ func PublicKeyToPEM(publicKey interface{}, pwd []byte) ([]byte, error) { return PublicKeyToEncryptedPEM(publicKey, pwd) } + if publicKey == nil { + return nil, errors.New("Invalid public key. It must be different from nil.") + } + switch k := publicKey.(type) { case *ecdsa.PublicKey: if k == nil { return nil, errors.New("Invalid ecdsa public key. It must be different from nil.") } - PubASN1, err := x509.MarshalPKIXPublicKey(k) if err != nil { return nil, err @@ -316,7 +324,6 @@ func PublicKeyToPEM(publicKey interface{}, pwd []byte) ([]byte, error) { if k == nil { return nil, errors.New("Invalid rsa public key. It must be different from nil.") } - PubASN1, err := x509.MarshalPKIXPublicKey(k) if err != nil { return nil, err @@ -336,12 +343,15 @@ func PublicKeyToPEM(publicKey interface{}, pwd []byte) ([]byte, error) { // PublicKeyToDER marshals a public key to the der format func PublicKeyToDER(publicKey interface{}) ([]byte, error) { + if publicKey == nil { + return nil, errors.New("Invalid public key. It must be different from nil.") + } + switch k := publicKey.(type) { case *ecdsa.PublicKey: if k == nil { return nil, errors.New("Invalid ecdsa public key. It must be different from nil.") } - PubASN1, err := x509.MarshalPKIXPublicKey(k) if err != nil { return nil, err @@ -356,13 +366,19 @@ func PublicKeyToDER(publicKey interface{}) ([]byte, error) { // PublicKeyToEncryptedPEM converts a public key to encrypted pem func PublicKeyToEncryptedPEM(publicKey interface{}, pwd []byte) ([]byte, error) { + if publicKey == nil { + return nil, errors.New("Invalid public key. It must be different from nil.") + } + if len(pwd) == 0 { + return nil, errors.New("Invalid password. It must be different from nil.") + } + switch k := publicKey.(type) { case *ecdsa.PublicKey: if k == nil { return nil, errors.New("Invalid ecdsa public key. It must be different from nil.") } raw, err := x509.MarshalPKIXPublicKey(k) - if err != nil { return nil, err } diff --git a/bccsp/utils/keys_test.go b/bccsp/utils/keys_test.go index 2812258f519..a948f95167a 100644 --- a/bccsp/utils/keys_test.go +++ b/bccsp/utils/keys_test.go @@ -4,6 +4,7 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" + "crypto/rsa" "crypto/x509" "encoding/asn1" "encoding/pem" @@ -271,4 +272,100 @@ func TestECDSAKeys(t *testing.T) { if err == nil { t.Fatal("PEMtoPublicKey should fail on nil PEM and wrong password") } + + // Public Key DER format + der, err = PublicKeyToDER(&key.PublicKey) + assert.NoError(t, err) + keyFromDER, err = DERToPublicKey(der) + assert.NoError(t, err) + ecdsaPkFromPEM = keyFromDER.(*ecdsa.PublicKey) + // TODO: check the curve + if key.X.Cmp(ecdsaPkFromPEM.X) != 0 { + t.Fatal("Failed converting PEM to private key. Invalid X coordinate.") + } + if key.Y.Cmp(ecdsaPkFromPEM.Y) != 0 { + t.Fatal("Failed converting PEM to private key. Invalid Y coordinate.") + } +} + +func TestAESKey(t *testing.T) { + k := []byte{0, 1, 2, 3, 4, 5} + pem := AEStoPEM(k) + + k2, err := PEMtoAES(pem, nil) + assert.NoError(t, err) + assert.Equal(t, k, k2) + + pem, err = AEStoEncryptedPEM(k, k) + assert.NoError(t, err) + + k2, err = PEMtoAES(pem, k) + assert.NoError(t, err) + assert.Equal(t, k, k2) +} + +func TestDERToPublicKey(t *testing.T) { + _, err := DERToPublicKey(nil) + assert.Error(t, err) +} + +func TestNil(t *testing.T) { + _, err := PrivateKeyToEncryptedPEM(nil, nil) + assert.Error(t, err) + + _, err = PEMtoAES(nil, nil) + assert.Error(t, err) + + _, err = AEStoEncryptedPEM(nil, nil) + assert.Error(t, err) + + _, err = PublicKeyToPEM(nil, nil) + assert.Error(t, err) + _, err = PublicKeyToPEM(nil, []byte("hello world")) + assert.Error(t, err) + + _, err = PublicKeyToPEM("hello world", nil) + assert.Error(t, err) + _, err = PublicKeyToPEM("hello world", []byte("hello world")) + assert.Error(t, err) + + _, err = PublicKeyToDER(nil) + assert.Error(t, err) + _, err = PublicKeyToDER("hello world") + assert.Error(t, err) + + _, err = PublicKeyToEncryptedPEM(nil, nil) + assert.Error(t, err) + _, err = PublicKeyToEncryptedPEM("hello world", nil) + assert.Error(t, err) + _, err = PublicKeyToEncryptedPEM("hello world", []byte("Hello world")) + assert.Error(t, err) + +} + +func TestPrivateKeyToPEM(t *testing.T) { + _, err := PrivateKeyToPEM(nil, nil) + assert.Error(t, err) + + _, err = PrivateKeyToPEM("hello world", nil) + assert.Error(t, err) + + key, err := rsa.GenerateKey(rand.Reader, 1024) + assert.NoError(t, err) + pem, err := PrivateKeyToPEM(key, nil) + assert.NoError(t, err) + assert.NotNil(t, pem) + key2, err := PEMtoPrivateKey(pem, nil) + assert.NoError(t, err) + assert.NotNil(t, key2) + assert.Equal(t, key.D, key2.(*rsa.PrivateKey).D) + + pem, err = PublicKeyToPEM(&key.PublicKey, nil) + assert.NoError(t, err) + assert.NotNil(t, pem) + key3, err := PEMtoPublicKey(pem, nil) + assert.NoError(t, err) + assert.NotNil(t, key2) + assert.Equal(t, key.PublicKey.E, key3.(*rsa.PublicKey).E) + assert.Equal(t, key.PublicKey.N, key3.(*rsa.PublicKey).N) } diff --git a/bccsp/utils/slice_test.go b/bccsp/utils/slice_test.go new file mode 100644 index 00000000000..099ee341843 --- /dev/null +++ b/bccsp/utils/slice_test.go @@ -0,0 +1,29 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestClone(t *testing.T) { + src := []byte{0, 1, 2, 3, 4} + clone := Clone(src) + assert.Equal(t, src, clone) +} diff --git a/bccsp/utils/x509_test.go b/bccsp/utils/x509_test.go new file mode 100644 index 00000000000..04df6fafb5b --- /dev/null +++ b/bccsp/utils/x509_test.go @@ -0,0 +1,101 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/asn1" + "math/big" + "net" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestDERToX509Certificate(t *testing.T) { + testExtKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth} + testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}} + extraExtensionData := []byte("extra extension") + commonName := "test.example.com" + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: commonName, + Organization: []string{"Σ Acme Co"}, + Country: []string{"US"}, + ExtraNames: []pkix.AttributeTypeAndValue{ + { + Type: []int{2, 5, 4, 42}, + Value: "Gopher", + }, + // This should override the Country, above. + { + Type: []int{2, 5, 4, 6}, + Value: "NL", + }, + }, + }, + NotBefore: time.Now().Add(-1 * time.Hour), + NotAfter: time.Now().Add(1 * time.Hour), + + SignatureAlgorithm: x509.ECDSAWithSHA256, + + SubjectKeyId: []byte{1, 2, 3, 4}, + KeyUsage: x509.KeyUsageCertSign, + + ExtKeyUsage: testExtKeyUsage, + UnknownExtKeyUsage: testUnknownExtKeyUsage, + + BasicConstraintsValid: true, + IsCA: true, + + OCSPServer: []string{"http://ocurrentBCCSP.example.com"}, + IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"}, + + DNSNames: []string{"test.example.com"}, + EmailAddresses: []string{"gopher@golang.org"}, + IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, + + PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}}, + PermittedDNSDomains: []string{".example.com", "example.com"}, + + CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"}, + + ExtraExtensions: []pkix.Extension{ + { + Id: []int{1, 2, 3, 4}, + Value: extraExtensionData, + }, + }, + } + + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + assert.NoError(t, err) + certRaw, err := x509.CreateCertificate(rand.Reader, &template, &template, key.Public(), key) + assert.NoError(t, err) + + cert, err := DERToX509Certificate(certRaw) + assert.NoError(t, err) + assert.NotNil(t, cert) + assert.Equal(t, cert.Raw, certRaw) + +}