lkml.org 
[lkml]   [2021]   [Feb]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v8 3/4] x509: Add support for parsing x509 certs with ECDSA keys
Date
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.

Cc: David Howells <dhowells@redhat.com>
Cc: keyrings@vger.kernel.org
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>

---

v7->v8:
- do not detect key algo using parse_OID() in public_key.c but set
pkey_algo to the key type 'ecdsa-nist-p192/256' when parsing cert
---
crypto/asymmetric_keys/public_key.c | 4 ++-
crypto/asymmetric_keys/x509_cert_parser.c | 34 ++++++++++++++++++++++-
crypto/asymmetric_keys/x509_public_key.c | 4 ++-
include/linux/oid_registry.h | 2 ++
4 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 788a4ba1e2e7..4fefb219bfdc 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>
@@ -85,7 +86,8 @@ int software_key_determine_akcipher(const char *encoding,
return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
}

- if (strcmp(encoding, "raw") == 0) {
+ if (strcmp(encoding, "raw") == 0 ||
+ strcmp(encoding, "x962") == 0) {
strcpy(alg_name, pkey->pkey_algo);
return 0;
}
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 1621ceaf5c95..f5d547c6dfb5 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,12 @@ int x509_extract_key_data(void *context, size_t hdrlen,
case OID_sm2:
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-nist-p256";
+ break;
default:
return -ENOPKG;
}
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index ae450eb8be14..3d45161b271a 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -129,7 +129,9 @@ int x509_check_for_self_signed(struct x509_certificate *cert)
}

ret = -EKEYREJECTED;
- if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
+ if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0 &&
+ (strncmp(cert->pub->pkey_algo, "ecdsa-", 6) != 0 ||
+ strcmp(cert->sig->pkey_algo, "ecdsa") != 0))
goto out;

ret = public_key_verify_signature(cert->pub, cert->sig);
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
\
 
 \ /
  Last update: 2021-02-15 18:26    [W:0.118 / U:0.196 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site