diff --git a/kms/pkcs11/pkcs11.go b/kms/pkcs11/pkcs11.go index 46d0f962..0e9284a5 100644 --- a/kms/pkcs11/pkcs11.go +++ b/kms/pkcs11/pkcs11.go @@ -12,11 +12,17 @@ import ( "encoding/hex" "fmt" "math/big" + "os" + "os/exec" + "runtime" "strconv" + "strings" "sync" + "time" "github.com/ThalesIgnite/crypto11" "github.com/pkg/errors" + "go.step.sm/crypto/kms/apiv1" "go.step.sm/crypto/kms/uri" ) @@ -60,7 +66,6 @@ func New(ctx context.Context, opts apiv1.Options) (*PKCS11, error) { } config.Pin = u.Pin() - config.Path = u.Get("module-path") config.TokenLabel = u.Get("token") config.TokenSerial = u.Get("serial") if v := u.Get("slot-id"); v != "" { @@ -70,6 +75,10 @@ func New(ctx context.Context, opts apiv1.Options) (*PKCS11, error) { } config.SlotNumber = &n } + // Get module or default to use p11-kit-proxy.so + if config.Path = u.Get("module-path"); config.Path == "" { + config.Path = findP11KitProxy(ctx) + } } if config.Pin == "" && opts.Pin != "" { config.Pin = opts.Pin @@ -402,4 +411,34 @@ func findCertificate(ctx P11, rawuri string) (*x509.Certificate, error) { return cert, nil } +// findP11KitProxy uses pkg-config to locate p11-kit-proxy.so +func findP11KitProxy(ctx context.Context) string { + var out strings.Builder + + // It should be more than enough even in constraint VMs + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + cmd := exec.CommandContext(ctx, "pkg-config", "--variable=proxy_module", "p11-kit-1") + cmd.Stdout = &out + if err := cmd.Run(); err != nil { + return "" + } + + path := strings.TrimSpace(out.String()) + if _, err := os.Stat(path); err != nil { + if runtime.GOOS != "darwin" { + return "" + } + + // pkg-config might return an .so file instead of a .dylib on macOs. + path = strings.Replace(path, ".so", ".dylib", 1) + if _, err := os.Stat(path); err != nil { + return "" + } + } + + return path +} + var _ apiv1.CertificateManager = (*PKCS11)(nil) diff --git a/kms/pkcs11/pkcs11_test.go b/kms/pkcs11/pkcs11_test.go index e6fcae9f..580806a2 100644 --- a/kms/pkcs11/pkcs11_test.go +++ b/kms/pkcs11/pkcs11_test.go @@ -41,6 +41,18 @@ func TestNew(t *testing.T) { return k.p11, nil } + var ( + wantMissingModule *PKCS11 + wantErrMissingModule = true + ) + if findP11KitProxy(context.Background()) != "" { + wantMissingModule = k + wantErrMissingModule = false + } + + canceledContext, cancel := context.WithCancel(context.Background()) + cancel() + type args struct { ctx context.Context opts apiv1.Options @@ -68,10 +80,14 @@ func TestNew(t *testing.T) { URI: "pkcs11:module-path=/usr/local/lib/softhsm/libsofthsm2.so;token=pkcs11-test", Pin: "passowrd", }}, k, false}, - {"fail missing module", args{context.Background(), apiv1.Options{ + {"perhaps with missing module", args{context.Background(), apiv1.Options{ Type: "pkcs11", URI: "pkcs11:token=pkcs11-test", Pin: "passowrd", + }}, wantMissingModule, wantErrMissingModule}, + {"fail findP11KitProxy", args{canceledContext, apiv1.Options{ + Type: "pkcs11", + URI: "pkcs11:token=pkcs11-test?pin-value=password", }}, nil, true}, {"fail missing pin", args{context.Background(), apiv1.Options{ Type: "pkcs11",