From 0a8b4896bac27490eb73d205942833c04902a2e7 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Wed, 13 Apr 2022 08:30:20 +0200 Subject: [PATCH] Add PKCS#11 test to generate root certificate - add documentation how to initialize SoftHSM for testing - add cmd/signer package to hold future signer command - add test to use a private key from softhsm to create a root certificate --- .gitignore | 2 + README.md | 13 ++++++ cmd/signer/main.go | 4 ++ cmd/signer/main_test.go | 96 +++++++++++++++++++++++++++++++++++++++++ go.mod | 12 ++++-- go.sum | 15 ++++++- 6 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 README.md create mode 100644 cmd/signer/main.go create mode 100644 cmd/signer/main_test.go diff --git a/.gitignore b/.gitignore index 9f11b75..c438f58 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ +*.pem +*.pub .idea/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..6781e6a --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# Testing with softhsm2 + +``` +sudo apt install softhsm2 gnutls-bin +umask 077 +mkdir -p ~/.config/softhsm2/tokens +echo "directories.tokendir = $HOME/.config/softhsm2/tokens/" > ~/.config/softhsm2/softhsm2.conf +softhsm2-util --init-token --free --label localhsm --so-pin 47110815 --pin 123456 +export TOKEN_URL=$(p11tool --list-token-urls | grep localhsm | head -1) +p11tool --login --outfile=rootkey2022.pub --label=rootkey2022 --generate-privkey=ECDSA --curve=secp521r1 $TOKEN_URL +go test -v ./cmd/signer/ +openssl x509 -in /tmp/test.pem -noout -text +``` diff --git a/cmd/signer/main.go b/cmd/signer/main.go new file mode 100644 index 0000000..da29a2c --- /dev/null +++ b/cmd/signer/main.go @@ -0,0 +1,4 @@ +package main + +func main() { +} diff --git a/cmd/signer/main_test.go b/cmd/signer/main_test.go new file mode 100644 index 0000000..fe0b62e --- /dev/null +++ b/cmd/signer/main_test.go @@ -0,0 +1,96 @@ +package main + +import ( + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "os" + "testing" + "time" + + "github.com/ThalesIgnite/crypto11" +) + +const defaultPkcs11Module = "/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so" + +func TestStart(t *testing.T) { + pkcs11Module, found := os.LookupEnv("PKCS11_LIB") + if !found { + pkcs11Module = defaultPkcs11Module + } + p11Context, err := crypto11.Configure(&crypto11.Config{ + Path: pkcs11Module, + TokenLabel: "localhsm", + Pin: "123456", + }) + if err != nil { + t.Fatalf("could not configure PKCS#11 library: %v", err) + } + + defer func(p11Context *crypto11.Context) { + err := p11Context.Close() + if err != nil { + t.Errorf("could not close PKCS#11 library context: %v", err) + } + }(p11Context) + + pair, err := p11Context.FindKeyPair(nil, []byte("rootkey2022")) + if err != nil { + t.Fatalf("could not find requested key pair: %v", err) + } + + serial, err := randomSerialNumber() + if err != nil { + t.Fatal(err) + } + + notBefore := time.Now() + notAfter := notBefore.AddDate(20, 0, 0) + + certTemplate := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{ + Country: []string{"CH"}, + Organization: []string{"CAcert Inc."}, + Locality: []string{"Genève"}, + StreetAddress: []string{"Clos Belmont 2"}, + PostalCode: []string{"1208"}, + CommonName: "CAcert ECC Root 2022", + }, + NotBefore: notBefore, + NotAfter: notAfter, + MaxPathLen: 0, + MaxPathLenZero: true, + BasicConstraintsValid: true, + KeyUsage: x509.KeyUsageCRLSign | x509.KeyUsageCertSign, + IsCA: true, + SignatureAlgorithm: x509.ECDSAWithSHA256, + } + + certificate, err := x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, pair.Public(), pair) + if err != nil { + t.Fatalf("could not create root certificate: %v", err) + } + + certBlock := &pem.Block{ + Type: "CERTIFICATE", + Bytes: certificate, + } + + err = os.WriteFile("/tmp/test.pem", pem.EncodeToMemory(certBlock), 0o600) + if err != nil { + t.Errorf("could not write certificate: %v", err) + } +} + +func randomSerialNumber() (*big.Int, error) { + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return nil, fmt.Errorf("could not generate serial number: %w", err) + } + return serialNumber, nil +} diff --git a/go.mod b/go.mod index da17bb5..69a5eff 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,15 @@ module git.cacert.org/cacert-gosigner go 1.17 require ( - github.com/davecgh/go-spew v1.1.0 // indirect + github.com/ThalesIgnite/crypto11 v1.2.5 + github.com/stretchr/testify v1.7.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/miekg/pkcs11 v1.1.1 // indirect + github.com/pkg/errors v0.8.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/objx v0.1.0 // indirect - github.com/stretchr/testify v1.7.0 // indirect + github.com/thales-e-security/pool v0.0.2 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index 7b4dc41..5f3a9ae 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,22 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E= +github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= +github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=