Skip to content

Commit

Permalink
[signing] Support SPX signing with hsmtool
Browse files Browse the repository at this point in the history
1. Enhance the signing rules to use the spx signing commands added to
   hsmtool.
2. Change the PKCS#11 provider from sc-hsm-embedded to opensc.
   - sc-hsm-embedded supports RSA3072 and ECDSA P256 signatures, but does
     not support CKO_DATA objects.
   - opensc supports ECDSA P256 signatures and CKO_DATA objects, but does
     not support RSA3072 signatures.

   We no longer use RSA3072 signatures for signing code; we _can_ use
   CKO_DATA objects to hold SPX keys for signing.

Signed-off-by: Chris Frantz <[email protected]>
  • Loading branch information
cfrantz committed Dec 18, 2024
1 parent 3cddf8e commit 49c9d40
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 9 deletions.
54 changes: 47 additions & 7 deletions rules/signing.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,17 @@ def _presigning_artifacts(ctx, opentitantool, src, manifest, ecdsa_key, rsa_key,
executable = opentitantool,
mnemonic = "PreSigningSpxMessage",
)
# TODO(cfrantz): After adding SPX support to hsmtool, append an appropriate
# signing directive here.
signing_directives.append(struct(
command = "spx-sign",
id = None,
label = spx_key.name,
little_endian = False,
# TODO(cfrantz): Update the format/domain when we can support pre-hashed signing.
format = "PlainText",
domain = "Pure",
output = "{}.spx_sig".format(basename),
input = "{}.spx-message".format(basename),
))

return struct(pre = pre, digest = digest, spxmsg = spxmsg, script = signing_directives)

Expand Down Expand Up @@ -364,7 +373,7 @@ def _local_sign(ctx, tool, digest, ecdsa_key, rsa_key, spxmsg = None, spx_key =
fail("Expected an ECDSA or RSA key")

def _hsmtool_sign(ctx, tool, digest, ecdsa_key, rsa_key, spxmsg = None, spx_key = None, profile = None):
"""Sign a digest with a local on-disk RSA private key.
"""Sign a digest with a token-provided private key.
Args:
ctx: The rule context.
Expand All @@ -378,20 +387,20 @@ def _hsmtool_sign(ctx, tool, digest, ecdsa_key, rsa_key, spxmsg = None, spx_key
Returns:
file, file, file: The RSA and SPX signature files.
"""
if spxmsg or spx_key:
fail("hsmtool currently does not support SPX+ signing")
if not profile:
fail("Missing the `hsmtool` profile")

if rsa_key:
cmd = "rsa"
sig = ctx.actions.declare_file(paths.replace_extension(digest.basename, ".rsa-sig"))
label = rsa_key.name
mnemonic = "HsmtoolRsaSign"
retval = (None, sig, None)
elif ecdsa_key:
cmd = "ecdsa"
sig = ctx.actions.declare_file(paths.replace_extension(digest.basename, ".ecdsa-sig"))
label = ecdsa_key.name
mnemonic = "HsmtoolEcdsaSign"
retval = (sig, None, None)
else:
fail("Expected either rsa_key or ecdsa_key; got neither")
Expand All @@ -416,9 +425,40 @@ def _hsmtool_sign(ctx, tool, digest, ecdsa_key, rsa_key, spxmsg = None, spx_key
"no-sandbox": "",
},
env = tool.env,
mnemonic = "HsmtoolRsaSign",
mnemonic = mnemonic,
)
return retval

spx_sig = None
if spxmsg and spx_key:
spx_sig = ctx.actions.declare_file(paths.replace_extension(spxmsg.basename, ".spx-sig"))
ctx.actions.run(
outputs = [spx_sig],
inputs = [spxmsg, tool.tool] + tool.data,
arguments = [
"--quiet",
"--lockfile=/tmp/hsmtool.lock",
"--profile={}".format(profile),
"spx",
"sign",
"--format=plain-text",
"--label={}".format(spx_key.name),
"--output={}".format(spx_sig.path),
spxmsg.path,
],
executable = tool.tool,
execution_requirements = {
"no-sandbox": "",
},
env = tool.env,
mnemonic = "HsmtoolSpxSign",
)

if rsa_key:
return None, sig, spx_sig
elif ecdsa_key:
return sig, None, spx_sig
else:
fail("Expected an ECDSA or RSA key")

def _post_signing_attach(ctx, opentitantool, pre, ecdsa_sig, rsa_sig, spx_sig):
"""Attach signatures to an unsigned binary.
Expand Down
6 changes: 4 additions & 2 deletions signing/tokens/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ signing_tool(

signing_tool(
name = "nitrokey",
data = ["@sc_hsm//:gen_dir"],
data = ["@opensc//:gen_dir"],
env = {
"HSMTOOL_MODULE": "$(location @sc_hsm//:gen_dir)/lib/libsc-hsm-pkcs11.so",
"LD_LIBRARY_PATH": "$(location @opensc//:gen_dir)/lib",
"HSMTOOL_MODULE": "$(location @opensc//:gen_dir)/lib/opensc-pkcs11.so",
"HSMTOOL_SPX_MODULE": "pkcs11-ef",
},
location = "token",
tool = "//sw/host/hsmtool",
Expand Down
46 changes: 46 additions & 0 deletions third_party/hsm/BUILD.opensc.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

load("@rules_foreign_cc//foreign_cc:configure.bzl", "configure_make")

package(default_visibility = ["//visibility:public"])

filegroup(
name = "all_srcs",
srcs = glob(["**"]),
)

configure_make(
name = "opensc",
args = ["-j"],
autoreconf = True,
autoreconf_options = ["-fi"],
configure_in_place = True,
configure_options = [
# Lie about the completions dir so that "make install" won't get
# confused about what is already installed on the host.
# This doesn't affect the build, as the installation happens in
# a bazel-supplied target directory, but it does prevent make from
# seeing the system's `/usr/share/bash-completion/completions`
# directory and complaining that it will be unable to install there.
"--with-completiondir=xxx-completions",
],
lib_source = ":all_srcs",
out_shared_libs = [
# It would be nice to configure this package to build `opensc-pkcs11.so`
# as a shared object that statically links `libopensc`, but I don't see
# a way to do that via the configure script. Users of this library
# will have to set LD_LIBRARY_PATH appropriately to see the needed
# shared libraries (e.g. `//signing/tokens:nitrokey`).
"libopensc.so",
"libopensc.so.12",
"opensc-pkcs11.so",
],
)

filegroup(
name = "gen_dir",
srcs = [":opensc"],
output_group = "gen_dir",
)
7 changes: 7 additions & 0 deletions third_party/hsm/repos.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ def hsm_repos():
strip_prefix = "sc-hsm-embedded-2.12",
sha256 = "707fca9df630708e0e59a7d4a8a7a016c56c83a585957f0fd9f806c0762f1944",
)
http_archive(
name = "opensc",
build_file = Label("//third_party/hsm:BUILD.opensc.bazel"),
url = "https://github.com/OpenSC/OpenSC/archive/refs/tags/0.26.0.tar.gz",
strip_prefix = "OpenSC-0.26.0",
sha256 = "c692ac7639fa398f7f07b1070ea5358344000d49d08dcb825296d4cec94c6b1f",
)
http_archive(
name = "cloud_kms_hsm",
build_file = Label("//third_party/hsm:BUILD.cloud_kms_hsm.bazel"),
Expand Down

0 comments on commit 49c9d40

Please sign in to comment.