1*c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0 2817466cbSJens Wiklander /* 3817466cbSJens Wiklander * The RSA public-key cryptosystem 4817466cbSJens Wiklander * 5817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 6817466cbSJens Wiklander * 7817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8817466cbSJens Wiklander * not use this file except in compliance with the License. 9817466cbSJens Wiklander * You may obtain a copy of the License at 10817466cbSJens Wiklander * 11817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12817466cbSJens Wiklander * 13817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16817466cbSJens Wiklander * See the License for the specific language governing permissions and 17817466cbSJens Wiklander * limitations under the License. 18817466cbSJens Wiklander * 19817466cbSJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 20817466cbSJens Wiklander */ 21817466cbSJens Wiklander /* 22817466cbSJens Wiklander * The following sources were referenced in the design of this implementation 23817466cbSJens Wiklander * of the RSA algorithm: 24817466cbSJens Wiklander * 25817466cbSJens Wiklander * [1] A method for obtaining digital signatures and public-key cryptosystems 26817466cbSJens Wiklander * R Rivest, A Shamir, and L Adleman 27817466cbSJens Wiklander * http://people.csail.mit.edu/rivest/pubs.html#RSA78 28817466cbSJens Wiklander * 29817466cbSJens Wiklander * [2] Handbook of Applied Cryptography - 1997, Chapter 8 30817466cbSJens Wiklander * Menezes, van Oorschot and Vanstone 31817466cbSJens Wiklander * 32817466cbSJens Wiklander * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks 33817466cbSJens Wiklander * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and 34817466cbSJens Wiklander * Stefan Mangard 35817466cbSJens Wiklander * https://arxiv.org/abs/1702.08719v2 36817466cbSJens Wiklander * 37817466cbSJens Wiklander */ 38817466cbSJens Wiklander 39817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 40817466cbSJens Wiklander #include "mbedtls/config.h" 41817466cbSJens Wiklander #else 42817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 43817466cbSJens Wiklander #endif 44817466cbSJens Wiklander 45817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) 46817466cbSJens Wiklander 47817466cbSJens Wiklander #include "mbedtls/rsa.h" 48817466cbSJens Wiklander #include "mbedtls/oid.h" 49817466cbSJens Wiklander 50817466cbSJens Wiklander #include <string.h> 51817466cbSJens Wiklander 52817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 53817466cbSJens Wiklander #include "mbedtls/md.h" 54817466cbSJens Wiklander #endif 55817466cbSJens Wiklander 56817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) 57817466cbSJens Wiklander #include <stdlib.h> 58817466cbSJens Wiklander #endif 59817466cbSJens Wiklander 60817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 61817466cbSJens Wiklander #include "mbedtls/platform.h" 62817466cbSJens Wiklander #else 63817466cbSJens Wiklander #include <stdio.h> 64817466cbSJens Wiklander #define mbedtls_printf printf 65817466cbSJens Wiklander #define mbedtls_calloc calloc 66817466cbSJens Wiklander #define mbedtls_free free 67817466cbSJens Wiklander #endif 68817466cbSJens Wiklander 69817466cbSJens Wiklander /* Implementation that should never be optimized out by the compiler */ 70817466cbSJens Wiklander static void mbedtls_zeroize( void *v, size_t n ) { 71817466cbSJens Wiklander volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; 72817466cbSJens Wiklander } 73817466cbSJens Wiklander 74817466cbSJens Wiklander /* 75817466cbSJens Wiklander * Initialize an RSA context 76817466cbSJens Wiklander */ 77817466cbSJens Wiklander void mbedtls_rsa_init( mbedtls_rsa_context *ctx, 78817466cbSJens Wiklander int padding, 79817466cbSJens Wiklander int hash_id ) 80817466cbSJens Wiklander { 81817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); 82817466cbSJens Wiklander 83817466cbSJens Wiklander mbedtls_rsa_set_padding( ctx, padding, hash_id ); 84817466cbSJens Wiklander 85817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 86817466cbSJens Wiklander mbedtls_mutex_init( &ctx->mutex ); 87817466cbSJens Wiklander #endif 88817466cbSJens Wiklander } 89817466cbSJens Wiklander 90817466cbSJens Wiklander /* 91817466cbSJens Wiklander * Set padding for an existing RSA context 92817466cbSJens Wiklander */ 93817466cbSJens Wiklander void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) 94817466cbSJens Wiklander { 95817466cbSJens Wiklander ctx->padding = padding; 96817466cbSJens Wiklander ctx->hash_id = hash_id; 97817466cbSJens Wiklander } 98817466cbSJens Wiklander 99817466cbSJens Wiklander #if defined(MBEDTLS_GENPRIME) 100817466cbSJens Wiklander 101817466cbSJens Wiklander /* 102817466cbSJens Wiklander * Generate an RSA keypair 103817466cbSJens Wiklander */ 104817466cbSJens Wiklander int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, 105817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 106817466cbSJens Wiklander void *p_rng, 107817466cbSJens Wiklander unsigned int nbits, int exponent ) 108817466cbSJens Wiklander { 109817466cbSJens Wiklander int ret; 110817466cbSJens Wiklander mbedtls_mpi P1, Q1, H, G; 111817466cbSJens Wiklander 112817466cbSJens Wiklander if( f_rng == NULL || nbits < 128 || exponent < 3 ) 113817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 114817466cbSJens Wiklander 115817466cbSJens Wiklander if( nbits % 2 ) 116817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 117817466cbSJens Wiklander 118817466cbSJens Wiklander mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); 119817466cbSJens Wiklander mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); 120817466cbSJens Wiklander 121817466cbSJens Wiklander /* 122817466cbSJens Wiklander * find primes P and Q with Q < P so that: 123817466cbSJens Wiklander * GCD( E, (P-1)*(Q-1) ) == 1 124817466cbSJens Wiklander */ 125817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); 126817466cbSJens Wiklander 127817466cbSJens Wiklander do 128817466cbSJens Wiklander { 129817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, 130817466cbSJens Wiklander f_rng, p_rng ) ); 131817466cbSJens Wiklander 132817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, 133817466cbSJens Wiklander f_rng, p_rng ) ); 134817466cbSJens Wiklander 135817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) 136817466cbSJens Wiklander continue; 137817466cbSJens Wiklander 138817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); 139817466cbSJens Wiklander if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) 140817466cbSJens Wiklander continue; 141817466cbSJens Wiklander 142817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) 143817466cbSJens Wiklander mbedtls_mpi_swap( &ctx->P, &ctx->Q ); 144817466cbSJens Wiklander 145817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); 146817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); 147817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); 148817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); 149817466cbSJens Wiklander } 150817466cbSJens Wiklander while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); 151817466cbSJens Wiklander 152817466cbSJens Wiklander /* 153817466cbSJens Wiklander * D = E^-1 mod ((P-1)*(Q-1)) 154817466cbSJens Wiklander * DP = D mod (P - 1) 155817466cbSJens Wiklander * DQ = D mod (Q - 1) 156817466cbSJens Wiklander * QP = Q^-1 mod P 157817466cbSJens Wiklander */ 158817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); 159817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); 160817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); 161817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); 162817466cbSJens Wiklander 163817466cbSJens Wiklander ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; 164817466cbSJens Wiklander 165817466cbSJens Wiklander cleanup: 166817466cbSJens Wiklander 167817466cbSJens Wiklander mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); 168817466cbSJens Wiklander 169817466cbSJens Wiklander if( ret != 0 ) 170817466cbSJens Wiklander { 171817466cbSJens Wiklander mbedtls_rsa_free( ctx ); 172817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); 173817466cbSJens Wiklander } 174817466cbSJens Wiklander 175817466cbSJens Wiklander return( 0 ); 176817466cbSJens Wiklander } 177817466cbSJens Wiklander 178817466cbSJens Wiklander #endif /* MBEDTLS_GENPRIME */ 179817466cbSJens Wiklander 180817466cbSJens Wiklander /* 181817466cbSJens Wiklander * Check a public RSA key 182817466cbSJens Wiklander */ 183817466cbSJens Wiklander int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) 184817466cbSJens Wiklander { 185817466cbSJens Wiklander if( !ctx->N.p || !ctx->E.p ) 186817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 187817466cbSJens Wiklander 188817466cbSJens Wiklander if( ( ctx->N.p[0] & 1 ) == 0 || 189817466cbSJens Wiklander ( ctx->E.p[0] & 1 ) == 0 ) 190817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 191817466cbSJens Wiklander 192817466cbSJens Wiklander if( mbedtls_mpi_bitlen( &ctx->N ) < 128 || 193817466cbSJens Wiklander mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS ) 194817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 195817466cbSJens Wiklander 196817466cbSJens Wiklander if( mbedtls_mpi_bitlen( &ctx->E ) < 2 || 197817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) 198817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 199817466cbSJens Wiklander 200817466cbSJens Wiklander return( 0 ); 201817466cbSJens Wiklander } 202817466cbSJens Wiklander 203817466cbSJens Wiklander /* 204817466cbSJens Wiklander * Check a private RSA key 205817466cbSJens Wiklander */ 206817466cbSJens Wiklander int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) 207817466cbSJens Wiklander { 208817466cbSJens Wiklander int ret; 209817466cbSJens Wiklander mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; 210817466cbSJens Wiklander 211817466cbSJens Wiklander if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 ) 212817466cbSJens Wiklander return( ret ); 213817466cbSJens Wiklander 214817466cbSJens Wiklander if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) 215817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 216817466cbSJens Wiklander 217817466cbSJens Wiklander mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); 218817466cbSJens Wiklander mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); 219817466cbSJens Wiklander mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ ); 220817466cbSJens Wiklander mbedtls_mpi_init( &QP ); 221817466cbSJens Wiklander 222817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); 223817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); 224817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); 225817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); 226817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); 227817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); 228817466cbSJens Wiklander 229817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) ); 230817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) ); 231817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) ); 232817466cbSJens Wiklander 233817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); 234817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); 235817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); 236817466cbSJens Wiklander /* 237817466cbSJens Wiklander * Check for a valid PKCS1v2 private key 238817466cbSJens Wiklander */ 239817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || 240817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || 241817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || 242817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || 243817466cbSJens Wiklander mbedtls_mpi_cmp_int( &L2, 0 ) != 0 || 244817466cbSJens Wiklander mbedtls_mpi_cmp_int( &I, 1 ) != 0 || 245817466cbSJens Wiklander mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) 246817466cbSJens Wiklander { 247817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; 248817466cbSJens Wiklander } 249817466cbSJens Wiklander 250817466cbSJens Wiklander cleanup: 251817466cbSJens Wiklander mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); 252817466cbSJens Wiklander mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); 253817466cbSJens Wiklander mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); 254817466cbSJens Wiklander mbedtls_mpi_free( &QP ); 255817466cbSJens Wiklander 256817466cbSJens Wiklander if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) 257817466cbSJens Wiklander return( ret ); 258817466cbSJens Wiklander 259817466cbSJens Wiklander if( ret != 0 ) 260817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret ); 261817466cbSJens Wiklander 262817466cbSJens Wiklander return( 0 ); 263817466cbSJens Wiklander } 264817466cbSJens Wiklander 265817466cbSJens Wiklander /* 266817466cbSJens Wiklander * Check if contexts holding a public and private key match 267817466cbSJens Wiklander */ 268817466cbSJens Wiklander int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ) 269817466cbSJens Wiklander { 270817466cbSJens Wiklander if( mbedtls_rsa_check_pubkey( pub ) != 0 || 271817466cbSJens Wiklander mbedtls_rsa_check_privkey( prv ) != 0 ) 272817466cbSJens Wiklander { 273817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 274817466cbSJens Wiklander } 275817466cbSJens Wiklander 276817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || 277817466cbSJens Wiklander mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) 278817466cbSJens Wiklander { 279817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); 280817466cbSJens Wiklander } 281817466cbSJens Wiklander 282817466cbSJens Wiklander return( 0 ); 283817466cbSJens Wiklander } 284817466cbSJens Wiklander 285817466cbSJens Wiklander /* 286817466cbSJens Wiklander * Do an RSA public key operation 287817466cbSJens Wiklander */ 288817466cbSJens Wiklander int mbedtls_rsa_public( mbedtls_rsa_context *ctx, 289817466cbSJens Wiklander const unsigned char *input, 290817466cbSJens Wiklander unsigned char *output ) 291817466cbSJens Wiklander { 292817466cbSJens Wiklander int ret; 293817466cbSJens Wiklander size_t olen; 294817466cbSJens Wiklander mbedtls_mpi T; 295817466cbSJens Wiklander 296817466cbSJens Wiklander mbedtls_mpi_init( &T ); 297817466cbSJens Wiklander 298817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 299817466cbSJens Wiklander if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 300817466cbSJens Wiklander return( ret ); 301817466cbSJens Wiklander #endif 302817466cbSJens Wiklander 303817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); 304817466cbSJens Wiklander 305817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) 306817466cbSJens Wiklander { 307817466cbSJens Wiklander ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 308817466cbSJens Wiklander goto cleanup; 309817466cbSJens Wiklander } 310817466cbSJens Wiklander 311817466cbSJens Wiklander olen = ctx->len; 312817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); 313817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); 314817466cbSJens Wiklander 315817466cbSJens Wiklander cleanup: 316817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 317817466cbSJens Wiklander if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 318817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 319817466cbSJens Wiklander #endif 320817466cbSJens Wiklander 321817466cbSJens Wiklander mbedtls_mpi_free( &T ); 322817466cbSJens Wiklander 323817466cbSJens Wiklander if( ret != 0 ) 324817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); 325817466cbSJens Wiklander 326817466cbSJens Wiklander return( 0 ); 327817466cbSJens Wiklander } 328817466cbSJens Wiklander 329817466cbSJens Wiklander /* 330817466cbSJens Wiklander * Generate or update blinding values, see section 10 of: 331817466cbSJens Wiklander * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, 332817466cbSJens Wiklander * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer 333817466cbSJens Wiklander * Berlin Heidelberg, 1996. p. 104-113. 334817466cbSJens Wiklander */ 335817466cbSJens Wiklander static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, 336817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) 337817466cbSJens Wiklander { 338817466cbSJens Wiklander int ret, count = 0; 339817466cbSJens Wiklander 340817466cbSJens Wiklander if( ctx->Vf.p != NULL ) 341817466cbSJens Wiklander { 342817466cbSJens Wiklander /* We already have blinding values, just update them by squaring */ 343817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); 344817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); 345817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); 346817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); 347817466cbSJens Wiklander 348817466cbSJens Wiklander goto cleanup; 349817466cbSJens Wiklander } 350817466cbSJens Wiklander 351817466cbSJens Wiklander /* Unblinding value: Vf = random number, invertible mod N */ 352817466cbSJens Wiklander do { 353817466cbSJens Wiklander if( count++ > 10 ) 354817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_RNG_FAILED ); 355817466cbSJens Wiklander 356817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); 357817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); 358817466cbSJens Wiklander } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); 359817466cbSJens Wiklander 360817466cbSJens Wiklander /* Blinding value: Vi = Vf^(-e) mod N */ 361817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); 362817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); 363817466cbSJens Wiklander 364817466cbSJens Wiklander 365817466cbSJens Wiklander cleanup: 366817466cbSJens Wiklander return( ret ); 367817466cbSJens Wiklander } 368817466cbSJens Wiklander 369817466cbSJens Wiklander /* 370817466cbSJens Wiklander * Exponent blinding supposed to prevent side-channel attacks using multiple 371817466cbSJens Wiklander * traces of measurements to recover the RSA key. The more collisions are there, 372817466cbSJens Wiklander * the more bits of the key can be recovered. See [3]. 373817466cbSJens Wiklander * 374817466cbSJens Wiklander * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) 375817466cbSJens Wiklander * observations on avarage. 376817466cbSJens Wiklander * 377817466cbSJens Wiklander * For example with 28 byte blinding to achieve 2 collisions the adversary has 378817466cbSJens Wiklander * to make 2^112 observations on avarage. 379817466cbSJens Wiklander * 380817466cbSJens Wiklander * (With the currently (as of 2017 April) known best algorithms breaking 2048 381817466cbSJens Wiklander * bit RSA requires approximately as much time as trying out 2^112 random keys. 382817466cbSJens Wiklander * Thus in this sense with 28 byte blinding the security is not reduced by 383817466cbSJens Wiklander * side-channel attacks like the one in [3]) 384817466cbSJens Wiklander * 385817466cbSJens Wiklander * This countermeasure does not help if the key recovery is possible with a 386817466cbSJens Wiklander * single trace. 387817466cbSJens Wiklander */ 388817466cbSJens Wiklander #define RSA_EXPONENT_BLINDING 28 389817466cbSJens Wiklander 390817466cbSJens Wiklander /* 391817466cbSJens Wiklander * Do an RSA private key operation 392817466cbSJens Wiklander */ 393817466cbSJens Wiklander int mbedtls_rsa_private( mbedtls_rsa_context *ctx, 394817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 395817466cbSJens Wiklander void *p_rng, 396817466cbSJens Wiklander const unsigned char *input, 397817466cbSJens Wiklander unsigned char *output ) 398817466cbSJens Wiklander { 399817466cbSJens Wiklander int ret; 400817466cbSJens Wiklander size_t olen; 401817466cbSJens Wiklander mbedtls_mpi T, T1, T2; 402817466cbSJens Wiklander mbedtls_mpi P1, Q1, R; 403817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 404817466cbSJens Wiklander mbedtls_mpi D_blind; 405817466cbSJens Wiklander mbedtls_mpi *D = &ctx->D; 406817466cbSJens Wiklander #else 407817466cbSJens Wiklander mbedtls_mpi DP_blind, DQ_blind; 408817466cbSJens Wiklander mbedtls_mpi *DP = &ctx->DP; 409817466cbSJens Wiklander mbedtls_mpi *DQ = &ctx->DQ; 410817466cbSJens Wiklander #endif 411817466cbSJens Wiklander 412817466cbSJens Wiklander /* Make sure we have private key info, prevent possible misuse */ 413817466cbSJens Wiklander if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) 414817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 415817466cbSJens Wiklander 416817466cbSJens Wiklander mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); 417817466cbSJens Wiklander mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R ); 418817466cbSJens Wiklander 419817466cbSJens Wiklander 420817466cbSJens Wiklander if( f_rng != NULL ) 421817466cbSJens Wiklander { 422817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 423817466cbSJens Wiklander mbedtls_mpi_init( &D_blind ); 424817466cbSJens Wiklander #else 425817466cbSJens Wiklander mbedtls_mpi_init( &DP_blind ); 426817466cbSJens Wiklander mbedtls_mpi_init( &DQ_blind ); 427817466cbSJens Wiklander #endif 428817466cbSJens Wiklander } 429817466cbSJens Wiklander 430817466cbSJens Wiklander 431817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 432817466cbSJens Wiklander if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 433817466cbSJens Wiklander return( ret ); 434817466cbSJens Wiklander #endif 435817466cbSJens Wiklander 436817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); 437817466cbSJens Wiklander if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) 438817466cbSJens Wiklander { 439817466cbSJens Wiklander ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 440817466cbSJens Wiklander goto cleanup; 441817466cbSJens Wiklander } 442817466cbSJens Wiklander 443817466cbSJens Wiklander if( f_rng != NULL ) 444817466cbSJens Wiklander { 445817466cbSJens Wiklander /* 446817466cbSJens Wiklander * Blinding 447817466cbSJens Wiklander * T = T * Vi mod N 448817466cbSJens Wiklander */ 449817466cbSJens Wiklander MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); 450817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); 451817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); 452817466cbSJens Wiklander 453817466cbSJens Wiklander /* 454817466cbSJens Wiklander * Exponent blinding 455817466cbSJens Wiklander */ 456817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); 457817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); 458817466cbSJens Wiklander 459817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 460817466cbSJens Wiklander /* 461817466cbSJens Wiklander * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D 462817466cbSJens Wiklander */ 463817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, 464817466cbSJens Wiklander f_rng, p_rng ) ); 465817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); 466817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); 467817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); 468817466cbSJens Wiklander 469817466cbSJens Wiklander D = &D_blind; 470817466cbSJens Wiklander #else 471817466cbSJens Wiklander /* 472817466cbSJens Wiklander * DP_blind = ( P - 1 ) * R + DP 473817466cbSJens Wiklander */ 474817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, 475817466cbSJens Wiklander f_rng, p_rng ) ); 476817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); 477817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, 478817466cbSJens Wiklander &ctx->DP ) ); 479817466cbSJens Wiklander 480817466cbSJens Wiklander DP = &DP_blind; 481817466cbSJens Wiklander 482817466cbSJens Wiklander /* 483817466cbSJens Wiklander * DQ_blind = ( Q - 1 ) * R + DQ 484817466cbSJens Wiklander */ 485817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, 486817466cbSJens Wiklander f_rng, p_rng ) ); 487817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); 488817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, 489817466cbSJens Wiklander &ctx->DQ ) ); 490817466cbSJens Wiklander 491817466cbSJens Wiklander DQ = &DQ_blind; 492817466cbSJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */ 493817466cbSJens Wiklander } 494817466cbSJens Wiklander 495817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 496817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); 497817466cbSJens Wiklander #else 498817466cbSJens Wiklander /* 499817466cbSJens Wiklander * Faster decryption using the CRT 500817466cbSJens Wiklander * 501817466cbSJens Wiklander * T1 = input ^ dP mod P 502817466cbSJens Wiklander * T2 = input ^ dQ mod Q 503817466cbSJens Wiklander */ 504817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, DP, &ctx->P, &ctx->RP ) ); 505817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, DQ, &ctx->Q, &ctx->RQ ) ); 506817466cbSJens Wiklander 507817466cbSJens Wiklander /* 508817466cbSJens Wiklander * T = (T1 - T2) * (Q^-1 mod P) mod P 509817466cbSJens Wiklander */ 510817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); 511817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); 512817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); 513817466cbSJens Wiklander 514817466cbSJens Wiklander /* 515817466cbSJens Wiklander * T = T2 + T * Q 516817466cbSJens Wiklander */ 517817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); 518817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); 519817466cbSJens Wiklander #endif /* MBEDTLS_RSA_NO_CRT */ 520817466cbSJens Wiklander 521817466cbSJens Wiklander if( f_rng != NULL ) 522817466cbSJens Wiklander { 523817466cbSJens Wiklander /* 524817466cbSJens Wiklander * Unblind 525817466cbSJens Wiklander * T = T * Vf mod N 526817466cbSJens Wiklander */ 527817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); 528817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); 529817466cbSJens Wiklander } 530817466cbSJens Wiklander 531817466cbSJens Wiklander olen = ctx->len; 532817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); 533817466cbSJens Wiklander 534817466cbSJens Wiklander cleanup: 535817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 536817466cbSJens Wiklander if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 537817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 538817466cbSJens Wiklander #endif 539817466cbSJens Wiklander 540817466cbSJens Wiklander mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); 541817466cbSJens Wiklander mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &R ); 542817466cbSJens Wiklander 543817466cbSJens Wiklander if( f_rng != NULL ) 544817466cbSJens Wiklander { 545817466cbSJens Wiklander #if defined(MBEDTLS_RSA_NO_CRT) 546817466cbSJens Wiklander mbedtls_mpi_free( &D_blind ); 547817466cbSJens Wiklander #else 548817466cbSJens Wiklander mbedtls_mpi_free( &DP_blind ); 549817466cbSJens Wiklander mbedtls_mpi_free( &DQ_blind ); 550817466cbSJens Wiklander #endif 551817466cbSJens Wiklander } 552817466cbSJens Wiklander 553817466cbSJens Wiklander if( ret != 0 ) 554817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); 555817466cbSJens Wiklander 556817466cbSJens Wiklander return( 0 ); 557817466cbSJens Wiklander } 558817466cbSJens Wiklander 559817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 560817466cbSJens Wiklander /** 561817466cbSJens Wiklander * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. 562817466cbSJens Wiklander * 563817466cbSJens Wiklander * \param dst buffer to mask 564817466cbSJens Wiklander * \param dlen length of destination buffer 565817466cbSJens Wiklander * \param src source of the mask generation 566817466cbSJens Wiklander * \param slen length of the source buffer 567817466cbSJens Wiklander * \param md_ctx message digest context to use 568817466cbSJens Wiklander */ 569817466cbSJens Wiklander static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, 570817466cbSJens Wiklander size_t slen, mbedtls_md_context_t *md_ctx ) 571817466cbSJens Wiklander { 572817466cbSJens Wiklander unsigned char mask[MBEDTLS_MD_MAX_SIZE]; 573817466cbSJens Wiklander unsigned char counter[4]; 574817466cbSJens Wiklander unsigned char *p; 575817466cbSJens Wiklander unsigned int hlen; 576817466cbSJens Wiklander size_t i, use_len; 577817466cbSJens Wiklander 578817466cbSJens Wiklander memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); 579817466cbSJens Wiklander memset( counter, 0, 4 ); 580817466cbSJens Wiklander 581817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_ctx->md_info ); 582817466cbSJens Wiklander 583817466cbSJens Wiklander /* Generate and apply dbMask */ 584817466cbSJens Wiklander p = dst; 585817466cbSJens Wiklander 586817466cbSJens Wiklander while( dlen > 0 ) 587817466cbSJens Wiklander { 588817466cbSJens Wiklander use_len = hlen; 589817466cbSJens Wiklander if( dlen < hlen ) 590817466cbSJens Wiklander use_len = dlen; 591817466cbSJens Wiklander 592817466cbSJens Wiklander mbedtls_md_starts( md_ctx ); 593817466cbSJens Wiklander mbedtls_md_update( md_ctx, src, slen ); 594817466cbSJens Wiklander mbedtls_md_update( md_ctx, counter, 4 ); 595817466cbSJens Wiklander mbedtls_md_finish( md_ctx, mask ); 596817466cbSJens Wiklander 597817466cbSJens Wiklander for( i = 0; i < use_len; ++i ) 598817466cbSJens Wiklander *p++ ^= mask[i]; 599817466cbSJens Wiklander 600817466cbSJens Wiklander counter[3]++; 601817466cbSJens Wiklander 602817466cbSJens Wiklander dlen -= use_len; 603817466cbSJens Wiklander } 604817466cbSJens Wiklander 605817466cbSJens Wiklander mbedtls_zeroize( mask, sizeof( mask ) ); 606817466cbSJens Wiklander } 607817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 608817466cbSJens Wiklander 609817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 610817466cbSJens Wiklander /* 611817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function 612817466cbSJens Wiklander */ 613817466cbSJens Wiklander int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, 614817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 615817466cbSJens Wiklander void *p_rng, 616817466cbSJens Wiklander int mode, 617817466cbSJens Wiklander const unsigned char *label, size_t label_len, 618817466cbSJens Wiklander size_t ilen, 619817466cbSJens Wiklander const unsigned char *input, 620817466cbSJens Wiklander unsigned char *output ) 621817466cbSJens Wiklander { 622817466cbSJens Wiklander size_t olen; 623817466cbSJens Wiklander int ret; 624817466cbSJens Wiklander unsigned char *p = output; 625817466cbSJens Wiklander unsigned int hlen; 626817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 627817466cbSJens Wiklander mbedtls_md_context_t md_ctx; 628817466cbSJens Wiklander 629817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) 630817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 631817466cbSJens Wiklander 632817466cbSJens Wiklander if( f_rng == NULL ) 633817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 634817466cbSJens Wiklander 635817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); 636817466cbSJens Wiklander if( md_info == NULL ) 637817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 638817466cbSJens Wiklander 639817466cbSJens Wiklander olen = ctx->len; 640817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_info ); 641817466cbSJens Wiklander 642817466cbSJens Wiklander /* first comparison checks for overflow */ 643817466cbSJens Wiklander if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) 644817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 645817466cbSJens Wiklander 646817466cbSJens Wiklander memset( output, 0, olen ); 647817466cbSJens Wiklander 648817466cbSJens Wiklander *p++ = 0; 649817466cbSJens Wiklander 650817466cbSJens Wiklander /* Generate a random octet string seed */ 651817466cbSJens Wiklander if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) 652817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); 653817466cbSJens Wiklander 654817466cbSJens Wiklander p += hlen; 655817466cbSJens Wiklander 656817466cbSJens Wiklander /* Construct DB */ 657817466cbSJens Wiklander mbedtls_md( md_info, label, label_len, p ); 658817466cbSJens Wiklander p += hlen; 659817466cbSJens Wiklander p += olen - 2 * hlen - 2 - ilen; 660817466cbSJens Wiklander *p++ = 1; 661817466cbSJens Wiklander memcpy( p, input, ilen ); 662817466cbSJens Wiklander 663817466cbSJens Wiklander mbedtls_md_init( &md_ctx ); 664817466cbSJens Wiklander if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 665817466cbSJens Wiklander { 666817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 667817466cbSJens Wiklander return( ret ); 668817466cbSJens Wiklander } 669817466cbSJens Wiklander 670817466cbSJens Wiklander /* maskedDB: Apply dbMask to DB */ 671817466cbSJens Wiklander mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, 672817466cbSJens Wiklander &md_ctx ); 673817466cbSJens Wiklander 674817466cbSJens Wiklander /* maskedSeed: Apply seedMask to seed */ 675817466cbSJens Wiklander mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, 676817466cbSJens Wiklander &md_ctx ); 677817466cbSJens Wiklander 678817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 679817466cbSJens Wiklander 680817466cbSJens Wiklander return( ( mode == MBEDTLS_RSA_PUBLIC ) 681817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, output, output ) 682817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); 683817466cbSJens Wiklander } 684817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 685817466cbSJens Wiklander 686817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 687817466cbSJens Wiklander /* 688817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function 689817466cbSJens Wiklander */ 690817466cbSJens Wiklander int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, 691817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 692817466cbSJens Wiklander void *p_rng, 693817466cbSJens Wiklander int mode, size_t ilen, 694817466cbSJens Wiklander const unsigned char *input, 695817466cbSJens Wiklander unsigned char *output ) 696817466cbSJens Wiklander { 697817466cbSJens Wiklander size_t nb_pad, olen; 698817466cbSJens Wiklander int ret; 699817466cbSJens Wiklander unsigned char *p = output; 700817466cbSJens Wiklander 701817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 702817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 703817466cbSJens Wiklander 704817466cbSJens Wiklander // We don't check p_rng because it won't be dereferenced here 705817466cbSJens Wiklander if( f_rng == NULL || input == NULL || output == NULL ) 706817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 707817466cbSJens Wiklander 708817466cbSJens Wiklander olen = ctx->len; 709817466cbSJens Wiklander 710817466cbSJens Wiklander /* first comparison checks for overflow */ 711817466cbSJens Wiklander if( ilen + 11 < ilen || olen < ilen + 11 ) 712817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 713817466cbSJens Wiklander 714817466cbSJens Wiklander nb_pad = olen - 3 - ilen; 715817466cbSJens Wiklander 716817466cbSJens Wiklander *p++ = 0; 717817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PUBLIC ) 718817466cbSJens Wiklander { 719817466cbSJens Wiklander *p++ = MBEDTLS_RSA_CRYPT; 720817466cbSJens Wiklander 721817466cbSJens Wiklander while( nb_pad-- > 0 ) 722817466cbSJens Wiklander { 723817466cbSJens Wiklander int rng_dl = 100; 724817466cbSJens Wiklander 725817466cbSJens Wiklander do { 726817466cbSJens Wiklander ret = f_rng( p_rng, p, 1 ); 727817466cbSJens Wiklander } while( *p == 0 && --rng_dl && ret == 0 ); 728817466cbSJens Wiklander 729817466cbSJens Wiklander /* Check if RNG failed to generate data */ 730817466cbSJens Wiklander if( rng_dl == 0 || ret != 0 ) 731817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); 732817466cbSJens Wiklander 733817466cbSJens Wiklander p++; 734817466cbSJens Wiklander } 735817466cbSJens Wiklander } 736817466cbSJens Wiklander else 737817466cbSJens Wiklander { 738817466cbSJens Wiklander *p++ = MBEDTLS_RSA_SIGN; 739817466cbSJens Wiklander 740817466cbSJens Wiklander while( nb_pad-- > 0 ) 741817466cbSJens Wiklander *p++ = 0xFF; 742817466cbSJens Wiklander } 743817466cbSJens Wiklander 744817466cbSJens Wiklander *p++ = 0; 745817466cbSJens Wiklander memcpy( p, input, ilen ); 746817466cbSJens Wiklander 747817466cbSJens Wiklander return( ( mode == MBEDTLS_RSA_PUBLIC ) 748817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, output, output ) 749817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); 750817466cbSJens Wiklander } 751817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 752817466cbSJens Wiklander 753817466cbSJens Wiklander /* 754817466cbSJens Wiklander * Add the message padding, then do an RSA operation 755817466cbSJens Wiklander */ 756817466cbSJens Wiklander int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, 757817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 758817466cbSJens Wiklander void *p_rng, 759817466cbSJens Wiklander int mode, size_t ilen, 760817466cbSJens Wiklander const unsigned char *input, 761817466cbSJens Wiklander unsigned char *output ) 762817466cbSJens Wiklander { 763817466cbSJens Wiklander switch( ctx->padding ) 764817466cbSJens Wiklander { 765817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 766817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V15: 767817466cbSJens Wiklander return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, 768817466cbSJens Wiklander input, output ); 769817466cbSJens Wiklander #endif 770817466cbSJens Wiklander 771817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 772817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V21: 773817466cbSJens Wiklander return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, 774817466cbSJens Wiklander ilen, input, output ); 775817466cbSJens Wiklander #endif 776817466cbSJens Wiklander 777817466cbSJens Wiklander default: 778817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 779817466cbSJens Wiklander } 780817466cbSJens Wiklander } 781817466cbSJens Wiklander 782817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 783817466cbSJens Wiklander /* 784817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function 785817466cbSJens Wiklander */ 786817466cbSJens Wiklander int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, 787817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 788817466cbSJens Wiklander void *p_rng, 789817466cbSJens Wiklander int mode, 790817466cbSJens Wiklander const unsigned char *label, size_t label_len, 791817466cbSJens Wiklander size_t *olen, 792817466cbSJens Wiklander const unsigned char *input, 793817466cbSJens Wiklander unsigned char *output, 794817466cbSJens Wiklander size_t output_max_len ) 795817466cbSJens Wiklander { 796817466cbSJens Wiklander int ret; 797817466cbSJens Wiklander size_t ilen, i, pad_len; 798817466cbSJens Wiklander unsigned char *p, bad, pad_done; 799817466cbSJens Wiklander unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 800817466cbSJens Wiklander unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; 801817466cbSJens Wiklander unsigned int hlen; 802817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 803817466cbSJens Wiklander mbedtls_md_context_t md_ctx; 804817466cbSJens Wiklander 805817466cbSJens Wiklander /* 806817466cbSJens Wiklander * Parameters sanity checks 807817466cbSJens Wiklander */ 808817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) 809817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 810817466cbSJens Wiklander 811817466cbSJens Wiklander ilen = ctx->len; 812817466cbSJens Wiklander 813817466cbSJens Wiklander if( ilen < 16 || ilen > sizeof( buf ) ) 814817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 815817466cbSJens Wiklander 816817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); 817817466cbSJens Wiklander if( md_info == NULL ) 818817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 819817466cbSJens Wiklander 820817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_info ); 821817466cbSJens Wiklander 822817466cbSJens Wiklander // checking for integer underflow 823817466cbSJens Wiklander if( 2 * hlen + 2 > ilen ) 824817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 825817466cbSJens Wiklander 826817466cbSJens Wiklander /* 827817466cbSJens Wiklander * RSA operation 828817466cbSJens Wiklander */ 829817466cbSJens Wiklander ret = ( mode == MBEDTLS_RSA_PUBLIC ) 830817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, input, buf ) 831817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); 832817466cbSJens Wiklander 833817466cbSJens Wiklander if( ret != 0 ) 834817466cbSJens Wiklander goto cleanup; 835817466cbSJens Wiklander 836817466cbSJens Wiklander /* 837817466cbSJens Wiklander * Unmask data and generate lHash 838817466cbSJens Wiklander */ 839817466cbSJens Wiklander mbedtls_md_init( &md_ctx ); 840817466cbSJens Wiklander if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 841817466cbSJens Wiklander { 842817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 843817466cbSJens Wiklander goto cleanup; 844817466cbSJens Wiklander } 845817466cbSJens Wiklander 846817466cbSJens Wiklander 847817466cbSJens Wiklander /* Generate lHash */ 848817466cbSJens Wiklander mbedtls_md( md_info, label, label_len, lhash ); 849817466cbSJens Wiklander 850817466cbSJens Wiklander /* seed: Apply seedMask to maskedSeed */ 851817466cbSJens Wiklander mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, 852817466cbSJens Wiklander &md_ctx ); 853817466cbSJens Wiklander 854817466cbSJens Wiklander /* DB: Apply dbMask to maskedDB */ 855817466cbSJens Wiklander mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, 856817466cbSJens Wiklander &md_ctx ); 857817466cbSJens Wiklander 858817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 859817466cbSJens Wiklander 860817466cbSJens Wiklander /* 861817466cbSJens Wiklander * Check contents, in "constant-time" 862817466cbSJens Wiklander */ 863817466cbSJens Wiklander p = buf; 864817466cbSJens Wiklander bad = 0; 865817466cbSJens Wiklander 866817466cbSJens Wiklander bad |= *p++; /* First byte must be 0 */ 867817466cbSJens Wiklander 868817466cbSJens Wiklander p += hlen; /* Skip seed */ 869817466cbSJens Wiklander 870817466cbSJens Wiklander /* Check lHash */ 871817466cbSJens Wiklander for( i = 0; i < hlen; i++ ) 872817466cbSJens Wiklander bad |= lhash[i] ^ *p++; 873817466cbSJens Wiklander 874817466cbSJens Wiklander /* Get zero-padding len, but always read till end of buffer 875817466cbSJens Wiklander * (minus one, for the 01 byte) */ 876817466cbSJens Wiklander pad_len = 0; 877817466cbSJens Wiklander pad_done = 0; 878817466cbSJens Wiklander for( i = 0; i < ilen - 2 * hlen - 2; i++ ) 879817466cbSJens Wiklander { 880817466cbSJens Wiklander pad_done |= p[i]; 881817466cbSJens Wiklander pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; 882817466cbSJens Wiklander } 883817466cbSJens Wiklander 884817466cbSJens Wiklander p += pad_len; 885817466cbSJens Wiklander bad |= *p++ ^ 0x01; 886817466cbSJens Wiklander 887817466cbSJens Wiklander /* 888817466cbSJens Wiklander * The only information "leaked" is whether the padding was correct or not 889817466cbSJens Wiklander * (eg, no data is copied if it was not correct). This meets the 890817466cbSJens Wiklander * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between 891817466cbSJens Wiklander * the different error conditions. 892817466cbSJens Wiklander */ 893817466cbSJens Wiklander if( bad != 0 ) 894817466cbSJens Wiklander { 895817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_INVALID_PADDING; 896817466cbSJens Wiklander goto cleanup; 897817466cbSJens Wiklander } 898817466cbSJens Wiklander 899817466cbSJens Wiklander if( ilen - ( p - buf ) > output_max_len ) 900817466cbSJens Wiklander { 901817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; 902817466cbSJens Wiklander goto cleanup; 903817466cbSJens Wiklander } 904817466cbSJens Wiklander 905817466cbSJens Wiklander *olen = ilen - (p - buf); 906817466cbSJens Wiklander memcpy( output, p, *olen ); 907817466cbSJens Wiklander ret = 0; 908817466cbSJens Wiklander 909817466cbSJens Wiklander cleanup: 910817466cbSJens Wiklander mbedtls_zeroize( buf, sizeof( buf ) ); 911817466cbSJens Wiklander mbedtls_zeroize( lhash, sizeof( lhash ) ); 912817466cbSJens Wiklander 913817466cbSJens Wiklander return( ret ); 914817466cbSJens Wiklander } 915817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 916817466cbSJens Wiklander 917817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 918817466cbSJens Wiklander /* 919817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function 920817466cbSJens Wiklander */ 921817466cbSJens Wiklander int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, 922817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 923817466cbSJens Wiklander void *p_rng, 924817466cbSJens Wiklander int mode, size_t *olen, 925817466cbSJens Wiklander const unsigned char *input, 926817466cbSJens Wiklander unsigned char *output, 927817466cbSJens Wiklander size_t output_max_len) 928817466cbSJens Wiklander { 929817466cbSJens Wiklander int ret; 930817466cbSJens Wiklander size_t ilen, pad_count = 0, i; 931817466cbSJens Wiklander unsigned char *p, bad, pad_done = 0; 932817466cbSJens Wiklander unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 933817466cbSJens Wiklander 934817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 935817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 936817466cbSJens Wiklander 937817466cbSJens Wiklander ilen = ctx->len; 938817466cbSJens Wiklander 939817466cbSJens Wiklander if( ilen < 16 || ilen > sizeof( buf ) ) 940817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 941817466cbSJens Wiklander 942817466cbSJens Wiklander ret = ( mode == MBEDTLS_RSA_PUBLIC ) 943817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, input, buf ) 944817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); 945817466cbSJens Wiklander 946817466cbSJens Wiklander if( ret != 0 ) 947817466cbSJens Wiklander goto cleanup; 948817466cbSJens Wiklander 949817466cbSJens Wiklander p = buf; 950817466cbSJens Wiklander bad = 0; 951817466cbSJens Wiklander 952817466cbSJens Wiklander /* 953817466cbSJens Wiklander * Check and get padding len in "constant-time" 954817466cbSJens Wiklander */ 955817466cbSJens Wiklander bad |= *p++; /* First byte must be 0 */ 956817466cbSJens Wiklander 957817466cbSJens Wiklander /* This test does not depend on secret data */ 958817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE ) 959817466cbSJens Wiklander { 960817466cbSJens Wiklander bad |= *p++ ^ MBEDTLS_RSA_CRYPT; 961817466cbSJens Wiklander 962817466cbSJens Wiklander /* Get padding len, but always read till end of buffer 963817466cbSJens Wiklander * (minus one, for the 00 byte) */ 964817466cbSJens Wiklander for( i = 0; i < ilen - 3; i++ ) 965817466cbSJens Wiklander { 966817466cbSJens Wiklander pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; 967817466cbSJens Wiklander pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; 968817466cbSJens Wiklander } 969817466cbSJens Wiklander 970817466cbSJens Wiklander p += pad_count; 971817466cbSJens Wiklander bad |= *p++; /* Must be zero */ 972817466cbSJens Wiklander } 973817466cbSJens Wiklander else 974817466cbSJens Wiklander { 975817466cbSJens Wiklander bad |= *p++ ^ MBEDTLS_RSA_SIGN; 976817466cbSJens Wiklander 977817466cbSJens Wiklander /* Get padding len, but always read till end of buffer 978817466cbSJens Wiklander * (minus one, for the 00 byte) */ 979817466cbSJens Wiklander for( i = 0; i < ilen - 3; i++ ) 980817466cbSJens Wiklander { 981817466cbSJens Wiklander pad_done |= ( p[i] != 0xFF ); 982817466cbSJens Wiklander pad_count += ( pad_done == 0 ); 983817466cbSJens Wiklander } 984817466cbSJens Wiklander 985817466cbSJens Wiklander p += pad_count; 986817466cbSJens Wiklander bad |= *p++; /* Must be zero */ 987817466cbSJens Wiklander } 988817466cbSJens Wiklander 989817466cbSJens Wiklander bad |= ( pad_count < 8 ); 990817466cbSJens Wiklander 991817466cbSJens Wiklander if( bad ) 992817466cbSJens Wiklander { 993817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_INVALID_PADDING; 994817466cbSJens Wiklander goto cleanup; 995817466cbSJens Wiklander } 996817466cbSJens Wiklander 997817466cbSJens Wiklander if( ilen - ( p - buf ) > output_max_len ) 998817466cbSJens Wiklander { 999817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; 1000817466cbSJens Wiklander goto cleanup; 1001817466cbSJens Wiklander } 1002817466cbSJens Wiklander 1003817466cbSJens Wiklander *olen = ilen - (p - buf); 1004817466cbSJens Wiklander memcpy( output, p, *olen ); 1005817466cbSJens Wiklander ret = 0; 1006817466cbSJens Wiklander 1007817466cbSJens Wiklander cleanup: 1008817466cbSJens Wiklander mbedtls_zeroize( buf, sizeof( buf ) ); 1009817466cbSJens Wiklander 1010817466cbSJens Wiklander return( ret ); 1011817466cbSJens Wiklander } 1012817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1013817466cbSJens Wiklander 1014817466cbSJens Wiklander /* 1015817466cbSJens Wiklander * Do an RSA operation, then remove the message padding 1016817466cbSJens Wiklander */ 1017817466cbSJens Wiklander int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, 1018817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1019817466cbSJens Wiklander void *p_rng, 1020817466cbSJens Wiklander int mode, size_t *olen, 1021817466cbSJens Wiklander const unsigned char *input, 1022817466cbSJens Wiklander unsigned char *output, 1023817466cbSJens Wiklander size_t output_max_len) 1024817466cbSJens Wiklander { 1025817466cbSJens Wiklander switch( ctx->padding ) 1026817466cbSJens Wiklander { 1027817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1028817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V15: 1029817466cbSJens Wiklander return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, 1030817466cbSJens Wiklander input, output, output_max_len ); 1031817466cbSJens Wiklander #endif 1032817466cbSJens Wiklander 1033817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1034817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V21: 1035817466cbSJens Wiklander return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, 1036817466cbSJens Wiklander olen, input, output, 1037817466cbSJens Wiklander output_max_len ); 1038817466cbSJens Wiklander #endif 1039817466cbSJens Wiklander 1040817466cbSJens Wiklander default: 1041817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1042817466cbSJens Wiklander } 1043817466cbSJens Wiklander } 1044817466cbSJens Wiklander 1045817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1046817466cbSJens Wiklander /* 1047817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function 1048817466cbSJens Wiklander */ 1049817466cbSJens Wiklander int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, 1050817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1051817466cbSJens Wiklander void *p_rng, 1052817466cbSJens Wiklander int mode, 1053817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1054817466cbSJens Wiklander unsigned int hashlen, 1055817466cbSJens Wiklander const unsigned char *hash, 1056817466cbSJens Wiklander unsigned char *sig ) 1057817466cbSJens Wiklander { 1058817466cbSJens Wiklander size_t olen; 1059817466cbSJens Wiklander unsigned char *p = sig; 1060817466cbSJens Wiklander unsigned char salt[MBEDTLS_MD_MAX_SIZE]; 1061817466cbSJens Wiklander unsigned int slen, hlen, offset = 0; 1062817466cbSJens Wiklander int ret; 1063817466cbSJens Wiklander size_t msb; 1064817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 1065817466cbSJens Wiklander mbedtls_md_context_t md_ctx; 1066817466cbSJens Wiklander 1067817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) 1068817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1069817466cbSJens Wiklander 1070817466cbSJens Wiklander if( f_rng == NULL ) 1071817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1072817466cbSJens Wiklander 1073817466cbSJens Wiklander olen = ctx->len; 1074817466cbSJens Wiklander 1075817466cbSJens Wiklander if( md_alg != MBEDTLS_MD_NONE ) 1076817466cbSJens Wiklander { 1077817466cbSJens Wiklander /* Gather length of hash to sign */ 1078817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( md_alg ); 1079817466cbSJens Wiklander if( md_info == NULL ) 1080817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1081817466cbSJens Wiklander 1082817466cbSJens Wiklander hashlen = mbedtls_md_get_size( md_info ); 1083817466cbSJens Wiklander } 1084817466cbSJens Wiklander 1085817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); 1086817466cbSJens Wiklander if( md_info == NULL ) 1087817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1088817466cbSJens Wiklander 1089817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_info ); 1090817466cbSJens Wiklander slen = hlen; 1091817466cbSJens Wiklander 1092817466cbSJens Wiklander if( olen < hlen + slen + 2 ) 1093817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1094817466cbSJens Wiklander 1095817466cbSJens Wiklander memset( sig, 0, olen ); 1096817466cbSJens Wiklander 1097817466cbSJens Wiklander /* Generate salt of length slen */ 1098817466cbSJens Wiklander if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) 1099817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); 1100817466cbSJens Wiklander 1101817466cbSJens Wiklander /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ 1102817466cbSJens Wiklander msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; 1103817466cbSJens Wiklander p += olen - hlen * 2 - 2; 1104817466cbSJens Wiklander *p++ = 0x01; 1105817466cbSJens Wiklander memcpy( p, salt, slen ); 1106817466cbSJens Wiklander p += slen; 1107817466cbSJens Wiklander 1108817466cbSJens Wiklander mbedtls_md_init( &md_ctx ); 1109817466cbSJens Wiklander if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 1110817466cbSJens Wiklander { 1111817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1112817466cbSJens Wiklander /* No need to zeroize salt: we didn't use it. */ 1113817466cbSJens Wiklander return( ret ); 1114817466cbSJens Wiklander } 1115817466cbSJens Wiklander 1116817466cbSJens Wiklander /* Generate H = Hash( M' ) */ 1117817466cbSJens Wiklander mbedtls_md_starts( &md_ctx ); 1118817466cbSJens Wiklander mbedtls_md_update( &md_ctx, p, 8 ); 1119817466cbSJens Wiklander mbedtls_md_update( &md_ctx, hash, hashlen ); 1120817466cbSJens Wiklander mbedtls_md_update( &md_ctx, salt, slen ); 1121817466cbSJens Wiklander mbedtls_md_finish( &md_ctx, p ); 1122817466cbSJens Wiklander mbedtls_zeroize( salt, sizeof( salt ) ); 1123817466cbSJens Wiklander 1124817466cbSJens Wiklander /* Compensate for boundary condition when applying mask */ 1125817466cbSJens Wiklander if( msb % 8 == 0 ) 1126817466cbSJens Wiklander offset = 1; 1127817466cbSJens Wiklander 1128817466cbSJens Wiklander /* maskedDB: Apply dbMask to DB */ 1129817466cbSJens Wiklander mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); 1130817466cbSJens Wiklander 1131817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1132817466cbSJens Wiklander 1133817466cbSJens Wiklander msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; 1134817466cbSJens Wiklander sig[0] &= 0xFF >> ( olen * 8 - msb ); 1135817466cbSJens Wiklander 1136817466cbSJens Wiklander p += hlen; 1137817466cbSJens Wiklander *p++ = 0xBC; 1138817466cbSJens Wiklander 1139817466cbSJens Wiklander return( ( mode == MBEDTLS_RSA_PUBLIC ) 1140817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, sig, sig ) 1141817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); 1142817466cbSJens Wiklander } 1143817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 1144817466cbSJens Wiklander 1145817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1146817466cbSJens Wiklander /* 1147817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function 1148817466cbSJens Wiklander */ 1149817466cbSJens Wiklander /* 1150817466cbSJens Wiklander * Do an RSA operation to sign the message digest 1151817466cbSJens Wiklander */ 1152817466cbSJens Wiklander int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, 1153817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1154817466cbSJens Wiklander void *p_rng, 1155817466cbSJens Wiklander int mode, 1156817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1157817466cbSJens Wiklander unsigned int hashlen, 1158817466cbSJens Wiklander const unsigned char *hash, 1159817466cbSJens Wiklander unsigned char *sig ) 1160817466cbSJens Wiklander { 1161817466cbSJens Wiklander size_t nb_pad, olen, oid_size = 0; 1162817466cbSJens Wiklander unsigned char *p = sig; 1163817466cbSJens Wiklander const char *oid = NULL; 1164817466cbSJens Wiklander unsigned char *sig_try = NULL, *verif = NULL; 1165817466cbSJens Wiklander size_t i; 1166817466cbSJens Wiklander unsigned char diff; 1167817466cbSJens Wiklander volatile unsigned char diff_no_optimize; 1168817466cbSJens Wiklander int ret; 1169817466cbSJens Wiklander 1170817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 1171817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1172817466cbSJens Wiklander 1173817466cbSJens Wiklander olen = ctx->len; 1174817466cbSJens Wiklander nb_pad = olen - 3; 1175817466cbSJens Wiklander 1176817466cbSJens Wiklander if( md_alg != MBEDTLS_MD_NONE ) 1177817466cbSJens Wiklander { 1178817466cbSJens Wiklander const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); 1179817466cbSJens Wiklander if( md_info == NULL ) 1180817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1181817466cbSJens Wiklander 1182817466cbSJens Wiklander if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) 1183817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1184817466cbSJens Wiklander 1185817466cbSJens Wiklander nb_pad -= 10 + oid_size; 1186817466cbSJens Wiklander 1187817466cbSJens Wiklander hashlen = mbedtls_md_get_size( md_info ); 1188817466cbSJens Wiklander } 1189817466cbSJens Wiklander 1190817466cbSJens Wiklander nb_pad -= hashlen; 1191817466cbSJens Wiklander 1192817466cbSJens Wiklander if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) 1193817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1194817466cbSJens Wiklander 1195817466cbSJens Wiklander *p++ = 0; 1196817466cbSJens Wiklander *p++ = MBEDTLS_RSA_SIGN; 1197817466cbSJens Wiklander memset( p, 0xFF, nb_pad ); 1198817466cbSJens Wiklander p += nb_pad; 1199817466cbSJens Wiklander *p++ = 0; 1200817466cbSJens Wiklander 1201817466cbSJens Wiklander if( md_alg == MBEDTLS_MD_NONE ) 1202817466cbSJens Wiklander { 1203817466cbSJens Wiklander memcpy( p, hash, hashlen ); 1204817466cbSJens Wiklander } 1205817466cbSJens Wiklander else 1206817466cbSJens Wiklander { 1207817466cbSJens Wiklander /* 1208817466cbSJens Wiklander * DigestInfo ::= SEQUENCE { 1209817466cbSJens Wiklander * digestAlgorithm DigestAlgorithmIdentifier, 1210817466cbSJens Wiklander * digest Digest } 1211817466cbSJens Wiklander * 1212817466cbSJens Wiklander * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 1213817466cbSJens Wiklander * 1214817466cbSJens Wiklander * Digest ::= OCTET STRING 1215817466cbSJens Wiklander */ 1216817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; 1217817466cbSJens Wiklander *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); 1218817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; 1219817466cbSJens Wiklander *p++ = (unsigned char) ( 0x04 + oid_size ); 1220817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_OID; 1221817466cbSJens Wiklander *p++ = oid_size & 0xFF; 1222817466cbSJens Wiklander memcpy( p, oid, oid_size ); 1223817466cbSJens Wiklander p += oid_size; 1224817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_NULL; 1225817466cbSJens Wiklander *p++ = 0x00; 1226817466cbSJens Wiklander *p++ = MBEDTLS_ASN1_OCTET_STRING; 1227817466cbSJens Wiklander *p++ = hashlen; 1228817466cbSJens Wiklander memcpy( p, hash, hashlen ); 1229817466cbSJens Wiklander } 1230817466cbSJens Wiklander 1231817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PUBLIC ) 1232817466cbSJens Wiklander return( mbedtls_rsa_public( ctx, sig, sig ) ); 1233817466cbSJens Wiklander 1234817466cbSJens Wiklander /* 1235817466cbSJens Wiklander * In order to prevent Lenstra's attack, make the signature in a 1236817466cbSJens Wiklander * temporary buffer and check it before returning it. 1237817466cbSJens Wiklander */ 1238817466cbSJens Wiklander sig_try = mbedtls_calloc( 1, ctx->len ); 1239817466cbSJens Wiklander if( sig_try == NULL ) 1240817466cbSJens Wiklander return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 1241817466cbSJens Wiklander 1242817466cbSJens Wiklander verif = mbedtls_calloc( 1, ctx->len ); 1243817466cbSJens Wiklander if( verif == NULL ) 1244817466cbSJens Wiklander { 1245817466cbSJens Wiklander mbedtls_free( sig_try ); 1246817466cbSJens Wiklander return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 1247817466cbSJens Wiklander } 1248817466cbSJens Wiklander 1249817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); 1250817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); 1251817466cbSJens Wiklander 1252817466cbSJens Wiklander /* Compare in constant time just in case */ 1253817466cbSJens Wiklander for( diff = 0, i = 0; i < ctx->len; i++ ) 1254817466cbSJens Wiklander diff |= verif[i] ^ sig[i]; 1255817466cbSJens Wiklander diff_no_optimize = diff; 1256817466cbSJens Wiklander 1257817466cbSJens Wiklander if( diff_no_optimize != 0 ) 1258817466cbSJens Wiklander { 1259817466cbSJens Wiklander ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; 1260817466cbSJens Wiklander goto cleanup; 1261817466cbSJens Wiklander } 1262817466cbSJens Wiklander 1263817466cbSJens Wiklander memcpy( sig, sig_try, ctx->len ); 1264817466cbSJens Wiklander 1265817466cbSJens Wiklander cleanup: 1266817466cbSJens Wiklander mbedtls_free( sig_try ); 1267817466cbSJens Wiklander mbedtls_free( verif ); 1268817466cbSJens Wiklander 1269817466cbSJens Wiklander return( ret ); 1270817466cbSJens Wiklander } 1271817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1272817466cbSJens Wiklander 1273817466cbSJens Wiklander /* 1274817466cbSJens Wiklander * Do an RSA operation to sign the message digest 1275817466cbSJens Wiklander */ 1276817466cbSJens Wiklander int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, 1277817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1278817466cbSJens Wiklander void *p_rng, 1279817466cbSJens Wiklander int mode, 1280817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1281817466cbSJens Wiklander unsigned int hashlen, 1282817466cbSJens Wiklander const unsigned char *hash, 1283817466cbSJens Wiklander unsigned char *sig ) 1284817466cbSJens Wiklander { 1285817466cbSJens Wiklander switch( ctx->padding ) 1286817466cbSJens Wiklander { 1287817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1288817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V15: 1289817466cbSJens Wiklander return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, 1290817466cbSJens Wiklander hashlen, hash, sig ); 1291817466cbSJens Wiklander #endif 1292817466cbSJens Wiklander 1293817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1294817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V21: 1295817466cbSJens Wiklander return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, 1296817466cbSJens Wiklander hashlen, hash, sig ); 1297817466cbSJens Wiklander #endif 1298817466cbSJens Wiklander 1299817466cbSJens Wiklander default: 1300817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1301817466cbSJens Wiklander } 1302817466cbSJens Wiklander } 1303817466cbSJens Wiklander 1304817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1305817466cbSJens Wiklander /* 1306817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function 1307817466cbSJens Wiklander */ 1308817466cbSJens Wiklander int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, 1309817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1310817466cbSJens Wiklander void *p_rng, 1311817466cbSJens Wiklander int mode, 1312817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1313817466cbSJens Wiklander unsigned int hashlen, 1314817466cbSJens Wiklander const unsigned char *hash, 1315817466cbSJens Wiklander mbedtls_md_type_t mgf1_hash_id, 1316817466cbSJens Wiklander int expected_salt_len, 1317817466cbSJens Wiklander const unsigned char *sig ) 1318817466cbSJens Wiklander { 1319817466cbSJens Wiklander int ret; 1320817466cbSJens Wiklander size_t siglen; 1321817466cbSJens Wiklander unsigned char *p; 1322817466cbSJens Wiklander unsigned char result[MBEDTLS_MD_MAX_SIZE]; 1323817466cbSJens Wiklander unsigned char zeros[8]; 1324817466cbSJens Wiklander unsigned int hlen; 1325817466cbSJens Wiklander size_t slen, msb; 1326817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 1327817466cbSJens Wiklander mbedtls_md_context_t md_ctx; 1328817466cbSJens Wiklander unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 1329817466cbSJens Wiklander 1330817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) 1331817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1332817466cbSJens Wiklander 1333817466cbSJens Wiklander siglen = ctx->len; 1334817466cbSJens Wiklander 1335817466cbSJens Wiklander if( siglen < 16 || siglen > sizeof( buf ) ) 1336817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1337817466cbSJens Wiklander 1338817466cbSJens Wiklander ret = ( mode == MBEDTLS_RSA_PUBLIC ) 1339817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, sig, buf ) 1340817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); 1341817466cbSJens Wiklander 1342817466cbSJens Wiklander if( ret != 0 ) 1343817466cbSJens Wiklander return( ret ); 1344817466cbSJens Wiklander 1345817466cbSJens Wiklander p = buf; 1346817466cbSJens Wiklander 1347817466cbSJens Wiklander if( buf[siglen - 1] != 0xBC ) 1348817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1349817466cbSJens Wiklander 1350817466cbSJens Wiklander if( md_alg != MBEDTLS_MD_NONE ) 1351817466cbSJens Wiklander { 1352817466cbSJens Wiklander /* Gather length of hash to sign */ 1353817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( md_alg ); 1354817466cbSJens Wiklander if( md_info == NULL ) 1355817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1356817466cbSJens Wiklander 1357817466cbSJens Wiklander hashlen = mbedtls_md_get_size( md_info ); 1358817466cbSJens Wiklander } 1359817466cbSJens Wiklander 1360817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( mgf1_hash_id ); 1361817466cbSJens Wiklander if( md_info == NULL ) 1362817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1363817466cbSJens Wiklander 1364817466cbSJens Wiklander hlen = mbedtls_md_get_size( md_info ); 1365817466cbSJens Wiklander slen = siglen - hlen - 1; /* Currently length of salt + padding */ 1366817466cbSJens Wiklander 1367817466cbSJens Wiklander memset( zeros, 0, 8 ); 1368817466cbSJens Wiklander 1369817466cbSJens Wiklander /* 1370817466cbSJens Wiklander * Note: EMSA-PSS verification is over the length of N - 1 bits 1371817466cbSJens Wiklander */ 1372817466cbSJens Wiklander msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; 1373817466cbSJens Wiklander 1374817466cbSJens Wiklander /* Compensate for boundary condition when applying mask */ 1375817466cbSJens Wiklander if( msb % 8 == 0 ) 1376817466cbSJens Wiklander { 1377817466cbSJens Wiklander p++; 1378817466cbSJens Wiklander siglen -= 1; 1379817466cbSJens Wiklander } 1380817466cbSJens Wiklander if( buf[0] >> ( 8 - siglen * 8 + msb ) ) 1381817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1382817466cbSJens Wiklander 1383817466cbSJens Wiklander mbedtls_md_init( &md_ctx ); 1384817466cbSJens Wiklander if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 1385817466cbSJens Wiklander { 1386817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1387817466cbSJens Wiklander return( ret ); 1388817466cbSJens Wiklander } 1389817466cbSJens Wiklander 1390817466cbSJens Wiklander mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); 1391817466cbSJens Wiklander 1392817466cbSJens Wiklander buf[0] &= 0xFF >> ( siglen * 8 - msb ); 1393817466cbSJens Wiklander 1394817466cbSJens Wiklander while( p < buf + siglen && *p == 0 ) 1395817466cbSJens Wiklander p++; 1396817466cbSJens Wiklander 1397817466cbSJens Wiklander if( p == buf + siglen || 1398817466cbSJens Wiklander *p++ != 0x01 ) 1399817466cbSJens Wiklander { 1400817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1401817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1402817466cbSJens Wiklander } 1403817466cbSJens Wiklander 1404817466cbSJens Wiklander /* Actual salt len */ 1405817466cbSJens Wiklander slen -= p - buf; 1406817466cbSJens Wiklander 1407817466cbSJens Wiklander if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && 1408817466cbSJens Wiklander slen != (size_t) expected_salt_len ) 1409817466cbSJens Wiklander { 1410817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1411817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1412817466cbSJens Wiklander } 1413817466cbSJens Wiklander 1414817466cbSJens Wiklander /* 1415817466cbSJens Wiklander * Generate H = Hash( M' ) 1416817466cbSJens Wiklander */ 1417817466cbSJens Wiklander mbedtls_md_starts( &md_ctx ); 1418817466cbSJens Wiklander mbedtls_md_update( &md_ctx, zeros, 8 ); 1419817466cbSJens Wiklander mbedtls_md_update( &md_ctx, hash, hashlen ); 1420817466cbSJens Wiklander mbedtls_md_update( &md_ctx, p, slen ); 1421817466cbSJens Wiklander mbedtls_md_finish( &md_ctx, result ); 1422817466cbSJens Wiklander 1423817466cbSJens Wiklander mbedtls_md_free( &md_ctx ); 1424817466cbSJens Wiklander 1425817466cbSJens Wiklander if( memcmp( p + slen, result, hlen ) == 0 ) 1426817466cbSJens Wiklander return( 0 ); 1427817466cbSJens Wiklander else 1428817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1429817466cbSJens Wiklander } 1430817466cbSJens Wiklander 1431817466cbSJens Wiklander /* 1432817466cbSJens Wiklander * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function 1433817466cbSJens Wiklander */ 1434817466cbSJens Wiklander int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, 1435817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1436817466cbSJens Wiklander void *p_rng, 1437817466cbSJens Wiklander int mode, 1438817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1439817466cbSJens Wiklander unsigned int hashlen, 1440817466cbSJens Wiklander const unsigned char *hash, 1441817466cbSJens Wiklander const unsigned char *sig ) 1442817466cbSJens Wiklander { 1443817466cbSJens Wiklander mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) 1444817466cbSJens Wiklander ? (mbedtls_md_type_t) ctx->hash_id 1445817466cbSJens Wiklander : md_alg; 1446817466cbSJens Wiklander 1447817466cbSJens Wiklander return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, 1448817466cbSJens Wiklander md_alg, hashlen, hash, 1449817466cbSJens Wiklander mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, 1450817466cbSJens Wiklander sig ) ); 1451817466cbSJens Wiklander 1452817466cbSJens Wiklander } 1453817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V21 */ 1454817466cbSJens Wiklander 1455817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1456817466cbSJens Wiklander /* 1457817466cbSJens Wiklander * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function 1458817466cbSJens Wiklander */ 1459817466cbSJens Wiklander int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, 1460817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1461817466cbSJens Wiklander void *p_rng, 1462817466cbSJens Wiklander int mode, 1463817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1464817466cbSJens Wiklander unsigned int hashlen, 1465817466cbSJens Wiklander const unsigned char *hash, 1466817466cbSJens Wiklander const unsigned char *sig ) 1467817466cbSJens Wiklander { 1468817466cbSJens Wiklander int ret; 1469817466cbSJens Wiklander size_t len, siglen, asn1_len; 1470817466cbSJens Wiklander unsigned char *p, *p0, *end; 1471817466cbSJens Wiklander mbedtls_md_type_t msg_md_alg; 1472817466cbSJens Wiklander const mbedtls_md_info_t *md_info; 1473817466cbSJens Wiklander mbedtls_asn1_buf oid; 1474817466cbSJens Wiklander unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 1475817466cbSJens Wiklander 1476817466cbSJens Wiklander if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) 1477817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1478817466cbSJens Wiklander 1479817466cbSJens Wiklander siglen = ctx->len; 1480817466cbSJens Wiklander 1481817466cbSJens Wiklander if( siglen < 16 || siglen > sizeof( buf ) ) 1482817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1483817466cbSJens Wiklander 1484817466cbSJens Wiklander ret = ( mode == MBEDTLS_RSA_PUBLIC ) 1485817466cbSJens Wiklander ? mbedtls_rsa_public( ctx, sig, buf ) 1486817466cbSJens Wiklander : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); 1487817466cbSJens Wiklander 1488817466cbSJens Wiklander if( ret != 0 ) 1489817466cbSJens Wiklander return( ret ); 1490817466cbSJens Wiklander 1491817466cbSJens Wiklander p = buf; 1492817466cbSJens Wiklander 1493817466cbSJens Wiklander if( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN ) 1494817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1495817466cbSJens Wiklander 1496817466cbSJens Wiklander while( *p != 0 ) 1497817466cbSJens Wiklander { 1498817466cbSJens Wiklander if( p >= buf + siglen - 1 || *p != 0xFF ) 1499817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1500817466cbSJens Wiklander p++; 1501817466cbSJens Wiklander } 1502817466cbSJens Wiklander p++; /* skip 00 byte */ 1503817466cbSJens Wiklander 1504817466cbSJens Wiklander /* We've read: 00 01 PS 00 where PS must be at least 8 bytes */ 1505817466cbSJens Wiklander if( p - buf < 11 ) 1506817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1507817466cbSJens Wiklander 1508817466cbSJens Wiklander len = siglen - ( p - buf ); 1509817466cbSJens Wiklander 1510817466cbSJens Wiklander if( len == hashlen && md_alg == MBEDTLS_MD_NONE ) 1511817466cbSJens Wiklander { 1512817466cbSJens Wiklander if( memcmp( p, hash, hashlen ) == 0 ) 1513817466cbSJens Wiklander return( 0 ); 1514817466cbSJens Wiklander else 1515817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1516817466cbSJens Wiklander } 1517817466cbSJens Wiklander 1518817466cbSJens Wiklander md_info = mbedtls_md_info_from_type( md_alg ); 1519817466cbSJens Wiklander if( md_info == NULL ) 1520817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); 1521817466cbSJens Wiklander hashlen = mbedtls_md_get_size( md_info ); 1522817466cbSJens Wiklander 1523817466cbSJens Wiklander end = p + len; 1524817466cbSJens Wiklander 1525817466cbSJens Wiklander /* 1526817466cbSJens Wiklander * Parse the ASN.1 structure inside the PKCS#1 v1.5 structure. 1527817466cbSJens Wiklander * Insist on 2-byte length tags, to protect against variants of 1528817466cbSJens Wiklander * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification. 1529817466cbSJens Wiklander */ 1530817466cbSJens Wiklander p0 = p; 1531817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, 1532817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 1533817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1534817466cbSJens Wiklander if( p != p0 + 2 || asn1_len + 2 != len ) 1535817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1536817466cbSJens Wiklander 1537817466cbSJens Wiklander p0 = p; 1538817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, 1539817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 1540817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1541817466cbSJens Wiklander if( p != p0 + 2 || asn1_len + 6 + hashlen != len ) 1542817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1543817466cbSJens Wiklander 1544817466cbSJens Wiklander p0 = p; 1545817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) 1546817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1547817466cbSJens Wiklander if( p != p0 + 2 ) 1548817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1549817466cbSJens Wiklander 1550817466cbSJens Wiklander oid.p = p; 1551817466cbSJens Wiklander p += oid.len; 1552817466cbSJens Wiklander 1553817466cbSJens Wiklander if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) 1554817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1555817466cbSJens Wiklander 1556817466cbSJens Wiklander if( md_alg != msg_md_alg ) 1557817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1558817466cbSJens Wiklander 1559817466cbSJens Wiklander /* 1560817466cbSJens Wiklander * assume the algorithm parameters must be NULL 1561817466cbSJens Wiklander */ 1562817466cbSJens Wiklander p0 = p; 1563817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 ) 1564817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1565817466cbSJens Wiklander if( p != p0 + 2 ) 1566817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1567817466cbSJens Wiklander 1568817466cbSJens Wiklander p0 = p; 1569817466cbSJens Wiklander if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 1570817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1571817466cbSJens Wiklander if( p != p0 + 2 || asn1_len != hashlen ) 1572817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1573817466cbSJens Wiklander 1574817466cbSJens Wiklander if( memcmp( p, hash, hashlen ) != 0 ) 1575817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1576817466cbSJens Wiklander 1577817466cbSJens Wiklander p += hashlen; 1578817466cbSJens Wiklander 1579817466cbSJens Wiklander if( p != end ) 1580817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); 1581817466cbSJens Wiklander 1582817466cbSJens Wiklander return( 0 ); 1583817466cbSJens Wiklander } 1584817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1585817466cbSJens Wiklander 1586817466cbSJens Wiklander /* 1587817466cbSJens Wiklander * Do an RSA operation and check the message digest 1588817466cbSJens Wiklander */ 1589817466cbSJens Wiklander int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, 1590817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1591817466cbSJens Wiklander void *p_rng, 1592817466cbSJens Wiklander int mode, 1593817466cbSJens Wiklander mbedtls_md_type_t md_alg, 1594817466cbSJens Wiklander unsigned int hashlen, 1595817466cbSJens Wiklander const unsigned char *hash, 1596817466cbSJens Wiklander const unsigned char *sig ) 1597817466cbSJens Wiklander { 1598817466cbSJens Wiklander switch( ctx->padding ) 1599817466cbSJens Wiklander { 1600817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1601817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V15: 1602817466cbSJens Wiklander return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, 1603817466cbSJens Wiklander hashlen, hash, sig ); 1604817466cbSJens Wiklander #endif 1605817466cbSJens Wiklander 1606817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V21) 1607817466cbSJens Wiklander case MBEDTLS_RSA_PKCS_V21: 1608817466cbSJens Wiklander return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, 1609817466cbSJens Wiklander hashlen, hash, sig ); 1610817466cbSJens Wiklander #endif 1611817466cbSJens Wiklander 1612817466cbSJens Wiklander default: 1613817466cbSJens Wiklander return( MBEDTLS_ERR_RSA_INVALID_PADDING ); 1614817466cbSJens Wiklander } 1615817466cbSJens Wiklander } 1616817466cbSJens Wiklander 1617817466cbSJens Wiklander /* 1618817466cbSJens Wiklander * Copy the components of an RSA key 1619817466cbSJens Wiklander */ 1620817466cbSJens Wiklander int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) 1621817466cbSJens Wiklander { 1622817466cbSJens Wiklander int ret; 1623817466cbSJens Wiklander 1624817466cbSJens Wiklander dst->ver = src->ver; 1625817466cbSJens Wiklander dst->len = src->len; 1626817466cbSJens Wiklander 1627817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); 1628817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); 1629817466cbSJens Wiklander 1630817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); 1631817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); 1632817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); 1633817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); 1634817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); 1635817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); 1636817466cbSJens Wiklander 1637817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); 1638817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); 1639817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); 1640817466cbSJens Wiklander 1641817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); 1642817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); 1643817466cbSJens Wiklander 1644817466cbSJens Wiklander dst->padding = src->padding; 1645817466cbSJens Wiklander dst->hash_id = src->hash_id; 1646817466cbSJens Wiklander 1647817466cbSJens Wiklander cleanup: 1648817466cbSJens Wiklander if( ret != 0 ) 1649817466cbSJens Wiklander mbedtls_rsa_free( dst ); 1650817466cbSJens Wiklander 1651817466cbSJens Wiklander return( ret ); 1652817466cbSJens Wiklander } 1653817466cbSJens Wiklander 1654817466cbSJens Wiklander /* 1655817466cbSJens Wiklander * Free the components of an RSA key 1656817466cbSJens Wiklander */ 1657817466cbSJens Wiklander void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) 1658817466cbSJens Wiklander { 1659817466cbSJens Wiklander mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); 1660817466cbSJens Wiklander mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN ); 1661817466cbSJens Wiklander mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); 1662817466cbSJens Wiklander mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D ); 1663817466cbSJens Wiklander mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); 1664817466cbSJens Wiklander 1665817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 1666817466cbSJens Wiklander mbedtls_mutex_free( &ctx->mutex ); 1667817466cbSJens Wiklander #endif 1668817466cbSJens Wiklander } 1669817466cbSJens Wiklander 1670817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 1671817466cbSJens Wiklander 1672817466cbSJens Wiklander #include "mbedtls/sha1.h" 1673817466cbSJens Wiklander 1674817466cbSJens Wiklander /* 1675817466cbSJens Wiklander * Example RSA-1024 keypair, for test purposes 1676817466cbSJens Wiklander */ 1677817466cbSJens Wiklander #define KEY_LEN 128 1678817466cbSJens Wiklander 1679817466cbSJens Wiklander #define RSA_N "9292758453063D803DD603D5E777D788" \ 1680817466cbSJens Wiklander "8ED1D5BF35786190FA2F23EBC0848AEA" \ 1681817466cbSJens Wiklander "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ 1682817466cbSJens Wiklander "7130B9CED7ACDF54CFC7555AC14EEBAB" \ 1683817466cbSJens Wiklander "93A89813FBF3C4F8066D2D800F7C38A8" \ 1684817466cbSJens Wiklander "1AE31942917403FF4946B0A83D3D3E05" \ 1685817466cbSJens Wiklander "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ 1686817466cbSJens Wiklander "5E94BB77B07507233A0BC7BAC8F90F79" 1687817466cbSJens Wiklander 1688817466cbSJens Wiklander #define RSA_E "10001" 1689817466cbSJens Wiklander 1690817466cbSJens Wiklander #define RSA_D "24BF6185468786FDD303083D25E64EFC" \ 1691817466cbSJens Wiklander "66CA472BC44D253102F8B4A9D3BFA750" \ 1692817466cbSJens Wiklander "91386C0077937FE33FA3252D28855837" \ 1693817466cbSJens Wiklander "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ 1694817466cbSJens Wiklander "DF79C5CE07EE72C7F123142198164234" \ 1695817466cbSJens Wiklander "CABB724CF78B8173B9F880FC86322407" \ 1696817466cbSJens Wiklander "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ 1697817466cbSJens Wiklander "071513A1E85B5DFA031F21ECAE91A34D" 1698817466cbSJens Wiklander 1699817466cbSJens Wiklander #define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ 1700817466cbSJens Wiklander "2C01CAD19EA484A87EA4377637E75500" \ 1701817466cbSJens Wiklander "FCB2005C5C7DD6EC4AC023CDA285D796" \ 1702817466cbSJens Wiklander "C3D9E75E1EFC42488BB4F1D13AC30A57" 1703817466cbSJens Wiklander 1704817466cbSJens Wiklander #define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ 1705817466cbSJens Wiklander "E211C2B9E5DB1ED0BF61D0D9899620F4" \ 1706817466cbSJens Wiklander "910E4168387E3C30AA1E00C339A79508" \ 1707817466cbSJens Wiklander "8452DD96A9A5EA5D9DCA68DA636032AF" 1708817466cbSJens Wiklander 1709817466cbSJens Wiklander #define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ 1710817466cbSJens Wiklander "3C94D22288ACD763FD8E5600ED4A702D" \ 1711817466cbSJens Wiklander "F84198A5F06C2E72236AE490C93F07F8" \ 1712817466cbSJens Wiklander "3CC559CD27BC2D1CA488811730BB5725" 1713817466cbSJens Wiklander 1714817466cbSJens Wiklander #define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ 1715817466cbSJens Wiklander "D8AAEA56749EA28623272E4F7D0592AF" \ 1716817466cbSJens Wiklander "7C1F1313CAC9471B5C523BFE592F517B" \ 1717817466cbSJens Wiklander "407A1BD76C164B93DA2D32A383E58357" 1718817466cbSJens Wiklander 1719817466cbSJens Wiklander #define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ 1720817466cbSJens Wiklander "F38D18D2B2F0E2DD275AA977E2BF4411" \ 1721817466cbSJens Wiklander "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ 1722817466cbSJens Wiklander "A74206CEC169D74BF5A8C50D6F48EA08" 1723817466cbSJens Wiklander 1724817466cbSJens Wiklander #define PT_LEN 24 1725817466cbSJens Wiklander #define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ 1726817466cbSJens Wiklander "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" 1727817466cbSJens Wiklander 1728817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1729817466cbSJens Wiklander static int myrand( void *rng_state, unsigned char *output, size_t len ) 1730817466cbSJens Wiklander { 1731817466cbSJens Wiklander #if !defined(__OpenBSD__) 1732817466cbSJens Wiklander size_t i; 1733817466cbSJens Wiklander 1734817466cbSJens Wiklander if( rng_state != NULL ) 1735817466cbSJens Wiklander rng_state = NULL; 1736817466cbSJens Wiklander 1737817466cbSJens Wiklander for( i = 0; i < len; ++i ) 1738817466cbSJens Wiklander output[i] = rand(); 1739817466cbSJens Wiklander #else 1740817466cbSJens Wiklander if( rng_state != NULL ) 1741817466cbSJens Wiklander rng_state = NULL; 1742817466cbSJens Wiklander 1743817466cbSJens Wiklander arc4random_buf( output, len ); 1744817466cbSJens Wiklander #endif /* !OpenBSD */ 1745817466cbSJens Wiklander 1746817466cbSJens Wiklander return( 0 ); 1747817466cbSJens Wiklander } 1748817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1749817466cbSJens Wiklander 1750817466cbSJens Wiklander /* 1751817466cbSJens Wiklander * Checkup routine 1752817466cbSJens Wiklander */ 1753817466cbSJens Wiklander int mbedtls_rsa_self_test( int verbose ) 1754817466cbSJens Wiklander { 1755817466cbSJens Wiklander int ret = 0; 1756817466cbSJens Wiklander #if defined(MBEDTLS_PKCS1_V15) 1757817466cbSJens Wiklander size_t len; 1758817466cbSJens Wiklander mbedtls_rsa_context rsa; 1759817466cbSJens Wiklander unsigned char rsa_plaintext[PT_LEN]; 1760817466cbSJens Wiklander unsigned char rsa_decrypted[PT_LEN]; 1761817466cbSJens Wiklander unsigned char rsa_ciphertext[KEY_LEN]; 1762817466cbSJens Wiklander #if defined(MBEDTLS_SHA1_C) 1763817466cbSJens Wiklander unsigned char sha1sum[20]; 1764817466cbSJens Wiklander #endif 1765817466cbSJens Wiklander 1766817466cbSJens Wiklander mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); 1767817466cbSJens Wiklander 1768817466cbSJens Wiklander rsa.len = KEY_LEN; 1769817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) ); 1770817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) ); 1771817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) ); 1772817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) ); 1773817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) ); 1774817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) ); 1775817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); 1776817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) ); 1777817466cbSJens Wiklander 1778817466cbSJens Wiklander if( verbose != 0 ) 1779817466cbSJens Wiklander mbedtls_printf( " RSA key validation: " ); 1780817466cbSJens Wiklander 1781817466cbSJens Wiklander if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || 1782817466cbSJens Wiklander mbedtls_rsa_check_privkey( &rsa ) != 0 ) 1783817466cbSJens Wiklander { 1784817466cbSJens Wiklander if( verbose != 0 ) 1785817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1786817466cbSJens Wiklander 1787817466cbSJens Wiklander return( 1 ); 1788817466cbSJens Wiklander } 1789817466cbSJens Wiklander 1790817466cbSJens Wiklander if( verbose != 0 ) 1791817466cbSJens Wiklander mbedtls_printf( "passed\n PKCS#1 encryption : " ); 1792817466cbSJens Wiklander 1793817466cbSJens Wiklander memcpy( rsa_plaintext, RSA_PT, PT_LEN ); 1794817466cbSJens Wiklander 1795817466cbSJens Wiklander if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN, 1796817466cbSJens Wiklander rsa_plaintext, rsa_ciphertext ) != 0 ) 1797817466cbSJens Wiklander { 1798817466cbSJens Wiklander if( verbose != 0 ) 1799817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1800817466cbSJens Wiklander 1801817466cbSJens Wiklander return( 1 ); 1802817466cbSJens Wiklander } 1803817466cbSJens Wiklander 1804817466cbSJens Wiklander if( verbose != 0 ) 1805817466cbSJens Wiklander mbedtls_printf( "passed\n PKCS#1 decryption : " ); 1806817466cbSJens Wiklander 1807817466cbSJens Wiklander if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len, 1808817466cbSJens Wiklander rsa_ciphertext, rsa_decrypted, 1809817466cbSJens Wiklander sizeof(rsa_decrypted) ) != 0 ) 1810817466cbSJens Wiklander { 1811817466cbSJens Wiklander if( verbose != 0 ) 1812817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1813817466cbSJens Wiklander 1814817466cbSJens Wiklander return( 1 ); 1815817466cbSJens Wiklander } 1816817466cbSJens Wiklander 1817817466cbSJens Wiklander if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) 1818817466cbSJens Wiklander { 1819817466cbSJens Wiklander if( verbose != 0 ) 1820817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1821817466cbSJens Wiklander 1822817466cbSJens Wiklander return( 1 ); 1823817466cbSJens Wiklander } 1824817466cbSJens Wiklander 1825817466cbSJens Wiklander if( verbose != 0 ) 1826817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 1827817466cbSJens Wiklander 1828817466cbSJens Wiklander #if defined(MBEDTLS_SHA1_C) 1829817466cbSJens Wiklander if( verbose != 0 ) 1830817466cbSJens Wiklander mbedtls_printf( " PKCS#1 data sign : " ); 1831817466cbSJens Wiklander 1832817466cbSJens Wiklander mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ); 1833817466cbSJens Wiklander 1834817466cbSJens Wiklander if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, 1835817466cbSJens Wiklander sha1sum, rsa_ciphertext ) != 0 ) 1836817466cbSJens Wiklander { 1837817466cbSJens Wiklander if( verbose != 0 ) 1838817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1839817466cbSJens Wiklander 1840817466cbSJens Wiklander return( 1 ); 1841817466cbSJens Wiklander } 1842817466cbSJens Wiklander 1843817466cbSJens Wiklander if( verbose != 0 ) 1844817466cbSJens Wiklander mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); 1845817466cbSJens Wiklander 1846817466cbSJens Wiklander if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, 1847817466cbSJens Wiklander sha1sum, rsa_ciphertext ) != 0 ) 1848817466cbSJens Wiklander { 1849817466cbSJens Wiklander if( verbose != 0 ) 1850817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 1851817466cbSJens Wiklander 1852817466cbSJens Wiklander return( 1 ); 1853817466cbSJens Wiklander } 1854817466cbSJens Wiklander 1855817466cbSJens Wiklander if( verbose != 0 ) 1856817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 1857817466cbSJens Wiklander #endif /* MBEDTLS_SHA1_C */ 1858817466cbSJens Wiklander 1859817466cbSJens Wiklander if( verbose != 0 ) 1860817466cbSJens Wiklander mbedtls_printf( "\n" ); 1861817466cbSJens Wiklander 1862817466cbSJens Wiklander cleanup: 1863817466cbSJens Wiklander mbedtls_rsa_free( &rsa ); 1864817466cbSJens Wiklander #else /* MBEDTLS_PKCS1_V15 */ 1865817466cbSJens Wiklander ((void) verbose); 1866817466cbSJens Wiklander #endif /* MBEDTLS_PKCS1_V15 */ 1867817466cbSJens Wiklander return( ret ); 1868817466cbSJens Wiklander } 1869817466cbSJens Wiklander 1870817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 1871817466cbSJens Wiklander 1872817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C */ 1873