Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[signing] Support SPX signing with hsmtool #25702

Merged
merged 2 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
8 changes: 4 additions & 4 deletions sw/host/sphincsplus/variants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,11 @@ algorithms! {
#[derive(EnumString, Display, Serialize, Deserialize)]
#[strum(ascii_case_insensitive)]
pub enum SphincsPlus {
#[serde(rename="SPHINCS+-SHAKE-128s-simple", alias="SHAKE-128s-simple")]
#[strum(serialize="SPHINCS+-SHAKE-128s-simple", serialize="SHAKE-128s-simple")]
#[serde(rename="SLA-DSA-SHAKE-128s", alias="SPHINCS+-SHAKE-128s-simple", alias="SHAKE-128s-simple")]
#[strum(to_string="SLA-DSA-SHAKE-128s", serialize="SPHINCS+-SHAKE-128s-simple", serialize="SHAKE-128s-simple")]
Shake128sSimple => shake_128s_simple,
#[serde(rename="SPHINCS+-SHA2-128s-simple", alias="SHA2-128s-simple")]
#[strum(serialize="SPHINCS+-SHA2-128s-simple", serialize="SHA2-128s-simple")]
#[serde(rename="SLA-DSA-SHA2-128s", alias="SPHINCS+-SHA2-128s-simple", alias="SHA2-128s-simple")]
#[strum(to_string="SLA-DSA-SHA2-128s", serialize="SPHINCS+-SHA2-128s-simple", serialize="SHA2-128s-simple")]
Sha2128sSimple => sha2_128s_simple,
}
}
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
Loading