[PATCH 1/5] x509: add support for rsa-pss

Hongbo Li
2021-04-06T13:12:24Z

This patch make x509 support rsa-pss, because the sha algo is
in signature, so we need to parse the sha parameter, and skip
other params.

Signed-off-by: Hongbo Li <herberthbli@tencent.com>
---
crypto/asymmetric_keys/Makefile | 7 ++-
crypto/asymmetric_keys/public_key.c | 5 +++
crypto/asymmetric_keys/x509_cert_parser.c | 71 +++++++++++++++++++++++++++++--
include/linux/oid_registry.h | 2 +
4 files changed, 80 insertions(+), 5 deletions(-)

diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index 28b91ad..9092de7 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -20,15 +20,20 @@ obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
x509_key_parser-y := \
x509.asn1.o \
x509_akid.asn1.o \
+ x509_rsapss_params.asn1.o \
x509_cert_parser.o \
x509_public_key.o

$(obj)/x509_cert_parser.o: \
$(obj)/x509.asn1.h \
- $(obj)/x509_akid.asn1.h
+ $(obj)/x509_akid.asn1.h \
+ $(obj)/x509_rsapss_params.asn1.h
+

$(obj)/x509.asn1.o: $(obj)/x509.asn1.c $(obj)/x509.asn1.h
$(obj)/x509_akid.asn1.o: $(obj)/x509_akid.asn1.c $(obj)/x509_akid.asn1.h
+$(obj)/x509_rsapss_params.asn1.o: \
+ $(obj)/x509_rsapss_params.asn1.c $(obj)/x509_rsapss_params.asn1.h

#
# PKCS#8 private key handling
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 788a4ba..cf049fd 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -83,6 +83,11 @@ int software_key_determine_akcipher(const char *encoding,
"pkcs1pad(%s,%s)",
pkey->pkey_algo, hash_algo);
return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
+ } else if (strcmp(encoding, "pss") == 0) {
+ n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
+ "psspad(%s)",
+ pkey->pkey_algo);
+ return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
}

if (strcmp(encoding, "raw") == 0) {
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 52c9b45..ec3428d 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -15,6 +15,7 @@
#include "x509_parser.h"
#include "x509.asn1.h"
#include "x509_akid.asn1.h"
+#include "x509_rsapss_params.asn1.h"

struct x509_parse_context {
struct x509_certificate *cert; /* Certificate being constructed */
@@ -115,6 +116,17 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
cert->pub->paramlen = ctx->params_size;
cert->pub->algo = ctx->key_algo;

+ if (!strcmp(cert->sig->pkey_algo, "rsa") &&
+ !strcmp(cert->sig->encoding, "pss") &&
+ cert->pub->paramlen) {
+ ret = asn1_ber_decoder(&x509_rsapss_params_decoder, ctx,
+ cert->pub->params, cert->pub->paramlen);
+ if (ret < 0) {
+ pr_warn("Couldn't decode rsapss params\n");
+ goto error_decode;
+ }
+ }
+
/* Grab the signature bits */
ret = x509_get_sig_params(cert);
if (ret < 0)
@@ -211,6 +223,10 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
ctx->cert->sig->hash_algo = "sha1";
goto rsa_pkcs1;

+ case OID_rsa_pss:
+ ctx->cert->sig->hash_algo = "sha1";
+ goto rsa_pss;
+
case OID_sha256WithRSAEncryption:
ctx->cert->sig->hash_algo = "sha256";
goto rsa_pkcs1;
@@ -245,6 +261,11 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
ctx->cert->sig->encoding = "pkcs1";
ctx->algo_oid = ctx->last_oid;
return 0;
+rsa_pss:
+ ctx->cert->sig->pkey_algo = "rsa";
+ ctx->cert->sig->encoding = "pss";
+ ctx->algo_oid = ctx->last_oid;
+ return 0;
ecrdsa:
ctx->cert->sig->pkey_algo = "ecrdsa";
ctx->cert->sig->encoding = "raw";
@@ -440,17 +461,59 @@ int x509_note_params(void *context, size_t hdrlen,
struct x509_parse_context *ctx = context;

/*
- * AlgorithmIdentifier is used three times in the x509, we should skip
- * first and ignore third, using second one which is after subject and
- * before subjectPublicKey.
+ * AlgorithmIdentifier is used three times in the x509,
+ * rsapss:
+ * we skip first(same as third) and second(may omit params).
+ * others:
+ * we should skip first and ignore third, using second one
+ * which is after subject and before subjectPublicKey.
*/
- if (!ctx->cert->raw_subject || ctx->key)
+ if (!ctx->cert->raw_subject) {
+ return 0;
+ } else if (strcmp(ctx->cert->sig->pkey_algo, "rsa") ||
+ strcmp(ctx->cert->sig->encoding, "pss")) {
+ if (ctx->key)
+ return 0;
+ } else if (!ctx->key) {
return 0;
+ }
+
ctx->params = value - hdrlen;
ctx->params_size = vlen + hdrlen;
return 0;
}

+int x509_note_rsapss_hash(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ enum OID oid;
+
+ oid = look_up_OID(value, vlen);
+ switch (oid) {
+ case OID_sha1:
+ ctx->cert->sig->hash_algo = "sha1";
+ break;
+ case OID_sha224:
+ ctx->cert->sig->hash_algo = "sha224";
+ break;
+ case OID_sha256:
+ ctx->cert->sig->hash_algo = "sha256";
+ break;
+ case OID_sha384:
+ ctx->cert->sig->hash_algo = "sha384";
+ break;
+ case OID_sha512:
+ ctx->cert->sig->hash_algo = "sha512";
+ break;
+ default:
+ return -ENOPKG;
+ }
+
+ return 0;
+}
+
/*
* Extract the data for the public key algorithm
*/
diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
index 4462ed2..bb22b84 100644
--- a/include/linux/oid_registry.h
+++ b/include/linux/oid_registry.h
@@ -28,6 +28,8 @@ enum OID {
OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */
OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */
OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */
+ OID_rsa_mgf1, /* 1.2.840.113549.1.1.8 */
+ OID_rsa_pss, /* 1.2.840.113549.1.1.10 */
OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */
OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */
OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */
--
1.8.3.1