raw
mpi-genesis             1 /* mpiutil.ac  -  Utility functions for MPI
mpi-genesis 2 * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
mpi-genesis 3 *
mpi-genesis 4 * This file is part of GnuPG.
mpi-genesis 5 *
mpi-genesis 6 * GnuPG is free software; you can redistribute it and/or modify
mpi-genesis 7 * it under the terms of the GNU General Public License as published by
mpi-genesis 8 * the Free Software Foundation; either version 3 of the License, or
mpi-genesis 9 * (at your option) any later version.
mpi-genesis 10 *
mpi-genesis 11 * GnuPG is distributed in the hope that it will be useful,
mpi-genesis 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mpi-genesis 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
mpi-genesis 14 * GNU General Public License for more details.
mpi-genesis 15 *
mpi-genesis 16 * You should have received a copy of the GNU General Public License
mpi-genesis 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
mpi-genesis 18 */
mpi-genesis 19
mpi-genesis 20 #include <config.h>
mpi-genesis 21 #include <stdio.h>
mpi-genesis 22 #include <stdlib.h>
mpi-genesis 23 #include <string.h>
mpi-genesis 24 #include <assert.h>
mpi-genesis 25
mpi-genesis 26 #include "mpi.h"
mpi-genesis 27 #include "mpi-internal.h"
mpi-genesis 28 #include "memory.h"
mpi-genesis 29 #include "util.h"
mpi-genesis 30
mpi-genesis 31
mpi-genesis 32 #ifdef M_DEBUG
mpi-genesis 33 #undef mpi_alloc
mpi-genesis 34 #undef mpi_alloc_secure
mpi-genesis 35 #undef mpi_free
mpi-genesis 36 #endif
mpi-genesis 37
mpi-genesis 38 /****************
mpi-genesis 39 * Note: It was a bad idea to use the number of limbs to allocate
mpi-genesis 40 * because on a alpha the limbs are large but we normally need
mpi-genesis 41 * integers of n bits - So we should chnage this to bits (or bytes).
mpi-genesis 42 *
mpi-genesis 43 * But mpi_alloc is used in a lot of places :-)
mpi-genesis 44 */
mpi-genesis 45 MPI
mpi-genesis 46 #ifdef M_DEBUG
mpi-genesis 47 mpi_debug_alloc( unsigned nlimbs, const char *info )
mpi-genesis 48 #else
mpi-genesis 49 mpi_alloc( unsigned nlimbs )
mpi-genesis 50 #endif
mpi-genesis 51 {
mpi-genesis 52 MPI a;
mpi-genesis 53
mpi-genesis 54 if( DBG_MEMORY )
mpi-genesis 55 log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
mpi-genesis 56 #ifdef M_DEBUG
mpi-genesis 57 a = m_debug_alloc( sizeof *a, info );
mpi-genesis 58 a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL;
mpi-genesis 59 #else
mpi-genesis 60 a = xmalloc( sizeof *a );
mpi-genesis 61 a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
mpi-genesis 62 #endif
mpi-genesis 63 a->alloced = nlimbs;
mpi-genesis 64 a->nlimbs = 0;
mpi-genesis 65 a->sign = 0;
mpi-genesis 66 a->flags = 0;
mpi-genesis 67 a->nbits = 0;
mpi-genesis 68 return a;
mpi-genesis 69 }
mpi-genesis 70
mpi-genesis 71 void
mpi-genesis 72 mpi_m_check( MPI a )
mpi-genesis 73 {
mpi-genesis 74 m_check(a);
mpi-genesis 75 m_check(a->d);
mpi-genesis 76 }
mpi-genesis 77
mpi-genesis 78 MPI
mpi-genesis 79 #ifdef M_DEBUG
mpi-genesis 80 mpi_debug_alloc_secure( unsigned nlimbs, const char *info )
mpi-genesis 81 #else
mpi-genesis 82 mpi_alloc_secure( unsigned nlimbs )
mpi-genesis 83 #endif
mpi-genesis 84 {
mpi-genesis 85 MPI a;
mpi-genesis 86
mpi-genesis 87 if( DBG_MEMORY )
mpi-genesis 88 log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
mpi-genesis 89 #ifdef M_DEBUG
mpi-genesis 90 a = m_debug_alloc( sizeof *a, info );
mpi-genesis 91 a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL;
mpi-genesis 92 #else
mpi-genesis 93 a = xmalloc( sizeof *a );
mpi-genesis 94 a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
mpi-genesis 95 #endif
mpi-genesis 96 a->alloced = nlimbs;
mpi-genesis 97 a->flags = 1;
mpi-genesis 98 a->nlimbs = 0;
mpi-genesis 99 a->sign = 0;
mpi-genesis 100 a->nbits = 0;
mpi-genesis 101 return a;
mpi-genesis 102 }
mpi-genesis 103
mpi-genesis 104
mpi-genesis 105 #if 0
mpi-genesis 106 static void *unused_limbs_5;
mpi-genesis 107 static void *unused_limbs_32;
mpi-genesis 108 static void *unused_limbs_64;
mpi-genesis 109 #endif
mpi-genesis 110
mpi-genesis 111 mpi_ptr_t
mpi-genesis 112 #ifdef M_DEBUG
mpi-genesis 113 mpi_debug_alloc_limb_space( unsigned nlimbs, int secure, const char *info )
mpi-genesis 114 #else
mpi-genesis 115 mpi_alloc_limb_space( unsigned nlimbs, int secure )
mpi-genesis 116 #endif
mpi-genesis 117 {
mpi-genesis 118 size_t len = nlimbs * sizeof(mpi_limb_t);
mpi-genesis 119 mpi_ptr_t p;
mpi-genesis 120
mpi-genesis 121 if( DBG_MEMORY )
mpi-genesis 122 log_debug("mpi_alloc_limb_space(%u)\n", (unsigned)len*8 );
mpi-genesis 123 #if 0
mpi-genesis 124 if( !secure ) {
mpi-genesis 125 if( nlimbs == 5 && unused_limbs_5 ) { /* DSA 160 bits */
mpi-genesis 126 p = unused_limbs_5;
mpi-genesis 127 unused_limbs_5 = *p;
mpi-genesis 128 return p;
mpi-genesis 129 }
mpi-genesis 130 else if( nlimbs == 32 && unused_limbs_32 ) { /* DSA 1024 bits */
mpi-genesis 131 p = unused_limbs_32;
mpi-genesis 132 unused_limbs_32 = *p;
mpi-genesis 133 return p;
mpi-genesis 134 }
mpi-genesis 135 else if( nlimbs == 64 && unused_limbs_64 ) { /* DSA 2*1024 bits */
mpi-genesis 136 p = unused_limbs_64;
mpi-genesis 137 unused_limbs_64 = *p;
mpi-genesis 138 return p;
mpi-genesis 139 }
mpi-genesis 140 }
mpi-genesis 141 #endif
mpi-genesis 142
mpi-genesis 143 #ifdef M_DEBUG
mpi-genesis 144 p = secure? m_debug_alloc_secure(len, info):m_debug_alloc( len, info );
mpi-genesis 145 #else
mpi-genesis 146 p = secure? xmalloc_secure( len ):xmalloc( len );
mpi-genesis 147 #endif
mpi-genesis 148
mpi-genesis 149 return p;
mpi-genesis 150 }
mpi-genesis 151
mpi-genesis 152 void
mpi-genesis 153 #ifdef M_DEBUG
mpi-genesis 154 mpi_debug_free_limb_space( mpi_ptr_t a, const char *info )
mpi-genesis 155 #else
mpi-genesis 156 mpi_free_limb_space( mpi_ptr_t a )
mpi-genesis 157 #endif
mpi-genesis 158 {
mpi-genesis 159 if( !a )
mpi-genesis 160 return;
mpi-genesis 161 if( DBG_MEMORY )
mpi-genesis 162 log_debug("mpi_free_limb_space of size %lu\n", (ulong)m_size(a)*8 );
mpi-genesis 163
mpi-genesis 164 #if 0
mpi-genesis 165 if( !m_is_secure(a) ) {
mpi-genesis 166 size_t nlimbs = m_size(a) / 4 ;
mpi-genesis 167 void *p = a;
mpi-genesis 168
mpi-genesis 169 if( nlimbs == 5 ) { /* DSA 160 bits */
mpi-genesis 170 *a = unused_limbs_5;
mpi-genesis 171 unused_limbs_5 = a;
mpi-genesis 172 return;
mpi-genesis 173 }
mpi-genesis 174 else if( nlimbs == 32 ) { /* DSA 1024 bits */
mpi-genesis 175 *a = unused_limbs_32;
mpi-genesis 176 unused_limbs_32 = a;
mpi-genesis 177 return;
mpi-genesis 178 }
mpi-genesis 179 else if( nlimbs == 64 ) { /* DSA 2*1024 bits */
mpi-genesis 180 *a = unused_limbs_64;
mpi-genesis 181 unused_limbs_64 = a;
mpi-genesis 182 return;
mpi-genesis 183 }
mpi-genesis 184 }
mpi-genesis 185 #endif
mpi-genesis 186
mpi-genesis 187 xfree(a);
mpi-genesis 188 }
mpi-genesis 189
mpi-genesis 190
mpi-genesis 191 void
mpi-genesis 192 mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs )
mpi-genesis 193 {
mpi-genesis 194 mpi_free_limb_space(a->d);
mpi-genesis 195 a->d = ap;
mpi-genesis 196 a->alloced = nlimbs;
mpi-genesis 197 }
mpi-genesis 198
mpi-genesis 199
mpi-genesis 200
mpi-genesis 201 /****************
mpi-genesis 202 * Resize the array of A to NLIMBS. the additional space is cleared
mpi-genesis 203 * (set to 0) [done by xrealloc()]
mpi-genesis 204 */
mpi-genesis 205 void
mpi-genesis 206 #ifdef M_DEBUG
mpi-genesis 207 mpi_debug_resize( MPI a, unsigned nlimbs, const char *info )
mpi-genesis 208 #else
mpi-genesis 209 mpi_resize( MPI a, unsigned nlimbs )
mpi-genesis 210 #endif
mpi-genesis 211 {
mpi-genesis 212 if( nlimbs <= a->alloced )
mpi-genesis 213 return; /* no need to do it */
mpi-genesis 214 /* Note: a->secure is not used - instead the realloc functions
mpi-genesis 215 * take care of it. Maybe we should drop a->secure completely
mpi-genesis 216 * and rely on a mpi_is_secure function, which would be
mpi-genesis 217 * a wrapper around m_is_secure
mpi-genesis 218 */
mpi-genesis 219 #ifdef M_DEBUG
mpi-genesis 220 if( a->d )
mpi-genesis 221 a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info );
mpi-genesis 222 else
mpi-genesis 223 a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info );
mpi-genesis 224 #else
mpi-genesis 225 if( a->d )
mpi-genesis 226 a->d = xrealloc(a->d, nlimbs * sizeof(mpi_limb_t) );
mpi-genesis 227 else
mpi-genesis 228 a->d = xmalloc_clear( nlimbs * sizeof(mpi_limb_t) );
mpi-genesis 229 #endif
mpi-genesis 230 a->alloced = nlimbs;
mpi-genesis 231 }
mpi-genesis 232
mpi-genesis 233 void
mpi-genesis 234 mpi_clear( MPI a )
mpi-genesis 235 {
mpi-genesis 236 a->nlimbs = 0;
mpi-genesis 237 a->nbits = 0;
mpi-genesis 238 a->flags = 0;
mpi-genesis 239 }
mpi-genesis 240
mpi-genesis 241
mpi-genesis 242 void
mpi-genesis 243 #ifdef M_DEBUG
mpi-genesis 244 mpi_debug_free( MPI a, const char *info )
mpi-genesis 245 #else
mpi-genesis 246 mpi_free( MPI a )
mpi-genesis 247 #endif
mpi-genesis 248 {
mpi-genesis 249 if( !a )
mpi-genesis 250 return;
mpi-genesis 251 if( DBG_MEMORY )
mpi-genesis 252 log_debug("mpi_free\n" );
mpi-genesis 253 if( a->flags & 4 )
mpi-genesis 254 xfree( a->d );
mpi-genesis 255 else {
mpi-genesis 256 #ifdef M_DEBUG
mpi-genesis 257 mpi_debug_free_limb_space(a->d, info);
mpi-genesis 258 #else
mpi-genesis 259 mpi_free_limb_space(a->d);
mpi-genesis 260 #endif
mpi-genesis 261 }
mpi-genesis 262 if( a->flags & ~7 )
mpi-genesis 263 log_bug("invalid flag value in mpi\n");
mpi-genesis 264 xfree(a);
mpi-genesis 265 }
mpi-genesis 266
mpi-genesis 267
mpi-genesis 268 void
mpi-genesis 269 mpi_set_secure( MPI a )
mpi-genesis 270 {
mpi-genesis 271 mpi_ptr_t ap, bp;
mpi-genesis 272
mpi-genesis 273 if( (a->flags & 1) )
mpi-genesis 274 return;
mpi-genesis 275 a->flags |= 1;
mpi-genesis 276 ap = a->d;
mpi-genesis 277 if( !a->nlimbs ) {
mpi-genesis 278 assert(!ap);
mpi-genesis 279 return;
mpi-genesis 280 }
mpi-genesis 281 #ifdef M_DEBUG
mpi-genesis 282 bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" );
mpi-genesis 283 #else
mpi-genesis 284 bp = mpi_alloc_limb_space( a->nlimbs, 1 );
mpi-genesis 285 #endif
mpi-genesis 286 MPN_COPY( bp, ap, a->nlimbs );
mpi-genesis 287 a->d = bp;
mpi-genesis 288 #ifdef M_DEBUG
mpi-genesis 289 mpi_debug_free_limb_space(ap, "set_secure");
mpi-genesis 290 #else
mpi-genesis 291 mpi_free_limb_space(ap);
mpi-genesis 292 #endif
mpi-genesis 293 }
mpi-genesis 294
mpi-genesis 295
mpi-genesis 296 MPI
mpi-genesis 297 mpi_set_opaque( MPI a, void *p, unsigned int len )
mpi-genesis 298 {
mpi-genesis 299 if( !a ) {
mpi-genesis 300 #ifdef M_DEBUG
mpi-genesis 301 a = mpi_debug_alloc(0,"alloc_opaque");
mpi-genesis 302 #else
mpi-genesis 303 a = mpi_alloc(0);
mpi-genesis 304 #endif
mpi-genesis 305 }
mpi-genesis 306
mpi-genesis 307 if( a->flags & 4 )
mpi-genesis 308 xfree( a->d );
mpi-genesis 309 else {
mpi-genesis 310 #ifdef M_DEBUG
mpi-genesis 311 mpi_debug_free_limb_space(a->d, "alloc_opaque");
mpi-genesis 312 #else
mpi-genesis 313 mpi_free_limb_space(a->d);
mpi-genesis 314 #endif
mpi-genesis 315 }
mpi-genesis 316
mpi-genesis 317 a->d = p;
mpi-genesis 318 a->alloced = 0;
mpi-genesis 319 a->nlimbs = 0;
mpi-genesis 320 a->nbits = len;
mpi-genesis 321 a->flags = 4;
mpi-genesis 322 return a;
mpi-genesis 323 }
mpi-genesis 324
mpi-genesis 325
mpi-genesis 326 void *
mpi-genesis 327 mpi_get_opaque( MPI a, unsigned int *len )
mpi-genesis 328 {
mpi-genesis 329 if( !(a->flags & 4) )
mpi-genesis 330 log_bug("mpi_get_opaque on normal mpi\n");
mpi-genesis 331 if( len )
mpi-genesis 332 *len = a->nbits;
mpi-genesis 333 return a->d;
mpi-genesis 334 }
mpi-genesis 335
mpi-genesis 336
mpi-genesis 337 /****************
mpi-genesis 338 * Note: This copy function should not interpret the MPI
mpi-genesis 339 * but copy it transparently.
mpi-genesis 340 */
mpi-genesis 341 MPI
mpi-genesis 342 #ifdef M_DEBUG
mpi-genesis 343 mpi_debug_copy( MPI a, const char *info )
mpi-genesis 344 #else
mpi-genesis 345 mpi_copy( MPI a )
mpi-genesis 346 #endif
mpi-genesis 347 {
mpi-genesis 348 int i;
mpi-genesis 349 MPI b;
mpi-genesis 350
mpi-genesis 351 if( a && (a->flags & 4) ) {
mpi-genesis 352 void *p = m_is_secure(a->d)? xmalloc_secure( a->nbits )
mpi-genesis 353 : xmalloc( a->nbits );
mpi-genesis 354 memcpy( p, a->d, a->nbits );
mpi-genesis 355 b = mpi_set_opaque( NULL, p, a->nbits );
mpi-genesis 356 }
mpi-genesis 357 else if( a ) {
mpi-genesis 358 #ifdef M_DEBUG
mpi-genesis 359 b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info )
mpi-genesis 360 : mpi_debug_alloc( a->nlimbs, info );
mpi-genesis 361 #else
mpi-genesis 362 b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
mpi-genesis 363 : mpi_alloc( a->nlimbs );
mpi-genesis 364 #endif
mpi-genesis 365 b->nlimbs = a->nlimbs;
mpi-genesis 366 b->sign = a->sign;
mpi-genesis 367 b->flags = a->flags;
mpi-genesis 368 b->nbits = a->nbits;
mpi-genesis 369 for(i=0; i < b->nlimbs; i++ )
mpi-genesis 370 b->d[i] = a->d[i];
mpi-genesis 371 }
mpi-genesis 372 else
mpi-genesis 373 b = NULL;
mpi-genesis 374 return b;
mpi-genesis 375 }
mpi-genesis 376
mpi-genesis 377
mpi-genesis 378 /****************
mpi-genesis 379 * This function allocates an MPI which is optimized to hold
mpi-genesis 380 * a value as large as the one given in the argument and allocates it
mpi-genesis 381 * with the same flags as A.
mpi-genesis 382 */
mpi-genesis 383 MPI
mpi-genesis 384 #ifdef M_DEBUG
mpi-genesis 385 mpi_debug_alloc_like( MPI a, const char *info )
mpi-genesis 386 #else
mpi-genesis 387 mpi_alloc_like( MPI a )
mpi-genesis 388 #endif
mpi-genesis 389 {
mpi-genesis 390 MPI b;
mpi-genesis 391
mpi-genesis 392 if( a && (a->flags & 4) ) {
mpi-genesis 393 void *p = m_is_secure(a->d)? xmalloc_secure( a->nbits )
mpi-genesis 394 : xmalloc( a->nbits );
mpi-genesis 395 memcpy( p, a->d, a->nbits );
mpi-genesis 396 b = mpi_set_opaque( NULL, p, a->nbits );
mpi-genesis 397 }
mpi-genesis 398 else if( a ) {
mpi-genesis 399 #ifdef M_DEBUG
mpi-genesis 400 b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info )
mpi-genesis 401 : mpi_debug_alloc( a->nlimbs, info );
mpi-genesis 402 #else
mpi-genesis 403 b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
mpi-genesis 404 : mpi_alloc( a->nlimbs );
mpi-genesis 405 #endif
mpi-genesis 406 b->nlimbs = 0;
mpi-genesis 407 b->sign = 0;
mpi-genesis 408 b->flags = a->flags;
mpi-genesis 409 b->nbits = 0;
mpi-genesis 410 }
mpi-genesis 411 else
mpi-genesis 412 b = NULL;
mpi-genesis 413 return b;
mpi-genesis 414 }
mpi-genesis 415
mpi-genesis 416
mpi-genesis 417 void
mpi-genesis 418 mpi_set( MPI w, MPI u)
mpi-genesis 419 {
mpi-genesis 420 mpi_ptr_t wp, up;
mpi-genesis 421 mpi_size_t usize = u->nlimbs;
mpi-genesis 422 int usign = u->sign;
mpi-genesis 423
mpi-genesis 424 RESIZE_IF_NEEDED(w, usize);
mpi-genesis 425 wp = w->d;
mpi-genesis 426 up = u->d;
mpi-genesis 427 MPN_COPY( wp, up, usize );
mpi-genesis 428 w->nlimbs = usize;
mpi-genesis 429 w->nbits = u->nbits;
mpi-genesis 430 w->flags = u->flags;
mpi-genesis 431 w->sign = usign;
mpi-genesis 432 }
mpi-genesis 433
mpi-genesis 434
mpi-genesis 435 void
mpi-genesis 436 mpi_set_ui( MPI w, unsigned long u)
mpi-genesis 437 {
mpi-genesis 438 RESIZE_IF_NEEDED(w, 1);
mpi-genesis 439 w->d[0] = u;
mpi-genesis 440 w->nlimbs = u? 1:0;
mpi-genesis 441 w->sign = 0;
mpi-genesis 442 w->nbits = 0;
mpi-genesis 443 w->flags = 0;
mpi-genesis 444 }
mpi-genesis 445
mpi-genesis 446
mpi-genesis 447 MPI
mpi-genesis 448 mpi_alloc_set_ui( unsigned long u)
mpi-genesis 449 {
mpi-genesis 450 #ifdef M_DEBUG
mpi-genesis 451 MPI w = mpi_debug_alloc(1,"alloc_set_ui");
mpi-genesis 452 #else
mpi-genesis 453 MPI w = mpi_alloc(1);
mpi-genesis 454 #endif
mpi-genesis 455 w->d[0] = u;
mpi-genesis 456 w->nlimbs = u? 1:0;
mpi-genesis 457 w->sign = 0;
mpi-genesis 458 return w;
mpi-genesis 459 }
mpi-genesis 460
mpi-genesis 461
mpi-genesis 462 void
mpi-genesis 463 mpi_swap( MPI a, MPI b)
mpi-genesis 464 {
mpi-genesis 465 struct gcry_mpi tmp;
mpi-genesis 466
mpi-genesis 467 tmp = *a; *a = *b; *b = tmp;
mpi-genesis 468 }
mpi-genesis 469
mpi-genesis 470
mpi-genesis 471 int
mpi-genesis 472 mpi_get_nlimbs (MPI a)
mpi-genesis 473 {
mpi-genesis 474 return a->nlimbs;
mpi-genesis 475 }
mpi-genesis 476
mpi-genesis 477
mpi-genesis 478 int
mpi-genesis 479 mpi_is_neg (MPI a)
mpi-genesis 480 {
mpi-genesis 481 return a->sign;
mpi-genesis 482 }
mpi-genesis 483
mpi-genesis 484
mpi-genesis 485 /* Return the number of limbs to store an MPI which is specified by
mpi-genesis 486 the number of bytes to represent it. */
mpi-genesis 487 unsigned int
mpi-genesis 488 mpi_nlimb_hint_from_nbytes (unsigned int nbytes)
mpi-genesis 489 {
mpi-genesis 490 return (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
mpi-genesis 491 }
mpi-genesis 492
mpi-genesis 493 /* Return the number of limbs to store an MPI which is specified by
mpi-genesis 494 the number of bytes to represent it. */
mpi-genesis 495 unsigned int
mpi-genesis 496 mpi_nlimb_hint_from_nbits (unsigned int nbits)
mpi-genesis 497 {
mpi-genesis 498 return (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB;
mpi-genesis 499 }
mpi-genesis 500
mpi-genesis 501 unsigned int
mpi-genesis 502 mpi_get_flags (MPI a)
mpi-genesis 503 {
mpi-genesis 504 return a->flags;
mpi-genesis 505 }