Skip to content

Commit

Permalink
PKCS11 signing support (#985)
Browse files Browse the repository at this point in the history
* Implemented PKCS11 support.

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>

* Fixed lint and doc issues, and added pkcs11key flag to verify.sh.

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>

* Added missing = sign

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>

* Improved PKCS11 URI parsing.
Added PKCS11 tests.

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>

* Fixed typo.

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>

* Resolve go.mod and go.sum conflicts

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>

* Fix go.mod indentation

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>

* Fixed docgen and lint issues.

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>

* Reduce duplication of code by moving PKCS11 URI detection down.

Signed-off-by: Kieran Miller <kieran.miller@garantir.io>
  • Loading branch information
garantir-km authored Nov 6, 2021
1 parent 9b9cd94 commit 7066f12
Show file tree
Hide file tree
Showing 25 changed files with 1,822 additions and 6 deletions.
15 changes: 15 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ builds:
env:
- PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig/"

- id: linux-pkcs11key-amd64
binary: cosign-linux-pkcs11key-amd64
main: ./cmd/cosign
flags:
- -trimpath
mod_timestamp: '{{ .CommitTimestamp }}'
goos:
- linux
goarch:
- amd64
ldflags:
- "{{ .Env.LDFLAGS }}"
tags:
- pkcs11key

- id: darwin-amd64
binary: cosign-darwin-amd64
no_unique_dist_dir: true
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ cosign: $(SRCS)
cosign-pivkey: $(SRCS)
CGO_ENABLED=1 go build -trimpath -tags=pivkey -ldflags $(LDFLAGS) -o cosign ./cmd/cosign

cosign-pkcs11key: $(SRCS)
CGO_ENABLED=1 go build -trimpath -tags=pkcs11key -ldflags $(LDFLAGS) -o cosign ./cmd/cosign

GOLANGCI_LINT_DIR = $(shell pwd)/bin
GOLANGCI_LINT_BIN = $(GOLANGCI_LINT_DIR)/golangci-lint
golangci-lint:
Expand Down
89 changes: 89 additions & 0 deletions PKCS11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# PKCS11 Tokens

The `cosign` command line tool optionally supports PKCS11 tokens for signing.
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.

## Quick Start

### Setup

To get started, make sure you already have your PKCS11 module installed, and insert your PKCS11-compatible token.

Then, run the command `cosign pkcs11-tool list-tokens` to get the slot id of your token, as follows :

```shell
$ cosign pkcs11-tool list-tokens --module-path /usr/local/lib/libp11.so
Listing tokens of PKCS11 module '/usr/local/lib/libp11.so'
Token in slot 1
Label: TokenLabel
Manufacturer: Token Manufacturer
Model: Token Model
S/N: 68800ca5c75e074c
```

Afterwards, run the command `cosign pkcs11-tool list-keys-uris` to retrieve the PKCS11 URI of the key you wish to use, as follows :

```shell
$ cosign pkcs11-tool list-keys-uris --module-path /usr/local/lib/libp11.so --slot-id 1 --pin 1234
Listing URIs of keys in slot '1' of PKCS11 module '/usr/local/lib/libp11.so'
Object 0
Label: key_label_1
ID: 4a8d2f6ed9c4152b260d6c74a1ae72fcfdc64b65
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
Object 1
Label: key_label_2
ID: 57b39235cc6dec404c2310d7e37d5cbb5f1bba70
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
```

You can also construct the PKCS11 URI of your key manually by providing the following URI components :

* **module-path** : the absolute path to the PKCS11 module **(optional)**

* **token** and/or **slot-id** : either or both of the PKCS11 token label and the PKCS11 slot id **(mandatory)**

* **object** and/or **id** : either or both of the PKCS11 key label and the PKCS11 key id **(mandatory)**

* **pin-value** : the PIN of the PKCS11 token **(optional)**

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.

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`.

### Signing

You can then use the normal `cosign` commands to sign images and blobs with your PKCS11 key.

```shell
$ cosign sign --key "<PKCS11_URI>" gcr.io/dlorenc-vmtest2/demo
Pushing signature to: gcr.io/dlorenc-vmtest2/demo:sha256-410a07f17151ffffb513f942a01748dfdb921de915ea6427d61d60b0357c1dcd.sig
```

To verify, you can either use the PKCS11 token key directly:

```shell
$ cosign verify --key "<PKCS11_URI>" gcr.io/dlorenc-vmtest2/demo
Verification for gcr.io/dlorenc-vmtest2/demo --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
- Any certificates were verified against the Fulcio roots.

[{"critical":{"identity":{"docker-reference":"gcr.io/dlorenc-vmtest2/demo"},"image":{"docker-manifest-digest":"sha256:410a07f17151ffffb513f942a01748dfdb921de915ea6427d61d60b0357c1dcd"},"type":"cosign container image signature"},"optional":null}]
```

Or export the public key and verify against that:

```shell
$ cosign public-key --key "<PKCS11_URI>" > pub.key

$ cosign verify --key pub.key gcr.io/dlorenc-vmtest2/demo
Verification for gcr.io/dlorenc-vmtest2/demo --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
- Any certificates were verified against the Fulcio roots.

[{"critical":{"identity":{"docker-reference":"gcr.io/dlorenc-vmtest2/demo"},"image":{"docker-manifest-digest":"sha256:410a07f17151ffffb513f942a01748dfdb921de915ea6427d61d60b0357c1dcd"},"type":"cosign container image signature"},"optional":null}]

```
1 change: 1 addition & 0 deletions cmd/cosign/cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func New() *cobra.Command {
cmd.AddCommand(Initialize())
cmd.AddCommand(Manifest())
cmd.AddCommand(PIVTool())
cmd.AddCommand(PKCS11Tool())
cmd.AddCommand(Policy())
cmd.AddCommand(PublicKey())
cmd.AddCommand(Sign())
Expand Down
54 changes: 54 additions & 0 deletions cmd/cosign/cli/options/pkcs11_tool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// Copyright 2021 The Sigstore Authors.
//
// 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 options

import (
"github.com/spf13/cobra"
)

// PKCS11ToolListTokens is the wrapper for `pkcs11-tool list-tokens` related options.
type PKCS11ToolListTokensOptions struct {
ModulePath string
}

var _ Interface = (*PKCS11ToolListTokensOptions)(nil)

// AddFlags implements Interface
func (o *PKCS11ToolListTokensOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.ModulePath, "module-path", "",
"absolute path to the PKCS11 module")
}

// PKCS11ToolListKeysUrisOptions is the wrapper for `pkcs11-tool list-keys-uris` related options.
type PKCS11ToolListKeysUrisOptions struct {
ModulePath string
SlotID uint
Pin string
}

var _ Interface = (*PKCS11ToolListKeysUrisOptions)(nil)

// AddFlags implements Interface
func (o *PKCS11ToolListKeysUrisOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.ModulePath, "module-path", "",
"absolute path to the PKCS11 module")

cmd.Flags().UintVar(&o.SlotID, "slot-id", 0,
"id of the PKCS11 slot, uses 0 if empty")

cmd.Flags().StringVar(&o.Pin, "pin", "",
"pin of the PKCS11 slot, uses environment variable COSIGN_PKCS11_PIN if empty")
}
80 changes: 80 additions & 0 deletions cmd/cosign/cli/pkcs11_tool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//go:build pkcs11key
// +build pkcs11key

// Copyright 2021 The Sigstore Authors
//
// 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 cli

import (
"github.com/spf13/cobra"

"github.com/sigstore/cosign/cmd/cosign/cli/options"
"github.com/sigstore/cosign/cmd/cosign/cli/pkcs11cli"
)

var pkcs11ToolForce bool

func PKCS11Tool() *cobra.Command {
cmd := &cobra.Command{
Use: "pkcs11-tool",
Short: "Provides utilities for retrieving information from a PKCS11 token.",
}

cmd.AddCommand(
pkcs11ToolListTokens(),
PKCS11ToolListKeysUrisOptions(),
)

// TODO: drop -f in favor of --no-input only
// TODO: use the force flag.
cmd.PersistentFlags().BoolVarP(&pkcs11ToolForce, "no-input", "f", false,
"skip warnings and confirmations")

return cmd
}

func pkcs11ToolListTokens() *cobra.Command {
o := &options.PKCS11ToolListTokensOptions{}

cmd := &cobra.Command{
Use: "list-tokens",
Short: "list-tokens lists all PKCS11 tokens linked to a PKCS11 module",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
return pkcs11cli.ListTokensCmd(cmd.Context(), o.ModulePath)
},
}

o.AddFlags(cmd)

return cmd
}

func PKCS11ToolListKeysUrisOptions() *cobra.Command {
o := &options.PKCS11ToolListKeysUrisOptions{}

cmd := &cobra.Command{
Use: "list-keys-uris",
Short: "list-keys-uris lists URIs of all keys in a PKCS11 token",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
return pkcs11cli.ListKeysUrisCmd(cmd.Context(), o.ModulePath, o.SlotID, o.Pin)
},
}

o.AddFlags(cmd)

return cmd
}
29 changes: 29 additions & 0 deletions cmd/cosign/cli/pkcs11_tool_disabled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//go:build !pkcs11key
// +build !pkcs11key

// Copyright 2021 The Sigstore Authors
//
// 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 cli

import (
"github.com/spf13/cobra"
)

func PKCS11Tool() *cobra.Command {
return &cobra.Command{
Use: "pkcs11-tool",
Short: "This cosign was not built with pkcs11-tool support!",
}
}
Loading

0 comments on commit 7066f12

Please sign in to comment.