From nobody Mon Jan 26 22:45:22 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8B88F33E35C for ; Mon, 26 Jan 2026 14:29:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437798; cv=none; b=raA2yYV0/eWnkQqqpAATvM++v2hEGfM6FFiay4RmxPaDuippvfTSsjrJJen9Yl2+GWbVKKk01U7yyt+ZsbhtsnX8nJnD0At6o/hqE7uu8TZxzxiAoDo+fJayKlYwKqZmsXX7fYBE6y1HzcneI1L5OzSYzBjvABBfN0Wj1d21C4w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437798; c=relaxed/simple; bh=yxuz1XGwka25nwbP3TQtMQjnCd1A9XYnkw4fpQ+1zI4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OfBRrY+vZHWE9I/NEtDl77k6PyuW5lHOhB5aFgIImLKsomYD+jTMUF9algEH6sypGMh/O9cdDfqpyTlVdRwiiQdbNhk+BMQ0Xkgb7Bn/2v1e7WTyo2UnlAWSwg4GxlRjGjxTDhrt41e1B1B9CAmBfH0YgWSsHBuB3iHxqkmrB0c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=aMhSJ/AN; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="aMhSJ/AN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769437794; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PrapPTZIg/B6PDqm9XjQ/SresbhuKzegBZp9ZIwUVT0=; b=aMhSJ/AN5ZcuwOEzaE0HFj9saBiSR28LxlBKd7KtlEpYAs7gwSDVrsl3Zw7aaUJd1eg0CI 0qiz+h184FNt3GZTEuUcRFbrQVnwML3523tGYJilSaSPd2HCrz/DCJnWwmhpKOaQS5UG9I dm2ZpUnukjiNuXl1KoqYKsXdtHWg4WE= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-50-wjpE7r4MOwufjKWD_dXKdg-1; Mon, 26 Jan 2026 09:29:51 -0500 X-MC-Unique: wjpE7r4MOwufjKWD_dXKdg-1 X-Mimecast-MFC-AGG-ID: wjpE7r4MOwufjKWD_dXKdg_1769437789 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 93479180034D; Mon, 26 Jan 2026 14:29:48 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.44.33.164]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8F9171800993; Mon, 26 Jan 2026 14:29:43 +0000 (UTC) From: David Howells To: Lukas Wunner , Ignat Korchagin Cc: David Howells , Jarkko Sakkinen , Herbert Xu , Eric Biggers , Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , "Jason A . Donenfeld" , Ard Biesheuvel , Stephan Mueller , linux-crypto@vger.kernel.org, keyrings@vger.kernel.org, linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v15 1/7] crypto: Add ML-DSA crypto_sig support Date: Mon, 26 Jan 2026 14:29:22 +0000 Message-ID: <20260126142931.1940586-2-dhowells@redhat.com> In-Reply-To: <20260126142931.1940586-1-dhowells@redhat.com> References: <20260126142931.1940586-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Add verify-only public key crypto support for ML-DSA so that the X.509/PKCS#7 signature verification code, as used by module signing, amongst other things, can make use of it through the common crypto_sig API. Signed-off-by: David Howells Reviewed-by: Jarkko Sakkinen cc: Eric Biggers cc: Lukas Wunner cc: Ignat Korchagin cc: Stephan Mueller cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org --- crypto/Kconfig | 9 +++ crypto/Makefile | 2 + crypto/mldsa.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 crypto/mldsa.c diff --git a/crypto/Kconfig b/crypto/Kconfig index 12a87f7cf150..a210575fa5e0 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -344,6 +344,15 @@ config CRYPTO_ECRDSA One of the Russian cryptographic standard algorithms (called GOST algorithms). Only signature verification is implemented. =20 +config CRYPTO_MLDSA + tristate "ML-DSA (Module-Lattice-Based Digital Signature Algorithm)" + select CRYPTO_SIG + select CRYPTO_LIB_MLDSA + help + ML-DSA (Module-Lattice-Based Digital Signature Algorithm) (FIPS-204). + + Only signature verification is implemented. + endmenu =20 menu "Block ciphers" diff --git a/crypto/Makefile b/crypto/Makefile index 23d3db7be425..267d5403045b 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -60,6 +60,8 @@ ecdsa_generic-y +=3D ecdsa-p1363.o ecdsa_generic-y +=3D ecdsasignature.asn1.o obj-$(CONFIG_CRYPTO_ECDSA) +=3D ecdsa_generic.o =20 +obj-$(CONFIG_CRYPTO_MLDSA) +=3D mldsa.o + crypto_acompress-y :=3D acompress.o crypto_acompress-y +=3D scompress.o obj-$(CONFIG_CRYPTO_ACOMP2) +=3D crypto_acompress.o diff --git a/crypto/mldsa.c b/crypto/mldsa.c new file mode 100644 index 000000000000..d8de082cc67a --- /dev/null +++ b/crypto/mldsa.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * crypto_sig wrapper around ML-DSA library. + */ +#include +#include +#include +#include + +struct crypto_mldsa_ctx { + u8 pk[MAX(MAX(MLDSA44_PUBLIC_KEY_SIZE, + MLDSA65_PUBLIC_KEY_SIZE), + MLDSA87_PUBLIC_KEY_SIZE)]; + unsigned int pk_len; + enum mldsa_alg strength; + bool key_set; +}; + +static int crypto_mldsa_sign(struct crypto_sig *tfm, + const void *msg, unsigned int msg_len, + void *sig, unsigned int sig_len) +{ + return -EOPNOTSUPP; +} + +static int crypto_mldsa_verify(struct crypto_sig *tfm, + const void *sig, unsigned int sig_len, + const void *msg, unsigned int msg_len) +{ + const struct crypto_mldsa_ctx *ctx =3D crypto_sig_ctx(tfm); + + if (unlikely(!ctx->key_set)) + return -EINVAL; + + return mldsa_verify(ctx->strength, sig, sig_len, msg, msg_len, + ctx->pk, ctx->pk_len); +} + +static unsigned int crypto_mldsa_key_size(struct crypto_sig *tfm) +{ + struct crypto_mldsa_ctx *ctx =3D crypto_sig_ctx(tfm); + + switch (ctx->strength) { + case MLDSA44: + return MLDSA44_PUBLIC_KEY_SIZE; + case MLDSA65: + return MLDSA65_PUBLIC_KEY_SIZE; + case MLDSA87: + return MLDSA87_PUBLIC_KEY_SIZE; + default: + WARN_ON_ONCE(1); + return 0; + } +} + +static int crypto_mldsa_set_pub_key(struct crypto_sig *tfm, + const void *key, unsigned int keylen) +{ + struct crypto_mldsa_ctx *ctx =3D crypto_sig_ctx(tfm); + unsigned int expected_len =3D crypto_mldsa_key_size(tfm); + + if (keylen !=3D expected_len) + return -EINVAL; + + ctx->pk_len =3D keylen; + memcpy(ctx->pk, key, keylen); + ctx->key_set =3D true; + return 0; +} + +static int crypto_mldsa_set_priv_key(struct crypto_sig *tfm, + const void *key, unsigned int keylen) +{ + return -EOPNOTSUPP; +} + +static unsigned int crypto_mldsa_max_size(struct crypto_sig *tfm) +{ + struct crypto_mldsa_ctx *ctx =3D crypto_sig_ctx(tfm); + + switch (ctx->strength) { + case MLDSA44: + return MLDSA44_SIGNATURE_SIZE; + case MLDSA65: + return MLDSA65_SIGNATURE_SIZE; + case MLDSA87: + return MLDSA87_SIGNATURE_SIZE; + default: + WARN_ON_ONCE(1); + return 0; + } +} + +static int crypto_mldsa44_alg_init(struct crypto_sig *tfm) +{ + struct crypto_mldsa_ctx *ctx =3D crypto_sig_ctx(tfm); + + ctx->strength =3D MLDSA44; + ctx->key_set =3D false; + return 0; +} + +static int crypto_mldsa65_alg_init(struct crypto_sig *tfm) +{ + struct crypto_mldsa_ctx *ctx =3D crypto_sig_ctx(tfm); + + ctx->strength =3D MLDSA65; + ctx->key_set =3D false; + return 0; +} + +static int crypto_mldsa87_alg_init(struct crypto_sig *tfm) +{ + struct crypto_mldsa_ctx *ctx =3D crypto_sig_ctx(tfm); + + ctx->strength =3D MLDSA87; + ctx->key_set =3D false; + return 0; +} + +static void crypto_mldsa_alg_exit(struct crypto_sig *tfm) +{ +} + +static struct sig_alg crypto_mldsa_algs[] =3D { + { + .sign =3D crypto_mldsa_sign, + .verify =3D crypto_mldsa_verify, + .set_pub_key =3D crypto_mldsa_set_pub_key, + .set_priv_key =3D crypto_mldsa_set_priv_key, + .key_size =3D crypto_mldsa_key_size, + .max_size =3D crypto_mldsa_max_size, + .init =3D crypto_mldsa44_alg_init, + .exit =3D crypto_mldsa_alg_exit, + .base.cra_name =3D "mldsa44", + .base.cra_driver_name =3D "mldsa44-lib", + .base.cra_ctxsize =3D sizeof(struct crypto_mldsa_ctx), + .base.cra_module =3D THIS_MODULE, + .base.cra_priority =3D 5000, + }, { + .sign =3D crypto_mldsa_sign, + .verify =3D crypto_mldsa_verify, + .set_pub_key =3D crypto_mldsa_set_pub_key, + .set_priv_key =3D crypto_mldsa_set_priv_key, + .key_size =3D crypto_mldsa_key_size, + .max_size =3D crypto_mldsa_max_size, + .init =3D crypto_mldsa65_alg_init, + .exit =3D crypto_mldsa_alg_exit, + .base.cra_name =3D "mldsa65", + .base.cra_driver_name =3D "mldsa65-lib", + .base.cra_ctxsize =3D sizeof(struct crypto_mldsa_ctx), + .base.cra_module =3D THIS_MODULE, + .base.cra_priority =3D 5000, + }, { + .sign =3D crypto_mldsa_sign, + .verify =3D crypto_mldsa_verify, + .set_pub_key =3D crypto_mldsa_set_pub_key, + .set_priv_key =3D crypto_mldsa_set_priv_key, + .key_size =3D crypto_mldsa_key_size, + .max_size =3D crypto_mldsa_max_size, + .init =3D crypto_mldsa87_alg_init, + .exit =3D crypto_mldsa_alg_exit, + .base.cra_name =3D "mldsa87", + .base.cra_driver_name =3D "mldsa87-lib", + .base.cra_ctxsize =3D sizeof(struct crypto_mldsa_ctx), + .base.cra_module =3D THIS_MODULE, + .base.cra_priority =3D 5000, + }, +}; + +static int __init mldsa_init(void) +{ + int ret, i; + + for (i =3D 0; i < ARRAY_SIZE(crypto_mldsa_algs); i++) { + ret =3D crypto_register_sig(&crypto_mldsa_algs[i]); + if (ret < 0) + goto error; + } + return 0; + +error: + pr_err("Failed to register (%d)\n", ret); + for (i--; i >=3D 0; i--) + crypto_unregister_sig(&crypto_mldsa_algs[i]); + return ret; +} +module_init(mldsa_init); + +static void mldsa_exit(void) +{ + for (int i =3D 0; i < ARRAY_SIZE(crypto_mldsa_algs); i++) + crypto_unregister_sig(&crypto_mldsa_algs[i]); +} +module_exit(mldsa_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Crypto API support for ML-DSA signature verification"); +MODULE_ALIAS_CRYPTO("mldsa44"); +MODULE_ALIAS_CRYPTO("mldsa65"); +MODULE_ALIAS_CRYPTO("mldsa87"); From nobody Mon Jan 26 22:45:22 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7E1670814 for ; Mon, 26 Jan 2026 14:30:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437804; cv=none; b=mV5rfKhKkNfBgVXqtmYHBY1RZbW1Fu71e9kNEGM9aembxxI/xl3/xdPiAdjoRfsPaZnxATX8LRQdCxT8IBwKAFGFr70C/M8A+cw8ZJNHe95/m8MTwYUgHWXEFhm1sPVI3+z2jOJRL9DAXB5KUUl0ce5ENZuAYCIYPU9zG3FJdsM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437804; c=relaxed/simple; bh=zWVGbSoeJSeylJFg4xuPPQw0S4v4e6q+ZujCzsynMak=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IzrCwjfb+MBVp5nvGroVAMkUaMSGtLSu+TOM1HAICK36QR26+oxgUFLNW1XBjvTL6valw6fOc3X/q7vvy5eK1nnU9RnbY8jZpz7JkjNV0yQaoipT8w28OhSB+x6/bPmN7KUs2BzCY1WKXEpf7zYun4Wu4Y39+BYDiNH422kOGp4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=EgT3Tm1+; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="EgT3Tm1+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769437801; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bq4OwZOcUv7PYvsl6dWJhmpDgkmBNkgX15y9m0yEJ7k=; b=EgT3Tm1++EebksEnbVuYEafRvN5L7jGdQfA85dqRECCgQv4fxMfeYW5JbQ/UaQtSklpEtf /79kjwYbRvnockvbyPRVVnYKMyec825g1CyHaGEe3lhI0lZzCzyWSXZoOt4i0rtv7VvIhj oYT1dmF3xfbY1kialjMTaARbCmxmTg0= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-57-YSegEDuxMTCa3hefZMcbKA-1; Mon, 26 Jan 2026 09:29:57 -0500 X-MC-Unique: YSegEDuxMTCa3hefZMcbKA-1 X-Mimecast-MFC-AGG-ID: YSegEDuxMTCa3hefZMcbKA_1769437795 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 37E651800365; Mon, 26 Jan 2026 14:29:55 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.44.33.164]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 382401956095; Mon, 26 Jan 2026 14:29:49 +0000 (UTC) From: David Howells To: Lukas Wunner , Ignat Korchagin Cc: David Howells , Jarkko Sakkinen , Herbert Xu , Eric Biggers , Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , "Jason A . Donenfeld" , Ard Biesheuvel , Stephan Mueller , linux-crypto@vger.kernel.org, keyrings@vger.kernel.org, linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v15 2/7] x509: Separately calculate sha256 for blacklist Date: Mon, 26 Jan 2026 14:29:23 +0000 Message-ID: <20260126142931.1940586-3-dhowells@redhat.com> In-Reply-To: <20260126142931.1940586-1-dhowells@redhat.com> References: <20260126142931.1940586-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Calculate the SHA256 hash for blacklisting purposes independently of the signature hash (which may be something other than SHA256). This is necessary because when ML-DSA is used, no digest is calculated. Note that this represents a change of behaviour in that the hash used for the blacklist check would previously have been whatever digest was used for, say, RSA-based signatures. It may be that this is inadvisable. Signed-off-by: David Howells cc: Lukas Wunner cc: Ignat Korchagin cc: Stephan Mueller cc: Eric Biggers cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org --- crypto/asymmetric_keys/x509_parser.h | 2 ++ crypto/asymmetric_keys/x509_public_key.c | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/= x509_parser.h index 0688c222806b..b7aeebdddb36 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -9,12 +9,14 @@ #include #include #include +#include =20 struct x509_certificate { struct x509_certificate *next; struct x509_certificate *signer; /* Certificate that signed this one */ struct public_key *pub; /* Public key details */ struct public_key_signature *sig; /* Signature parameters */ + u8 sha256[SHA256_DIGEST_SIZE]; /* Hash for blacklist purposes */ char *issuer; /* Name of certificate issuer */ char *subject; /* Name of certificate subject */ struct asymmetric_key_id *id; /* Issuer + Serial number */ diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_k= eys/x509_public_key.c index 12e3341e806b..79cc7b7a0630 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -31,6 +31,19 @@ int x509_get_sig_params(struct x509_certificate *cert) =20 pr_devel("=3D=3D>%s()\n", __func__); =20 + /* Calculate a SHA256 hash of the TBS and check it against the + * blacklist. + */ + sha256(cert->tbs, cert->tbs_size, cert->sha256); + ret =3D is_hash_blacklisted(cert->sha256, sizeof(cert->sha256), + BLACKLIST_HASH_X509_TBS); + if (ret =3D=3D -EKEYREJECTED) { + pr_err("Cert %*phN is blacklisted\n", + (int)sizeof(cert->sha256), cert->sha256); + cert->blacklisted =3D true; + ret =3D 0; + } + sig->s =3D kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL); if (!sig->s) return -ENOMEM; @@ -69,15 +82,6 @@ int x509_get_sig_params(struct x509_certificate *cert) if (ret < 0) goto error_2; =20 - ret =3D is_hash_blacklisted(sig->digest, sig->digest_size, - BLACKLIST_HASH_X509_TBS); - if (ret =3D=3D -EKEYREJECTED) { - pr_err("Cert %*phN is blacklisted\n", - sig->digest_size, sig->digest); - cert->blacklisted =3D true; - ret =3D 0; - } - error_2: kfree(desc); error: From nobody Mon Jan 26 22:45:22 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF7E01F1537 for ; Mon, 26 Jan 2026 14:30:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437812; cv=none; b=Qtu6O4ro+Jq8AymOUAdePorq+JnM6R/B7bcvH72xtDn1otQiJ2qy1oMWpaKglGm0mGTFS8Vw6OGYgdoWR8wo0dIL3XxziKs58XlTkHCxhEd1j23uHGnd+YRAM2fCEMtmkx4SYIwPaVpMPbKYpdqZyUE194nOA5xhxTd4o+IuuKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437812; c=relaxed/simple; bh=BaZwkH+RnIU/w8tcrlS+3/n3/FqQIRDSqJGaDeb2APE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ipfVRdeD5WPHARAsKXPQlDP9e9CQ3Ze3ycWIZ84GU9k9xnxysOU6+kAgiwGVwtcvXIzuAmlw8jLeDOyAzA/7bZD18yWiK1bbcyiOMc8I8LNWRbfP/c0euBzv1+EPbdHapSL2wo/BGtninz5UzL7UusSxuG7DUfhxCEDtplwPHtA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=EtswgNmB; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="EtswgNmB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769437808; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RcGuaPaMRdnlMQS/hyjV74vU7Y2QsfjgMG98WcB7epo=; b=EtswgNmBGErLnmaQFhA8hiw8nSSARTFxfjYYmnnUFJ8TZTAwkkAClWOzMc2z33Oz1Kch+E EPnjaQc1D6Vv/M/2pAf7wGKSKeFk5tNlqU7clDtGIXFKIe3S4yjdIZKOsgR/e9G6l1Vo2D lI2gku8MTCAT+wnvyNVOTmN+xCDTlYM= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-628-bNllV1vXPpaHTFsYBK0fJw-1; Mon, 26 Jan 2026 09:30:04 -0500 X-MC-Unique: bNllV1vXPpaHTFsYBK0fJw-1 X-Mimecast-MFC-AGG-ID: bNllV1vXPpaHTFsYBK0fJw_1769437802 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 78BE01944DF2; Mon, 26 Jan 2026 14:30:02 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.44.33.164]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2F8661956053; Mon, 26 Jan 2026 14:29:56 +0000 (UTC) From: David Howells To: Lukas Wunner , Ignat Korchagin Cc: David Howells , Jarkko Sakkinen , Herbert Xu , Eric Biggers , Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , "Jason A . Donenfeld" , Ard Biesheuvel , Stephan Mueller , linux-crypto@vger.kernel.org, keyrings@vger.kernel.org, linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v15 3/7] pkcs7, x509: Rename ->digest to ->m Date: Mon, 26 Jan 2026 14:29:24 +0000 Message-ID: <20260126142931.1940586-4-dhowells@redhat.com> In-Reply-To: <20260126142931.1940586-1-dhowells@redhat.com> References: <20260126142931.1940586-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Rename ->digest and ->digest_len to ->m and ->m_size to represent the input to the signature verification algorithm, reflecting that ->digest may no longer actually *be* a digest. Signed-off-by: David Howells cc: Lukas Wunner cc: Ignat Korchagin cc: Jarkko Sakkinen cc: Stephan Mueller cc: Eric Biggers cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org --- crypto/asymmetric_keys/asymmetric_type.c | 4 ++-- crypto/asymmetric_keys/pkcs7_verify.c | 28 ++++++++++++------------ crypto/asymmetric_keys/public_key.c | 3 +-- crypto/asymmetric_keys/signature.c | 2 +- crypto/asymmetric_keys/x509_public_key.c | 10 ++++----- include/crypto/public_key.h | 4 ++-- security/integrity/digsig_asymmetric.c | 4 ++-- 7 files changed, 26 insertions(+), 29 deletions(-) diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_k= eys/asymmetric_type.c index 348966ea2175..2326743310b1 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -593,10 +593,10 @@ static int asymmetric_key_verify_signature(struct ker= nel_pkey_params *params, { struct public_key_signature sig =3D { .s_size =3D params->in2_len, - .digest_size =3D params->in_len, + .m_size =3D params->in_len, .encoding =3D params->encoding, .hash_algo =3D params->hash_algo, - .digest =3D (void *)in, + .m =3D (void *)in, .s =3D (void *)in2, }; =20 diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys= /pkcs7_verify.c index 6d6475e3a9bf..aa085ec6fb1c 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -31,7 +31,7 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); =20 /* The digest was calculated already. */ - if (sig->digest) + if (sig->m) return 0; =20 if (!sinfo->sig->hash_algo) @@ -45,11 +45,11 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, return (PTR_ERR(tfm) =3D=3D -ENOENT) ? -ENOPKG : PTR_ERR(tfm); =20 desc_size =3D crypto_shash_descsize(tfm) + sizeof(*desc); - sig->digest_size =3D crypto_shash_digestsize(tfm); + sig->m_size =3D crypto_shash_digestsize(tfm); =20 ret =3D -ENOMEM; - sig->digest =3D kmalloc(sig->digest_size, GFP_KERNEL); - if (!sig->digest) + sig->m =3D kmalloc(sig->m_size, GFP_KERNEL); + if (!sig->m) goto error_no_desc; =20 desc =3D kzalloc(desc_size, GFP_KERNEL); @@ -59,11 +59,10 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, desc->tfm =3D tfm; =20 /* Digest the message [RFC2315 9.3] */ - ret =3D crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len, - sig->digest); + ret =3D crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len, sig->m); if (ret < 0) goto error; - pr_devel("MsgDigest =3D [%*ph]\n", 8, sig->digest); + pr_devel("MsgDigest =3D [%*ph]\n", 8, sig->m); =20 /* However, if there are authenticated attributes, there must be a * message digest attribute amongst them which corresponds to the @@ -78,14 +77,14 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, goto error; } =20 - if (sinfo->msgdigest_len !=3D sig->digest_size) { + if (sinfo->msgdigest_len !=3D sig->m_size) { pr_warn("Sig %u: Invalid digest size (%u)\n", sinfo->index, sinfo->msgdigest_len); ret =3D -EBADMSG; goto error; } =20 - if (memcmp(sig->digest, sinfo->msgdigest, + if (memcmp(sig->m, sinfo->msgdigest, sinfo->msgdigest_len) !=3D 0) { pr_warn("Sig %u: Message digest doesn't match\n", sinfo->index); @@ -98,7 +97,8 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, * convert the attributes from a CONT.0 into a SET before we * hash it. */ - memset(sig->digest, 0, sig->digest_size); + memset(sig->m, 0, sig->m_size); + =20 ret =3D crypto_shash_init(desc); if (ret < 0) @@ -108,10 +108,10 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, if (ret < 0) goto error; ret =3D crypto_shash_finup(desc, sinfo->authattrs, - sinfo->authattrs_len, sig->digest); + sinfo->authattrs_len, sig->m); if (ret < 0) goto error; - pr_devel("AADigest =3D [%*ph]\n", 8, sig->digest); + pr_devel("AADigest =3D [%*ph]\n", 8, sig->m); } =20 error: @@ -138,8 +138,8 @@ int pkcs7_get_digest(struct pkcs7_message *pkcs7, const= u8 **buf, u32 *len, if (ret) return ret; =20 - *buf =3D sinfo->sig->digest; - *len =3D sinfo->sig->digest_size; + *buf =3D sinfo->sig->m; + *len =3D sinfo->sig->m_size; =20 i =3D match_string(hash_algo_name, HASH_ALGO__LAST, sinfo->sig->hash_algo); diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/p= ublic_key.c index e5b177c8e842..a46356e0c08b 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -425,8 +425,7 @@ int public_key_verify_signature(const struct public_key= *pkey, if (ret) goto error_free_key; =20 - ret =3D crypto_sig_verify(tfm, sig->s, sig->s_size, - sig->digest, sig->digest_size); + ret =3D crypto_sig_verify(tfm, sig->s, sig->s_size, sig->m, sig->m_size); =20 error_free_key: kfree_sensitive(key); diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/si= gnature.c index 041d04b5c953..f4ec126121b3 100644 --- a/crypto/asymmetric_keys/signature.c +++ b/crypto/asymmetric_keys/signature.c @@ -28,7 +28,7 @@ void public_key_signature_free(struct public_key_signatur= e *sig) for (i =3D 0; i < ARRAY_SIZE(sig->auth_ids); i++) kfree(sig->auth_ids[i]); kfree(sig->s); - kfree(sig->digest); + kfree(sig->m); kfree(sig); } } diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_k= eys/x509_public_key.c index 79cc7b7a0630..3854f7ae4ed0 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -63,11 +63,11 @@ int x509_get_sig_params(struct x509_certificate *cert) } =20 desc_size =3D crypto_shash_descsize(tfm) + sizeof(*desc); - sig->digest_size =3D crypto_shash_digestsize(tfm); + sig->m_size =3D crypto_shash_digestsize(tfm); =20 ret =3D -ENOMEM; - sig->digest =3D kmalloc(sig->digest_size, GFP_KERNEL); - if (!sig->digest) + sig->m =3D kmalloc(sig->m_size, GFP_KERNEL); + if (!sig->m) goto error; =20 desc =3D kzalloc(desc_size, GFP_KERNEL); @@ -76,9 +76,7 @@ int x509_get_sig_params(struct x509_certificate *cert) =20 desc->tfm =3D tfm; =20 - ret =3D crypto_shash_digest(desc, cert->tbs, cert->tbs_size, - sig->digest); - + ret =3D crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->m); if (ret < 0) goto error_2; =20 diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 81098e00c08f..bd38ba4d217d 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -43,9 +43,9 @@ extern void public_key_free(struct public_key *key); struct public_key_signature { struct asymmetric_key_id *auth_ids[3]; u8 *s; /* Signature */ - u8 *digest; + u8 *m; /* Message data to pass to verifier */ u32 s_size; /* Number of bytes in signature */ - u32 digest_size; /* Number of bytes in digest */ + u32 m_size; /* Number of bytes in ->m */ const char *pkey_algo; const char *hash_algo; const char *encoding; diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/di= gsig_asymmetric.c index 457c0a396caf..87be85f477d1 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -121,8 +121,8 @@ int asymmetric_verify(struct key *keyring, const char *= sig, goto out; } =20 - pks.digest =3D (u8 *)data; - pks.digest_size =3D datalen; + pks.m =3D (u8 *)data; + pks.m_size =3D datalen; pks.s =3D hdr->sig; pks.s_size =3D siglen; ret =3D verify_signature(key, &pks); From nobody Mon Jan 26 22:45:22 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1294023D290 for ; Mon, 26 Jan 2026 14:30:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437819; cv=none; b=H94NZzinbyvIK0hvC5OPsKNMDHSVkuDJ88yucrtBf450IlodY7IIumT2xwRpxxHFG3BdTvslNivZrhziPqtThRCLC2FghjN26RRDE2z18wfNz4AUNwMsNiKgNPAG3QAuVTIQ3BTouKf/r6R/O2OmI1k3q3AIo/Roh8RnNYhdh3s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437819; c=relaxed/simple; bh=DFb76c+PUi4IziO0qvjEAggO+1DAEB4SYumgeLR5/uw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JSzEwVlTjPwHb/K6YwRMX9mMIdr2X2yvv0XFtMEbPtpcWiPbOnfp54iA9P1awMnMJyzKJiSzUSVaNrhFtpb07NvmzZzJScyqXkoEPc+FdOaEPlAacBkekXFGNEWkHEXyVVIWx9NeapwfmISrfyJkXoB0+zrMzSV0h+bqQBTtbmQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=dXkonsnz; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="dXkonsnz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769437817; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZqciBHgX80r/eitlB1B79Iv3FzWXlKpKclGh0VAs2lk=; b=dXkonsnzq9PM9PRiS85C5qMuGRyXPpLqQ5I2Q9WxZIoOvU0HuUgvMNeiZ3WrtKT0d6vHS1 3rcziJELhcfEkmI517guDTti7gEvGe6yvAS5PUkpRzypQaJTspiaj17YEhHnu0JQKu074o RwsvXu2XVwlJgdWKI6lAdiENK0Xxaqo= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-599-8y8aMo8ANPippaPriXV3sQ-1; Mon, 26 Jan 2026 09:30:11 -0500 X-MC-Unique: 8y8aMo8ANPippaPriXV3sQ-1 X-Mimecast-MFC-AGG-ID: 8y8aMo8ANPippaPriXV3sQ_1769437809 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id F3E49193E8C8; Mon, 26 Jan 2026 14:30:08 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.44.33.164]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 28D9F195419B; Mon, 26 Jan 2026 14:30:03 +0000 (UTC) From: David Howells To: Lukas Wunner , Ignat Korchagin Cc: David Howells , Jarkko Sakkinen , Herbert Xu , Eric Biggers , Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , "Jason A . Donenfeld" , Ard Biesheuvel , Stephan Mueller , linux-crypto@vger.kernel.org, keyrings@vger.kernel.org, linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v15 4/7] pkcs7: Allow the signing algo to do whatever digestion it wants itself Date: Mon, 26 Jan 2026 14:29:25 +0000 Message-ID: <20260126142931.1940586-5-dhowells@redhat.com> In-Reply-To: <20260126142931.1940586-1-dhowells@redhat.com> References: <20260126142931.1940586-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Allow the data to be verified in a PKCS#7 or CMS message to be passed directly to an asymmetric cipher algorithm (e.g. ML-DSA) if it wants to do whatever passes for hashing/digestion itself. The normal digestion of the data is then skipped as that would be ignored unless another signed info in the message has some other algorithm that needs it. The 'data to be verified' may be the content of the PKCS#7 message or it will be the authenticatedAttributes (signedAttrs if CMS), modified, if those are present. This is done by: (1) Make ->m and ->m_size point to the data to be verified rather than making public_key_verify_signature() access the data directly. This is so that keyctl(KEYCTL_PKEY_VERIFY) will still work. (2) Add a flag, ->algo_takes_data, to indicate that the verification algorithm wants to access the data to be verified directly rather than having it digested first. (3) If the PKCS#7 message has authenticatedAttributes (or CMS signedAttrs), then the digest contained therein will be validated as now, and the modified attrs blob will either be digested or assigned to ->m as appropriate. (4) If present, always copy and modify the authenticatedAttributes (or signedAttrs) then digest that in one go rather than calling the shash update twice (once for the tag and once for the rest). (5) For ML-DSA, point ->m to the TBSCertificate instead of digesting it and using the digest. Note that whilst ML-DSA does allow for an "external mu", CMS doesn't yet have that standardised. Signed-off-by: David Howells cc: Lukas Wunner cc: Ignat Korchagin cc: Stephan Mueller cc: Eric Biggers cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org --- crypto/asymmetric_keys/pkcs7_parser.c | 4 +- crypto/asymmetric_keys/pkcs7_verify.c | 52 ++++++++++++++++-------- crypto/asymmetric_keys/signature.c | 3 +- crypto/asymmetric_keys/x509_public_key.c | 10 +++++ include/crypto/public_key.h | 2 + 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys= /pkcs7_parser.c index 423d13c47545..3cdbab3b9f50 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -599,8 +599,8 @@ int pkcs7_sig_note_set_of_authattrs(void *context, size= _t hdrlen, } =20 /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ - sinfo->authattrs =3D value - (hdrlen - 1); - sinfo->authattrs_len =3D vlen + (hdrlen - 1); + sinfo->authattrs =3D value - hdrlen; + sinfo->authattrs_len =3D vlen + hdrlen; return 0; } =20 diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys= /pkcs7_verify.c index aa085ec6fb1c..06abb9838f95 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -30,6 +30,16 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, =20 kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); =20 + if (!sinfo->authattrs && sig->algo_takes_data) { + /* There's no intermediate digest and the signature algo + * doesn't want the data prehashing. + */ + sig->m =3D (void *)pkcs7->data; + sig->m_size =3D pkcs7->data_len; + sig->m_free =3D false; + return 0; + } + /* The digest was calculated already. */ if (sig->m) return 0; @@ -48,9 +58,10 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, sig->m_size =3D crypto_shash_digestsize(tfm); =20 ret =3D -ENOMEM; - sig->m =3D kmalloc(sig->m_size, GFP_KERNEL); + sig->m =3D kmalloc(umax(sinfo->authattrs_len, sig->m_size), GFP_KERNEL); if (!sig->m) goto error_no_desc; + sig->m_free =3D true; =20 desc =3D kzalloc(desc_size, GFP_KERNEL); if (!desc) @@ -69,8 +80,6 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, * digest we just calculated. */ if (sinfo->authattrs) { - u8 tag; - if (!sinfo->msgdigest) { pr_warn("Sig %u: No messageDigest\n", sinfo->index); ret =3D -EKEYREJECTED; @@ -96,21 +105,25 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, * as the contents of the digest instead. Note that we need to * convert the attributes from a CONT.0 into a SET before we * hash it. + * + * However, for certain algorithms, such as ML-DSA, the digest + * is integrated into the signing algorithm. In such a case, + * we copy the authattrs, modifying the tag type, and set that + * as the digest. */ - memset(sig->m, 0, sig->m_size); - - - ret =3D crypto_shash_init(desc); - if (ret < 0) - goto error; - tag =3D ASN1_CONS_BIT | ASN1_SET; - ret =3D crypto_shash_update(desc, &tag, 1); - if (ret < 0) - goto error; - ret =3D crypto_shash_finup(desc, sinfo->authattrs, - sinfo->authattrs_len, sig->m); - if (ret < 0) - goto error; + memcpy(sig->m, sinfo->authattrs, sinfo->authattrs_len); + sig->m[0] =3D ASN1_CONS_BIT | ASN1_SET; + + if (sig->algo_takes_data) { + sig->m_size =3D sinfo->authattrs_len; + ret =3D 0; + } else { + ret =3D crypto_shash_digest(desc, sig->m, + sinfo->authattrs_len, + sig->m); + if (ret < 0) + goto error; + } pr_devel("AADigest =3D [%*ph]\n", 8, sig->m); } =20 @@ -137,6 +150,11 @@ int pkcs7_get_digest(struct pkcs7_message *pkcs7, cons= t u8 **buf, u32 *len, ret =3D pkcs7_digest(pkcs7, sinfo); if (ret) return ret; + if (!sinfo->sig->m_free) { + pr_notice_once("%s: No digest available\n", __func__); + return -EINVAL; /* TODO: MLDSA doesn't necessarily calculate an + * intermediate digest. */ + } =20 *buf =3D sinfo->sig->m; *len =3D sinfo->sig->m_size; diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/si= gnature.c index f4ec126121b3..a5ac7a53b670 100644 --- a/crypto/asymmetric_keys/signature.c +++ b/crypto/asymmetric_keys/signature.c @@ -28,7 +28,8 @@ void public_key_signature_free(struct public_key_signatur= e *sig) for (i =3D 0; i < ARRAY_SIZE(sig->auth_ids); i++) kfree(sig->auth_ids[i]); kfree(sig->s); - kfree(sig->m); + if (sig->m_free) + kfree(sig->m); kfree(sig); } } diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_k= eys/x509_public_key.c index 3854f7ae4ed0..27b4fea37845 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -50,6 +50,14 @@ int x509_get_sig_params(struct x509_certificate *cert) =20 sig->s_size =3D cert->raw_sig_size; =20 + if (sig->algo_takes_data) { + /* The signature algorithm does whatever passes for hashing. */ + sig->m =3D (u8 *)cert->tbs; + sig->m_size =3D cert->tbs_size; + sig->m_free =3D false; + goto out; + } + /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ @@ -69,6 +77,7 @@ int x509_get_sig_params(struct x509_certificate *cert) sig->m =3D kmalloc(sig->m_size, GFP_KERNEL); if (!sig->m) goto error; + sig->m_free =3D true; =20 desc =3D kzalloc(desc_size, GFP_KERNEL); if (!desc) @@ -84,6 +93,7 @@ int x509_get_sig_params(struct x509_certificate *cert) kfree(desc); error: crypto_free_shash(tfm); +out: pr_devel("<=3D=3D%s() =3D %d\n", __func__, ret); return ret; } diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index bd38ba4d217d..4c5199b20338 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -46,6 +46,8 @@ struct public_key_signature { u8 *m; /* Message data to pass to verifier */ u32 s_size; /* Number of bytes in signature */ u32 m_size; /* Number of bytes in ->m */ + bool m_free; /* T if ->m needs freeing */ + bool algo_takes_data; /* T if public key algo operates on data, not a has= h */ const char *pkey_algo; const char *hash_algo; const char *encoding; From nobody Mon Jan 26 22:45:22 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0CEBB22DFB8 for ; Mon, 26 Jan 2026 14:30:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437825; cv=none; b=LXMaEo5pkmzuwL1PHFECisV0RgcThd+NSEK98IyjnNvanAZkuA4IzgeymFQd0XjwSUacuTAolYJk47d/UWHfXkNY1uYJRbg76MqcboHeStPZg1vKRRx0AYl9CRIEbKhivCvoyboAg8//5w3LmKRDGrcLsyIwst7yWfHImeD4wRs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437825; c=relaxed/simple; bh=l/fa67HBV5uX6Gdt7JrduYhxUxeS2/+/0g+TUOR714A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SbZthQemrWXMaGQYhbO/zfaWufQu8Oaz9o+ohcKiPIRN5SBNdXo1qY4ypi0j2QGxUnUM69uBqV9HZ3dAR2OwIjrQuXQyALC49YV36Hj01ce96RGmdUkAyhl2/VYCUexE+mvvORjgH+Ds0hOTxVsKaR2a/+8b2mNwdf5vCdwQvnc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Oht62j4v; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Oht62j4v" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769437823; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RIPQr5EvD0RaYtFXC8NPZPZWU9cXfzbV/hp3jKESUjo=; b=Oht62j4vIdZ7LyhcSsQi0fl5vrsk9TuqVRiOi2RkJAPIZXMDXSej9Kfo8QRTGhljVJZL3K oPlZkoMHAhHBwhowhdC/0PdGI8i6BLf9EFsQzNEJ5hQkvxeT9K9anBE2Mv0Kwk70GPDBXh 1Ey5tAABD4tV0XMOY2hP89yyDeGGyao= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-259-EhNtqsVGOFmx7X9IOM9gKg-1; Mon, 26 Jan 2026 09:30:18 -0500 X-MC-Unique: EhNtqsVGOFmx7X9IOM9gKg-1 X-Mimecast-MFC-AGG-ID: EhNtqsVGOFmx7X9IOM9gKg_1769437815 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 88C0218005BF; Mon, 26 Jan 2026 14:30:15 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.44.33.164]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CAC1819560B2; Mon, 26 Jan 2026 14:30:10 +0000 (UTC) From: David Howells To: Lukas Wunner , Ignat Korchagin Cc: David Howells , Jarkko Sakkinen , Herbert Xu , Eric Biggers , Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , "Jason A . Donenfeld" , Ard Biesheuvel , Stephan Mueller , linux-crypto@vger.kernel.org, keyrings@vger.kernel.org, linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v15 5/7] pkcs7, x509: Add ML-DSA support Date: Mon, 26 Jan 2026 14:29:26 +0000 Message-ID: <20260126142931.1940586-6-dhowells@redhat.com> In-Reply-To: <20260126142931.1940586-1-dhowells@redhat.com> References: <20260126142931.1940586-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" Add support for ML-DSA keys and signatures to the CMS/PKCS#7 and X.509 implementations. ML-DSA-44, -65 and -87 are all supported. For X.509 certificates, the TBSCertificate is required to be signed directly; for CMS, direct signing of the data is preferred, though use of SHA512 (and only tha= t) as an intermediate hash of the content is permitted with signedAttrs. Signed-off-by: David Howells cc: Lukas Wunner cc: Ignat Korchagin cc: Stephan Mueller cc: Eric Biggers cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org --- crypto/asymmetric_keys/pkcs7_parser.c | 24 +++++++++++++++++++- crypto/asymmetric_keys/public_key.c | 10 +++++++++ crypto/asymmetric_keys/x509_cert_parser.c | 27 ++++++++++++++++++++++- include/linux/oid_registry.h | 5 +++++ 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys= /pkcs7_parser.c index 3cdbab3b9f50..594a8f1d9dfb 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -95,11 +95,18 @@ static int pkcs7_check_authattrs(struct pkcs7_message *= msg) if (sinfo->authattrs) { want =3D true; msg->have_authattrs =3D true; + } else if (sinfo->sig->algo_takes_data) { + sinfo->sig->hash_algo =3D "none"; } =20 - for (sinfo =3D sinfo->next; sinfo; sinfo =3D sinfo->next) + for (sinfo =3D sinfo->next; sinfo; sinfo =3D sinfo->next) { if (!!sinfo->authattrs !=3D want) goto inconsistent; + + if (!sinfo->authattrs && + sinfo->sig->algo_takes_data) + sinfo->sig->hash_algo =3D "none"; + } return 0; =20 inconsistent: @@ -297,6 +304,21 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdr= len, ctx->sinfo->sig->pkey_algo =3D "ecrdsa"; ctx->sinfo->sig->encoding =3D "raw"; break; + case OID_id_ml_dsa_44: + ctx->sinfo->sig->pkey_algo =3D "mldsa44"; + ctx->sinfo->sig->encoding =3D "raw"; + ctx->sinfo->sig->algo_takes_data =3D true; + break; + case OID_id_ml_dsa_65: + ctx->sinfo->sig->pkey_algo =3D "mldsa65"; + ctx->sinfo->sig->encoding =3D "raw"; + ctx->sinfo->sig->algo_takes_data =3D true; + break; + case OID_id_ml_dsa_87: + ctx->sinfo->sig->pkey_algo =3D "mldsa87"; + ctx->sinfo->sig->encoding =3D "raw"; + ctx->sinfo->sig->algo_takes_data =3D true; + break; default: printk("Unsupported pkey algo: %u\n", ctx->last_oid); return -ENOPKG; diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/p= ublic_key.c index a46356e0c08b..09a0b83d5d77 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -142,6 +142,16 @@ software_key_determine_akcipher(const struct public_ke= y *pkey, if (strcmp(hash_algo, "streebog256") !=3D 0 && strcmp(hash_algo, "streebog512") !=3D 0) return -EINVAL; + } else if (strcmp(pkey->pkey_algo, "mldsa44") =3D=3D 0 || + strcmp(pkey->pkey_algo, "mldsa65") =3D=3D 0 || + strcmp(pkey->pkey_algo, "mldsa87") =3D=3D 0) { + if (strcmp(encoding, "raw") !=3D 0) + return -EINVAL; + if (!hash_algo) + return -EINVAL; + if (strcmp(hash_algo, "none") !=3D 0 && + strcmp(hash_algo, "sha512") !=3D 0) + return -EINVAL; } else { /* Unknown public key algorithm */ return -ENOPKG; diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_= keys/x509_cert_parser.c index b37cae914987..2fe094f5caf3 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -257,6 +257,15 @@ int x509_note_sig_algo(void *context, size_t hdrlen, u= nsigned char tag, case OID_gost2012Signature512: ctx->cert->sig->hash_algo =3D "streebog512"; goto ecrdsa; + case OID_id_ml_dsa_44: + ctx->cert->sig->pkey_algo =3D "mldsa44"; + goto ml_dsa; + case OID_id_ml_dsa_65: + ctx->cert->sig->pkey_algo =3D "mldsa65"; + goto ml_dsa; + case OID_id_ml_dsa_87: + ctx->cert->sig->pkey_algo =3D "mldsa87"; + goto ml_dsa; } =20 rsa_pkcs1: @@ -274,6 +283,12 @@ int x509_note_sig_algo(void *context, size_t hdrlen, u= nsigned char tag, ctx->cert->sig->encoding =3D "x962"; ctx->sig_algo =3D ctx->last_oid; return 0; +ml_dsa: + ctx->cert->sig->algo_takes_data =3D true; + ctx->cert->sig->hash_algo =3D "none"; + ctx->cert->sig->encoding =3D "raw"; + ctx->sig_algo =3D ctx->last_oid; + return 0; } =20 /* @@ -300,7 +315,8 @@ int x509_note_signature(void *context, size_t hdrlen, =20 if (strcmp(ctx->cert->sig->pkey_algo, "rsa") =3D=3D 0 || strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") =3D=3D 0 || - strcmp(ctx->cert->sig->pkey_algo, "ecdsa") =3D=3D 0) { + strcmp(ctx->cert->sig->pkey_algo, "ecdsa") =3D=3D 0 || + strncmp(ctx->cert->sig->pkey_algo, "mldsa", 5) =3D=3D 0) { /* Discard the BIT STRING metadata */ if (vlen < 1 || *(const u8 *)value !=3D 0) return -EBADMSG; @@ -524,6 +540,15 @@ int x509_extract_key_data(void *context, size_t hdrlen, return -ENOPKG; } break; + case OID_id_ml_dsa_44: + ctx->cert->pub->pkey_algo =3D "mldsa44"; + break; + case OID_id_ml_dsa_65: + ctx->cert->pub->pkey_algo =3D "mldsa65"; + break; + case OID_id_ml_dsa_87: + ctx->cert->pub->pkey_algo =3D "mldsa87"; + break; default: return -ENOPKG; } diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h index 6de479ebbe5d..ebce402854de 100644 --- a/include/linux/oid_registry.h +++ b/include/linux/oid_registry.h @@ -145,6 +145,11 @@ enum OID { OID_id_rsassa_pkcs1_v1_5_with_sha3_384, /* 2.16.840.1.101.3.4.3.15 */ OID_id_rsassa_pkcs1_v1_5_with_sha3_512, /* 2.16.840.1.101.3.4.3.16 */ =20 + /* NIST FIPS-204 ML-DSA */ + OID_id_ml_dsa_44, /* 2.16.840.1.101.3.4.3.17 */ + OID_id_ml_dsa_65, /* 2.16.840.1.101.3.4.3.18 */ + OID_id_ml_dsa_87, /* 2.16.840.1.101.3.4.3.19 */ + OID__NR }; From nobody Mon Jan 26 22:45:22 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 692EF18FDDE for ; Mon, 26 Jan 2026 14:30:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437832; cv=none; b=Kuh7ZCCo8xmzKxyy/uKN91cJOlSBNEuIQmigvJ0gieZ7XDN2E6lFjEb9iE8jLQhnWyVigWdYnVqTcgRvB6oERHEI4g7tHILq/V9VBZA+9Z3CLsSnjohMjkyeu+EAWMsXx9+SZdVoJRe2W0IMrZc8gCGeO864EfHekq8hPTpmbmg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437832; c=relaxed/simple; bh=ZKqV4jdfUAWA5T+vgn8F9FloZgvwNgzM9afWi0tnKSM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WgMaJjGVfLrpBj6pC81VzMWYT9X1HgKgUeyF/OljrKPwOxX3wNVu8OOXmxrC19dop58Web7PEAxlya0bNUkFIenEo5ozIm6tYcalL/FWECtCbS1G869R4DmszfSn2a9pRkMw3aAC59yRzQeMqzb/sYJXe0jPKveGQxOPkOmeVrc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=bRlN/M3I; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="bRlN/M3I" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769437829; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UTvzySqwRBAB/UJpm0FXsBqjnOHhxCKseoxuTP/uJ7A=; b=bRlN/M3IUSKZMu1uODg6cWaCX6NPcS7sV1Xzgr+dsfKdXHwgfNKe7LWo9KBbSqwWSaLnKp dwCVcoi9xWIKL005CTZ+fwNK55b5/w4ZMKcNLcAwpdy6OjOIiD5MX9k3vvaWICLqUZn+pQ yQs60EvXHzt9Crw2VaZBCEYi1W0HMng= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-382-brTXolUjOO-x8Ob9AaXbaQ-1; Mon, 26 Jan 2026 09:30:25 -0500 X-MC-Unique: brTXolUjOO-x8Ob9AaXbaQ-1 X-Mimecast-MFC-AGG-ID: brTXolUjOO-x8Ob9AaXbaQ_1769437822 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 46BBF180034F; Mon, 26 Jan 2026 14:30:22 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.44.33.164]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 81DF730001A8; Mon, 26 Jan 2026 14:30:17 +0000 (UTC) From: David Howells To: Lukas Wunner , Ignat Korchagin Cc: David Howells , Jarkko Sakkinen , Herbert Xu , Eric Biggers , Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , "Jason A . Donenfeld" , Ard Biesheuvel , Stephan Mueller , linux-crypto@vger.kernel.org, keyrings@vger.kernel.org, linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v15 6/7] modsign: Enable ML-DSA module signing Date: Mon, 26 Jan 2026 14:29:27 +0000 Message-ID: <20260126142931.1940586-7-dhowells@redhat.com> In-Reply-To: <20260126142931.1940586-1-dhowells@redhat.com> References: <20260126142931.1940586-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Allow ML-DSA module signing to be enabled. Note that OpenSSL's CMS_*() function suite does not, as of OpenSSL-3.6, support the use of CMS_NOATTR with ML-DSA, so the prohibition against using signedAttrs with module signing has to be removed. The selected digest then applies only to the algorithm used to calculate the digest stored in the messageDigest attribute. The OpenSSL development branch has patches applied that fix this[1], but it appears that that will only be available in OpenSSL-4. [1] https://github.com/openssl/openssl/pull/28923 sign-file won't set CMS_NOATTR if openssl is earlier than v4, resulting in the use of signed attributes. The ML-DSA algorithm takes the raw data to be signed without regard to what digest algorithm is specified in the CMS message. The CMS specified digest algorithm is ignored unless signedAttrs are used; in such a case, only SHA512 is permitted. Signed-off-by: David Howells Reviewed-by: Jarkko Sakkinen cc: Eric Biggers cc: Lukas Wunner cc: Ignat Korchagin cc: Stephan Mueller cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org --- Documentation/admin-guide/module-signing.rst | 16 +++++---- certs/Kconfig | 30 +++++++++++++++++ certs/Makefile | 3 ++ scripts/sign-file.c | 34 +++++++++++++++----- 4 files changed, 68 insertions(+), 15 deletions(-) diff --git a/Documentation/admin-guide/module-signing.rst b/Documentation/a= dmin-guide/module-signing.rst index a8667a777490..7f2f127dc76f 100644 --- a/Documentation/admin-guide/module-signing.rst +++ b/Documentation/admin-guide/module-signing.rst @@ -28,10 +28,12 @@ trusted userspace bits. =20 This facility uses X.509 ITU-T standard certificates to encode the public = keys involved. The signatures are not themselves encoded in any industrial sta= ndard -type. The built-in facility currently only supports the RSA & NIST P-384 = ECDSA -public key signing standard (though it is pluggable and permits others to = be -used). The possible hash algorithms that can be used are SHA-2 and SHA-3 = of -sizes 256, 384, and 512 (the algorithm is selected by data in the signatur= e). +type. The built-in facility currently only supports the RSA, NIST P-384 E= CDSA +and NIST FIPS-204 ML-DSA public key signing standards (though it is plugga= ble +and permits others to be used). For RSA and ECDSA, the possible hash +algorithms that can be used are SHA-2 and SHA-3 of sizes 256, 384, and 512= (the +algorithm is selected by data in the signature); ML-DSA does its own hashi= ng, +but is allowed to be used with a SHA512 hash for signed attributes. =20 =20 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D @@ -146,9 +148,9 @@ into vmlinux) using parameters in the:: =20 file (which is also generated if it does not already exist). =20 -One can select between RSA (``MODULE_SIG_KEY_TYPE_RSA``) and ECDSA -(``MODULE_SIG_KEY_TYPE_ECDSA``) to generate either RSA 4k or NIST -P-384 keypair. +One can select between RSA (``MODULE_SIG_KEY_TYPE_RSA``), ECDSA +(``MODULE_SIG_KEY_TYPE_ECDSA``) and ML-DSA (``MODULE_SIG_KEY_TYPE_MLDSA_*`= `) to +generate an RSA 4k, a NIST P-384 keypair or an ML-DSA 44, 65 or 87 keypair. =20 It is strongly recommended that you provide your own x509.genkey file. =20 diff --git a/certs/Kconfig b/certs/Kconfig index 78307dc25559..2b088ef58373 100644 --- a/certs/Kconfig +++ b/certs/Kconfig @@ -39,6 +39,36 @@ config MODULE_SIG_KEY_TYPE_ECDSA Note: Remove all ECDSA signing keys, e.g. certs/signing_key.pem, when falling back to building Linux 5.14 and older kernels. =20 +config MODULE_SIG_KEY_TYPE_MLDSA_44 + bool "ML-DSA-44" + select CRYPTO_MLDSA + help + Use an ML-DSA-44 key (NIST FIPS 204) for module signing. ML-DSA + support requires OpenSSL-3.5 minimum; preferably OpenSSL-4+. With + the latter, the entire module body will be signed; with the former, + signedAttrs will be used as it lacks support for CMS_NOATTR with + ML-DSA. + +config MODULE_SIG_KEY_TYPE_MLDSA_65 + bool "ML-DSA-65" + select CRYPTO_MLDSA + help + Use an ML-DSA-65 key (NIST FIPS 204) for module signing. ML-DSA + support requires OpenSSL-3.5 minimum; preferably OpenSSL-4+. With + the latter, the entire module body will be signed; with the former, + signedAttrs will be used as it lacks support for CMS_NOATTR with + ML-DSA. + +config MODULE_SIG_KEY_TYPE_MLDSA_87 + bool "ML-DSA-87" + select CRYPTO_MLDSA + help + Use an ML-DSA-87 key (NIST FIPS 204) for module signing. ML-DSA + support requires OpenSSL-3.5 minimum; preferably OpenSSL-4+. With + the latter, the entire module body will be signed; with the former, + signedAttrs will be used as it lacks support for CMS_NOATTR with + ML-DSA. + endchoice =20 config SYSTEM_TRUSTED_KEYRING diff --git a/certs/Makefile b/certs/Makefile index f6fa4d8d75e0..3ee1960f9f4a 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -43,6 +43,9 @@ targets +=3D x509_certificate_list ifeq ($(CONFIG_MODULE_SIG_KEY),certs/signing_key.pem) =20 keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_ECDSA) :=3D -newkey ec -pkeyopt ec_pa= ramgen_curve:secp384r1 +keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_44) :=3D -newkey ml-dsa-44 +keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_65) :=3D -newkey ml-dsa-65 +keytype-$(CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_87) :=3D -newkey ml-dsa-87 =20 quiet_cmd_gen_key =3D GENKEY $@ cmd_gen_key =3D openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_H= ASH) -days 36500 \ diff --git a/scripts/sign-file.c b/scripts/sign-file.c index 7070245edfc1..547b97097230 100644 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -315,18 +315,36 @@ int main(int argc, char **argv) ERR(!digest_algo, "EVP_get_digestbyname"); =20 #ifndef USE_PKCS7 + + unsigned int flags =3D + CMS_NOCERTS | + CMS_PARTIAL | + CMS_BINARY | + CMS_DETACHED | + CMS_STREAM | + CMS_NOSMIMECAP | + CMS_NO_SIGNING_TIME | + use_keyid; + + if ((EVP_PKEY_is_a(private_key, "ML-DSA-44") || + EVP_PKEY_is_a(private_key, "ML-DSA-65") || + EVP_PKEY_is_a(private_key, "ML-DSA-87")) && + OPENSSL_VERSION_MAJOR < 4) { + /* ML-DSA + CMS_NOATTR is not supported in openssl-3.5 + * and before. + */ + use_signed_attrs =3D 0; + } + + flags |=3D use_signed_attrs; + /* Load the signature message from the digest buffer. */ - cms =3D CMS_sign(NULL, NULL, NULL, NULL, - CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | - CMS_DETACHED | CMS_STREAM); + cms =3D CMS_sign(NULL, NULL, NULL, NULL, flags); ERR(!cms, "CMS_sign"); =20 - ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, - CMS_NOCERTS | CMS_BINARY | - CMS_NOSMIMECAP | use_keyid | - use_signed_attrs), + ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, flags), "CMS_add1_signer"); - ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) !=3D 1, + ERR(CMS_final(cms, bm, NULL, flags) !=3D 1, "CMS_final"); =20 #else From nobody Mon Jan 26 22:45:22 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC9FA23A58F for ; Mon, 26 Jan 2026 14:30:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437836; cv=none; b=TpkBgziT6fuLYUN3hFXd5cjdRdf5otvVAiI+2QW3nvjyvdRVj7S5A7qZDzhHJo62unF6IubD7OHnKFtJiEeFcTnTaMTm5rWBXubPzUeevFZVi86Dy7oeuhhiH5BCl/dVBFlmusqmkrPLFsfg/0KYZJ/aXmVaswTY2qIqB996YHI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769437836; c=relaxed/simple; bh=YmYddHPvZEgOqKJmE8MugDptUWnHZHtuSGeVaqPbG3g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=N3KYHraP+lekF0v53YRI1N6mmbg6Xm56ERXsn3bnDPrRK+2z8I3Qm/wMZhOGULBuFKsUBNvJnhASbQUuKjqXNq5R9PbMpmeNFSrIKQk6sOCSAAPIKSDTbnrrBXLdstRIK0Pb7qG5rggfGR3kjmw/Eqk5S0WdoNiivm84SA+VVJ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=hyKe6rGf; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="hyKe6rGf" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1769437833; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RUvLtsQUIbuT8aNyKAbRO6AgrSzDL4SrRGZc9+zngls=; b=hyKe6rGfYpOIqgJ7pfvvhz12DTk29mDXbKWijYAaIIBg7QnA4ZWFgtahuVB3izBG98+DCh UdkEDxrNwrIM5IvSX6d13Hhyv6hrBxaegUAMB0R8126lWfbnY8S8ueW8JKva7FZYVT+ZQS 6c6cncCfLR0wOIc0tCFRdCxWXdUzHts= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-604-MXrR1Hh7NU2KjnMXnBYR3g-1; Mon, 26 Jan 2026 09:30:31 -0500 X-MC-Unique: MXrR1Hh7NU2KjnMXnBYR3g-1 X-Mimecast-MFC-AGG-ID: MXrR1Hh7NU2KjnMXnBYR3g_1769437828 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BE9EE18002E9; Mon, 26 Jan 2026 14:30:28 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.44.33.164]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0DD9F30001A7; Mon, 26 Jan 2026 14:30:23 +0000 (UTC) From: David Howells To: Lukas Wunner , Ignat Korchagin Cc: David Howells , Jarkko Sakkinen , Herbert Xu , Eric Biggers , Luis Chamberlain , Petr Pavlu , Daniel Gomez , Sami Tolvanen , "Jason A . Donenfeld" , Ard Biesheuvel , Stephan Mueller , linux-crypto@vger.kernel.org, keyrings@vger.kernel.org, linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v15 7/7] pkcs7: Allow authenticatedAttributes for ML-DSA Date: Mon, 26 Jan 2026 14:29:28 +0000 Message-ID: <20260126142931.1940586-8-dhowells@redhat.com> In-Reply-To: <20260126142931.1940586-1-dhowells@redhat.com> References: <20260126142931.1940586-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Allow the rejection of authenticatedAttributes in PKCS#7 (signedAttrs in CMS) to be waived in the kernel config for ML-DSA when used for module signing. This reflects the issue that openssl < 4.0 cannot do this and openssl-4 has not yet been released. This does not permit RSA, ECDSA or ECRDSA to be so waived (behaviour unchanged). Signed-off-by: David Howells cc: Lukas Wunner cc: Ignat Korchagin cc: Jarkko Sakkinen cc: Stephan Mueller cc: Eric Biggers cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org --- crypto/asymmetric_keys/Kconfig | 11 +++++++++++ crypto/asymmetric_keys/pkcs7_parser.c | 8 ++++++++ crypto/asymmetric_keys/pkcs7_parser.h | 3 +++ crypto/asymmetric_keys/pkcs7_verify.c | 6 ++++++ 4 files changed, 28 insertions(+) diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index e1345b8f39f1..1dae2232fe9a 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -53,6 +53,17 @@ config PKCS7_MESSAGE_PARSER This option provides support for parsing PKCS#7 format messages for signature data and provides the ability to verify the signature. =20 +config PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA + bool "Waive rejection of authenticatedAttributes for ML-DSA" + depends on PKCS7_MESSAGE_PARSER + depends on CRYPTO_MLDSA + help + Due to use of CMS_NOATTR with ML-DSA not being supported in + OpenSSL < 4.0 (and thus any released version), enabling this + allows authenticatedAttributes to be used with ML-DSA for + module signing. Use of authenticatedAttributes in this + context is normally rejected. + config PKCS7_TEST_KEY tristate "PKCS#7 testing key type" depends on SYSTEM_DATA_VERIFICATION diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys= /pkcs7_parser.c index 594a8f1d9dfb..db1c90ca6fc1 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -92,9 +92,17 @@ static int pkcs7_check_authattrs(struct pkcs7_message *m= sg) if (!sinfo) goto inconsistent; =20 +#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA + msg->authattrs_rej_waivable =3D true; +#endif + if (sinfo->authattrs) { want =3D true; msg->have_authattrs =3D true; +#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA + if (strncmp(sinfo->sig->pkey_algo, "mldsa", 5) !=3D 0) + msg->authattrs_rej_waivable =3D false; +#endif } else if (sinfo->sig->algo_takes_data) { sinfo->sig->hash_algo =3D "none"; } diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys= /pkcs7_parser.h index e17f7ce4fb43..6ef9f335bb17 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.h +++ b/crypto/asymmetric_keys/pkcs7_parser.h @@ -55,6 +55,9 @@ struct pkcs7_message { struct pkcs7_signed_info *signed_infos; u8 version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */ bool have_authattrs; /* T if have authattrs */ +#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA + bool authattrs_rej_waivable; /* T if authatts rejection can be waived */ +#endif =20 /* Content Data (or NULL) */ enum OID data_type; /* Type of Data */ diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys= /pkcs7_verify.c index 06abb9838f95..519eecfe6778 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -425,6 +425,12 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, return -EKEYREJECTED; } if (pkcs7->have_authattrs) { +#ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA + if (pkcs7->authattrs_rej_waivable) { + pr_warn("Waived invalid module sig (has authattrs)\n"); + break; + } +#endif pr_warn("Invalid module sig (has authattrs)\n"); return -EKEYREJECTED; }