diff mbox series

[v3,21/25] mbedtls: add RSA helper layer on MbedTLS

Message ID 20240528140955.1960172-22-raymond.mao@linaro.org
State RFC
Delegated to: Tom Rini
Headers show
Series Integrate MbedTLS v3.6 LTS with U-Boot | expand

Commit Message

Raymond Mao May 28, 2024, 2:09 p.m. UTC
Add RSA helper layer on top on MbedTLS PK and RSA library.

Signed-off-by: Raymond Mao <raymond.mao@linaro.org>
---
Changes in v2
- Initial patch.
Changes in v3
- None.

 lib/mbedtls/Makefile     |  1 +
 lib/mbedtls/rsa_helper.c | 99 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+)
 create mode 100644 lib/mbedtls/rsa_helper.c

Comments

Ilias Apalodimas May 31, 2024, 9:59 a.m. UTC | #1
Hi Raymond,

[...]

> +
> +/**
> + * rsa_parse_pub_key() - decodes the BER encoded buffer and stores in the
> + *                       provided struct rsa_key, pointers to the raw key as is,
> + *                       so that the caller can copy it or MPI parse it, etc.
> + *
> + * @rsa_key:   struct rsa_key key representation
> + * @key:       key in BER format
> + * @key_len:   length of key
> + *
> + * Return:     0 on success or error code in case of error
> + */
> +int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
> +                     unsigned int key_len)
> +{
> +       int ret = 0;
> +       mbedtls_pk_context pk;
> +       mbedtls_rsa_context *rsa;
> +
> +       mbedtls_pk_init(&pk);
> +
> +       ret = mbedtls_pk_parse_public_key(&pk, (const unsigned char *)key,
> +                                         key_len);
> +       if (ret) {
> +               pr_err("Failed to parse public key, ret:-0x%04x\n",
> +                      (unsigned int)-ret);
> +               ret = -EINVAL;
> +               goto clean_pubkey;
> +       }
> +
> +       /* Ensure that it is a RSA key */
> +       if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_RSA) {
> +               pr_err("Non-RSA keys are not supported\n");
> +               ret = -EKEYREJECTED;
> +               goto clean_pubkey;
> +       }
> +
> +       /* Get RSA key context */
> +       rsa = mbedtls_pk_rsa(pk);
> +       if (!rsa) {
> +               pr_err("Failed to get RSA key context, ret:-0x%04x\n",
> +                      (unsigned int)-ret);

Why do we need to cast the result here? Just print ret
Also, would it make sense to create a mapping between mbedTLS API
errors and internal error codes?
instead of doing ret -EINVAL etc  we could have something like
ret = mbedtls_to_errno(ret);

> +               ret = -EINVAL;
> +               goto clean_pubkey;
> +       }
> +
> +       /* Parse modulus (n) */
> +       rsa_key->n_sz = mbedtls_mpi_size(&rsa->N);
> +       rsa_key->n = kzalloc(rsa_key->n_sz, GFP_KERNEL);
> +       if (!rsa_key->n) {
> +               ret = -ENOMEM;
> +               goto clean_pubkey;
> +       }
> +       ret = mbedtls_mpi_write_binary(&rsa->N, (unsigned char *)rsa_key->n,
> +                                      rsa_key->n_sz);
> +       if (ret) {
> +               pr_err("Failed to parse modulus (n), ret:-0x%04x\n",
> +                      (unsigned int)-ret);

Same here

> +               ret = -EINVAL;
> +               goto clean_modulus;
> +       }
> +
> +       /* Parse public exponent (e) */
> +       rsa_key->e_sz = mbedtls_mpi_size(&rsa->E);
> +       rsa_key->e = kzalloc(rsa_key->e_sz, GFP_KERNEL);
> +       if (!rsa_key->e) {
> +               ret = -ENOMEM;
> +               goto clean_modulus;
> +       }
> +       ret = mbedtls_mpi_write_binary(&rsa->E, (unsigned char *)rsa_key->e,
> +                                      rsa_key->e_sz);
> +       if (!ret)
> +               return 0;
> +
> +       pr_err("Failed to parse public exponent (e), ret:-0x%04x\n",
> +              (unsigned int)-ret);

 and here

> +       ret = -EINVAL;
> +
> +       kfree(rsa_key->e);
> +clean_modulus:
> +       kfree(rsa_key->n);
> +clean_pubkey:
> +       mbedtls_pk_free(&pk);
> +       return ret;
> +}
> --
> 2.25.1
>
Thanks
/Ilias
Raymond Mao June 4, 2024, 4:43 p.m. UTC | #2
Hi Ilias,

On Fri, 31 May 2024 at 06:00, Ilias Apalodimas <ilias.apalodimas@linaro.org>
wrote:

> Hi Raymond,
>
> [...]
>
> > +
> > +/**
> > + * rsa_parse_pub_key() - decodes the BER encoded buffer and stores in
> the
> > + *                       provided struct rsa_key, pointers to the raw
> key as is,
> > + *                       so that the caller can copy it or MPI parse
> it, etc.
> > + *
> > + * @rsa_key:   struct rsa_key key representation
> > + * @key:       key in BER format
> > + * @key_len:   length of key
> > + *
> > + * Return:     0 on success or error code in case of error
> > + */
> > +int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
> > +                     unsigned int key_len)
> > +{
> > +       int ret = 0;
> > +       mbedtls_pk_context pk;
> > +       mbedtls_rsa_context *rsa;
> > +
> > +       mbedtls_pk_init(&pk);
> > +
> > +       ret = mbedtls_pk_parse_public_key(&pk, (const unsigned char
> *)key,
> > +                                         key_len);
> > +       if (ret) {
> > +               pr_err("Failed to parse public key, ret:-0x%04x\n",
> > +                      (unsigned int)-ret);
> > +               ret = -EINVAL;
> > +               goto clean_pubkey;
> > +       }
> > +
> > +       /* Ensure that it is a RSA key */
> > +       if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_RSA) {
> > +               pr_err("Non-RSA keys are not supported\n");
> > +               ret = -EKEYREJECTED;
> > +               goto clean_pubkey;
> > +       }
> > +
> > +       /* Get RSA key context */
> > +       rsa = mbedtls_pk_rsa(pk);
> > +       if (!rsa) {
> > +               pr_err("Failed to get RSA key context, ret:-0x%04x\n",
> > +                      (unsigned int)-ret);
>
> Why do we need to cast the result here? Just print ret
> Also, would it make sense to create a mapping between mbedTLS API
> errors and internal error codes?
> instead of doing ret -EINVAL etc  we could have something like
> ret = mbedtls_to_errno(ret);
>
> I can remove all the cast.
But it is not able to 1/1 map the mbedtls errors to general ones via a
helper
function since the error code should reflect the current scenario of the
operation.
Even with the same MbedTLS API and same error code, the purpose of
caller is different, it is hard to get them mapped in a common
interpretation.

[...]

Regards,
Raymond
diff mbox series

Patch

diff --git a/lib/mbedtls/Makefile b/lib/mbedtls/Makefile
index f0b8a1c4003..dab110891af 100644
--- a/lib/mbedtls/Makefile
+++ b/lib/mbedtls/Makefile
@@ -27,6 +27,7 @@  x509_mbedtls-$(CONFIG_$(SPL_)ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
 x509_mbedtls-$(CONFIG_$(SPL_)X509_CERTIFICATE_PARSER) += x509_cert_parser.o
 x509_mbedtls-$(CONFIG_$(SPL_)PKCS7_MESSAGE_PARSER) += pkcs7_parser.o
 x509_mbedtls-$(CONFIG_$(SPL_)MSCODE_PARSER) += mscode_parser.o
+x509_mbedtls-$(CONFIG_$(SPL_)RSA_PUBLIC_KEY_PARSER) += rsa_helper.o
 
 obj-$(CONFIG_MBEDTLS_LIB_CRYPTO) += mbedtls_lib_crypto.o
 mbedtls_lib_crypto-y := \
diff --git a/lib/mbedtls/rsa_helper.c b/lib/mbedtls/rsa_helper.c
new file mode 100644
index 00000000000..956e550c856
--- /dev/null
+++ b/lib/mbedtls/rsa_helper.c
@@ -0,0 +1,99 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * RSA helper functions using MbedTLS
+ *
+ * Copyright (c) 2024 Linaro Limited
+ * Author: Raymond Mao <raymond.mao@linaro.org>
+ */
+
+#include <linux/err.h>
+#include <crypto/internal/rsa.h>
+#include <external/mbedtls/library/common.h>
+#include <external/mbedtls/include/mbedtls/pk.h>
+#include <external/mbedtls/include/mbedtls/rsa.h>
+#include <external/mbedtls/include/mbedtls/asn1.h>
+
+/**
+ * rsa_parse_pub_key() - decodes the BER encoded buffer and stores in the
+ *                       provided struct rsa_key, pointers to the raw key as is,
+ *                       so that the caller can copy it or MPI parse it, etc.
+ *
+ * @rsa_key:	struct rsa_key key representation
+ * @key:	key in BER format
+ * @key_len:	length of key
+ *
+ * Return:	0 on success or error code in case of error
+ */
+int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
+		      unsigned int key_len)
+{
+	int ret = 0;
+	mbedtls_pk_context pk;
+	mbedtls_rsa_context *rsa;
+
+	mbedtls_pk_init(&pk);
+
+	ret = mbedtls_pk_parse_public_key(&pk, (const unsigned char *)key,
+					  key_len);
+	if (ret) {
+		pr_err("Failed to parse public key, ret:-0x%04x\n",
+		       (unsigned int)-ret);
+		ret = -EINVAL;
+		goto clean_pubkey;
+	}
+
+	/* Ensure that it is a RSA key */
+	if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_RSA) {
+		pr_err("Non-RSA keys are not supported\n");
+		ret = -EKEYREJECTED;
+		goto clean_pubkey;
+	}
+
+	/* Get RSA key context */
+	rsa = mbedtls_pk_rsa(pk);
+	if (!rsa) {
+		pr_err("Failed to get RSA key context, ret:-0x%04x\n",
+		       (unsigned int)-ret);
+		ret = -EINVAL;
+		goto clean_pubkey;
+	}
+
+	/* Parse modulus (n) */
+	rsa_key->n_sz = mbedtls_mpi_size(&rsa->N);
+	rsa_key->n = kzalloc(rsa_key->n_sz, GFP_KERNEL);
+	if (!rsa_key->n) {
+		ret = -ENOMEM;
+		goto clean_pubkey;
+	}
+	ret = mbedtls_mpi_write_binary(&rsa->N, (unsigned char *)rsa_key->n,
+				       rsa_key->n_sz);
+	if (ret) {
+		pr_err("Failed to parse modulus (n), ret:-0x%04x\n",
+		       (unsigned int)-ret);
+		ret = -EINVAL;
+		goto clean_modulus;
+	}
+
+	/* Parse public exponent (e) */
+	rsa_key->e_sz = mbedtls_mpi_size(&rsa->E);
+	rsa_key->e = kzalloc(rsa_key->e_sz, GFP_KERNEL);
+	if (!rsa_key->e) {
+		ret = -ENOMEM;
+		goto clean_modulus;
+	}
+	ret = mbedtls_mpi_write_binary(&rsa->E, (unsigned char *)rsa_key->e,
+				       rsa_key->e_sz);
+	if (!ret)
+		return 0;
+
+	pr_err("Failed to parse public exponent (e), ret:-0x%04x\n",
+	       (unsigned int)-ret);
+	ret = -EINVAL;
+
+	kfree(rsa_key->e);
+clean_modulus:
+	kfree(rsa_key->n);
+clean_pubkey:
+	mbedtls_pk_free(&pk);
+	return ret;
+}