1c2c66affSColin Finck /* 2c2c66affSColin Finck * Multi-precision integer library 3c2c66affSColin Finck * 4c2c66affSColin Finck * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5c2c66affSColin Finck * SPDX-License-Identifier: GPL-2.0 6c2c66affSColin Finck * 7c2c66affSColin Finck * This program is free software; you can redistribute it and/or modify 8c2c66affSColin Finck * it under the terms of the GNU General Public License as published by 9c2c66affSColin Finck * the Free Software Foundation; either version 2 of the License, or 10c2c66affSColin Finck * (at your option) any later version. 11c2c66affSColin Finck * 12c2c66affSColin Finck * This program is distributed in the hope that it will be useful, 13c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 14c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15c2c66affSColin Finck * GNU General Public License for more details. 16c2c66affSColin Finck * 17c2c66affSColin Finck * You should have received a copy of the GNU General Public License along 18c2c66affSColin Finck * with this program; if not, write to the Free Software Foundation, Inc., 19c2c66affSColin Finck * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20c2c66affSColin Finck * 21c2c66affSColin Finck * This file is part of mbed TLS (https://tls.mbed.org) 22c2c66affSColin Finck */ 23c2c66affSColin Finck 24c2c66affSColin Finck /* 25c2c66affSColin Finck * The following sources were referenced in the design of this Multi-precision 26c2c66affSColin Finck * Integer library: 27c2c66affSColin Finck * 28c2c66affSColin Finck * [1] Handbook of Applied Cryptography - 1997 29c2c66affSColin Finck * Menezes, van Oorschot and Vanstone 30c2c66affSColin Finck * 31c2c66affSColin Finck * [2] Multi-Precision Math 32c2c66affSColin Finck * Tom St Denis 33c2c66affSColin Finck * https://github.com/libtom/libtommath/blob/develop/tommath.pdf 34c2c66affSColin Finck * 35c2c66affSColin Finck * [3] GNU Multi-Precision Arithmetic Library 36c2c66affSColin Finck * https://gmplib.org/manual/index.html 37c2c66affSColin Finck * 38c2c66affSColin Finck */ 39c2c66affSColin Finck 40c2c66affSColin Finck #if !defined(MBEDTLS_CONFIG_FILE) 41c2c66affSColin Finck #include "mbedtls/config.h" 42c2c66affSColin Finck #else 43c2c66affSColin Finck #include MBEDTLS_CONFIG_FILE 44c2c66affSColin Finck #endif 45c2c66affSColin Finck 46c2c66affSColin Finck #if defined(MBEDTLS_BIGNUM_C) 47c2c66affSColin Finck 48c2c66affSColin Finck #include "mbedtls/bignum.h" 49c2c66affSColin Finck #include "mbedtls/bn_mul.h" 50c2c66affSColin Finck 51c2c66affSColin Finck #include <string.h> 52c2c66affSColin Finck 53c2c66affSColin Finck #if defined(MBEDTLS_PLATFORM_C) 54c2c66affSColin Finck #include "mbedtls/platform.h" 55c2c66affSColin Finck #else 56c2c66affSColin Finck #include <stdio.h> 57c2c66affSColin Finck #include <stdlib.h> 58c2c66affSColin Finck #define mbedtls_printf printf 59c2c66affSColin Finck #define mbedtls_calloc calloc 60c2c66affSColin Finck #define mbedtls_free free 61c2c66affSColin Finck #endif 62c2c66affSColin Finck 63c2c66affSColin Finck /* Implementation that should never be optimized out by the compiler */ 64c2c66affSColin Finck static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { 65c2c66affSColin Finck volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; 66c2c66affSColin Finck } 67c2c66affSColin Finck 68*d9e6c9b5SThomas Faber /* Implementation that should never be optimized out by the compiler */ 69*d9e6c9b5SThomas Faber static void mbedtls_zeroize( void *v, size_t n ) { 70*d9e6c9b5SThomas Faber volatile unsigned char *p = v; while( n-- ) *p++ = 0; 71*d9e6c9b5SThomas Faber } 72*d9e6c9b5SThomas Faber 73c2c66affSColin Finck #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ 74c2c66affSColin Finck #define biL (ciL << 3) /* bits in limb */ 75c2c66affSColin Finck #define biH (ciL << 2) /* half limb size */ 76c2c66affSColin Finck 77c2c66affSColin Finck #define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ 78c2c66affSColin Finck 79c2c66affSColin Finck /* 80c2c66affSColin Finck * Convert between bits/chars and number of limbs 81c2c66affSColin Finck * Divide first in order to avoid potential overflows 82c2c66affSColin Finck */ 83c2c66affSColin Finck #define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) 84c2c66affSColin Finck #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) 85c2c66affSColin Finck 86c2c66affSColin Finck /* 87c2c66affSColin Finck * Initialize one MPI 88c2c66affSColin Finck */ 89c2c66affSColin Finck void mbedtls_mpi_init( mbedtls_mpi *X ) 90c2c66affSColin Finck { 91c2c66affSColin Finck if( X == NULL ) 92c2c66affSColin Finck return; 93c2c66affSColin Finck 94c2c66affSColin Finck X->s = 1; 95c2c66affSColin Finck X->n = 0; 96c2c66affSColin Finck X->p = NULL; 97c2c66affSColin Finck } 98c2c66affSColin Finck 99c2c66affSColin Finck /* 100c2c66affSColin Finck * Unallocate one MPI 101c2c66affSColin Finck */ 102c2c66affSColin Finck void mbedtls_mpi_free( mbedtls_mpi *X ) 103c2c66affSColin Finck { 104c2c66affSColin Finck if( X == NULL ) 105c2c66affSColin Finck return; 106c2c66affSColin Finck 107c2c66affSColin Finck if( X->p != NULL ) 108c2c66affSColin Finck { 109c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n ); 110c2c66affSColin Finck mbedtls_free( X->p ); 111c2c66affSColin Finck } 112c2c66affSColin Finck 113c2c66affSColin Finck X->s = 1; 114c2c66affSColin Finck X->n = 0; 115c2c66affSColin Finck X->p = NULL; 116c2c66affSColin Finck } 117c2c66affSColin Finck 118c2c66affSColin Finck /* 119c2c66affSColin Finck * Enlarge to the specified number of limbs 120c2c66affSColin Finck */ 121c2c66affSColin Finck int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) 122c2c66affSColin Finck { 123c2c66affSColin Finck mbedtls_mpi_uint *p; 124c2c66affSColin Finck 125c2c66affSColin Finck if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) 126c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 127c2c66affSColin Finck 128c2c66affSColin Finck if( X->n < nblimbs ) 129c2c66affSColin Finck { 130c2c66affSColin Finck if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) 131c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 132c2c66affSColin Finck 133c2c66affSColin Finck if( X->p != NULL ) 134c2c66affSColin Finck { 135c2c66affSColin Finck memcpy( p, X->p, X->n * ciL ); 136c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n ); 137c2c66affSColin Finck mbedtls_free( X->p ); 138c2c66affSColin Finck } 139c2c66affSColin Finck 140c2c66affSColin Finck X->n = nblimbs; 141c2c66affSColin Finck X->p = p; 142c2c66affSColin Finck } 143c2c66affSColin Finck 144c2c66affSColin Finck return( 0 ); 145c2c66affSColin Finck } 146c2c66affSColin Finck 147c2c66affSColin Finck /* 148c2c66affSColin Finck * Resize down as much as possible, 149c2c66affSColin Finck * while keeping at least the specified number of limbs 150c2c66affSColin Finck */ 151c2c66affSColin Finck int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) 152c2c66affSColin Finck { 153c2c66affSColin Finck mbedtls_mpi_uint *p; 154c2c66affSColin Finck size_t i; 155c2c66affSColin Finck 156c2c66affSColin Finck /* Actually resize up in this case */ 157c2c66affSColin Finck if( X->n <= nblimbs ) 158c2c66affSColin Finck return( mbedtls_mpi_grow( X, nblimbs ) ); 159c2c66affSColin Finck 160c2c66affSColin Finck for( i = X->n - 1; i > 0; i-- ) 161c2c66affSColin Finck if( X->p[i] != 0 ) 162c2c66affSColin Finck break; 163c2c66affSColin Finck i++; 164c2c66affSColin Finck 165c2c66affSColin Finck if( i < nblimbs ) 166c2c66affSColin Finck i = nblimbs; 167c2c66affSColin Finck 168c2c66affSColin Finck if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) 169c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 170c2c66affSColin Finck 171c2c66affSColin Finck if( X->p != NULL ) 172c2c66affSColin Finck { 173c2c66affSColin Finck memcpy( p, X->p, i * ciL ); 174c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n ); 175c2c66affSColin Finck mbedtls_free( X->p ); 176c2c66affSColin Finck } 177c2c66affSColin Finck 178c2c66affSColin Finck X->n = i; 179c2c66affSColin Finck X->p = p; 180c2c66affSColin Finck 181c2c66affSColin Finck return( 0 ); 182c2c66affSColin Finck } 183c2c66affSColin Finck 184c2c66affSColin Finck /* 185c2c66affSColin Finck * Copy the contents of Y into X 186c2c66affSColin Finck */ 187c2c66affSColin Finck int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) 188c2c66affSColin Finck { 189c2c66affSColin Finck int ret; 190c2c66affSColin Finck size_t i; 191c2c66affSColin Finck 192c2c66affSColin Finck if( X == Y ) 193c2c66affSColin Finck return( 0 ); 194c2c66affSColin Finck 195c2c66affSColin Finck if( Y->p == NULL ) 196c2c66affSColin Finck { 197c2c66affSColin Finck mbedtls_mpi_free( X ); 198c2c66affSColin Finck return( 0 ); 199c2c66affSColin Finck } 200c2c66affSColin Finck 201c2c66affSColin Finck for( i = Y->n - 1; i > 0; i-- ) 202c2c66affSColin Finck if( Y->p[i] != 0 ) 203c2c66affSColin Finck break; 204c2c66affSColin Finck i++; 205c2c66affSColin Finck 206c2c66affSColin Finck X->s = Y->s; 207c2c66affSColin Finck 208c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); 209c2c66affSColin Finck 210c2c66affSColin Finck memset( X->p, 0, X->n * ciL ); 211c2c66affSColin Finck memcpy( X->p, Y->p, i * ciL ); 212c2c66affSColin Finck 213c2c66affSColin Finck cleanup: 214c2c66affSColin Finck 215c2c66affSColin Finck return( ret ); 216c2c66affSColin Finck } 217c2c66affSColin Finck 218c2c66affSColin Finck /* 219c2c66affSColin Finck * Swap the contents of X and Y 220c2c66affSColin Finck */ 221c2c66affSColin Finck void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) 222c2c66affSColin Finck { 223c2c66affSColin Finck mbedtls_mpi T; 224c2c66affSColin Finck 225c2c66affSColin Finck memcpy( &T, X, sizeof( mbedtls_mpi ) ); 226c2c66affSColin Finck memcpy( X, Y, sizeof( mbedtls_mpi ) ); 227c2c66affSColin Finck memcpy( Y, &T, sizeof( mbedtls_mpi ) ); 228c2c66affSColin Finck } 229c2c66affSColin Finck 230c2c66affSColin Finck /* 231c2c66affSColin Finck * Conditionally assign X = Y, without leaking information 232c2c66affSColin Finck * about whether the assignment was made or not. 233c2c66affSColin Finck * (Leaking information about the respective sizes of X and Y is ok however.) 234c2c66affSColin Finck */ 235c2c66affSColin Finck int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) 236c2c66affSColin Finck { 237c2c66affSColin Finck int ret = 0; 238c2c66affSColin Finck size_t i; 239c2c66affSColin Finck 240c2c66affSColin Finck /* make sure assign is 0 or 1 in a time-constant manner */ 241c2c66affSColin Finck assign = (assign | (unsigned char)-assign) >> 7; 242c2c66affSColin Finck 243c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); 244c2c66affSColin Finck 245c2c66affSColin Finck X->s = X->s * ( 1 - assign ) + Y->s * assign; 246c2c66affSColin Finck 247c2c66affSColin Finck for( i = 0; i < Y->n; i++ ) 248c2c66affSColin Finck X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; 249c2c66affSColin Finck 250c2c66affSColin Finck for( ; i < X->n; i++ ) 251c2c66affSColin Finck X->p[i] *= ( 1 - assign ); 252c2c66affSColin Finck 253c2c66affSColin Finck cleanup: 254c2c66affSColin Finck return( ret ); 255c2c66affSColin Finck } 256c2c66affSColin Finck 257c2c66affSColin Finck /* 258c2c66affSColin Finck * Conditionally swap X and Y, without leaking information 259c2c66affSColin Finck * about whether the swap was made or not. 260c2c66affSColin Finck * Here it is not ok to simply swap the pointers, which whould lead to 261c2c66affSColin Finck * different memory access patterns when X and Y are used afterwards. 262c2c66affSColin Finck */ 263c2c66affSColin Finck int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) 264c2c66affSColin Finck { 265c2c66affSColin Finck int ret, s; 266c2c66affSColin Finck size_t i; 267c2c66affSColin Finck mbedtls_mpi_uint tmp; 268c2c66affSColin Finck 269c2c66affSColin Finck if( X == Y ) 270c2c66affSColin Finck return( 0 ); 271c2c66affSColin Finck 272c2c66affSColin Finck /* make sure swap is 0 or 1 in a time-constant manner */ 273c2c66affSColin Finck swap = (swap | (unsigned char)-swap) >> 7; 274c2c66affSColin Finck 275c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); 276c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); 277c2c66affSColin Finck 278c2c66affSColin Finck s = X->s; 279c2c66affSColin Finck X->s = X->s * ( 1 - swap ) + Y->s * swap; 280c2c66affSColin Finck Y->s = Y->s * ( 1 - swap ) + s * swap; 281c2c66affSColin Finck 282c2c66affSColin Finck 283c2c66affSColin Finck for( i = 0; i < X->n; i++ ) 284c2c66affSColin Finck { 285c2c66affSColin Finck tmp = X->p[i]; 286c2c66affSColin Finck X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; 287c2c66affSColin Finck Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; 288c2c66affSColin Finck } 289c2c66affSColin Finck 290c2c66affSColin Finck cleanup: 291c2c66affSColin Finck return( ret ); 292c2c66affSColin Finck } 293c2c66affSColin Finck 294c2c66affSColin Finck /* 295c2c66affSColin Finck * Set value from integer 296c2c66affSColin Finck */ 297c2c66affSColin Finck int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) 298c2c66affSColin Finck { 299c2c66affSColin Finck int ret; 300c2c66affSColin Finck 301c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); 302c2c66affSColin Finck memset( X->p, 0, X->n * ciL ); 303c2c66affSColin Finck 304c2c66affSColin Finck X->p[0] = ( z < 0 ) ? -z : z; 305c2c66affSColin Finck X->s = ( z < 0 ) ? -1 : 1; 306c2c66affSColin Finck 307c2c66affSColin Finck cleanup: 308c2c66affSColin Finck 309c2c66affSColin Finck return( ret ); 310c2c66affSColin Finck } 311c2c66affSColin Finck 312c2c66affSColin Finck /* 313c2c66affSColin Finck * Get a specific bit 314c2c66affSColin Finck */ 315c2c66affSColin Finck int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) 316c2c66affSColin Finck { 317c2c66affSColin Finck if( X->n * biL <= pos ) 318c2c66affSColin Finck return( 0 ); 319c2c66affSColin Finck 320c2c66affSColin Finck return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); 321c2c66affSColin Finck } 322c2c66affSColin Finck 323c2c66affSColin Finck /* 324c2c66affSColin Finck * Set a bit to a specific value of 0 or 1 325c2c66affSColin Finck */ 326c2c66affSColin Finck int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) 327c2c66affSColin Finck { 328c2c66affSColin Finck int ret = 0; 329c2c66affSColin Finck size_t off = pos / biL; 330c2c66affSColin Finck size_t idx = pos % biL; 331c2c66affSColin Finck 332c2c66affSColin Finck if( val != 0 && val != 1 ) 333c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 334c2c66affSColin Finck 335c2c66affSColin Finck if( X->n * biL <= pos ) 336c2c66affSColin Finck { 337c2c66affSColin Finck if( val == 0 ) 338c2c66affSColin Finck return( 0 ); 339c2c66affSColin Finck 340c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); 341c2c66affSColin Finck } 342c2c66affSColin Finck 343c2c66affSColin Finck X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); 344c2c66affSColin Finck X->p[off] |= (mbedtls_mpi_uint) val << idx; 345c2c66affSColin Finck 346c2c66affSColin Finck cleanup: 347c2c66affSColin Finck 348c2c66affSColin Finck return( ret ); 349c2c66affSColin Finck } 350c2c66affSColin Finck 351c2c66affSColin Finck /* 352c2c66affSColin Finck * Return the number of less significant zero-bits 353c2c66affSColin Finck */ 354c2c66affSColin Finck size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) 355c2c66affSColin Finck { 356c2c66affSColin Finck size_t i, j, count = 0; 357c2c66affSColin Finck 358c2c66affSColin Finck for( i = 0; i < X->n; i++ ) 359c2c66affSColin Finck for( j = 0; j < biL; j++, count++ ) 360c2c66affSColin Finck if( ( ( X->p[i] >> j ) & 1 ) != 0 ) 361c2c66affSColin Finck return( count ); 362c2c66affSColin Finck 363c2c66affSColin Finck return( 0 ); 364c2c66affSColin Finck } 365c2c66affSColin Finck 366c2c66affSColin Finck /* 367c2c66affSColin Finck * Count leading zero bits in a given integer 368c2c66affSColin Finck */ 369c2c66affSColin Finck static size_t mbedtls_clz( const mbedtls_mpi_uint x ) 370c2c66affSColin Finck { 371c2c66affSColin Finck size_t j; 372c2c66affSColin Finck mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); 373c2c66affSColin Finck 374c2c66affSColin Finck for( j = 0; j < biL; j++ ) 375c2c66affSColin Finck { 376c2c66affSColin Finck if( x & mask ) break; 377c2c66affSColin Finck 378c2c66affSColin Finck mask >>= 1; 379c2c66affSColin Finck } 380c2c66affSColin Finck 381c2c66affSColin Finck return j; 382c2c66affSColin Finck } 383c2c66affSColin Finck 384c2c66affSColin Finck /* 385c2c66affSColin Finck * Return the number of bits 386c2c66affSColin Finck */ 387c2c66affSColin Finck size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) 388c2c66affSColin Finck { 389c2c66affSColin Finck size_t i, j; 390c2c66affSColin Finck 391c2c66affSColin Finck if( X->n == 0 ) 392c2c66affSColin Finck return( 0 ); 393c2c66affSColin Finck 394c2c66affSColin Finck for( i = X->n - 1; i > 0; i-- ) 395c2c66affSColin Finck if( X->p[i] != 0 ) 396c2c66affSColin Finck break; 397c2c66affSColin Finck 398c2c66affSColin Finck j = biL - mbedtls_clz( X->p[i] ); 399c2c66affSColin Finck 400c2c66affSColin Finck return( ( i * biL ) + j ); 401c2c66affSColin Finck } 402c2c66affSColin Finck 403c2c66affSColin Finck /* 404c2c66affSColin Finck * Return the total size in bytes 405c2c66affSColin Finck */ 406c2c66affSColin Finck size_t mbedtls_mpi_size( const mbedtls_mpi *X ) 407c2c66affSColin Finck { 408c2c66affSColin Finck return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); 409c2c66affSColin Finck } 410c2c66affSColin Finck 411c2c66affSColin Finck /* 412c2c66affSColin Finck * Convert an ASCII character to digit value 413c2c66affSColin Finck */ 414c2c66affSColin Finck static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) 415c2c66affSColin Finck { 416c2c66affSColin Finck *d = 255; 417c2c66affSColin Finck 418c2c66affSColin Finck if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; 419c2c66affSColin Finck if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; 420c2c66affSColin Finck if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; 421c2c66affSColin Finck 422c2c66affSColin Finck if( *d >= (mbedtls_mpi_uint) radix ) 423c2c66affSColin Finck return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); 424c2c66affSColin Finck 425c2c66affSColin Finck return( 0 ); 426c2c66affSColin Finck } 427c2c66affSColin Finck 428c2c66affSColin Finck /* 429c2c66affSColin Finck * Import from an ASCII string 430c2c66affSColin Finck */ 431c2c66affSColin Finck int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) 432c2c66affSColin Finck { 433c2c66affSColin Finck int ret; 434c2c66affSColin Finck size_t i, j, slen, n; 435c2c66affSColin Finck mbedtls_mpi_uint d; 436c2c66affSColin Finck mbedtls_mpi T; 437c2c66affSColin Finck 438c2c66affSColin Finck if( radix < 2 || radix > 16 ) 439c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 440c2c66affSColin Finck 441c2c66affSColin Finck mbedtls_mpi_init( &T ); 442c2c66affSColin Finck 443c2c66affSColin Finck slen = strlen( s ); 444c2c66affSColin Finck 445c2c66affSColin Finck if( radix == 16 ) 446c2c66affSColin Finck { 447c2c66affSColin Finck if( slen > MPI_SIZE_T_MAX >> 2 ) 448c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 449c2c66affSColin Finck 450c2c66affSColin Finck n = BITS_TO_LIMBS( slen << 2 ); 451c2c66affSColin Finck 452c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); 453c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 454c2c66affSColin Finck 455c2c66affSColin Finck for( i = slen, j = 0; i > 0; i--, j++ ) 456c2c66affSColin Finck { 457c2c66affSColin Finck if( i == 1 && s[i - 1] == '-' ) 458c2c66affSColin Finck { 459c2c66affSColin Finck X->s = -1; 460c2c66affSColin Finck break; 461c2c66affSColin Finck } 462c2c66affSColin Finck 463c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); 464c2c66affSColin Finck X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); 465c2c66affSColin Finck } 466c2c66affSColin Finck } 467c2c66affSColin Finck else 468c2c66affSColin Finck { 469c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 470c2c66affSColin Finck 471c2c66affSColin Finck for( i = 0; i < slen; i++ ) 472c2c66affSColin Finck { 473c2c66affSColin Finck if( i == 0 && s[i] == '-' ) 474c2c66affSColin Finck { 475c2c66affSColin Finck X->s = -1; 476c2c66affSColin Finck continue; 477c2c66affSColin Finck } 478c2c66affSColin Finck 479c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); 480c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); 481c2c66affSColin Finck 482c2c66affSColin Finck if( X->s == 1 ) 483c2c66affSColin Finck { 484c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); 485c2c66affSColin Finck } 486c2c66affSColin Finck else 487c2c66affSColin Finck { 488c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); 489c2c66affSColin Finck } 490c2c66affSColin Finck } 491c2c66affSColin Finck } 492c2c66affSColin Finck 493c2c66affSColin Finck cleanup: 494c2c66affSColin Finck 495c2c66affSColin Finck mbedtls_mpi_free( &T ); 496c2c66affSColin Finck 497c2c66affSColin Finck return( ret ); 498c2c66affSColin Finck } 499c2c66affSColin Finck 500c2c66affSColin Finck /* 501c2c66affSColin Finck * Helper to write the digits high-order first 502c2c66affSColin Finck */ 503c2c66affSColin Finck static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) 504c2c66affSColin Finck { 505c2c66affSColin Finck int ret; 506c2c66affSColin Finck mbedtls_mpi_uint r; 507c2c66affSColin Finck 508c2c66affSColin Finck if( radix < 2 || radix > 16 ) 509c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 510c2c66affSColin Finck 511c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); 512c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); 513c2c66affSColin Finck 514c2c66affSColin Finck if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) 515c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); 516c2c66affSColin Finck 517c2c66affSColin Finck if( r < 10 ) 518c2c66affSColin Finck *(*p)++ = (char)( r + 0x30 ); 519c2c66affSColin Finck else 520c2c66affSColin Finck *(*p)++ = (char)( r + 0x37 ); 521c2c66affSColin Finck 522c2c66affSColin Finck cleanup: 523c2c66affSColin Finck 524c2c66affSColin Finck return( ret ); 525c2c66affSColin Finck } 526c2c66affSColin Finck 527c2c66affSColin Finck /* 528c2c66affSColin Finck * Export into an ASCII string 529c2c66affSColin Finck */ 530c2c66affSColin Finck int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, 531c2c66affSColin Finck char *buf, size_t buflen, size_t *olen ) 532c2c66affSColin Finck { 533c2c66affSColin Finck int ret = 0; 534c2c66affSColin Finck size_t n; 535c2c66affSColin Finck char *p; 536c2c66affSColin Finck mbedtls_mpi T; 537c2c66affSColin Finck 538c2c66affSColin Finck if( radix < 2 || radix > 16 ) 539c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 540c2c66affSColin Finck 541c2c66affSColin Finck n = mbedtls_mpi_bitlen( X ); 542c2c66affSColin Finck if( radix >= 4 ) n >>= 1; 543c2c66affSColin Finck if( radix >= 16 ) n >>= 1; 544c2c66affSColin Finck /* 545c2c66affSColin Finck * Round up the buffer length to an even value to ensure that there is 546c2c66affSColin Finck * enough room for hexadecimal values that can be represented in an odd 547c2c66affSColin Finck * number of digits. 548c2c66affSColin Finck */ 549c2c66affSColin Finck n += 3 + ( ( n + 1 ) & 1 ); 550c2c66affSColin Finck 551c2c66affSColin Finck if( buflen < n ) 552c2c66affSColin Finck { 553c2c66affSColin Finck *olen = n; 554c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 555c2c66affSColin Finck } 556c2c66affSColin Finck 557c2c66affSColin Finck p = buf; 558c2c66affSColin Finck mbedtls_mpi_init( &T ); 559c2c66affSColin Finck 560c2c66affSColin Finck if( X->s == -1 ) 561c2c66affSColin Finck *p++ = '-'; 562c2c66affSColin Finck 563c2c66affSColin Finck if( radix == 16 ) 564c2c66affSColin Finck { 565c2c66affSColin Finck int c; 566c2c66affSColin Finck size_t i, j, k; 567c2c66affSColin Finck 568c2c66affSColin Finck for( i = X->n, k = 0; i > 0; i-- ) 569c2c66affSColin Finck { 570c2c66affSColin Finck for( j = ciL; j > 0; j-- ) 571c2c66affSColin Finck { 572c2c66affSColin Finck c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; 573c2c66affSColin Finck 574c2c66affSColin Finck if( c == 0 && k == 0 && ( i + j ) != 2 ) 575c2c66affSColin Finck continue; 576c2c66affSColin Finck 577c2c66affSColin Finck *(p++) = "0123456789ABCDEF" [c / 16]; 578c2c66affSColin Finck *(p++) = "0123456789ABCDEF" [c % 16]; 579c2c66affSColin Finck k = 1; 580c2c66affSColin Finck } 581c2c66affSColin Finck } 582c2c66affSColin Finck } 583c2c66affSColin Finck else 584c2c66affSColin Finck { 585c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); 586c2c66affSColin Finck 587c2c66affSColin Finck if( T.s == -1 ) 588c2c66affSColin Finck T.s = 1; 589c2c66affSColin Finck 590c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); 591c2c66affSColin Finck } 592c2c66affSColin Finck 593c2c66affSColin Finck *p++ = '\0'; 594c2c66affSColin Finck *olen = p - buf; 595c2c66affSColin Finck 596c2c66affSColin Finck cleanup: 597c2c66affSColin Finck 598c2c66affSColin Finck mbedtls_mpi_free( &T ); 599c2c66affSColin Finck 600c2c66affSColin Finck return( ret ); 601c2c66affSColin Finck } 602c2c66affSColin Finck 603c2c66affSColin Finck #if defined(MBEDTLS_FS_IO) 604c2c66affSColin Finck /* 605c2c66affSColin Finck * Read X from an opened file 606c2c66affSColin Finck */ 607c2c66affSColin Finck int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) 608c2c66affSColin Finck { 609c2c66affSColin Finck mbedtls_mpi_uint d; 610c2c66affSColin Finck size_t slen; 611c2c66affSColin Finck char *p; 612c2c66affSColin Finck /* 613c2c66affSColin Finck * Buffer should have space for (short) label and decimal formatted MPI, 614c2c66affSColin Finck * newline characters and '\0' 615c2c66affSColin Finck */ 616c2c66affSColin Finck char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; 617c2c66affSColin Finck 618c2c66affSColin Finck memset( s, 0, sizeof( s ) ); 619c2c66affSColin Finck if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) 620c2c66affSColin Finck return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); 621c2c66affSColin Finck 622c2c66affSColin Finck slen = strlen( s ); 623c2c66affSColin Finck if( slen == sizeof( s ) - 2 ) 624c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 625c2c66affSColin Finck 626c2c66affSColin Finck if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } 627c2c66affSColin Finck if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } 628c2c66affSColin Finck 629c2c66affSColin Finck p = s + slen; 630c2c66affSColin Finck while( p-- > s ) 631c2c66affSColin Finck if( mpi_get_digit( &d, radix, *p ) != 0 ) 632c2c66affSColin Finck break; 633c2c66affSColin Finck 634c2c66affSColin Finck return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); 635c2c66affSColin Finck } 636c2c66affSColin Finck 637c2c66affSColin Finck /* 638c2c66affSColin Finck * Write X into an opened file (or stdout if fout == NULL) 639c2c66affSColin Finck */ 640c2c66affSColin Finck int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) 641c2c66affSColin Finck { 642c2c66affSColin Finck int ret; 643c2c66affSColin Finck size_t n, slen, plen; 644c2c66affSColin Finck /* 645c2c66affSColin Finck * Buffer should have space for (short) label and decimal formatted MPI, 646c2c66affSColin Finck * newline characters and '\0' 647c2c66affSColin Finck */ 648c2c66affSColin Finck char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; 649c2c66affSColin Finck 650c2c66affSColin Finck memset( s, 0, sizeof( s ) ); 651c2c66affSColin Finck 652c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); 653c2c66affSColin Finck 654c2c66affSColin Finck if( p == NULL ) p = ""; 655c2c66affSColin Finck 656c2c66affSColin Finck plen = strlen( p ); 657c2c66affSColin Finck slen = strlen( s ); 658c2c66affSColin Finck s[slen++] = '\r'; 659c2c66affSColin Finck s[slen++] = '\n'; 660c2c66affSColin Finck 661c2c66affSColin Finck if( fout != NULL ) 662c2c66affSColin Finck { 663c2c66affSColin Finck if( fwrite( p, 1, plen, fout ) != plen || 664c2c66affSColin Finck fwrite( s, 1, slen, fout ) != slen ) 665c2c66affSColin Finck return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); 666c2c66affSColin Finck } 667c2c66affSColin Finck else 668c2c66affSColin Finck mbedtls_printf( "%s%s", p, s ); 669c2c66affSColin Finck 670c2c66affSColin Finck cleanup: 671c2c66affSColin Finck 672c2c66affSColin Finck return( ret ); 673c2c66affSColin Finck } 674c2c66affSColin Finck #endif /* MBEDTLS_FS_IO */ 675c2c66affSColin Finck 676c2c66affSColin Finck /* 677c2c66affSColin Finck * Import X from unsigned binary data, big endian 678c2c66affSColin Finck */ 679c2c66affSColin Finck int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) 680c2c66affSColin Finck { 681c2c66affSColin Finck int ret; 682*d9e6c9b5SThomas Faber size_t i, j; 683*d9e6c9b5SThomas Faber size_t const limbs = CHARS_TO_LIMBS( buflen ); 684c2c66affSColin Finck 685*d9e6c9b5SThomas Faber /* Ensure that target MPI has exactly the necessary number of limbs */ 686*d9e6c9b5SThomas Faber if( X->n != limbs ) 687*d9e6c9b5SThomas Faber { 688*d9e6c9b5SThomas Faber mbedtls_mpi_free( X ); 689*d9e6c9b5SThomas Faber mbedtls_mpi_init( X ); 690*d9e6c9b5SThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); 691*d9e6c9b5SThomas Faber } 692c2c66affSColin Finck 693c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 694c2c66affSColin Finck 695*d9e6c9b5SThomas Faber for( i = buflen, j = 0; i > 0; i--, j++ ) 696c2c66affSColin Finck X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); 697c2c66affSColin Finck 698c2c66affSColin Finck cleanup: 699c2c66affSColin Finck 700c2c66affSColin Finck return( ret ); 701c2c66affSColin Finck } 702c2c66affSColin Finck 703c2c66affSColin Finck /* 704c2c66affSColin Finck * Export X into unsigned binary data, big endian 705c2c66affSColin Finck */ 706c2c66affSColin Finck int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) 707c2c66affSColin Finck { 708c2c66affSColin Finck size_t i, j, n; 709c2c66affSColin Finck 710c2c66affSColin Finck n = mbedtls_mpi_size( X ); 711c2c66affSColin Finck 712c2c66affSColin Finck if( buflen < n ) 713c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 714c2c66affSColin Finck 715c2c66affSColin Finck memset( buf, 0, buflen ); 716c2c66affSColin Finck 717c2c66affSColin Finck for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) 718c2c66affSColin Finck buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); 719c2c66affSColin Finck 720c2c66affSColin Finck return( 0 ); 721c2c66affSColin Finck } 722c2c66affSColin Finck 723c2c66affSColin Finck /* 724c2c66affSColin Finck * Left-shift: X <<= count 725c2c66affSColin Finck */ 726c2c66affSColin Finck int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) 727c2c66affSColin Finck { 728c2c66affSColin Finck int ret; 729c2c66affSColin Finck size_t i, v0, t1; 730c2c66affSColin Finck mbedtls_mpi_uint r0 = 0, r1; 731c2c66affSColin Finck 732c2c66affSColin Finck v0 = count / (biL ); 733c2c66affSColin Finck t1 = count & (biL - 1); 734c2c66affSColin Finck 735c2c66affSColin Finck i = mbedtls_mpi_bitlen( X ) + count; 736c2c66affSColin Finck 737c2c66affSColin Finck if( X->n * biL < i ) 738c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); 739c2c66affSColin Finck 740c2c66affSColin Finck ret = 0; 741c2c66affSColin Finck 742c2c66affSColin Finck /* 743c2c66affSColin Finck * shift by count / limb_size 744c2c66affSColin Finck */ 745c2c66affSColin Finck if( v0 > 0 ) 746c2c66affSColin Finck { 747c2c66affSColin Finck for( i = X->n; i > v0; i-- ) 748c2c66affSColin Finck X->p[i - 1] = X->p[i - v0 - 1]; 749c2c66affSColin Finck 750c2c66affSColin Finck for( ; i > 0; i-- ) 751c2c66affSColin Finck X->p[i - 1] = 0; 752c2c66affSColin Finck } 753c2c66affSColin Finck 754c2c66affSColin Finck /* 755c2c66affSColin Finck * shift by count % limb_size 756c2c66affSColin Finck */ 757c2c66affSColin Finck if( t1 > 0 ) 758c2c66affSColin Finck { 759c2c66affSColin Finck for( i = v0; i < X->n; i++ ) 760c2c66affSColin Finck { 761c2c66affSColin Finck r1 = X->p[i] >> (biL - t1); 762c2c66affSColin Finck X->p[i] <<= t1; 763c2c66affSColin Finck X->p[i] |= r0; 764c2c66affSColin Finck r0 = r1; 765c2c66affSColin Finck } 766c2c66affSColin Finck } 767c2c66affSColin Finck 768c2c66affSColin Finck cleanup: 769c2c66affSColin Finck 770c2c66affSColin Finck return( ret ); 771c2c66affSColin Finck } 772c2c66affSColin Finck 773c2c66affSColin Finck /* 774c2c66affSColin Finck * Right-shift: X >>= count 775c2c66affSColin Finck */ 776c2c66affSColin Finck int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) 777c2c66affSColin Finck { 778c2c66affSColin Finck size_t i, v0, v1; 779c2c66affSColin Finck mbedtls_mpi_uint r0 = 0, r1; 780c2c66affSColin Finck 781c2c66affSColin Finck v0 = count / biL; 782c2c66affSColin Finck v1 = count & (biL - 1); 783c2c66affSColin Finck 784c2c66affSColin Finck if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) 785c2c66affSColin Finck return mbedtls_mpi_lset( X, 0 ); 786c2c66affSColin Finck 787c2c66affSColin Finck /* 788c2c66affSColin Finck * shift by count / limb_size 789c2c66affSColin Finck */ 790c2c66affSColin Finck if( v0 > 0 ) 791c2c66affSColin Finck { 792c2c66affSColin Finck for( i = 0; i < X->n - v0; i++ ) 793c2c66affSColin Finck X->p[i] = X->p[i + v0]; 794c2c66affSColin Finck 795c2c66affSColin Finck for( ; i < X->n; i++ ) 796c2c66affSColin Finck X->p[i] = 0; 797c2c66affSColin Finck } 798c2c66affSColin Finck 799c2c66affSColin Finck /* 800c2c66affSColin Finck * shift by count % limb_size 801c2c66affSColin Finck */ 802c2c66affSColin Finck if( v1 > 0 ) 803c2c66affSColin Finck { 804c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 805c2c66affSColin Finck { 806c2c66affSColin Finck r1 = X->p[i - 1] << (biL - v1); 807c2c66affSColin Finck X->p[i - 1] >>= v1; 808c2c66affSColin Finck X->p[i - 1] |= r0; 809c2c66affSColin Finck r0 = r1; 810c2c66affSColin Finck } 811c2c66affSColin Finck } 812c2c66affSColin Finck 813c2c66affSColin Finck return( 0 ); 814c2c66affSColin Finck } 815c2c66affSColin Finck 816c2c66affSColin Finck /* 817c2c66affSColin Finck * Compare unsigned values 818c2c66affSColin Finck */ 819c2c66affSColin Finck int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) 820c2c66affSColin Finck { 821c2c66affSColin Finck size_t i, j; 822c2c66affSColin Finck 823c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 824c2c66affSColin Finck if( X->p[i - 1] != 0 ) 825c2c66affSColin Finck break; 826c2c66affSColin Finck 827c2c66affSColin Finck for( j = Y->n; j > 0; j-- ) 828c2c66affSColin Finck if( Y->p[j - 1] != 0 ) 829c2c66affSColin Finck break; 830c2c66affSColin Finck 831c2c66affSColin Finck if( i == 0 && j == 0 ) 832c2c66affSColin Finck return( 0 ); 833c2c66affSColin Finck 834c2c66affSColin Finck if( i > j ) return( 1 ); 835c2c66affSColin Finck if( j > i ) return( -1 ); 836c2c66affSColin Finck 837c2c66affSColin Finck for( ; i > 0; i-- ) 838c2c66affSColin Finck { 839c2c66affSColin Finck if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); 840c2c66affSColin Finck if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); 841c2c66affSColin Finck } 842c2c66affSColin Finck 843c2c66affSColin Finck return( 0 ); 844c2c66affSColin Finck } 845c2c66affSColin Finck 846c2c66affSColin Finck /* 847c2c66affSColin Finck * Compare signed values 848c2c66affSColin Finck */ 849c2c66affSColin Finck int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) 850c2c66affSColin Finck { 851c2c66affSColin Finck size_t i, j; 852c2c66affSColin Finck 853c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 854c2c66affSColin Finck if( X->p[i - 1] != 0 ) 855c2c66affSColin Finck break; 856c2c66affSColin Finck 857c2c66affSColin Finck for( j = Y->n; j > 0; j-- ) 858c2c66affSColin Finck if( Y->p[j - 1] != 0 ) 859c2c66affSColin Finck break; 860c2c66affSColin Finck 861c2c66affSColin Finck if( i == 0 && j == 0 ) 862c2c66affSColin Finck return( 0 ); 863c2c66affSColin Finck 864c2c66affSColin Finck if( i > j ) return( X->s ); 865c2c66affSColin Finck if( j > i ) return( -Y->s ); 866c2c66affSColin Finck 867c2c66affSColin Finck if( X->s > 0 && Y->s < 0 ) return( 1 ); 868c2c66affSColin Finck if( Y->s > 0 && X->s < 0 ) return( -1 ); 869c2c66affSColin Finck 870c2c66affSColin Finck for( ; i > 0; i-- ) 871c2c66affSColin Finck { 872c2c66affSColin Finck if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); 873c2c66affSColin Finck if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); 874c2c66affSColin Finck } 875c2c66affSColin Finck 876c2c66affSColin Finck return( 0 ); 877c2c66affSColin Finck } 878c2c66affSColin Finck 879c2c66affSColin Finck /* 880c2c66affSColin Finck * Compare signed values 881c2c66affSColin Finck */ 882c2c66affSColin Finck int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) 883c2c66affSColin Finck { 884c2c66affSColin Finck mbedtls_mpi Y; 885c2c66affSColin Finck mbedtls_mpi_uint p[1]; 886c2c66affSColin Finck 887c2c66affSColin Finck *p = ( z < 0 ) ? -z : z; 888c2c66affSColin Finck Y.s = ( z < 0 ) ? -1 : 1; 889c2c66affSColin Finck Y.n = 1; 890c2c66affSColin Finck Y.p = p; 891c2c66affSColin Finck 892c2c66affSColin Finck return( mbedtls_mpi_cmp_mpi( X, &Y ) ); 893c2c66affSColin Finck } 894c2c66affSColin Finck 895c2c66affSColin Finck /* 896c2c66affSColin Finck * Unsigned addition: X = |A| + |B| (HAC 14.7) 897c2c66affSColin Finck */ 898c2c66affSColin Finck int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 899c2c66affSColin Finck { 900c2c66affSColin Finck int ret; 901c2c66affSColin Finck size_t i, j; 902c2c66affSColin Finck mbedtls_mpi_uint *o, *p, c, tmp; 903c2c66affSColin Finck 904c2c66affSColin Finck if( X == B ) 905c2c66affSColin Finck { 906c2c66affSColin Finck const mbedtls_mpi *T = A; A = X; B = T; 907c2c66affSColin Finck } 908c2c66affSColin Finck 909c2c66affSColin Finck if( X != A ) 910c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); 911c2c66affSColin Finck 912c2c66affSColin Finck /* 913c2c66affSColin Finck * X should always be positive as a result of unsigned additions. 914c2c66affSColin Finck */ 915c2c66affSColin Finck X->s = 1; 916c2c66affSColin Finck 917c2c66affSColin Finck for( j = B->n; j > 0; j-- ) 918c2c66affSColin Finck if( B->p[j - 1] != 0 ) 919c2c66affSColin Finck break; 920c2c66affSColin Finck 921c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); 922c2c66affSColin Finck 923c2c66affSColin Finck o = B->p; p = X->p; c = 0; 924c2c66affSColin Finck 925c2c66affSColin Finck /* 926c2c66affSColin Finck * tmp is used because it might happen that p == o 927c2c66affSColin Finck */ 928c2c66affSColin Finck for( i = 0; i < j; i++, o++, p++ ) 929c2c66affSColin Finck { 930c2c66affSColin Finck tmp= *o; 931c2c66affSColin Finck *p += c; c = ( *p < c ); 932c2c66affSColin Finck *p += tmp; c += ( *p < tmp ); 933c2c66affSColin Finck } 934c2c66affSColin Finck 935c2c66affSColin Finck while( c != 0 ) 936c2c66affSColin Finck { 937c2c66affSColin Finck if( i >= X->n ) 938c2c66affSColin Finck { 939c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); 940c2c66affSColin Finck p = X->p + i; 941c2c66affSColin Finck } 942c2c66affSColin Finck 943c2c66affSColin Finck *p += c; c = ( *p < c ); i++; p++; 944c2c66affSColin Finck } 945c2c66affSColin Finck 946c2c66affSColin Finck cleanup: 947c2c66affSColin Finck 948c2c66affSColin Finck return( ret ); 949c2c66affSColin Finck } 950c2c66affSColin Finck 951c2c66affSColin Finck /* 952c2c66affSColin Finck * Helper for mbedtls_mpi subtraction 953c2c66affSColin Finck */ 954c2c66affSColin Finck static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) 955c2c66affSColin Finck { 956c2c66affSColin Finck size_t i; 957c2c66affSColin Finck mbedtls_mpi_uint c, z; 958c2c66affSColin Finck 959c2c66affSColin Finck for( i = c = 0; i < n; i++, s++, d++ ) 960c2c66affSColin Finck { 961c2c66affSColin Finck z = ( *d < c ); *d -= c; 962c2c66affSColin Finck c = ( *d < *s ) + z; *d -= *s; 963c2c66affSColin Finck } 964c2c66affSColin Finck 965c2c66affSColin Finck while( c != 0 ) 966c2c66affSColin Finck { 967c2c66affSColin Finck z = ( *d < c ); *d -= c; 968c2c66affSColin Finck c = z; i++; d++; 969c2c66affSColin Finck } 970c2c66affSColin Finck } 971c2c66affSColin Finck 972c2c66affSColin Finck /* 973c2c66affSColin Finck * Unsigned subtraction: X = |A| - |B| (HAC 14.9) 974c2c66affSColin Finck */ 975c2c66affSColin Finck int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 976c2c66affSColin Finck { 977c2c66affSColin Finck mbedtls_mpi TB; 978c2c66affSColin Finck int ret; 979c2c66affSColin Finck size_t n; 980c2c66affSColin Finck 981c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) 982c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); 983c2c66affSColin Finck 984c2c66affSColin Finck mbedtls_mpi_init( &TB ); 985c2c66affSColin Finck 986c2c66affSColin Finck if( X == B ) 987c2c66affSColin Finck { 988c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); 989c2c66affSColin Finck B = &TB; 990c2c66affSColin Finck } 991c2c66affSColin Finck 992c2c66affSColin Finck if( X != A ) 993c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); 994c2c66affSColin Finck 995c2c66affSColin Finck /* 996c2c66affSColin Finck * X should always be positive as a result of unsigned subtractions. 997c2c66affSColin Finck */ 998c2c66affSColin Finck X->s = 1; 999c2c66affSColin Finck 1000c2c66affSColin Finck ret = 0; 1001c2c66affSColin Finck 1002c2c66affSColin Finck for( n = B->n; n > 0; n-- ) 1003c2c66affSColin Finck if( B->p[n - 1] != 0 ) 1004c2c66affSColin Finck break; 1005c2c66affSColin Finck 1006c2c66affSColin Finck mpi_sub_hlp( n, B->p, X->p ); 1007c2c66affSColin Finck 1008c2c66affSColin Finck cleanup: 1009c2c66affSColin Finck 1010c2c66affSColin Finck mbedtls_mpi_free( &TB ); 1011c2c66affSColin Finck 1012c2c66affSColin Finck return( ret ); 1013c2c66affSColin Finck } 1014c2c66affSColin Finck 1015c2c66affSColin Finck /* 1016c2c66affSColin Finck * Signed addition: X = A + B 1017c2c66affSColin Finck */ 1018c2c66affSColin Finck int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1019c2c66affSColin Finck { 1020c2c66affSColin Finck int ret, s = A->s; 1021c2c66affSColin Finck 1022c2c66affSColin Finck if( A->s * B->s < 0 ) 1023c2c66affSColin Finck { 1024c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) 1025c2c66affSColin Finck { 1026c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); 1027c2c66affSColin Finck X->s = s; 1028c2c66affSColin Finck } 1029c2c66affSColin Finck else 1030c2c66affSColin Finck { 1031c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); 1032c2c66affSColin Finck X->s = -s; 1033c2c66affSColin Finck } 1034c2c66affSColin Finck } 1035c2c66affSColin Finck else 1036c2c66affSColin Finck { 1037c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); 1038c2c66affSColin Finck X->s = s; 1039c2c66affSColin Finck } 1040c2c66affSColin Finck 1041c2c66affSColin Finck cleanup: 1042c2c66affSColin Finck 1043c2c66affSColin Finck return( ret ); 1044c2c66affSColin Finck } 1045c2c66affSColin Finck 1046c2c66affSColin Finck /* 1047c2c66affSColin Finck * Signed subtraction: X = A - B 1048c2c66affSColin Finck */ 1049c2c66affSColin Finck int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1050c2c66affSColin Finck { 1051c2c66affSColin Finck int ret, s = A->s; 1052c2c66affSColin Finck 1053c2c66affSColin Finck if( A->s * B->s > 0 ) 1054c2c66affSColin Finck { 1055c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) 1056c2c66affSColin Finck { 1057c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); 1058c2c66affSColin Finck X->s = s; 1059c2c66affSColin Finck } 1060c2c66affSColin Finck else 1061c2c66affSColin Finck { 1062c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); 1063c2c66affSColin Finck X->s = -s; 1064c2c66affSColin Finck } 1065c2c66affSColin Finck } 1066c2c66affSColin Finck else 1067c2c66affSColin Finck { 1068c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); 1069c2c66affSColin Finck X->s = s; 1070c2c66affSColin Finck } 1071c2c66affSColin Finck 1072c2c66affSColin Finck cleanup: 1073c2c66affSColin Finck 1074c2c66affSColin Finck return( ret ); 1075c2c66affSColin Finck } 1076c2c66affSColin Finck 1077c2c66affSColin Finck /* 1078c2c66affSColin Finck * Signed addition: X = A + b 1079c2c66affSColin Finck */ 1080c2c66affSColin Finck int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1081c2c66affSColin Finck { 1082c2c66affSColin Finck mbedtls_mpi _B; 1083c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1084c2c66affSColin Finck 1085c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1086c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1087c2c66affSColin Finck _B.n = 1; 1088c2c66affSColin Finck _B.p = p; 1089c2c66affSColin Finck 1090c2c66affSColin Finck return( mbedtls_mpi_add_mpi( X, A, &_B ) ); 1091c2c66affSColin Finck } 1092c2c66affSColin Finck 1093c2c66affSColin Finck /* 1094c2c66affSColin Finck * Signed subtraction: X = A - b 1095c2c66affSColin Finck */ 1096c2c66affSColin Finck int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1097c2c66affSColin Finck { 1098c2c66affSColin Finck mbedtls_mpi _B; 1099c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1100c2c66affSColin Finck 1101c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1102c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1103c2c66affSColin Finck _B.n = 1; 1104c2c66affSColin Finck _B.p = p; 1105c2c66affSColin Finck 1106c2c66affSColin Finck return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); 1107c2c66affSColin Finck } 1108c2c66affSColin Finck 1109c2c66affSColin Finck /* 1110c2c66affSColin Finck * Helper for mbedtls_mpi multiplication 1111c2c66affSColin Finck */ 1112c2c66affSColin Finck static 1113c2c66affSColin Finck #if defined(__APPLE__) && defined(__arm__) 1114c2c66affSColin Finck /* 1115c2c66affSColin Finck * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) 1116c2c66affSColin Finck * appears to need this to prevent bad ARM code generation at -O3. 1117c2c66affSColin Finck */ 1118c2c66affSColin Finck __attribute__ ((noinline)) 1119c2c66affSColin Finck #endif 1120c2c66affSColin Finck void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) 1121c2c66affSColin Finck { 1122c2c66affSColin Finck mbedtls_mpi_uint c = 0, t = 0; 1123c2c66affSColin Finck 1124c2c66affSColin Finck #if defined(MULADDC_HUIT) 1125c2c66affSColin Finck for( ; i >= 8; i -= 8 ) 1126c2c66affSColin Finck { 1127c2c66affSColin Finck MULADDC_INIT 1128c2c66affSColin Finck MULADDC_HUIT 1129c2c66affSColin Finck MULADDC_STOP 1130c2c66affSColin Finck } 1131c2c66affSColin Finck 1132c2c66affSColin Finck for( ; i > 0; i-- ) 1133c2c66affSColin Finck { 1134c2c66affSColin Finck MULADDC_INIT 1135c2c66affSColin Finck MULADDC_CORE 1136c2c66affSColin Finck MULADDC_STOP 1137c2c66affSColin Finck } 1138c2c66affSColin Finck #else /* MULADDC_HUIT */ 1139c2c66affSColin Finck for( ; i >= 16; i -= 16 ) 1140c2c66affSColin Finck { 1141c2c66affSColin Finck MULADDC_INIT 1142c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1143c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1144c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1145c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1146c2c66affSColin Finck 1147c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1148c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1149c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1150c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1151c2c66affSColin Finck MULADDC_STOP 1152c2c66affSColin Finck } 1153c2c66affSColin Finck 1154c2c66affSColin Finck for( ; i >= 8; i -= 8 ) 1155c2c66affSColin Finck { 1156c2c66affSColin Finck MULADDC_INIT 1157c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1158c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1159c2c66affSColin Finck 1160c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1161c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1162c2c66affSColin Finck MULADDC_STOP 1163c2c66affSColin Finck } 1164c2c66affSColin Finck 1165c2c66affSColin Finck for( ; i > 0; i-- ) 1166c2c66affSColin Finck { 1167c2c66affSColin Finck MULADDC_INIT 1168c2c66affSColin Finck MULADDC_CORE 1169c2c66affSColin Finck MULADDC_STOP 1170c2c66affSColin Finck } 1171c2c66affSColin Finck #endif /* MULADDC_HUIT */ 1172c2c66affSColin Finck 1173c2c66affSColin Finck t++; 1174c2c66affSColin Finck 1175c2c66affSColin Finck do { 1176c2c66affSColin Finck *d += c; c = ( *d < c ); d++; 1177c2c66affSColin Finck } 1178c2c66affSColin Finck while( c != 0 ); 1179c2c66affSColin Finck } 1180c2c66affSColin Finck 1181c2c66affSColin Finck /* 1182c2c66affSColin Finck * Baseline multiplication: X = A * B (HAC 14.12) 1183c2c66affSColin Finck */ 1184c2c66affSColin Finck int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1185c2c66affSColin Finck { 1186c2c66affSColin Finck int ret; 1187c2c66affSColin Finck size_t i, j; 1188c2c66affSColin Finck mbedtls_mpi TA, TB; 1189c2c66affSColin Finck 1190c2c66affSColin Finck mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); 1191c2c66affSColin Finck 1192c2c66affSColin Finck if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } 1193c2c66affSColin Finck if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } 1194c2c66affSColin Finck 1195c2c66affSColin Finck for( i = A->n; i > 0; i-- ) 1196c2c66affSColin Finck if( A->p[i - 1] != 0 ) 1197c2c66affSColin Finck break; 1198c2c66affSColin Finck 1199c2c66affSColin Finck for( j = B->n; j > 0; j-- ) 1200c2c66affSColin Finck if( B->p[j - 1] != 0 ) 1201c2c66affSColin Finck break; 1202c2c66affSColin Finck 1203c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); 1204c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 1205c2c66affSColin Finck 1206c2c66affSColin Finck for( i++; j > 0; j-- ) 1207c2c66affSColin Finck mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); 1208c2c66affSColin Finck 1209c2c66affSColin Finck X->s = A->s * B->s; 1210c2c66affSColin Finck 1211c2c66affSColin Finck cleanup: 1212c2c66affSColin Finck 1213c2c66affSColin Finck mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); 1214c2c66affSColin Finck 1215c2c66affSColin Finck return( ret ); 1216c2c66affSColin Finck } 1217c2c66affSColin Finck 1218c2c66affSColin Finck /* 1219c2c66affSColin Finck * Baseline multiplication: X = A * b 1220c2c66affSColin Finck */ 1221c2c66affSColin Finck int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) 1222c2c66affSColin Finck { 1223c2c66affSColin Finck mbedtls_mpi _B; 1224c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1225c2c66affSColin Finck 1226c2c66affSColin Finck _B.s = 1; 1227c2c66affSColin Finck _B.n = 1; 1228c2c66affSColin Finck _B.p = p; 1229c2c66affSColin Finck p[0] = b; 1230c2c66affSColin Finck 1231c2c66affSColin Finck return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); 1232c2c66affSColin Finck } 1233c2c66affSColin Finck 1234c2c66affSColin Finck /* 1235c2c66affSColin Finck * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and 1236c2c66affSColin Finck * mbedtls_mpi_uint divisor, d 1237c2c66affSColin Finck */ 1238c2c66affSColin Finck static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, 1239c2c66affSColin Finck mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) 1240c2c66affSColin Finck { 1241c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL) 1242c2c66affSColin Finck mbedtls_t_udbl dividend, quotient; 1243c2c66affSColin Finck #else 1244c2c66affSColin Finck const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; 1245c2c66affSColin Finck const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; 1246c2c66affSColin Finck mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; 1247c2c66affSColin Finck mbedtls_mpi_uint u0_msw, u0_lsw; 1248c2c66affSColin Finck size_t s; 1249c2c66affSColin Finck #endif 1250c2c66affSColin Finck 1251c2c66affSColin Finck /* 1252c2c66affSColin Finck * Check for overflow 1253c2c66affSColin Finck */ 1254c2c66affSColin Finck if( 0 == d || u1 >= d ) 1255c2c66affSColin Finck { 1256c2c66affSColin Finck if (r != NULL) *r = ~0; 1257c2c66affSColin Finck 1258c2c66affSColin Finck return ( ~0 ); 1259c2c66affSColin Finck } 1260c2c66affSColin Finck 1261c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL) 1262c2c66affSColin Finck dividend = (mbedtls_t_udbl) u1 << biL; 1263c2c66affSColin Finck dividend |= (mbedtls_t_udbl) u0; 1264c2c66affSColin Finck quotient = dividend / d; 1265c2c66affSColin Finck if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) 1266c2c66affSColin Finck quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; 1267c2c66affSColin Finck 1268c2c66affSColin Finck if( r != NULL ) 1269c2c66affSColin Finck *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); 1270c2c66affSColin Finck 1271c2c66affSColin Finck return (mbedtls_mpi_uint) quotient; 1272c2c66affSColin Finck #else 1273c2c66affSColin Finck 1274c2c66affSColin Finck /* 1275c2c66affSColin Finck * Algorithm D, Section 4.3.1 - The Art of Computer Programming 1276c2c66affSColin Finck * Vol. 2 - Seminumerical Algorithms, Knuth 1277c2c66affSColin Finck */ 1278c2c66affSColin Finck 1279c2c66affSColin Finck /* 1280c2c66affSColin Finck * Normalize the divisor, d, and dividend, u0, u1 1281c2c66affSColin Finck */ 1282c2c66affSColin Finck s = mbedtls_clz( d ); 1283c2c66affSColin Finck d = d << s; 1284c2c66affSColin Finck 1285c2c66affSColin Finck u1 = u1 << s; 1286c2c66affSColin Finck u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); 1287c2c66affSColin Finck u0 = u0 << s; 1288c2c66affSColin Finck 1289c2c66affSColin Finck d1 = d >> biH; 1290c2c66affSColin Finck d0 = d & uint_halfword_mask; 1291c2c66affSColin Finck 1292c2c66affSColin Finck u0_msw = u0 >> biH; 1293c2c66affSColin Finck u0_lsw = u0 & uint_halfword_mask; 1294c2c66affSColin Finck 1295c2c66affSColin Finck /* 1296c2c66affSColin Finck * Find the first quotient and remainder 1297c2c66affSColin Finck */ 1298c2c66affSColin Finck q1 = u1 / d1; 1299c2c66affSColin Finck r0 = u1 - d1 * q1; 1300c2c66affSColin Finck 1301c2c66affSColin Finck while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) 1302c2c66affSColin Finck { 1303c2c66affSColin Finck q1 -= 1; 1304c2c66affSColin Finck r0 += d1; 1305c2c66affSColin Finck 1306c2c66affSColin Finck if ( r0 >= radix ) break; 1307c2c66affSColin Finck } 1308c2c66affSColin Finck 1309c2c66affSColin Finck rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); 1310c2c66affSColin Finck q0 = rAX / d1; 1311c2c66affSColin Finck r0 = rAX - q0 * d1; 1312c2c66affSColin Finck 1313c2c66affSColin Finck while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) 1314c2c66affSColin Finck { 1315c2c66affSColin Finck q0 -= 1; 1316c2c66affSColin Finck r0 += d1; 1317c2c66affSColin Finck 1318c2c66affSColin Finck if ( r0 >= radix ) break; 1319c2c66affSColin Finck } 1320c2c66affSColin Finck 1321c2c66affSColin Finck if (r != NULL) 1322c2c66affSColin Finck *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; 1323c2c66affSColin Finck 1324c2c66affSColin Finck quotient = q1 * radix + q0; 1325c2c66affSColin Finck 1326c2c66affSColin Finck return quotient; 1327c2c66affSColin Finck #endif 1328c2c66affSColin Finck } 1329c2c66affSColin Finck 1330c2c66affSColin Finck /* 1331c2c66affSColin Finck * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) 1332c2c66affSColin Finck */ 1333c2c66affSColin Finck int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1334c2c66affSColin Finck { 1335c2c66affSColin Finck int ret; 1336c2c66affSColin Finck size_t i, n, t, k; 1337c2c66affSColin Finck mbedtls_mpi X, Y, Z, T1, T2; 1338c2c66affSColin Finck 1339c2c66affSColin Finck if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) 1340c2c66affSColin Finck return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); 1341c2c66affSColin Finck 1342c2c66affSColin Finck mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); 1343c2c66affSColin Finck mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); 1344c2c66affSColin Finck 1345c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) 1346c2c66affSColin Finck { 1347c2c66affSColin Finck if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); 1348c2c66affSColin Finck if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); 1349c2c66affSColin Finck return( 0 ); 1350c2c66affSColin Finck } 1351c2c66affSColin Finck 1352c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); 1353c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); 1354c2c66affSColin Finck X.s = Y.s = 1; 1355c2c66affSColin Finck 1356c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); 1357c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); 1358c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); 1359c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); 1360c2c66affSColin Finck 1361c2c66affSColin Finck k = mbedtls_mpi_bitlen( &Y ) % biL; 1362c2c66affSColin Finck if( k < biL - 1 ) 1363c2c66affSColin Finck { 1364c2c66affSColin Finck k = biL - 1 - k; 1365c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); 1366c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); 1367c2c66affSColin Finck } 1368c2c66affSColin Finck else k = 0; 1369c2c66affSColin Finck 1370c2c66affSColin Finck n = X.n - 1; 1371c2c66affSColin Finck t = Y.n - 1; 1372c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); 1373c2c66affSColin Finck 1374c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) 1375c2c66affSColin Finck { 1376c2c66affSColin Finck Z.p[n - t]++; 1377c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); 1378c2c66affSColin Finck } 1379c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); 1380c2c66affSColin Finck 1381c2c66affSColin Finck for( i = n; i > t ; i-- ) 1382c2c66affSColin Finck { 1383c2c66affSColin Finck if( X.p[i] >= Y.p[t] ) 1384c2c66affSColin Finck Z.p[i - t - 1] = ~0; 1385c2c66affSColin Finck else 1386c2c66affSColin Finck { 1387c2c66affSColin Finck Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], 1388c2c66affSColin Finck Y.p[t], NULL); 1389c2c66affSColin Finck } 1390c2c66affSColin Finck 1391c2c66affSColin Finck Z.p[i - t - 1]++; 1392c2c66affSColin Finck do 1393c2c66affSColin Finck { 1394c2c66affSColin Finck Z.p[i - t - 1]--; 1395c2c66affSColin Finck 1396c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); 1397c2c66affSColin Finck T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; 1398c2c66affSColin Finck T1.p[1] = Y.p[t]; 1399c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); 1400c2c66affSColin Finck 1401c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); 1402c2c66affSColin Finck T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; 1403c2c66affSColin Finck T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; 1404c2c66affSColin Finck T2.p[2] = X.p[i]; 1405c2c66affSColin Finck } 1406c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); 1407c2c66affSColin Finck 1408c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); 1409c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); 1410c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); 1411c2c66affSColin Finck 1412c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) 1413c2c66affSColin Finck { 1414c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); 1415c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); 1416c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); 1417c2c66affSColin Finck Z.p[i - t - 1]--; 1418c2c66affSColin Finck } 1419c2c66affSColin Finck } 1420c2c66affSColin Finck 1421c2c66affSColin Finck if( Q != NULL ) 1422c2c66affSColin Finck { 1423c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); 1424c2c66affSColin Finck Q->s = A->s * B->s; 1425c2c66affSColin Finck } 1426c2c66affSColin Finck 1427c2c66affSColin Finck if( R != NULL ) 1428c2c66affSColin Finck { 1429c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); 1430c2c66affSColin Finck X.s = A->s; 1431c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); 1432c2c66affSColin Finck 1433c2c66affSColin Finck if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) 1434c2c66affSColin Finck R->s = 1; 1435c2c66affSColin Finck } 1436c2c66affSColin Finck 1437c2c66affSColin Finck cleanup: 1438c2c66affSColin Finck 1439c2c66affSColin Finck mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); 1440c2c66affSColin Finck mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); 1441c2c66affSColin Finck 1442c2c66affSColin Finck return( ret ); 1443c2c66affSColin Finck } 1444c2c66affSColin Finck 1445c2c66affSColin Finck /* 1446c2c66affSColin Finck * Division by int: A = Q * b + R 1447c2c66affSColin Finck */ 1448c2c66affSColin Finck int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1449c2c66affSColin Finck { 1450c2c66affSColin Finck mbedtls_mpi _B; 1451c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1452c2c66affSColin Finck 1453c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1454c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1455c2c66affSColin Finck _B.n = 1; 1456c2c66affSColin Finck _B.p = p; 1457c2c66affSColin Finck 1458c2c66affSColin Finck return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); 1459c2c66affSColin Finck } 1460c2c66affSColin Finck 1461c2c66affSColin Finck /* 1462c2c66affSColin Finck * Modulo: R = A mod B 1463c2c66affSColin Finck */ 1464c2c66affSColin Finck int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1465c2c66affSColin Finck { 1466c2c66affSColin Finck int ret; 1467c2c66affSColin Finck 1468c2c66affSColin Finck if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) 1469c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); 1470c2c66affSColin Finck 1471c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); 1472c2c66affSColin Finck 1473c2c66affSColin Finck while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) 1474c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); 1475c2c66affSColin Finck 1476c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) 1477c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); 1478c2c66affSColin Finck 1479c2c66affSColin Finck cleanup: 1480c2c66affSColin Finck 1481c2c66affSColin Finck return( ret ); 1482c2c66affSColin Finck } 1483c2c66affSColin Finck 1484c2c66affSColin Finck /* 1485c2c66affSColin Finck * Modulo: r = A mod b 1486c2c66affSColin Finck */ 1487c2c66affSColin Finck int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1488c2c66affSColin Finck { 1489c2c66affSColin Finck size_t i; 1490c2c66affSColin Finck mbedtls_mpi_uint x, y, z; 1491c2c66affSColin Finck 1492c2c66affSColin Finck if( b == 0 ) 1493c2c66affSColin Finck return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); 1494c2c66affSColin Finck 1495c2c66affSColin Finck if( b < 0 ) 1496c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); 1497c2c66affSColin Finck 1498c2c66affSColin Finck /* 1499c2c66affSColin Finck * handle trivial cases 1500c2c66affSColin Finck */ 1501c2c66affSColin Finck if( b == 1 ) 1502c2c66affSColin Finck { 1503c2c66affSColin Finck *r = 0; 1504c2c66affSColin Finck return( 0 ); 1505c2c66affSColin Finck } 1506c2c66affSColin Finck 1507c2c66affSColin Finck if( b == 2 ) 1508c2c66affSColin Finck { 1509c2c66affSColin Finck *r = A->p[0] & 1; 1510c2c66affSColin Finck return( 0 ); 1511c2c66affSColin Finck } 1512c2c66affSColin Finck 1513c2c66affSColin Finck /* 1514c2c66affSColin Finck * general case 1515c2c66affSColin Finck */ 1516c2c66affSColin Finck for( i = A->n, y = 0; i > 0; i-- ) 1517c2c66affSColin Finck { 1518c2c66affSColin Finck x = A->p[i - 1]; 1519c2c66affSColin Finck y = ( y << biH ) | ( x >> biH ); 1520c2c66affSColin Finck z = y / b; 1521c2c66affSColin Finck y -= z * b; 1522c2c66affSColin Finck 1523c2c66affSColin Finck x <<= biH; 1524c2c66affSColin Finck y = ( y << biH ) | ( x >> biH ); 1525c2c66affSColin Finck z = y / b; 1526c2c66affSColin Finck y -= z * b; 1527c2c66affSColin Finck } 1528c2c66affSColin Finck 1529c2c66affSColin Finck /* 1530c2c66affSColin Finck * If A is negative, then the current y represents a negative value. 1531c2c66affSColin Finck * Flipping it to the positive side. 1532c2c66affSColin Finck */ 1533c2c66affSColin Finck if( A->s < 0 && y != 0 ) 1534c2c66affSColin Finck y = b - y; 1535c2c66affSColin Finck 1536c2c66affSColin Finck *r = y; 1537c2c66affSColin Finck 1538c2c66affSColin Finck return( 0 ); 1539c2c66affSColin Finck } 1540c2c66affSColin Finck 1541c2c66affSColin Finck /* 1542c2c66affSColin Finck * Fast Montgomery initialization (thanks to Tom St Denis) 1543c2c66affSColin Finck */ 1544c2c66affSColin Finck static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) 1545c2c66affSColin Finck { 1546c2c66affSColin Finck mbedtls_mpi_uint x, m0 = N->p[0]; 1547c2c66affSColin Finck unsigned int i; 1548c2c66affSColin Finck 1549c2c66affSColin Finck x = m0; 1550c2c66affSColin Finck x += ( ( m0 + 2 ) & 4 ) << 1; 1551c2c66affSColin Finck 1552c2c66affSColin Finck for( i = biL; i >= 8; i /= 2 ) 1553c2c66affSColin Finck x *= ( 2 - ( m0 * x ) ); 1554c2c66affSColin Finck 1555c2c66affSColin Finck *mm = ~x + 1; 1556c2c66affSColin Finck } 1557c2c66affSColin Finck 1558c2c66affSColin Finck /* 1559c2c66affSColin Finck * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) 1560c2c66affSColin Finck */ 1561c2c66affSColin Finck static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, 1562c2c66affSColin Finck const mbedtls_mpi *T ) 1563c2c66affSColin Finck { 1564c2c66affSColin Finck size_t i, n, m; 1565c2c66affSColin Finck mbedtls_mpi_uint u0, u1, *d; 1566c2c66affSColin Finck 1567c2c66affSColin Finck if( T->n < N->n + 1 || T->p == NULL ) 1568c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 1569c2c66affSColin Finck 1570c2c66affSColin Finck memset( T->p, 0, T->n * ciL ); 1571c2c66affSColin Finck 1572c2c66affSColin Finck d = T->p; 1573c2c66affSColin Finck n = N->n; 1574c2c66affSColin Finck m = ( B->n < n ) ? B->n : n; 1575c2c66affSColin Finck 1576c2c66affSColin Finck for( i = 0; i < n; i++ ) 1577c2c66affSColin Finck { 1578c2c66affSColin Finck /* 1579c2c66affSColin Finck * T = (T + u0*B + u1*N) / 2^biL 1580c2c66affSColin Finck */ 1581c2c66affSColin Finck u0 = A->p[i]; 1582c2c66affSColin Finck u1 = ( d[0] + u0 * B->p[0] ) * mm; 1583c2c66affSColin Finck 1584c2c66affSColin Finck mpi_mul_hlp( m, B->p, d, u0 ); 1585c2c66affSColin Finck mpi_mul_hlp( n, N->p, d, u1 ); 1586c2c66affSColin Finck 1587c2c66affSColin Finck *d++ = u0; d[n + 1] = 0; 1588c2c66affSColin Finck } 1589c2c66affSColin Finck 1590c2c66affSColin Finck memcpy( A->p, d, ( n + 1 ) * ciL ); 1591c2c66affSColin Finck 1592c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) 1593c2c66affSColin Finck mpi_sub_hlp( n, N->p, A->p ); 1594c2c66affSColin Finck else 1595c2c66affSColin Finck /* prevent timing attacks */ 1596c2c66affSColin Finck mpi_sub_hlp( n, A->p, T->p ); 1597c2c66affSColin Finck 1598c2c66affSColin Finck return( 0 ); 1599c2c66affSColin Finck } 1600c2c66affSColin Finck 1601c2c66affSColin Finck /* 1602c2c66affSColin Finck * Montgomery reduction: A = A * R^-1 mod N 1603c2c66affSColin Finck */ 1604c2c66affSColin Finck static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) 1605c2c66affSColin Finck { 1606c2c66affSColin Finck mbedtls_mpi_uint z = 1; 1607c2c66affSColin Finck mbedtls_mpi U; 1608c2c66affSColin Finck 1609c2c66affSColin Finck U.n = U.s = (int) z; 1610c2c66affSColin Finck U.p = &z; 1611c2c66affSColin Finck 1612c2c66affSColin Finck return( mpi_montmul( A, &U, N, mm, T ) ); 1613c2c66affSColin Finck } 1614c2c66affSColin Finck 1615c2c66affSColin Finck /* 1616c2c66affSColin Finck * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) 1617c2c66affSColin Finck */ 1618c2c66affSColin Finck int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) 1619c2c66affSColin Finck { 1620c2c66affSColin Finck int ret; 1621c2c66affSColin Finck size_t wbits, wsize, one = 1; 1622c2c66affSColin Finck size_t i, j, nblimbs; 1623c2c66affSColin Finck size_t bufsize, nbits; 1624c2c66affSColin Finck mbedtls_mpi_uint ei, mm, state; 1625c2c66affSColin Finck mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; 1626c2c66affSColin Finck int neg; 1627c2c66affSColin Finck 1628*d9e6c9b5SThomas Faber if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) 1629c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 1630c2c66affSColin Finck 1631c2c66affSColin Finck if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) 1632c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 1633c2c66affSColin Finck 1634c2c66affSColin Finck /* 1635c2c66affSColin Finck * Init temps and window size 1636c2c66affSColin Finck */ 1637c2c66affSColin Finck mpi_montg_init( &mm, N ); 1638c2c66affSColin Finck mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); 1639c2c66affSColin Finck mbedtls_mpi_init( &Apos ); 1640c2c66affSColin Finck memset( W, 0, sizeof( W ) ); 1641c2c66affSColin Finck 1642c2c66affSColin Finck i = mbedtls_mpi_bitlen( E ); 1643c2c66affSColin Finck 1644c2c66affSColin Finck wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : 1645c2c66affSColin Finck ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; 1646c2c66affSColin Finck 1647c2c66affSColin Finck if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) 1648c2c66affSColin Finck wsize = MBEDTLS_MPI_WINDOW_SIZE; 1649c2c66affSColin Finck 1650c2c66affSColin Finck j = N->n + 1; 1651c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); 1652c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); 1653c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); 1654c2c66affSColin Finck 1655c2c66affSColin Finck /* 1656c2c66affSColin Finck * Compensate for negative A (and correct at the end) 1657c2c66affSColin Finck */ 1658c2c66affSColin Finck neg = ( A->s == -1 ); 1659c2c66affSColin Finck if( neg ) 1660c2c66affSColin Finck { 1661c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); 1662c2c66affSColin Finck Apos.s = 1; 1663c2c66affSColin Finck A = &Apos; 1664c2c66affSColin Finck } 1665c2c66affSColin Finck 1666c2c66affSColin Finck /* 1667c2c66affSColin Finck * If 1st call, pre-compute R^2 mod N 1668c2c66affSColin Finck */ 1669c2c66affSColin Finck if( _RR == NULL || _RR->p == NULL ) 1670c2c66affSColin Finck { 1671c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); 1672c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); 1673c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); 1674c2c66affSColin Finck 1675c2c66affSColin Finck if( _RR != NULL ) 1676c2c66affSColin Finck memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); 1677c2c66affSColin Finck } 1678c2c66affSColin Finck else 1679c2c66affSColin Finck memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); 1680c2c66affSColin Finck 1681c2c66affSColin Finck /* 1682c2c66affSColin Finck * W[1] = A * R^2 * R^-1 mod N = A * R mod N 1683c2c66affSColin Finck */ 1684c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) 1685c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); 1686c2c66affSColin Finck else 1687c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); 1688c2c66affSColin Finck 1689c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); 1690c2c66affSColin Finck 1691c2c66affSColin Finck /* 1692c2c66affSColin Finck * X = R^2 * R^-1 mod N = R mod N 1693c2c66affSColin Finck */ 1694c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); 1695c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); 1696c2c66affSColin Finck 1697c2c66affSColin Finck if( wsize > 1 ) 1698c2c66affSColin Finck { 1699c2c66affSColin Finck /* 1700c2c66affSColin Finck * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) 1701c2c66affSColin Finck */ 1702c2c66affSColin Finck j = one << ( wsize - 1 ); 1703c2c66affSColin Finck 1704c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); 1705c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); 1706c2c66affSColin Finck 1707c2c66affSColin Finck for( i = 0; i < wsize - 1; i++ ) 1708c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); 1709c2c66affSColin Finck 1710c2c66affSColin Finck /* 1711c2c66affSColin Finck * W[i] = W[i - 1] * W[1] 1712c2c66affSColin Finck */ 1713c2c66affSColin Finck for( i = j + 1; i < ( one << wsize ); i++ ) 1714c2c66affSColin Finck { 1715c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); 1716c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); 1717c2c66affSColin Finck 1718c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); 1719c2c66affSColin Finck } 1720c2c66affSColin Finck } 1721c2c66affSColin Finck 1722c2c66affSColin Finck nblimbs = E->n; 1723c2c66affSColin Finck bufsize = 0; 1724c2c66affSColin Finck nbits = 0; 1725c2c66affSColin Finck wbits = 0; 1726c2c66affSColin Finck state = 0; 1727c2c66affSColin Finck 1728c2c66affSColin Finck while( 1 ) 1729c2c66affSColin Finck { 1730c2c66affSColin Finck if( bufsize == 0 ) 1731c2c66affSColin Finck { 1732c2c66affSColin Finck if( nblimbs == 0 ) 1733c2c66affSColin Finck break; 1734c2c66affSColin Finck 1735c2c66affSColin Finck nblimbs--; 1736c2c66affSColin Finck 1737c2c66affSColin Finck bufsize = sizeof( mbedtls_mpi_uint ) << 3; 1738c2c66affSColin Finck } 1739c2c66affSColin Finck 1740c2c66affSColin Finck bufsize--; 1741c2c66affSColin Finck 1742c2c66affSColin Finck ei = (E->p[nblimbs] >> bufsize) & 1; 1743c2c66affSColin Finck 1744c2c66affSColin Finck /* 1745c2c66affSColin Finck * skip leading 0s 1746c2c66affSColin Finck */ 1747c2c66affSColin Finck if( ei == 0 && state == 0 ) 1748c2c66affSColin Finck continue; 1749c2c66affSColin Finck 1750c2c66affSColin Finck if( ei == 0 && state == 1 ) 1751c2c66affSColin Finck { 1752c2c66affSColin Finck /* 1753c2c66affSColin Finck * out of window, square X 1754c2c66affSColin Finck */ 1755c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); 1756c2c66affSColin Finck continue; 1757c2c66affSColin Finck } 1758c2c66affSColin Finck 1759c2c66affSColin Finck /* 1760c2c66affSColin Finck * add ei to current window 1761c2c66affSColin Finck */ 1762c2c66affSColin Finck state = 2; 1763c2c66affSColin Finck 1764c2c66affSColin Finck nbits++; 1765c2c66affSColin Finck wbits |= ( ei << ( wsize - nbits ) ); 1766c2c66affSColin Finck 1767c2c66affSColin Finck if( nbits == wsize ) 1768c2c66affSColin Finck { 1769c2c66affSColin Finck /* 1770c2c66affSColin Finck * X = X^wsize R^-1 mod N 1771c2c66affSColin Finck */ 1772c2c66affSColin Finck for( i = 0; i < wsize; i++ ) 1773c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); 1774c2c66affSColin Finck 1775c2c66affSColin Finck /* 1776c2c66affSColin Finck * X = X * W[wbits] R^-1 mod N 1777c2c66affSColin Finck */ 1778c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); 1779c2c66affSColin Finck 1780c2c66affSColin Finck state--; 1781c2c66affSColin Finck nbits = 0; 1782c2c66affSColin Finck wbits = 0; 1783c2c66affSColin Finck } 1784c2c66affSColin Finck } 1785c2c66affSColin Finck 1786c2c66affSColin Finck /* 1787c2c66affSColin Finck * process the remaining bits 1788c2c66affSColin Finck */ 1789c2c66affSColin Finck for( i = 0; i < nbits; i++ ) 1790c2c66affSColin Finck { 1791c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); 1792c2c66affSColin Finck 1793c2c66affSColin Finck wbits <<= 1; 1794c2c66affSColin Finck 1795c2c66affSColin Finck if( ( wbits & ( one << wsize ) ) != 0 ) 1796c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); 1797c2c66affSColin Finck } 1798c2c66affSColin Finck 1799c2c66affSColin Finck /* 1800c2c66affSColin Finck * X = A^E * R * R^-1 mod N = A^E mod N 1801c2c66affSColin Finck */ 1802c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); 1803c2c66affSColin Finck 1804c2c66affSColin Finck if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) 1805c2c66affSColin Finck { 1806c2c66affSColin Finck X->s = -1; 1807c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); 1808c2c66affSColin Finck } 1809c2c66affSColin Finck 1810c2c66affSColin Finck cleanup: 1811c2c66affSColin Finck 1812c2c66affSColin Finck for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) 1813c2c66affSColin Finck mbedtls_mpi_free( &W[i] ); 1814c2c66affSColin Finck 1815c2c66affSColin Finck mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); 1816c2c66affSColin Finck 1817c2c66affSColin Finck if( _RR == NULL || _RR->p == NULL ) 1818c2c66affSColin Finck mbedtls_mpi_free( &RR ); 1819c2c66affSColin Finck 1820c2c66affSColin Finck return( ret ); 1821c2c66affSColin Finck } 1822c2c66affSColin Finck 1823c2c66affSColin Finck /* 1824c2c66affSColin Finck * Greatest common divisor: G = gcd(A, B) (HAC 14.54) 1825c2c66affSColin Finck */ 1826c2c66affSColin Finck int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1827c2c66affSColin Finck { 1828c2c66affSColin Finck int ret; 1829c2c66affSColin Finck size_t lz, lzt; 1830c2c66affSColin Finck mbedtls_mpi TG, TA, TB; 1831c2c66affSColin Finck 1832c2c66affSColin Finck mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); 1833c2c66affSColin Finck 1834c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); 1835c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); 1836c2c66affSColin Finck 1837c2c66affSColin Finck lz = mbedtls_mpi_lsb( &TA ); 1838c2c66affSColin Finck lzt = mbedtls_mpi_lsb( &TB ); 1839c2c66affSColin Finck 1840c2c66affSColin Finck if( lzt < lz ) 1841c2c66affSColin Finck lz = lzt; 1842c2c66affSColin Finck 1843c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); 1844c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); 1845c2c66affSColin Finck 1846c2c66affSColin Finck TA.s = TB.s = 1; 1847c2c66affSColin Finck 1848c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) 1849c2c66affSColin Finck { 1850c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); 1851c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); 1852c2c66affSColin Finck 1853c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) 1854c2c66affSColin Finck { 1855c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); 1856c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); 1857c2c66affSColin Finck } 1858c2c66affSColin Finck else 1859c2c66affSColin Finck { 1860c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); 1861c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); 1862c2c66affSColin Finck } 1863c2c66affSColin Finck } 1864c2c66affSColin Finck 1865c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); 1866c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); 1867c2c66affSColin Finck 1868c2c66affSColin Finck cleanup: 1869c2c66affSColin Finck 1870c2c66affSColin Finck mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); 1871c2c66affSColin Finck 1872c2c66affSColin Finck return( ret ); 1873c2c66affSColin Finck } 1874c2c66affSColin Finck 1875c2c66affSColin Finck /* 1876c2c66affSColin Finck * Fill X with size bytes of random. 1877c2c66affSColin Finck * 1878c2c66affSColin Finck * Use a temporary bytes representation to make sure the result is the same 1879c2c66affSColin Finck * regardless of the platform endianness (useful when f_rng is actually 1880c2c66affSColin Finck * deterministic, eg for tests). 1881c2c66affSColin Finck */ 1882c2c66affSColin Finck int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, 1883c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 1884c2c66affSColin Finck void *p_rng ) 1885c2c66affSColin Finck { 1886c2c66affSColin Finck int ret; 1887c2c66affSColin Finck unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 1888c2c66affSColin Finck 1889c2c66affSColin Finck if( size > MBEDTLS_MPI_MAX_SIZE ) 1890c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 1891c2c66affSColin Finck 1892c2c66affSColin Finck MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); 1893c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); 1894c2c66affSColin Finck 1895c2c66affSColin Finck cleanup: 1896*d9e6c9b5SThomas Faber mbedtls_zeroize( buf, sizeof( buf ) ); 1897c2c66affSColin Finck return( ret ); 1898c2c66affSColin Finck } 1899c2c66affSColin Finck 1900c2c66affSColin Finck /* 1901c2c66affSColin Finck * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) 1902c2c66affSColin Finck */ 1903c2c66affSColin Finck int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) 1904c2c66affSColin Finck { 1905c2c66affSColin Finck int ret; 1906c2c66affSColin Finck mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; 1907c2c66affSColin Finck 1908c2c66affSColin Finck if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) 1909c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 1910c2c66affSColin Finck 1911c2c66affSColin Finck mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); 1912c2c66affSColin Finck mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); 1913c2c66affSColin Finck mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); 1914c2c66affSColin Finck 1915c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); 1916c2c66affSColin Finck 1917c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) 1918c2c66affSColin Finck { 1919c2c66affSColin Finck ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 1920c2c66affSColin Finck goto cleanup; 1921c2c66affSColin Finck } 1922c2c66affSColin Finck 1923c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); 1924c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); 1925c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); 1926c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); 1927c2c66affSColin Finck 1928c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); 1929c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); 1930c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); 1931c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); 1932c2c66affSColin Finck 1933c2c66affSColin Finck do 1934c2c66affSColin Finck { 1935c2c66affSColin Finck while( ( TU.p[0] & 1 ) == 0 ) 1936c2c66affSColin Finck { 1937c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); 1938c2c66affSColin Finck 1939c2c66affSColin Finck if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) 1940c2c66affSColin Finck { 1941c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); 1942c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); 1943c2c66affSColin Finck } 1944c2c66affSColin Finck 1945c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); 1946c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); 1947c2c66affSColin Finck } 1948c2c66affSColin Finck 1949c2c66affSColin Finck while( ( TV.p[0] & 1 ) == 0 ) 1950c2c66affSColin Finck { 1951c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); 1952c2c66affSColin Finck 1953c2c66affSColin Finck if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) 1954c2c66affSColin Finck { 1955c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); 1956c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); 1957c2c66affSColin Finck } 1958c2c66affSColin Finck 1959c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); 1960c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); 1961c2c66affSColin Finck } 1962c2c66affSColin Finck 1963c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) 1964c2c66affSColin Finck { 1965c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); 1966c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); 1967c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); 1968c2c66affSColin Finck } 1969c2c66affSColin Finck else 1970c2c66affSColin Finck { 1971c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); 1972c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); 1973c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); 1974c2c66affSColin Finck } 1975c2c66affSColin Finck } 1976c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); 1977c2c66affSColin Finck 1978c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) 1979c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); 1980c2c66affSColin Finck 1981c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) 1982c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); 1983c2c66affSColin Finck 1984c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); 1985c2c66affSColin Finck 1986c2c66affSColin Finck cleanup: 1987c2c66affSColin Finck 1988c2c66affSColin Finck mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); 1989c2c66affSColin Finck mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); 1990c2c66affSColin Finck mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); 1991c2c66affSColin Finck 1992c2c66affSColin Finck return( ret ); 1993c2c66affSColin Finck } 1994c2c66affSColin Finck 1995c2c66affSColin Finck #if defined(MBEDTLS_GENPRIME) 1996c2c66affSColin Finck 1997c2c66affSColin Finck static const int small_prime[] = 1998c2c66affSColin Finck { 1999c2c66affSColin Finck 3, 5, 7, 11, 13, 17, 19, 23, 2000c2c66affSColin Finck 29, 31, 37, 41, 43, 47, 53, 59, 2001c2c66affSColin Finck 61, 67, 71, 73, 79, 83, 89, 97, 2002c2c66affSColin Finck 101, 103, 107, 109, 113, 127, 131, 137, 2003c2c66affSColin Finck 139, 149, 151, 157, 163, 167, 173, 179, 2004c2c66affSColin Finck 181, 191, 193, 197, 199, 211, 223, 227, 2005c2c66affSColin Finck 229, 233, 239, 241, 251, 257, 263, 269, 2006c2c66affSColin Finck 271, 277, 281, 283, 293, 307, 311, 313, 2007c2c66affSColin Finck 317, 331, 337, 347, 349, 353, 359, 367, 2008c2c66affSColin Finck 373, 379, 383, 389, 397, 401, 409, 419, 2009c2c66affSColin Finck 421, 431, 433, 439, 443, 449, 457, 461, 2010c2c66affSColin Finck 463, 467, 479, 487, 491, 499, 503, 509, 2011c2c66affSColin Finck 521, 523, 541, 547, 557, 563, 569, 571, 2012c2c66affSColin Finck 577, 587, 593, 599, 601, 607, 613, 617, 2013c2c66affSColin Finck 619, 631, 641, 643, 647, 653, 659, 661, 2014c2c66affSColin Finck 673, 677, 683, 691, 701, 709, 719, 727, 2015c2c66affSColin Finck 733, 739, 743, 751, 757, 761, 769, 773, 2016c2c66affSColin Finck 787, 797, 809, 811, 821, 823, 827, 829, 2017c2c66affSColin Finck 839, 853, 857, 859, 863, 877, 881, 883, 2018c2c66affSColin Finck 887, 907, 911, 919, 929, 937, 941, 947, 2019c2c66affSColin Finck 953, 967, 971, 977, 983, 991, 997, -103 2020c2c66affSColin Finck }; 2021c2c66affSColin Finck 2022c2c66affSColin Finck /* 2023c2c66affSColin Finck * Small divisors test (X must be positive) 2024c2c66affSColin Finck * 2025c2c66affSColin Finck * Return values: 2026c2c66affSColin Finck * 0: no small factor (possible prime, more tests needed) 2027c2c66affSColin Finck * 1: certain prime 2028c2c66affSColin Finck * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime 2029c2c66affSColin Finck * other negative: error 2030c2c66affSColin Finck */ 2031c2c66affSColin Finck static int mpi_check_small_factors( const mbedtls_mpi *X ) 2032c2c66affSColin Finck { 2033c2c66affSColin Finck int ret = 0; 2034c2c66affSColin Finck size_t i; 2035c2c66affSColin Finck mbedtls_mpi_uint r; 2036c2c66affSColin Finck 2037c2c66affSColin Finck if( ( X->p[0] & 1 ) == 0 ) 2038c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2039c2c66affSColin Finck 2040c2c66affSColin Finck for( i = 0; small_prime[i] > 0; i++ ) 2041c2c66affSColin Finck { 2042c2c66affSColin Finck if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) 2043c2c66affSColin Finck return( 1 ); 2044c2c66affSColin Finck 2045c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); 2046c2c66affSColin Finck 2047c2c66affSColin Finck if( r == 0 ) 2048c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2049c2c66affSColin Finck } 2050c2c66affSColin Finck 2051c2c66affSColin Finck cleanup: 2052c2c66affSColin Finck return( ret ); 2053c2c66affSColin Finck } 2054c2c66affSColin Finck 2055c2c66affSColin Finck /* 2056c2c66affSColin Finck * Miller-Rabin pseudo-primality test (HAC 4.24) 2057c2c66affSColin Finck */ 2058c2c66affSColin Finck static int mpi_miller_rabin( const mbedtls_mpi *X, 2059c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2060c2c66affSColin Finck void *p_rng ) 2061c2c66affSColin Finck { 2062c2c66affSColin Finck int ret, count; 2063c2c66affSColin Finck size_t i, j, k, n, s; 2064c2c66affSColin Finck mbedtls_mpi W, R, T, A, RR; 2065c2c66affSColin Finck 2066c2c66affSColin Finck mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); 2067c2c66affSColin Finck mbedtls_mpi_init( &RR ); 2068c2c66affSColin Finck 2069c2c66affSColin Finck /* 2070c2c66affSColin Finck * W = |X| - 1 2071c2c66affSColin Finck * R = W >> lsb( W ) 2072c2c66affSColin Finck */ 2073c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); 2074c2c66affSColin Finck s = mbedtls_mpi_lsb( &W ); 2075c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); 2076c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); 2077c2c66affSColin Finck 2078c2c66affSColin Finck i = mbedtls_mpi_bitlen( X ); 2079c2c66affSColin Finck /* 2080c2c66affSColin Finck * HAC, table 4.4 2081c2c66affSColin Finck */ 2082c2c66affSColin Finck n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : 2083c2c66affSColin Finck ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : 2084c2c66affSColin Finck ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); 2085c2c66affSColin Finck 2086c2c66affSColin Finck for( i = 0; i < n; i++ ) 2087c2c66affSColin Finck { 2088c2c66affSColin Finck /* 2089c2c66affSColin Finck * pick a random A, 1 < A < |X| - 1 2090c2c66affSColin Finck */ 2091c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); 2092c2c66affSColin Finck 2093c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) 2094c2c66affSColin Finck { 2095c2c66affSColin Finck j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); 2096c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); 2097c2c66affSColin Finck } 2098c2c66affSColin Finck A.p[0] |= 3; 2099c2c66affSColin Finck 2100c2c66affSColin Finck count = 0; 2101c2c66affSColin Finck do { 2102c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); 2103c2c66affSColin Finck 2104c2c66affSColin Finck j = mbedtls_mpi_bitlen( &A ); 2105c2c66affSColin Finck k = mbedtls_mpi_bitlen( &W ); 2106c2c66affSColin Finck if (j > k) { 2107c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); 2108c2c66affSColin Finck } 2109c2c66affSColin Finck 2110c2c66affSColin Finck if (count++ > 30) { 2111c2c66affSColin Finck return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2112c2c66affSColin Finck } 2113c2c66affSColin Finck 2114c2c66affSColin Finck } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || 2115c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); 2116c2c66affSColin Finck 2117c2c66affSColin Finck /* 2118c2c66affSColin Finck * A = A^R mod |X| 2119c2c66affSColin Finck */ 2120c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); 2121c2c66affSColin Finck 2122c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || 2123c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2124c2c66affSColin Finck continue; 2125c2c66affSColin Finck 2126c2c66affSColin Finck j = 1; 2127c2c66affSColin Finck while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) 2128c2c66affSColin Finck { 2129c2c66affSColin Finck /* 2130c2c66affSColin Finck * A = A * A mod |X| 2131c2c66affSColin Finck */ 2132c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); 2133c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); 2134c2c66affSColin Finck 2135c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2136c2c66affSColin Finck break; 2137c2c66affSColin Finck 2138c2c66affSColin Finck j++; 2139c2c66affSColin Finck } 2140c2c66affSColin Finck 2141c2c66affSColin Finck /* 2142c2c66affSColin Finck * not prime if A != |X| - 1 or A == 1 2143c2c66affSColin Finck */ 2144c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || 2145c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2146c2c66affSColin Finck { 2147c2c66affSColin Finck ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2148c2c66affSColin Finck break; 2149c2c66affSColin Finck } 2150c2c66affSColin Finck } 2151c2c66affSColin Finck 2152c2c66affSColin Finck cleanup: 2153c2c66affSColin Finck mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); 2154c2c66affSColin Finck mbedtls_mpi_free( &RR ); 2155c2c66affSColin Finck 2156c2c66affSColin Finck return( ret ); 2157c2c66affSColin Finck } 2158c2c66affSColin Finck 2159c2c66affSColin Finck /* 2160c2c66affSColin Finck * Pseudo-primality test: small factors, then Miller-Rabin 2161c2c66affSColin Finck */ 2162c2c66affSColin Finck int mbedtls_mpi_is_prime( const mbedtls_mpi *X, 2163c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2164c2c66affSColin Finck void *p_rng ) 2165c2c66affSColin Finck { 2166c2c66affSColin Finck int ret; 2167c2c66affSColin Finck mbedtls_mpi XX; 2168c2c66affSColin Finck 2169c2c66affSColin Finck XX.s = 1; 2170c2c66affSColin Finck XX.n = X->n; 2171c2c66affSColin Finck XX.p = X->p; 2172c2c66affSColin Finck 2173c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || 2174c2c66affSColin Finck mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) 2175c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2176c2c66affSColin Finck 2177c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) 2178c2c66affSColin Finck return( 0 ); 2179c2c66affSColin Finck 2180c2c66affSColin Finck if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) 2181c2c66affSColin Finck { 2182c2c66affSColin Finck if( ret == 1 ) 2183c2c66affSColin Finck return( 0 ); 2184c2c66affSColin Finck 2185c2c66affSColin Finck return( ret ); 2186c2c66affSColin Finck } 2187c2c66affSColin Finck 2188c2c66affSColin Finck return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); 2189c2c66affSColin Finck } 2190c2c66affSColin Finck 2191c2c66affSColin Finck /* 2192c2c66affSColin Finck * Prime number generation 2193c2c66affSColin Finck */ 2194c2c66affSColin Finck int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, 2195c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2196c2c66affSColin Finck void *p_rng ) 2197c2c66affSColin Finck { 2198c2c66affSColin Finck int ret; 2199c2c66affSColin Finck size_t k, n; 2200c2c66affSColin Finck mbedtls_mpi_uint r; 2201c2c66affSColin Finck mbedtls_mpi Y; 2202c2c66affSColin Finck 2203c2c66affSColin Finck if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) 2204c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 2205c2c66affSColin Finck 2206c2c66affSColin Finck mbedtls_mpi_init( &Y ); 2207c2c66affSColin Finck 2208c2c66affSColin Finck n = BITS_TO_LIMBS( nbits ); 2209c2c66affSColin Finck 2210c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); 2211c2c66affSColin Finck 2212c2c66affSColin Finck k = mbedtls_mpi_bitlen( X ); 2213c2c66affSColin Finck if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); 2214c2c66affSColin Finck 2215c2c66affSColin Finck mbedtls_mpi_set_bit( X, nbits-1, 1 ); 2216c2c66affSColin Finck 2217c2c66affSColin Finck X->p[0] |= 1; 2218c2c66affSColin Finck 2219c2c66affSColin Finck if( dh_flag == 0 ) 2220c2c66affSColin Finck { 2221c2c66affSColin Finck while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) 2222c2c66affSColin Finck { 2223c2c66affSColin Finck if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) 2224c2c66affSColin Finck goto cleanup; 2225c2c66affSColin Finck 2226c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); 2227c2c66affSColin Finck } 2228c2c66affSColin Finck } 2229c2c66affSColin Finck else 2230c2c66affSColin Finck { 2231c2c66affSColin Finck /* 2232c2c66affSColin Finck * An necessary condition for Y and X = 2Y + 1 to be prime 2233c2c66affSColin Finck * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). 2234c2c66affSColin Finck * Make sure it is satisfied, while keeping X = 3 mod 4 2235c2c66affSColin Finck */ 2236c2c66affSColin Finck 2237c2c66affSColin Finck X->p[0] |= 2; 2238c2c66affSColin Finck 2239c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); 2240c2c66affSColin Finck if( r == 0 ) 2241c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); 2242c2c66affSColin Finck else if( r == 1 ) 2243c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); 2244c2c66affSColin Finck 2245c2c66affSColin Finck /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ 2246c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); 2247c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); 2248c2c66affSColin Finck 2249c2c66affSColin Finck while( 1 ) 2250c2c66affSColin Finck { 2251c2c66affSColin Finck /* 2252c2c66affSColin Finck * First, check small factors for X and Y 2253c2c66affSColin Finck * before doing Miller-Rabin on any of them 2254c2c66affSColin Finck */ 2255c2c66affSColin Finck if( ( ret = mpi_check_small_factors( X ) ) == 0 && 2256c2c66affSColin Finck ( ret = mpi_check_small_factors( &Y ) ) == 0 && 2257c2c66affSColin Finck ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && 2258c2c66affSColin Finck ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) 2259c2c66affSColin Finck { 2260c2c66affSColin Finck break; 2261c2c66affSColin Finck } 2262c2c66affSColin Finck 2263c2c66affSColin Finck if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) 2264c2c66affSColin Finck goto cleanup; 2265c2c66affSColin Finck 2266c2c66affSColin Finck /* 2267c2c66affSColin Finck * Next candidates. We want to preserve Y = (X-1) / 2 and 2268c2c66affSColin Finck * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) 2269c2c66affSColin Finck * so up Y by 6 and X by 12. 2270c2c66affSColin Finck */ 2271c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); 2272c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); 2273c2c66affSColin Finck } 2274c2c66affSColin Finck } 2275c2c66affSColin Finck 2276c2c66affSColin Finck cleanup: 2277c2c66affSColin Finck 2278c2c66affSColin Finck mbedtls_mpi_free( &Y ); 2279c2c66affSColin Finck 2280c2c66affSColin Finck return( ret ); 2281c2c66affSColin Finck } 2282c2c66affSColin Finck 2283c2c66affSColin Finck #endif /* MBEDTLS_GENPRIME */ 2284c2c66affSColin Finck 2285c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST) 2286c2c66affSColin Finck 2287c2c66affSColin Finck #define GCD_PAIR_COUNT 3 2288c2c66affSColin Finck 2289c2c66affSColin Finck static const int gcd_pairs[GCD_PAIR_COUNT][3] = 2290c2c66affSColin Finck { 2291c2c66affSColin Finck { 693, 609, 21 }, 2292c2c66affSColin Finck { 1764, 868, 28 }, 2293c2c66affSColin Finck { 768454923, 542167814, 1 } 2294c2c66affSColin Finck }; 2295c2c66affSColin Finck 2296c2c66affSColin Finck /* 2297c2c66affSColin Finck * Checkup routine 2298c2c66affSColin Finck */ 2299c2c66affSColin Finck int mbedtls_mpi_self_test( int verbose ) 2300c2c66affSColin Finck { 2301c2c66affSColin Finck int ret, i; 2302c2c66affSColin Finck mbedtls_mpi A, E, N, X, Y, U, V; 2303c2c66affSColin Finck 2304c2c66affSColin Finck mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); 2305c2c66affSColin Finck mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); 2306c2c66affSColin Finck 2307c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, 2308c2c66affSColin Finck "EFE021C2645FD1DC586E69184AF4A31E" \ 2309c2c66affSColin Finck "D5F53E93B5F123FA41680867BA110131" \ 2310c2c66affSColin Finck "944FE7952E2517337780CB0DB80E61AA" \ 2311c2c66affSColin Finck "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); 2312c2c66affSColin Finck 2313c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, 2314c2c66affSColin Finck "B2E7EFD37075B9F03FF989C7C5051C20" \ 2315c2c66affSColin Finck "34D2A323810251127E7BF8625A4F49A5" \ 2316c2c66affSColin Finck "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ 2317c2c66affSColin Finck "5B5C25763222FEFCCFC38B832366C29E" ) ); 2318c2c66affSColin Finck 2319c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, 2320c2c66affSColin Finck "0066A198186C18C10B2F5ED9B522752A" \ 2321c2c66affSColin Finck "9830B69916E535C8F047518A889A43A5" \ 2322c2c66affSColin Finck "94B6BED27A168D31D4A52F88925AA8F5" ) ); 2323c2c66affSColin Finck 2324c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); 2325c2c66affSColin Finck 2326c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2327c2c66affSColin Finck "602AB7ECA597A3D6B56FF9829A5E8B85" \ 2328c2c66affSColin Finck "9E857EA95A03512E2BAE7391688D264A" \ 2329c2c66affSColin Finck "A5663B0341DB9CCFD2C4C5F421FEC814" \ 2330c2c66affSColin Finck "8001B72E848A38CAE1C65F78E56ABDEF" \ 2331c2c66affSColin Finck "E12D3C039B8A02D6BE593F0BBBDA56F1" \ 2332c2c66affSColin Finck "ECF677152EF804370C1A305CAF3B5BF1" \ 2333c2c66affSColin Finck "30879B56C61DE584A0F53A2447A51E" ) ); 2334c2c66affSColin Finck 2335c2c66affSColin Finck if( verbose != 0 ) 2336c2c66affSColin Finck mbedtls_printf( " MPI test #1 (mul_mpi): " ); 2337c2c66affSColin Finck 2338c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2339c2c66affSColin Finck { 2340c2c66affSColin Finck if( verbose != 0 ) 2341c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2342c2c66affSColin Finck 2343c2c66affSColin Finck ret = 1; 2344c2c66affSColin Finck goto cleanup; 2345c2c66affSColin Finck } 2346c2c66affSColin Finck 2347c2c66affSColin Finck if( verbose != 0 ) 2348c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2349c2c66affSColin Finck 2350c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); 2351c2c66affSColin Finck 2352c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2353c2c66affSColin Finck "256567336059E52CAE22925474705F39A94" ) ); 2354c2c66affSColin Finck 2355c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, 2356c2c66affSColin Finck "6613F26162223DF488E9CD48CC132C7A" \ 2357c2c66affSColin Finck "0AC93C701B001B092E4E5B9F73BCD27B" \ 2358c2c66affSColin Finck "9EE50D0657C77F374E903CDFA4C642" ) ); 2359c2c66affSColin Finck 2360c2c66affSColin Finck if( verbose != 0 ) 2361c2c66affSColin Finck mbedtls_printf( " MPI test #2 (div_mpi): " ); 2362c2c66affSColin Finck 2363c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || 2364c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) 2365c2c66affSColin Finck { 2366c2c66affSColin Finck if( verbose != 0 ) 2367c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2368c2c66affSColin Finck 2369c2c66affSColin Finck ret = 1; 2370c2c66affSColin Finck goto cleanup; 2371c2c66affSColin Finck } 2372c2c66affSColin Finck 2373c2c66affSColin Finck if( verbose != 0 ) 2374c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2375c2c66affSColin Finck 2376c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); 2377c2c66affSColin Finck 2378c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2379c2c66affSColin Finck "36E139AEA55215609D2816998ED020BB" \ 2380c2c66affSColin Finck "BD96C37890F65171D948E9BC7CBAA4D9" \ 2381c2c66affSColin Finck "325D24D6A3C12710F10A09FA08AB87" ) ); 2382c2c66affSColin Finck 2383c2c66affSColin Finck if( verbose != 0 ) 2384c2c66affSColin Finck mbedtls_printf( " MPI test #3 (exp_mod): " ); 2385c2c66affSColin Finck 2386c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2387c2c66affSColin Finck { 2388c2c66affSColin Finck if( verbose != 0 ) 2389c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2390c2c66affSColin Finck 2391c2c66affSColin Finck ret = 1; 2392c2c66affSColin Finck goto cleanup; 2393c2c66affSColin Finck } 2394c2c66affSColin Finck 2395c2c66affSColin Finck if( verbose != 0 ) 2396c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2397c2c66affSColin Finck 2398c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); 2399c2c66affSColin Finck 2400c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2401c2c66affSColin Finck "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ 2402c2c66affSColin Finck "C3DBA76456363A10869622EAC2DD84EC" \ 2403c2c66affSColin Finck "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); 2404c2c66affSColin Finck 2405c2c66affSColin Finck if( verbose != 0 ) 2406c2c66affSColin Finck mbedtls_printf( " MPI test #4 (inv_mod): " ); 2407c2c66affSColin Finck 2408c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2409c2c66affSColin Finck { 2410c2c66affSColin Finck if( verbose != 0 ) 2411c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2412c2c66affSColin Finck 2413c2c66affSColin Finck ret = 1; 2414c2c66affSColin Finck goto cleanup; 2415c2c66affSColin Finck } 2416c2c66affSColin Finck 2417c2c66affSColin Finck if( verbose != 0 ) 2418c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2419c2c66affSColin Finck 2420c2c66affSColin Finck if( verbose != 0 ) 2421c2c66affSColin Finck mbedtls_printf( " MPI test #5 (simple gcd): " ); 2422c2c66affSColin Finck 2423c2c66affSColin Finck for( i = 0; i < GCD_PAIR_COUNT; i++ ) 2424c2c66affSColin Finck { 2425c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); 2426c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); 2427c2c66affSColin Finck 2428c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); 2429c2c66affSColin Finck 2430c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) 2431c2c66affSColin Finck { 2432c2c66affSColin Finck if( verbose != 0 ) 2433c2c66affSColin Finck mbedtls_printf( "failed at %d\n", i ); 2434c2c66affSColin Finck 2435c2c66affSColin Finck ret = 1; 2436c2c66affSColin Finck goto cleanup; 2437c2c66affSColin Finck } 2438c2c66affSColin Finck } 2439c2c66affSColin Finck 2440c2c66affSColin Finck if( verbose != 0 ) 2441c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2442c2c66affSColin Finck 2443c2c66affSColin Finck cleanup: 2444c2c66affSColin Finck 2445c2c66affSColin Finck if( ret != 0 && verbose != 0 ) 2446c2c66affSColin Finck mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); 2447c2c66affSColin Finck 2448c2c66affSColin Finck mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); 2449c2c66affSColin Finck mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); 2450c2c66affSColin Finck 2451c2c66affSColin Finck if( verbose != 0 ) 2452c2c66affSColin Finck mbedtls_printf( "\n" ); 2453c2c66affSColin Finck 2454c2c66affSColin Finck return( ret ); 2455c2c66affSColin Finck } 2456c2c66affSColin Finck 2457c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */ 2458c2c66affSColin Finck 2459c2c66affSColin Finck #endif /* MBEDTLS_BIGNUM_C */ 2460