xref: /optee_os/lib/libmbedtls/mbedtls/library/rsa.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  The RSA public-key cryptosystem
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
193d3b0591SJens Wiklander 
20817466cbSJens Wiklander /*
21817466cbSJens Wiklander  *  The following sources were referenced in the design of this implementation
22817466cbSJens Wiklander  *  of the RSA algorithm:
23817466cbSJens Wiklander  *
24817466cbSJens Wiklander  *  [1] A method for obtaining digital signatures and public-key cryptosystems
25817466cbSJens Wiklander  *      R Rivest, A Shamir, and L Adleman
26817466cbSJens Wiklander  *      http://people.csail.mit.edu/rivest/pubs.html#RSA78
27817466cbSJens Wiklander  *
28817466cbSJens Wiklander  *  [2] Handbook of Applied Cryptography - 1997, Chapter 8
29817466cbSJens Wiklander  *      Menezes, van Oorschot and Vanstone
30817466cbSJens Wiklander  *
31817466cbSJens Wiklander  *  [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks
32817466cbSJens Wiklander  *      Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and
33817466cbSJens Wiklander  *      Stefan Mangard
34817466cbSJens Wiklander  *      https://arxiv.org/abs/1702.08719v2
35817466cbSJens Wiklander  *
36817466cbSJens Wiklander  */
37817466cbSJens Wiklander 
387901324dSJerome Forissier #include "common.h"
39817466cbSJens Wiklander 
40817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
41817466cbSJens Wiklander 
42817466cbSJens Wiklander #include "mbedtls/rsa.h"
43*32b31808SJens Wiklander #include "rsa_alt_helpers.h"
44817466cbSJens Wiklander #include "mbedtls/oid.h"
453d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
4611fa71b9SJerome Forissier #include "mbedtls/error.h"
47039e02dfSJerome Forissier #include "constant_time_internal.h"
48039e02dfSJerome Forissier #include "mbedtls/constant_time.h"
49*32b31808SJens Wiklander #include "hash_info.h"
50817466cbSJens Wiklander 
51817466cbSJens Wiklander #include <string.h>
52817466cbSJens Wiklander 
537901324dSJerome Forissier #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__)
54817466cbSJens Wiklander #include <stdlib.h>
55817466cbSJens Wiklander #endif
56817466cbSJens Wiklander 
57*32b31808SJens Wiklander /* We use MD first if it's available (for compatibility reasons)
58*32b31808SJens Wiklander  * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */
59*32b31808SJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
60*32b31808SJens Wiklander #if !defined(MBEDTLS_MD_C)
61*32b31808SJens Wiklander #include "psa/crypto.h"
62*32b31808SJens Wiklander #include "mbedtls/psa_util.h"
63*32b31808SJens Wiklander #define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
64*32b31808SJens Wiklander                                                            psa_to_md_errors,              \
65*32b31808SJens Wiklander                                                            psa_generic_status_to_mbedtls)
66*32b31808SJens Wiklander #endif /* !MBEDTLS_MD_C */
67*32b31808SJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */
68*32b31808SJens Wiklander 
69817466cbSJens Wiklander #include "mbedtls/platform.h"
70817466cbSJens Wiklander 
71a846630fSJens Wiklander #include <fault_mitigation.h>
72a846630fSJens Wiklander 
733d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_ALT)
743d3b0591SJens Wiklander 
753d3b0591SJens Wiklander int mbedtls_rsa_import(mbedtls_rsa_context *ctx,
763d3b0591SJens Wiklander                        const mbedtls_mpi *N,
773d3b0591SJens Wiklander                        const mbedtls_mpi *P, const mbedtls_mpi *Q,
783d3b0591SJens Wiklander                        const mbedtls_mpi *D, const mbedtls_mpi *E)
793d3b0591SJens Wiklander {
8011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
813d3b0591SJens Wiklander 
823d3b0591SJens Wiklander     if ((N != NULL && (ret = mbedtls_mpi_copy(&ctx->N, N)) != 0) ||
833d3b0591SJens Wiklander         (P != NULL && (ret = mbedtls_mpi_copy(&ctx->P, P)) != 0) ||
843d3b0591SJens Wiklander         (Q != NULL && (ret = mbedtls_mpi_copy(&ctx->Q, Q)) != 0) ||
853d3b0591SJens Wiklander         (D != NULL && (ret = mbedtls_mpi_copy(&ctx->D, D)) != 0) ||
86*32b31808SJens Wiklander         (E != NULL && (ret = mbedtls_mpi_copy(&ctx->E, E)) != 0)) {
87*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
883d3b0591SJens Wiklander     }
893d3b0591SJens Wiklander 
90*32b31808SJens Wiklander     if (N != NULL) {
913d3b0591SJens Wiklander         ctx->len = mbedtls_mpi_size(&ctx->N);
92*32b31808SJens Wiklander     }
933d3b0591SJens Wiklander 
94*32b31808SJens Wiklander     return 0;
953d3b0591SJens Wiklander }
963d3b0591SJens Wiklander 
973d3b0591SJens Wiklander int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx,
983d3b0591SJens Wiklander                            unsigned char const *N, size_t N_len,
993d3b0591SJens Wiklander                            unsigned char const *P, size_t P_len,
1003d3b0591SJens Wiklander                            unsigned char const *Q, size_t Q_len,
1013d3b0591SJens Wiklander                            unsigned char const *D, size_t D_len,
1023d3b0591SJens Wiklander                            unsigned char const *E, size_t E_len)
1033d3b0591SJens Wiklander {
1043d3b0591SJens Wiklander     int ret = 0;
1053d3b0591SJens Wiklander 
106*32b31808SJens Wiklander     if (N != NULL) {
1073d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->N, N, N_len));
1083d3b0591SJens Wiklander         ctx->len = mbedtls_mpi_size(&ctx->N);
1093d3b0591SJens Wiklander     }
1103d3b0591SJens Wiklander 
111*32b31808SJens Wiklander     if (P != NULL) {
1123d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->P, P, P_len));
113*32b31808SJens Wiklander     }
1143d3b0591SJens Wiklander 
115*32b31808SJens Wiklander     if (Q != NULL) {
1163d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->Q, Q, Q_len));
117*32b31808SJens Wiklander     }
1183d3b0591SJens Wiklander 
119*32b31808SJens Wiklander     if (D != NULL) {
1203d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->D, D, D_len));
121*32b31808SJens Wiklander     }
1223d3b0591SJens Wiklander 
123*32b31808SJens Wiklander     if (E != NULL) {
1243d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->E, E, E_len));
125*32b31808SJens Wiklander     }
1263d3b0591SJens Wiklander 
1273d3b0591SJens Wiklander cleanup:
1283d3b0591SJens Wiklander 
129*32b31808SJens Wiklander     if (ret != 0) {
130*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
131*32b31808SJens Wiklander     }
1323d3b0591SJens Wiklander 
133*32b31808SJens Wiklander     return 0;
1343d3b0591SJens Wiklander }
1353d3b0591SJens Wiklander 
1363d3b0591SJens Wiklander /*
1373d3b0591SJens Wiklander  * Checks whether the context fields are set in such a way
1383d3b0591SJens Wiklander  * that the RSA primitives will be able to execute without error.
1393d3b0591SJens Wiklander  * It does *not* make guarantees for consistency of the parameters.
1403d3b0591SJens Wiklander  */
1413d3b0591SJens Wiklander static int rsa_check_context(mbedtls_rsa_context const *ctx, int is_priv,
1423d3b0591SJens Wiklander                              int blinding_needed)
1433d3b0591SJens Wiklander {
1443d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
1453d3b0591SJens Wiklander     /* blinding_needed is only used for NO_CRT to decide whether
1463d3b0591SJens Wiklander      * P,Q need to be present or not. */
1473d3b0591SJens Wiklander     ((void) blinding_needed);
1483d3b0591SJens Wiklander #endif
1493d3b0591SJens Wiklander 
1503d3b0591SJens Wiklander     if (ctx->len != mbedtls_mpi_size(&ctx->N) ||
151*32b31808SJens Wiklander         ctx->len > MBEDTLS_MPI_MAX_SIZE) {
152*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1533d3b0591SJens Wiklander     }
1543d3b0591SJens Wiklander 
1553d3b0591SJens Wiklander     /*
1563d3b0591SJens Wiklander      * 1. Modular exponentiation needs positive, odd moduli.
1573d3b0591SJens Wiklander      */
1583d3b0591SJens Wiklander 
1593d3b0591SJens Wiklander     /* Modular exponentiation wrt. N is always used for
1603d3b0591SJens Wiklander      * RSA public key operations. */
1613d3b0591SJens Wiklander     if (mbedtls_mpi_cmp_int(&ctx->N, 0) <= 0 ||
162*32b31808SJens Wiklander         mbedtls_mpi_get_bit(&ctx->N, 0) == 0) {
163*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1643d3b0591SJens Wiklander     }
1653d3b0591SJens Wiklander 
1663d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
1673d3b0591SJens Wiklander     /* Modular exponentiation for P and Q is only
1683d3b0591SJens Wiklander      * used for private key operations and if CRT
1693d3b0591SJens Wiklander      * is used. */
1703d3b0591SJens Wiklander     if (is_priv &&
1713d3b0591SJens Wiklander         (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 ||
1723d3b0591SJens Wiklander          mbedtls_mpi_get_bit(&ctx->P, 0) == 0 ||
1733d3b0591SJens Wiklander          mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0 ||
174*32b31808SJens Wiklander          mbedtls_mpi_get_bit(&ctx->Q, 0) == 0)) {
175*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1763d3b0591SJens Wiklander     }
1773d3b0591SJens Wiklander #endif /* !MBEDTLS_RSA_NO_CRT */
1783d3b0591SJens Wiklander 
1793d3b0591SJens Wiklander     /*
1803d3b0591SJens Wiklander      * 2. Exponents must be positive
1813d3b0591SJens Wiklander      */
1823d3b0591SJens Wiklander 
1833d3b0591SJens Wiklander     /* Always need E for public key operations */
184*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(&ctx->E, 0) <= 0) {
185*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
186*32b31808SJens Wiklander     }
1873d3b0591SJens Wiklander 
1883d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT)
1893d3b0591SJens Wiklander     /* For private key operations, use D or DP & DQ
1903d3b0591SJens Wiklander      * as (unblinded) exponents. */
191*32b31808SJens Wiklander     if (is_priv && mbedtls_mpi_cmp_int(&ctx->D, 0) <= 0) {
192*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
193*32b31808SJens Wiklander     }
1943d3b0591SJens Wiklander #else
1953d3b0591SJens Wiklander     if (is_priv &&
1963d3b0591SJens Wiklander         (mbedtls_mpi_cmp_int(&ctx->DP, 0) <= 0 ||
197*32b31808SJens Wiklander          mbedtls_mpi_cmp_int(&ctx->DQ, 0) <= 0)) {
198*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1993d3b0591SJens Wiklander     }
2003d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */
2013d3b0591SJens Wiklander 
2023d3b0591SJens Wiklander     /* Blinding shouldn't make exponents negative either,
2033d3b0591SJens Wiklander      * so check that P, Q >= 1 if that hasn't yet been
2043d3b0591SJens Wiklander      * done as part of 1. */
2053d3b0591SJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT)
2063d3b0591SJens Wiklander     if (is_priv && blinding_needed &&
2073d3b0591SJens Wiklander         (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 ||
208*32b31808SJens Wiklander          mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0)) {
209*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2103d3b0591SJens Wiklander     }
2113d3b0591SJens Wiklander #endif
2123d3b0591SJens Wiklander 
2133d3b0591SJens Wiklander     /* It wouldn't lead to an error if it wasn't satisfied,
2143d3b0591SJens Wiklander      * but check for QP >= 1 nonetheless. */
2153d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
2163d3b0591SJens Wiklander     if (is_priv &&
217*32b31808SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->QP, 0) <= 0) {
218*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2193d3b0591SJens Wiklander     }
2203d3b0591SJens Wiklander #endif
2213d3b0591SJens Wiklander 
222*32b31808SJens Wiklander     return 0;
2233d3b0591SJens Wiklander }
2243d3b0591SJens Wiklander 
2253d3b0591SJens Wiklander int mbedtls_rsa_complete(mbedtls_rsa_context *ctx)
2263d3b0591SJens Wiklander {
2273d3b0591SJens Wiklander     int ret = 0;
2283d3b0591SJens Wiklander     int have_N, have_P, have_Q, have_D, have_E;
2295b25c76aSJerome Forissier #if !defined(MBEDTLS_RSA_NO_CRT)
2305b25c76aSJerome Forissier     int have_DP, have_DQ, have_QP;
2315b25c76aSJerome Forissier #endif
2323d3b0591SJens Wiklander     int n_missing, pq_missing, d_missing, is_pub, is_priv;
2333d3b0591SJens Wiklander 
2343d3b0591SJens Wiklander     have_N = (mbedtls_mpi_cmp_int(&ctx->N, 0) != 0);
2353d3b0591SJens Wiklander     have_P = (mbedtls_mpi_cmp_int(&ctx->P, 0) != 0);
2363d3b0591SJens Wiklander     have_Q = (mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0);
2373d3b0591SJens Wiklander     have_D = (mbedtls_mpi_cmp_int(&ctx->D, 0) != 0);
2383d3b0591SJens Wiklander     have_E = (mbedtls_mpi_cmp_int(&ctx->E, 0) != 0);
2393d3b0591SJens Wiklander 
2405b25c76aSJerome Forissier #if !defined(MBEDTLS_RSA_NO_CRT)
2415b25c76aSJerome Forissier     have_DP = (mbedtls_mpi_cmp_int(&ctx->DP, 0) != 0);
2425b25c76aSJerome Forissier     have_DQ = (mbedtls_mpi_cmp_int(&ctx->DQ, 0) != 0);
2435b25c76aSJerome Forissier     have_QP = (mbedtls_mpi_cmp_int(&ctx->QP, 0) != 0);
2445b25c76aSJerome Forissier #endif
2455b25c76aSJerome Forissier 
2463d3b0591SJens Wiklander     /*
2473d3b0591SJens Wiklander      * Check whether provided parameters are enough
2483d3b0591SJens Wiklander      * to deduce all others. The following incomplete
2493d3b0591SJens Wiklander      * parameter sets for private keys are supported:
2503d3b0591SJens Wiklander      *
2513d3b0591SJens Wiklander      * (1) P, Q missing.
2523d3b0591SJens Wiklander      * (2) D and potentially N missing.
2533d3b0591SJens Wiklander      *
2543d3b0591SJens Wiklander      */
2553d3b0591SJens Wiklander 
2563d3b0591SJens Wiklander     n_missing  =              have_P &&  have_Q &&  have_D && have_E;
2573d3b0591SJens Wiklander     pq_missing =   have_N && !have_P && !have_Q &&  have_D && have_E;
2583d3b0591SJens Wiklander     d_missing  =              have_P &&  have_Q && !have_D && have_E;
2593d3b0591SJens Wiklander     is_pub     =   have_N && !have_P && !have_Q && !have_D && have_E;
2603d3b0591SJens Wiklander 
2613d3b0591SJens Wiklander     /* These three alternatives are mutually exclusive */
2623d3b0591SJens Wiklander     is_priv = n_missing || pq_missing || d_missing;
2633d3b0591SJens Wiklander 
264*32b31808SJens Wiklander     if (!is_priv && !is_pub) {
265*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
266*32b31808SJens Wiklander     }
2673d3b0591SJens Wiklander 
2683d3b0591SJens Wiklander     /*
2693d3b0591SJens Wiklander      * Step 1: Deduce N if P, Q are provided.
2703d3b0591SJens Wiklander      */
2713d3b0591SJens Wiklander 
272*32b31808SJens Wiklander     if (!have_N && have_P && have_Q) {
2733d3b0591SJens Wiklander         if ((ret = mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P,
274*32b31808SJens Wiklander                                        &ctx->Q)) != 0) {
275*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
2763d3b0591SJens Wiklander         }
2773d3b0591SJens Wiklander 
2783d3b0591SJens Wiklander         ctx->len = mbedtls_mpi_size(&ctx->N);
2793d3b0591SJens Wiklander     }
2803d3b0591SJens Wiklander 
2813d3b0591SJens Wiklander     /*
2823d3b0591SJens Wiklander      * Step 2: Deduce and verify all remaining core parameters.
2833d3b0591SJens Wiklander      */
2843d3b0591SJens Wiklander 
285*32b31808SJens Wiklander     if (pq_missing) {
2863d3b0591SJens Wiklander         ret = mbedtls_rsa_deduce_primes(&ctx->N, &ctx->E, &ctx->D,
2873d3b0591SJens Wiklander                                         &ctx->P, &ctx->Q);
288*32b31808SJens Wiklander         if (ret != 0) {
289*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
2903d3b0591SJens Wiklander         }
291*32b31808SJens Wiklander 
292*32b31808SJens Wiklander     } else if (d_missing) {
2933d3b0591SJens Wiklander         if ((ret = mbedtls_rsa_deduce_private_exponent(&ctx->P,
2943d3b0591SJens Wiklander                                                        &ctx->Q,
2953d3b0591SJens Wiklander                                                        &ctx->E,
296*32b31808SJens Wiklander                                                        &ctx->D)) != 0) {
297*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
2983d3b0591SJens Wiklander         }
2993d3b0591SJens Wiklander     }
3003d3b0591SJens Wiklander 
3013d3b0591SJens Wiklander     /*
3023d3b0591SJens Wiklander      * Step 3: Deduce all additional parameters specific
3033d3b0591SJens Wiklander      *         to our current RSA implementation.
3043d3b0591SJens Wiklander      */
3053d3b0591SJens Wiklander 
3063d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
307*32b31808SJens Wiklander     if (is_priv && !(have_DP && have_DQ && have_QP)) {
3083d3b0591SJens Wiklander         ret = mbedtls_rsa_deduce_crt(&ctx->P,  &ctx->Q,  &ctx->D,
3093d3b0591SJens Wiklander                                      &ctx->DP, &ctx->DQ, &ctx->QP);
310*32b31808SJens Wiklander         if (ret != 0) {
311*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
312*32b31808SJens Wiklander         }
3133d3b0591SJens Wiklander     }
3143d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */
3153d3b0591SJens Wiklander 
3163d3b0591SJens Wiklander     /*
3173d3b0591SJens Wiklander      * Step 3: Basic sanity checks
3183d3b0591SJens Wiklander      */
3193d3b0591SJens Wiklander 
320*32b31808SJens Wiklander     return rsa_check_context(ctx, is_priv, 1);
3213d3b0591SJens Wiklander }
3223d3b0591SJens Wiklander 
3233d3b0591SJens Wiklander int mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx,
3243d3b0591SJens Wiklander                            unsigned char *N, size_t N_len,
3253d3b0591SJens Wiklander                            unsigned char *P, size_t P_len,
3263d3b0591SJens Wiklander                            unsigned char *Q, size_t Q_len,
3273d3b0591SJens Wiklander                            unsigned char *D, size_t D_len,
3283d3b0591SJens Wiklander                            unsigned char *E, size_t E_len)
3293d3b0591SJens Wiklander {
3303d3b0591SJens Wiklander     int ret = 0;
3313d3b0591SJens Wiklander     int is_priv;
3323d3b0591SJens Wiklander 
3333d3b0591SJens Wiklander     /* Check if key is private or public */
3343d3b0591SJens Wiklander     is_priv =
3353d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&
3363d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&
3373d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&
3383d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&
3393d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;
3403d3b0591SJens Wiklander 
341*32b31808SJens Wiklander     if (!is_priv) {
3423d3b0591SJens Wiklander         /* If we're trying to export private parameters for a public key,
3433d3b0591SJens Wiklander          * something must be wrong. */
344*32b31808SJens Wiklander         if (P != NULL || Q != NULL || D != NULL) {
345*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
346*32b31808SJens Wiklander         }
3473d3b0591SJens Wiklander 
3483d3b0591SJens Wiklander     }
3493d3b0591SJens Wiklander 
350*32b31808SJens Wiklander     if (N != NULL) {
3513d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->N, N, N_len));
352*32b31808SJens Wiklander     }
3533d3b0591SJens Wiklander 
354*32b31808SJens Wiklander     if (P != NULL) {
3553d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->P, P, P_len));
356*32b31808SJens Wiklander     }
3573d3b0591SJens Wiklander 
358*32b31808SJens Wiklander     if (Q != NULL) {
3593d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->Q, Q, Q_len));
360*32b31808SJens Wiklander     }
3613d3b0591SJens Wiklander 
362*32b31808SJens Wiklander     if (D != NULL) {
3633d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->D, D, D_len));
364*32b31808SJens Wiklander     }
3653d3b0591SJens Wiklander 
366*32b31808SJens Wiklander     if (E != NULL) {
3673d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->E, E, E_len));
368*32b31808SJens Wiklander     }
3693d3b0591SJens Wiklander 
3703d3b0591SJens Wiklander cleanup:
3713d3b0591SJens Wiklander 
372*32b31808SJens Wiklander     return ret;
3733d3b0591SJens Wiklander }
3743d3b0591SJens Wiklander 
3753d3b0591SJens Wiklander int mbedtls_rsa_export(const mbedtls_rsa_context *ctx,
3763d3b0591SJens Wiklander                        mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,
3773d3b0591SJens Wiklander                        mbedtls_mpi *D, mbedtls_mpi *E)
3783d3b0591SJens Wiklander {
37911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3803d3b0591SJens Wiklander     int is_priv;
3813d3b0591SJens Wiklander 
3823d3b0591SJens Wiklander     /* Check if key is private or public */
3833d3b0591SJens Wiklander     is_priv =
3843d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&
3853d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&
3863d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&
3873d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&
3883d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;
3893d3b0591SJens Wiklander 
390*32b31808SJens Wiklander     if (!is_priv) {
3913d3b0591SJens Wiklander         /* If we're trying to export private parameters for a public key,
3923d3b0591SJens Wiklander          * something must be wrong. */
393*32b31808SJens Wiklander         if (P != NULL || Q != NULL || D != NULL) {
394*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
395*32b31808SJens Wiklander         }
3963d3b0591SJens Wiklander 
3973d3b0591SJens Wiklander     }
3983d3b0591SJens Wiklander 
3993d3b0591SJens Wiklander     /* Export all requested core parameters. */
4003d3b0591SJens Wiklander 
4013d3b0591SJens Wiklander     if ((N != NULL && (ret = mbedtls_mpi_copy(N, &ctx->N)) != 0) ||
4023d3b0591SJens Wiklander         (P != NULL && (ret = mbedtls_mpi_copy(P, &ctx->P)) != 0) ||
4033d3b0591SJens Wiklander         (Q != NULL && (ret = mbedtls_mpi_copy(Q, &ctx->Q)) != 0) ||
4043d3b0591SJens Wiklander         (D != NULL && (ret = mbedtls_mpi_copy(D, &ctx->D)) != 0) ||
405*32b31808SJens Wiklander         (E != NULL && (ret = mbedtls_mpi_copy(E, &ctx->E)) != 0)) {
406*32b31808SJens Wiklander         return ret;
4073d3b0591SJens Wiklander     }
4083d3b0591SJens Wiklander 
409*32b31808SJens Wiklander     return 0;
4103d3b0591SJens Wiklander }
4113d3b0591SJens Wiklander 
4123d3b0591SJens Wiklander /*
4133d3b0591SJens Wiklander  * Export CRT parameters
4143d3b0591SJens Wiklander  * This must also be implemented if CRT is not used, for being able to
4153d3b0591SJens Wiklander  * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt
4163d3b0591SJens Wiklander  * can be used in this case.
4173d3b0591SJens Wiklander  */
4183d3b0591SJens Wiklander int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx,
4193d3b0591SJens Wiklander                            mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP)
4203d3b0591SJens Wiklander {
42111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4223d3b0591SJens Wiklander     int is_priv;
4233d3b0591SJens Wiklander 
4243d3b0591SJens Wiklander     /* Check if key is private or public */
4253d3b0591SJens Wiklander     is_priv =
4263d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&
4273d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&
4283d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&
4293d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&
4303d3b0591SJens Wiklander         mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;
4313d3b0591SJens Wiklander 
432*32b31808SJens Wiklander     if (!is_priv) {
433*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
434*32b31808SJens Wiklander     }
4353d3b0591SJens Wiklander 
4363d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
4373d3b0591SJens Wiklander     /* Export all requested blinding parameters. */
4383d3b0591SJens Wiklander     if ((DP != NULL && (ret = mbedtls_mpi_copy(DP, &ctx->DP)) != 0) ||
4393d3b0591SJens Wiklander         (DQ != NULL && (ret = mbedtls_mpi_copy(DQ, &ctx->DQ)) != 0) ||
440*32b31808SJens Wiklander         (QP != NULL && (ret = mbedtls_mpi_copy(QP, &ctx->QP)) != 0)) {
441*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
4423d3b0591SJens Wiklander     }
4433d3b0591SJens Wiklander #else
4443d3b0591SJens Wiklander     if ((ret = mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,
445*32b31808SJens Wiklander                                       DP, DQ, QP)) != 0) {
446*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
4473d3b0591SJens Wiklander     }
4483d3b0591SJens Wiklander #endif
4493d3b0591SJens Wiklander 
450*32b31808SJens Wiklander     return 0;
451817466cbSJens Wiklander }
452817466cbSJens Wiklander 
453817466cbSJens Wiklander /*
454817466cbSJens Wiklander  * Initialize an RSA context
455817466cbSJens Wiklander  */
456*32b31808SJens Wiklander void mbedtls_rsa_init(mbedtls_rsa_context *ctx)
457817466cbSJens Wiklander {
458817466cbSJens Wiklander     memset(ctx, 0, sizeof(mbedtls_rsa_context));
459817466cbSJens Wiklander 
460*32b31808SJens Wiklander     ctx->padding = MBEDTLS_RSA_PKCS_V15;
461*32b31808SJens Wiklander     ctx->hash_id = MBEDTLS_MD_NONE;
462817466cbSJens Wiklander 
463817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
4647901324dSJerome Forissier     /* Set ctx->ver to nonzero to indicate that the mutex has been
4657901324dSJerome Forissier      * initialized and will need to be freed. */
4667901324dSJerome Forissier     ctx->ver = 1;
467817466cbSJens Wiklander     mbedtls_mutex_init(&ctx->mutex);
468817466cbSJens Wiklander #endif
469817466cbSJens Wiklander }
470817466cbSJens Wiklander 
471817466cbSJens Wiklander /*
472817466cbSJens Wiklander  * Set padding for an existing RSA context
473817466cbSJens Wiklander  */
474*32b31808SJens Wiklander int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding,
475*32b31808SJens Wiklander                             mbedtls_md_type_t hash_id)
476817466cbSJens Wiklander {
477*32b31808SJens Wiklander     switch (padding) {
478*32b31808SJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
479*32b31808SJens Wiklander         case MBEDTLS_RSA_PKCS_V15:
480*32b31808SJens Wiklander             break;
481*32b31808SJens Wiklander #endif
482*32b31808SJens Wiklander 
483*32b31808SJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
484*32b31808SJens Wiklander         case MBEDTLS_RSA_PKCS_V21:
485*32b31808SJens Wiklander             break;
486*32b31808SJens Wiklander #endif
487*32b31808SJens Wiklander         default:
488*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_INVALID_PADDING;
489*32b31808SJens Wiklander     }
490*32b31808SJens Wiklander 
491*32b31808SJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
492*32b31808SJens Wiklander     if ((padding == MBEDTLS_RSA_PKCS_V21) &&
493*32b31808SJens Wiklander         (hash_id != MBEDTLS_MD_NONE)) {
494*32b31808SJens Wiklander         /* Just make sure this hash is supported in this build. */
495*32b31808SJens Wiklander         if (mbedtls_hash_info_psa_from_md(hash_id) == PSA_ALG_NONE) {
496*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_INVALID_PADDING;
497*32b31808SJens Wiklander         }
498*32b31808SJens Wiklander     }
499*32b31808SJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */
5003d3b0591SJens Wiklander 
501817466cbSJens Wiklander     ctx->padding = padding;
502817466cbSJens Wiklander     ctx->hash_id = hash_id;
503*32b31808SJens Wiklander 
504*32b31808SJens Wiklander     return 0;
505*32b31808SJens Wiklander }
506*32b31808SJens Wiklander 
507*32b31808SJens Wiklander /*
508*32b31808SJens Wiklander  * Get padding mode of initialized RSA context
509*32b31808SJens Wiklander  */
510*32b31808SJens Wiklander int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx)
511*32b31808SJens Wiklander {
512*32b31808SJens Wiklander     return ctx->padding;
513*32b31808SJens Wiklander }
514*32b31808SJens Wiklander 
515*32b31808SJens Wiklander /*
516*32b31808SJens Wiklander  * Get hash identifier of mbedtls_md_type_t type
517*32b31808SJens Wiklander  */
518*32b31808SJens Wiklander int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx)
519*32b31808SJens Wiklander {
520*32b31808SJens Wiklander     return ctx->hash_id;
521817466cbSJens Wiklander }
522817466cbSJens Wiklander 
5233d3b0591SJens Wiklander /*
5243d3b0591SJens Wiklander  * Get length in bytes of RSA modulus
5253d3b0591SJens Wiklander  */
5263d3b0591SJens Wiklander size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)
5273d3b0591SJens Wiklander {
528*32b31808SJens Wiklander     return ctx->len;
5293d3b0591SJens Wiklander }
5303d3b0591SJens Wiklander 
5313d3b0591SJens Wiklander 
532817466cbSJens Wiklander #if defined(MBEDTLS_GENPRIME)
533817466cbSJens Wiklander 
534817466cbSJens Wiklander /*
535817466cbSJens Wiklander  * Generate an RSA keypair
5363d3b0591SJens Wiklander  *
5373d3b0591SJens Wiklander  * This generation method follows the RSA key pair generation procedure of
5383d3b0591SJens Wiklander  * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072.
539817466cbSJens Wiklander  */
540817466cbSJens Wiklander int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx,
541817466cbSJens Wiklander                         int (*f_rng)(void *, unsigned char *, size_t),
542817466cbSJens Wiklander                         void *p_rng,
543817466cbSJens Wiklander                         unsigned int nbits, int exponent)
544817466cbSJens Wiklander {
54511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
5463d3b0591SJens Wiklander     mbedtls_mpi H, G, L;
5473d3b0591SJens Wiklander     int prime_quality = 0;
548817466cbSJens Wiklander 
5493d3b0591SJens Wiklander     /*
5503d3b0591SJens Wiklander      * If the modulus is 1024 bit long or shorter, then the security strength of
5513d3b0591SJens Wiklander      * the RSA algorithm is less than or equal to 80 bits and therefore an error
5523d3b0591SJens Wiklander      * rate of 2^-80 is sufficient.
5533d3b0591SJens Wiklander      */
554*32b31808SJens Wiklander     if (nbits > 1024) {
5553d3b0591SJens Wiklander         prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR;
556*32b31808SJens Wiklander     }
557817466cbSJens Wiklander 
5583d3b0591SJens Wiklander     mbedtls_mpi_init(&H);
5593d3b0591SJens Wiklander     mbedtls_mpi_init(&G);
5603d3b0591SJens Wiklander     mbedtls_mpi_init(&L);
561817466cbSJens Wiklander 
562*32b31808SJens Wiklander     if (nbits < 128 || exponent < 3 || nbits % 2 != 0) {
5637901324dSJerome Forissier         ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
5647901324dSJerome Forissier         goto cleanup;
5657901324dSJerome Forissier     }
5667901324dSJerome Forissier 
567817466cbSJens Wiklander     /*
568817466cbSJens Wiklander      * find primes P and Q with Q < P so that:
5693d3b0591SJens Wiklander      * 1.  |P-Q| > 2^( nbits / 2 - 100 )
5703d3b0591SJens Wiklander      * 2.  GCD( E, (P-1)*(Q-1) ) == 1
5713d3b0591SJens Wiklander      * 3.  E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 )
572817466cbSJens Wiklander      */
573817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->E, exponent));
574817466cbSJens Wiklander 
575*32b31808SJens Wiklander     do {
5763d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->P, nbits >> 1,
5773d3b0591SJens Wiklander                                               prime_quality, f_rng, p_rng));
578817466cbSJens Wiklander 
5793d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->Q, nbits >> 1,
5803d3b0591SJens Wiklander                                               prime_quality, f_rng, p_rng));
581817466cbSJens Wiklander 
5823d3b0591SJens Wiklander         /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */
5833d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&H, &ctx->P, &ctx->Q));
584*32b31808SJens Wiklander         if (mbedtls_mpi_bitlen(&H) <= ((nbits >= 200) ? ((nbits >> 1) - 99) : 0)) {
585817466cbSJens Wiklander             continue;
586*32b31808SJens Wiklander         }
587817466cbSJens Wiklander 
5883d3b0591SJens Wiklander         /* not required by any standards, but some users rely on the fact that P > Q */
589*32b31808SJens Wiklander         if (H.s < 0) {
590817466cbSJens Wiklander             mbedtls_mpi_swap(&ctx->P, &ctx->Q);
591*32b31808SJens Wiklander         }
592817466cbSJens Wiklander 
5933d3b0591SJens Wiklander         /* Temporarily replace P,Q by P-1, Q-1 */
5943d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->P, &ctx->P, 1));
5953d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->Q, &ctx->Q, 1));
5963d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&H, &ctx->P, &ctx->Q));
597817466cbSJens Wiklander 
5983d3b0591SJens Wiklander         /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */
5993d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->E, &H));
600*32b31808SJens Wiklander         if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
6013d3b0591SJens Wiklander             continue;
602*32b31808SJens Wiklander         }
6033d3b0591SJens Wiklander 
6043d3b0591SJens Wiklander         /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */
6053d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->P, &ctx->Q));
6063d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&L, NULL, &H, &G));
6073d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->D, &ctx->E, &L));
6083d3b0591SJens Wiklander 
609*32b31808SJens Wiklander         if (mbedtls_mpi_bitlen(&ctx->D) <= ((nbits + 1) / 2)) {      // (FIPS 186-4 §B.3.1 criterion 3(a))
6103d3b0591SJens Wiklander             continue;
611*32b31808SJens Wiklander         }
6123d3b0591SJens Wiklander 
6133d3b0591SJens Wiklander         break;
614*32b31808SJens Wiklander     } while (1);
6153d3b0591SJens Wiklander 
6163d3b0591SJens Wiklander     /* Restore P,Q */
6173d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->P,  &ctx->P, 1));
6183d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->Q,  &ctx->Q, 1));
6193d3b0591SJens Wiklander 
6203d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q));
6213d3b0591SJens Wiklander 
6223d3b0591SJens Wiklander     ctx->len = mbedtls_mpi_size(&ctx->N);
6233d3b0591SJens Wiklander 
6243d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
625817466cbSJens Wiklander     /*
626817466cbSJens Wiklander      * DP = D mod (P - 1)
627817466cbSJens Wiklander      * DQ = D mod (Q - 1)
628817466cbSJens Wiklander      * QP = Q^-1 mod P
629817466cbSJens Wiklander      */
6303d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,
6313d3b0591SJens Wiklander                                            &ctx->DP, &ctx->DQ, &ctx->QP));
6323d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */
633817466cbSJens Wiklander 
6343d3b0591SJens Wiklander     /* Double-check */
6353d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_check_privkey(ctx));
636817466cbSJens Wiklander 
637817466cbSJens Wiklander cleanup:
638817466cbSJens Wiklander 
6393d3b0591SJens Wiklander     mbedtls_mpi_free(&H);
6403d3b0591SJens Wiklander     mbedtls_mpi_free(&G);
6413d3b0591SJens Wiklander     mbedtls_mpi_free(&L);
642817466cbSJens Wiklander 
643*32b31808SJens Wiklander     if (ret != 0) {
644817466cbSJens Wiklander         mbedtls_rsa_free(ctx);
6457901324dSJerome Forissier 
646*32b31808SJens Wiklander         if ((-ret & ~0x7f) == 0) {
6477901324dSJerome Forissier             ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret);
648*32b31808SJens Wiklander         }
649*32b31808SJens Wiklander         return ret;
650817466cbSJens Wiklander     }
651817466cbSJens Wiklander 
652*32b31808SJens Wiklander     return 0;
653817466cbSJens Wiklander }
654817466cbSJens Wiklander 
655817466cbSJens Wiklander #endif /* MBEDTLS_GENPRIME */
656817466cbSJens Wiklander 
657817466cbSJens Wiklander /*
658817466cbSJens Wiklander  * Check a public RSA key
659817466cbSJens Wiklander  */
660817466cbSJens Wiklander int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx)
661817466cbSJens Wiklander {
662*32b31808SJens Wiklander     if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */) != 0) {
663*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
664*32b31808SJens Wiklander     }
6653d3b0591SJens Wiklander 
666*32b31808SJens Wiklander     if (mbedtls_mpi_bitlen(&ctx->N) < 128) {
667*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
6683d3b0591SJens Wiklander     }
669817466cbSJens Wiklander 
6703d3b0591SJens Wiklander     if (mbedtls_mpi_get_bit(&ctx->E, 0) == 0 ||
6713d3b0591SJens Wiklander         mbedtls_mpi_bitlen(&ctx->E)     < 2  ||
672*32b31808SJens Wiklander         mbedtls_mpi_cmp_mpi(&ctx->E, &ctx->N) >= 0) {
673*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
6743d3b0591SJens Wiklander     }
675817466cbSJens Wiklander 
676*32b31808SJens Wiklander     return 0;
677817466cbSJens Wiklander }
678817466cbSJens Wiklander 
679817466cbSJens Wiklander /*
6803d3b0591SJens Wiklander  * Check for the consistency of all fields in an RSA private key context
681817466cbSJens Wiklander  */
682817466cbSJens Wiklander int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx)
683817466cbSJens Wiklander {
6843d3b0591SJens Wiklander     if (mbedtls_rsa_check_pubkey(ctx) != 0 ||
685*32b31808SJens Wiklander         rsa_check_context(ctx, 1 /* private */, 1 /* blinding */) != 0) {
686*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
687817466cbSJens Wiklander     }
688817466cbSJens Wiklander 
6893d3b0591SJens Wiklander     if (mbedtls_rsa_validate_params(&ctx->N, &ctx->P, &ctx->Q,
690*32b31808SJens Wiklander                                     &ctx->D, &ctx->E, NULL, NULL) != 0) {
691*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
6923d3b0591SJens Wiklander     }
693817466cbSJens Wiklander 
6943d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
6953d3b0591SJens Wiklander     else if (mbedtls_rsa_validate_crt(&ctx->P, &ctx->Q, &ctx->D,
696*32b31808SJens Wiklander                                       &ctx->DP, &ctx->DQ, &ctx->QP) != 0) {
697*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
6983d3b0591SJens Wiklander     }
6993d3b0591SJens Wiklander #endif
700817466cbSJens Wiklander 
701*32b31808SJens Wiklander     return 0;
702817466cbSJens Wiklander }
703817466cbSJens Wiklander 
704817466cbSJens Wiklander /*
705817466cbSJens Wiklander  * Check if contexts holding a public and private key match
706817466cbSJens Wiklander  */
7073d3b0591SJens Wiklander int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub,
7083d3b0591SJens Wiklander                                const mbedtls_rsa_context *prv)
709817466cbSJens Wiklander {
710817466cbSJens Wiklander     if (mbedtls_rsa_check_pubkey(pub)  != 0 ||
711*32b31808SJens Wiklander         mbedtls_rsa_check_privkey(prv) != 0) {
712*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
713817466cbSJens Wiklander     }
714817466cbSJens Wiklander 
715817466cbSJens Wiklander     if (mbedtls_mpi_cmp_mpi(&pub->N, &prv->N) != 0 ||
716*32b31808SJens Wiklander         mbedtls_mpi_cmp_mpi(&pub->E, &prv->E) != 0) {
717*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
718817466cbSJens Wiklander     }
719817466cbSJens Wiklander 
720*32b31808SJens Wiklander     return 0;
721817466cbSJens Wiklander }
722817466cbSJens Wiklander 
723817466cbSJens Wiklander /*
724817466cbSJens Wiklander  * Do an RSA public key operation
725817466cbSJens Wiklander  */
726817466cbSJens Wiklander int mbedtls_rsa_public(mbedtls_rsa_context *ctx,
727817466cbSJens Wiklander                        const unsigned char *input,
728817466cbSJens Wiklander                        unsigned char *output)
729817466cbSJens Wiklander {
73011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
731817466cbSJens Wiklander     size_t olen;
732817466cbSJens Wiklander     mbedtls_mpi T;
7333d3b0591SJens Wiklander 
734*32b31808SJens Wiklander     if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */)) {
735*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
736*32b31808SJens Wiklander     }
737817466cbSJens Wiklander 
738817466cbSJens Wiklander     mbedtls_mpi_init(&T);
739817466cbSJens Wiklander 
740817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
741*32b31808SJens Wiklander     if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
742*32b31808SJens Wiklander         return ret;
743*32b31808SJens Wiklander     }
744817466cbSJens Wiklander #endif
745817466cbSJens Wiklander 
746817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len));
747817466cbSJens Wiklander 
748*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) {
749817466cbSJens Wiklander         ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
750817466cbSJens Wiklander         goto cleanup;
751817466cbSJens Wiklander     }
752817466cbSJens Wiklander 
753817466cbSJens Wiklander     olen = ctx->len;
754817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &ctx->E, &ctx->N, &ctx->RN));
755817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));
756817466cbSJens Wiklander 
757817466cbSJens Wiklander cleanup:
758817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
759*32b31808SJens Wiklander     if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
760*32b31808SJens Wiklander         return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
761*32b31808SJens Wiklander     }
762817466cbSJens Wiklander #endif
763817466cbSJens Wiklander 
764817466cbSJens Wiklander     mbedtls_mpi_free(&T);
765817466cbSJens Wiklander 
766*32b31808SJens Wiklander     if (ret != 0) {
767*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret);
768*32b31808SJens Wiklander     }
769817466cbSJens Wiklander 
770*32b31808SJens Wiklander     return 0;
771817466cbSJens Wiklander }
772817466cbSJens Wiklander 
773817466cbSJens Wiklander /*
774817466cbSJens Wiklander  * Generate or update blinding values, see section 10 of:
775817466cbSJens Wiklander  *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
776817466cbSJens Wiklander  *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
777817466cbSJens Wiklander  *  Berlin Heidelberg, 1996. p. 104-113.
778817466cbSJens Wiklander  */
779817466cbSJens Wiklander static int rsa_prepare_blinding(mbedtls_rsa_context *ctx,
780817466cbSJens Wiklander                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
781817466cbSJens Wiklander {
782817466cbSJens Wiklander     int ret, count = 0;
7837901324dSJerome Forissier     mbedtls_mpi R;
7847901324dSJerome Forissier 
7857901324dSJerome Forissier     mbedtls_mpi_init(&R);
786817466cbSJens Wiklander 
787*32b31808SJens Wiklander     if (ctx->Vf.p != NULL) {
788817466cbSJens Wiklander         /* We already have blinding values, just update them by squaring */
789817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
790817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N));
791817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
792817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->N));
793817466cbSJens Wiklander 
794817466cbSJens Wiklander         goto cleanup;
795817466cbSJens Wiklander     }
796817466cbSJens Wiklander 
797817466cbSJens Wiklander     /* Unblinding value: Vf = random number, invertible mod N */
798817466cbSJens Wiklander     do {
799*32b31808SJens Wiklander         if (count++ > 10) {
8007901324dSJerome Forissier             ret = MBEDTLS_ERR_RSA_RNG_FAILED;
8017901324dSJerome Forissier             goto cleanup;
8027901324dSJerome Forissier         }
803817466cbSJens Wiklander 
804817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->Vf, ctx->len - 1, f_rng, p_rng));
805817466cbSJens Wiklander 
8067901324dSJerome Forissier         /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */
8077901324dSJerome Forissier         MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, ctx->len - 1, f_rng, p_rng));
8087901324dSJerome Forissier         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vf, &R));
8097901324dSJerome Forissier         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N));
8107901324dSJerome Forissier 
8117901324dSJerome Forissier         /* At this point, Vi is invertible mod N if and only if both Vf and R
8127901324dSJerome Forissier          * are invertible mod N. If one of them isn't, we don't need to know
8137901324dSJerome Forissier          * which one, we just loop and choose new values for both of them.
8147901324dSJerome Forissier          * (Each iteration succeeds with overwhelming probability.) */
8157901324dSJerome Forissier         ret = mbedtls_mpi_inv_mod(&ctx->Vi, &ctx->Vi, &ctx->N);
816*32b31808SJens Wiklander         if (ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
8177901324dSJerome Forissier             goto cleanup;
818*32b31808SJens Wiklander         }
8197901324dSJerome Forissier 
8207901324dSJerome Forissier     } while (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE);
8217901324dSJerome Forissier 
8227901324dSJerome Forissier     /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */
8237901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &R));
8247901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N));
8257901324dSJerome Forissier 
8267901324dSJerome Forissier     /* Blinding value: Vi = Vf^(-e) mod N
8277901324dSJerome Forissier      * (Vi already contains Vf^-1 at this point) */
828817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN));
829817466cbSJens Wiklander 
830817466cbSJens Wiklander 
831817466cbSJens Wiklander cleanup:
8327901324dSJerome Forissier     mbedtls_mpi_free(&R);
8337901324dSJerome Forissier 
834*32b31808SJens Wiklander     return ret;
835817466cbSJens Wiklander }
836817466cbSJens Wiklander 
837817466cbSJens Wiklander /*
838817466cbSJens Wiklander  * Exponent blinding supposed to prevent side-channel attacks using multiple
839817466cbSJens Wiklander  * traces of measurements to recover the RSA key. The more collisions are there,
840817466cbSJens Wiklander  * the more bits of the key can be recovered. See [3].
841817466cbSJens Wiklander  *
842817466cbSJens Wiklander  * Collecting n collisions with m bit long blinding value requires 2^(m-m/n)
843039e02dfSJerome Forissier  * observations on average.
844817466cbSJens Wiklander  *
845817466cbSJens Wiklander  * For example with 28 byte blinding to achieve 2 collisions the adversary has
846039e02dfSJerome Forissier  * to make 2^112 observations on average.
847817466cbSJens Wiklander  *
848817466cbSJens Wiklander  * (With the currently (as of 2017 April) known best algorithms breaking 2048
849817466cbSJens Wiklander  * bit RSA requires approximately as much time as trying out 2^112 random keys.
850817466cbSJens Wiklander  * Thus in this sense with 28 byte blinding the security is not reduced by
851817466cbSJens Wiklander  * side-channel attacks like the one in [3])
852817466cbSJens Wiklander  *
853817466cbSJens Wiklander  * This countermeasure does not help if the key recovery is possible with a
854817466cbSJens Wiklander  * single trace.
855817466cbSJens Wiklander  */
856817466cbSJens Wiklander #define RSA_EXPONENT_BLINDING 28
857817466cbSJens Wiklander 
858817466cbSJens Wiklander /*
859817466cbSJens Wiklander  * Do an RSA private key operation
860817466cbSJens Wiklander  */
861817466cbSJens Wiklander int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
862817466cbSJens Wiklander                         int (*f_rng)(void *, unsigned char *, size_t),
863817466cbSJens Wiklander                         void *p_rng,
864817466cbSJens Wiklander                         const unsigned char *input,
865817466cbSJens Wiklander                         unsigned char *output)
866817466cbSJens Wiklander {
86711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
868817466cbSJens Wiklander     size_t olen;
8693d3b0591SJens Wiklander 
8703d3b0591SJens Wiklander     /* Temporary holding the result */
8713d3b0591SJens Wiklander     mbedtls_mpi T;
8723d3b0591SJens Wiklander 
8733d3b0591SJens Wiklander     /* Temporaries holding P-1, Q-1 and the
8743d3b0591SJens Wiklander      * exponent blinding factor, respectively. */
875817466cbSJens Wiklander     mbedtls_mpi P1, Q1, R;
8763d3b0591SJens Wiklander 
8773d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
8783d3b0591SJens Wiklander     /* Temporaries holding the results mod p resp. mod q. */
8793d3b0591SJens Wiklander     mbedtls_mpi TP, TQ;
8803d3b0591SJens Wiklander 
8813d3b0591SJens Wiklander     /* Temporaries holding the blinded exponents for
8823d3b0591SJens Wiklander      * the mod p resp. mod q computation (if used). */
883817466cbSJens Wiklander     mbedtls_mpi DP_blind, DQ_blind;
8843d3b0591SJens Wiklander 
8853d3b0591SJens Wiklander     /* Pointers to actual exponents to be used - either the unblinded
8863d3b0591SJens Wiklander      * or the blinded ones, depending on the presence of a PRNG. */
887817466cbSJens Wiklander     mbedtls_mpi *DP = &ctx->DP;
888817466cbSJens Wiklander     mbedtls_mpi *DQ = &ctx->DQ;
8893d3b0591SJens Wiklander #else
8903d3b0591SJens Wiklander     /* Temporary holding the blinded exponent (if used). */
8913d3b0591SJens Wiklander     mbedtls_mpi D_blind;
8923d3b0591SJens Wiklander 
8933d3b0591SJens Wiklander     /* Pointer to actual exponent to be used - either the unblinded
8943d3b0591SJens Wiklander      * or the blinded one, depending on the presence of a PRNG. */
8953d3b0591SJens Wiklander     mbedtls_mpi *D = &ctx->D;
8963d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */
8973d3b0591SJens Wiklander 
8983d3b0591SJens Wiklander     /* Temporaries holding the initial input and the double
8993d3b0591SJens Wiklander      * checked result; should be the same in the end. */
9003d3b0591SJens Wiklander     mbedtls_mpi I, C;
9013d3b0591SJens Wiklander 
902*32b31808SJens Wiklander     if (f_rng == NULL) {
903*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
904*32b31808SJens Wiklander     }
9053d3b0591SJens Wiklander 
9063d3b0591SJens Wiklander     if (rsa_check_context(ctx, 1 /* private key checks */,
907*32b31808SJens Wiklander                           1 /* blinding on        */) != 0) {
908*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
9093d3b0591SJens Wiklander     }
9103d3b0591SJens Wiklander 
9113d3b0591SJens Wiklander #if defined(MBEDTLS_THREADING_C)
912*32b31808SJens Wiklander     if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
913*32b31808SJens Wiklander         return ret;
914*32b31808SJens Wiklander     }
915817466cbSJens Wiklander #endif
916817466cbSJens Wiklander 
9173d3b0591SJens Wiklander     /* MPI Initialization */
9183d3b0591SJens Wiklander     mbedtls_mpi_init(&T);
919817466cbSJens Wiklander 
9203d3b0591SJens Wiklander     mbedtls_mpi_init(&P1);
9213d3b0591SJens Wiklander     mbedtls_mpi_init(&Q1);
9223d3b0591SJens Wiklander     mbedtls_mpi_init(&R);
923817466cbSJens Wiklander 
924817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT)
925817466cbSJens Wiklander     mbedtls_mpi_init(&D_blind);
926817466cbSJens Wiklander #else
927817466cbSJens Wiklander     mbedtls_mpi_init(&DP_blind);
928817466cbSJens Wiklander     mbedtls_mpi_init(&DQ_blind);
929817466cbSJens Wiklander #endif
930817466cbSJens Wiklander 
9313d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
9323d3b0591SJens Wiklander     mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ);
933817466cbSJens Wiklander #endif
934817466cbSJens Wiklander 
9353d3b0591SJens Wiklander     mbedtls_mpi_init(&I);
9363d3b0591SJens Wiklander     mbedtls_mpi_init(&C);
9373d3b0591SJens Wiklander 
9383d3b0591SJens Wiklander     /* End of MPI initialization */
9393d3b0591SJens Wiklander 
940817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len));
941*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) {
942817466cbSJens Wiklander         ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
943817466cbSJens Wiklander         goto cleanup;
944817466cbSJens Wiklander     }
945817466cbSJens Wiklander 
9463d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&I, &T));
9473d3b0591SJens Wiklander 
948817466cbSJens Wiklander     /*
949817466cbSJens Wiklander      * Blinding
950817466cbSJens Wiklander      * T = T * Vi mod N
951817466cbSJens Wiklander      */
952817466cbSJens Wiklander     MBEDTLS_MPI_CHK(rsa_prepare_blinding(ctx, f_rng, p_rng));
953817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi));
954817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N));
955817466cbSJens Wiklander 
956817466cbSJens Wiklander     /*
957817466cbSJens Wiklander      * Exponent blinding
958817466cbSJens Wiklander      */
959817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&P1, &ctx->P, 1));
960817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&Q1, &ctx->Q, 1));
961817466cbSJens Wiklander 
962817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT)
963817466cbSJens Wiklander     /*
964817466cbSJens Wiklander      * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D
965817466cbSJens Wiklander      */
966817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,
967817466cbSJens Wiklander                                             f_rng, p_rng));
968817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1));
969817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R));
970817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D));
971817466cbSJens Wiklander 
972817466cbSJens Wiklander     D = &D_blind;
973817466cbSJens Wiklander #else
974817466cbSJens Wiklander     /*
975817466cbSJens Wiklander      * DP_blind = ( P - 1 ) * R + DP
976817466cbSJens Wiklander      */
977817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,
978817466cbSJens Wiklander                                             f_rng, p_rng));
979817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DP_blind, &P1, &R));
980817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind,
981817466cbSJens Wiklander                                         &ctx->DP));
982817466cbSJens Wiklander 
983817466cbSJens Wiklander     DP = &DP_blind;
984817466cbSJens Wiklander 
985817466cbSJens Wiklander     /*
986817466cbSJens Wiklander      * DQ_blind = ( Q - 1 ) * R + DQ
987817466cbSJens Wiklander      */
988817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,
989817466cbSJens Wiklander                                             f_rng, p_rng));
990817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R));
991817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind,
992817466cbSJens Wiklander                                         &ctx->DQ));
993817466cbSJens Wiklander 
994817466cbSJens Wiklander     DQ = &DQ_blind;
995817466cbSJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */
996817466cbSJens Wiklander 
997817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT)
998817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, D, &ctx->N, &ctx->RN));
999817466cbSJens Wiklander #else
1000817466cbSJens Wiklander     /*
1001817466cbSJens Wiklander      * Faster decryption using the CRT
1002817466cbSJens Wiklander      *
10033d3b0591SJens Wiklander      * TP = input ^ dP mod P
10043d3b0591SJens Wiklander      * TQ = input ^ dQ mod Q
1005817466cbSJens Wiklander      */
10063d3b0591SJens Wiklander 
10073d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, DP, &ctx->P, &ctx->RP));
10083d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, DQ, &ctx->Q, &ctx->RQ));
1009817466cbSJens Wiklander 
1010817466cbSJens Wiklander     /*
10113d3b0591SJens Wiklander      * T = (TP - TQ) * (Q^-1 mod P) mod P
1012817466cbSJens Wiklander      */
10133d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&T, &TP, &TQ));
10143d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->QP));
10153d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &TP, &ctx->P));
1016817466cbSJens Wiklander 
1017817466cbSJens Wiklander     /*
10183d3b0591SJens Wiklander      * T = TQ + T * Q
1019817466cbSJens Wiklander      */
10203d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->Q));
10213d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP));
1022817466cbSJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */
1023817466cbSJens Wiklander 
1024817466cbSJens Wiklander     /*
1025817466cbSJens Wiklander      * Unblind
1026817466cbSJens Wiklander      * T = T * Vf mod N
1027817466cbSJens Wiklander      */
1028817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vf));
1029817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N));
1030817466cbSJens Wiklander 
10313d3b0591SJens Wiklander     /* Verify the result to prevent glitching attacks. */
10323d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&C, &T, &ctx->E,
10333d3b0591SJens Wiklander                                         &ctx->N, &ctx->RN));
1034*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&C, &I) != 0) {
10353d3b0591SJens Wiklander         ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
10363d3b0591SJens Wiklander         goto cleanup;
10373d3b0591SJens Wiklander     }
10383d3b0591SJens Wiklander 
1039817466cbSJens Wiklander     olen = ctx->len;
1040817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));
1041817466cbSJens Wiklander 
1042817466cbSJens Wiklander cleanup:
1043817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
1044*32b31808SJens Wiklander     if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
1045*32b31808SJens Wiklander         return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
1046*32b31808SJens Wiklander     }
1047817466cbSJens Wiklander #endif
1048817466cbSJens Wiklander 
10493d3b0591SJens Wiklander     mbedtls_mpi_free(&P1);
10503d3b0591SJens Wiklander     mbedtls_mpi_free(&Q1);
10513d3b0591SJens Wiklander     mbedtls_mpi_free(&R);
1052817466cbSJens Wiklander 
1053817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT)
1054817466cbSJens Wiklander     mbedtls_mpi_free(&D_blind);
1055817466cbSJens Wiklander #else
1056817466cbSJens Wiklander     mbedtls_mpi_free(&DP_blind);
1057817466cbSJens Wiklander     mbedtls_mpi_free(&DQ_blind);
1058817466cbSJens Wiklander #endif
1059817466cbSJens Wiklander 
10603d3b0591SJens Wiklander     mbedtls_mpi_free(&T);
10613d3b0591SJens Wiklander 
10623d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
10633d3b0591SJens Wiklander     mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ);
10643d3b0591SJens Wiklander #endif
10653d3b0591SJens Wiklander 
10663d3b0591SJens Wiklander     mbedtls_mpi_free(&C);
10673d3b0591SJens Wiklander     mbedtls_mpi_free(&I);
10683d3b0591SJens Wiklander 
1069*32b31808SJens Wiklander     if (ret != 0 && ret >= -0x007f) {
1070*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret);
1071*32b31808SJens Wiklander     }
1072817466cbSJens Wiklander 
1073*32b31808SJens Wiklander     return ret;
1074817466cbSJens Wiklander }
1075817466cbSJens Wiklander 
1076817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
1077817466cbSJens Wiklander /**
1078817466cbSJens Wiklander  * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
1079817466cbSJens Wiklander  *
1080817466cbSJens Wiklander  * \param dst       buffer to mask
1081817466cbSJens Wiklander  * \param dlen      length of destination buffer
1082817466cbSJens Wiklander  * \param src       source of the mask generation
1083817466cbSJens Wiklander  * \param slen      length of the source buffer
1084*32b31808SJens Wiklander  * \param md_alg    message digest to use
1085817466cbSJens Wiklander  */
10863d3b0591SJens Wiklander static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
1087*32b31808SJens Wiklander                     size_t slen, mbedtls_md_type_t md_alg)
1088817466cbSJens Wiklander {
1089817466cbSJens Wiklander     unsigned char counter[4];
1090817466cbSJens Wiklander     unsigned char *p;
1091817466cbSJens Wiklander     unsigned int hlen;
1092817466cbSJens Wiklander     size_t i, use_len;
1093*32b31808SJens Wiklander     unsigned char mask[MBEDTLS_HASH_MAX_SIZE];
1094*32b31808SJens Wiklander #if defined(MBEDTLS_MD_C)
10953d3b0591SJens Wiklander     int ret = 0;
1096*32b31808SJens Wiklander     const mbedtls_md_info_t *md_info;
1097*32b31808SJens Wiklander     mbedtls_md_context_t md_ctx;
1098817466cbSJens Wiklander 
1099*32b31808SJens Wiklander     mbedtls_md_init(&md_ctx);
1100*32b31808SJens Wiklander     md_info = mbedtls_md_info_from_type(md_alg);
1101*32b31808SJens Wiklander     if (md_info == NULL) {
1102*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1103*32b31808SJens Wiklander     }
1104*32b31808SJens Wiklander 
1105*32b31808SJens Wiklander     mbedtls_md_init(&md_ctx);
1106*32b31808SJens Wiklander     if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
1107*32b31808SJens Wiklander         goto exit;
1108*32b31808SJens Wiklander     }
1109*32b31808SJens Wiklander 
1110*32b31808SJens Wiklander     hlen = mbedtls_md_get_size(md_info);
1111*32b31808SJens Wiklander #else
1112*32b31808SJens Wiklander     psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
1113*32b31808SJens Wiklander     psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
1114*32b31808SJens Wiklander     psa_status_t status = PSA_SUCCESS;
1115*32b31808SJens Wiklander     size_t out_len;
1116*32b31808SJens Wiklander 
1117*32b31808SJens Wiklander     hlen = PSA_HASH_LENGTH(alg);
1118*32b31808SJens Wiklander #endif
1119*32b31808SJens Wiklander 
1120*32b31808SJens Wiklander     memset(mask, 0, sizeof(mask));
1121817466cbSJens Wiklander     memset(counter, 0, 4);
1122817466cbSJens Wiklander 
1123817466cbSJens Wiklander     /* Generate and apply dbMask */
1124817466cbSJens Wiklander     p = dst;
1125817466cbSJens Wiklander 
1126*32b31808SJens Wiklander     while (dlen > 0) {
1127817466cbSJens Wiklander         use_len = hlen;
1128*32b31808SJens Wiklander         if (dlen < hlen) {
1129817466cbSJens Wiklander             use_len = dlen;
1130*32b31808SJens Wiklander         }
1131817466cbSJens Wiklander 
1132*32b31808SJens Wiklander #if defined(MBEDTLS_MD_C)
1133*32b31808SJens Wiklander         if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
11343d3b0591SJens Wiklander             goto exit;
1135*32b31808SJens Wiklander         }
1136*32b31808SJens Wiklander         if ((ret = mbedtls_md_update(&md_ctx, src, slen)) != 0) {
11373d3b0591SJens Wiklander             goto exit;
1138*32b31808SJens Wiklander         }
1139*32b31808SJens Wiklander         if ((ret = mbedtls_md_update(&md_ctx, counter, 4)) != 0) {
11403d3b0591SJens Wiklander             goto exit;
1141*32b31808SJens Wiklander         }
1142*32b31808SJens Wiklander         if ((ret = mbedtls_md_finish(&md_ctx, mask)) != 0) {
11433d3b0591SJens Wiklander             goto exit;
1144*32b31808SJens Wiklander         }
1145*32b31808SJens Wiklander #else
1146*32b31808SJens Wiklander         if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
1147*32b31808SJens Wiklander             goto exit;
1148*32b31808SJens Wiklander         }
1149*32b31808SJens Wiklander         if ((status = psa_hash_update(&op, src, slen)) != PSA_SUCCESS) {
1150*32b31808SJens Wiklander             goto exit;
1151*32b31808SJens Wiklander         }
1152*32b31808SJens Wiklander         if ((status = psa_hash_update(&op, counter, 4)) != PSA_SUCCESS) {
1153*32b31808SJens Wiklander             goto exit;
1154*32b31808SJens Wiklander         }
1155*32b31808SJens Wiklander         status = psa_hash_finish(&op, mask, sizeof(mask), &out_len);
1156*32b31808SJens Wiklander         if (status != PSA_SUCCESS) {
1157*32b31808SJens Wiklander             goto exit;
1158*32b31808SJens Wiklander         }
1159*32b31808SJens Wiklander #endif
1160817466cbSJens Wiklander 
1161*32b31808SJens Wiklander         for (i = 0; i < use_len; ++i) {
1162817466cbSJens Wiklander             *p++ ^= mask[i];
1163*32b31808SJens Wiklander         }
1164817466cbSJens Wiklander 
1165817466cbSJens Wiklander         counter[3]++;
1166817466cbSJens Wiklander 
1167817466cbSJens Wiklander         dlen -= use_len;
1168817466cbSJens Wiklander     }
1169817466cbSJens Wiklander 
11703d3b0591SJens Wiklander exit:
11713d3b0591SJens Wiklander     mbedtls_platform_zeroize(mask, sizeof(mask));
1172*32b31808SJens Wiklander #if defined(MBEDTLS_MD_C)
1173*32b31808SJens Wiklander     mbedtls_md_free(&md_ctx);
11743d3b0591SJens Wiklander 
1175*32b31808SJens Wiklander     return ret;
1176*32b31808SJens Wiklander #else
1177*32b31808SJens Wiklander     psa_hash_abort(&op);
1178*32b31808SJens Wiklander 
1179*32b31808SJens Wiklander     return PSA_TO_MBEDTLS_ERR(status);
1180*32b31808SJens Wiklander #endif
1181*32b31808SJens Wiklander }
1182*32b31808SJens Wiklander 
1183*32b31808SJens Wiklander /**
1184*32b31808SJens Wiklander  * Generate Hash(M') as in RFC 8017 page 43 points 5 and 6.
1185*32b31808SJens Wiklander  *
1186*32b31808SJens Wiklander  * \param hash      the input hash
1187*32b31808SJens Wiklander  * \param hlen      length of the input hash
1188*32b31808SJens Wiklander  * \param salt      the input salt
1189*32b31808SJens Wiklander  * \param slen      length of the input salt
1190*32b31808SJens Wiklander  * \param out       the output buffer - must be large enough for \p md_alg
1191*32b31808SJens Wiklander  * \param md_alg    message digest to use
1192*32b31808SJens Wiklander  */
1193*32b31808SJens Wiklander static int hash_mprime(const unsigned char *hash, size_t hlen,
1194*32b31808SJens Wiklander                        const unsigned char *salt, size_t slen,
1195*32b31808SJens Wiklander                        unsigned char *out, mbedtls_md_type_t md_alg)
1196*32b31808SJens Wiklander {
1197*32b31808SJens Wiklander     const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1198*32b31808SJens Wiklander 
1199*32b31808SJens Wiklander #if defined(MBEDTLS_MD_C)
1200*32b31808SJens Wiklander     mbedtls_md_context_t md_ctx;
1201*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1202*32b31808SJens Wiklander 
1203*32b31808SJens Wiklander     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);
1204*32b31808SJens Wiklander     if (md_info == NULL) {
1205*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1206*32b31808SJens Wiklander     }
1207*32b31808SJens Wiklander 
1208*32b31808SJens Wiklander     mbedtls_md_init(&md_ctx);
1209*32b31808SJens Wiklander     if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
1210*32b31808SJens Wiklander         goto exit;
1211*32b31808SJens Wiklander     }
1212*32b31808SJens Wiklander     if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
1213*32b31808SJens Wiklander         goto exit;
1214*32b31808SJens Wiklander     }
1215*32b31808SJens Wiklander     if ((ret = mbedtls_md_update(&md_ctx, zeros, sizeof(zeros))) != 0) {
1216*32b31808SJens Wiklander         goto exit;
1217*32b31808SJens Wiklander     }
1218*32b31808SJens Wiklander     if ((ret = mbedtls_md_update(&md_ctx, hash, hlen)) != 0) {
1219*32b31808SJens Wiklander         goto exit;
1220*32b31808SJens Wiklander     }
1221*32b31808SJens Wiklander     if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) {
1222*32b31808SJens Wiklander         goto exit;
1223*32b31808SJens Wiklander     }
1224*32b31808SJens Wiklander     if ((ret = mbedtls_md_finish(&md_ctx, out)) != 0) {
1225*32b31808SJens Wiklander         goto exit;
1226*32b31808SJens Wiklander     }
1227*32b31808SJens Wiklander 
1228*32b31808SJens Wiklander exit:
1229*32b31808SJens Wiklander     mbedtls_md_free(&md_ctx);
1230*32b31808SJens Wiklander 
1231*32b31808SJens Wiklander     return ret;
1232*32b31808SJens Wiklander #else
1233*32b31808SJens Wiklander     psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
1234*32b31808SJens Wiklander     psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
1235*32b31808SJens Wiklander     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
1236*32b31808SJens Wiklander     size_t out_size = PSA_HASH_LENGTH(alg);
1237*32b31808SJens Wiklander     size_t out_len;
1238*32b31808SJens Wiklander 
1239*32b31808SJens Wiklander     if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
1240*32b31808SJens Wiklander         goto exit;
1241*32b31808SJens Wiklander     }
1242*32b31808SJens Wiklander     if ((status = psa_hash_update(&op, zeros, sizeof(zeros))) != PSA_SUCCESS) {
1243*32b31808SJens Wiklander         goto exit;
1244*32b31808SJens Wiklander     }
1245*32b31808SJens Wiklander     if ((status = psa_hash_update(&op, hash, hlen)) != PSA_SUCCESS) {
1246*32b31808SJens Wiklander         goto exit;
1247*32b31808SJens Wiklander     }
1248*32b31808SJens Wiklander     if ((status = psa_hash_update(&op, salt, slen)) != PSA_SUCCESS) {
1249*32b31808SJens Wiklander         goto exit;
1250*32b31808SJens Wiklander     }
1251*32b31808SJens Wiklander     status = psa_hash_finish(&op, out, out_size, &out_len);
1252*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
1253*32b31808SJens Wiklander         goto exit;
1254*32b31808SJens Wiklander     }
1255*32b31808SJens Wiklander 
1256*32b31808SJens Wiklander exit:
1257*32b31808SJens Wiklander     psa_hash_abort(&op);
1258*32b31808SJens Wiklander 
1259*32b31808SJens Wiklander     return PSA_TO_MBEDTLS_ERR(status);
1260*32b31808SJens Wiklander #endif /* !MBEDTLS_MD_C */
1261*32b31808SJens Wiklander }
1262*32b31808SJens Wiklander 
1263*32b31808SJens Wiklander /**
1264*32b31808SJens Wiklander  * Compute a hash.
1265*32b31808SJens Wiklander  *
1266*32b31808SJens Wiklander  * \param md_alg    algorithm to use
1267*32b31808SJens Wiklander  * \param input     input message to hash
1268*32b31808SJens Wiklander  * \param ilen      input length
1269*32b31808SJens Wiklander  * \param output    the output buffer - must be large enough for \p md_alg
1270*32b31808SJens Wiklander  */
1271*32b31808SJens Wiklander static int compute_hash(mbedtls_md_type_t md_alg,
1272*32b31808SJens Wiklander                         const unsigned char *input, size_t ilen,
1273*32b31808SJens Wiklander                         unsigned char *output)
1274*32b31808SJens Wiklander {
1275*32b31808SJens Wiklander #if defined(MBEDTLS_MD_C)
1276*32b31808SJens Wiklander     const mbedtls_md_info_t *md_info;
1277*32b31808SJens Wiklander 
1278*32b31808SJens Wiklander     md_info = mbedtls_md_info_from_type(md_alg);
1279*32b31808SJens Wiklander     if (md_info == NULL) {
1280*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1281*32b31808SJens Wiklander     }
1282*32b31808SJens Wiklander 
1283*32b31808SJens Wiklander     return mbedtls_md(md_info, input, ilen, output);
1284*32b31808SJens Wiklander #else
1285*32b31808SJens Wiklander     psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
1286*32b31808SJens Wiklander     psa_status_t status;
1287*32b31808SJens Wiklander     size_t out_size = PSA_HASH_LENGTH(alg);
1288*32b31808SJens Wiklander     size_t out_len;
1289*32b31808SJens Wiklander 
1290*32b31808SJens Wiklander     status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
1291*32b31808SJens Wiklander 
1292*32b31808SJens Wiklander     return PSA_TO_MBEDTLS_ERR(status);
1293*32b31808SJens Wiklander #endif /* !MBEDTLS_MD_C */
1294817466cbSJens Wiklander }
1295817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */
1296817466cbSJens Wiklander 
1297817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
1298817466cbSJens Wiklander /*
1299817466cbSJens Wiklander  * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function
1300817466cbSJens Wiklander  */
1301817466cbSJens Wiklander int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx,
1302817466cbSJens Wiklander                                    int (*f_rng)(void *, unsigned char *, size_t),
1303817466cbSJens Wiklander                                    void *p_rng,
1304817466cbSJens Wiklander                                    const unsigned char *label, size_t label_len,
1305817466cbSJens Wiklander                                    size_t ilen,
1306817466cbSJens Wiklander                                    const unsigned char *input,
1307817466cbSJens Wiklander                                    unsigned char *output)
1308817466cbSJens Wiklander {
1309817466cbSJens Wiklander     size_t olen;
131011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1311817466cbSJens Wiklander     unsigned char *p = output;
1312817466cbSJens Wiklander     unsigned int hlen;
1313817466cbSJens Wiklander 
1314*32b31808SJens Wiklander     if (f_rng == NULL) {
1315*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1316*32b31808SJens Wiklander     }
13173d3b0591SJens Wiklander 
1318*32b31808SJens Wiklander     hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
1319*32b31808SJens Wiklander     if (hlen == 0) {
1320*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1321*32b31808SJens Wiklander     }
1322817466cbSJens Wiklander 
1323817466cbSJens Wiklander     olen = ctx->len;
1324817466cbSJens Wiklander 
1325817466cbSJens Wiklander     /* first comparison checks for overflow */
1326*32b31808SJens Wiklander     if (ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2) {
1327*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1328*32b31808SJens Wiklander     }
1329817466cbSJens Wiklander 
1330817466cbSJens Wiklander     memset(output, 0, olen);
1331817466cbSJens Wiklander 
1332817466cbSJens Wiklander     *p++ = 0;
1333817466cbSJens Wiklander 
1334817466cbSJens Wiklander     /* Generate a random octet string seed */
1335*32b31808SJens Wiklander     if ((ret = f_rng(p_rng, p, hlen)) != 0) {
1336*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);
1337*32b31808SJens Wiklander     }
1338817466cbSJens Wiklander 
1339817466cbSJens Wiklander     p += hlen;
1340817466cbSJens Wiklander 
1341817466cbSJens Wiklander     /* Construct DB */
1342*32b31808SJens Wiklander     ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, p);
1343*32b31808SJens Wiklander     if (ret != 0) {
1344*32b31808SJens Wiklander         return ret;
1345*32b31808SJens Wiklander     }
1346817466cbSJens Wiklander     p += hlen;
1347817466cbSJens Wiklander     p += olen - 2 * hlen - 2 - ilen;
1348817466cbSJens Wiklander     *p++ = 1;
1349*32b31808SJens Wiklander     if (ilen != 0) {
1350817466cbSJens Wiklander         memcpy(p, input, ilen);
1351*32b31808SJens Wiklander     }
1352817466cbSJens Wiklander 
1353817466cbSJens Wiklander     /* maskedDB: Apply dbMask to DB */
13543d3b0591SJens Wiklander     if ((ret = mgf_mask(output + hlen + 1, olen - hlen - 1, output + 1, hlen,
1355*32b31808SJens Wiklander                         ctx->hash_id)) != 0) {
1356*32b31808SJens Wiklander         return ret;
1357*32b31808SJens Wiklander     }
1358817466cbSJens Wiklander 
1359817466cbSJens Wiklander     /* maskedSeed: Apply seedMask to seed */
13603d3b0591SJens Wiklander     if ((ret = mgf_mask(output + 1, hlen, output + hlen + 1, olen - hlen - 1,
1361*32b31808SJens Wiklander                         ctx->hash_id)) != 0) {
1362*32b31808SJens Wiklander         return ret;
1363*32b31808SJens Wiklander     }
1364817466cbSJens Wiklander 
1365*32b31808SJens Wiklander     return mbedtls_rsa_public(ctx, output, output);
1366817466cbSJens Wiklander }
1367817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */
1368817466cbSJens Wiklander 
1369817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
1370817466cbSJens Wiklander /*
1371817466cbSJens Wiklander  * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function
1372817466cbSJens Wiklander  */
1373817466cbSJens Wiklander int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx,
1374817466cbSJens Wiklander                                         int (*f_rng)(void *, unsigned char *, size_t),
1375*32b31808SJens Wiklander                                         void *p_rng, size_t ilen,
1376817466cbSJens Wiklander                                         const unsigned char *input,
1377817466cbSJens Wiklander                                         unsigned char *output)
1378817466cbSJens Wiklander {
1379817466cbSJens Wiklander     size_t nb_pad, olen;
138011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1381817466cbSJens Wiklander     unsigned char *p = output;
1382817466cbSJens Wiklander 
1383817466cbSJens Wiklander     olen = ctx->len;
1384817466cbSJens Wiklander 
1385817466cbSJens Wiklander     /* first comparison checks for overflow */
1386*32b31808SJens Wiklander     if (ilen + 11 < ilen || olen < ilen + 11) {
1387*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1388*32b31808SJens Wiklander     }
1389817466cbSJens Wiklander 
1390817466cbSJens Wiklander     nb_pad = olen - 3 - ilen;
1391817466cbSJens Wiklander 
1392817466cbSJens Wiklander     *p++ = 0;
1393*32b31808SJens Wiklander 
1394*32b31808SJens Wiklander     if (f_rng == NULL) {
1395*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1396*32b31808SJens Wiklander     }
13973d3b0591SJens Wiklander 
1398817466cbSJens Wiklander     *p++ = MBEDTLS_RSA_CRYPT;
1399817466cbSJens Wiklander 
1400*32b31808SJens Wiklander     while (nb_pad-- > 0) {
1401817466cbSJens Wiklander         int rng_dl = 100;
1402817466cbSJens Wiklander 
1403817466cbSJens Wiklander         do {
1404817466cbSJens Wiklander             ret = f_rng(p_rng, p, 1);
1405817466cbSJens Wiklander         } while (*p == 0 && --rng_dl && ret == 0);
1406817466cbSJens Wiklander 
1407817466cbSJens Wiklander         /* Check if RNG failed to generate data */
1408*32b31808SJens Wiklander         if (rng_dl == 0 || ret != 0) {
1409*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);
1410*32b31808SJens Wiklander         }
1411817466cbSJens Wiklander 
1412817466cbSJens Wiklander         p++;
1413817466cbSJens Wiklander     }
1414817466cbSJens Wiklander 
1415817466cbSJens Wiklander     *p++ = 0;
1416*32b31808SJens Wiklander     if (ilen != 0) {
1417817466cbSJens Wiklander         memcpy(p, input, ilen);
1418*32b31808SJens Wiklander     }
1419817466cbSJens Wiklander 
1420*32b31808SJens Wiklander     return mbedtls_rsa_public(ctx, output, output);
1421817466cbSJens Wiklander }
1422817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */
1423817466cbSJens Wiklander 
1424817466cbSJens Wiklander /*
1425817466cbSJens Wiklander  * Add the message padding, then do an RSA operation
1426817466cbSJens Wiklander  */
1427817466cbSJens Wiklander int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx,
1428817466cbSJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t),
1429817466cbSJens Wiklander                               void *p_rng,
1430*32b31808SJens Wiklander                               size_t ilen,
1431817466cbSJens Wiklander                               const unsigned char *input,
1432817466cbSJens Wiklander                               unsigned char *output)
1433817466cbSJens Wiklander {
1434*32b31808SJens Wiklander     switch (ctx->padding) {
1435817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
1436817466cbSJens Wiklander         case MBEDTLS_RSA_PKCS_V15:
1437*32b31808SJens Wiklander             return mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx, f_rng, p_rng,
1438*32b31808SJens Wiklander                                                        ilen, input, output);
1439817466cbSJens Wiklander #endif
1440817466cbSJens Wiklander 
1441817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
1442817466cbSJens Wiklander         case MBEDTLS_RSA_PKCS_V21:
1443*32b31808SJens Wiklander             return mbedtls_rsa_rsaes_oaep_encrypt(ctx, f_rng, p_rng, NULL, 0,
1444817466cbSJens Wiklander                                                   ilen, input, output);
1445817466cbSJens Wiklander #endif
1446817466cbSJens Wiklander 
1447817466cbSJens Wiklander         default:
1448*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_INVALID_PADDING;
1449817466cbSJens Wiklander     }
1450817466cbSJens Wiklander }
1451817466cbSJens Wiklander 
1452817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
1453817466cbSJens Wiklander /*
1454817466cbSJens Wiklander  * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function
1455817466cbSJens Wiklander  */
1456817466cbSJens Wiklander int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
1457817466cbSJens Wiklander                                    int (*f_rng)(void *, unsigned char *, size_t),
1458817466cbSJens Wiklander                                    void *p_rng,
1459817466cbSJens Wiklander                                    const unsigned char *label, size_t label_len,
1460817466cbSJens Wiklander                                    size_t *olen,
1461817466cbSJens Wiklander                                    const unsigned char *input,
1462817466cbSJens Wiklander                                    unsigned char *output,
1463817466cbSJens Wiklander                                    size_t output_max_len)
1464817466cbSJens Wiklander {
146511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1466817466cbSJens Wiklander     size_t ilen, i, pad_len;
1467817466cbSJens Wiklander     unsigned char *p, bad, pad_done;
1468817466cbSJens Wiklander     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
1469*32b31808SJens Wiklander     unsigned char lhash[MBEDTLS_HASH_MAX_SIZE];
1470817466cbSJens Wiklander     unsigned int hlen;
14713d3b0591SJens Wiklander 
1472817466cbSJens Wiklander     /*
1473817466cbSJens Wiklander      * Parameters sanity checks
1474817466cbSJens Wiklander      */
1475*32b31808SJens Wiklander     if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {
1476*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1477*32b31808SJens Wiklander     }
1478817466cbSJens Wiklander 
1479817466cbSJens Wiklander     ilen = ctx->len;
1480817466cbSJens Wiklander 
1481*32b31808SJens Wiklander     if (ilen < 16 || ilen > sizeof(buf)) {
1482*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1483*32b31808SJens Wiklander     }
1484817466cbSJens Wiklander 
1485*32b31808SJens Wiklander     hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
1486*32b31808SJens Wiklander     if (hlen == 0) {
1487*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1488*32b31808SJens Wiklander     }
1489817466cbSJens Wiklander 
1490817466cbSJens Wiklander     // checking for integer underflow
1491*32b31808SJens Wiklander     if (2 * hlen + 2 > ilen) {
1492*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1493*32b31808SJens Wiklander     }
1494817466cbSJens Wiklander 
1495817466cbSJens Wiklander     /*
1496817466cbSJens Wiklander      * RSA operation
1497817466cbSJens Wiklander      */
14988452b181SSummer Qin     if( ctx->P.n == 0 )
1499*32b31808SJens Wiklander         ret = mbedtls_rsa_private( ctx, NULL, NULL, input, buf );
15008452b181SSummer Qin     else
1501*32b31808SJens Wiklander         ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf);
1502817466cbSJens Wiklander 
1503*32b31808SJens Wiklander     if (ret != 0) {
1504817466cbSJens Wiklander         goto cleanup;
1505*32b31808SJens Wiklander     }
1506817466cbSJens Wiklander 
1507817466cbSJens Wiklander     /*
1508817466cbSJens Wiklander      * Unmask data and generate lHash
1509817466cbSJens Wiklander      */
1510817466cbSJens Wiklander     /* seed: Apply seedMask to maskedSeed */
15113d3b0591SJens Wiklander     if ((ret = mgf_mask(buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
1512*32b31808SJens Wiklander                         ctx->hash_id)) != 0 ||
1513817466cbSJens Wiklander         /* DB: Apply dbMask to maskedDB */
15143d3b0591SJens Wiklander         (ret = mgf_mask(buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
1515*32b31808SJens Wiklander                         ctx->hash_id)) != 0) {
15163d3b0591SJens Wiklander         goto cleanup;
15173d3b0591SJens Wiklander     }
1518817466cbSJens Wiklander 
15193d3b0591SJens Wiklander     /* Generate lHash */
1520*32b31808SJens Wiklander     ret = compute_hash((mbedtls_md_type_t) ctx->hash_id,
1521*32b31808SJens Wiklander                        label, label_len, lhash);
1522*32b31808SJens Wiklander     if (ret != 0) {
15233d3b0591SJens Wiklander         goto cleanup;
1524*32b31808SJens Wiklander     }
15253d3b0591SJens Wiklander 
1526817466cbSJens Wiklander     /*
1527817466cbSJens Wiklander      * Check contents, in "constant-time"
1528817466cbSJens Wiklander      */
1529817466cbSJens Wiklander     p = buf;
1530817466cbSJens Wiklander     bad = 0;
1531817466cbSJens Wiklander 
1532817466cbSJens Wiklander     bad |= *p++; /* First byte must be 0 */
1533817466cbSJens Wiklander 
1534817466cbSJens Wiklander     p += hlen; /* Skip seed */
1535817466cbSJens Wiklander 
1536817466cbSJens Wiklander     /* Check lHash */
1537*32b31808SJens Wiklander     for (i = 0; i < hlen; i++) {
1538817466cbSJens Wiklander         bad |= lhash[i] ^ *p++;
1539*32b31808SJens Wiklander     }
1540817466cbSJens Wiklander 
1541817466cbSJens Wiklander     /* Get zero-padding len, but always read till end of buffer
1542817466cbSJens Wiklander      * (minus one, for the 01 byte) */
1543817466cbSJens Wiklander     pad_len = 0;
1544817466cbSJens Wiklander     pad_done = 0;
1545*32b31808SJens Wiklander     for (i = 0; i < ilen - 2 * hlen - 2; i++) {
1546817466cbSJens Wiklander         pad_done |= p[i];
1547817466cbSJens Wiklander         pad_len += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
1548817466cbSJens Wiklander     }
1549817466cbSJens Wiklander 
1550817466cbSJens Wiklander     p += pad_len;
1551817466cbSJens Wiklander     bad |= *p++ ^ 0x01;
1552817466cbSJens Wiklander 
1553817466cbSJens Wiklander     /*
1554817466cbSJens Wiklander      * The only information "leaked" is whether the padding was correct or not
1555817466cbSJens Wiklander      * (eg, no data is copied if it was not correct). This meets the
1556817466cbSJens Wiklander      * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
1557817466cbSJens Wiklander      * the different error conditions.
1558817466cbSJens Wiklander      */
1559*32b31808SJens Wiklander     if (bad != 0) {
1560817466cbSJens Wiklander         ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
1561817466cbSJens Wiklander         goto cleanup;
1562817466cbSJens Wiklander     }
1563817466cbSJens Wiklander 
1564*32b31808SJens Wiklander     if (ilen - (p - buf) > output_max_len) {
1565817466cbSJens Wiklander         ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
1566817466cbSJens Wiklander         goto cleanup;
1567817466cbSJens Wiklander     }
1568817466cbSJens Wiklander 
1569817466cbSJens Wiklander     *olen = ilen - (p - buf);
1570*32b31808SJens Wiklander     if (*olen != 0) {
1571817466cbSJens Wiklander         memcpy(output, p, *olen);
1572*32b31808SJens Wiklander     }
1573817466cbSJens Wiklander     ret = 0;
1574817466cbSJens Wiklander 
1575817466cbSJens Wiklander cleanup:
15763d3b0591SJens Wiklander     mbedtls_platform_zeroize(buf, sizeof(buf));
15773d3b0591SJens Wiklander     mbedtls_platform_zeroize(lhash, sizeof(lhash));
1578817466cbSJens Wiklander 
1579*32b31808SJens Wiklander     return ret;
1580817466cbSJens Wiklander }
1581817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */
1582817466cbSJens Wiklander 
1583817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
1584817466cbSJens Wiklander /*
1585817466cbSJens Wiklander  * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
1586817466cbSJens Wiklander  */
1587817466cbSJens Wiklander int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx,
1588817466cbSJens Wiklander                                         int (*f_rng)(void *, unsigned char *, size_t),
1589817466cbSJens Wiklander                                         void *p_rng,
1590039e02dfSJerome Forissier                                         size_t *olen,
1591817466cbSJens Wiklander                                         const unsigned char *input,
1592817466cbSJens Wiklander                                         unsigned char *output,
1593817466cbSJens Wiklander                                         size_t output_max_len)
1594817466cbSJens Wiklander {
159511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1596039e02dfSJerome Forissier     size_t ilen;
1597817466cbSJens Wiklander     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
15983d3b0591SJens Wiklander 
15993d3b0591SJens Wiklander     ilen = ctx->len;
1600817466cbSJens Wiklander 
1601*32b31808SJens Wiklander     if (ctx->padding != MBEDTLS_RSA_PKCS_V15) {
1602*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1603*32b31808SJens Wiklander     }
1604817466cbSJens Wiklander 
1605*32b31808SJens Wiklander     if (ilen < 16 || ilen > sizeof(buf)) {
1606*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1607*32b31808SJens Wiklander     }
1608817466cbSJens Wiklander 
1609*32b31808SJens Wiklander     ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf);
1610817466cbSJens Wiklander 
1611*32b31808SJens Wiklander     if (ret != 0) {
1612817466cbSJens Wiklander         goto cleanup;
1613*32b31808SJens Wiklander     }
1614817466cbSJens Wiklander 
1615*32b31808SJens Wiklander     ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding(buf, ilen,
1616039e02dfSJerome Forissier                                                output, output_max_len, olen);
1617817466cbSJens Wiklander 
1618817466cbSJens Wiklander cleanup:
16193d3b0591SJens Wiklander     mbedtls_platform_zeroize(buf, sizeof(buf));
1620817466cbSJens Wiklander 
1621*32b31808SJens Wiklander     return ret;
1622817466cbSJens Wiklander }
1623817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */
1624817466cbSJens Wiklander 
1625817466cbSJens Wiklander /*
1626817466cbSJens Wiklander  * Do an RSA operation, then remove the message padding
1627817466cbSJens Wiklander  */
1628817466cbSJens Wiklander int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx,
1629817466cbSJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t),
1630817466cbSJens Wiklander                               void *p_rng,
1631*32b31808SJens Wiklander                               size_t *olen,
1632817466cbSJens Wiklander                               const unsigned char *input,
1633817466cbSJens Wiklander                               unsigned char *output,
1634817466cbSJens Wiklander                               size_t output_max_len)
1635817466cbSJens Wiklander {
1636*32b31808SJens Wiklander     switch (ctx->padding) {
1637817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
1638817466cbSJens Wiklander         case MBEDTLS_RSA_PKCS_V15:
1639*32b31808SJens Wiklander             return mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx, f_rng, p_rng, olen,
1640817466cbSJens Wiklander                                                        input, output, output_max_len);
1641817466cbSJens Wiklander #endif
1642817466cbSJens Wiklander 
1643817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
1644817466cbSJens Wiklander         case MBEDTLS_RSA_PKCS_V21:
1645*32b31808SJens Wiklander             return mbedtls_rsa_rsaes_oaep_decrypt(ctx, f_rng, p_rng, NULL, 0,
1646817466cbSJens Wiklander                                                   olen, input, output,
1647817466cbSJens Wiklander                                                   output_max_len);
1648817466cbSJens Wiklander #endif
1649817466cbSJens Wiklander 
1650817466cbSJens Wiklander         default:
1651*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_INVALID_PADDING;
1652817466cbSJens Wiklander     }
1653817466cbSJens Wiklander }
1654817466cbSJens Wiklander 
1655817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
16567901324dSJerome Forissier static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
1657817466cbSJens Wiklander                                int (*f_rng)(void *, unsigned char *, size_t),
1658817466cbSJens Wiklander                                void *p_rng,
1659817466cbSJens Wiklander                                mbedtls_md_type_t md_alg,
1660817466cbSJens Wiklander                                unsigned int hashlen,
1661817466cbSJens Wiklander                                const unsigned char *hash,
16627901324dSJerome Forissier                                int saltlen,
1663817466cbSJens Wiklander                                unsigned char *sig)
1664817466cbSJens Wiklander {
1665817466cbSJens Wiklander     size_t olen;
1666817466cbSJens Wiklander     unsigned char *p = sig;
16677901324dSJerome Forissier     unsigned char *salt = NULL;
16683d3b0591SJens Wiklander     size_t slen, min_slen, hlen, offset = 0;
166911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1670817466cbSJens Wiklander     size_t msb;
1671817466cbSJens Wiklander 
1672*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
1673*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1674*32b31808SJens Wiklander     }
1675817466cbSJens Wiklander 
1676*32b31808SJens Wiklander     if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {
1677*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1678*32b31808SJens Wiklander     }
1679*32b31808SJens Wiklander 
1680*32b31808SJens Wiklander     if (f_rng == NULL) {
1681*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1682*32b31808SJens Wiklander     }
1683817466cbSJens Wiklander 
1684817466cbSJens Wiklander     olen = ctx->len;
1685817466cbSJens Wiklander 
1686*32b31808SJens Wiklander     if (md_alg != MBEDTLS_MD_NONE) {
1687817466cbSJens Wiklander         /* Gather length of hash to sign */
1688*32b31808SJens Wiklander         size_t exp_hashlen = mbedtls_hash_info_get_size(md_alg);
1689*32b31808SJens Wiklander         if (exp_hashlen == 0) {
1690*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1691817466cbSJens Wiklander         }
1692817466cbSJens Wiklander 
1693*32b31808SJens Wiklander         if (hashlen != exp_hashlen) {
1694*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1695*32b31808SJens Wiklander         }
1696*32b31808SJens Wiklander     }
1697817466cbSJens Wiklander 
1698*32b31808SJens Wiklander     hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
1699*32b31808SJens Wiklander     if (hlen == 0) {
1700*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1701*32b31808SJens Wiklander     }
1702817466cbSJens Wiklander 
1703*32b31808SJens Wiklander     if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) {
17047901324dSJerome Forissier         /* Calculate the largest possible salt length, up to the hash size.
17057901324dSJerome Forissier          * Normally this is the hash length, which is the maximum salt length
17067901324dSJerome Forissier          * according to FIPS 185-4 §5.5 (e) and common practice. If there is not
17073d3b0591SJens Wiklander          * enough room, use the maximum salt length that fits. The constraint is
17083d3b0591SJens Wiklander          * that the hash length plus the salt length plus 2 bytes must be at most
17093d3b0591SJens Wiklander          * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
17103d3b0591SJens Wiklander          * (PKCS#1 v2.2) §9.1.1 step 3. */
17113d3b0591SJens Wiklander         min_slen = hlen - 2;
1712*32b31808SJens Wiklander         if (olen < hlen + min_slen + 2) {
1713*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1714*32b31808SJens Wiklander         } else if (olen >= hlen + hlen + 2) {
17153d3b0591SJens Wiklander             slen = hlen;
1716*32b31808SJens Wiklander         } else {
17173d3b0591SJens Wiklander             slen = olen - hlen - 2;
17187901324dSJerome Forissier         }
1719*32b31808SJens Wiklander     } else if ((saltlen < 0) || (saltlen + hlen + 2 > olen)) {
1720*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1721*32b31808SJens Wiklander     } else {
17227901324dSJerome Forissier         slen = (size_t) saltlen;
17237901324dSJerome Forissier     }
1724817466cbSJens Wiklander 
1725817466cbSJens Wiklander     memset(sig, 0, olen);
1726817466cbSJens Wiklander 
1727817466cbSJens Wiklander     /* Note: EMSA-PSS encoding is over the length of N - 1 bits */
1728817466cbSJens Wiklander     msb = mbedtls_mpi_bitlen(&ctx->N) - 1;
17293d3b0591SJens Wiklander     p += olen - hlen - slen - 2;
1730817466cbSJens Wiklander     *p++ = 0x01;
17317901324dSJerome Forissier 
17327901324dSJerome Forissier     /* Generate salt of length slen in place in the encoded message */
17337901324dSJerome Forissier     salt = p;
1734*32b31808SJens Wiklander     if ((ret = f_rng(p_rng, salt, slen)) != 0) {
1735*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);
1736*32b31808SJens Wiklander     }
17377901324dSJerome Forissier 
1738817466cbSJens Wiklander     p += slen;
1739817466cbSJens Wiklander 
1740817466cbSJens Wiklander     /* Generate H = Hash( M' ) */
1741*32b31808SJens Wiklander     ret = hash_mprime(hash, hashlen, salt, slen, p, ctx->hash_id);
1742*32b31808SJens Wiklander     if (ret != 0) {
1743*32b31808SJens Wiklander         return ret;
1744*32b31808SJens Wiklander     }
1745817466cbSJens Wiklander 
1746817466cbSJens Wiklander     /* Compensate for boundary condition when applying mask */
1747*32b31808SJens Wiklander     if (msb % 8 == 0) {
1748817466cbSJens Wiklander         offset = 1;
1749*32b31808SJens Wiklander     }
1750817466cbSJens Wiklander 
1751817466cbSJens Wiklander     /* maskedDB: Apply dbMask to DB */
1752*32b31808SJens Wiklander     ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen,
1753*32b31808SJens Wiklander                    ctx->hash_id);
1754*32b31808SJens Wiklander     if (ret != 0) {
1755*32b31808SJens Wiklander         return ret;
1756*32b31808SJens Wiklander     }
1757817466cbSJens Wiklander 
1758817466cbSJens Wiklander     msb = mbedtls_mpi_bitlen(&ctx->N) - 1;
1759817466cbSJens Wiklander     sig[0] &= 0xFF >> (olen * 8 - msb);
1760817466cbSJens Wiklander 
1761817466cbSJens Wiklander     p += hlen;
1762817466cbSJens Wiklander     *p++ = 0xBC;
1763817466cbSJens Wiklander 
17648452b181SSummer Qin     if (ctx->P.n == 0)
1765*32b31808SJens Wiklander         return mbedtls_rsa_private(ctx, NULL, NULL, sig, sig);
1766*32b31808SJens Wiklander 
1767*32b31808SJens Wiklander     return mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig);
1768817466cbSJens Wiklander }
17697901324dSJerome Forissier 
17707901324dSJerome Forissier /*
17717901324dSJerome Forissier  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with
17727901324dSJerome Forissier  * the option to pass in the salt length.
17737901324dSJerome Forissier  */
17747901324dSJerome Forissier int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx,
17757901324dSJerome Forissier                                     int (*f_rng)(void *, unsigned char *, size_t),
17767901324dSJerome Forissier                                     void *p_rng,
17777901324dSJerome Forissier                                     mbedtls_md_type_t md_alg,
17787901324dSJerome Forissier                                     unsigned int hashlen,
17797901324dSJerome Forissier                                     const unsigned char *hash,
17807901324dSJerome Forissier                                     int saltlen,
17817901324dSJerome Forissier                                     unsigned char *sig)
17827901324dSJerome Forissier {
1783*32b31808SJens Wiklander     return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,
17847901324dSJerome Forissier                                hashlen, hash, saltlen, sig);
17857901324dSJerome Forissier }
17867901324dSJerome Forissier 
17877901324dSJerome Forissier 
17887901324dSJerome Forissier /*
17897901324dSJerome Forissier  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
17907901324dSJerome Forissier  */
17917901324dSJerome Forissier int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
17927901324dSJerome Forissier                                 int (*f_rng)(void *, unsigned char *, size_t),
17937901324dSJerome Forissier                                 void *p_rng,
17947901324dSJerome Forissier                                 mbedtls_md_type_t md_alg,
17957901324dSJerome Forissier                                 unsigned int hashlen,
17967901324dSJerome Forissier                                 const unsigned char *hash,
17977901324dSJerome Forissier                                 unsigned char *sig)
17987901324dSJerome Forissier {
1799*32b31808SJens Wiklander     return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,
18007901324dSJerome Forissier                                hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig);
18017901324dSJerome Forissier }
1802817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */
1803817466cbSJens Wiklander 
1804817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
1805817466cbSJens Wiklander /*
1806817466cbSJens Wiklander  * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
1807817466cbSJens Wiklander  */
18083d3b0591SJens Wiklander 
18093d3b0591SJens Wiklander /* Construct a PKCS v1.5 encoding of a hashed message
18103d3b0591SJens Wiklander  *
18113d3b0591SJens Wiklander  * This is used both for signature generation and verification.
18123d3b0591SJens Wiklander  *
18133d3b0591SJens Wiklander  * Parameters:
18143d3b0591SJens Wiklander  * - md_alg:  Identifies the hash algorithm used to generate the given hash;
18153d3b0591SJens Wiklander  *            MBEDTLS_MD_NONE if raw data is signed.
1816*32b31808SJens Wiklander  * - hashlen: Length of hash. Must match md_alg if that's not NONE.
18173d3b0591SJens Wiklander  * - hash:    Buffer containing the hashed message or the raw data.
18183d3b0591SJens Wiklander  * - dst_len: Length of the encoded message.
18193d3b0591SJens Wiklander  * - dst:     Buffer to hold the encoded message.
18203d3b0591SJens Wiklander  *
18213d3b0591SJens Wiklander  * Assumptions:
1822*32b31808SJens Wiklander  * - hash has size hashlen.
18233d3b0591SJens Wiklander  * - dst points to a buffer of size at least dst_len.
18243d3b0591SJens Wiklander  *
18253d3b0591SJens Wiklander  */
18263d3b0591SJens Wiklander static int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg,
18273d3b0591SJens Wiklander                                        unsigned int hashlen,
18283d3b0591SJens Wiklander                                        const unsigned char *hash,
18293d3b0591SJens Wiklander                                        size_t dst_len,
18303d3b0591SJens Wiklander                                        unsigned char *dst)
18313d3b0591SJens Wiklander {
18323d3b0591SJens Wiklander     size_t oid_size  = 0;
18333d3b0591SJens Wiklander     size_t nb_pad    = dst_len;
18343d3b0591SJens Wiklander     unsigned char *p = dst;
18353d3b0591SJens Wiklander     const char *oid  = NULL;
18363d3b0591SJens Wiklander 
18373d3b0591SJens Wiklander     /* Are we signing hashed or raw data? */
1838*32b31808SJens Wiklander     if (md_alg != MBEDTLS_MD_NONE) {
1839*32b31808SJens Wiklander         unsigned char md_size = mbedtls_hash_info_get_size(md_alg);
1840*32b31808SJens Wiklander         if (md_size == 0) {
1841*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1842*32b31808SJens Wiklander         }
18433d3b0591SJens Wiklander 
1844*32b31808SJens Wiklander         if (mbedtls_oid_get_oid_by_md(md_alg, &oid, &oid_size) != 0) {
1845*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1846*32b31808SJens Wiklander         }
18473d3b0591SJens Wiklander 
1848*32b31808SJens Wiklander         if (hashlen != md_size) {
1849*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1850*32b31808SJens Wiklander         }
18513d3b0591SJens Wiklander 
18523d3b0591SJens Wiklander         /* Double-check that 8 + hashlen + oid_size can be used as a
18533d3b0591SJens Wiklander          * 1-byte ASN.1 length encoding and that there's no overflow. */
18543d3b0591SJens Wiklander         if (8 + hashlen + oid_size  >= 0x80         ||
18553d3b0591SJens Wiklander             10 + hashlen            <  hashlen      ||
1856*32b31808SJens Wiklander             10 + hashlen + oid_size <  10 + hashlen) {
1857*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1858*32b31808SJens Wiklander         }
18593d3b0591SJens Wiklander 
18603d3b0591SJens Wiklander         /*
18613d3b0591SJens Wiklander          * Static bounds check:
18623d3b0591SJens Wiklander          * - Need 10 bytes for five tag-length pairs.
18633d3b0591SJens Wiklander          *   (Insist on 1-byte length encodings to protect against variants of
18643d3b0591SJens Wiklander          *    Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification)
18653d3b0591SJens Wiklander          * - Need hashlen bytes for hash
18663d3b0591SJens Wiklander          * - Need oid_size bytes for hash alg OID.
18673d3b0591SJens Wiklander          */
1868*32b31808SJens Wiklander         if (nb_pad < 10 + hashlen + oid_size) {
1869*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
18703d3b0591SJens Wiklander         }
1871*32b31808SJens Wiklander         nb_pad -= 10 + hashlen + oid_size;
1872*32b31808SJens Wiklander     } else {
1873*32b31808SJens Wiklander         if (nb_pad < hashlen) {
1874*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1875*32b31808SJens Wiklander         }
18763d3b0591SJens Wiklander 
18773d3b0591SJens Wiklander         nb_pad -= hashlen;
18783d3b0591SJens Wiklander     }
18793d3b0591SJens Wiklander 
18803d3b0591SJens Wiklander     /* Need space for signature header and padding delimiter (3 bytes),
18813d3b0591SJens Wiklander      * and 8 bytes for the minimal padding */
1882*32b31808SJens Wiklander     if (nb_pad < 3 + 8) {
1883*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1884*32b31808SJens Wiklander     }
18853d3b0591SJens Wiklander     nb_pad -= 3;
18863d3b0591SJens Wiklander 
18873d3b0591SJens Wiklander     /* Now nb_pad is the amount of memory to be filled
18883d3b0591SJens Wiklander      * with padding, and at least 8 bytes long. */
18893d3b0591SJens Wiklander 
18903d3b0591SJens Wiklander     /* Write signature header and padding */
18913d3b0591SJens Wiklander     *p++ = 0;
18923d3b0591SJens Wiklander     *p++ = MBEDTLS_RSA_SIGN;
18933d3b0591SJens Wiklander     memset(p, 0xFF, nb_pad);
18943d3b0591SJens Wiklander     p += nb_pad;
18953d3b0591SJens Wiklander     *p++ = 0;
18963d3b0591SJens Wiklander 
18973d3b0591SJens Wiklander     /* Are we signing raw data? */
1898*32b31808SJens Wiklander     if (md_alg == MBEDTLS_MD_NONE) {
18993d3b0591SJens Wiklander         memcpy(p, hash, hashlen);
1900*32b31808SJens Wiklander         return 0;
19013d3b0591SJens Wiklander     }
19023d3b0591SJens Wiklander 
19033d3b0591SJens Wiklander     /* Signing hashed data, add corresponding ASN.1 structure
19043d3b0591SJens Wiklander      *
19053d3b0591SJens Wiklander      * DigestInfo ::= SEQUENCE {
19063d3b0591SJens Wiklander      *   digestAlgorithm DigestAlgorithmIdentifier,
19073d3b0591SJens Wiklander      *   digest Digest }
19083d3b0591SJens Wiklander      * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
19093d3b0591SJens Wiklander      * Digest ::= OCTET STRING
19103d3b0591SJens Wiklander      *
19113d3b0591SJens Wiklander      * Schematic:
19123d3b0591SJens Wiklander      * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID  + LEN [ OID  ]
19133d3b0591SJens Wiklander      *                                 TAG-NULL + LEN [ NULL ] ]
19143d3b0591SJens Wiklander      *                 TAG-OCTET + LEN [ HASH ] ]
19153d3b0591SJens Wiklander      */
19163d3b0591SJens Wiklander     *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
19173d3b0591SJens Wiklander     *p++ = (unsigned char) (0x08 + oid_size + hashlen);
19183d3b0591SJens Wiklander     *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
19193d3b0591SJens Wiklander     *p++ = (unsigned char) (0x04 + oid_size);
19203d3b0591SJens Wiklander     *p++ = MBEDTLS_ASN1_OID;
19213d3b0591SJens Wiklander     *p++ = (unsigned char) oid_size;
19223d3b0591SJens Wiklander     memcpy(p, oid, oid_size);
19233d3b0591SJens Wiklander     p += oid_size;
19243d3b0591SJens Wiklander     *p++ = MBEDTLS_ASN1_NULL;
19253d3b0591SJens Wiklander     *p++ = 0x00;
19263d3b0591SJens Wiklander     *p++ = MBEDTLS_ASN1_OCTET_STRING;
19273d3b0591SJens Wiklander     *p++ = (unsigned char) hashlen;
19283d3b0591SJens Wiklander     memcpy(p, hash, hashlen);
19293d3b0591SJens Wiklander     p += hashlen;
19303d3b0591SJens Wiklander 
19313d3b0591SJens Wiklander     /* Just a sanity-check, should be automatic
19323d3b0591SJens Wiklander      * after the initial bounds check. */
1933*32b31808SJens Wiklander     if (p != dst + dst_len) {
19343d3b0591SJens Wiklander         mbedtls_platform_zeroize(dst, dst_len);
1935*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
19363d3b0591SJens Wiklander     }
19373d3b0591SJens Wiklander 
1938*32b31808SJens Wiklander     return 0;
19393d3b0591SJens Wiklander }
19403d3b0591SJens Wiklander 
1941817466cbSJens Wiklander /*
1942817466cbSJens Wiklander  * Do an RSA operation to sign the message digest
1943817466cbSJens Wiklander  */
1944817466cbSJens Wiklander int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx,
1945817466cbSJens Wiklander                                       int (*f_rng)(void *, unsigned char *, size_t),
1946817466cbSJens Wiklander                                       void *p_rng,
1947817466cbSJens Wiklander                                       mbedtls_md_type_t md_alg,
1948817466cbSJens Wiklander                                       unsigned int hashlen,
1949817466cbSJens Wiklander                                       const unsigned char *hash,
1950817466cbSJens Wiklander                                       unsigned char *sig)
1951817466cbSJens Wiklander {
195211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
19533d3b0591SJens Wiklander     unsigned char *sig_try = NULL, *verif = NULL;
19543d3b0591SJens Wiklander 
1955*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
1956*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1957*32b31808SJens Wiklander     }
1958817466cbSJens Wiklander 
1959*32b31808SJens Wiklander     if (ctx->padding != MBEDTLS_RSA_PKCS_V15) {
1960*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
1961*32b31808SJens Wiklander     }
1962817466cbSJens Wiklander 
1963817466cbSJens Wiklander     /*
19643d3b0591SJens Wiklander      * Prepare PKCS1-v1.5 encoding (padding and hash identifier)
1965817466cbSJens Wiklander      */
19663d3b0591SJens Wiklander 
19673d3b0591SJens Wiklander     if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash,
1968*32b31808SJens Wiklander                                            ctx->len, sig)) != 0) {
1969*32b31808SJens Wiklander         return ret;
19703d3b0591SJens Wiklander     }
1971817466cbSJens Wiklander 
19723d3b0591SJens Wiklander     /* Private key operation
19733d3b0591SJens Wiklander      *
1974817466cbSJens Wiklander      * In order to prevent Lenstra's attack, make the signature in a
1975817466cbSJens Wiklander      * temporary buffer and check it before returning it.
1976817466cbSJens Wiklander      */
19773d3b0591SJens Wiklander 
1978817466cbSJens Wiklander     sig_try = mbedtls_calloc(1, ctx->len);
1979*32b31808SJens Wiklander     if (sig_try == NULL) {
1980*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
1981*32b31808SJens Wiklander     }
1982817466cbSJens Wiklander 
1983817466cbSJens Wiklander     verif = mbedtls_calloc(1, ctx->len);
1984*32b31808SJens Wiklander     if (verif == NULL) {
1985817466cbSJens Wiklander         mbedtls_free(sig_try);
1986*32b31808SJens Wiklander         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
1987817466cbSJens Wiklander     }
1988817466cbSJens Wiklander 
1989817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig_try));
1990817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_public(ctx, sig_try, verif));
1991817466cbSJens Wiklander 
1992*32b31808SJens Wiklander     if (mbedtls_ct_memcmp(verif, sig, ctx->len) != 0) {
1993817466cbSJens Wiklander         ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
1994817466cbSJens Wiklander         goto cleanup;
1995817466cbSJens Wiklander     }
1996817466cbSJens Wiklander 
1997817466cbSJens Wiklander     memcpy(sig, sig_try, ctx->len);
1998817466cbSJens Wiklander 
1999817466cbSJens Wiklander cleanup:
2000039e02dfSJerome Forissier     mbedtls_platform_zeroize(sig_try, ctx->len);
2001039e02dfSJerome Forissier     mbedtls_platform_zeroize(verif, ctx->len);
2002817466cbSJens Wiklander     mbedtls_free(sig_try);
2003817466cbSJens Wiklander     mbedtls_free(verif);
2004817466cbSJens Wiklander 
2005*32b31808SJens Wiklander     if (ret != 0) {
2006039e02dfSJerome Forissier         memset(sig, '!', ctx->len);
2007*32b31808SJens Wiklander     }
2008*32b31808SJens Wiklander     return ret;
2009817466cbSJens Wiklander }
2010817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */
2011817466cbSJens Wiklander 
2012817466cbSJens Wiklander /*
2013817466cbSJens Wiklander  * Do an RSA operation to sign the message digest
2014817466cbSJens Wiklander  */
2015817466cbSJens Wiklander int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx,
2016817466cbSJens Wiklander                            int (*f_rng)(void *, unsigned char *, size_t),
2017817466cbSJens Wiklander                            void *p_rng,
2018817466cbSJens Wiklander                            mbedtls_md_type_t md_alg,
2019817466cbSJens Wiklander                            unsigned int hashlen,
2020817466cbSJens Wiklander                            const unsigned char *hash,
2021817466cbSJens Wiklander                            unsigned char *sig)
2022817466cbSJens Wiklander {
2023*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
2024*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2025*32b31808SJens Wiklander     }
20263d3b0591SJens Wiklander 
2027*32b31808SJens Wiklander     switch (ctx->padding) {
2028817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
2029817466cbSJens Wiklander         case MBEDTLS_RSA_PKCS_V15:
2030*32b31808SJens Wiklander             return mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx, f_rng, p_rng,
2031*32b31808SJens Wiklander                                                      md_alg, hashlen, hash, sig);
2032817466cbSJens Wiklander #endif
2033817466cbSJens Wiklander 
2034817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
2035817466cbSJens Wiklander         case MBEDTLS_RSA_PKCS_V21:
2036*32b31808SJens Wiklander             return mbedtls_rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,
2037817466cbSJens Wiklander                                                hashlen, hash, sig);
2038817466cbSJens Wiklander #endif
2039817466cbSJens Wiklander 
2040817466cbSJens Wiklander         default:
2041*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_INVALID_PADDING;
2042817466cbSJens Wiklander     }
2043817466cbSJens Wiklander }
2044817466cbSJens Wiklander 
2045817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
2046817466cbSJens Wiklander /*
2047817466cbSJens Wiklander  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
2048817466cbSJens Wiklander  */
2049817466cbSJens Wiklander int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx,
2050817466cbSJens Wiklander                                       mbedtls_md_type_t md_alg,
2051817466cbSJens Wiklander                                       unsigned int hashlen,
2052817466cbSJens Wiklander                                       const unsigned char *hash,
2053817466cbSJens Wiklander                                       mbedtls_md_type_t mgf1_hash_id,
2054817466cbSJens Wiklander                                       int expected_salt_len,
2055817466cbSJens Wiklander                                       const unsigned char *sig)
2056817466cbSJens Wiklander {
205711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2058817466cbSJens Wiklander     size_t siglen;
2059817466cbSJens Wiklander     unsigned char *p;
20603d3b0591SJens Wiklander     unsigned char *hash_start;
2061*32b31808SJens Wiklander     unsigned char result[MBEDTLS_HASH_MAX_SIZE];
2062817466cbSJens Wiklander     unsigned int hlen;
20633d3b0591SJens Wiklander     size_t observed_salt_len, msb;
2064*32b31808SJens Wiklander     unsigned char buf[MBEDTLS_MPI_MAX_SIZE] = { 0 };
2065817466cbSJens Wiklander 
2066*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
2067*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2068*32b31808SJens Wiklander     }
2069817466cbSJens Wiklander 
2070817466cbSJens Wiklander     siglen = ctx->len;
2071817466cbSJens Wiklander 
2072*32b31808SJens Wiklander     if (siglen < 16 || siglen > sizeof(buf)) {
2073*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2074*32b31808SJens Wiklander     }
2075817466cbSJens Wiklander 
2076*32b31808SJens Wiklander     ret = mbedtls_rsa_public(ctx, sig, buf);
2077817466cbSJens Wiklander 
2078*32b31808SJens Wiklander     if (ret != 0) {
2079*32b31808SJens Wiklander         return ret;
2080*32b31808SJens Wiklander     }
2081817466cbSJens Wiklander 
2082817466cbSJens Wiklander     p = buf;
2083817466cbSJens Wiklander 
2084*32b31808SJens Wiklander     if (buf[siglen - 1] != 0xBC) {
2085*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_INVALID_PADDING;
2086817466cbSJens Wiklander     }
2087817466cbSJens Wiklander 
2088*32b31808SJens Wiklander     if (md_alg != MBEDTLS_MD_NONE) {
2089*32b31808SJens Wiklander         /* Gather length of hash to sign */
2090*32b31808SJens Wiklander         size_t exp_hashlen = mbedtls_hash_info_get_size(md_alg);
2091*32b31808SJens Wiklander         if (exp_hashlen == 0) {
2092*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2093*32b31808SJens Wiklander         }
2094817466cbSJens Wiklander 
2095*32b31808SJens Wiklander         if (hashlen != exp_hashlen) {
2096*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2097*32b31808SJens Wiklander         }
2098*32b31808SJens Wiklander     }
2099817466cbSJens Wiklander 
2100*32b31808SJens Wiklander     hlen = mbedtls_hash_info_get_size(mgf1_hash_id);
2101*32b31808SJens Wiklander     if (hlen == 0) {
2102*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2103*32b31808SJens Wiklander     }
2104817466cbSJens Wiklander 
2105817466cbSJens Wiklander     /*
2106817466cbSJens Wiklander      * Note: EMSA-PSS verification is over the length of N - 1 bits
2107817466cbSJens Wiklander      */
2108817466cbSJens Wiklander     msb = mbedtls_mpi_bitlen(&ctx->N) - 1;
2109817466cbSJens Wiklander 
2110*32b31808SJens Wiklander     if (buf[0] >> (8 - siglen * 8 + msb)) {
2111*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2112*32b31808SJens Wiklander     }
21133d3b0591SJens Wiklander 
2114817466cbSJens Wiklander     /* Compensate for boundary condition when applying mask */
2115*32b31808SJens Wiklander     if (msb % 8 == 0) {
2116817466cbSJens Wiklander         p++;
2117817466cbSJens Wiklander         siglen -= 1;
2118817466cbSJens Wiklander     }
21193d3b0591SJens Wiklander 
2120*32b31808SJens Wiklander     if (siglen < hlen + 2) {
2121*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2122*32b31808SJens Wiklander     }
21233d3b0591SJens Wiklander     hash_start = p + siglen - hlen - 1;
2124817466cbSJens Wiklander 
2125*32b31808SJens Wiklander     ret = mgf_mask(p, siglen - hlen - 1, hash_start, hlen, mgf1_hash_id);
2126*32b31808SJens Wiklander     if (ret != 0) {
2127*32b31808SJens Wiklander         return ret;
2128*32b31808SJens Wiklander     }
2129817466cbSJens Wiklander 
2130817466cbSJens Wiklander     buf[0] &= 0xFF >> (siglen * 8 - msb);
2131817466cbSJens Wiklander 
2132*32b31808SJens Wiklander     while (p < hash_start - 1 && *p == 0) {
2133817466cbSJens Wiklander         p++;
2134*32b31808SJens Wiklander     }
2135817466cbSJens Wiklander 
2136*32b31808SJens Wiklander     if (*p++ != 0x01) {
2137*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_INVALID_PADDING;
2138817466cbSJens Wiklander     }
2139817466cbSJens Wiklander 
21403d3b0591SJens Wiklander     observed_salt_len = hash_start - p;
2141817466cbSJens Wiklander 
2142817466cbSJens Wiklander     if (expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&
2143*32b31808SJens Wiklander         observed_salt_len != (size_t) expected_salt_len) {
2144*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_INVALID_PADDING;
2145817466cbSJens Wiklander     }
2146817466cbSJens Wiklander 
2147817466cbSJens Wiklander     /*
2148817466cbSJens Wiklander      * Generate H = Hash( M' )
2149817466cbSJens Wiklander      */
2150*32b31808SJens Wiklander     ret = hash_mprime(hash, hashlen, p, observed_salt_len,
2151*32b31808SJens Wiklander                       result, mgf1_hash_id);
2152*32b31808SJens Wiklander     if (ret != 0) {
2153*32b31808SJens Wiklander         return ret;
21543d3b0591SJens Wiklander     }
21553d3b0591SJens Wiklander 
2156*32b31808SJens Wiklander     if (FTMN_CALLEE_DONE_MEMCMP(memcmp, hash_start, result, hlen) != 0) {
2157*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_VERIFY_FAILED;
2158*32b31808SJens Wiklander     }
2159817466cbSJens Wiklander 
2160*32b31808SJens Wiklander     return 0;
2161817466cbSJens Wiklander }
2162817466cbSJens Wiklander 
2163817466cbSJens Wiklander /*
2164817466cbSJens Wiklander  * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function
2165817466cbSJens Wiklander  */
2166817466cbSJens Wiklander int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx,
2167817466cbSJens Wiklander                                   mbedtls_md_type_t md_alg,
2168817466cbSJens Wiklander                                   unsigned int hashlen,
2169817466cbSJens Wiklander                                   const unsigned char *hash,
2170817466cbSJens Wiklander                                   const unsigned char *sig)
2171817466cbSJens Wiklander {
21723d3b0591SJens Wiklander     mbedtls_md_type_t mgf1_hash_id;
2173*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
2174*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2175*32b31808SJens Wiklander     }
21763d3b0591SJens Wiklander 
21773d3b0591SJens Wiklander     mgf1_hash_id = (ctx->hash_id != MBEDTLS_MD_NONE)
2178817466cbSJens Wiklander                              ? (mbedtls_md_type_t) ctx->hash_id
2179817466cbSJens Wiklander                              : md_alg;
2180817466cbSJens Wiklander 
2181*32b31808SJens Wiklander     return mbedtls_rsa_rsassa_pss_verify_ext(ctx,
2182817466cbSJens Wiklander                                              md_alg, hashlen, hash,
2183*32b31808SJens Wiklander                                              mgf1_hash_id,
2184*32b31808SJens Wiklander                                              MBEDTLS_RSA_SALT_LEN_ANY,
2185*32b31808SJens Wiklander                                              sig);
2186817466cbSJens Wiklander 
2187817466cbSJens Wiklander }
2188817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */
2189817466cbSJens Wiklander 
2190817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
2191817466cbSJens Wiklander /*
2192817466cbSJens Wiklander  * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
2193817466cbSJens Wiklander  */
2194817466cbSJens Wiklander int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx,
2195817466cbSJens Wiklander                                         mbedtls_md_type_t md_alg,
2196817466cbSJens Wiklander                                         unsigned int hashlen,
2197817466cbSJens Wiklander                                         const unsigned char *hash,
2198817466cbSJens Wiklander                                         const unsigned char *sig)
2199817466cbSJens Wiklander {
22003d3b0591SJens Wiklander     int ret = 0;
22013d3b0591SJens Wiklander     size_t sig_len;
22023d3b0591SJens Wiklander     unsigned char *encoded = NULL, *encoded_expected = NULL;
22033d3b0591SJens Wiklander 
2204*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
2205*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2206*32b31808SJens Wiklander     }
22073d3b0591SJens Wiklander 
22083d3b0591SJens Wiklander     sig_len = ctx->len;
2209817466cbSJens Wiklander 
22103d3b0591SJens Wiklander     /*
22113d3b0591SJens Wiklander      * Prepare expected PKCS1 v1.5 encoding of hash.
22123d3b0591SJens Wiklander      */
2213817466cbSJens Wiklander 
22143d3b0591SJens Wiklander     if ((encoded          = mbedtls_calloc(1, sig_len)) == NULL ||
2215*32b31808SJens Wiklander         (encoded_expected = mbedtls_calloc(1, sig_len)) == NULL) {
22163d3b0591SJens Wiklander         ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
22173d3b0591SJens Wiklander         goto cleanup;
22183d3b0591SJens Wiklander     }
22193d3b0591SJens Wiklander 
22203d3b0591SJens Wiklander     if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash, sig_len,
2221*32b31808SJens Wiklander                                            encoded_expected)) != 0) {
22223d3b0591SJens Wiklander         goto cleanup;
2223*32b31808SJens Wiklander     }
22243d3b0591SJens Wiklander 
22253d3b0591SJens Wiklander     /*
22263d3b0591SJens Wiklander      * Apply RSA primitive to get what should be PKCS1 encoded hash.
22273d3b0591SJens Wiklander      */
2228817466cbSJens Wiklander 
2229*32b31808SJens Wiklander     ret = mbedtls_rsa_public(ctx, sig, encoded);
2230*32b31808SJens Wiklander     if (ret != 0) {
22313d3b0591SJens Wiklander         goto cleanup;
2232*32b31808SJens Wiklander     }
22333d3b0591SJens Wiklander 
22343d3b0591SJens Wiklander     /*
22353d3b0591SJens Wiklander      * Compare
22363d3b0591SJens Wiklander      */
22373d3b0591SJens Wiklander 
223806de6080SJens Wiklander     if ((ret = FTMN_CALLEE_DONE_MEMCMP(mbedtls_ct_memcmp, encoded,
2239*32b31808SJens Wiklander                                        encoded_expected, sig_len )) != 0) {
22403d3b0591SJens Wiklander         ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
22413d3b0591SJens Wiklander         goto cleanup;
22423d3b0591SJens Wiklander     }
22433d3b0591SJens Wiklander 
22443d3b0591SJens Wiklander cleanup:
22453d3b0591SJens Wiklander 
2246*32b31808SJens Wiklander     if (encoded != NULL) {
22473d3b0591SJens Wiklander         mbedtls_platform_zeroize(encoded, sig_len);
22483d3b0591SJens Wiklander         mbedtls_free(encoded);
22493d3b0591SJens Wiklander     }
22503d3b0591SJens Wiklander 
2251*32b31808SJens Wiklander     if (encoded_expected != NULL) {
22523d3b0591SJens Wiklander         mbedtls_platform_zeroize(encoded_expected, sig_len);
22533d3b0591SJens Wiklander         mbedtls_free(encoded_expected);
22543d3b0591SJens Wiklander     }
22553d3b0591SJens Wiklander 
2256*32b31808SJens Wiklander     return ret;
2257817466cbSJens Wiklander }
2258817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */
2259817466cbSJens Wiklander 
2260817466cbSJens Wiklander /*
2261817466cbSJens Wiklander  * Do an RSA operation and check the message digest
2262817466cbSJens Wiklander  */
2263817466cbSJens Wiklander int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx,
2264817466cbSJens Wiklander                              mbedtls_md_type_t md_alg,
2265817466cbSJens Wiklander                              unsigned int hashlen,
2266817466cbSJens Wiklander                              const unsigned char *hash,
2267817466cbSJens Wiklander                              const unsigned char *sig)
2268817466cbSJens Wiklander {
2269*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
2270*32b31808SJens Wiklander         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
2271*32b31808SJens Wiklander     }
22723d3b0591SJens Wiklander 
2273*32b31808SJens Wiklander     switch (ctx->padding) {
2274817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
2275817466cbSJens Wiklander         case MBEDTLS_RSA_PKCS_V15:
2276*32b31808SJens Wiklander             return mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx, md_alg,
2277817466cbSJens Wiklander                                                        hashlen, hash, sig);
2278817466cbSJens Wiklander #endif
2279817466cbSJens Wiklander 
2280817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21)
2281817466cbSJens Wiklander         case MBEDTLS_RSA_PKCS_V21:
2282*32b31808SJens Wiklander             return mbedtls_rsa_rsassa_pss_verify(ctx, md_alg,
2283817466cbSJens Wiklander                                                  hashlen, hash, sig);
2284817466cbSJens Wiklander #endif
2285817466cbSJens Wiklander 
2286817466cbSJens Wiklander         default:
2287*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_INVALID_PADDING;
2288817466cbSJens Wiklander     }
2289817466cbSJens Wiklander }
2290817466cbSJens Wiklander 
2291817466cbSJens Wiklander /*
2292817466cbSJens Wiklander  * Copy the components of an RSA key
2293817466cbSJens Wiklander  */
2294817466cbSJens Wiklander int mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src)
2295817466cbSJens Wiklander {
229611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2297817466cbSJens Wiklander 
2298817466cbSJens Wiklander     dst->len = src->len;
2299817466cbSJens Wiklander 
2300817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->N, &src->N));
2301817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->E, &src->E));
2302817466cbSJens Wiklander 
2303817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->D, &src->D));
2304817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->P, &src->P));
2305817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Q, &src->Q));
23063d3b0591SJens Wiklander 
23073d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
2308817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DP, &src->DP));
2309817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DQ, &src->DQ));
2310817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->QP, &src->QP));
2311817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RP, &src->RP));
2312817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RQ, &src->RQ));
23133d3b0591SJens Wiklander #endif
23143d3b0591SJens Wiklander 
23153d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RN, &src->RN));
2316817466cbSJens Wiklander 
2317817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vi, &src->Vi));
2318817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vf, &src->Vf));
2319817466cbSJens Wiklander 
2320817466cbSJens Wiklander     dst->padding = src->padding;
2321817466cbSJens Wiklander     dst->hash_id = src->hash_id;
2322817466cbSJens Wiklander 
2323817466cbSJens Wiklander cleanup:
2324*32b31808SJens Wiklander     if (ret != 0) {
2325817466cbSJens Wiklander         mbedtls_rsa_free(dst);
2326*32b31808SJens Wiklander     }
2327817466cbSJens Wiklander 
2328*32b31808SJens Wiklander     return ret;
2329817466cbSJens Wiklander }
2330817466cbSJens Wiklander 
2331817466cbSJens Wiklander /*
2332817466cbSJens Wiklander  * Free the components of an RSA key
2333817466cbSJens Wiklander  */
2334817466cbSJens Wiklander void mbedtls_rsa_free(mbedtls_rsa_context *ctx)
2335817466cbSJens Wiklander {
2336*32b31808SJens Wiklander     if (ctx == NULL) {
23373d3b0591SJens Wiklander         return;
2338*32b31808SJens Wiklander     }
23393d3b0591SJens Wiklander 
23403d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->Vi);
23413d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->Vf);
23423d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->RN);
23433d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->D);
23443d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->Q);
23453d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->P);
23463d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->E);
23473d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->N);
23483d3b0591SJens Wiklander 
23493d3b0591SJens Wiklander #if !defined(MBEDTLS_RSA_NO_CRT)
23503d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->RQ);
23513d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->RP);
23523d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->QP);
23533d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->DQ);
23543d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->DP);
23553d3b0591SJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */
2356817466cbSJens Wiklander 
2357817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C)
23587901324dSJerome Forissier     /* Free the mutex, but only if it hasn't been freed already. */
2359*32b31808SJens Wiklander     if (ctx->ver != 0) {
2360817466cbSJens Wiklander         mbedtls_mutex_free(&ctx->mutex);
23617901324dSJerome Forissier         ctx->ver = 0;
23627901324dSJerome Forissier     }
2363817466cbSJens Wiklander #endif
2364817466cbSJens Wiklander }
2365817466cbSJens Wiklander 
23663d3b0591SJens Wiklander #endif /* !MBEDTLS_RSA_ALT */
23673d3b0591SJens Wiklander 
2368817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
2369817466cbSJens Wiklander 
2370*32b31808SJens Wiklander #include "mbedtls/md.h"
2371817466cbSJens Wiklander 
2372817466cbSJens Wiklander /*
2373817466cbSJens Wiklander  * Example RSA-1024 keypair, for test purposes
2374817466cbSJens Wiklander  */
2375817466cbSJens Wiklander #define KEY_LEN 128
2376817466cbSJens Wiklander 
2377817466cbSJens Wiklander #define RSA_N   "9292758453063D803DD603D5E777D788" \
2378817466cbSJens Wiklander                 "8ED1D5BF35786190FA2F23EBC0848AEA" \
2379817466cbSJens Wiklander                 "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
2380817466cbSJens Wiklander                 "7130B9CED7ACDF54CFC7555AC14EEBAB" \
2381817466cbSJens Wiklander                 "93A89813FBF3C4F8066D2D800F7C38A8" \
2382817466cbSJens Wiklander                 "1AE31942917403FF4946B0A83D3D3E05" \
2383817466cbSJens Wiklander                 "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
2384817466cbSJens Wiklander                 "5E94BB77B07507233A0BC7BAC8F90F79"
2385817466cbSJens Wiklander 
2386817466cbSJens Wiklander #define RSA_E   "10001"
2387817466cbSJens Wiklander 
2388817466cbSJens Wiklander #define RSA_D   "24BF6185468786FDD303083D25E64EFC" \
2389817466cbSJens Wiklander                 "66CA472BC44D253102F8B4A9D3BFA750" \
2390817466cbSJens Wiklander                 "91386C0077937FE33FA3252D28855837" \
2391817466cbSJens Wiklander                 "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
2392817466cbSJens Wiklander                 "DF79C5CE07EE72C7F123142198164234" \
2393817466cbSJens Wiklander                 "CABB724CF78B8173B9F880FC86322407" \
2394817466cbSJens Wiklander                 "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
2395817466cbSJens Wiklander                 "071513A1E85B5DFA031F21ECAE91A34D"
2396817466cbSJens Wiklander 
2397817466cbSJens Wiklander #define RSA_P   "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
2398817466cbSJens Wiklander                 "2C01CAD19EA484A87EA4377637E75500" \
2399817466cbSJens Wiklander                 "FCB2005C5C7DD6EC4AC023CDA285D796" \
2400817466cbSJens Wiklander                 "C3D9E75E1EFC42488BB4F1D13AC30A57"
2401817466cbSJens Wiklander 
2402817466cbSJens Wiklander #define RSA_Q   "C000DF51A7C77AE8D7C7370C1FF55B69" \
2403817466cbSJens Wiklander                 "E211C2B9E5DB1ED0BF61D0D9899620F4" \
2404817466cbSJens Wiklander                 "910E4168387E3C30AA1E00C339A79508" \
2405817466cbSJens Wiklander                 "8452DD96A9A5EA5D9DCA68DA636032AF"
2406817466cbSJens Wiklander 
2407817466cbSJens Wiklander #define PT_LEN  24
2408817466cbSJens Wiklander #define RSA_PT  "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
2409817466cbSJens Wiklander                 "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
2410817466cbSJens Wiklander 
2411817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
2412817466cbSJens Wiklander static int myrand(void *rng_state, unsigned char *output, size_t len)
2413817466cbSJens Wiklander {
24147901324dSJerome Forissier #if !defined(__OpenBSD__) && !defined(__NetBSD__)
2415817466cbSJens Wiklander     size_t i;
2416817466cbSJens Wiklander 
2417*32b31808SJens Wiklander     if (rng_state != NULL) {
2418817466cbSJens Wiklander         rng_state  = NULL;
2419*32b31808SJens Wiklander     }
2420817466cbSJens Wiklander 
2421*32b31808SJens Wiklander     for (i = 0; i < len; ++i) {
2422817466cbSJens Wiklander         output[i] = rand();
2423*32b31808SJens Wiklander     }
2424817466cbSJens Wiklander #else
2425*32b31808SJens Wiklander     if (rng_state != NULL) {
2426817466cbSJens Wiklander         rng_state = NULL;
2427*32b31808SJens Wiklander     }
2428817466cbSJens Wiklander 
2429817466cbSJens Wiklander     arc4random_buf(output, len);
24307901324dSJerome Forissier #endif /* !OpenBSD && !NetBSD */
2431817466cbSJens Wiklander 
2432*32b31808SJens Wiklander     return 0;
2433817466cbSJens Wiklander }
2434817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */
2435817466cbSJens Wiklander 
2436817466cbSJens Wiklander /*
2437817466cbSJens Wiklander  * Checkup routine
2438817466cbSJens Wiklander  */
2439817466cbSJens Wiklander int mbedtls_rsa_self_test(int verbose)
2440817466cbSJens Wiklander {
2441817466cbSJens Wiklander     int ret = 0;
2442817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15)
2443817466cbSJens Wiklander     size_t len;
2444817466cbSJens Wiklander     mbedtls_rsa_context rsa;
2445817466cbSJens Wiklander     unsigned char rsa_plaintext[PT_LEN];
2446817466cbSJens Wiklander     unsigned char rsa_decrypted[PT_LEN];
2447817466cbSJens Wiklander     unsigned char rsa_ciphertext[KEY_LEN];
2448817466cbSJens Wiklander #if defined(MBEDTLS_SHA1_C)
2449817466cbSJens Wiklander     unsigned char sha1sum[20];
2450817466cbSJens Wiklander #endif
2451817466cbSJens Wiklander 
24523d3b0591SJens Wiklander     mbedtls_mpi K;
24533d3b0591SJens Wiklander 
24543d3b0591SJens Wiklander     mbedtls_mpi_init(&K);
2455*32b31808SJens Wiklander     mbedtls_rsa_init(&rsa);
2456817466cbSJens Wiklander 
24573d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_N));
24583d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, &K, NULL, NULL, NULL, NULL));
24593d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_P));
24603d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, &K, NULL, NULL, NULL));
24613d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_Q));
24623d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, &K, NULL, NULL));
24633d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_D));
24643d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, &K, NULL));
24653d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_E));
24663d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, NULL, &K));
24673d3b0591SJens Wiklander 
24683d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_rsa_complete(&rsa));
2469817466cbSJens Wiklander 
2470*32b31808SJens Wiklander     if (verbose != 0) {
2471817466cbSJens Wiklander         mbedtls_printf("  RSA key validation: ");
2472*32b31808SJens Wiklander     }
2473817466cbSJens Wiklander 
2474817466cbSJens Wiklander     if (mbedtls_rsa_check_pubkey(&rsa) != 0 ||
2475*32b31808SJens Wiklander         mbedtls_rsa_check_privkey(&rsa) != 0) {
2476*32b31808SJens Wiklander         if (verbose != 0) {
2477817466cbSJens Wiklander             mbedtls_printf("failed\n");
2478*32b31808SJens Wiklander         }
2479817466cbSJens Wiklander 
24803d3b0591SJens Wiklander         ret = 1;
24813d3b0591SJens Wiklander         goto cleanup;
2482817466cbSJens Wiklander     }
2483817466cbSJens Wiklander 
2484*32b31808SJens Wiklander     if (verbose != 0) {
2485817466cbSJens Wiklander         mbedtls_printf("passed\n  PKCS#1 encryption : ");
2486*32b31808SJens Wiklander     }
2487817466cbSJens Wiklander 
2488817466cbSJens Wiklander     memcpy(rsa_plaintext, RSA_PT, PT_LEN);
2489817466cbSJens Wiklander 
2490*32b31808SJens Wiklander     if (mbedtls_rsa_pkcs1_encrypt(&rsa, myrand, NULL,
24913d3b0591SJens Wiklander                                   PT_LEN, rsa_plaintext,
2492*32b31808SJens Wiklander                                   rsa_ciphertext) != 0) {
2493*32b31808SJens Wiklander         if (verbose != 0) {
2494817466cbSJens Wiklander             mbedtls_printf("failed\n");
2495*32b31808SJens Wiklander         }
2496817466cbSJens Wiklander 
24973d3b0591SJens Wiklander         ret = 1;
24983d3b0591SJens Wiklander         goto cleanup;
2499817466cbSJens Wiklander     }
2500817466cbSJens Wiklander 
2501*32b31808SJens Wiklander     if (verbose != 0) {
2502817466cbSJens Wiklander         mbedtls_printf("passed\n  PKCS#1 decryption : ");
2503*32b31808SJens Wiklander     }
2504817466cbSJens Wiklander 
2505*32b31808SJens Wiklander     if (mbedtls_rsa_pkcs1_decrypt(&rsa, myrand, NULL,
25063d3b0591SJens Wiklander                                   &len, rsa_ciphertext, rsa_decrypted,
2507*32b31808SJens Wiklander                                   sizeof(rsa_decrypted)) != 0) {
2508*32b31808SJens Wiklander         if (verbose != 0) {
2509817466cbSJens Wiklander             mbedtls_printf("failed\n");
2510*32b31808SJens Wiklander         }
2511817466cbSJens Wiklander 
25123d3b0591SJens Wiklander         ret = 1;
25133d3b0591SJens Wiklander         goto cleanup;
2514817466cbSJens Wiklander     }
2515817466cbSJens Wiklander 
2516*32b31808SJens Wiklander     if (memcmp(rsa_decrypted, rsa_plaintext, len) != 0) {
2517*32b31808SJens Wiklander         if (verbose != 0) {
2518817466cbSJens Wiklander             mbedtls_printf("failed\n");
2519*32b31808SJens Wiklander         }
2520817466cbSJens Wiklander 
25213d3b0591SJens Wiklander         ret = 1;
25223d3b0591SJens Wiklander         goto cleanup;
2523817466cbSJens Wiklander     }
2524817466cbSJens Wiklander 
2525*32b31808SJens Wiklander     if (verbose != 0) {
2526817466cbSJens Wiklander         mbedtls_printf("passed\n");
2527*32b31808SJens Wiklander     }
2528817466cbSJens Wiklander 
2529817466cbSJens Wiklander #if defined(MBEDTLS_SHA1_C)
2530*32b31808SJens Wiklander     if (verbose != 0) {
2531817466cbSJens Wiklander         mbedtls_printf("  PKCS#1 data sign  : ");
2532*32b31808SJens Wiklander     }
2533817466cbSJens Wiklander 
2534*32b31808SJens Wiklander     if (mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1),
2535*32b31808SJens Wiklander                    rsa_plaintext, PT_LEN, sha1sum) != 0) {
2536*32b31808SJens Wiklander         if (verbose != 0) {
2537817466cbSJens Wiklander             mbedtls_printf("failed\n");
2538*32b31808SJens Wiklander         }
2539817466cbSJens Wiklander 
2540*32b31808SJens Wiklander         return 1;
2541817466cbSJens Wiklander     }
2542817466cbSJens Wiklander 
25433d3b0591SJens Wiklander     if (mbedtls_rsa_pkcs1_sign(&rsa, myrand, NULL,
2544*32b31808SJens Wiklander                                MBEDTLS_MD_SHA1, 20,
2545*32b31808SJens Wiklander                                sha1sum, rsa_ciphertext) != 0) {
2546*32b31808SJens Wiklander         if (verbose != 0) {
2547817466cbSJens Wiklander             mbedtls_printf("failed\n");
2548*32b31808SJens Wiklander         }
2549817466cbSJens Wiklander 
25503d3b0591SJens Wiklander         ret = 1;
25513d3b0591SJens Wiklander         goto cleanup;
25523d3b0591SJens Wiklander     }
25533d3b0591SJens Wiklander 
2554*32b31808SJens Wiklander     if (verbose != 0) {
25553d3b0591SJens Wiklander         mbedtls_printf("passed\n  PKCS#1 sig. verify: ");
2556*32b31808SJens Wiklander     }
25573d3b0591SJens Wiklander 
2558*32b31808SJens Wiklander     if (mbedtls_rsa_pkcs1_verify(&rsa, MBEDTLS_MD_SHA1, 20,
2559*32b31808SJens Wiklander                                  sha1sum, rsa_ciphertext) != 0) {
2560*32b31808SJens Wiklander         if (verbose != 0) {
25613d3b0591SJens Wiklander             mbedtls_printf("failed\n");
2562*32b31808SJens Wiklander         }
25633d3b0591SJens Wiklander 
25643d3b0591SJens Wiklander         ret = 1;
25653d3b0591SJens Wiklander         goto cleanup;
2566817466cbSJens Wiklander     }
2567817466cbSJens Wiklander 
2568*32b31808SJens Wiklander     if (verbose != 0) {
2569817466cbSJens Wiklander         mbedtls_printf("passed\n");
2570*32b31808SJens Wiklander     }
2571817466cbSJens Wiklander #endif /* MBEDTLS_SHA1_C */
2572817466cbSJens Wiklander 
2573*32b31808SJens Wiklander     if (verbose != 0) {
2574817466cbSJens Wiklander         mbedtls_printf("\n");
2575*32b31808SJens Wiklander     }
2576817466cbSJens Wiklander 
2577817466cbSJens Wiklander cleanup:
25783d3b0591SJens Wiklander     mbedtls_mpi_free(&K);
2579817466cbSJens Wiklander     mbedtls_rsa_free(&rsa);
2580817466cbSJens Wiklander #else /* MBEDTLS_PKCS1_V15 */
2581817466cbSJens Wiklander     ((void) verbose);
2582817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */
2583*32b31808SJens Wiklander     return ret;
2584817466cbSJens Wiklander }
2585817466cbSJens Wiklander 
2586817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
2587817466cbSJens Wiklander 
2588817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */
2589