github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/ca/keyreadwriter_test.go (about)

     1  package ca_test
     2  
     3  import (
     4  	"encoding/pem"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	"github.com/docker/swarmkit/ca"
    12  	"github.com/docker/swarmkit/ca/keyutils"
    13  	"github.com/docker/swarmkit/ca/pkcs8"
    14  	"github.com/docker/swarmkit/ca/testutils"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  // can read and write tls keys that aren't encrypted, and that are encrypted.  without
    19  // a pem header manager, the headers are all preserved and not overwritten
    20  func TestKeyReadWriter(t *testing.T) {
    21  	cert, key, err := testutils.CreateRootCertAndKey("cn")
    22  	require.NoError(t, err)
    23  
    24  	expectedKey := key
    25  
    26  	tempdir, err := ioutil.TempDir("", "KeyReadWriter")
    27  	require.NoError(t, err)
    28  	defer os.RemoveAll(tempdir)
    29  
    30  	path := ca.NewConfigPaths(filepath.Join(tempdir, "subdir")) // to make sure subdirectories are created
    31  
    32  	checkCanReadWithKEK := func(kek []byte) *ca.KeyReadWriter {
    33  		k := ca.NewKeyReadWriter(path.Node, kek, nil)
    34  		readCert, readKey, err := k.Read()
    35  		require.NoError(t, err)
    36  		require.Equal(t, cert, readCert)
    37  		require.Equal(t, expectedKey, readKey, "Expected %s, Got %s", string(expectedKey), string(readKey))
    38  		return k
    39  	}
    40  
    41  	k := ca.NewKeyReadWriter(path.Node, nil, nil)
    42  
    43  	// can't read things that don't exist
    44  	_, _, err = k.Read()
    45  	require.Error(t, err)
    46  
    47  	// can write an unencrypted key with no updates
    48  	require.NoError(t, k.Write(cert, expectedKey, nil))
    49  
    50  	// can read unencrypted
    51  	k = checkCanReadWithKEK(nil)
    52  	_, kekData := k.GetCurrentState()
    53  	require.EqualValues(t, 0, kekData.Version) // the first version was 0
    54  
    55  	// write a key with headers to the key to make sure they're cleaned
    56  	keyBlock, _ := pem.Decode(expectedKey)
    57  	require.NotNil(t, keyBlock)
    58  	keyBlock.Headers = map[string]string{"hello": "world"}
    59  	expectedKey = pem.EncodeToMemory(keyBlock)
    60  	// write a version, but that's not what we'd expect back once we read
    61  	keyBlock.Headers["kek-version"] = "8"
    62  	require.NoError(t, ioutil.WriteFile(path.Node.Key, pem.EncodeToMemory(keyBlock), 0600))
    63  
    64  	// if a kek is provided, we can still read unencrypted keys, and read
    65  	// the provided version
    66  	k = checkCanReadWithKEK([]byte("original kek"))
    67  	_, kekData = k.GetCurrentState()
    68  	require.EqualValues(t, 8, kekData.Version)
    69  
    70  	// we can update the kek and write at the same time
    71  	require.NoError(t, k.Write(cert, key, &ca.KEKData{KEK: []byte("new kek!"), Version: 3}))
    72  
    73  	// the same kek can still read, and will continue to write with this key if
    74  	// no further kek updates are provided
    75  	_, _, err = k.Read()
    76  	require.NoError(t, err)
    77  	require.NoError(t, k.Write(cert, expectedKey, nil))
    78  
    79  	expectedKey = key
    80  
    81  	// without the right kek, we can't read
    82  	k = ca.NewKeyReadWriter(path.Node, []byte("original kek"), nil)
    83  	_, _, err = k.Read()
    84  	require.Error(t, err)
    85  
    86  	// same new key, just for sanity
    87  	k = checkCanReadWithKEK([]byte("new kek!"))
    88  	_, kekData = k.GetCurrentState()
    89  	require.EqualValues(t, 3, kekData.Version)
    90  
    91  	// we can also change the kek back to nil, which means the key is unencrypted
    92  	require.NoError(t, k.Write(cert, key, &ca.KEKData{KEK: nil}))
    93  	k = checkCanReadWithKEK(nil)
    94  	_, kekData = k.GetCurrentState()
    95  	require.EqualValues(t, 0, kekData.Version)
    96  }
    97  
    98  type testHeaders struct {
    99  	setHeaders func(map[string]string, ca.KEKData) (ca.PEMKeyHeaders, error)
   100  	newHeaders func(ca.KEKData) (map[string]string, error)
   101  }
   102  
   103  func (p testHeaders) UnmarshalHeaders(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) {
   104  	if p.setHeaders != nil {
   105  		return p.setHeaders(h, k)
   106  	}
   107  	return nil, fmt.Errorf("set header error")
   108  }
   109  
   110  func (p testHeaders) MarshalHeaders(k ca.KEKData) (map[string]string, error) {
   111  	if p.newHeaders != nil {
   112  		return p.newHeaders(k)
   113  	}
   114  	return nil, fmt.Errorf("update header error")
   115  }
   116  
   117  func (p testHeaders) UpdateKEK(ca.KEKData, ca.KEKData) ca.PEMKeyHeaders {
   118  	return p
   119  }
   120  
   121  // KeyReaderWriter makes a call to a get headers updater, if write is called,
   122  // and set headers, if read is called.  The KEK version header is always preserved
   123  // no matter what.
   124  func TestKeyReadWriterWithPemHeaderManager(t *testing.T) {
   125  	cert, key, err := testutils.CreateRootCertAndKey("cn")
   126  	require.NoError(t, err)
   127  
   128  	// write a key with headers to the key to make sure it gets overwritten
   129  	keyBlock, _ := pem.Decode(key)
   130  	require.NotNil(t, keyBlock)
   131  	keyBlock.Headers = map[string]string{"hello": "world"}
   132  	key = pem.EncodeToMemory(keyBlock)
   133  
   134  	tempdir, err := ioutil.TempDir("", "KeyReadWriter")
   135  	require.NoError(t, err)
   136  	defer os.RemoveAll(tempdir)
   137  
   138  	path := ca.NewConfigPaths(filepath.Join(tempdir, "subdir")) // to make sure subdirectories are created
   139  
   140  	// if if getting new headers fail, writing a key fails, and the key does not rotate
   141  	var count int
   142  	badKEKData := ca.KEKData{KEK: []byte("failed kek"), Version: 3}
   143  	k := ca.NewKeyReadWriter(path.Node, nil, testHeaders{newHeaders: func(k ca.KEKData) (map[string]string, error) {
   144  		if count == 0 {
   145  			count++
   146  			require.Equal(t, badKEKData, k)
   147  			return nil, fmt.Errorf("fail")
   148  		}
   149  		require.Equal(t, ca.KEKData{}, k)
   150  		return nil, nil
   151  	}})
   152  	// first write will fail
   153  	require.Error(t, k.Write(cert, key, &badKEKData))
   154  	// the stored kek data will be not be updated because the write failed
   155  	_, kekData := k.GetCurrentState()
   156  	require.Equal(t, ca.KEKData{}, kekData)
   157  	// second write will succeed, using the original kek (nil)
   158  	require.NoError(t, k.Write(cert, key, nil))
   159  
   160  	var (
   161  		headers map[string]string
   162  		kek     ca.KEKData
   163  	)
   164  
   165  	// if setting headers fail, reading fails
   166  	k = ca.NewKeyReadWriter(path.Node, nil, testHeaders{setHeaders: func(map[string]string, ca.KEKData) (ca.PEMKeyHeaders, error) {
   167  		return nil, fmt.Errorf("nope")
   168  	}})
   169  	_, _, err = k.Read()
   170  	require.Error(t, err)
   171  
   172  	k = ca.NewKeyReadWriter(path.Node, nil, testHeaders{setHeaders: func(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) {
   173  		headers = h
   174  		kek = k
   175  		return testHeaders{}, nil
   176  	}})
   177  
   178  	_, _, err = k.Read()
   179  	require.NoError(t, err)
   180  	require.Equal(t, ca.KEKData{}, kek)
   181  	require.Equal(t, keyBlock.Headers, headers)
   182  
   183  	// writing new headers is called with existing headers, and will write a key that has the headers
   184  	// returned by the header update function
   185  	k = ca.NewKeyReadWriter(path.Node, []byte("oldKek"), testHeaders{newHeaders: func(kek ca.KEKData) (map[string]string, error) {
   186  		require.Equal(t, []byte("newKEK"), kek.KEK)
   187  		return map[string]string{"updated": "headers"}, nil
   188  	}})
   189  	require.NoError(t, k.Write(cert, key, &ca.KEKData{KEK: []byte("newKEK"), Version: 2}))
   190  
   191  	// make sure headers were correctly set
   192  	k = ca.NewKeyReadWriter(path.Node, []byte("newKEK"), testHeaders{setHeaders: func(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) {
   193  		headers = h
   194  		kek = k
   195  		return testHeaders{}, nil
   196  	}})
   197  	_, _, err = k.Read()
   198  	require.NoError(t, err)
   199  	require.Equal(t, ca.KEKData{KEK: []byte("newKEK"), Version: 2}, kek)
   200  
   201  	_, kekData = k.GetCurrentState()
   202  	require.Equal(t, kek, kekData)
   203  	require.Equal(t, map[string]string{"updated": "headers"}, headers)
   204  }
   205  
   206  func TestKeyReadWriterViewAndUpdateHeaders(t *testing.T) {
   207  	cert, key, err := testutils.CreateRootCertAndKey("cn")
   208  	require.NoError(t, err)
   209  
   210  	tempdir, err := ioutil.TempDir("", "KeyReadWriter")
   211  	require.NoError(t, err)
   212  	defer os.RemoveAll(tempdir)
   213  
   214  	path := ca.NewConfigPaths(filepath.Join(tempdir))
   215  
   216  	// write a key with headers to the key to make sure it gets passed when reading/writing headers
   217  	keyBlock, _ := pem.Decode(key)
   218  	require.NotNil(t, keyBlock)
   219  	keyBlock.Headers = map[string]string{"hello": "world"}
   220  	key = pem.EncodeToMemory(keyBlock)
   221  	require.NoError(t, ioutil.WriteFile(path.Node.Cert, cert, 0644))
   222  	require.NoError(t, ioutil.WriteFile(path.Node.Key, key, 0600))
   223  
   224  	// if the update headers callback function fails, updating headers fails
   225  	k := ca.NewKeyReadWriter(path.Node, nil, nil)
   226  	err = k.ViewAndUpdateHeaders(func(h ca.PEMKeyHeaders) (ca.PEMKeyHeaders, error) {
   227  		require.Nil(t, h)
   228  		return nil, fmt.Errorf("nope")
   229  	})
   230  	require.Error(t, err)
   231  	require.Equal(t, "nope", err.Error())
   232  
   233  	// updating headers succeed and is called with the latest kek data
   234  	err = k.ViewAndUpdateHeaders(func(h ca.PEMKeyHeaders) (ca.PEMKeyHeaders, error) {
   235  		require.Nil(t, h)
   236  		return testHeaders{newHeaders: func(kek ca.KEKData) (map[string]string, error) {
   237  			return map[string]string{"updated": "headers"}, nil
   238  		}}, nil
   239  	})
   240  	require.NoError(t, err)
   241  
   242  	k = ca.NewKeyReadWriter(path.Node, nil, testHeaders{setHeaders: func(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) {
   243  		require.Equal(t, map[string]string{"updated": "headers"}, h)
   244  		require.Equal(t, ca.KEKData{}, k)
   245  		return testHeaders{}, nil
   246  	}})
   247  	_, _, err = k.Read()
   248  	require.NoError(t, err)
   249  
   250  	// we can also update headers on an encrypted key
   251  	k = ca.NewKeyReadWriter(path.Node, []byte("kek"), nil)
   252  	require.NoError(t, k.Write(cert, key, nil))
   253  
   254  	err = k.ViewAndUpdateHeaders(func(h ca.PEMKeyHeaders) (ca.PEMKeyHeaders, error) {
   255  		require.Nil(t, h)
   256  		return testHeaders{newHeaders: func(kek ca.KEKData) (map[string]string, error) {
   257  			require.Equal(t, ca.KEKData{KEK: []byte("kek")}, kek)
   258  			return map[string]string{"updated": "headers"}, nil
   259  		}}, nil
   260  	})
   261  	require.NoError(t, err)
   262  
   263  	k = ca.NewKeyReadWriter(path.Node, []byte("kek"), testHeaders{setHeaders: func(h map[string]string, k ca.KEKData) (ca.PEMKeyHeaders, error) {
   264  		require.Equal(t, map[string]string{"updated": "headers"}, h)
   265  		require.Equal(t, ca.KEKData{KEK: []byte("kek")}, k)
   266  		return testHeaders{}, nil
   267  	}})
   268  	_, _, err = k.Read()
   269  	require.NoError(t, err)
   270  }
   271  
   272  func TestKeyReadWriterViewAndRotateKEK(t *testing.T) {
   273  	cert, key, err := testutils.CreateRootCertAndKey("cn")
   274  	require.NoError(t, err)
   275  
   276  	tempdir, err := ioutil.TempDir("", "KeyReadWriter")
   277  	require.NoError(t, err)
   278  	defer os.RemoveAll(tempdir)
   279  
   280  	path := ca.NewConfigPaths(filepath.Join(tempdir))
   281  
   282  	// write a key with headers to the key to make sure it gets passed when reading/writing headers
   283  	keyBlock, _ := pem.Decode(key)
   284  	require.NotNil(t, keyBlock)
   285  	keyBlock.Headers = map[string]string{"hello": "world"}
   286  	key = pem.EncodeToMemory(keyBlock)
   287  	require.NoError(t, ca.NewKeyReadWriter(path.Node, nil, nil).Write(cert, key, nil))
   288  
   289  	// if if getting new kek and headers fail, rotating a KEK fails, and the kek does not rotate
   290  	k := ca.NewKeyReadWriter(path.Node, nil, nil)
   291  	require.Error(t, k.ViewAndRotateKEK(func(k ca.KEKData, h ca.PEMKeyHeaders) (ca.KEKData, ca.PEMKeyHeaders, error) {
   292  		require.Equal(t, ca.KEKData{}, k)
   293  		require.Nil(t, h)
   294  		return ca.KEKData{}, nil, fmt.Errorf("Nope")
   295  	}))
   296  
   297  	// writing new headers will write a key that has the headers returned by the header update function
   298  	k = ca.NewKeyReadWriter(path.Node, []byte("oldKEK"), nil)
   299  	require.NoError(t, k.ViewAndRotateKEK(func(k ca.KEKData, h ca.PEMKeyHeaders) (ca.KEKData, ca.PEMKeyHeaders, error) {
   300  		require.Equal(t, ca.KEKData{KEK: []byte("oldKEK")}, k)
   301  		require.Nil(t, h)
   302  		return ca.KEKData{KEK: []byte("newKEK"), Version: uint64(2)},
   303  			testHeaders{newHeaders: func(kek ca.KEKData) (map[string]string, error) {
   304  				require.Equal(t, []byte("newKEK"), kek.KEK)
   305  				return map[string]string{"updated": "headers"}, nil
   306  			}}, nil
   307  	}))
   308  
   309  	// ensure the key has been re-encrypted and we can read it
   310  	k = ca.NewKeyReadWriter(path.Node, nil, nil)
   311  	_, _, err = k.Read()
   312  	require.Error(t, err)
   313  
   314  	var headers map[string]string
   315  
   316  	k = ca.NewKeyReadWriter(path.Node, []byte("newKEK"), testHeaders{setHeaders: func(h map[string]string, _ ca.KEKData) (ca.PEMKeyHeaders, error) {
   317  		headers = h
   318  		return testHeaders{}, nil
   319  	}})
   320  	_, _, err = k.Read()
   321  	require.NoError(t, err)
   322  	require.Equal(t, map[string]string{"updated": "headers"}, headers)
   323  }
   324  
   325  // If we abort in the middle of writing the key and cert, such that only the key is written
   326  // to the final location, when we read we can still read the cert from the temporary
   327  // location.
   328  func TestTwoPhaseReadWrite(t *testing.T) {
   329  	cert1, _, err := testutils.CreateRootCertAndKey("cn")
   330  	require.NoError(t, err)
   331  
   332  	cert2, key2, err := testutils.CreateRootCertAndKey("cn")
   333  	require.NoError(t, err)
   334  
   335  	tempdir, err := ioutil.TempDir("", "KeyReadWriter")
   336  	require.NoError(t, err)
   337  	defer os.RemoveAll(tempdir)
   338  
   339  	path := ca.NewConfigPaths(filepath.Join(tempdir))
   340  	krw := ca.NewKeyReadWriter(path.Node, nil, nil)
   341  
   342  	// put a directory in the location where the cert goes, so we can't actually move
   343  	// the cert from the temporary location to the final location.
   344  	require.NoError(t, os.Mkdir(filepath.Join(path.Node.Cert), 0755))
   345  	require.Error(t, krw.Write(cert2, key2, nil))
   346  
   347  	// the temp cert file should exist
   348  	tempCertPath := filepath.Join(filepath.Dir(path.Node.Cert), "."+filepath.Base(path.Node.Cert))
   349  	readCert, err := ioutil.ReadFile(tempCertPath)
   350  	require.NoError(t, err)
   351  	require.Equal(t, cert2, readCert)
   352  
   353  	// remove the directory, to simulate it failing to write the first time
   354  	os.RemoveAll(path.Node.Cert)
   355  	readCert, readKey, err := krw.Read()
   356  	require.NoError(t, err)
   357  	require.Equal(t, cert2, readCert)
   358  	require.Equal(t, key2, readKey)
   359  	// the cert should have been moved to its proper location
   360  	_, err = os.Stat(tempCertPath)
   361  	require.True(t, os.IsNotExist(err))
   362  
   363  	// If the cert in the proper location doesn't match the key, the temp location is checked
   364  	require.NoError(t, ioutil.WriteFile(tempCertPath, cert2, 0644))
   365  	require.NoError(t, ioutil.WriteFile(path.Node.Cert, cert1, 0644))
   366  	readCert, readKey, err = krw.Read()
   367  	require.NoError(t, err)
   368  	require.Equal(t, cert2, readCert)
   369  	require.Equal(t, key2, readKey)
   370  	// the cert should have been moved to its proper location
   371  	_, err = os.Stat(tempCertPath)
   372  	require.True(t, os.IsNotExist(err))
   373  
   374  	// If the cert in the temp location also doesn't match, the failure matching the
   375  	// correctly-located cert is returned
   376  	require.NoError(t, os.Remove(path.Node.Cert))
   377  	require.NoError(t, ioutil.WriteFile(tempCertPath, cert1, 0644)) // mismatching cert
   378  	_, _, err = krw.Read()
   379  	require.True(t, os.IsNotExist(err))
   380  	// the cert should have been removed
   381  	_, err = os.Stat(tempCertPath)
   382  	require.True(t, os.IsNotExist(err))
   383  }
   384  
   385  func TestKeyReadWriterMigrate(t *testing.T) {
   386  	cert, key, err := testutils.CreateRootCertAndKey("cn")
   387  	require.NoError(t, err)
   388  
   389  	tempdir, err := ioutil.TempDir("", "KeyReadWriter")
   390  	require.NoError(t, err)
   391  	defer os.RemoveAll(tempdir)
   392  
   393  	path := ca.NewConfigPaths(filepath.Join(tempdir))
   394  
   395  	// if the key exists in an old location, migrate it from there.
   396  	tempKeyPath := filepath.Join(filepath.Dir(path.Node.Key), "."+filepath.Base(path.Node.Key))
   397  	require.NoError(t, ioutil.WriteFile(path.Node.Cert, cert, 0644))
   398  	require.NoError(t, ioutil.WriteFile(tempKeyPath, key, 0600))
   399  
   400  	krw := ca.NewKeyReadWriter(path.Node, nil, nil)
   401  	require.NoError(t, krw.Migrate())
   402  	_, err = os.Stat(tempKeyPath)
   403  	require.True(t, os.IsNotExist(err)) // it's been moved to the right place
   404  	_, _, err = krw.Read()
   405  	require.NoError(t, err)
   406  
   407  	// migrate does not affect any existing files
   408  	dirList, err := ioutil.ReadDir(filepath.Dir(path.Node.Key))
   409  	require.NoError(t, err)
   410  	require.NoError(t, krw.Migrate())
   411  	dirList2, err := ioutil.ReadDir(filepath.Dir(path.Node.Key))
   412  	require.NoError(t, err)
   413  	require.Equal(t, dirList, dirList2)
   414  	_, _, err = krw.Read()
   415  	require.NoError(t, err)
   416  }
   417  
   418  type downgradeTestCase struct {
   419  	encrypted bool
   420  	pkcs8     bool
   421  	errorStr  string
   422  }
   423  
   424  func testKeyReadWriterDowngradeKeyCase(t *testing.T, tc downgradeTestCase) error {
   425  	cert, key, err := testutils.CreateRootCertAndKey("cn")
   426  	require.NoError(t, err)
   427  
   428  	if !tc.pkcs8 {
   429  		key, err = pkcs8.ConvertToECPrivateKeyPEM(key)
   430  		require.NoError(t, err)
   431  	}
   432  
   433  	var kek []byte
   434  	if tc.encrypted {
   435  		block, _ := pem.Decode(key)
   436  		require.NotNil(t, block)
   437  
   438  		kek = []byte("kek")
   439  		block, err = keyutils.Default.EncryptPEMBlock(block.Bytes, kek)
   440  		require.NoError(t, err)
   441  
   442  		key = pem.EncodeToMemory(block)
   443  	}
   444  
   445  	tempdir, err := ioutil.TempDir("", "KeyReadWriterDowngrade")
   446  	require.NoError(t, err)
   447  	defer os.RemoveAll(tempdir)
   448  
   449  	path := ca.NewConfigPaths(filepath.Join(tempdir))
   450  
   451  	block, _ := pem.Decode(key)
   452  	require.NotNil(t, block)
   453  
   454  	// add kek-version to later check if it is still there
   455  	block.Headers["kek-version"] = "5"
   456  
   457  	key = pem.EncodeToMemory(block)
   458  	require.NoError(t, ioutil.WriteFile(path.Node.Cert, cert, 0644))
   459  	require.NoError(t, ioutil.WriteFile(path.Node.Key, key, 0600))
   460  
   461  	// if the update headers callback function fails, updating headers fails
   462  	k := ca.NewKeyReadWriter(path.Node, kek, nil)
   463  	if err := k.DowngradeKey(); err != nil {
   464  		return err
   465  	}
   466  
   467  	// read the key directly from fs so we can check if key
   468  	key, err = ioutil.ReadFile(path.Node.Key)
   469  	require.NoError(t, err)
   470  
   471  	keyBlock, _ := pem.Decode(key)
   472  	require.NotNil(t, block)
   473  	require.False(t, keyutils.IsPKCS8(keyBlock.Bytes))
   474  
   475  	if tc.encrypted {
   476  		require.True(t, keyutils.IsEncryptedPEMBlock(keyBlock))
   477  	}
   478  	require.Equal(t, "5", keyBlock.Headers["kek-version"])
   479  
   480  	// check if KeyReaderWriter can read the key
   481  	_, _, err = k.Read()
   482  	require.NoError(t, err)
   483  	return nil
   484  }
   485  
   486  func TestKeyReadWriterDowngradeKey(t *testing.T) {
   487  	invalid := []downgradeTestCase{
   488  		{
   489  			encrypted: false,
   490  			pkcs8:     false,
   491  			errorStr:  "key is already downgraded to PKCS#1",
   492  		}, {
   493  			encrypted: true,
   494  			pkcs8:     false,
   495  			errorStr:  "key is already downgraded to PKCS#1",
   496  		},
   497  	}
   498  
   499  	for _, c := range invalid {
   500  		err := testKeyReadWriterDowngradeKeyCase(t, c)
   501  		require.Error(t, err)
   502  		require.EqualError(t, err, c.errorStr)
   503  	}
   504  
   505  	valid := []downgradeTestCase{
   506  		{
   507  			encrypted: false,
   508  			pkcs8:     true,
   509  		}, {
   510  			encrypted: true,
   511  			pkcs8:     true,
   512  		},
   513  	}
   514  
   515  	for _, c := range valid {
   516  		err := testKeyReadWriterDowngradeKeyCase(t, c)
   517  		require.NoError(t, err)
   518  	}
   519  }
   520  
   521  // In FIPS mode, when reading a PKCS1 encrypted key, a PKCS1 error is returned as opposed
   522  // to any other type of invalid KEK error
   523  func TestKeyReadWriterReadNonFIPS(t *testing.T) {
   524  	t.Parallel()
   525  	cert, key, err := testutils.CreateRootCertAndKey("cn")
   526  	require.NoError(t, err)
   527  
   528  	key, err = pkcs8.ConvertToECPrivateKeyPEM(key)
   529  	require.NoError(t, err)
   530  
   531  	tempdir, err := ioutil.TempDir("", "KeyReadWriter")
   532  	require.NoError(t, err)
   533  	defer os.RemoveAll(tempdir)
   534  
   535  	path := ca.NewConfigPaths(filepath.Join(tempdir, "subdir")) // to make sure subdirectories are created
   536  
   537  	k := ca.NewKeyReadWriter(path.Node, nil, nil)
   538  	k.SetKeyFormatter(keyutils.FIPS)
   539  
   540  	// can write an unencrypted PKCS1 key with no issues
   541  	require.NoError(t, k.Write(cert, key, nil))
   542  	// can read the unencrypted key with no issues
   543  	readCert, readKey, err := k.Read()
   544  	require.NoError(t, err)
   545  	require.Equal(t, cert, readCert)
   546  	require.Equal(t, key, readKey)
   547  
   548  	// cannot write an encrypted PKCS1 key
   549  	passphrase := []byte("passphrase")
   550  	require.Equal(t, keyutils.ErrFIPSUnsupportedKeyFormat, k.Write(cert, key, &ca.KEKData{KEK: passphrase}))
   551  
   552  	k.SetKeyFormatter(keyutils.Default)
   553  	require.NoError(t, k.Write(cert, key, &ca.KEKData{KEK: passphrase}))
   554  
   555  	// cannot read an encrypted PKCS1 key
   556  	k.SetKeyFormatter(keyutils.FIPS)
   557  	_, _, err = k.Read()
   558  	require.Equal(t, keyutils.ErrFIPSUnsupportedKeyFormat, err)
   559  
   560  	k.SetKeyFormatter(keyutils.Default)
   561  	_, _, err = k.Read()
   562  	require.NoError(t, err)
   563  }