RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /*
kevman 0:38ceb79fef03 2 * The RSA public-key cryptosystem
kevman 0:38ceb79fef03 3 *
kevman 0:38ceb79fef03 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
kevman 0:38ceb79fef03 5 * SPDX-License-Identifier: Apache-2.0
kevman 0:38ceb79fef03 6 *
kevman 0:38ceb79fef03 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kevman 0:38ceb79fef03 8 * not use this file except in compliance with the License.
kevman 0:38ceb79fef03 9 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 10 *
kevman 0:38ceb79fef03 11 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 12 *
kevman 0:38ceb79fef03 13 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kevman 0:38ceb79fef03 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 16 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 17 * limitations under the License.
kevman 0:38ceb79fef03 18 *
kevman 0:38ceb79fef03 19 * This file is part of mbed TLS (https://tls.mbed.org)
kevman 0:38ceb79fef03 20 */
kevman 0:38ceb79fef03 21
kevman 0:38ceb79fef03 22 /*
kevman 0:38ceb79fef03 23 * The following sources were referenced in the design of this implementation
kevman 0:38ceb79fef03 24 * of the RSA algorithm:
kevman 0:38ceb79fef03 25 *
kevman 0:38ceb79fef03 26 * [1] A method for obtaining digital signatures and public-key cryptosystems
kevman 0:38ceb79fef03 27 * R Rivest, A Shamir, and L Adleman
kevman 0:38ceb79fef03 28 * http://people.csail.mit.edu/rivest/pubs.html#RSA78
kevman 0:38ceb79fef03 29 *
kevman 0:38ceb79fef03 30 * [2] Handbook of Applied Cryptography - 1997, Chapter 8
kevman 0:38ceb79fef03 31 * Menezes, van Oorschot and Vanstone
kevman 0:38ceb79fef03 32 *
kevman 0:38ceb79fef03 33 * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks
kevman 0:38ceb79fef03 34 * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and
kevman 0:38ceb79fef03 35 * Stefan Mangard
kevman 0:38ceb79fef03 36 * https://arxiv.org/abs/1702.08719v2
kevman 0:38ceb79fef03 37 *
kevman 0:38ceb79fef03 38 */
kevman 0:38ceb79fef03 39
kevman 0:38ceb79fef03 40 #if !defined(MBEDTLS_CONFIG_FILE)
kevman 0:38ceb79fef03 41 #include "mbedtls/config.h"
kevman 0:38ceb79fef03 42 #else
kevman 0:38ceb79fef03 43 #include MBEDTLS_CONFIG_FILE
kevman 0:38ceb79fef03 44 #endif
kevman 0:38ceb79fef03 45
kevman 0:38ceb79fef03 46 #if defined(MBEDTLS_RSA_C)
kevman 0:38ceb79fef03 47
kevman 0:38ceb79fef03 48 #include "mbedtls/rsa.h"
kevman 0:38ceb79fef03 49 #include "mbedtls/rsa_internal.h"
kevman 0:38ceb79fef03 50 #include "mbedtls/oid.h"
kevman 0:38ceb79fef03 51 #include "mbedtls/platform_util.h"
kevman 0:38ceb79fef03 52
kevman 0:38ceb79fef03 53 #include <string.h>
kevman 0:38ceb79fef03 54
kevman 0:38ceb79fef03 55 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 56 #include "mbedtls/md.h"
kevman 0:38ceb79fef03 57 #endif
kevman 0:38ceb79fef03 58
kevman 0:38ceb79fef03 59 #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__)
kevman 0:38ceb79fef03 60 #include <stdlib.h>
kevman 0:38ceb79fef03 61 #endif
kevman 0:38ceb79fef03 62
kevman 0:38ceb79fef03 63 #if defined(MBEDTLS_PLATFORM_C)
kevman 0:38ceb79fef03 64 #include "mbedtls/platform.h"
kevman 0:38ceb79fef03 65 #else
kevman 0:38ceb79fef03 66 #include <stdio.h>
kevman 0:38ceb79fef03 67 #define mbedtls_printf printf
kevman 0:38ceb79fef03 68 #define mbedtls_calloc calloc
kevman 0:38ceb79fef03 69 #define mbedtls_free free
kevman 0:38ceb79fef03 70 #endif
kevman 0:38ceb79fef03 71
kevman 0:38ceb79fef03 72 #if !defined(MBEDTLS_RSA_ALT)
kevman 0:38ceb79fef03 73
kevman 0:38ceb79fef03 74 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 75 /* constant-time buffer comparison */
kevman 0:38ceb79fef03 76 static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
kevman 0:38ceb79fef03 77 {
kevman 0:38ceb79fef03 78 size_t i;
kevman 0:38ceb79fef03 79 const unsigned char *A = (const unsigned char *) a;
kevman 0:38ceb79fef03 80 const unsigned char *B = (const unsigned char *) b;
kevman 0:38ceb79fef03 81 unsigned char diff = 0;
kevman 0:38ceb79fef03 82
kevman 0:38ceb79fef03 83 for( i = 0; i < n; i++ )
kevman 0:38ceb79fef03 84 diff |= A[i] ^ B[i];
kevman 0:38ceb79fef03 85
kevman 0:38ceb79fef03 86 return( diff );
kevman 0:38ceb79fef03 87 }
kevman 0:38ceb79fef03 88 #endif /* MBEDTLS_PKCS1_V15 */
kevman 0:38ceb79fef03 89
kevman 0:38ceb79fef03 90 int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 91 const mbedtls_mpi *N,
kevman 0:38ceb79fef03 92 const mbedtls_mpi *P, const mbedtls_mpi *Q,
kevman 0:38ceb79fef03 93 const mbedtls_mpi *D, const mbedtls_mpi *E )
kevman 0:38ceb79fef03 94 {
kevman 0:38ceb79fef03 95 int ret;
kevman 0:38ceb79fef03 96
kevman 0:38ceb79fef03 97 if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) ||
kevman 0:38ceb79fef03 98 ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) ||
kevman 0:38ceb79fef03 99 ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) ||
kevman 0:38ceb79fef03 100 ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) ||
kevman 0:38ceb79fef03 101 ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) )
kevman 0:38ceb79fef03 102 {
kevman 0:38ceb79fef03 103 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
kevman 0:38ceb79fef03 104 }
kevman 0:38ceb79fef03 105
kevman 0:38ceb79fef03 106 if( N != NULL )
kevman 0:38ceb79fef03 107 ctx->len = mbedtls_mpi_size( &ctx->N );
kevman 0:38ceb79fef03 108
kevman 0:38ceb79fef03 109 return( 0 );
kevman 0:38ceb79fef03 110 }
kevman 0:38ceb79fef03 111
kevman 0:38ceb79fef03 112 int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 113 unsigned char const *N, size_t N_len,
kevman 0:38ceb79fef03 114 unsigned char const *P, size_t P_len,
kevman 0:38ceb79fef03 115 unsigned char const *Q, size_t Q_len,
kevman 0:38ceb79fef03 116 unsigned char const *D, size_t D_len,
kevman 0:38ceb79fef03 117 unsigned char const *E, size_t E_len )
kevman 0:38ceb79fef03 118 {
kevman 0:38ceb79fef03 119 int ret = 0;
kevman 0:38ceb79fef03 120
kevman 0:38ceb79fef03 121 if( N != NULL )
kevman 0:38ceb79fef03 122 {
kevman 0:38ceb79fef03 123 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) );
kevman 0:38ceb79fef03 124 ctx->len = mbedtls_mpi_size( &ctx->N );
kevman 0:38ceb79fef03 125 }
kevman 0:38ceb79fef03 126
kevman 0:38ceb79fef03 127 if( P != NULL )
kevman 0:38ceb79fef03 128 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) );
kevman 0:38ceb79fef03 129
kevman 0:38ceb79fef03 130 if( Q != NULL )
kevman 0:38ceb79fef03 131 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) );
kevman 0:38ceb79fef03 132
kevman 0:38ceb79fef03 133 if( D != NULL )
kevman 0:38ceb79fef03 134 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) );
kevman 0:38ceb79fef03 135
kevman 0:38ceb79fef03 136 if( E != NULL )
kevman 0:38ceb79fef03 137 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) );
kevman 0:38ceb79fef03 138
kevman 0:38ceb79fef03 139 cleanup:
kevman 0:38ceb79fef03 140
kevman 0:38ceb79fef03 141 if( ret != 0 )
kevman 0:38ceb79fef03 142 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
kevman 0:38ceb79fef03 143
kevman 0:38ceb79fef03 144 return( 0 );
kevman 0:38ceb79fef03 145 }
kevman 0:38ceb79fef03 146
kevman 0:38ceb79fef03 147 /*
kevman 0:38ceb79fef03 148 * Checks whether the context fields are set in such a way
kevman 0:38ceb79fef03 149 * that the RSA primitives will be able to execute without error.
kevman 0:38ceb79fef03 150 * It does *not* make guarantees for consistency of the parameters.
kevman 0:38ceb79fef03 151 */
kevman 0:38ceb79fef03 152 static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv,
kevman 0:38ceb79fef03 153 int blinding_needed )
kevman 0:38ceb79fef03 154 {
kevman 0:38ceb79fef03 155 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 156 /* blinding_needed is only used for NO_CRT to decide whether
kevman 0:38ceb79fef03 157 * P,Q need to be present or not. */
kevman 0:38ceb79fef03 158 ((void) blinding_needed);
kevman 0:38ceb79fef03 159 #endif
kevman 0:38ceb79fef03 160
kevman 0:38ceb79fef03 161 if( ctx->len != mbedtls_mpi_size( &ctx->N ) ||
kevman 0:38ceb79fef03 162 ctx->len > MBEDTLS_MPI_MAX_SIZE )
kevman 0:38ceb79fef03 163 {
kevman 0:38ceb79fef03 164 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 165 }
kevman 0:38ceb79fef03 166
kevman 0:38ceb79fef03 167 /*
kevman 0:38ceb79fef03 168 * 1. Modular exponentiation needs positive, odd moduli.
kevman 0:38ceb79fef03 169 */
kevman 0:38ceb79fef03 170
kevman 0:38ceb79fef03 171 /* Modular exponentiation wrt. N is always used for
kevman 0:38ceb79fef03 172 * RSA public key operations. */
kevman 0:38ceb79fef03 173 if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 ||
kevman 0:38ceb79fef03 174 mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 )
kevman 0:38ceb79fef03 175 {
kevman 0:38ceb79fef03 176 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 177 }
kevman 0:38ceb79fef03 178
kevman 0:38ceb79fef03 179 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 180 /* Modular exponentiation for P and Q is only
kevman 0:38ceb79fef03 181 * used for private key operations and if CRT
kevman 0:38ceb79fef03 182 * is used. */
kevman 0:38ceb79fef03 183 if( is_priv &&
kevman 0:38ceb79fef03 184 ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
kevman 0:38ceb79fef03 185 mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 ||
kevman 0:38ceb79fef03 186 mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ||
kevman 0:38ceb79fef03 187 mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) )
kevman 0:38ceb79fef03 188 {
kevman 0:38ceb79fef03 189 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 190 }
kevman 0:38ceb79fef03 191 #endif /* !MBEDTLS_RSA_NO_CRT */
kevman 0:38ceb79fef03 192
kevman 0:38ceb79fef03 193 /*
kevman 0:38ceb79fef03 194 * 2. Exponents must be positive
kevman 0:38ceb79fef03 195 */
kevman 0:38ceb79fef03 196
kevman 0:38ceb79fef03 197 /* Always need E for public key operations */
kevman 0:38ceb79fef03 198 if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 )
kevman 0:38ceb79fef03 199 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 200
kevman 0:38ceb79fef03 201 #if defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 202 /* For private key operations, use D or DP & DQ
kevman 0:38ceb79fef03 203 * as (unblinded) exponents. */
kevman 0:38ceb79fef03 204 if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 )
kevman 0:38ceb79fef03 205 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 206 #else
kevman 0:38ceb79fef03 207 if( is_priv &&
kevman 0:38ceb79fef03 208 ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 ||
kevman 0:38ceb79fef03 209 mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) )
kevman 0:38ceb79fef03 210 {
kevman 0:38ceb79fef03 211 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 212 }
kevman 0:38ceb79fef03 213 #endif /* MBEDTLS_RSA_NO_CRT */
kevman 0:38ceb79fef03 214
kevman 0:38ceb79fef03 215 /* Blinding shouldn't make exponents negative either,
kevman 0:38ceb79fef03 216 * so check that P, Q >= 1 if that hasn't yet been
kevman 0:38ceb79fef03 217 * done as part of 1. */
kevman 0:38ceb79fef03 218 #if defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 219 if( is_priv && blinding_needed &&
kevman 0:38ceb79fef03 220 ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
kevman 0:38ceb79fef03 221 mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) )
kevman 0:38ceb79fef03 222 {
kevman 0:38ceb79fef03 223 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 224 }
kevman 0:38ceb79fef03 225 #endif
kevman 0:38ceb79fef03 226
kevman 0:38ceb79fef03 227 /* It wouldn't lead to an error if it wasn't satisfied,
kevman 0:38ceb79fef03 228 * but check for QP >= 1 nonetheless. */
kevman 0:38ceb79fef03 229 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 230 if( is_priv &&
kevman 0:38ceb79fef03 231 mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 )
kevman 0:38ceb79fef03 232 {
kevman 0:38ceb79fef03 233 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 234 }
kevman 0:38ceb79fef03 235 #endif
kevman 0:38ceb79fef03 236
kevman 0:38ceb79fef03 237 return( 0 );
kevman 0:38ceb79fef03 238 }
kevman 0:38ceb79fef03 239
kevman 0:38ceb79fef03 240 int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
kevman 0:38ceb79fef03 241 {
kevman 0:38ceb79fef03 242 int ret = 0;
kevman 0:38ceb79fef03 243
kevman 0:38ceb79fef03 244 const int have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 );
kevman 0:38ceb79fef03 245 const int have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 );
kevman 0:38ceb79fef03 246 const int have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 );
kevman 0:38ceb79fef03 247 const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
kevman 0:38ceb79fef03 248 const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
kevman 0:38ceb79fef03 249
kevman 0:38ceb79fef03 250 /*
kevman 0:38ceb79fef03 251 * Check whether provided parameters are enough
kevman 0:38ceb79fef03 252 * to deduce all others. The following incomplete
kevman 0:38ceb79fef03 253 * parameter sets for private keys are supported:
kevman 0:38ceb79fef03 254 *
kevman 0:38ceb79fef03 255 * (1) P, Q missing.
kevman 0:38ceb79fef03 256 * (2) D and potentially N missing.
kevman 0:38ceb79fef03 257 *
kevman 0:38ceb79fef03 258 */
kevman 0:38ceb79fef03 259
kevman 0:38ceb79fef03 260 const int n_missing = have_P && have_Q && have_D && have_E;
kevman 0:38ceb79fef03 261 const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E;
kevman 0:38ceb79fef03 262 const int d_missing = have_P && have_Q && !have_D && have_E;
kevman 0:38ceb79fef03 263 const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E;
kevman 0:38ceb79fef03 264
kevman 0:38ceb79fef03 265 /* These three alternatives are mutually exclusive */
kevman 0:38ceb79fef03 266 const int is_priv = n_missing || pq_missing || d_missing;
kevman 0:38ceb79fef03 267
kevman 0:38ceb79fef03 268 if( !is_priv && !is_pub )
kevman 0:38ceb79fef03 269 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 270
kevman 0:38ceb79fef03 271 /*
kevman 0:38ceb79fef03 272 * Step 1: Deduce N if P, Q are provided.
kevman 0:38ceb79fef03 273 */
kevman 0:38ceb79fef03 274
kevman 0:38ceb79fef03 275 if( !have_N && have_P && have_Q )
kevman 0:38ceb79fef03 276 {
kevman 0:38ceb79fef03 277 if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P,
kevman 0:38ceb79fef03 278 &ctx->Q ) ) != 0 )
kevman 0:38ceb79fef03 279 {
kevman 0:38ceb79fef03 280 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
kevman 0:38ceb79fef03 281 }
kevman 0:38ceb79fef03 282
kevman 0:38ceb79fef03 283 ctx->len = mbedtls_mpi_size( &ctx->N );
kevman 0:38ceb79fef03 284 }
kevman 0:38ceb79fef03 285
kevman 0:38ceb79fef03 286 /*
kevman 0:38ceb79fef03 287 * Step 2: Deduce and verify all remaining core parameters.
kevman 0:38ceb79fef03 288 */
kevman 0:38ceb79fef03 289
kevman 0:38ceb79fef03 290 if( pq_missing )
kevman 0:38ceb79fef03 291 {
kevman 0:38ceb79fef03 292 ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D,
kevman 0:38ceb79fef03 293 &ctx->P, &ctx->Q );
kevman 0:38ceb79fef03 294 if( ret != 0 )
kevman 0:38ceb79fef03 295 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
kevman 0:38ceb79fef03 296
kevman 0:38ceb79fef03 297 }
kevman 0:38ceb79fef03 298 else if( d_missing )
kevman 0:38ceb79fef03 299 {
kevman 0:38ceb79fef03 300 if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P,
kevman 0:38ceb79fef03 301 &ctx->Q,
kevman 0:38ceb79fef03 302 &ctx->E,
kevman 0:38ceb79fef03 303 &ctx->D ) ) != 0 )
kevman 0:38ceb79fef03 304 {
kevman 0:38ceb79fef03 305 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
kevman 0:38ceb79fef03 306 }
kevman 0:38ceb79fef03 307 }
kevman 0:38ceb79fef03 308
kevman 0:38ceb79fef03 309 /*
kevman 0:38ceb79fef03 310 * Step 3: Deduce all additional parameters specific
kevman 0:38ceb79fef03 311 * to our current RSA implementation.
kevman 0:38ceb79fef03 312 */
kevman 0:38ceb79fef03 313
kevman 0:38ceb79fef03 314 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 315 if( is_priv )
kevman 0:38ceb79fef03 316 {
kevman 0:38ceb79fef03 317 ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
kevman 0:38ceb79fef03 318 &ctx->DP, &ctx->DQ, &ctx->QP );
kevman 0:38ceb79fef03 319 if( ret != 0 )
kevman 0:38ceb79fef03 320 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
kevman 0:38ceb79fef03 321 }
kevman 0:38ceb79fef03 322 #endif /* MBEDTLS_RSA_NO_CRT */
kevman 0:38ceb79fef03 323
kevman 0:38ceb79fef03 324 /*
kevman 0:38ceb79fef03 325 * Step 3: Basic sanity checks
kevman 0:38ceb79fef03 326 */
kevman 0:38ceb79fef03 327
kevman 0:38ceb79fef03 328 return( rsa_check_context( ctx, is_priv, 1 ) );
kevman 0:38ceb79fef03 329 }
kevman 0:38ceb79fef03 330
kevman 0:38ceb79fef03 331 int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 332 unsigned char *N, size_t N_len,
kevman 0:38ceb79fef03 333 unsigned char *P, size_t P_len,
kevman 0:38ceb79fef03 334 unsigned char *Q, size_t Q_len,
kevman 0:38ceb79fef03 335 unsigned char *D, size_t D_len,
kevman 0:38ceb79fef03 336 unsigned char *E, size_t E_len )
kevman 0:38ceb79fef03 337 {
kevman 0:38ceb79fef03 338 int ret = 0;
kevman 0:38ceb79fef03 339
kevman 0:38ceb79fef03 340 /* Check if key is private or public */
kevman 0:38ceb79fef03 341 const int is_priv =
kevman 0:38ceb79fef03 342 mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
kevman 0:38ceb79fef03 343 mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
kevman 0:38ceb79fef03 344 mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
kevman 0:38ceb79fef03 345 mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
kevman 0:38ceb79fef03 346 mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
kevman 0:38ceb79fef03 347
kevman 0:38ceb79fef03 348 if( !is_priv )
kevman 0:38ceb79fef03 349 {
kevman 0:38ceb79fef03 350 /* If we're trying to export private parameters for a public key,
kevman 0:38ceb79fef03 351 * something must be wrong. */
kevman 0:38ceb79fef03 352 if( P != NULL || Q != NULL || D != NULL )
kevman 0:38ceb79fef03 353 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 354
kevman 0:38ceb79fef03 355 }
kevman 0:38ceb79fef03 356
kevman 0:38ceb79fef03 357 if( N != NULL )
kevman 0:38ceb79fef03 358 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) );
kevman 0:38ceb79fef03 359
kevman 0:38ceb79fef03 360 if( P != NULL )
kevman 0:38ceb79fef03 361 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) );
kevman 0:38ceb79fef03 362
kevman 0:38ceb79fef03 363 if( Q != NULL )
kevman 0:38ceb79fef03 364 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) );
kevman 0:38ceb79fef03 365
kevman 0:38ceb79fef03 366 if( D != NULL )
kevman 0:38ceb79fef03 367 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) );
kevman 0:38ceb79fef03 368
kevman 0:38ceb79fef03 369 if( E != NULL )
kevman 0:38ceb79fef03 370 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) );
kevman 0:38ceb79fef03 371
kevman 0:38ceb79fef03 372 cleanup:
kevman 0:38ceb79fef03 373
kevman 0:38ceb79fef03 374 return( ret );
kevman 0:38ceb79fef03 375 }
kevman 0:38ceb79fef03 376
kevman 0:38ceb79fef03 377 int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 378 mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,
kevman 0:38ceb79fef03 379 mbedtls_mpi *D, mbedtls_mpi *E )
kevman 0:38ceb79fef03 380 {
kevman 0:38ceb79fef03 381 int ret;
kevman 0:38ceb79fef03 382
kevman 0:38ceb79fef03 383 /* Check if key is private or public */
kevman 0:38ceb79fef03 384 int is_priv =
kevman 0:38ceb79fef03 385 mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
kevman 0:38ceb79fef03 386 mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
kevman 0:38ceb79fef03 387 mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
kevman 0:38ceb79fef03 388 mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
kevman 0:38ceb79fef03 389 mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
kevman 0:38ceb79fef03 390
kevman 0:38ceb79fef03 391 if( !is_priv )
kevman 0:38ceb79fef03 392 {
kevman 0:38ceb79fef03 393 /* If we're trying to export private parameters for a public key,
kevman 0:38ceb79fef03 394 * something must be wrong. */
kevman 0:38ceb79fef03 395 if( P != NULL || Q != NULL || D != NULL )
kevman 0:38ceb79fef03 396 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 397
kevman 0:38ceb79fef03 398 }
kevman 0:38ceb79fef03 399
kevman 0:38ceb79fef03 400 /* Export all requested core parameters. */
kevman 0:38ceb79fef03 401
kevman 0:38ceb79fef03 402 if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) ||
kevman 0:38ceb79fef03 403 ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) ||
kevman 0:38ceb79fef03 404 ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) ||
kevman 0:38ceb79fef03 405 ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) ||
kevman 0:38ceb79fef03 406 ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) )
kevman 0:38ceb79fef03 407 {
kevman 0:38ceb79fef03 408 return( ret );
kevman 0:38ceb79fef03 409 }
kevman 0:38ceb79fef03 410
kevman 0:38ceb79fef03 411 return( 0 );
kevman 0:38ceb79fef03 412 }
kevman 0:38ceb79fef03 413
kevman 0:38ceb79fef03 414 /*
kevman 0:38ceb79fef03 415 * Export CRT parameters
kevman 0:38ceb79fef03 416 * This must also be implemented if CRT is not used, for being able to
kevman 0:38ceb79fef03 417 * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt
kevman 0:38ceb79fef03 418 * can be used in this case.
kevman 0:38ceb79fef03 419 */
kevman 0:38ceb79fef03 420 int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 421 mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
kevman 0:38ceb79fef03 422 {
kevman 0:38ceb79fef03 423 int ret;
kevman 0:38ceb79fef03 424
kevman 0:38ceb79fef03 425 /* Check if key is private or public */
kevman 0:38ceb79fef03 426 int is_priv =
kevman 0:38ceb79fef03 427 mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
kevman 0:38ceb79fef03 428 mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
kevman 0:38ceb79fef03 429 mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
kevman 0:38ceb79fef03 430 mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
kevman 0:38ceb79fef03 431 mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
kevman 0:38ceb79fef03 432
kevman 0:38ceb79fef03 433 if( !is_priv )
kevman 0:38ceb79fef03 434 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 435
kevman 0:38ceb79fef03 436 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 437 /* Export all requested blinding parameters. */
kevman 0:38ceb79fef03 438 if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) ||
kevman 0:38ceb79fef03 439 ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) ||
kevman 0:38ceb79fef03 440 ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) )
kevman 0:38ceb79fef03 441 {
kevman 0:38ceb79fef03 442 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
kevman 0:38ceb79fef03 443 }
kevman 0:38ceb79fef03 444 #else
kevman 0:38ceb79fef03 445 if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
kevman 0:38ceb79fef03 446 DP, DQ, QP ) ) != 0 )
kevman 0:38ceb79fef03 447 {
kevman 0:38ceb79fef03 448 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
kevman 0:38ceb79fef03 449 }
kevman 0:38ceb79fef03 450 #endif
kevman 0:38ceb79fef03 451
kevman 0:38ceb79fef03 452 return( 0 );
kevman 0:38ceb79fef03 453 }
kevman 0:38ceb79fef03 454
kevman 0:38ceb79fef03 455 /*
kevman 0:38ceb79fef03 456 * Initialize an RSA context
kevman 0:38ceb79fef03 457 */
kevman 0:38ceb79fef03 458 void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 459 int padding,
kevman 0:38ceb79fef03 460 int hash_id )
kevman 0:38ceb79fef03 461 {
kevman 0:38ceb79fef03 462 memset( ctx, 0, sizeof( mbedtls_rsa_context ) );
kevman 0:38ceb79fef03 463
kevman 0:38ceb79fef03 464 mbedtls_rsa_set_padding( ctx, padding, hash_id );
kevman 0:38ceb79fef03 465
kevman 0:38ceb79fef03 466 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 467 mbedtls_mutex_init( &ctx->mutex );
kevman 0:38ceb79fef03 468 #endif
kevman 0:38ceb79fef03 469 }
kevman 0:38ceb79fef03 470
kevman 0:38ceb79fef03 471 /*
kevman 0:38ceb79fef03 472 * Set padding for an existing RSA context
kevman 0:38ceb79fef03 473 */
kevman 0:38ceb79fef03 474 void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id )
kevman 0:38ceb79fef03 475 {
kevman 0:38ceb79fef03 476 ctx->padding = padding;
kevman 0:38ceb79fef03 477 ctx->hash_id = hash_id;
kevman 0:38ceb79fef03 478 }
kevman 0:38ceb79fef03 479
kevman 0:38ceb79fef03 480 /*
kevman 0:38ceb79fef03 481 * Get length in bytes of RSA modulus
kevman 0:38ceb79fef03 482 */
kevman 0:38ceb79fef03 483
kevman 0:38ceb79fef03 484 size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx )
kevman 0:38ceb79fef03 485 {
kevman 0:38ceb79fef03 486 return( ctx->len );
kevman 0:38ceb79fef03 487 }
kevman 0:38ceb79fef03 488
kevman 0:38ceb79fef03 489
kevman 0:38ceb79fef03 490 #if defined(MBEDTLS_GENPRIME)
kevman 0:38ceb79fef03 491
kevman 0:38ceb79fef03 492 /*
kevman 0:38ceb79fef03 493 * Generate an RSA keypair
kevman 0:38ceb79fef03 494 *
kevman 0:38ceb79fef03 495 * This generation method follows the RSA key pair generation procedure of
kevman 0:38ceb79fef03 496 * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072.
kevman 0:38ceb79fef03 497 */
kevman 0:38ceb79fef03 498 int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 499 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 500 void *p_rng,
kevman 0:38ceb79fef03 501 unsigned int nbits, int exponent )
kevman 0:38ceb79fef03 502 {
kevman 0:38ceb79fef03 503 int ret;
kevman 0:38ceb79fef03 504 mbedtls_mpi H, G, L;
kevman 0:38ceb79fef03 505
kevman 0:38ceb79fef03 506 if( f_rng == NULL || nbits < 128 || exponent < 3 )
kevman 0:38ceb79fef03 507 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 508
kevman 0:38ceb79fef03 509 if( nbits % 2 )
kevman 0:38ceb79fef03 510 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 511
kevman 0:38ceb79fef03 512 mbedtls_mpi_init( &H );
kevman 0:38ceb79fef03 513 mbedtls_mpi_init( &G );
kevman 0:38ceb79fef03 514 mbedtls_mpi_init( &L );
kevman 0:38ceb79fef03 515
kevman 0:38ceb79fef03 516 /*
kevman 0:38ceb79fef03 517 * find primes P and Q with Q < P so that:
kevman 0:38ceb79fef03 518 * 1. |P-Q| > 2^( nbits / 2 - 100 )
kevman 0:38ceb79fef03 519 * 2. GCD( E, (P-1)*(Q-1) ) == 1
kevman 0:38ceb79fef03 520 * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 )
kevman 0:38ceb79fef03 521 */
kevman 0:38ceb79fef03 522 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) );
kevman 0:38ceb79fef03 523
kevman 0:38ceb79fef03 524 do
kevman 0:38ceb79fef03 525 {
kevman 0:38ceb79fef03 526 MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0,
kevman 0:38ceb79fef03 527 f_rng, p_rng ) );
kevman 0:38ceb79fef03 528
kevman 0:38ceb79fef03 529 MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0,
kevman 0:38ceb79fef03 530 f_rng, p_rng ) );
kevman 0:38ceb79fef03 531
kevman 0:38ceb79fef03 532 /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */
kevman 0:38ceb79fef03 533 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) );
kevman 0:38ceb79fef03 534 if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) )
kevman 0:38ceb79fef03 535 continue;
kevman 0:38ceb79fef03 536
kevman 0:38ceb79fef03 537 /* not required by any standards, but some users rely on the fact that P > Q */
kevman 0:38ceb79fef03 538 if( H.s < 0 )
kevman 0:38ceb79fef03 539 mbedtls_mpi_swap( &ctx->P, &ctx->Q );
kevman 0:38ceb79fef03 540
kevman 0:38ceb79fef03 541 /* Temporarily replace P,Q by P-1, Q-1 */
kevman 0:38ceb79fef03 542 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) );
kevman 0:38ceb79fef03 543 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) );
kevman 0:38ceb79fef03 544 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) );
kevman 0:38ceb79fef03 545
kevman 0:38ceb79fef03 546 /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */
kevman 0:38ceb79fef03 547 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) );
kevman 0:38ceb79fef03 548 if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
kevman 0:38ceb79fef03 549 continue;
kevman 0:38ceb79fef03 550
kevman 0:38ceb79fef03 551 /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */
kevman 0:38ceb79fef03 552 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) );
kevman 0:38ceb79fef03 553 MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) );
kevman 0:38ceb79fef03 554 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) );
kevman 0:38ceb79fef03 555
kevman 0:38ceb79fef03 556 if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a))
kevman 0:38ceb79fef03 557 continue;
kevman 0:38ceb79fef03 558
kevman 0:38ceb79fef03 559 break;
kevman 0:38ceb79fef03 560 }
kevman 0:38ceb79fef03 561 while( 1 );
kevman 0:38ceb79fef03 562
kevman 0:38ceb79fef03 563 /* Restore P,Q */
kevman 0:38ceb79fef03 564 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) );
kevman 0:38ceb79fef03 565 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) );
kevman 0:38ceb79fef03 566
kevman 0:38ceb79fef03 567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
kevman 0:38ceb79fef03 568
kevman 0:38ceb79fef03 569 ctx->len = mbedtls_mpi_size( &ctx->N );
kevman 0:38ceb79fef03 570
kevman 0:38ceb79fef03 571 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 572 /*
kevman 0:38ceb79fef03 573 * DP = D mod (P - 1)
kevman 0:38ceb79fef03 574 * DQ = D mod (Q - 1)
kevman 0:38ceb79fef03 575 * QP = Q^-1 mod P
kevman 0:38ceb79fef03 576 */
kevman 0:38ceb79fef03 577 MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
kevman 0:38ceb79fef03 578 &ctx->DP, &ctx->DQ, &ctx->QP ) );
kevman 0:38ceb79fef03 579 #endif /* MBEDTLS_RSA_NO_CRT */
kevman 0:38ceb79fef03 580
kevman 0:38ceb79fef03 581 /* Double-check */
kevman 0:38ceb79fef03 582 MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) );
kevman 0:38ceb79fef03 583
kevman 0:38ceb79fef03 584 cleanup:
kevman 0:38ceb79fef03 585
kevman 0:38ceb79fef03 586 mbedtls_mpi_free( &H );
kevman 0:38ceb79fef03 587 mbedtls_mpi_free( &G );
kevman 0:38ceb79fef03 588 mbedtls_mpi_free( &L );
kevman 0:38ceb79fef03 589
kevman 0:38ceb79fef03 590 if( ret != 0 )
kevman 0:38ceb79fef03 591 {
kevman 0:38ceb79fef03 592 mbedtls_rsa_free( ctx );
kevman 0:38ceb79fef03 593 return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret );
kevman 0:38ceb79fef03 594 }
kevman 0:38ceb79fef03 595
kevman 0:38ceb79fef03 596 return( 0 );
kevman 0:38ceb79fef03 597 }
kevman 0:38ceb79fef03 598
kevman 0:38ceb79fef03 599 #endif /* MBEDTLS_GENPRIME */
kevman 0:38ceb79fef03 600
kevman 0:38ceb79fef03 601 /*
kevman 0:38ceb79fef03 602 * Check a public RSA key
kevman 0:38ceb79fef03 603 */
kevman 0:38ceb79fef03 604 int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
kevman 0:38ceb79fef03 605 {
kevman 0:38ceb79fef03 606 if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 )
kevman 0:38ceb79fef03 607 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
kevman 0:38ceb79fef03 608
kevman 0:38ceb79fef03 609 if( mbedtls_mpi_bitlen( &ctx->N ) < 128 )
kevman 0:38ceb79fef03 610 {
kevman 0:38ceb79fef03 611 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
kevman 0:38ceb79fef03 612 }
kevman 0:38ceb79fef03 613
kevman 0:38ceb79fef03 614 if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 ||
kevman 0:38ceb79fef03 615 mbedtls_mpi_bitlen( &ctx->E ) < 2 ||
kevman 0:38ceb79fef03 616 mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 )
kevman 0:38ceb79fef03 617 {
kevman 0:38ceb79fef03 618 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
kevman 0:38ceb79fef03 619 }
kevman 0:38ceb79fef03 620
kevman 0:38ceb79fef03 621 return( 0 );
kevman 0:38ceb79fef03 622 }
kevman 0:38ceb79fef03 623
kevman 0:38ceb79fef03 624 /*
kevman 0:38ceb79fef03 625 * Check for the consistency of all fields in an RSA private key context
kevman 0:38ceb79fef03 626 */
kevman 0:38ceb79fef03 627 int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
kevman 0:38ceb79fef03 628 {
kevman 0:38ceb79fef03 629 if( mbedtls_rsa_check_pubkey( ctx ) != 0 ||
kevman 0:38ceb79fef03 630 rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 )
kevman 0:38ceb79fef03 631 {
kevman 0:38ceb79fef03 632 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
kevman 0:38ceb79fef03 633 }
kevman 0:38ceb79fef03 634
kevman 0:38ceb79fef03 635 if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q,
kevman 0:38ceb79fef03 636 &ctx->D, &ctx->E, NULL, NULL ) != 0 )
kevman 0:38ceb79fef03 637 {
kevman 0:38ceb79fef03 638 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
kevman 0:38ceb79fef03 639 }
kevman 0:38ceb79fef03 640
kevman 0:38ceb79fef03 641 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 642 else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D,
kevman 0:38ceb79fef03 643 &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 )
kevman 0:38ceb79fef03 644 {
kevman 0:38ceb79fef03 645 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
kevman 0:38ceb79fef03 646 }
kevman 0:38ceb79fef03 647 #endif
kevman 0:38ceb79fef03 648
kevman 0:38ceb79fef03 649 return( 0 );
kevman 0:38ceb79fef03 650 }
kevman 0:38ceb79fef03 651
kevman 0:38ceb79fef03 652 /*
kevman 0:38ceb79fef03 653 * Check if contexts holding a public and private key match
kevman 0:38ceb79fef03 654 */
kevman 0:38ceb79fef03 655 int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub,
kevman 0:38ceb79fef03 656 const mbedtls_rsa_context *prv )
kevman 0:38ceb79fef03 657 {
kevman 0:38ceb79fef03 658 if( mbedtls_rsa_check_pubkey( pub ) != 0 ||
kevman 0:38ceb79fef03 659 mbedtls_rsa_check_privkey( prv ) != 0 )
kevman 0:38ceb79fef03 660 {
kevman 0:38ceb79fef03 661 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
kevman 0:38ceb79fef03 662 }
kevman 0:38ceb79fef03 663
kevman 0:38ceb79fef03 664 if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 ||
kevman 0:38ceb79fef03 665 mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 )
kevman 0:38ceb79fef03 666 {
kevman 0:38ceb79fef03 667 return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
kevman 0:38ceb79fef03 668 }
kevman 0:38ceb79fef03 669
kevman 0:38ceb79fef03 670 return( 0 );
kevman 0:38ceb79fef03 671 }
kevman 0:38ceb79fef03 672
kevman 0:38ceb79fef03 673 /*
kevman 0:38ceb79fef03 674 * Do an RSA public key operation
kevman 0:38ceb79fef03 675 */
kevman 0:38ceb79fef03 676 int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 677 const unsigned char *input,
kevman 0:38ceb79fef03 678 unsigned char *output )
kevman 0:38ceb79fef03 679 {
kevman 0:38ceb79fef03 680 int ret;
kevman 0:38ceb79fef03 681 size_t olen;
kevman 0:38ceb79fef03 682 mbedtls_mpi T;
kevman 0:38ceb79fef03 683
kevman 0:38ceb79fef03 684 if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) )
kevman 0:38ceb79fef03 685 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 686
kevman 0:38ceb79fef03 687 mbedtls_mpi_init( &T );
kevman 0:38ceb79fef03 688
kevman 0:38ceb79fef03 689 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 690 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
kevman 0:38ceb79fef03 691 return( ret );
kevman 0:38ceb79fef03 692 #endif
kevman 0:38ceb79fef03 693
kevman 0:38ceb79fef03 694 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
kevman 0:38ceb79fef03 695
kevman 0:38ceb79fef03 696 if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
kevman 0:38ceb79fef03 697 {
kevman 0:38ceb79fef03 698 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
kevman 0:38ceb79fef03 699 goto cleanup;
kevman 0:38ceb79fef03 700 }
kevman 0:38ceb79fef03 701
kevman 0:38ceb79fef03 702 olen = ctx->len;
kevman 0:38ceb79fef03 703 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
kevman 0:38ceb79fef03 704 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
kevman 0:38ceb79fef03 705
kevman 0:38ceb79fef03 706 cleanup:
kevman 0:38ceb79fef03 707 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 708 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
kevman 0:38ceb79fef03 709 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
kevman 0:38ceb79fef03 710 #endif
kevman 0:38ceb79fef03 711
kevman 0:38ceb79fef03 712 mbedtls_mpi_free( &T );
kevman 0:38ceb79fef03 713
kevman 0:38ceb79fef03 714 if( ret != 0 )
kevman 0:38ceb79fef03 715 return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret );
kevman 0:38ceb79fef03 716
kevman 0:38ceb79fef03 717 return( 0 );
kevman 0:38ceb79fef03 718 }
kevman 0:38ceb79fef03 719
kevman 0:38ceb79fef03 720 /*
kevman 0:38ceb79fef03 721 * Generate or update blinding values, see section 10 of:
kevman 0:38ceb79fef03 722 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
kevman 0:38ceb79fef03 723 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
kevman 0:38ceb79fef03 724 * Berlin Heidelberg, 1996. p. 104-113.
kevman 0:38ceb79fef03 725 */
kevman 0:38ceb79fef03 726 static int rsa_prepare_blinding( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 727 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
kevman 0:38ceb79fef03 728 {
kevman 0:38ceb79fef03 729 int ret, count = 0;
kevman 0:38ceb79fef03 730
kevman 0:38ceb79fef03 731 if( ctx->Vf.p != NULL )
kevman 0:38ceb79fef03 732 {
kevman 0:38ceb79fef03 733 /* We already have blinding values, just update them by squaring */
kevman 0:38ceb79fef03 734 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
kevman 0:38ceb79fef03 735 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
kevman 0:38ceb79fef03 736 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
kevman 0:38ceb79fef03 737 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) );
kevman 0:38ceb79fef03 738
kevman 0:38ceb79fef03 739 goto cleanup;
kevman 0:38ceb79fef03 740 }
kevman 0:38ceb79fef03 741
kevman 0:38ceb79fef03 742 /* Unblinding value: Vf = random number, invertible mod N */
kevman 0:38ceb79fef03 743 do {
kevman 0:38ceb79fef03 744 if( count++ > 10 )
kevman 0:38ceb79fef03 745 return( MBEDTLS_ERR_RSA_RNG_FAILED );
kevman 0:38ceb79fef03 746
kevman 0:38ceb79fef03 747 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) );
kevman 0:38ceb79fef03 748 MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) );
kevman 0:38ceb79fef03 749 } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 );
kevman 0:38ceb79fef03 750
kevman 0:38ceb79fef03 751 /* Blinding value: Vi = Vf^(-e) mod N */
kevman 0:38ceb79fef03 752 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) );
kevman 0:38ceb79fef03 753 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) );
kevman 0:38ceb79fef03 754
kevman 0:38ceb79fef03 755
kevman 0:38ceb79fef03 756 cleanup:
kevman 0:38ceb79fef03 757 return( ret );
kevman 0:38ceb79fef03 758 }
kevman 0:38ceb79fef03 759
kevman 0:38ceb79fef03 760 /*
kevman 0:38ceb79fef03 761 * Exponent blinding supposed to prevent side-channel attacks using multiple
kevman 0:38ceb79fef03 762 * traces of measurements to recover the RSA key. The more collisions are there,
kevman 0:38ceb79fef03 763 * the more bits of the key can be recovered. See [3].
kevman 0:38ceb79fef03 764 *
kevman 0:38ceb79fef03 765 * Collecting n collisions with m bit long blinding value requires 2^(m-m/n)
kevman 0:38ceb79fef03 766 * observations on avarage.
kevman 0:38ceb79fef03 767 *
kevman 0:38ceb79fef03 768 * For example with 28 byte blinding to achieve 2 collisions the adversary has
kevman 0:38ceb79fef03 769 * to make 2^112 observations on avarage.
kevman 0:38ceb79fef03 770 *
kevman 0:38ceb79fef03 771 * (With the currently (as of 2017 April) known best algorithms breaking 2048
kevman 0:38ceb79fef03 772 * bit RSA requires approximately as much time as trying out 2^112 random keys.
kevman 0:38ceb79fef03 773 * Thus in this sense with 28 byte blinding the security is not reduced by
kevman 0:38ceb79fef03 774 * side-channel attacks like the one in [3])
kevman 0:38ceb79fef03 775 *
kevman 0:38ceb79fef03 776 * This countermeasure does not help if the key recovery is possible with a
kevman 0:38ceb79fef03 777 * single trace.
kevman 0:38ceb79fef03 778 */
kevman 0:38ceb79fef03 779 #define RSA_EXPONENT_BLINDING 28
kevman 0:38ceb79fef03 780
kevman 0:38ceb79fef03 781 /*
kevman 0:38ceb79fef03 782 * Do an RSA private key operation
kevman 0:38ceb79fef03 783 */
kevman 0:38ceb79fef03 784 int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 785 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 786 void *p_rng,
kevman 0:38ceb79fef03 787 const unsigned char *input,
kevman 0:38ceb79fef03 788 unsigned char *output )
kevman 0:38ceb79fef03 789 {
kevman 0:38ceb79fef03 790 int ret;
kevman 0:38ceb79fef03 791 size_t olen;
kevman 0:38ceb79fef03 792
kevman 0:38ceb79fef03 793 /* Temporary holding the result */
kevman 0:38ceb79fef03 794 mbedtls_mpi T;
kevman 0:38ceb79fef03 795
kevman 0:38ceb79fef03 796 /* Temporaries holding P-1, Q-1 and the
kevman 0:38ceb79fef03 797 * exponent blinding factor, respectively. */
kevman 0:38ceb79fef03 798 mbedtls_mpi P1, Q1, R;
kevman 0:38ceb79fef03 799
kevman 0:38ceb79fef03 800 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 801 /* Temporaries holding the results mod p resp. mod q. */
kevman 0:38ceb79fef03 802 mbedtls_mpi TP, TQ;
kevman 0:38ceb79fef03 803
kevman 0:38ceb79fef03 804 /* Temporaries holding the blinded exponents for
kevman 0:38ceb79fef03 805 * the mod p resp. mod q computation (if used). */
kevman 0:38ceb79fef03 806 mbedtls_mpi DP_blind, DQ_blind;
kevman 0:38ceb79fef03 807
kevman 0:38ceb79fef03 808 /* Pointers to actual exponents to be used - either the unblinded
kevman 0:38ceb79fef03 809 * or the blinded ones, depending on the presence of a PRNG. */
kevman 0:38ceb79fef03 810 mbedtls_mpi *DP = &ctx->DP;
kevman 0:38ceb79fef03 811 mbedtls_mpi *DQ = &ctx->DQ;
kevman 0:38ceb79fef03 812 #else
kevman 0:38ceb79fef03 813 /* Temporary holding the blinded exponent (if used). */
kevman 0:38ceb79fef03 814 mbedtls_mpi D_blind;
kevman 0:38ceb79fef03 815
kevman 0:38ceb79fef03 816 /* Pointer to actual exponent to be used - either the unblinded
kevman 0:38ceb79fef03 817 * or the blinded one, depending on the presence of a PRNG. */
kevman 0:38ceb79fef03 818 mbedtls_mpi *D = &ctx->D;
kevman 0:38ceb79fef03 819 #endif /* MBEDTLS_RSA_NO_CRT */
kevman 0:38ceb79fef03 820
kevman 0:38ceb79fef03 821 /* Temporaries holding the initial input and the double
kevman 0:38ceb79fef03 822 * checked result; should be the same in the end. */
kevman 0:38ceb79fef03 823 mbedtls_mpi I, C;
kevman 0:38ceb79fef03 824
kevman 0:38ceb79fef03 825 if( rsa_check_context( ctx, 1 /* private key checks */,
kevman 0:38ceb79fef03 826 f_rng != NULL /* blinding y/n */ ) != 0 )
kevman 0:38ceb79fef03 827 {
kevman 0:38ceb79fef03 828 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 829 }
kevman 0:38ceb79fef03 830
kevman 0:38ceb79fef03 831 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 832 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
kevman 0:38ceb79fef03 833 return( ret );
kevman 0:38ceb79fef03 834 #endif
kevman 0:38ceb79fef03 835
kevman 0:38ceb79fef03 836 /* MPI Initialization */
kevman 0:38ceb79fef03 837 mbedtls_mpi_init( &T );
kevman 0:38ceb79fef03 838
kevman 0:38ceb79fef03 839 mbedtls_mpi_init( &P1 );
kevman 0:38ceb79fef03 840 mbedtls_mpi_init( &Q1 );
kevman 0:38ceb79fef03 841 mbedtls_mpi_init( &R );
kevman 0:38ceb79fef03 842
kevman 0:38ceb79fef03 843 if( f_rng != NULL )
kevman 0:38ceb79fef03 844 {
kevman 0:38ceb79fef03 845 #if defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 846 mbedtls_mpi_init( &D_blind );
kevman 0:38ceb79fef03 847 #else
kevman 0:38ceb79fef03 848 mbedtls_mpi_init( &DP_blind );
kevman 0:38ceb79fef03 849 mbedtls_mpi_init( &DQ_blind );
kevman 0:38ceb79fef03 850 #endif
kevman 0:38ceb79fef03 851 }
kevman 0:38ceb79fef03 852
kevman 0:38ceb79fef03 853 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 854 mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ );
kevman 0:38ceb79fef03 855 #endif
kevman 0:38ceb79fef03 856
kevman 0:38ceb79fef03 857 mbedtls_mpi_init( &I );
kevman 0:38ceb79fef03 858 mbedtls_mpi_init( &C );
kevman 0:38ceb79fef03 859
kevman 0:38ceb79fef03 860 /* End of MPI initialization */
kevman 0:38ceb79fef03 861
kevman 0:38ceb79fef03 862 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
kevman 0:38ceb79fef03 863 if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
kevman 0:38ceb79fef03 864 {
kevman 0:38ceb79fef03 865 ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
kevman 0:38ceb79fef03 866 goto cleanup;
kevman 0:38ceb79fef03 867 }
kevman 0:38ceb79fef03 868
kevman 0:38ceb79fef03 869 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) );
kevman 0:38ceb79fef03 870
kevman 0:38ceb79fef03 871 if( f_rng != NULL )
kevman 0:38ceb79fef03 872 {
kevman 0:38ceb79fef03 873 /*
kevman 0:38ceb79fef03 874 * Blinding
kevman 0:38ceb79fef03 875 * T = T * Vi mod N
kevman 0:38ceb79fef03 876 */
kevman 0:38ceb79fef03 877 MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) );
kevman 0:38ceb79fef03 878 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) );
kevman 0:38ceb79fef03 879 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
kevman 0:38ceb79fef03 880
kevman 0:38ceb79fef03 881 /*
kevman 0:38ceb79fef03 882 * Exponent blinding
kevman 0:38ceb79fef03 883 */
kevman 0:38ceb79fef03 884 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) );
kevman 0:38ceb79fef03 885 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
kevman 0:38ceb79fef03 886
kevman 0:38ceb79fef03 887 #if defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 888 /*
kevman 0:38ceb79fef03 889 * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D
kevman 0:38ceb79fef03 890 */
kevman 0:38ceb79fef03 891 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
kevman 0:38ceb79fef03 892 f_rng, p_rng ) );
kevman 0:38ceb79fef03 893 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) );
kevman 0:38ceb79fef03 894 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) );
kevman 0:38ceb79fef03 895 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) );
kevman 0:38ceb79fef03 896
kevman 0:38ceb79fef03 897 D = &D_blind;
kevman 0:38ceb79fef03 898 #else
kevman 0:38ceb79fef03 899 /*
kevman 0:38ceb79fef03 900 * DP_blind = ( P - 1 ) * R + DP
kevman 0:38ceb79fef03 901 */
kevman 0:38ceb79fef03 902 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
kevman 0:38ceb79fef03 903 f_rng, p_rng ) );
kevman 0:38ceb79fef03 904 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) );
kevman 0:38ceb79fef03 905 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind,
kevman 0:38ceb79fef03 906 &ctx->DP ) );
kevman 0:38ceb79fef03 907
kevman 0:38ceb79fef03 908 DP = &DP_blind;
kevman 0:38ceb79fef03 909
kevman 0:38ceb79fef03 910 /*
kevman 0:38ceb79fef03 911 * DQ_blind = ( Q - 1 ) * R + DQ
kevman 0:38ceb79fef03 912 */
kevman 0:38ceb79fef03 913 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
kevman 0:38ceb79fef03 914 f_rng, p_rng ) );
kevman 0:38ceb79fef03 915 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) );
kevman 0:38ceb79fef03 916 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind,
kevman 0:38ceb79fef03 917 &ctx->DQ ) );
kevman 0:38ceb79fef03 918
kevman 0:38ceb79fef03 919 DQ = &DQ_blind;
kevman 0:38ceb79fef03 920 #endif /* MBEDTLS_RSA_NO_CRT */
kevman 0:38ceb79fef03 921 }
kevman 0:38ceb79fef03 922
kevman 0:38ceb79fef03 923 #if defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 924 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) );
kevman 0:38ceb79fef03 925 #else
kevman 0:38ceb79fef03 926 /*
kevman 0:38ceb79fef03 927 * Faster decryption using the CRT
kevman 0:38ceb79fef03 928 *
kevman 0:38ceb79fef03 929 * TP = input ^ dP mod P
kevman 0:38ceb79fef03 930 * TQ = input ^ dQ mod Q
kevman 0:38ceb79fef03 931 */
kevman 0:38ceb79fef03 932
kevman 0:38ceb79fef03 933 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) );
kevman 0:38ceb79fef03 934 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) );
kevman 0:38ceb79fef03 935
kevman 0:38ceb79fef03 936 /*
kevman 0:38ceb79fef03 937 * T = (TP - TQ) * (Q^-1 mod P) mod P
kevman 0:38ceb79fef03 938 */
kevman 0:38ceb79fef03 939 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) );
kevman 0:38ceb79fef03 940 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) );
kevman 0:38ceb79fef03 941 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) );
kevman 0:38ceb79fef03 942
kevman 0:38ceb79fef03 943 /*
kevman 0:38ceb79fef03 944 * T = TQ + T * Q
kevman 0:38ceb79fef03 945 */
kevman 0:38ceb79fef03 946 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) );
kevman 0:38ceb79fef03 947 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) );
kevman 0:38ceb79fef03 948 #endif /* MBEDTLS_RSA_NO_CRT */
kevman 0:38ceb79fef03 949
kevman 0:38ceb79fef03 950 if( f_rng != NULL )
kevman 0:38ceb79fef03 951 {
kevman 0:38ceb79fef03 952 /*
kevman 0:38ceb79fef03 953 * Unblind
kevman 0:38ceb79fef03 954 * T = T * Vf mod N
kevman 0:38ceb79fef03 955 */
kevman 0:38ceb79fef03 956 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) );
kevman 0:38ceb79fef03 957 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
kevman 0:38ceb79fef03 958 }
kevman 0:38ceb79fef03 959
kevman 0:38ceb79fef03 960 /* Verify the result to prevent glitching attacks. */
kevman 0:38ceb79fef03 961 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E,
kevman 0:38ceb79fef03 962 &ctx->N, &ctx->RN ) );
kevman 0:38ceb79fef03 963 if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 )
kevman 0:38ceb79fef03 964 {
kevman 0:38ceb79fef03 965 ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
kevman 0:38ceb79fef03 966 goto cleanup;
kevman 0:38ceb79fef03 967 }
kevman 0:38ceb79fef03 968
kevman 0:38ceb79fef03 969 olen = ctx->len;
kevman 0:38ceb79fef03 970 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
kevman 0:38ceb79fef03 971
kevman 0:38ceb79fef03 972 cleanup:
kevman 0:38ceb79fef03 973 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 974 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
kevman 0:38ceb79fef03 975 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
kevman 0:38ceb79fef03 976 #endif
kevman 0:38ceb79fef03 977
kevman 0:38ceb79fef03 978 mbedtls_mpi_free( &P1 );
kevman 0:38ceb79fef03 979 mbedtls_mpi_free( &Q1 );
kevman 0:38ceb79fef03 980 mbedtls_mpi_free( &R );
kevman 0:38ceb79fef03 981
kevman 0:38ceb79fef03 982 if( f_rng != NULL )
kevman 0:38ceb79fef03 983 {
kevman 0:38ceb79fef03 984 #if defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 985 mbedtls_mpi_free( &D_blind );
kevman 0:38ceb79fef03 986 #else
kevman 0:38ceb79fef03 987 mbedtls_mpi_free( &DP_blind );
kevman 0:38ceb79fef03 988 mbedtls_mpi_free( &DQ_blind );
kevman 0:38ceb79fef03 989 #endif
kevman 0:38ceb79fef03 990 }
kevman 0:38ceb79fef03 991
kevman 0:38ceb79fef03 992 mbedtls_mpi_free( &T );
kevman 0:38ceb79fef03 993
kevman 0:38ceb79fef03 994 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 995 mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ );
kevman 0:38ceb79fef03 996 #endif
kevman 0:38ceb79fef03 997
kevman 0:38ceb79fef03 998 mbedtls_mpi_free( &C );
kevman 0:38ceb79fef03 999 mbedtls_mpi_free( &I );
kevman 0:38ceb79fef03 1000
kevman 0:38ceb79fef03 1001 if( ret != 0 )
kevman 0:38ceb79fef03 1002 return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
kevman 0:38ceb79fef03 1003
kevman 0:38ceb79fef03 1004 return( 0 );
kevman 0:38ceb79fef03 1005 }
kevman 0:38ceb79fef03 1006
kevman 0:38ceb79fef03 1007 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 1008 /**
kevman 0:38ceb79fef03 1009 * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
kevman 0:38ceb79fef03 1010 *
kevman 0:38ceb79fef03 1011 * \param dst buffer to mask
kevman 0:38ceb79fef03 1012 * \param dlen length of destination buffer
kevman 0:38ceb79fef03 1013 * \param src source of the mask generation
kevman 0:38ceb79fef03 1014 * \param slen length of the source buffer
kevman 0:38ceb79fef03 1015 * \param md_ctx message digest context to use
kevman 0:38ceb79fef03 1016 */
kevman 0:38ceb79fef03 1017 static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
kevman 0:38ceb79fef03 1018 size_t slen, mbedtls_md_context_t *md_ctx )
kevman 0:38ceb79fef03 1019 {
kevman 0:38ceb79fef03 1020 unsigned char mask[MBEDTLS_MD_MAX_SIZE];
kevman 0:38ceb79fef03 1021 unsigned char counter[4];
kevman 0:38ceb79fef03 1022 unsigned char *p;
kevman 0:38ceb79fef03 1023 unsigned int hlen;
kevman 0:38ceb79fef03 1024 size_t i, use_len;
kevman 0:38ceb79fef03 1025 int ret = 0;
kevman 0:38ceb79fef03 1026
kevman 0:38ceb79fef03 1027 memset( mask, 0, MBEDTLS_MD_MAX_SIZE );
kevman 0:38ceb79fef03 1028 memset( counter, 0, 4 );
kevman 0:38ceb79fef03 1029
kevman 0:38ceb79fef03 1030 hlen = mbedtls_md_get_size( md_ctx->md_info );
kevman 0:38ceb79fef03 1031
kevman 0:38ceb79fef03 1032 /* Generate and apply dbMask */
kevman 0:38ceb79fef03 1033 p = dst;
kevman 0:38ceb79fef03 1034
kevman 0:38ceb79fef03 1035 while( dlen > 0 )
kevman 0:38ceb79fef03 1036 {
kevman 0:38ceb79fef03 1037 use_len = hlen;
kevman 0:38ceb79fef03 1038 if( dlen < hlen )
kevman 0:38ceb79fef03 1039 use_len = dlen;
kevman 0:38ceb79fef03 1040
kevman 0:38ceb79fef03 1041 if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 )
kevman 0:38ceb79fef03 1042 goto exit;
kevman 0:38ceb79fef03 1043 if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 )
kevman 0:38ceb79fef03 1044 goto exit;
kevman 0:38ceb79fef03 1045 if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 )
kevman 0:38ceb79fef03 1046 goto exit;
kevman 0:38ceb79fef03 1047 if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 )
kevman 0:38ceb79fef03 1048 goto exit;
kevman 0:38ceb79fef03 1049
kevman 0:38ceb79fef03 1050 for( i = 0; i < use_len; ++i )
kevman 0:38ceb79fef03 1051 *p++ ^= mask[i];
kevman 0:38ceb79fef03 1052
kevman 0:38ceb79fef03 1053 counter[3]++;
kevman 0:38ceb79fef03 1054
kevman 0:38ceb79fef03 1055 dlen -= use_len;
kevman 0:38ceb79fef03 1056 }
kevman 0:38ceb79fef03 1057
kevman 0:38ceb79fef03 1058 exit:
kevman 0:38ceb79fef03 1059 mbedtls_platform_zeroize( mask, sizeof( mask ) );
kevman 0:38ceb79fef03 1060
kevman 0:38ceb79fef03 1061 return( ret );
kevman 0:38ceb79fef03 1062 }
kevman 0:38ceb79fef03 1063 #endif /* MBEDTLS_PKCS1_V21 */
kevman 0:38ceb79fef03 1064
kevman 0:38ceb79fef03 1065 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 1066 /*
kevman 0:38ceb79fef03 1067 * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function
kevman 0:38ceb79fef03 1068 */
kevman 0:38ceb79fef03 1069 int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1070 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1071 void *p_rng,
kevman 0:38ceb79fef03 1072 int mode,
kevman 0:38ceb79fef03 1073 const unsigned char *label, size_t label_len,
kevman 0:38ceb79fef03 1074 size_t ilen,
kevman 0:38ceb79fef03 1075 const unsigned char *input,
kevman 0:38ceb79fef03 1076 unsigned char *output )
kevman 0:38ceb79fef03 1077 {
kevman 0:38ceb79fef03 1078 size_t olen;
kevman 0:38ceb79fef03 1079 int ret;
kevman 0:38ceb79fef03 1080 unsigned char *p = output;
kevman 0:38ceb79fef03 1081 unsigned int hlen;
kevman 0:38ceb79fef03 1082 const mbedtls_md_info_t *md_info;
kevman 0:38ceb79fef03 1083 mbedtls_md_context_t md_ctx;
kevman 0:38ceb79fef03 1084
kevman 0:38ceb79fef03 1085 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
kevman 0:38ceb79fef03 1086 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1087
kevman 0:38ceb79fef03 1088 if( f_rng == NULL )
kevman 0:38ceb79fef03 1089 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1090
kevman 0:38ceb79fef03 1091 md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
kevman 0:38ceb79fef03 1092 if( md_info == NULL )
kevman 0:38ceb79fef03 1093 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1094
kevman 0:38ceb79fef03 1095 olen = ctx->len;
kevman 0:38ceb79fef03 1096 hlen = mbedtls_md_get_size( md_info );
kevman 0:38ceb79fef03 1097
kevman 0:38ceb79fef03 1098 /* first comparison checks for overflow */
kevman 0:38ceb79fef03 1099 if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 )
kevman 0:38ceb79fef03 1100 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1101
kevman 0:38ceb79fef03 1102 memset( output, 0, olen );
kevman 0:38ceb79fef03 1103
kevman 0:38ceb79fef03 1104 *p++ = 0;
kevman 0:38ceb79fef03 1105
kevman 0:38ceb79fef03 1106 /* Generate a random octet string seed */
kevman 0:38ceb79fef03 1107 if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
kevman 0:38ceb79fef03 1108 return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
kevman 0:38ceb79fef03 1109
kevman 0:38ceb79fef03 1110 p += hlen;
kevman 0:38ceb79fef03 1111
kevman 0:38ceb79fef03 1112 /* Construct DB */
kevman 0:38ceb79fef03 1113 if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 )
kevman 0:38ceb79fef03 1114 return( ret );
kevman 0:38ceb79fef03 1115 p += hlen;
kevman 0:38ceb79fef03 1116 p += olen - 2 * hlen - 2 - ilen;
kevman 0:38ceb79fef03 1117 *p++ = 1;
kevman 0:38ceb79fef03 1118 memcpy( p, input, ilen );
kevman 0:38ceb79fef03 1119
kevman 0:38ceb79fef03 1120 mbedtls_md_init( &md_ctx );
kevman 0:38ceb79fef03 1121 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
kevman 0:38ceb79fef03 1122 goto exit;
kevman 0:38ceb79fef03 1123
kevman 0:38ceb79fef03 1124 /* maskedDB: Apply dbMask to DB */
kevman 0:38ceb79fef03 1125 if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
kevman 0:38ceb79fef03 1126 &md_ctx ) ) != 0 )
kevman 0:38ceb79fef03 1127 goto exit;
kevman 0:38ceb79fef03 1128
kevman 0:38ceb79fef03 1129 /* maskedSeed: Apply seedMask to seed */
kevman 0:38ceb79fef03 1130 if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
kevman 0:38ceb79fef03 1131 &md_ctx ) ) != 0 )
kevman 0:38ceb79fef03 1132 goto exit;
kevman 0:38ceb79fef03 1133
kevman 0:38ceb79fef03 1134 exit:
kevman 0:38ceb79fef03 1135 mbedtls_md_free( &md_ctx );
kevman 0:38ceb79fef03 1136
kevman 0:38ceb79fef03 1137 if( ret != 0 )
kevman 0:38ceb79fef03 1138 return( ret );
kevman 0:38ceb79fef03 1139
kevman 0:38ceb79fef03 1140 return( ( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 1141 ? mbedtls_rsa_public( ctx, output, output )
kevman 0:38ceb79fef03 1142 : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) );
kevman 0:38ceb79fef03 1143 }
kevman 0:38ceb79fef03 1144 #endif /* MBEDTLS_PKCS1_V21 */
kevman 0:38ceb79fef03 1145
kevman 0:38ceb79fef03 1146 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 1147 /*
kevman 0:38ceb79fef03 1148 * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function
kevman 0:38ceb79fef03 1149 */
kevman 0:38ceb79fef03 1150 int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1151 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1152 void *p_rng,
kevman 0:38ceb79fef03 1153 int mode, size_t ilen,
kevman 0:38ceb79fef03 1154 const unsigned char *input,
kevman 0:38ceb79fef03 1155 unsigned char *output )
kevman 0:38ceb79fef03 1156 {
kevman 0:38ceb79fef03 1157 size_t nb_pad, olen;
kevman 0:38ceb79fef03 1158 int ret;
kevman 0:38ceb79fef03 1159 unsigned char *p = output;
kevman 0:38ceb79fef03 1160
kevman 0:38ceb79fef03 1161 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
kevman 0:38ceb79fef03 1162 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1163
kevman 0:38ceb79fef03 1164 // We don't check p_rng because it won't be dereferenced here
kevman 0:38ceb79fef03 1165 if( f_rng == NULL || input == NULL || output == NULL )
kevman 0:38ceb79fef03 1166 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1167
kevman 0:38ceb79fef03 1168 olen = ctx->len;
kevman 0:38ceb79fef03 1169
kevman 0:38ceb79fef03 1170 /* first comparison checks for overflow */
kevman 0:38ceb79fef03 1171 if( ilen + 11 < ilen || olen < ilen + 11 )
kevman 0:38ceb79fef03 1172 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1173
kevman 0:38ceb79fef03 1174 nb_pad = olen - 3 - ilen;
kevman 0:38ceb79fef03 1175
kevman 0:38ceb79fef03 1176 *p++ = 0;
kevman 0:38ceb79fef03 1177 if( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 1178 {
kevman 0:38ceb79fef03 1179 *p++ = MBEDTLS_RSA_CRYPT;
kevman 0:38ceb79fef03 1180
kevman 0:38ceb79fef03 1181 while( nb_pad-- > 0 )
kevman 0:38ceb79fef03 1182 {
kevman 0:38ceb79fef03 1183 int rng_dl = 100;
kevman 0:38ceb79fef03 1184
kevman 0:38ceb79fef03 1185 do {
kevman 0:38ceb79fef03 1186 ret = f_rng( p_rng, p, 1 );
kevman 0:38ceb79fef03 1187 } while( *p == 0 && --rng_dl && ret == 0 );
kevman 0:38ceb79fef03 1188
kevman 0:38ceb79fef03 1189 /* Check if RNG failed to generate data */
kevman 0:38ceb79fef03 1190 if( rng_dl == 0 || ret != 0 )
kevman 0:38ceb79fef03 1191 return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
kevman 0:38ceb79fef03 1192
kevman 0:38ceb79fef03 1193 p++;
kevman 0:38ceb79fef03 1194 }
kevman 0:38ceb79fef03 1195 }
kevman 0:38ceb79fef03 1196 else
kevman 0:38ceb79fef03 1197 {
kevman 0:38ceb79fef03 1198 *p++ = MBEDTLS_RSA_SIGN;
kevman 0:38ceb79fef03 1199
kevman 0:38ceb79fef03 1200 while( nb_pad-- > 0 )
kevman 0:38ceb79fef03 1201 *p++ = 0xFF;
kevman 0:38ceb79fef03 1202 }
kevman 0:38ceb79fef03 1203
kevman 0:38ceb79fef03 1204 *p++ = 0;
kevman 0:38ceb79fef03 1205 memcpy( p, input, ilen );
kevman 0:38ceb79fef03 1206
kevman 0:38ceb79fef03 1207 return( ( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 1208 ? mbedtls_rsa_public( ctx, output, output )
kevman 0:38ceb79fef03 1209 : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) );
kevman 0:38ceb79fef03 1210 }
kevman 0:38ceb79fef03 1211 #endif /* MBEDTLS_PKCS1_V15 */
kevman 0:38ceb79fef03 1212
kevman 0:38ceb79fef03 1213 /*
kevman 0:38ceb79fef03 1214 * Add the message padding, then do an RSA operation
kevman 0:38ceb79fef03 1215 */
kevman 0:38ceb79fef03 1216 int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1217 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1218 void *p_rng,
kevman 0:38ceb79fef03 1219 int mode, size_t ilen,
kevman 0:38ceb79fef03 1220 const unsigned char *input,
kevman 0:38ceb79fef03 1221 unsigned char *output )
kevman 0:38ceb79fef03 1222 {
kevman 0:38ceb79fef03 1223 switch( ctx->padding )
kevman 0:38ceb79fef03 1224 {
kevman 0:38ceb79fef03 1225 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 1226 case MBEDTLS_RSA_PKCS_V15:
kevman 0:38ceb79fef03 1227 return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen,
kevman 0:38ceb79fef03 1228 input, output );
kevman 0:38ceb79fef03 1229 #endif
kevman 0:38ceb79fef03 1230
kevman 0:38ceb79fef03 1231 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 1232 case MBEDTLS_RSA_PKCS_V21:
kevman 0:38ceb79fef03 1233 return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0,
kevman 0:38ceb79fef03 1234 ilen, input, output );
kevman 0:38ceb79fef03 1235 #endif
kevman 0:38ceb79fef03 1236
kevman 0:38ceb79fef03 1237 default:
kevman 0:38ceb79fef03 1238 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
kevman 0:38ceb79fef03 1239 }
kevman 0:38ceb79fef03 1240 }
kevman 0:38ceb79fef03 1241
kevman 0:38ceb79fef03 1242 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 1243 /*
kevman 0:38ceb79fef03 1244 * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function
kevman 0:38ceb79fef03 1245 */
kevman 0:38ceb79fef03 1246 int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1247 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1248 void *p_rng,
kevman 0:38ceb79fef03 1249 int mode,
kevman 0:38ceb79fef03 1250 const unsigned char *label, size_t label_len,
kevman 0:38ceb79fef03 1251 size_t *olen,
kevman 0:38ceb79fef03 1252 const unsigned char *input,
kevman 0:38ceb79fef03 1253 unsigned char *output,
kevman 0:38ceb79fef03 1254 size_t output_max_len )
kevman 0:38ceb79fef03 1255 {
kevman 0:38ceb79fef03 1256 int ret;
kevman 0:38ceb79fef03 1257 size_t ilen, i, pad_len;
kevman 0:38ceb79fef03 1258 unsigned char *p, bad, pad_done;
kevman 0:38ceb79fef03 1259 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
kevman 0:38ceb79fef03 1260 unsigned char lhash[MBEDTLS_MD_MAX_SIZE];
kevman 0:38ceb79fef03 1261 unsigned int hlen;
kevman 0:38ceb79fef03 1262 const mbedtls_md_info_t *md_info;
kevman 0:38ceb79fef03 1263 mbedtls_md_context_t md_ctx;
kevman 0:38ceb79fef03 1264
kevman 0:38ceb79fef03 1265 /*
kevman 0:38ceb79fef03 1266 * Parameters sanity checks
kevman 0:38ceb79fef03 1267 */
kevman 0:38ceb79fef03 1268 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
kevman 0:38ceb79fef03 1269 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1270
kevman 0:38ceb79fef03 1271 ilen = ctx->len;
kevman 0:38ceb79fef03 1272
kevman 0:38ceb79fef03 1273 if( ilen < 16 || ilen > sizeof( buf ) )
kevman 0:38ceb79fef03 1274 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1275
kevman 0:38ceb79fef03 1276 md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
kevman 0:38ceb79fef03 1277 if( md_info == NULL )
kevman 0:38ceb79fef03 1278 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1279
kevman 0:38ceb79fef03 1280 hlen = mbedtls_md_get_size( md_info );
kevman 0:38ceb79fef03 1281
kevman 0:38ceb79fef03 1282 // checking for integer underflow
kevman 0:38ceb79fef03 1283 if( 2 * hlen + 2 > ilen )
kevman 0:38ceb79fef03 1284 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1285
kevman 0:38ceb79fef03 1286 /*
kevman 0:38ceb79fef03 1287 * RSA operation
kevman 0:38ceb79fef03 1288 */
kevman 0:38ceb79fef03 1289 ret = ( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 1290 ? mbedtls_rsa_public( ctx, input, buf )
kevman 0:38ceb79fef03 1291 : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf );
kevman 0:38ceb79fef03 1292
kevman 0:38ceb79fef03 1293 if( ret != 0 )
kevman 0:38ceb79fef03 1294 goto cleanup;
kevman 0:38ceb79fef03 1295
kevman 0:38ceb79fef03 1296 /*
kevman 0:38ceb79fef03 1297 * Unmask data and generate lHash
kevman 0:38ceb79fef03 1298 */
kevman 0:38ceb79fef03 1299 mbedtls_md_init( &md_ctx );
kevman 0:38ceb79fef03 1300 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
kevman 0:38ceb79fef03 1301 {
kevman 0:38ceb79fef03 1302 mbedtls_md_free( &md_ctx );
kevman 0:38ceb79fef03 1303 goto cleanup;
kevman 0:38ceb79fef03 1304 }
kevman 0:38ceb79fef03 1305
kevman 0:38ceb79fef03 1306 /* seed: Apply seedMask to maskedSeed */
kevman 0:38ceb79fef03 1307 if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
kevman 0:38ceb79fef03 1308 &md_ctx ) ) != 0 ||
kevman 0:38ceb79fef03 1309 /* DB: Apply dbMask to maskedDB */
kevman 0:38ceb79fef03 1310 ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
kevman 0:38ceb79fef03 1311 &md_ctx ) ) != 0 )
kevman 0:38ceb79fef03 1312 {
kevman 0:38ceb79fef03 1313 mbedtls_md_free( &md_ctx );
kevman 0:38ceb79fef03 1314 goto cleanup;
kevman 0:38ceb79fef03 1315 }
kevman 0:38ceb79fef03 1316
kevman 0:38ceb79fef03 1317 mbedtls_md_free( &md_ctx );
kevman 0:38ceb79fef03 1318
kevman 0:38ceb79fef03 1319 /* Generate lHash */
kevman 0:38ceb79fef03 1320 if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 )
kevman 0:38ceb79fef03 1321 goto cleanup;
kevman 0:38ceb79fef03 1322
kevman 0:38ceb79fef03 1323 /*
kevman 0:38ceb79fef03 1324 * Check contents, in "constant-time"
kevman 0:38ceb79fef03 1325 */
kevman 0:38ceb79fef03 1326 p = buf;
kevman 0:38ceb79fef03 1327 bad = 0;
kevman 0:38ceb79fef03 1328
kevman 0:38ceb79fef03 1329 bad |= *p++; /* First byte must be 0 */
kevman 0:38ceb79fef03 1330
kevman 0:38ceb79fef03 1331 p += hlen; /* Skip seed */
kevman 0:38ceb79fef03 1332
kevman 0:38ceb79fef03 1333 /* Check lHash */
kevman 0:38ceb79fef03 1334 for( i = 0; i < hlen; i++ )
kevman 0:38ceb79fef03 1335 bad |= lhash[i] ^ *p++;
kevman 0:38ceb79fef03 1336
kevman 0:38ceb79fef03 1337 /* Get zero-padding len, but always read till end of buffer
kevman 0:38ceb79fef03 1338 * (minus one, for the 01 byte) */
kevman 0:38ceb79fef03 1339 pad_len = 0;
kevman 0:38ceb79fef03 1340 pad_done = 0;
kevman 0:38ceb79fef03 1341 for( i = 0; i < ilen - 2 * hlen - 2; i++ )
kevman 0:38ceb79fef03 1342 {
kevman 0:38ceb79fef03 1343 pad_done |= p[i];
kevman 0:38ceb79fef03 1344 pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
kevman 0:38ceb79fef03 1345 }
kevman 0:38ceb79fef03 1346
kevman 0:38ceb79fef03 1347 p += pad_len;
kevman 0:38ceb79fef03 1348 bad |= *p++ ^ 0x01;
kevman 0:38ceb79fef03 1349
kevman 0:38ceb79fef03 1350 /*
kevman 0:38ceb79fef03 1351 * The only information "leaked" is whether the padding was correct or not
kevman 0:38ceb79fef03 1352 * (eg, no data is copied if it was not correct). This meets the
kevman 0:38ceb79fef03 1353 * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
kevman 0:38ceb79fef03 1354 * the different error conditions.
kevman 0:38ceb79fef03 1355 */
kevman 0:38ceb79fef03 1356 if( bad != 0 )
kevman 0:38ceb79fef03 1357 {
kevman 0:38ceb79fef03 1358 ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
kevman 0:38ceb79fef03 1359 goto cleanup;
kevman 0:38ceb79fef03 1360 }
kevman 0:38ceb79fef03 1361
kevman 0:38ceb79fef03 1362 if( ilen - ( p - buf ) > output_max_len )
kevman 0:38ceb79fef03 1363 {
kevman 0:38ceb79fef03 1364 ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
kevman 0:38ceb79fef03 1365 goto cleanup;
kevman 0:38ceb79fef03 1366 }
kevman 0:38ceb79fef03 1367
kevman 0:38ceb79fef03 1368 *olen = ilen - (p - buf);
kevman 0:38ceb79fef03 1369 memcpy( output, p, *olen );
kevman 0:38ceb79fef03 1370 ret = 0;
kevman 0:38ceb79fef03 1371
kevman 0:38ceb79fef03 1372 cleanup:
kevman 0:38ceb79fef03 1373 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kevman 0:38ceb79fef03 1374 mbedtls_platform_zeroize( lhash, sizeof( lhash ) );
kevman 0:38ceb79fef03 1375
kevman 0:38ceb79fef03 1376 return( ret );
kevman 0:38ceb79fef03 1377 }
kevman 0:38ceb79fef03 1378 #endif /* MBEDTLS_PKCS1_V21 */
kevman 0:38ceb79fef03 1379
kevman 0:38ceb79fef03 1380 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 1381 /*
kevman 0:38ceb79fef03 1382 * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
kevman 0:38ceb79fef03 1383 */
kevman 0:38ceb79fef03 1384 int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1385 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1386 void *p_rng,
kevman 0:38ceb79fef03 1387 int mode, size_t *olen,
kevman 0:38ceb79fef03 1388 const unsigned char *input,
kevman 0:38ceb79fef03 1389 unsigned char *output,
kevman 0:38ceb79fef03 1390 size_t output_max_len)
kevman 0:38ceb79fef03 1391 {
kevman 0:38ceb79fef03 1392 int ret;
kevman 0:38ceb79fef03 1393 size_t ilen, pad_count = 0, i;
kevman 0:38ceb79fef03 1394 unsigned char *p, bad, pad_done = 0;
kevman 0:38ceb79fef03 1395 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
kevman 0:38ceb79fef03 1396
kevman 0:38ceb79fef03 1397 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
kevman 0:38ceb79fef03 1398 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1399
kevman 0:38ceb79fef03 1400 ilen = ctx->len;
kevman 0:38ceb79fef03 1401
kevman 0:38ceb79fef03 1402 if( ilen < 16 || ilen > sizeof( buf ) )
kevman 0:38ceb79fef03 1403 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1404
kevman 0:38ceb79fef03 1405 ret = ( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 1406 ? mbedtls_rsa_public( ctx, input, buf )
kevman 0:38ceb79fef03 1407 : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf );
kevman 0:38ceb79fef03 1408
kevman 0:38ceb79fef03 1409 if( ret != 0 )
kevman 0:38ceb79fef03 1410 goto cleanup;
kevman 0:38ceb79fef03 1411
kevman 0:38ceb79fef03 1412 p = buf;
kevman 0:38ceb79fef03 1413 bad = 0;
kevman 0:38ceb79fef03 1414
kevman 0:38ceb79fef03 1415 /*
kevman 0:38ceb79fef03 1416 * Check and get padding len in "constant-time"
kevman 0:38ceb79fef03 1417 */
kevman 0:38ceb79fef03 1418 bad |= *p++; /* First byte must be 0 */
kevman 0:38ceb79fef03 1419
kevman 0:38ceb79fef03 1420 /* This test does not depend on secret data */
kevman 0:38ceb79fef03 1421 if( mode == MBEDTLS_RSA_PRIVATE )
kevman 0:38ceb79fef03 1422 {
kevman 0:38ceb79fef03 1423 bad |= *p++ ^ MBEDTLS_RSA_CRYPT;
kevman 0:38ceb79fef03 1424
kevman 0:38ceb79fef03 1425 /* Get padding len, but always read till end of buffer
kevman 0:38ceb79fef03 1426 * (minus one, for the 00 byte) */
kevman 0:38ceb79fef03 1427 for( i = 0; i < ilen - 3; i++ )
kevman 0:38ceb79fef03 1428 {
kevman 0:38ceb79fef03 1429 pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1;
kevman 0:38ceb79fef03 1430 pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
kevman 0:38ceb79fef03 1431 }
kevman 0:38ceb79fef03 1432
kevman 0:38ceb79fef03 1433 p += pad_count;
kevman 0:38ceb79fef03 1434 bad |= *p++; /* Must be zero */
kevman 0:38ceb79fef03 1435 }
kevman 0:38ceb79fef03 1436 else
kevman 0:38ceb79fef03 1437 {
kevman 0:38ceb79fef03 1438 bad |= *p++ ^ MBEDTLS_RSA_SIGN;
kevman 0:38ceb79fef03 1439
kevman 0:38ceb79fef03 1440 /* Get padding len, but always read till end of buffer
kevman 0:38ceb79fef03 1441 * (minus one, for the 00 byte) */
kevman 0:38ceb79fef03 1442 for( i = 0; i < ilen - 3; i++ )
kevman 0:38ceb79fef03 1443 {
kevman 0:38ceb79fef03 1444 pad_done |= ( p[i] != 0xFF );
kevman 0:38ceb79fef03 1445 pad_count += ( pad_done == 0 );
kevman 0:38ceb79fef03 1446 }
kevman 0:38ceb79fef03 1447
kevman 0:38ceb79fef03 1448 p += pad_count;
kevman 0:38ceb79fef03 1449 bad |= *p++; /* Must be zero */
kevman 0:38ceb79fef03 1450 }
kevman 0:38ceb79fef03 1451
kevman 0:38ceb79fef03 1452 bad |= ( pad_count < 8 );
kevman 0:38ceb79fef03 1453
kevman 0:38ceb79fef03 1454 if( bad )
kevman 0:38ceb79fef03 1455 {
kevman 0:38ceb79fef03 1456 ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
kevman 0:38ceb79fef03 1457 goto cleanup;
kevman 0:38ceb79fef03 1458 }
kevman 0:38ceb79fef03 1459
kevman 0:38ceb79fef03 1460 if( ilen - ( p - buf ) > output_max_len )
kevman 0:38ceb79fef03 1461 {
kevman 0:38ceb79fef03 1462 ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
kevman 0:38ceb79fef03 1463 goto cleanup;
kevman 0:38ceb79fef03 1464 }
kevman 0:38ceb79fef03 1465
kevman 0:38ceb79fef03 1466 *olen = ilen - (p - buf);
kevman 0:38ceb79fef03 1467 memcpy( output, p, *olen );
kevman 0:38ceb79fef03 1468 ret = 0;
kevman 0:38ceb79fef03 1469
kevman 0:38ceb79fef03 1470 cleanup:
kevman 0:38ceb79fef03 1471 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kevman 0:38ceb79fef03 1472
kevman 0:38ceb79fef03 1473 return( ret );
kevman 0:38ceb79fef03 1474 }
kevman 0:38ceb79fef03 1475 #endif /* MBEDTLS_PKCS1_V15 */
kevman 0:38ceb79fef03 1476
kevman 0:38ceb79fef03 1477 /*
kevman 0:38ceb79fef03 1478 * Do an RSA operation, then remove the message padding
kevman 0:38ceb79fef03 1479 */
kevman 0:38ceb79fef03 1480 int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1481 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1482 void *p_rng,
kevman 0:38ceb79fef03 1483 int mode, size_t *olen,
kevman 0:38ceb79fef03 1484 const unsigned char *input,
kevman 0:38ceb79fef03 1485 unsigned char *output,
kevman 0:38ceb79fef03 1486 size_t output_max_len)
kevman 0:38ceb79fef03 1487 {
kevman 0:38ceb79fef03 1488 switch( ctx->padding )
kevman 0:38ceb79fef03 1489 {
kevman 0:38ceb79fef03 1490 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 1491 case MBEDTLS_RSA_PKCS_V15:
kevman 0:38ceb79fef03 1492 return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen,
kevman 0:38ceb79fef03 1493 input, output, output_max_len );
kevman 0:38ceb79fef03 1494 #endif
kevman 0:38ceb79fef03 1495
kevman 0:38ceb79fef03 1496 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 1497 case MBEDTLS_RSA_PKCS_V21:
kevman 0:38ceb79fef03 1498 return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0,
kevman 0:38ceb79fef03 1499 olen, input, output,
kevman 0:38ceb79fef03 1500 output_max_len );
kevman 0:38ceb79fef03 1501 #endif
kevman 0:38ceb79fef03 1502
kevman 0:38ceb79fef03 1503 default:
kevman 0:38ceb79fef03 1504 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
kevman 0:38ceb79fef03 1505 }
kevman 0:38ceb79fef03 1506 }
kevman 0:38ceb79fef03 1507
kevman 0:38ceb79fef03 1508 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 1509 /*
kevman 0:38ceb79fef03 1510 * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
kevman 0:38ceb79fef03 1511 */
kevman 0:38ceb79fef03 1512 int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1513 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1514 void *p_rng,
kevman 0:38ceb79fef03 1515 int mode,
kevman 0:38ceb79fef03 1516 mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 1517 unsigned int hashlen,
kevman 0:38ceb79fef03 1518 const unsigned char *hash,
kevman 0:38ceb79fef03 1519 unsigned char *sig )
kevman 0:38ceb79fef03 1520 {
kevman 0:38ceb79fef03 1521 size_t olen;
kevman 0:38ceb79fef03 1522 unsigned char *p = sig;
kevman 0:38ceb79fef03 1523 unsigned char salt[MBEDTLS_MD_MAX_SIZE];
kevman 0:38ceb79fef03 1524 unsigned int slen, hlen, offset = 0;
kevman 0:38ceb79fef03 1525 int ret;
kevman 0:38ceb79fef03 1526 size_t msb;
kevman 0:38ceb79fef03 1527 const mbedtls_md_info_t *md_info;
kevman 0:38ceb79fef03 1528 mbedtls_md_context_t md_ctx;
kevman 0:38ceb79fef03 1529
kevman 0:38ceb79fef03 1530 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
kevman 0:38ceb79fef03 1531 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1532
kevman 0:38ceb79fef03 1533 if( f_rng == NULL )
kevman 0:38ceb79fef03 1534 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1535
kevman 0:38ceb79fef03 1536 olen = ctx->len;
kevman 0:38ceb79fef03 1537
kevman 0:38ceb79fef03 1538 if( md_alg != MBEDTLS_MD_NONE )
kevman 0:38ceb79fef03 1539 {
kevman 0:38ceb79fef03 1540 /* Gather length of hash to sign */
kevman 0:38ceb79fef03 1541 md_info = mbedtls_md_info_from_type( md_alg );
kevman 0:38ceb79fef03 1542 if( md_info == NULL )
kevman 0:38ceb79fef03 1543 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1544
kevman 0:38ceb79fef03 1545 hashlen = mbedtls_md_get_size( md_info );
kevman 0:38ceb79fef03 1546 }
kevman 0:38ceb79fef03 1547
kevman 0:38ceb79fef03 1548 md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
kevman 0:38ceb79fef03 1549 if( md_info == NULL )
kevman 0:38ceb79fef03 1550 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1551
kevman 0:38ceb79fef03 1552 hlen = mbedtls_md_get_size( md_info );
kevman 0:38ceb79fef03 1553 slen = hlen;
kevman 0:38ceb79fef03 1554
kevman 0:38ceb79fef03 1555 if( olen < hlen + slen + 2 )
kevman 0:38ceb79fef03 1556 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1557
kevman 0:38ceb79fef03 1558 memset( sig, 0, olen );
kevman 0:38ceb79fef03 1559
kevman 0:38ceb79fef03 1560 /* Generate salt of length slen */
kevman 0:38ceb79fef03 1561 if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
kevman 0:38ceb79fef03 1562 return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
kevman 0:38ceb79fef03 1563
kevman 0:38ceb79fef03 1564 /* Note: EMSA-PSS encoding is over the length of N - 1 bits */
kevman 0:38ceb79fef03 1565 msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
kevman 0:38ceb79fef03 1566 p += olen - hlen * 2 - 2;
kevman 0:38ceb79fef03 1567 *p++ = 0x01;
kevman 0:38ceb79fef03 1568 memcpy( p, salt, slen );
kevman 0:38ceb79fef03 1569 p += slen;
kevman 0:38ceb79fef03 1570
kevman 0:38ceb79fef03 1571 mbedtls_md_init( &md_ctx );
kevman 0:38ceb79fef03 1572 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
kevman 0:38ceb79fef03 1573 goto exit;
kevman 0:38ceb79fef03 1574
kevman 0:38ceb79fef03 1575 /* Generate H = Hash( M' ) */
kevman 0:38ceb79fef03 1576 if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 )
kevman 0:38ceb79fef03 1577 goto exit;
kevman 0:38ceb79fef03 1578 if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 )
kevman 0:38ceb79fef03 1579 goto exit;
kevman 0:38ceb79fef03 1580 if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 )
kevman 0:38ceb79fef03 1581 goto exit;
kevman 0:38ceb79fef03 1582 if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 )
kevman 0:38ceb79fef03 1583 goto exit;
kevman 0:38ceb79fef03 1584 if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 )
kevman 0:38ceb79fef03 1585 goto exit;
kevman 0:38ceb79fef03 1586
kevman 0:38ceb79fef03 1587 /* Compensate for boundary condition when applying mask */
kevman 0:38ceb79fef03 1588 if( msb % 8 == 0 )
kevman 0:38ceb79fef03 1589 offset = 1;
kevman 0:38ceb79fef03 1590
kevman 0:38ceb79fef03 1591 /* maskedDB: Apply dbMask to DB */
kevman 0:38ceb79fef03 1592 if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen,
kevman 0:38ceb79fef03 1593 &md_ctx ) ) != 0 )
kevman 0:38ceb79fef03 1594 goto exit;
kevman 0:38ceb79fef03 1595
kevman 0:38ceb79fef03 1596 msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
kevman 0:38ceb79fef03 1597 sig[0] &= 0xFF >> ( olen * 8 - msb );
kevman 0:38ceb79fef03 1598
kevman 0:38ceb79fef03 1599 p += hlen;
kevman 0:38ceb79fef03 1600 *p++ = 0xBC;
kevman 0:38ceb79fef03 1601
kevman 0:38ceb79fef03 1602 mbedtls_platform_zeroize( salt, sizeof( salt ) );
kevman 0:38ceb79fef03 1603
kevman 0:38ceb79fef03 1604 exit:
kevman 0:38ceb79fef03 1605 mbedtls_md_free( &md_ctx );
kevman 0:38ceb79fef03 1606
kevman 0:38ceb79fef03 1607 if( ret != 0 )
kevman 0:38ceb79fef03 1608 return( ret );
kevman 0:38ceb79fef03 1609
kevman 0:38ceb79fef03 1610 return( ( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 1611 ? mbedtls_rsa_public( ctx, sig, sig )
kevman 0:38ceb79fef03 1612 : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
kevman 0:38ceb79fef03 1613 }
kevman 0:38ceb79fef03 1614 #endif /* MBEDTLS_PKCS1_V21 */
kevman 0:38ceb79fef03 1615
kevman 0:38ceb79fef03 1616 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 1617 /*
kevman 0:38ceb79fef03 1618 * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
kevman 0:38ceb79fef03 1619 */
kevman 0:38ceb79fef03 1620
kevman 0:38ceb79fef03 1621 /* Construct a PKCS v1.5 encoding of a hashed message
kevman 0:38ceb79fef03 1622 *
kevman 0:38ceb79fef03 1623 * This is used both for signature generation and verification.
kevman 0:38ceb79fef03 1624 *
kevman 0:38ceb79fef03 1625 * Parameters:
kevman 0:38ceb79fef03 1626 * - md_alg: Identifies the hash algorithm used to generate the given hash;
kevman 0:38ceb79fef03 1627 * MBEDTLS_MD_NONE if raw data is signed.
kevman 0:38ceb79fef03 1628 * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE.
kevman 0:38ceb79fef03 1629 * - hash: Buffer containing the hashed message or the raw data.
kevman 0:38ceb79fef03 1630 * - dst_len: Length of the encoded message.
kevman 0:38ceb79fef03 1631 * - dst: Buffer to hold the encoded message.
kevman 0:38ceb79fef03 1632 *
kevman 0:38ceb79fef03 1633 * Assumptions:
kevman 0:38ceb79fef03 1634 * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE.
kevman 0:38ceb79fef03 1635 * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE.
kevman 0:38ceb79fef03 1636 * - dst points to a buffer of size at least dst_len.
kevman 0:38ceb79fef03 1637 *
kevman 0:38ceb79fef03 1638 */
kevman 0:38ceb79fef03 1639 static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 1640 unsigned int hashlen,
kevman 0:38ceb79fef03 1641 const unsigned char *hash,
kevman 0:38ceb79fef03 1642 size_t dst_len,
kevman 0:38ceb79fef03 1643 unsigned char *dst )
kevman 0:38ceb79fef03 1644 {
kevman 0:38ceb79fef03 1645 size_t oid_size = 0;
kevman 0:38ceb79fef03 1646 size_t nb_pad = dst_len;
kevman 0:38ceb79fef03 1647 unsigned char *p = dst;
kevman 0:38ceb79fef03 1648 const char *oid = NULL;
kevman 0:38ceb79fef03 1649
kevman 0:38ceb79fef03 1650 /* Are we signing hashed or raw data? */
kevman 0:38ceb79fef03 1651 if( md_alg != MBEDTLS_MD_NONE )
kevman 0:38ceb79fef03 1652 {
kevman 0:38ceb79fef03 1653 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
kevman 0:38ceb79fef03 1654 if( md_info == NULL )
kevman 0:38ceb79fef03 1655 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1656
kevman 0:38ceb79fef03 1657 if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
kevman 0:38ceb79fef03 1658 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1659
kevman 0:38ceb79fef03 1660 hashlen = mbedtls_md_get_size( md_info );
kevman 0:38ceb79fef03 1661
kevman 0:38ceb79fef03 1662 /* Double-check that 8 + hashlen + oid_size can be used as a
kevman 0:38ceb79fef03 1663 * 1-byte ASN.1 length encoding and that there's no overflow. */
kevman 0:38ceb79fef03 1664 if( 8 + hashlen + oid_size >= 0x80 ||
kevman 0:38ceb79fef03 1665 10 + hashlen < hashlen ||
kevman 0:38ceb79fef03 1666 10 + hashlen + oid_size < 10 + hashlen )
kevman 0:38ceb79fef03 1667 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1668
kevman 0:38ceb79fef03 1669 /*
kevman 0:38ceb79fef03 1670 * Static bounds check:
kevman 0:38ceb79fef03 1671 * - Need 10 bytes for five tag-length pairs.
kevman 0:38ceb79fef03 1672 * (Insist on 1-byte length encodings to protect against variants of
kevman 0:38ceb79fef03 1673 * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification)
kevman 0:38ceb79fef03 1674 * - Need hashlen bytes for hash
kevman 0:38ceb79fef03 1675 * - Need oid_size bytes for hash alg OID.
kevman 0:38ceb79fef03 1676 */
kevman 0:38ceb79fef03 1677 if( nb_pad < 10 + hashlen + oid_size )
kevman 0:38ceb79fef03 1678 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1679 nb_pad -= 10 + hashlen + oid_size;
kevman 0:38ceb79fef03 1680 }
kevman 0:38ceb79fef03 1681 else
kevman 0:38ceb79fef03 1682 {
kevman 0:38ceb79fef03 1683 if( nb_pad < hashlen )
kevman 0:38ceb79fef03 1684 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1685
kevman 0:38ceb79fef03 1686 nb_pad -= hashlen;
kevman 0:38ceb79fef03 1687 }
kevman 0:38ceb79fef03 1688
kevman 0:38ceb79fef03 1689 /* Need space for signature header and padding delimiter (3 bytes),
kevman 0:38ceb79fef03 1690 * and 8 bytes for the minimal padding */
kevman 0:38ceb79fef03 1691 if( nb_pad < 3 + 8 )
kevman 0:38ceb79fef03 1692 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1693 nb_pad -= 3;
kevman 0:38ceb79fef03 1694
kevman 0:38ceb79fef03 1695 /* Now nb_pad is the amount of memory to be filled
kevman 0:38ceb79fef03 1696 * with padding, and at least 8 bytes long. */
kevman 0:38ceb79fef03 1697
kevman 0:38ceb79fef03 1698 /* Write signature header and padding */
kevman 0:38ceb79fef03 1699 *p++ = 0;
kevman 0:38ceb79fef03 1700 *p++ = MBEDTLS_RSA_SIGN;
kevman 0:38ceb79fef03 1701 memset( p, 0xFF, nb_pad );
kevman 0:38ceb79fef03 1702 p += nb_pad;
kevman 0:38ceb79fef03 1703 *p++ = 0;
kevman 0:38ceb79fef03 1704
kevman 0:38ceb79fef03 1705 /* Are we signing raw data? */
kevman 0:38ceb79fef03 1706 if( md_alg == MBEDTLS_MD_NONE )
kevman 0:38ceb79fef03 1707 {
kevman 0:38ceb79fef03 1708 memcpy( p, hash, hashlen );
kevman 0:38ceb79fef03 1709 return( 0 );
kevman 0:38ceb79fef03 1710 }
kevman 0:38ceb79fef03 1711
kevman 0:38ceb79fef03 1712 /* Signing hashed data, add corresponding ASN.1 structure
kevman 0:38ceb79fef03 1713 *
kevman 0:38ceb79fef03 1714 * DigestInfo ::= SEQUENCE {
kevman 0:38ceb79fef03 1715 * digestAlgorithm DigestAlgorithmIdentifier,
kevman 0:38ceb79fef03 1716 * digest Digest }
kevman 0:38ceb79fef03 1717 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
kevman 0:38ceb79fef03 1718 * Digest ::= OCTET STRING
kevman 0:38ceb79fef03 1719 *
kevman 0:38ceb79fef03 1720 * Schematic:
kevman 0:38ceb79fef03 1721 * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ]
kevman 0:38ceb79fef03 1722 * TAG-NULL + LEN [ NULL ] ]
kevman 0:38ceb79fef03 1723 * TAG-OCTET + LEN [ HASH ] ]
kevman 0:38ceb79fef03 1724 */
kevman 0:38ceb79fef03 1725 *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
kevman 0:38ceb79fef03 1726 *p++ = (unsigned char)( 0x08 + oid_size + hashlen );
kevman 0:38ceb79fef03 1727 *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
kevman 0:38ceb79fef03 1728 *p++ = (unsigned char)( 0x04 + oid_size );
kevman 0:38ceb79fef03 1729 *p++ = MBEDTLS_ASN1_OID;
kevman 0:38ceb79fef03 1730 *p++ = (unsigned char) oid_size;
kevman 0:38ceb79fef03 1731 memcpy( p, oid, oid_size );
kevman 0:38ceb79fef03 1732 p += oid_size;
kevman 0:38ceb79fef03 1733 *p++ = MBEDTLS_ASN1_NULL;
kevman 0:38ceb79fef03 1734 *p++ = 0x00;
kevman 0:38ceb79fef03 1735 *p++ = MBEDTLS_ASN1_OCTET_STRING;
kevman 0:38ceb79fef03 1736 *p++ = (unsigned char) hashlen;
kevman 0:38ceb79fef03 1737 memcpy( p, hash, hashlen );
kevman 0:38ceb79fef03 1738 p += hashlen;
kevman 0:38ceb79fef03 1739
kevman 0:38ceb79fef03 1740 /* Just a sanity-check, should be automatic
kevman 0:38ceb79fef03 1741 * after the initial bounds check. */
kevman 0:38ceb79fef03 1742 if( p != dst + dst_len )
kevman 0:38ceb79fef03 1743 {
kevman 0:38ceb79fef03 1744 mbedtls_platform_zeroize( dst, dst_len );
kevman 0:38ceb79fef03 1745 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1746 }
kevman 0:38ceb79fef03 1747
kevman 0:38ceb79fef03 1748 return( 0 );
kevman 0:38ceb79fef03 1749 }
kevman 0:38ceb79fef03 1750
kevman 0:38ceb79fef03 1751 /*
kevman 0:38ceb79fef03 1752 * Do an RSA operation to sign the message digest
kevman 0:38ceb79fef03 1753 */
kevman 0:38ceb79fef03 1754 int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1755 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1756 void *p_rng,
kevman 0:38ceb79fef03 1757 int mode,
kevman 0:38ceb79fef03 1758 mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 1759 unsigned int hashlen,
kevman 0:38ceb79fef03 1760 const unsigned char *hash,
kevman 0:38ceb79fef03 1761 unsigned char *sig )
kevman 0:38ceb79fef03 1762 {
kevman 0:38ceb79fef03 1763 int ret;
kevman 0:38ceb79fef03 1764 unsigned char *sig_try = NULL, *verif = NULL;
kevman 0:38ceb79fef03 1765
kevman 0:38ceb79fef03 1766 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
kevman 0:38ceb79fef03 1767 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1768
kevman 0:38ceb79fef03 1769 /*
kevman 0:38ceb79fef03 1770 * Prepare PKCS1-v1.5 encoding (padding and hash identifier)
kevman 0:38ceb79fef03 1771 */
kevman 0:38ceb79fef03 1772
kevman 0:38ceb79fef03 1773 if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash,
kevman 0:38ceb79fef03 1774 ctx->len, sig ) ) != 0 )
kevman 0:38ceb79fef03 1775 return( ret );
kevman 0:38ceb79fef03 1776
kevman 0:38ceb79fef03 1777 /*
kevman 0:38ceb79fef03 1778 * Call respective RSA primitive
kevman 0:38ceb79fef03 1779 */
kevman 0:38ceb79fef03 1780
kevman 0:38ceb79fef03 1781 if( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 1782 {
kevman 0:38ceb79fef03 1783 /* Skip verification on a public key operation */
kevman 0:38ceb79fef03 1784 return( mbedtls_rsa_public( ctx, sig, sig ) );
kevman 0:38ceb79fef03 1785 }
kevman 0:38ceb79fef03 1786
kevman 0:38ceb79fef03 1787 /* Private key operation
kevman 0:38ceb79fef03 1788 *
kevman 0:38ceb79fef03 1789 * In order to prevent Lenstra's attack, make the signature in a
kevman 0:38ceb79fef03 1790 * temporary buffer and check it before returning it.
kevman 0:38ceb79fef03 1791 */
kevman 0:38ceb79fef03 1792
kevman 0:38ceb79fef03 1793 sig_try = mbedtls_calloc( 1, ctx->len );
kevman 0:38ceb79fef03 1794 if( sig_try == NULL )
kevman 0:38ceb79fef03 1795 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
kevman 0:38ceb79fef03 1796
kevman 0:38ceb79fef03 1797 verif = mbedtls_calloc( 1, ctx->len );
kevman 0:38ceb79fef03 1798 if( verif == NULL )
kevman 0:38ceb79fef03 1799 {
kevman 0:38ceb79fef03 1800 mbedtls_free( sig_try );
kevman 0:38ceb79fef03 1801 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
kevman 0:38ceb79fef03 1802 }
kevman 0:38ceb79fef03 1803
kevman 0:38ceb79fef03 1804 MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) );
kevman 0:38ceb79fef03 1805 MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) );
kevman 0:38ceb79fef03 1806
kevman 0:38ceb79fef03 1807 if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 )
kevman 0:38ceb79fef03 1808 {
kevman 0:38ceb79fef03 1809 ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
kevman 0:38ceb79fef03 1810 goto cleanup;
kevman 0:38ceb79fef03 1811 }
kevman 0:38ceb79fef03 1812
kevman 0:38ceb79fef03 1813 memcpy( sig, sig_try, ctx->len );
kevman 0:38ceb79fef03 1814
kevman 0:38ceb79fef03 1815 cleanup:
kevman 0:38ceb79fef03 1816 mbedtls_free( sig_try );
kevman 0:38ceb79fef03 1817 mbedtls_free( verif );
kevman 0:38ceb79fef03 1818
kevman 0:38ceb79fef03 1819 return( ret );
kevman 0:38ceb79fef03 1820 }
kevman 0:38ceb79fef03 1821 #endif /* MBEDTLS_PKCS1_V15 */
kevman 0:38ceb79fef03 1822
kevman 0:38ceb79fef03 1823 /*
kevman 0:38ceb79fef03 1824 * Do an RSA operation to sign the message digest
kevman 0:38ceb79fef03 1825 */
kevman 0:38ceb79fef03 1826 int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1827 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1828 void *p_rng,
kevman 0:38ceb79fef03 1829 int mode,
kevman 0:38ceb79fef03 1830 mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 1831 unsigned int hashlen,
kevman 0:38ceb79fef03 1832 const unsigned char *hash,
kevman 0:38ceb79fef03 1833 unsigned char *sig )
kevman 0:38ceb79fef03 1834 {
kevman 0:38ceb79fef03 1835 switch( ctx->padding )
kevman 0:38ceb79fef03 1836 {
kevman 0:38ceb79fef03 1837 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 1838 case MBEDTLS_RSA_PKCS_V15:
kevman 0:38ceb79fef03 1839 return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg,
kevman 0:38ceb79fef03 1840 hashlen, hash, sig );
kevman 0:38ceb79fef03 1841 #endif
kevman 0:38ceb79fef03 1842
kevman 0:38ceb79fef03 1843 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 1844 case MBEDTLS_RSA_PKCS_V21:
kevman 0:38ceb79fef03 1845 return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg,
kevman 0:38ceb79fef03 1846 hashlen, hash, sig );
kevman 0:38ceb79fef03 1847 #endif
kevman 0:38ceb79fef03 1848
kevman 0:38ceb79fef03 1849 default:
kevman 0:38ceb79fef03 1850 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
kevman 0:38ceb79fef03 1851 }
kevman 0:38ceb79fef03 1852 }
kevman 0:38ceb79fef03 1853
kevman 0:38ceb79fef03 1854 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 1855 /*
kevman 0:38ceb79fef03 1856 * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
kevman 0:38ceb79fef03 1857 */
kevman 0:38ceb79fef03 1858 int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 1859 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 1860 void *p_rng,
kevman 0:38ceb79fef03 1861 int mode,
kevman 0:38ceb79fef03 1862 mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 1863 unsigned int hashlen,
kevman 0:38ceb79fef03 1864 const unsigned char *hash,
kevman 0:38ceb79fef03 1865 mbedtls_md_type_t mgf1_hash_id,
kevman 0:38ceb79fef03 1866 int expected_salt_len,
kevman 0:38ceb79fef03 1867 const unsigned char *sig )
kevman 0:38ceb79fef03 1868 {
kevman 0:38ceb79fef03 1869 int ret;
kevman 0:38ceb79fef03 1870 size_t siglen;
kevman 0:38ceb79fef03 1871 unsigned char *p;
kevman 0:38ceb79fef03 1872 unsigned char *hash_start;
kevman 0:38ceb79fef03 1873 unsigned char result[MBEDTLS_MD_MAX_SIZE];
kevman 0:38ceb79fef03 1874 unsigned char zeros[8];
kevman 0:38ceb79fef03 1875 unsigned int hlen;
kevman 0:38ceb79fef03 1876 size_t observed_salt_len, msb;
kevman 0:38ceb79fef03 1877 const mbedtls_md_info_t *md_info;
kevman 0:38ceb79fef03 1878 mbedtls_md_context_t md_ctx;
kevman 0:38ceb79fef03 1879 unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
kevman 0:38ceb79fef03 1880
kevman 0:38ceb79fef03 1881 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
kevman 0:38ceb79fef03 1882 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1883
kevman 0:38ceb79fef03 1884 siglen = ctx->len;
kevman 0:38ceb79fef03 1885
kevman 0:38ceb79fef03 1886 if( siglen < 16 || siglen > sizeof( buf ) )
kevman 0:38ceb79fef03 1887 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1888
kevman 0:38ceb79fef03 1889 ret = ( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 1890 ? mbedtls_rsa_public( ctx, sig, buf )
kevman 0:38ceb79fef03 1891 : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf );
kevman 0:38ceb79fef03 1892
kevman 0:38ceb79fef03 1893 if( ret != 0 )
kevman 0:38ceb79fef03 1894 return( ret );
kevman 0:38ceb79fef03 1895
kevman 0:38ceb79fef03 1896 p = buf;
kevman 0:38ceb79fef03 1897
kevman 0:38ceb79fef03 1898 if( buf[siglen - 1] != 0xBC )
kevman 0:38ceb79fef03 1899 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
kevman 0:38ceb79fef03 1900
kevman 0:38ceb79fef03 1901 if( md_alg != MBEDTLS_MD_NONE )
kevman 0:38ceb79fef03 1902 {
kevman 0:38ceb79fef03 1903 /* Gather length of hash to sign */
kevman 0:38ceb79fef03 1904 md_info = mbedtls_md_info_from_type( md_alg );
kevman 0:38ceb79fef03 1905 if( md_info == NULL )
kevman 0:38ceb79fef03 1906 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1907
kevman 0:38ceb79fef03 1908 hashlen = mbedtls_md_get_size( md_info );
kevman 0:38ceb79fef03 1909 }
kevman 0:38ceb79fef03 1910
kevman 0:38ceb79fef03 1911 md_info = mbedtls_md_info_from_type( mgf1_hash_id );
kevman 0:38ceb79fef03 1912 if( md_info == NULL )
kevman 0:38ceb79fef03 1913 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1914
kevman 0:38ceb79fef03 1915 hlen = mbedtls_md_get_size( md_info );
kevman 0:38ceb79fef03 1916
kevman 0:38ceb79fef03 1917 memset( zeros, 0, 8 );
kevman 0:38ceb79fef03 1918
kevman 0:38ceb79fef03 1919 /*
kevman 0:38ceb79fef03 1920 * Note: EMSA-PSS verification is over the length of N - 1 bits
kevman 0:38ceb79fef03 1921 */
kevman 0:38ceb79fef03 1922 msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
kevman 0:38ceb79fef03 1923
kevman 0:38ceb79fef03 1924 if( buf[0] >> ( 8 - siglen * 8 + msb ) )
kevman 0:38ceb79fef03 1925 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1926
kevman 0:38ceb79fef03 1927 /* Compensate for boundary condition when applying mask */
kevman 0:38ceb79fef03 1928 if( msb % 8 == 0 )
kevman 0:38ceb79fef03 1929 {
kevman 0:38ceb79fef03 1930 p++;
kevman 0:38ceb79fef03 1931 siglen -= 1;
kevman 0:38ceb79fef03 1932 }
kevman 0:38ceb79fef03 1933
kevman 0:38ceb79fef03 1934 if( siglen < hlen + 2 )
kevman 0:38ceb79fef03 1935 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 1936 hash_start = p + siglen - hlen - 1;
kevman 0:38ceb79fef03 1937
kevman 0:38ceb79fef03 1938 mbedtls_md_init( &md_ctx );
kevman 0:38ceb79fef03 1939 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
kevman 0:38ceb79fef03 1940 goto exit;
kevman 0:38ceb79fef03 1941
kevman 0:38ceb79fef03 1942 ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx );
kevman 0:38ceb79fef03 1943 if( ret != 0 )
kevman 0:38ceb79fef03 1944 goto exit;
kevman 0:38ceb79fef03 1945
kevman 0:38ceb79fef03 1946 buf[0] &= 0xFF >> ( siglen * 8 - msb );
kevman 0:38ceb79fef03 1947
kevman 0:38ceb79fef03 1948 while( p < hash_start - 1 && *p == 0 )
kevman 0:38ceb79fef03 1949 p++;
kevman 0:38ceb79fef03 1950
kevman 0:38ceb79fef03 1951 if( *p++ != 0x01 )
kevman 0:38ceb79fef03 1952 {
kevman 0:38ceb79fef03 1953 ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
kevman 0:38ceb79fef03 1954 goto exit;
kevman 0:38ceb79fef03 1955 }
kevman 0:38ceb79fef03 1956
kevman 0:38ceb79fef03 1957 observed_salt_len = hash_start - p;
kevman 0:38ceb79fef03 1958
kevman 0:38ceb79fef03 1959 if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&
kevman 0:38ceb79fef03 1960 observed_salt_len != (size_t) expected_salt_len )
kevman 0:38ceb79fef03 1961 {
kevman 0:38ceb79fef03 1962 ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
kevman 0:38ceb79fef03 1963 goto exit;
kevman 0:38ceb79fef03 1964 }
kevman 0:38ceb79fef03 1965
kevman 0:38ceb79fef03 1966 /*
kevman 0:38ceb79fef03 1967 * Generate H = Hash( M' )
kevman 0:38ceb79fef03 1968 */
kevman 0:38ceb79fef03 1969 ret = mbedtls_md_starts( &md_ctx );
kevman 0:38ceb79fef03 1970 if ( ret != 0 )
kevman 0:38ceb79fef03 1971 goto exit;
kevman 0:38ceb79fef03 1972 ret = mbedtls_md_update( &md_ctx, zeros, 8 );
kevman 0:38ceb79fef03 1973 if ( ret != 0 )
kevman 0:38ceb79fef03 1974 goto exit;
kevman 0:38ceb79fef03 1975 ret = mbedtls_md_update( &md_ctx, hash, hashlen );
kevman 0:38ceb79fef03 1976 if ( ret != 0 )
kevman 0:38ceb79fef03 1977 goto exit;
kevman 0:38ceb79fef03 1978 ret = mbedtls_md_update( &md_ctx, p, observed_salt_len );
kevman 0:38ceb79fef03 1979 if ( ret != 0 )
kevman 0:38ceb79fef03 1980 goto exit;
kevman 0:38ceb79fef03 1981 ret = mbedtls_md_finish( &md_ctx, result );
kevman 0:38ceb79fef03 1982 if ( ret != 0 )
kevman 0:38ceb79fef03 1983 goto exit;
kevman 0:38ceb79fef03 1984
kevman 0:38ceb79fef03 1985 if( memcmp( hash_start, result, hlen ) != 0 )
kevman 0:38ceb79fef03 1986 {
kevman 0:38ceb79fef03 1987 ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
kevman 0:38ceb79fef03 1988 goto exit;
kevman 0:38ceb79fef03 1989 }
kevman 0:38ceb79fef03 1990
kevman 0:38ceb79fef03 1991 exit:
kevman 0:38ceb79fef03 1992 mbedtls_md_free( &md_ctx );
kevman 0:38ceb79fef03 1993
kevman 0:38ceb79fef03 1994 return( ret );
kevman 0:38ceb79fef03 1995 }
kevman 0:38ceb79fef03 1996
kevman 0:38ceb79fef03 1997 /*
kevman 0:38ceb79fef03 1998 * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function
kevman 0:38ceb79fef03 1999 */
kevman 0:38ceb79fef03 2000 int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 2001 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 2002 void *p_rng,
kevman 0:38ceb79fef03 2003 int mode,
kevman 0:38ceb79fef03 2004 mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 2005 unsigned int hashlen,
kevman 0:38ceb79fef03 2006 const unsigned char *hash,
kevman 0:38ceb79fef03 2007 const unsigned char *sig )
kevman 0:38ceb79fef03 2008 {
kevman 0:38ceb79fef03 2009 mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE )
kevman 0:38ceb79fef03 2010 ? (mbedtls_md_type_t) ctx->hash_id
kevman 0:38ceb79fef03 2011 : md_alg;
kevman 0:38ceb79fef03 2012
kevman 0:38ceb79fef03 2013 return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode,
kevman 0:38ceb79fef03 2014 md_alg, hashlen, hash,
kevman 0:38ceb79fef03 2015 mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY,
kevman 0:38ceb79fef03 2016 sig ) );
kevman 0:38ceb79fef03 2017
kevman 0:38ceb79fef03 2018 }
kevman 0:38ceb79fef03 2019 #endif /* MBEDTLS_PKCS1_V21 */
kevman 0:38ceb79fef03 2020
kevman 0:38ceb79fef03 2021 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 2022 /*
kevman 0:38ceb79fef03 2023 * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
kevman 0:38ceb79fef03 2024 */
kevman 0:38ceb79fef03 2025 int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 2026 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 2027 void *p_rng,
kevman 0:38ceb79fef03 2028 int mode,
kevman 0:38ceb79fef03 2029 mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 2030 unsigned int hashlen,
kevman 0:38ceb79fef03 2031 const unsigned char *hash,
kevman 0:38ceb79fef03 2032 const unsigned char *sig )
kevman 0:38ceb79fef03 2033 {
kevman 0:38ceb79fef03 2034 int ret = 0;
kevman 0:38ceb79fef03 2035 const size_t sig_len = ctx->len;
kevman 0:38ceb79fef03 2036 unsigned char *encoded = NULL, *encoded_expected = NULL;
kevman 0:38ceb79fef03 2037
kevman 0:38ceb79fef03 2038 if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
kevman 0:38ceb79fef03 2039 return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
kevman 0:38ceb79fef03 2040
kevman 0:38ceb79fef03 2041 /*
kevman 0:38ceb79fef03 2042 * Prepare expected PKCS1 v1.5 encoding of hash.
kevman 0:38ceb79fef03 2043 */
kevman 0:38ceb79fef03 2044
kevman 0:38ceb79fef03 2045 if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL ||
kevman 0:38ceb79fef03 2046 ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL )
kevman 0:38ceb79fef03 2047 {
kevman 0:38ceb79fef03 2048 ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
kevman 0:38ceb79fef03 2049 goto cleanup;
kevman 0:38ceb79fef03 2050 }
kevman 0:38ceb79fef03 2051
kevman 0:38ceb79fef03 2052 if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len,
kevman 0:38ceb79fef03 2053 encoded_expected ) ) != 0 )
kevman 0:38ceb79fef03 2054 goto cleanup;
kevman 0:38ceb79fef03 2055
kevman 0:38ceb79fef03 2056 /*
kevman 0:38ceb79fef03 2057 * Apply RSA primitive to get what should be PKCS1 encoded hash.
kevman 0:38ceb79fef03 2058 */
kevman 0:38ceb79fef03 2059
kevman 0:38ceb79fef03 2060 ret = ( mode == MBEDTLS_RSA_PUBLIC )
kevman 0:38ceb79fef03 2061 ? mbedtls_rsa_public( ctx, sig, encoded )
kevman 0:38ceb79fef03 2062 : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded );
kevman 0:38ceb79fef03 2063 if( ret != 0 )
kevman 0:38ceb79fef03 2064 goto cleanup;
kevman 0:38ceb79fef03 2065
kevman 0:38ceb79fef03 2066 /*
kevman 0:38ceb79fef03 2067 * Compare
kevman 0:38ceb79fef03 2068 */
kevman 0:38ceb79fef03 2069
kevman 0:38ceb79fef03 2070 if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected,
kevman 0:38ceb79fef03 2071 sig_len ) ) != 0 )
kevman 0:38ceb79fef03 2072 {
kevman 0:38ceb79fef03 2073 ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
kevman 0:38ceb79fef03 2074 goto cleanup;
kevman 0:38ceb79fef03 2075 }
kevman 0:38ceb79fef03 2076
kevman 0:38ceb79fef03 2077 cleanup:
kevman 0:38ceb79fef03 2078
kevman 0:38ceb79fef03 2079 if( encoded != NULL )
kevman 0:38ceb79fef03 2080 {
kevman 0:38ceb79fef03 2081 mbedtls_platform_zeroize( encoded, sig_len );
kevman 0:38ceb79fef03 2082 mbedtls_free( encoded );
kevman 0:38ceb79fef03 2083 }
kevman 0:38ceb79fef03 2084
kevman 0:38ceb79fef03 2085 if( encoded_expected != NULL )
kevman 0:38ceb79fef03 2086 {
kevman 0:38ceb79fef03 2087 mbedtls_platform_zeroize( encoded_expected, sig_len );
kevman 0:38ceb79fef03 2088 mbedtls_free( encoded_expected );
kevman 0:38ceb79fef03 2089 }
kevman 0:38ceb79fef03 2090
kevman 0:38ceb79fef03 2091 return( ret );
kevman 0:38ceb79fef03 2092 }
kevman 0:38ceb79fef03 2093 #endif /* MBEDTLS_PKCS1_V15 */
kevman 0:38ceb79fef03 2094
kevman 0:38ceb79fef03 2095 /*
kevman 0:38ceb79fef03 2096 * Do an RSA operation and check the message digest
kevman 0:38ceb79fef03 2097 */
kevman 0:38ceb79fef03 2098 int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
kevman 0:38ceb79fef03 2099 int (*f_rng)(void *, unsigned char *, size_t),
kevman 0:38ceb79fef03 2100 void *p_rng,
kevman 0:38ceb79fef03 2101 int mode,
kevman 0:38ceb79fef03 2102 mbedtls_md_type_t md_alg,
kevman 0:38ceb79fef03 2103 unsigned int hashlen,
kevman 0:38ceb79fef03 2104 const unsigned char *hash,
kevman 0:38ceb79fef03 2105 const unsigned char *sig )
kevman 0:38ceb79fef03 2106 {
kevman 0:38ceb79fef03 2107 switch( ctx->padding )
kevman 0:38ceb79fef03 2108 {
kevman 0:38ceb79fef03 2109 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 2110 case MBEDTLS_RSA_PKCS_V15:
kevman 0:38ceb79fef03 2111 return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg,
kevman 0:38ceb79fef03 2112 hashlen, hash, sig );
kevman 0:38ceb79fef03 2113 #endif
kevman 0:38ceb79fef03 2114
kevman 0:38ceb79fef03 2115 #if defined(MBEDTLS_PKCS1_V21)
kevman 0:38ceb79fef03 2116 case MBEDTLS_RSA_PKCS_V21:
kevman 0:38ceb79fef03 2117 return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg,
kevman 0:38ceb79fef03 2118 hashlen, hash, sig );
kevman 0:38ceb79fef03 2119 #endif
kevman 0:38ceb79fef03 2120
kevman 0:38ceb79fef03 2121 default:
kevman 0:38ceb79fef03 2122 return( MBEDTLS_ERR_RSA_INVALID_PADDING );
kevman 0:38ceb79fef03 2123 }
kevman 0:38ceb79fef03 2124 }
kevman 0:38ceb79fef03 2125
kevman 0:38ceb79fef03 2126 /*
kevman 0:38ceb79fef03 2127 * Copy the components of an RSA key
kevman 0:38ceb79fef03 2128 */
kevman 0:38ceb79fef03 2129 int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
kevman 0:38ceb79fef03 2130 {
kevman 0:38ceb79fef03 2131 int ret;
kevman 0:38ceb79fef03 2132
kevman 0:38ceb79fef03 2133 dst->ver = src->ver;
kevman 0:38ceb79fef03 2134 dst->len = src->len;
kevman 0:38ceb79fef03 2135
kevman 0:38ceb79fef03 2136 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
kevman 0:38ceb79fef03 2137 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) );
kevman 0:38ceb79fef03 2138
kevman 0:38ceb79fef03 2139 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) );
kevman 0:38ceb79fef03 2140 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) );
kevman 0:38ceb79fef03 2141 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) );
kevman 0:38ceb79fef03 2142
kevman 0:38ceb79fef03 2143 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 2144 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) );
kevman 0:38ceb79fef03 2145 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) );
kevman 0:38ceb79fef03 2146 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) );
kevman 0:38ceb79fef03 2147 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) );
kevman 0:38ceb79fef03 2148 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) );
kevman 0:38ceb79fef03 2149 #endif
kevman 0:38ceb79fef03 2150
kevman 0:38ceb79fef03 2151 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) );
kevman 0:38ceb79fef03 2152
kevman 0:38ceb79fef03 2153 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) );
kevman 0:38ceb79fef03 2154 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) );
kevman 0:38ceb79fef03 2155
kevman 0:38ceb79fef03 2156 dst->padding = src->padding;
kevman 0:38ceb79fef03 2157 dst->hash_id = src->hash_id;
kevman 0:38ceb79fef03 2158
kevman 0:38ceb79fef03 2159 cleanup:
kevman 0:38ceb79fef03 2160 if( ret != 0 )
kevman 0:38ceb79fef03 2161 mbedtls_rsa_free( dst );
kevman 0:38ceb79fef03 2162
kevman 0:38ceb79fef03 2163 return( ret );
kevman 0:38ceb79fef03 2164 }
kevman 0:38ceb79fef03 2165
kevman 0:38ceb79fef03 2166 /*
kevman 0:38ceb79fef03 2167 * Free the components of an RSA key
kevman 0:38ceb79fef03 2168 */
kevman 0:38ceb79fef03 2169 void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
kevman 0:38ceb79fef03 2170 {
kevman 0:38ceb79fef03 2171 mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf );
kevman 0:38ceb79fef03 2172 mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->D );
kevman 0:38ceb79fef03 2173 mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P );
kevman 0:38ceb79fef03 2174 mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N );
kevman 0:38ceb79fef03 2175
kevman 0:38ceb79fef03 2176 #if !defined(MBEDTLS_RSA_NO_CRT)
kevman 0:38ceb79fef03 2177 mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP );
kevman 0:38ceb79fef03 2178 mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ );
kevman 0:38ceb79fef03 2179 mbedtls_mpi_free( &ctx->DP );
kevman 0:38ceb79fef03 2180 #endif /* MBEDTLS_RSA_NO_CRT */
kevman 0:38ceb79fef03 2181
kevman 0:38ceb79fef03 2182 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 2183 mbedtls_mutex_free( &ctx->mutex );
kevman 0:38ceb79fef03 2184 #endif
kevman 0:38ceb79fef03 2185 }
kevman 0:38ceb79fef03 2186
kevman 0:38ceb79fef03 2187 #endif /* !MBEDTLS_RSA_ALT */
kevman 0:38ceb79fef03 2188
kevman 0:38ceb79fef03 2189 #if defined(MBEDTLS_SELF_TEST)
kevman 0:38ceb79fef03 2190
kevman 0:38ceb79fef03 2191 #include "mbedtls/sha1.h"
kevman 0:38ceb79fef03 2192
kevman 0:38ceb79fef03 2193 /*
kevman 0:38ceb79fef03 2194 * Example RSA-1024 keypair, for test purposes
kevman 0:38ceb79fef03 2195 */
kevman 0:38ceb79fef03 2196 #define KEY_LEN 128
kevman 0:38ceb79fef03 2197
kevman 0:38ceb79fef03 2198 #define RSA_N "9292758453063D803DD603D5E777D788" \
kevman 0:38ceb79fef03 2199 "8ED1D5BF35786190FA2F23EBC0848AEA" \
kevman 0:38ceb79fef03 2200 "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
kevman 0:38ceb79fef03 2201 "7130B9CED7ACDF54CFC7555AC14EEBAB" \
kevman 0:38ceb79fef03 2202 "93A89813FBF3C4F8066D2D800F7C38A8" \
kevman 0:38ceb79fef03 2203 "1AE31942917403FF4946B0A83D3D3E05" \
kevman 0:38ceb79fef03 2204 "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
kevman 0:38ceb79fef03 2205 "5E94BB77B07507233A0BC7BAC8F90F79"
kevman 0:38ceb79fef03 2206
kevman 0:38ceb79fef03 2207 #define RSA_E "10001"
kevman 0:38ceb79fef03 2208
kevman 0:38ceb79fef03 2209 #define RSA_D "24BF6185468786FDD303083D25E64EFC" \
kevman 0:38ceb79fef03 2210 "66CA472BC44D253102F8B4A9D3BFA750" \
kevman 0:38ceb79fef03 2211 "91386C0077937FE33FA3252D28855837" \
kevman 0:38ceb79fef03 2212 "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
kevman 0:38ceb79fef03 2213 "DF79C5CE07EE72C7F123142198164234" \
kevman 0:38ceb79fef03 2214 "CABB724CF78B8173B9F880FC86322407" \
kevman 0:38ceb79fef03 2215 "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
kevman 0:38ceb79fef03 2216 "071513A1E85B5DFA031F21ECAE91A34D"
kevman 0:38ceb79fef03 2217
kevman 0:38ceb79fef03 2218 #define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
kevman 0:38ceb79fef03 2219 "2C01CAD19EA484A87EA4377637E75500" \
kevman 0:38ceb79fef03 2220 "FCB2005C5C7DD6EC4AC023CDA285D796" \
kevman 0:38ceb79fef03 2221 "C3D9E75E1EFC42488BB4F1D13AC30A57"
kevman 0:38ceb79fef03 2222
kevman 0:38ceb79fef03 2223 #define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
kevman 0:38ceb79fef03 2224 "E211C2B9E5DB1ED0BF61D0D9899620F4" \
kevman 0:38ceb79fef03 2225 "910E4168387E3C30AA1E00C339A79508" \
kevman 0:38ceb79fef03 2226 "8452DD96A9A5EA5D9DCA68DA636032AF"
kevman 0:38ceb79fef03 2227
kevman 0:38ceb79fef03 2228 #define PT_LEN 24
kevman 0:38ceb79fef03 2229 #define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
kevman 0:38ceb79fef03 2230 "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
kevman 0:38ceb79fef03 2231
kevman 0:38ceb79fef03 2232 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 2233 static int myrand( void *rng_state, unsigned char *output, size_t len )
kevman 0:38ceb79fef03 2234 {
kevman 0:38ceb79fef03 2235 #if !defined(__OpenBSD__)
kevman 0:38ceb79fef03 2236 size_t i;
kevman 0:38ceb79fef03 2237
kevman 0:38ceb79fef03 2238 if( rng_state != NULL )
kevman 0:38ceb79fef03 2239 rng_state = NULL;
kevman 0:38ceb79fef03 2240
kevman 0:38ceb79fef03 2241 for( i = 0; i < len; ++i )
kevman 0:38ceb79fef03 2242 output[i] = rand();
kevman 0:38ceb79fef03 2243 #else
kevman 0:38ceb79fef03 2244 if( rng_state != NULL )
kevman 0:38ceb79fef03 2245 rng_state = NULL;
kevman 0:38ceb79fef03 2246
kevman 0:38ceb79fef03 2247 arc4random_buf( output, len );
kevman 0:38ceb79fef03 2248 #endif /* !OpenBSD */
kevman 0:38ceb79fef03 2249
kevman 0:38ceb79fef03 2250 return( 0 );
kevman 0:38ceb79fef03 2251 }
kevman 0:38ceb79fef03 2252 #endif /* MBEDTLS_PKCS1_V15 */
kevman 0:38ceb79fef03 2253
kevman 0:38ceb79fef03 2254 /*
kevman 0:38ceb79fef03 2255 * Checkup routine
kevman 0:38ceb79fef03 2256 */
kevman 0:38ceb79fef03 2257 int mbedtls_rsa_self_test( int verbose )
kevman 0:38ceb79fef03 2258 {
kevman 0:38ceb79fef03 2259 int ret = 0;
kevman 0:38ceb79fef03 2260 #if defined(MBEDTLS_PKCS1_V15)
kevman 0:38ceb79fef03 2261 size_t len;
kevman 0:38ceb79fef03 2262 mbedtls_rsa_context rsa;
kevman 0:38ceb79fef03 2263 unsigned char rsa_plaintext[PT_LEN];
kevman 0:38ceb79fef03 2264 unsigned char rsa_decrypted[PT_LEN];
kevman 0:38ceb79fef03 2265 unsigned char rsa_ciphertext[KEY_LEN];
kevman 0:38ceb79fef03 2266 #if defined(MBEDTLS_SHA1_C)
kevman 0:38ceb79fef03 2267 unsigned char sha1sum[20];
kevman 0:38ceb79fef03 2268 #endif
kevman 0:38ceb79fef03 2269
kevman 0:38ceb79fef03 2270 mbedtls_mpi K;
kevman 0:38ceb79fef03 2271
kevman 0:38ceb79fef03 2272 mbedtls_mpi_init( &K );
kevman 0:38ceb79fef03 2273 mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
kevman 0:38ceb79fef03 2274
kevman 0:38ceb79fef03 2275 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) );
kevman 0:38ceb79fef03 2276 MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) );
kevman 0:38ceb79fef03 2277 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) );
kevman 0:38ceb79fef03 2278 MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) );
kevman 0:38ceb79fef03 2279 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) );
kevman 0:38ceb79fef03 2280 MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) );
kevman 0:38ceb79fef03 2281 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) );
kevman 0:38ceb79fef03 2282 MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) );
kevman 0:38ceb79fef03 2283 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) );
kevman 0:38ceb79fef03 2284 MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) );
kevman 0:38ceb79fef03 2285
kevman 0:38ceb79fef03 2286 MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) );
kevman 0:38ceb79fef03 2287
kevman 0:38ceb79fef03 2288 if( verbose != 0 )
kevman 0:38ceb79fef03 2289 mbedtls_printf( " RSA key validation: " );
kevman 0:38ceb79fef03 2290
kevman 0:38ceb79fef03 2291 if( mbedtls_rsa_check_pubkey( &rsa ) != 0 ||
kevman 0:38ceb79fef03 2292 mbedtls_rsa_check_privkey( &rsa ) != 0 )
kevman 0:38ceb79fef03 2293 {
kevman 0:38ceb79fef03 2294 if( verbose != 0 )
kevman 0:38ceb79fef03 2295 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 2296
kevman 0:38ceb79fef03 2297 ret = 1;
kevman 0:38ceb79fef03 2298 goto cleanup;
kevman 0:38ceb79fef03 2299 }
kevman 0:38ceb79fef03 2300
kevman 0:38ceb79fef03 2301 if( verbose != 0 )
kevman 0:38ceb79fef03 2302 mbedtls_printf( "passed\n PKCS#1 encryption : " );
kevman 0:38ceb79fef03 2303
kevman 0:38ceb79fef03 2304 memcpy( rsa_plaintext, RSA_PT, PT_LEN );
kevman 0:38ceb79fef03 2305
kevman 0:38ceb79fef03 2306 if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC,
kevman 0:38ceb79fef03 2307 PT_LEN, rsa_plaintext,
kevman 0:38ceb79fef03 2308 rsa_ciphertext ) != 0 )
kevman 0:38ceb79fef03 2309 {
kevman 0:38ceb79fef03 2310 if( verbose != 0 )
kevman 0:38ceb79fef03 2311 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 2312
kevman 0:38ceb79fef03 2313 ret = 1;
kevman 0:38ceb79fef03 2314 goto cleanup;
kevman 0:38ceb79fef03 2315 }
kevman 0:38ceb79fef03 2316
kevman 0:38ceb79fef03 2317 if( verbose != 0 )
kevman 0:38ceb79fef03 2318 mbedtls_printf( "passed\n PKCS#1 decryption : " );
kevman 0:38ceb79fef03 2319
kevman 0:38ceb79fef03 2320 if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE,
kevman 0:38ceb79fef03 2321 &len, rsa_ciphertext, rsa_decrypted,
kevman 0:38ceb79fef03 2322 sizeof(rsa_decrypted) ) != 0 )
kevman 0:38ceb79fef03 2323 {
kevman 0:38ceb79fef03 2324 if( verbose != 0 )
kevman 0:38ceb79fef03 2325 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 2326
kevman 0:38ceb79fef03 2327 ret = 1;
kevman 0:38ceb79fef03 2328 goto cleanup;
kevman 0:38ceb79fef03 2329 }
kevman 0:38ceb79fef03 2330
kevman 0:38ceb79fef03 2331 if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
kevman 0:38ceb79fef03 2332 {
kevman 0:38ceb79fef03 2333 if( verbose != 0 )
kevman 0:38ceb79fef03 2334 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 2335
kevman 0:38ceb79fef03 2336 ret = 1;
kevman 0:38ceb79fef03 2337 goto cleanup;
kevman 0:38ceb79fef03 2338 }
kevman 0:38ceb79fef03 2339
kevman 0:38ceb79fef03 2340 if( verbose != 0 )
kevman 0:38ceb79fef03 2341 mbedtls_printf( "passed\n" );
kevman 0:38ceb79fef03 2342
kevman 0:38ceb79fef03 2343 #if defined(MBEDTLS_SHA1_C)
kevman 0:38ceb79fef03 2344 if( verbose != 0 )
kevman 0:38ceb79fef03 2345 mbedtls_printf( " PKCS#1 data sign : " );
kevman 0:38ceb79fef03 2346
kevman 0:38ceb79fef03 2347 if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 )
kevman 0:38ceb79fef03 2348 {
kevman 0:38ceb79fef03 2349 if( verbose != 0 )
kevman 0:38ceb79fef03 2350 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 2351
kevman 0:38ceb79fef03 2352 return( 1 );
kevman 0:38ceb79fef03 2353 }
kevman 0:38ceb79fef03 2354
kevman 0:38ceb79fef03 2355 if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL,
kevman 0:38ceb79fef03 2356 MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0,
kevman 0:38ceb79fef03 2357 sha1sum, rsa_ciphertext ) != 0 )
kevman 0:38ceb79fef03 2358 {
kevman 0:38ceb79fef03 2359 if( verbose != 0 )
kevman 0:38ceb79fef03 2360 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 2361
kevman 0:38ceb79fef03 2362 ret = 1;
kevman 0:38ceb79fef03 2363 goto cleanup;
kevman 0:38ceb79fef03 2364 }
kevman 0:38ceb79fef03 2365
kevman 0:38ceb79fef03 2366 if( verbose != 0 )
kevman 0:38ceb79fef03 2367 mbedtls_printf( "passed\n PKCS#1 sig. verify: " );
kevman 0:38ceb79fef03 2368
kevman 0:38ceb79fef03 2369 if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL,
kevman 0:38ceb79fef03 2370 MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0,
kevman 0:38ceb79fef03 2371 sha1sum, rsa_ciphertext ) != 0 )
kevman 0:38ceb79fef03 2372 {
kevman 0:38ceb79fef03 2373 if( verbose != 0 )
kevman 0:38ceb79fef03 2374 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 2375
kevman 0:38ceb79fef03 2376 ret = 1;
kevman 0:38ceb79fef03 2377 goto cleanup;
kevman 0:38ceb79fef03 2378 }
kevman 0:38ceb79fef03 2379
kevman 0:38ceb79fef03 2380 if( verbose != 0 )
kevman 0:38ceb79fef03 2381 mbedtls_printf( "passed\n" );
kevman 0:38ceb79fef03 2382 #endif /* MBEDTLS_SHA1_C */
kevman 0:38ceb79fef03 2383
kevman 0:38ceb79fef03 2384 if( verbose != 0 )
kevman 0:38ceb79fef03 2385 mbedtls_printf( "\n" );
kevman 0:38ceb79fef03 2386
kevman 0:38ceb79fef03 2387 cleanup:
kevman 0:38ceb79fef03 2388 mbedtls_mpi_free( &K );
kevman 0:38ceb79fef03 2389 mbedtls_rsa_free( &rsa );
kevman 0:38ceb79fef03 2390 #else /* MBEDTLS_PKCS1_V15 */
kevman 0:38ceb79fef03 2391 ((void) verbose);
kevman 0:38ceb79fef03 2392 #endif /* MBEDTLS_PKCS1_V15 */
kevman 0:38ceb79fef03 2393 return( ret );
kevman 0:38ceb79fef03 2394 }
kevman 0:38ceb79fef03 2395
kevman 0:38ceb79fef03 2396 #endif /* MBEDTLS_SELF_TEST */
kevman 0:38ceb79fef03 2397
kevman 0:38ceb79fef03 2398 #endif /* MBEDTLS_RSA_C */