2021-02-01 15:25:14

by Stefan Berger

[permalink] [raw]
Subject: [PATCH v7 3/4] x509: Add support for parsing x509 certs with ECDSA keys

This patch adds support for parsing of x509 certificates that contain
ECDSA keys, such as NIST P256, that have been signed by a CA using any
of the current SHA hash algorithms.

Signed-off-by: Stefan Berger <[email protected]>
Cc: David Howells <[email protected]>
Cc: [email protected]
---
crypto/asymmetric_keys/public_key.c | 19 ++++++++++++++
crypto/asymmetric_keys/x509_cert_parser.c | 32 ++++++++++++++++++++++-
include/linux/oid_registry.h | 2 ++
3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 8892908ad58c..7dae61b79d5a 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/scatterlist.h>
+#include <linux/asn1.h>
#include <keys/asymmetric-subtype.h>
#include <crypto/public_key.h>
#include <crypto/akcipher.h>
@@ -90,6 +91,24 @@ int software_key_determine_akcipher(const char *encoding,
return 0;
}

+ if (strcmp(encoding, "x962") == 0) {
+ enum OID oid;
+
+ if (parse_OID(pkey->params, pkey->paramlen, &oid) != 0)
+ return -EBADMSG;
+
+ switch (oid) {
+ case OID_id_prime192v1:
+ strcpy(alg_name, "ecdsa-nist-p192");
+ return 0;
+ case OID_id_prime256v1:
+ strcpy(alg_name, "ecdsa-nist-p256");
+ return 0;
+ default:
+ return -EINVAL;
+ }
+ }
+
return -ENOPKG;
}

diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 1621ceaf5c95..0aff4e584b11 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -227,6 +227,26 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
ctx->cert->sig->hash_algo = "sha224";
goto rsa_pkcs1;

+ case OID_id_ecdsa_with_sha1:
+ ctx->cert->sig->hash_algo = "sha1";
+ goto ecdsa;
+
+ case OID_id_ecdsa_with_sha224:
+ ctx->cert->sig->hash_algo = "sha224";
+ goto ecdsa;
+
+ case OID_id_ecdsa_with_sha256:
+ ctx->cert->sig->hash_algo = "sha256";
+ goto ecdsa;
+
+ case OID_id_ecdsa_with_sha384:
+ ctx->cert->sig->hash_algo = "sha384";
+ goto ecdsa;
+
+ case OID_id_ecdsa_with_sha512:
+ ctx->cert->sig->hash_algo = "sha512";
+ goto ecdsa;
+
case OID_gost2012Signature256:
ctx->cert->sig->hash_algo = "streebog256";
goto ecrdsa;
@@ -255,6 +275,11 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
ctx->cert->sig->encoding = "raw";
ctx->algo_oid = ctx->last_oid;
return 0;
+ecdsa:
+ ctx->cert->sig->pkey_algo = "ecdsa";
+ ctx->cert->sig->encoding = "x962";
+ ctx->algo_oid = ctx->last_oid;
+ return 0;
}

/*
@@ -276,7 +301,8 @@ int x509_note_signature(void *context, size_t hdrlen,

if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 ||
strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0 ||
- strcmp(ctx->cert->sig->pkey_algo, "sm2") == 0) {
+ strcmp(ctx->cert->sig->pkey_algo, "sm2") == 0 ||
+ strcmp(ctx->cert->sig->pkey_algo, "ecdsa") == 0) {
/* Discard the BIT STRING metadata */
if (vlen < 1 || *(const u8 *)value != 0)
return -EBADMSG;
@@ -478,6 +504,10 @@ int x509_extract_key_data(void *context, size_t hdrlen,
case OID_sm2:
ctx->cert->pub->pkey_algo = "sm2";
break;
+ case OID_id_prime192v1:
+ case OID_id_prime256v1:
+ ctx->cert->pub->pkey_algo = "ecdsa";
+ break;
default:
return -ENOPKG;
}
diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
index f3b2c097c886..ff3cad9f8c1f 100644
--- a/include/linux/oid_registry.h
+++ b/include/linux/oid_registry.h
@@ -21,6 +21,8 @@ enum OID {
OID_id_dsa, /* 1.2.840.10040.4.1 */
OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */
OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */
+ OID_id_prime192v1, /* 1.2.840.10045.3.1.1 */
+ OID_id_prime256v1, /* 1.2.840.10045.3.1.7 */
OID_id_ecdsa_with_sha224, /* 1.2.840.10045.4.3.1 */
OID_id_ecdsa_with_sha256, /* 1.2.840.10045.4.3.2 */
OID_id_ecdsa_with_sha384, /* 1.2.840.10045.4.3.3 */
--
2.29.2


2021-02-11 17:34:57

by Stefan Berger

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] x509: Add support for parsing x509 certs with ECDSA keys

On 2/11/21 3:03 AM, kernel test robot wrote:
> Hi Stefan,
>
> Thank you for the patch! Yet something to improve:
>
>>> crypto/asymmetric_keys/public_key.c:97: undefined reference to `parse_OID'


So the issue is that? only ASYMMETRIC_PUBLIC_KEY_SUBTYPE is selected in
this config and the selection of OID_REGISTRY is missing. I am not sure
whether ASYMMETRIC_PUBLIC_KEY_SUBTYPE should/could select OID_REGISTRY
or whether that would be wrong... ?


??? Stefan

2021-02-11 18:22:54

by Stefan Berger

[permalink] [raw]
Subject: Re: [PATCH v7 3/4] x509: Add support for parsing x509 certs with ECDSA keys

On 2/11/21 12:30 PM, Stefan Berger wrote:
> On 2/11/21 3:03 AM, kernel test robot wrote:
>> Hi Stefan,
>>
>> Thank you for the patch! Yet something to improve:
>>
>>>> crypto/asymmetric_keys/public_key.c:97: undefined reference to
>>>> `parse_OID'
>
>
> So the issue is that? only ASYMMETRIC_PUBLIC_KEY_SUBTYPE is selected
> in this config and the selection of OID_REGISTRY is missing. I am not
> sure whether ASYMMETRIC_PUBLIC_KEY_SUBTYPE should/could select
> OID_REGISTRY or whether that would be wrong... ?


David,

? if the above is not desired then the following change would let us
get rid of the offending parse_OID(). The below change is only for NIST
p192 in this experiment but shows that we need to add additional
strcmp() cases in x509_check_for_self_signed() since
cert->sig->pkey_algo is set to "ecdsa". I am not sure whether we should
derive from the signature which curve was used to create the signature
so that cert->sig->pkey_algo could be more specific and the simple
existing strcmp() would pass. So two possible ways to go forward. Which
way should we go?

?? Stefan


diff --git a/crypto/asymmetric_keys/x509_cert_parser.c
b/crypto/asymmetric_keys/x509_cert_parser.c
index 0aff4e584b11..71d83bb345c4 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -505,6 +505,8 @@ int x509_extract_key_data(void *context, size_t hdrlen,
??????????????????????? ctx->cert->pub->pkey_algo = "sm2";
??????????????????????? break;
??????????????? case OID_id_prime192v1:
+?????????????????????? ctx->cert->pub->pkey_algo = "ecdsa-nist-p192";
+?????????????????????? break;
??????????????? case OID_id_prime256v1:
??????????????????????? ctx->cert->pub->pkey_algo = "ecdsa";
??????????????????????? break;
diff --git a/crypto/asymmetric_keys/x509_public_key.c
b/crypto/asymmetric_keys/x509_public_key.c
index ae450eb8be14..3ebeed195b61 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -129,7 +129,10 @@ int x509_check_for_self_signed(struct
x509_certificate *cert)
??????? }

??????? ret = -EKEYREJECTED;
-?????? if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
+printk(KERN_INFO "%s: %s ==? %s\n", __func__, cert->pub->pkey_algo,
cert->sig->pkey_algo);
+?????? if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0 &&
+?????????? strncmp(cert->pub->pkey_algo, "ecdsa-nist-p", 12) != 0 &&
+?????????? strcmp(cert->sig->pkey_algo, "ecdsa") != 0)
??????????????? goto out;

??????? ret = public_key_verify_signature(cert->pub, cert->sig);


>
>
> ??? Stefan
>