1*817466cbSJens Wiklander /* 2*817466cbSJens Wiklander * The RSA public-key cryptosystem 3*817466cbSJens Wiklander * 4*817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5*817466cbSJens Wiklander * SPDX-License-Identifier: Apache-2.0 6*817466cbSJens Wiklander * 7*817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8*817466cbSJens Wiklander * not use this file except in compliance with the License. 9*817466cbSJens Wiklander * You may obtain a copy of the License at 10*817466cbSJens Wiklander * 11*817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12*817466cbSJens Wiklander * 13*817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14*817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15*817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16*817466cbSJens Wiklander * See the License for the specific language governing permissions and 17*817466cbSJens Wiklander * limitations under the License. 18*817466cbSJens Wiklander * 19*817466cbSJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 20*817466cbSJens Wiklander */ 21*817466cbSJens Wiklander /* 22*817466cbSJens Wiklander * The following sources were referenced in the design of this implementation 23*817466cbSJens Wiklander * of the RSA algorithm: 24*817466cbSJens Wiklander * 25*817466cbSJens Wiklander * [1] A method for obtaining digital signatures and public-key cryptosystems 26*817466cbSJens Wiklander * R Rivest, A Shamir, and L Adleman 27*817466cbSJens Wiklander * http://people.csail.mit.edu/rivest/pubs.html#RSA78 28*817466cbSJens Wiklander * 29*817466cbSJens Wiklander * [2] Handbook of Applied Cryptography - 1997, Chapter 8 30*817466cbSJens Wiklander * Menezes, van Oorschot and Vanstone 31*817466cbSJens Wiklander * 32*817466cbSJens Wiklander * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks 33*817466cbSJens Wiklander * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and 34*817466cbSJens Wiklander * Stefan Mangard 35*817466cbSJens Wiklander * https://arxiv.org/abs/1702.08719v2 36*817466cbSJens Wiklander * 37*817466cbSJens Wiklander */ 38*817466cbSJens Wiklander 39*817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 40*817466cbSJens Wiklander #include "mbedtls/config.h" 41*817466cbSJens Wiklander #else 42*817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 43*817466cbSJens Wiklander #endif 44*817466cbSJens Wiklander 45*817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 46*817466cbSJens Wiklander 47*817466cbSJens Wiklander #include "mbedtls/rsa.h" 48*817466cbSJens Wiklander #include "mbedtls/oid.h" 49*817466cbSJens Wiklander 50*817466cbSJens Wiklander #include <string.h> 51*817466cbSJens Wiklander 52*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 53*817466cbSJens Wiklander #include "mbedtls/md.h" 54*817466cbSJens Wiklander #endif 55*817466cbSJens Wiklander 56*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) 57*817466cbSJens Wiklander #include <stdlib.h> 58*817466cbSJens Wiklander #endif 59*817466cbSJens Wiklander 60*817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 61*817466cbSJens Wiklander #include "mbedtls/platform.h" 62*817466cbSJens Wiklander #else 63*817466cbSJens Wiklander #include <stdio.h> 64*817466cbSJens Wiklander #define mbedtls_printf printf 65*817466cbSJens Wiklander #define mbedtls_calloc calloc 66*817466cbSJens Wiklander #define mbedtls_free free 67*817466cbSJens Wiklander #endif 68*817466cbSJens Wiklander 69*817466cbSJens Wiklander /* Implementation that should never be optimized out by the compiler */ 70*817466cbSJens Wiklander static void mbedtls_zeroize( void *v, size_t n ) { 71*817466cbSJens Wiklander volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; 72*817466cbSJens Wiklander } 73*817466cbSJens Wiklander 74*817466cbSJens Wiklander /* 75*817466cbSJens Wiklander * Initialize an RSA context 76*817466cbSJens Wiklander */ 77*817466cbSJens Wiklander void mbedtls_rsa_init( mbedtls_rsa_context *ctx, 78*817466cbSJens Wiklander int padding, 79*817466cbSJens Wiklander int hash_id ) 80*817466cbSJens Wiklander { 81*817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); 82*817466cbSJens Wiklander 83*817466cbSJens Wiklander mbedtls_rsa_set_padding( ctx, padding, hash_id ); 84*817466cbSJens Wiklander 85*817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 86*817466cbSJens Wiklander mbedtls_mutex_init( &ctx->mutex ); 87*817466cbSJens Wiklander #endif 88*817466cbSJens Wiklander } 89*817466cbSJens Wiklander 90*817466cbSJens Wiklander /* 91*817466cbSJens Wiklander * Set padding for an existing RSA context 92*817466cbSJens Wiklander */ 93*817466cbSJens Wiklander void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) 94*817466cbSJens Wiklander { 95*817466cbSJens Wiklander ctx->padding = padding; 96*817466cbSJens Wiklander ctx->hash_id = hash_id; 97*817466cbSJens Wiklander } 98*817466cbSJens Wiklander 99*817466cbSJens Wiklander #if defined(MBEDTLS_GENPRIME) 100*817466cbSJens Wiklander 101*817466cbSJens Wiklander /* 102*817466cbSJens Wiklander * Generate an RSA keypair 103*817466cbSJens Wiklander */ 104*817466cbSJens Wiklander int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, 105*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 106*817466cbSJens Wiklander void *p_rng, 107*817466cbSJens Wiklander unsigned int nbits, int exponent ) 108*817466cbSJens Wiklander { 109*817466cbSJens Wiklander int ret; 110*817466cbSJens Wiklander mbedtls_mpi P1, Q1, H, G; 111*817466cbSJens Wiklander 112*817466cbSJens Wiklander if( f_rng == NULL || nbits < 128 || exponent < 3 ) 113*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 114*817466cbSJens Wiklander 115*817466cbSJens Wiklander if( nbits % 2 ) 116*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 117*817466cbSJens Wiklander 118*817466cbSJens Wiklander mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); 119*817466cbSJens Wiklander mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); 120*817466cbSJens Wiklander 121*817466cbSJens Wiklander /* 122*817466cbSJens Wiklander * find primes P and Q with Q < P so that: 123*817466cbSJens Wiklander * GCD( E, (P-1)*(Q-1) ) == 1 124*817466cbSJens Wiklander */ 125*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); 126*817466cbSJens Wiklander 127*817466cbSJens Wiklander do 128*817466cbSJens Wiklander { 129*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, 130*817466cbSJens Wiklander f_rng, p_rng ) ); 131*817466cbSJens Wiklander 132*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, 133*817466cbSJens Wiklander f_rng, p_rng ) ); 134*817466cbSJens Wiklander 135*817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) 136*817466cbSJens Wiklander continue; 137*817466cbSJens Wiklander 138*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); 139*817466cbSJens Wiklander if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) 140*817466cbSJens Wiklander continue; 141*817466cbSJens Wiklander 142*817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) 143*817466cbSJens Wiklander mbedtls_mpi_swap( &ctx->P, &ctx->Q ); 144*817466cbSJens Wiklander 145*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); 146*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); 147*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); 148*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); 149*817466cbSJens Wiklander } 150*817466cbSJens Wiklander while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); 151*817466cbSJens Wiklander 152*817466cbSJens Wiklander /* 153*817466cbSJens Wiklander * D = E^-1 mod ((P-1)*(Q-1)) 154*817466cbSJens Wiklander * DP = D mod (P - 1) 155*817466cbSJens Wiklander * DQ = D mod (Q - 1) 156*817466cbSJens Wiklander * QP = Q^-1 mod P 157*817466cbSJens Wiklander */ 158*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); 159*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); 160*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); 161*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); 162*817466cbSJens Wiklander 163*817466cbSJens Wiklander ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; 164*817466cbSJens Wiklander 165*817466cbSJens Wiklander cleanup: 166*817466cbSJens Wiklander 167*817466cbSJens Wiklander mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); 168*817466cbSJens Wiklander 169*817466cbSJens Wiklander if( ret != 0 ) 170*817466cbSJens Wiklander { 171*817466cbSJens Wiklander mbedtls_rsa_free( ctx ); 172*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); 173*817466cbSJens Wiklander } 174*817466cbSJens Wiklander 175*817466cbSJens Wiklander return( 0 ); 176*817466cbSJens Wiklander } 177*817466cbSJens Wiklander 178*817466cbSJens Wiklander #endif /* MBEDTLS_GENPRIME */ 179*817466cbSJens Wiklander 180*817466cbSJens Wiklander /* 181*817466cbSJens Wiklander * Check a public RSA key 182*817466cbSJens Wiklander */ 183*817466cbSJens Wiklander int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) 184*817466cbSJens Wiklander { 185*817466cbSJens Wiklander if( !ctx->N.p || !ctx->E.p ) 186*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 187*817466cbSJens Wiklander 188*817466cbSJens Wiklander if( ( ctx->N.p[0] & 1 ) == 0 || 189*817466cbSJens Wiklander ( ctx->E.p[0] & 1 ) == 0 ) 190*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 191*817466cbSJens Wiklander 192*817466cbSJens Wiklander if( mbedtls_mpi_bitlen( &ctx->N ) < 128 || 193*817466cbSJens Wiklander mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS ) 194*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 195*817466cbSJens Wiklander 196*817466cbSJens Wiklander if( mbedtls_mpi_bitlen( &ctx->E ) < 2 || 197*817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) 198*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 199*817466cbSJens Wiklander 200*817466cbSJens Wiklander return( 0 ); 201*817466cbSJens Wiklander } 202*817466cbSJens Wiklander 203*817466cbSJens Wiklander /* 204*817466cbSJens Wiklander * Check a private RSA key 205*817466cbSJens Wiklander */ 206*817466cbSJens Wiklander int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) 207*817466cbSJens Wiklander { 208*817466cbSJens Wiklander int ret; 209*817466cbSJens Wiklander mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; 210*817466cbSJens Wiklander 211*817466cbSJens Wiklander if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 ) 212*817466cbSJens Wiklander return( ret ); 213*817466cbSJens Wiklander 214*817466cbSJens Wiklander if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) 215*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 216*817466cbSJens Wiklander 217*817466cbSJens Wiklander mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); 218*817466cbSJens Wiklander mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); 219*817466cbSJens Wiklander mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ ); 220*817466cbSJens Wiklander mbedtls_mpi_init( &QP ); 221*817466cbSJens Wiklander 222*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); 223*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); 224*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); 225*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); 226*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); 227*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); 228*817466cbSJens Wiklander 229*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) ); 230*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) ); 231*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) ); 232*817466cbSJens Wiklander 233*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); 234*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); 235*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); 236*817466cbSJens Wiklander /* 237*817466cbSJens Wiklander * Check for a valid PKCS1v2 private key 238*817466cbSJens Wiklander */ 239*817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || 240*817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || 241*817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || 242*817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || 243*817466cbSJens Wiklander mbedtls_mpi_cmp_int( &L2, 0 ) != 0 || 244*817466cbSJens Wiklander mbedtls_mpi_cmp_int( &I, 1 ) != 0 || 245*817466cbSJens Wiklander mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) 246*817466cbSJens Wiklander { 247*817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 248*817466cbSJens Wiklander } 249*817466cbSJens Wiklander 250*817466cbSJens Wiklander cleanup: 251*817466cbSJens Wiklander mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); 252*817466cbSJens Wiklander mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); 253*817466cbSJens Wiklander mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); 254*817466cbSJens Wiklander mbedtls_mpi_free( &QP ); 255*817466cbSJens Wiklander 256*817466cbSJens Wiklander if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) 257*817466cbSJens Wiklander return( ret ); 258*817466cbSJens Wiklander 259*817466cbSJens Wiklander if( ret != 0 ) 260*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret ); 261*817466cbSJens Wiklander 262*817466cbSJens Wiklander return( 0 ); 263*817466cbSJens Wiklander } 264*817466cbSJens Wiklander 265*817466cbSJens Wiklander /* 266*817466cbSJens Wiklander * Check if contexts holding a public and private key match 267*817466cbSJens Wiklander */ 268*817466cbSJens Wiklander int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ) 269*817466cbSJens Wiklander { 270*817466cbSJens Wiklander if( mbedtls_rsa_check_pubkey( pub ) != 0 || 271*817466cbSJens Wiklander mbedtls_rsa_check_privkey( prv ) != 0 ) 272*817466cbSJens Wiklander { 273*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 274*817466cbSJens Wiklander } 275*817466cbSJens Wiklander 276*817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || 277*817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) 278*817466cbSJens Wiklander { 279*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 280*817466cbSJens Wiklander } 281*817466cbSJens Wiklander 282*817466cbSJens Wiklander return( 0 ); 283*817466cbSJens Wiklander } 284*817466cbSJens Wiklander 285*817466cbSJens Wiklander /* 286*817466cbSJens Wiklander * Do an RSA public key operation 287*817466cbSJens Wiklander */ 288*817466cbSJens Wiklander int mbedtls_rsa_public( mbedtls_rsa_context *ctx, 289*817466cbSJens Wiklander const unsigned char *input, 290*817466cbSJens Wiklander unsigned char *output ) 291*817466cbSJens Wiklander { 292*817466cbSJens Wiklander int ret; 293*817466cbSJens Wiklander size_t olen; 294*817466cbSJens Wiklander mbedtls_mpi T; 295*817466cbSJens Wiklander 296*817466cbSJens Wiklander mbedtls_mpi_init( &T ); 297*817466cbSJens Wiklander 298*817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 299*817466cbSJens Wiklander if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 300*817466cbSJens Wiklander return( ret ); 301*817466cbSJens Wiklander #endif 302*817466cbSJens Wiklander 303*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); 304*817466cbSJens Wiklander 305*817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) 306*817466cbSJens Wiklander { 307*817466cbSJens Wiklander ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 308*817466cbSJens Wiklander goto cleanup; 309*817466cbSJens Wiklander } 310*817466cbSJens Wiklander 311*817466cbSJens Wiklander olen = ctx->len; 312*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); 313*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); 314*817466cbSJens Wiklander 315*817466cbSJens Wiklander cleanup: 316*817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 317*817466cbSJens Wiklander if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 318*817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 319*817466cbSJens Wiklander #endif 320*817466cbSJens Wiklander 321*817466cbSJens Wiklander mbedtls_mpi_free( &T ); 322*817466cbSJens Wiklander 323*817466cbSJens Wiklander if( ret != 0 ) 324*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); 325*817466cbSJens Wiklander 326*817466cbSJens Wiklander return( 0 ); 327*817466cbSJens Wiklander } 328*817466cbSJens Wiklander 329*817466cbSJens Wiklander /* 330*817466cbSJens Wiklander * Generate or update blinding values, see section 10 of: 331*817466cbSJens Wiklander * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, 332*817466cbSJens Wiklander * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer 333*817466cbSJens Wiklander * Berlin Heidelberg, 1996. p. 104-113. 334*817466cbSJens Wiklander */ 335*817466cbSJens Wiklander static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, 336*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) 337*817466cbSJens Wiklander { 338*817466cbSJens Wiklander int ret, count = 0; 339*817466cbSJens Wiklander 340*817466cbSJens Wiklander if( ctx->Vf.p != NULL ) 341*817466cbSJens Wiklander { 342*817466cbSJens Wiklander /* We already have blinding values, just update them by squaring */ 343*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); 344*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); 345*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); 346*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); 347*817466cbSJens Wiklander 348*817466cbSJens Wiklander goto cleanup; 349*817466cbSJens Wiklander } 350*817466cbSJens Wiklander 351*817466cbSJens Wiklander /* Unblinding value: Vf = random number, invertible mod N */ 352*817466cbSJens Wiklander do { 353*817466cbSJens Wiklander if( count++ > 10 ) 354*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_RNG_FAILED ); 355*817466cbSJens Wiklander 356*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); 357*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); 358*817466cbSJens Wiklander } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); 359*817466cbSJens Wiklander 360*817466cbSJens Wiklander /* Blinding value: Vi = Vf^(-e) mod N */ 361*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); 362*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); 363*817466cbSJens Wiklander 364*817466cbSJens Wiklander 365*817466cbSJens Wiklander cleanup: 366*817466cbSJens Wiklander return( ret ); 367*817466cbSJens Wiklander } 368*817466cbSJens Wiklander 369*817466cbSJens Wiklander /* 370*817466cbSJens Wiklander * Exponent blinding supposed to prevent side-channel attacks using multiple 371*817466cbSJens Wiklander * traces of measurements to recover the RSA key. The more collisions are there, 372*817466cbSJens Wiklander * the more bits of the key can be recovered. See [3]. 373*817466cbSJens Wiklander * 374*817466cbSJens Wiklander * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) 375*817466cbSJens Wiklander * observations on avarage. 376*817466cbSJens Wiklander * 377*817466cbSJens Wiklander * For example with 28 byte blinding to achieve 2 collisions the adversary has 378*817466cbSJens Wiklander * to make 2^112 observations on avarage. 379*817466cbSJens Wiklander * 380*817466cbSJens Wiklander * (With the currently (as of 2017 April) known best algorithms breaking 2048 381*817466cbSJens Wiklander * bit RSA requires approximately as much time as trying out 2^112 random keys. 382*817466cbSJens Wiklander * Thus in this sense with 28 byte blinding the security is not reduced by 383*817466cbSJens Wiklander * side-channel attacks like the one in [3]) 384*817466cbSJens Wiklander * 385*817466cbSJens Wiklander * This countermeasure does not help if the key recovery is possible with a 386*817466cbSJens Wiklander * single trace. 387*817466cbSJens Wiklander */ 388*817466cbSJens Wiklander #define RSA_EXPONENT_BLINDING 28 389*817466cbSJens Wiklander 390*817466cbSJens Wiklander /* 391*817466cbSJens Wiklander * Do an RSA private key operation 392*817466cbSJens Wiklander */ 393*817466cbSJens Wiklander int mbedtls_rsa_private( mbedtls_rsa_context *ctx, 394*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 395*817466cbSJens Wiklander void *p_rng, 396*817466cbSJens Wiklander const unsigned char *input, 397*817466cbSJens Wiklander unsigned char *output ) 398*817466cbSJens Wiklander { 399*817466cbSJens Wiklander int ret; 400*817466cbSJens Wiklander size_t olen; 401*817466cbSJens Wiklander mbedtls_mpi T, T1, T2; 402*817466cbSJens Wiklander mbedtls_mpi P1, Q1, R; 403*817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 404*817466cbSJens Wiklander mbedtls_mpi D_blind; 405*817466cbSJens Wiklander mbedtls_mpi *D = &ctx->D; 406*817466cbSJens Wiklander #else 407*817466cbSJens Wiklander mbedtls_mpi DP_blind, DQ_blind; 408*817466cbSJens Wiklander mbedtls_mpi *DP = &ctx->DP; 409*817466cbSJens Wiklander mbedtls_mpi *DQ = &ctx->DQ; 410*817466cbSJens Wiklander #endif 411*817466cbSJens Wiklander 412*817466cbSJens Wiklander /* Make sure we have private key info, prevent possible misuse */ 413*817466cbSJens Wiklander if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) 414*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 415*817466cbSJens Wiklander 416*817466cbSJens Wiklander mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); 417*817466cbSJens Wiklander mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R ); 418*817466cbSJens Wiklander 419*817466cbSJens Wiklander 420*817466cbSJens Wiklander if( f_rng != NULL ) 421*817466cbSJens Wiklander { 422*817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 423*817466cbSJens Wiklander mbedtls_mpi_init( &D_blind ); 424*817466cbSJens Wiklander #else 425*817466cbSJens Wiklander mbedtls_mpi_init( &DP_blind ); 426*817466cbSJens Wiklander mbedtls_mpi_init( &DQ_blind ); 427*817466cbSJens Wiklander #endif 428*817466cbSJens Wiklander } 429*817466cbSJens Wiklander 430*817466cbSJens Wiklander 431*817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 432*817466cbSJens Wiklander if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 433*817466cbSJens Wiklander return( ret ); 434*817466cbSJens Wiklander #endif 435*817466cbSJens Wiklander 436*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); 437*817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) 438*817466cbSJens Wiklander { 439*817466cbSJens Wiklander ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 440*817466cbSJens Wiklander goto cleanup; 441*817466cbSJens Wiklander } 442*817466cbSJens Wiklander 443*817466cbSJens Wiklander if( f_rng != NULL ) 444*817466cbSJens Wiklander { 445*817466cbSJens Wiklander /* 446*817466cbSJens Wiklander * Blinding 447*817466cbSJens Wiklander * T = T * Vi mod N 448*817466cbSJens Wiklander */ 449*817466cbSJens Wiklander MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); 450*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); 451*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); 452*817466cbSJens Wiklander 453*817466cbSJens Wiklander /* 454*817466cbSJens Wiklander * Exponent blinding 455*817466cbSJens Wiklander */ 456*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); 457*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); 458*817466cbSJens Wiklander 459*817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 460*817466cbSJens Wiklander /* 461*817466cbSJens Wiklander * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D 462*817466cbSJens Wiklander */ 463*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, 464*817466cbSJens Wiklander f_rng, p_rng ) ); 465*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); 466*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); 467*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); 468*817466cbSJens Wiklander 469*817466cbSJens Wiklander D = &D_blind; 470*817466cbSJens Wiklander #else 471*817466cbSJens Wiklander /* 472*817466cbSJens Wiklander * DP_blind = ( P - 1 ) * R + DP 473*817466cbSJens Wiklander */ 474*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, 475*817466cbSJens Wiklander f_rng, p_rng ) ); 476*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); 477*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, 478*817466cbSJens Wiklander &ctx->DP ) ); 479*817466cbSJens Wiklander 480*817466cbSJens Wiklander DP = &DP_blind; 481*817466cbSJens Wiklander 482*817466cbSJens Wiklander /* 483*817466cbSJens Wiklander * DQ_blind = ( Q - 1 ) * R + DQ 484*817466cbSJens Wiklander */ 485*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, 486*817466cbSJens Wiklander f_rng, p_rng ) ); 487*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); 488*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, 489*817466cbSJens Wiklander &ctx->DQ ) ); 490*817466cbSJens Wiklander 491*817466cbSJens Wiklander DQ = &DQ_blind; 492*817466cbSJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */ 493*817466cbSJens Wiklander } 494*817466cbSJens Wiklander 495*817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 496*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); 497*817466cbSJens Wiklander #else 498*817466cbSJens Wiklander /* 499*817466cbSJens Wiklander * Faster decryption using the CRT 500*817466cbSJens Wiklander * 501*817466cbSJens Wiklander * T1 = input ^ dP mod P 502*817466cbSJens Wiklander * T2 = input ^ dQ mod Q 503*817466cbSJens Wiklander */ 504*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, DP, &ctx->P, &ctx->RP ) ); 505*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, DQ, &ctx->Q, &ctx->RQ ) ); 506*817466cbSJens Wiklander 507*817466cbSJens Wiklander /* 508*817466cbSJens Wiklander * T = (T1 - T2) * (Q^-1 mod P) mod P 509*817466cbSJens Wiklander */ 510*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); 511*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); 512*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); 513*817466cbSJens Wiklander 514*817466cbSJens Wiklander /* 515*817466cbSJens Wiklander * T = T2 + T * Q 516*817466cbSJens Wiklander */ 517*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); 518*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); 519*817466cbSJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */ 520*817466cbSJens Wiklander 521*817466cbSJens Wiklander if( f_rng != NULL ) 522*817466cbSJens Wiklander { 523*817466cbSJens Wiklander /* 524*817466cbSJens Wiklander * Unblind 525*817466cbSJens Wiklander * T = T * Vf mod N 526*817466cbSJens Wiklander */ 527*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); 528*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); 529*817466cbSJens Wiklander } 530*817466cbSJens Wiklander 531*817466cbSJens Wiklander olen = ctx->len; 532*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); 533*817466cbSJens Wiklander 534*817466cbSJens Wiklander cleanup: 535*817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 536*817466cbSJens Wiklander if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 537*817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 538*817466cbSJens Wiklander #endif 539*817466cbSJens Wiklander 540*817466cbSJens Wiklander mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); 541*817466cbSJens Wiklander mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &R ); 542*817466cbSJens Wiklander 543*817466cbSJens Wiklander if( f_rng != NULL ) 544*817466cbSJens Wiklander { 545*817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 546*817466cbSJens Wiklander mbedtls_mpi_free( &D_blind ); 547*817466cbSJens Wiklander #else 548*817466cbSJens Wiklander mbedtls_mpi_free( &DP_blind ); 549*817466cbSJens Wiklander mbedtls_mpi_free( &DQ_blind ); 550*817466cbSJens Wiklander #endif 551*817466cbSJens Wiklander } 552*817466cbSJens Wiklander 553*817466cbSJens Wiklander if( ret != 0 ) 554*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); 555*817466cbSJens Wiklander 556*817466cbSJens Wiklander return( 0 ); 557*817466cbSJens Wiklander } 558*817466cbSJens Wiklander 559*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 560*817466cbSJens Wiklander /** 561*817466cbSJens Wiklander * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. 562*817466cbSJens Wiklander * 563*817466cbSJens Wiklander * \param dst buffer to mask 564*817466cbSJens Wiklander * \param dlen length of destination buffer 565*817466cbSJens Wiklander * \param src source of the mask generation 566*817466cbSJens Wiklander * \param slen length of the source buffer 567*817466cbSJens Wiklander * \param md_ctx message digest context to use 568*817466cbSJens Wiklander */ 569*817466cbSJens Wiklander static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, 570*817466cbSJens Wiklander size_t slen, mbedtls_md_context_t *md_ctx ) 571*817466cbSJens Wiklander { 572*817466cbSJens Wiklander unsigned char mask[MBEDTLS_MD_MAX_SIZE]; 573*817466cbSJens Wiklander unsigned char counter[4]; 574*817466cbSJens Wiklander unsigned char *p; 575*817466cbSJens Wiklander unsigned int hlen; 576*817466cbSJens Wiklander size_t i, use_len; 577*817466cbSJens Wiklander 578*817466cbSJens Wiklander memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); 579*817466cbSJens Wiklander memset( counter, 0, 4 ); 580*817466cbSJens Wiklander 581*817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_ctx->md_info ); 582*817466cbSJens Wiklander 583*817466cbSJens Wiklander /* Generate and apply dbMask */ 584*817466cbSJens Wiklander p = dst; 585*817466cbSJens Wiklander 586*817466cbSJens Wiklander while( dlen > 0 ) 587*817466cbSJens Wiklander { 588*817466cbSJens Wiklander use_len = hlen; 589*817466cbSJens Wiklander if( dlen < hlen ) 590*817466cbSJens Wiklander use_len = dlen; 591*817466cbSJens Wiklander 592*817466cbSJens Wiklander mbedtls_md_starts( md_ctx ); 593*817466cbSJens Wiklander mbedtls_md_update( md_ctx, src, slen ); 594*817466cbSJens Wiklander mbedtls_md_update( md_ctx, counter, 4 ); 595*817466cbSJens Wiklander mbedtls_md_finish( md_ctx, mask ); 596*817466cbSJens Wiklander 597*817466cbSJens Wiklander for( i = 0; i < use_len; ++i ) 598*817466cbSJens Wiklander *p++ ^= mask[i]; 599*817466cbSJens Wiklander 600*817466cbSJens Wiklander counter[3]++; 601*817466cbSJens Wiklander 602*817466cbSJens Wiklander dlen -= use_len; 603*817466cbSJens Wiklander } 604*817466cbSJens Wiklander 605*817466cbSJens Wiklander mbedtls_zeroize( mask, sizeof( mask ) ); 606*817466cbSJens Wiklander } 607*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 608*817466cbSJens Wiklander 609*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 610*817466cbSJens Wiklander /* 611*817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function 612*817466cbSJens Wiklander */ 613*817466cbSJens Wiklander int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, 614*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 615*817466cbSJens Wiklander void *p_rng, 616*817466cbSJens Wiklander int mode, 617*817466cbSJens Wiklander const unsigned char *label, size_t label_len, 618*817466cbSJens Wiklander size_t ilen, 619*817466cbSJens Wiklander const unsigned char *input, 620*817466cbSJens Wiklander unsigned char *output ) 621*817466cbSJens Wiklander { 622*817466cbSJens Wiklander size_t olen; 623*817466cbSJens Wiklander int ret; 624*817466cbSJens Wiklander unsigned char *p = output; 625*817466cbSJens Wiklander unsigned int hlen; 626*817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 627*817466cbSJens Wiklander mbedtls_md_context_t md_ctx; 628*817466cbSJens Wiklander 629*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) 630*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 631*817466cbSJens Wiklander 632*817466cbSJens Wiklander if( f_rng == NULL ) 633*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 634*817466cbSJens Wiklander 635*817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); 636*817466cbSJens Wiklander if( md_info == NULL ) 637*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 638*817466cbSJens Wiklander 639*817466cbSJens Wiklander olen = ctx->len; 640*817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_info ); 641*817466cbSJens Wiklander 642*817466cbSJens Wiklander /* first comparison checks for overflow */ 643*817466cbSJens Wiklander if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) 644*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 645*817466cbSJens Wiklander 646*817466cbSJens Wiklander memset( output, 0, olen ); 647*817466cbSJens Wiklander 648*817466cbSJens Wiklander *p++ = 0; 649*817466cbSJens Wiklander 650*817466cbSJens Wiklander /* Generate a random octet string seed */ 651*817466cbSJens Wiklander if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) 652*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); 653*817466cbSJens Wiklander 654*817466cbSJens Wiklander p += hlen; 655*817466cbSJens Wiklander 656*817466cbSJens Wiklander /* Construct DB */ 657*817466cbSJens Wiklander mbedtls_md( md_info, label, label_len, p ); 658*817466cbSJens Wiklander p += hlen; 659*817466cbSJens Wiklander p += olen - 2 * hlen - 2 - ilen; 660*817466cbSJens Wiklander *p++ = 1; 661*817466cbSJens Wiklander memcpy( p, input, ilen ); 662*817466cbSJens Wiklander 663*817466cbSJens Wiklander mbedtls_md_init( &md_ctx ); 664*817466cbSJens Wiklander if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 665*817466cbSJens Wiklander { 666*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 667*817466cbSJens Wiklander return( ret ); 668*817466cbSJens Wiklander } 669*817466cbSJens Wiklander 670*817466cbSJens Wiklander /* maskedDB: Apply dbMask to DB */ 671*817466cbSJens Wiklander mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, 672*817466cbSJens Wiklander &md_ctx ); 673*817466cbSJens Wiklander 674*817466cbSJens Wiklander /* maskedSeed: Apply seedMask to seed */ 675*817466cbSJens Wiklander mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, 676*817466cbSJens Wiklander &md_ctx ); 677*817466cbSJens Wiklander 678*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 679*817466cbSJens Wiklander 680*817466cbSJens Wiklander return( ( mode == MBEDTLS_RSA_PUBLIC ) 681*817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, output, output ) 682*817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); 683*817466cbSJens Wiklander } 684*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 685*817466cbSJens Wiklander 686*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 687*817466cbSJens Wiklander /* 688*817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function 689*817466cbSJens Wiklander */ 690*817466cbSJens Wiklander int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, 691*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 692*817466cbSJens Wiklander void *p_rng, 693*817466cbSJens Wiklander int mode, size_t ilen, 694*817466cbSJens Wiklander const unsigned char *input, 695*817466cbSJens Wiklander unsigned char *output ) 696*817466cbSJens Wiklander { 697*817466cbSJens Wiklander size_t nb_pad, olen; 698*817466cbSJens Wiklander int ret; 699*817466cbSJens Wiklander unsigned char *p = output; 700*817466cbSJens Wiklander 701*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 702*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 703*817466cbSJens Wiklander 704*817466cbSJens Wiklander // We don't check p_rng because it won't be dereferenced here 705*817466cbSJens Wiklander if( f_rng == NULL || input == NULL || output == NULL ) 706*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 707*817466cbSJens Wiklander 708*817466cbSJens Wiklander olen = ctx->len; 709*817466cbSJens Wiklander 710*817466cbSJens Wiklander /* first comparison checks for overflow */ 711*817466cbSJens Wiklander if( ilen + 11 < ilen || olen < ilen + 11 ) 712*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 713*817466cbSJens Wiklander 714*817466cbSJens Wiklander nb_pad = olen - 3 - ilen; 715*817466cbSJens Wiklander 716*817466cbSJens Wiklander *p++ = 0; 717*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PUBLIC ) 718*817466cbSJens Wiklander { 719*817466cbSJens Wiklander *p++ = MBEDTLS_RSA_CRYPT; 720*817466cbSJens Wiklander 721*817466cbSJens Wiklander while( nb_pad-- > 0 ) 722*817466cbSJens Wiklander { 723*817466cbSJens Wiklander int rng_dl = 100; 724*817466cbSJens Wiklander 725*817466cbSJens Wiklander do { 726*817466cbSJens Wiklander ret = f_rng( p_rng, p, 1 ); 727*817466cbSJens Wiklander } while( *p == 0 && --rng_dl && ret == 0 ); 728*817466cbSJens Wiklander 729*817466cbSJens Wiklander /* Check if RNG failed to generate data */ 730*817466cbSJens Wiklander if( rng_dl == 0 || ret != 0 ) 731*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); 732*817466cbSJens Wiklander 733*817466cbSJens Wiklander p++; 734*817466cbSJens Wiklander } 735*817466cbSJens Wiklander } 736*817466cbSJens Wiklander else 737*817466cbSJens Wiklander { 738*817466cbSJens Wiklander *p++ = MBEDTLS_RSA_SIGN; 739*817466cbSJens Wiklander 740*817466cbSJens Wiklander while( nb_pad-- > 0 ) 741*817466cbSJens Wiklander *p++ = 0xFF; 742*817466cbSJens Wiklander } 743*817466cbSJens Wiklander 744*817466cbSJens Wiklander *p++ = 0; 745*817466cbSJens Wiklander memcpy( p, input, ilen ); 746*817466cbSJens Wiklander 747*817466cbSJens Wiklander return( ( mode == MBEDTLS_RSA_PUBLIC ) 748*817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, output, output ) 749*817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); 750*817466cbSJens Wiklander } 751*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 752*817466cbSJens Wiklander 753*817466cbSJens Wiklander /* 754*817466cbSJens Wiklander * Add the message padding, then do an RSA operation 755*817466cbSJens Wiklander */ 756*817466cbSJens Wiklander int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, 757*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 758*817466cbSJens Wiklander void *p_rng, 759*817466cbSJens Wiklander int mode, size_t ilen, 760*817466cbSJens Wiklander const unsigned char *input, 761*817466cbSJens Wiklander unsigned char *output ) 762*817466cbSJens Wiklander { 763*817466cbSJens Wiklander switch( ctx->padding ) 764*817466cbSJens Wiklander { 765*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 766*817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V15: 767*817466cbSJens Wiklander return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, 768*817466cbSJens Wiklander input, output ); 769*817466cbSJens Wiklander #endif 770*817466cbSJens Wiklander 771*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 772*817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V21: 773*817466cbSJens Wiklander return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, 774*817466cbSJens Wiklander ilen, input, output ); 775*817466cbSJens Wiklander #endif 776*817466cbSJens Wiklander 777*817466cbSJens Wiklander default: 778*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 779*817466cbSJens Wiklander } 780*817466cbSJens Wiklander } 781*817466cbSJens Wiklander 782*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 783*817466cbSJens Wiklander /* 784*817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function 785*817466cbSJens Wiklander */ 786*817466cbSJens Wiklander int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, 787*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 788*817466cbSJens Wiklander void *p_rng, 789*817466cbSJens Wiklander int mode, 790*817466cbSJens Wiklander const unsigned char *label, size_t label_len, 791*817466cbSJens Wiklander size_t *olen, 792*817466cbSJens Wiklander const unsigned char *input, 793*817466cbSJens Wiklander unsigned char *output, 794*817466cbSJens Wiklander size_t output_max_len ) 795*817466cbSJens Wiklander { 796*817466cbSJens Wiklander int ret; 797*817466cbSJens Wiklander size_t ilen, i, pad_len; 798*817466cbSJens Wiklander unsigned char *p, bad, pad_done; 799*817466cbSJens Wiklander unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 800*817466cbSJens Wiklander unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; 801*817466cbSJens Wiklander unsigned int hlen; 802*817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 803*817466cbSJens Wiklander mbedtls_md_context_t md_ctx; 804*817466cbSJens Wiklander 805*817466cbSJens Wiklander /* 806*817466cbSJens Wiklander * Parameters sanity checks 807*817466cbSJens Wiklander */ 808*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) 809*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 810*817466cbSJens Wiklander 811*817466cbSJens Wiklander ilen = ctx->len; 812*817466cbSJens Wiklander 813*817466cbSJens Wiklander if( ilen < 16 || ilen > sizeof( buf ) ) 814*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 815*817466cbSJens Wiklander 816*817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); 817*817466cbSJens Wiklander if( md_info == NULL ) 818*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 819*817466cbSJens Wiklander 820*817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_info ); 821*817466cbSJens Wiklander 822*817466cbSJens Wiklander // checking for integer underflow 823*817466cbSJens Wiklander if( 2 * hlen + 2 > ilen ) 824*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 825*817466cbSJens Wiklander 826*817466cbSJens Wiklander /* 827*817466cbSJens Wiklander * RSA operation 828*817466cbSJens Wiklander */ 829*817466cbSJens Wiklander ret = ( mode == MBEDTLS_RSA_PUBLIC ) 830*817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, input, buf ) 831*817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); 832*817466cbSJens Wiklander 833*817466cbSJens Wiklander if( ret != 0 ) 834*817466cbSJens Wiklander goto cleanup; 835*817466cbSJens Wiklander 836*817466cbSJens Wiklander /* 837*817466cbSJens Wiklander * Unmask data and generate lHash 838*817466cbSJens Wiklander */ 839*817466cbSJens Wiklander mbedtls_md_init( &md_ctx ); 840*817466cbSJens Wiklander if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 841*817466cbSJens Wiklander { 842*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 843*817466cbSJens Wiklander goto cleanup; 844*817466cbSJens Wiklander } 845*817466cbSJens Wiklander 846*817466cbSJens Wiklander 847*817466cbSJens Wiklander /* Generate lHash */ 848*817466cbSJens Wiklander mbedtls_md( md_info, label, label_len, lhash ); 849*817466cbSJens Wiklander 850*817466cbSJens Wiklander /* seed: Apply seedMask to maskedSeed */ 851*817466cbSJens Wiklander mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, 852*817466cbSJens Wiklander &md_ctx ); 853*817466cbSJens Wiklander 854*817466cbSJens Wiklander /* DB: Apply dbMask to maskedDB */ 855*817466cbSJens Wiklander mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, 856*817466cbSJens Wiklander &md_ctx ); 857*817466cbSJens Wiklander 858*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 859*817466cbSJens Wiklander 860*817466cbSJens Wiklander /* 861*817466cbSJens Wiklander * Check contents, in "constant-time" 862*817466cbSJens Wiklander */ 863*817466cbSJens Wiklander p = buf; 864*817466cbSJens Wiklander bad = 0; 865*817466cbSJens Wiklander 866*817466cbSJens Wiklander bad |= *p++; /* First byte must be 0 */ 867*817466cbSJens Wiklander 868*817466cbSJens Wiklander p += hlen; /* Skip seed */ 869*817466cbSJens Wiklander 870*817466cbSJens Wiklander /* Check lHash */ 871*817466cbSJens Wiklander for( i = 0; i < hlen; i++ ) 872*817466cbSJens Wiklander bad |= lhash[i] ^ *p++; 873*817466cbSJens Wiklander 874*817466cbSJens Wiklander /* Get zero-padding len, but always read till end of buffer 875*817466cbSJens Wiklander * (minus one, for the 01 byte) */ 876*817466cbSJens Wiklander pad_len = 0; 877*817466cbSJens Wiklander pad_done = 0; 878*817466cbSJens Wiklander for( i = 0; i < ilen - 2 * hlen - 2; i++ ) 879*817466cbSJens Wiklander { 880*817466cbSJens Wiklander pad_done |= p[i]; 881*817466cbSJens Wiklander pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; 882*817466cbSJens Wiklander } 883*817466cbSJens Wiklander 884*817466cbSJens Wiklander p += pad_len; 885*817466cbSJens Wiklander bad |= *p++ ^ 0x01; 886*817466cbSJens Wiklander 887*817466cbSJens Wiklander /* 888*817466cbSJens Wiklander * The only information "leaked" is whether the padding was correct or not 889*817466cbSJens Wiklander * (eg, no data is copied if it was not correct). This meets the 890*817466cbSJens Wiklander * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between 891*817466cbSJens Wiklander * the different error conditions. 892*817466cbSJens Wiklander */ 893*817466cbSJens Wiklander if( bad != 0 ) 894*817466cbSJens Wiklander { 895*817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_INVALID_PADDING; 896*817466cbSJens Wiklander goto cleanup; 897*817466cbSJens Wiklander } 898*817466cbSJens Wiklander 899*817466cbSJens Wiklander if( ilen - ( p - buf ) > output_max_len ) 900*817466cbSJens Wiklander { 901*817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; 902*817466cbSJens Wiklander goto cleanup; 903*817466cbSJens Wiklander } 904*817466cbSJens Wiklander 905*817466cbSJens Wiklander *olen = ilen - (p - buf); 906*817466cbSJens Wiklander memcpy( output, p, *olen ); 907*817466cbSJens Wiklander ret = 0; 908*817466cbSJens Wiklander 909*817466cbSJens Wiklander cleanup: 910*817466cbSJens Wiklander mbedtls_zeroize( buf, sizeof( buf ) ); 911*817466cbSJens Wiklander mbedtls_zeroize( lhash, sizeof( lhash ) ); 912*817466cbSJens Wiklander 913*817466cbSJens Wiklander return( ret ); 914*817466cbSJens Wiklander } 915*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 916*817466cbSJens Wiklander 917*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 918*817466cbSJens Wiklander /* 919*817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function 920*817466cbSJens Wiklander */ 921*817466cbSJens Wiklander int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, 922*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 923*817466cbSJens Wiklander void *p_rng, 924*817466cbSJens Wiklander int mode, size_t *olen, 925*817466cbSJens Wiklander const unsigned char *input, 926*817466cbSJens Wiklander unsigned char *output, 927*817466cbSJens Wiklander size_t output_max_len) 928*817466cbSJens Wiklander { 929*817466cbSJens Wiklander int ret; 930*817466cbSJens Wiklander size_t ilen, pad_count = 0, i; 931*817466cbSJens Wiklander unsigned char *p, bad, pad_done = 0; 932*817466cbSJens Wiklander unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 933*817466cbSJens Wiklander 934*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 935*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 936*817466cbSJens Wiklander 937*817466cbSJens Wiklander ilen = ctx->len; 938*817466cbSJens Wiklander 939*817466cbSJens Wiklander if( ilen < 16 || ilen > sizeof( buf ) ) 940*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 941*817466cbSJens Wiklander 942*817466cbSJens Wiklander ret = ( mode == MBEDTLS_RSA_PUBLIC ) 943*817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, input, buf ) 944*817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); 945*817466cbSJens Wiklander 946*817466cbSJens Wiklander if( ret != 0 ) 947*817466cbSJens Wiklander goto cleanup; 948*817466cbSJens Wiklander 949*817466cbSJens Wiklander p = buf; 950*817466cbSJens Wiklander bad = 0; 951*817466cbSJens Wiklander 952*817466cbSJens Wiklander /* 953*817466cbSJens Wiklander * Check and get padding len in "constant-time" 954*817466cbSJens Wiklander */ 955*817466cbSJens Wiklander bad |= *p++; /* First byte must be 0 */ 956*817466cbSJens Wiklander 957*817466cbSJens Wiklander /* This test does not depend on secret data */ 958*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE ) 959*817466cbSJens Wiklander { 960*817466cbSJens Wiklander bad |= *p++ ^ MBEDTLS_RSA_CRYPT; 961*817466cbSJens Wiklander 962*817466cbSJens Wiklander /* Get padding len, but always read till end of buffer 963*817466cbSJens Wiklander * (minus one, for the 00 byte) */ 964*817466cbSJens Wiklander for( i = 0; i < ilen - 3; i++ ) 965*817466cbSJens Wiklander { 966*817466cbSJens Wiklander pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; 967*817466cbSJens Wiklander pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; 968*817466cbSJens Wiklander } 969*817466cbSJens Wiklander 970*817466cbSJens Wiklander p += pad_count; 971*817466cbSJens Wiklander bad |= *p++; /* Must be zero */ 972*817466cbSJens Wiklander } 973*817466cbSJens Wiklander else 974*817466cbSJens Wiklander { 975*817466cbSJens Wiklander bad |= *p++ ^ MBEDTLS_RSA_SIGN; 976*817466cbSJens Wiklander 977*817466cbSJens Wiklander /* Get padding len, but always read till end of buffer 978*817466cbSJens Wiklander * (minus one, for the 00 byte) */ 979*817466cbSJens Wiklander for( i = 0; i < ilen - 3; i++ ) 980*817466cbSJens Wiklander { 981*817466cbSJens Wiklander pad_done |= ( p[i] != 0xFF ); 982*817466cbSJens Wiklander pad_count += ( pad_done == 0 ); 983*817466cbSJens Wiklander } 984*817466cbSJens Wiklander 985*817466cbSJens Wiklander p += pad_count; 986*817466cbSJens Wiklander bad |= *p++; /* Must be zero */ 987*817466cbSJens Wiklander } 988*817466cbSJens Wiklander 989*817466cbSJens Wiklander bad |= ( pad_count < 8 ); 990*817466cbSJens Wiklander 991*817466cbSJens Wiklander if( bad ) 992*817466cbSJens Wiklander { 993*817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_INVALID_PADDING; 994*817466cbSJens Wiklander goto cleanup; 995*817466cbSJens Wiklander } 996*817466cbSJens Wiklander 997*817466cbSJens Wiklander if( ilen - ( p - buf ) > output_max_len ) 998*817466cbSJens Wiklander { 999*817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; 1000*817466cbSJens Wiklander goto cleanup; 1001*817466cbSJens Wiklander } 1002*817466cbSJens Wiklander 1003*817466cbSJens Wiklander *olen = ilen - (p - buf); 1004*817466cbSJens Wiklander memcpy( output, p, *olen ); 1005*817466cbSJens Wiklander ret = 0; 1006*817466cbSJens Wiklander 1007*817466cbSJens Wiklander cleanup: 1008*817466cbSJens Wiklander mbedtls_zeroize( buf, sizeof( buf ) ); 1009*817466cbSJens Wiklander 1010*817466cbSJens Wiklander return( ret ); 1011*817466cbSJens Wiklander } 1012*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1013*817466cbSJens Wiklander 1014*817466cbSJens Wiklander /* 1015*817466cbSJens Wiklander * Do an RSA operation, then remove the message padding 1016*817466cbSJens Wiklander */ 1017*817466cbSJens Wiklander int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, 1018*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1019*817466cbSJens Wiklander void *p_rng, 1020*817466cbSJens Wiklander int mode, size_t *olen, 1021*817466cbSJens Wiklander const unsigned char *input, 1022*817466cbSJens Wiklander unsigned char *output, 1023*817466cbSJens Wiklander size_t output_max_len) 1024*817466cbSJens Wiklander { 1025*817466cbSJens Wiklander switch( ctx->padding ) 1026*817466cbSJens Wiklander { 1027*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1028*817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V15: 1029*817466cbSJens Wiklander return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, 1030*817466cbSJens Wiklander input, output, output_max_len ); 1031*817466cbSJens Wiklander #endif 1032*817466cbSJens Wiklander 1033*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1034*817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V21: 1035*817466cbSJens Wiklander return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, 1036*817466cbSJens Wiklander olen, input, output, 1037*817466cbSJens Wiklander output_max_len ); 1038*817466cbSJens Wiklander #endif 1039*817466cbSJens Wiklander 1040*817466cbSJens Wiklander default: 1041*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1042*817466cbSJens Wiklander } 1043*817466cbSJens Wiklander } 1044*817466cbSJens Wiklander 1045*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1046*817466cbSJens Wiklander /* 1047*817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function 1048*817466cbSJens Wiklander */ 1049*817466cbSJens Wiklander int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, 1050*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1051*817466cbSJens Wiklander void *p_rng, 1052*817466cbSJens Wiklander int mode, 1053*817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1054*817466cbSJens Wiklander unsigned int hashlen, 1055*817466cbSJens Wiklander const unsigned char *hash, 1056*817466cbSJens Wiklander unsigned char *sig ) 1057*817466cbSJens Wiklander { 1058*817466cbSJens Wiklander size_t olen; 1059*817466cbSJens Wiklander unsigned char *p = sig; 1060*817466cbSJens Wiklander unsigned char salt[MBEDTLS_MD_MAX_SIZE]; 1061*817466cbSJens Wiklander unsigned int slen, hlen, offset = 0; 1062*817466cbSJens Wiklander int ret; 1063*817466cbSJens Wiklander size_t msb; 1064*817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 1065*817466cbSJens Wiklander mbedtls_md_context_t md_ctx; 1066*817466cbSJens Wiklander 1067*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) 1068*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1069*817466cbSJens Wiklander 1070*817466cbSJens Wiklander if( f_rng == NULL ) 1071*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1072*817466cbSJens Wiklander 1073*817466cbSJens Wiklander olen = ctx->len; 1074*817466cbSJens Wiklander 1075*817466cbSJens Wiklander if( md_alg != MBEDTLS_MD_NONE ) 1076*817466cbSJens Wiklander { 1077*817466cbSJens Wiklander /* Gather length of hash to sign */ 1078*817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( md_alg ); 1079*817466cbSJens Wiklander if( md_info == NULL ) 1080*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1081*817466cbSJens Wiklander 1082*817466cbSJens Wiklander hashlen = mbedtls_md_get_size( md_info ); 1083*817466cbSJens Wiklander } 1084*817466cbSJens Wiklander 1085*817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); 1086*817466cbSJens Wiklander if( md_info == NULL ) 1087*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1088*817466cbSJens Wiklander 1089*817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_info ); 1090*817466cbSJens Wiklander slen = hlen; 1091*817466cbSJens Wiklander 1092*817466cbSJens Wiklander if( olen < hlen + slen + 2 ) 1093*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1094*817466cbSJens Wiklander 1095*817466cbSJens Wiklander memset( sig, 0, olen ); 1096*817466cbSJens Wiklander 1097*817466cbSJens Wiklander /* Generate salt of length slen */ 1098*817466cbSJens Wiklander if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) 1099*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); 1100*817466cbSJens Wiklander 1101*817466cbSJens Wiklander /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ 1102*817466cbSJens Wiklander msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; 1103*817466cbSJens Wiklander p += olen - hlen * 2 - 2; 1104*817466cbSJens Wiklander *p++ = 0x01; 1105*817466cbSJens Wiklander memcpy( p, salt, slen ); 1106*817466cbSJens Wiklander p += slen; 1107*817466cbSJens Wiklander 1108*817466cbSJens Wiklander mbedtls_md_init( &md_ctx ); 1109*817466cbSJens Wiklander if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 1110*817466cbSJens Wiklander { 1111*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1112*817466cbSJens Wiklander /* No need to zeroize salt: we didn't use it. */ 1113*817466cbSJens Wiklander return( ret ); 1114*817466cbSJens Wiklander } 1115*817466cbSJens Wiklander 1116*817466cbSJens Wiklander /* Generate H = Hash( M' ) */ 1117*817466cbSJens Wiklander mbedtls_md_starts( &md_ctx ); 1118*817466cbSJens Wiklander mbedtls_md_update( &md_ctx, p, 8 ); 1119*817466cbSJens Wiklander mbedtls_md_update( &md_ctx, hash, hashlen ); 1120*817466cbSJens Wiklander mbedtls_md_update( &md_ctx, salt, slen ); 1121*817466cbSJens Wiklander mbedtls_md_finish( &md_ctx, p ); 1122*817466cbSJens Wiklander mbedtls_zeroize( salt, sizeof( salt ) ); 1123*817466cbSJens Wiklander 1124*817466cbSJens Wiklander /* Compensate for boundary condition when applying mask */ 1125*817466cbSJens Wiklander if( msb % 8 == 0 ) 1126*817466cbSJens Wiklander offset = 1; 1127*817466cbSJens Wiklander 1128*817466cbSJens Wiklander /* maskedDB: Apply dbMask to DB */ 1129*817466cbSJens Wiklander mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); 1130*817466cbSJens Wiklander 1131*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1132*817466cbSJens Wiklander 1133*817466cbSJens Wiklander msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; 1134*817466cbSJens Wiklander sig[0] &= 0xFF >> ( olen * 8 - msb ); 1135*817466cbSJens Wiklander 1136*817466cbSJens Wiklander p += hlen; 1137*817466cbSJens Wiklander *p++ = 0xBC; 1138*817466cbSJens Wiklander 1139*817466cbSJens Wiklander return( ( mode == MBEDTLS_RSA_PUBLIC ) 1140*817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, sig, sig ) 1141*817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); 1142*817466cbSJens Wiklander } 1143*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 1144*817466cbSJens Wiklander 1145*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1146*817466cbSJens Wiklander /* 1147*817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function 1148*817466cbSJens Wiklander */ 1149*817466cbSJens Wiklander /* 1150*817466cbSJens Wiklander * Do an RSA operation to sign the message digest 1151*817466cbSJens Wiklander */ 1152*817466cbSJens Wiklander int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, 1153*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1154*817466cbSJens Wiklander void *p_rng, 1155*817466cbSJens Wiklander int mode, 1156*817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1157*817466cbSJens Wiklander unsigned int hashlen, 1158*817466cbSJens Wiklander const unsigned char *hash, 1159*817466cbSJens Wiklander unsigned char *sig ) 1160*817466cbSJens Wiklander { 1161*817466cbSJens Wiklander size_t nb_pad, olen, oid_size = 0; 1162*817466cbSJens Wiklander unsigned char *p = sig; 1163*817466cbSJens Wiklander const char *oid = NULL; 1164*817466cbSJens Wiklander unsigned char *sig_try = NULL, *verif = NULL; 1165*817466cbSJens Wiklander size_t i; 1166*817466cbSJens Wiklander unsigned char diff; 1167*817466cbSJens Wiklander volatile unsigned char diff_no_optimize; 1168*817466cbSJens Wiklander int ret; 1169*817466cbSJens Wiklander 1170*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 1171*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1172*817466cbSJens Wiklander 1173*817466cbSJens Wiklander olen = ctx->len; 1174*817466cbSJens Wiklander nb_pad = olen - 3; 1175*817466cbSJens Wiklander 1176*817466cbSJens Wiklander if( md_alg != MBEDTLS_MD_NONE ) 1177*817466cbSJens Wiklander { 1178*817466cbSJens Wiklander const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); 1179*817466cbSJens Wiklander if( md_info == NULL ) 1180*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1181*817466cbSJens Wiklander 1182*817466cbSJens Wiklander if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) 1183*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1184*817466cbSJens Wiklander 1185*817466cbSJens Wiklander nb_pad -= 10 + oid_size; 1186*817466cbSJens Wiklander 1187*817466cbSJens Wiklander hashlen = mbedtls_md_get_size( md_info ); 1188*817466cbSJens Wiklander } 1189*817466cbSJens Wiklander 1190*817466cbSJens Wiklander nb_pad -= hashlen; 1191*817466cbSJens Wiklander 1192*817466cbSJens Wiklander if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) 1193*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1194*817466cbSJens Wiklander 1195*817466cbSJens Wiklander *p++ = 0; 1196*817466cbSJens Wiklander *p++ = MBEDTLS_RSA_SIGN; 1197*817466cbSJens Wiklander memset( p, 0xFF, nb_pad ); 1198*817466cbSJens Wiklander p += nb_pad; 1199*817466cbSJens Wiklander *p++ = 0; 1200*817466cbSJens Wiklander 1201*817466cbSJens Wiklander if( md_alg == MBEDTLS_MD_NONE ) 1202*817466cbSJens Wiklander { 1203*817466cbSJens Wiklander memcpy( p, hash, hashlen ); 1204*817466cbSJens Wiklander } 1205*817466cbSJens Wiklander else 1206*817466cbSJens Wiklander { 1207*817466cbSJens Wiklander /* 1208*817466cbSJens Wiklander * DigestInfo ::= SEQUENCE { 1209*817466cbSJens Wiklander * digestAlgorithm DigestAlgorithmIdentifier, 1210*817466cbSJens Wiklander * digest Digest } 1211*817466cbSJens Wiklander * 1212*817466cbSJens Wiklander * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 1213*817466cbSJens Wiklander * 1214*817466cbSJens Wiklander * Digest ::= OCTET STRING 1215*817466cbSJens Wiklander */ 1216*817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; 1217*817466cbSJens Wiklander *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); 1218*817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; 1219*817466cbSJens Wiklander *p++ = (unsigned char) ( 0x04 + oid_size ); 1220*817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_OID; 1221*817466cbSJens Wiklander *p++ = oid_size & 0xFF; 1222*817466cbSJens Wiklander memcpy( p, oid, oid_size ); 1223*817466cbSJens Wiklander p += oid_size; 1224*817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_NULL; 1225*817466cbSJens Wiklander *p++ = 0x00; 1226*817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_OCTET_STRING; 1227*817466cbSJens Wiklander *p++ = hashlen; 1228*817466cbSJens Wiklander memcpy( p, hash, hashlen ); 1229*817466cbSJens Wiklander } 1230*817466cbSJens Wiklander 1231*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PUBLIC ) 1232*817466cbSJens Wiklander return( mbedtls_rsa_public( ctx, sig, sig ) ); 1233*817466cbSJens Wiklander 1234*817466cbSJens Wiklander /* 1235*817466cbSJens Wiklander * In order to prevent Lenstra's attack, make the signature in a 1236*817466cbSJens Wiklander * temporary buffer and check it before returning it. 1237*817466cbSJens Wiklander */ 1238*817466cbSJens Wiklander sig_try = mbedtls_calloc( 1, ctx->len ); 1239*817466cbSJens Wiklander if( sig_try == NULL ) 1240*817466cbSJens Wiklander return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 1241*817466cbSJens Wiklander 1242*817466cbSJens Wiklander verif = mbedtls_calloc( 1, ctx->len ); 1243*817466cbSJens Wiklander if( verif == NULL ) 1244*817466cbSJens Wiklander { 1245*817466cbSJens Wiklander mbedtls_free( sig_try ); 1246*817466cbSJens Wiklander return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 1247*817466cbSJens Wiklander } 1248*817466cbSJens Wiklander 1249*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); 1250*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); 1251*817466cbSJens Wiklander 1252*817466cbSJens Wiklander /* Compare in constant time just in case */ 1253*817466cbSJens Wiklander for( diff = 0, i = 0; i < ctx->len; i++ ) 1254*817466cbSJens Wiklander diff |= verif[i] ^ sig[i]; 1255*817466cbSJens Wiklander diff_no_optimize = diff; 1256*817466cbSJens Wiklander 1257*817466cbSJens Wiklander if( diff_no_optimize != 0 ) 1258*817466cbSJens Wiklander { 1259*817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; 1260*817466cbSJens Wiklander goto cleanup; 1261*817466cbSJens Wiklander } 1262*817466cbSJens Wiklander 1263*817466cbSJens Wiklander memcpy( sig, sig_try, ctx->len ); 1264*817466cbSJens Wiklander 1265*817466cbSJens Wiklander cleanup: 1266*817466cbSJens Wiklander mbedtls_free( sig_try ); 1267*817466cbSJens Wiklander mbedtls_free( verif ); 1268*817466cbSJens Wiklander 1269*817466cbSJens Wiklander return( ret ); 1270*817466cbSJens Wiklander } 1271*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1272*817466cbSJens Wiklander 1273*817466cbSJens Wiklander /* 1274*817466cbSJens Wiklander * Do an RSA operation to sign the message digest 1275*817466cbSJens Wiklander */ 1276*817466cbSJens Wiklander int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, 1277*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1278*817466cbSJens Wiklander void *p_rng, 1279*817466cbSJens Wiklander int mode, 1280*817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1281*817466cbSJens Wiklander unsigned int hashlen, 1282*817466cbSJens Wiklander const unsigned char *hash, 1283*817466cbSJens Wiklander unsigned char *sig ) 1284*817466cbSJens Wiklander { 1285*817466cbSJens Wiklander switch( ctx->padding ) 1286*817466cbSJens Wiklander { 1287*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1288*817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V15: 1289*817466cbSJens Wiklander return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, 1290*817466cbSJens Wiklander hashlen, hash, sig ); 1291*817466cbSJens Wiklander #endif 1292*817466cbSJens Wiklander 1293*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1294*817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V21: 1295*817466cbSJens Wiklander return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, 1296*817466cbSJens Wiklander hashlen, hash, sig ); 1297*817466cbSJens Wiklander #endif 1298*817466cbSJens Wiklander 1299*817466cbSJens Wiklander default: 1300*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1301*817466cbSJens Wiklander } 1302*817466cbSJens Wiklander } 1303*817466cbSJens Wiklander 1304*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1305*817466cbSJens Wiklander /* 1306*817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function 1307*817466cbSJens Wiklander */ 1308*817466cbSJens Wiklander int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, 1309*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1310*817466cbSJens Wiklander void *p_rng, 1311*817466cbSJens Wiklander int mode, 1312*817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1313*817466cbSJens Wiklander unsigned int hashlen, 1314*817466cbSJens Wiklander const unsigned char *hash, 1315*817466cbSJens Wiklander mbedtls_md_type_t mgf1_hash_id, 1316*817466cbSJens Wiklander int expected_salt_len, 1317*817466cbSJens Wiklander const unsigned char *sig ) 1318*817466cbSJens Wiklander { 1319*817466cbSJens Wiklander int ret; 1320*817466cbSJens Wiklander size_t siglen; 1321*817466cbSJens Wiklander unsigned char *p; 1322*817466cbSJens Wiklander unsigned char result[MBEDTLS_MD_MAX_SIZE]; 1323*817466cbSJens Wiklander unsigned char zeros[8]; 1324*817466cbSJens Wiklander unsigned int hlen; 1325*817466cbSJens Wiklander size_t slen, msb; 1326*817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 1327*817466cbSJens Wiklander mbedtls_md_context_t md_ctx; 1328*817466cbSJens Wiklander unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 1329*817466cbSJens Wiklander 1330*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) 1331*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1332*817466cbSJens Wiklander 1333*817466cbSJens Wiklander siglen = ctx->len; 1334*817466cbSJens Wiklander 1335*817466cbSJens Wiklander if( siglen < 16 || siglen > sizeof( buf ) ) 1336*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1337*817466cbSJens Wiklander 1338*817466cbSJens Wiklander ret = ( mode == MBEDTLS_RSA_PUBLIC ) 1339*817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, sig, buf ) 1340*817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); 1341*817466cbSJens Wiklander 1342*817466cbSJens Wiklander if( ret != 0 ) 1343*817466cbSJens Wiklander return( ret ); 1344*817466cbSJens Wiklander 1345*817466cbSJens Wiklander p = buf; 1346*817466cbSJens Wiklander 1347*817466cbSJens Wiklander if( buf[siglen - 1] != 0xBC ) 1348*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1349*817466cbSJens Wiklander 1350*817466cbSJens Wiklander if( md_alg != MBEDTLS_MD_NONE ) 1351*817466cbSJens Wiklander { 1352*817466cbSJens Wiklander /* Gather length of hash to sign */ 1353*817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( md_alg ); 1354*817466cbSJens Wiklander if( md_info == NULL ) 1355*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1356*817466cbSJens Wiklander 1357*817466cbSJens Wiklander hashlen = mbedtls_md_get_size( md_info ); 1358*817466cbSJens Wiklander } 1359*817466cbSJens Wiklander 1360*817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( mgf1_hash_id ); 1361*817466cbSJens Wiklander if( md_info == NULL ) 1362*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1363*817466cbSJens Wiklander 1364*817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_info ); 1365*817466cbSJens Wiklander slen = siglen - hlen - 1; /* Currently length of salt + padding */ 1366*817466cbSJens Wiklander 1367*817466cbSJens Wiklander memset( zeros, 0, 8 ); 1368*817466cbSJens Wiklander 1369*817466cbSJens Wiklander /* 1370*817466cbSJens Wiklander * Note: EMSA-PSS verification is over the length of N - 1 bits 1371*817466cbSJens Wiklander */ 1372*817466cbSJens Wiklander msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; 1373*817466cbSJens Wiklander 1374*817466cbSJens Wiklander /* Compensate for boundary condition when applying mask */ 1375*817466cbSJens Wiklander if( msb % 8 == 0 ) 1376*817466cbSJens Wiklander { 1377*817466cbSJens Wiklander p++; 1378*817466cbSJens Wiklander siglen -= 1; 1379*817466cbSJens Wiklander } 1380*817466cbSJens Wiklander if( buf[0] >> ( 8 - siglen * 8 + msb ) ) 1381*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1382*817466cbSJens Wiklander 1383*817466cbSJens Wiklander mbedtls_md_init( &md_ctx ); 1384*817466cbSJens Wiklander if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 1385*817466cbSJens Wiklander { 1386*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1387*817466cbSJens Wiklander return( ret ); 1388*817466cbSJens Wiklander } 1389*817466cbSJens Wiklander 1390*817466cbSJens Wiklander mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); 1391*817466cbSJens Wiklander 1392*817466cbSJens Wiklander buf[0] &= 0xFF >> ( siglen * 8 - msb ); 1393*817466cbSJens Wiklander 1394*817466cbSJens Wiklander while( p < buf + siglen && *p == 0 ) 1395*817466cbSJens Wiklander p++; 1396*817466cbSJens Wiklander 1397*817466cbSJens Wiklander if( p == buf + siglen || 1398*817466cbSJens Wiklander *p++ != 0x01 ) 1399*817466cbSJens Wiklander { 1400*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1401*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1402*817466cbSJens Wiklander } 1403*817466cbSJens Wiklander 1404*817466cbSJens Wiklander /* Actual salt len */ 1405*817466cbSJens Wiklander slen -= p - buf; 1406*817466cbSJens Wiklander 1407*817466cbSJens Wiklander if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && 1408*817466cbSJens Wiklander slen != (size_t) expected_salt_len ) 1409*817466cbSJens Wiklander { 1410*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1411*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1412*817466cbSJens Wiklander } 1413*817466cbSJens Wiklander 1414*817466cbSJens Wiklander /* 1415*817466cbSJens Wiklander * Generate H = Hash( M' ) 1416*817466cbSJens Wiklander */ 1417*817466cbSJens Wiklander mbedtls_md_starts( &md_ctx ); 1418*817466cbSJens Wiklander mbedtls_md_update( &md_ctx, zeros, 8 ); 1419*817466cbSJens Wiklander mbedtls_md_update( &md_ctx, hash, hashlen ); 1420*817466cbSJens Wiklander mbedtls_md_update( &md_ctx, p, slen ); 1421*817466cbSJens Wiklander mbedtls_md_finish( &md_ctx, result ); 1422*817466cbSJens Wiklander 1423*817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1424*817466cbSJens Wiklander 1425*817466cbSJens Wiklander if( memcmp( p + slen, result, hlen ) == 0 ) 1426*817466cbSJens Wiklander return( 0 ); 1427*817466cbSJens Wiklander else 1428*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1429*817466cbSJens Wiklander } 1430*817466cbSJens Wiklander 1431*817466cbSJens Wiklander /* 1432*817466cbSJens Wiklander * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function 1433*817466cbSJens Wiklander */ 1434*817466cbSJens Wiklander int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, 1435*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1436*817466cbSJens Wiklander void *p_rng, 1437*817466cbSJens Wiklander int mode, 1438*817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1439*817466cbSJens Wiklander unsigned int hashlen, 1440*817466cbSJens Wiklander const unsigned char *hash, 1441*817466cbSJens Wiklander const unsigned char *sig ) 1442*817466cbSJens Wiklander { 1443*817466cbSJens Wiklander mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) 1444*817466cbSJens Wiklander ? (mbedtls_md_type_t) ctx->hash_id 1445*817466cbSJens Wiklander : md_alg; 1446*817466cbSJens Wiklander 1447*817466cbSJens Wiklander return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, 1448*817466cbSJens Wiklander md_alg, hashlen, hash, 1449*817466cbSJens Wiklander mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, 1450*817466cbSJens Wiklander sig ) ); 1451*817466cbSJens Wiklander 1452*817466cbSJens Wiklander } 1453*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 1454*817466cbSJens Wiklander 1455*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1456*817466cbSJens Wiklander /* 1457*817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function 1458*817466cbSJens Wiklander */ 1459*817466cbSJens Wiklander int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, 1460*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1461*817466cbSJens Wiklander void *p_rng, 1462*817466cbSJens Wiklander int mode, 1463*817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1464*817466cbSJens Wiklander unsigned int hashlen, 1465*817466cbSJens Wiklander const unsigned char *hash, 1466*817466cbSJens Wiklander const unsigned char *sig ) 1467*817466cbSJens Wiklander { 1468*817466cbSJens Wiklander int ret; 1469*817466cbSJens Wiklander size_t len, siglen, asn1_len; 1470*817466cbSJens Wiklander unsigned char *p, *p0, *end; 1471*817466cbSJens Wiklander mbedtls_md_type_t msg_md_alg; 1472*817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 1473*817466cbSJens Wiklander mbedtls_asn1_buf oid; 1474*817466cbSJens Wiklander unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 1475*817466cbSJens Wiklander 1476*817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 1477*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1478*817466cbSJens Wiklander 1479*817466cbSJens Wiklander siglen = ctx->len; 1480*817466cbSJens Wiklander 1481*817466cbSJens Wiklander if( siglen < 16 || siglen > sizeof( buf ) ) 1482*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1483*817466cbSJens Wiklander 1484*817466cbSJens Wiklander ret = ( mode == MBEDTLS_RSA_PUBLIC ) 1485*817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, sig, buf ) 1486*817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); 1487*817466cbSJens Wiklander 1488*817466cbSJens Wiklander if( ret != 0 ) 1489*817466cbSJens Wiklander return( ret ); 1490*817466cbSJens Wiklander 1491*817466cbSJens Wiklander p = buf; 1492*817466cbSJens Wiklander 1493*817466cbSJens Wiklander if( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN ) 1494*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1495*817466cbSJens Wiklander 1496*817466cbSJens Wiklander while( *p != 0 ) 1497*817466cbSJens Wiklander { 1498*817466cbSJens Wiklander if( p >= buf + siglen - 1 || *p != 0xFF ) 1499*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1500*817466cbSJens Wiklander p++; 1501*817466cbSJens Wiklander } 1502*817466cbSJens Wiklander p++; /* skip 00 byte */ 1503*817466cbSJens Wiklander 1504*817466cbSJens Wiklander /* We've read: 00 01 PS 00 where PS must be at least 8 bytes */ 1505*817466cbSJens Wiklander if( p - buf < 11 ) 1506*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1507*817466cbSJens Wiklander 1508*817466cbSJens Wiklander len = siglen - ( p - buf ); 1509*817466cbSJens Wiklander 1510*817466cbSJens Wiklander if( len == hashlen && md_alg == MBEDTLS_MD_NONE ) 1511*817466cbSJens Wiklander { 1512*817466cbSJens Wiklander if( memcmp( p, hash, hashlen ) == 0 ) 1513*817466cbSJens Wiklander return( 0 ); 1514*817466cbSJens Wiklander else 1515*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1516*817466cbSJens Wiklander } 1517*817466cbSJens Wiklander 1518*817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( md_alg ); 1519*817466cbSJens Wiklander if( md_info == NULL ) 1520*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1521*817466cbSJens Wiklander hashlen = mbedtls_md_get_size( md_info ); 1522*817466cbSJens Wiklander 1523*817466cbSJens Wiklander end = p + len; 1524*817466cbSJens Wiklander 1525*817466cbSJens Wiklander /* 1526*817466cbSJens Wiklander * Parse the ASN.1 structure inside the PKCS#1 v1.5 structure. 1527*817466cbSJens Wiklander * Insist on 2-byte length tags, to protect against variants of 1528*817466cbSJens Wiklander * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification. 1529*817466cbSJens Wiklander */ 1530*817466cbSJens Wiklander p0 = p; 1531*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, 1532*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 1533*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1534*817466cbSJens Wiklander if( p != p0 + 2 || asn1_len + 2 != len ) 1535*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1536*817466cbSJens Wiklander 1537*817466cbSJens Wiklander p0 = p; 1538*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, 1539*817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 1540*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1541*817466cbSJens Wiklander if( p != p0 + 2 || asn1_len + 6 + hashlen != len ) 1542*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1543*817466cbSJens Wiklander 1544*817466cbSJens Wiklander p0 = p; 1545*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) 1546*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1547*817466cbSJens Wiklander if( p != p0 + 2 ) 1548*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1549*817466cbSJens Wiklander 1550*817466cbSJens Wiklander oid.p = p; 1551*817466cbSJens Wiklander p += oid.len; 1552*817466cbSJens Wiklander 1553*817466cbSJens Wiklander if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) 1554*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1555*817466cbSJens Wiklander 1556*817466cbSJens Wiklander if( md_alg != msg_md_alg ) 1557*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1558*817466cbSJens Wiklander 1559*817466cbSJens Wiklander /* 1560*817466cbSJens Wiklander * assume the algorithm parameters must be NULL 1561*817466cbSJens Wiklander */ 1562*817466cbSJens Wiklander p0 = p; 1563*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 ) 1564*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1565*817466cbSJens Wiklander if( p != p0 + 2 ) 1566*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1567*817466cbSJens Wiklander 1568*817466cbSJens Wiklander p0 = p; 1569*817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 1570*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1571*817466cbSJens Wiklander if( p != p0 + 2 || asn1_len != hashlen ) 1572*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1573*817466cbSJens Wiklander 1574*817466cbSJens Wiklander if( memcmp( p, hash, hashlen ) != 0 ) 1575*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1576*817466cbSJens Wiklander 1577*817466cbSJens Wiklander p += hashlen; 1578*817466cbSJens Wiklander 1579*817466cbSJens Wiklander if( p != end ) 1580*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1581*817466cbSJens Wiklander 1582*817466cbSJens Wiklander return( 0 ); 1583*817466cbSJens Wiklander } 1584*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1585*817466cbSJens Wiklander 1586*817466cbSJens Wiklander /* 1587*817466cbSJens Wiklander * Do an RSA operation and check the message digest 1588*817466cbSJens Wiklander */ 1589*817466cbSJens Wiklander int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, 1590*817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1591*817466cbSJens Wiklander void *p_rng, 1592*817466cbSJens Wiklander int mode, 1593*817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1594*817466cbSJens Wiklander unsigned int hashlen, 1595*817466cbSJens Wiklander const unsigned char *hash, 1596*817466cbSJens Wiklander const unsigned char *sig ) 1597*817466cbSJens Wiklander { 1598*817466cbSJens Wiklander switch( ctx->padding ) 1599*817466cbSJens Wiklander { 1600*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1601*817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V15: 1602*817466cbSJens Wiklander return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, 1603*817466cbSJens Wiklander hashlen, hash, sig ); 1604*817466cbSJens Wiklander #endif 1605*817466cbSJens Wiklander 1606*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1607*817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V21: 1608*817466cbSJens Wiklander return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, 1609*817466cbSJens Wiklander hashlen, hash, sig ); 1610*817466cbSJens Wiklander #endif 1611*817466cbSJens Wiklander 1612*817466cbSJens Wiklander default: 1613*817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1614*817466cbSJens Wiklander } 1615*817466cbSJens Wiklander } 1616*817466cbSJens Wiklander 1617*817466cbSJens Wiklander /* 1618*817466cbSJens Wiklander * Copy the components of an RSA key 1619*817466cbSJens Wiklander */ 1620*817466cbSJens Wiklander int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) 1621*817466cbSJens Wiklander { 1622*817466cbSJens Wiklander int ret; 1623*817466cbSJens Wiklander 1624*817466cbSJens Wiklander dst->ver = src->ver; 1625*817466cbSJens Wiklander dst->len = src->len; 1626*817466cbSJens Wiklander 1627*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); 1628*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); 1629*817466cbSJens Wiklander 1630*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); 1631*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); 1632*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); 1633*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); 1634*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); 1635*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); 1636*817466cbSJens Wiklander 1637*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); 1638*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); 1639*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); 1640*817466cbSJens Wiklander 1641*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); 1642*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); 1643*817466cbSJens Wiklander 1644*817466cbSJens Wiklander dst->padding = src->padding; 1645*817466cbSJens Wiklander dst->hash_id = src->hash_id; 1646*817466cbSJens Wiklander 1647*817466cbSJens Wiklander cleanup: 1648*817466cbSJens Wiklander if( ret != 0 ) 1649*817466cbSJens Wiklander mbedtls_rsa_free( dst ); 1650*817466cbSJens Wiklander 1651*817466cbSJens Wiklander return( ret ); 1652*817466cbSJens Wiklander } 1653*817466cbSJens Wiklander 1654*817466cbSJens Wiklander /* 1655*817466cbSJens Wiklander * Free the components of an RSA key 1656*817466cbSJens Wiklander */ 1657*817466cbSJens Wiklander void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) 1658*817466cbSJens Wiklander { 1659*817466cbSJens Wiklander mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); 1660*817466cbSJens Wiklander mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN ); 1661*817466cbSJens Wiklander mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); 1662*817466cbSJens Wiklander mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D ); 1663*817466cbSJens Wiklander mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); 1664*817466cbSJens Wiklander 1665*817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 1666*817466cbSJens Wiklander mbedtls_mutex_free( &ctx->mutex ); 1667*817466cbSJens Wiklander #endif 1668*817466cbSJens Wiklander } 1669*817466cbSJens Wiklander 1670*817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 1671*817466cbSJens Wiklander 1672*817466cbSJens Wiklander #include "mbedtls/sha1.h" 1673*817466cbSJens Wiklander 1674*817466cbSJens Wiklander /* 1675*817466cbSJens Wiklander * Example RSA-1024 keypair, for test purposes 1676*817466cbSJens Wiklander */ 1677*817466cbSJens Wiklander #define KEY_LEN 128 1678*817466cbSJens Wiklander 1679*817466cbSJens Wiklander #define RSA_N "9292758453063D803DD603D5E777D788" \ 1680*817466cbSJens Wiklander "8ED1D5BF35786190FA2F23EBC0848AEA" \ 1681*817466cbSJens Wiklander "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ 1682*817466cbSJens Wiklander "7130B9CED7ACDF54CFC7555AC14EEBAB" \ 1683*817466cbSJens Wiklander "93A89813FBF3C4F8066D2D800F7C38A8" \ 1684*817466cbSJens Wiklander "1AE31942917403FF4946B0A83D3D3E05" \ 1685*817466cbSJens Wiklander "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ 1686*817466cbSJens Wiklander "5E94BB77B07507233A0BC7BAC8F90F79" 1687*817466cbSJens Wiklander 1688*817466cbSJens Wiklander #define RSA_E "10001" 1689*817466cbSJens Wiklander 1690*817466cbSJens Wiklander #define RSA_D "24BF6185468786FDD303083D25E64EFC" \ 1691*817466cbSJens Wiklander "66CA472BC44D253102F8B4A9D3BFA750" \ 1692*817466cbSJens Wiklander "91386C0077937FE33FA3252D28855837" \ 1693*817466cbSJens Wiklander "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ 1694*817466cbSJens Wiklander "DF79C5CE07EE72C7F123142198164234" \ 1695*817466cbSJens Wiklander "CABB724CF78B8173B9F880FC86322407" \ 1696*817466cbSJens Wiklander "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ 1697*817466cbSJens Wiklander "071513A1E85B5DFA031F21ECAE91A34D" 1698*817466cbSJens Wiklander 1699*817466cbSJens Wiklander #define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ 1700*817466cbSJens Wiklander "2C01CAD19EA484A87EA4377637E75500" \ 1701*817466cbSJens Wiklander "FCB2005C5C7DD6EC4AC023CDA285D796" \ 1702*817466cbSJens Wiklander "C3D9E75E1EFC42488BB4F1D13AC30A57" 1703*817466cbSJens Wiklander 1704*817466cbSJens Wiklander #define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ 1705*817466cbSJens Wiklander "E211C2B9E5DB1ED0BF61D0D9899620F4" \ 1706*817466cbSJens Wiklander "910E4168387E3C30AA1E00C339A79508" \ 1707*817466cbSJens Wiklander "8452DD96A9A5EA5D9DCA68DA636032AF" 1708*817466cbSJens Wiklander 1709*817466cbSJens Wiklander #define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ 1710*817466cbSJens Wiklander "3C94D22288ACD763FD8E5600ED4A702D" \ 1711*817466cbSJens Wiklander "F84198A5F06C2E72236AE490C93F07F8" \ 1712*817466cbSJens Wiklander "3CC559CD27BC2D1CA488811730BB5725" 1713*817466cbSJens Wiklander 1714*817466cbSJens Wiklander #define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ 1715*817466cbSJens Wiklander "D8AAEA56749EA28623272E4F7D0592AF" \ 1716*817466cbSJens Wiklander "7C1F1313CAC9471B5C523BFE592F517B" \ 1717*817466cbSJens Wiklander "407A1BD76C164B93DA2D32A383E58357" 1718*817466cbSJens Wiklander 1719*817466cbSJens Wiklander #define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ 1720*817466cbSJens Wiklander "F38D18D2B2F0E2DD275AA977E2BF4411" \ 1721*817466cbSJens Wiklander "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ 1722*817466cbSJens Wiklander "A74206CEC169D74BF5A8C50D6F48EA08" 1723*817466cbSJens Wiklander 1724*817466cbSJens Wiklander #define PT_LEN 24 1725*817466cbSJens Wiklander #define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ 1726*817466cbSJens Wiklander "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" 1727*817466cbSJens Wiklander 1728*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1729*817466cbSJens Wiklander static int myrand( void *rng_state, unsigned char *output, size_t len ) 1730*817466cbSJens Wiklander { 1731*817466cbSJens Wiklander #if !defined(__OpenBSD__) 1732*817466cbSJens Wiklander size_t i; 1733*817466cbSJens Wiklander 1734*817466cbSJens Wiklander if( rng_state != NULL ) 1735*817466cbSJens Wiklander rng_state = NULL; 1736*817466cbSJens Wiklander 1737*817466cbSJens Wiklander for( i = 0; i < len; ++i ) 1738*817466cbSJens Wiklander output[i] = rand(); 1739*817466cbSJens Wiklander #else 1740*817466cbSJens Wiklander if( rng_state != NULL ) 1741*817466cbSJens Wiklander rng_state = NULL; 1742*817466cbSJens Wiklander 1743*817466cbSJens Wiklander arc4random_buf( output, len ); 1744*817466cbSJens Wiklander #endif /* !OpenBSD */ 1745*817466cbSJens Wiklander 1746*817466cbSJens Wiklander return( 0 ); 1747*817466cbSJens Wiklander } 1748*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1749*817466cbSJens Wiklander 1750*817466cbSJens Wiklander /* 1751*817466cbSJens Wiklander * Checkup routine 1752*817466cbSJens Wiklander */ 1753*817466cbSJens Wiklander int mbedtls_rsa_self_test( int verbose ) 1754*817466cbSJens Wiklander { 1755*817466cbSJens Wiklander int ret = 0; 1756*817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1757*817466cbSJens Wiklander size_t len; 1758*817466cbSJens Wiklander mbedtls_rsa_context rsa; 1759*817466cbSJens Wiklander unsigned char rsa_plaintext[PT_LEN]; 1760*817466cbSJens Wiklander unsigned char rsa_decrypted[PT_LEN]; 1761*817466cbSJens Wiklander unsigned char rsa_ciphertext[KEY_LEN]; 1762*817466cbSJens Wiklander #if defined(MBEDTLS_SHA1_C) 1763*817466cbSJens Wiklander unsigned char sha1sum[20]; 1764*817466cbSJens Wiklander #endif 1765*817466cbSJens Wiklander 1766*817466cbSJens Wiklander mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); 1767*817466cbSJens Wiklander 1768*817466cbSJens Wiklander rsa.len = KEY_LEN; 1769*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) ); 1770*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) ); 1771*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) ); 1772*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) ); 1773*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) ); 1774*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) ); 1775*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); 1776*817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) ); 1777*817466cbSJens Wiklander 1778*817466cbSJens Wiklander if( verbose != 0 ) 1779*817466cbSJens Wiklander mbedtls_printf( " RSA key validation: " ); 1780*817466cbSJens Wiklander 1781*817466cbSJens Wiklander if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || 1782*817466cbSJens Wiklander mbedtls_rsa_check_privkey( &rsa ) != 0 ) 1783*817466cbSJens Wiklander { 1784*817466cbSJens Wiklander if( verbose != 0 ) 1785*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1786*817466cbSJens Wiklander 1787*817466cbSJens Wiklander return( 1 ); 1788*817466cbSJens Wiklander } 1789*817466cbSJens Wiklander 1790*817466cbSJens Wiklander if( verbose != 0 ) 1791*817466cbSJens Wiklander mbedtls_printf( "passed\n PKCS#1 encryption : " ); 1792*817466cbSJens Wiklander 1793*817466cbSJens Wiklander memcpy( rsa_plaintext, RSA_PT, PT_LEN ); 1794*817466cbSJens Wiklander 1795*817466cbSJens Wiklander if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN, 1796*817466cbSJens Wiklander rsa_plaintext, rsa_ciphertext ) != 0 ) 1797*817466cbSJens Wiklander { 1798*817466cbSJens Wiklander if( verbose != 0 ) 1799*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1800*817466cbSJens Wiklander 1801*817466cbSJens Wiklander return( 1 ); 1802*817466cbSJens Wiklander } 1803*817466cbSJens Wiklander 1804*817466cbSJens Wiklander if( verbose != 0 ) 1805*817466cbSJens Wiklander mbedtls_printf( "passed\n PKCS#1 decryption : " ); 1806*817466cbSJens Wiklander 1807*817466cbSJens Wiklander if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len, 1808*817466cbSJens Wiklander rsa_ciphertext, rsa_decrypted, 1809*817466cbSJens Wiklander sizeof(rsa_decrypted) ) != 0 ) 1810*817466cbSJens Wiklander { 1811*817466cbSJens Wiklander if( verbose != 0 ) 1812*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1813*817466cbSJens Wiklander 1814*817466cbSJens Wiklander return( 1 ); 1815*817466cbSJens Wiklander } 1816*817466cbSJens Wiklander 1817*817466cbSJens Wiklander if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) 1818*817466cbSJens Wiklander { 1819*817466cbSJens Wiklander if( verbose != 0 ) 1820*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1821*817466cbSJens Wiklander 1822*817466cbSJens Wiklander return( 1 ); 1823*817466cbSJens Wiklander } 1824*817466cbSJens Wiklander 1825*817466cbSJens Wiklander if( verbose != 0 ) 1826*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 1827*817466cbSJens Wiklander 1828*817466cbSJens Wiklander #if defined(MBEDTLS_SHA1_C) 1829*817466cbSJens Wiklander if( verbose != 0 ) 1830*817466cbSJens Wiklander mbedtls_printf( " PKCS#1 data sign : " ); 1831*817466cbSJens Wiklander 1832*817466cbSJens Wiklander mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ); 1833*817466cbSJens Wiklander 1834*817466cbSJens Wiklander if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, 1835*817466cbSJens Wiklander sha1sum, rsa_ciphertext ) != 0 ) 1836*817466cbSJens Wiklander { 1837*817466cbSJens Wiklander if( verbose != 0 ) 1838*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1839*817466cbSJens Wiklander 1840*817466cbSJens Wiklander return( 1 ); 1841*817466cbSJens Wiklander } 1842*817466cbSJens Wiklander 1843*817466cbSJens Wiklander if( verbose != 0 ) 1844*817466cbSJens Wiklander mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); 1845*817466cbSJens Wiklander 1846*817466cbSJens Wiklander if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, 1847*817466cbSJens Wiklander sha1sum, rsa_ciphertext ) != 0 ) 1848*817466cbSJens Wiklander { 1849*817466cbSJens Wiklander if( verbose != 0 ) 1850*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1851*817466cbSJens Wiklander 1852*817466cbSJens Wiklander return( 1 ); 1853*817466cbSJens Wiklander } 1854*817466cbSJens Wiklander 1855*817466cbSJens Wiklander if( verbose != 0 ) 1856*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 1857*817466cbSJens Wiklander #endif /* MBEDTLS_SHA1_C */ 1858*817466cbSJens Wiklander 1859*817466cbSJens Wiklander if( verbose != 0 ) 1860*817466cbSJens Wiklander mbedtls_printf( "\n" ); 1861*817466cbSJens Wiklander 1862*817466cbSJens Wiklander cleanup: 1863*817466cbSJens Wiklander mbedtls_rsa_free( &rsa ); 1864*817466cbSJens Wiklander #else /* MBEDTLS_PKCS1_V15 */ 1865*817466cbSJens Wiklander ((void) verbose); 1866*817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1867*817466cbSJens Wiklander return( ret ); 1868*817466cbSJens Wiklander } 1869*817466cbSJens Wiklander 1870*817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 1871*817466cbSJens Wiklander 1872*817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 1873