1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * RSA helper functions using MbedTLS
4  *
5  * Copyright (c) 2024 Linaro Limited
6  * Author: Raymond Mao <raymond.mao@linaro.org>
7  */
8 
9 #include <linux/err.h>
10 #include <crypto/internal/rsa.h>
11 #include <library/common.h>
12 #include <mbedtls/pk.h>
13 #include <mbedtls/rsa.h>
14 #include <mbedtls/asn1.h>
15 
16 /**
17  * rsa_parse_pub_key() - decodes the BER encoded buffer and stores in the
18  *                       provided struct rsa_key, pointers to the raw key as is,
19  *                       so that the caller can copy it or MPI parse it, etc.
20  *
21  * @rsa_key:	struct rsa_key key representation
22  * @key:	key in BER format
23  * @key_len:	length of key
24  *
25  * Return:	0 on success or error code in case of error
26  */
rsa_parse_pub_key(struct rsa_key * rsa_key,const void * key,unsigned int key_len)27 int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
28 		      unsigned int key_len)
29 {
30 	int ret = 0;
31 	mbedtls_pk_context pk;
32 	mbedtls_rsa_context *rsa;
33 
34 	mbedtls_pk_init(&pk);
35 
36 	ret = mbedtls_pk_parse_public_key(&pk, (const unsigned char *)key,
37 					  key_len);
38 	if (ret) {
39 		pr_err("Failed to parse public key, ret:-0x%04x\n", -ret);
40 		ret = -EINVAL;
41 		goto clean_pubkey;
42 	}
43 
44 	/* Ensure that it is a RSA key */
45 	if (mbedtls_pk_get_type(&pk) != MBEDTLS_PK_RSA) {
46 		pr_err("Non-RSA keys are not supported\n");
47 		ret = -EKEYREJECTED;
48 		goto clean_pubkey;
49 	}
50 
51 	/* Get RSA key context */
52 	rsa = mbedtls_pk_rsa(pk);
53 	if (!rsa) {
54 		pr_err("Failed to get RSA key context, ret:-0x%04x\n", -ret);
55 		ret = -EINVAL;
56 		goto clean_pubkey;
57 	}
58 
59 	/* Parse modulus (n) */
60 	rsa_key->n_sz = mbedtls_mpi_size(&rsa->N);
61 	rsa_key->n = kzalloc(rsa_key->n_sz, GFP_KERNEL);
62 	if (!rsa_key->n) {
63 		ret = -ENOMEM;
64 		goto clean_pubkey;
65 	}
66 	ret = mbedtls_mpi_write_binary(&rsa->N, (unsigned char *)rsa_key->n,
67 				       rsa_key->n_sz);
68 	if (ret) {
69 		pr_err("Failed to parse modulus (n), ret:-0x%04x\n", -ret);
70 		ret = -EINVAL;
71 		goto clean_modulus;
72 	}
73 
74 	/* Parse public exponent (e) */
75 	rsa_key->e_sz = mbedtls_mpi_size(&rsa->E);
76 	rsa_key->e = kzalloc(rsa_key->e_sz, GFP_KERNEL);
77 	if (!rsa_key->e) {
78 		ret = -ENOMEM;
79 		goto clean_modulus;
80 	}
81 	ret = mbedtls_mpi_write_binary(&rsa->E, (unsigned char *)rsa_key->e,
82 				       rsa_key->e_sz);
83 	if (!ret)
84 		return 0;
85 
86 	pr_err("Failed to parse public exponent (e), ret:-0x%04x\n", -ret);
87 	ret = -EINVAL;
88 
89 	kfree(rsa_key->e);
90 clean_modulus:
91 	kfree(rsa_key->n);
92 clean_pubkey:
93 	mbedtls_pk_free(&pk);
94 	return ret;
95 }
96