...

Source file src/github.com/ThalesIgnite/crypto11/crypto11_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  	"encoding/json"
    26  	"fmt"
    27  	"log"
    28  	"math/rand"
    29  	"os"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/miekg/pkcs11"
    34  
    35  	"github.com/stretchr/testify/assert"
    36  
    37  	"github.com/stretchr/testify/require"
    38  )
    39  
    40  func TestKeysPersistAcrossContexts(t *testing.T) {
    41  	// Verify that close and re-open works.
    42  	ctx, err := ConfigureFromFile("config")
    43  	require.NoError(t, err)
    44  
    45  	id := randomBytes()
    46  	_, err = ctx.GenerateRSAKeyPair(id, rsaSize)
    47  	if err != nil {
    48  		_ = ctx.Close()
    49  		t.Fatal(err)
    50  	}
    51  
    52  	require.NoError(t, ctx.Close())
    53  
    54  	ctx, err = ConfigureFromFile("config")
    55  	require.NoError(t, err)
    56  
    57  	key2, err := ctx.FindKeyPair(id, nil)
    58  	require.NoError(t, err)
    59  
    60  	testRsaSigning(t, key2, false)
    61  	_ = key2.Delete()
    62  	require.NoError(t, ctx.Close())
    63  }
    64  
    65  func configureWithPin(t *testing.T) (*Context, error) {
    66  	cfg, err := getConfig("config")
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  
    71  	if cfg.Pin == "" {
    72  		t.Fatal("invalid configuration. configuration must have PIN non empty.")
    73  	}
    74  
    75  	ctx, err := Configure(cfg)
    76  	if err != nil {
    77  		t.Fatal("failed to configure service:", err)
    78  	}
    79  
    80  	return ctx, nil
    81  }
    82  
    83  func getConfig(configLocation string) (ctx *Config, err error) {
    84  	file, err := os.Open(configLocation)
    85  	if err != nil {
    86  		log.Printf("Could not open config file: %s", configLocation)
    87  		return nil, err
    88  	}
    89  	defer func() {
    90  		err = file.Close()
    91  	}()
    92  
    93  	configDecoder := json.NewDecoder(file)
    94  	config := &Config{}
    95  	err = configDecoder.Decode(config)
    96  	if err != nil {
    97  		log.Printf("Could decode config file: %s", err.Error())
    98  		return nil, err
    99  	}
   100  	return config, nil
   101  }
   102  
   103  func TestKeyPairDelete(t *testing.T) {
   104  	ctx, err := ConfigureFromFile("config")
   105  	require.NoError(t, err)
   106  
   107  	defer func() {
   108  		require.NoError(t, ctx.Close())
   109  	}()
   110  
   111  	id := randomBytes()
   112  	key, err := ctx.GenerateRSAKeyPair(id, 2048)
   113  	require.NoError(t, err)
   114  
   115  	// Check we can find it
   116  	_, err = ctx.FindKeyPair(id, nil)
   117  	require.NoError(t, err)
   118  
   119  	err = key.Delete()
   120  	require.NoError(t, err)
   121  
   122  	k, err := ctx.FindKeyPair(id, nil)
   123  	require.NoError(t, err)
   124  	require.Nil(t, k)
   125  }
   126  
   127  func TestKeyDelete(t *testing.T) {
   128  	ctx, err := ConfigureFromFile("config")
   129  	require.NoError(t, err)
   130  
   131  	defer func() {
   132  		require.NoError(t, ctx.Close())
   133  	}()
   134  
   135  	id := randomBytes()
   136  	key, err := ctx.GenerateSecretKey(id, 128, CipherAES)
   137  	require.NoError(t, err)
   138  
   139  	// Check we can find it
   140  	_, err = ctx.FindKey(id, nil)
   141  	require.NoError(t, err)
   142  
   143  	err = key.Delete()
   144  	require.NoError(t, err)
   145  
   146  	k, err := ctx.FindKey(id, nil)
   147  	require.NoError(t, err)
   148  	require.Nil(t, k)
   149  }
   150  
   151  func TestAmbiguousTokenConfig(t *testing.T) {
   152  	slotNum := 1
   153  	tests := []struct {
   154  		config *Config
   155  		err    string
   156  	}{
   157  		{
   158  			config: &Config{TokenSerial: "serial", TokenLabel: "label"},
   159  			err:    "config must specify exactly one way to select a token: token label, token serial number given",
   160  		},
   161  		{
   162  			config: &Config{TokenSerial: "serial", SlotNumber: &slotNum},
   163  			err:    "config must specify exactly one way to select a token: slot number, token serial number given",
   164  		},
   165  		{
   166  			config: &Config{SlotNumber: &slotNum, TokenLabel: "label"},
   167  			err:    "config must specify exactly one way to select a token: slot number, token label given",
   168  		},
   169  		{
   170  			config: &Config{},
   171  			err:    "config must specify exactly one way to select a token: none given",
   172  		},
   173  	}
   174  	for i, test := range tests {
   175  		t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
   176  			_, err := Configure(test.config)
   177  			if assert.Error(t, err) {
   178  				assert.Equal(t, test.err, err.Error())
   179  			}
   180  		})
   181  	}
   182  }
   183  
   184  func TestSelectBySlot(t *testing.T) {
   185  	config, err := loadConfigFromFile("config")
   186  	require.NoError(t, err)
   187  
   188  	// Look up slot number for label
   189  	ctx, err := Configure(config)
   190  	require.NoError(t, err)
   191  
   192  	slotNumber := int(ctx.slot)
   193  	t.Logf("Using slot %d", slotNumber)
   194  	err = ctx.Close()
   195  	require.NoError(t, err)
   196  
   197  	slotConfig := &Config{
   198  		SlotNumber: &slotNumber,
   199  		Pin:        config.Pin,
   200  		Path:       config.Path,
   201  	}
   202  
   203  	ctx, err = Configure(slotConfig)
   204  	require.NoError(t, err)
   205  
   206  	slotNumber2 := int(ctx.slot)
   207  	err = ctx.Close()
   208  	require.NoError(t, err)
   209  
   210  	assert.Equal(t, slotNumber, slotNumber2)
   211  }
   212  
   213  func TestSelectByNonExistingSlot(t *testing.T) {
   214  	config, err := loadConfigFromFile("config")
   215  	require.NoError(t, err)
   216  
   217  	rand.Seed(time.Now().UnixNano())
   218  	randomSlot := int(rand.Uint32())
   219  
   220  	config.TokenLabel = ""
   221  	config.TokenSerial = ""
   222  	config.SlotNumber = &randomSlot
   223  
   224  	// Look up slot number for label
   225  	_, err = Configure(config)
   226  	require.Equal(t, errTokenNotFound, err)
   227  }
   228  
   229  func TestAccessSameLibraryTwice(t *testing.T) {
   230  	ctx1, err := ConfigureFromFile("config")
   231  	require.NoError(t, err)
   232  
   233  	ctx2, err := ConfigureFromFile("config")
   234  	require.NoError(t, err)
   235  
   236  	// Close the first context, which shouldn't render the second
   237  	// context unusable
   238  	err = ctx1.Close()
   239  	require.NoError(t, err)
   240  
   241  	// Try to find a non-existant key. We are just checking that we can
   242  	// use the underlying P11 lib.
   243  	_, err = ctx2.FindKey(randomBytes(), nil)
   244  	require.NoError(t, err)
   245  
   246  	err = ctx2.Close()
   247  	require.NoError(t, err)
   248  
   249  	// Check we can open this again and use it without error
   250  	ctx3, err := ConfigureFromFile("config")
   251  	require.NoError(t, err)
   252  
   253  	// Try to find a non-existant key. We are just checking that we can
   254  	// use the underlying P11 lib.
   255  	_, err = ctx3.FindKey(randomBytes(), nil)
   256  	require.NoError(t, err)
   257  
   258  	err = ctx3.Close()
   259  	require.NoError(t, err)
   260  }
   261  
   262  func TestNoLogin(t *testing.T) {
   263  	// To test that no login is respected, we attempt to perform an operation on our
   264  	// SoftHSM HSM without logging in and check for the error.
   265  	cfg, err := getConfig("config")
   266  	require.NoError(t, err)
   267  	cfg.LoginNotSupported = true
   268  
   269  	ctx, err := Configure(cfg)
   270  	require.NoError(t, err)
   271  
   272  	_, err = ctx.GenerateSecretKey(randomBytes(), 256, CipherAES)
   273  	require.Error(t, err)
   274  
   275  	p11Err, ok := err.(pkcs11.Error)
   276  	require.True(t, ok)
   277  
   278  	assert.Equal(t, pkcs11.Error(pkcs11.CKR_USER_NOT_LOGGED_IN), p11Err)
   279  }
   280  
   281  func TestInvalidMaxSessions(t *testing.T) {
   282  	cfg, err := getConfig("config")
   283  	require.NoError(t, err)
   284  
   285  	cfg.MaxSessions = 1
   286  	_, err = Configure(cfg)
   287  	require.Error(t, err)
   288  }
   289  
   290  // randomBytes returns 32 random bytes.
   291  func randomBytes() []byte {
   292  	result := make([]byte, 32)
   293  	rand.Read(result)
   294  	return result
   295  }
   296  
   297  func init() {
   298  	rand.Seed(time.Now().UnixNano())
   299  }
   300  

View as plain text