...

Source file src/github.com/ThalesIgnite/crypto11/ecdsa_test.go

Documentation: github.com/ThalesIgnite/crypto11

     1  // Copyright 2016, 2017 Thales e-Security, Inc
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining
     4  // a copy of this software and associated documentation files (the
     5  // "Software"), to deal in the Software without restriction, including
     6  // without limitation the rights to use, copy, modify, merge, publish,
     7  // distribute, sublicense, and/or sell copies of the Software, and to
     8  // permit persons to whom the Software is furnished to do so, subject to
     9  // the following conditions:
    10  //
    11  // The above copyright notice and this permission notice shall be
    12  // included in all copies or substantial portions of the Software.
    13  //
    14  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    17  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    18  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    19  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    20  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  
    22  package crypto11
    23  
    24  import (
    25  	"crypto"
    26  	"crypto/ecdsa"
    27  	"crypto/elliptic"
    28  	"crypto/rand"
    29  	_ "crypto/sha1"
    30  	_ "crypto/sha256"
    31  	_ "crypto/sha512"
    32  	"testing"
    33  
    34  	"github.com/miekg/pkcs11"
    35  
    36  	"github.com/stretchr/testify/assert"
    37  
    38  	"github.com/stretchr/testify/require"
    39  )
    40  
    41  var curves = []elliptic.Curve{
    42  	elliptic.P224(),
    43  	elliptic.P256(),
    44  	elliptic.P384(),
    45  	elliptic.P521(),
    46  	// plus something with explicit parameters
    47  }
    48  
    49  func TestNativeECDSA(t *testing.T) {
    50  	var err error
    51  	var key *ecdsa.PrivateKey
    52  	for _, curve := range curves {
    53  		if key, err = ecdsa.GenerateKey(curve, rand.Reader); err != nil {
    54  			t.Errorf("crypto.ecdsa.GenerateKey: %v", err)
    55  			return
    56  		}
    57  		testEcdsaSigning(t, key, crypto.SHA1, curve.Params().Name, "SHA-1")
    58  		testEcdsaSigning(t, key, crypto.SHA224, curve.Params().Name, "SHA-224")
    59  		testEcdsaSigning(t, key, crypto.SHA256, curve.Params().Name, "SHA-256")
    60  		testEcdsaSigning(t, key, crypto.SHA384, curve.Params().Name, "SHA-384")
    61  		testEcdsaSigning(t, key, crypto.SHA512, curve.Params().Name, "SHA-512")
    62  	}
    63  }
    64  
    65  func TestHardECDSA(t *testing.T) {
    66  	ctx, err := ConfigureFromFile("config")
    67  	require.NoError(t, err)
    68  
    69  	defer func() {
    70  		err = ctx.Close()
    71  		require.NoError(t, err)
    72  	}()
    73  
    74  	for _, curve := range curves {
    75  		id := randomBytes()
    76  		label := randomBytes()
    77  
    78  		key, err := ctx.GenerateECDSAKeyPairWithLabel(id, label, curve)
    79  		require.NoError(t, err)
    80  		require.NotNil(t, key)
    81  		defer func(k Signer) { _ = k.Delete() }(key)
    82  
    83  		testEcdsaSigning(t, key, crypto.SHA1, curve.Params().Name, "SHA-1")
    84  		testEcdsaSigning(t, key, crypto.SHA224, curve.Params().Name, "SHA-224")
    85  		testEcdsaSigning(t, key, crypto.SHA256, curve.Params().Name, "SHA-256")
    86  		testEcdsaSigning(t, key, crypto.SHA384, curve.Params().Name, "SHA-384")
    87  		testEcdsaSigning(t, key, crypto.SHA512, curve.Params().Name, "SHA-512")
    88  
    89  		key2, err := ctx.FindKeyPair(id, nil)
    90  		require.NoError(t, err)
    91  		testEcdsaSigning(t, key2.(*pkcs11PrivateKeyECDSA), crypto.SHA256, curve.Params().Name, "SHA-256")
    92  
    93  		key3, err := ctx.FindKeyPair(nil, label)
    94  		require.NoError(t, err)
    95  		testEcdsaSigning(t, key3.(crypto.Signer), crypto.SHA384, curve.Params().Name, "SHA-384")
    96  	}
    97  }
    98  
    99  func testEcdsaSigning(t *testing.T, key crypto.Signer, hashFunction crypto.Hash, curveName, hashName string) {
   100  
   101  	plaintext := []byte("sign me with ECDSA")
   102  	h := hashFunction.New()
   103  	_, err := h.Write(plaintext)
   104  	require.NoError(t, err)
   105  	plaintextHash := h.Sum(nil)
   106  
   107  	sigDER, err := key.Sign(rand.Reader, plaintextHash, nil)
   108  
   109  	p11Err, ok := err.(pkcs11.Error)
   110  	if ok && p11Err == pkcs11.CKR_KEY_SIZE_RANGE {
   111  		// Returned by CloudHSM (at least), for key sizes it doesn't support.
   112  		t.Logf("Skipping unsupported curve %s and hash %s", curveName, hashName)
   113  		return
   114  	}
   115  
   116  	assert.NoErrorf(t, err, "Sign failed for curve %s and hash %s", curveName, hashName)
   117  	if err != nil {
   118  		// We assert and return, so that errors are more informative over a range of curves
   119  		// and hashes.
   120  		return
   121  	}
   122  
   123  	var sig dsaSignature
   124  	err = sig.unmarshalDER(sigDER)
   125  	require.NoError(t, err)
   126  
   127  	ecdsaPubkey := key.Public().(crypto.PublicKey).(*ecdsa.PublicKey)
   128  	if !ecdsa.Verify(ecdsaPubkey, plaintextHash, sig.R, sig.S) {
   129  		t.Errorf("ECDSA Verify (hash %v): %v", hashFunction, err)
   130  	}
   131  
   132  }
   133  
   134  func TestEcdsaRequiredArgs(t *testing.T) {
   135  	ctx, err := ConfigureFromFile("config")
   136  	require.NoError(t, err)
   137  
   138  	defer func() {
   139  		require.NoError(t, ctx.Close())
   140  	}()
   141  
   142  	_, err = ctx.GenerateECDSAKeyPair(nil, elliptic.P224())
   143  	require.Error(t, err)
   144  
   145  	val := randomBytes()
   146  
   147  	_, err = ctx.GenerateECDSAKeyPairWithLabel(nil, val, elliptic.P224())
   148  	require.Error(t, err)
   149  
   150  	_, err = ctx.GenerateECDSAKeyPairWithLabel(val, nil, elliptic.P224())
   151  	require.Error(t, err)
   152  }
   153  

View as plain text