250 lines
5.7 KiB
Go
250 lines
5.7 KiB
Go
/*
|
|
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 (
|
|
"context"
|
|
"fmt"
|
|
"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{}
|
|
|
|
ctx := hsm.SetupContext(hsm.CaConfigOption(&testSignerConfig))
|
|
|
|
assert.Equal(t, &testSignerConfig, hsm.GetSignerConfig(ctx))
|
|
}
|
|
|
|
func TestGetSignerConfig_empty(t *testing.T) {
|
|
ctx := hsm.SetupContext()
|
|
|
|
assert.Nil(t, hsm.GetSignerConfig(ctx))
|
|
}
|
|
|
|
func TestSetupModeOption(t *testing.T) {
|
|
ctx := hsm.SetupContext(hsm.SetupModeOption())
|
|
|
|
assert.True(t, hsm.IsSetupMode(ctx))
|
|
}
|
|
|
|
func TestIsSetupMode_not_set(t *testing.T) {
|
|
ctx := hsm.SetupContext()
|
|
|
|
assert.False(t, hsm.IsSetupMode(ctx))
|
|
}
|
|
|
|
func TestVerboseLoggingOption(t *testing.T) {
|
|
ctx := hsm.SetupContext(hsm.VerboseLoggingOption())
|
|
|
|
assert.True(t, hsm.IsVerbose(ctx))
|
|
}
|
|
|
|
func TestIsVerbose_not_set(t *testing.T) {
|
|
ctx := hsm.SetupContext()
|
|
|
|
assert.False(t, hsm.IsVerbose(ctx))
|
|
}
|
|
|
|
func TestSetupContext(t *testing.T) {
|
|
testConfig := setupSignerConfig(t)
|
|
|
|
ctx := hsm.SetupContext(hsm.SetupModeOption(), hsm.VerboseLoggingOption(), hsm.CaConfigOption(testConfig))
|
|
|
|
assert.True(t, hsm.IsSetupMode(ctx))
|
|
assert.True(t, hsm.IsVerbose(ctx))
|
|
assert.Equal(t, hsm.GetSignerConfig(ctx), testConfig)
|
|
}
|
|
|
|
func TestGetP11Context_missing_SetupContext(t *testing.T) {
|
|
p11Context, err := hsm.GetP11Context(context.Background(), &config.CaCertificateEntry{Storage: "default"})
|
|
|
|
assert.Error(t, err)
|
|
assert.ErrorContains(t, err, "type assertion failed, use hsm.SetupContext first")
|
|
assert.Nil(t, p11Context)
|
|
}
|
|
|
|
func TestGetP11Context_unknown_storage(t *testing.T) {
|
|
testConfig := setupSignerConfig(t)
|
|
|
|
ctx := hsm.SetupContext(hsm.SetupModeOption(), hsm.CaConfigOption(testConfig))
|
|
|
|
definition := &config.CaCertificateEntry{Storage: "undefined"}
|
|
|
|
p11Context, err := hsm.GetP11Context(ctx, definition)
|
|
|
|
assert.Error(t, err)
|
|
assert.ErrorContains(t, err, "key storage undefined not available")
|
|
assert.Nil(t, p11Context)
|
|
}
|
|
|
|
func TestGetP11Context_wrong_pin(t *testing.T) {
|
|
testConfig := setupSignerConfig(t)
|
|
setupSoftHsm(t)
|
|
|
|
t.Setenv("TOKEN_PIN_ACME_TEST_HSM", "wrongpin")
|
|
|
|
ctx := hsm.SetupContext(hsm.CaConfigOption(testConfig))
|
|
|
|
definition, err := testConfig.GetCADefinition("root")
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = hsm.GetP11Context(ctx, definition)
|
|
|
|
assert.ErrorContains(t, err, "could not configure PKCS#11 library")
|
|
}
|
|
|
|
func TestGetP11Context_no_pin(t *testing.T) {
|
|
testConfig := setupSignerConfig(t)
|
|
setupSoftHsm(t)
|
|
|
|
ctx := hsm.SetupContext(hsm.CaConfigOption(testConfig))
|
|
|
|
definition, err := testConfig.GetCADefinition("root")
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = hsm.GetP11Context(ctx, definition)
|
|
|
|
assert.ErrorContains(t, err, "stdin is not a terminal")
|
|
}
|
|
|
|
func TestGetP11Context(t *testing.T) {
|
|
testConfig := setupSignerConfig(t)
|
|
setupSoftHsm(t)
|
|
|
|
t.Setenv("TOKEN_PIN_ACME_TEST_HSM", "123456")
|
|
|
|
ctx := hsm.SetupContext(hsm.CaConfigOption(testConfig))
|
|
|
|
definition, err := testConfig.GetCADefinition("root")
|
|
|
|
require.NoError(t, err)
|
|
|
|
p11Context1, err := hsm.GetP11Context(ctx, definition)
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, p11Context1)
|
|
|
|
p11Context2, err := hsm.GetP11Context(ctx, definition)
|
|
|
|
t.Cleanup(func() {
|
|
err := hsm.CloseP11Contexts(ctx)
|
|
assert.NoError(t, err)
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, p11Context1)
|
|
assert.Equal(t, p11Context1, p11Context2)
|
|
}
|
|
|
|
const testSignerConfig = `---
|
|
Settings:
|
|
organization:
|
|
organization: ["Acme CAs Ltd."]
|
|
validity-years:
|
|
root: 30
|
|
intermediary: 10
|
|
url-patterns:
|
|
ocsp: http://ocsp.example.org/
|
|
crl: http://crl.example.org/%s.crl
|
|
issuer: http://%s.cas.example.org/
|
|
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
|
|
`
|
|
|
|
func setupSignerConfig(t *testing.T) *config.SignerConfig {
|
|
t.Helper()
|
|
|
|
conf, err := config.LoadConfiguration(strings.NewReader(testSignerConfig))
|
|
|
|
require.NoError(t, err)
|
|
|
|
return conf
|
|
}
|
|
|
|
func setupSoftHsm(t *testing.T) {
|
|
t.Helper()
|
|
|
|
tempdir := t.TempDir()
|
|
|
|
tokenDir := path.Join(tempdir, "tokens")
|
|
softhsmConfig := path.Join(tempdir, "softhsm2.conf")
|
|
|
|
err := os.Mkdir(tokenDir, 0o700)
|
|
|
|
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)
|
|
}
|
|
|
|
func TestCloseP11Contexts_without_setup(t *testing.T) {
|
|
ctx := context.Background()
|
|
err := hsm.CloseP11Contexts(ctx)
|
|
|
|
assert.ErrorContains(t, err, "type assertion failed, use hsm.SetupContext first")
|
|
}
|