LCOV - code coverage report
Current view: top level - mpi - mpiutil.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 252 330 76.4 %
Date: 2017-03-02 16:44:37 Functions: 34 38 89.5 %

          Line data    Source code
       1             : /* mpiutil.ac  -  Utility functions for MPI
       2             :  * Copyright (C) 1998, 2000, 2001, 2002, 2003,
       3             :  *               2007  Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013  g10 Code GmbH
       5             :  *
       6             :  * This file is part of Libgcrypt.
       7             :  *
       8             :  * Libgcrypt is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU Lesser General Public License as
      10             :  * published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * Libgcrypt is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : 
      27             : #include "g10lib.h"
      28             : #include "mpi-internal.h"
      29             : #include "mod-source-info.h"
      30             : 
      31             : /* Constants allocated right away at startup.  */
      32             : static gcry_mpi_t constants[MPI_NUMBER_OF_CONSTANTS];
      33             : 
      34             : 
      35             : 
      36             : const char *
      37           1 : _gcry_mpi_get_hw_config (void)
      38             : {
      39           1 :   return mod_source_info + 1;
      40             : }
      41             : 
      42             : 
      43             : /* Initialize the MPI subsystem.  This is called early and allows to
      44             :    do some initialization without taking care of threading issues.  */
      45             : gcry_err_code_t
      46          34 : _gcry_mpi_init (void)
      47             : {
      48             :   int idx;
      49             :   unsigned long value;
      50             : 
      51         238 :   for (idx=0; idx < MPI_NUMBER_OF_CONSTANTS; idx++)
      52             :     {
      53         204 :       switch (idx)
      54             :         {
      55          34 :         case MPI_C_ZERO:  value = 0; break;
      56          34 :         case MPI_C_ONE:   value = 1; break;
      57          34 :         case MPI_C_TWO:   value = 2; break;
      58          34 :         case MPI_C_THREE: value = 3; break;
      59          34 :         case MPI_C_FOUR:  value = 4; break;
      60          34 :         case MPI_C_EIGHT: value = 8; break;
      61           0 :         default: log_bug ("invalid mpi_const selector %d\n", idx);
      62             :         }
      63         204 :       constants[idx] = mpi_alloc_set_ui (value);
      64         204 :       constants[idx]->flags = (16|32);
      65             :     }
      66             : 
      67          34 :   return 0;
      68             : }
      69             : 
      70             : 
      71             : /****************
      72             :  * Note:  It was a bad idea to use the number of limbs to allocate
      73             :  *        because on a alpha the limbs are large but we normally need
      74             :  *        integers of n bits - So we should change this to bits (or bytes).
      75             :  *
      76             :  *        But mpi_alloc is used in a lot of places :-(.  New code
      77             :  *        should use mpi_new.
      78             :  */
      79             : gcry_mpi_t
      80    18984164 : _gcry_mpi_alloc( unsigned nlimbs )
      81             : {
      82             :     gcry_mpi_t a;
      83             : 
      84    18984164 :     a = xmalloc( sizeof *a );
      85    18984164 :     a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
      86    18984164 :     a->alloced = nlimbs;
      87    18984164 :     a->nlimbs = 0;
      88    18984164 :     a->sign = 0;
      89    18984164 :     a->flags = 0;
      90    18984164 :     return a;
      91             : }
      92             : 
      93             : void
      94           0 : _gcry_mpi_m_check( gcry_mpi_t a )
      95             : {
      96           0 :     _gcry_check_heap(a);
      97           0 :     _gcry_check_heap(a->d);
      98           0 : }
      99             : 
     100             : gcry_mpi_t
     101      647231 : _gcry_mpi_alloc_secure( unsigned nlimbs )
     102             : {
     103             :     gcry_mpi_t a;
     104             : 
     105      647231 :     a = xmalloc( sizeof *a );
     106      647231 :     a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
     107      647231 :     a->alloced = nlimbs;
     108      647231 :     a->flags = 1;
     109      647231 :     a->nlimbs = 0;
     110      647231 :     a->sign = 0;
     111      647231 :     return a;
     112             : }
     113             : 
     114             : 
     115             : 
     116             : mpi_ptr_t
     117    70570847 : _gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
     118             : {
     119             :     mpi_ptr_t p;
     120             :     size_t len;
     121             : 
     122    70570847 :     len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
     123    70570847 :     p = secure ? xmalloc_secure (len) : xmalloc (len);
     124    70570847 :     if (! nlimbs)
     125        7517 :       *p = 0;
     126             : 
     127    70570847 :     return p;
     128             : }
     129             : 
     130             : void
     131    70685931 : _gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs)
     132             : {
     133    70685931 :   if (a)
     134             :     {
     135    70648316 :       size_t len = nlimbs * sizeof(mpi_limb_t);
     136             : 
     137             :       /* If we have information on the number of allocated limbs, we
     138             :          better wipe that space out.  This is a failsafe feature if
     139             :          secure memory has been disabled or was not properly
     140             :          implemented in user provided allocation functions. */
     141    70648316 :       if (len)
     142    69226074 :         wipememory (a, len);
     143    70648316 :       xfree(a);
     144             :     }
     145    70685931 : }
     146             : 
     147             : 
     148             : void
     149       17824 : _gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs )
     150             : {
     151       17824 :   _gcry_mpi_free_limb_space (a->d, a->alloced);
     152       17824 :   a->d = ap;
     153       17824 :   a->alloced = nlimbs;
     154       17824 : }
     155             : 
     156             : 
     157             : 
     158             : /****************
     159             :  * Resize the array of A to NLIMBS. The additional space is cleared
     160             :  * (set to 0).
     161             :  */
     162             : void
     163    38706260 : _gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
     164             : {
     165             :   size_t i;
     166             : 
     167    38706260 :   if (nlimbs <= a->alloced)
     168             :     {
     169             :       /* We only need to clear the new space (this is a nop if the
     170             :          limb space is already of the correct size. */
     171   113830300 :       for (i=a->nlimbs; i < a->alloced; i++)
     172    75415528 :         a->d[i] = 0;
     173    38414772 :       return;
     174             :     }
     175             : 
     176             :   /* Actually resize the limb space.  */
     177      291488 :   if (a->d)
     178             :     {
     179      213519 :       a->d = xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
     180     1488236 :       for (i=a->alloced; i < nlimbs; i++)
     181     1274717 :         a->d[i] = 0;
     182             :     }
     183             :   else
     184             :     {
     185       77969 :       if (a->flags & 1)
     186             :         /* Secure memory is wanted.  */
     187        1301 :         a->d = xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
     188             :       else
     189             :         /* Standard memory.  */
     190       76668 :         a->d = xcalloc (nlimbs , sizeof (mpi_limb_t));
     191             :     }
     192      291488 :   a->alloced = nlimbs;
     193             : }
     194             : 
     195             : void
     196        2045 : _gcry_mpi_clear( gcry_mpi_t a )
     197             : {
     198        2045 :   if (mpi_is_immutable (a))
     199             :     {
     200           0 :       mpi_immutable_failed ();
     201           0 :       return;
     202             :     }
     203        2045 :   a->nlimbs = 0;
     204        2045 :   a->flags = 0;
     205             : }
     206             : 
     207             : 
     208             : void
     209    19656613 : _gcry_mpi_free( gcry_mpi_t a )
     210             : {
     211    19656613 :   if (!a )
     212       25717 :     return;
     213    19630896 :   if ((a->flags & 32))
     214             :   {
     215             : #if GPGRT_VERSION_NUMBER >= 0x011600  /* 1.22 */
     216           1 :     gpgrt_annotate_leaked_object(a);
     217             : #endif
     218           1 :     return; /* Never release a constant. */
     219             :   }
     220    19630895 :   if ((a->flags & 4))
     221        7890 :     xfree( a->d );
     222             :   else
     223             :     {
     224    19623005 :       _gcry_mpi_free_limb_space(a->d, a->alloced);
     225             :     }
     226             :   /* Check that the flags makes sense.  We better allow for bit 1
     227             :      (value 2) for backward ABI compatibility.  */
     228    19630895 :   if ((a->flags & ~(1|2|4|16
     229             :                     |GCRYMPI_FLAG_USER1
     230             :                     |GCRYMPI_FLAG_USER2
     231             :                     |GCRYMPI_FLAG_USER3
     232             :                     |GCRYMPI_FLAG_USER4)))
     233           0 :     log_bug("invalid flag value in mpi_free\n");
     234    19630895 :   xfree (a);
     235             : }
     236             : 
     237             : 
     238             : void
     239           0 : _gcry_mpi_immutable_failed (void)
     240             : {
     241           0 :   log_info ("Warning: trying to change an immutable MPI\n");
     242           0 : }
     243             : 
     244             : 
     245             : static void
     246           0 : mpi_set_secure( gcry_mpi_t a )
     247             : {
     248             :   mpi_ptr_t ap, bp;
     249             : 
     250           0 :   if ( (a->flags & 1) )
     251           0 :     return;
     252           0 :   a->flags |= 1;
     253           0 :   ap = a->d;
     254           0 :   if (!a->nlimbs)
     255             :     {
     256           0 :       gcry_assert (!ap);
     257           0 :       return;
     258             :     }
     259           0 :   bp = mpi_alloc_limb_space (a->nlimbs, 1);
     260           0 :   MPN_COPY( bp, ap, a->nlimbs );
     261           0 :   a->d = bp;
     262           0 :   _gcry_mpi_free_limb_space (ap, a->alloced);
     263             : }
     264             : 
     265             : 
     266             : gcry_mpi_t
     267        7892 : _gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits)
     268             : {
     269        7892 :   if (!a)
     270        2272 :     a = mpi_alloc(0);
     271             : 
     272        7892 :   if (mpi_is_immutable (a))
     273             :     {
     274           0 :       mpi_immutable_failed ();
     275           0 :       return a;
     276             :     }
     277             : 
     278        7892 :   if( a->flags & 4 )
     279           2 :     xfree (a->d);
     280             :   else
     281        7890 :     _gcry_mpi_free_limb_space (a->d, a->alloced);
     282             : 
     283        7892 :   a->d = p;
     284        7892 :   a->alloced = 0;
     285        7892 :   a->nlimbs = 0;
     286        7892 :   a->sign  = nbits;
     287        7892 :   a->flags = 4 | (a->flags & (GCRYMPI_FLAG_USER1|GCRYMPI_FLAG_USER2
     288             :                               |GCRYMPI_FLAG_USER3|GCRYMPI_FLAG_USER4));
     289        7892 :   if (_gcry_is_secure (a->d))
     290           0 :     a->flags |= 1;
     291        7892 :   return a;
     292             : }
     293             : 
     294             : 
     295             : gcry_mpi_t
     296           2 : _gcry_mpi_set_opaque_copy (gcry_mpi_t a, const void *p, unsigned int nbits)
     297             : {
     298             :   void *d;
     299             :   unsigned int n;
     300             : 
     301           2 :   n = (nbits+7)/8;
     302           2 :   d = _gcry_is_secure (p)? xtrymalloc_secure (n) : xtrymalloc (n);
     303           2 :   if (!d)
     304           0 :     return NULL;
     305           2 :   memcpy (d, p, n);
     306           2 :   return mpi_set_opaque (a, d, nbits);
     307             : }
     308             : 
     309             : 
     310             : void *
     311        7804 : _gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits)
     312             : {
     313        7804 :     if( !(a->flags & 4) )
     314           0 :         log_bug("mpi_get_opaque on normal mpi\n");
     315        7804 :     if( nbits )
     316        7804 :         *nbits = a->sign;
     317        7804 :     return a->d;
     318             : }
     319             : 
     320             : 
     321             : void *
     322        1036 : _gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits)
     323             : {
     324             :   const void *s;
     325             :   void *d;
     326             :   unsigned int n;
     327             : 
     328        1036 :   s = mpi_get_opaque (a, nbits);
     329        1036 :   if (!s && nbits)
     330           0 :     return NULL;
     331        1036 :   n = (*nbits+7)/8;
     332        1036 :   d = _gcry_is_secure (s)? xtrymalloc_secure (n) : xtrymalloc (n);
     333        1036 :   if (d)
     334        1036 :     memcpy (d, s, n);
     335        1036 :   return d;
     336             : }
     337             : 
     338             : /****************
     339             :  * Note: This copy function should not interpret the MPI
     340             :  *       but copy it transparently.
     341             :  */
     342             : gcry_mpi_t
     343    19394961 : _gcry_mpi_copy (gcry_mpi_t a)
     344             : {
     345             :     int i;
     346             :     gcry_mpi_t b;
     347             : 
     348    19394961 :     if( a && (a->flags & 4) ) {
     349           0 :         void *p = _gcry_is_secure(a->d)? xmalloc_secure ((a->sign+7)/8)
     350           0 :                                        : xmalloc ((a->sign+7)/8);
     351           0 :         if (a->d)
     352           0 :           memcpy( p, a->d, (a->sign+7)/8 );
     353           0 :         b = mpi_set_opaque( NULL, p, a->sign );
     354           0 :         b->flags &= ~(16|32); /* Reset the immutable and constant flags.  */
     355             :     }
     356    19394961 :     else if( a ) {
     357    38789884 :         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
     358    20033859 :                             : mpi_alloc( a->nlimbs );
     359    19394942 :         b->nlimbs = a->nlimbs;
     360    19394942 :         b->sign = a->sign;
     361    19394942 :         b->flags  = a->flags;
     362    19394942 :         b->flags &= ~(16|32); /* Reset the immutable and constant flags.  */
     363   133869663 :         for(i=0; i < b->nlimbs; i++ )
     364   114474721 :             b->d[i] = a->d[i];
     365             :     }
     366             :     else
     367          19 :         b = NULL;
     368    19394961 :     return b;
     369             : }
     370             : 
     371             : 
     372             : /* Return true if A is negative.  */
     373             : int
     374          70 : _gcry_mpi_is_neg (gcry_mpi_t a)
     375             : {
     376          70 :   if (a->sign && _gcry_mpi_cmp_ui (a, 0))
     377          33 :     return 1;
     378             :   else
     379          37 :     return 0;
     380             : }
     381             : 
     382             : 
     383             : /* W = - U */
     384             : void
     385          36 : _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u)
     386             : {
     387          36 :   if (w != u)
     388           0 :     mpi_set (w, u);
     389          36 :   else if (mpi_is_immutable (w))
     390             :     {
     391           0 :       mpi_immutable_failed ();
     392           0 :       return;
     393             :     }
     394             : 
     395          36 :   w->sign = !u->sign;
     396             : }
     397             : 
     398             : 
     399             : /* W = [W] */
     400             : void
     401           1 : _gcry_mpi_abs (gcry_mpi_t w)
     402             : {
     403           1 :   if (mpi_is_immutable (w))
     404             :     {
     405           0 :       mpi_immutable_failed ();
     406           0 :       return;
     407             :     }
     408             : 
     409           1 :   w->sign = 0;
     410             : }
     411             : 
     412             : 
     413             : /****************
     414             :  * This function allocates an MPI which is optimized to hold
     415             :  * a value as large as the one given in the argument and allocates it
     416             :  * with the same flags as A.
     417             :  */
     418             : gcry_mpi_t
     419       36769 : _gcry_mpi_alloc_like( gcry_mpi_t a )
     420             : {
     421             :     gcry_mpi_t b;
     422             : 
     423       36769 :     if( a && (a->flags & 4) ) {
     424           0 :         int n = (a->sign+7)/8;
     425           0 :         void *p = _gcry_is_secure(a->d)? xtrymalloc_secure (n)
     426           0 :                                        : xtrymalloc (n);
     427           0 :         memcpy( p, a->d, n );
     428           0 :         b = mpi_set_opaque( NULL, p, a->sign );
     429             :     }
     430       36769 :     else if( a ) {
     431       73538 :         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
     432       37105 :                             : mpi_alloc( a->nlimbs );
     433       36769 :         b->nlimbs = 0;
     434       36769 :         b->sign = 0;
     435       36769 :         b->flags = a->flags;
     436             :     }
     437             :     else
     438           0 :         b = NULL;
     439       36769 :     return b;
     440             : }
     441             : 
     442             : 
     443             : /* Set U into W and release U.  If W is NULL only U will be released. */
     444             : void
     445          79 : _gcry_mpi_snatch (gcry_mpi_t w, gcry_mpi_t u)
     446             : {
     447          79 :   if (w)
     448             :     {
     449          79 :       if (mpi_is_immutable (w))
     450             :         {
     451           0 :           mpi_immutable_failed ();
     452           0 :           return;
     453             :         }
     454          79 :       _gcry_mpi_assign_limb_space (w, u->d, u->alloced);
     455          79 :       w->nlimbs = u->nlimbs;
     456          79 :       w->sign   = u->sign;
     457          79 :       w->flags  = u->flags;
     458          79 :       u->alloced = 0;
     459          79 :       u->nlimbs = 0;
     460          79 :       u->d = NULL;
     461             :     }
     462          79 :   _gcry_mpi_free (u);
     463             : }
     464             : 
     465             : 
     466             : gcry_mpi_t
     467     3864524 : _gcry_mpi_set (gcry_mpi_t w, gcry_mpi_t u)
     468             : {
     469             :   mpi_ptr_t wp, up;
     470     3864524 :   mpi_size_t usize = u->nlimbs;
     471     3864524 :   int usign = u->sign;
     472             : 
     473     3864524 :   if (!w)
     474           3 :     w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
     475     3864524 :   if (mpi_is_immutable (w))
     476             :     {
     477           0 :       mpi_immutable_failed ();
     478           0 :       return w;
     479             :     }
     480     3864524 :   RESIZE_IF_NEEDED(w, usize);
     481     3864524 :   wp = w->d;
     482     3864524 :   up = u->d;
     483     3864524 :   MPN_COPY( wp, up, usize );
     484     3864524 :   w->nlimbs = usize;
     485     3864524 :   w->flags = u->flags;
     486     3864524 :   w->flags &= ~(16|32); /* Reset the immutable and constant flags.  */
     487     3864524 :   w->sign = usign;
     488     3864524 :   return w;
     489             : }
     490             : 
     491             : /****************
     492             :  * Set the value of W by the one of U, when SET is 1.
     493             :  * Leave the value when SET is 0.
     494             :  * This implementation should be constant-time regardless of SET.
     495             :  */
     496             : gcry_mpi_t
     497    24564128 : _gcry_mpi_set_cond (gcry_mpi_t w, const gcry_mpi_t u, unsigned long set)
     498             : {
     499             :   mpi_size_t i;
     500    24564128 :   mpi_size_t nlimbs = u->alloced;
     501    24564128 :   mpi_limb_t mask = ((mpi_limb_t)0) - set;
     502             :   mpi_limb_t x;
     503             : 
     504    24564128 :   if (w->alloced != u->alloced)
     505           0 :     log_bug ("mpi_set_cond: different sizes\n");
     506             : 
     507   375846209 :   for (i = 0; i < nlimbs; i++)
     508             :     {
     509   351282081 :       x = mask & (w->d[i] ^ u->d[i]);
     510   351282081 :       w->d[i] = w->d[i] ^ x;
     511             :     }
     512             : 
     513    24564128 :   x = mask & (w->nlimbs ^ u->nlimbs);
     514    24564128 :   w->nlimbs = w->nlimbs ^ x;
     515             : 
     516    24564128 :   x = mask & (w->sign ^ u->sign);
     517    24564128 :   w->sign = w->sign ^ x;
     518    24564128 :   return w;
     519             : }
     520             : 
     521             : 
     522             : gcry_mpi_t
     523       32359 : _gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u)
     524             : {
     525       32359 :   if (!w)
     526          35 :     w = _gcry_mpi_alloc (1);
     527             :   /* FIXME: If U is 0 we have no need to resize and thus possible
     528             :      allocating the the limbs. */
     529       32359 :   if (mpi_is_immutable (w))
     530             :     {
     531           0 :       mpi_immutable_failed ();
     532           0 :       return w;
     533             :     }
     534       32359 :   RESIZE_IF_NEEDED(w, 1);
     535       32359 :   w->d[0] = u;
     536       32359 :   w->nlimbs = u? 1:0;
     537       32359 :   w->sign = 0;
     538       32359 :   w->flags = 0;
     539       32359 :   return w;
     540             : }
     541             : 
     542             : gcry_err_code_t
     543           0 : _gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
     544             : {
     545           0 :   gcry_err_code_t err = GPG_ERR_NO_ERROR;
     546           0 :   unsigned long x = 0;
     547             : 
     548           0 :   if (w->nlimbs > 1)
     549           0 :     err = GPG_ERR_TOO_LARGE;
     550           0 :   else if (w->nlimbs == 1)
     551           0 :     x = w->d[0];
     552             :   else
     553           0 :     x = 0;
     554             : 
     555           0 :   if (! err)
     556           0 :     *u = x;
     557             : 
     558           0 :   return err;
     559             : }
     560             : 
     561             : 
     562             : gcry_mpi_t
     563       20774 : _gcry_mpi_alloc_set_ui( unsigned long u)
     564             : {
     565       20774 :     gcry_mpi_t w = mpi_alloc(1);
     566       20774 :     w->d[0] = u;
     567       20774 :     w->nlimbs = u? 1:0;
     568       20774 :     w->sign = 0;
     569       20774 :     return w;
     570             : }
     571             : 
     572             : void
     573          18 : _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
     574             : {
     575             :     struct gcry_mpi tmp;
     576             : 
     577          18 :     tmp = *a; *a = *b; *b = tmp;
     578          18 : }
     579             : 
     580             : 
     581             : /****************
     582             :  * Swap the value of A and B, when SWAP is 1.
     583             :  * Leave the value when SWAP is 0.
     584             :  * This implementation should be constant-time regardless of SWAP.
     585             :  */
     586             : void
     587     1972913 : _gcry_mpi_swap_cond (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
     588             : {
     589             :   mpi_size_t i;
     590             :   mpi_size_t nlimbs;
     591     1972913 :   mpi_limb_t mask = ((mpi_limb_t)0) - swap;
     592             :   mpi_limb_t x;
     593             : 
     594     1972913 :   if (a->alloced > b->alloced)
     595           0 :     nlimbs = b->alloced;
     596             :   else
     597     1972913 :     nlimbs = a->alloced;
     598     1972913 :   if (a->nlimbs > nlimbs || b->nlimbs > nlimbs)
     599           0 :     log_bug ("mpi_swap_cond: different sizes\n");
     600             : 
     601    20153906 :   for (i = 0; i < nlimbs; i++)
     602             :     {
     603    18180993 :       x = mask & (a->d[i] ^ b->d[i]);
     604    18180993 :       a->d[i] = a->d[i] ^ x;
     605    18180993 :       b->d[i] = b->d[i] ^ x;
     606             :     }
     607             : 
     608     1972913 :   x = mask & (a->nlimbs ^ b->nlimbs);
     609     1972913 :   a->nlimbs = a->nlimbs ^ x;
     610     1972913 :   b->nlimbs = b->nlimbs ^ x;
     611             : 
     612     1972913 :   x = mask & (a->sign ^ b->sign);
     613     1972913 :   a->sign = a->sign ^ x;
     614     1972913 :   b->sign = b->sign ^ x;
     615     1972913 : }
     616             : 
     617             : 
     618             : gcry_mpi_t
     619       66654 : _gcry_mpi_new (unsigned int nbits)
     620             : {
     621       66654 :     return _gcry_mpi_alloc ( (nbits+BITS_PER_MPI_LIMB-1)
     622             :                              / BITS_PER_MPI_LIMB );
     623             : }
     624             : 
     625             : 
     626             : gcry_mpi_t
     627        5873 : _gcry_mpi_snew (unsigned int nbits)
     628             : {
     629        5873 :   return _gcry_mpi_alloc_secure ( (nbits+BITS_PER_MPI_LIMB-1)
     630             :                                   / BITS_PER_MPI_LIMB );
     631             : }
     632             : 
     633             : void
     634      131068 : _gcry_mpi_release( gcry_mpi_t a )
     635             : {
     636      131068 :     _gcry_mpi_free( a );
     637      131068 : }
     638             : 
     639             : void
     640        8502 : _gcry_mpi_randomize (gcry_mpi_t w,
     641             :                      unsigned int nbits, enum gcry_random_level level)
     642             : {
     643             :   unsigned char *p;
     644        8502 :   size_t nbytes = (nbits+7)/8;
     645             : 
     646        8502 :   if (mpi_is_immutable (w))
     647             :     {
     648           0 :       mpi_immutable_failed ();
     649           0 :       return;
     650             :     }
     651        8502 :   if (level == GCRY_WEAK_RANDOM)
     652             :     {
     653        8408 :       p = mpi_is_secure(w) ? xmalloc_secure (nbytes)
     654             :                            : xmalloc (nbytes);
     655        8408 :       _gcry_create_nonce (p, nbytes);
     656             :     }
     657             :   else
     658             :     {
     659          94 :       p = mpi_is_secure(w) ? _gcry_random_bytes_secure (nbytes, level)
     660             :                            : _gcry_random_bytes (nbytes, level);
     661             :     }
     662        8502 :   _gcry_mpi_set_buffer( w, p, nbytes, 0 );
     663        8502 :   xfree (p);
     664             : }
     665             : 
     666             : 
     667             : void
     668           2 : _gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
     669             : {
     670           2 :   switch (flag)
     671             :     {
     672           0 :     case GCRYMPI_FLAG_SECURE:     mpi_set_secure(a); break;
     673           1 :     case GCRYMPI_FLAG_CONST:      a->flags |= (16|32); break;
     674           1 :     case GCRYMPI_FLAG_IMMUTABLE:  a->flags |= 16; break;
     675             : 
     676             :     case GCRYMPI_FLAG_USER1:
     677             :     case GCRYMPI_FLAG_USER2:
     678             :     case GCRYMPI_FLAG_USER3:
     679           0 :     case GCRYMPI_FLAG_USER4:      a->flags |= flag; break;
     680             : 
     681             :     case GCRYMPI_FLAG_OPAQUE:
     682           0 :     default: log_bug("invalid flag value\n");
     683             :     }
     684           2 : }
     685             : 
     686             : void
     687           2 : _gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
     688             : {
     689             :   (void)a; /* Not yet used. */
     690             : 
     691           2 :   switch (flag)
     692             :     {
     693             :     case GCRYMPI_FLAG_IMMUTABLE:
     694           2 :       if (!(a->flags & 32))
     695           1 :         a->flags &= ~16;
     696           2 :       break;
     697             : 
     698             :     case GCRYMPI_FLAG_USER1:
     699             :     case GCRYMPI_FLAG_USER2:
     700             :     case GCRYMPI_FLAG_USER3:
     701             :     case GCRYMPI_FLAG_USER4:
     702           0 :       a->flags &= ~flag;
     703           0 :       break;
     704             : 
     705             :     case GCRYMPI_FLAG_CONST:
     706             :     case GCRYMPI_FLAG_SECURE:
     707             :     case GCRYMPI_FLAG_OPAQUE:
     708           0 :     default: log_bug("invalid flag value\n");
     709             :     }
     710           2 : }
     711             : 
     712             : int
     713        8138 : _gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
     714             : {
     715        8138 :   switch (flag)
     716             :     {
     717        3984 :     case GCRYMPI_FLAG_SECURE:    return !!(a->flags & 1);
     718        4134 :     case GCRYMPI_FLAG_OPAQUE:    return !!(a->flags & 4);
     719          10 :     case GCRYMPI_FLAG_IMMUTABLE: return !!(a->flags & 16);
     720          10 :     case GCRYMPI_FLAG_CONST:     return !!(a->flags & 32);
     721             :     case GCRYMPI_FLAG_USER1:
     722             :     case GCRYMPI_FLAG_USER2:
     723             :     case GCRYMPI_FLAG_USER3:
     724           0 :     case GCRYMPI_FLAG_USER4:     return !!(a->flags & flag);
     725           0 :     default: log_bug("invalid flag value\n");
     726             :     }
     727             :   /*NOTREACHED*/
     728             :   return 0;
     729             : }
     730             : 
     731             : 
     732             : /* Return a constant MPI descripbed by NO which is one of the
     733             :    MPI_C_xxx macros.  There is no need to copy this returned value; it
     734             :    may be used directly.  */
     735             : gcry_mpi_t
     736      838936 : _gcry_mpi_const (enum gcry_mpi_constants no)
     737             : {
     738      838936 :   if ((int)no < 0 || no > MPI_NUMBER_OF_CONSTANTS)
     739           0 :     log_bug("invalid mpi_const selector %d\n", no);
     740      838936 :   if (!constants[no])
     741           0 :     log_bug("MPI subsystem not initialized\n");
     742      838936 :   return constants[no];
     743             : }

Generated by: LCOV version 1.13