1/* mpiutil.ac - Utility functions for MPI 2 * Copyright (C) 1998, 2000, 2001, 2002, 2003, 3 * 2007 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, see <http://www.gnu.org/licenses/>. 19 */ 20 21#include <config.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25 26#include "g10lib.h" 27#include "mpi-internal.h" 28#include "mod-source-info.h" 29 30 31const char * 32_gcry_mpi_get_hw_config (void) 33{ 34 return mod_source_info + 1; 35} 36 37 38/**************** 39 * Note: It was a bad idea to use the number of limbs to allocate 40 * because on a alpha the limbs are large but we normally need 41 * integers of n bits - So we should change this to bits (or bytes). 42 * 43 * But mpi_alloc is used in a lot of places :-(. New code 44 * should use mpi_new. 45 */ 46gcry_mpi_t 47_gcry_mpi_alloc( unsigned nlimbs ) 48{ 49 gcry_mpi_t a; 50 51 a = gcry_xmalloc( sizeof *a ); 52 a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL; 53 a->alloced = nlimbs; 54 a->nlimbs = 0; 55 a->sign = 0; 56 a->flags = 0; 57 return a; 58} 59 60void 61_gcry_mpi_m_check( gcry_mpi_t a ) 62{ 63 _gcry_check_heap(a); 64 _gcry_check_heap(a->d); 65} 66 67gcry_mpi_t 68_gcry_mpi_alloc_secure( unsigned nlimbs ) 69{ 70 gcry_mpi_t a; 71 72 a = gcry_xmalloc( sizeof *a ); 73 a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL; 74 a->alloced = nlimbs; 75 a->flags = 1; 76 a->nlimbs = 0; 77 a->sign = 0; 78 return a; 79} 80 81 82 83mpi_ptr_t 84_gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure ) 85{ 86 mpi_ptr_t p; 87 size_t len; 88 89 len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t); 90 p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len); 91 if (! nlimbs) 92 *p = 0; 93 94 return p; 95} 96 97void 98_gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs) 99{ 100 if (a) 101 { 102 size_t len = nlimbs * sizeof(mpi_limb_t); 103 104 /* If we have information on the number of allocated limbs, we 105 better wipe that space out. This is a failsafe feature if 106 secure memory has been disabled or was not properly 107 implemented in user provided allocation functions. */ 108 if (len) 109 wipememory (a, len); 110 gcry_free(a); 111 } 112} 113 114 115void 116_gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs ) 117{ 118 _gcry_mpi_free_limb_space (a->d, a->alloced); 119 a->d = ap; 120 a->alloced = nlimbs; 121} 122 123 124 125/**************** 126 * Resize the array of A to NLIMBS. The additional space is cleared 127 * (set to 0). 128 */ 129void 130_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs) 131{ 132 size_t i; 133 134 if (nlimbs <= a->alloced) 135 { 136 /* We only need to clear the new space (this is a nop if the 137 limb space is already of the correct size. */ 138 for (i=a->nlimbs; i < a->alloced; i++) 139 a->d[i] = 0; 140 return; 141 } 142 143 /* Actually resize the limb space. */ 144 if (a->d) 145 { 146 a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t)); 147 for (i=a->alloced; i < nlimbs; i++) 148 a->d[i] = 0; 149 } 150 else 151 { 152 if (a->flags & 1) 153 /* Secure memory is wanted. */ 154 a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t)); 155 else 156 /* Standard memory. */ 157 a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t)); 158 } 159 a->alloced = nlimbs; 160} 161 162void 163_gcry_mpi_clear( gcry_mpi_t a ) 164{ 165 a->nlimbs = 0; 166 a->flags = 0; 167} 168 169 170void 171_gcry_mpi_free( gcry_mpi_t a ) 172{ 173 if (!a ) 174 return; 175 if ((a->flags & 4)) 176 gcry_free( a->d ); 177 else 178 { 179 _gcry_mpi_free_limb_space(a->d, a->alloced); 180 } 181 if ((a->flags & ~7)) 182 log_bug("invalid flag value in mpi\n"); 183 gcry_free(a); 184} 185 186static void 187mpi_set_secure( gcry_mpi_t a ) 188{ 189 mpi_ptr_t ap, bp; 190 191 if ( (a->flags & 1) ) 192 return; 193 a->flags |= 1; 194 ap = a->d; 195 if (!a->nlimbs) 196 { 197 gcry_assert (!ap); 198 return; 199 } 200 bp = mpi_alloc_limb_space (a->nlimbs, 1); 201 MPN_COPY( bp, ap, a->nlimbs ); 202 a->d = bp; 203 _gcry_mpi_free_limb_space (ap, a->alloced); 204} 205 206 207gcry_mpi_t 208gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits ) 209{ 210 if (!a) 211 a = mpi_alloc(0); 212 213 if( a->flags & 4 ) 214 gcry_free( a->d ); 215 else 216 _gcry_mpi_free_limb_space (a->d, a->alloced); 217 218 a->d = p; 219 a->alloced = 0; 220 a->nlimbs = 0; 221 a->sign = nbits; 222 a->flags = 4; 223 return a; 224} 225 226 227void * 228gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits ) 229{ 230 if( !(a->flags & 4) ) 231 log_bug("mpi_get_opaque on normal mpi\n"); 232 if( nbits ) 233 *nbits = a->sign; 234 return a->d; 235} 236 237 238/**************** 239 * Note: This copy function should not interpret the MPI 240 * but copy it transparently. 241 */ 242gcry_mpi_t 243gcry_mpi_copy( gcry_mpi_t a ) 244{ 245 int i; 246 gcry_mpi_t b; 247 248 if( a && (a->flags & 4) ) { 249 void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 ) 250 : gcry_xmalloc( (a->sign+7)/8 ); 251 memcpy( p, a->d, (a->sign+7)/8 ); 252 b = gcry_mpi_set_opaque( NULL, p, a->sign ); 253 } 254 else if( a ) { 255 b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) 256 : mpi_alloc( a->nlimbs ); 257 b->nlimbs = a->nlimbs; 258 b->sign = a->sign; 259 b->flags = a->flags; 260 for(i=0; i < b->nlimbs; i++ ) 261 b->d[i] = a->d[i]; 262 } 263 else 264 b = NULL; 265 return b; 266} 267 268 269/**************** 270 * This function allocates an MPI which is optimized to hold 271 * a value as large as the one given in the argument and allocates it 272 * with the same flags as A. 273 */ 274gcry_mpi_t 275_gcry_mpi_alloc_like( gcry_mpi_t a ) 276{ 277 gcry_mpi_t b; 278 279 if( a && (a->flags & 4) ) { 280 int n = (a->sign+7)/8; 281 void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n ) 282 : gcry_malloc( n ); 283 memcpy( p, a->d, n ); 284 b = gcry_mpi_set_opaque( NULL, p, a->sign ); 285 } 286 else if( a ) { 287 b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) 288 : mpi_alloc( a->nlimbs ); 289 b->nlimbs = 0; 290 b->sign = 0; 291 b->flags = a->flags; 292 } 293 else 294 b = NULL; 295 return b; 296} 297 298 299gcry_mpi_t 300gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u) 301{ 302 mpi_ptr_t wp, up; 303 mpi_size_t usize = u->nlimbs; 304 int usign = u->sign; 305 306 if (!w) 307 w = _gcry_mpi_alloc( mpi_get_nlimbs(u) ); 308 RESIZE_IF_NEEDED(w, usize); 309 wp = w->d; 310 up = u->d; 311 MPN_COPY( wp, up, usize ); 312 w->nlimbs = usize; 313 w->flags = u->flags; 314 w->sign = usign; 315 return w; 316} 317 318 319gcry_mpi_t 320gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u) 321{ 322 if (!w) 323 w = _gcry_mpi_alloc (1); 324 /* FIXME: If U is 0 we have no need to resize and thus possible 325 allocating the the limbs. */ 326 RESIZE_IF_NEEDED(w, 1); 327 w->d[0] = u; 328 w->nlimbs = u? 1:0; 329 w->sign = 0; 330 w->flags = 0; 331 return w; 332} 333 334gcry_err_code_t 335_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u) 336{ 337 gcry_err_code_t err = GPG_ERR_NO_ERROR; 338 unsigned long x = 0; 339 340 if (w->nlimbs > 1) 341 err = GPG_ERR_TOO_LARGE; 342 else if (w->nlimbs == 1) 343 x = w->d[0]; 344 else 345 x = 0; 346 347 if (! err) 348 *u = x; 349 350 return err; 351} 352 353gcry_error_t 354gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u) 355{ 356 gcry_err_code_t err = GPG_ERR_NO_ERROR; 357 358 err = _gcry_mpi_get_ui (w, u); 359 360 return gcry_error (err); 361} 362 363gcry_mpi_t 364_gcry_mpi_alloc_set_ui( unsigned long u) 365{ 366 gcry_mpi_t w = mpi_alloc(1); 367 w->d[0] = u; 368 w->nlimbs = u? 1:0; 369 w->sign = 0; 370 return w; 371} 372 373void 374gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b) 375{ 376 struct gcry_mpi tmp; 377 378 tmp = *a; *a = *b; *b = tmp; 379} 380 381 382gcry_mpi_t 383gcry_mpi_new( unsigned int nbits ) 384{ 385 return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1) 386 / BITS_PER_MPI_LIMB ); 387} 388 389 390gcry_mpi_t 391gcry_mpi_snew( unsigned int nbits ) 392{ 393 return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1) 394 / BITS_PER_MPI_LIMB ); 395} 396 397void 398gcry_mpi_release( gcry_mpi_t a ) 399{ 400 _gcry_mpi_free( a ); 401} 402 403void 404gcry_mpi_randomize( gcry_mpi_t w, 405 unsigned int nbits, enum gcry_random_level level ) 406{ 407 unsigned char *p; 408 size_t nbytes = (nbits+7)/8; 409 410 if (level == GCRY_WEAK_RANDOM) 411 { 412 p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes) 413 : gcry_xmalloc (nbytes); 414 gcry_create_nonce (p, nbytes); 415 } 416 else 417 { 418 p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level) 419 : gcry_random_bytes (nbytes, level); 420 } 421 _gcry_mpi_set_buffer( w, p, nbytes, 0 ); 422 gcry_free (p); 423} 424 425 426void 427gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) 428{ 429 switch( flag ) { 430 case GCRYMPI_FLAG_SECURE: mpi_set_secure(a); break; 431 case GCRYMPI_FLAG_OPAQUE: 432 default: log_bug("invalid flag value\n"); 433 } 434} 435 436void 437gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) 438{ 439 (void)a; /* Not yet used. */ 440 441 switch (flag) 442 { 443 case GCRYMPI_FLAG_SECURE: 444 case GCRYMPI_FLAG_OPAQUE: 445 default: log_bug("invalid flag value\n"); 446 } 447} 448 449int 450gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag ) 451{ 452 switch (flag) 453 { 454 case GCRYMPI_FLAG_SECURE: return (a->flags & 1); 455 case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4); 456 default: log_bug("invalid flag value\n"); 457 } 458 /*NOTREACHED*/ 459 return 0; 460} 461