xref: /optee_os/lib/libmbedtls/mbedtls/library/rsa.c (revision 817466cb476de705a8e3dabe1ef165fe27a18c2f)
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