| # Licensed under the Apache-2.0 license |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| load("@pigweed//pw_kernel/tooling:system_image.bzl", "SystemImageInfo") |
| load( |
| "//target/earlgrey/tooling/signing:pre_post.bzl", |
| "post_signing_attach", |
| "presigning_artifacts", |
| ) |
| load( |
| "//target/earlgrey/tooling/signing:util.bzl", |
| "clear_if_none_key", |
| "get_override", |
| "key_from_dict", |
| "signing_tool_info", |
| ) |
| |
| def sign_binary(ctx, opentitantool, **kwargs): |
| """Sign a binary. |
| |
| Args: |
| ctx: The rule context. |
| opentitantool: An opentitantool FilesToRun provider. |
| **kwargs: Overrides of values normally retrived from the context object. |
| ecdsa_key: The ECDSA signing key. |
| rsa_key: The RSA signing key. |
| spx_key: The SPHINCS+ signing key. |
| bin: The input binary. |
| manifest: The manifest header. |
| _tool: The signing tool (opentitantool). |
| Returns: |
| A dict of all of the signing artifacts: |
| pre: The pre-signing binary (input binary with manifest changes applied). |
| digest: The SHA256 hash over the pre-signing binary. |
| spxmsg: The SPHINCS+ message to be signed. |
| ecdsa_sig: The ECDSA signature of the digest. |
| rsa_sig: The RSA signature of the digest. |
| spx_sig: The SPHINCS+ signature over the message. |
| signed: The final signed binary. |
| """ |
| key_attr = get_override(ctx, "attr.ecdsa_key", kwargs) |
| key_attr = clear_if_none_key(key_attr) |
| ecdsa_key = key_from_dict(key_attr, "ecdsa_key") |
| |
| # TODO(cfrantz): Refactor to remove RSA, as we no longer support |
| # signing with RSA keys. |
| rsa_attr = {} |
| |
| if rsa_attr and key_attr: |
| fail("Only one of ECDSA or RSA key should be provided") |
| |
| if rsa_attr: |
| # Select RSA as the key attribute since at this point we have already |
| # determined that only one of ECDSA or RSA key should be provided. |
| key_attr = rsa_attr |
| |
| rsa_key = key_from_dict(rsa_attr, "rsa_key") |
| spx_key = key_from_dict(get_override(ctx, "attr.spx_key", kwargs), "spx_key") |
| |
| artifacts = presigning_artifacts( |
| ctx, |
| opentitantool, |
| get_override(ctx, "file.bin", kwargs), |
| get_override(ctx, "attr.manifest", kwargs), |
| ecdsa_key, |
| rsa_key, |
| spx_key, |
| basename = kwargs.get("basename"), |
| keyname_in_filenames = True, |
| ) |
| tool, signing_func, profile = signing_tool_info(ctx, key_attr, opentitantool) |
| ecdsa_sig, rsa_sig, spx_sig = signing_func( |
| ctx, |
| tool, |
| artifacts.digest, |
| ecdsa_key, |
| rsa_key, |
| artifacts.spxmsg, |
| spx_key, |
| profile, |
| ) |
| signed = post_signing_attach( |
| ctx, |
| opentitantool, |
| artifacts.pre, |
| ecdsa_sig, |
| rsa_sig, |
| spx_sig, |
| ) |
| return { |
| "digest": artifacts.digest, |
| "ecdsa_sig": ecdsa_sig, |
| "pre": artifacts.pre, |
| "rsa_sig": rsa_sig, |
| "signed": signed, |
| "spx_sig": spx_sig, |
| "spxmsg": artifacts.spxmsg, |
| } |
| |
| def _sign_bin_impl(ctx): |
| bin_file = None |
| if SystemImageInfo in ctx.attr.bin: |
| bin_file = ctx.attr.bin[SystemImageInfo].bin |
| else: |
| for f in ctx.files.bin: |
| if f.basename.endswith(".bin"): |
| bin_file = f |
| break |
| if not bin_file: |
| fail("No .bin file found in bin attribute") |
| |
| result = sign_binary( |
| ctx, |
| ctx.executable._opentitantool, |
| bin = bin_file, |
| basename = ctx.attr.basename or None, |
| ) |
| return [ |
| DefaultInfo(files = depset([result["signed"]]), data_runfiles = ctx.runfiles(files = [result["signed"]])), |
| ] |
| |
| sign_bin = rule( |
| implementation = _sign_bin_impl, |
| attrs = { |
| "basename": attr.string(doc = "Optional output filename basename"), |
| "bin": attr.label(allow_files = True), |
| "ecdsa_key": attr.label_keyed_string_dict( |
| allow_files = True, |
| doc = "ECDSA public key to validate this image", |
| ), |
| "manifest": attr.label(allow_files = True), |
| "rsa_key": attr.label_keyed_string_dict( |
| allow_files = True, |
| doc = "RSA public key to validate this image", |
| ), |
| "spx_key": attr.label_keyed_string_dict( |
| allow_files = True, |
| doc = "SPX public key to validate this image", |
| ), |
| "_opentitantool": attr.label( |
| executable = True, |
| allow_single_file = True, |
| cfg = "exec", |
| default = "@opentitan_devbundle//:opentitantool/opentitantool", |
| doc = "opentitantool", |
| ), |
| }, |
| ) |