blob: f4ab6b2a62fe979f3f679d42a7afa73d179a40e9 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * The RSA public-key cryptosystem
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
21/*
22 * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
23 *
24 * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
25 * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
26 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_RSA_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/rsa.h"
37#include "mbedtls/oid.h"
Paul Bakkerbb51f0c2012-08-23 07:46:58 +000038
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_PKCS1_V21)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000042#include "mbedtls/md.h"
Paul Bakkerbb51f0c2012-08-23 07:46:58 +000043#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__)
Paul Bakker5121ce52009-01-03 21:22:43 +000046#include <stdlib.h>
Rich Evans00ab4702015-02-06 13:43:58 +000047#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010051#else
Rich Evans00ab4702015-02-06 13:43:58 +000052#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#define mbedtls_printf printf
Paul Bakker7dc4c442014-02-01 22:50:26 +010054#endif
55
Paul Bakker5121ce52009-01-03 21:22:43 +000056/*
57 * Initialize an RSA context
58 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +000060 int padding,
Paul Bakker21eb2802010-08-16 11:10:02 +000061 int hash_id )
Paul Bakker5121ce52009-01-03 21:22:43 +000062{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063 memset( ctx, 0, sizeof( mbedtls_rsa_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +000064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065 mbedtls_rsa_set_padding( ctx, padding, hash_id );
Paul Bakkerc9965dc2013-09-29 14:58:17 +020066
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#if defined(MBEDTLS_THREADING_C)
68 mbedtls_mutex_init( &ctx->mutex );
Paul Bakkerc9965dc2013-09-29 14:58:17 +020069#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000070}
71
Manuel Pégourié-Gonnard844a4c02014-03-10 21:55:35 +010072/*
73 * Set padding for an existing RSA context
74 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id )
Manuel Pégourié-Gonnard844a4c02014-03-10 21:55:35 +010076{
77 ctx->padding = padding;
78 ctx->hash_id = hash_id;
79}
80
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081#if defined(MBEDTLS_GENPRIME)
Paul Bakker5121ce52009-01-03 21:22:43 +000082
83/*
84 * Generate an RSA keypair
85 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
Paul Bakkera3d195c2011-11-27 21:07:34 +000087 int (*f_rng)(void *, unsigned char *, size_t),
88 void *p_rng,
89 unsigned int nbits, int exponent )
Paul Bakker5121ce52009-01-03 21:22:43 +000090{
91 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 mbedtls_mpi P1, Q1, H, G;
Paul Bakker5121ce52009-01-03 21:22:43 +000093
Paul Bakker21eb2802010-08-16 11:10:02 +000094 if( f_rng == NULL || nbits < 128 || exponent < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000096
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097 mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G );
Paul Bakker5121ce52009-01-03 21:22:43 +000098
99 /*
100 * find primes P and Q with Q < P so that:
101 * GCD( E, (P-1)*(Q-1) ) == 1
102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
105 do
106 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
Paul Bakker21eb2802010-08-16 11:10:02 +0000108 f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
Paul Bakker21eb2802010-08-16 11:10:02 +0000111 f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
114 mbedtls_mpi_swap( &ctx->P, &ctx->Q );
Paul Bakker5121ce52009-01-03 21:22:43 +0000115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000117 continue;
118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200120 if( mbedtls_mpi_bitlen( &ctx->N ) != nbits )
Paul Bakker5121ce52009-01-03 21:22:43 +0000121 continue;
122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) );
124 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
125 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) );
126 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000127 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000129
130 /*
131 * D = E^-1 mod ((P-1)*(Q-1))
132 * DP = D mod (P - 1)
133 * DQ = D mod (Q - 1)
134 * QP = Q^-1 mod P
135 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
137 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
138 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
139 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000140
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200141 ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000142
143cleanup:
144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G );
Paul Bakker5121ce52009-01-03 21:22:43 +0000146
147 if( ret != 0 )
148 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 mbedtls_rsa_free( ctx );
150 return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000151 }
152
Paul Bakker48377d92013-08-30 12:06:24 +0200153 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000154}
155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156#endif /* MBEDTLS_GENPRIME */
Paul Bakker5121ce52009-01-03 21:22:43 +0000157
158/*
159 * Check a public RSA key
160 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000162{
Paul Bakker37940d92009-07-10 22:38:58 +0000163 if( !ctx->N.p || !ctx->E.p )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
Paul Bakker37940d92009-07-10 22:38:58 +0000165
Paul Bakker48377d92013-08-30 12:06:24 +0200166 if( ( ctx->N.p[0] & 1 ) == 0 ||
Paul Bakker5121ce52009-01-03 21:22:43 +0000167 ( ctx->E.p[0] & 1 ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000169
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200170 if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ||
171 mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000173
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200174 if( mbedtls_mpi_bitlen( &ctx->E ) < 2 ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 )
176 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +0000177
178 return( 0 );
179}
180
181/*
182 * Check a private RSA key
183 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000185{
186 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP;
Paul Bakker5121ce52009-01-03 21:22:43 +0000188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000190 return( ret );
191
Paul Bakker37940d92009-07-10 22:38:58 +0000192 if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
Paul Bakker37940d92009-07-10 22:38:58 +0000194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 );
196 mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 );
197 mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ );
198 mbedtls_mpi_init( &QP );
Paul Bakker5121ce52009-01-03 21:22:43 +0000199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
201 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
202 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) );
203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
204 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) );
205 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) );
208 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) );
209 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) );
Paul Bakkerb572adf2010-07-18 08:29:32 +0000210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) );
212 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) );
213 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) );
Paul Bakkerb572adf2010-07-18 08:29:32 +0000214 /*
215 * Check for a valid PKCS1v2 private key
216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217 if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
218 mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 ||
219 mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 ||
220 mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 ||
221 mbedtls_mpi_cmp_int( &L2, 0 ) != 0 ||
222 mbedtls_mpi_cmp_int( &I, 1 ) != 0 ||
223 mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
Paul Bakker5121ce52009-01-03 21:22:43 +0000226 }
Paul Bakker48377d92013-08-30 12:06:24 +0200227
Paul Bakker5121ce52009-01-03 21:22:43 +0000228cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 );
230 mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 );
231 mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ );
232 mbedtls_mpi_free( &QP );
Paul Bakker6c591fa2011-05-05 11:49:20 +0000233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED )
Paul Bakker9d781402011-05-09 16:17:09 +0000235 return( ret );
236
Paul Bakker6c591fa2011-05-05 11:49:20 +0000237 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200238 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret );
Paul Bakker6c591fa2011-05-05 11:49:20 +0000239
240 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000241}
242
243/*
Manuel Pégourié-Gonnard2f8d1f92014-11-06 14:02:51 +0100244 * Check if contexts holding a public and private key match
245 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200246int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv )
Manuel Pégourié-Gonnard2f8d1f92014-11-06 14:02:51 +0100247{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248 if( mbedtls_rsa_check_pubkey( pub ) != 0 ||
249 mbedtls_rsa_check_privkey( prv ) != 0 )
Manuel Pégourié-Gonnard2f8d1f92014-11-06 14:02:51 +0100250 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
Manuel Pégourié-Gonnard2f8d1f92014-11-06 14:02:51 +0100252 }
253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 ||
255 mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 )
Manuel Pégourié-Gonnard2f8d1f92014-11-06 14:02:51 +0100256 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
Manuel Pégourié-Gonnard2f8d1f92014-11-06 14:02:51 +0100258 }
259
260 return( 0 );
261}
262
263/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000264 * Do an RSA public key operation
265 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000267 const unsigned char *input,
Paul Bakker5121ce52009-01-03 21:22:43 +0000268 unsigned char *output )
269{
Paul Bakker23986e52011-04-24 08:57:21 +0000270 int ret;
271 size_t olen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 mbedtls_mpi T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 mbedtls_mpi_init( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000275
Manuel Pégourié-Gonnard1385a282015-08-27 11:30:58 +0200276#if defined(MBEDTLS_THREADING_C)
277 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
278 return( ret );
279#endif
280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000284 {
Manuel Pégourié-Gonnard4d04cdc2015-08-28 10:32:21 +0200285 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
286 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +0000287 }
288
289 olen = ctx->len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
291 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000292
293cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard4d04cdc2015-08-28 10:32:21 +0200295 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
296 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
Manuel Pégourié-Gonnard88fca3e2015-03-27 15:06:07 +0100297#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 mbedtls_mpi_free( &T );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300
301 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000303
304 return( 0 );
305}
306
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200307/*
Manuel Pégourié-Gonnard8a109f12013-09-10 13:37:26 +0200308 * Generate or update blinding values, see section 10 of:
309 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200310 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard8a109f12013-09-10 13:37:26 +0200311 * Berlin Heidelberg, 1996. p. 104-113.
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200312 */
Manuel Pégourié-Gonnard1385a282015-08-27 11:30:58 +0200313static int rsa_prepare_blinding( mbedtls_rsa_context *ctx,
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200314 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
315{
Manuel Pégourié-Gonnard4d89c7e2013-10-04 15:18:38 +0200316 int ret, count = 0;
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200317
Manuel Pégourié-Gonnard8a109f12013-09-10 13:37:26 +0200318 if( ctx->Vf.p != NULL )
319 {
320 /* We already have blinding values, just update them by squaring */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
322 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
323 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
324 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) );
Manuel Pégourié-Gonnard8a109f12013-09-10 13:37:26 +0200325
Manuel Pégourié-Gonnard1385a282015-08-27 11:30:58 +0200326 goto cleanup;
Manuel Pégourié-Gonnard8a109f12013-09-10 13:37:26 +0200327 }
328
Manuel Pégourié-Gonnard4d89c7e2013-10-04 15:18:38 +0200329 /* Unblinding value: Vf = random number, invertible mod N */
330 do {
331 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 return( MBEDTLS_ERR_RSA_RNG_FAILED );
Manuel Pégourié-Gonnard4d89c7e2013-10-04 15:18:38 +0200333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) );
335 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) );
336 } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 );
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200337
338 /* Blinding value: Vi = Vf^(-e) mod N */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) );
340 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) );
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200341
Manuel Pégourié-Gonnardae102992013-10-04 17:07:12 +0200342
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200343cleanup:
344 return( ret );
345}
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200346
Paul Bakker5121ce52009-01-03 21:22:43 +0000347/*
348 * Do an RSA private key operation
349 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
Paul Bakker548957d2013-08-30 10:30:02 +0200351 int (*f_rng)(void *, unsigned char *, size_t),
352 void *p_rng,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000353 const unsigned char *input,
Paul Bakker5121ce52009-01-03 21:22:43 +0000354 unsigned char *output )
355{
Paul Bakker23986e52011-04-24 08:57:21 +0000356 int ret;
357 size_t olen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 mbedtls_mpi T, T1, T2;
Paul Bakker5121ce52009-01-03 21:22:43 +0000359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000361
Manuel Pégourié-Gonnard1385a282015-08-27 11:30:58 +0200362#if defined(MBEDTLS_THREADING_C)
363 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
364 return( ret );
365#endif
366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
368 if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000369 {
Manuel Pégourié-Gonnard4d04cdc2015-08-28 10:32:21 +0200370 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
371 goto cleanup;
Paul Bakker5121ce52009-01-03 21:22:43 +0000372 }
373
Paul Bakkerf451bac2013-08-30 15:37:02 +0200374 if( f_rng != NULL )
375 {
376 /*
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200377 * Blinding
378 * T = T * Vi mod N
Paul Bakkerf451bac2013-08-30 15:37:02 +0200379 */
Manuel Pégourié-Gonnard1385a282015-08-27 11:30:58 +0200380 MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) );
381 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
Paul Bakkerf451bac2013-08-30 15:37:02 +0200383 }
Paul Bakkeraab30c12013-08-30 11:00:25 +0200384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385#if defined(MBEDTLS_RSA_NO_CRT)
386 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
Manuel Pégourié-Gonnarde10e06d2014-11-06 18:15:12 +0100387#else
Paul Bakkeraab30c12013-08-30 11:00:25 +0200388 /*
Paul Bakker5121ce52009-01-03 21:22:43 +0000389 * faster decryption using the CRT
390 *
391 * T1 = input ^ dP mod P
392 * T2 = input ^ dQ mod Q
393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
395 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000396
397 /*
398 * T = (T1 - T2) * (Q^-1 mod P) mod P
399 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) );
401 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) );
402 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000403
404 /*
Paul Bakkerf451bac2013-08-30 15:37:02 +0200405 * T = T2 + T * Q
Paul Bakker5121ce52009-01-03 21:22:43 +0000406 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) );
408 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) );
409#endif /* MBEDTLS_RSA_NO_CRT */
Paul Bakkeraab30c12013-08-30 11:00:25 +0200410
Paul Bakkerf451bac2013-08-30 15:37:02 +0200411 if( f_rng != NULL )
412 {
413 /*
414 * Unblind
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +0200415 * T = T * Vf mod N
Paul Bakkerf451bac2013-08-30 15:37:02 +0200416 */
Manuel Pégourié-Gonnard1385a282015-08-27 11:30:58 +0200417 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
Paul Bakkerf451bac2013-08-30 15:37:02 +0200419 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000420
421 olen = ctx->len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000423
424cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard4d04cdc2015-08-28 10:32:21 +0200426 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
427 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
Manuel Pégourié-Gonnardae102992013-10-04 17:07:12 +0200428#endif
Manuel Pégourié-Gonnard1385a282015-08-27 11:30:58 +0200429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000431
432 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000434
435 return( 0 );
436}
437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438#if defined(MBEDTLS_PKCS1_V21)
Paul Bakker9dcc3222011-03-08 14:16:06 +0000439/**
440 * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
441 *
Paul Bakkerb125ed82011-11-10 13:33:51 +0000442 * \param dst buffer to mask
443 * \param dlen length of destination buffer
444 * \param src source of the mask generation
445 * \param slen length of the source buffer
446 * \param md_ctx message digest context to use
Paul Bakker9dcc3222011-03-08 14:16:06 +0000447 */
Paul Bakker48377d92013-08-30 12:06:24 +0200448static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 size_t slen, mbedtls_md_context_t *md_ctx )
Paul Bakker9dcc3222011-03-08 14:16:06 +0000450{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 unsigned char mask[MBEDTLS_MD_MAX_SIZE];
Paul Bakker9dcc3222011-03-08 14:16:06 +0000452 unsigned char counter[4];
453 unsigned char *p;
Paul Bakker23986e52011-04-24 08:57:21 +0000454 unsigned int hlen;
455 size_t i, use_len;
Paul Bakker9dcc3222011-03-08 14:16:06 +0000456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 memset( mask, 0, MBEDTLS_MD_MAX_SIZE );
Paul Bakker9dcc3222011-03-08 14:16:06 +0000458 memset( counter, 0, 4 );
459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 hlen = mbedtls_md_get_size( md_ctx->md_info );
Paul Bakker9dcc3222011-03-08 14:16:06 +0000461
462 // Generate and apply dbMask
463 //
464 p = dst;
465
466 while( dlen > 0 )
467 {
468 use_len = hlen;
469 if( dlen < hlen )
470 use_len = dlen;
471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 mbedtls_md_starts( md_ctx );
473 mbedtls_md_update( md_ctx, src, slen );
474 mbedtls_md_update( md_ctx, counter, 4 );
475 mbedtls_md_finish( md_ctx, mask );
Paul Bakker9dcc3222011-03-08 14:16:06 +0000476
477 for( i = 0; i < use_len; ++i )
478 *p++ ^= mask[i];
479
480 counter[3]++;
481
482 dlen -= use_len;
483 }
484}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485#endif /* MBEDTLS_PKCS1_V21 */
Paul Bakker9dcc3222011-03-08 14:16:06 +0000486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487#if defined(MBEDTLS_PKCS1_V21)
Paul Bakkerb3869132013-02-28 17:21:01 +0100488/*
489 * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function
490 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
Paul Bakkerb3869132013-02-28 17:21:01 +0100492 int (*f_rng)(void *, unsigned char *, size_t),
493 void *p_rng,
Paul Bakkera43231c2013-02-28 17:33:49 +0100494 int mode,
495 const unsigned char *label, size_t label_len,
496 size_t ilen,
Paul Bakkerb3869132013-02-28 17:21:01 +0100497 const unsigned char *input,
498 unsigned char *output )
499{
500 size_t olen;
501 int ret;
502 unsigned char *p = output;
503 unsigned int hlen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 const mbedtls_md_info_t *md_info;
505 mbedtls_md_context_t md_ctx;
Paul Bakkerb3869132013-02-28 17:21:01 +0100506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
508 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarde6d1d822014-06-02 16:47:02 +0200509
510 if( f_rng == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513 md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
Paul Bakkerb3869132013-02-28 17:21:01 +0100514 if( md_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100516
517 olen = ctx->len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 hlen = mbedtls_md_get_size( md_info );
Paul Bakkerb3869132013-02-28 17:21:01 +0100519
Manuel Pégourié-Gonnarde6d1d822014-06-02 16:47:02 +0200520 if( olen < ilen + 2 * hlen + 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100522
523 memset( output, 0, olen );
524
525 *p++ = 0;
526
527 // Generate a random octet string seed
528 //
529 if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
Paul Bakkerb3869132013-02-28 17:21:01 +0100531
532 p += hlen;
533
534 // Construct DB
535 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 mbedtls_md( md_info, label, label_len, p );
Paul Bakkerb3869132013-02-28 17:21:01 +0100537 p += hlen;
538 p += olen - 2 * hlen - 2 - ilen;
539 *p++ = 1;
540 memcpy( p, input, ilen );
541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 mbedtls_md_init( &md_ctx );
543 mbedtls_md_setup( &md_ctx, md_info, 0 );
Paul Bakkerb3869132013-02-28 17:21:01 +0100544
545 // maskedDB: Apply dbMask to DB
546 //
547 mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
548 &md_ctx );
549
550 // maskedSeed: Apply seedMask to seed
551 //
552 mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
553 &md_ctx );
554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 mbedtls_md_free( &md_ctx );
Paul Bakkerb3869132013-02-28 17:21:01 +0100556
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 return( ( mode == MBEDTLS_RSA_PUBLIC )
558 ? mbedtls_rsa_public( ctx, output, output )
559 : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) );
Paul Bakkerb3869132013-02-28 17:21:01 +0100560}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561#endif /* MBEDTLS_PKCS1_V21 */
Paul Bakkerb3869132013-02-28 17:21:01 +0100562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563#if defined(MBEDTLS_PKCS1_V15)
Paul Bakkerb3869132013-02-28 17:21:01 +0100564/*
565 * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function
566 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
Paul Bakkerb3869132013-02-28 17:21:01 +0100568 int (*f_rng)(void *, unsigned char *, size_t),
569 void *p_rng,
570 int mode, size_t ilen,
571 const unsigned char *input,
572 unsigned char *output )
573{
574 size_t nb_pad, olen;
575 int ret;
576 unsigned char *p = output;
577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
579 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarde6d1d822014-06-02 16:47:02 +0200580
581 if( f_rng == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100583
584 olen = ctx->len;
585
586 if( olen < ilen + 11 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100588
589 nb_pad = olen - 3 - ilen;
590
591 *p++ = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 if( mode == MBEDTLS_RSA_PUBLIC )
Paul Bakkerb3869132013-02-28 17:21:01 +0100593 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 *p++ = MBEDTLS_RSA_CRYPT;
Paul Bakkerb3869132013-02-28 17:21:01 +0100595
596 while( nb_pad-- > 0 )
597 {
598 int rng_dl = 100;
599
600 do {
601 ret = f_rng( p_rng, p, 1 );
602 } while( *p == 0 && --rng_dl && ret == 0 );
603
604 // Check if RNG failed to generate data
605 //
Paul Bakker66d5d072014-06-17 16:39:18 +0200606 if( rng_dl == 0 || ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
Paul Bakkerb3869132013-02-28 17:21:01 +0100608
609 p++;
610 }
611 }
612 else
613 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 *p++ = MBEDTLS_RSA_SIGN;
Paul Bakkerb3869132013-02-28 17:21:01 +0100615
616 while( nb_pad-- > 0 )
617 *p++ = 0xFF;
618 }
619
620 *p++ = 0;
621 memcpy( p, input, ilen );
622
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 return( ( mode == MBEDTLS_RSA_PUBLIC )
624 ? mbedtls_rsa_public( ctx, output, output )
625 : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) );
Paul Bakkerb3869132013-02-28 17:21:01 +0100626}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627#endif /* MBEDTLS_PKCS1_V15 */
Paul Bakkerb3869132013-02-28 17:21:01 +0100628
Paul Bakker5121ce52009-01-03 21:22:43 +0000629/*
630 * Add the message padding, then do an RSA operation
631 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000633 int (*f_rng)(void *, unsigned char *, size_t),
Paul Bakker21eb2802010-08-16 11:10:02 +0000634 void *p_rng,
Paul Bakker23986e52011-04-24 08:57:21 +0000635 int mode, size_t ilen,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000636 const unsigned char *input,
Paul Bakker5121ce52009-01-03 21:22:43 +0000637 unsigned char *output )
638{
Paul Bakker5121ce52009-01-03 21:22:43 +0000639 switch( ctx->padding )
640 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641#if defined(MBEDTLS_PKCS1_V15)
642 case MBEDTLS_RSA_PKCS_V15:
643 return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen,
Paul Bakkerb3869132013-02-28 17:21:01 +0100644 input, output );
Paul Bakker48377d92013-08-30 12:06:24 +0200645#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000646
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647#if defined(MBEDTLS_PKCS1_V21)
648 case MBEDTLS_RSA_PKCS_V21:
649 return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0,
Paul Bakkerb3869132013-02-28 17:21:01 +0100650 ilen, input, output );
Paul Bakker9dcc3222011-03-08 14:16:06 +0000651#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000652
653 default:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakker5121ce52009-01-03 21:22:43 +0000655 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000656}
657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658#if defined(MBEDTLS_PKCS1_V21)
Paul Bakker5121ce52009-01-03 21:22:43 +0000659/*
Paul Bakkerb3869132013-02-28 17:21:01 +0100660 * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function
Paul Bakker5121ce52009-01-03 21:22:43 +0000661 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
Paul Bakker548957d2013-08-30 10:30:02 +0200663 int (*f_rng)(void *, unsigned char *, size_t),
664 void *p_rng,
665 int mode,
Paul Bakkera43231c2013-02-28 17:33:49 +0100666 const unsigned char *label, size_t label_len,
667 size_t *olen,
Paul Bakkerb3869132013-02-28 17:21:01 +0100668 const unsigned char *input,
669 unsigned char *output,
670 size_t output_max_len )
Paul Bakker5121ce52009-01-03 21:22:43 +0000671{
Paul Bakker23986e52011-04-24 08:57:21 +0000672 int ret;
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100673 size_t ilen, i, pad_len;
674 unsigned char *p, bad, pad_done;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
676 unsigned char lhash[MBEDTLS_MD_MAX_SIZE];
Paul Bakker23986e52011-04-24 08:57:21 +0000677 unsigned int hlen;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 const mbedtls_md_info_t *md_info;
679 mbedtls_md_context_t md_ctx;
Paul Bakkerb3869132013-02-28 17:21:01 +0100680
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100681 /*
682 * Parameters sanity checks
683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
685 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000686
687 ilen = ctx->len;
688
Paul Bakker27fdf462011-06-09 13:55:13 +0000689 if( ilen < 16 || ilen > sizeof( buf ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100693 if( md_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100695
696 /*
697 * RSA operation
698 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 ret = ( mode == MBEDTLS_RSA_PUBLIC )
700 ? mbedtls_rsa_public( ctx, input, buf )
701 : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf );
Paul Bakker5121ce52009-01-03 21:22:43 +0000702
703 if( ret != 0 )
704 return( ret );
705
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100706 /*
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100707 * Unmask data and generate lHash
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100708 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 hlen = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 mbedtls_md_init( &md_ctx );
712 mbedtls_md_setup( &md_ctx, md_info, 0 );
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100713
714 /* Generate lHash */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 mbedtls_md( md_info, label, label_len, lhash );
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100716
717 /* seed: Apply seedMask to maskedSeed */
718 mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
719 &md_ctx );
720
721 /* DB: Apply dbMask to maskedDB */
722 mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
723 &md_ctx );
724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725 mbedtls_md_free( &md_ctx );
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100726
727 /*
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100728 * Check contents, in "constant-time"
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100729 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000730 p = buf;
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100731 bad = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100733 bad |= *p++; /* First byte must be 0 */
Paul Bakkerb3869132013-02-28 17:21:01 +0100734
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100735 p += hlen; /* Skip seed */
Paul Bakkerb3869132013-02-28 17:21:01 +0100736
Manuel Pégourié-Gonnarda5cfc352013-11-28 15:57:52 +0100737 /* Check lHash */
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100738 for( i = 0; i < hlen; i++ )
739 bad |= lhash[i] ^ *p++;
Paul Bakkerb3869132013-02-28 17:21:01 +0100740
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100741 /* Get zero-padding len, but always read till end of buffer
742 * (minus one, for the 01 byte) */
743 pad_len = 0;
744 pad_done = 0;
745 for( i = 0; i < ilen - 2 * hlen - 2; i++ )
746 {
747 pad_done |= p[i];
Pascal Junodb99183d2015-03-11 16:49:45 +0100748 pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100749 }
Paul Bakkerb3869132013-02-28 17:21:01 +0100750
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100751 p += pad_len;
752 bad |= *p++ ^ 0x01;
Paul Bakkerb3869132013-02-28 17:21:01 +0100753
Manuel Pégourié-Gonnardab44d7e2013-11-29 12:49:44 +0100754 /*
755 * The only information "leaked" is whether the padding was correct or not
756 * (eg, no data is copied if it was not correct). This meets the
757 * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
758 * the different error conditions.
759 */
760 if( bad != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakkerb3869132013-02-28 17:21:01 +0100762
Paul Bakker66d5d072014-06-17 16:39:18 +0200763 if( ilen - ( p - buf ) > output_max_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );
Paul Bakkerb3869132013-02-28 17:21:01 +0100765
766 *olen = ilen - (p - buf);
767 memcpy( output, p, *olen );
768
769 return( 0 );
770}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200771#endif /* MBEDTLS_PKCS1_V21 */
Paul Bakkerb3869132013-02-28 17:21:01 +0100772
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773#if defined(MBEDTLS_PKCS1_V15)
Paul Bakkerb3869132013-02-28 17:21:01 +0100774/*
775 * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
776 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
Paul Bakker548957d2013-08-30 10:30:02 +0200778 int (*f_rng)(void *, unsigned char *, size_t),
779 void *p_rng,
Paul Bakkerb3869132013-02-28 17:21:01 +0100780 int mode, size_t *olen,
781 const unsigned char *input,
782 unsigned char *output,
783 size_t output_max_len)
784{
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100785 int ret;
786 size_t ilen, pad_count = 0, i;
787 unsigned char *p, bad, pad_done = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
Paul Bakkerb3869132013-02-28 17:21:01 +0100789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
791 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100792
793 ilen = ctx->len;
794
795 if( ilen < 16 || ilen > sizeof( buf ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100797
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200798 ret = ( mode == MBEDTLS_RSA_PUBLIC )
799 ? mbedtls_rsa_public( ctx, input, buf )
800 : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf );
Paul Bakkerb3869132013-02-28 17:21:01 +0100801
802 if( ret != 0 )
803 return( ret );
804
805 p = buf;
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100806 bad = 0;
Paul Bakkerb3869132013-02-28 17:21:01 +0100807
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100808 /*
809 * Check and get padding len in "constant-time"
810 */
811 bad |= *p++; /* First byte must be 0 */
Paul Bakkerb3869132013-02-28 17:21:01 +0100812
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100813 /* This test does not depend on secret data */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 if( mode == MBEDTLS_RSA_PRIVATE )
Paul Bakker5121ce52009-01-03 21:22:43 +0000815 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200816 bad |= *p++ ^ MBEDTLS_RSA_CRYPT;
Paul Bakker5121ce52009-01-03 21:22:43 +0000817
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100818 /* Get padding len, but always read till end of buffer
819 * (minus one, for the 00 byte) */
820 for( i = 0; i < ilen - 3; i++ )
821 {
Pascal Junodb99183d2015-03-11 16:49:45 +0100822 pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1;
823 pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100824 }
Paul Bakkere6ee41f2012-05-19 08:43:48 +0000825
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100826 p += pad_count;
827 bad |= *p++; /* Must be zero */
Paul Bakkerb3869132013-02-28 17:21:01 +0100828 }
829 else
830 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 bad |= *p++ ^ MBEDTLS_RSA_SIGN;
Paul Bakkerb3869132013-02-28 17:21:01 +0100832
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100833 /* Get padding len, but always read till end of buffer
834 * (minus one, for the 00 byte) */
835 for( i = 0; i < ilen - 3; i++ )
836 {
Manuel Pégourié-Gonnardfbf09152014-02-03 11:58:55 +0100837 pad_done |= ( p[i] != 0xFF );
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100838 pad_count += ( pad_done == 0 );
839 }
Paul Bakkerb3869132013-02-28 17:21:01 +0100840
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100841 p += pad_count;
842 bad |= *p++; /* Must be zero */
Paul Bakker5121ce52009-01-03 21:22:43 +0000843 }
844
Manuel Pégourié-Gonnard27290da2013-11-30 13:36:53 +0100845 if( bad )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200846 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakker8804f692013-02-28 18:06:26 +0100847
Paul Bakker66d5d072014-06-17 16:39:18 +0200848 if( ilen - ( p - buf ) > output_max_len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );
Paul Bakker060c5682009-01-12 21:48:39 +0000850
Paul Bakker27fdf462011-06-09 13:55:13 +0000851 *olen = ilen - (p - buf);
Paul Bakker5121ce52009-01-03 21:22:43 +0000852 memcpy( output, p, *olen );
853
854 return( 0 );
855}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200856#endif /* MBEDTLS_PKCS1_V15 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000857
858/*
Paul Bakkerb3869132013-02-28 17:21:01 +0100859 * Do an RSA operation, then remove the message padding
860 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
Paul Bakker548957d2013-08-30 10:30:02 +0200862 int (*f_rng)(void *, unsigned char *, size_t),
863 void *p_rng,
Paul Bakkerb3869132013-02-28 17:21:01 +0100864 int mode, size_t *olen,
865 const unsigned char *input,
866 unsigned char *output,
867 size_t output_max_len)
868{
869 switch( ctx->padding )
870 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871#if defined(MBEDTLS_PKCS1_V15)
872 case MBEDTLS_RSA_PKCS_V15:
873 return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen,
Paul Bakker548957d2013-08-30 10:30:02 +0200874 input, output, output_max_len );
Paul Bakker48377d92013-08-30 12:06:24 +0200875#endif
Paul Bakkerb3869132013-02-28 17:21:01 +0100876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877#if defined(MBEDTLS_PKCS1_V21)
878 case MBEDTLS_RSA_PKCS_V21:
879 return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0,
Paul Bakker548957d2013-08-30 10:30:02 +0200880 olen, input, output,
881 output_max_len );
Paul Bakkerb3869132013-02-28 17:21:01 +0100882#endif
883
884 default:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakkerb3869132013-02-28 17:21:01 +0100886 }
887}
888
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889#if defined(MBEDTLS_PKCS1_V21)
Paul Bakkerb3869132013-02-28 17:21:01 +0100890/*
891 * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
892 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
Paul Bakkerb3869132013-02-28 17:21:01 +0100894 int (*f_rng)(void *, unsigned char *, size_t),
895 void *p_rng,
896 int mode,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200897 mbedtls_md_type_t md_alg,
Paul Bakkerb3869132013-02-28 17:21:01 +0100898 unsigned int hashlen,
899 const unsigned char *hash,
900 unsigned char *sig )
901{
902 size_t olen;
903 unsigned char *p = sig;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200904 unsigned char salt[MBEDTLS_MD_MAX_SIZE];
Paul Bakkerb3869132013-02-28 17:21:01 +0100905 unsigned int slen, hlen, offset = 0;
906 int ret;
907 size_t msb;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908 const mbedtls_md_info_t *md_info;
909 mbedtls_md_context_t md_ctx;
Paul Bakkerb3869132013-02-28 17:21:01 +0100910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200911 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
912 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarde6d1d822014-06-02 16:47:02 +0200913
914 if( f_rng == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100916
917 olen = ctx->len;
918
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 if( md_alg != MBEDTLS_MD_NONE )
Paul Bakkerb3869132013-02-28 17:21:01 +0100920 {
Paul Bakkerc70b9822013-04-07 22:00:46 +0200921 // Gather length of hash to sign
922 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 md_info = mbedtls_md_info_from_type( md_alg );
Paul Bakkerc70b9822013-04-07 22:00:46 +0200924 if( md_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerc70b9822013-04-07 22:00:46 +0200926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 hashlen = mbedtls_md_get_size( md_info );
Paul Bakkerb3869132013-02-28 17:21:01 +0100928 }
929
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200930 md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
Paul Bakkerb3869132013-02-28 17:21:01 +0100931 if( md_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100933
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934 hlen = mbedtls_md_get_size( md_info );
Paul Bakkerb3869132013-02-28 17:21:01 +0100935 slen = hlen;
936
937 if( olen < hlen + slen + 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +0100939
940 memset( sig, 0, olen );
941
Paul Bakkerb3869132013-02-28 17:21:01 +0100942 // Generate salt of length slen
943 //
944 if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
Paul Bakkerb3869132013-02-28 17:21:01 +0100946
947 // Note: EMSA-PSS encoding is over the length of N - 1 bits
948 //
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200949 msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
Paul Bakkerb3869132013-02-28 17:21:01 +0100950 p += olen - hlen * 2 - 2;
951 *p++ = 0x01;
952 memcpy( p, salt, slen );
953 p += slen;
954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200955 mbedtls_md_init( &md_ctx );
956 mbedtls_md_setup( &md_ctx, md_info, 0 );
Paul Bakkerb3869132013-02-28 17:21:01 +0100957
958 // Generate H = Hash( M' )
959 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960 mbedtls_md_starts( &md_ctx );
961 mbedtls_md_update( &md_ctx, p, 8 );
962 mbedtls_md_update( &md_ctx, hash, hashlen );
963 mbedtls_md_update( &md_ctx, salt, slen );
964 mbedtls_md_finish( &md_ctx, p );
Paul Bakkerb3869132013-02-28 17:21:01 +0100965
966 // Compensate for boundary condition when applying mask
967 //
968 if( msb % 8 == 0 )
969 offset = 1;
970
971 // maskedDB: Apply dbMask to DB
972 //
973 mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );
974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975 mbedtls_md_free( &md_ctx );
Paul Bakkerb3869132013-02-28 17:21:01 +0100976
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200977 msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
Paul Bakkerb3869132013-02-28 17:21:01 +0100978 sig[0] &= 0xFF >> ( olen * 8 - msb );
979
980 p += hlen;
981 *p++ = 0xBC;
982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 return( ( mode == MBEDTLS_RSA_PUBLIC )
984 ? mbedtls_rsa_public( ctx, sig, sig )
985 : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
Paul Bakkerb3869132013-02-28 17:21:01 +0100986}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987#endif /* MBEDTLS_PKCS1_V21 */
Paul Bakkerb3869132013-02-28 17:21:01 +0100988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989#if defined(MBEDTLS_PKCS1_V15)
Paul Bakkerb3869132013-02-28 17:21:01 +0100990/*
991 * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
992 */
993/*
994 * Do an RSA operation to sign the message digest
995 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200996int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
Paul Bakker548957d2013-08-30 10:30:02 +0200997 int (*f_rng)(void *, unsigned char *, size_t),
998 void *p_rng,
Paul Bakkerb3869132013-02-28 17:21:01 +0100999 int mode,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001000 mbedtls_md_type_t md_alg,
Paul Bakkerb3869132013-02-28 17:21:01 +01001001 unsigned int hashlen,
1002 const unsigned char *hash,
1003 unsigned char *sig )
1004{
Paul Bakkerc70b9822013-04-07 22:00:46 +02001005 size_t nb_pad, olen, oid_size = 0;
Paul Bakkerb3869132013-02-28 17:21:01 +01001006 unsigned char *p = sig;
Paul Bakker21e081b2014-07-24 10:38:01 +02001007 const char *oid = NULL;
Paul Bakkerb3869132013-02-28 17:21:01 +01001008
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001009 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
1010 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +01001011
1012 olen = ctx->len;
Paul Bakkerc70b9822013-04-07 22:00:46 +02001013 nb_pad = olen - 3;
Paul Bakkerb3869132013-02-28 17:21:01 +01001014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 if( md_alg != MBEDTLS_MD_NONE )
Paul Bakkerb3869132013-02-28 17:21:01 +01001016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001018 if( md_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001020
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
1022 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001023
Paul Bakkerc70b9822013-04-07 22:00:46 +02001024 nb_pad -= 10 + oid_size;
1025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 hashlen = mbedtls_md_get_size( md_info );
Paul Bakkerb3869132013-02-28 17:21:01 +01001027 }
1028
Paul Bakkerc70b9822013-04-07 22:00:46 +02001029 nb_pad -= hashlen;
1030
Paul Bakkerb3869132013-02-28 17:21:01 +01001031 if( ( nb_pad < 8 ) || ( nb_pad > olen ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +01001033
1034 *p++ = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035 *p++ = MBEDTLS_RSA_SIGN;
Paul Bakkerb3869132013-02-28 17:21:01 +01001036 memset( p, 0xFF, nb_pad );
1037 p += nb_pad;
1038 *p++ = 0;
1039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 if( md_alg == MBEDTLS_MD_NONE )
Paul Bakkerb3869132013-02-28 17:21:01 +01001041 {
Paul Bakkerc70b9822013-04-07 22:00:46 +02001042 memcpy( p, hash, hashlen );
1043 }
1044 else
1045 {
1046 /*
1047 * DigestInfo ::= SEQUENCE {
1048 * digestAlgorithm DigestAlgorithmIdentifier,
1049 * digest Digest }
1050 *
1051 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
1052 *
1053 * Digest ::= OCTET STRING
1054 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001056 *p++ = (unsigned char) ( 0x08 + oid_size + hashlen );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001058 *p++ = (unsigned char) ( 0x04 + oid_size );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059 *p++ = MBEDTLS_ASN1_OID;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001060 *p++ = oid_size & 0xFF;
Paul Bakkerc70b9822013-04-07 22:00:46 +02001061 memcpy( p, oid, oid_size );
1062 p += oid_size;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001063 *p++ = MBEDTLS_ASN1_NULL;
Paul Bakkerc70b9822013-04-07 22:00:46 +02001064 *p++ = 0x00;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 *p++ = MBEDTLS_ASN1_OCTET_STRING;
Paul Bakkerc70b9822013-04-07 22:00:46 +02001066 *p++ = hashlen;
1067 memcpy( p, hash, hashlen );
Paul Bakkerb3869132013-02-28 17:21:01 +01001068 }
1069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 return( ( mode == MBEDTLS_RSA_PUBLIC )
1071 ? mbedtls_rsa_public( ctx, sig, sig )
1072 : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
Paul Bakkerb3869132013-02-28 17:21:01 +01001073}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074#endif /* MBEDTLS_PKCS1_V15 */
Paul Bakkerb3869132013-02-28 17:21:01 +01001075
1076/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001077 * Do an RSA operation to sign the message digest
1078 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
Paul Bakkera3d195c2011-11-27 21:07:34 +00001080 int (*f_rng)(void *, unsigned char *, size_t),
Paul Bakker9dcc3222011-03-08 14:16:06 +00001081 void *p_rng,
Paul Bakker5121ce52009-01-03 21:22:43 +00001082 int mode,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 mbedtls_md_type_t md_alg,
Paul Bakker23986e52011-04-24 08:57:21 +00001084 unsigned int hashlen,
Paul Bakkerff60ee62010-03-16 21:09:09 +00001085 const unsigned char *hash,
Paul Bakker5121ce52009-01-03 21:22:43 +00001086 unsigned char *sig )
1087{
Paul Bakker5121ce52009-01-03 21:22:43 +00001088 switch( ctx->padding )
1089 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090#if defined(MBEDTLS_PKCS1_V15)
1091 case MBEDTLS_RSA_PKCS_V15:
1092 return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg,
Paul Bakkerb3869132013-02-28 17:21:01 +01001093 hashlen, hash, sig );
Paul Bakker48377d92013-08-30 12:06:24 +02001094#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001095
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096#if defined(MBEDTLS_PKCS1_V21)
1097 case MBEDTLS_RSA_PKCS_V21:
1098 return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg,
Paul Bakkerb3869132013-02-28 17:21:01 +01001099 hashlen, hash, sig );
Paul Bakker9dcc3222011-03-08 14:16:06 +00001100#endif
1101
Paul Bakker5121ce52009-01-03 21:22:43 +00001102 default:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakker5121ce52009-01-03 21:22:43 +00001104 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001105}
1106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107#if defined(MBEDTLS_PKCS1_V21)
Paul Bakker5121ce52009-01-03 21:22:43 +00001108/*
Paul Bakkerb3869132013-02-28 17:21:01 +01001109 * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
Paul Bakker5121ce52009-01-03 21:22:43 +00001110 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001112 int (*f_rng)(void *, unsigned char *, size_t),
1113 void *p_rng,
1114 int mode,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_md_type_t md_alg,
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001116 unsigned int hashlen,
1117 const unsigned char *hash,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118 mbedtls_md_type_t mgf1_hash_id,
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001119 int expected_salt_len,
1120 const unsigned char *sig )
Paul Bakker5121ce52009-01-03 21:22:43 +00001121{
Paul Bakker23986e52011-04-24 08:57:21 +00001122 int ret;
Paul Bakkerb3869132013-02-28 17:21:01 +01001123 size_t siglen;
1124 unsigned char *p;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
1126 unsigned char result[MBEDTLS_MD_MAX_SIZE];
Paul Bakker9dcc3222011-03-08 14:16:06 +00001127 unsigned char zeros[8];
Paul Bakker23986e52011-04-24 08:57:21 +00001128 unsigned int hlen;
1129 size_t slen, msb;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130 const mbedtls_md_info_t *md_info;
1131 mbedtls_md_context_t md_ctx;
Paul Bakkerb3869132013-02-28 17:21:01 +01001132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
1134 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +01001135
Paul Bakker5121ce52009-01-03 21:22:43 +00001136 siglen = ctx->len;
1137
Paul Bakker27fdf462011-06-09 13:55:13 +00001138 if( siglen < 16 || siglen > sizeof( buf ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001139 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001140
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 ret = ( mode == MBEDTLS_RSA_PUBLIC )
1142 ? mbedtls_rsa_public( ctx, sig, buf )
1143 : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf );
Paul Bakker5121ce52009-01-03 21:22:43 +00001144
1145 if( ret != 0 )
1146 return( ret );
1147
1148 p = buf;
1149
Paul Bakkerb3869132013-02-28 17:21:01 +01001150 if( buf[siglen - 1] != 0xBC )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakkerb3869132013-02-28 17:21:01 +01001152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001153 if( md_alg != MBEDTLS_MD_NONE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001154 {
Paul Bakkerc70b9822013-04-07 22:00:46 +02001155 // Gather length of hash to sign
1156 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001157 md_info = mbedtls_md_info_from_type( md_alg );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001158 if( md_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001159 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001160
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001161 hashlen = mbedtls_md_get_size( md_info );
Paul Bakkerb3869132013-02-28 17:21:01 +01001162 }
Paul Bakker9dcc3222011-03-08 14:16:06 +00001163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001164 md_info = mbedtls_md_info_from_type( mgf1_hash_id );
Paul Bakkerb3869132013-02-28 17:21:01 +01001165 if( md_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakker9dcc3222011-03-08 14:16:06 +00001167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168 hlen = mbedtls_md_get_size( md_info );
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001169 slen = siglen - hlen - 1; /* Currently length of salt + padding */
Paul Bakker9dcc3222011-03-08 14:16:06 +00001170
Paul Bakkerb3869132013-02-28 17:21:01 +01001171 memset( zeros, 0, 8 );
Paul Bakker53019ae2011-03-25 13:58:48 +00001172
Paul Bakkerb3869132013-02-28 17:21:01 +01001173 // Note: EMSA-PSS verification is over the length of N - 1 bits
1174 //
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001175 msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
Paul Bakker9dcc3222011-03-08 14:16:06 +00001176
Paul Bakkerb3869132013-02-28 17:21:01 +01001177 // Compensate for boundary condition when applying mask
1178 //
1179 if( msb % 8 == 0 )
1180 {
1181 p++;
1182 siglen -= 1;
1183 }
1184 if( buf[0] >> ( 8 - siglen * 8 + msb ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakker9dcc3222011-03-08 14:16:06 +00001186
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001187 mbedtls_md_init( &md_ctx );
1188 mbedtls_md_setup( &md_ctx, md_info, 0 );
Paul Bakker9dcc3222011-03-08 14:16:06 +00001189
Paul Bakkerb3869132013-02-28 17:21:01 +01001190 mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );
Paul Bakker02303e82013-01-03 11:08:31 +01001191
Paul Bakkerb3869132013-02-28 17:21:01 +01001192 buf[0] &= 0xFF >> ( siglen * 8 - msb );
Paul Bakker9dcc3222011-03-08 14:16:06 +00001193
Paul Bakker4de44aa2013-12-31 11:43:01 +01001194 while( p < buf + siglen && *p == 0 )
Paul Bakkerb3869132013-02-28 17:21:01 +01001195 p++;
Paul Bakker9dcc3222011-03-08 14:16:06 +00001196
Paul Bakkerb3869132013-02-28 17:21:01 +01001197 if( p == buf + siglen ||
1198 *p++ != 0x01 )
1199 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200 mbedtls_md_free( &md_ctx );
1201 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakkerb3869132013-02-28 17:21:01 +01001202 }
Paul Bakker9dcc3222011-03-08 14:16:06 +00001203
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001204 /* Actual salt len */
Paul Bakkerb3869132013-02-28 17:21:01 +01001205 slen -= p - buf;
Paul Bakker9dcc3222011-03-08 14:16:06 +00001206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207 if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001208 slen != (size_t) expected_salt_len )
1209 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 mbedtls_md_free( &md_ctx );
1211 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001212 }
1213
Paul Bakkerb3869132013-02-28 17:21:01 +01001214 // Generate H = Hash( M' )
1215 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 mbedtls_md_starts( &md_ctx );
1217 mbedtls_md_update( &md_ctx, zeros, 8 );
1218 mbedtls_md_update( &md_ctx, hash, hashlen );
1219 mbedtls_md_update( &md_ctx, p, slen );
1220 mbedtls_md_finish( &md_ctx, result );
Paul Bakker53019ae2011-03-25 13:58:48 +00001221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222 mbedtls_md_free( &md_ctx );
Paul Bakker9dcc3222011-03-08 14:16:06 +00001223
Paul Bakkerb3869132013-02-28 17:21:01 +01001224 if( memcmp( p + slen, result, hlen ) == 0 )
1225 return( 0 );
1226 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001227 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerb3869132013-02-28 17:21:01 +01001228}
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001229
1230/*
1231 * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function
1232 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx,
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001234 int (*f_rng)(void *, unsigned char *, size_t),
1235 void *p_rng,
1236 int mode,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001237 mbedtls_md_type_t md_alg,
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001238 unsigned int hashlen,
1239 const unsigned char *hash,
1240 const unsigned char *sig )
1241{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE )
1243 ? (mbedtls_md_type_t) ctx->hash_id
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001244 : md_alg;
1245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode,
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001247 md_alg, hashlen, hash,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY,
Manuel Pégourié-Gonnard5ec628a2014-06-03 11:44:06 +02001249 sig ) );
1250
1251}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252#endif /* MBEDTLS_PKCS1_V21 */
Paul Bakker40628ba2013-01-03 10:50:31 +01001253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254#if defined(MBEDTLS_PKCS1_V15)
Paul Bakkerb3869132013-02-28 17:21:01 +01001255/*
1256 * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
1257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
Paul Bakker548957d2013-08-30 10:30:02 +02001259 int (*f_rng)(void *, unsigned char *, size_t),
1260 void *p_rng,
Paul Bakkerb3869132013-02-28 17:21:01 +01001261 int mode,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 mbedtls_md_type_t md_alg,
Paul Bakkerb3869132013-02-28 17:21:01 +01001263 unsigned int hashlen,
1264 const unsigned char *hash,
Manuel Pégourié-Gonnardcc0a9d02013-08-12 11:34:35 +02001265 const unsigned char *sig )
Paul Bakkerb3869132013-02-28 17:21:01 +01001266{
1267 int ret;
Paul Bakkerc70b9822013-04-07 22:00:46 +02001268 size_t len, siglen, asn1_len;
1269 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001270 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
1271 mbedtls_md_type_t msg_md_alg;
1272 const mbedtls_md_info_t *md_info;
1273 mbedtls_asn1_buf oid;
Paul Bakkerb3869132013-02-28 17:21:01 +01001274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
1276 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +01001277
1278 siglen = ctx->len;
1279
1280 if( siglen < 16 || siglen > sizeof( buf ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001281 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
Paul Bakkerb3869132013-02-28 17:21:01 +01001282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283 ret = ( mode == MBEDTLS_RSA_PUBLIC )
1284 ? mbedtls_rsa_public( ctx, sig, buf )
1285 : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf );
Paul Bakkerb3869132013-02-28 17:21:01 +01001286
1287 if( ret != 0 )
1288 return( ret );
1289
1290 p = buf;
1291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292 if( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN )
1293 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakkerb3869132013-02-28 17:21:01 +01001294
1295 while( *p != 0 )
1296 {
1297 if( p >= buf + siglen - 1 || *p != 0xFF )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001298 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakkerb3869132013-02-28 17:21:01 +01001299 p++;
1300 }
1301 p++;
1302
1303 len = siglen - ( p - buf );
1304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001305 if( len == hashlen && md_alg == MBEDTLS_MD_NONE )
Paul Bakkerb3869132013-02-28 17:21:01 +01001306 {
1307 if( memcmp( p, hash, hashlen ) == 0 )
1308 return( 0 );
1309 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001311 }
1312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 md_info = mbedtls_md_info_from_type( md_alg );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001314 if( md_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
1316 hashlen = mbedtls_md_get_size( md_info );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001317
1318 end = p + len;
1319
1320 // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure
1321 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len,
1323 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1324 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001325
1326 if( asn1_len + 2 != len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len,
1330 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1331 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001332
1333 if( asn1_len + 6 + hashlen != len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
1337 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001338
1339 oid.p = p;
1340 p += oid.len;
1341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342 if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 )
1343 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001344
1345 if( md_alg != msg_md_alg )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001347
1348 /*
1349 * assume the algorithm parameters must be NULL
1350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 )
1352 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001354 if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
1355 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001356
1357 if( asn1_len != hashlen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001359
1360 if( memcmp( p, hash, hashlen ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001362
1363 p += hashlen;
1364
1365 if( p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Paul Bakkerc70b9822013-04-07 22:00:46 +02001367
1368 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001369}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370#endif /* MBEDTLS_PKCS1_V15 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001371
1372/*
Paul Bakkerb3869132013-02-28 17:21:01 +01001373 * Do an RSA operation and check the message digest
1374 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001375int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
Paul Bakker548957d2013-08-30 10:30:02 +02001376 int (*f_rng)(void *, unsigned char *, size_t),
1377 void *p_rng,
Paul Bakkerb3869132013-02-28 17:21:01 +01001378 int mode,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 mbedtls_md_type_t md_alg,
Paul Bakkerb3869132013-02-28 17:21:01 +01001380 unsigned int hashlen,
1381 const unsigned char *hash,
Manuel Pégourié-Gonnardcc0a9d02013-08-12 11:34:35 +02001382 const unsigned char *sig )
Paul Bakkerb3869132013-02-28 17:21:01 +01001383{
1384 switch( ctx->padding )
1385 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001386#if defined(MBEDTLS_PKCS1_V15)
1387 case MBEDTLS_RSA_PKCS_V15:
1388 return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg,
Paul Bakkerb3869132013-02-28 17:21:01 +01001389 hashlen, hash, sig );
Paul Bakker48377d92013-08-30 12:06:24 +02001390#endif
Paul Bakkerb3869132013-02-28 17:21:01 +01001391
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392#if defined(MBEDTLS_PKCS1_V21)
1393 case MBEDTLS_RSA_PKCS_V21:
1394 return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg,
Paul Bakkerb3869132013-02-28 17:21:01 +01001395 hashlen, hash, sig );
1396#endif
1397
1398 default:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
Paul Bakkerb3869132013-02-28 17:21:01 +01001400 }
1401}
1402
1403/*
Manuel Pégourié-Gonnard3053f5b2013-08-14 13:39:57 +02001404 * Copy the components of an RSA key
1405 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
Manuel Pégourié-Gonnard3053f5b2013-08-14 13:39:57 +02001407{
1408 int ret;
1409
1410 dst->ver = src->ver;
1411 dst->len = src->len;
1412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
1414 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) );
Manuel Pégourié-Gonnard3053f5b2013-08-14 13:39:57 +02001415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) );
1417 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) );
1418 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) );
1419 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) );
1420 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) );
1421 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) );
Manuel Pégourié-Gonnard3053f5b2013-08-14 13:39:57 +02001422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) );
1424 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) );
1425 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) );
Manuel Pégourié-Gonnard3053f5b2013-08-14 13:39:57 +02001426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001427 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) );
1428 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) );
Manuel Pégourié-Gonnardea53a552013-09-10 13:29:30 +02001429
Manuel Pégourié-Gonnard3053f5b2013-08-14 13:39:57 +02001430 dst->padding = src->padding;
Manuel Pégourié-Gonnardfdddac92014-03-25 15:58:35 +01001431 dst->hash_id = src->hash_id;
Manuel Pégourié-Gonnard3053f5b2013-08-14 13:39:57 +02001432
1433cleanup:
1434 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435 mbedtls_rsa_free( dst );
Manuel Pégourié-Gonnard3053f5b2013-08-14 13:39:57 +02001436
1437 return( ret );
1438}
1439
1440/*
Paul Bakker5121ce52009-01-03 21:22:43 +00001441 * Free the components of an RSA key
1442 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +00001444{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001445 mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf );
1446 mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN );
1447 mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP );
1448 mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D );
1449 mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N );
Paul Bakkerc9965dc2013-09-29 14:58:17 +02001450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001451#if defined(MBEDTLS_THREADING_C)
1452 mbedtls_mutex_free( &ctx->mutex );
Paul Bakkerc9965dc2013-09-29 14:58:17 +02001453#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001454}
1455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001457
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00001458#include "mbedtls/sha1.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00001459
1460/*
1461 * Example RSA-1024 keypair, for test purposes
1462 */
1463#define KEY_LEN 128
1464
1465#define RSA_N "9292758453063D803DD603D5E777D788" \
1466 "8ED1D5BF35786190FA2F23EBC0848AEA" \
1467 "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
1468 "7130B9CED7ACDF54CFC7555AC14EEBAB" \
1469 "93A89813FBF3C4F8066D2D800F7C38A8" \
1470 "1AE31942917403FF4946B0A83D3D3E05" \
1471 "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
1472 "5E94BB77B07507233A0BC7BAC8F90F79"
1473
1474#define RSA_E "10001"
1475
1476#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
1477 "66CA472BC44D253102F8B4A9D3BFA750" \
1478 "91386C0077937FE33FA3252D28855837" \
1479 "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
1480 "DF79C5CE07EE72C7F123142198164234" \
1481 "CABB724CF78B8173B9F880FC86322407" \
1482 "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
1483 "071513A1E85B5DFA031F21ECAE91A34D"
1484
1485#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
1486 "2C01CAD19EA484A87EA4377637E75500" \
1487 "FCB2005C5C7DD6EC4AC023CDA285D796" \
1488 "C3D9E75E1EFC42488BB4F1D13AC30A57"
1489
1490#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
1491 "E211C2B9E5DB1ED0BF61D0D9899620F4" \
1492 "910E4168387E3C30AA1E00C339A79508" \
1493 "8452DD96A9A5EA5D9DCA68DA636032AF"
1494
1495#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
1496 "3C94D22288ACD763FD8E5600ED4A702D" \
1497 "F84198A5F06C2E72236AE490C93F07F8" \
1498 "3CC559CD27BC2D1CA488811730BB5725"
1499
1500#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
1501 "D8AAEA56749EA28623272E4F7D0592AF" \
1502 "7C1F1313CAC9471B5C523BFE592F517B" \
1503 "407A1BD76C164B93DA2D32A383E58357"
1504
1505#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
1506 "F38D18D2B2F0E2DD275AA977E2BF4411" \
1507 "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
1508 "A74206CEC169D74BF5A8C50D6F48EA08"
1509
1510#define PT_LEN 24
1511#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
1512 "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
1513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514#if defined(MBEDTLS_PKCS1_V15)
Paul Bakkera3d195c2011-11-27 21:07:34 +00001515static int myrand( void *rng_state, unsigned char *output, size_t len )
Paul Bakker545570e2010-07-18 09:00:25 +00001516{
Paul Bakkerf96f7b62014-04-30 16:02:38 +02001517#if !defined(__OpenBSD__)
Paul Bakkera3d195c2011-11-27 21:07:34 +00001518 size_t i;
1519
Paul Bakker545570e2010-07-18 09:00:25 +00001520 if( rng_state != NULL )
1521 rng_state = NULL;
1522
Paul Bakkera3d195c2011-11-27 21:07:34 +00001523 for( i = 0; i < len; ++i )
1524 output[i] = rand();
Paul Bakkerf96f7b62014-04-30 16:02:38 +02001525#else
1526 if( rng_state != NULL )
1527 rng_state = NULL;
1528
1529 arc4random_buf( output, len );
1530#endif /* !OpenBSD */
Paul Bakker48377d92013-08-30 12:06:24 +02001531
Paul Bakkera3d195c2011-11-27 21:07:34 +00001532 return( 0 );
Paul Bakker545570e2010-07-18 09:00:25 +00001533}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001534#endif /* MBEDTLS_PKCS1_V15 */
Paul Bakker545570e2010-07-18 09:00:25 +00001535
Paul Bakker5121ce52009-01-03 21:22:43 +00001536/*
1537 * Checkup routine
1538 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539int mbedtls_rsa_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +00001540{
Paul Bakker3d8fb632014-04-17 12:42:41 +02001541 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542#if defined(MBEDTLS_PKCS1_V15)
Paul Bakker23986e52011-04-24 08:57:21 +00001543 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 mbedtls_rsa_context rsa;
Paul Bakker5121ce52009-01-03 21:22:43 +00001545 unsigned char rsa_plaintext[PT_LEN];
1546 unsigned char rsa_decrypted[PT_LEN];
1547 unsigned char rsa_ciphertext[KEY_LEN];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001548#if defined(MBEDTLS_SHA1_C)
Paul Bakker5690efc2011-05-26 13:16:06 +00001549 unsigned char sha1sum[20];
1550#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +00001553
1554 rsa.len = KEY_LEN;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) );
1556 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) );
1557 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) );
1558 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) );
1559 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) );
1560 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) );
1561 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001563
1564 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 mbedtls_printf( " RSA key validation: " );
Paul Bakker5121ce52009-01-03 21:22:43 +00001566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 if( mbedtls_rsa_check_pubkey( &rsa ) != 0 ||
1568 mbedtls_rsa_check_privkey( &rsa ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001569 {
1570 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001572
1573 return( 1 );
1574 }
1575
1576 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 mbedtls_printf( "passed\n PKCS#1 encryption : " );
Paul Bakker5121ce52009-01-03 21:22:43 +00001578
1579 memcpy( rsa_plaintext, RSA_PT, PT_LEN );
1580
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN,
Paul Bakker5121ce52009-01-03 21:22:43 +00001582 rsa_plaintext, rsa_ciphertext ) != 0 )
1583 {
1584 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001586
1587 return( 1 );
1588 }
1589
1590 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 mbedtls_printf( "passed\n PKCS#1 decryption : " );
Paul Bakker5121ce52009-01-03 21:22:43 +00001592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len,
Paul Bakker060c5682009-01-12 21:48:39 +00001594 rsa_ciphertext, rsa_decrypted,
Paul Bakker23986e52011-04-24 08:57:21 +00001595 sizeof(rsa_decrypted) ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001596 {
1597 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001598 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001599
1600 return( 1 );
1601 }
1602
1603 if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
1604 {
1605 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001607
1608 return( 1 );
1609 }
1610
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +02001611 if( verbose != 0 )
1612 mbedtls_printf( "passed\n" );
1613
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001614#if defined(MBEDTLS_SHA1_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001615 if( verbose != 0 )
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +02001616 mbedtls_printf( "PKCS#1 data sign : " );
Paul Bakker5121ce52009-01-03 21:22:43 +00001617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum );
Paul Bakker5121ce52009-01-03 21:22:43 +00001619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0,
Paul Bakker5121ce52009-01-03 21:22:43 +00001621 sha1sum, rsa_ciphertext ) != 0 )
1622 {
1623 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001625
1626 return( 1 );
1627 }
1628
1629 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 mbedtls_printf( "passed\n PKCS#1 sig. verify: " );
Paul Bakker5121ce52009-01-03 21:22:43 +00001631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0,
Paul Bakker5121ce52009-01-03 21:22:43 +00001633 sha1sum, rsa_ciphertext ) != 0 )
1634 {
1635 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 mbedtls_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001637
1638 return( 1 );
1639 }
1640
1641 if( verbose != 0 )
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +02001642 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001643#endif /* MBEDTLS_SHA1_C */
Paul Bakker5121ce52009-01-03 21:22:43 +00001644
Manuel Pégourié-Gonnardd1004f02015-08-07 10:46:54 +02001645 if( verbose != 0 )
1646 mbedtls_printf( "\n" );
1647
Paul Bakker3d8fb632014-04-17 12:42:41 +02001648cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 mbedtls_rsa_free( &rsa );
1650#else /* MBEDTLS_PKCS1_V15 */
Paul Bakker3e41fe82013-09-15 17:42:50 +02001651 ((void) verbose);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652#endif /* MBEDTLS_PKCS1_V15 */
Paul Bakker3d8fb632014-04-17 12:42:41 +02001653 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001654}
1655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001656#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00001657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658#endif /* MBEDTLS_RSA_C */