From: Hongbo Li <herberth...@tencent.com>

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 <herberth...@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

Reply via email to