Compare commits

..

37 Commits

Author SHA1 Message Date
9352be5341 Merge pull request #1694 from thaJeztah/18.09_backport_nolibtool
[18.09 backport] Update PKCS11 library
2019-02-27 08:39:46 -08:00
b4f607fb4f Update PKCS11 library
The new version no longer links to libltdl which simplifies build
and dependencies.

See https://github.com/theupdateframework/notary/pull/1434

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
(cherry picked from commit cb3e55bf58)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-02-26 13:17:22 +01:00
af2647d55b Merge pull request #1634 from thaJeztah/18.09_bump_golang_1.10.8
[18.09] Bump Golang 1.10.8 (CVE-2019-6486)
2019-01-24 14:27:59 +01:00
c71aa11c0a [18.09] Bump Golang 1.10.8 (CVE-2019-6486)
See the milestone for details;
https://github.com/golang/go/issues?q=milestone%3AGo1.10.8+label%3ACherryPickApproved

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-24 02:07:03 +01:00
336b2a5cac Merge pull request #1580 from thaJeztah/18.09_backport_e2e-invocation-nit
[18.09 backport] e2e updates
2018-12-19 14:20:03 +01:00
c462e06fcd e2e: assign a default value of 0 to DOCKERD_EXPERIMENTAL
Currently running the e2e tests produces a warning/error:

    $ make -f docker.Makefile test-e2e
    «...»
    docker run --rm -v /var/run/docker.sock:/var/run/docker.sock docker-cli-e2e
    ./scripts/test/e2e/run: line 20: test: : integer expression expected

This is from:

    test "${DOCKERD_EXPERIMENTAL:-}" -eq "1" && «...»

Where `${DOCKERD_EXPERIMENTAL:-}` expands to the empty string, resulting in
`test "" -eq "1"` which produces the warning. This error is enough to trigger
the short-circuiting behaviour of `&&` so the result is as expected, but fix
the issue nonetheless by provdiing a default `0`.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 4f483276cf)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-12-17 17:23:04 +01:00
719508a935 connhelper: add e2e
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
(cherry picked from commit 9b148db87a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-12-17 17:22:58 +01:00
2fa3aae9ed Merge pull request #1575 from thaJeztah/bump_golang_1.10.6
[18.09] Bump Golang 1.10.6 (CVE-2018-16875)
2018-12-14 20:56:04 +00:00
6c3a10aaed Bump Golang 1.10.6 (CVE-2018-16875)
go1.10.6 (released 2018/12/14)

- crypto/x509: CPU denial of service in chain validation golang/go#29233
- cmd/go: directory traversal in "go get" via curly braces in import paths golang/go#29231
- cmd/go: remote command execution during "go get -u" golang/go#29230

See the Go 1.10.6 milestone on the issue tracker for details:
https://github.com/golang/go/issues?q=milestone%3AGo1.10.6

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-12-14 01:41:33 +01:00
3ee6755815 Merge pull request #1567 from thaJeztah/18.09_backport_fix_panic_on_update
[18.09 backport] Fix panic (npe) when updating service limits/reservations
2018-12-13 10:39:37 +00:00
16349f6e33 Fix panic (npe) when updating service limits/reservations
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 579bb91853)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-12-13 02:22:43 +01:00
2aa77af30f Merge pull request #1554 from thaJeztah/18.09_backport_completion-import--platform
[18.09 backport] Add bash completion for `import --platform`
2018-12-07 13:10:27 -08:00
456c1ce695 Merge pull request #1553 from thaJeztah/18.09_backport_completion-log-driver-local
[18.09 backport] Add bash completion for "local" log driver
2018-12-07 13:10:06 -08:00
bcadc9061c Add bash completion for import --platform
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit e0fe546c37)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-12-07 20:08:35 +01:00
e05745b4a5 Add bash completion for "local" log driver
Ref: https://github.com/moby/moby/pull/37092

Also adds log-opt `compress` to json-file log driver because this was
also added in the referenced PR.

Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit c59038b15c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-12-07 20:05:08 +01:00
b6ecef353f Merge pull request #1552 from thaJeztah/18.09_backport_fix_filter_panic
[18.09 backport] Fix panic when pruning images with label-filter
2018-12-07 19:29:32 +01:00
e380ddaddf Fix panic when pruning images with label-filter
Before this change:

    docker image prune --force --filter "label=foobar"
    panic: assignment to entry in nil map

    goroutine 1 [running]:
    github.com/docker/cli/vendor/github.com/docker/docker/api/types/filters.Args.Add(...)
    /go/src/github.com/docker/cli/vendor/github.com/docker/docker/api/types/filters/parse.go:167
    github.com/docker/cli/cli/command/image.runPrune(0x1db3a20, 0xc000344cf0, 0x16e0001, 0xc00015e600, 0x4, 0x3, 0xc00024e160, 0xc000545c70, 0x5ab4b5)
    /go/src/github.com/docker/cli/cli/command/image/prune.go:79 +0xbaf
    github.com/docker/cli/cli/command/image.NewPruneCommand.func1(0xc00029ef00, 0xc0004a8180, 0x0, 0x3, 0x0, 0x0)
    /go/src/github.com/docker/cli/cli/command/image/prune.go:32 +0x64
    github.com/docker/cli/vendor/github.com/spf13/cobra.(*Command).execute(0xc00029ef00, 0xc000038210, 0x3, 0x3, 0xc00029ef00, 0xc000038210)
    /go/src/github.com/docker/cli/vendor/github.com/spf13/cobra/command.go:762 +0x473
    github.com/docker/cli/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0xc000127180, 0xc000272770, 0x1836ce0, 0xc000272780)
    /go/src/github.com/docker/cli/vendor/github.com/spf13/cobra/command.go:852 +0x2fd
    github.com/docker/cli/vendor/github.com/spf13/cobra.(*Command).Execute(0xc000127180, 0xc000127180, 0x1d60880)
    /go/src/github.com/docker/cli/vendor/github.com/spf13/cobra/command.go:800 +0x2b
    main.main()
    /go/src/github.com/docker/cli/cmd/docker/docker.go:180 +0xdc

With this patch applied:

    docker image prune --force --filter "label=foobar"
    Total reclaimed space: 0B

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 1e1dd5bca4)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-12-07 17:58:38 +01:00
12834eeff6 Merge pull request #1542 from thaJeztah/18.09_backport_completion_cli_experimental
[18.09 backport] Add bash completion for experimental CLI commands (manifest)
2018-12-03 13:34:56 -08:00
bb46da9fba Merge pull request #1544 from thaJeztah/18.09_bump_go_to_1.10.5
[18.09] Bump Go to 1.10.5
2018-11-30 14:03:12 -08:00
871d24d3fc Bump Go to 1.10.5
go1.10.5 (released 2018/11/02) includes fixes to the go command, linker,
runtime and the database/sql package. See the milestone on the issue
tracker for details:

List of changes; https://github.com/golang/go/issues?q=milestone%3AGo1.10.5

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-30 21:59:54 +01:00
61a9096b8d Merge pull request #1540 from thaJeztah/18.09_backport_fix_flags_in_usage
[18.09 backport] Fix yamldocs outputing `[flags]` in usage output
2018-11-29 13:26:27 -08:00
2ac475cf97 Add bash completion for manifest command family
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 0fb4256a00)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-29 17:15:06 +01:00
2a36695037 Add support for experimental cli features to bash completion
This is needed for implementing bash completion for the `docker manifest`
command family.

Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit a183c952c6)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-29 17:15:04 +01:00
dc74fc81f2 Refactor usage of docker version in bash completion
This preapares bash completion for more context sensitivity:

- experimental cli features
- orchestrator specific features

Also renames _daemon_ to _server_ where used in context of `docker version`
because the fields there are grouped unter _Server_.

Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 564d4da06e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-29 17:15:02 +01:00
7e90635652 Fix yamldocs outputing [flags] in usage output
A similar change was made in the CLI itself, but is not
inherited by the code that generates the YAML docs.

Before this patch is applied;

```
usage: docker container exec [OPTIONS] CONTAINER COMMAND [ARG...] [flags]
```

With this patch applied:

```
usage: docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 44d96e9120)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-29 15:44:16 +01:00
3f7989903a Merge pull request #1454 from thaJeztah/18.09_backport_defaulttcpschema
[18.09 backport] fixes #1441 set default schema to tcp for docker host
2018-11-27 09:32:51 -08:00
7059d069c3 Merge pull request #1532 from tiborvass/18.09-fix-system-prune-filters
[18.09] prune: move image pruning before build cache pruning
2018-11-26 16:07:21 -08:00
4a4a1f3615 prune: move image pruning before build cache pruning
This is cleaner because running system prune twice in a row
now results in a no-op the second time.

Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 6c10abb247)
Signed-off-by: Tibor Vass <tibor@docker.com>
2018-11-21 22:01:54 +00:00
1274f23252 Merge pull request #1531 from thaJeztah/18.09_backport_builder_docs
[18.09 backport] builder documentation updates
2018-11-21 18:10:29 +01:00
3af1848dda buildkit reference docs
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tibor Vass <tibor@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 83aeb219f0)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-21 17:16:30 +01:00
6d91f5d55d Documenting ENTRYPOINT can empty value of CMD
Signed-off-by: Brandon Mitchell <git@bmitch.net>
(cherry picked from commit cc316fde55)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-21 17:16:24 +01:00
d56948c12c Merge pull request #1530 from thaJeztah/18.09_backport_add_logging_driver_example
[18.09 backport] Update daemon.json example to show that log-opts must be a string
2018-11-21 17:10:02 +01:00
9b3eea87ee Update daemon.json example to show that log-opts must be a string
log-opts are passed to logging-drivers as-is, so the daemon is not
aware what value-type each option takes.

For this reason, all options must be provided as a string, even if
they are used as numeric values by the logging driver.

For example, to pass the "max-file" option to the default (json-file)
logging driver, this value has to be passed as a string;

```json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
```

When passed as a _number_ (`"max-file": 3`), the daemon will invalidate
the configuration file, and fail to start;

    unable to configure the Docker daemon with file /etc/docker/daemon.json: json: cannot unmarshal number into Go value of type string

This patch adds an example to the daemon.json to show these  values
have to be passed as strings.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit fd33e0d933)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-21 15:34:41 +01:00
31c092e155 Merge pull request #1526 from thaJeztah/18.09_backport_completion_fix_service__force
[18.09 backport] Fix bash completion for `service update --force`
2018-11-21 11:38:28 +01:00
046ffa4e87 Fix bash completion for service update --force
- `--force` is not available in `service create`
- `--force` is a boolean option

Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 5fa5eb1da6)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-11-20 18:18:33 +01:00
8ae4453d46 add test case TestNewAPIClientFromFlagsForDefaultSchema
Signed-off-by: Lifubang <lifubang@acmcoder.com>
(cherry picked from commit beed8748c0)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-10-17 17:48:07 +02:00
aeea559129 set default schema to tcp for docker host
Signed-off-by: Lifubang <lifubang@acmcoder.com>
(cherry picked from commit 2431dd1448)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-10-17 17:47:58 +02:00
35 changed files with 1025 additions and 369 deletions

View File

@ -4,7 +4,7 @@ clone_folder: c:\gopath\src\github.com\docker\cli
environment:
GOPATH: c:\gopath
GOVERSION: 1.10.4
GOVERSION: 1.10.8
DEPVERSION: v0.4.1
install:

View File

@ -274,21 +274,17 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, isTrusted bool, containe
// NewAPIClientFromFlags creates a new APIClient from command line flags
func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.ConfigFile) (client.APIClient, error) {
unparsedHost, err := getUnparsedServerHost(opts.Hosts)
host, err := getServerHost(opts.Hosts, opts.TLSOptions)
if err != nil {
return &client.Client{}, err
}
var clientOpts []func(*client.Client) error
helper, err := connhelper.GetConnectionHelper(unparsedHost)
helper, err := connhelper.GetConnectionHelper(host)
if err != nil {
return &client.Client{}, err
}
if helper == nil {
clientOpts = append(clientOpts, withHTTPClient(opts.TLSOptions))
host, err := dopts.ParseHost(opts.TLSOptions != nil, unparsedHost)
if err != nil {
return &client.Client{}, err
}
clientOpts = append(clientOpts, client.WithHost(host))
} else {
clientOpts = append(clientOpts, func(c *client.Client) error {
@ -321,7 +317,7 @@ func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.
return client.NewClientWithOpts(clientOpts...)
}
func getUnparsedServerHost(hosts []string) (string, error) {
func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error) {
var host string
switch len(hosts) {
case 0:
@ -331,7 +327,8 @@ func getUnparsedServerHost(hosts []string) (string, error) {
default:
return "", errors.New("Please specify only one -H")
}
return host, nil
return dopts.ParseHost(tlsOptions != nil, host)
}
func withHTTPClient(tlsOpts *tlsconfig.Options) func(*client.Client) error {

View File

@ -43,6 +43,26 @@ func TestNewAPIClientFromFlags(t *testing.T) {
assert.Check(t, is.Equal(api.DefaultVersion, apiclient.ClientVersion()))
}
func TestNewAPIClientFromFlagsForDefaultSchema(t *testing.T) {
host := ":2375"
opts := &flags.CommonOptions{Hosts: []string{host}}
configFile := &configfile.ConfigFile{
HTTPHeaders: map[string]string{
"My-Header": "Custom-Value",
},
}
apiclient, err := NewAPIClientFromFlags(opts, configFile)
assert.NilError(t, err)
assert.Check(t, is.Equal("tcp://localhost"+host, apiclient.DaemonHost()))
expectedHeaders := map[string]string{
"My-Header": "Custom-Value",
"User-Agent": UserAgent(),
}
assert.Check(t, is.DeepEqual(expectedHeaders, apiclient.(*client.Client).CustomHTTPHeaders()))
assert.Check(t, is.Equal(api.DefaultVersion, apiclient.ClientVersion()))
}
func TestNewAPIClientFromFlagsWithAPIVersionFromEnv(t *testing.T) {
customVersion := "v3.3.3"
defer env.Patch(t, "DOCKER_API_VERSION", customVersion)()

View File

@ -8,7 +8,9 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types/filters"
units "github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -55,8 +57,24 @@ Are you sure you want to continue?`
Are you sure you want to continue?`
)
// cloneFilter is a temporary workaround that uses existing public APIs from the filters package to clone a filter.
// TODO(tiborvass): remove this once filters.Args.Clone() is added.
func cloneFilter(args filters.Args) (newArgs filters.Args, err error) {
if args.Len() == 0 {
return filters.NewArgs(), nil
}
b, err := args.MarshalJSON()
if err != nil {
return newArgs, err
}
return filters.FromJSON(string(b))
}
func runPrune(dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint64, output string, err error) {
pruneFilters := options.filter.Value()
pruneFilters, err := cloneFilter(options.filter.Value())
if err != nil {
return 0, "", errors.Wrap(err, "could not copy filter in image prune")
}
pruneFilters.Add("dangling", fmt.Sprintf("%v", !options.all))
pruneFilters = command.PruneFilters(dockerCli, pruneFilters)

View File

@ -70,6 +70,14 @@ func TestNewPruneCommandSuccess(t *testing.T) {
}, nil
},
},
{
name: "label-filter",
args: []string{"--force", "--filter", "label=foobar"},
imagesPruneFunc: func(pruneFilter filters.Args) (types.ImagesPruneReport, error) {
assert.Check(t, is.Equal("foobar", pruneFilter.Get("label")[0]))
return types.ImagesPruneReport{}, nil
},
},
{
name: "force-untagged",
args: []string{"--force"},

View File

@ -0,0 +1 @@
Total reclaimed space: 0B

View File

@ -18,6 +18,7 @@ type osArch struct {
// list of valid os/arch values (see "Optional Environment Variables" section
// of https://golang.org/doc/install/source
// Added linux/s390x as we know System z support already exists
// Keep in sync with _docker_manifest_annotate in contrib/completion/bash/docker
var validOSArches = map[osArch]bool{
{os: "darwin", arch: "386"}: true,
{os: "darwin", arch: "amd64"}: true,

View File

@ -302,6 +302,12 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags
if task.Resources == nil {
task.Resources = &swarm.ResourceRequirements{}
}
if task.Resources.Limits == nil {
task.Resources.Limits = &swarm.Resources{}
}
if task.Resources.Reservations == nil {
task.Resources.Reservations = &swarm.Resources{}
}
return task.Resources
}

View File

@ -617,6 +617,38 @@ func TestUpdateIsolationValid(t *testing.T) {
// and that values are not updated are not reset to their default value
func TestUpdateLimitsReservations(t *testing.T) {
spec := swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{},
},
}
// test that updating works if the service did not previously
// have limits set (https://github.com/moby/moby/issues/38363)
flags := newUpdateCommand(nil).Flags()
err := flags.Set(flagLimitCPU, "2")
assert.NilError(t, err)
err = flags.Set(flagLimitMemory, "200M")
assert.NilError(t, err)
err = updateService(context.Background(), nil, flags, &spec)
assert.NilError(t, err)
spec = swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{},
},
}
// test that updating works if the service did not previously
// have reservations set (https://github.com/moby/moby/issues/38363)
flags = newUpdateCommand(nil).Flags()
err = flags.Set(flagReserveCPU, "2")
assert.NilError(t, err)
err = flags.Set(flagReserveMemory, "200M")
assert.NilError(t, err)
err = updateService(context.Background(), nil, flags, &spec)
assert.NilError(t, err)
spec = swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{},
Resources: &swarm.ResourceRequirements{
@ -632,8 +664,8 @@ func TestUpdateLimitsReservations(t *testing.T) {
},
}
flags := newUpdateCommand(nil).Flags()
err := flags.Set(flagLimitCPU, "2")
flags = newUpdateCommand(nil).Flags()
err = flags.Set(flagLimitCPU, "2")
assert.NilError(t, err)
err = flags.Set(flagReserveCPU, "2")
assert.NilError(t, err)

View File

@ -73,11 +73,10 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error {
if options.pruneVolumes {
pruneFuncs = append(pruneFuncs, volume.RunPrune)
}
pruneFuncs = append(pruneFuncs, image.RunPrune)
if options.pruneBuildCache {
pruneFuncs = append(pruneFuncs, builder.CachePrune)
}
// FIXME: modify image.RunPrune to not modify options.filter, otherwise this has to be last in the list.
pruneFuncs = append(pruneFuncs, image.RunPrune)
var spaceReclaimed uint64
for _, pruneFn := range pruneFuncs {

View File

@ -563,23 +563,39 @@ __docker_append_to_completions() {
COMPREPLY=( ${COMPREPLY[@]/%/"$1"} )
}
# __docker_daemon_is_experimental tests whether the currently configured Docker
# daemon runs in experimental mode. If so, the function exits with 0 (true).
# Otherwise, or if the result cannot be determined, the exit value is 1 (false).
__docker_daemon_is_experimental() {
[ "$(__docker_q version -f '{{.Server.Experimental}}')" = "true" ]
# __docker_fetch_info fetches information about the configured Docker server and updates
# several variables with the results.
# The result is cached for the duration of one invocation of bash completion.
__docker_fetch_info() {
if [ -z "$info_fetched" ] ; then
read -r client_experimental server_experimental server_os < <(__docker_q version -f '{{.Client.Experimental}} {{.Server.Experimental}} {{.Server.Os}}')
info_fetched=true
fi
}
# __docker_daemon_os_is tests whether the currently configured Docker daemon runs
# __docker_client_is_experimental tests whether the Docker cli is configured to support
# experimental features. If so, the function exits with 0 (true).
# Otherwise, or if the result cannot be determined, the exit value is 1 (false).
__docker_client_is_experimental() {
__docker_fetch_info
[ "$client_experimental" = "true" ]
}
# __docker_server_is_experimental tests whether the currently configured Docker
# server runs in experimental mode. If so, the function exits with 0 (true).
# Otherwise, or if the result cannot be determined, the exit value is 1 (false).
__docker_server_is_experimental() {
__docker_fetch_info
[ "$server_experimental" = "true" ]
}
# __docker_server_os_is tests whether the currently configured Docker server runs
# on the operating system passed in as the first argument.
# It does so by querying the daemon for its OS. The result is cached for the duration
# of one invocation of bash completion so that this function can be used to test for
# several different operating systems without additional costs.
# Known operating systems: linux, windows.
__docker_daemon_os_is() {
__docker_server_os_is() {
local expected_os="$1"
local actual_os=${daemon_os=$(__docker_q version -f '{{.Server.Os}}')}
[ "$actual_os" = "$expected_os" ]
__docker_fetch_info
[ "$server_os" = "$expected_os" ]
}
# __docker_stack_orchestrator_is tests whether the client is configured to use
@ -865,6 +881,7 @@ __docker_complete_log_drivers() {
gelf
journald
json-file
local
logentries
none
splunk
@ -888,7 +905,8 @@ __docker_complete_log_options() {
local gcplogs_options="$common_options1 $common_options2 gcp-log-cmd gcp-meta-id gcp-meta-name gcp-meta-zone gcp-project"
local gelf_options="$common_options1 $common_options2 gelf-address gelf-compression-level gelf-compression-type gelf-tcp-max-reconnect gelf-tcp-reconnect-delay tag"
local journald_options="$common_options1 $common_options2 tag"
local json_file_options="$common_options1 $common_options2 max-file max-size"
local json_file_options="$common_options1 $common_options2 compress max-file max-size"
local local_options="$common_options1 compress max-file max-size"
local logentries_options="$common_options1 $common_options2 line-only logentries-token tag"
local splunk_options="$common_options1 $common_options2 splunk-caname splunk-capath splunk-format splunk-gzip splunk-gzip-level splunk-index splunk-insecureskipverify splunk-source splunk-sourcetype splunk-token splunk-url splunk-verify-connection tag"
local syslog_options="$common_options1 $common_options2 syslog-address syslog-facility syslog-format syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify tag"
@ -917,6 +935,9 @@ __docker_complete_log_options() {
json-file)
COMPREPLY=( $( compgen -W "$json_file_options" -S = -- "$cur" ) )
;;
local)
COMPREPLY=( $( compgen -W "$local_options" -S = -- "$cur" ) )
;;
logentries)
COMPREPLY=( $( compgen -W "$logentries_options" -S = -- "$cur" ) )
;;
@ -946,7 +967,7 @@ __docker_complete_log_driver_options() {
__docker_nospace
return
;;
fluentd-async-connect)
compress|fluentd-async-connect)
COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) )
return
;;
@ -1128,7 +1149,8 @@ _docker_docker() {
*)
local counter=$( __docker_pos_first_nonflag "$(__docker_to_extglob "$global_options_with_args")" )
if [ "$cword" -eq "$counter" ]; then
__docker_daemon_is_experimental && commands+=(${experimental_commands[*]})
__docker_client_is_experimental && commands+=(${experimental_client_commands[*]})
__docker_server_is_experimental && commands+=(${experimental_server_commands[*]})
COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) )
fi
;;
@ -1837,14 +1859,14 @@ _docker_container_run_and_create() {
--volume -v
--workdir -w
"
__docker_daemon_os_is windows && options_with_args+="
__docker_server_os_is windows && options_with_args+="
--cpu-count
--cpu-percent
--io-maxbandwidth
--io-maxiops
--isolation
"
__docker_daemon_is_experimental && options_with_args+="
__docker_server_is_experimental && options_with_args+="
--platform
"
@ -1960,7 +1982,7 @@ _docker_container_run_and_create() {
return
;;
--isolation)
if __docker_daemon_os_is windows ; then
if __docker_server_os_is windows ; then
__docker_complete_isolation
return
fi
@ -2071,12 +2093,12 @@ _docker_container_start() {
__docker_complete_detach_keys && return
case "$prev" in
--checkpoint)
if __docker_daemon_is_experimental ; then
if __docker_server_is_experimental ; then
return
fi
;;
--checkpoint-dir)
if __docker_daemon_is_experimental ; then
if __docker_server_is_experimental ; then
_filedir -d
return
fi
@ -2086,7 +2108,7 @@ _docker_container_start() {
case "$cur" in
-*)
local options="--attach -a --detach-keys --help --interactive -i"
__docker_daemon_is_experimental && options+=" --checkpoint --checkpoint-dir"
__docker_server_is_experimental && options+=" --checkpoint --checkpoint-dir"
COMPREPLY=( $( compgen -W "$options" -- "$cur" ) )
;;
*)
@ -2449,7 +2471,7 @@ _docker_daemon() {
}
_docker_deploy() {
__docker_daemon_is_experimental && _docker_stack_deploy
__docker_server_is_experimental && _docker_stack_deploy
}
_docker_diff() {
@ -2535,7 +2557,7 @@ _docker_image_build() {
--target
--ulimit
"
__docker_daemon_os_is windows && options_with_args+="
__docker_server_os_is windows && options_with_args+="
--isolation
"
@ -2549,7 +2571,7 @@ _docker_image_build() {
--quiet -q
--rm
"
if __docker_daemon_is_experimental ; then
if __docker_server_is_experimental ; then
options_with_args+="
--platform
"
@ -2584,7 +2606,7 @@ _docker_image_build() {
return
;;
--isolation)
if __docker_daemon_os_is windows ; then
if __docker_server_os_is windows ; then
__docker_complete_isolation
return
fi
@ -2664,14 +2686,16 @@ _docker_image_images() {
_docker_image_import() {
case "$prev" in
--change|-c|--message|-m)
--change|-c|--message|-m|--platform)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--change -c --help --message -m" -- "$cur" ) )
local options="--change -c --help --message -m"
__docker_server_is_experimental && options+=" --platform"
COMPREPLY=( $( compgen -W "$options" -- "$cur" ) )
;;
*)
local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m')
@ -2779,7 +2803,7 @@ _docker_image_pull() {
case "$cur" in
-*)
local options="--all-tags -a --disable-content-trust=false --help"
__docker_daemon_is_experimental && options+=" --platform"
__docker_server_is_experimental && options+=" --platform"
COMPREPLY=( $( compgen -W "$options" -- "$cur" ) )
;;
@ -3395,7 +3419,6 @@ _docker_service_update_and_create() {
local options_with_args="
--endpoint-mode
--entrypoint
--force
--health-cmd
--health-interval
--health-retries
@ -3431,7 +3454,7 @@ _docker_service_update_and_create() {
--user -u
--workdir -w
"
__docker_daemon_os_is windows && options_with_args+="
__docker_server_os_is windows && options_with_args+="
--credential-spec
"
@ -3520,6 +3543,10 @@ _docker_service_update_and_create() {
--secret-rm
"
boolean_options="$boolean_options
--force
"
case "$prev" in
--env-rm)
COMPREPLY=( $( compgen -e -- "$cur" ) )
@ -3817,6 +3844,109 @@ _docker_swarm_update() {
esac
}
_docker_manifest() {
local subcommands="
annotate
create
inspect
push
"
__docker_subcommands "$subcommands" && return
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
;;
*)
COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) )
;;
esac
}
_docker_manifest_annotate() {
case "$prev" in
--arch)
COMPREPLY=( $( compgen -W "
386
amd64
arm
arm64
mips64
mips64le
ppc64le
s390x" -- "$cur" ) )
return
;;
--os)
COMPREPLY=( $( compgen -W "
darwin
dragonfly
freebsd
linux
netbsd
openbsd
plan9
solaris
windows" -- "$cur" ) )
return
;;
--os-features|--variant)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--arch --help --os --os-features --variant" -- "$cur" ) )
;;
*)
local counter=$( __docker_pos_first_nonflag "--arch|--os|--os-features|--variant" )
if [ "$cword" -eq "$counter" ] || [ "$cword" -eq "$((counter + 1))" ]; then
__docker_complete_images --force-tag --id
fi
;;
esac
}
_docker_manifest_create() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--amend -a --help --insecure" -- "$cur" ) )
;;
*)
__docker_complete_images --force-tag --id
;;
esac
}
_docker_manifest_inspect() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help --insecure --verbose -v" -- "$cur" ) )
;;
*)
local counter=$( __docker_pos_first_nonflag )
if [ "$cword" -eq "$counter" ] || [ "$cword" -eq "$((counter + 1))" ]; then
__docker_complete_images --force-tag --id
fi
;;
esac
}
_docker_manifest_push() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help --insecure --purge -p" -- "$cur" ) )
;;
*)
local counter=$( __docker_pos_first_nonflag )
if [ "$cword" -eq "$counter" ]; then
__docker_complete_images --force-tag --id
fi
;;
esac
}
_docker_node() {
local subcommands="
demote
@ -4451,7 +4581,7 @@ _docker_stack_deploy() {
case "$cur" in
-*)
local options="--compose-file -c --help --orchestrator"
__docker_daemon_is_experimental && __docker_stack_orchestrator_is swarm && options+=" --bundle-file"
__docker_server_is_experimental && __docker_stack_orchestrator_is swarm && options+=" --bundle-file"
__docker_stack_orchestrator_is kubernetes && options+=" --kubeconfig --namespace"
__docker_stack_orchestrator_is swarm && options+=" --prune --resolve-image --with-registry-auth"
COMPREPLY=( $( compgen -W "$options" -- "$cur" ) )
@ -5074,7 +5204,11 @@ _docker() {
wait
)
local experimental_commands=(
local experimental_client_commands=(
manifest
)
local experimental_server_commands=(
checkpoint
deploy
)
@ -5098,10 +5232,12 @@ _docker() {
--tlskey
"
local host config daemon_os
# variables to cache server info, populated on demand for performance reasons
local info_fetched server_experimental server_os
# variables to cache client info, populated on demand for performance reasons
local stack_orchestrator_is_kubernetes stack_orchestrator_is_swarm
local client_experimental stack_orchestrator_is_kubernetes stack_orchestrator_is_swarm
local host config
COMPREPLY=()
local cur prev words cword

View File

@ -105,7 +105,7 @@ shellcheck: build_shell_validate_image ## run shellcheck validation
docker run -ti --rm $(ENVVARS) $(MOUNTS) $(VALIDATE_IMAGE_NAME) make shellcheck
.PHONY: test-e2e ## run e2e tests
test-e2e: test-e2e-non-experimental test-e2e-experimental
test-e2e: test-e2e-non-experimental test-e2e-experimental test-e2e-connhelper-ssh
.PHONY: test-e2e-experimental
test-e2e-experimental: build_e2e_image
@ -115,6 +115,10 @@ test-e2e-experimental: build_e2e_image
test-e2e-non-experimental: build_e2e_image
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock $(E2E_IMAGE_NAME)
.PHONY: test-e2e-connhelper-ssh
test-e2e-connhelper-ssh: build_e2e_image
docker run -e TEST_CONNHELPER=ssh -e DOCKERD_EXPERIMENTAL=1 --rm -v /var/run/docker.sock:/var/run/docker.sock $(E2E_IMAGE_NAME)
.PHONY: help
help: ## print this help
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

View File

@ -1,4 +1,4 @@
FROM golang:1.10.4-alpine
FROM golang:1.10.8-alpine
RUN apk add -U git bash coreutils gcc musl-dev

View File

@ -1,3 +1,3 @@
FROM dockercore/golang-cross:1.10.4@sha256:55c7b933ac944f4922b673b4d4340d1a0404f3c324bd0b3f13a4326c427b1f2a
FROM dockercore/golang-cross:1.10.8@sha256:a93210f55a8137b4aa4b9f033ac7a80b66ab6337e98e7afb62abe93b4ad73cad
ENV DISABLE_WARN_OUTSIDE_CONTAINER=1
WORKDIR /go/src/github.com/docker/cli

View File

@ -1,5 +1,5 @@
FROM golang:1.10.4-alpine
FROM golang:1.10.8-alpine
RUN apk add -U git make bash coreutils ca-certificates curl

View File

@ -1,4 +1,4 @@
ARG GO_VERSION=1.10.4
ARG GO_VERSION=1.10.8
FROM docker/containerd-shim-process:a4d1531 AS containerd-shim-process
@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -y \
libapparmor-dev \
libseccomp-dev \
iptables \
openssh-client \
&& rm -rf /var/lib/apt/lists/*
ARG COMPOSE_VERSION=1.21.2

View File

@ -1,4 +1,4 @@
FROM golang:1.10.4-alpine
FROM golang:1.10.8-alpine
RUN apk add -U git

View File

@ -121,6 +121,28 @@ registries.
When you're done with your build, you're ready to look into [*Pushing a
repository to its registry*](https://docs.docker.com/engine/tutorials/dockerrepos/#/contributing-to-docker-hub).
## BuildKit
Starting with version 18.09, Docker supports a new backend for executing your
builds that is provided by the [moby/buildkit](https://github.com/moby/buildkit)
project. The BuildKit backend provides many benefits compared to the old
implementation. For example, BuildKit can:
* Detect and skip executing unused build stages
* Parallelize building independent build stages
* Incrementally transfer only the changed files in your build context between builds
* Detect and skip transferring unused files in your build context
* Use external Dockerfile implementations with many new features
* Avoid side-effects with rest of the API (intermediate images and containers)
* Prioritize your build cache for automatic pruning
To use the BuildKit backend, you need to set an environment variable
`DOCKER_BUILDKIT=1` on the CLI before invoking `docker build`.
To learn about the experimental Dockerfile syntax available to BuildKit-based
builds [refer to the documentation in the BuildKit repository](https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md).
## Format
Here is the format of the `Dockerfile`:
@ -224,10 +246,64 @@ following lines are all treated identically:
# dIrEcTiVe=value
```
The following parser directive is supported:
The following parser directives are supported:
* `syntax`
* `escape`
## syntax
# syntax=[remote image reference]
For example:
# syntax=docker/dockerfile
# syntax=docker/dockerfile:1.0
# syntax=docker.io/docker/dockerfile:1
# syntax=docker/dockerfile:1.0.0-experimental
# syntax=example.com/user/repo:tag@sha256:abcdef...
This feature is only enabled if the [BuildKit](#buildkit) backend is used.
The syntax directive defines the location of the Dockerfile builder that is used for
building the current Dockerfile. The BuildKit backend allows to seamlessly use
external implementations of builders that are distributed as Docker images and
execute inside a container sandbox environment.
Custom Dockerfile implementation allows you to:
- Automatically get bugfixes without updating the daemon
- Make sure all users are using the same implementation to build your Dockerfile
- Use the latest features without updating the daemon
- Try out new experimental or third-party features
### Official releases
Docker distributes official versions of the images that can be used for building
Dockerfiles under `docker/dockerfile` repository on Docker Hub. There are two
channels where new images are released: stable and experimental.
Stable channel follows semantic versioning. For example:
- docker/dockerfile:1.0.0 - only allow immutable version 1.0.0
- docker/dockerfile:1.0 - allow versions 1.0.*
- docker/dockerfile:1 - allow versions 1.*.*
- docker/dockerfile:latest - latest release on stable channel
The experimental channel uses incremental versioning with the major and minor
component from the stable channel on the time of the release. For example:
- docker/dockerfile:1.0.1-experimental - only allow immutable version 1.0.1-experimental
- docker/dockerfile:1.0-experimental - latest experimental releases after 1.0
- docker/dockerfile:experimental - latest release on experimental channel
You should choose a channel that best fits your needs. If you only want
bugfixes, you should use `docker/dockerfile:1.0`. If you want to benefit from
experimental features, you should use the experimental channel. If you are using
the experimental channel, newer releases may not be backwards compatible, so it
is recommended to use an immutable full version variant.
For master builds and nightly feature releases refer to the description in [the source repository](https://github.com/moby/buildkit/blob/master/README.md).
## escape
# escape=\ (backslash)
@ -1339,6 +1415,10 @@ The table below shows what command is executed for different `ENTRYPOINT` / `CMD
| **CMD ["p1_cmd", "p2_cmd"]** | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
| **CMD exec_cmd p1_cmd** | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
> **Note**: If `CMD` is defined from the base image, setting `ENTRYPOINT` will
> reset `CMD` to an empty value. In this scenario, `CMD` must be defined in the
> current image to have a value.
## VOLUME
VOLUME ["/data"]
@ -1623,6 +1703,38 @@ RUN echo "Hello World"
When building this Dockerfile, the `HTTP_PROXY` is preserved in the
`docker history`, and changing its value invalidates the build cache.
### Automatic platform ARGs in the global scope
This feature is only available when using the [BuildKit](#buildkit) backend.
Docker predefines a set of `ARG` variables with information on the platform of
the node performing the build (build platform) and on the platform of the
resulting image (target platform). The target platform can be specified with
the `--platform` flag on `docker build`.
The following `ARG` variables are set automatically:
* `TARGETPLATFORM` - platform of the build result. Eg `linux/amd64`, `linux/arm/v7`, `windows/amd64`.
* `TARGETOS` - OS component of TARGETPLATFORM
* `TARGETARCH` - architecture component of TARGETPLATFORM
* `TARGETVARIANT` - variant component of TARGETPLATFORM
* `BUILDPLATFORM` - platform of the node performing the build.
* `BUILDOS` - OS component of BUILDPLATFORM
* `BUILDARCH` - OS component of BUILDPLATFORM
* `BUILDVARIANT` - OS component of BUILDPLATFORM
These arguments are defined in the global scope so are not automatically
available inside build stages or for your `RUN` commands. To expose one of
these arguments inside the build stage redefine it without value.
For example:
```Dockerfile
FROM alpine
ARG TARGETPLATFORM
RUN echo "I'm building for $TARGETPLATFORM"
```
### Impact on build caching
`ARG` variables are not persisted into the built image as `ENV` variables are.
@ -1931,6 +2043,14 @@ required such as `zsh`, `csh`, `tcsh` and others.
The `SHELL` feature was added in Docker 1.12.
## External implementation features
This feature is only available when using the [BuildKit](#buildkit) backend.
Docker build supports experimental features like cache mounts, build secrets and
ssh forwarding that are enabled by using an external implementation of the
builder with a syntax directive. To learn about these features, [refer to the documentation in BuildKit repository](https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md).
## Dockerfile examples
Below you can see some examples of Dockerfile syntax. If you're interested in

View File

@ -1305,8 +1305,13 @@ This is a full example of the allowed configuration options on Linux:
"storage-opts": [],
"labels": [],
"live-restore": true,
"log-driver": "",
"log-opts": {},
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-files":"5",
"labels": "somelabel",
"env": "os,customer"
},
"mtu": 0,
"pidfile": "",
"cluster-store": "",

View File

@ -22,6 +22,7 @@ func generateCliYaml(opts *options) error {
dockerCli := command.NewDockerCli(stdin, stdout, stderr, false, nil)
cmd := &cobra.Command{Use: "docker"}
commands.AddCommands(cmd, dockerCli)
disableFlagsInUseLine(cmd)
source := filepath.Join(opts.source, descriptionSourcePath)
if err := loadLongDescription(cmd, source); err != nil {
return err
@ -31,6 +32,23 @@ func generateCliYaml(opts *options) error {
return GenYamlTree(cmd, opts.target)
}
func disableFlagsInUseLine(cmd *cobra.Command) {
visitAll(cmd, func(ccmd *cobra.Command) {
// do not add a `[flags]` to the end of the usage line.
ccmd.DisableFlagsInUseLine = true
})
}
// visitAll will traverse all commands from the root.
// This is different from the VisitAll of cobra.Command where only parents
// are checked.
func visitAll(root *cobra.Command, fn func(*cobra.Command)) {
for _, cmd := range root.Commands() {
visitAll(cmd, fn)
}
fn(root)
}
func loadLongDescription(cmd *cobra.Command, path ...string) error {
for _, cmd := range cmd.Commands() {
if cmd.Name() == "" {

View File

@ -0,0 +1,9 @@
version: '2.1'
services:
engine:
build:
context: ./testdata
dockerfile: Dockerfile.connhelper-ssh
environment:
- TEST_CONNHELPER_SSH_ID_RSA_PUB

14
e2e/testdata/Dockerfile.connhelper-ssh vendored Normal file
View File

@ -0,0 +1,14 @@
FROM docker:test-dind
RUN apk --no-cache add shadow openssh-server && \
groupadd -f docker && \
useradd -m penguin && \
usermod -aG docker penguin && \
usermod -p $(head -c32 /dev/urandom | base64) penguin && \
chsh -s /bin/sh penguin && \
ssh-keygen -A
# workaround: ssh session excludes /usr/local/bin from $PATH
RUN ln -s /usr/local/bin/docker /usr/bin/docker
COPY ./connhelper-ssh/entrypoint.sh /
EXPOSE 22
ENTRYPOINT ["/entrypoint.sh"]
# usage: docker run --privileged -e TEST_CONNHELPER_SSH_ID_RSA_PUB=$(cat ~/.ssh/id_rsa.pub) -p 22 $THIS_IMAGE

8
e2e/testdata/connhelper-ssh/entrypoint.sh vendored Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
set -ex
mkdir -m 0700 -p /home/penguin/.ssh
echo ${TEST_CONNHELPER_SSH_ID_RSA_PUB} > /home/penguin/.ssh/authorized_keys
chmod 0600 /home/penguin/.ssh/authorized_keys
chown -R penguin:penguin /home/penguin
/usr/sbin/sshd -E /var/log/sshd.log
exec dockerd-entrypoint.sh $@

View File

@ -1,15 +1,13 @@
package environment
import (
"context"
"os"
"strings"
"testing"
"time"
"github.com/docker/docker/client"
"github.com/pkg/errors"
"gotest.tools/assert"
"gotest.tools/icmd"
"gotest.tools/poll"
"gotest.tools/skip"
)
@ -79,21 +77,14 @@ func boolFromString(val string) bool {
}
}
func dockerClient(t *testing.T) client.APIClient {
t.Helper()
c, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.37"))
assert.NilError(t, err)
return c
}
// DefaultPollSettings used with gotestyourself/poll
var DefaultPollSettings = poll.WithDelay(100 * time.Millisecond)
// SkipIfNotExperimentalDaemon returns whether the test docker daemon is in experimental mode
func SkipIfNotExperimentalDaemon(t *testing.T) {
t.Helper()
c := dockerClient(t)
info, err := c.Info(context.Background())
assert.NilError(t, err)
skip.If(t, !info.ExperimentalBuild, "running against a non-experimental daemon")
result := icmd.RunCmd(icmd.Command("docker", "info", "--format", "{{.ExperimentalBuild}}"))
result.Assert(t, icmd.Expected{Err: icmd.None})
experimentalBuild := strings.TrimSpace(result.Stdout()) == "true"
skip.If(t, !experimentalBuild, "running against a non-experimental daemon")
}

View File

@ -77,6 +77,8 @@ func parseDockerDaemonHost(addr string) (string, error) {
return parseSimpleProtoAddr("npipe", addrParts[1], DefaultNamedPipe)
case "fd":
return addr, nil
case "ssh":
return addr, nil
default:
return "", fmt.Errorf("Invalid bind address format: %s", addr)
}

View File

@ -17,7 +17,15 @@ function setup {
local project=$1
local file=$2
test "${DOCKERD_EXPERIMENTAL:-}" -eq "1" && file="${file}:./e2e/compose-env.experimental.yaml"
test "${DOCKERD_EXPERIMENTAL:-0}" -eq "1" && file="${file}:./e2e/compose-env.experimental.yaml"
if [[ "${TEST_CONNHELPER:-}" = "ssh" ]];then
test ! -f "${HOME}/.ssh/id_rsa" && ssh-keygen -t rsa -C docker-e2e-dummy -N "" -f "${HOME}/.ssh/id_rsa" -q
grep "^StrictHostKeyChecking no" "${HOME}/.ssh/config" > /dev/null 2>&1 || echo "StrictHostKeyChecking no" > "${HOME}/.ssh/config"
TEST_CONNHELPER_SSH_ID_RSA_PUB=$(cat "${HOME}/.ssh/id_rsa.pub")
export TEST_CONNHELPER_SSH_ID_RSA_PUB
file="${file}:./e2e/compose-env.connhelper-ssh.yaml"
fi
COMPOSE_PROJECT_NAME=$project COMPOSE_FILE=$file docker-compose up --build -d >&2
local network="${project}_default"
@ -26,6 +34,9 @@ function setup {
engine_ip="$(container_ip "${project}_engine_1" "$network")"
engine_host="tcp://$engine_ip:2375"
if [[ "${TEST_CONNHELPER:-}" = "ssh" ]];then
engine_host="ssh://penguin@${engine_ip}"
fi
(
export DOCKER_HOST="$engine_host"
timeout 200 ./scripts/test/e2e/wait-on-daemon
@ -57,7 +68,7 @@ function runtests {
TEST_REMOTE_DAEMON="${REMOTE_DAEMON-}" \
TEST_SKIP_PLUGIN_TESTS="${SKIP_PLUGIN_TESTS-}" \
GOPATH="$GOPATH" \
PATH="$PWD/build/" \
PATH="$PWD/build/:/usr/bin" \
"$(which go)" test -v ./e2e/... ${TESTFLAGS-}
}

View File

@ -49,7 +49,7 @@ github.com/mattn/go-shellwords v1.0.3
github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55
github.com/Microsoft/go-winio v0.4.10
github.com/miekg/pkcs11 287d9350987cc9334667882061e202e96cdfb4d0
github.com/miekg/pkcs11 6120d95c0e9576ccf4a78ba40855809dca31a9ed
github.com/mitchellh/mapstructure f15292f7a699fcc1a38a80977f80a046874ba8ac
github.com/moby/buildkit 520201006c9dc676da9cf9655337ac711f7f127d
github.com/modern-go/concurrent bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94 # 1.0.3

View File

@ -12,13 +12,13 @@ were it makes sense. It has been tested with SoftHSM.
softhsm --init-token --slot 0 --label test --pin 1234
* Then use `libsofthsm.so` as the pkcs11 module:
```go
p := pkcs11.New("/usr/lib/softhsm/libsofthsm.so")
```
## Examples
A skeleton program would look somewhat like this (yes, pkcs#11 is verbose):
```go
p := pkcs11.New("/usr/lib/softhsm/libsofthsm.so")
err := p.Initialize()
if err != nil {
@ -55,7 +55,7 @@ A skeleton program would look somewhat like this (yes, pkcs#11 is verbose):
fmt.Printf("%x", d)
}
fmt.Println()
```
Further examples are included in the tests.
To expose PKCS#11 keys using the

View File

@ -24,15 +24,19 @@ const (
)
const (
CKG_MGF1_SHA1 uint = 0x00000001
CKG_MGF1_SHA224 uint = 0x00000005
CKG_MGF1_SHA256 uint = 0x00000002
CKG_MGF1_SHA384 uint = 0x00000003
CKG_MGF1_SHA512 uint = 0x00000004
CKG_MGF1_SHA1 uint = 0x00000001
CKG_MGF1_SHA224 uint = 0x00000005
CKG_MGF1_SHA256 uint = 0x00000002
CKG_MGF1_SHA384 uint = 0x00000003
CKG_MGF1_SHA512 uint = 0x00000004
CKG_MGF1_SHA3_224 uint = 0x00000006
CKG_MGF1_SHA3_256 uint = 0x00000007
CKG_MGF1_SHA3_384 uint = 0x00000008
CKG_MGF1_SHA3_512 uint = 0x00000009
)
const (
CKZ_DATA_SPECIFIED uint = 0x00000001
CKZ_DATA_SPECIFIED uint = 0x00000001
)
// Generated with: awk '/#define CK[AFKMRC]/{ print $2 " = " $3 }' pkcs11t.h | sed -e 's/UL$//g' -e 's/UL)$/)/g'
@ -98,15 +102,19 @@ const (
CKK_SHA512_224_HMAC = 0x00000027
CKK_SHA512_256_HMAC = 0x00000028
CKK_SHA512_T_HMAC = 0x00000029
CKK_SHA_1_HMAC = 0x00000028
CKK_SHA224_HMAC = 0x0000002E
CKK_SHA256_HMAC = 0x0000002B
CKK_SHA384_HMAC = 0x0000002C
CKK_SHA512_HMAC = 0x0000002D
CKK_SEED = 0x00000050
CKK_GOSTR3410 = 0x00000060
CKK_GOSTR3411 = 0x00000061
CKK_GOST28147 = 0x00000062
CKK_SHA_1_HMAC = 0x00000028
CKK_SHA224_HMAC = 0x0000002E
CKK_SHA256_HMAC = 0x0000002B
CKK_SHA384_HMAC = 0x0000002C
CKK_SHA512_HMAC = 0x0000002D
CKK_SEED = 0x0000002F
CKK_GOSTR3410 = 0x00000030
CKK_GOSTR3411 = 0x00000031
CKK_GOST28147 = 0x00000032
CKK_SHA3_224_HMAC = 0x00000033
CKK_SHA3_256_HMAC = 0x00000034
CKK_SHA3_384_HMAC = 0x00000035
CKK_SHA3_512_HMAC = 0x00000036
CKK_VENDOR_DEFINED = 0x80000000
CKC_X_509 = 0x00000000
CKC_X_509_ATTR_CERT = 0x00000001
@ -182,8 +190,8 @@ const (
CKA_AUTH_PIN_FLAGS = 0x00000201
CKA_ALWAYS_AUTHENTICATE = 0x00000202
CKA_WRAP_WITH_TRUSTED = 0x00000210
CKA_WRAP_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000211)
CKA_UNWRAP_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000212)
CKA_WRAP_TEMPLATE = CKF_ARRAY_ATTRIBUTE | 0x00000211
CKA_UNWRAP_TEMPLATE = CKF_ARRAY_ATTRIBUTE | 0x00000212
CKA_OTP_FORMAT = 0x00000220
CKA_OTP_LENGTH = 0x00000221
CKA_OTP_TIME_INTERVAL = 0x00000222
@ -218,7 +226,7 @@ const (
CKA_REQUIRED_CMS_ATTRIBUTES = 0x00000501
CKA_DEFAULT_CMS_ATTRIBUTES = 0x00000502
CKA_SUPPORTED_CMS_ATTRIBUTES = 0x00000503
CKA_ALLOWED_MECHANISMS = (CKF_ARRAY_ATTRIBUTE | 0x00000600)
CKA_ALLOWED_MECHANISMS = CKF_ARRAY_ATTRIBUTE | 0x00000600
CKA_VENDOR_DEFINED = 0x80000000
CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000000
CKM_RSA_PKCS = 0x00000001
@ -243,6 +251,10 @@ const (
CKM_DSA_SHA256 = 0x00000015
CKM_DSA_SHA384 = 0x00000016
CKM_DSA_SHA512 = 0x00000017
CKM_DSA_SHA3_224 = 0x00000018
CKM_DSA_SHA3_256 = 0x00000019
CKM_DSA_SHA3_384 = 0x0000001A
CKM_DSA_SHA3_512 = 0x0000001B
CKM_DH_PKCS_KEY_PAIR_GEN = 0x00000020
CKM_DH_PKCS_DERIVE = 0x00000021
CKM_X9_42_DH_KEY_PAIR_GEN = 0x00000030
@ -269,6 +281,14 @@ const (
CKM_SHA512_T_HMAC = 0x00000051
CKM_SHA512_T_HMAC_GENERAL = 0x00000052
CKM_SHA512_T_KEY_DERIVATION = 0x00000053
CKM_SHA3_256_RSA_PKCS = 0x00000060
CKM_SHA3_384_RSA_PKCS = 0x00000061
CKM_SHA3_512_RSA_PKCS = 0x00000062
CKM_SHA3_256_RSA_PKCS_PSS = 0x00000063
CKM_SHA3_384_RSA_PKCS_PSS = 0x00000064
CKM_SHA3_512_RSA_PKCS_PSS = 0x00000065
CKM_SHA3_224_RSA_PKCS = 0x00000066
CKM_SHA3_224_RSA_PKCS_PSS = 0x00000067
CKM_RC2_KEY_GEN = 0x00000100
CKM_RC2_ECB = 0x00000101
CKM_RC2_CBC = 0x00000102
@ -335,6 +355,22 @@ const (
CKM_HOTP = 0x00000291
CKM_ACTI = 0x000002A0
CKM_ACTI_KEY_GEN = 0x000002A1
CKM_SHA3_256 = 0x000002B0
CKM_SHA3_256_HMAC = 0x000002B1
CKM_SHA3_256_HMAC_GENERAL = 0x000002B2
CKM_SHA3_256_KEY_GEN = 0x000002B3
CKM_SHA3_224 = 0x000002B5
CKM_SHA3_224_HMAC = 0x000002B6
CKM_SHA3_224_HMAC_GENERAL = 0x000002B7
CKM_SHA3_224_KEY_GEN = 0x000002B8
CKM_SHA3_384 = 0x000002C0
CKM_SHA3_384_HMAC = 0x000002C1
CKM_SHA3_384_HMAC_GENERAL = 0x000002C2
CKM_SHA3_384_KEY_GEN = 0x000002C3
CKM_SHA3_512 = 0x000002D0
CKM_SHA3_512_HMAC = 0x000002D1
CKM_SHA3_512_HMAC_GENERAL = 0x000002D2
CKM_SHA3_512_KEY_GEN = 0x000002D3
CKM_CAST_KEY_GEN = 0x00000300
CKM_CAST_ECB = 0x00000301
CKM_CAST_CBC = 0x00000302
@ -395,6 +431,12 @@ const (
CKM_SHA384_KEY_DERIVATION = 0x00000394
CKM_SHA512_KEY_DERIVATION = 0x00000395
CKM_SHA224_KEY_DERIVATION = 0x00000396
CKM_SHA3_256_KEY_DERIVE = 0x00000397
CKM_SHA3_224_KEY_DERIVE = 0x00000398
CKM_SHA3_384_KEY_DERIVE = 0x00000399
CKM_SHA3_512_KEY_DERIVE = 0x0000039A
CKM_SHAKE_128_KEY_DERIVE = 0x0000039B
CKM_SHAKE_256_KEY_DERIVE = 0x0000039C
CKM_PBE_MD2_DES_CBC = 0x000003A0
CKM_PBE_MD5_DES_CBC = 0x000003A1
CKM_PBE_MD5_CAST_CBC = 0x000003A2
@ -678,4 +720,6 @@ const (
CKF_EXCLUDE_CHALLENGE = 0x00000008
CKF_EXCLUDE_PIN = 0x00000010
CKF_USER_FRIENDLY_OTP = 0x00000020
CKD_NULL = 0x00000001
CKD_SHA1_KDF = 0x00000002
)

View File

@ -8,6 +8,24 @@ package pkcs11
#include <stdlib.h>
#include <string.h>
#include "pkcs11go.h"
static inline void putOAEPParams(CK_RSA_PKCS_OAEP_PARAMS_PTR params, CK_VOID_PTR pSourceData, CK_ULONG ulSourceDataLen)
{
params->pSourceData = pSourceData;
params->ulSourceDataLen = ulSourceDataLen;
}
static inline void putECDH1SharedParams(CK_ECDH1_DERIVE_PARAMS_PTR params, CK_VOID_PTR pSharedData, CK_ULONG ulSharedDataLen)
{
params->pSharedData = pSharedData;
params->ulSharedDataLen = ulSharedDataLen;
}
static inline void putECDH1PublicParams(CK_ECDH1_DERIVE_PARAMS_PTR params, CK_VOID_PTR pPublicData, CK_ULONG ulPublicDataLen)
{
params->pPublicData = pPublicData;
params->ulPublicDataLen = ulPublicDataLen;
}
*/
import "C"
import "unsafe"
@ -21,9 +39,8 @@ type GCMParams struct {
tagSize int
}
// NewGCMParams returns a pointer to AES-GCM parameters.
// This is a convenience function for passing GCM parameters to
// available mechanisms.
// NewGCMParams returns a pointer to AES-GCM parameters that can be used with the CKM_AES_GCM mechanism.
// The Free() method must be called after the operation is complete.
//
// *NOTE*
// Some HSMs, like CloudHSM, will ignore the IV you pass in and write their
@ -55,17 +72,23 @@ func cGCMParams(p *GCMParams) []byte {
iv, ivLen := arena.Allocate(p.iv)
params.pIv = C.CK_BYTE_PTR(iv)
params.ulIvLen = ivLen
params.ulIvBits = ivLen * 8
}
if len(p.aad) > 0 {
aad, aadLen := arena.Allocate(p.aad)
params.pAAD = C.CK_BYTE_PTR(aad)
params.ulAADLen = aadLen
}
p.Free()
p.arena = arena
p.params = &params
return C.GoBytes(unsafe.Pointer(&params), C.int(unsafe.Sizeof(params)))
}
// IV returns a copy of the actual IV used for the operation.
//
// Some HSMs may ignore the user-specified IV and write their own at the end of
// the encryption operation; this method allows you to retrieve it.
func (p *GCMParams) IV() []byte {
if p == nil || p.params == nil {
return nil
@ -76,6 +99,10 @@ func (p *GCMParams) IV() []byte {
return iv
}
// Free deallocates the memory reserved for the HSM to write back the actual IV.
//
// This must be called after the entire operation is complete, i.e. after
// Encrypt or EncryptFinal. It is safe to call Free multiple times.
func (p *GCMParams) Free() {
if p == nil || p.arena == nil {
return
@ -84,3 +111,78 @@ func (p *GCMParams) Free() {
p.params = nil
p.arena = nil
}
// NewPSSParams creates a CK_RSA_PKCS_PSS_PARAMS structure and returns it as a byte array for use with the CKM_RSA_PKCS_PSS mechanism
func NewPSSParams(hashAlg, mgf, saltLength uint) []byte {
p := C.CK_RSA_PKCS_PSS_PARAMS{
hashAlg: C.CK_MECHANISM_TYPE(hashAlg),
mgf: C.CK_RSA_PKCS_MGF_TYPE(mgf),
sLen: C.CK_ULONG(saltLength),
}
return C.GoBytes(unsafe.Pointer(&p), C.int(unsafe.Sizeof(p)))
}
// OAEPParams can be passed to NewMechanism to implement CKM_RSA_PKCS_OAEP
type OAEPParams struct {
HashAlg uint
MGF uint
SourceType uint
SourceData []byte
}
// NewOAEPParams creates a CK_RSA_PKCS_OAEP_PARAMS structure suitable for use with the CKM_RSA_PKCS_OAEP mechanism
func NewOAEPParams(hashAlg, mgf, sourceType uint, sourceData []byte) *OAEPParams {
return &OAEPParams{
HashAlg: hashAlg,
MGF: mgf,
SourceType: sourceType,
SourceData: sourceData,
}
}
func cOAEPParams(p *OAEPParams, arena arena) ([]byte, arena) {
params := C.CK_RSA_PKCS_OAEP_PARAMS{
hashAlg: C.CK_MECHANISM_TYPE(p.HashAlg),
mgf: C.CK_RSA_PKCS_MGF_TYPE(p.MGF),
source: C.CK_RSA_PKCS_OAEP_SOURCE_TYPE(p.SourceType),
}
if len(p.SourceData) != 0 {
buf, len := arena.Allocate(p.SourceData)
// field is unaligned on windows so this has to call into C
C.putOAEPParams(&params, buf, len)
}
return C.GoBytes(unsafe.Pointer(&params), C.int(unsafe.Sizeof(params))), arena
}
// ECDH1DeriveParams can be passed to NewMechanism to implement CK_ECDH1_DERIVE_PARAMS
type ECDH1DeriveParams struct {
KDF uint
SharedData []byte
PublicKeyData []byte
}
// NewECDH1DeriveParams creates a CK_ECDH1_DERIVE_PARAMS structure suitable for use with the CKM_ECDH1_DERIVE mechanism
func NewECDH1DeriveParams(kdf uint, sharedData []byte, publicKeyData []byte) *ECDH1DeriveParams {
return &ECDH1DeriveParams{
KDF: kdf,
SharedData: sharedData,
PublicKeyData: publicKeyData,
}
}
func cECDH1DeriveParams(p *ECDH1DeriveParams, arena arena) ([]byte, arena) {
params := C.CK_ECDH1_DERIVE_PARAMS{
kdf: C.CK_EC_KDF_TYPE(p.KDF),
}
// SharedData MUST be null if key derivation function (KDF) is CKD_NULL
if len(p.SharedData) != 0 {
sharedData, sharedDataLen := arena.Allocate(p.SharedData)
C.putECDH1SharedParams(&params, sharedData, sharedDataLen)
}
publicKeyData, publicKeyDataLen := arena.Allocate(p.PublicKeyData)
C.putECDH1PublicParams(&params, publicKeyData, publicKeyDataLen)
return C.GoBytes(unsafe.Pointer(&params), C.int(unsafe.Sizeof(params))), arena
}

View File

@ -11,43 +11,73 @@ package pkcs11
// * CK_ULONG never overflows an Go int
/*
#cgo windows CFLAGS: -DREPACK_STRUCTURES
#cgo windows LDFLAGS: -lltdl
#cgo linux LDFLAGS: -lltdl -ldl
#cgo darwin CFLAGS: -I/usr/local/share/libtool
#cgo darwin LDFLAGS: -lltdl -L/usr/local/lib/
#cgo openbsd CFLAGS: -I/usr/local/include/
#cgo openbsd LDFLAGS: -lltdl -L/usr/local/lib/
#cgo freebsd CFLAGS: -I/usr/local/include/
#cgo freebsd LDFLAGS: -lltdl -L/usr/local/lib/
#cgo LDFLAGS: -lltdl
#cgo windows CFLAGS: -DPACKED_STRUCTURES
#cgo linux LDFLAGS: -ldl
#cgo darwin LDFLAGS: -ldl
#cgo openbsd LDFLAGS: -ldl
#cgo freebsd LDFLAGS: -ldl
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ltdl.h>
#include <unistd.h>
#include "pkcs11go.h"
#ifdef _WIN32
#include <windows.h>
struct ctx {
lt_dlhandle handle;
HMODULE handle;
CK_FUNCTION_LIST_PTR sym;
};
// New initializes a ctx and fills the symbol table.
struct ctx *New(const char *module)
{
if (lt_dlinit() != 0) {
return NULL;
}
CK_C_GetFunctionList list;
struct ctx *c = calloc(1, sizeof(struct ctx));
c->handle = lt_dlopen(module);
c->handle = LoadLibrary(module);
if (c->handle == NULL) {
free(c);
return NULL;
}
list = (CK_C_GetFunctionList) lt_dlsym(c->handle, "C_GetFunctionList");
list = (CK_C_GetFunctionList) GetProcAddress(c->handle, "C_GetFunctionList");
if (list == NULL) {
free(c);
return NULL;
}
list(&c->sym);
return c;
}
// Destroy cleans up a ctx.
void Destroy(struct ctx *c)
{
if (!c) {
return;
}
free(c);
}
#else
#include <dlfcn.h>
struct ctx {
void *handle;
CK_FUNCTION_LIST_PTR sym;
};
// New initializes a ctx and fills the symbol table.
struct ctx *New(const char *module)
{
CK_C_GetFunctionList list;
struct ctx *c = calloc(1, sizeof(struct ctx));
c->handle = dlopen(module, RTLD_LAZY);
if (c->handle == NULL) {
free(c);
return NULL;
}
list = (CK_C_GetFunctionList) dlsym(c->handle, "C_GetFunctionList");
if (list == NULL) {
free(c);
return NULL;
@ -65,12 +95,12 @@ void Destroy(struct ctx *c)
if (c->handle == NULL) {
return;
}
if (lt_dlclose(c->handle) < 0) {
if (dlclose(c->handle) < 0) {
return;
}
lt_dlexit();
free(c);
}
#endif
CK_RV Initialize(struct ctx * c)
{
@ -238,23 +268,17 @@ CK_RV Logout(struct ctx * c, CK_SESSION_HANDLE session)
}
CK_RV CreateObject(struct ctx * c, CK_SESSION_HANDLE session,
ckAttrPtr temp, CK_ULONG tempCount,
CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount,
CK_OBJECT_HANDLE_PTR obj)
{
ATTR_TO_C(tempc, temp, tempCount, NULL);
CK_RV e = c->sym->C_CreateObject(session, tempc, tempCount, obj);
ATTR_FREE(tempc);
return e;
return c->sym->C_CreateObject(session, temp, tempCount, obj);
}
CK_RV CopyObject(struct ctx * c, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE o,
ckAttrPtr temp, CK_ULONG tempCount,
CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount,
CK_OBJECT_HANDLE_PTR obj)
{
ATTR_TO_C(tempc, temp, tempCount, NULL);
CK_RV e = c->sym->C_CopyObject(session, o, tempc, tempCount, obj);
ATTR_FREE(tempc);
return e;
return c->sym->C_CopyObject(session, o, temp, tempCount, obj);
}
CK_RV DestroyObject(struct ctx * c, CK_SESSION_HANDLE session,
@ -272,48 +296,37 @@ CK_RV GetObjectSize(struct ctx * c, CK_SESSION_HANDLE session,
}
CK_RV GetAttributeValue(struct ctx * c, CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, ckAttrPtr temp,
CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR temp,
CK_ULONG templen)
{
ATTR_TO_C(tempc, temp, templen, NULL);
// Call for the first time, check the returned ulValue in the attributes, then
// allocate enough space and try again.
CK_RV e = c->sym->C_GetAttributeValue(session, object, tempc, templen);
CK_RV e = c->sym->C_GetAttributeValue(session, object, temp, templen);
if (e != CKR_OK) {
ATTR_FREE(tempc);
return e;
}
CK_ULONG i;
for (i = 0; i < templen; i++) {
if ((CK_LONG) tempc[i].ulValueLen == -1) {
if ((CK_LONG) temp[i].ulValueLen == -1) {
// either access denied or no such object
continue;
}
tempc[i].pValue = calloc(tempc[i].ulValueLen, sizeof(CK_BYTE));
temp[i].pValue = calloc(temp[i].ulValueLen, sizeof(CK_BYTE));
}
e = c->sym->C_GetAttributeValue(session, object, tempc, templen);
ATTR_FROM_C(temp, tempc, templen);
ATTR_FREE(tempc);
return e;
return c->sym->C_GetAttributeValue(session, object, temp, templen);
}
CK_RV SetAttributeValue(struct ctx * c, CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE object, ckAttrPtr temp,
CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR temp,
CK_ULONG templen)
{
ATTR_TO_C(tempc, temp, templen, NULL);
CK_RV e = c->sym->C_SetAttributeValue(session, object, tempc, templen);
ATTR_FREE(tempc);
return e;
return c->sym->C_SetAttributeValue(session, object, temp, templen);
}
CK_RV FindObjectsInit(struct ctx * c, CK_SESSION_HANDLE session,
ckAttrPtr temp, CK_ULONG tempCount)
CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount)
{
ATTR_TO_C(tempc, temp, tempCount, NULL);
CK_RV e = c->sym->C_FindObjectsInit(session, tempc, tempCount);
ATTR_FREE(tempc);
return e;
return c->sym->C_FindObjectsInit(session, temp, tempCount);
}
CK_RV FindObjects(struct ctx * c, CK_SESSION_HANDLE session,
@ -332,11 +345,9 @@ CK_RV FindObjectsFinal(struct ctx * c, CK_SESSION_HANDLE session)
}
CK_RV EncryptInit(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mechanism, CK_OBJECT_HANDLE key)
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
{
MECH_TO_C(m, mechanism);
CK_RV e = c->sym->C_EncryptInit(session, m, key);
return e;
return c->sym->C_EncryptInit(session, mechanism, key);
}
CK_RV Encrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
@ -388,17 +399,15 @@ CK_RV EncryptFinal(struct ctx * c, CK_SESSION_HANDLE session,
}
CK_RV DecryptInit(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mechanism, CK_OBJECT_HANDLE key)
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
{
MECH_TO_C(m, mechanism);
CK_RV e = c->sym->C_DecryptInit(session, m, key);
return e;
return c->sym->C_DecryptInit(session, mechanism, key);
}
CK_RV Decrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR cypher,
CK_RV Decrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR cipher,
CK_ULONG clen, CK_BYTE_PTR * plain, CK_ULONG_PTR plainlen)
{
CK_RV e = c->sym->C_Decrypt(session, cypher, clen, NULL, plainlen);
CK_RV e = c->sym->C_Decrypt(session, cipher, clen, NULL, plainlen);
if (e != CKR_OK) {
return e;
}
@ -406,7 +415,7 @@ CK_RV Decrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR cypher,
if (*plain == NULL) {
return CKR_HOST_MEMORY;
}
e = c->sym->C_Decrypt(session, cypher, clen, *plain, plainlen);
e = c->sym->C_Decrypt(session, cipher, clen, *plain, plainlen);
return e;
}
@ -444,11 +453,9 @@ CK_RV DecryptFinal(struct ctx * c, CK_SESSION_HANDLE session,
}
CK_RV DigestInit(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mechanism)
CK_MECHANISM_PTR mechanism)
{
MECH_TO_C(m, mechanism);
CK_RV e = c->sym->C_DigestInit(session, m);
return e;
return c->sym->C_DigestInit(session, mechanism);
}
CK_RV Digest(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
@ -495,11 +502,9 @@ CK_RV DigestFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR * hash,
}
CK_RV SignInit(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mechanism, CK_OBJECT_HANDLE key)
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
{
MECH_TO_C(m, mechanism);
CK_RV e = c->sym->C_SignInit(session, m, key);
return e;
return c->sym->C_SignInit(session, mechanism, key);
}
CK_RV Sign(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
@ -540,11 +545,9 @@ CK_RV SignFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR * sig,
}
CK_RV SignRecoverInit(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mech, CK_OBJECT_HANDLE key)
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
{
MECH_TO_C(m, mech);
CK_RV rv = c->sym->C_SignRecoverInit(session, m, key);
return rv;
return c->sym->C_SignRecoverInit(session, mechanism, key);
}
CK_RV SignRecover(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR data,
@ -563,11 +566,9 @@ CK_RV SignRecover(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR data,
}
CK_RV VerifyInit(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mech, CK_OBJECT_HANDLE key)
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
{
MECH_TO_C(m, mech);
CK_RV rv = c->sym->C_VerifyInit(session, m, key);
return rv;
return c->sym->C_VerifyInit(session, mechanism, key);
}
CK_RV Verify(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
@ -592,11 +593,9 @@ CK_RV VerifyFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR sig,
}
CK_RV VerifyRecoverInit(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mech, CK_OBJECT_HANDLE key)
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
{
MECH_TO_C(m, mech);
CK_RV rv = c->sym->C_VerifyRecoverInit(session, m, key);
return rv;
return c->sym->C_VerifyRecoverInit(session, mechanism, key);
}
CK_RV VerifyRecover(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR sig,
@ -688,39 +687,28 @@ CK_RV DecryptVerifyUpdate(struct ctx * c, CK_SESSION_HANDLE session,
}
CK_RV GenerateKey(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mechanism, ckAttrPtr temp,
CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR temp,
CK_ULONG tempCount, CK_OBJECT_HANDLE_PTR key)
{
MECH_TO_C(m, mechanism);
ATTR_TO_C(tempc, temp, tempCount, NULL);
CK_RV e = c->sym->C_GenerateKey(session, m, tempc, tempCount, key);
ATTR_FREE(tempc);
return e;
return c->sym->C_GenerateKey(session, mechanism, temp, tempCount, key);
}
CK_RV GenerateKeyPair(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mechanism, ckAttrPtr pub,
CK_ULONG pubCount, ckAttrPtr priv,
CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR pub,
CK_ULONG pubCount, CK_ATTRIBUTE_PTR priv,
CK_ULONG privCount, CK_OBJECT_HANDLE_PTR pubkey,
CK_OBJECT_HANDLE_PTR privkey)
{
MECH_TO_C(m, mechanism);
ATTR_TO_C(pubc, pub, pubCount, NULL);
ATTR_TO_C(privc, priv, privCount, pubc);
CK_RV e = c->sym->C_GenerateKeyPair(session, m, pubc, pubCount,
privc, privCount, pubkey, privkey);
ATTR_FREE(pubc);
ATTR_FREE(privc);
return e;
return c->sym->C_GenerateKeyPair(session, mechanism, pub, pubCount,
priv, privCount, pubkey, privkey);
}
CK_RV WrapKey(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mechanism, CK_OBJECT_HANDLE wrappingkey,
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE wrappingkey,
CK_OBJECT_HANDLE key, CK_BYTE_PTR * wrapped,
CK_ULONG_PTR wrappedlen)
{
MECH_TO_C(m, mechanism);
CK_RV rv = c->sym->C_WrapKey(session, m, wrappingkey, key, NULL,
CK_RV rv = c->sym->C_WrapKey(session, mechanism, wrappingkey, key, NULL,
wrappedlen);
if (rv != CKR_OK) {
return rv;
@ -729,33 +717,25 @@ CK_RV WrapKey(struct ctx * c, CK_SESSION_HANDLE session,
if (*wrapped == NULL) {
return CKR_HOST_MEMORY;
}
rv = c->sym->C_WrapKey(session, m, wrappingkey, key, *wrapped,
rv = c->sym->C_WrapKey(session, mechanism, wrappingkey, key, *wrapped,
wrappedlen);
return rv;
}
CK_RV DeriveKey(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mech, CK_OBJECT_HANDLE basekey,
ckAttrPtr a, CK_ULONG alen, CK_OBJECT_HANDLE_PTR key)
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE basekey,
CK_ATTRIBUTE_PTR a, CK_ULONG alen, CK_OBJECT_HANDLE_PTR key)
{
MECH_TO_C(m, mech);
ATTR_TO_C(tempc, a, alen, NULL);
CK_RV e = c->sym->C_DeriveKey(session, m, basekey, tempc, alen, key);
ATTR_FREE(tempc);
return e;
return c->sym->C_DeriveKey(session, mechanism, basekey, a, alen, key);
}
CK_RV UnwrapKey(struct ctx * c, CK_SESSION_HANDLE session,
ckMechPtr mech, CK_OBJECT_HANDLE unwrappingkey,
CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE unwrappingkey,
CK_BYTE_PTR wrappedkey, CK_ULONG wrappedkeylen,
ckAttrPtr a, CK_ULONG alen, CK_OBJECT_HANDLE_PTR key)
CK_ATTRIBUTE_PTR a, CK_ULONG alen, CK_OBJECT_HANDLE_PTR key)
{
MECH_TO_C(m, mech);
ATTR_TO_C(tempc, a, alen, NULL);
CK_RV e = c->sym->C_UnwrapKey(session, m, unwrappingkey, wrappedkey,
wrappedkeylen, tempc, alen, key);
ATTR_FREE(tempc);
return e;
return c->sym->C_UnwrapKey(session, mechanism, unwrappingkey, wrappedkey,
wrappedkeylen, a, alen, key);
}
CK_RV SeedRandom(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR seed,
@ -783,37 +763,11 @@ CK_RV WaitForSlotEvent(struct ctx * c, CK_FLAGS flags, CK_ULONG_PTR slot)
return e;
}
#ifdef REPACK_STRUCTURES
CK_RV attrsToC(CK_ATTRIBUTE_PTR *attrOut, ckAttrPtr attrIn, CK_ULONG count) {
CK_ATTRIBUTE_PTR attr = calloc(count, sizeof(CK_ATTRIBUTE));
if (attr == NULL) {
return CKR_HOST_MEMORY;
}
for (int i = 0; i < count; i++) {
attr[i].type = attrIn[i].type;
attr[i].pValue = attrIn[i].pValue;
attr[i].ulValueLen = attrIn[i].ulValueLen;
}
*attrOut = attr;
return CKR_OK;
static inline CK_VOID_PTR getAttributePval(CK_ATTRIBUTE_PTR a)
{
return a->pValue;
}
void attrsFromC(ckAttrPtr attrOut, CK_ATTRIBUTE_PTR attrIn, CK_ULONG count) {
for (int i = 0; i < count; i++) {
attrOut[i].type = attrIn[i].type;
attrOut[i].pValue = attrIn[i].pValue;
attrOut[i].ulValueLen = attrIn[i].ulValueLen;
}
}
void mechToC(CK_MECHANISM_PTR mechOut, ckMechPtr mechIn) {
mechOut->mechanism = mechIn->mechanism;
mechOut->pParameter = mechIn->pParameter;
mechOut->ulParameterLen = mechIn->ulParameterLen;
}
#endif
*/
import "C"
import "strings"
@ -827,11 +781,6 @@ type Ctx struct {
// New creates a new context and initializes the module/library for use.
func New(module string) *Ctx {
// libtool-ltdl will return an assertion error if passed an empty string, so
// we check for it explicitly.
if module == "" {
return nil
}
c := new(Ctx)
mod := C.CString(module)
defer C.free(unsafe.Pointer(mod))
@ -1124,21 +1073,22 @@ func (c *Ctx) GetObjectSize(sh SessionHandle, oh ObjectHandle) (uint, error) {
func (c *Ctx) GetAttributeValue(sh SessionHandle, o ObjectHandle, a []*Attribute) ([]*Attribute, error) {
// copy the attribute list and make all the values nil, so that
// the C function can (allocate) fill them in
pa := make([]C.ckAttr, len(a))
pa := make([]C.CK_ATTRIBUTE, len(a))
for i := 0; i < len(a); i++ {
pa[i]._type = C.CK_ATTRIBUTE_TYPE(a[i].Type)
}
e := C.GetAttributeValue(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), C.ckAttrPtr(&pa[0]), C.CK_ULONG(len(a)))
if toError(e) != nil {
return nil, toError(e)
e := C.GetAttributeValue(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), &pa[0], C.CK_ULONG(len(a)))
if err := toError(e); err != nil {
return nil, err
}
a1 := make([]*Attribute, len(a))
for i, c := range pa {
x := new(Attribute)
x.Type = uint(c._type)
if int(c.ulValueLen) != -1 {
x.Value = C.GoBytes(unsafe.Pointer(c.pValue), C.int(c.ulValueLen))
C.free(unsafe.Pointer(c.pValue))
buf := unsafe.Pointer(C.getAttributePval(&c))
x.Value = C.GoBytes(buf, C.int(c.ulValueLen))
C.free(buf)
}
a1[i] = x
}
@ -1164,8 +1114,10 @@ func (c *Ctx) FindObjectsInit(sh SessionHandle, temp []*Attribute) error {
// FindObjects continues a search for token and session
// objects that match a template, obtaining additional object
// handles. The returned boolean indicates if the list would
// have been larger than max.
// handles. Calling the function repeatedly may yield additional results until
// an empty slice is returned.
//
// The returned boolean value is deprecated and should be ignored.
func (c *Ctx) FindObjects(sh SessionHandle, max int) ([]ObjectHandle, bool, error) {
var (
objectList C.CK_OBJECT_HANDLE_PTR
@ -1193,7 +1145,7 @@ func (c *Ctx) FindObjectsFinal(sh SessionHandle) error {
// EncryptInit initializes an encryption operation.
func (c *Ctx) EncryptInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
arena, mech, _ := cMechanismList(m)
arena, mech := cMechanism(m)
defer arena.Free()
e := C.EncryptInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
return toError(e)
@ -1205,7 +1157,7 @@ func (c *Ctx) Encrypt(sh SessionHandle, message []byte) ([]byte, error) {
enc C.CK_BYTE_PTR
enclen C.CK_ULONG
)
e := C.Encrypt(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)), &enc, &enclen)
e := C.Encrypt(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), &enc, &enclen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1220,7 +1172,7 @@ func (c *Ctx) EncryptUpdate(sh SessionHandle, plain []byte) ([]byte, error) {
part C.CK_BYTE_PTR
partlen C.CK_ULONG
)
e := C.EncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&plain[0])), C.CK_ULONG(len(plain)), &part, &partlen)
e := C.EncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(plain), C.CK_ULONG(len(plain)), &part, &partlen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1246,19 +1198,19 @@ func (c *Ctx) EncryptFinal(sh SessionHandle) ([]byte, error) {
// DecryptInit initializes a decryption operation.
func (c *Ctx) DecryptInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
arena, mech, _ := cMechanismList(m)
arena, mech := cMechanism(m)
defer arena.Free()
e := C.DecryptInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
return toError(e)
}
// Decrypt decrypts encrypted data in a single part.
func (c *Ctx) Decrypt(sh SessionHandle, cypher []byte) ([]byte, error) {
func (c *Ctx) Decrypt(sh SessionHandle, cipher []byte) ([]byte, error) {
var (
plain C.CK_BYTE_PTR
plainlen C.CK_ULONG
)
e := C.Decrypt(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&cypher[0])), C.CK_ULONG(len(cypher)), &plain, &plainlen)
e := C.Decrypt(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), &plain, &plainlen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1273,7 +1225,7 @@ func (c *Ctx) DecryptUpdate(sh SessionHandle, cipher []byte) ([]byte, error) {
part C.CK_BYTE_PTR
partlen C.CK_ULONG
)
e := C.DecryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&cipher[0])), C.CK_ULONG(len(cipher)), &part, &partlen)
e := C.DecryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), &part, &partlen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1299,7 +1251,7 @@ func (c *Ctx) DecryptFinal(sh SessionHandle) ([]byte, error) {
// DigestInit initializes a message-digesting operation.
func (c *Ctx) DigestInit(sh SessionHandle, m []*Mechanism) error {
arena, mech, _ := cMechanismList(m)
arena, mech := cMechanism(m)
defer arena.Free()
e := C.DigestInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech)
return toError(e)
@ -1311,7 +1263,7 @@ func (c *Ctx) Digest(sh SessionHandle, message []byte) ([]byte, error) {
hash C.CK_BYTE_PTR
hashlen C.CK_ULONG
)
e := C.Digest(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)), &hash, &hashlen)
e := C.Digest(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), &hash, &hashlen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1322,7 +1274,7 @@ func (c *Ctx) Digest(sh SessionHandle, message []byte) ([]byte, error) {
// DigestUpdate continues a multiple-part message-digesting operation.
func (c *Ctx) DigestUpdate(sh SessionHandle, message []byte) error {
e := C.DigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)))
e := C.DigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)))
if toError(e) != nil {
return toError(e)
}
@ -1359,7 +1311,7 @@ func (c *Ctx) DigestFinal(sh SessionHandle) ([]byte, error) {
// operation, where the signature is (will be) an appendix to
// the data, and plaintext cannot be recovered from the signature.
func (c *Ctx) SignInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
arena, mech, _ := cMechanismList(m) // Only the first is used, but still use a list.
arena, mech := cMechanism(m)
defer arena.Free()
e := C.SignInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
return toError(e)
@ -1372,7 +1324,7 @@ func (c *Ctx) Sign(sh SessionHandle, message []byte) ([]byte, error) {
sig C.CK_BYTE_PTR
siglen C.CK_ULONG
)
e := C.Sign(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)), &sig, &siglen)
e := C.Sign(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), &sig, &siglen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1385,7 +1337,7 @@ func (c *Ctx) Sign(sh SessionHandle, message []byte) ([]byte, error) {
// where the signature is (will be) an appendix to the data,
// and plaintext cannot be recovered from the signature.
func (c *Ctx) SignUpdate(sh SessionHandle, message []byte) error {
e := C.SignUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&message[0])), C.CK_ULONG(len(message)))
e := C.SignUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)))
return toError(e)
}
@ -1406,7 +1358,7 @@ func (c *Ctx) SignFinal(sh SessionHandle) ([]byte, error) {
// SignRecoverInit initializes a signature operation, where the data can be recovered from the signature.
func (c *Ctx) SignRecoverInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
arena, mech, _ := cMechanismList(m)
arena, mech := cMechanism(m)
defer arena.Free()
e := C.SignRecoverInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
return toError(e)
@ -1418,7 +1370,7 @@ func (c *Ctx) SignRecover(sh SessionHandle, data []byte) ([]byte, error) {
sig C.CK_BYTE_PTR
siglen C.CK_ULONG
)
e := C.SignRecover(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&data[0])), C.CK_ULONG(len(data)), &sig, &siglen)
e := C.SignRecover(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(data), C.CK_ULONG(len(data)), &sig, &siglen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1431,7 +1383,7 @@ func (c *Ctx) SignRecover(sh SessionHandle, data []byte) ([]byte, error) {
// signature is an appendix to the data, and plaintext cannot
// be recovered from the signature (e.g. DSA).
func (c *Ctx) VerifyInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
arena, mech, _ := cMechanismList(m) // only use one here
arena, mech := cMechanism(m)
defer arena.Free()
e := C.VerifyInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
return toError(e)
@ -1441,7 +1393,7 @@ func (c *Ctx) VerifyInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) err
// where the signature is an appendix to the data, and plaintext
// cannot be recovered from the signature.
func (c *Ctx) Verify(sh SessionHandle, data []byte, signature []byte) error {
e := C.Verify(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&data[0])), C.CK_ULONG(len(data)), C.CK_BYTE_PTR(unsafe.Pointer(&signature[0])), C.CK_ULONG(len(signature)))
e := C.Verify(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(data), C.CK_ULONG(len(data)), cMessage(signature), C.CK_ULONG(len(signature)))
return toError(e)
}
@ -1449,21 +1401,21 @@ func (c *Ctx) Verify(sh SessionHandle, data []byte, signature []byte) error {
// operation, where the signature is an appendix to the data,
// and plaintext cannot be recovered from the signature.
func (c *Ctx) VerifyUpdate(sh SessionHandle, part []byte) error {
e := C.VerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&part[0])), C.CK_ULONG(len(part)))
e := C.VerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(part), C.CK_ULONG(len(part)))
return toError(e)
}
// VerifyFinal finishes a multiple-part verification
// operation, checking the signature.
func (c *Ctx) VerifyFinal(sh SessionHandle, signature []byte) error {
e := C.VerifyFinal(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&signature[0])), C.CK_ULONG(len(signature)))
e := C.VerifyFinal(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(signature), C.CK_ULONG(len(signature)))
return toError(e)
}
// VerifyRecoverInit initializes a signature verification
// operation, where the data is recovered from the signature.
func (c *Ctx) VerifyRecoverInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
arena, mech, _ := cMechanismList(m)
arena, mech := cMechanism(m)
defer arena.Free()
e := C.VerifyRecoverInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
return toError(e)
@ -1476,7 +1428,7 @@ func (c *Ctx) VerifyRecover(sh SessionHandle, signature []byte) ([]byte, error)
data C.CK_BYTE_PTR
datalen C.CK_ULONG
)
e := C.DecryptVerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&signature[0])), C.CK_ULONG(len(signature)), &data, &datalen)
e := C.DecryptVerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(signature), C.CK_ULONG(len(signature)), &data, &datalen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1491,7 +1443,7 @@ func (c *Ctx) DigestEncryptUpdate(sh SessionHandle, part []byte) ([]byte, error)
enc C.CK_BYTE_PTR
enclen C.CK_ULONG
)
e := C.DigestEncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&part[0])), C.CK_ULONG(len(part)), &enc, &enclen)
e := C.DigestEncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(part), C.CK_ULONG(len(part)), &enc, &enclen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1506,7 +1458,7 @@ func (c *Ctx) DecryptDigestUpdate(sh SessionHandle, cipher []byte) ([]byte, erro
part C.CK_BYTE_PTR
partlen C.CK_ULONG
)
e := C.DecryptDigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&cipher[0])), C.CK_ULONG(len(cipher)), &part, &partlen)
e := C.DecryptDigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), &part, &partlen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1521,7 +1473,7 @@ func (c *Ctx) SignEncryptUpdate(sh SessionHandle, part []byte) ([]byte, error) {
enc C.CK_BYTE_PTR
enclen C.CK_ULONG
)
e := C.SignEncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&part[0])), C.CK_ULONG(len(part)), &enc, &enclen)
e := C.SignEncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(part), C.CK_ULONG(len(part)), &enc, &enclen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1536,7 +1488,7 @@ func (c *Ctx) DecryptVerifyUpdate(sh SessionHandle, cipher []byte) ([]byte, erro
part C.CK_BYTE_PTR
partlen C.CK_ULONG
)
e := C.DecryptVerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&cipher[0])), C.CK_ULONG(len(cipher)), &part, &partlen)
e := C.DecryptVerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), &part, &partlen)
if toError(e) != nil {
return nil, toError(e)
}
@ -1550,7 +1502,7 @@ func (c *Ctx) GenerateKey(sh SessionHandle, m []*Mechanism, temp []*Attribute) (
var key C.CK_OBJECT_HANDLE
attrarena, t, tcount := cAttributeList(temp)
defer attrarena.Free()
mecharena, mech, _ := cMechanismList(m)
mecharena, mech := cMechanism(m)
defer mecharena.Free()
e := C.GenerateKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, t, tcount, C.CK_OBJECT_HANDLE_PTR(&key))
e1 := toError(e)
@ -1570,7 +1522,7 @@ func (c *Ctx) GenerateKeyPair(sh SessionHandle, m []*Mechanism, public, private
defer pubarena.Free()
privarena, priv, privcount := cAttributeList(private)
defer privarena.Free()
mecharena, mech, _ := cMechanismList(m)
mecharena, mech := cMechanism(m)
defer mecharena.Free()
e := C.GenerateKeyPair(c.ctx, C.CK_SESSION_HANDLE(sh), mech, pub, pubcount, priv, privcount, C.CK_OBJECT_HANDLE_PTR(&pubkey), C.CK_OBJECT_HANDLE_PTR(&privkey))
e1 := toError(e)
@ -1586,7 +1538,7 @@ func (c *Ctx) WrapKey(sh SessionHandle, m []*Mechanism, wrappingkey, key ObjectH
wrappedkey C.CK_BYTE_PTR
wrappedkeylen C.CK_ULONG
)
arena, mech, _ := cMechanismList(m)
arena, mech := cMechanism(m)
defer arena.Free()
e := C.WrapKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(wrappingkey), C.CK_OBJECT_HANDLE(key), &wrappedkey, &wrappedkeylen)
if toError(e) != nil {
@ -1602,7 +1554,7 @@ func (c *Ctx) UnwrapKey(sh SessionHandle, m []*Mechanism, unwrappingkey ObjectHa
var key C.CK_OBJECT_HANDLE
attrarena, ac, aclen := cAttributeList(a)
defer attrarena.Free()
mecharena, mech, _ := cMechanismList(m)
mecharena, mech := cMechanism(m)
defer mecharena.Free()
e := C.UnwrapKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(unwrappingkey), C.CK_BYTE_PTR(unsafe.Pointer(&wrappedkey[0])), C.CK_ULONG(len(wrappedkey)), ac, aclen, &key)
return ObjectHandle(key), toError(e)
@ -1613,7 +1565,7 @@ func (c *Ctx) DeriveKey(sh SessionHandle, m []*Mechanism, basekey ObjectHandle,
var key C.CK_OBJECT_HANDLE
attrarena, ac, aclen := cAttributeList(a)
defer attrarena.Free()
mecharena, mech, _ := cMechanismList(m)
mecharena, mech := cMechanism(m)
defer mecharena.Free()
e := C.DeriveKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(basekey), ac, aclen, &key)
return ObjectHandle(key), toError(e)

View File

@ -13,7 +13,7 @@
#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
#include <unistd.h>
#ifdef REPACK_STRUCTURES
#ifdef PACKED_STRUCTURES
# pragma pack(push, 1)
# include "pkcs11.h"
# pragma pack(pop)
@ -21,12 +21,9 @@
# include "pkcs11.h"
#endif
#ifdef REPACK_STRUCTURES
// Go doesn't support structures with non-default packing, but PKCS#11 requires
// pack(1) on Windows. Use structures with the same members as the CK_ ones but
// default packing, and copy data between the two.
// Copy of CK_INFO but with default alignment (not packed). Go hides unaligned
// struct fields so copying to an aligned struct is necessary to read CK_INFO
// from Go on Windows where packing is required.
typedef struct ckInfo {
CK_VERSION cryptokiVersion;
CK_UTF8CHAR manufacturerID[32];
@ -34,50 +31,3 @@ typedef struct ckInfo {
CK_UTF8CHAR libraryDescription[32];
CK_VERSION libraryVersion;
} ckInfo, *ckInfoPtr;
typedef struct ckAttr {
CK_ATTRIBUTE_TYPE type;
CK_VOID_PTR pValue;
CK_ULONG ulValueLen;
} ckAttr, *ckAttrPtr;
typedef struct ckMech {
CK_MECHANISM_TYPE mechanism;
CK_VOID_PTR pParameter;
CK_ULONG ulParameterLen;
} ckMech, *ckMechPtr;
CK_RV attrsToC(CK_ATTRIBUTE_PTR *attrOut, ckAttrPtr attrIn, CK_ULONG count);
void attrsFromC(ckAttrPtr attrOut, CK_ATTRIBUTE_PTR attrIn, CK_ULONG count);
void mechToC(CK_MECHANISM_PTR mechOut, ckMechPtr mechIn);
#define ATTR_TO_C(aout, ain, count, other) \
CK_ATTRIBUTE_PTR aout; \
{ \
CK_RV e = attrsToC(&aout, ain, count); \
if (e != CKR_OK ) { \
if (other != NULL) free(other); \
return e; \
} \
}
#define ATTR_FREE(aout) free(aout)
#define ATTR_FROM_C(aout, ain, count) attrsFromC(aout, ain, count)
#define MECH_TO_C(mout, min) \
CK_MECHANISM mval, *mout = &mval; \
if (min != NULL) { mechToC(mout, min); \
} else { mout = NULL; }
#else // REPACK_STRUCTURES
// Dummy types and macros to avoid any unnecessary copying on UNIX
typedef CK_INFO ckInfo, *ckInfoPtr;
typedef CK_ATTRIBUTE ckAttr, *ckAttrPtr;
typedef CK_MECHANISM ckMech, *ckMechPtr;
#define ATTR_TO_C(aout, ain, count, other) CK_ATTRIBUTE_PTR aout = ain
#define ATTR_FREE(aout)
#define ATTR_FROM_C(aout, ain, count)
#define MECH_TO_C(mout, min) CK_MECHANISM_PTR mout = min
#endif // REPACK_STRUCTURES

View File

@ -383,6 +383,11 @@ typedef CK_ULONG CK_KEY_TYPE;
#define CKK_GOSTR3411 0x00000031UL
#define CKK_GOST28147 0x00000032UL
#define CKK_SHA3_224_HMAC 0x00000033UL
#define CKK_SHA3_256_HMAC 0x00000034UL
#define CKK_SHA3_384_HMAC 0x00000035UL
#define CKK_SHA3_512_HMAC 0x00000036UL
#define CKK_VENDOR_DEFINED 0x80000000UL
@ -610,6 +615,10 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_DSA_SHA256 0x00000014UL
#define CKM_DSA_SHA384 0x00000015UL
#define CKM_DSA_SHA512 0x00000016UL
#define CKM_DSA_SHA3_224 0x00000018UL
#define CKM_DSA_SHA3_256 0x00000019UL
#define CKM_DSA_SHA3_384 0x0000001AUL
#define CKM_DSA_SHA3_512 0x0000001BUL
#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020UL
#define CKM_DH_PKCS_DERIVE 0x00000021UL
@ -643,6 +652,15 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_SHA512_T_HMAC_GENERAL 0x00000052UL
#define CKM_SHA512_T_KEY_DERIVATION 0x00000053UL
#define CKM_SHA3_256_RSA_PKCS 0x00000060UL
#define CKM_SHA3_384_RSA_PKCS 0x00000061UL
#define CKM_SHA3_512_RSA_PKCS 0x00000062UL
#define CKM_SHA3_256_RSA_PKCS_PSS 0x00000063UL
#define CKM_SHA3_384_RSA_PKCS_PSS 0x00000064UL
#define CKM_SHA3_512_RSA_PKCS_PSS 0x00000065UL
#define CKM_SHA3_224_RSA_PKCS 0x00000066UL
#define CKM_SHA3_224_RSA_PKCS_PSS 0x00000067UL
#define CKM_RC2_KEY_GEN 0x00000100UL
#define CKM_RC2_ECB 0x00000101UL
#define CKM_RC2_CBC 0x00000102UL
@ -724,6 +742,23 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_ACTI 0x000002A0UL
#define CKM_ACTI_KEY_GEN 0x000002A1UL
#define CKM_SHA3_256 0x000002B0UL
#define CKM_SHA3_256_HMAC 0x000002B1UL
#define CKM_SHA3_256_HMAC_GENERAL 0x000002B2UL
#define CKM_SHA3_256_KEY_GEN 0x000002B3UL
#define CKM_SHA3_224 0x000002B5UL
#define CKM_SHA3_224_HMAC 0x000002B6UL
#define CKM_SHA3_224_HMAC_GENERAL 0x000002B7UL
#define CKM_SHA3_224_KEY_GEN 0x000002B8UL
#define CKM_SHA3_384 0x000002C0UL
#define CKM_SHA3_384_HMAC 0x000002C1UL
#define CKM_SHA3_384_HMAC_GENERAL 0x000002C2UL
#define CKM_SHA3_384_KEY_GEN 0x000002C3UL
#define CKM_SHA3_512 0x000002D0UL
#define CKM_SHA3_512_HMAC 0x000002D1UL
#define CKM_SHA3_512_HMAC_GENERAL 0x000002D2UL
#define CKM_SHA3_512_KEY_GEN 0x000002D3UL
#define CKM_CAST_KEY_GEN 0x00000300UL
#define CKM_CAST_ECB 0x00000301UL
#define CKM_CAST_CBC 0x00000302UL
@ -789,6 +824,12 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
#define CKM_SHA384_KEY_DERIVATION 0x00000394UL
#define CKM_SHA512_KEY_DERIVATION 0x00000395UL
#define CKM_SHA224_KEY_DERIVATION 0x00000396UL
#define CKM_SHA3_256_KEY_DERIVE 0x00000397UL
#define CKM_SHA3_224_KEY_DERIVE 0x00000398UL
#define CKM_SHA3_384_KEY_DERIVE 0x00000399UL
#define CKM_SHA3_512_KEY_DERIVE 0x0000039AUL
#define CKM_SHAKE_128_KEY_DERIVE 0x0000039BUL
#define CKM_SHAKE_256_KEY_DERIVE 0x0000039CUL
#define CKM_PBE_MD2_DES_CBC 0x000003A0UL
#define CKM_PBE_MD5_DES_CBC 0x000003A1UL
@ -1299,7 +1340,10 @@ typedef CK_ULONG CK_EC_KDF_TYPE;
#define CKD_SHA384_KDF 0x00000007UL
#define CKD_SHA512_KDF 0x00000008UL
#define CKD_CPDIVERSIFY_KDF 0x00000009UL
#define CKD_SHA3_224_KDF 0x0000000AUL
#define CKD_SHA3_256_KDF 0x0000000BUL
#define CKD_SHA3_384_KDF 0x0000000CUL
#define CKD_SHA3_512_KDF 0x0000000DUL
/* CK_ECDH1_DERIVE_PARAMS provides the parameters to the
* CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,

View File

@ -13,6 +13,16 @@ CK_ULONG Index(CK_ULONG_PTR array, CK_ULONG i)
{
return array[i];
}
static inline void putAttributePval(CK_ATTRIBUTE_PTR a, CK_VOID_PTR pValue)
{
a->pValue = pValue;
}
static inline void putMechanismParam(CK_MECHANISM_PTR m, CK_VOID_PTR pParameter)
{
m->pParameter = pParameter;
}
*/
import "C"
@ -187,22 +197,22 @@ func NewAttribute(typ uint, x interface{}) *Attribute {
}
// cAttribute returns the start address and the length of an attribute list.
func cAttributeList(a []*Attribute) (arena, C.ckAttrPtr, C.CK_ULONG) {
func cAttributeList(a []*Attribute) (arena, C.CK_ATTRIBUTE_PTR, C.CK_ULONG) {
var arena arena
if len(a) == 0 {
return nil, nil, 0
}
pa := make([]C.ckAttr, len(a))
for i := 0; i < len(a); i++ {
pa[i]._type = C.CK_ATTRIBUTE_TYPE(a[i].Type)
//skip attribute if length is 0 to prevent panic in arena.Allocate
if a[i].Value == nil || len(a[i].Value) == 0 {
continue
pa := make([]C.CK_ATTRIBUTE, len(a))
for i, attr := range a {
pa[i]._type = C.CK_ATTRIBUTE_TYPE(attr.Type)
if len(attr.Value) != 0 {
buf, len := arena.Allocate(attr.Value)
// field is unaligned on windows so this has to call into C
C.putAttributePval(&pa[i], buf)
pa[i].ulValueLen = len
}
pa[i].pValue, pa[i].ulValueLen = arena.Allocate(a[i].Value)
}
return arena, C.ckAttrPtr(&pa[0]), C.CK_ULONG(len(a))
return arena, &pa[0], C.CK_ULONG(len(a))
}
func cDate(t time.Time) []byte {
@ -221,6 +231,7 @@ func cDate(t time.Time) []byte {
type Mechanism struct {
Mechanism uint
Parameter []byte
generator interface{}
}
// NewMechanism returns a pointer to an initialized Mechanism.
@ -231,32 +242,44 @@ func NewMechanism(mech uint, x interface{}) *Mechanism {
return m
}
switch x.(type) {
case *GCMParams:
m.Parameter = cGCMParams(x.(*GCMParams))
switch p := x.(type) {
case *GCMParams, *OAEPParams, *ECDH1DeriveParams:
// contains pointers; defer serialization until cMechanism
m.generator = p
case []byte:
m.Parameter = p
default:
m.Parameter = x.([]byte)
panic("parameter must be one of type: []byte, *GCMParams, *OAEPParams, *ECDH1DeriveParams")
}
return m
}
func cMechanismList(m []*Mechanism) (arena, C.ckMechPtr, C.CK_ULONG) {
func cMechanism(mechList []*Mechanism) (arena, *C.CK_MECHANISM) {
if len(mechList) != 1 {
panic("expected exactly one mechanism")
}
mech := mechList[0]
cmech := &C.CK_MECHANISM{mechanism: C.CK_MECHANISM_TYPE(mech.Mechanism)}
// params that contain pointers are allocated here
param := mech.Parameter
var arena arena
if len(m) == 0 {
return nil, nil, 0
switch p := mech.generator.(type) {
case *GCMParams:
// uses its own arena because it has to outlive this function call (yuck)
param = cGCMParams(p)
case *OAEPParams:
param, arena = cOAEPParams(p, arena)
case *ECDH1DeriveParams:
param, arena = cECDH1DeriveParams(p, arena)
}
pm := make([]C.ckMech, len(m))
for i := 0; i < len(m); i++ {
pm[i].mechanism = C.CK_MECHANISM_TYPE(m[i].Mechanism)
//skip parameter if length is 0 to prevent panic in arena.Allocate
if m[i].Parameter == nil || len(m[i].Parameter) == 0 {
continue
}
pm[i].pParameter, pm[i].ulParameterLen = arena.Allocate(m[i].Parameter)
if len(param) != 0 {
buf, len := arena.Allocate(param)
// field is unaligned on windows so this has to call into C
C.putMechanismParam(cmech, buf)
cmech.ulParameterLen = len
}
return arena, C.ckMechPtr(&pm[0]), C.CK_ULONG(len(m))
return arena, cmech
}
// MechanismInfo provides information about a particular mechanism.
@ -265,3 +288,16 @@ type MechanismInfo struct {
MaxKeySize uint
Flags uint
}
// stubData is a persistent nonempty byte array used by cMessage.
var stubData = []byte{0}
// cMessage returns the pointer/length pair corresponding to data.
func cMessage(data []byte) (dataPtr C.CK_BYTE_PTR) {
l := len(data)
if l == 0 {
// &data[0] is forbidden in this case, so use a nontrivial array instead.
data = stubData
}
return C.CK_BYTE_PTR(unsafe.Pointer(&data[0]))
}

127
vendor/github.com/miekg/pkcs11/vendor.go generated vendored Normal file
View File

@ -0,0 +1,127 @@
package pkcs11
// Vendor specific range for Ncipher network HSM.
const (
NFCK_VENDOR_NCIPHER = 0xde436972
CKA_NCIPHER = NFCK_VENDOR_NCIPHER
CKM_NCIPHER = NFCK_VENDOR_NCIPHER
CKK_NCIPHER = NFCK_VENDOR_NCIPHER
)
// Vendor specific mechanisms for HMAC on Ncipher HSMs where Ncipher does not allow use of generic_secret keys.
const (
CKM_NC_SHA_1_HMAC_KEY_GEN = CKM_NCIPHER + 0x3 /* no params */
CKM_NC_MD5_HMAC_KEY_GEN = CKM_NCIPHER + 0x6 /* no params */
CKM_NC_SHA224_HMAC_KEY_GEN = CKM_NCIPHER + 0x24 /* no params */
CKM_NC_SHA256_HMAC_KEY_GEN = CKM_NCIPHER + 0x25 /* no params */
CKM_NC_SHA384_HMAC_KEY_GEN = CKM_NCIPHER + 0x26 /* no params */
CKM_NC_SHA512_HMAC_KEY_GEN = CKM_NCIPHER + 0x27 /* no params */
)
// Vendor specific range for Mozilla NSS.
const (
NSSCK_VENDOR_NSS = 0x4E534350
CKO_NSS = CKO_VENDOR_DEFINED | NSSCK_VENDOR_NSS
CKK_NSS = CKK_VENDOR_DEFINED | NSSCK_VENDOR_NSS
CKC_NSS = CKC_VENDOR_DEFINED | NSSCK_VENDOR_NSS
CKA_NSS = CKA_VENDOR_DEFINED | NSSCK_VENDOR_NSS
CKA_TRUST = CKA_NSS + 0x2000
CKM_NSS = CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS
CKR_NSS = CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS
CKT_VENDOR_DEFINED = 0x80000000
CKT_NSS = CKT_VENDOR_DEFINED | NSSCK_VENDOR_NSS
)
// Vendor specific values for Mozilla NSS.
const (
CKO_NSS_CRL = CKO_NSS + 1
CKO_NSS_SMIME = CKO_NSS + 2
CKO_NSS_TRUST = CKO_NSS + 3
CKO_NSS_BUILTIN_ROOT_LIST = CKO_NSS + 4
CKO_NSS_NEWSLOT = CKO_NSS + 5
CKO_NSS_DELSLOT = CKO_NSS + 6
CKK_NSS_PKCS8 = CKK_NSS + 1
CKK_NSS_JPAKE_ROUND1 = CKK_NSS + 2
CKK_NSS_JPAKE_ROUND2 = CKK_NSS + 3
CKK_NSS_CHACHA20 = CKK_NSS + 4
CKA_NSS_URL = CKA_NSS + 1
CKA_NSS_EMAIL = CKA_NSS + 2
CKA_NSS_SMIME_INFO = CKA_NSS + 3
CKA_NSS_SMIME_TIMESTAMP = CKA_NSS + 4
CKA_NSS_PKCS8_SALT = CKA_NSS + 5
CKA_NSS_PASSWORD_CHECK = CKA_NSS + 6
CKA_NSS_EXPIRES = CKA_NSS + 7
CKA_NSS_KRL = CKA_NSS + 8
CKA_NSS_PQG_COUNTER = CKA_NSS + 20
CKA_NSS_PQG_SEED = CKA_NSS + 21
CKA_NSS_PQG_H = CKA_NSS + 22
CKA_NSS_PQG_SEED_BITS = CKA_NSS + 23
CKA_NSS_MODULE_SPEC = CKA_NSS + 24
CKA_NSS_OVERRIDE_EXTENSIONS = CKA_NSS + 25
CKA_NSS_JPAKE_SIGNERID = CKA_NSS + 26
CKA_NSS_JPAKE_PEERID = CKA_NSS + 27
CKA_NSS_JPAKE_GX1 = CKA_NSS + 28
CKA_NSS_JPAKE_GX2 = CKA_NSS + 29
CKA_NSS_JPAKE_GX3 = CKA_NSS + 30
CKA_NSS_JPAKE_GX4 = CKA_NSS + 31
CKA_NSS_JPAKE_X2 = CKA_NSS + 32
CKA_NSS_JPAKE_X2S = CKA_NSS + 33
CKA_NSS_MOZILLA_CA_POLICY = CKA_NSS + 34
CKA_TRUST_DIGITAL_SIGNATURE = CKA_TRUST + 1
CKA_TRUST_NON_REPUDIATION = CKA_TRUST + 2
CKA_TRUST_KEY_ENCIPHERMENT = CKA_TRUST + 3
CKA_TRUST_DATA_ENCIPHERMENT = CKA_TRUST + 4
CKA_TRUST_KEY_AGREEMENT = CKA_TRUST + 5
CKA_TRUST_KEY_CERT_SIGN = CKA_TRUST + 6
CKA_TRUST_CRL_SIGN = CKA_TRUST + 7
CKA_TRUST_SERVER_AUTH = CKA_TRUST + 8
CKA_TRUST_CLIENT_AUTH = CKA_TRUST + 9
CKA_TRUST_CODE_SIGNING = CKA_TRUST + 10
CKA_TRUST_EMAIL_PROTECTION = CKA_TRUST + 11
CKA_TRUST_IPSEC_END_SYSTEM = CKA_TRUST + 12
CKA_TRUST_IPSEC_TUNNEL = CKA_TRUST + 13
CKA_TRUST_IPSEC_USER = CKA_TRUST + 14
CKA_TRUST_TIME_STAMPING = CKA_TRUST + 15
CKA_TRUST_STEP_UP_APPROVED = CKA_TRUST + 16
CKA_CERT_SHA1_HASH = CKA_TRUST + 100
CKA_CERT_MD5_HASH = CKA_TRUST + 101
CKM_NSS_AES_KEY_WRAP = CKM_NSS + 1
CKM_NSS_AES_KEY_WRAP_PAD = CKM_NSS + 2
CKM_NSS_HKDF_SHA1 = CKM_NSS + 3
CKM_NSS_HKDF_SHA256 = CKM_NSS + 4
CKM_NSS_HKDF_SHA384 = CKM_NSS + 5
CKM_NSS_HKDF_SHA512 = CKM_NSS + 6
CKM_NSS_JPAKE_ROUND1_SHA1 = CKM_NSS + 7
CKM_NSS_JPAKE_ROUND1_SHA256 = CKM_NSS + 8
CKM_NSS_JPAKE_ROUND1_SHA384 = CKM_NSS + 9
CKM_NSS_JPAKE_ROUND1_SHA512 = CKM_NSS + 10
CKM_NSS_JPAKE_ROUND2_SHA1 = CKM_NSS + 11
CKM_NSS_JPAKE_ROUND2_SHA256 = CKM_NSS + 12
CKM_NSS_JPAKE_ROUND2_SHA384 = CKM_NSS + 13
CKM_NSS_JPAKE_ROUND2_SHA512 = CKM_NSS + 14
CKM_NSS_JPAKE_FINAL_SHA1 = CKM_NSS + 15
CKM_NSS_JPAKE_FINAL_SHA256 = CKM_NSS + 16
CKM_NSS_JPAKE_FINAL_SHA384 = CKM_NSS + 17
CKM_NSS_JPAKE_FINAL_SHA512 = CKM_NSS + 18
CKM_NSS_HMAC_CONSTANT_TIME = CKM_NSS + 19
CKM_NSS_SSL3_MAC_CONSTANT_TIME = CKM_NSS + 20
CKM_NSS_TLS_PRF_GENERAL_SHA256 = CKM_NSS + 21
CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256 = CKM_NSS + 22
CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256 = CKM_NSS + 23
CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 = CKM_NSS + 24
CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE = CKM_NSS + 25
CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH = CKM_NSS + 26
CKM_NSS_CHACHA20_KEY_GEN = CKM_NSS + 27
CKM_NSS_CHACHA20_POLY1305 = CKM_NSS + 28
CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN = CKM_NSS + 29
CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN = CKM_NSS + 30
CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN = CKM_NSS + 31
CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN = CKM_NSS + 32
CKR_NSS_CERTDB_FAILED = CKR_NSS + 1
CKR_NSS_KEYDB_FAILED = CKR_NSS + 2
CKT_NSS_TRUSTED = CKT_NSS + 1
CKT_NSS_TRUSTED_DELEGATOR = CKT_NSS + 2
CKT_NSS_MUST_VERIFY_TRUST = CKT_NSS + 3
CKT_NSS_NOT_TRUSTED = CKT_NSS + 10
CKT_NSS_TRUST_UNKNOWN = CKT_NSS + 5
)