1/* mpi-inline.h - Internal to the Multi Precision Integers 2 * Copyright (C) 1994, 1996, 1998, 1999, 3 * 2001, 2002 Free Software Foundation, Inc. 4 * 5 * This file is part of Libgcrypt. 6 * 7 * Libgcrypt is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser General Public License as 9 * published by the Free Software Foundation; either version 2.1 of 10 * the License, or (at your option) any later version. 11 * 12 * Libgcrypt is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 20 * 21 * Note: This code is heavily based on the GNU MP Library. 22 * Actually it's the same code with only minor changes in the 23 * way the data is stored; this is to support the abstraction 24 * of an optional secure memory allocation which may be used 25 * to avoid revealing of sensitive data due to paging etc. 26 */ 27 28#ifndef G10_MPI_INLINE_H 29#define G10_MPI_INLINE_H 30 31#ifndef G10_MPI_INLINE_DECL 32#define G10_MPI_INLINE_DECL extern __inline__ 33#endif 34 35G10_MPI_INLINE_DECL mpi_limb_t 36_gcry_mpih_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, 37 mpi_size_t s1_size, mpi_limb_t s2_limb) 38{ 39 mpi_limb_t x; 40 41 x = *s1_ptr++; 42 s2_limb += x; 43 *res_ptr++ = s2_limb; 44 if( s2_limb < x ) { /* sum is less than the left operand: handle carry */ 45 while( --s1_size ) { 46 x = *s1_ptr++ + 1; /* add carry */ 47 *res_ptr++ = x; /* and store */ 48 if( x ) /* not 0 (no overflow): we can stop */ 49 goto leave; 50 } 51 return 1; /* return carry (size of s1 to small) */ 52 } 53 54 leave: 55 if( res_ptr != s1_ptr ) { /* not the same variable */ 56 mpi_size_t i; /* copy the rest */ 57 for( i=0; i < s1_size-1; i++ ) 58 res_ptr[i] = s1_ptr[i]; 59 } 60 return 0; /* no carry */ 61} 62 63 64 65G10_MPI_INLINE_DECL mpi_limb_t 66_gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, 67 mpi_ptr_t s2_ptr, mpi_size_t s2_size) 68{ 69 mpi_limb_t cy = 0; 70 71 if( s2_size ) 72 cy = _gcry_mpih_add_n( res_ptr, s1_ptr, s2_ptr, s2_size ); 73 74 if( s1_size - s2_size ) 75 cy = _gcry_mpih_add_1( res_ptr + s2_size, s1_ptr + s2_size, 76 s1_size - s2_size, cy); 77 return cy; 78} 79 80 81G10_MPI_INLINE_DECL mpi_limb_t 82_gcry_mpih_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, 83 mpi_size_t s1_size, mpi_limb_t s2_limb ) 84{ 85 mpi_limb_t x; 86 87 x = *s1_ptr++; 88 s2_limb = x - s2_limb; 89 *res_ptr++ = s2_limb; 90 if( s2_limb > x ) { 91 while( --s1_size ) { 92 x = *s1_ptr++; 93 *res_ptr++ = x - 1; 94 if( x ) 95 goto leave; 96 } 97 return 1; 98 } 99 100 leave: 101 if( res_ptr != s1_ptr ) { 102 mpi_size_t i; 103 for( i=0; i < s1_size-1; i++ ) 104 res_ptr[i] = s1_ptr[i]; 105 } 106 return 0; 107} 108 109 110 111G10_MPI_INLINE_DECL mpi_limb_t 112_gcry_mpih_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, 113 mpi_ptr_t s2_ptr, mpi_size_t s2_size) 114{ 115 mpi_limb_t cy = 0; 116 117 if( s2_size ) 118 cy = _gcry_mpih_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size); 119 120 if( s1_size - s2_size ) 121 cy = _gcry_mpih_sub_1(res_ptr + s2_size, s1_ptr + s2_size, 122 s1_size - s2_size, cy); 123 return cy; 124} 125 126/**************** 127 * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. 128 * There are no restrictions on the relative sizes of 129 * the two arguments. 130 * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. 131 */ 132G10_MPI_INLINE_DECL int 133_gcry_mpih_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ) 134{ 135 mpi_size_t i; 136 mpi_limb_t op1_word, op2_word; 137 138 for( i = size - 1; i >= 0 ; i--) { 139 op1_word = op1_ptr[i]; 140 op2_word = op2_ptr[i]; 141 if( op1_word != op2_word ) 142 goto diff; 143 } 144 return 0; 145 146 diff: 147 /* This can *not* be simplified to 148 * op2_word - op2_word 149 * since that expression might give signed overflow. */ 150 return (op1_word > op2_word) ? 1 : -1; 151} 152 153 154#endif /*G10_MPI_INLINE_H*/ 155