Skip to content

Commit 7066f12

Browse files
authored
PKCS11 signing support (#985)
* Implemented PKCS11 support. Signed-off-by: Kieran Miller <[email protected]> * Fixed lint and doc issues, and added pkcs11key flag to verify.sh. Signed-off-by: Kieran Miller <[email protected]> * Added missing = sign Signed-off-by: Kieran Miller <[email protected]> * Improved PKCS11 URI parsing. Added PKCS11 tests. Signed-off-by: Kieran Miller <[email protected]> * Fixed typo. Signed-off-by: Kieran Miller <[email protected]> * Resolve go.mod and go.sum conflicts Signed-off-by: Kieran Miller <[email protected]> * Fix go.mod indentation Signed-off-by: Kieran Miller <[email protected]> * Fixed docgen and lint issues. Signed-off-by: Kieran Miller <[email protected]> * Reduce duplication of code by moving PKCS11 URI detection down. Signed-off-by: Kieran Miller <[email protected]>
1 parent 9b9cd94 commit 7066f12

25 files changed

+1822
-6
lines changed

.goreleaser.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,21 @@ builds:
4949
env:
5050
- PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig/"
5151

52+
- id: linux-pkcs11key-amd64
53+
binary: cosign-linux-pkcs11key-amd64
54+
main: ./cmd/cosign
55+
flags:
56+
- -trimpath
57+
mod_timestamp: '{{ .CommitTimestamp }}'
58+
goos:
59+
- linux
60+
goarch:
61+
- amd64
62+
ldflags:
63+
- "{{ .Env.LDFLAGS }}"
64+
tags:
65+
- pkcs11key
66+
5267
- id: darwin-amd64
5368
binary: cosign-darwin-amd64
5469
no_unique_dist_dir: true

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ cosign: $(SRCS)
6161
cosign-pivkey: $(SRCS)
6262
CGO_ENABLED=1 go build -trimpath -tags=pivkey -ldflags $(LDFLAGS) -o cosign ./cmd/cosign
6363

64+
cosign-pkcs11key: $(SRCS)
65+
CGO_ENABLED=1 go build -trimpath -tags=pkcs11key -ldflags $(LDFLAGS) -o cosign ./cmd/cosign
66+
6467
GOLANGCI_LINT_DIR = $(shell pwd)/bin
6568
GOLANGCI_LINT_BIN = $(GOLANGCI_LINT_DIR)/golangci-lint
6669
golangci-lint:

PKCS11.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# PKCS11 Tokens
2+
3+
The `cosign` command line tool optionally supports PKCS11 tokens for signing.
4+
This support is enabled through the [crypto11](https://github.com/ThalesIgnite/crypto11) and the [pkcs11](https://github.com/miekg/pkcs11) libraries, which are not included in the standard release. Use [`make cosign-pkcs11key`](https://github.com/sigstore/cosign/blob/a8d1cc1132d4a019a62ff515b9375c8c5b98a5c5/Makefile#L52), or `go build -tags=pkcs11key`, to build `cosign` with support for PKCS11 tokens.
5+
6+
## Quick Start
7+
8+
### Setup
9+
10+
To get started, make sure you already have your PKCS11 module installed, and insert your PKCS11-compatible token.
11+
12+
Then, run the command `cosign pkcs11-tool list-tokens` to get the slot id of your token, as follows :
13+
14+
```shell
15+
$ cosign pkcs11-tool list-tokens --module-path /usr/local/lib/libp11.so
16+
Listing tokens of PKCS11 module '/usr/local/lib/libp11.so'
17+
Token in slot 1
18+
Label: TokenLabel
19+
Manufacturer: Token Manufacturer
20+
Model: Token Model
21+
S/N: 68800ca5c75e074c
22+
```
23+
24+
Afterwards, run the command `cosign pkcs11-tool list-keys-uris` to retrieve the PKCS11 URI of the key you wish to use, as follows :
25+
26+
```shell
27+
$ cosign pkcs11-tool list-keys-uris --module-path /usr/local/lib/libp11.so --slot-id 1 --pin 1234
28+
Listing URIs of keys in slot '1' of PKCS11 module '/usr/local/lib/libp11.so'
29+
Object 0
30+
Label: key_label_1
31+
ID: 4a8d2f6ed9c4152b260d6c74a1ae72fcfdc64b65
32+
URI: pkcs11:token=TokenLabel;slot-id=1;id=%4a%8d%2f%6e%d9%c4%15%2b%26%0d%6c%74%a1%ae%72%fc%fd%c6%4b%65?module-path=/usr/local/lib/libp11.so&pin-value=1234
33+
Object 1
34+
Label: key_label_2
35+
ID: 57b39235cc6dec404c2310d7e37d5cbb5f1bba70
36+
URI: pkcs11:token=TokenLabel;slot-id=1;id=%57%b3%92%35%cc%6d%ec%40%4c%23%10%d7%e3%7d%5c%bb%5f%1b%ba%70?module-path=/usr/local/lib/libp11.so&pin-value=1234
37+
```
38+
39+
You can also construct the PKCS11 URI of your key manually by providing the following URI components :
40+
41+
* **module-path** : the absolute path to the PKCS11 module **(optional)**
42+
43+
* **token** and/or **slot-id** : either or both of the PKCS11 token label and the PKCS11 slot id **(mandatory)**
44+
45+
* **object** and/or **id** : either or both of the PKCS11 key label and the PKCS11 key id **(mandatory)**
46+
47+
* **pin-value** : the PIN of the PKCS11 token **(optional)**
48+
49+
If `module-path` is not present in the URI, `cosign` expects the PKCS11 module path to be set using the environment variable `COSIGN_PKCS11_MODULE_PATH`. If neither are set, `cosign` will fail. If both are set, `module-path` has priority over `COSIGN_PKCS11_MODULE_PATH` environment variable.
50+
51+
If `pin-value` is not present in the URI, `cosign` expects the PIN to be set using the environment variable `COSIGN_PKCS11_PIN`. If it is not, `cosign` checks whether the PKCS11 token requires user login (flag CKF_LOGIN_REQUIRED set), and if so, `cosign` will invite the user to enter the PIN only during signing. If both `pin-value` and `COSIGN_PKCS11_PIN` environment variable are set, `pin-value` has priority over `COSIGN_PKCS11_PIN`.
52+
53+
### Signing
54+
55+
You can then use the normal `cosign` commands to sign images and blobs with your PKCS11 key.
56+
57+
```shell
58+
$ cosign sign --key "<PKCS11_URI>" gcr.io/dlorenc-vmtest2/demo
59+
Pushing signature to: gcr.io/dlorenc-vmtest2/demo:sha256-410a07f17151ffffb513f942a01748dfdb921de915ea6427d61d60b0357c1dcd.sig
60+
```
61+
62+
To verify, you can either use the PKCS11 token key directly:
63+
64+
```shell
65+
$ cosign verify --key "<PKCS11_URI>" gcr.io/dlorenc-vmtest2/demo
66+
Verification for gcr.io/dlorenc-vmtest2/demo --
67+
The following checks were performed on each of these signatures:
68+
- The cosign claims were validated
69+
- The signatures were verified against the specified public key
70+
- Any certificates were verified against the Fulcio roots.
71+
72+
[{"critical":{"identity":{"docker-reference":"gcr.io/dlorenc-vmtest2/demo"},"image":{"docker-manifest-digest":"sha256:410a07f17151ffffb513f942a01748dfdb921de915ea6427d61d60b0357c1dcd"},"type":"cosign container image signature"},"optional":null}]
73+
```
74+
75+
Or export the public key and verify against that:
76+
77+
```shell
78+
$ cosign public-key --key "<PKCS11_URI>" > pub.key
79+
80+
$ cosign verify --key pub.key gcr.io/dlorenc-vmtest2/demo
81+
Verification for gcr.io/dlorenc-vmtest2/demo --
82+
The following checks were performed on each of these signatures:
83+
- The cosign claims were validated
84+
- The signatures were verified against the specified public key
85+
- Any certificates were verified against the Fulcio roots.
86+
87+
[{"critical":{"identity":{"docker-reference":"gcr.io/dlorenc-vmtest2/demo"},"image":{"docker-manifest-digest":"sha256:410a07f17151ffffb513f942a01748dfdb921de915ea6427d61d60b0357c1dcd"},"type":"cosign container image signature"},"optional":null}]
88+
89+
```

cmd/cosign/cli/commands.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func New() *cobra.Command {
7070
cmd.AddCommand(Initialize())
7171
cmd.AddCommand(Manifest())
7272
cmd.AddCommand(PIVTool())
73+
cmd.AddCommand(PKCS11Tool())
7374
cmd.AddCommand(Policy())
7475
cmd.AddCommand(PublicKey())
7576
cmd.AddCommand(Sign())
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// Copyright 2021 The Sigstore Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package options
17+
18+
import (
19+
"github.com/spf13/cobra"
20+
)
21+
22+
// PKCS11ToolListTokens is the wrapper for `pkcs11-tool list-tokens` related options.
23+
type PKCS11ToolListTokensOptions struct {
24+
ModulePath string
25+
}
26+
27+
var _ Interface = (*PKCS11ToolListTokensOptions)(nil)
28+
29+
// AddFlags implements Interface
30+
func (o *PKCS11ToolListTokensOptions) AddFlags(cmd *cobra.Command) {
31+
cmd.Flags().StringVar(&o.ModulePath, "module-path", "",
32+
"absolute path to the PKCS11 module")
33+
}
34+
35+
// PKCS11ToolListKeysUrisOptions is the wrapper for `pkcs11-tool list-keys-uris` related options.
36+
type PKCS11ToolListKeysUrisOptions struct {
37+
ModulePath string
38+
SlotID uint
39+
Pin string
40+
}
41+
42+
var _ Interface = (*PKCS11ToolListKeysUrisOptions)(nil)
43+
44+
// AddFlags implements Interface
45+
func (o *PKCS11ToolListKeysUrisOptions) AddFlags(cmd *cobra.Command) {
46+
cmd.Flags().StringVar(&o.ModulePath, "module-path", "",
47+
"absolute path to the PKCS11 module")
48+
49+
cmd.Flags().UintVar(&o.SlotID, "slot-id", 0,
50+
"id of the PKCS11 slot, uses 0 if empty")
51+
52+
cmd.Flags().StringVar(&o.Pin, "pin", "",
53+
"pin of the PKCS11 slot, uses environment variable COSIGN_PKCS11_PIN if empty")
54+
}

cmd/cosign/cli/pkcs11_tool.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//go:build pkcs11key
2+
// +build pkcs11key
3+
4+
// Copyright 2021 The Sigstore Authors
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
package cli
19+
20+
import (
21+
"github.com/spf13/cobra"
22+
23+
"github.com/sigstore/cosign/cmd/cosign/cli/options"
24+
"github.com/sigstore/cosign/cmd/cosign/cli/pkcs11cli"
25+
)
26+
27+
var pkcs11ToolForce bool
28+
29+
func PKCS11Tool() *cobra.Command {
30+
cmd := &cobra.Command{
31+
Use: "pkcs11-tool",
32+
Short: "Provides utilities for retrieving information from a PKCS11 token.",
33+
}
34+
35+
cmd.AddCommand(
36+
pkcs11ToolListTokens(),
37+
PKCS11ToolListKeysUrisOptions(),
38+
)
39+
40+
// TODO: drop -f in favor of --no-input only
41+
// TODO: use the force flag.
42+
cmd.PersistentFlags().BoolVarP(&pkcs11ToolForce, "no-input", "f", false,
43+
"skip warnings and confirmations")
44+
45+
return cmd
46+
}
47+
48+
func pkcs11ToolListTokens() *cobra.Command {
49+
o := &options.PKCS11ToolListTokensOptions{}
50+
51+
cmd := &cobra.Command{
52+
Use: "list-tokens",
53+
Short: "list-tokens lists all PKCS11 tokens linked to a PKCS11 module",
54+
Args: cobra.ExactArgs(0),
55+
RunE: func(cmd *cobra.Command, args []string) error {
56+
return pkcs11cli.ListTokensCmd(cmd.Context(), o.ModulePath)
57+
},
58+
}
59+
60+
o.AddFlags(cmd)
61+
62+
return cmd
63+
}
64+
65+
func PKCS11ToolListKeysUrisOptions() *cobra.Command {
66+
o := &options.PKCS11ToolListKeysUrisOptions{}
67+
68+
cmd := &cobra.Command{
69+
Use: "list-keys-uris",
70+
Short: "list-keys-uris lists URIs of all keys in a PKCS11 token",
71+
Args: cobra.ExactArgs(0),
72+
RunE: func(cmd *cobra.Command, args []string) error {
73+
return pkcs11cli.ListKeysUrisCmd(cmd.Context(), o.ModulePath, o.SlotID, o.Pin)
74+
},
75+
}
76+
77+
o.AddFlags(cmd)
78+
79+
return cmd
80+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//go:build !pkcs11key
2+
// +build !pkcs11key
3+
4+
// Copyright 2021 The Sigstore Authors
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
package cli
19+
20+
import (
21+
"github.com/spf13/cobra"
22+
)
23+
24+
func PKCS11Tool() *cobra.Command {
25+
return &cobra.Command{
26+
Use: "pkcs11-tool",
27+
Short: "This cosign was not built with pkcs11-tool support!",
28+
}
29+
}

0 commit comments

Comments
 (0)