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 68d9e6c9b5SThomas Faber /* Implementation that should never be optimized out by the compiler */ 69d9e6c9b5SThomas Faber static void mbedtls_zeroize( void *v, size_t n ) { 70d9e6c9b5SThomas Faber volatile unsigned char *p = v; while( n-- ) *p++ = 0; 71d9e6c9b5SThomas Faber } 72d9e6c9b5SThomas 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 3230ba5bc40SThomas Faber /* Get a specific byte, without range checks. */ 3240ba5bc40SThomas Faber #define GET_BYTE( X, i ) \ 3250ba5bc40SThomas Faber ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) 3260ba5bc40SThomas Faber 327c2c66affSColin Finck /* 328c2c66affSColin Finck * Set a bit to a specific value of 0 or 1 329c2c66affSColin Finck */ 330c2c66affSColin Finck int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) 331c2c66affSColin Finck { 332c2c66affSColin Finck int ret = 0; 333c2c66affSColin Finck size_t off = pos / biL; 334c2c66affSColin Finck size_t idx = pos % biL; 335c2c66affSColin Finck 336c2c66affSColin Finck if( val != 0 && val != 1 ) 337c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 338c2c66affSColin Finck 339c2c66affSColin Finck if( X->n * biL <= pos ) 340c2c66affSColin Finck { 341c2c66affSColin Finck if( val == 0 ) 342c2c66affSColin Finck return( 0 ); 343c2c66affSColin Finck 344c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); 345c2c66affSColin Finck } 346c2c66affSColin Finck 347c2c66affSColin Finck X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); 348c2c66affSColin Finck X->p[off] |= (mbedtls_mpi_uint) val << idx; 349c2c66affSColin Finck 350c2c66affSColin Finck cleanup: 351c2c66affSColin Finck 352c2c66affSColin Finck return( ret ); 353c2c66affSColin Finck } 354c2c66affSColin Finck 355c2c66affSColin Finck /* 356c2c66affSColin Finck * Return the number of less significant zero-bits 357c2c66affSColin Finck */ 358c2c66affSColin Finck size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) 359c2c66affSColin Finck { 360c2c66affSColin Finck size_t i, j, count = 0; 361c2c66affSColin Finck 362c2c66affSColin Finck for( i = 0; i < X->n; i++ ) 363c2c66affSColin Finck for( j = 0; j < biL; j++, count++ ) 364c2c66affSColin Finck if( ( ( X->p[i] >> j ) & 1 ) != 0 ) 365c2c66affSColin Finck return( count ); 366c2c66affSColin Finck 367c2c66affSColin Finck return( 0 ); 368c2c66affSColin Finck } 369c2c66affSColin Finck 370c2c66affSColin Finck /* 371c2c66affSColin Finck * Count leading zero bits in a given integer 372c2c66affSColin Finck */ 373c2c66affSColin Finck static size_t mbedtls_clz( const mbedtls_mpi_uint x ) 374c2c66affSColin Finck { 375c2c66affSColin Finck size_t j; 376c2c66affSColin Finck mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); 377c2c66affSColin Finck 378c2c66affSColin Finck for( j = 0; j < biL; j++ ) 379c2c66affSColin Finck { 380c2c66affSColin Finck if( x & mask ) break; 381c2c66affSColin Finck 382c2c66affSColin Finck mask >>= 1; 383c2c66affSColin Finck } 384c2c66affSColin Finck 385c2c66affSColin Finck return j; 386c2c66affSColin Finck } 387c2c66affSColin Finck 388c2c66affSColin Finck /* 389c2c66affSColin Finck * Return the number of bits 390c2c66affSColin Finck */ 391c2c66affSColin Finck size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) 392c2c66affSColin Finck { 393c2c66affSColin Finck size_t i, j; 394c2c66affSColin Finck 395c2c66affSColin Finck if( X->n == 0 ) 396c2c66affSColin Finck return( 0 ); 397c2c66affSColin Finck 398c2c66affSColin Finck for( i = X->n - 1; i > 0; i-- ) 399c2c66affSColin Finck if( X->p[i] != 0 ) 400c2c66affSColin Finck break; 401c2c66affSColin Finck 402c2c66affSColin Finck j = biL - mbedtls_clz( X->p[i] ); 403c2c66affSColin Finck 404c2c66affSColin Finck return( ( i * biL ) + j ); 405c2c66affSColin Finck } 406c2c66affSColin Finck 407c2c66affSColin Finck /* 408c2c66affSColin Finck * Return the total size in bytes 409c2c66affSColin Finck */ 410c2c66affSColin Finck size_t mbedtls_mpi_size( const mbedtls_mpi *X ) 411c2c66affSColin Finck { 412c2c66affSColin Finck return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); 413c2c66affSColin Finck } 414c2c66affSColin Finck 415c2c66affSColin Finck /* 416c2c66affSColin Finck * Convert an ASCII character to digit value 417c2c66affSColin Finck */ 418c2c66affSColin Finck static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) 419c2c66affSColin Finck { 420c2c66affSColin Finck *d = 255; 421c2c66affSColin Finck 422c2c66affSColin Finck if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; 423c2c66affSColin Finck if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; 424c2c66affSColin Finck if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; 425c2c66affSColin Finck 426c2c66affSColin Finck if( *d >= (mbedtls_mpi_uint) radix ) 427c2c66affSColin Finck return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); 428c2c66affSColin Finck 429c2c66affSColin Finck return( 0 ); 430c2c66affSColin Finck } 431c2c66affSColin Finck 432c2c66affSColin Finck /* 433c2c66affSColin Finck * Import from an ASCII string 434c2c66affSColin Finck */ 435c2c66affSColin Finck int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) 436c2c66affSColin Finck { 437c2c66affSColin Finck int ret; 438c2c66affSColin Finck size_t i, j, slen, n; 439c2c66affSColin Finck mbedtls_mpi_uint d; 440c2c66affSColin Finck mbedtls_mpi T; 441c2c66affSColin Finck 442c2c66affSColin Finck if( radix < 2 || radix > 16 ) 443c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 444c2c66affSColin Finck 445c2c66affSColin Finck mbedtls_mpi_init( &T ); 446c2c66affSColin Finck 447c2c66affSColin Finck slen = strlen( s ); 448c2c66affSColin Finck 449c2c66affSColin Finck if( radix == 16 ) 450c2c66affSColin Finck { 451c2c66affSColin Finck if( slen > MPI_SIZE_T_MAX >> 2 ) 452c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 453c2c66affSColin Finck 454c2c66affSColin Finck n = BITS_TO_LIMBS( slen << 2 ); 455c2c66affSColin Finck 456c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); 457c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 458c2c66affSColin Finck 459c2c66affSColin Finck for( i = slen, j = 0; i > 0; i--, j++ ) 460c2c66affSColin Finck { 461c2c66affSColin Finck if( i == 1 && s[i - 1] == '-' ) 462c2c66affSColin Finck { 463c2c66affSColin Finck X->s = -1; 464c2c66affSColin Finck break; 465c2c66affSColin Finck } 466c2c66affSColin Finck 467c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); 468c2c66affSColin Finck X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); 469c2c66affSColin Finck } 470c2c66affSColin Finck } 471c2c66affSColin Finck else 472c2c66affSColin Finck { 473c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 474c2c66affSColin Finck 475c2c66affSColin Finck for( i = 0; i < slen; i++ ) 476c2c66affSColin Finck { 477c2c66affSColin Finck if( i == 0 && s[i] == '-' ) 478c2c66affSColin Finck { 479c2c66affSColin Finck X->s = -1; 480c2c66affSColin Finck continue; 481c2c66affSColin Finck } 482c2c66affSColin Finck 483c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); 484c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); 485c2c66affSColin Finck 486c2c66affSColin Finck if( X->s == 1 ) 487c2c66affSColin Finck { 488c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); 489c2c66affSColin Finck } 490c2c66affSColin Finck else 491c2c66affSColin Finck { 492c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); 493c2c66affSColin Finck } 494c2c66affSColin Finck } 495c2c66affSColin Finck } 496c2c66affSColin Finck 497c2c66affSColin Finck cleanup: 498c2c66affSColin Finck 499c2c66affSColin Finck mbedtls_mpi_free( &T ); 500c2c66affSColin Finck 501c2c66affSColin Finck return( ret ); 502c2c66affSColin Finck } 503c2c66affSColin Finck 504c2c66affSColin Finck /* 505ca86ee9cSThomas Faber * Helper to write the digits high-order first. 506c2c66affSColin Finck */ 507ca86ee9cSThomas Faber static int mpi_write_hlp( mbedtls_mpi *X, int radix, 508ca86ee9cSThomas Faber char **p, const size_t buflen ) 509c2c66affSColin Finck { 510c2c66affSColin Finck int ret; 511c2c66affSColin Finck mbedtls_mpi_uint r; 512ca86ee9cSThomas Faber size_t length = 0; 513ca86ee9cSThomas Faber char *p_end = *p + buflen; 514c2c66affSColin Finck 515ca86ee9cSThomas Faber do 516ca86ee9cSThomas Faber { 517ca86ee9cSThomas Faber if( length >= buflen ) 518ca86ee9cSThomas Faber { 519ca86ee9cSThomas Faber return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 520ca86ee9cSThomas Faber } 521c2c66affSColin Finck 522c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); 523c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); 524ca86ee9cSThomas Faber /* 525ca86ee9cSThomas Faber * Write the residue in the current position, as an ASCII character. 526ca86ee9cSThomas Faber */ 527ca86ee9cSThomas Faber if( r < 0xA ) 528ca86ee9cSThomas Faber *(--p_end) = (char)( '0' + r ); 529c2c66affSColin Finck else 530ca86ee9cSThomas Faber *(--p_end) = (char)( 'A' + ( r - 0xA ) ); 531ca86ee9cSThomas Faber 532ca86ee9cSThomas Faber length++; 533ca86ee9cSThomas Faber } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); 534ca86ee9cSThomas Faber 535ca86ee9cSThomas Faber memmove( *p, p_end, length ); 536ca86ee9cSThomas Faber *p += length; 537c2c66affSColin Finck 538c2c66affSColin Finck cleanup: 539c2c66affSColin Finck 540c2c66affSColin Finck return( ret ); 541c2c66affSColin Finck } 542c2c66affSColin Finck 543c2c66affSColin Finck /* 544c2c66affSColin Finck * Export into an ASCII string 545c2c66affSColin Finck */ 546c2c66affSColin Finck int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, 547c2c66affSColin Finck char *buf, size_t buflen, size_t *olen ) 548c2c66affSColin Finck { 549c2c66affSColin Finck int ret = 0; 550c2c66affSColin Finck size_t n; 551c2c66affSColin Finck char *p; 552c2c66affSColin Finck mbedtls_mpi T; 553c2c66affSColin Finck 554c2c66affSColin Finck if( radix < 2 || radix > 16 ) 555c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 556c2c66affSColin Finck 557430656f0SThomas Faber n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ 558430656f0SThomas Faber if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present 559430656f0SThomas Faber * `n`. If radix > 4, this might be a strict 560430656f0SThomas Faber * overapproximation of the number of 561430656f0SThomas Faber * radix-adic digits needed to present `n`. */ 562430656f0SThomas Faber if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to 563430656f0SThomas Faber * present `n`. */ 564430656f0SThomas Faber 565430656f0SThomas Faber n += 1; /* Terminating null byte */ 566430656f0SThomas Faber n += 1; /* Compensate for the divisions above, which round down `n` 567430656f0SThomas Faber * in case it's not even. */ 568430656f0SThomas Faber n += 1; /* Potential '-'-sign. */ 569430656f0SThomas Faber n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, 570430656f0SThomas Faber * which always uses an even number of hex-digits. */ 571c2c66affSColin Finck 572c2c66affSColin Finck if( buflen < n ) 573c2c66affSColin Finck { 574c2c66affSColin Finck *olen = n; 575c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 576c2c66affSColin Finck } 577c2c66affSColin Finck 578c2c66affSColin Finck p = buf; 579c2c66affSColin Finck mbedtls_mpi_init( &T ); 580c2c66affSColin Finck 581c2c66affSColin Finck if( X->s == -1 ) 582430656f0SThomas Faber { 583c2c66affSColin Finck *p++ = '-'; 584430656f0SThomas Faber buflen--; 585430656f0SThomas Faber } 586c2c66affSColin Finck 587c2c66affSColin Finck if( radix == 16 ) 588c2c66affSColin Finck { 589c2c66affSColin Finck int c; 590c2c66affSColin Finck size_t i, j, k; 591c2c66affSColin Finck 592c2c66affSColin Finck for( i = X->n, k = 0; i > 0; i-- ) 593c2c66affSColin Finck { 594c2c66affSColin Finck for( j = ciL; j > 0; j-- ) 595c2c66affSColin Finck { 596c2c66affSColin Finck c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; 597c2c66affSColin Finck 598c2c66affSColin Finck if( c == 0 && k == 0 && ( i + j ) != 2 ) 599c2c66affSColin Finck continue; 600c2c66affSColin Finck 601c2c66affSColin Finck *(p++) = "0123456789ABCDEF" [c / 16]; 602c2c66affSColin Finck *(p++) = "0123456789ABCDEF" [c % 16]; 603c2c66affSColin Finck k = 1; 604c2c66affSColin Finck } 605c2c66affSColin Finck } 606c2c66affSColin Finck } 607c2c66affSColin Finck else 608c2c66affSColin Finck { 609c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); 610c2c66affSColin Finck 611c2c66affSColin Finck if( T.s == -1 ) 612c2c66affSColin Finck T.s = 1; 613c2c66affSColin Finck 614ca86ee9cSThomas Faber MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); 615c2c66affSColin Finck } 616c2c66affSColin Finck 617c2c66affSColin Finck *p++ = '\0'; 618c2c66affSColin Finck *olen = p - buf; 619c2c66affSColin Finck 620c2c66affSColin Finck cleanup: 621c2c66affSColin Finck 622c2c66affSColin Finck mbedtls_mpi_free( &T ); 623c2c66affSColin Finck 624c2c66affSColin Finck return( ret ); 625c2c66affSColin Finck } 626c2c66affSColin Finck 627c2c66affSColin Finck #if defined(MBEDTLS_FS_IO) 628c2c66affSColin Finck /* 629c2c66affSColin Finck * Read X from an opened file 630c2c66affSColin Finck */ 631c2c66affSColin Finck int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) 632c2c66affSColin Finck { 633c2c66affSColin Finck mbedtls_mpi_uint d; 634c2c66affSColin Finck size_t slen; 635c2c66affSColin Finck char *p; 636c2c66affSColin Finck /* 637c2c66affSColin Finck * Buffer should have space for (short) label and decimal formatted MPI, 638c2c66affSColin Finck * newline characters and '\0' 639c2c66affSColin Finck */ 640c2c66affSColin Finck char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; 641c2c66affSColin Finck 642c2c66affSColin Finck memset( s, 0, sizeof( s ) ); 643c2c66affSColin Finck if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) 644c2c66affSColin Finck return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); 645c2c66affSColin Finck 646c2c66affSColin Finck slen = strlen( s ); 647c2c66affSColin Finck if( slen == sizeof( s ) - 2 ) 648c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 649c2c66affSColin Finck 650c2c66affSColin Finck if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } 651c2c66affSColin Finck if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } 652c2c66affSColin Finck 653c2c66affSColin Finck p = s + slen; 654c2c66affSColin Finck while( p-- > s ) 655c2c66affSColin Finck if( mpi_get_digit( &d, radix, *p ) != 0 ) 656c2c66affSColin Finck break; 657c2c66affSColin Finck 658c2c66affSColin Finck return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); 659c2c66affSColin Finck } 660c2c66affSColin Finck 661c2c66affSColin Finck /* 662c2c66affSColin Finck * Write X into an opened file (or stdout if fout == NULL) 663c2c66affSColin Finck */ 664c2c66affSColin Finck int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) 665c2c66affSColin Finck { 666c2c66affSColin Finck int ret; 667c2c66affSColin Finck size_t n, slen, plen; 668c2c66affSColin Finck /* 669c2c66affSColin Finck * Buffer should have space for (short) label and decimal formatted MPI, 670c2c66affSColin Finck * newline characters and '\0' 671c2c66affSColin Finck */ 672c2c66affSColin Finck char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; 673c2c66affSColin Finck 674c2c66affSColin Finck memset( s, 0, sizeof( s ) ); 675c2c66affSColin Finck 676c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); 677c2c66affSColin Finck 678c2c66affSColin Finck if( p == NULL ) p = ""; 679c2c66affSColin Finck 680c2c66affSColin Finck plen = strlen( p ); 681c2c66affSColin Finck slen = strlen( s ); 682c2c66affSColin Finck s[slen++] = '\r'; 683c2c66affSColin Finck s[slen++] = '\n'; 684c2c66affSColin Finck 685c2c66affSColin Finck if( fout != NULL ) 686c2c66affSColin Finck { 687c2c66affSColin Finck if( fwrite( p, 1, plen, fout ) != plen || 688c2c66affSColin Finck fwrite( s, 1, slen, fout ) != slen ) 689c2c66affSColin Finck return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); 690c2c66affSColin Finck } 691c2c66affSColin Finck else 692c2c66affSColin Finck mbedtls_printf( "%s%s", p, s ); 693c2c66affSColin Finck 694c2c66affSColin Finck cleanup: 695c2c66affSColin Finck 696c2c66affSColin Finck return( ret ); 697c2c66affSColin Finck } 698c2c66affSColin Finck #endif /* MBEDTLS_FS_IO */ 699c2c66affSColin Finck 700c2c66affSColin Finck /* 701c2c66affSColin Finck * Import X from unsigned binary data, big endian 702c2c66affSColin Finck */ 703c2c66affSColin Finck int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) 704c2c66affSColin Finck { 705c2c66affSColin Finck int ret; 706d9e6c9b5SThomas Faber size_t i, j; 707d9e6c9b5SThomas Faber size_t const limbs = CHARS_TO_LIMBS( buflen ); 708c2c66affSColin Finck 709d9e6c9b5SThomas Faber /* Ensure that target MPI has exactly the necessary number of limbs */ 710d9e6c9b5SThomas Faber if( X->n != limbs ) 711d9e6c9b5SThomas Faber { 712d9e6c9b5SThomas Faber mbedtls_mpi_free( X ); 713d9e6c9b5SThomas Faber mbedtls_mpi_init( X ); 714d9e6c9b5SThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); 715d9e6c9b5SThomas Faber } 716c2c66affSColin Finck 717c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 718c2c66affSColin Finck 719d9e6c9b5SThomas Faber for( i = buflen, j = 0; i > 0; i--, j++ ) 720c2c66affSColin Finck X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); 721c2c66affSColin Finck 722c2c66affSColin Finck cleanup: 723c2c66affSColin Finck 724c2c66affSColin Finck return( ret ); 725c2c66affSColin Finck } 726c2c66affSColin Finck 727c2c66affSColin Finck /* 728c2c66affSColin Finck * Export X into unsigned binary data, big endian 729c2c66affSColin Finck */ 7300ba5bc40SThomas Faber int mbedtls_mpi_write_binary( const mbedtls_mpi *X, 7310ba5bc40SThomas Faber unsigned char *buf, size_t buflen ) 732c2c66affSColin Finck { 7330ba5bc40SThomas Faber size_t stored_bytes = X->n * ciL; 7340ba5bc40SThomas Faber size_t bytes_to_copy; 7350ba5bc40SThomas Faber unsigned char *p; 7360ba5bc40SThomas Faber size_t i; 737c2c66affSColin Finck 7380ba5bc40SThomas Faber if( stored_bytes < buflen ) 7390ba5bc40SThomas Faber { 7400ba5bc40SThomas Faber /* There is enough space in the output buffer. Write initial 7410ba5bc40SThomas Faber * null bytes and record the position at which to start 7420ba5bc40SThomas Faber * writing the significant bytes. In this case, the execution 7430ba5bc40SThomas Faber * trace of this function does not depend on the value of the 7440ba5bc40SThomas Faber * number. */ 7450ba5bc40SThomas Faber bytes_to_copy = stored_bytes; 7460ba5bc40SThomas Faber p = buf + buflen - stored_bytes; 7470ba5bc40SThomas Faber memset( buf, 0, buflen - stored_bytes ); 7480ba5bc40SThomas Faber } 7490ba5bc40SThomas Faber else 7500ba5bc40SThomas Faber { 7510ba5bc40SThomas Faber /* The output buffer is smaller than the allocated size of X. 7520ba5bc40SThomas Faber * However X may fit if its leading bytes are zero. */ 7530ba5bc40SThomas Faber bytes_to_copy = buflen; 7540ba5bc40SThomas Faber p = buf; 7550ba5bc40SThomas Faber for( i = bytes_to_copy; i < stored_bytes; i++ ) 7560ba5bc40SThomas Faber { 7570ba5bc40SThomas Faber if( GET_BYTE( X, i ) != 0 ) 758c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 7590ba5bc40SThomas Faber } 7600ba5bc40SThomas Faber } 761c2c66affSColin Finck 7620ba5bc40SThomas Faber for( i = 0; i < bytes_to_copy; i++ ) 7630ba5bc40SThomas Faber p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); 764c2c66affSColin Finck 765c2c66affSColin Finck return( 0 ); 766c2c66affSColin Finck } 767c2c66affSColin Finck 768c2c66affSColin Finck /* 769c2c66affSColin Finck * Left-shift: X <<= count 770c2c66affSColin Finck */ 771c2c66affSColin Finck int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) 772c2c66affSColin Finck { 773c2c66affSColin Finck int ret; 774c2c66affSColin Finck size_t i, v0, t1; 775c2c66affSColin Finck mbedtls_mpi_uint r0 = 0, r1; 776c2c66affSColin Finck 777c2c66affSColin Finck v0 = count / (biL ); 778c2c66affSColin Finck t1 = count & (biL - 1); 779c2c66affSColin Finck 780c2c66affSColin Finck i = mbedtls_mpi_bitlen( X ) + count; 781c2c66affSColin Finck 782c2c66affSColin Finck if( X->n * biL < i ) 783c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); 784c2c66affSColin Finck 785c2c66affSColin Finck ret = 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 = X->n; i > v0; i-- ) 793c2c66affSColin Finck X->p[i - 1] = X->p[i - v0 - 1]; 794c2c66affSColin Finck 795c2c66affSColin Finck for( ; i > 0; i-- ) 796c2c66affSColin Finck X->p[i - 1] = 0; 797c2c66affSColin Finck } 798c2c66affSColin Finck 799c2c66affSColin Finck /* 800c2c66affSColin Finck * shift by count % limb_size 801c2c66affSColin Finck */ 802c2c66affSColin Finck if( t1 > 0 ) 803c2c66affSColin Finck { 804c2c66affSColin Finck for( i = v0; i < X->n; i++ ) 805c2c66affSColin Finck { 806c2c66affSColin Finck r1 = X->p[i] >> (biL - t1); 807c2c66affSColin Finck X->p[i] <<= t1; 808c2c66affSColin Finck X->p[i] |= r0; 809c2c66affSColin Finck r0 = r1; 810c2c66affSColin Finck } 811c2c66affSColin Finck } 812c2c66affSColin Finck 813c2c66affSColin Finck cleanup: 814c2c66affSColin Finck 815c2c66affSColin Finck return( ret ); 816c2c66affSColin Finck } 817c2c66affSColin Finck 818c2c66affSColin Finck /* 819c2c66affSColin Finck * Right-shift: X >>= count 820c2c66affSColin Finck */ 821c2c66affSColin Finck int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) 822c2c66affSColin Finck { 823c2c66affSColin Finck size_t i, v0, v1; 824c2c66affSColin Finck mbedtls_mpi_uint r0 = 0, r1; 825c2c66affSColin Finck 826c2c66affSColin Finck v0 = count / biL; 827c2c66affSColin Finck v1 = count & (biL - 1); 828c2c66affSColin Finck 829c2c66affSColin Finck if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) 830c2c66affSColin Finck return mbedtls_mpi_lset( X, 0 ); 831c2c66affSColin Finck 832c2c66affSColin Finck /* 833c2c66affSColin Finck * shift by count / limb_size 834c2c66affSColin Finck */ 835c2c66affSColin Finck if( v0 > 0 ) 836c2c66affSColin Finck { 837c2c66affSColin Finck for( i = 0; i < X->n - v0; i++ ) 838c2c66affSColin Finck X->p[i] = X->p[i + v0]; 839c2c66affSColin Finck 840c2c66affSColin Finck for( ; i < X->n; i++ ) 841c2c66affSColin Finck X->p[i] = 0; 842c2c66affSColin Finck } 843c2c66affSColin Finck 844c2c66affSColin Finck /* 845c2c66affSColin Finck * shift by count % limb_size 846c2c66affSColin Finck */ 847c2c66affSColin Finck if( v1 > 0 ) 848c2c66affSColin Finck { 849c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 850c2c66affSColin Finck { 851c2c66affSColin Finck r1 = X->p[i - 1] << (biL - v1); 852c2c66affSColin Finck X->p[i - 1] >>= v1; 853c2c66affSColin Finck X->p[i - 1] |= r0; 854c2c66affSColin Finck r0 = r1; 855c2c66affSColin Finck } 856c2c66affSColin Finck } 857c2c66affSColin Finck 858c2c66affSColin Finck return( 0 ); 859c2c66affSColin Finck } 860c2c66affSColin Finck 861c2c66affSColin Finck /* 862c2c66affSColin Finck * Compare unsigned values 863c2c66affSColin Finck */ 864c2c66affSColin Finck int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) 865c2c66affSColin Finck { 866c2c66affSColin Finck size_t i, j; 867c2c66affSColin Finck 868c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 869c2c66affSColin Finck if( X->p[i - 1] != 0 ) 870c2c66affSColin Finck break; 871c2c66affSColin Finck 872c2c66affSColin Finck for( j = Y->n; j > 0; j-- ) 873c2c66affSColin Finck if( Y->p[j - 1] != 0 ) 874c2c66affSColin Finck break; 875c2c66affSColin Finck 876c2c66affSColin Finck if( i == 0 && j == 0 ) 877c2c66affSColin Finck return( 0 ); 878c2c66affSColin Finck 879c2c66affSColin Finck if( i > j ) return( 1 ); 880c2c66affSColin Finck if( j > i ) return( -1 ); 881c2c66affSColin Finck 882c2c66affSColin Finck for( ; i > 0; i-- ) 883c2c66affSColin Finck { 884c2c66affSColin Finck if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); 885c2c66affSColin Finck if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); 886c2c66affSColin Finck } 887c2c66affSColin Finck 888c2c66affSColin Finck return( 0 ); 889c2c66affSColin Finck } 890c2c66affSColin Finck 891c2c66affSColin Finck /* 892c2c66affSColin Finck * Compare signed values 893c2c66affSColin Finck */ 894c2c66affSColin Finck int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) 895c2c66affSColin Finck { 896c2c66affSColin Finck size_t i, j; 897c2c66affSColin Finck 898c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 899c2c66affSColin Finck if( X->p[i - 1] != 0 ) 900c2c66affSColin Finck break; 901c2c66affSColin Finck 902c2c66affSColin Finck for( j = Y->n; j > 0; j-- ) 903c2c66affSColin Finck if( Y->p[j - 1] != 0 ) 904c2c66affSColin Finck break; 905c2c66affSColin Finck 906c2c66affSColin Finck if( i == 0 && j == 0 ) 907c2c66affSColin Finck return( 0 ); 908c2c66affSColin Finck 909c2c66affSColin Finck if( i > j ) return( X->s ); 910c2c66affSColin Finck if( j > i ) return( -Y->s ); 911c2c66affSColin Finck 912c2c66affSColin Finck if( X->s > 0 && Y->s < 0 ) return( 1 ); 913c2c66affSColin Finck if( Y->s > 0 && X->s < 0 ) return( -1 ); 914c2c66affSColin Finck 915c2c66affSColin Finck for( ; i > 0; i-- ) 916c2c66affSColin Finck { 917c2c66affSColin Finck if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); 918c2c66affSColin Finck if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); 919c2c66affSColin Finck } 920c2c66affSColin Finck 921c2c66affSColin Finck return( 0 ); 922c2c66affSColin Finck } 923c2c66affSColin Finck 924*d152519aSThomas Faber /** Decide if an integer is less than the other, without branches. 925*d152519aSThomas Faber * 926*d152519aSThomas Faber * \param x First integer. 927*d152519aSThomas Faber * \param y Second integer. 928*d152519aSThomas Faber * 929*d152519aSThomas Faber * \return 1 if \p x is less than \p y, 0 otherwise 930*d152519aSThomas Faber */ 931*d152519aSThomas Faber static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x, 932*d152519aSThomas Faber const mbedtls_mpi_uint y ) 933*d152519aSThomas Faber { 934*d152519aSThomas Faber mbedtls_mpi_uint ret; 935*d152519aSThomas Faber mbedtls_mpi_uint cond; 936*d152519aSThomas Faber 937*d152519aSThomas Faber /* 938*d152519aSThomas Faber * Check if the most significant bits (MSB) of the operands are different. 939*d152519aSThomas Faber */ 940*d152519aSThomas Faber cond = ( x ^ y ); 941*d152519aSThomas Faber /* 942*d152519aSThomas Faber * If the MSB are the same then the difference x-y will be negative (and 943*d152519aSThomas Faber * have its MSB set to 1 during conversion to unsigned) if and only if x<y. 944*d152519aSThomas Faber */ 945*d152519aSThomas Faber ret = ( x - y ) & ~cond; 946*d152519aSThomas Faber /* 947*d152519aSThomas Faber * If the MSB are different, then the operand with the MSB of 1 is the 948*d152519aSThomas Faber * bigger. (That is if y has MSB of 1, then x<y is true and it is false if 949*d152519aSThomas Faber * the MSB of y is 0.) 950*d152519aSThomas Faber */ 951*d152519aSThomas Faber ret |= y & cond; 952*d152519aSThomas Faber 953*d152519aSThomas Faber 954*d152519aSThomas Faber ret = ret >> ( biL - 1 ); 955*d152519aSThomas Faber 956*d152519aSThomas Faber return (unsigned) ret; 957*d152519aSThomas Faber } 958*d152519aSThomas Faber 959*d152519aSThomas Faber /* 960*d152519aSThomas Faber * Compare signed values in constant time 961*d152519aSThomas Faber */ 962*d152519aSThomas Faber int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, 963*d152519aSThomas Faber unsigned *ret ) 964*d152519aSThomas Faber { 965*d152519aSThomas Faber size_t i; 966*d152519aSThomas Faber /* The value of any of these variables is either 0 or 1 at all times. */ 967*d152519aSThomas Faber unsigned cond, done, X_is_negative, Y_is_negative; 968*d152519aSThomas Faber 969*d152519aSThomas Faber if( X->n != Y->n ) 970*d152519aSThomas Faber return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 971*d152519aSThomas Faber 972*d152519aSThomas Faber /* 973*d152519aSThomas Faber * Set sign_N to 1 if N >= 0, 0 if N < 0. 974*d152519aSThomas Faber * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. 975*d152519aSThomas Faber */ 976*d152519aSThomas Faber X_is_negative = ( X->s & 2 ) >> 1; 977*d152519aSThomas Faber Y_is_negative = ( Y->s & 2 ) >> 1; 978*d152519aSThomas Faber 979*d152519aSThomas Faber /* 980*d152519aSThomas Faber * If the signs are different, then the positive operand is the bigger. 981*d152519aSThomas Faber * That is if X is negative (X_is_negative == 1), then X < Y is true and it 982*d152519aSThomas Faber * is false if X is positive (X_is_negative == 0). 983*d152519aSThomas Faber */ 984*d152519aSThomas Faber cond = ( X_is_negative ^ Y_is_negative ); 985*d152519aSThomas Faber *ret = cond & X_is_negative; 986*d152519aSThomas Faber 987*d152519aSThomas Faber /* 988*d152519aSThomas Faber * This is a constant-time function. We might have the result, but we still 989*d152519aSThomas Faber * need to go through the loop. Record if we have the result already. 990*d152519aSThomas Faber */ 991*d152519aSThomas Faber done = cond; 992*d152519aSThomas Faber 993*d152519aSThomas Faber for( i = X->n; i > 0; i-- ) 994*d152519aSThomas Faber { 995*d152519aSThomas Faber /* 996*d152519aSThomas Faber * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both 997*d152519aSThomas Faber * X and Y are negative. 998*d152519aSThomas Faber * 999*d152519aSThomas Faber * Again even if we can make a decision, we just mark the result and 1000*d152519aSThomas Faber * the fact that we are done and continue looping. 1001*d152519aSThomas Faber */ 1002*d152519aSThomas Faber cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ); 1003*d152519aSThomas Faber *ret |= cond & ( 1 - done ) & X_is_negative; 1004*d152519aSThomas Faber done |= cond; 1005*d152519aSThomas Faber 1006*d152519aSThomas Faber /* 1007*d152519aSThomas Faber * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both 1008*d152519aSThomas Faber * X and Y are positive. 1009*d152519aSThomas Faber * 1010*d152519aSThomas Faber * Again even if we can make a decision, we just mark the result and 1011*d152519aSThomas Faber * the fact that we are done and continue looping. 1012*d152519aSThomas Faber */ 1013*d152519aSThomas Faber cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ); 1014*d152519aSThomas Faber *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); 1015*d152519aSThomas Faber done |= cond; 1016*d152519aSThomas Faber } 1017*d152519aSThomas Faber 1018*d152519aSThomas Faber return( 0 ); 1019*d152519aSThomas Faber } 1020*d152519aSThomas Faber 1021c2c66affSColin Finck /* 1022c2c66affSColin Finck * Compare signed values 1023c2c66affSColin Finck */ 1024c2c66affSColin Finck int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) 1025c2c66affSColin Finck { 1026c2c66affSColin Finck mbedtls_mpi Y; 1027c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1028c2c66affSColin Finck 1029c2c66affSColin Finck *p = ( z < 0 ) ? -z : z; 1030c2c66affSColin Finck Y.s = ( z < 0 ) ? -1 : 1; 1031c2c66affSColin Finck Y.n = 1; 1032c2c66affSColin Finck Y.p = p; 1033c2c66affSColin Finck 1034c2c66affSColin Finck return( mbedtls_mpi_cmp_mpi( X, &Y ) ); 1035c2c66affSColin Finck } 1036c2c66affSColin Finck 1037c2c66affSColin Finck /* 1038c2c66affSColin Finck * Unsigned addition: X = |A| + |B| (HAC 14.7) 1039c2c66affSColin Finck */ 1040c2c66affSColin Finck int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1041c2c66affSColin Finck { 1042c2c66affSColin Finck int ret; 1043c2c66affSColin Finck size_t i, j; 1044c2c66affSColin Finck mbedtls_mpi_uint *o, *p, c, tmp; 1045c2c66affSColin Finck 1046c2c66affSColin Finck if( X == B ) 1047c2c66affSColin Finck { 1048c2c66affSColin Finck const mbedtls_mpi *T = A; A = X; B = T; 1049c2c66affSColin Finck } 1050c2c66affSColin Finck 1051c2c66affSColin Finck if( X != A ) 1052c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); 1053c2c66affSColin Finck 1054c2c66affSColin Finck /* 1055c2c66affSColin Finck * X should always be positive as a result of unsigned additions. 1056c2c66affSColin Finck */ 1057c2c66affSColin Finck X->s = 1; 1058c2c66affSColin Finck 1059c2c66affSColin Finck for( j = B->n; j > 0; j-- ) 1060c2c66affSColin Finck if( B->p[j - 1] != 0 ) 1061c2c66affSColin Finck break; 1062c2c66affSColin Finck 1063c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); 1064c2c66affSColin Finck 1065c2c66affSColin Finck o = B->p; p = X->p; c = 0; 1066c2c66affSColin Finck 1067c2c66affSColin Finck /* 1068c2c66affSColin Finck * tmp is used because it might happen that p == o 1069c2c66affSColin Finck */ 1070c2c66affSColin Finck for( i = 0; i < j; i++, o++, p++ ) 1071c2c66affSColin Finck { 1072c2c66affSColin Finck tmp= *o; 1073c2c66affSColin Finck *p += c; c = ( *p < c ); 1074c2c66affSColin Finck *p += tmp; c += ( *p < tmp ); 1075c2c66affSColin Finck } 1076c2c66affSColin Finck 1077c2c66affSColin Finck while( c != 0 ) 1078c2c66affSColin Finck { 1079c2c66affSColin Finck if( i >= X->n ) 1080c2c66affSColin Finck { 1081c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); 1082c2c66affSColin Finck p = X->p + i; 1083c2c66affSColin Finck } 1084c2c66affSColin Finck 1085c2c66affSColin Finck *p += c; c = ( *p < c ); i++; p++; 1086c2c66affSColin Finck } 1087c2c66affSColin Finck 1088c2c66affSColin Finck cleanup: 1089c2c66affSColin Finck 1090c2c66affSColin Finck return( ret ); 1091c2c66affSColin Finck } 1092c2c66affSColin Finck 1093c2c66affSColin Finck /* 1094c2c66affSColin Finck * Helper for mbedtls_mpi subtraction 1095c2c66affSColin Finck */ 1096c2c66affSColin Finck static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) 1097c2c66affSColin Finck { 1098c2c66affSColin Finck size_t i; 1099c2c66affSColin Finck mbedtls_mpi_uint c, z; 1100c2c66affSColin Finck 1101c2c66affSColin Finck for( i = c = 0; i < n; i++, s++, d++ ) 1102c2c66affSColin Finck { 1103c2c66affSColin Finck z = ( *d < c ); *d -= c; 1104c2c66affSColin Finck c = ( *d < *s ) + z; *d -= *s; 1105c2c66affSColin Finck } 1106c2c66affSColin Finck 1107c2c66affSColin Finck while( c != 0 ) 1108c2c66affSColin Finck { 1109c2c66affSColin Finck z = ( *d < c ); *d -= c; 1110c2c66affSColin Finck c = z; i++; d++; 1111c2c66affSColin Finck } 1112c2c66affSColin Finck } 1113c2c66affSColin Finck 1114c2c66affSColin Finck /* 1115c2c66affSColin Finck * Unsigned subtraction: X = |A| - |B| (HAC 14.9) 1116c2c66affSColin Finck */ 1117c2c66affSColin Finck int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1118c2c66affSColin Finck { 1119c2c66affSColin Finck mbedtls_mpi TB; 1120c2c66affSColin Finck int ret; 1121c2c66affSColin Finck size_t n; 1122c2c66affSColin Finck 1123c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) 1124c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); 1125c2c66affSColin Finck 1126c2c66affSColin Finck mbedtls_mpi_init( &TB ); 1127c2c66affSColin Finck 1128c2c66affSColin Finck if( X == B ) 1129c2c66affSColin Finck { 1130c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); 1131c2c66affSColin Finck B = &TB; 1132c2c66affSColin Finck } 1133c2c66affSColin Finck 1134c2c66affSColin Finck if( X != A ) 1135c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); 1136c2c66affSColin Finck 1137c2c66affSColin Finck /* 1138c2c66affSColin Finck * X should always be positive as a result of unsigned subtractions. 1139c2c66affSColin Finck */ 1140c2c66affSColin Finck X->s = 1; 1141c2c66affSColin Finck 1142c2c66affSColin Finck ret = 0; 1143c2c66affSColin Finck 1144c2c66affSColin Finck for( n = B->n; n > 0; n-- ) 1145c2c66affSColin Finck if( B->p[n - 1] != 0 ) 1146c2c66affSColin Finck break; 1147c2c66affSColin Finck 1148c2c66affSColin Finck mpi_sub_hlp( n, B->p, X->p ); 1149c2c66affSColin Finck 1150c2c66affSColin Finck cleanup: 1151c2c66affSColin Finck 1152c2c66affSColin Finck mbedtls_mpi_free( &TB ); 1153c2c66affSColin Finck 1154c2c66affSColin Finck return( ret ); 1155c2c66affSColin Finck } 1156c2c66affSColin Finck 1157c2c66affSColin Finck /* 1158c2c66affSColin Finck * Signed addition: X = A + B 1159c2c66affSColin Finck */ 1160c2c66affSColin Finck int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1161c2c66affSColin Finck { 1162c2c66affSColin Finck int ret, s = A->s; 1163c2c66affSColin Finck 1164c2c66affSColin Finck if( A->s * B->s < 0 ) 1165c2c66affSColin Finck { 1166c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) 1167c2c66affSColin Finck { 1168c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); 1169c2c66affSColin Finck X->s = s; 1170c2c66affSColin Finck } 1171c2c66affSColin Finck else 1172c2c66affSColin Finck { 1173c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); 1174c2c66affSColin Finck X->s = -s; 1175c2c66affSColin Finck } 1176c2c66affSColin Finck } 1177c2c66affSColin Finck else 1178c2c66affSColin Finck { 1179c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); 1180c2c66affSColin Finck X->s = s; 1181c2c66affSColin Finck } 1182c2c66affSColin Finck 1183c2c66affSColin Finck cleanup: 1184c2c66affSColin Finck 1185c2c66affSColin Finck return( ret ); 1186c2c66affSColin Finck } 1187c2c66affSColin Finck 1188c2c66affSColin Finck /* 1189c2c66affSColin Finck * Signed subtraction: X = A - B 1190c2c66affSColin Finck */ 1191c2c66affSColin Finck int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1192c2c66affSColin Finck { 1193c2c66affSColin Finck int ret, s = A->s; 1194c2c66affSColin Finck 1195c2c66affSColin Finck if( A->s * B->s > 0 ) 1196c2c66affSColin Finck { 1197c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) 1198c2c66affSColin Finck { 1199c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); 1200c2c66affSColin Finck X->s = s; 1201c2c66affSColin Finck } 1202c2c66affSColin Finck else 1203c2c66affSColin Finck { 1204c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); 1205c2c66affSColin Finck X->s = -s; 1206c2c66affSColin Finck } 1207c2c66affSColin Finck } 1208c2c66affSColin Finck else 1209c2c66affSColin Finck { 1210c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); 1211c2c66affSColin Finck X->s = s; 1212c2c66affSColin Finck } 1213c2c66affSColin Finck 1214c2c66affSColin Finck cleanup: 1215c2c66affSColin Finck 1216c2c66affSColin Finck return( ret ); 1217c2c66affSColin Finck } 1218c2c66affSColin Finck 1219c2c66affSColin Finck /* 1220c2c66affSColin Finck * Signed addition: X = A + b 1221c2c66affSColin Finck */ 1222c2c66affSColin Finck int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1223c2c66affSColin Finck { 1224c2c66affSColin Finck mbedtls_mpi _B; 1225c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1226c2c66affSColin Finck 1227c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1228c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1229c2c66affSColin Finck _B.n = 1; 1230c2c66affSColin Finck _B.p = p; 1231c2c66affSColin Finck 1232c2c66affSColin Finck return( mbedtls_mpi_add_mpi( X, A, &_B ) ); 1233c2c66affSColin Finck } 1234c2c66affSColin Finck 1235c2c66affSColin Finck /* 1236c2c66affSColin Finck * Signed subtraction: X = A - b 1237c2c66affSColin Finck */ 1238c2c66affSColin Finck int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1239c2c66affSColin Finck { 1240c2c66affSColin Finck mbedtls_mpi _B; 1241c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1242c2c66affSColin Finck 1243c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1244c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1245c2c66affSColin Finck _B.n = 1; 1246c2c66affSColin Finck _B.p = p; 1247c2c66affSColin Finck 1248c2c66affSColin Finck return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); 1249c2c66affSColin Finck } 1250c2c66affSColin Finck 1251c2c66affSColin Finck /* 1252c2c66affSColin Finck * Helper for mbedtls_mpi multiplication 1253c2c66affSColin Finck */ 1254c2c66affSColin Finck static 1255c2c66affSColin Finck #if defined(__APPLE__) && defined(__arm__) 1256c2c66affSColin Finck /* 1257c2c66affSColin Finck * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) 1258c2c66affSColin Finck * appears to need this to prevent bad ARM code generation at -O3. 1259c2c66affSColin Finck */ 1260c2c66affSColin Finck __attribute__ ((noinline)) 1261c2c66affSColin Finck #endif 1262c2c66affSColin Finck void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) 1263c2c66affSColin Finck { 1264c2c66affSColin Finck mbedtls_mpi_uint c = 0, t = 0; 1265c2c66affSColin Finck 1266c2c66affSColin Finck #if defined(MULADDC_HUIT) 1267c2c66affSColin Finck for( ; i >= 8; i -= 8 ) 1268c2c66affSColin Finck { 1269c2c66affSColin Finck MULADDC_INIT 1270c2c66affSColin Finck MULADDC_HUIT 1271c2c66affSColin Finck MULADDC_STOP 1272c2c66affSColin Finck } 1273c2c66affSColin Finck 1274c2c66affSColin Finck for( ; i > 0; i-- ) 1275c2c66affSColin Finck { 1276c2c66affSColin Finck MULADDC_INIT 1277c2c66affSColin Finck MULADDC_CORE 1278c2c66affSColin Finck MULADDC_STOP 1279c2c66affSColin Finck } 1280c2c66affSColin Finck #else /* MULADDC_HUIT */ 1281c2c66affSColin Finck for( ; i >= 16; i -= 16 ) 1282c2c66affSColin Finck { 1283c2c66affSColin Finck MULADDC_INIT 1284c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1285c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1286c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1287c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1288c2c66affSColin Finck 1289c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1290c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1291c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1292c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1293c2c66affSColin Finck MULADDC_STOP 1294c2c66affSColin Finck } 1295c2c66affSColin Finck 1296c2c66affSColin Finck for( ; i >= 8; i -= 8 ) 1297c2c66affSColin Finck { 1298c2c66affSColin Finck MULADDC_INIT 1299c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1300c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1301c2c66affSColin Finck 1302c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1303c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1304c2c66affSColin Finck MULADDC_STOP 1305c2c66affSColin Finck } 1306c2c66affSColin Finck 1307c2c66affSColin Finck for( ; i > 0; i-- ) 1308c2c66affSColin Finck { 1309c2c66affSColin Finck MULADDC_INIT 1310c2c66affSColin Finck MULADDC_CORE 1311c2c66affSColin Finck MULADDC_STOP 1312c2c66affSColin Finck } 1313c2c66affSColin Finck #endif /* MULADDC_HUIT */ 1314c2c66affSColin Finck 1315c2c66affSColin Finck t++; 1316c2c66affSColin Finck 1317c2c66affSColin Finck do { 1318c2c66affSColin Finck *d += c; c = ( *d < c ); d++; 1319c2c66affSColin Finck } 1320c2c66affSColin Finck while( c != 0 ); 1321c2c66affSColin Finck } 1322c2c66affSColin Finck 1323c2c66affSColin Finck /* 1324c2c66affSColin Finck * Baseline multiplication: X = A * B (HAC 14.12) 1325c2c66affSColin Finck */ 1326c2c66affSColin Finck int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1327c2c66affSColin Finck { 1328c2c66affSColin Finck int ret; 1329c2c66affSColin Finck size_t i, j; 1330c2c66affSColin Finck mbedtls_mpi TA, TB; 1331c2c66affSColin Finck 1332c2c66affSColin Finck mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); 1333c2c66affSColin Finck 1334c2c66affSColin Finck if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } 1335c2c66affSColin Finck if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } 1336c2c66affSColin Finck 1337c2c66affSColin Finck for( i = A->n; i > 0; i-- ) 1338c2c66affSColin Finck if( A->p[i - 1] != 0 ) 1339c2c66affSColin Finck break; 1340c2c66affSColin Finck 1341c2c66affSColin Finck for( j = B->n; j > 0; j-- ) 1342c2c66affSColin Finck if( B->p[j - 1] != 0 ) 1343c2c66affSColin Finck break; 1344c2c66affSColin Finck 1345c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); 1346c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 1347c2c66affSColin Finck 1348c2c66affSColin Finck for( i++; j > 0; j-- ) 1349c2c66affSColin Finck mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); 1350c2c66affSColin Finck 1351c2c66affSColin Finck X->s = A->s * B->s; 1352c2c66affSColin Finck 1353c2c66affSColin Finck cleanup: 1354c2c66affSColin Finck 1355c2c66affSColin Finck mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); 1356c2c66affSColin Finck 1357c2c66affSColin Finck return( ret ); 1358c2c66affSColin Finck } 1359c2c66affSColin Finck 1360c2c66affSColin Finck /* 1361c2c66affSColin Finck * Baseline multiplication: X = A * b 1362c2c66affSColin Finck */ 1363c2c66affSColin Finck int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) 1364c2c66affSColin Finck { 1365c2c66affSColin Finck mbedtls_mpi _B; 1366c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1367c2c66affSColin Finck 1368c2c66affSColin Finck _B.s = 1; 1369c2c66affSColin Finck _B.n = 1; 1370c2c66affSColin Finck _B.p = p; 1371c2c66affSColin Finck p[0] = b; 1372c2c66affSColin Finck 1373c2c66affSColin Finck return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); 1374c2c66affSColin Finck } 1375c2c66affSColin Finck 1376c2c66affSColin Finck /* 1377c2c66affSColin Finck * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and 1378c2c66affSColin Finck * mbedtls_mpi_uint divisor, d 1379c2c66affSColin Finck */ 1380c2c66affSColin Finck static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, 1381c2c66affSColin Finck mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) 1382c2c66affSColin Finck { 1383c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL) 1384c2c66affSColin Finck mbedtls_t_udbl dividend, quotient; 1385c2c66affSColin Finck #else 1386c2c66affSColin Finck const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; 1387c2c66affSColin Finck const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; 1388c2c66affSColin Finck mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; 1389c2c66affSColin Finck mbedtls_mpi_uint u0_msw, u0_lsw; 1390c2c66affSColin Finck size_t s; 1391c2c66affSColin Finck #endif 1392c2c66affSColin Finck 1393c2c66affSColin Finck /* 1394c2c66affSColin Finck * Check for overflow 1395c2c66affSColin Finck */ 1396c2c66affSColin Finck if( 0 == d || u1 >= d ) 1397c2c66affSColin Finck { 1398c2c66affSColin Finck if (r != NULL) *r = ~0; 1399c2c66affSColin Finck 1400c2c66affSColin Finck return ( ~0 ); 1401c2c66affSColin Finck } 1402c2c66affSColin Finck 1403c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL) 1404c2c66affSColin Finck dividend = (mbedtls_t_udbl) u1 << biL; 1405c2c66affSColin Finck dividend |= (mbedtls_t_udbl) u0; 1406c2c66affSColin Finck quotient = dividend / d; 1407c2c66affSColin Finck if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) 1408c2c66affSColin Finck quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; 1409c2c66affSColin Finck 1410c2c66affSColin Finck if( r != NULL ) 1411c2c66affSColin Finck *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); 1412c2c66affSColin Finck 1413c2c66affSColin Finck return (mbedtls_mpi_uint) quotient; 1414c2c66affSColin Finck #else 1415c2c66affSColin Finck 1416c2c66affSColin Finck /* 1417c2c66affSColin Finck * Algorithm D, Section 4.3.1 - The Art of Computer Programming 1418c2c66affSColin Finck * Vol. 2 - Seminumerical Algorithms, Knuth 1419c2c66affSColin Finck */ 1420c2c66affSColin Finck 1421c2c66affSColin Finck /* 1422c2c66affSColin Finck * Normalize the divisor, d, and dividend, u0, u1 1423c2c66affSColin Finck */ 1424c2c66affSColin Finck s = mbedtls_clz( d ); 1425c2c66affSColin Finck d = d << s; 1426c2c66affSColin Finck 1427c2c66affSColin Finck u1 = u1 << s; 1428c2c66affSColin Finck u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); 1429c2c66affSColin Finck u0 = u0 << s; 1430c2c66affSColin Finck 1431c2c66affSColin Finck d1 = d >> biH; 1432c2c66affSColin Finck d0 = d & uint_halfword_mask; 1433c2c66affSColin Finck 1434c2c66affSColin Finck u0_msw = u0 >> biH; 1435c2c66affSColin Finck u0_lsw = u0 & uint_halfword_mask; 1436c2c66affSColin Finck 1437c2c66affSColin Finck /* 1438c2c66affSColin Finck * Find the first quotient and remainder 1439c2c66affSColin Finck */ 1440c2c66affSColin Finck q1 = u1 / d1; 1441c2c66affSColin Finck r0 = u1 - d1 * q1; 1442c2c66affSColin Finck 1443c2c66affSColin Finck while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) 1444c2c66affSColin Finck { 1445c2c66affSColin Finck q1 -= 1; 1446c2c66affSColin Finck r0 += d1; 1447c2c66affSColin Finck 1448c2c66affSColin Finck if ( r0 >= radix ) break; 1449c2c66affSColin Finck } 1450c2c66affSColin Finck 1451c2c66affSColin Finck rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); 1452c2c66affSColin Finck q0 = rAX / d1; 1453c2c66affSColin Finck r0 = rAX - q0 * d1; 1454c2c66affSColin Finck 1455c2c66affSColin Finck while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) 1456c2c66affSColin Finck { 1457c2c66affSColin Finck q0 -= 1; 1458c2c66affSColin Finck r0 += d1; 1459c2c66affSColin Finck 1460c2c66affSColin Finck if ( r0 >= radix ) break; 1461c2c66affSColin Finck } 1462c2c66affSColin Finck 1463c2c66affSColin Finck if (r != NULL) 1464c2c66affSColin Finck *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; 1465c2c66affSColin Finck 1466c2c66affSColin Finck quotient = q1 * radix + q0; 1467c2c66affSColin Finck 1468c2c66affSColin Finck return quotient; 1469c2c66affSColin Finck #endif 1470c2c66affSColin Finck } 1471c2c66affSColin Finck 1472c2c66affSColin Finck /* 1473c2c66affSColin Finck * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) 1474c2c66affSColin Finck */ 1475c2c66affSColin Finck int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1476c2c66affSColin Finck { 1477c2c66affSColin Finck int ret; 1478c2c66affSColin Finck size_t i, n, t, k; 1479c2c66affSColin Finck mbedtls_mpi X, Y, Z, T1, T2; 1480c2c66affSColin Finck 1481c2c66affSColin Finck if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) 1482c2c66affSColin Finck return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); 1483c2c66affSColin Finck 1484c2c66affSColin Finck mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); 1485c2c66affSColin Finck mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); 1486c2c66affSColin Finck 1487c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) 1488c2c66affSColin Finck { 1489c2c66affSColin Finck if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); 1490c2c66affSColin Finck if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); 1491c2c66affSColin Finck return( 0 ); 1492c2c66affSColin Finck } 1493c2c66affSColin Finck 1494c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); 1495c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); 1496c2c66affSColin Finck X.s = Y.s = 1; 1497c2c66affSColin Finck 1498c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); 1499c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); 1500c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); 1501c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); 1502c2c66affSColin Finck 1503c2c66affSColin Finck k = mbedtls_mpi_bitlen( &Y ) % biL; 1504c2c66affSColin Finck if( k < biL - 1 ) 1505c2c66affSColin Finck { 1506c2c66affSColin Finck k = biL - 1 - k; 1507c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); 1508c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); 1509c2c66affSColin Finck } 1510c2c66affSColin Finck else k = 0; 1511c2c66affSColin Finck 1512c2c66affSColin Finck n = X.n - 1; 1513c2c66affSColin Finck t = Y.n - 1; 1514c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); 1515c2c66affSColin Finck 1516c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) 1517c2c66affSColin Finck { 1518c2c66affSColin Finck Z.p[n - t]++; 1519c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); 1520c2c66affSColin Finck } 1521c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); 1522c2c66affSColin Finck 1523c2c66affSColin Finck for( i = n; i > t ; i-- ) 1524c2c66affSColin Finck { 1525c2c66affSColin Finck if( X.p[i] >= Y.p[t] ) 1526c2c66affSColin Finck Z.p[i - t - 1] = ~0; 1527c2c66affSColin Finck else 1528c2c66affSColin Finck { 1529c2c66affSColin Finck Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], 1530c2c66affSColin Finck Y.p[t], NULL); 1531c2c66affSColin Finck } 1532c2c66affSColin Finck 1533c2c66affSColin Finck Z.p[i - t - 1]++; 1534c2c66affSColin Finck do 1535c2c66affSColin Finck { 1536c2c66affSColin Finck Z.p[i - t - 1]--; 1537c2c66affSColin Finck 1538c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); 1539c2c66affSColin Finck T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; 1540c2c66affSColin Finck T1.p[1] = Y.p[t]; 1541c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); 1542c2c66affSColin Finck 1543c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); 1544c2c66affSColin Finck T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; 1545c2c66affSColin Finck T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; 1546c2c66affSColin Finck T2.p[2] = X.p[i]; 1547c2c66affSColin Finck } 1548c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); 1549c2c66affSColin Finck 1550c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); 1551c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); 1552c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); 1553c2c66affSColin Finck 1554c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) 1555c2c66affSColin Finck { 1556c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); 1557c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); 1558c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); 1559c2c66affSColin Finck Z.p[i - t - 1]--; 1560c2c66affSColin Finck } 1561c2c66affSColin Finck } 1562c2c66affSColin Finck 1563c2c66affSColin Finck if( Q != NULL ) 1564c2c66affSColin Finck { 1565c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); 1566c2c66affSColin Finck Q->s = A->s * B->s; 1567c2c66affSColin Finck } 1568c2c66affSColin Finck 1569c2c66affSColin Finck if( R != NULL ) 1570c2c66affSColin Finck { 1571c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); 1572c2c66affSColin Finck X.s = A->s; 1573c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); 1574c2c66affSColin Finck 1575c2c66affSColin Finck if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) 1576c2c66affSColin Finck R->s = 1; 1577c2c66affSColin Finck } 1578c2c66affSColin Finck 1579c2c66affSColin Finck cleanup: 1580c2c66affSColin Finck 1581c2c66affSColin Finck mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); 1582c2c66affSColin Finck mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); 1583c2c66affSColin Finck 1584c2c66affSColin Finck return( ret ); 1585c2c66affSColin Finck } 1586c2c66affSColin Finck 1587c2c66affSColin Finck /* 1588c2c66affSColin Finck * Division by int: A = Q * b + R 1589c2c66affSColin Finck */ 1590c2c66affSColin Finck int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1591c2c66affSColin Finck { 1592c2c66affSColin Finck mbedtls_mpi _B; 1593c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1594c2c66affSColin Finck 1595c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1596c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1597c2c66affSColin Finck _B.n = 1; 1598c2c66affSColin Finck _B.p = p; 1599c2c66affSColin Finck 1600c2c66affSColin Finck return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); 1601c2c66affSColin Finck } 1602c2c66affSColin Finck 1603c2c66affSColin Finck /* 1604c2c66affSColin Finck * Modulo: R = A mod B 1605c2c66affSColin Finck */ 1606c2c66affSColin Finck int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1607c2c66affSColin Finck { 1608c2c66affSColin Finck int ret; 1609c2c66affSColin Finck 1610c2c66affSColin Finck if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) 1611c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); 1612c2c66affSColin Finck 1613c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); 1614c2c66affSColin Finck 1615c2c66affSColin Finck while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) 1616c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); 1617c2c66affSColin Finck 1618c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) 1619c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); 1620c2c66affSColin Finck 1621c2c66affSColin Finck cleanup: 1622c2c66affSColin Finck 1623c2c66affSColin Finck return( ret ); 1624c2c66affSColin Finck } 1625c2c66affSColin Finck 1626c2c66affSColin Finck /* 1627c2c66affSColin Finck * Modulo: r = A mod b 1628c2c66affSColin Finck */ 1629c2c66affSColin Finck int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1630c2c66affSColin Finck { 1631c2c66affSColin Finck size_t i; 1632c2c66affSColin Finck mbedtls_mpi_uint x, y, z; 1633c2c66affSColin Finck 1634c2c66affSColin Finck if( b == 0 ) 1635c2c66affSColin Finck return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); 1636c2c66affSColin Finck 1637c2c66affSColin Finck if( b < 0 ) 1638c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); 1639c2c66affSColin Finck 1640c2c66affSColin Finck /* 1641c2c66affSColin Finck * handle trivial cases 1642c2c66affSColin Finck */ 1643c2c66affSColin Finck if( b == 1 ) 1644c2c66affSColin Finck { 1645c2c66affSColin Finck *r = 0; 1646c2c66affSColin Finck return( 0 ); 1647c2c66affSColin Finck } 1648c2c66affSColin Finck 1649c2c66affSColin Finck if( b == 2 ) 1650c2c66affSColin Finck { 1651c2c66affSColin Finck *r = A->p[0] & 1; 1652c2c66affSColin Finck return( 0 ); 1653c2c66affSColin Finck } 1654c2c66affSColin Finck 1655c2c66affSColin Finck /* 1656c2c66affSColin Finck * general case 1657c2c66affSColin Finck */ 1658c2c66affSColin Finck for( i = A->n, y = 0; i > 0; i-- ) 1659c2c66affSColin Finck { 1660c2c66affSColin Finck x = A->p[i - 1]; 1661c2c66affSColin Finck y = ( y << biH ) | ( x >> biH ); 1662c2c66affSColin Finck z = y / b; 1663c2c66affSColin Finck y -= z * b; 1664c2c66affSColin Finck 1665c2c66affSColin Finck x <<= biH; 1666c2c66affSColin Finck y = ( y << biH ) | ( x >> biH ); 1667c2c66affSColin Finck z = y / b; 1668c2c66affSColin Finck y -= z * b; 1669c2c66affSColin Finck } 1670c2c66affSColin Finck 1671c2c66affSColin Finck /* 1672c2c66affSColin Finck * If A is negative, then the current y represents a negative value. 1673c2c66affSColin Finck * Flipping it to the positive side. 1674c2c66affSColin Finck */ 1675c2c66affSColin Finck if( A->s < 0 && y != 0 ) 1676c2c66affSColin Finck y = b - y; 1677c2c66affSColin Finck 1678c2c66affSColin Finck *r = y; 1679c2c66affSColin Finck 1680c2c66affSColin Finck return( 0 ); 1681c2c66affSColin Finck } 1682c2c66affSColin Finck 1683c2c66affSColin Finck /* 1684c2c66affSColin Finck * Fast Montgomery initialization (thanks to Tom St Denis) 1685c2c66affSColin Finck */ 1686c2c66affSColin Finck static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) 1687c2c66affSColin Finck { 1688c2c66affSColin Finck mbedtls_mpi_uint x, m0 = N->p[0]; 1689c2c66affSColin Finck unsigned int i; 1690c2c66affSColin Finck 1691c2c66affSColin Finck x = m0; 1692c2c66affSColin Finck x += ( ( m0 + 2 ) & 4 ) << 1; 1693c2c66affSColin Finck 1694c2c66affSColin Finck for( i = biL; i >= 8; i /= 2 ) 1695c2c66affSColin Finck x *= ( 2 - ( m0 * x ) ); 1696c2c66affSColin Finck 1697c2c66affSColin Finck *mm = ~x + 1; 1698c2c66affSColin Finck } 1699c2c66affSColin Finck 1700c2c66affSColin Finck /* 1701c2c66affSColin Finck * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) 1702c2c66affSColin Finck */ 1703c2c66affSColin Finck static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, 1704c2c66affSColin Finck const mbedtls_mpi *T ) 1705c2c66affSColin Finck { 1706c2c66affSColin Finck size_t i, n, m; 1707c2c66affSColin Finck mbedtls_mpi_uint u0, u1, *d; 1708c2c66affSColin Finck 1709c2c66affSColin Finck if( T->n < N->n + 1 || T->p == NULL ) 1710c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 1711c2c66affSColin Finck 1712c2c66affSColin Finck memset( T->p, 0, T->n * ciL ); 1713c2c66affSColin Finck 1714c2c66affSColin Finck d = T->p; 1715c2c66affSColin Finck n = N->n; 1716c2c66affSColin Finck m = ( B->n < n ) ? B->n : n; 1717c2c66affSColin Finck 1718c2c66affSColin Finck for( i = 0; i < n; i++ ) 1719c2c66affSColin Finck { 1720c2c66affSColin Finck /* 1721c2c66affSColin Finck * T = (T + u0*B + u1*N) / 2^biL 1722c2c66affSColin Finck */ 1723c2c66affSColin Finck u0 = A->p[i]; 1724c2c66affSColin Finck u1 = ( d[0] + u0 * B->p[0] ) * mm; 1725c2c66affSColin Finck 1726c2c66affSColin Finck mpi_mul_hlp( m, B->p, d, u0 ); 1727c2c66affSColin Finck mpi_mul_hlp( n, N->p, d, u1 ); 1728c2c66affSColin Finck 1729c2c66affSColin Finck *d++ = u0; d[n + 1] = 0; 1730c2c66affSColin Finck } 1731c2c66affSColin Finck 1732c2c66affSColin Finck memcpy( A->p, d, ( n + 1 ) * ciL ); 1733c2c66affSColin Finck 1734c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) 1735c2c66affSColin Finck mpi_sub_hlp( n, N->p, A->p ); 1736c2c66affSColin Finck else 1737c2c66affSColin Finck /* prevent timing attacks */ 1738c2c66affSColin Finck mpi_sub_hlp( n, A->p, T->p ); 1739c2c66affSColin Finck 1740c2c66affSColin Finck return( 0 ); 1741c2c66affSColin Finck } 1742c2c66affSColin Finck 1743c2c66affSColin Finck /* 1744c2c66affSColin Finck * Montgomery reduction: A = A * R^-1 mod N 1745c2c66affSColin Finck */ 1746c2c66affSColin Finck static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) 1747c2c66affSColin Finck { 1748c2c66affSColin Finck mbedtls_mpi_uint z = 1; 1749c2c66affSColin Finck mbedtls_mpi U; 1750c2c66affSColin Finck 1751c2c66affSColin Finck U.n = U.s = (int) z; 1752c2c66affSColin Finck U.p = &z; 1753c2c66affSColin Finck 1754c2c66affSColin Finck return( mpi_montmul( A, &U, N, mm, T ) ); 1755c2c66affSColin Finck } 1756c2c66affSColin Finck 1757c2c66affSColin Finck /* 1758c2c66affSColin Finck * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) 1759c2c66affSColin Finck */ 1760c2c66affSColin Finck int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) 1761c2c66affSColin Finck { 1762c2c66affSColin Finck int ret; 1763c2c66affSColin Finck size_t wbits, wsize, one = 1; 1764c2c66affSColin Finck size_t i, j, nblimbs; 1765c2c66affSColin Finck size_t bufsize, nbits; 1766c2c66affSColin Finck mbedtls_mpi_uint ei, mm, state; 1767c2c66affSColin Finck mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; 1768c2c66affSColin Finck int neg; 1769c2c66affSColin Finck 1770d9e6c9b5SThomas Faber if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) 1771c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 1772c2c66affSColin Finck 1773c2c66affSColin Finck if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) 1774c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 1775c2c66affSColin Finck 1776c2c66affSColin Finck /* 1777c2c66affSColin Finck * Init temps and window size 1778c2c66affSColin Finck */ 1779c2c66affSColin Finck mpi_montg_init( &mm, N ); 1780c2c66affSColin Finck mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); 1781c2c66affSColin Finck mbedtls_mpi_init( &Apos ); 1782c2c66affSColin Finck memset( W, 0, sizeof( W ) ); 1783c2c66affSColin Finck 1784c2c66affSColin Finck i = mbedtls_mpi_bitlen( E ); 1785c2c66affSColin Finck 1786c2c66affSColin Finck wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : 1787c2c66affSColin Finck ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; 1788c2c66affSColin Finck 1789430656f0SThomas Faber #if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) 1790c2c66affSColin Finck if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) 1791c2c66affSColin Finck wsize = MBEDTLS_MPI_WINDOW_SIZE; 1792430656f0SThomas Faber #endif 1793c2c66affSColin Finck 1794c2c66affSColin Finck j = N->n + 1; 1795c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); 1796c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); 1797c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); 1798c2c66affSColin Finck 1799c2c66affSColin Finck /* 1800c2c66affSColin Finck * Compensate for negative A (and correct at the end) 1801c2c66affSColin Finck */ 1802c2c66affSColin Finck neg = ( A->s == -1 ); 1803c2c66affSColin Finck if( neg ) 1804c2c66affSColin Finck { 1805c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); 1806c2c66affSColin Finck Apos.s = 1; 1807c2c66affSColin Finck A = &Apos; 1808c2c66affSColin Finck } 1809c2c66affSColin Finck 1810c2c66affSColin Finck /* 1811c2c66affSColin Finck * If 1st call, pre-compute R^2 mod N 1812c2c66affSColin Finck */ 1813c2c66affSColin Finck if( _RR == NULL || _RR->p == NULL ) 1814c2c66affSColin Finck { 1815c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); 1816c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); 1817c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); 1818c2c66affSColin Finck 1819c2c66affSColin Finck if( _RR != NULL ) 1820c2c66affSColin Finck memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); 1821c2c66affSColin Finck } 1822c2c66affSColin Finck else 1823c2c66affSColin Finck memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); 1824c2c66affSColin Finck 1825c2c66affSColin Finck /* 1826c2c66affSColin Finck * W[1] = A * R^2 * R^-1 mod N = A * R mod N 1827c2c66affSColin Finck */ 1828c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) 1829c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); 1830c2c66affSColin Finck else 1831c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); 1832c2c66affSColin Finck 1833c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); 1834c2c66affSColin Finck 1835c2c66affSColin Finck /* 1836c2c66affSColin Finck * X = R^2 * R^-1 mod N = R mod N 1837c2c66affSColin Finck */ 1838c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); 1839c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); 1840c2c66affSColin Finck 1841c2c66affSColin Finck if( wsize > 1 ) 1842c2c66affSColin Finck { 1843c2c66affSColin Finck /* 1844c2c66affSColin Finck * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) 1845c2c66affSColin Finck */ 1846c2c66affSColin Finck j = one << ( wsize - 1 ); 1847c2c66affSColin Finck 1848c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); 1849c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); 1850c2c66affSColin Finck 1851c2c66affSColin Finck for( i = 0; i < wsize - 1; i++ ) 1852c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); 1853c2c66affSColin Finck 1854c2c66affSColin Finck /* 1855c2c66affSColin Finck * W[i] = W[i - 1] * W[1] 1856c2c66affSColin Finck */ 1857c2c66affSColin Finck for( i = j + 1; i < ( one << wsize ); i++ ) 1858c2c66affSColin Finck { 1859c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); 1860c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); 1861c2c66affSColin Finck 1862c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); 1863c2c66affSColin Finck } 1864c2c66affSColin Finck } 1865c2c66affSColin Finck 1866c2c66affSColin Finck nblimbs = E->n; 1867c2c66affSColin Finck bufsize = 0; 1868c2c66affSColin Finck nbits = 0; 1869c2c66affSColin Finck wbits = 0; 1870c2c66affSColin Finck state = 0; 1871c2c66affSColin Finck 1872c2c66affSColin Finck while( 1 ) 1873c2c66affSColin Finck { 1874c2c66affSColin Finck if( bufsize == 0 ) 1875c2c66affSColin Finck { 1876c2c66affSColin Finck if( nblimbs == 0 ) 1877c2c66affSColin Finck break; 1878c2c66affSColin Finck 1879c2c66affSColin Finck nblimbs--; 1880c2c66affSColin Finck 1881c2c66affSColin Finck bufsize = sizeof( mbedtls_mpi_uint ) << 3; 1882c2c66affSColin Finck } 1883c2c66affSColin Finck 1884c2c66affSColin Finck bufsize--; 1885c2c66affSColin Finck 1886c2c66affSColin Finck ei = (E->p[nblimbs] >> bufsize) & 1; 1887c2c66affSColin Finck 1888c2c66affSColin Finck /* 1889c2c66affSColin Finck * skip leading 0s 1890c2c66affSColin Finck */ 1891c2c66affSColin Finck if( ei == 0 && state == 0 ) 1892c2c66affSColin Finck continue; 1893c2c66affSColin Finck 1894c2c66affSColin Finck if( ei == 0 && state == 1 ) 1895c2c66affSColin Finck { 1896c2c66affSColin Finck /* 1897c2c66affSColin Finck * out of window, square X 1898c2c66affSColin Finck */ 1899c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); 1900c2c66affSColin Finck continue; 1901c2c66affSColin Finck } 1902c2c66affSColin Finck 1903c2c66affSColin Finck /* 1904c2c66affSColin Finck * add ei to current window 1905c2c66affSColin Finck */ 1906c2c66affSColin Finck state = 2; 1907c2c66affSColin Finck 1908c2c66affSColin Finck nbits++; 1909c2c66affSColin Finck wbits |= ( ei << ( wsize - nbits ) ); 1910c2c66affSColin Finck 1911c2c66affSColin Finck if( nbits == wsize ) 1912c2c66affSColin Finck { 1913c2c66affSColin Finck /* 1914c2c66affSColin Finck * X = X^wsize R^-1 mod N 1915c2c66affSColin Finck */ 1916c2c66affSColin Finck for( i = 0; i < wsize; i++ ) 1917c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); 1918c2c66affSColin Finck 1919c2c66affSColin Finck /* 1920c2c66affSColin Finck * X = X * W[wbits] R^-1 mod N 1921c2c66affSColin Finck */ 1922c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); 1923c2c66affSColin Finck 1924c2c66affSColin Finck state--; 1925c2c66affSColin Finck nbits = 0; 1926c2c66affSColin Finck wbits = 0; 1927c2c66affSColin Finck } 1928c2c66affSColin Finck } 1929c2c66affSColin Finck 1930c2c66affSColin Finck /* 1931c2c66affSColin Finck * process the remaining bits 1932c2c66affSColin Finck */ 1933c2c66affSColin Finck for( i = 0; i < nbits; i++ ) 1934c2c66affSColin Finck { 1935c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); 1936c2c66affSColin Finck 1937c2c66affSColin Finck wbits <<= 1; 1938c2c66affSColin Finck 1939c2c66affSColin Finck if( ( wbits & ( one << wsize ) ) != 0 ) 1940c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); 1941c2c66affSColin Finck } 1942c2c66affSColin Finck 1943c2c66affSColin Finck /* 1944c2c66affSColin Finck * X = A^E * R * R^-1 mod N = A^E mod N 1945c2c66affSColin Finck */ 1946c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); 1947c2c66affSColin Finck 1948c2c66affSColin Finck if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) 1949c2c66affSColin Finck { 1950c2c66affSColin Finck X->s = -1; 1951c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); 1952c2c66affSColin Finck } 1953c2c66affSColin Finck 1954c2c66affSColin Finck cleanup: 1955c2c66affSColin Finck 1956c2c66affSColin Finck for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) 1957c2c66affSColin Finck mbedtls_mpi_free( &W[i] ); 1958c2c66affSColin Finck 1959c2c66affSColin Finck mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); 1960c2c66affSColin Finck 1961c2c66affSColin Finck if( _RR == NULL || _RR->p == NULL ) 1962c2c66affSColin Finck mbedtls_mpi_free( &RR ); 1963c2c66affSColin Finck 1964c2c66affSColin Finck return( ret ); 1965c2c66affSColin Finck } 1966c2c66affSColin Finck 1967c2c66affSColin Finck /* 1968c2c66affSColin Finck * Greatest common divisor: G = gcd(A, B) (HAC 14.54) 1969c2c66affSColin Finck */ 1970c2c66affSColin Finck int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1971c2c66affSColin Finck { 1972c2c66affSColin Finck int ret; 1973c2c66affSColin Finck size_t lz, lzt; 1974c2c66affSColin Finck mbedtls_mpi TG, TA, TB; 1975c2c66affSColin Finck 1976c2c66affSColin Finck mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); 1977c2c66affSColin Finck 1978c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); 1979c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); 1980c2c66affSColin Finck 1981c2c66affSColin Finck lz = mbedtls_mpi_lsb( &TA ); 1982c2c66affSColin Finck lzt = mbedtls_mpi_lsb( &TB ); 1983c2c66affSColin Finck 1984c2c66affSColin Finck if( lzt < lz ) 1985c2c66affSColin Finck lz = lzt; 1986c2c66affSColin Finck 1987c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); 1988c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); 1989c2c66affSColin Finck 1990c2c66affSColin Finck TA.s = TB.s = 1; 1991c2c66affSColin Finck 1992c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) 1993c2c66affSColin Finck { 1994c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); 1995c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); 1996c2c66affSColin Finck 1997c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) 1998c2c66affSColin Finck { 1999c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); 2000c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); 2001c2c66affSColin Finck } 2002c2c66affSColin Finck else 2003c2c66affSColin Finck { 2004c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); 2005c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); 2006c2c66affSColin Finck } 2007c2c66affSColin Finck } 2008c2c66affSColin Finck 2009c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); 2010c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); 2011c2c66affSColin Finck 2012c2c66affSColin Finck cleanup: 2013c2c66affSColin Finck 2014c2c66affSColin Finck mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); 2015c2c66affSColin Finck 2016c2c66affSColin Finck return( ret ); 2017c2c66affSColin Finck } 2018c2c66affSColin Finck 2019c2c66affSColin Finck /* 2020c2c66affSColin Finck * Fill X with size bytes of random. 2021c2c66affSColin Finck * 2022c2c66affSColin Finck * Use a temporary bytes representation to make sure the result is the same 2023c2c66affSColin Finck * regardless of the platform endianness (useful when f_rng is actually 2024c2c66affSColin Finck * deterministic, eg for tests). 2025c2c66affSColin Finck */ 2026c2c66affSColin Finck int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, 2027c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2028c2c66affSColin Finck void *p_rng ) 2029c2c66affSColin Finck { 2030c2c66affSColin Finck int ret; 2031c2c66affSColin Finck unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; 2032c2c66affSColin Finck 2033c2c66affSColin Finck if( size > MBEDTLS_MPI_MAX_SIZE ) 2034c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 2035c2c66affSColin Finck 2036c2c66affSColin Finck MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); 2037c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); 2038c2c66affSColin Finck 2039c2c66affSColin Finck cleanup: 2040d9e6c9b5SThomas Faber mbedtls_zeroize( buf, sizeof( buf ) ); 2041c2c66affSColin Finck return( ret ); 2042c2c66affSColin Finck } 2043c2c66affSColin Finck 2044c2c66affSColin Finck /* 2045c2c66affSColin Finck * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) 2046c2c66affSColin Finck */ 2047c2c66affSColin Finck int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) 2048c2c66affSColin Finck { 2049c2c66affSColin Finck int ret; 2050c2c66affSColin Finck mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; 2051c2c66affSColin Finck 2052c2c66affSColin Finck if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) 2053c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 2054c2c66affSColin Finck 2055c2c66affSColin Finck mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); 2056c2c66affSColin Finck mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); 2057c2c66affSColin Finck mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); 2058c2c66affSColin Finck 2059c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); 2060c2c66affSColin Finck 2061c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) 2062c2c66affSColin Finck { 2063c2c66affSColin Finck ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2064c2c66affSColin Finck goto cleanup; 2065c2c66affSColin Finck } 2066c2c66affSColin Finck 2067c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); 2068c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); 2069c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); 2070c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); 2071c2c66affSColin Finck 2072c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); 2073c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); 2074c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); 2075c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); 2076c2c66affSColin Finck 2077c2c66affSColin Finck do 2078c2c66affSColin Finck { 2079c2c66affSColin Finck while( ( TU.p[0] & 1 ) == 0 ) 2080c2c66affSColin Finck { 2081c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); 2082c2c66affSColin Finck 2083c2c66affSColin Finck if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) 2084c2c66affSColin Finck { 2085c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); 2086c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); 2087c2c66affSColin Finck } 2088c2c66affSColin Finck 2089c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); 2090c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); 2091c2c66affSColin Finck } 2092c2c66affSColin Finck 2093c2c66affSColin Finck while( ( TV.p[0] & 1 ) == 0 ) 2094c2c66affSColin Finck { 2095c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); 2096c2c66affSColin Finck 2097c2c66affSColin Finck if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) 2098c2c66affSColin Finck { 2099c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); 2100c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); 2101c2c66affSColin Finck } 2102c2c66affSColin Finck 2103c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); 2104c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); 2105c2c66affSColin Finck } 2106c2c66affSColin Finck 2107c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) 2108c2c66affSColin Finck { 2109c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); 2110c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); 2111c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); 2112c2c66affSColin Finck } 2113c2c66affSColin Finck else 2114c2c66affSColin Finck { 2115c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); 2116c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); 2117c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); 2118c2c66affSColin Finck } 2119c2c66affSColin Finck } 2120c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); 2121c2c66affSColin Finck 2122c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) 2123c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); 2124c2c66affSColin Finck 2125c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) 2126c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); 2127c2c66affSColin Finck 2128c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); 2129c2c66affSColin Finck 2130c2c66affSColin Finck cleanup: 2131c2c66affSColin Finck 2132c2c66affSColin Finck mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); 2133c2c66affSColin Finck mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); 2134c2c66affSColin Finck mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); 2135c2c66affSColin Finck 2136c2c66affSColin Finck return( ret ); 2137c2c66affSColin Finck } 2138c2c66affSColin Finck 2139c2c66affSColin Finck #if defined(MBEDTLS_GENPRIME) 2140c2c66affSColin Finck 2141c2c66affSColin Finck static const int small_prime[] = 2142c2c66affSColin Finck { 2143c2c66affSColin Finck 3, 5, 7, 11, 13, 17, 19, 23, 2144c2c66affSColin Finck 29, 31, 37, 41, 43, 47, 53, 59, 2145c2c66affSColin Finck 61, 67, 71, 73, 79, 83, 89, 97, 2146c2c66affSColin Finck 101, 103, 107, 109, 113, 127, 131, 137, 2147c2c66affSColin Finck 139, 149, 151, 157, 163, 167, 173, 179, 2148c2c66affSColin Finck 181, 191, 193, 197, 199, 211, 223, 227, 2149c2c66affSColin Finck 229, 233, 239, 241, 251, 257, 263, 269, 2150c2c66affSColin Finck 271, 277, 281, 283, 293, 307, 311, 313, 2151c2c66affSColin Finck 317, 331, 337, 347, 349, 353, 359, 367, 2152c2c66affSColin Finck 373, 379, 383, 389, 397, 401, 409, 419, 2153c2c66affSColin Finck 421, 431, 433, 439, 443, 449, 457, 461, 2154c2c66affSColin Finck 463, 467, 479, 487, 491, 499, 503, 509, 2155c2c66affSColin Finck 521, 523, 541, 547, 557, 563, 569, 571, 2156c2c66affSColin Finck 577, 587, 593, 599, 601, 607, 613, 617, 2157c2c66affSColin Finck 619, 631, 641, 643, 647, 653, 659, 661, 2158c2c66affSColin Finck 673, 677, 683, 691, 701, 709, 719, 727, 2159c2c66affSColin Finck 733, 739, 743, 751, 757, 761, 769, 773, 2160c2c66affSColin Finck 787, 797, 809, 811, 821, 823, 827, 829, 2161c2c66affSColin Finck 839, 853, 857, 859, 863, 877, 881, 883, 2162c2c66affSColin Finck 887, 907, 911, 919, 929, 937, 941, 947, 2163c2c66affSColin Finck 953, 967, 971, 977, 983, 991, 997, -103 2164c2c66affSColin Finck }; 2165c2c66affSColin Finck 2166c2c66affSColin Finck /* 2167c2c66affSColin Finck * Small divisors test (X must be positive) 2168c2c66affSColin Finck * 2169c2c66affSColin Finck * Return values: 2170c2c66affSColin Finck * 0: no small factor (possible prime, more tests needed) 2171c2c66affSColin Finck * 1: certain prime 2172c2c66affSColin Finck * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime 2173c2c66affSColin Finck * other negative: error 2174c2c66affSColin Finck */ 2175c2c66affSColin Finck static int mpi_check_small_factors( const mbedtls_mpi *X ) 2176c2c66affSColin Finck { 2177c2c66affSColin Finck int ret = 0; 2178c2c66affSColin Finck size_t i; 2179c2c66affSColin Finck mbedtls_mpi_uint r; 2180c2c66affSColin Finck 2181c2c66affSColin Finck if( ( X->p[0] & 1 ) == 0 ) 2182c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2183c2c66affSColin Finck 2184c2c66affSColin Finck for( i = 0; small_prime[i] > 0; i++ ) 2185c2c66affSColin Finck { 2186c2c66affSColin Finck if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) 2187c2c66affSColin Finck return( 1 ); 2188c2c66affSColin Finck 2189c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); 2190c2c66affSColin Finck 2191c2c66affSColin Finck if( r == 0 ) 2192c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2193c2c66affSColin Finck } 2194c2c66affSColin Finck 2195c2c66affSColin Finck cleanup: 2196c2c66affSColin Finck return( ret ); 2197c2c66affSColin Finck } 2198c2c66affSColin Finck 2199c2c66affSColin Finck /* 2200c2c66affSColin Finck * Miller-Rabin pseudo-primality test (HAC 4.24) 2201c2c66affSColin Finck */ 22020ba5bc40SThomas Faber static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, 2203c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2204c2c66affSColin Finck void *p_rng ) 2205c2c66affSColin Finck { 2206c2c66affSColin Finck int ret, count; 22070ba5bc40SThomas Faber size_t i, j, k, s; 2208c2c66affSColin Finck mbedtls_mpi W, R, T, A, RR; 2209c2c66affSColin Finck 2210c2c66affSColin Finck mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); 2211c2c66affSColin Finck mbedtls_mpi_init( &RR ); 2212c2c66affSColin Finck 2213c2c66affSColin Finck /* 2214c2c66affSColin Finck * W = |X| - 1 2215c2c66affSColin Finck * R = W >> lsb( W ) 2216c2c66affSColin Finck */ 2217c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); 2218c2c66affSColin Finck s = mbedtls_mpi_lsb( &W ); 2219c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); 2220c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); 2221c2c66affSColin Finck 2222c2c66affSColin Finck i = mbedtls_mpi_bitlen( X ); 2223c2c66affSColin Finck 22240ba5bc40SThomas Faber for( i = 0; i < rounds; i++ ) 2225c2c66affSColin Finck { 2226c2c66affSColin Finck /* 2227c2c66affSColin Finck * pick a random A, 1 < A < |X| - 1 2228c2c66affSColin Finck */ 2229c2c66affSColin Finck count = 0; 2230c2c66affSColin Finck do { 2231c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); 2232c2c66affSColin Finck 2233c2c66affSColin Finck j = mbedtls_mpi_bitlen( &A ); 2234c2c66affSColin Finck k = mbedtls_mpi_bitlen( &W ); 2235c2c66affSColin Finck if (j > k) { 22360ba5bc40SThomas Faber A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; 2237c2c66affSColin Finck } 2238c2c66affSColin Finck 2239c2c66affSColin Finck if (count++ > 30) { 2240c1eccaffSThomas Faber ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2241c1eccaffSThomas Faber goto cleanup; 2242c2c66affSColin Finck } 2243c2c66affSColin Finck 2244c2c66affSColin Finck } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || 2245c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); 2246c2c66affSColin Finck 2247c2c66affSColin Finck /* 2248c2c66affSColin Finck * A = A^R mod |X| 2249c2c66affSColin Finck */ 2250c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); 2251c2c66affSColin Finck 2252c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || 2253c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2254c2c66affSColin Finck continue; 2255c2c66affSColin Finck 2256c2c66affSColin Finck j = 1; 2257c2c66affSColin Finck while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) 2258c2c66affSColin Finck { 2259c2c66affSColin Finck /* 2260c2c66affSColin Finck * A = A * A mod |X| 2261c2c66affSColin Finck */ 2262c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); 2263c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); 2264c2c66affSColin Finck 2265c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2266c2c66affSColin Finck break; 2267c2c66affSColin Finck 2268c2c66affSColin Finck j++; 2269c2c66affSColin Finck } 2270c2c66affSColin Finck 2271c2c66affSColin Finck /* 2272c2c66affSColin Finck * not prime if A != |X| - 1 or A == 1 2273c2c66affSColin Finck */ 2274c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || 2275c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2276c2c66affSColin Finck { 2277c2c66affSColin Finck ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2278c2c66affSColin Finck break; 2279c2c66affSColin Finck } 2280c2c66affSColin Finck } 2281c2c66affSColin Finck 2282c2c66affSColin Finck cleanup: 2283c2c66affSColin Finck mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); 2284c2c66affSColin Finck mbedtls_mpi_free( &RR ); 2285c2c66affSColin Finck 2286c2c66affSColin Finck return( ret ); 2287c2c66affSColin Finck } 2288c2c66affSColin Finck 2289c2c66affSColin Finck /* 2290c2c66affSColin Finck * Pseudo-primality test: small factors, then Miller-Rabin 2291c2c66affSColin Finck */ 22920ba5bc40SThomas Faber static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds, 2293c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2294c2c66affSColin Finck void *p_rng ) 2295c2c66affSColin Finck { 2296c2c66affSColin Finck int ret; 2297c2c66affSColin Finck mbedtls_mpi XX; 2298c2c66affSColin Finck 2299c2c66affSColin Finck XX.s = 1; 2300c2c66affSColin Finck XX.n = X->n; 2301c2c66affSColin Finck XX.p = X->p; 2302c2c66affSColin Finck 2303c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || 2304c2c66affSColin Finck mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) 2305c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2306c2c66affSColin Finck 2307c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) 2308c2c66affSColin Finck return( 0 ); 2309c2c66affSColin Finck 2310c2c66affSColin Finck if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) 2311c2c66affSColin Finck { 2312c2c66affSColin Finck if( ret == 1 ) 2313c2c66affSColin Finck return( 0 ); 2314c2c66affSColin Finck 2315c2c66affSColin Finck return( ret ); 2316c2c66affSColin Finck } 2317c2c66affSColin Finck 23180ba5bc40SThomas Faber return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); 23190ba5bc40SThomas Faber } 23200ba5bc40SThomas Faber 23210ba5bc40SThomas Faber /* 23220ba5bc40SThomas Faber * Pseudo-primality test, error probability 2^-80 23230ba5bc40SThomas Faber */ 23240ba5bc40SThomas Faber int mbedtls_mpi_is_prime( const mbedtls_mpi *X, 23250ba5bc40SThomas Faber int (*f_rng)(void *, unsigned char *, size_t), 23260ba5bc40SThomas Faber void *p_rng ) 23270ba5bc40SThomas Faber { 23280ba5bc40SThomas Faber return mpi_is_prime_internal( X, 40, f_rng, p_rng ); 2329c2c66affSColin Finck } 2330c2c66affSColin Finck 2331c2c66affSColin Finck /* 2332c2c66affSColin Finck * Prime number generation 2333c2c66affSColin Finck */ 2334c2c66affSColin Finck int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, 2335c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2336c2c66affSColin Finck void *p_rng ) 2337c2c66affSColin Finck { 2338c2c66affSColin Finck int ret; 2339c2c66affSColin Finck size_t k, n; 23400ba5bc40SThomas Faber int rounds; 2341c2c66affSColin Finck mbedtls_mpi_uint r; 2342c2c66affSColin Finck mbedtls_mpi Y; 2343c2c66affSColin Finck 2344c2c66affSColin Finck if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) 2345c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 2346c2c66affSColin Finck 2347c2c66affSColin Finck mbedtls_mpi_init( &Y ); 2348c2c66affSColin Finck 2349c2c66affSColin Finck n = BITS_TO_LIMBS( nbits ); 2350c2c66affSColin Finck 23510ba5bc40SThomas Faber /* 23520ba5bc40SThomas Faber * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 23530ba5bc40SThomas Faber */ 23540ba5bc40SThomas Faber rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : 23550ba5bc40SThomas Faber ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : 23560ba5bc40SThomas Faber ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); 23570ba5bc40SThomas Faber 2358c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); 2359c2c66affSColin Finck 2360c2c66affSColin Finck k = mbedtls_mpi_bitlen( X ); 2361c2c66affSColin Finck if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); 2362c2c66affSColin Finck 2363c2c66affSColin Finck mbedtls_mpi_set_bit( X, nbits-1, 1 ); 2364c2c66affSColin Finck 2365c2c66affSColin Finck X->p[0] |= 1; 2366c2c66affSColin Finck 2367c2c66affSColin Finck if( dh_flag == 0 ) 2368c2c66affSColin Finck { 23690ba5bc40SThomas Faber while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 ) 2370c2c66affSColin Finck { 2371c2c66affSColin Finck if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) 2372c2c66affSColin Finck goto cleanup; 2373c2c66affSColin Finck 2374c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); 2375c2c66affSColin Finck } 2376c2c66affSColin Finck } 2377c2c66affSColin Finck else 2378c2c66affSColin Finck { 2379c2c66affSColin Finck /* 2380c2c66affSColin Finck * An necessary condition for Y and X = 2Y + 1 to be prime 2381c2c66affSColin Finck * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). 2382c2c66affSColin Finck * Make sure it is satisfied, while keeping X = 3 mod 4 2383c2c66affSColin Finck */ 2384c2c66affSColin Finck 2385c2c66affSColin Finck X->p[0] |= 2; 2386c2c66affSColin Finck 2387c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); 2388c2c66affSColin Finck if( r == 0 ) 2389c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); 2390c2c66affSColin Finck else if( r == 1 ) 2391c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); 2392c2c66affSColin Finck 2393c2c66affSColin Finck /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ 2394c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); 2395c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); 2396c2c66affSColin Finck 2397c2c66affSColin Finck while( 1 ) 2398c2c66affSColin Finck { 2399c2c66affSColin Finck /* 2400c2c66affSColin Finck * First, check small factors for X and Y 2401c2c66affSColin Finck * before doing Miller-Rabin on any of them 2402c2c66affSColin Finck */ 2403c2c66affSColin Finck if( ( ret = mpi_check_small_factors( X ) ) == 0 && 2404c2c66affSColin Finck ( ret = mpi_check_small_factors( &Y ) ) == 0 && 24050ba5bc40SThomas Faber ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) 24060ba5bc40SThomas Faber == 0 && 24070ba5bc40SThomas Faber ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) 24080ba5bc40SThomas Faber == 0 ) 2409c2c66affSColin Finck { 2410c2c66affSColin Finck break; 2411c2c66affSColin Finck } 2412c2c66affSColin Finck 2413c2c66affSColin Finck if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) 2414c2c66affSColin Finck goto cleanup; 2415c2c66affSColin Finck 2416c2c66affSColin Finck /* 2417c2c66affSColin Finck * Next candidates. We want to preserve Y = (X-1) / 2 and 2418c2c66affSColin Finck * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) 2419c2c66affSColin Finck * so up Y by 6 and X by 12. 2420c2c66affSColin Finck */ 2421c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); 2422c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); 2423c2c66affSColin Finck } 2424c2c66affSColin Finck } 2425c2c66affSColin Finck 2426c2c66affSColin Finck cleanup: 2427c2c66affSColin Finck 2428c2c66affSColin Finck mbedtls_mpi_free( &Y ); 2429c2c66affSColin Finck 2430c2c66affSColin Finck return( ret ); 2431c2c66affSColin Finck } 2432c2c66affSColin Finck 2433c2c66affSColin Finck #endif /* MBEDTLS_GENPRIME */ 2434c2c66affSColin Finck 2435c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST) 2436c2c66affSColin Finck 2437c2c66affSColin Finck #define GCD_PAIR_COUNT 3 2438c2c66affSColin Finck 2439c2c66affSColin Finck static const int gcd_pairs[GCD_PAIR_COUNT][3] = 2440c2c66affSColin Finck { 2441c2c66affSColin Finck { 693, 609, 21 }, 2442c2c66affSColin Finck { 1764, 868, 28 }, 2443c2c66affSColin Finck { 768454923, 542167814, 1 } 2444c2c66affSColin Finck }; 2445c2c66affSColin Finck 2446c2c66affSColin Finck /* 2447c2c66affSColin Finck * Checkup routine 2448c2c66affSColin Finck */ 2449c2c66affSColin Finck int mbedtls_mpi_self_test( int verbose ) 2450c2c66affSColin Finck { 2451c2c66affSColin Finck int ret, i; 2452c2c66affSColin Finck mbedtls_mpi A, E, N, X, Y, U, V; 2453c2c66affSColin Finck 2454c2c66affSColin Finck mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); 2455c2c66affSColin Finck mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); 2456c2c66affSColin Finck 2457c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, 2458c2c66affSColin Finck "EFE021C2645FD1DC586E69184AF4A31E" \ 2459c2c66affSColin Finck "D5F53E93B5F123FA41680867BA110131" \ 2460c2c66affSColin Finck "944FE7952E2517337780CB0DB80E61AA" \ 2461c2c66affSColin Finck "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); 2462c2c66affSColin Finck 2463c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, 2464c2c66affSColin Finck "B2E7EFD37075B9F03FF989C7C5051C20" \ 2465c2c66affSColin Finck "34D2A323810251127E7BF8625A4F49A5" \ 2466c2c66affSColin Finck "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ 2467c2c66affSColin Finck "5B5C25763222FEFCCFC38B832366C29E" ) ); 2468c2c66affSColin Finck 2469c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, 2470c2c66affSColin Finck "0066A198186C18C10B2F5ED9B522752A" \ 2471c2c66affSColin Finck "9830B69916E535C8F047518A889A43A5" \ 2472c2c66affSColin Finck "94B6BED27A168D31D4A52F88925AA8F5" ) ); 2473c2c66affSColin Finck 2474c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); 2475c2c66affSColin Finck 2476c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2477c2c66affSColin Finck "602AB7ECA597A3D6B56FF9829A5E8B85" \ 2478c2c66affSColin Finck "9E857EA95A03512E2BAE7391688D264A" \ 2479c2c66affSColin Finck "A5663B0341DB9CCFD2C4C5F421FEC814" \ 2480c2c66affSColin Finck "8001B72E848A38CAE1C65F78E56ABDEF" \ 2481c2c66affSColin Finck "E12D3C039B8A02D6BE593F0BBBDA56F1" \ 2482c2c66affSColin Finck "ECF677152EF804370C1A305CAF3B5BF1" \ 2483c2c66affSColin Finck "30879B56C61DE584A0F53A2447A51E" ) ); 2484c2c66affSColin Finck 2485c2c66affSColin Finck if( verbose != 0 ) 2486c2c66affSColin Finck mbedtls_printf( " MPI test #1 (mul_mpi): " ); 2487c2c66affSColin Finck 2488c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2489c2c66affSColin Finck { 2490c2c66affSColin Finck if( verbose != 0 ) 2491c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2492c2c66affSColin Finck 2493c2c66affSColin Finck ret = 1; 2494c2c66affSColin Finck goto cleanup; 2495c2c66affSColin Finck } 2496c2c66affSColin Finck 2497c2c66affSColin Finck if( verbose != 0 ) 2498c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2499c2c66affSColin Finck 2500c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); 2501c2c66affSColin Finck 2502c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2503c2c66affSColin Finck "256567336059E52CAE22925474705F39A94" ) ); 2504c2c66affSColin Finck 2505c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, 2506c2c66affSColin Finck "6613F26162223DF488E9CD48CC132C7A" \ 2507c2c66affSColin Finck "0AC93C701B001B092E4E5B9F73BCD27B" \ 2508c2c66affSColin Finck "9EE50D0657C77F374E903CDFA4C642" ) ); 2509c2c66affSColin Finck 2510c2c66affSColin Finck if( verbose != 0 ) 2511c2c66affSColin Finck mbedtls_printf( " MPI test #2 (div_mpi): " ); 2512c2c66affSColin Finck 2513c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || 2514c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) 2515c2c66affSColin Finck { 2516c2c66affSColin Finck if( verbose != 0 ) 2517c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2518c2c66affSColin Finck 2519c2c66affSColin Finck ret = 1; 2520c2c66affSColin Finck goto cleanup; 2521c2c66affSColin Finck } 2522c2c66affSColin Finck 2523c2c66affSColin Finck if( verbose != 0 ) 2524c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2525c2c66affSColin Finck 2526c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); 2527c2c66affSColin Finck 2528c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2529c2c66affSColin Finck "36E139AEA55215609D2816998ED020BB" \ 2530c2c66affSColin Finck "BD96C37890F65171D948E9BC7CBAA4D9" \ 2531c2c66affSColin Finck "325D24D6A3C12710F10A09FA08AB87" ) ); 2532c2c66affSColin Finck 2533c2c66affSColin Finck if( verbose != 0 ) 2534c2c66affSColin Finck mbedtls_printf( " MPI test #3 (exp_mod): " ); 2535c2c66affSColin Finck 2536c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2537c2c66affSColin Finck { 2538c2c66affSColin Finck if( verbose != 0 ) 2539c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2540c2c66affSColin Finck 2541c2c66affSColin Finck ret = 1; 2542c2c66affSColin Finck goto cleanup; 2543c2c66affSColin Finck } 2544c2c66affSColin Finck 2545c2c66affSColin Finck if( verbose != 0 ) 2546c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2547c2c66affSColin Finck 2548c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); 2549c2c66affSColin Finck 2550c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2551c2c66affSColin Finck "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ 2552c2c66affSColin Finck "C3DBA76456363A10869622EAC2DD84EC" \ 2553c2c66affSColin Finck "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); 2554c2c66affSColin Finck 2555c2c66affSColin Finck if( verbose != 0 ) 2556c2c66affSColin Finck mbedtls_printf( " MPI test #4 (inv_mod): " ); 2557c2c66affSColin Finck 2558c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2559c2c66affSColin Finck { 2560c2c66affSColin Finck if( verbose != 0 ) 2561c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2562c2c66affSColin Finck 2563c2c66affSColin Finck ret = 1; 2564c2c66affSColin Finck goto cleanup; 2565c2c66affSColin Finck } 2566c2c66affSColin Finck 2567c2c66affSColin Finck if( verbose != 0 ) 2568c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2569c2c66affSColin Finck 2570c2c66affSColin Finck if( verbose != 0 ) 2571c2c66affSColin Finck mbedtls_printf( " MPI test #5 (simple gcd): " ); 2572c2c66affSColin Finck 2573c2c66affSColin Finck for( i = 0; i < GCD_PAIR_COUNT; i++ ) 2574c2c66affSColin Finck { 2575c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); 2576c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); 2577c2c66affSColin Finck 2578c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); 2579c2c66affSColin Finck 2580c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) 2581c2c66affSColin Finck { 2582c2c66affSColin Finck if( verbose != 0 ) 2583c2c66affSColin Finck mbedtls_printf( "failed at %d\n", i ); 2584c2c66affSColin Finck 2585c2c66affSColin Finck ret = 1; 2586c2c66affSColin Finck goto cleanup; 2587c2c66affSColin Finck } 2588c2c66affSColin Finck } 2589c2c66affSColin Finck 2590c2c66affSColin Finck if( verbose != 0 ) 2591c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2592c2c66affSColin Finck 2593c2c66affSColin Finck cleanup: 2594c2c66affSColin Finck 2595c2c66affSColin Finck if( ret != 0 && verbose != 0 ) 2596c2c66affSColin Finck mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); 2597c2c66affSColin Finck 2598c2c66affSColin Finck mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); 2599c2c66affSColin Finck mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); 2600c2c66affSColin Finck 2601c2c66affSColin Finck if( verbose != 0 ) 2602c2c66affSColin Finck mbedtls_printf( "\n" ); 2603c2c66affSColin Finck 2604c2c66affSColin Finck return( ret ); 2605c2c66affSColin Finck } 2606c2c66affSColin Finck 2607c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */ 2608c2c66affSColin Finck 2609c2c66affSColin Finck #endif /* MBEDTLS_BIGNUM_C */ 2610