Linux 6.9-rc1
[linux-2.6-microblaze.git] / crypto / rsa.c
index 0e555ee..d9be9e8 100644 (file)
@@ -24,14 +24,38 @@ struct rsa_mpi_key {
        MPI qinv;
 };
 
+static int rsa_check_payload(MPI x, MPI n)
+{
+       MPI n1;
+
+       if (mpi_cmp_ui(x, 1) <= 0)
+               return -EINVAL;
+
+       n1 = mpi_alloc(0);
+       if (!n1)
+               return -ENOMEM;
+
+       if (mpi_sub_ui(n1, n, 1) || mpi_cmp(x, n1) >= 0) {
+               mpi_free(n1);
+               return -EINVAL;
+       }
+
+       mpi_free(n1);
+       return 0;
+}
+
 /*
  * RSAEP function [RFC3447 sec 5.1.1]
  * c = m^e mod n;
  */
 static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m)
 {
-       /* (1) Validate 0 <= m < n */
-       if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
+       /*
+        * Even though (1) in RFC3447 only requires 0 <= m <= n - 1, we are
+        * slightly more conservative and require 1 < m < n - 1. This is in line
+        * with SP 800-56Br2, Section 7.1.1.
+        */
+       if (rsa_check_payload(m, key->n))
                return -EINVAL;
 
        /* (2) c = m^e mod n */
@@ -50,8 +74,12 @@ static int _rsa_dec_crt(const struct rsa_mpi_key *key, MPI m_or_m1_or_h, MPI c)
        MPI m2, m12_or_qh;
        int ret = -ENOMEM;
 
-       /* (1) Validate 0 <= c < n */
-       if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0)
+       /*
+        * Even though (1) in RFC3447 only requires 0 <= c <= n - 1, we are
+        * slightly more conservative and require 1 < c < n - 1. This is in line
+        * with SP 800-56Br2, Section 7.1.2.
+        */
+       if (rsa_check_payload(c, key->n))
                return -EINVAL;
 
        m2 = mpi_alloc(0);
@@ -205,6 +233,34 @@ static int rsa_check_key_length(unsigned int len)
        return -EINVAL;
 }
 
+static int rsa_check_exponent_fips(MPI e)
+{
+       MPI e_max = NULL;
+
+       /* check if odd */
+       if (!mpi_test_bit(e, 0)) {
+               return -EINVAL;
+       }
+
+       /* check if 2^16 < e < 2^256. */
+       if (mpi_cmp_ui(e, 65536) <= 0) {
+               return -EINVAL;
+       }
+
+       e_max = mpi_alloc(0);
+       if (!e_max)
+               return -ENOMEM;
+       mpi_set_bit(e_max, 256);
+
+       if (mpi_cmp(e, e_max) >= 0) {
+               mpi_free(e_max);
+               return -EINVAL;
+       }
+
+       mpi_free(e_max);
+       return 0;
+}
+
 static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
                           unsigned int keylen)
 {
@@ -232,6 +288,11 @@ static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
                return -EINVAL;
        }
 
+       if (fips_enabled && rsa_check_exponent_fips(mpi_key->e)) {
+               rsa_free_mpi_key(mpi_key);
+               return -EINVAL;
+       }
+
        return 0;
 
 err:
@@ -290,6 +351,11 @@ static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
                return -EINVAL;
        }
 
+       if (fips_enabled && rsa_check_exponent_fips(mpi_key->e)) {
+               rsa_free_mpi_key(mpi_key);
+               return -EINVAL;
+       }
+
        return 0;
 
 err:
@@ -327,7 +393,7 @@ static struct akcipher_alg rsa = {
        },
 };
 
-static int rsa_init(void)
+static int __init rsa_init(void)
 {
        int err;
 
@@ -344,7 +410,7 @@ static int rsa_init(void)
        return 0;
 }
 
-static void rsa_exit(void)
+static void __exit rsa_exit(void)
 {
        crypto_unregister_template(&rsa_pkcs1pad_tmpl);
        crypto_unregister_akcipher(&rsa);