* [PATCH 1/2] crypto: pkcs7: add ability to extract signed attributes by OID
2025-11-25 19:02 [PATCH 0/2] pkcs7: better handling of signed attributes James Bottomley
@ 2025-11-25 19:02 ` James Bottomley
2025-11-25 20:39 ` David Howells
2025-11-25 19:02 ` [PATCH 2/2] crypto: pkcs7: add tests for pkcs7_get_authattr James Bottomley
2025-11-26 17:45 ` [PATCH 0/2] pkcs7: better handling of signed attributes James Bottomley
2 siblings, 1 reply; 7+ messages in thread
From: James Bottomley @ 2025-11-25 19:02 UTC (permalink / raw)
To: linux-crypto; +Cc: David Howells, Blaise Boscaccy
Signers may add any information they like in signed attributes and
sometimes this information turns out to be relevant to specific
signing cases, so add an api pkcs7_get_authattr() to extract the value
of an authenticated attribute by specific OID. The current
implementation is designed for the single signer use case and simply
terminates the search when it finds the relevant OID.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
crypto/asymmetric_keys/Makefile | 4 +-
crypto/asymmetric_keys/pkcs7_aa.asn1 | 18 ++++++
crypto/asymmetric_keys/pkcs7_parser.c | 84 +++++++++++++++++++++++++++
include/crypto/pkcs7.h | 4 ++
4 files changed, 109 insertions(+), 1 deletion(-)
create mode 100644 crypto/asymmetric_keys/pkcs7_aa.asn1
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index bc65d3b98dcb..f99b7169ae7c 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -53,12 +53,14 @@ clean-files += pkcs8.asn1.c pkcs8.asn1.h
obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o
pkcs7_message-y := \
pkcs7.asn1.o \
+ pkcs7_aa.asn1.o \
pkcs7_parser.o \
pkcs7_trust.o \
pkcs7_verify.o
-$(obj)/pkcs7_parser.o: $(obj)/pkcs7.asn1.h
+$(obj)/pkcs7_parser.o: $(obj)/pkcs7.asn1.h $(obj)/pkcs7_aa.asn1.h
$(obj)/pkcs7.asn1.o: $(obj)/pkcs7.asn1.c $(obj)/pkcs7.asn1.h
+$(obj)/pkcs7_aa.asn1.o: $(obj)/pkcs7_aa.asn1.c $(obj)/pkcs7_aa.asn1.h
#
# PKCS#7 parser testing key
diff --git a/crypto/asymmetric_keys/pkcs7_aa.asn1 b/crypto/asymmetric_keys/pkcs7_aa.asn1
new file mode 100644
index 000000000000..7a8857bdf56e
--- /dev/null
+++ b/crypto/asymmetric_keys/pkcs7_aa.asn1
@@ -0,0 +1,18 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+--
+-- Copyright (C) 2009 IETF Trust and the persons identified as authors
+-- of the code
+--
+-- https://www.rfc-editor.org/rfc/rfc5652#section-3
+
+AA ::= CHOICE {
+ aaSet [0] IMPLICIT AASet,
+ aaSequence [2] EXPLICIT SEQUENCE OF AuthenticatedAttribute
+}
+
+AASet ::= SET OF AuthenticatedAttribute
+
+AuthenticatedAttribute ::= SEQUENCE {
+ type OBJECT IDENTIFIER ({ pkcs7_aa_note_OID }),
+ values SET OF ANY ({ pkcs7_aa_note_attr })
+}
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 423d13c47545..124963e047c9 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -15,6 +15,7 @@
#include <crypto/public_key.h>
#include "pkcs7_parser.h"
#include "pkcs7.asn1.h"
+#include "pkcs7_aa.asn1.h"
MODULE_DESCRIPTION("PKCS#7 parser");
MODULE_AUTHOR("Red Hat, Inc.");
@@ -197,6 +198,89 @@ int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
}
EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
+struct pkcs7_aa_context {
+ bool found;
+ enum OID oid_to_find;
+ const void *data;
+ size_t len;
+};
+
+int pkcs7_aa_note_OID(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_aa_context *ctx = context;
+ enum OID oid = look_up_OID(value, vlen);
+
+ ctx->found = (oid == ctx->oid_to_find);
+
+ return 0;
+}
+
+int pkcs7_aa_note_attr(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs7_aa_context *ctx = context;
+
+ if (ctx->found) {
+ ctx->data = value;
+ ctx->len = vlen;
+ }
+
+ return 0;
+}
+
+/**
+ * pkcs7_get_authattr - get authenticated attribute by OID
+ *
+ * @pkcs7: The preparsed PKCS#7 message
+ * @oid: the enum value of the OID to find
+ * @_data: Place to return a pointer to the attribute value
+ * @_len: length of the attribute value
+ *
+ * Searches the authenticated attributes until one is found with a
+ * matching OID. Note that because the attributes are per signer
+ * there could be multiple signers with different values, but this
+ * routine will simply return the first one in parse order.
+ *
+ * Returns -ENODATA if the attribute can't be found
+ */
+int pkcs7_get_authattr(const struct pkcs7_message *pkcs7,
+ enum OID oid,
+ const void **_data, size_t *_len)
+{
+ struct pkcs7_signed_info *sinfo = pkcs7->signed_infos;
+ struct pkcs7_aa_context ctx;
+
+ ctx.data = NULL;
+ ctx.oid_to_find = oid;
+
+ for (; sinfo; sinfo = sinfo->next) {
+ int ret;
+
+ /*
+ * Note: authattrs is missing the initial tag for
+ * digesting reasons. Step one back in the stream to
+ * point to the initial tag for fully formed ASN.1
+ */
+ ret = asn1_ber_decoder(&pkcs7_aa_decoder, &ctx,
+ sinfo->authattrs - 1,
+ sinfo->authattrs_len + 1);
+ if (ret < 0 || ctx.data != NULL)
+ break;
+ }
+
+ if (!ctx.data)
+ return -ENODATA;
+
+ *_data = ctx.data;
+ *_len = ctx.len;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pkcs7_get_authattr);
+
/*
* Note an OID when we find one for later processing when we know how
* to interpret it.
diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
index 38ec7f5f9041..bd83202cd805 100644
--- a/include/crypto/pkcs7.h
+++ b/include/crypto/pkcs7.h
@@ -25,6 +25,10 @@ extern void pkcs7_free_message(struct pkcs7_message *pkcs7);
extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
const void **_data, size_t *_datalen,
size_t *_headerlen);
+extern int pkcs7_get_authattr(const struct pkcs7_message *pkcs7,
+ enum OID oid,
+ const void **_data, size_t *_len);
+
/*
* pkcs7_trust.c
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 1/2] crypto: pkcs7: add ability to extract signed attributes by OID
2025-11-25 19:02 ` [PATCH 1/2] crypto: pkcs7: add ability to extract signed attributes by OID James Bottomley
@ 2025-11-25 20:39 ` David Howells
2025-11-25 22:18 ` James Bottomley
0 siblings, 1 reply; 7+ messages in thread
From: David Howells @ 2025-11-25 20:39 UTC (permalink / raw)
To: James Bottomley; +Cc: dhowells, linux-crypto, Blaise Boscaccy
James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> +/**
> + * pkcs7_get_authattr - get authenticated attribute by OID
> + *
> + * @pkcs7: The preparsed PKCS#7 message
There shouldn't be a gap between those.
> + /*
> + * Note: authattrs is missing the initial tag for
> + * digesting reasons. Step one back in the stream to
> + * point to the initial tag for fully formed ASN.1
> + */
That will probably have to change to support ML-DSA.
David
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] crypto: pkcs7: add ability to extract signed attributes by OID
2025-11-25 20:39 ` David Howells
@ 2025-11-25 22:18 ` James Bottomley
0 siblings, 0 replies; 7+ messages in thread
From: James Bottomley @ 2025-11-25 22:18 UTC (permalink / raw)
To: David Howells; +Cc: linux-crypto, Blaise Boscaccy
On Tue, 2025-11-25 at 20:39 +0000, David Howells wrote:
> James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> > +/**
> > + * pkcs7_get_authattr - get authenticated attribute by OID
> > + *
> > + * @pkcs7: The preparsed PKCS#7 message
>
> There shouldn't be a gap between those.
OK, removed.
>
> > + /*
> > + * Note: authattrs is missing the initial tag for
> > + * digesting reasons. Step one back in the stream
> > to
> > + * point to the initial tag for fully formed ASN.1
> > + */
>
> That will probably have to change to support ML-DSA.
Well it doesn't exactly work for [2] EXPLICIT ... either; however the
kernel pkcs7 parser itself doesn't seem to cope correctly with that so
I thought there wasn't much point fixing it given all crypto systems
seem to go with the set choice.
Regards,
James
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] crypto: pkcs7: add tests for pkcs7_get_authattr
2025-11-25 19:02 [PATCH 0/2] pkcs7: better handling of signed attributes James Bottomley
2025-11-25 19:02 ` [PATCH 1/2] crypto: pkcs7: add ability to extract signed attributes by OID James Bottomley
@ 2025-11-25 19:02 ` James Bottomley
2025-11-25 20:41 ` David Howells
2025-11-26 17:45 ` [PATCH 0/2] pkcs7: better handling of signed attributes James Bottomley
2 siblings, 1 reply; 7+ messages in thread
From: James Bottomley @ 2025-11-25 19:02 UTC (permalink / raw)
To: linux-crypto; +Cc: David Howells, Blaise Boscaccy
Add example code to the test module pkcs7_key_type.c that verifies a
message and then pulls out a known authenticated attribute.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
I'm not convinced this needs adding, but it provided a convenient
mechanism for testing the pcks7_get_authattr() call so I added it in
case others find it useful.
---
crypto/asymmetric_keys/pkcs7_key_type.c | 27 ++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c
index b930d3bbf1af..d67bf1dc96b9 100644
--- a/crypto/asymmetric_keys/pkcs7_key_type.c
+++ b/crypto/asymmetric_keys/pkcs7_key_type.c
@@ -12,6 +12,7 @@
#include <linux/verification.h>
#include <linux/key-type.h>
#include <keys/user-type.h>
+#include <crypto/pkcs7.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PKCS#7 testing key type");
@@ -51,16 +52,40 @@ static int pkcs7_view_content(void *ctx, const void *data, size_t len,
static int pkcs7_preparse(struct key_preparsed_payload *prep)
{
enum key_being_used_for usage = pkcs7_usage;
+ int ret;
+ struct pkcs7_message *pkcs7;
+ const void *data;
+ size_t len;
if (usage >= NR__KEY_BEING_USED_FOR) {
pr_err("Invalid usage type %d\n", usage);
return -EINVAL;
}
- return verify_pkcs7_signature(NULL, 0,
+ ret = verify_pkcs7_signature(NULL, 0,
prep->data, prep->datalen,
VERIFY_USE_SECONDARY_KEYRING, usage,
pkcs7_view_content, prep);
+ if (ret)
+ return ret;
+
+ pkcs7 = pkcs7_parse_message(prep->data, prep->datalen);
+ if (IS_ERR(pkcs7)) {
+ pr_err("pkcs7 parse error\n");
+ return PTR_ERR(pkcs7);
+ }
+
+ ret = pkcs7_get_authattr(pkcs7, OID_messageDigest, &data, &len);
+ if (ret) {
+ pr_err("Failed to get message digest\n");
+ goto out;
+ }
+
+ pr_info("Correctly Got message hash, size=%ld\n", len);
+
+ out:
+ pkcs7_free_message(pkcs7);
+ return 0;
}
/*
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 0/2] pkcs7: better handling of signed attributes
2025-11-25 19:02 [PATCH 0/2] pkcs7: better handling of signed attributes James Bottomley
2025-11-25 19:02 ` [PATCH 1/2] crypto: pkcs7: add ability to extract signed attributes by OID James Bottomley
2025-11-25 19:02 ` [PATCH 2/2] crypto: pkcs7: add tests for pkcs7_get_authattr James Bottomley
@ 2025-11-26 17:45 ` James Bottomley
2 siblings, 0 replies; 7+ messages in thread
From: James Bottomley @ 2025-11-26 17:45 UTC (permalink / raw)
To: linux-crypto; +Cc: David Howells, Blaise Boscaccy
On Tue, 2025-11-25 at 14:02 -0500, James Bottomley wrote:
> Although the biggest use of signed attributes is PKCS#7 and X509
> specific data, they can be added to a signature to support arbitrary
> and verifiable objects. This makes them particularly useful when you
> want to take an existing signature scheme and extend it with
> additional (but always verified) data in such a way that it still
> looks valid to both the old and new schemes.
There's a security problem in the patches in that if we're using the
attribute for additional security, we must also verify it comes from a
trusted signature. The potential attack vector is that an attacker
could take a validly signed pkcs7 and add their own signer info to it
(which would validate but not back to a trusted key). If they
manipulate the pkcs7 so this appears first, we'd pull the trusted
attribute the attacker has supplied, since we return after finding the
first matching OID. To fix this, I'm going to add a bool sinfo-
>verified argument which is set when the sinfo is verified against a
kering and only trust sinfos in the attribute search if this tag is
true.
For the case where we only parse then get the OID (without a validation
step, because the pkcs7 was previously validated but the pkcs7 object
was lost), I'm going to add a new validate_pkcs7_trust() call that
allows setting the sinfo->verified flag based on the trusted keyring
... and thread this through system_keyring.c to avoid leaking the
trusted keyrings.
I'll post the v2 with all the new patches to do the above shortly.
Regards,
James
^ permalink raw reply [flat|nested] 7+ messages in thread