2022-01-14 14:37:47

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 0/4] KEYS: x509: various cleanups

This series cleans up a few things in the X.509 certificate parser.

Eric Biggers (4):
KEYS: x509: clearly distinguish between key and signature algorithms
KEYS: x509: remove unused fields
KEYS: x509: remove never-set ->unsupported_key flag
KEYS: x509: remove dead code that set ->unsupported_sig

crypto/asymmetric_keys/pkcs7_verify.c | 3 --
crypto/asymmetric_keys/x509.asn1 | 2 +-
crypto/asymmetric_keys/x509_cert_parser.c | 34 ++++++++++++-----------
crypto/asymmetric_keys/x509_parser.h | 1 -
crypto/asymmetric_keys/x509_public_key.c | 18 ------------
5 files changed, 19 insertions(+), 39 deletions(-)


base-commit: feb7a43de5ef625ad74097d8fd3481d5dbc06a59
--
2.34.1


2022-01-14 14:37:49

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 3/4] KEYS: x509: remove never-set ->unsupported_key flag

From: Eric Biggers <[email protected]>

The X.509 parser always sets cert->pub->pkey_algo on success, since
x509_extract_key_data() is a mandatory action in the X.509 ASN.1
grammar, and it returns an error if the algorithm is unknown. Thus,
remove the dead code which handled this field being NULL. This results
in the ->unsupported_key flag never being set, so remove that too.

Signed-off-by: Eric Biggers <[email protected]>
---
crypto/asymmetric_keys/pkcs7_verify.c | 3 ---
crypto/asymmetric_keys/x509_parser.h | 1 -
crypto/asymmetric_keys/x509_public_key.c | 9 ---------
3 files changed, 13 deletions(-)

diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 0b4d07aa8811..4ba81be3cd77 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -226,9 +226,6 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
return 0;
}

- if (x509->unsupported_key)
- goto unsupported_crypto_in_x509;
-
pr_debug("- issuer %s\n", x509->issuer);
sig = x509->sig;
if (sig->auth_ids[0])
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index c233f136fb35..da854c94f111 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -36,7 +36,6 @@ struct x509_certificate {
bool seen; /* Infinite recursion prevention */
bool verified;
bool self_signed; /* T if self-signed (check unsupported_sig too) */
- bool unsupported_key; /* T if key uses unsupported crypto */
bool unsupported_sig; /* T if signature uses unsupported crypto */
bool blacklisted;
};
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index fe14cae115b5..b03d04d78eb9 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -33,9 +33,6 @@ int x509_get_sig_params(struct x509_certificate *cert)
sig->data = cert->tbs;
sig->data_size = cert->tbs_size;

- if (!cert->pub->pkey_algo)
- cert->unsupported_key = true;
-
if (!sig->pkey_algo)
cert->unsupported_sig = true;

@@ -173,12 +170,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)

pr_devel("Cert Issuer: %s\n", cert->issuer);
pr_devel("Cert Subject: %s\n", cert->subject);
-
- if (cert->unsupported_key) {
- ret = -ENOPKG;
- goto error_free_cert;
- }
-
pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);

--
2.34.1

2022-01-14 14:37:49

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 2/4] KEYS: x509: remove unused fields

From: Eric Biggers <[email protected]>

Remove unused fields from struct x509_parse_context.

Signed-off-by: Eric Biggers <[email protected]>
---
crypto/asymmetric_keys/x509_cert_parser.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index aec2396a7f7e..2899ed80bb18 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -19,7 +19,6 @@
struct x509_parse_context {
struct x509_certificate *cert; /* Certificate being constructed */
unsigned long data; /* Start of data */
- const void *cert_start; /* Start of cert content */
const void *key; /* Key data */
size_t key_size; /* Size of key data */
const void *params; /* Key parameters */
@@ -27,7 +26,6 @@ struct x509_parse_context {
enum OID key_algo; /* Algorithm used by the cert's key */
enum OID last_oid; /* Last OID encountered */
enum OID sig_algo; /* Algorithm used to sign the cert */
- unsigned char nr_mpi; /* Number of MPIs stored */
u8 o_size; /* Size of organizationName (O) */
u8 cn_size; /* Size of commonName (CN) */
u8 email_size; /* Size of emailAddress */
--
2.34.1

2022-01-14 14:37:49

by Eric Biggers

[permalink] [raw]
Subject: [PATCH 1/4] KEYS: x509: clearly distinguish between key and signature algorithms

From: Eric Biggers <[email protected]>

An X.509 certificate has two, potentially different public key
algorithms: the one used by the certificate's key, and the one that was
used to sign the certificate. Some of the naming made it unclear which
algorithm was meant. Rename things appropriately:

- x509_note_pkey_algo() => x509_note_sig_algo()
- algo_oid => sig_algo

Signed-off-by: Eric Biggers <[email protected]>
---
crypto/asymmetric_keys/x509.asn1 | 2 +-
crypto/asymmetric_keys/x509_cert_parser.c | 32 +++++++++++++----------
2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1
index 5c9f4e4a5231..92d59c32f96a 100644
--- a/crypto/asymmetric_keys/x509.asn1
+++ b/crypto/asymmetric_keys/x509.asn1
@@ -7,7 +7,7 @@ Certificate ::= SEQUENCE {
TBSCertificate ::= SEQUENCE {
version [ 0 ] Version DEFAULT,
serialNumber CertificateSerialNumber ({ x509_note_serial }),
- signature AlgorithmIdentifier ({ x509_note_pkey_algo }),
+ signature AlgorithmIdentifier ({ x509_note_sig_algo }),
issuer Name ({ x509_note_issuer }),
validity Validity,
subject Name ({ x509_note_subject }),
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 083405eb80c3..aec2396a7f7e 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -24,9 +24,9 @@ struct x509_parse_context {
size_t key_size; /* Size of key data */
const void *params; /* Key parameters */
size_t params_size; /* Size of key parameters */
- enum OID key_algo; /* Public key algorithm */
+ enum OID key_algo; /* Algorithm used by the cert's key */
enum OID last_oid; /* Last OID encountered */
- enum OID algo_oid; /* Algorithm OID */
+ enum OID sig_algo; /* Algorithm used to sign the cert */
unsigned char nr_mpi; /* Number of MPIs stored */
u8 o_size; /* Size of organizationName (O) */
u8 cn_size; /* Size of commonName (CN) */
@@ -187,11 +187,10 @@ int x509_note_tbs_certificate(void *context, size_t hdrlen,
}

/*
- * Record the public key algorithm
+ * Record the algorithm that was used to sign this certificate.
*/
-int x509_note_pkey_algo(void *context, size_t hdrlen,
- unsigned char tag,
- const void *value, size_t vlen)
+int x509_note_sig_algo(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
{
struct x509_parse_context *ctx = context;

@@ -263,22 +262,22 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
rsa_pkcs1:
ctx->cert->sig->pkey_algo = "rsa";
ctx->cert->sig->encoding = "pkcs1";
- ctx->algo_oid = ctx->last_oid;
+ ctx->sig_algo = ctx->last_oid;
return 0;
ecrdsa:
ctx->cert->sig->pkey_algo = "ecrdsa";
ctx->cert->sig->encoding = "raw";
- ctx->algo_oid = ctx->last_oid;
+ ctx->sig_algo = ctx->last_oid;
return 0;
sm2:
ctx->cert->sig->pkey_algo = "sm2";
ctx->cert->sig->encoding = "raw";
- ctx->algo_oid = ctx->last_oid;
+ ctx->sig_algo = ctx->last_oid;
return 0;
ecdsa:
ctx->cert->sig->pkey_algo = "ecdsa";
ctx->cert->sig->encoding = "x962";
- ctx->algo_oid = ctx->last_oid;
+ ctx->sig_algo = ctx->last_oid;
return 0;
}

@@ -291,11 +290,16 @@ int x509_note_signature(void *context, size_t hdrlen,
{
struct x509_parse_context *ctx = context;

- pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen);
+ pr_debug("Signature: alg=%u, size=%zu\n", ctx->last_oid, vlen);

- if (ctx->last_oid != ctx->algo_oid) {
- pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n",
- ctx->algo_oid, ctx->last_oid);
+ /*
+ * In X.509 certificates, the signature's algorithm is stored in two
+ * places: inside the TBSCertificate (the data that is signed), and
+ * alongside the signature. These *must* match.
+ */
+ if (ctx->last_oid != ctx->sig_algo) {
+ pr_warn("signatureAlgorithm (%u) differs from tbsCertificate.signature (%u)\n",
+ ctx->last_oid, ctx->sig_algo);
return -EINVAL;
}

--
2.34.1

2022-01-16 16:22:26

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH 3/4] KEYS: x509: remove never-set ->unsupported_key flag

On Thu, Jan 13, 2022 at 04:29:19PM -0800, Eric Biggers wrote:
> From: Eric Biggers <[email protected]>
>
> The X.509 parser always sets cert->pub->pkey_algo on success, since
> x509_extract_key_data() is a mandatory action in the X.509 ASN.1
> grammar, and it returns an error if the algorithm is unknown. Thus,
> remove the dead code which handled this field being NULL. This results
> in the ->unsupported_key flag never being set, so remove that too.
>
> Signed-off-by: Eric Biggers <[email protected]>
> ---
> crypto/asymmetric_keys/pkcs7_verify.c | 3 ---
> crypto/asymmetric_keys/x509_parser.h | 1 -
> crypto/asymmetric_keys/x509_public_key.c | 9 ---------
> 3 files changed, 13 deletions(-)
>
> diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
> index 0b4d07aa8811..4ba81be3cd77 100644
> --- a/crypto/asymmetric_keys/pkcs7_verify.c
> +++ b/crypto/asymmetric_keys/pkcs7_verify.c
> @@ -226,9 +226,6 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
> return 0;
> }
>
> - if (x509->unsupported_key)
> - goto unsupported_crypto_in_x509;

Just a minor nit.

You see now there is only this statement left with a ref to that
label:

/* If there's no authority certificate specified, then
* the certificate must be self-signed and is the root
* of the chain. Likewise if the cert is its own
* authority.
*/
if (x509->unsupported_sig)
goto unsupported_crypto_in_x509;

I'd suggest to rename this as unsupported_sig_in_x509.

> -
> pr_debug("- issuer %s\n", x509->issuer);
> sig = x509->sig;
> if (sig->auth_ids[0])
> diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
> index c233f136fb35..da854c94f111 100644
> --- a/crypto/asymmetric_keys/x509_parser.h
> +++ b/crypto/asymmetric_keys/x509_parser.h
> @@ -36,7 +36,6 @@ struct x509_certificate {
> bool seen; /* Infinite recursion prevention */
> bool verified;
> bool self_signed; /* T if self-signed (check unsupported_sig too) */
> - bool unsupported_key; /* T if key uses unsupported crypto */
> bool unsupported_sig; /* T if signature uses unsupported crypto */
> bool blacklisted;
> };
> diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
> index fe14cae115b5..b03d04d78eb9 100644
> --- a/crypto/asymmetric_keys/x509_public_key.c
> +++ b/crypto/asymmetric_keys/x509_public_key.c
> @@ -33,9 +33,6 @@ int x509_get_sig_params(struct x509_certificate *cert)
> sig->data = cert->tbs;
> sig->data_size = cert->tbs_size;
>
> - if (!cert->pub->pkey_algo)
> - cert->unsupported_key = true;
> -
> if (!sig->pkey_algo)
> cert->unsupported_sig = true;
>
> @@ -173,12 +170,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
>
> pr_devel("Cert Issuer: %s\n", cert->issuer);
> pr_devel("Cert Subject: %s\n", cert->subject);
> -
> - if (cert->unsupported_key) {
> - ret = -ENOPKG;
> - goto error_free_cert;
> - }
> -
> pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
> pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
>
> --
> 2.34.1
>

/Jarkko

2022-01-16 16:22:27

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH 1/4] KEYS: x509: clearly distinguish between key and signature algorithms

On Thu, Jan 13, 2022 at 04:29:17PM -0800, Eric Biggers wrote:
> From: Eric Biggers <[email protected]>
>
> An X.509 certificate has two, potentially different public key
> algorithms: the one used by the certificate's key, and the one that was
> used to sign the certificate. Some of the naming made it unclear which
> algorithm was meant. Rename things appropriately:
>
> - x509_note_pkey_algo() => x509_note_sig_algo()
> - algo_oid => sig_algo
>
> Signed-off-by: Eric Biggers <[email protected]>

Acked-by: Jarkko Sakkinen <[email protected]>

BR, Jarkko

2022-01-16 16:22:30

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH 2/4] KEYS: x509: remove unused fields

On Thu, Jan 13, 2022 at 04:29:18PM -0800, Eric Biggers wrote:
> From: Eric Biggers <[email protected]>
>
> Remove unused fields from struct x509_parse_context.
>
> Signed-off-by: Eric Biggers <[email protected]>

Acked-by: Jarkko Sakkinen <[email protected]>

/Jarkko