This is a fork due to permission issues

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of 6_songs-from-the-cloud by MakingMusicWorkshop

Committer:
maclobdell
Date:
Wed May 18 19:06:32 2016 +0000
Revision:
0:f7c60d3e7b8a
clean version

Who changed what in which revision?

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