1c2c66affSColin Finck /* 2c2c66affSColin Finck * Multi-precision integer library 3c2c66affSColin Finck * 4218e2596SThomas Faber * Copyright The Mbed TLS Contributors 5e57126f5SThomas Faber * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6e57126f5SThomas Faber * 7e57126f5SThomas Faber * This file is provided under the Apache License 2.0, or the 8e57126f5SThomas Faber * GNU General Public License v2.0 or later. 9e57126f5SThomas Faber * 10e57126f5SThomas Faber * ********** 11e57126f5SThomas Faber * Apache License 2.0: 12e57126f5SThomas Faber * 13e57126f5SThomas Faber * Licensed under the Apache License, Version 2.0 (the "License"); you may 14e57126f5SThomas Faber * not use this file except in compliance with the License. 15e57126f5SThomas Faber * You may obtain a copy of the License at 16e57126f5SThomas Faber * 17e57126f5SThomas Faber * http://www.apache.org/licenses/LICENSE-2.0 18e57126f5SThomas Faber * 19e57126f5SThomas Faber * Unless required by applicable law or agreed to in writing, software 20e57126f5SThomas Faber * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 21e57126f5SThomas Faber * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22e57126f5SThomas Faber * See the License for the specific language governing permissions and 23e57126f5SThomas Faber * limitations under the License. 24e57126f5SThomas Faber * 25e57126f5SThomas Faber * ********** 26e57126f5SThomas Faber * 27e57126f5SThomas Faber * ********** 28e57126f5SThomas Faber * GNU General Public License v2.0 or later: 29c2c66affSColin Finck * 30c2c66affSColin Finck * This program is free software; you can redistribute it and/or modify 31c2c66affSColin Finck * it under the terms of the GNU General Public License as published by 32c2c66affSColin Finck * the Free Software Foundation; either version 2 of the License, or 33c2c66affSColin Finck * (at your option) any later version. 34c2c66affSColin Finck * 35c2c66affSColin Finck * This program is distributed in the hope that it will be useful, 36c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 37c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38c2c66affSColin Finck * GNU General Public License for more details. 39c2c66affSColin Finck * 40c2c66affSColin Finck * You should have received a copy of the GNU General Public License along 41c2c66affSColin Finck * with this program; if not, write to the Free Software Foundation, Inc., 42c2c66affSColin Finck * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 43c2c66affSColin Finck * 44e57126f5SThomas Faber * ********** 45c2c66affSColin Finck */ 46c2c66affSColin Finck 47c2c66affSColin Finck /* 48c2c66affSColin Finck * The following sources were referenced in the design of this Multi-precision 49c2c66affSColin Finck * Integer library: 50c2c66affSColin Finck * 51c2c66affSColin Finck * [1] Handbook of Applied Cryptography - 1997 52c2c66affSColin Finck * Menezes, van Oorschot and Vanstone 53c2c66affSColin Finck * 54c2c66affSColin Finck * [2] Multi-Precision Math 55c2c66affSColin Finck * Tom St Denis 56c2c66affSColin Finck * https://github.com/libtom/libtommath/blob/develop/tommath.pdf 57c2c66affSColin Finck * 58c2c66affSColin Finck * [3] GNU Multi-Precision Arithmetic Library 59c2c66affSColin Finck * https://gmplib.org/manual/index.html 60c2c66affSColin Finck * 61c2c66affSColin Finck */ 62c2c66affSColin Finck 63c2c66affSColin Finck #if !defined(MBEDTLS_CONFIG_FILE) 64c2c66affSColin Finck #include "mbedtls/config.h" 65c2c66affSColin Finck #else 66c2c66affSColin Finck #include MBEDTLS_CONFIG_FILE 67c2c66affSColin Finck #endif 68c2c66affSColin Finck 69c2c66affSColin Finck #if defined(MBEDTLS_BIGNUM_C) 70c2c66affSColin Finck 71c2c66affSColin Finck #include "mbedtls/bignum.h" 72c2c66affSColin Finck #include "mbedtls/bn_mul.h" 73*cbda039fSThomas Faber #include "mbedtls/platform_util.h" 74c2c66affSColin Finck 75c2c66affSColin Finck #include <string.h> 76c2c66affSColin Finck 77c2c66affSColin Finck #if defined(MBEDTLS_PLATFORM_C) 78c2c66affSColin Finck #include "mbedtls/platform.h" 79c2c66affSColin Finck #else 80c2c66affSColin Finck #include <stdio.h> 81c2c66affSColin Finck #include <stdlib.h> 82c2c66affSColin Finck #define mbedtls_printf printf 83c2c66affSColin Finck #define mbedtls_calloc calloc 84c2c66affSColin Finck #define mbedtls_free free 85c2c66affSColin Finck #endif 86c2c66affSColin Finck 87*cbda039fSThomas Faber #define MPI_VALIDATE_RET( cond ) \ 88*cbda039fSThomas Faber MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) 89*cbda039fSThomas Faber #define MPI_VALIDATE( cond ) \ 90*cbda039fSThomas Faber MBEDTLS_INTERNAL_VALIDATE( cond ) 91d9e6c9b5SThomas Faber 92c2c66affSColin Finck #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ 93c2c66affSColin Finck #define biL (ciL << 3) /* bits in limb */ 94c2c66affSColin Finck #define biH (ciL << 2) /* half limb size */ 95c2c66affSColin Finck 96c2c66affSColin Finck #define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ 97c2c66affSColin Finck 98c2c66affSColin Finck /* 99c2c66affSColin Finck * Convert between bits/chars and number of limbs 100c2c66affSColin Finck * Divide first in order to avoid potential overflows 101c2c66affSColin Finck */ 102c2c66affSColin Finck #define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) 103c2c66affSColin Finck #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) 104c2c66affSColin Finck 105*cbda039fSThomas Faber /* Implementation that should never be optimized out by the compiler */ 106*cbda039fSThomas Faber static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) 107*cbda039fSThomas Faber { 108*cbda039fSThomas Faber mbedtls_platform_zeroize( v, ciL * n ); 109*cbda039fSThomas Faber } 110*cbda039fSThomas Faber 111c2c66affSColin Finck /* 112c2c66affSColin Finck * Initialize one MPI 113c2c66affSColin Finck */ 114c2c66affSColin Finck void mbedtls_mpi_init( mbedtls_mpi *X ) 115c2c66affSColin Finck { 116*cbda039fSThomas Faber MPI_VALIDATE( X != NULL ); 117c2c66affSColin Finck 118c2c66affSColin Finck X->s = 1; 119c2c66affSColin Finck X->n = 0; 120c2c66affSColin Finck X->p = NULL; 121c2c66affSColin Finck } 122c2c66affSColin Finck 123c2c66affSColin Finck /* 124c2c66affSColin Finck * Unallocate one MPI 125c2c66affSColin Finck */ 126c2c66affSColin Finck void mbedtls_mpi_free( mbedtls_mpi *X ) 127c2c66affSColin Finck { 128c2c66affSColin Finck if( X == NULL ) 129c2c66affSColin Finck return; 130c2c66affSColin Finck 131c2c66affSColin Finck if( X->p != NULL ) 132c2c66affSColin Finck { 133c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n ); 134c2c66affSColin Finck mbedtls_free( X->p ); 135c2c66affSColin Finck } 136c2c66affSColin Finck 137c2c66affSColin Finck X->s = 1; 138c2c66affSColin Finck X->n = 0; 139c2c66affSColin Finck X->p = NULL; 140c2c66affSColin Finck } 141c2c66affSColin Finck 142c2c66affSColin Finck /* 143c2c66affSColin Finck * Enlarge to the specified number of limbs 144c2c66affSColin Finck */ 145c2c66affSColin Finck int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) 146c2c66affSColin Finck { 147c2c66affSColin Finck mbedtls_mpi_uint *p; 148*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 149c2c66affSColin Finck 150c2c66affSColin Finck if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) 151c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 152c2c66affSColin Finck 153c2c66affSColin Finck if( X->n < nblimbs ) 154c2c66affSColin Finck { 155c2c66affSColin Finck if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) 156c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 157c2c66affSColin Finck 158c2c66affSColin Finck if( X->p != NULL ) 159c2c66affSColin Finck { 160c2c66affSColin Finck memcpy( p, X->p, X->n * ciL ); 161c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n ); 162c2c66affSColin Finck mbedtls_free( X->p ); 163c2c66affSColin Finck } 164c2c66affSColin Finck 165c2c66affSColin Finck X->n = nblimbs; 166c2c66affSColin Finck X->p = p; 167c2c66affSColin Finck } 168c2c66affSColin Finck 169c2c66affSColin Finck return( 0 ); 170c2c66affSColin Finck } 171c2c66affSColin Finck 172c2c66affSColin Finck /* 173c2c66affSColin Finck * Resize down as much as possible, 174c2c66affSColin Finck * while keeping at least the specified number of limbs 175c2c66affSColin Finck */ 176c2c66affSColin Finck int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) 177c2c66affSColin Finck { 178c2c66affSColin Finck mbedtls_mpi_uint *p; 179c2c66affSColin Finck size_t i; 180*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 181*cbda039fSThomas Faber 182*cbda039fSThomas Faber if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) 183*cbda039fSThomas Faber return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 184c2c66affSColin Finck 1851b00a1f5SThomas Faber /* Actually resize up if there are currently fewer than nblimbs limbs. */ 186c2c66affSColin Finck if( X->n <= nblimbs ) 187c2c66affSColin Finck return( mbedtls_mpi_grow( X, nblimbs ) ); 1881b00a1f5SThomas Faber /* After this point, then X->n > nblimbs and in particular X->n > 0. */ 189c2c66affSColin Finck 190c2c66affSColin Finck for( i = X->n - 1; i > 0; i-- ) 191c2c66affSColin Finck if( X->p[i] != 0 ) 192c2c66affSColin Finck break; 193c2c66affSColin Finck i++; 194c2c66affSColin Finck 195c2c66affSColin Finck if( i < nblimbs ) 196c2c66affSColin Finck i = nblimbs; 197c2c66affSColin Finck 198c2c66affSColin Finck if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) 199c2c66affSColin Finck return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); 200c2c66affSColin Finck 201c2c66affSColin Finck if( X->p != NULL ) 202c2c66affSColin Finck { 203c2c66affSColin Finck memcpy( p, X->p, i * ciL ); 204c2c66affSColin Finck mbedtls_mpi_zeroize( X->p, X->n ); 205c2c66affSColin Finck mbedtls_free( X->p ); 206c2c66affSColin Finck } 207c2c66affSColin Finck 208c2c66affSColin Finck X->n = i; 209c2c66affSColin Finck X->p = p; 210c2c66affSColin Finck 211c2c66affSColin Finck return( 0 ); 212c2c66affSColin Finck } 213c2c66affSColin Finck 214c2c66affSColin Finck /* 215c2c66affSColin Finck * Copy the contents of Y into X 216c2c66affSColin Finck */ 217c2c66affSColin Finck int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) 218c2c66affSColin Finck { 219*cbda039fSThomas Faber int ret = 0; 220c2c66affSColin Finck size_t i; 221*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 222*cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL ); 223c2c66affSColin Finck 224c2c66affSColin Finck if( X == Y ) 225c2c66affSColin Finck return( 0 ); 226c2c66affSColin Finck 2271b00a1f5SThomas Faber if( Y->n == 0 ) 228c2c66affSColin Finck { 229c2c66affSColin Finck mbedtls_mpi_free( X ); 230c2c66affSColin Finck return( 0 ); 231c2c66affSColin Finck } 232c2c66affSColin Finck 233c2c66affSColin Finck for( i = Y->n - 1; i > 0; i-- ) 234c2c66affSColin Finck if( Y->p[i] != 0 ) 235c2c66affSColin Finck break; 236c2c66affSColin Finck i++; 237c2c66affSColin Finck 238c2c66affSColin Finck X->s = Y->s; 239c2c66affSColin Finck 240*cbda039fSThomas Faber if( X->n < i ) 241*cbda039fSThomas Faber { 242c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); 243*cbda039fSThomas Faber } 244*cbda039fSThomas Faber else 245*cbda039fSThomas Faber { 246*cbda039fSThomas Faber memset( X->p + i, 0, ( X->n - i ) * ciL ); 247*cbda039fSThomas Faber } 248c2c66affSColin Finck 249c2c66affSColin Finck memcpy( X->p, Y->p, i * ciL ); 250c2c66affSColin Finck 251c2c66affSColin Finck cleanup: 252c2c66affSColin Finck 253c2c66affSColin Finck return( ret ); 254c2c66affSColin Finck } 255c2c66affSColin Finck 256c2c66affSColin Finck /* 257c2c66affSColin Finck * Swap the contents of X and Y 258c2c66affSColin Finck */ 259c2c66affSColin Finck void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) 260c2c66affSColin Finck { 261c2c66affSColin Finck mbedtls_mpi T; 262*cbda039fSThomas Faber MPI_VALIDATE( X != NULL ); 263*cbda039fSThomas Faber MPI_VALIDATE( Y != NULL ); 264c2c66affSColin Finck 265c2c66affSColin Finck memcpy( &T, X, sizeof( mbedtls_mpi ) ); 266c2c66affSColin Finck memcpy( X, Y, sizeof( mbedtls_mpi ) ); 267c2c66affSColin Finck memcpy( Y, &T, sizeof( mbedtls_mpi ) ); 268c2c66affSColin Finck } 269c2c66affSColin Finck 270c2c66affSColin Finck /* 271292f67afSThomas Faber * Conditionally assign dest = src, without leaking information 272292f67afSThomas Faber * about whether the assignment was made or not. 273292f67afSThomas Faber * dest and src must be arrays of limbs of size n. 274292f67afSThomas Faber * assign must be 0 or 1. 275292f67afSThomas Faber */ 276292f67afSThomas Faber static void mpi_safe_cond_assign( size_t n, 277292f67afSThomas Faber mbedtls_mpi_uint *dest, 278292f67afSThomas Faber const mbedtls_mpi_uint *src, 279292f67afSThomas Faber unsigned char assign ) 280292f67afSThomas Faber { 281292f67afSThomas Faber size_t i; 282292f67afSThomas Faber for( i = 0; i < n; i++ ) 283292f67afSThomas Faber dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign; 284292f67afSThomas Faber } 285292f67afSThomas Faber 286292f67afSThomas Faber /* 287c2c66affSColin Finck * Conditionally assign X = Y, without leaking information 288c2c66affSColin Finck * about whether the assignment was made or not. 289c2c66affSColin Finck * (Leaking information about the respective sizes of X and Y is ok however.) 290c2c66affSColin Finck */ 291c2c66affSColin Finck int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) 292c2c66affSColin Finck { 293c2c66affSColin Finck int ret = 0; 294c2c66affSColin Finck size_t i; 295*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 296*cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL ); 297c2c66affSColin Finck 298c2c66affSColin Finck /* make sure assign is 0 or 1 in a time-constant manner */ 299c2c66affSColin Finck assign = (assign | (unsigned char)-assign) >> 7; 300c2c66affSColin Finck 301c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); 302c2c66affSColin Finck 303c2c66affSColin Finck X->s = X->s * ( 1 - assign ) + Y->s * assign; 304c2c66affSColin Finck 305292f67afSThomas Faber mpi_safe_cond_assign( Y->n, X->p, Y->p, assign ); 306c2c66affSColin Finck 307292f67afSThomas Faber for( i = Y->n; i < X->n; i++ ) 308c2c66affSColin Finck X->p[i] *= ( 1 - assign ); 309c2c66affSColin Finck 310c2c66affSColin Finck cleanup: 311c2c66affSColin Finck return( ret ); 312c2c66affSColin Finck } 313c2c66affSColin Finck 314c2c66affSColin Finck /* 315c2c66affSColin Finck * Conditionally swap X and Y, without leaking information 316c2c66affSColin Finck * about whether the swap was made or not. 317c2c66affSColin Finck * Here it is not ok to simply swap the pointers, which whould lead to 318c2c66affSColin Finck * different memory access patterns when X and Y are used afterwards. 319c2c66affSColin Finck */ 320c2c66affSColin Finck int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) 321c2c66affSColin Finck { 322c2c66affSColin Finck int ret, s; 323c2c66affSColin Finck size_t i; 324c2c66affSColin Finck mbedtls_mpi_uint tmp; 325*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 326*cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL ); 327c2c66affSColin Finck 328c2c66affSColin Finck if( X == Y ) 329c2c66affSColin Finck return( 0 ); 330c2c66affSColin Finck 331c2c66affSColin Finck /* make sure swap is 0 or 1 in a time-constant manner */ 332c2c66affSColin Finck swap = (swap | (unsigned char)-swap) >> 7; 333c2c66affSColin Finck 334c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); 335c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); 336c2c66affSColin Finck 337c2c66affSColin Finck s = X->s; 338c2c66affSColin Finck X->s = X->s * ( 1 - swap ) + Y->s * swap; 339c2c66affSColin Finck Y->s = Y->s * ( 1 - swap ) + s * swap; 340c2c66affSColin Finck 341c2c66affSColin Finck 342c2c66affSColin Finck for( i = 0; i < X->n; i++ ) 343c2c66affSColin Finck { 344c2c66affSColin Finck tmp = X->p[i]; 345c2c66affSColin Finck X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; 346c2c66affSColin Finck Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; 347c2c66affSColin Finck } 348c2c66affSColin Finck 349c2c66affSColin Finck cleanup: 350c2c66affSColin Finck return( ret ); 351c2c66affSColin Finck } 352c2c66affSColin Finck 353c2c66affSColin Finck /* 354c2c66affSColin Finck * Set value from integer 355c2c66affSColin Finck */ 356c2c66affSColin Finck int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) 357c2c66affSColin Finck { 358c2c66affSColin Finck int ret; 359*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 360c2c66affSColin Finck 361c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); 362c2c66affSColin Finck memset( X->p, 0, X->n * ciL ); 363c2c66affSColin Finck 364c2c66affSColin Finck X->p[0] = ( z < 0 ) ? -z : z; 365c2c66affSColin Finck X->s = ( z < 0 ) ? -1 : 1; 366c2c66affSColin Finck 367c2c66affSColin Finck cleanup: 368c2c66affSColin Finck 369c2c66affSColin Finck return( ret ); 370c2c66affSColin Finck } 371c2c66affSColin Finck 372c2c66affSColin Finck /* 373c2c66affSColin Finck * Get a specific bit 374c2c66affSColin Finck */ 375c2c66affSColin Finck int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) 376c2c66affSColin Finck { 377*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 378*cbda039fSThomas Faber 379c2c66affSColin Finck if( X->n * biL <= pos ) 380c2c66affSColin Finck return( 0 ); 381c2c66affSColin Finck 382c2c66affSColin Finck return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); 383c2c66affSColin Finck } 384c2c66affSColin Finck 3850ba5bc40SThomas Faber /* Get a specific byte, without range checks. */ 3860ba5bc40SThomas Faber #define GET_BYTE( X, i ) \ 3870ba5bc40SThomas Faber ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) 3880ba5bc40SThomas Faber 389c2c66affSColin Finck /* 390c2c66affSColin Finck * Set a bit to a specific value of 0 or 1 391c2c66affSColin Finck */ 392c2c66affSColin Finck int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) 393c2c66affSColin Finck { 394c2c66affSColin Finck int ret = 0; 395c2c66affSColin Finck size_t off = pos / biL; 396c2c66affSColin Finck size_t idx = pos % biL; 397*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 398c2c66affSColin Finck 399c2c66affSColin Finck if( val != 0 && val != 1 ) 400c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 401c2c66affSColin Finck 402c2c66affSColin Finck if( X->n * biL <= pos ) 403c2c66affSColin Finck { 404c2c66affSColin Finck if( val == 0 ) 405c2c66affSColin Finck return( 0 ); 406c2c66affSColin Finck 407c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); 408c2c66affSColin Finck } 409c2c66affSColin Finck 410c2c66affSColin Finck X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); 411c2c66affSColin Finck X->p[off] |= (mbedtls_mpi_uint) val << idx; 412c2c66affSColin Finck 413c2c66affSColin Finck cleanup: 414c2c66affSColin Finck 415c2c66affSColin Finck return( ret ); 416c2c66affSColin Finck } 417c2c66affSColin Finck 418c2c66affSColin Finck /* 419c2c66affSColin Finck * Return the number of less significant zero-bits 420c2c66affSColin Finck */ 421c2c66affSColin Finck size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) 422c2c66affSColin Finck { 423c2c66affSColin Finck size_t i, j, count = 0; 424*cbda039fSThomas Faber MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); 425c2c66affSColin Finck 426c2c66affSColin Finck for( i = 0; i < X->n; i++ ) 427c2c66affSColin Finck for( j = 0; j < biL; j++, count++ ) 428c2c66affSColin Finck if( ( ( X->p[i] >> j ) & 1 ) != 0 ) 429c2c66affSColin Finck return( count ); 430c2c66affSColin Finck 431c2c66affSColin Finck return( 0 ); 432c2c66affSColin Finck } 433c2c66affSColin Finck 434c2c66affSColin Finck /* 435c2c66affSColin Finck * Count leading zero bits in a given integer 436c2c66affSColin Finck */ 437c2c66affSColin Finck static size_t mbedtls_clz( const mbedtls_mpi_uint x ) 438c2c66affSColin Finck { 439c2c66affSColin Finck size_t j; 440c2c66affSColin Finck mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); 441c2c66affSColin Finck 442c2c66affSColin Finck for( j = 0; j < biL; j++ ) 443c2c66affSColin Finck { 444c2c66affSColin Finck if( x & mask ) break; 445c2c66affSColin Finck 446c2c66affSColin Finck mask >>= 1; 447c2c66affSColin Finck } 448c2c66affSColin Finck 449c2c66affSColin Finck return j; 450c2c66affSColin Finck } 451c2c66affSColin Finck 452c2c66affSColin Finck /* 453c2c66affSColin Finck * Return the number of bits 454c2c66affSColin Finck */ 455c2c66affSColin Finck size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) 456c2c66affSColin Finck { 457c2c66affSColin Finck size_t i, j; 458c2c66affSColin Finck 459c2c66affSColin Finck if( X->n == 0 ) 460c2c66affSColin Finck return( 0 ); 461c2c66affSColin Finck 462c2c66affSColin Finck for( i = X->n - 1; i > 0; i-- ) 463c2c66affSColin Finck if( X->p[i] != 0 ) 464c2c66affSColin Finck break; 465c2c66affSColin Finck 466c2c66affSColin Finck j = biL - mbedtls_clz( X->p[i] ); 467c2c66affSColin Finck 468c2c66affSColin Finck return( ( i * biL ) + j ); 469c2c66affSColin Finck } 470c2c66affSColin Finck 471c2c66affSColin Finck /* 472c2c66affSColin Finck * Return the total size in bytes 473c2c66affSColin Finck */ 474c2c66affSColin Finck size_t mbedtls_mpi_size( const mbedtls_mpi *X ) 475c2c66affSColin Finck { 476c2c66affSColin Finck return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); 477c2c66affSColin Finck } 478c2c66affSColin Finck 479c2c66affSColin Finck /* 480c2c66affSColin Finck * Convert an ASCII character to digit value 481c2c66affSColin Finck */ 482c2c66affSColin Finck static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) 483c2c66affSColin Finck { 484c2c66affSColin Finck *d = 255; 485c2c66affSColin Finck 486c2c66affSColin Finck if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; 487c2c66affSColin Finck if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; 488c2c66affSColin Finck if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; 489c2c66affSColin Finck 490c2c66affSColin Finck if( *d >= (mbedtls_mpi_uint) radix ) 491c2c66affSColin Finck return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); 492c2c66affSColin Finck 493c2c66affSColin Finck return( 0 ); 494c2c66affSColin Finck } 495c2c66affSColin Finck 496c2c66affSColin Finck /* 497c2c66affSColin Finck * Import from an ASCII string 498c2c66affSColin Finck */ 499c2c66affSColin Finck int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) 500c2c66affSColin Finck { 501c2c66affSColin Finck int ret; 502c2c66affSColin Finck size_t i, j, slen, n; 503c2c66affSColin Finck mbedtls_mpi_uint d; 504c2c66affSColin Finck mbedtls_mpi T; 505*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 506*cbda039fSThomas Faber MPI_VALIDATE_RET( s != NULL ); 507c2c66affSColin Finck 508c2c66affSColin Finck if( radix < 2 || radix > 16 ) 509c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 510c2c66affSColin Finck 511c2c66affSColin Finck mbedtls_mpi_init( &T ); 512c2c66affSColin Finck 513c2c66affSColin Finck slen = strlen( s ); 514c2c66affSColin Finck 515c2c66affSColin Finck if( radix == 16 ) 516c2c66affSColin Finck { 517c2c66affSColin Finck if( slen > MPI_SIZE_T_MAX >> 2 ) 518c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 519c2c66affSColin Finck 520c2c66affSColin Finck n = BITS_TO_LIMBS( slen << 2 ); 521c2c66affSColin Finck 522c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); 523c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 524c2c66affSColin Finck 525c2c66affSColin Finck for( i = slen, j = 0; i > 0; i--, j++ ) 526c2c66affSColin Finck { 527c2c66affSColin Finck if( i == 1 && s[i - 1] == '-' ) 528c2c66affSColin Finck { 529c2c66affSColin Finck X->s = -1; 530c2c66affSColin Finck break; 531c2c66affSColin Finck } 532c2c66affSColin Finck 533c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); 534c2c66affSColin Finck X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); 535c2c66affSColin Finck } 536c2c66affSColin Finck } 537c2c66affSColin Finck else 538c2c66affSColin Finck { 539c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 540c2c66affSColin Finck 541c2c66affSColin Finck for( i = 0; i < slen; i++ ) 542c2c66affSColin Finck { 543c2c66affSColin Finck if( i == 0 && s[i] == '-' ) 544c2c66affSColin Finck { 545c2c66affSColin Finck X->s = -1; 546c2c66affSColin Finck continue; 547c2c66affSColin Finck } 548c2c66affSColin Finck 549c2c66affSColin Finck MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); 550c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); 551c2c66affSColin Finck 552c2c66affSColin Finck if( X->s == 1 ) 553c2c66affSColin Finck { 554c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); 555c2c66affSColin Finck } 556c2c66affSColin Finck else 557c2c66affSColin Finck { 558c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); 559c2c66affSColin Finck } 560c2c66affSColin Finck } 561c2c66affSColin Finck } 562c2c66affSColin Finck 563c2c66affSColin Finck cleanup: 564c2c66affSColin Finck 565c2c66affSColin Finck mbedtls_mpi_free( &T ); 566c2c66affSColin Finck 567c2c66affSColin Finck return( ret ); 568c2c66affSColin Finck } 569c2c66affSColin Finck 570c2c66affSColin Finck /* 571ca86ee9cSThomas Faber * Helper to write the digits high-order first. 572c2c66affSColin Finck */ 573ca86ee9cSThomas Faber static int mpi_write_hlp( mbedtls_mpi *X, int radix, 574ca86ee9cSThomas Faber char **p, const size_t buflen ) 575c2c66affSColin Finck { 576c2c66affSColin Finck int ret; 577c2c66affSColin Finck mbedtls_mpi_uint r; 578ca86ee9cSThomas Faber size_t length = 0; 579ca86ee9cSThomas Faber char *p_end = *p + buflen; 580c2c66affSColin Finck 581ca86ee9cSThomas Faber do 582ca86ee9cSThomas Faber { 583ca86ee9cSThomas Faber if( length >= buflen ) 584ca86ee9cSThomas Faber { 585ca86ee9cSThomas Faber return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 586ca86ee9cSThomas Faber } 587c2c66affSColin Finck 588c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); 589c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); 590ca86ee9cSThomas Faber /* 591ca86ee9cSThomas Faber * Write the residue in the current position, as an ASCII character. 592ca86ee9cSThomas Faber */ 593ca86ee9cSThomas Faber if( r < 0xA ) 594ca86ee9cSThomas Faber *(--p_end) = (char)( '0' + r ); 595c2c66affSColin Finck else 596ca86ee9cSThomas Faber *(--p_end) = (char)( 'A' + ( r - 0xA ) ); 597ca86ee9cSThomas Faber 598ca86ee9cSThomas Faber length++; 599ca86ee9cSThomas Faber } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); 600ca86ee9cSThomas Faber 601ca86ee9cSThomas Faber memmove( *p, p_end, length ); 602ca86ee9cSThomas Faber *p += length; 603c2c66affSColin Finck 604c2c66affSColin Finck cleanup: 605c2c66affSColin Finck 606c2c66affSColin Finck return( ret ); 607c2c66affSColin Finck } 608c2c66affSColin Finck 609c2c66affSColin Finck /* 610c2c66affSColin Finck * Export into an ASCII string 611c2c66affSColin Finck */ 612c2c66affSColin Finck int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, 613c2c66affSColin Finck char *buf, size_t buflen, size_t *olen ) 614c2c66affSColin Finck { 615c2c66affSColin Finck int ret = 0; 616c2c66affSColin Finck size_t n; 617c2c66affSColin Finck char *p; 618c2c66affSColin Finck mbedtls_mpi T; 619*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 620*cbda039fSThomas Faber MPI_VALIDATE_RET( olen != NULL ); 621*cbda039fSThomas Faber MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); 622c2c66affSColin Finck 623c2c66affSColin Finck if( radix < 2 || radix > 16 ) 624c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 625c2c66affSColin Finck 626430656f0SThomas Faber n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ 627430656f0SThomas Faber if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present 628430656f0SThomas Faber * `n`. If radix > 4, this might be a strict 629430656f0SThomas Faber * overapproximation of the number of 630430656f0SThomas Faber * radix-adic digits needed to present `n`. */ 631430656f0SThomas Faber if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to 632430656f0SThomas Faber * present `n`. */ 633430656f0SThomas Faber 634430656f0SThomas Faber n += 1; /* Terminating null byte */ 635430656f0SThomas Faber n += 1; /* Compensate for the divisions above, which round down `n` 636430656f0SThomas Faber * in case it's not even. */ 637430656f0SThomas Faber n += 1; /* Potential '-'-sign. */ 638430656f0SThomas Faber n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, 639430656f0SThomas Faber * which always uses an even number of hex-digits. */ 640c2c66affSColin Finck 641c2c66affSColin Finck if( buflen < n ) 642c2c66affSColin Finck { 643c2c66affSColin Finck *olen = n; 644c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 645c2c66affSColin Finck } 646c2c66affSColin Finck 647c2c66affSColin Finck p = buf; 648c2c66affSColin Finck mbedtls_mpi_init( &T ); 649c2c66affSColin Finck 650c2c66affSColin Finck if( X->s == -1 ) 651430656f0SThomas Faber { 652c2c66affSColin Finck *p++ = '-'; 653430656f0SThomas Faber buflen--; 654430656f0SThomas Faber } 655c2c66affSColin Finck 656c2c66affSColin Finck if( radix == 16 ) 657c2c66affSColin Finck { 658c2c66affSColin Finck int c; 659c2c66affSColin Finck size_t i, j, k; 660c2c66affSColin Finck 661c2c66affSColin Finck for( i = X->n, k = 0; i > 0; i-- ) 662c2c66affSColin Finck { 663c2c66affSColin Finck for( j = ciL; j > 0; j-- ) 664c2c66affSColin Finck { 665c2c66affSColin Finck c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; 666c2c66affSColin Finck 667c2c66affSColin Finck if( c == 0 && k == 0 && ( i + j ) != 2 ) 668c2c66affSColin Finck continue; 669c2c66affSColin Finck 670c2c66affSColin Finck *(p++) = "0123456789ABCDEF" [c / 16]; 671c2c66affSColin Finck *(p++) = "0123456789ABCDEF" [c % 16]; 672c2c66affSColin Finck k = 1; 673c2c66affSColin Finck } 674c2c66affSColin Finck } 675c2c66affSColin Finck } 676c2c66affSColin Finck else 677c2c66affSColin Finck { 678c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); 679c2c66affSColin Finck 680c2c66affSColin Finck if( T.s == -1 ) 681c2c66affSColin Finck T.s = 1; 682c2c66affSColin Finck 683ca86ee9cSThomas Faber MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); 684c2c66affSColin Finck } 685c2c66affSColin Finck 686c2c66affSColin Finck *p++ = '\0'; 687c2c66affSColin Finck *olen = p - buf; 688c2c66affSColin Finck 689c2c66affSColin Finck cleanup: 690c2c66affSColin Finck 691c2c66affSColin Finck mbedtls_mpi_free( &T ); 692c2c66affSColin Finck 693c2c66affSColin Finck return( ret ); 694c2c66affSColin Finck } 695c2c66affSColin Finck 696c2c66affSColin Finck #if defined(MBEDTLS_FS_IO) 697c2c66affSColin Finck /* 698c2c66affSColin Finck * Read X from an opened file 699c2c66affSColin Finck */ 700c2c66affSColin Finck int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) 701c2c66affSColin Finck { 702c2c66affSColin Finck mbedtls_mpi_uint d; 703c2c66affSColin Finck size_t slen; 704c2c66affSColin Finck char *p; 705c2c66affSColin Finck /* 706c2c66affSColin Finck * Buffer should have space for (short) label and decimal formatted MPI, 707c2c66affSColin Finck * newline characters and '\0' 708c2c66affSColin Finck */ 709c2c66affSColin Finck char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; 710c2c66affSColin Finck 711*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 712*cbda039fSThomas Faber MPI_VALIDATE_RET( fin != NULL ); 713*cbda039fSThomas Faber 714*cbda039fSThomas Faber if( radix < 2 || radix > 16 ) 715*cbda039fSThomas Faber return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 716*cbda039fSThomas Faber 717c2c66affSColin Finck memset( s, 0, sizeof( s ) ); 718c2c66affSColin Finck if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) 719c2c66affSColin Finck return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); 720c2c66affSColin Finck 721c2c66affSColin Finck slen = strlen( s ); 722c2c66affSColin Finck if( slen == sizeof( s ) - 2 ) 723c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 724c2c66affSColin Finck 725c2c66affSColin Finck if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } 726c2c66affSColin Finck if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } 727c2c66affSColin Finck 728c2c66affSColin Finck p = s + slen; 729c2c66affSColin Finck while( p-- > s ) 730c2c66affSColin Finck if( mpi_get_digit( &d, radix, *p ) != 0 ) 731c2c66affSColin Finck break; 732c2c66affSColin Finck 733c2c66affSColin Finck return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); 734c2c66affSColin Finck } 735c2c66affSColin Finck 736c2c66affSColin Finck /* 737c2c66affSColin Finck * Write X into an opened file (or stdout if fout == NULL) 738c2c66affSColin Finck */ 739c2c66affSColin Finck int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) 740c2c66affSColin Finck { 741c2c66affSColin Finck int ret; 742c2c66affSColin Finck size_t n, slen, plen; 743c2c66affSColin Finck /* 744c2c66affSColin Finck * Buffer should have space for (short) label and decimal formatted MPI, 745c2c66affSColin Finck * newline characters and '\0' 746c2c66affSColin Finck */ 747c2c66affSColin Finck char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; 748*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 749*cbda039fSThomas Faber 750*cbda039fSThomas Faber if( radix < 2 || radix > 16 ) 751*cbda039fSThomas Faber return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 752c2c66affSColin Finck 753c2c66affSColin Finck memset( s, 0, sizeof( s ) ); 754c2c66affSColin Finck 755c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); 756c2c66affSColin Finck 757c2c66affSColin Finck if( p == NULL ) p = ""; 758c2c66affSColin Finck 759c2c66affSColin Finck plen = strlen( p ); 760c2c66affSColin Finck slen = strlen( s ); 761c2c66affSColin Finck s[slen++] = '\r'; 762c2c66affSColin Finck s[slen++] = '\n'; 763c2c66affSColin Finck 764c2c66affSColin Finck if( fout != NULL ) 765c2c66affSColin Finck { 766c2c66affSColin Finck if( fwrite( p, 1, plen, fout ) != plen || 767c2c66affSColin Finck fwrite( s, 1, slen, fout ) != slen ) 768c2c66affSColin Finck return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); 769c2c66affSColin Finck } 770c2c66affSColin Finck else 771c2c66affSColin Finck mbedtls_printf( "%s%s", p, s ); 772c2c66affSColin Finck 773c2c66affSColin Finck cleanup: 774c2c66affSColin Finck 775c2c66affSColin Finck return( ret ); 776c2c66affSColin Finck } 777c2c66affSColin Finck #endif /* MBEDTLS_FS_IO */ 778c2c66affSColin Finck 779*cbda039fSThomas Faber 780*cbda039fSThomas Faber /* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint 781*cbda039fSThomas Faber * into the storage form used by mbedtls_mpi. */ 782*cbda039fSThomas Faber 783*cbda039fSThomas Faber static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) 784*cbda039fSThomas Faber { 785*cbda039fSThomas Faber uint8_t i; 786*cbda039fSThomas Faber unsigned char *x_ptr; 787*cbda039fSThomas Faber mbedtls_mpi_uint tmp = 0; 788*cbda039fSThomas Faber 789*cbda039fSThomas Faber for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ ) 790*cbda039fSThomas Faber { 791*cbda039fSThomas Faber tmp <<= CHAR_BIT; 792*cbda039fSThomas Faber tmp |= (mbedtls_mpi_uint) *x_ptr; 793*cbda039fSThomas Faber } 794*cbda039fSThomas Faber 795*cbda039fSThomas Faber return( tmp ); 796*cbda039fSThomas Faber } 797*cbda039fSThomas Faber 798*cbda039fSThomas Faber static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) 799*cbda039fSThomas Faber { 800*cbda039fSThomas Faber #if defined(__BYTE_ORDER__) 801*cbda039fSThomas Faber 802*cbda039fSThomas Faber /* Nothing to do on bigendian systems. */ 803*cbda039fSThomas Faber #if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) 804*cbda039fSThomas Faber return( x ); 805*cbda039fSThomas Faber #endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ 806*cbda039fSThomas Faber 807*cbda039fSThomas Faber #if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) 808*cbda039fSThomas Faber 809*cbda039fSThomas Faber /* For GCC and Clang, have builtins for byte swapping. */ 810*cbda039fSThomas Faber #if defined(__GNUC__) && defined(__GNUC_PREREQ) 811*cbda039fSThomas Faber #if __GNUC_PREREQ(4,3) 812*cbda039fSThomas Faber #define have_bswap 813*cbda039fSThomas Faber #endif 814*cbda039fSThomas Faber #endif 815*cbda039fSThomas Faber 816*cbda039fSThomas Faber #if defined(__clang__) && defined(__has_builtin) 817*cbda039fSThomas Faber #if __has_builtin(__builtin_bswap32) && \ 818*cbda039fSThomas Faber __has_builtin(__builtin_bswap64) 819*cbda039fSThomas Faber #define have_bswap 820*cbda039fSThomas Faber #endif 821*cbda039fSThomas Faber #endif 822*cbda039fSThomas Faber 823*cbda039fSThomas Faber #if defined(have_bswap) 824*cbda039fSThomas Faber /* The compiler is hopefully able to statically evaluate this! */ 825*cbda039fSThomas Faber switch( sizeof(mbedtls_mpi_uint) ) 826*cbda039fSThomas Faber { 827*cbda039fSThomas Faber case 4: 828*cbda039fSThomas Faber return( __builtin_bswap32(x) ); 829*cbda039fSThomas Faber case 8: 830*cbda039fSThomas Faber return( __builtin_bswap64(x) ); 831*cbda039fSThomas Faber } 832*cbda039fSThomas Faber #endif 833*cbda039fSThomas Faber #endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ 834*cbda039fSThomas Faber #endif /* __BYTE_ORDER__ */ 835*cbda039fSThomas Faber 836*cbda039fSThomas Faber /* Fall back to C-based reordering if we don't know the byte order 837*cbda039fSThomas Faber * or we couldn't use a compiler-specific builtin. */ 838*cbda039fSThomas Faber return( mpi_uint_bigendian_to_host_c( x ) ); 839*cbda039fSThomas Faber } 840*cbda039fSThomas Faber 841*cbda039fSThomas Faber static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) 842*cbda039fSThomas Faber { 843*cbda039fSThomas Faber mbedtls_mpi_uint *cur_limb_left; 844*cbda039fSThomas Faber mbedtls_mpi_uint *cur_limb_right; 845*cbda039fSThomas Faber if( limbs == 0 ) 846*cbda039fSThomas Faber return; 847*cbda039fSThomas Faber 848*cbda039fSThomas Faber /* 849*cbda039fSThomas Faber * Traverse limbs and 850*cbda039fSThomas Faber * - adapt byte-order in each limb 851*cbda039fSThomas Faber * - swap the limbs themselves. 852*cbda039fSThomas Faber * For that, simultaneously traverse the limbs from left to right 853*cbda039fSThomas Faber * and from right to left, as long as the left index is not bigger 854*cbda039fSThomas Faber * than the right index (it's not a problem if limbs is odd and the 855*cbda039fSThomas Faber * indices coincide in the last iteration). 856*cbda039fSThomas Faber */ 857*cbda039fSThomas Faber for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); 858*cbda039fSThomas Faber cur_limb_left <= cur_limb_right; 859*cbda039fSThomas Faber cur_limb_left++, cur_limb_right-- ) 860*cbda039fSThomas Faber { 861*cbda039fSThomas Faber mbedtls_mpi_uint tmp; 862*cbda039fSThomas Faber /* Note that if cur_limb_left == cur_limb_right, 863*cbda039fSThomas Faber * this code effectively swaps the bytes only once. */ 864*cbda039fSThomas Faber tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); 865*cbda039fSThomas Faber *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); 866*cbda039fSThomas Faber *cur_limb_right = tmp; 867*cbda039fSThomas Faber } 868*cbda039fSThomas Faber } 869*cbda039fSThomas Faber 870c2c66affSColin Finck /* 871c2c66affSColin Finck * Import X from unsigned binary data, big endian 872c2c66affSColin Finck */ 873c2c66affSColin Finck int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) 874c2c66affSColin Finck { 875c2c66affSColin Finck int ret; 876d9e6c9b5SThomas Faber size_t const limbs = CHARS_TO_LIMBS( buflen ); 877*cbda039fSThomas Faber size_t const overhead = ( limbs * ciL ) - buflen; 878*cbda039fSThomas Faber unsigned char *Xp; 879*cbda039fSThomas Faber 880*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 881*cbda039fSThomas Faber MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); 882c2c66affSColin Finck 883d9e6c9b5SThomas Faber /* Ensure that target MPI has exactly the necessary number of limbs */ 884d9e6c9b5SThomas Faber if( X->n != limbs ) 885d9e6c9b5SThomas Faber { 886d9e6c9b5SThomas Faber mbedtls_mpi_free( X ); 887d9e6c9b5SThomas Faber mbedtls_mpi_init( X ); 888d9e6c9b5SThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); 889d9e6c9b5SThomas Faber } 890c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 891c2c66affSColin Finck 892*cbda039fSThomas Faber /* Avoid calling `memcpy` with NULL source argument, 893*cbda039fSThomas Faber * even if buflen is 0. */ 894*cbda039fSThomas Faber if( buf != NULL ) 895*cbda039fSThomas Faber { 896*cbda039fSThomas Faber Xp = (unsigned char*) X->p; 897*cbda039fSThomas Faber memcpy( Xp + overhead, buf, buflen ); 898*cbda039fSThomas Faber 899*cbda039fSThomas Faber mpi_bigendian_to_host( X->p, limbs ); 900*cbda039fSThomas Faber } 901c2c66affSColin Finck 902c2c66affSColin Finck cleanup: 903c2c66affSColin Finck 904c2c66affSColin Finck return( ret ); 905c2c66affSColin Finck } 906c2c66affSColin Finck 907c2c66affSColin Finck /* 908c2c66affSColin Finck * Export X into unsigned binary data, big endian 909c2c66affSColin Finck */ 9100ba5bc40SThomas Faber int mbedtls_mpi_write_binary( const mbedtls_mpi *X, 9110ba5bc40SThomas Faber unsigned char *buf, size_t buflen ) 912c2c66affSColin Finck { 913*cbda039fSThomas Faber size_t stored_bytes; 9140ba5bc40SThomas Faber size_t bytes_to_copy; 9150ba5bc40SThomas Faber unsigned char *p; 9160ba5bc40SThomas Faber size_t i; 917c2c66affSColin Finck 918*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 919*cbda039fSThomas Faber MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); 920*cbda039fSThomas Faber 921*cbda039fSThomas Faber stored_bytes = X->n * ciL; 922*cbda039fSThomas Faber 9230ba5bc40SThomas Faber if( stored_bytes < buflen ) 9240ba5bc40SThomas Faber { 9250ba5bc40SThomas Faber /* There is enough space in the output buffer. Write initial 9260ba5bc40SThomas Faber * null bytes and record the position at which to start 9270ba5bc40SThomas Faber * writing the significant bytes. In this case, the execution 9280ba5bc40SThomas Faber * trace of this function does not depend on the value of the 9290ba5bc40SThomas Faber * number. */ 9300ba5bc40SThomas Faber bytes_to_copy = stored_bytes; 9310ba5bc40SThomas Faber p = buf + buflen - stored_bytes; 9320ba5bc40SThomas Faber memset( buf, 0, buflen - stored_bytes ); 9330ba5bc40SThomas Faber } 9340ba5bc40SThomas Faber else 9350ba5bc40SThomas Faber { 9360ba5bc40SThomas Faber /* The output buffer is smaller than the allocated size of X. 9370ba5bc40SThomas Faber * However X may fit if its leading bytes are zero. */ 9380ba5bc40SThomas Faber bytes_to_copy = buflen; 9390ba5bc40SThomas Faber p = buf; 9400ba5bc40SThomas Faber for( i = bytes_to_copy; i < stored_bytes; i++ ) 9410ba5bc40SThomas Faber { 9420ba5bc40SThomas Faber if( GET_BYTE( X, i ) != 0 ) 943c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); 9440ba5bc40SThomas Faber } 9450ba5bc40SThomas Faber } 946c2c66affSColin Finck 9470ba5bc40SThomas Faber for( i = 0; i < bytes_to_copy; i++ ) 9480ba5bc40SThomas Faber p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); 949c2c66affSColin Finck 950c2c66affSColin Finck return( 0 ); 951c2c66affSColin Finck } 952c2c66affSColin Finck 953c2c66affSColin Finck /* 954c2c66affSColin Finck * Left-shift: X <<= count 955c2c66affSColin Finck */ 956c2c66affSColin Finck int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) 957c2c66affSColin Finck { 958c2c66affSColin Finck int ret; 959c2c66affSColin Finck size_t i, v0, t1; 960c2c66affSColin Finck mbedtls_mpi_uint r0 = 0, r1; 961*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 962c2c66affSColin Finck 963c2c66affSColin Finck v0 = count / (biL ); 964c2c66affSColin Finck t1 = count & (biL - 1); 965c2c66affSColin Finck 966c2c66affSColin Finck i = mbedtls_mpi_bitlen( X ) + count; 967c2c66affSColin Finck 968c2c66affSColin Finck if( X->n * biL < i ) 969c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); 970c2c66affSColin Finck 971c2c66affSColin Finck ret = 0; 972c2c66affSColin Finck 973c2c66affSColin Finck /* 974c2c66affSColin Finck * shift by count / limb_size 975c2c66affSColin Finck */ 976c2c66affSColin Finck if( v0 > 0 ) 977c2c66affSColin Finck { 978c2c66affSColin Finck for( i = X->n; i > v0; i-- ) 979c2c66affSColin Finck X->p[i - 1] = X->p[i - v0 - 1]; 980c2c66affSColin Finck 981c2c66affSColin Finck for( ; i > 0; i-- ) 982c2c66affSColin Finck X->p[i - 1] = 0; 983c2c66affSColin Finck } 984c2c66affSColin Finck 985c2c66affSColin Finck /* 986c2c66affSColin Finck * shift by count % limb_size 987c2c66affSColin Finck */ 988c2c66affSColin Finck if( t1 > 0 ) 989c2c66affSColin Finck { 990c2c66affSColin Finck for( i = v0; i < X->n; i++ ) 991c2c66affSColin Finck { 992c2c66affSColin Finck r1 = X->p[i] >> (biL - t1); 993c2c66affSColin Finck X->p[i] <<= t1; 994c2c66affSColin Finck X->p[i] |= r0; 995c2c66affSColin Finck r0 = r1; 996c2c66affSColin Finck } 997c2c66affSColin Finck } 998c2c66affSColin Finck 999c2c66affSColin Finck cleanup: 1000c2c66affSColin Finck 1001c2c66affSColin Finck return( ret ); 1002c2c66affSColin Finck } 1003c2c66affSColin Finck 1004c2c66affSColin Finck /* 1005c2c66affSColin Finck * Right-shift: X >>= count 1006c2c66affSColin Finck */ 1007c2c66affSColin Finck int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) 1008c2c66affSColin Finck { 1009c2c66affSColin Finck size_t i, v0, v1; 1010c2c66affSColin Finck mbedtls_mpi_uint r0 = 0, r1; 1011*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1012c2c66affSColin Finck 1013c2c66affSColin Finck v0 = count / biL; 1014c2c66affSColin Finck v1 = count & (biL - 1); 1015c2c66affSColin Finck 1016c2c66affSColin Finck if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) 1017c2c66affSColin Finck return mbedtls_mpi_lset( X, 0 ); 1018c2c66affSColin Finck 1019c2c66affSColin Finck /* 1020c2c66affSColin Finck * shift by count / limb_size 1021c2c66affSColin Finck */ 1022c2c66affSColin Finck if( v0 > 0 ) 1023c2c66affSColin Finck { 1024c2c66affSColin Finck for( i = 0; i < X->n - v0; i++ ) 1025c2c66affSColin Finck X->p[i] = X->p[i + v0]; 1026c2c66affSColin Finck 1027c2c66affSColin Finck for( ; i < X->n; i++ ) 1028c2c66affSColin Finck X->p[i] = 0; 1029c2c66affSColin Finck } 1030c2c66affSColin Finck 1031c2c66affSColin Finck /* 1032c2c66affSColin Finck * shift by count % limb_size 1033c2c66affSColin Finck */ 1034c2c66affSColin Finck if( v1 > 0 ) 1035c2c66affSColin Finck { 1036c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 1037c2c66affSColin Finck { 1038c2c66affSColin Finck r1 = X->p[i - 1] << (biL - v1); 1039c2c66affSColin Finck X->p[i - 1] >>= v1; 1040c2c66affSColin Finck X->p[i - 1] |= r0; 1041c2c66affSColin Finck r0 = r1; 1042c2c66affSColin Finck } 1043c2c66affSColin Finck } 1044c2c66affSColin Finck 1045c2c66affSColin Finck return( 0 ); 1046c2c66affSColin Finck } 1047c2c66affSColin Finck 1048c2c66affSColin Finck /* 1049c2c66affSColin Finck * Compare unsigned values 1050c2c66affSColin Finck */ 1051c2c66affSColin Finck int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) 1052c2c66affSColin Finck { 1053c2c66affSColin Finck size_t i, j; 1054*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1055*cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL ); 1056c2c66affSColin Finck 1057c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 1058c2c66affSColin Finck if( X->p[i - 1] != 0 ) 1059c2c66affSColin Finck break; 1060c2c66affSColin Finck 1061c2c66affSColin Finck for( j = Y->n; j > 0; j-- ) 1062c2c66affSColin Finck if( Y->p[j - 1] != 0 ) 1063c2c66affSColin Finck break; 1064c2c66affSColin Finck 1065c2c66affSColin Finck if( i == 0 && j == 0 ) 1066c2c66affSColin Finck return( 0 ); 1067c2c66affSColin Finck 1068c2c66affSColin Finck if( i > j ) return( 1 ); 1069c2c66affSColin Finck if( j > i ) return( -1 ); 1070c2c66affSColin Finck 1071c2c66affSColin Finck for( ; i > 0; i-- ) 1072c2c66affSColin Finck { 1073c2c66affSColin Finck if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); 1074c2c66affSColin Finck if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); 1075c2c66affSColin Finck } 1076c2c66affSColin Finck 1077c2c66affSColin Finck return( 0 ); 1078c2c66affSColin Finck } 1079c2c66affSColin Finck 1080c2c66affSColin Finck /* 1081c2c66affSColin Finck * Compare signed values 1082c2c66affSColin Finck */ 1083c2c66affSColin Finck int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) 1084c2c66affSColin Finck { 1085c2c66affSColin Finck size_t i, j; 1086*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1087*cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL ); 1088c2c66affSColin Finck 1089c2c66affSColin Finck for( i = X->n; i > 0; i-- ) 1090c2c66affSColin Finck if( X->p[i - 1] != 0 ) 1091c2c66affSColin Finck break; 1092c2c66affSColin Finck 1093c2c66affSColin Finck for( j = Y->n; j > 0; j-- ) 1094c2c66affSColin Finck if( Y->p[j - 1] != 0 ) 1095c2c66affSColin Finck break; 1096c2c66affSColin Finck 1097c2c66affSColin Finck if( i == 0 && j == 0 ) 1098c2c66affSColin Finck return( 0 ); 1099c2c66affSColin Finck 1100c2c66affSColin Finck if( i > j ) return( X->s ); 1101c2c66affSColin Finck if( j > i ) return( -Y->s ); 1102c2c66affSColin Finck 1103c2c66affSColin Finck if( X->s > 0 && Y->s < 0 ) return( 1 ); 1104c2c66affSColin Finck if( Y->s > 0 && X->s < 0 ) return( -1 ); 1105c2c66affSColin Finck 1106c2c66affSColin Finck for( ; i > 0; i-- ) 1107c2c66affSColin Finck { 1108c2c66affSColin Finck if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); 1109c2c66affSColin Finck if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); 1110c2c66affSColin Finck } 1111c2c66affSColin Finck 1112c2c66affSColin Finck return( 0 ); 1113c2c66affSColin Finck } 1114c2c66affSColin Finck 1115d152519aSThomas Faber /** Decide if an integer is less than the other, without branches. 1116d152519aSThomas Faber * 1117d152519aSThomas Faber * \param x First integer. 1118d152519aSThomas Faber * \param y Second integer. 1119d152519aSThomas Faber * 1120d152519aSThomas Faber * \return 1 if \p x is less than \p y, 0 otherwise 1121d152519aSThomas Faber */ 1122d152519aSThomas Faber static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x, 1123d152519aSThomas Faber const mbedtls_mpi_uint y ) 1124d152519aSThomas Faber { 1125d152519aSThomas Faber mbedtls_mpi_uint ret; 1126d152519aSThomas Faber mbedtls_mpi_uint cond; 1127d152519aSThomas Faber 1128d152519aSThomas Faber /* 1129d152519aSThomas Faber * Check if the most significant bits (MSB) of the operands are different. 1130d152519aSThomas Faber */ 1131d152519aSThomas Faber cond = ( x ^ y ); 1132d152519aSThomas Faber /* 1133d152519aSThomas Faber * If the MSB are the same then the difference x-y will be negative (and 1134d152519aSThomas Faber * have its MSB set to 1 during conversion to unsigned) if and only if x<y. 1135d152519aSThomas Faber */ 1136d152519aSThomas Faber ret = ( x - y ) & ~cond; 1137d152519aSThomas Faber /* 1138d152519aSThomas Faber * If the MSB are different, then the operand with the MSB of 1 is the 1139d152519aSThomas Faber * bigger. (That is if y has MSB of 1, then x<y is true and it is false if 1140d152519aSThomas Faber * the MSB of y is 0.) 1141d152519aSThomas Faber */ 1142d152519aSThomas Faber ret |= y & cond; 1143d152519aSThomas Faber 1144d152519aSThomas Faber 1145d152519aSThomas Faber ret = ret >> ( biL - 1 ); 1146d152519aSThomas Faber 1147d152519aSThomas Faber return (unsigned) ret; 1148d152519aSThomas Faber } 1149d152519aSThomas Faber 1150d152519aSThomas Faber /* 1151d152519aSThomas Faber * Compare signed values in constant time 1152d152519aSThomas Faber */ 1153d152519aSThomas Faber int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, 1154d152519aSThomas Faber unsigned *ret ) 1155d152519aSThomas Faber { 1156d152519aSThomas Faber size_t i; 1157d152519aSThomas Faber /* The value of any of these variables is either 0 or 1 at all times. */ 1158d152519aSThomas Faber unsigned cond, done, X_is_negative, Y_is_negative; 1159d152519aSThomas Faber 1160*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1161*cbda039fSThomas Faber MPI_VALIDATE_RET( Y != NULL ); 1162*cbda039fSThomas Faber MPI_VALIDATE_RET( ret != NULL ); 1163*cbda039fSThomas Faber 1164d152519aSThomas Faber if( X->n != Y->n ) 1165d152519aSThomas Faber return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; 1166d152519aSThomas Faber 1167d152519aSThomas Faber /* 1168d152519aSThomas Faber * Set sign_N to 1 if N >= 0, 0 if N < 0. 1169d152519aSThomas Faber * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. 1170d152519aSThomas Faber */ 1171d152519aSThomas Faber X_is_negative = ( X->s & 2 ) >> 1; 1172d152519aSThomas Faber Y_is_negative = ( Y->s & 2 ) >> 1; 1173d152519aSThomas Faber 1174d152519aSThomas Faber /* 1175d152519aSThomas Faber * If the signs are different, then the positive operand is the bigger. 1176d152519aSThomas Faber * That is if X is negative (X_is_negative == 1), then X < Y is true and it 1177d152519aSThomas Faber * is false if X is positive (X_is_negative == 0). 1178d152519aSThomas Faber */ 1179d152519aSThomas Faber cond = ( X_is_negative ^ Y_is_negative ); 1180d152519aSThomas Faber *ret = cond & X_is_negative; 1181d152519aSThomas Faber 1182d152519aSThomas Faber /* 1183d152519aSThomas Faber * This is a constant-time function. We might have the result, but we still 1184d152519aSThomas Faber * need to go through the loop. Record if we have the result already. 1185d152519aSThomas Faber */ 1186d152519aSThomas Faber done = cond; 1187d152519aSThomas Faber 1188d152519aSThomas Faber for( i = X->n; i > 0; i-- ) 1189d152519aSThomas Faber { 1190d152519aSThomas Faber /* 1191d152519aSThomas Faber * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both 1192d152519aSThomas Faber * X and Y are negative. 1193d152519aSThomas Faber * 1194d152519aSThomas Faber * Again even if we can make a decision, we just mark the result and 1195d152519aSThomas Faber * the fact that we are done and continue looping. 1196d152519aSThomas Faber */ 1197d152519aSThomas Faber cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ); 1198d152519aSThomas Faber *ret |= cond & ( 1 - done ) & X_is_negative; 1199d152519aSThomas Faber done |= cond; 1200d152519aSThomas Faber 1201d152519aSThomas Faber /* 1202d152519aSThomas Faber * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both 1203d152519aSThomas Faber * X and Y are positive. 1204d152519aSThomas Faber * 1205d152519aSThomas Faber * Again even if we can make a decision, we just mark the result and 1206d152519aSThomas Faber * the fact that we are done and continue looping. 1207d152519aSThomas Faber */ 1208d152519aSThomas Faber cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ); 1209d152519aSThomas Faber *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); 1210d152519aSThomas Faber done |= cond; 1211d152519aSThomas Faber } 1212d152519aSThomas Faber 1213d152519aSThomas Faber return( 0 ); 1214d152519aSThomas Faber } 1215d152519aSThomas Faber 1216c2c66affSColin Finck /* 1217c2c66affSColin Finck * Compare signed values 1218c2c66affSColin Finck */ 1219c2c66affSColin Finck int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) 1220c2c66affSColin Finck { 1221c2c66affSColin Finck mbedtls_mpi Y; 1222c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1223*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1224c2c66affSColin Finck 1225c2c66affSColin Finck *p = ( z < 0 ) ? -z : z; 1226c2c66affSColin Finck Y.s = ( z < 0 ) ? -1 : 1; 1227c2c66affSColin Finck Y.n = 1; 1228c2c66affSColin Finck Y.p = p; 1229c2c66affSColin Finck 1230c2c66affSColin Finck return( mbedtls_mpi_cmp_mpi( X, &Y ) ); 1231c2c66affSColin Finck } 1232c2c66affSColin Finck 1233c2c66affSColin Finck /* 1234c2c66affSColin Finck * Unsigned addition: X = |A| + |B| (HAC 14.7) 1235c2c66affSColin Finck */ 1236c2c66affSColin Finck int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1237c2c66affSColin Finck { 1238c2c66affSColin Finck int ret; 1239c2c66affSColin Finck size_t i, j; 1240c2c66affSColin Finck mbedtls_mpi_uint *o, *p, c, tmp; 1241*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1242*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1243*cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL ); 1244c2c66affSColin Finck 1245c2c66affSColin Finck if( X == B ) 1246c2c66affSColin Finck { 1247c2c66affSColin Finck const mbedtls_mpi *T = A; A = X; B = T; 1248c2c66affSColin Finck } 1249c2c66affSColin Finck 1250c2c66affSColin Finck if( X != A ) 1251c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); 1252c2c66affSColin Finck 1253c2c66affSColin Finck /* 1254c2c66affSColin Finck * X should always be positive as a result of unsigned additions. 1255c2c66affSColin Finck */ 1256c2c66affSColin Finck X->s = 1; 1257c2c66affSColin Finck 1258c2c66affSColin Finck for( j = B->n; j > 0; j-- ) 1259c2c66affSColin Finck if( B->p[j - 1] != 0 ) 1260c2c66affSColin Finck break; 1261c2c66affSColin Finck 1262c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); 1263c2c66affSColin Finck 1264c2c66affSColin Finck o = B->p; p = X->p; c = 0; 1265c2c66affSColin Finck 1266c2c66affSColin Finck /* 1267c2c66affSColin Finck * tmp is used because it might happen that p == o 1268c2c66affSColin Finck */ 1269c2c66affSColin Finck for( i = 0; i < j; i++, o++, p++ ) 1270c2c66affSColin Finck { 1271c2c66affSColin Finck tmp= *o; 1272c2c66affSColin Finck *p += c; c = ( *p < c ); 1273c2c66affSColin Finck *p += tmp; c += ( *p < tmp ); 1274c2c66affSColin Finck } 1275c2c66affSColin Finck 1276c2c66affSColin Finck while( c != 0 ) 1277c2c66affSColin Finck { 1278c2c66affSColin Finck if( i >= X->n ) 1279c2c66affSColin Finck { 1280c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); 1281c2c66affSColin Finck p = X->p + i; 1282c2c66affSColin Finck } 1283c2c66affSColin Finck 1284c2c66affSColin Finck *p += c; c = ( *p < c ); i++; p++; 1285c2c66affSColin Finck } 1286c2c66affSColin Finck 1287c2c66affSColin Finck cleanup: 1288c2c66affSColin Finck 1289c2c66affSColin Finck return( ret ); 1290c2c66affSColin Finck } 1291c2c66affSColin Finck 1292292f67afSThomas Faber /** 1293292f67afSThomas Faber * Helper for mbedtls_mpi subtraction. 1294292f67afSThomas Faber * 1295292f67afSThomas Faber * Calculate d - s where d and s have the same size. 1296292f67afSThomas Faber * This function operates modulo (2^ciL)^n and returns the carry 1297292f67afSThomas Faber * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise). 1298292f67afSThomas Faber * 1299292f67afSThomas Faber * \param n Number of limbs of \p d and \p s. 1300292f67afSThomas Faber * \param[in,out] d On input, the left operand. 1301292f67afSThomas Faber * On output, the result of the subtraction: 1302292f67afSThomas Faber * \param[in] s The right operand. 1303292f67afSThomas Faber * 1304292f67afSThomas Faber * \return 1 if `d < s`. 1305292f67afSThomas Faber * 0 if `d >= s`. 1306c2c66affSColin Finck */ 1307292f67afSThomas Faber static mbedtls_mpi_uint mpi_sub_hlp( size_t n, 1308292f67afSThomas Faber mbedtls_mpi_uint *d, 1309292f67afSThomas Faber const mbedtls_mpi_uint *s ) 1310c2c66affSColin Finck { 1311c2c66affSColin Finck size_t i; 1312c2c66affSColin Finck mbedtls_mpi_uint c, z; 1313c2c66affSColin Finck 1314c2c66affSColin Finck for( i = c = 0; i < n; i++, s++, d++ ) 1315c2c66affSColin Finck { 1316c2c66affSColin Finck z = ( *d < c ); *d -= c; 1317c2c66affSColin Finck c = ( *d < *s ) + z; *d -= *s; 1318c2c66affSColin Finck } 1319c2c66affSColin Finck 1320292f67afSThomas Faber return( c ); 1321c2c66affSColin Finck } 1322c2c66affSColin Finck 1323c2c66affSColin Finck /* 1324292f67afSThomas Faber * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) 1325c2c66affSColin Finck */ 1326c2c66affSColin Finck int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1327c2c66affSColin Finck { 1328c2c66affSColin Finck mbedtls_mpi TB; 1329c2c66affSColin Finck int ret; 1330c2c66affSColin Finck size_t n; 1331292f67afSThomas Faber mbedtls_mpi_uint carry; 1332*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1333*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1334*cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL ); 1335c2c66affSColin Finck 1336c2c66affSColin Finck mbedtls_mpi_init( &TB ); 1337c2c66affSColin Finck 1338c2c66affSColin Finck if( X == B ) 1339c2c66affSColin Finck { 1340c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); 1341c2c66affSColin Finck B = &TB; 1342c2c66affSColin Finck } 1343c2c66affSColin Finck 1344c2c66affSColin Finck if( X != A ) 1345c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); 1346c2c66affSColin Finck 1347c2c66affSColin Finck /* 1348c2c66affSColin Finck * X should always be positive as a result of unsigned subtractions. 1349c2c66affSColin Finck */ 1350c2c66affSColin Finck X->s = 1; 1351c2c66affSColin Finck 1352c2c66affSColin Finck ret = 0; 1353c2c66affSColin Finck 1354c2c66affSColin Finck for( n = B->n; n > 0; n-- ) 1355c2c66affSColin Finck if( B->p[n - 1] != 0 ) 1356c2c66affSColin Finck break; 1357a01a8faaSThomas Faber if( n > A->n ) 1358a01a8faaSThomas Faber { 1359a01a8faaSThomas Faber /* B >= (2^ciL)^n > A */ 1360a01a8faaSThomas Faber ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 1361a01a8faaSThomas Faber goto cleanup; 1362a01a8faaSThomas Faber } 1363c2c66affSColin Finck 1364292f67afSThomas Faber carry = mpi_sub_hlp( n, X->p, B->p ); 1365292f67afSThomas Faber if( carry != 0 ) 1366292f67afSThomas Faber { 1367292f67afSThomas Faber /* Propagate the carry to the first nonzero limb of X. */ 1368292f67afSThomas Faber for( ; n < X->n && X->p[n] == 0; n++ ) 1369292f67afSThomas Faber --X->p[n]; 1370292f67afSThomas Faber /* If we ran out of space for the carry, it means that the result 1371292f67afSThomas Faber * is negative. */ 1372292f67afSThomas Faber if( n == X->n ) 13732e53fc8eSThomas Faber { 13742e53fc8eSThomas Faber ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; 13752e53fc8eSThomas Faber goto cleanup; 13762e53fc8eSThomas Faber } 1377292f67afSThomas Faber --X->p[n]; 1378292f67afSThomas Faber } 1379c2c66affSColin Finck 1380c2c66affSColin Finck cleanup: 1381c2c66affSColin Finck 1382c2c66affSColin Finck mbedtls_mpi_free( &TB ); 1383c2c66affSColin Finck 1384c2c66affSColin Finck return( ret ); 1385c2c66affSColin Finck } 1386c2c66affSColin Finck 1387c2c66affSColin Finck /* 1388c2c66affSColin Finck * Signed addition: X = A + B 1389c2c66affSColin Finck */ 1390c2c66affSColin Finck int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1391c2c66affSColin Finck { 1392*cbda039fSThomas Faber int ret, s; 1393*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1394*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1395*cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL ); 1396c2c66affSColin Finck 1397*cbda039fSThomas Faber s = A->s; 1398c2c66affSColin Finck if( A->s * B->s < 0 ) 1399c2c66affSColin Finck { 1400c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) 1401c2c66affSColin Finck { 1402c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); 1403c2c66affSColin Finck X->s = s; 1404c2c66affSColin Finck } 1405c2c66affSColin Finck else 1406c2c66affSColin Finck { 1407c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); 1408c2c66affSColin Finck X->s = -s; 1409c2c66affSColin Finck } 1410c2c66affSColin Finck } 1411c2c66affSColin Finck else 1412c2c66affSColin Finck { 1413c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); 1414c2c66affSColin Finck X->s = s; 1415c2c66affSColin Finck } 1416c2c66affSColin Finck 1417c2c66affSColin Finck cleanup: 1418c2c66affSColin Finck 1419c2c66affSColin Finck return( ret ); 1420c2c66affSColin Finck } 1421c2c66affSColin Finck 1422c2c66affSColin Finck /* 1423c2c66affSColin Finck * Signed subtraction: X = A - B 1424c2c66affSColin Finck */ 1425c2c66affSColin Finck int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1426c2c66affSColin Finck { 1427*cbda039fSThomas Faber int ret, s; 1428*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1429*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1430*cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL ); 1431c2c66affSColin Finck 1432*cbda039fSThomas Faber s = A->s; 1433c2c66affSColin Finck if( A->s * B->s > 0 ) 1434c2c66affSColin Finck { 1435c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) 1436c2c66affSColin Finck { 1437c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); 1438c2c66affSColin Finck X->s = s; 1439c2c66affSColin Finck } 1440c2c66affSColin Finck else 1441c2c66affSColin Finck { 1442c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); 1443c2c66affSColin Finck X->s = -s; 1444c2c66affSColin Finck } 1445c2c66affSColin Finck } 1446c2c66affSColin Finck else 1447c2c66affSColin Finck { 1448c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); 1449c2c66affSColin Finck X->s = s; 1450c2c66affSColin Finck } 1451c2c66affSColin Finck 1452c2c66affSColin Finck cleanup: 1453c2c66affSColin Finck 1454c2c66affSColin Finck return( ret ); 1455c2c66affSColin Finck } 1456c2c66affSColin Finck 1457c2c66affSColin Finck /* 1458c2c66affSColin Finck * Signed addition: X = A + b 1459c2c66affSColin Finck */ 1460c2c66affSColin Finck int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1461c2c66affSColin Finck { 1462c2c66affSColin Finck mbedtls_mpi _B; 1463c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1464*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1465*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1466c2c66affSColin Finck 1467c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1468c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1469c2c66affSColin Finck _B.n = 1; 1470c2c66affSColin Finck _B.p = p; 1471c2c66affSColin Finck 1472c2c66affSColin Finck return( mbedtls_mpi_add_mpi( X, A, &_B ) ); 1473c2c66affSColin Finck } 1474c2c66affSColin Finck 1475c2c66affSColin Finck /* 1476c2c66affSColin Finck * Signed subtraction: X = A - b 1477c2c66affSColin Finck */ 1478c2c66affSColin Finck int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1479c2c66affSColin Finck { 1480c2c66affSColin Finck mbedtls_mpi _B; 1481c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1482*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1483*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1484c2c66affSColin Finck 1485c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1486c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1487c2c66affSColin Finck _B.n = 1; 1488c2c66affSColin Finck _B.p = p; 1489c2c66affSColin Finck 1490c2c66affSColin Finck return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); 1491c2c66affSColin Finck } 1492c2c66affSColin Finck 1493c2c66affSColin Finck /* 1494c2c66affSColin Finck * Helper for mbedtls_mpi multiplication 1495c2c66affSColin Finck */ 1496c2c66affSColin Finck static 1497c2c66affSColin Finck #if defined(__APPLE__) && defined(__arm__) 1498c2c66affSColin Finck /* 1499c2c66affSColin Finck * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) 1500c2c66affSColin Finck * appears to need this to prevent bad ARM code generation at -O3. 1501c2c66affSColin Finck */ 1502c2c66affSColin Finck __attribute__ ((noinline)) 1503c2c66affSColin Finck #endif 1504c2c66affSColin Finck void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) 1505c2c66affSColin Finck { 1506c2c66affSColin Finck mbedtls_mpi_uint c = 0, t = 0; 1507c2c66affSColin Finck 1508c2c66affSColin Finck #if defined(MULADDC_HUIT) 1509c2c66affSColin Finck for( ; i >= 8; i -= 8 ) 1510c2c66affSColin Finck { 1511c2c66affSColin Finck MULADDC_INIT 1512c2c66affSColin Finck MULADDC_HUIT 1513c2c66affSColin Finck MULADDC_STOP 1514c2c66affSColin Finck } 1515c2c66affSColin Finck 1516c2c66affSColin Finck for( ; i > 0; i-- ) 1517c2c66affSColin Finck { 1518c2c66affSColin Finck MULADDC_INIT 1519c2c66affSColin Finck MULADDC_CORE 1520c2c66affSColin Finck MULADDC_STOP 1521c2c66affSColin Finck } 1522c2c66affSColin Finck #else /* MULADDC_HUIT */ 1523c2c66affSColin Finck for( ; i >= 16; i -= 16 ) 1524c2c66affSColin Finck { 1525c2c66affSColin Finck MULADDC_INIT 1526c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1527c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1528c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1529c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1530c2c66affSColin Finck 1531c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1532c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1533c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1534c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1535c2c66affSColin Finck MULADDC_STOP 1536c2c66affSColin Finck } 1537c2c66affSColin Finck 1538c2c66affSColin Finck for( ; i >= 8; i -= 8 ) 1539c2c66affSColin Finck { 1540c2c66affSColin Finck MULADDC_INIT 1541c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1542c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1543c2c66affSColin Finck 1544c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1545c2c66affSColin Finck MULADDC_CORE MULADDC_CORE 1546c2c66affSColin Finck MULADDC_STOP 1547c2c66affSColin Finck } 1548c2c66affSColin Finck 1549c2c66affSColin Finck for( ; i > 0; i-- ) 1550c2c66affSColin Finck { 1551c2c66affSColin Finck MULADDC_INIT 1552c2c66affSColin Finck MULADDC_CORE 1553c2c66affSColin Finck MULADDC_STOP 1554c2c66affSColin Finck } 1555c2c66affSColin Finck #endif /* MULADDC_HUIT */ 1556c2c66affSColin Finck 1557c2c66affSColin Finck t++; 1558c2c66affSColin Finck 1559c2c66affSColin Finck do { 1560c2c66affSColin Finck *d += c; c = ( *d < c ); d++; 1561c2c66affSColin Finck } 1562c2c66affSColin Finck while( c != 0 ); 1563c2c66affSColin Finck } 1564c2c66affSColin Finck 1565c2c66affSColin Finck /* 1566c2c66affSColin Finck * Baseline multiplication: X = A * B (HAC 14.12) 1567c2c66affSColin Finck */ 1568c2c66affSColin Finck int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1569c2c66affSColin Finck { 1570c2c66affSColin Finck int ret; 1571c2c66affSColin Finck size_t i, j; 1572c2c66affSColin Finck mbedtls_mpi TA, TB; 1573*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1574*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1575*cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL ); 1576c2c66affSColin Finck 1577c2c66affSColin Finck mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); 1578c2c66affSColin Finck 1579c2c66affSColin Finck if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } 1580c2c66affSColin Finck if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } 1581c2c66affSColin Finck 1582c2c66affSColin Finck for( i = A->n; i > 0; i-- ) 1583c2c66affSColin Finck if( A->p[i - 1] != 0 ) 1584c2c66affSColin Finck break; 1585c2c66affSColin Finck 1586c2c66affSColin Finck for( j = B->n; j > 0; j-- ) 1587c2c66affSColin Finck if( B->p[j - 1] != 0 ) 1588c2c66affSColin Finck break; 1589c2c66affSColin Finck 1590c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); 1591c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 1592c2c66affSColin Finck 1593*cbda039fSThomas Faber for( ; j > 0; j-- ) 1594*cbda039fSThomas Faber mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); 1595c2c66affSColin Finck 1596c2c66affSColin Finck X->s = A->s * B->s; 1597c2c66affSColin Finck 1598c2c66affSColin Finck cleanup: 1599c2c66affSColin Finck 1600c2c66affSColin Finck mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); 1601c2c66affSColin Finck 1602c2c66affSColin Finck return( ret ); 1603c2c66affSColin Finck } 1604c2c66affSColin Finck 1605c2c66affSColin Finck /* 1606c2c66affSColin Finck * Baseline multiplication: X = A * b 1607c2c66affSColin Finck */ 1608c2c66affSColin Finck int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) 1609c2c66affSColin Finck { 1610c2c66affSColin Finck mbedtls_mpi _B; 1611c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1612*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 1613*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1614c2c66affSColin Finck 1615c2c66affSColin Finck _B.s = 1; 1616c2c66affSColin Finck _B.n = 1; 1617c2c66affSColin Finck _B.p = p; 1618c2c66affSColin Finck p[0] = b; 1619c2c66affSColin Finck 1620c2c66affSColin Finck return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); 1621c2c66affSColin Finck } 1622c2c66affSColin Finck 1623c2c66affSColin Finck /* 1624c2c66affSColin Finck * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and 1625c2c66affSColin Finck * mbedtls_mpi_uint divisor, d 1626c2c66affSColin Finck */ 1627c2c66affSColin Finck static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, 1628c2c66affSColin Finck mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) 1629c2c66affSColin Finck { 1630c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL) 1631c2c66affSColin Finck mbedtls_t_udbl dividend, quotient; 1632c2c66affSColin Finck #else 1633c2c66affSColin Finck const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; 1634c2c66affSColin Finck const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; 1635c2c66affSColin Finck mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; 1636c2c66affSColin Finck mbedtls_mpi_uint u0_msw, u0_lsw; 1637c2c66affSColin Finck size_t s; 1638c2c66affSColin Finck #endif 1639c2c66affSColin Finck 1640c2c66affSColin Finck /* 1641c2c66affSColin Finck * Check for overflow 1642c2c66affSColin Finck */ 1643c2c66affSColin Finck if( 0 == d || u1 >= d ) 1644c2c66affSColin Finck { 1645c2c66affSColin Finck if (r != NULL) *r = ~0; 1646c2c66affSColin Finck 1647c2c66affSColin Finck return ( ~0 ); 1648c2c66affSColin Finck } 1649c2c66affSColin Finck 1650c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL) 1651c2c66affSColin Finck dividend = (mbedtls_t_udbl) u1 << biL; 1652c2c66affSColin Finck dividend |= (mbedtls_t_udbl) u0; 1653c2c66affSColin Finck quotient = dividend / d; 1654c2c66affSColin Finck if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) 1655c2c66affSColin Finck quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; 1656c2c66affSColin Finck 1657c2c66affSColin Finck if( r != NULL ) 1658c2c66affSColin Finck *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); 1659c2c66affSColin Finck 1660c2c66affSColin Finck return (mbedtls_mpi_uint) quotient; 1661c2c66affSColin Finck #else 1662c2c66affSColin Finck 1663c2c66affSColin Finck /* 1664c2c66affSColin Finck * Algorithm D, Section 4.3.1 - The Art of Computer Programming 1665c2c66affSColin Finck * Vol. 2 - Seminumerical Algorithms, Knuth 1666c2c66affSColin Finck */ 1667c2c66affSColin Finck 1668c2c66affSColin Finck /* 1669c2c66affSColin Finck * Normalize the divisor, d, and dividend, u0, u1 1670c2c66affSColin Finck */ 1671c2c66affSColin Finck s = mbedtls_clz( d ); 1672c2c66affSColin Finck d = d << s; 1673c2c66affSColin Finck 1674c2c66affSColin Finck u1 = u1 << s; 1675c2c66affSColin Finck u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); 1676c2c66affSColin Finck u0 = u0 << s; 1677c2c66affSColin Finck 1678c2c66affSColin Finck d1 = d >> biH; 1679c2c66affSColin Finck d0 = d & uint_halfword_mask; 1680c2c66affSColin Finck 1681c2c66affSColin Finck u0_msw = u0 >> biH; 1682c2c66affSColin Finck u0_lsw = u0 & uint_halfword_mask; 1683c2c66affSColin Finck 1684c2c66affSColin Finck /* 1685c2c66affSColin Finck * Find the first quotient and remainder 1686c2c66affSColin Finck */ 1687c2c66affSColin Finck q1 = u1 / d1; 1688c2c66affSColin Finck r0 = u1 - d1 * q1; 1689c2c66affSColin Finck 1690c2c66affSColin Finck while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) 1691c2c66affSColin Finck { 1692c2c66affSColin Finck q1 -= 1; 1693c2c66affSColin Finck r0 += d1; 1694c2c66affSColin Finck 1695c2c66affSColin Finck if ( r0 >= radix ) break; 1696c2c66affSColin Finck } 1697c2c66affSColin Finck 1698c2c66affSColin Finck rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); 1699c2c66affSColin Finck q0 = rAX / d1; 1700c2c66affSColin Finck r0 = rAX - q0 * d1; 1701c2c66affSColin Finck 1702c2c66affSColin Finck while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) 1703c2c66affSColin Finck { 1704c2c66affSColin Finck q0 -= 1; 1705c2c66affSColin Finck r0 += d1; 1706c2c66affSColin Finck 1707c2c66affSColin Finck if ( r0 >= radix ) break; 1708c2c66affSColin Finck } 1709c2c66affSColin Finck 1710c2c66affSColin Finck if (r != NULL) 1711c2c66affSColin Finck *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; 1712c2c66affSColin Finck 1713c2c66affSColin Finck quotient = q1 * radix + q0; 1714c2c66affSColin Finck 1715c2c66affSColin Finck return quotient; 1716c2c66affSColin Finck #endif 1717c2c66affSColin Finck } 1718c2c66affSColin Finck 1719c2c66affSColin Finck /* 1720c2c66affSColin Finck * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) 1721c2c66affSColin Finck */ 1722*cbda039fSThomas Faber int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, 1723*cbda039fSThomas Faber const mbedtls_mpi *B ) 1724c2c66affSColin Finck { 1725c2c66affSColin Finck int ret; 1726c2c66affSColin Finck size_t i, n, t, k; 1727c2c66affSColin Finck mbedtls_mpi X, Y, Z, T1, T2; 1728*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1729*cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL ); 1730c2c66affSColin Finck 1731c2c66affSColin Finck if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) 1732c2c66affSColin Finck return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); 1733c2c66affSColin Finck 1734c2c66affSColin Finck mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); 1735c2c66affSColin Finck mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); 1736c2c66affSColin Finck 1737c2c66affSColin Finck if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) 1738c2c66affSColin Finck { 1739c2c66affSColin Finck if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); 1740c2c66affSColin Finck if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); 1741c2c66affSColin Finck return( 0 ); 1742c2c66affSColin Finck } 1743c2c66affSColin Finck 1744c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); 1745c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); 1746c2c66affSColin Finck X.s = Y.s = 1; 1747c2c66affSColin Finck 1748c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); 1749c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); 1750c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); 1751c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); 1752c2c66affSColin Finck 1753c2c66affSColin Finck k = mbedtls_mpi_bitlen( &Y ) % biL; 1754c2c66affSColin Finck if( k < biL - 1 ) 1755c2c66affSColin Finck { 1756c2c66affSColin Finck k = biL - 1 - k; 1757c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); 1758c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); 1759c2c66affSColin Finck } 1760c2c66affSColin Finck else k = 0; 1761c2c66affSColin Finck 1762c2c66affSColin Finck n = X.n - 1; 1763c2c66affSColin Finck t = Y.n - 1; 1764c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); 1765c2c66affSColin Finck 1766c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) 1767c2c66affSColin Finck { 1768c2c66affSColin Finck Z.p[n - t]++; 1769c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); 1770c2c66affSColin Finck } 1771c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); 1772c2c66affSColin Finck 1773c2c66affSColin Finck for( i = n; i > t ; i-- ) 1774c2c66affSColin Finck { 1775c2c66affSColin Finck if( X.p[i] >= Y.p[t] ) 1776c2c66affSColin Finck Z.p[i - t - 1] = ~0; 1777c2c66affSColin Finck else 1778c2c66affSColin Finck { 1779c2c66affSColin Finck Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], 1780c2c66affSColin Finck Y.p[t], NULL); 1781c2c66affSColin Finck } 1782c2c66affSColin Finck 1783c2c66affSColin Finck Z.p[i - t - 1]++; 1784c2c66affSColin Finck do 1785c2c66affSColin Finck { 1786c2c66affSColin Finck Z.p[i - t - 1]--; 1787c2c66affSColin Finck 1788c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); 1789c2c66affSColin Finck T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; 1790c2c66affSColin Finck T1.p[1] = Y.p[t]; 1791c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); 1792c2c66affSColin Finck 1793c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); 1794c2c66affSColin Finck T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; 1795c2c66affSColin Finck T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; 1796c2c66affSColin Finck T2.p[2] = X.p[i]; 1797c2c66affSColin Finck } 1798c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); 1799c2c66affSColin Finck 1800c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); 1801c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); 1802c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); 1803c2c66affSColin Finck 1804c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) 1805c2c66affSColin Finck { 1806c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); 1807c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); 1808c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); 1809c2c66affSColin Finck Z.p[i - t - 1]--; 1810c2c66affSColin Finck } 1811c2c66affSColin Finck } 1812c2c66affSColin Finck 1813c2c66affSColin Finck if( Q != NULL ) 1814c2c66affSColin Finck { 1815c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); 1816c2c66affSColin Finck Q->s = A->s * B->s; 1817c2c66affSColin Finck } 1818c2c66affSColin Finck 1819c2c66affSColin Finck if( R != NULL ) 1820c2c66affSColin Finck { 1821c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); 1822c2c66affSColin Finck X.s = A->s; 1823c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); 1824c2c66affSColin Finck 1825c2c66affSColin Finck if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) 1826c2c66affSColin Finck R->s = 1; 1827c2c66affSColin Finck } 1828c2c66affSColin Finck 1829c2c66affSColin Finck cleanup: 1830c2c66affSColin Finck 1831c2c66affSColin Finck mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); 1832c2c66affSColin Finck mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); 1833c2c66affSColin Finck 1834c2c66affSColin Finck return( ret ); 1835c2c66affSColin Finck } 1836c2c66affSColin Finck 1837c2c66affSColin Finck /* 1838c2c66affSColin Finck * Division by int: A = Q * b + R 1839c2c66affSColin Finck */ 1840*cbda039fSThomas Faber int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, 1841*cbda039fSThomas Faber const mbedtls_mpi *A, 1842*cbda039fSThomas Faber mbedtls_mpi_sint b ) 1843c2c66affSColin Finck { 1844c2c66affSColin Finck mbedtls_mpi _B; 1845c2c66affSColin Finck mbedtls_mpi_uint p[1]; 1846*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1847c2c66affSColin Finck 1848c2c66affSColin Finck p[0] = ( b < 0 ) ? -b : b; 1849c2c66affSColin Finck _B.s = ( b < 0 ) ? -1 : 1; 1850c2c66affSColin Finck _B.n = 1; 1851c2c66affSColin Finck _B.p = p; 1852c2c66affSColin Finck 1853c2c66affSColin Finck return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); 1854c2c66affSColin Finck } 1855c2c66affSColin Finck 1856c2c66affSColin Finck /* 1857c2c66affSColin Finck * Modulo: R = A mod B 1858c2c66affSColin Finck */ 1859c2c66affSColin Finck int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) 1860c2c66affSColin Finck { 1861c2c66affSColin Finck int ret; 1862*cbda039fSThomas Faber MPI_VALIDATE_RET( R != NULL ); 1863*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1864*cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL ); 1865c2c66affSColin Finck 1866c2c66affSColin Finck if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) 1867c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); 1868c2c66affSColin Finck 1869c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); 1870c2c66affSColin Finck 1871c2c66affSColin Finck while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) 1872c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); 1873c2c66affSColin Finck 1874c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) 1875c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); 1876c2c66affSColin Finck 1877c2c66affSColin Finck cleanup: 1878c2c66affSColin Finck 1879c2c66affSColin Finck return( ret ); 1880c2c66affSColin Finck } 1881c2c66affSColin Finck 1882c2c66affSColin Finck /* 1883c2c66affSColin Finck * Modulo: r = A mod b 1884c2c66affSColin Finck */ 1885c2c66affSColin Finck int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) 1886c2c66affSColin Finck { 1887c2c66affSColin Finck size_t i; 1888c2c66affSColin Finck mbedtls_mpi_uint x, y, z; 1889*cbda039fSThomas Faber MPI_VALIDATE_RET( r != NULL ); 1890*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 1891c2c66affSColin Finck 1892c2c66affSColin Finck if( b == 0 ) 1893c2c66affSColin Finck return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); 1894c2c66affSColin Finck 1895c2c66affSColin Finck if( b < 0 ) 1896c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); 1897c2c66affSColin Finck 1898c2c66affSColin Finck /* 1899c2c66affSColin Finck * handle trivial cases 1900c2c66affSColin Finck */ 1901c2c66affSColin Finck if( b == 1 ) 1902c2c66affSColin Finck { 1903c2c66affSColin Finck *r = 0; 1904c2c66affSColin Finck return( 0 ); 1905c2c66affSColin Finck } 1906c2c66affSColin Finck 1907c2c66affSColin Finck if( b == 2 ) 1908c2c66affSColin Finck { 1909c2c66affSColin Finck *r = A->p[0] & 1; 1910c2c66affSColin Finck return( 0 ); 1911c2c66affSColin Finck } 1912c2c66affSColin Finck 1913c2c66affSColin Finck /* 1914c2c66affSColin Finck * general case 1915c2c66affSColin Finck */ 1916c2c66affSColin Finck for( i = A->n, y = 0; i > 0; i-- ) 1917c2c66affSColin Finck { 1918c2c66affSColin Finck x = A->p[i - 1]; 1919c2c66affSColin Finck y = ( y << biH ) | ( x >> biH ); 1920c2c66affSColin Finck z = y / b; 1921c2c66affSColin Finck y -= z * b; 1922c2c66affSColin Finck 1923c2c66affSColin Finck x <<= biH; 1924c2c66affSColin Finck y = ( y << biH ) | ( x >> biH ); 1925c2c66affSColin Finck z = y / b; 1926c2c66affSColin Finck y -= z * b; 1927c2c66affSColin Finck } 1928c2c66affSColin Finck 1929c2c66affSColin Finck /* 1930c2c66affSColin Finck * If A is negative, then the current y represents a negative value. 1931c2c66affSColin Finck * Flipping it to the positive side. 1932c2c66affSColin Finck */ 1933c2c66affSColin Finck if( A->s < 0 && y != 0 ) 1934c2c66affSColin Finck y = b - y; 1935c2c66affSColin Finck 1936c2c66affSColin Finck *r = y; 1937c2c66affSColin Finck 1938c2c66affSColin Finck return( 0 ); 1939c2c66affSColin Finck } 1940c2c66affSColin Finck 1941c2c66affSColin Finck /* 1942c2c66affSColin Finck * Fast Montgomery initialization (thanks to Tom St Denis) 1943c2c66affSColin Finck */ 1944c2c66affSColin Finck static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) 1945c2c66affSColin Finck { 1946c2c66affSColin Finck mbedtls_mpi_uint x, m0 = N->p[0]; 1947c2c66affSColin Finck unsigned int i; 1948c2c66affSColin Finck 1949c2c66affSColin Finck x = m0; 1950c2c66affSColin Finck x += ( ( m0 + 2 ) & 4 ) << 1; 1951c2c66affSColin Finck 1952c2c66affSColin Finck for( i = biL; i >= 8; i /= 2 ) 1953c2c66affSColin Finck x *= ( 2 - ( m0 * x ) ); 1954c2c66affSColin Finck 1955c2c66affSColin Finck *mm = ~x + 1; 1956c2c66affSColin Finck } 1957c2c66affSColin Finck 1958292f67afSThomas Faber /** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) 1959292f67afSThomas Faber * 1960292f67afSThomas Faber * \param[in,out] A One of the numbers to multiply. 1961292f67afSThomas Faber * It must have at least as many limbs as N 1962292f67afSThomas Faber * (A->n >= N->n), and any limbs beyond n are ignored. 1963292f67afSThomas Faber * On successful completion, A contains the result of 1964292f67afSThomas Faber * the multiplication A * B * R^-1 mod N where 1965292f67afSThomas Faber * R = (2^ciL)^n. 1966292f67afSThomas Faber * \param[in] B One of the numbers to multiply. 1967292f67afSThomas Faber * It must be nonzero and must not have more limbs than N 1968292f67afSThomas Faber * (B->n <= N->n). 1969292f67afSThomas Faber * \param[in] N The modulo. N must be odd. 1970292f67afSThomas Faber * \param mm The value calculated by `mpi_montg_init(&mm, N)`. 1971292f67afSThomas Faber * This is -N^-1 mod 2^ciL. 1972292f67afSThomas Faber * \param[in,out] T A bignum for temporary storage. 1973292f67afSThomas Faber * It must be at least twice the limb size of N plus 2 1974292f67afSThomas Faber * (T->n >= 2 * (N->n + 1)). 1975292f67afSThomas Faber * Its initial content is unused and 1976292f67afSThomas Faber * its final content is indeterminate. 1977292f67afSThomas Faber * Note that unlike the usual convention in the library 1978292f67afSThomas Faber * for `const mbedtls_mpi*`, the content of T can change. 1979c2c66affSColin Finck */ 1980292f67afSThomas Faber static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, 1981c2c66affSColin Finck const mbedtls_mpi *T ) 1982c2c66affSColin Finck { 1983c2c66affSColin Finck size_t i, n, m; 1984c2c66affSColin Finck mbedtls_mpi_uint u0, u1, *d; 1985c2c66affSColin Finck 1986c2c66affSColin Finck memset( T->p, 0, T->n * ciL ); 1987c2c66affSColin Finck 1988c2c66affSColin Finck d = T->p; 1989c2c66affSColin Finck n = N->n; 1990c2c66affSColin Finck m = ( B->n < n ) ? B->n : n; 1991c2c66affSColin Finck 1992c2c66affSColin Finck for( i = 0; i < n; i++ ) 1993c2c66affSColin Finck { 1994c2c66affSColin Finck /* 1995c2c66affSColin Finck * T = (T + u0*B + u1*N) / 2^biL 1996c2c66affSColin Finck */ 1997c2c66affSColin Finck u0 = A->p[i]; 1998c2c66affSColin Finck u1 = ( d[0] + u0 * B->p[0] ) * mm; 1999c2c66affSColin Finck 2000c2c66affSColin Finck mpi_mul_hlp( m, B->p, d, u0 ); 2001c2c66affSColin Finck mpi_mul_hlp( n, N->p, d, u1 ); 2002c2c66affSColin Finck 2003c2c66affSColin Finck *d++ = u0; d[n + 1] = 0; 2004c2c66affSColin Finck } 2005c2c66affSColin Finck 2006292f67afSThomas Faber /* At this point, d is either the desired result or the desired result 2007292f67afSThomas Faber * plus N. We now potentially subtract N, avoiding leaking whether the 2008292f67afSThomas Faber * subtraction is performed through side channels. */ 2009c2c66affSColin Finck 2010292f67afSThomas Faber /* Copy the n least significant limbs of d to A, so that 2011292f67afSThomas Faber * A = d if d < N (recall that N has n limbs). */ 2012292f67afSThomas Faber memcpy( A->p, d, n * ciL ); 2013292f67afSThomas Faber /* If d >= N then we want to set A to d - N. To prevent timing attacks, 2014292f67afSThomas Faber * do the calculation without using conditional tests. */ 2015292f67afSThomas Faber /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ 2016292f67afSThomas Faber d[n] += 1; 2017292f67afSThomas Faber d[n] -= mpi_sub_hlp( n, d, N->p ); 2018292f67afSThomas Faber /* If d0 < N then d < (2^biL)^n 2019292f67afSThomas Faber * so d[n] == 0 and we want to keep A as it is. 2020292f67afSThomas Faber * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n 2021292f67afSThomas Faber * so d[n] == 1 and we want to set A to the result of the subtraction 2022292f67afSThomas Faber * which is d - (2^biL)^n, i.e. the n least significant limbs of d. 2023292f67afSThomas Faber * This exactly corresponds to a conditional assignment. */ 2024292f67afSThomas Faber mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] ); 2025c2c66affSColin Finck } 2026c2c66affSColin Finck 2027c2c66affSColin Finck /* 2028c2c66affSColin Finck * Montgomery reduction: A = A * R^-1 mod N 2029292f67afSThomas Faber * 2030292f67afSThomas Faber * See mpi_montmul() regarding constraints and guarantees on the parameters. 2031c2c66affSColin Finck */ 2032*cbda039fSThomas Faber static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, 2033*cbda039fSThomas Faber mbedtls_mpi_uint mm, const mbedtls_mpi *T ) 2034c2c66affSColin Finck { 2035c2c66affSColin Finck mbedtls_mpi_uint z = 1; 2036c2c66affSColin Finck mbedtls_mpi U; 2037c2c66affSColin Finck 2038c2c66affSColin Finck U.n = U.s = (int) z; 2039c2c66affSColin Finck U.p = &z; 2040c2c66affSColin Finck 2041292f67afSThomas Faber mpi_montmul( A, &U, N, mm, T ); 2042c2c66affSColin Finck } 2043c2c66affSColin Finck 2044c2c66affSColin Finck /* 2045c2c66affSColin Finck * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) 2046c2c66affSColin Finck */ 2047*cbda039fSThomas Faber int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, 2048*cbda039fSThomas Faber const mbedtls_mpi *E, const mbedtls_mpi *N, 2049*cbda039fSThomas Faber mbedtls_mpi *_RR ) 2050c2c66affSColin Finck { 2051c2c66affSColin Finck int ret; 2052c2c66affSColin Finck size_t wbits, wsize, one = 1; 2053c2c66affSColin Finck size_t i, j, nblimbs; 2054c2c66affSColin Finck size_t bufsize, nbits; 2055c2c66affSColin Finck mbedtls_mpi_uint ei, mm, state; 20562e53fc8eSThomas Faber mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; 2057c2c66affSColin Finck int neg; 2058c2c66affSColin Finck 2059*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 2060*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 2061*cbda039fSThomas Faber MPI_VALIDATE_RET( E != NULL ); 2062*cbda039fSThomas Faber MPI_VALIDATE_RET( N != NULL ); 2063*cbda039fSThomas Faber 2064d9e6c9b5SThomas Faber if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) 2065c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 2066c2c66affSColin Finck 2067c2c66affSColin Finck if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) 2068c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 2069c2c66affSColin Finck 20702e53fc8eSThomas Faber if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS || 20712e53fc8eSThomas Faber mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS ) 20722e53fc8eSThomas Faber return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 20732e53fc8eSThomas Faber 2074c2c66affSColin Finck /* 2075c2c66affSColin Finck * Init temps and window size 2076c2c66affSColin Finck */ 2077c2c66affSColin Finck mpi_montg_init( &mm, N ); 2078c2c66affSColin Finck mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); 2079c2c66affSColin Finck mbedtls_mpi_init( &Apos ); 2080c2c66affSColin Finck memset( W, 0, sizeof( W ) ); 2081c2c66affSColin Finck 2082c2c66affSColin Finck i = mbedtls_mpi_bitlen( E ); 2083c2c66affSColin Finck 2084c2c66affSColin Finck wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : 2085c2c66affSColin Finck ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; 2086c2c66affSColin Finck 2087430656f0SThomas Faber #if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) 2088c2c66affSColin Finck if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) 2089c2c66affSColin Finck wsize = MBEDTLS_MPI_WINDOW_SIZE; 2090430656f0SThomas Faber #endif 2091c2c66affSColin Finck 2092c2c66affSColin Finck j = N->n + 1; 2093c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); 2094c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); 2095c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); 2096c2c66affSColin Finck 2097c2c66affSColin Finck /* 2098c2c66affSColin Finck * Compensate for negative A (and correct at the end) 2099c2c66affSColin Finck */ 2100c2c66affSColin Finck neg = ( A->s == -1 ); 2101c2c66affSColin Finck if( neg ) 2102c2c66affSColin Finck { 2103c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); 2104c2c66affSColin Finck Apos.s = 1; 2105c2c66affSColin Finck A = &Apos; 2106c2c66affSColin Finck } 2107c2c66affSColin Finck 2108c2c66affSColin Finck /* 2109c2c66affSColin Finck * If 1st call, pre-compute R^2 mod N 2110c2c66affSColin Finck */ 2111c2c66affSColin Finck if( _RR == NULL || _RR->p == NULL ) 2112c2c66affSColin Finck { 2113c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); 2114c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); 2115c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); 2116c2c66affSColin Finck 2117c2c66affSColin Finck if( _RR != NULL ) 2118c2c66affSColin Finck memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); 2119c2c66affSColin Finck } 2120c2c66affSColin Finck else 2121c2c66affSColin Finck memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); 2122c2c66affSColin Finck 2123c2c66affSColin Finck /* 2124c2c66affSColin Finck * W[1] = A * R^2 * R^-1 mod N = A * R mod N 2125c2c66affSColin Finck */ 2126c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) 2127c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); 2128c2c66affSColin Finck else 2129c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); 2130c2c66affSColin Finck 2131292f67afSThomas Faber mpi_montmul( &W[1], &RR, N, mm, &T ); 2132c2c66affSColin Finck 2133c2c66affSColin Finck /* 2134c2c66affSColin Finck * X = R^2 * R^-1 mod N = R mod N 2135c2c66affSColin Finck */ 2136c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); 2137292f67afSThomas Faber mpi_montred( X, N, mm, &T ); 2138c2c66affSColin Finck 2139c2c66affSColin Finck if( wsize > 1 ) 2140c2c66affSColin Finck { 2141c2c66affSColin Finck /* 2142c2c66affSColin Finck * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) 2143c2c66affSColin Finck */ 2144c2c66affSColin Finck j = one << ( wsize - 1 ); 2145c2c66affSColin Finck 2146c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); 2147c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); 2148c2c66affSColin Finck 2149c2c66affSColin Finck for( i = 0; i < wsize - 1; i++ ) 2150292f67afSThomas Faber mpi_montmul( &W[j], &W[j], N, mm, &T ); 2151c2c66affSColin Finck 2152c2c66affSColin Finck /* 2153c2c66affSColin Finck * W[i] = W[i - 1] * W[1] 2154c2c66affSColin Finck */ 2155c2c66affSColin Finck for( i = j + 1; i < ( one << wsize ); i++ ) 2156c2c66affSColin Finck { 2157c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); 2158c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); 2159c2c66affSColin Finck 2160292f67afSThomas Faber mpi_montmul( &W[i], &W[1], N, mm, &T ); 2161c2c66affSColin Finck } 2162c2c66affSColin Finck } 2163c2c66affSColin Finck 2164c2c66affSColin Finck nblimbs = E->n; 2165c2c66affSColin Finck bufsize = 0; 2166c2c66affSColin Finck nbits = 0; 2167c2c66affSColin Finck wbits = 0; 2168c2c66affSColin Finck state = 0; 2169c2c66affSColin Finck 2170c2c66affSColin Finck while( 1 ) 2171c2c66affSColin Finck { 2172c2c66affSColin Finck if( bufsize == 0 ) 2173c2c66affSColin Finck { 2174c2c66affSColin Finck if( nblimbs == 0 ) 2175c2c66affSColin Finck break; 2176c2c66affSColin Finck 2177c2c66affSColin Finck nblimbs--; 2178c2c66affSColin Finck 2179c2c66affSColin Finck bufsize = sizeof( mbedtls_mpi_uint ) << 3; 2180c2c66affSColin Finck } 2181c2c66affSColin Finck 2182c2c66affSColin Finck bufsize--; 2183c2c66affSColin Finck 2184c2c66affSColin Finck ei = (E->p[nblimbs] >> bufsize) & 1; 2185c2c66affSColin Finck 2186c2c66affSColin Finck /* 2187c2c66affSColin Finck * skip leading 0s 2188c2c66affSColin Finck */ 2189c2c66affSColin Finck if( ei == 0 && state == 0 ) 2190c2c66affSColin Finck continue; 2191c2c66affSColin Finck 2192c2c66affSColin Finck if( ei == 0 && state == 1 ) 2193c2c66affSColin Finck { 2194c2c66affSColin Finck /* 2195c2c66affSColin Finck * out of window, square X 2196c2c66affSColin Finck */ 2197292f67afSThomas Faber mpi_montmul( X, X, N, mm, &T ); 2198c2c66affSColin Finck continue; 2199c2c66affSColin Finck } 2200c2c66affSColin Finck 2201c2c66affSColin Finck /* 2202c2c66affSColin Finck * add ei to current window 2203c2c66affSColin Finck */ 2204c2c66affSColin Finck state = 2; 2205c2c66affSColin Finck 2206c2c66affSColin Finck nbits++; 2207c2c66affSColin Finck wbits |= ( ei << ( wsize - nbits ) ); 2208c2c66affSColin Finck 2209c2c66affSColin Finck if( nbits == wsize ) 2210c2c66affSColin Finck { 2211c2c66affSColin Finck /* 2212c2c66affSColin Finck * X = X^wsize R^-1 mod N 2213c2c66affSColin Finck */ 2214c2c66affSColin Finck for( i = 0; i < wsize; i++ ) 2215292f67afSThomas Faber mpi_montmul( X, X, N, mm, &T ); 2216c2c66affSColin Finck 2217c2c66affSColin Finck /* 2218c2c66affSColin Finck * X = X * W[wbits] R^-1 mod N 2219c2c66affSColin Finck */ 2220292f67afSThomas Faber mpi_montmul( X, &W[wbits], N, mm, &T ); 2221c2c66affSColin Finck 2222c2c66affSColin Finck state--; 2223c2c66affSColin Finck nbits = 0; 2224c2c66affSColin Finck wbits = 0; 2225c2c66affSColin Finck } 2226c2c66affSColin Finck } 2227c2c66affSColin Finck 2228c2c66affSColin Finck /* 2229c2c66affSColin Finck * process the remaining bits 2230c2c66affSColin Finck */ 2231c2c66affSColin Finck for( i = 0; i < nbits; i++ ) 2232c2c66affSColin Finck { 2233292f67afSThomas Faber mpi_montmul( X, X, N, mm, &T ); 2234c2c66affSColin Finck 2235c2c66affSColin Finck wbits <<= 1; 2236c2c66affSColin Finck 2237c2c66affSColin Finck if( ( wbits & ( one << wsize ) ) != 0 ) 2238292f67afSThomas Faber mpi_montmul( X, &W[1], N, mm, &T ); 2239c2c66affSColin Finck } 2240c2c66affSColin Finck 2241c2c66affSColin Finck /* 2242c2c66affSColin Finck * X = A^E * R * R^-1 mod N = A^E mod N 2243c2c66affSColin Finck */ 2244292f67afSThomas Faber mpi_montred( X, N, mm, &T ); 2245c2c66affSColin Finck 2246c2c66affSColin Finck if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) 2247c2c66affSColin Finck { 2248c2c66affSColin Finck X->s = -1; 2249c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); 2250c2c66affSColin Finck } 2251c2c66affSColin Finck 2252c2c66affSColin Finck cleanup: 2253c2c66affSColin Finck 2254c2c66affSColin Finck for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) 2255c2c66affSColin Finck mbedtls_mpi_free( &W[i] ); 2256c2c66affSColin Finck 2257c2c66affSColin Finck mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); 2258c2c66affSColin Finck 2259c2c66affSColin Finck if( _RR == NULL || _RR->p == NULL ) 2260c2c66affSColin Finck mbedtls_mpi_free( &RR ); 2261c2c66affSColin Finck 2262c2c66affSColin Finck return( ret ); 2263c2c66affSColin Finck } 2264c2c66affSColin Finck 2265c2c66affSColin Finck /* 2266c2c66affSColin Finck * Greatest common divisor: G = gcd(A, B) (HAC 14.54) 2267c2c66affSColin Finck */ 2268c2c66affSColin Finck int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) 2269c2c66affSColin Finck { 2270c2c66affSColin Finck int ret; 2271c2c66affSColin Finck size_t lz, lzt; 2272c2c66affSColin Finck mbedtls_mpi TG, TA, TB; 2273c2c66affSColin Finck 2274*cbda039fSThomas Faber MPI_VALIDATE_RET( G != NULL ); 2275*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 2276*cbda039fSThomas Faber MPI_VALIDATE_RET( B != NULL ); 2277*cbda039fSThomas Faber 2278c2c66affSColin Finck mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); 2279c2c66affSColin Finck 2280c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); 2281c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); 2282c2c66affSColin Finck 2283c2c66affSColin Finck lz = mbedtls_mpi_lsb( &TA ); 2284c2c66affSColin Finck lzt = mbedtls_mpi_lsb( &TB ); 2285c2c66affSColin Finck 2286c2c66affSColin Finck if( lzt < lz ) 2287c2c66affSColin Finck lz = lzt; 2288c2c66affSColin Finck 2289c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); 2290c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); 2291c2c66affSColin Finck 2292c2c66affSColin Finck TA.s = TB.s = 1; 2293c2c66affSColin Finck 2294c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) 2295c2c66affSColin Finck { 2296c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); 2297c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); 2298c2c66affSColin Finck 2299c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) 2300c2c66affSColin Finck { 2301c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); 2302c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); 2303c2c66affSColin Finck } 2304c2c66affSColin Finck else 2305c2c66affSColin Finck { 2306c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); 2307c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); 2308c2c66affSColin Finck } 2309c2c66affSColin Finck } 2310c2c66affSColin Finck 2311c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); 2312c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); 2313c2c66affSColin Finck 2314c2c66affSColin Finck cleanup: 2315c2c66affSColin Finck 2316c2c66affSColin Finck mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); 2317c2c66affSColin Finck 2318c2c66affSColin Finck return( ret ); 2319c2c66affSColin Finck } 2320c2c66affSColin Finck 2321c2c66affSColin Finck /* 2322c2c66affSColin Finck * Fill X with size bytes of random. 2323c2c66affSColin Finck * 2324c2c66affSColin Finck * Use a temporary bytes representation to make sure the result is the same 2325c2c66affSColin Finck * regardless of the platform endianness (useful when f_rng is actually 2326c2c66affSColin Finck * deterministic, eg for tests). 2327c2c66affSColin Finck */ 2328c2c66affSColin Finck int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, 2329c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2330c2c66affSColin Finck void *p_rng ) 2331c2c66affSColin Finck { 2332c2c66affSColin Finck int ret; 2333*cbda039fSThomas Faber size_t const limbs = CHARS_TO_LIMBS( size ); 2334*cbda039fSThomas Faber size_t const overhead = ( limbs * ciL ) - size; 2335*cbda039fSThomas Faber unsigned char *Xp; 2336c2c66affSColin Finck 2337*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 2338*cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL ); 2339c2c66affSColin Finck 2340*cbda039fSThomas Faber /* Ensure that target MPI has exactly the necessary number of limbs */ 2341*cbda039fSThomas Faber if( X->n != limbs ) 2342*cbda039fSThomas Faber { 2343*cbda039fSThomas Faber mbedtls_mpi_free( X ); 2344*cbda039fSThomas Faber mbedtls_mpi_init( X ); 2345*cbda039fSThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); 2346*cbda039fSThomas Faber } 2347*cbda039fSThomas Faber MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); 2348*cbda039fSThomas Faber 2349*cbda039fSThomas Faber Xp = (unsigned char*) X->p; 2350*cbda039fSThomas Faber MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) ); 2351*cbda039fSThomas Faber 2352*cbda039fSThomas Faber mpi_bigendian_to_host( X->p, limbs ); 2353c2c66affSColin Finck 2354c2c66affSColin Finck cleanup: 2355c2c66affSColin Finck return( ret ); 2356c2c66affSColin Finck } 2357c2c66affSColin Finck 2358c2c66affSColin Finck /* 2359c2c66affSColin Finck * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) 2360c2c66affSColin Finck */ 2361c2c66affSColin Finck int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) 2362c2c66affSColin Finck { 2363c2c66affSColin Finck int ret; 2364c2c66affSColin Finck mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; 2365*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 2366*cbda039fSThomas Faber MPI_VALIDATE_RET( A != NULL ); 2367*cbda039fSThomas Faber MPI_VALIDATE_RET( N != NULL ); 2368c2c66affSColin Finck 2369c2c66affSColin Finck if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) 2370c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 2371c2c66affSColin Finck 2372c2c66affSColin Finck mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); 2373c2c66affSColin Finck mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); 2374c2c66affSColin Finck mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); 2375c2c66affSColin Finck 2376c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); 2377c2c66affSColin Finck 2378c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) 2379c2c66affSColin Finck { 2380c2c66affSColin Finck ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2381c2c66affSColin Finck goto cleanup; 2382c2c66affSColin Finck } 2383c2c66affSColin Finck 2384c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); 2385c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); 2386c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); 2387c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); 2388c2c66affSColin Finck 2389c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); 2390c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); 2391c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); 2392c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); 2393c2c66affSColin Finck 2394c2c66affSColin Finck do 2395c2c66affSColin Finck { 2396c2c66affSColin Finck while( ( TU.p[0] & 1 ) == 0 ) 2397c2c66affSColin Finck { 2398c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); 2399c2c66affSColin Finck 2400c2c66affSColin Finck if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) 2401c2c66affSColin Finck { 2402c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); 2403c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); 2404c2c66affSColin Finck } 2405c2c66affSColin Finck 2406c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); 2407c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); 2408c2c66affSColin Finck } 2409c2c66affSColin Finck 2410c2c66affSColin Finck while( ( TV.p[0] & 1 ) == 0 ) 2411c2c66affSColin Finck { 2412c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); 2413c2c66affSColin Finck 2414c2c66affSColin Finck if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) 2415c2c66affSColin Finck { 2416c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); 2417c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); 2418c2c66affSColin Finck } 2419c2c66affSColin Finck 2420c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); 2421c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); 2422c2c66affSColin Finck } 2423c2c66affSColin Finck 2424c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) 2425c2c66affSColin Finck { 2426c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); 2427c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); 2428c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); 2429c2c66affSColin Finck } 2430c2c66affSColin Finck else 2431c2c66affSColin Finck { 2432c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); 2433c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); 2434c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); 2435c2c66affSColin Finck } 2436c2c66affSColin Finck } 2437c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); 2438c2c66affSColin Finck 2439c2c66affSColin Finck while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) 2440c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); 2441c2c66affSColin Finck 2442c2c66affSColin Finck while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) 2443c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); 2444c2c66affSColin Finck 2445c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); 2446c2c66affSColin Finck 2447c2c66affSColin Finck cleanup: 2448c2c66affSColin Finck 2449c2c66affSColin Finck mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); 2450c2c66affSColin Finck mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); 2451c2c66affSColin Finck mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); 2452c2c66affSColin Finck 2453c2c66affSColin Finck return( ret ); 2454c2c66affSColin Finck } 2455c2c66affSColin Finck 2456c2c66affSColin Finck #if defined(MBEDTLS_GENPRIME) 2457c2c66affSColin Finck 2458c2c66affSColin Finck static const int small_prime[] = 2459c2c66affSColin Finck { 2460c2c66affSColin Finck 3, 5, 7, 11, 13, 17, 19, 23, 2461c2c66affSColin Finck 29, 31, 37, 41, 43, 47, 53, 59, 2462c2c66affSColin Finck 61, 67, 71, 73, 79, 83, 89, 97, 2463c2c66affSColin Finck 101, 103, 107, 109, 113, 127, 131, 137, 2464c2c66affSColin Finck 139, 149, 151, 157, 163, 167, 173, 179, 2465c2c66affSColin Finck 181, 191, 193, 197, 199, 211, 223, 227, 2466c2c66affSColin Finck 229, 233, 239, 241, 251, 257, 263, 269, 2467c2c66affSColin Finck 271, 277, 281, 283, 293, 307, 311, 313, 2468c2c66affSColin Finck 317, 331, 337, 347, 349, 353, 359, 367, 2469c2c66affSColin Finck 373, 379, 383, 389, 397, 401, 409, 419, 2470c2c66affSColin Finck 421, 431, 433, 439, 443, 449, 457, 461, 2471c2c66affSColin Finck 463, 467, 479, 487, 491, 499, 503, 509, 2472c2c66affSColin Finck 521, 523, 541, 547, 557, 563, 569, 571, 2473c2c66affSColin Finck 577, 587, 593, 599, 601, 607, 613, 617, 2474c2c66affSColin Finck 619, 631, 641, 643, 647, 653, 659, 661, 2475c2c66affSColin Finck 673, 677, 683, 691, 701, 709, 719, 727, 2476c2c66affSColin Finck 733, 739, 743, 751, 757, 761, 769, 773, 2477c2c66affSColin Finck 787, 797, 809, 811, 821, 823, 827, 829, 2478c2c66affSColin Finck 839, 853, 857, 859, 863, 877, 881, 883, 2479c2c66affSColin Finck 887, 907, 911, 919, 929, 937, 941, 947, 2480c2c66affSColin Finck 953, 967, 971, 977, 983, 991, 997, -103 2481c2c66affSColin Finck }; 2482c2c66affSColin Finck 2483c2c66affSColin Finck /* 2484c2c66affSColin Finck * Small divisors test (X must be positive) 2485c2c66affSColin Finck * 2486c2c66affSColin Finck * Return values: 2487c2c66affSColin Finck * 0: no small factor (possible prime, more tests needed) 2488c2c66affSColin Finck * 1: certain prime 2489c2c66affSColin Finck * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime 2490c2c66affSColin Finck * other negative: error 2491c2c66affSColin Finck */ 2492c2c66affSColin Finck static int mpi_check_small_factors( const mbedtls_mpi *X ) 2493c2c66affSColin Finck { 2494c2c66affSColin Finck int ret = 0; 2495c2c66affSColin Finck size_t i; 2496c2c66affSColin Finck mbedtls_mpi_uint r; 2497c2c66affSColin Finck 2498c2c66affSColin Finck if( ( X->p[0] & 1 ) == 0 ) 2499c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2500c2c66affSColin Finck 2501c2c66affSColin Finck for( i = 0; small_prime[i] > 0; i++ ) 2502c2c66affSColin Finck { 2503c2c66affSColin Finck if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) 2504c2c66affSColin Finck return( 1 ); 2505c2c66affSColin Finck 2506c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); 2507c2c66affSColin Finck 2508c2c66affSColin Finck if( r == 0 ) 2509c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2510c2c66affSColin Finck } 2511c2c66affSColin Finck 2512c2c66affSColin Finck cleanup: 2513c2c66affSColin Finck return( ret ); 2514c2c66affSColin Finck } 2515c2c66affSColin Finck 2516c2c66affSColin Finck /* 2517c2c66affSColin Finck * Miller-Rabin pseudo-primality test (HAC 4.24) 2518c2c66affSColin Finck */ 25190ba5bc40SThomas Faber static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, 2520c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2521c2c66affSColin Finck void *p_rng ) 2522c2c66affSColin Finck { 2523c2c66affSColin Finck int ret, count; 25240ba5bc40SThomas Faber size_t i, j, k, s; 2525c2c66affSColin Finck mbedtls_mpi W, R, T, A, RR; 2526c2c66affSColin Finck 2527*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 2528*cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL ); 2529*cbda039fSThomas Faber 2530*cbda039fSThomas Faber mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); 2531*cbda039fSThomas Faber mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); 2532c2c66affSColin Finck mbedtls_mpi_init( &RR ); 2533c2c66affSColin Finck 2534c2c66affSColin Finck /* 2535c2c66affSColin Finck * W = |X| - 1 2536c2c66affSColin Finck * R = W >> lsb( W ) 2537c2c66affSColin Finck */ 2538c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); 2539c2c66affSColin Finck s = mbedtls_mpi_lsb( &W ); 2540c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); 2541c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); 2542c2c66affSColin Finck 25430ba5bc40SThomas Faber for( i = 0; i < rounds; i++ ) 2544c2c66affSColin Finck { 2545c2c66affSColin Finck /* 2546c2c66affSColin Finck * pick a random A, 1 < A < |X| - 1 2547c2c66affSColin Finck */ 2548c2c66affSColin Finck count = 0; 2549c2c66affSColin Finck do { 2550c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); 2551c2c66affSColin Finck 2552c2c66affSColin Finck j = mbedtls_mpi_bitlen( &A ); 2553c2c66affSColin Finck k = mbedtls_mpi_bitlen( &W ); 2554c2c66affSColin Finck if (j > k) { 25550ba5bc40SThomas Faber A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; 2556c2c66affSColin Finck } 2557c2c66affSColin Finck 2558c2c66affSColin Finck if (count++ > 30) { 2559c1eccaffSThomas Faber ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2560c1eccaffSThomas Faber goto cleanup; 2561c2c66affSColin Finck } 2562c2c66affSColin Finck 2563c2c66affSColin Finck } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || 2564c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); 2565c2c66affSColin Finck 2566c2c66affSColin Finck /* 2567c2c66affSColin Finck * A = A^R mod |X| 2568c2c66affSColin Finck */ 2569c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); 2570c2c66affSColin Finck 2571c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || 2572c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2573c2c66affSColin Finck continue; 2574c2c66affSColin Finck 2575c2c66affSColin Finck j = 1; 2576c2c66affSColin Finck while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) 2577c2c66affSColin Finck { 2578c2c66affSColin Finck /* 2579c2c66affSColin Finck * A = A * A mod |X| 2580c2c66affSColin Finck */ 2581c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); 2582c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); 2583c2c66affSColin Finck 2584c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2585c2c66affSColin Finck break; 2586c2c66affSColin Finck 2587c2c66affSColin Finck j++; 2588c2c66affSColin Finck } 2589c2c66affSColin Finck 2590c2c66affSColin Finck /* 2591c2c66affSColin Finck * not prime if A != |X| - 1 or A == 1 2592c2c66affSColin Finck */ 2593c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || 2594c2c66affSColin Finck mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) 2595c2c66affSColin Finck { 2596c2c66affSColin Finck ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2597c2c66affSColin Finck break; 2598c2c66affSColin Finck } 2599c2c66affSColin Finck } 2600c2c66affSColin Finck 2601c2c66affSColin Finck cleanup: 2602*cbda039fSThomas Faber mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); 2603*cbda039fSThomas Faber mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); 2604c2c66affSColin Finck mbedtls_mpi_free( &RR ); 2605c2c66affSColin Finck 2606c2c66affSColin Finck return( ret ); 2607c2c66affSColin Finck } 2608c2c66affSColin Finck 2609c2c66affSColin Finck /* 2610c2c66affSColin Finck * Pseudo-primality test: small factors, then Miller-Rabin 2611c2c66affSColin Finck */ 2612*cbda039fSThomas Faber int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, 2613c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2614c2c66affSColin Finck void *p_rng ) 2615c2c66affSColin Finck { 2616c2c66affSColin Finck int ret; 2617c2c66affSColin Finck mbedtls_mpi XX; 2618*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 2619*cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL ); 2620c2c66affSColin Finck 2621c2c66affSColin Finck XX.s = 1; 2622c2c66affSColin Finck XX.n = X->n; 2623c2c66affSColin Finck XX.p = X->p; 2624c2c66affSColin Finck 2625c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || 2626c2c66affSColin Finck mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) 2627c2c66affSColin Finck return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 2628c2c66affSColin Finck 2629c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) 2630c2c66affSColin Finck return( 0 ); 2631c2c66affSColin Finck 2632c2c66affSColin Finck if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) 2633c2c66affSColin Finck { 2634c2c66affSColin Finck if( ret == 1 ) 2635c2c66affSColin Finck return( 0 ); 2636c2c66affSColin Finck 2637c2c66affSColin Finck return( ret ); 2638c2c66affSColin Finck } 2639c2c66affSColin Finck 26400ba5bc40SThomas Faber return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); 26410ba5bc40SThomas Faber } 26420ba5bc40SThomas Faber 2643*cbda039fSThomas Faber #if !defined(MBEDTLS_DEPRECATED_REMOVED) 26440ba5bc40SThomas Faber /* 26450ba5bc40SThomas Faber * Pseudo-primality test, error probability 2^-80 26460ba5bc40SThomas Faber */ 26470ba5bc40SThomas Faber int mbedtls_mpi_is_prime( const mbedtls_mpi *X, 26480ba5bc40SThomas Faber int (*f_rng)(void *, unsigned char *, size_t), 26490ba5bc40SThomas Faber void *p_rng ) 26500ba5bc40SThomas Faber { 2651*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 2652*cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL ); 2653*cbda039fSThomas Faber 2654*cbda039fSThomas Faber /* 2655*cbda039fSThomas Faber * In the past our key generation aimed for an error rate of at most 2656*cbda039fSThomas Faber * 2^-80. Since this function is deprecated, aim for the same certainty 2657*cbda039fSThomas Faber * here as well. 2658*cbda039fSThomas Faber */ 2659*cbda039fSThomas Faber return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) ); 2660c2c66affSColin Finck } 2661*cbda039fSThomas Faber #endif 2662c2c66affSColin Finck 2663c2c66affSColin Finck /* 2664c2c66affSColin Finck * Prime number generation 2665*cbda039fSThomas Faber * 2666*cbda039fSThomas Faber * To generate an RSA key in a way recommended by FIPS 186-4, both primes must 2667*cbda039fSThomas Faber * be either 1024 bits or 1536 bits long, and flags must contain 2668*cbda039fSThomas Faber * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. 2669c2c66affSColin Finck */ 2670*cbda039fSThomas Faber int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, 2671c2c66affSColin Finck int (*f_rng)(void *, unsigned char *, size_t), 2672c2c66affSColin Finck void *p_rng ) 2673c2c66affSColin Finck { 2674*cbda039fSThomas Faber #ifdef MBEDTLS_HAVE_INT64 2675*cbda039fSThomas Faber // ceil(2^63.5) 2676*cbda039fSThomas Faber #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL 2677*cbda039fSThomas Faber #else 2678*cbda039fSThomas Faber // ceil(2^31.5) 2679*cbda039fSThomas Faber #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U 2680*cbda039fSThomas Faber #endif 2681*cbda039fSThomas Faber int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; 2682c2c66affSColin Finck size_t k, n; 26830ba5bc40SThomas Faber int rounds; 2684c2c66affSColin Finck mbedtls_mpi_uint r; 2685c2c66affSColin Finck mbedtls_mpi Y; 2686c2c66affSColin Finck 2687*cbda039fSThomas Faber MPI_VALIDATE_RET( X != NULL ); 2688*cbda039fSThomas Faber MPI_VALIDATE_RET( f_rng != NULL ); 2689*cbda039fSThomas Faber 2690c2c66affSColin Finck if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) 2691c2c66affSColin Finck return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); 2692c2c66affSColin Finck 2693c2c66affSColin Finck mbedtls_mpi_init( &Y ); 2694c2c66affSColin Finck 2695c2c66affSColin Finck n = BITS_TO_LIMBS( nbits ); 2696c2c66affSColin Finck 2697*cbda039fSThomas Faber if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) 2698*cbda039fSThomas Faber { 26990ba5bc40SThomas Faber /* 27000ba5bc40SThomas Faber * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 27010ba5bc40SThomas Faber */ 27020ba5bc40SThomas Faber rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : 27030ba5bc40SThomas Faber ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : 27040ba5bc40SThomas Faber ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); 2705*cbda039fSThomas Faber } 2706*cbda039fSThomas Faber else 2707*cbda039fSThomas Faber { 2708*cbda039fSThomas Faber /* 2709*cbda039fSThomas Faber * 2^-100 error probability, number of rounds computed based on HAC, 2710*cbda039fSThomas Faber * fact 4.48 2711*cbda039fSThomas Faber */ 2712*cbda039fSThomas Faber rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : 2713*cbda039fSThomas Faber ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : 2714*cbda039fSThomas Faber ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : 2715*cbda039fSThomas Faber ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); 2716*cbda039fSThomas Faber } 27170ba5bc40SThomas Faber 2718*cbda039fSThomas Faber while( 1 ) 2719*cbda039fSThomas Faber { 2720c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); 2721*cbda039fSThomas Faber /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ 2722*cbda039fSThomas Faber if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; 2723c2c66affSColin Finck 2724*cbda039fSThomas Faber k = n * biL; 2725*cbda039fSThomas Faber if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); 2726c2c66affSColin Finck X->p[0] |= 1; 2727c2c66affSColin Finck 2728*cbda039fSThomas Faber if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) 2729c2c66affSColin Finck { 2730*cbda039fSThomas Faber ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); 2731*cbda039fSThomas Faber 2732c2c66affSColin Finck if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) 2733c2c66affSColin Finck goto cleanup; 2734c2c66affSColin Finck } 2735c2c66affSColin Finck else 2736c2c66affSColin Finck { 2737c2c66affSColin Finck /* 2738c2c66affSColin Finck * An necessary condition for Y and X = 2Y + 1 to be prime 2739c2c66affSColin Finck * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). 2740c2c66affSColin Finck * Make sure it is satisfied, while keeping X = 3 mod 4 2741c2c66affSColin Finck */ 2742c2c66affSColin Finck 2743c2c66affSColin Finck X->p[0] |= 2; 2744c2c66affSColin Finck 2745c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); 2746c2c66affSColin Finck if( r == 0 ) 2747c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); 2748c2c66affSColin Finck else if( r == 1 ) 2749c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); 2750c2c66affSColin Finck 2751c2c66affSColin Finck /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ 2752c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); 2753c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); 2754c2c66affSColin Finck 2755c2c66affSColin Finck while( 1 ) 2756c2c66affSColin Finck { 2757c2c66affSColin Finck /* 2758c2c66affSColin Finck * First, check small factors for X and Y 2759c2c66affSColin Finck * before doing Miller-Rabin on any of them 2760c2c66affSColin Finck */ 2761c2c66affSColin Finck if( ( ret = mpi_check_small_factors( X ) ) == 0 && 2762c2c66affSColin Finck ( ret = mpi_check_small_factors( &Y ) ) == 0 && 27630ba5bc40SThomas Faber ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) 27640ba5bc40SThomas Faber == 0 && 27650ba5bc40SThomas Faber ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) 27660ba5bc40SThomas Faber == 0 ) 2767*cbda039fSThomas Faber goto cleanup; 2768c2c66affSColin Finck 2769c2c66affSColin Finck if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) 2770c2c66affSColin Finck goto cleanup; 2771c2c66affSColin Finck 2772c2c66affSColin Finck /* 2773c2c66affSColin Finck * Next candidates. We want to preserve Y = (X-1) / 2 and 2774c2c66affSColin Finck * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) 2775c2c66affSColin Finck * so up Y by 6 and X by 12. 2776c2c66affSColin Finck */ 2777c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); 2778c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); 2779c2c66affSColin Finck } 2780c2c66affSColin Finck } 2781*cbda039fSThomas Faber } 2782c2c66affSColin Finck 2783c2c66affSColin Finck cleanup: 2784c2c66affSColin Finck 2785c2c66affSColin Finck mbedtls_mpi_free( &Y ); 2786c2c66affSColin Finck 2787c2c66affSColin Finck return( ret ); 2788c2c66affSColin Finck } 2789c2c66affSColin Finck 2790c2c66affSColin Finck #endif /* MBEDTLS_GENPRIME */ 2791c2c66affSColin Finck 2792c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST) 2793c2c66affSColin Finck 2794c2c66affSColin Finck #define GCD_PAIR_COUNT 3 2795c2c66affSColin Finck 2796c2c66affSColin Finck static const int gcd_pairs[GCD_PAIR_COUNT][3] = 2797c2c66affSColin Finck { 2798c2c66affSColin Finck { 693, 609, 21 }, 2799c2c66affSColin Finck { 1764, 868, 28 }, 2800c2c66affSColin Finck { 768454923, 542167814, 1 } 2801c2c66affSColin Finck }; 2802c2c66affSColin Finck 2803c2c66affSColin Finck /* 2804c2c66affSColin Finck * Checkup routine 2805c2c66affSColin Finck */ 2806c2c66affSColin Finck int mbedtls_mpi_self_test( int verbose ) 2807c2c66affSColin Finck { 2808c2c66affSColin Finck int ret, i; 2809c2c66affSColin Finck mbedtls_mpi A, E, N, X, Y, U, V; 2810c2c66affSColin Finck 2811c2c66affSColin Finck mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); 2812c2c66affSColin Finck mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); 2813c2c66affSColin Finck 2814c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, 2815c2c66affSColin Finck "EFE021C2645FD1DC586E69184AF4A31E" \ 2816c2c66affSColin Finck "D5F53E93B5F123FA41680867BA110131" \ 2817c2c66affSColin Finck "944FE7952E2517337780CB0DB80E61AA" \ 2818c2c66affSColin Finck "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); 2819c2c66affSColin Finck 2820c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, 2821c2c66affSColin Finck "B2E7EFD37075B9F03FF989C7C5051C20" \ 2822c2c66affSColin Finck "34D2A323810251127E7BF8625A4F49A5" \ 2823c2c66affSColin Finck "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ 2824c2c66affSColin Finck "5B5C25763222FEFCCFC38B832366C29E" ) ); 2825c2c66affSColin Finck 2826c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, 2827c2c66affSColin Finck "0066A198186C18C10B2F5ED9B522752A" \ 2828c2c66affSColin Finck "9830B69916E535C8F047518A889A43A5" \ 2829c2c66affSColin Finck "94B6BED27A168D31D4A52F88925AA8F5" ) ); 2830c2c66affSColin Finck 2831c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); 2832c2c66affSColin Finck 2833c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2834c2c66affSColin Finck "602AB7ECA597A3D6B56FF9829A5E8B85" \ 2835c2c66affSColin Finck "9E857EA95A03512E2BAE7391688D264A" \ 2836c2c66affSColin Finck "A5663B0341DB9CCFD2C4C5F421FEC814" \ 2837c2c66affSColin Finck "8001B72E848A38CAE1C65F78E56ABDEF" \ 2838c2c66affSColin Finck "E12D3C039B8A02D6BE593F0BBBDA56F1" \ 2839c2c66affSColin Finck "ECF677152EF804370C1A305CAF3B5BF1" \ 2840c2c66affSColin Finck "30879B56C61DE584A0F53A2447A51E" ) ); 2841c2c66affSColin Finck 2842c2c66affSColin Finck if( verbose != 0 ) 2843c2c66affSColin Finck mbedtls_printf( " MPI test #1 (mul_mpi): " ); 2844c2c66affSColin Finck 2845c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2846c2c66affSColin Finck { 2847c2c66affSColin Finck if( verbose != 0 ) 2848c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2849c2c66affSColin Finck 2850c2c66affSColin Finck ret = 1; 2851c2c66affSColin Finck goto cleanup; 2852c2c66affSColin Finck } 2853c2c66affSColin Finck 2854c2c66affSColin Finck if( verbose != 0 ) 2855c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2856c2c66affSColin Finck 2857c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); 2858c2c66affSColin Finck 2859c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2860c2c66affSColin Finck "256567336059E52CAE22925474705F39A94" ) ); 2861c2c66affSColin Finck 2862c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, 2863c2c66affSColin Finck "6613F26162223DF488E9CD48CC132C7A" \ 2864c2c66affSColin Finck "0AC93C701B001B092E4E5B9F73BCD27B" \ 2865c2c66affSColin Finck "9EE50D0657C77F374E903CDFA4C642" ) ); 2866c2c66affSColin Finck 2867c2c66affSColin Finck if( verbose != 0 ) 2868c2c66affSColin Finck mbedtls_printf( " MPI test #2 (div_mpi): " ); 2869c2c66affSColin Finck 2870c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || 2871c2c66affSColin Finck mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) 2872c2c66affSColin Finck { 2873c2c66affSColin Finck if( verbose != 0 ) 2874c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2875c2c66affSColin Finck 2876c2c66affSColin Finck ret = 1; 2877c2c66affSColin Finck goto cleanup; 2878c2c66affSColin Finck } 2879c2c66affSColin Finck 2880c2c66affSColin Finck if( verbose != 0 ) 2881c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2882c2c66affSColin Finck 2883c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); 2884c2c66affSColin Finck 2885c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2886c2c66affSColin Finck "36E139AEA55215609D2816998ED020BB" \ 2887c2c66affSColin Finck "BD96C37890F65171D948E9BC7CBAA4D9" \ 2888c2c66affSColin Finck "325D24D6A3C12710F10A09FA08AB87" ) ); 2889c2c66affSColin Finck 2890c2c66affSColin Finck if( verbose != 0 ) 2891c2c66affSColin Finck mbedtls_printf( " MPI test #3 (exp_mod): " ); 2892c2c66affSColin Finck 2893c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2894c2c66affSColin Finck { 2895c2c66affSColin Finck if( verbose != 0 ) 2896c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2897c2c66affSColin Finck 2898c2c66affSColin Finck ret = 1; 2899c2c66affSColin Finck goto cleanup; 2900c2c66affSColin Finck } 2901c2c66affSColin Finck 2902c2c66affSColin Finck if( verbose != 0 ) 2903c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2904c2c66affSColin Finck 2905c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); 2906c2c66affSColin Finck 2907c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, 2908c2c66affSColin Finck "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ 2909c2c66affSColin Finck "C3DBA76456363A10869622EAC2DD84EC" \ 2910c2c66affSColin Finck "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); 2911c2c66affSColin Finck 2912c2c66affSColin Finck if( verbose != 0 ) 2913c2c66affSColin Finck mbedtls_printf( " MPI test #4 (inv_mod): " ); 2914c2c66affSColin Finck 2915c2c66affSColin Finck if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) 2916c2c66affSColin Finck { 2917c2c66affSColin Finck if( verbose != 0 ) 2918c2c66affSColin Finck mbedtls_printf( "failed\n" ); 2919c2c66affSColin Finck 2920c2c66affSColin Finck ret = 1; 2921c2c66affSColin Finck goto cleanup; 2922c2c66affSColin Finck } 2923c2c66affSColin Finck 2924c2c66affSColin Finck if( verbose != 0 ) 2925c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2926c2c66affSColin Finck 2927c2c66affSColin Finck if( verbose != 0 ) 2928c2c66affSColin Finck mbedtls_printf( " MPI test #5 (simple gcd): " ); 2929c2c66affSColin Finck 2930c2c66affSColin Finck for( i = 0; i < GCD_PAIR_COUNT; i++ ) 2931c2c66affSColin Finck { 2932c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); 2933c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); 2934c2c66affSColin Finck 2935c2c66affSColin Finck MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); 2936c2c66affSColin Finck 2937c2c66affSColin Finck if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) 2938c2c66affSColin Finck { 2939c2c66affSColin Finck if( verbose != 0 ) 2940c2c66affSColin Finck mbedtls_printf( "failed at %d\n", i ); 2941c2c66affSColin Finck 2942c2c66affSColin Finck ret = 1; 2943c2c66affSColin Finck goto cleanup; 2944c2c66affSColin Finck } 2945c2c66affSColin Finck } 2946c2c66affSColin Finck 2947c2c66affSColin Finck if( verbose != 0 ) 2948c2c66affSColin Finck mbedtls_printf( "passed\n" ); 2949c2c66affSColin Finck 2950c2c66affSColin Finck cleanup: 2951c2c66affSColin Finck 2952c2c66affSColin Finck if( ret != 0 && verbose != 0 ) 2953c2c66affSColin Finck mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); 2954c2c66affSColin Finck 2955c2c66affSColin Finck mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); 2956c2c66affSColin Finck mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); 2957c2c66affSColin Finck 2958c2c66affSColin Finck if( verbose != 0 ) 2959c2c66affSColin Finck mbedtls_printf( "\n" ); 2960c2c66affSColin Finck 2961c2c66affSColin Finck return( ret ); 2962c2c66affSColin Finck } 2963c2c66affSColin Finck 2964c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */ 2965c2c66affSColin Finck 2966c2c66affSColin Finck #endif /* MBEDTLS_BIGNUM_C */ 2967