2022-04-24 12:05:46 +00:00
|
|
|
/*
|
|
|
|
Copyright 2022 CAcert Inc.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
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 hsm_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-08-03 07:59:26 +00:00
|
|
|
"log"
|
2022-04-24 12:05:46 +00:00
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"path"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
"git.cacert.org/cacert-gosigner/pkg/config"
|
|
|
|
"git.cacert.org/cacert-gosigner/pkg/hsm"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestCaConfigOption(t *testing.T) {
|
|
|
|
testSignerConfig := config.SignerConfig{}
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default(), hsm.CaConfigOption(&testSignerConfig))
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
assert.Equal(t, &testSignerConfig, access.GetSignerConfig())
|
2022-04-24 12:05:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetSignerConfig_empty(t *testing.T) {
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default())
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
assert.Nil(t, access.GetSignerConfig())
|
2022-04-24 12:05:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetupModeOption(t *testing.T) {
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default(), hsm.SetupModeOption())
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
assert.True(t, access.IsSetupMode())
|
2022-04-24 12:05:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestIsSetupMode_not_set(t *testing.T) {
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default())
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
assert.False(t, access.IsSetupMode())
|
2022-04-24 12:05:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestVerboseLoggingOption(t *testing.T) {
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default(), hsm.VerboseLoggingOption())
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
assert.True(t, access.IsVerbose())
|
2022-04-24 12:05:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestIsVerbose_not_set(t *testing.T) {
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default())
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
assert.False(t, access.IsVerbose())
|
2022-04-24 12:05:46 +00:00
|
|
|
}
|
|
|
|
|
2022-04-24 12:13:52 +00:00
|
|
|
func TestSetupContext(t *testing.T) {
|
|
|
|
testConfig := setupSignerConfig(t)
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(
|
|
|
|
log.Default(),
|
|
|
|
hsm.SetupModeOption(),
|
|
|
|
hsm.VerboseLoggingOption(),
|
|
|
|
hsm.CaConfigOption(testConfig),
|
|
|
|
)
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:13:52 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
assert.True(t, access.IsSetupMode())
|
|
|
|
assert.True(t, access.IsVerbose())
|
|
|
|
assert.Equal(t, access.GetSignerConfig(), testConfig)
|
2022-04-24 12:13:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetP11Context_unknown_storage(t *testing.T) {
|
|
|
|
testConfig := setupSignerConfig(t)
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default(), hsm.SetupModeOption(), hsm.CaConfigOption(testConfig))
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:13:52 +00:00
|
|
|
|
|
|
|
definition := &config.CaCertificateEntry{Storage: "undefined"}
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
p11Context, err := access.GetP11Context(definition)
|
2022-04-24 12:13:52 +00:00
|
|
|
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.ErrorContains(t, err, "key storage undefined not available")
|
|
|
|
assert.Nil(t, p11Context)
|
|
|
|
}
|
|
|
|
|
2022-05-01 10:36:17 +00:00
|
|
|
func TestGetP11Context_wrong_pin(t *testing.T) {
|
|
|
|
testConfig := setupSignerConfig(t)
|
|
|
|
setupSoftHsm(t)
|
|
|
|
|
|
|
|
t.Setenv("TOKEN_PIN_ACME_TEST_HSM", "wrongpin")
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default(), hsm.CaConfigOption(testConfig))
|
|
|
|
assert.NoError(t, err)
|
2022-05-01 10:36:17 +00:00
|
|
|
|
|
|
|
definition, err := testConfig.GetCADefinition("root")
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
_, err = access.GetP11Context(definition)
|
2022-05-01 10:36:17 +00:00
|
|
|
|
|
|
|
assert.ErrorContains(t, err, "could not configure PKCS#11 library")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetP11Context_no_pin(t *testing.T) {
|
|
|
|
testConfig := setupSignerConfig(t)
|
|
|
|
setupSoftHsm(t)
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default(), hsm.CaConfigOption(testConfig))
|
|
|
|
assert.NoError(t, err)
|
2022-05-01 10:36:17 +00:00
|
|
|
|
|
|
|
definition, err := testConfig.GetCADefinition("root")
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
_, err = access.GetP11Context(definition)
|
2022-05-01 10:36:17 +00:00
|
|
|
|
|
|
|
assert.ErrorContains(t, err, "stdin is not a terminal")
|
|
|
|
}
|
|
|
|
|
2022-04-24 12:13:52 +00:00
|
|
|
func TestGetP11Context(t *testing.T) {
|
|
|
|
testConfig := setupSignerConfig(t)
|
|
|
|
setupSoftHsm(t)
|
|
|
|
|
2022-05-01 10:36:17 +00:00
|
|
|
t.Setenv("TOKEN_PIN_ACME_TEST_HSM", "123456")
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
access, err := hsm.NewAccess(log.Default(), hsm.CaConfigOption(testConfig))
|
|
|
|
assert.NoError(t, err)
|
2022-04-24 12:13:52 +00:00
|
|
|
|
|
|
|
definition, err := testConfig.GetCADefinition("root")
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
p11Context1, err := access.GetP11Context(definition)
|
2022-04-24 12:13:52 +00:00
|
|
|
assert.NoError(t, err)
|
2022-08-03 07:59:26 +00:00
|
|
|
|
2022-04-24 12:13:52 +00:00
|
|
|
assert.NotNil(t, p11Context1)
|
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
p11Context2, err := access.GetP11Context(definition)
|
|
|
|
assert.NoError(t, err)
|
2022-05-01 10:36:17 +00:00
|
|
|
|
|
|
|
t.Cleanup(func() {
|
2022-08-03 07:59:26 +00:00
|
|
|
err := access.CloseP11Contexts()
|
2022-05-01 10:36:17 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
})
|
2022-04-24 12:13:52 +00:00
|
|
|
|
|
|
|
assert.NotNil(t, p11Context1)
|
|
|
|
assert.Equal(t, p11Context1, p11Context2)
|
|
|
|
}
|
|
|
|
|
2022-04-24 12:05:46 +00:00
|
|
|
const testSignerConfig = `---
|
|
|
|
Settings:
|
|
|
|
organization:
|
|
|
|
organization: ["Acme CAs Ltd."]
|
|
|
|
validity-years:
|
|
|
|
root: 30
|
2022-08-03 14:01:06 +00:00
|
|
|
subordinate: 10
|
2022-04-24 12:05:46 +00:00
|
|
|
url-patterns:
|
|
|
|
ocsp: http://ocsp.example.org/
|
|
|
|
crl: http://crl.example.org/%s.crl
|
|
|
|
issuer: http://%s.cas.example.org/
|
2022-08-03 12:38:36 +00:00
|
|
|
serial:
|
|
|
|
device: /dev/ttyUSB0
|
2022-04-24 12:05:46 +00:00
|
|
|
CAs:
|
|
|
|
root:
|
|
|
|
common-name: "Acme CAs root"
|
|
|
|
key-info:
|
|
|
|
algorithm: EC
|
|
|
|
ecc-curve: secp521r1
|
|
|
|
sub1:
|
|
|
|
common-name: "Acme CAs server sub CA"
|
|
|
|
parent: root
|
|
|
|
key-info:
|
|
|
|
algorithm: EC
|
|
|
|
ecc-curve: secp256r1
|
|
|
|
sub2:
|
|
|
|
common-name: "Acme CAs people sub CA"
|
|
|
|
parent: root
|
|
|
|
key-info:
|
|
|
|
algorithm: EC
|
|
|
|
ecc-curve: secp256r1
|
|
|
|
KeyStorage:
|
|
|
|
default:
|
|
|
|
type: softhsm
|
|
|
|
label: acme-test-hsm
|
|
|
|
`
|
|
|
|
|
2022-04-24 12:13:52 +00:00
|
|
|
func setupSignerConfig(t *testing.T) *config.SignerConfig {
|
|
|
|
t.Helper()
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-04-24 12:13:52 +00:00
|
|
|
conf, err := config.LoadConfiguration(strings.NewReader(testSignerConfig))
|
2022-04-24 12:05:46 +00:00
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-04-24 12:13:52 +00:00
|
|
|
return conf
|
2022-04-24 12:05:46 +00:00
|
|
|
}
|
|
|
|
|
2022-04-24 12:13:52 +00:00
|
|
|
func setupSoftHsm(t *testing.T) {
|
|
|
|
t.Helper()
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
tempDir := t.TempDir()
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-08-03 07:59:26 +00:00
|
|
|
tokenDir := path.Join(tempDir, "tokens")
|
|
|
|
softhsmConfig := path.Join(tempDir, "softhsm2.conf")
|
2022-04-24 12:05:46 +00:00
|
|
|
|
2022-04-24 12:13:52 +00:00
|
|
|
err := os.Mkdir(tokenDir, 0o700)
|
2022-04-24 12:05:46 +00:00
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = os.WriteFile(softhsmConfig, []byte(fmt.Sprintf("directories.tokendir = %s", tokenDir)), 0o600)
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
t.Setenv("SOFTHSM2_CONF", softhsmConfig)
|
|
|
|
|
|
|
|
err = exec.Command(
|
|
|
|
"softhsm2-util",
|
|
|
|
"--init-token",
|
|
|
|
"--free",
|
|
|
|
"--label",
|
|
|
|
"acme-test-hsm",
|
|
|
|
"--so-pin",
|
|
|
|
"12345678",
|
|
|
|
"--pin",
|
|
|
|
"123456",
|
|
|
|
).Run()
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
2022-05-01 10:36:17 +00:00
|
|
|
}
|