1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  PSA RSA layer on top of Mbed TLS crypto
3a8e1175bSopenharmony_ci */
4a8e1175bSopenharmony_ci/*
5a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
6a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7a8e1175bSopenharmony_ci */
8a8e1175bSopenharmony_ci
9a8e1175bSopenharmony_ci#include "common.h"
10a8e1175bSopenharmony_ci
11a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_CRYPTO_C)
12a8e1175bSopenharmony_ci
13a8e1175bSopenharmony_ci#include <psa/crypto.h>
14a8e1175bSopenharmony_ci#include "psa/crypto_values.h"
15a8e1175bSopenharmony_ci#include "psa_crypto_core.h"
16a8e1175bSopenharmony_ci#include "psa_crypto_random_impl.h"
17a8e1175bSopenharmony_ci#include "psa_crypto_rsa.h"
18a8e1175bSopenharmony_ci#include "psa_crypto_hash.h"
19a8e1175bSopenharmony_ci#include "mbedtls/psa_util.h"
20a8e1175bSopenharmony_ci
21a8e1175bSopenharmony_ci#include <stdlib.h>
22a8e1175bSopenharmony_ci#include <string.h>
23a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
24a8e1175bSopenharmony_ci
25a8e1175bSopenharmony_ci#include <mbedtls/rsa.h>
26a8e1175bSopenharmony_ci#include <mbedtls/error.h>
27a8e1175bSopenharmony_ci#include "rsa_internal.h"
28a8e1175bSopenharmony_ci
29a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
30a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
31a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
32a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
33a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
34a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
35a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
36a8e1175bSopenharmony_ci
37a8e1175bSopenharmony_ci/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes
38a8e1175bSopenharmony_ci * that are not a multiple of 8) well. For example, there is only
39a8e1175bSopenharmony_ci * mbedtls_rsa_get_len(), which returns a number of bytes, and no
40a8e1175bSopenharmony_ci * way to return the exact bit size of a key.
41a8e1175bSopenharmony_ci * To keep things simple, reject non-byte-aligned key sizes. */
42a8e1175bSopenharmony_cistatic psa_status_t psa_check_rsa_key_byte_aligned(
43a8e1175bSopenharmony_ci    const mbedtls_rsa_context *rsa)
44a8e1175bSopenharmony_ci{
45a8e1175bSopenharmony_ci    mbedtls_mpi n;
46a8e1175bSopenharmony_ci    psa_status_t status;
47a8e1175bSopenharmony_ci    mbedtls_mpi_init(&n);
48a8e1175bSopenharmony_ci    status = mbedtls_to_psa_error(
49a8e1175bSopenharmony_ci        mbedtls_rsa_export(rsa, &n, NULL, NULL, NULL, NULL));
50a8e1175bSopenharmony_ci    if (status == PSA_SUCCESS) {
51a8e1175bSopenharmony_ci        if (mbedtls_mpi_bitlen(&n) % 8 != 0) {
52a8e1175bSopenharmony_ci            status = PSA_ERROR_NOT_SUPPORTED;
53a8e1175bSopenharmony_ci        }
54a8e1175bSopenharmony_ci    }
55a8e1175bSopenharmony_ci    mbedtls_mpi_free(&n);
56a8e1175bSopenharmony_ci    return status;
57a8e1175bSopenharmony_ci}
58a8e1175bSopenharmony_ci
59a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_rsa_load_representation(
60a8e1175bSopenharmony_ci    psa_key_type_t type, const uint8_t *data, size_t data_length,
61a8e1175bSopenharmony_ci    mbedtls_rsa_context **p_rsa)
62a8e1175bSopenharmony_ci{
63a8e1175bSopenharmony_ci    psa_status_t status;
64a8e1175bSopenharmony_ci    size_t bits;
65a8e1175bSopenharmony_ci
66a8e1175bSopenharmony_ci    *p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));
67a8e1175bSopenharmony_ci    if (*p_rsa == NULL) {
68a8e1175bSopenharmony_ci        return PSA_ERROR_INSUFFICIENT_MEMORY;
69a8e1175bSopenharmony_ci    }
70a8e1175bSopenharmony_ci    mbedtls_rsa_init(*p_rsa);
71a8e1175bSopenharmony_ci
72a8e1175bSopenharmony_ci    /* Parse the data. */
73a8e1175bSopenharmony_ci    if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
74a8e1175bSopenharmony_ci        status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length));
75a8e1175bSopenharmony_ci    } else {
76a8e1175bSopenharmony_ci        status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length));
77a8e1175bSopenharmony_ci    }
78a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
79a8e1175bSopenharmony_ci        goto exit;
80a8e1175bSopenharmony_ci    }
81a8e1175bSopenharmony_ci
82a8e1175bSopenharmony_ci    /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS
83a8e1175bSopenharmony_ci     * supports non-byte-aligned key sizes, but not well. For example,
84a8e1175bSopenharmony_ci     * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */
85a8e1175bSopenharmony_ci    bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa));
86a8e1175bSopenharmony_ci    if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {
87a8e1175bSopenharmony_ci        status = PSA_ERROR_NOT_SUPPORTED;
88a8e1175bSopenharmony_ci        goto exit;
89a8e1175bSopenharmony_ci    }
90a8e1175bSopenharmony_ci    status = psa_check_rsa_key_byte_aligned(*p_rsa);
91a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
92a8e1175bSopenharmony_ci        goto exit;
93a8e1175bSopenharmony_ci    }
94a8e1175bSopenharmony_ci
95a8e1175bSopenharmony_ciexit:
96a8e1175bSopenharmony_ci    return status;
97a8e1175bSopenharmony_ci}
98a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
99a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
100a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
101a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
102a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) ||
103a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
104a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
105a8e1175bSopenharmony_ci
106a8e1175bSopenharmony_ci#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
107a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
108a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
109a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_rsa_import_key(
110a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
111a8e1175bSopenharmony_ci    const uint8_t *data, size_t data_length,
112a8e1175bSopenharmony_ci    uint8_t *key_buffer, size_t key_buffer_size,
113a8e1175bSopenharmony_ci    size_t *key_buffer_length, size_t *bits)
114a8e1175bSopenharmony_ci{
115a8e1175bSopenharmony_ci    psa_status_t status;
116a8e1175bSopenharmony_ci    mbedtls_rsa_context *rsa = NULL;
117a8e1175bSopenharmony_ci
118a8e1175bSopenharmony_ci    /* Parse input */
119a8e1175bSopenharmony_ci    status = mbedtls_psa_rsa_load_representation(attributes->type,
120a8e1175bSopenharmony_ci                                                 data,
121a8e1175bSopenharmony_ci                                                 data_length,
122a8e1175bSopenharmony_ci                                                 &rsa);
123a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
124a8e1175bSopenharmony_ci        goto exit;
125a8e1175bSopenharmony_ci    }
126a8e1175bSopenharmony_ci
127a8e1175bSopenharmony_ci    *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(rsa));
128a8e1175bSopenharmony_ci
129a8e1175bSopenharmony_ci    /* Re-export the data to PSA export format, such that we can store export
130a8e1175bSopenharmony_ci     * representation in the key slot. Export representation in case of RSA is
131a8e1175bSopenharmony_ci     * the smallest representation that's allowed as input, so a straight-up
132a8e1175bSopenharmony_ci     * allocation of the same size as the input buffer will be large enough. */
133a8e1175bSopenharmony_ci    status = mbedtls_psa_rsa_export_key(attributes->type,
134a8e1175bSopenharmony_ci                                        rsa,
135a8e1175bSopenharmony_ci                                        key_buffer,
136a8e1175bSopenharmony_ci                                        key_buffer_size,
137a8e1175bSopenharmony_ci                                        key_buffer_length);
138a8e1175bSopenharmony_ciexit:
139a8e1175bSopenharmony_ci    /* Always free the RSA object */
140a8e1175bSopenharmony_ci    mbedtls_rsa_free(rsa);
141a8e1175bSopenharmony_ci    mbedtls_free(rsa);
142a8e1175bSopenharmony_ci
143a8e1175bSopenharmony_ci    return status;
144a8e1175bSopenharmony_ci}
145a8e1175bSopenharmony_ci#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&
146a8e1175bSopenharmony_ci        *  defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
147a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
148a8e1175bSopenharmony_ci
149a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
150a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
151a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type,
152a8e1175bSopenharmony_ci                                        mbedtls_rsa_context *rsa,
153a8e1175bSopenharmony_ci                                        uint8_t *data,
154a8e1175bSopenharmony_ci                                        size_t data_size,
155a8e1175bSopenharmony_ci                                        size_t *data_length)
156a8e1175bSopenharmony_ci{
157a8e1175bSopenharmony_ci    int ret;
158a8e1175bSopenharmony_ci    uint8_t *end = data + data_size;
159a8e1175bSopenharmony_ci
160a8e1175bSopenharmony_ci    /* PSA Crypto API defines the format of an RSA key as a DER-encoded
161a8e1175bSopenharmony_ci     * representation of the non-encrypted PKCS#1 RSAPrivateKey for a
162a8e1175bSopenharmony_ci     * private key and of the RFC3279 RSAPublicKey for a public key. */
163a8e1175bSopenharmony_ci    if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
164a8e1175bSopenharmony_ci        ret = mbedtls_rsa_write_key(rsa, data, &end);
165a8e1175bSopenharmony_ci    } else {
166a8e1175bSopenharmony_ci        ret = mbedtls_rsa_write_pubkey(rsa, data, &end);
167a8e1175bSopenharmony_ci    }
168a8e1175bSopenharmony_ci
169a8e1175bSopenharmony_ci    if (ret < 0) {
170a8e1175bSopenharmony_ci        /* Clean up in case pk_write failed halfway through. */
171a8e1175bSopenharmony_ci        memset(data, 0, data_size);
172a8e1175bSopenharmony_ci        return mbedtls_to_psa_error(ret);
173a8e1175bSopenharmony_ci    }
174a8e1175bSopenharmony_ci
175a8e1175bSopenharmony_ci    /* The mbedtls_pk_xxx functions write to the end of the buffer.
176a8e1175bSopenharmony_ci     * Move the data to the beginning and erase remaining data
177a8e1175bSopenharmony_ci     * at the original location. */
178a8e1175bSopenharmony_ci    if (2 * (size_t) ret <= data_size) {
179a8e1175bSopenharmony_ci        memcpy(data, data + data_size - ret, ret);
180a8e1175bSopenharmony_ci        memset(data + data_size - ret, 0, ret);
181a8e1175bSopenharmony_ci    } else if ((size_t) ret < data_size) {
182a8e1175bSopenharmony_ci        memmove(data, data + data_size - ret, ret);
183a8e1175bSopenharmony_ci        memset(data + ret, 0, data_size - ret);
184a8e1175bSopenharmony_ci    }
185a8e1175bSopenharmony_ci
186a8e1175bSopenharmony_ci    *data_length = ret;
187a8e1175bSopenharmony_ci    return PSA_SUCCESS;
188a8e1175bSopenharmony_ci}
189a8e1175bSopenharmony_ci
190a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_rsa_export_public_key(
191a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
192a8e1175bSopenharmony_ci    const uint8_t *key_buffer, size_t key_buffer_size,
193a8e1175bSopenharmony_ci    uint8_t *data, size_t data_size, size_t *data_length)
194a8e1175bSopenharmony_ci{
195a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
196a8e1175bSopenharmony_ci    mbedtls_rsa_context *rsa = NULL;
197a8e1175bSopenharmony_ci
198a8e1175bSopenharmony_ci    status = mbedtls_psa_rsa_load_representation(
199a8e1175bSopenharmony_ci        attributes->type, key_buffer, key_buffer_size, &rsa);
200a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
201a8e1175bSopenharmony_ci        return status;
202a8e1175bSopenharmony_ci    }
203a8e1175bSopenharmony_ci
204a8e1175bSopenharmony_ci    status = mbedtls_psa_rsa_export_key(PSA_KEY_TYPE_RSA_PUBLIC_KEY,
205a8e1175bSopenharmony_ci                                        rsa,
206a8e1175bSopenharmony_ci                                        data,
207a8e1175bSopenharmony_ci                                        data_size,
208a8e1175bSopenharmony_ci                                        data_length);
209a8e1175bSopenharmony_ci
210a8e1175bSopenharmony_ci    mbedtls_rsa_free(rsa);
211a8e1175bSopenharmony_ci    mbedtls_free(rsa);
212a8e1175bSopenharmony_ci
213a8e1175bSopenharmony_ci    return status;
214a8e1175bSopenharmony_ci}
215a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
216a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
217a8e1175bSopenharmony_ci
218a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
219a8e1175bSopenharmony_cistatic psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes,
220a8e1175bSopenharmony_ci                                          size_t e_length,
221a8e1175bSopenharmony_ci                                          int *exponent)
222a8e1175bSopenharmony_ci{
223a8e1175bSopenharmony_ci    size_t i;
224a8e1175bSopenharmony_ci    uint32_t acc = 0;
225a8e1175bSopenharmony_ci
226a8e1175bSopenharmony_ci    /* Mbed TLS encodes the public exponent as an int. For simplicity, only
227a8e1175bSopenharmony_ci     * support values that fit in a 32-bit integer, which is larger than
228a8e1175bSopenharmony_ci     * int on just about every platform anyway. */
229a8e1175bSopenharmony_ci    if (e_length > sizeof(acc)) {
230a8e1175bSopenharmony_ci        return PSA_ERROR_NOT_SUPPORTED;
231a8e1175bSopenharmony_ci    }
232a8e1175bSopenharmony_ci    for (i = 0; i < e_length; i++) {
233a8e1175bSopenharmony_ci        acc = (acc << 8) | e_bytes[i];
234a8e1175bSopenharmony_ci    }
235a8e1175bSopenharmony_ci    if (acc > INT_MAX) {
236a8e1175bSopenharmony_ci        return PSA_ERROR_NOT_SUPPORTED;
237a8e1175bSopenharmony_ci    }
238a8e1175bSopenharmony_ci    *exponent = acc;
239a8e1175bSopenharmony_ci    return PSA_SUCCESS;
240a8e1175bSopenharmony_ci}
241a8e1175bSopenharmony_ci
242a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_rsa_generate_key(
243a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
244a8e1175bSopenharmony_ci    const psa_key_production_parameters_t *params, size_t params_data_length,
245a8e1175bSopenharmony_ci    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
246a8e1175bSopenharmony_ci{
247a8e1175bSopenharmony_ci    psa_status_t status;
248a8e1175bSopenharmony_ci    mbedtls_rsa_context rsa;
249a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
250a8e1175bSopenharmony_ci    int exponent = 65537;
251a8e1175bSopenharmony_ci
252a8e1175bSopenharmony_ci    if (params_data_length != 0) {
253a8e1175bSopenharmony_ci        status = psa_rsa_read_exponent(params->data, params_data_length,
254a8e1175bSopenharmony_ci                                       &exponent);
255a8e1175bSopenharmony_ci        if (status != PSA_SUCCESS) {
256a8e1175bSopenharmony_ci            return status;
257a8e1175bSopenharmony_ci        }
258a8e1175bSopenharmony_ci    }
259a8e1175bSopenharmony_ci
260a8e1175bSopenharmony_ci    mbedtls_rsa_init(&rsa);
261a8e1175bSopenharmony_ci    ret = mbedtls_rsa_gen_key(&rsa,
262a8e1175bSopenharmony_ci                              mbedtls_psa_get_random,
263a8e1175bSopenharmony_ci                              MBEDTLS_PSA_RANDOM_STATE,
264a8e1175bSopenharmony_ci                              (unsigned int) attributes->bits,
265a8e1175bSopenharmony_ci                              exponent);
266a8e1175bSopenharmony_ci    if (ret != 0) {
267a8e1175bSopenharmony_ci        return mbedtls_to_psa_error(ret);
268a8e1175bSopenharmony_ci    }
269a8e1175bSopenharmony_ci
270a8e1175bSopenharmony_ci    status = mbedtls_psa_rsa_export_key(attributes->type,
271a8e1175bSopenharmony_ci                                        &rsa, key_buffer, key_buffer_size,
272a8e1175bSopenharmony_ci                                        key_buffer_length);
273a8e1175bSopenharmony_ci    mbedtls_rsa_free(&rsa);
274a8e1175bSopenharmony_ci
275a8e1175bSopenharmony_ci    return status;
276a8e1175bSopenharmony_ci}
277a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */
278a8e1175bSopenharmony_ci
279a8e1175bSopenharmony_ci/****************************************************************/
280a8e1175bSopenharmony_ci/* Sign/verify hashes */
281a8e1175bSopenharmony_ci/****************************************************************/
282a8e1175bSopenharmony_ci
283a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
284a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
285a8e1175bSopenharmony_ci
286a8e1175bSopenharmony_ci/* Decode the hash algorithm from alg and store the mbedtls encoding in
287a8e1175bSopenharmony_ci * md_alg. Verify that the hash length is acceptable. */
288a8e1175bSopenharmony_cistatic psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg,
289a8e1175bSopenharmony_ci                                           size_t hash_length,
290a8e1175bSopenharmony_ci                                           mbedtls_md_type_t *md_alg)
291a8e1175bSopenharmony_ci{
292a8e1175bSopenharmony_ci    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
293a8e1175bSopenharmony_ci    *md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
294a8e1175bSopenharmony_ci
295a8e1175bSopenharmony_ci    /* The Mbed TLS RSA module uses an unsigned int for hash length
296a8e1175bSopenharmony_ci     * parameters. Validate that it fits so that we don't risk an
297a8e1175bSopenharmony_ci     * overflow later. */
298a8e1175bSopenharmony_ci#if SIZE_MAX > UINT_MAX
299a8e1175bSopenharmony_ci    if ((int)hash_length > (int)UINT_MAX) {
300a8e1175bSopenharmony_ci        return PSA_ERROR_INVALID_ARGUMENT;
301a8e1175bSopenharmony_ci    }
302a8e1175bSopenharmony_ci#endif
303a8e1175bSopenharmony_ci
304a8e1175bSopenharmony_ci    /* For signatures using a hash, the hash length must be correct. */
305a8e1175bSopenharmony_ci    if (alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) {
306a8e1175bSopenharmony_ci        if (*md_alg == MBEDTLS_MD_NONE) {
307a8e1175bSopenharmony_ci            return PSA_ERROR_NOT_SUPPORTED;
308a8e1175bSopenharmony_ci        }
309a8e1175bSopenharmony_ci        if (mbedtls_md_get_size_from_type(*md_alg) != hash_length) {
310a8e1175bSopenharmony_ci            return PSA_ERROR_INVALID_ARGUMENT;
311a8e1175bSopenharmony_ci        }
312a8e1175bSopenharmony_ci    }
313a8e1175bSopenharmony_ci
314a8e1175bSopenharmony_ci    return PSA_SUCCESS;
315a8e1175bSopenharmony_ci}
316a8e1175bSopenharmony_ci
317a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_rsa_sign_hash(
318a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
319a8e1175bSopenharmony_ci    const uint8_t *key_buffer, size_t key_buffer_size,
320a8e1175bSopenharmony_ci    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
321a8e1175bSopenharmony_ci    uint8_t *signature, size_t signature_size, size_t *signature_length)
322a8e1175bSopenharmony_ci{
323a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
324a8e1175bSopenharmony_ci    mbedtls_rsa_context *rsa = NULL;
325a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
326a8e1175bSopenharmony_ci    mbedtls_md_type_t md_alg;
327a8e1175bSopenharmony_ci
328a8e1175bSopenharmony_ci    status = mbedtls_psa_rsa_load_representation(attributes->type,
329a8e1175bSopenharmony_ci                                                 key_buffer,
330a8e1175bSopenharmony_ci                                                 key_buffer_size,
331a8e1175bSopenharmony_ci                                                 &rsa);
332a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
333a8e1175bSopenharmony_ci        return status;
334a8e1175bSopenharmony_ci    }
335a8e1175bSopenharmony_ci
336a8e1175bSopenharmony_ci    status = psa_rsa_decode_md_type(alg, hash_length, &md_alg);
337a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
338a8e1175bSopenharmony_ci        goto exit;
339a8e1175bSopenharmony_ci    }
340a8e1175bSopenharmony_ci
341a8e1175bSopenharmony_ci    if (signature_size < mbedtls_rsa_get_len(rsa)) {
342a8e1175bSopenharmony_ci        status = PSA_ERROR_BUFFER_TOO_SMALL;
343a8e1175bSopenharmony_ci        goto exit;
344a8e1175bSopenharmony_ci    }
345a8e1175bSopenharmony_ci
346a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
347a8e1175bSopenharmony_ci    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
348a8e1175bSopenharmony_ci        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15,
349a8e1175bSopenharmony_ci                                      MBEDTLS_MD_NONE);
350a8e1175bSopenharmony_ci        if (ret == 0) {
351a8e1175bSopenharmony_ci            ret = mbedtls_rsa_pkcs1_sign(rsa,
352a8e1175bSopenharmony_ci                                         mbedtls_psa_get_random,
353a8e1175bSopenharmony_ci                                         MBEDTLS_PSA_RANDOM_STATE,
354a8e1175bSopenharmony_ci                                         md_alg,
355a8e1175bSopenharmony_ci                                         (unsigned int) hash_length,
356a8e1175bSopenharmony_ci                                         hash,
357a8e1175bSopenharmony_ci                                         signature);
358a8e1175bSopenharmony_ci        }
359a8e1175bSopenharmony_ci    } else
360a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
361a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
362a8e1175bSopenharmony_ci    if (PSA_ALG_IS_RSA_PSS(alg)) {
363a8e1175bSopenharmony_ci        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
364a8e1175bSopenharmony_ci
365a8e1175bSopenharmony_ci        if (ret == 0) {
366a8e1175bSopenharmony_ci            ret = mbedtls_rsa_rsassa_pss_sign(rsa,
367a8e1175bSopenharmony_ci                                              mbedtls_psa_get_random,
368a8e1175bSopenharmony_ci                                              MBEDTLS_PSA_RANDOM_STATE,
369a8e1175bSopenharmony_ci                                              MBEDTLS_MD_NONE,
370a8e1175bSopenharmony_ci                                              (unsigned int) hash_length,
371a8e1175bSopenharmony_ci                                              hash,
372a8e1175bSopenharmony_ci                                              signature);
373a8e1175bSopenharmony_ci        }
374a8e1175bSopenharmony_ci    } else
375a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
376a8e1175bSopenharmony_ci    {
377a8e1175bSopenharmony_ci        status = PSA_ERROR_INVALID_ARGUMENT;
378a8e1175bSopenharmony_ci        goto exit;
379a8e1175bSopenharmony_ci    }
380a8e1175bSopenharmony_ci
381a8e1175bSopenharmony_ci    if (ret == 0) {
382a8e1175bSopenharmony_ci        *signature_length = mbedtls_rsa_get_len(rsa);
383a8e1175bSopenharmony_ci    }
384a8e1175bSopenharmony_ci    status = mbedtls_to_psa_error(ret);
385a8e1175bSopenharmony_ci
386a8e1175bSopenharmony_ciexit:
387a8e1175bSopenharmony_ci    mbedtls_rsa_free(rsa);
388a8e1175bSopenharmony_ci    mbedtls_free(rsa);
389a8e1175bSopenharmony_ci
390a8e1175bSopenharmony_ci    return status;
391a8e1175bSopenharmony_ci}
392a8e1175bSopenharmony_ci
393a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
394a8e1175bSopenharmony_cistatic int rsa_pss_expected_salt_len(psa_algorithm_t alg,
395a8e1175bSopenharmony_ci                                     const mbedtls_rsa_context *rsa,
396a8e1175bSopenharmony_ci                                     size_t hash_length)
397a8e1175bSopenharmony_ci{
398a8e1175bSopenharmony_ci    if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) {
399a8e1175bSopenharmony_ci        return MBEDTLS_RSA_SALT_LEN_ANY;
400a8e1175bSopenharmony_ci    }
401a8e1175bSopenharmony_ci    /* Otherwise: standard salt length, i.e. largest possible salt length
402a8e1175bSopenharmony_ci     * up to the hash length. */
403a8e1175bSopenharmony_ci    int klen = (int) mbedtls_rsa_get_len(rsa);   // known to fit
404a8e1175bSopenharmony_ci    int hlen = (int) hash_length; // known to fit
405a8e1175bSopenharmony_ci    int room = klen - 2 - hlen;
406a8e1175bSopenharmony_ci    if (room < 0) {
407a8e1175bSopenharmony_ci        return 0;  // there is no valid signature in this case anyway
408a8e1175bSopenharmony_ci    } else if (room > hlen) {
409a8e1175bSopenharmony_ci        return hlen;
410a8e1175bSopenharmony_ci    } else {
411a8e1175bSopenharmony_ci        return room;
412a8e1175bSopenharmony_ci    }
413a8e1175bSopenharmony_ci}
414a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
415a8e1175bSopenharmony_ci
416a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_rsa_verify_hash(
417a8e1175bSopenharmony_ci    const psa_key_attributes_t *attributes,
418a8e1175bSopenharmony_ci    const uint8_t *key_buffer, size_t key_buffer_size,
419a8e1175bSopenharmony_ci    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
420a8e1175bSopenharmony_ci    const uint8_t *signature, size_t signature_length)
421a8e1175bSopenharmony_ci{
422a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
423a8e1175bSopenharmony_ci    mbedtls_rsa_context *rsa = NULL;
424a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
425a8e1175bSopenharmony_ci    mbedtls_md_type_t md_alg;
426a8e1175bSopenharmony_ci
427a8e1175bSopenharmony_ci    status = mbedtls_psa_rsa_load_representation(attributes->type,
428a8e1175bSopenharmony_ci                                                 key_buffer,
429a8e1175bSopenharmony_ci                                                 key_buffer_size,
430a8e1175bSopenharmony_ci                                                 &rsa);
431a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
432a8e1175bSopenharmony_ci        goto exit;
433a8e1175bSopenharmony_ci    }
434a8e1175bSopenharmony_ci
435a8e1175bSopenharmony_ci    status = psa_rsa_decode_md_type(alg, hash_length, &md_alg);
436a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
437a8e1175bSopenharmony_ci        goto exit;
438a8e1175bSopenharmony_ci    }
439a8e1175bSopenharmony_ci
440a8e1175bSopenharmony_ci    if (signature_length != mbedtls_rsa_get_len(rsa)) {
441a8e1175bSopenharmony_ci        status = PSA_ERROR_INVALID_SIGNATURE;
442a8e1175bSopenharmony_ci        goto exit;
443a8e1175bSopenharmony_ci    }
444a8e1175bSopenharmony_ci
445a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
446a8e1175bSopenharmony_ci    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
447a8e1175bSopenharmony_ci        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15,
448a8e1175bSopenharmony_ci                                      MBEDTLS_MD_NONE);
449a8e1175bSopenharmony_ci        if (ret == 0) {
450a8e1175bSopenharmony_ci            ret = mbedtls_rsa_pkcs1_verify(rsa,
451a8e1175bSopenharmony_ci                                           md_alg,
452a8e1175bSopenharmony_ci                                           (unsigned int) hash_length,
453a8e1175bSopenharmony_ci                                           hash,
454a8e1175bSopenharmony_ci                                           signature);
455a8e1175bSopenharmony_ci        }
456a8e1175bSopenharmony_ci    } else
457a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
458a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
459a8e1175bSopenharmony_ci    if (PSA_ALG_IS_RSA_PSS(alg)) {
460a8e1175bSopenharmony_ci        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
461a8e1175bSopenharmony_ci        if (ret == 0) {
462a8e1175bSopenharmony_ci            int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length);
463a8e1175bSopenharmony_ci            ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa,
464a8e1175bSopenharmony_ci                                                    md_alg,
465a8e1175bSopenharmony_ci                                                    (unsigned) hash_length,
466a8e1175bSopenharmony_ci                                                    hash,
467a8e1175bSopenharmony_ci                                                    md_alg,
468a8e1175bSopenharmony_ci                                                    slen,
469a8e1175bSopenharmony_ci                                                    signature);
470a8e1175bSopenharmony_ci        }
471a8e1175bSopenharmony_ci    } else
472a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
473a8e1175bSopenharmony_ci    {
474a8e1175bSopenharmony_ci        status = PSA_ERROR_INVALID_ARGUMENT;
475a8e1175bSopenharmony_ci        goto exit;
476a8e1175bSopenharmony_ci    }
477a8e1175bSopenharmony_ci
478a8e1175bSopenharmony_ci    /* Mbed TLS distinguishes "invalid padding" from "valid padding but
479a8e1175bSopenharmony_ci     * the rest of the signature is invalid". This has little use in
480a8e1175bSopenharmony_ci     * practice and PSA doesn't report this distinction. */
481a8e1175bSopenharmony_ci    status = (ret == MBEDTLS_ERR_RSA_INVALID_PADDING) ?
482a8e1175bSopenharmony_ci             PSA_ERROR_INVALID_SIGNATURE :
483a8e1175bSopenharmony_ci             mbedtls_to_psa_error(ret);
484a8e1175bSopenharmony_ci
485a8e1175bSopenharmony_ciexit:
486a8e1175bSopenharmony_ci    mbedtls_rsa_free(rsa);
487a8e1175bSopenharmony_ci    mbedtls_free(rsa);
488a8e1175bSopenharmony_ci
489a8e1175bSopenharmony_ci    return status;
490a8e1175bSopenharmony_ci}
491a8e1175bSopenharmony_ci
492a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
493a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
494a8e1175bSopenharmony_ci
495a8e1175bSopenharmony_ci/****************************************************************/
496a8e1175bSopenharmony_ci/* Asymmetric cryptography */
497a8e1175bSopenharmony_ci/****************************************************************/
498a8e1175bSopenharmony_ci
499a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
500a8e1175bSopenharmony_cistatic int psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg,
501a8e1175bSopenharmony_ci                                         mbedtls_rsa_context *rsa)
502a8e1175bSopenharmony_ci{
503a8e1175bSopenharmony_ci    psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg);
504a8e1175bSopenharmony_ci    mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
505a8e1175bSopenharmony_ci
506a8e1175bSopenharmony_ci    /* Just to get the error status right, as rsa_set_padding() doesn't
507a8e1175bSopenharmony_ci     * distinguish between "bad RSA algorithm" and "unknown hash". */
508a8e1175bSopenharmony_ci    if (mbedtls_md_info_from_type(md_alg) == NULL) {
509a8e1175bSopenharmony_ci        return PSA_ERROR_NOT_SUPPORTED;
510a8e1175bSopenharmony_ci    }
511a8e1175bSopenharmony_ci
512a8e1175bSopenharmony_ci    return mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
513a8e1175bSopenharmony_ci}
514a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
515a8e1175bSopenharmony_ci
516a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes,
517a8e1175bSopenharmony_ci                                            const uint8_t *key_buffer,
518a8e1175bSopenharmony_ci                                            size_t key_buffer_size,
519a8e1175bSopenharmony_ci                                            psa_algorithm_t alg,
520a8e1175bSopenharmony_ci                                            const uint8_t *input,
521a8e1175bSopenharmony_ci                                            size_t input_length,
522a8e1175bSopenharmony_ci                                            const uint8_t *salt,
523a8e1175bSopenharmony_ci                                            size_t salt_length,
524a8e1175bSopenharmony_ci                                            uint8_t *output,
525a8e1175bSopenharmony_ci                                            size_t output_size,
526a8e1175bSopenharmony_ci                                            size_t *output_length)
527a8e1175bSopenharmony_ci{
528a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
529a8e1175bSopenharmony_ci    (void) key_buffer;
530a8e1175bSopenharmony_ci    (void) key_buffer_size;
531a8e1175bSopenharmony_ci    (void) input;
532a8e1175bSopenharmony_ci    (void) input_length;
533a8e1175bSopenharmony_ci    (void) salt;
534a8e1175bSopenharmony_ci    (void) salt_length;
535a8e1175bSopenharmony_ci    (void) output;
536a8e1175bSopenharmony_ci    (void) output_size;
537a8e1175bSopenharmony_ci    (void) output_length;
538a8e1175bSopenharmony_ci
539a8e1175bSopenharmony_ci    if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {
540a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
541a8e1175bSopenharmony_ci        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
542a8e1175bSopenharmony_ci        mbedtls_rsa_context *rsa = NULL;
543a8e1175bSopenharmony_ci        status = mbedtls_psa_rsa_load_representation(attributes->type,
544a8e1175bSopenharmony_ci                                                     key_buffer,
545a8e1175bSopenharmony_ci                                                     key_buffer_size,
546a8e1175bSopenharmony_ci                                                     &rsa);
547a8e1175bSopenharmony_ci        if (status != PSA_SUCCESS) {
548a8e1175bSopenharmony_ci            goto rsa_exit;
549a8e1175bSopenharmony_ci        }
550a8e1175bSopenharmony_ci
551a8e1175bSopenharmony_ci        if (output_size < mbedtls_rsa_get_len(rsa)) {
552a8e1175bSopenharmony_ci            status = PSA_ERROR_BUFFER_TOO_SMALL;
553a8e1175bSopenharmony_ci            goto rsa_exit;
554a8e1175bSopenharmony_ci        }
555a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
556a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
557a8e1175bSopenharmony_ci        if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
558a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
559a8e1175bSopenharmony_ci            status = mbedtls_to_psa_error(
560a8e1175bSopenharmony_ci                mbedtls_rsa_pkcs1_encrypt(rsa,
561a8e1175bSopenharmony_ci                                          mbedtls_psa_get_random,
562a8e1175bSopenharmony_ci                                          MBEDTLS_PSA_RANDOM_STATE,
563a8e1175bSopenharmony_ci                                          input_length,
564a8e1175bSopenharmony_ci                                          input,
565a8e1175bSopenharmony_ci                                          output));
566a8e1175bSopenharmony_ci#else
567a8e1175bSopenharmony_ci            status = PSA_ERROR_NOT_SUPPORTED;
568a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
569a8e1175bSopenharmony_ci        } else
570a8e1175bSopenharmony_ci        if (PSA_ALG_IS_RSA_OAEP(alg)) {
571a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
572a8e1175bSopenharmony_ci            status = mbedtls_to_psa_error(
573a8e1175bSopenharmony_ci                psa_rsa_oaep_set_padding_mode(alg, rsa));
574a8e1175bSopenharmony_ci            if (status != PSA_SUCCESS) {
575a8e1175bSopenharmony_ci                goto rsa_exit;
576a8e1175bSopenharmony_ci            }
577a8e1175bSopenharmony_ci
578a8e1175bSopenharmony_ci            status = mbedtls_to_psa_error(
579a8e1175bSopenharmony_ci                mbedtls_rsa_rsaes_oaep_encrypt(rsa,
580a8e1175bSopenharmony_ci                                               mbedtls_psa_get_random,
581a8e1175bSopenharmony_ci                                               MBEDTLS_PSA_RANDOM_STATE,
582a8e1175bSopenharmony_ci                                               salt, salt_length,
583a8e1175bSopenharmony_ci                                               input_length,
584a8e1175bSopenharmony_ci                                               input,
585a8e1175bSopenharmony_ci                                               output));
586a8e1175bSopenharmony_ci#else
587a8e1175bSopenharmony_ci            status = PSA_ERROR_NOT_SUPPORTED;
588a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
589a8e1175bSopenharmony_ci        } else {
590a8e1175bSopenharmony_ci            status = PSA_ERROR_INVALID_ARGUMENT;
591a8e1175bSopenharmony_ci        }
592a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
593a8e1175bSopenharmony_ci        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
594a8e1175bSopenharmony_cirsa_exit:
595a8e1175bSopenharmony_ci        if (status == PSA_SUCCESS) {
596a8e1175bSopenharmony_ci            *output_length = mbedtls_rsa_get_len(rsa);
597a8e1175bSopenharmony_ci        }
598a8e1175bSopenharmony_ci
599a8e1175bSopenharmony_ci        mbedtls_rsa_free(rsa);
600a8e1175bSopenharmony_ci        mbedtls_free(rsa);
601a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
602a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
603a8e1175bSopenharmony_ci    } else {
604a8e1175bSopenharmony_ci        status = PSA_ERROR_NOT_SUPPORTED;
605a8e1175bSopenharmony_ci    }
606a8e1175bSopenharmony_ci
607a8e1175bSopenharmony_ci    return status;
608a8e1175bSopenharmony_ci}
609a8e1175bSopenharmony_ci
610a8e1175bSopenharmony_cipsa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes,
611a8e1175bSopenharmony_ci                                            const uint8_t *key_buffer,
612a8e1175bSopenharmony_ci                                            size_t key_buffer_size,
613a8e1175bSopenharmony_ci                                            psa_algorithm_t alg,
614a8e1175bSopenharmony_ci                                            const uint8_t *input,
615a8e1175bSopenharmony_ci                                            size_t input_length,
616a8e1175bSopenharmony_ci                                            const uint8_t *salt,
617a8e1175bSopenharmony_ci                                            size_t salt_length,
618a8e1175bSopenharmony_ci                                            uint8_t *output,
619a8e1175bSopenharmony_ci                                            size_t output_size,
620a8e1175bSopenharmony_ci                                            size_t *output_length)
621a8e1175bSopenharmony_ci{
622a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
623a8e1175bSopenharmony_ci    (void) key_buffer;
624a8e1175bSopenharmony_ci    (void) key_buffer_size;
625a8e1175bSopenharmony_ci    (void) input;
626a8e1175bSopenharmony_ci    (void) input_length;
627a8e1175bSopenharmony_ci    (void) salt;
628a8e1175bSopenharmony_ci    (void) salt_length;
629a8e1175bSopenharmony_ci    (void) output;
630a8e1175bSopenharmony_ci    (void) output_size;
631a8e1175bSopenharmony_ci    (void) output_length;
632a8e1175bSopenharmony_ci
633a8e1175bSopenharmony_ci    *output_length = 0;
634a8e1175bSopenharmony_ci
635a8e1175bSopenharmony_ci    if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
636a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
637a8e1175bSopenharmony_ci        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
638a8e1175bSopenharmony_ci        mbedtls_rsa_context *rsa = NULL;
639a8e1175bSopenharmony_ci        status = mbedtls_psa_rsa_load_representation(attributes->type,
640a8e1175bSopenharmony_ci                                                     key_buffer,
641a8e1175bSopenharmony_ci                                                     key_buffer_size,
642a8e1175bSopenharmony_ci                                                     &rsa);
643a8e1175bSopenharmony_ci        if (status != PSA_SUCCESS) {
644a8e1175bSopenharmony_ci            goto rsa_exit;
645a8e1175bSopenharmony_ci        }
646a8e1175bSopenharmony_ci
647a8e1175bSopenharmony_ci        if (input_length != mbedtls_rsa_get_len(rsa)) {
648a8e1175bSopenharmony_ci            status = PSA_ERROR_INVALID_ARGUMENT;
649a8e1175bSopenharmony_ci            goto rsa_exit;
650a8e1175bSopenharmony_ci        }
651a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
652a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
653a8e1175bSopenharmony_ci
654a8e1175bSopenharmony_ci        if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
655a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
656a8e1175bSopenharmony_ci            status = mbedtls_to_psa_error(
657a8e1175bSopenharmony_ci                mbedtls_rsa_pkcs1_decrypt(rsa,
658a8e1175bSopenharmony_ci                                          mbedtls_psa_get_random,
659a8e1175bSopenharmony_ci                                          MBEDTLS_PSA_RANDOM_STATE,
660a8e1175bSopenharmony_ci                                          output_length,
661a8e1175bSopenharmony_ci                                          input,
662a8e1175bSopenharmony_ci                                          output,
663a8e1175bSopenharmony_ci                                          output_size));
664a8e1175bSopenharmony_ci#else
665a8e1175bSopenharmony_ci            status = PSA_ERROR_NOT_SUPPORTED;
666a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
667a8e1175bSopenharmony_ci        } else
668a8e1175bSopenharmony_ci        if (PSA_ALG_IS_RSA_OAEP(alg)) {
669a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
670a8e1175bSopenharmony_ci            status = mbedtls_to_psa_error(
671a8e1175bSopenharmony_ci                psa_rsa_oaep_set_padding_mode(alg, rsa));
672a8e1175bSopenharmony_ci            if (status != PSA_SUCCESS) {
673a8e1175bSopenharmony_ci                goto rsa_exit;
674a8e1175bSopenharmony_ci            }
675a8e1175bSopenharmony_ci
676a8e1175bSopenharmony_ci            status = mbedtls_to_psa_error(
677a8e1175bSopenharmony_ci                mbedtls_rsa_rsaes_oaep_decrypt(rsa,
678a8e1175bSopenharmony_ci                                               mbedtls_psa_get_random,
679a8e1175bSopenharmony_ci                                               MBEDTLS_PSA_RANDOM_STATE,
680a8e1175bSopenharmony_ci                                               salt, salt_length,
681a8e1175bSopenharmony_ci                                               output_length,
682a8e1175bSopenharmony_ci                                               input,
683a8e1175bSopenharmony_ci                                               output,
684a8e1175bSopenharmony_ci                                               output_size));
685a8e1175bSopenharmony_ci#else
686a8e1175bSopenharmony_ci            status = PSA_ERROR_NOT_SUPPORTED;
687a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
688a8e1175bSopenharmony_ci        } else {
689a8e1175bSopenharmony_ci            status = PSA_ERROR_INVALID_ARGUMENT;
690a8e1175bSopenharmony_ci        }
691a8e1175bSopenharmony_ci
692a8e1175bSopenharmony_ci#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
693a8e1175bSopenharmony_ci        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
694a8e1175bSopenharmony_cirsa_exit:
695a8e1175bSopenharmony_ci        mbedtls_rsa_free(rsa);
696a8e1175bSopenharmony_ci        mbedtls_free(rsa);
697a8e1175bSopenharmony_ci#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
698a8e1175bSopenharmony_ci        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
699a8e1175bSopenharmony_ci    } else {
700a8e1175bSopenharmony_ci        status = PSA_ERROR_NOT_SUPPORTED;
701a8e1175bSopenharmony_ci    }
702a8e1175bSopenharmony_ci
703a8e1175bSopenharmony_ci    return status;
704a8e1175bSopenharmony_ci}
705a8e1175bSopenharmony_ci
706a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_CRYPTO_C */
707