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