Skip to content

Support signing image layers with PKCS#7 envelope #1337

@dallasd1

Description

@dallasd1

Is your feature request related to a problem?

Notation currently supports signing container images at the manifest level, which adds protection at image pull time. This model can be extended to add protection at runtime by additionally signing the image layer root hashes. The kernel would then be able to verify each layer's signature to ensure no tampering happened after the image pull.

In order to achieve this, the CLI can be extended to enable the extra signing.

What solution do you propose?

A new parameter --dm-verity can be added to the notation sign command. Initially, the only signature format that will be supported is PKCS#7. Since this is the default format, no other parameters need to be added at this time. An example of the full proposed command is below.

notation sign --dm-verity --id myKeyId myregistry.azurecr.io/myapp@sha256:def456...

This new parameter will initiate the original manifest signing and additionally sign each image layer's dm-verity root hash. The signatures will be stored in an OCI artifact referrer attached to the original image manifest.

What alternatives have you considered?

None

Any additional context?

There is a proposal in review with more details here #1335


PR Descriptions

PR 1: notation-core-go — Add PKCS#7 Envelope

Repo: notation-core-go

Reason: The kernel's dm-verity verification requires signatures to be in PKCS#7 format. This change adds a new envelope type alongside the JWS and COSE envelopes.

Code changes:

  • Add signature/pkcs7/envelope.go, which implements the Envelope interface
  • Register via signature.RegisterEnvelopeType() with argument application/pkcs7-signature
  • Pulls in the Mozilla PKCS#7 library go.mozilla.org/pkcs7 to use pre-defined data structures
  • Add a signerAdapter that wraps a raw signature and certs from signature.Signer. This is used by the imported Mozilla package to create the PKCS#7 structure. The package expects a crypto.Signer object, so we use the wrapper to satisfy that requirement.
  • Configure for kernel compatibility: SHA-256 digest, RSA encryption, no authenticated attributes, detached signature

Dependencies:

  • go.mozilla.org/pkcs7

PR 2: notation-go — Export PluginPrimitiveSigner

Repo: notation-go

Reason: The dm-verity flow needs access to signature.Signer (interface that returns raw signatures) rather than notation.Signer (interface that returns JWS/COSE envelopes). The existing pluginPrimitiveSigner already implements signature.Signer for plugins, but it's private. Exporting it allows the notation CLI to use signing plugins for with the PKCS#7 envelope. JWS and COSE use PluginSigner, which is already a public API.

Code changes:

  • Capitalize name pluginPrimitiveSigner to PluginPrimitiveSigner so we can export it.
  • Add NewPluginPrimitiveSigner() constructor
  • Add GetKeySpecFromPlugin() helper to query key metadata from plugins. This provides metadata from the signing key and is required to create a PluginPrimitiveSigner.

PR 3: notation-azure-kv — Add Kernel-Compliant Signing Config

Repo: notation-azure-kv

Reason: The Linux kernel requires PKCS#1 signature padding, but the AKV plugin only supports PSS padding. This is a fundamental limitation of the upstream Linux kernel.

The CLI will pass this PKCS#1 config to the plugin. The plugin will then call the Azure Key Vault API to sign using this kernel-compliant algorithm.

Code changes:

  • Protocol/KeySpec.cs — Add RSASSA-PKCS1-v1_5 algorithm constants and SigningScheme class
  • KeyVault/KeySpecExtension.cs — Add ToKeyVaultSignatureAlgorithmPKCS1() returning RS256/RS384/RS512
  • Command/GenerateSignature.cs — Read signing_scheme from plugin config, select algorithm accordingly

PR 4: notation — Add dm-verity Root Hash Calculations, EROFS Conversion, CLI Options

Repo: notation

Reason: This change adds utilities to convert container image layers to EROFS format, calculate dm-verity root hashes, sign them using the PKCS#7 envelope, and attach signatures to the registry.

Code changes:

  • internal/erofs/converter.go — Convert image layer tar.gz to EROFS filesystem image
  • internal/erofs/veritysetup.go — Calculate dm-verity Merkle tree and root hash
  • internal/dmverity/dmverity.go — Invoke signing using notation-core-go PKCS#7 envelope (PR 1)
  • cmd/notation/sign.go — Add --dm-verity flag
  • cmd/notation/internal/sign/sign.go — Add GetPrimitiveSigner() to obtain signature.Signer for scenarios using either local keys or plugins (PR 2)

Dependencies:

  • PR 1 (PKCS#7 envelope)
  • PR 2 (PluginPrimitiveSigner export)
  • mkfs.erofs tool for EROFS conversion

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttriageNeed to triage

    Type

    No type

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions