Skip to content

Commit f9d8b99

Browse files
committed
Add PKCS#11 changes back
1 parent 989ae54 commit f9d8b99

11 files changed

+1173
-20
lines changed

Makefile

+36-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
VERSION=1.0.5
1+
VERSION=1.0.6
22

33
release:
44
go build -buildmode=pie -ldflags "-X 'github.com/aws/rolesanywhere-credential-helper/cmd.Version=${VERSION}' -linkmode=external -w -s" -trimpath -o build/bin/aws_signing_helper main.go
55

6+
# Setting up SoftHSM for PKCS#11 tests.
7+
# This portion is largely copied from https://gitlab.com/openconnect/openconnect/-/blob/v9.12/tests/Makefile.am#L363.
8+
SHM2_UTIL=SOFTHSM2_CONF=tst/softhsm2.conf.tmp softhsm2-util
9+
P11TOOL=SOFTHSM2_CONF=tst/softhsm2.conf.tmp p11tool
10+
611
certsdir=tst/certs
712
curdir=$(shell pwd)
813

@@ -13,8 +18,30 @@ ECCERTS := $(foreach digest, sha1 sha256 sha384 sha512, $(patsubst %-key.pem, %-
1318
RSACERTS := $(foreach digest, md5 sha1 sha256 sha384 sha512, $(patsubst %-key.pem, %-$(digest)-cert.pem, $(RSAKEYS)))
1419
PKCS12CERTS := $(patsubst %-cert.pem, %.p12, $(RSACERTS) $(ECCERTS))
1520

16-
test: test-certs
17-
go test -v ./...
21+
# It's hard to do a file-based rule for the contents of the SoftHSM token.
22+
# So just populate it as a side-effect of creating the softhsm2.conf file.
23+
tst/softhsm2.conf: tst/softhsm2.conf.template $(PKCS8KEYS) $(RSACERTS) $(ECCERTS)
24+
rm -rf tst/softhsm/*
25+
sed 's|@top_srcdir@|${curdir}|g' $< > $@.tmp
26+
$(SHM2_UTIL) --show-slots
27+
$(SHM2_UTIL) --init-token --free --label credential-helper-test \
28+
--so-pin 12345678 --pin 1234
29+
30+
$(SHM2_UTIL) --token credential-helper-test --pin 1234 \
31+
--import $(certsdir)/rsa-2048-key-pkcs8.pem --label RSA --id 01
32+
$(P11TOOL) --load-certificate $(certsdir)/rsa-2048-sha256-cert.pem \
33+
--no-mark-private --label RSA --id 01 --set-pin 1234 --login \
34+
--write "pkcs11:token=credential-helper-test;pin-value=1234"
35+
36+
$(SHM2_UTIL) --token credential-helper-test --pin 1234 \
37+
--import $(certsdir)/ec-prime256v1-key-pkcs8.pem --label EC --id 02
38+
$(P11TOOL) --load-certificate $(certsdir)/ec-prime256v1-sha256-cert.pem \
39+
--no-mark-private --label EC --id 02 --set-pin 1234 --login \
40+
--write "pkcs11:token=credential-helper-test;pin-value=1234"
41+
mv $@.tmp $@
42+
43+
test: test-certs tst/softhsm2.conf
44+
SOFTHSM2_CONF=$(curdir)/tst/softhsm2.conf go test -v ./...
1845

1946
%-md5-cert.pem: %-key.pem
2047
SUBJ=$$(echo "$@" | sed -r 's|.*/([^/]+)-cert.pem|\1|'); \
@@ -43,6 +70,8 @@ test: test-certs
4370
-keypbe pbeWithSHA1And3-KeyTripleDES-CBC \
4471
-inkey $${KEY} -out "$@" -in $${CERT}
4572

73+
# And once again, it's hard to do a file-based rule for the contents of the certificate store.
74+
# So just populate it as a side-effect of creating the p12 file.
4675
%-pass.p12: %-cert.pem
4776
echo Creating $@...
4877
ls -l $<
@@ -66,11 +95,14 @@ $(ECKEYS):
6695
$(certsdir)/cert-bundle.pem: $(RSACERTS) $(ECCERTS)
6796
cat $^ > $@
6897

69-
test-certs: $(PKCS8KEYS) $(RSAKEYS) $(ECKEYS) $(RSACERTS) $(ECCERTS) $(PKCS12CERTS) $(certsdir)/cert-bundle.pem
98+
test-certs: $(PKCS8KEYS) $(RSAKEYS) $(ECKEYS) $(RSACERTS) $(ECCERTS) $(PKCS12CERTS) $(certsdir)/cert-bundle.pem tst/softhsm2.conf
7099

100+
# TODO: Need to clean certificates and keys added to certificate store as well
71101
test-clean:
72102
rm -f $(RSAKEYS) $(ECKEYS)
73103
rm -f $(PKCS8KEYS)
74104
rm -f $(RSACERTS) $(ECCERTS)
75105
rm -f $(PKCS12CERTS)
76106
rm -f $(certsdir)/cert-bundle.pem
107+
rm -f tst/softhsm2.conf
108+
rm -rf tst/softhsm/*

README.md

+31-2
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ The project also comes with two bash scripts at its root, called `generate-certs
3636

3737
### read-certificate-data
3838

39-
Reads a certificate that is on disk. Either the path to the certificate on disk is provided with the `--certificate` parameter, or the `--cert-selector` flag is provided to select a certificate within an OS certificate store. Further details about the flag are provided below.
39+
Reads a certificate. Either the path to the certificate on disk or PKCS#11 URI to identify the certificate is provided with the `--certificate` parameter, or the `--cert-selector` flag is provided to select a certificate within an OS certificate store. Further details about the `--cert-selector` flag are provided below.
4040

41-
If there are multiple certificates that match a given `--cert-selector`, information about each of them is printed.
41+
If there are multiple certificates that match a given `--cert-selector` or PKCS#11 URI (as specified through the `--certificate` parameter), information about each of them is printed. For PKCS#11, URIs for each matched certificate is also printed in the hopes that it will be useful in uniquely identifying a certificate.
4242

4343
#### cert-selector flag
4444

@@ -129,6 +129,35 @@ The above command will import the PFX file into the user's "MY" certificate stor
129129

130130
Also note that the above step can be done through a [Powershell cmdlet](https://learn.microsoft.com/en-us/powershell/module/pki/import-pfxcertificate?view=windowsserver2022-ps) or through [Windows CNG/Cryptography APIs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-pfximportcertstore).
131131

132+
#### PKCS#11 Integration
133+
134+
As you should expect from all applications which use keys and certificates, you can simply give a
135+
[PKCS#11 URI](https://datatracker.ietf.org/doc/html/rfc7512) in place of a filename in order to
136+
use certificates and/or keys from hardware or software PKCS#11 tokens / HSMs. A hybrid mode
137+
using a certificate from a file but only the key in PKCS#11 is also supported. Some examples:
138+
139+
* `--certificate 'pkcs11:manufacturer=piv_II;id=%01'`
140+
* `--certificate 'pkcs11:object=My%20RA%20key'`
141+
* `--certificate client-cert.pem --private-key 'pkcs11:model=SoftHSM%20v2;object=My%20RA%20key'`
142+
143+
Some documentation which may assist with finding the correct URI for
144+
your key can be found [here](https://www.infradead.org/openconnect/pkcs11.html).
145+
146+
Most Linux and similar *nix systems use
147+
[p11-kit](https://p11-glue.github.io/p11-glue/p11-kit/manual/config.html)
148+
to provide consistent system-wide and per-user configuration of
149+
available PKCS#11 providers. Any properly packaged provider module
150+
will register itself with p11-kit and will be automatically visible
151+
through the `p11-kit-proxy.so` provider which is used by default.
152+
153+
If you have a poorly packaged provider module from a vendor, then
154+
after you have filed a bug you can manually create a p11-kit [module
155+
file](https://p11-glue.github.io/p11-glue/p11-kit/manual/pkcs11-conf.html)
156+
for it.
157+
158+
For systems or containers which lack p11-kit, a specific PKCS#11
159+
provider library can be specified using the `--pkcs11-lib` parameter.
160+
132161
### update
133162

134163
Updates temporary credentials in the [credential file](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html). Parameters for this command include those for the `credential-process` command, as well as `--profile`, which specifies the named profile for which credentials should be updated (if the profile doesn't already exist, it will be created), and `--once`, which specifies that credentials should be updated only once. Both arguments are optional. If `--profile` isn't specified, the default profile will have its credentials updated, and if `--once` isn't specified, credentials will be continuously updated. In this case, credentials will be updated through a call to `CreateSession` five minutes before the previous set of credentials are set to expire. Please note that running the `update` command multiple times, creating multiple processes, may not work as intended. There may be issues with concurrent writes to the credentials file.

TODO.pkcs11

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
3+
4+
TODO for PKCS#11 support
5+
6+
• Clean up the support for entering PIN interactively, perhaps add URI
7+
pin-source= support
8+
9+
• Automated testing, perhaps by pulling in the prepopulated SoftHSM tokens
10+
used for openconnect testing. I've manually tested those and Yubikey PIV
11+
URIs including the following as --private-key arguments:
12+
• pkcs11:token=openconnect-test;object=RSA;pin-value=1234
13+
• pkcs11:token=openconnect-test;object=EC;pin-value=1234
14+
Repeat those as --certificate in order to test cert to key matching.
15+
Repeat (as both key and cert arguments) with openconnect-test[123] tokens
16+
which are torture tests for various things seen in the wild (no pubkey,
17+
having to log in to the token, and tokens lacking CKF_LOGIN_REQUIRED).
18+
19+
My Yubikey is old and doesn't have EC support, but it's useful for testing
20+
the CKA_ALWAYS_AUTHENTICATE support (on the Digital Signature key) and the
21+
matching by CKA_ID when CKA_LABEL doesn't match. So (assuming you provision
22+
the slot) this should work as both --private-key and --certificate:
23+
• pkcs11:manufacturer=piv_II;id=%02;pin-value=123456
24+
And this should work as --certificate, correctly finding the key:
25+
• pkcs11:manufacturer=piv_II;object=Certificate%20for%20Digital%20Signature?pin-value=123456
26+
27+
Check the output by using 'openssl dgst -verify', for example:
28+
29+
$ build/bin/aws_signing_helper sign-string --certificate pkcs11:token=openconnect-test\;object=RSA?pin-value=1234 <<< Test | xxd -r -ps > testsig
30+
$ openssl dgst -sha256 -engine pkcs11 -keyform engine -verify 'pkcs11:token=openconnect-test;object=RSA?pin-value=1234' -signature testsig <<< Test
31+
32+
33+
References:
34+
http://david.woodhou.se/draft-woodhouse-cert-best-practice.html#rfc.section.8
35+
https://datatracker.ietf.org/doc/html/rfc7512
36+
https://gitlab.com/openconnect/openconnect/-/blob/v9.12/openssl-pkcs11.c

0 commit comments

Comments
 (0)