~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/crypto/mpi/mpi-pow.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /lib/crypto/mpi/mpi-pow.c (Architecture ppc) and /lib/crypto/mpi/mpi-pow.c (Architecture sparc64)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /* mpi-pow.c  -  MPI functions                      2 /* mpi-pow.c  -  MPI functions
  3  *      Copyright (C) 1994, 1996, 1998, 2000 F      3  *      Copyright (C) 1994, 1996, 1998, 2000 Free Software Foundation, Inc.
  4  *                                                  4  *
  5  * This file is part of GnuPG.                      5  * This file is part of GnuPG.
  6  *                                                  6  *
  7  * Note: This code is heavily based on the GNU      7  * Note: This code is heavily based on the GNU MP Library.
  8  *       Actually it's the same code with only      8  *       Actually it's the same code with only minor changes in the
  9  *       way the data is stored; this is to su      9  *       way the data is stored; this is to support the abstraction
 10  *       of an optional secure memory allocati     10  *       of an optional secure memory allocation which may be used
 11  *       to avoid revealing of sensitive data      11  *       to avoid revealing of sensitive data due to paging etc.
 12  *       The GNU MP Library itself is publishe     12  *       The GNU MP Library itself is published under the LGPL;
 13  *       however I decided to publish this cod     13  *       however I decided to publish this code under the plain GPL.
 14  */                                                14  */
 15                                                    15 
 16 #include <linux/sched.h>                           16 #include <linux/sched.h>
 17 #include <linux/string.h>                          17 #include <linux/string.h>
 18 #include "mpi-internal.h"                          18 #include "mpi-internal.h"
 19 #include "longlong.h"                              19 #include "longlong.h"
 20                                                    20 
 21 /****************                                  21 /****************
 22  * RES = BASE ^ EXP mod MOD                        22  * RES = BASE ^ EXP mod MOD
 23  */                                                23  */
 24 int mpi_powm(MPI res, MPI base, MPI exp, MPI m     24 int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
 25 {                                                  25 {
 26         mpi_ptr_t mp_marker = NULL, bp_marker      26         mpi_ptr_t mp_marker = NULL, bp_marker = NULL, ep_marker = NULL;
 27         struct karatsuba_ctx karactx = {};         27         struct karatsuba_ctx karactx = {};
 28         mpi_ptr_t xp_marker = NULL;                28         mpi_ptr_t xp_marker = NULL;
 29         mpi_ptr_t tspace = NULL;                   29         mpi_ptr_t tspace = NULL;
 30         mpi_ptr_t rp, ep, mp, bp;                  30         mpi_ptr_t rp, ep, mp, bp;
 31         mpi_size_t esize, msize, bsize, rsize;     31         mpi_size_t esize, msize, bsize, rsize;
 32         int msign, bsign, rsign;                   32         int msign, bsign, rsign;
 33         mpi_size_t size;                           33         mpi_size_t size;
 34         int mod_shift_cnt;                         34         int mod_shift_cnt;
 35         int negative_result;                       35         int negative_result;
 36         int assign_rp = 0;                         36         int assign_rp = 0;
 37         mpi_size_t tsize = 0;   /* to avoid co     37         mpi_size_t tsize = 0;   /* to avoid compiler warning */
 38         /* fixme: we should check that the war     38         /* fixme: we should check that the warning is void */
 39         int rc = -ENOMEM;                          39         int rc = -ENOMEM;
 40                                                    40 
 41         esize = exp->nlimbs;                       41         esize = exp->nlimbs;
 42         msize = mod->nlimbs;                       42         msize = mod->nlimbs;
 43         size = 2 * msize;                          43         size = 2 * msize;
 44         msign = mod->sign;                         44         msign = mod->sign;
 45                                                    45 
 46         rp = res->d;                               46         rp = res->d;
 47         ep = exp->d;                               47         ep = exp->d;
 48                                                    48 
 49         if (!msize)                                49         if (!msize)
 50                 return -EINVAL;                    50                 return -EINVAL;
 51                                                    51 
 52         if (!esize) {                              52         if (!esize) {
 53                 /* Exponent is zero, result is     53                 /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
 54                  * depending on if MOD equals      54                  * depending on if MOD equals 1.  */
 55                 res->nlimbs = (msize == 1 && m     55                 res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
 56                 if (res->nlimbs) {                 56                 if (res->nlimbs) {
 57                         if (mpi_resize(res, 1)     57                         if (mpi_resize(res, 1) < 0)
 58                                 goto enomem;       58                                 goto enomem;
 59                         rp = res->d;               59                         rp = res->d;
 60                         rp[0] = 1;                 60                         rp[0] = 1;
 61                 }                                  61                 }
 62                 res->sign = 0;                     62                 res->sign = 0;
 63                 goto leave;                        63                 goto leave;
 64         }                                          64         }
 65                                                    65 
 66         /* Normalize MOD (i.e. make its most s     66         /* Normalize MOD (i.e. make its most significant bit set) as required by
 67          * mpn_divrem.  This will make the int     67          * mpn_divrem.  This will make the intermediate values in the calculation
 68          * slightly larger, but the correct re     68          * slightly larger, but the correct result is obtained after a final
 69          * reduction using the original MOD va     69          * reduction using the original MOD value.  */
 70         mp = mp_marker = mpi_alloc_limb_space(     70         mp = mp_marker = mpi_alloc_limb_space(msize);
 71         if (!mp)                                   71         if (!mp)
 72                 goto enomem;                       72                 goto enomem;
 73         mod_shift_cnt = count_leading_zeros(mo     73         mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]);
 74         if (mod_shift_cnt)                         74         if (mod_shift_cnt)
 75                 mpihelp_lshift(mp, mod->d, msi     75                 mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt);
 76         else                                       76         else
 77                 MPN_COPY(mp, mod->d, msize);       77                 MPN_COPY(mp, mod->d, msize);
 78                                                    78 
 79         bsize = base->nlimbs;                      79         bsize = base->nlimbs;
 80         bsign = base->sign;                        80         bsign = base->sign;
 81         if (bsize > msize) {    /* The base is     81         if (bsize > msize) {    /* The base is larger than the module. Reduce it. */
 82                 /* Allocate (BSIZE + 1) with s     82                 /* Allocate (BSIZE + 1) with space for remainder and quotient.
 83                  * (The quotient is (bsize - m     83                  * (The quotient is (bsize - msize + 1) limbs.)  */
 84                 bp = bp_marker = mpi_alloc_lim     84                 bp = bp_marker = mpi_alloc_limb_space(bsize + 1);
 85                 if (!bp)                           85                 if (!bp)
 86                         goto enomem;               86                         goto enomem;
 87                 MPN_COPY(bp, base->d, bsize);      87                 MPN_COPY(bp, base->d, bsize);
 88                 /* We don't care about the quo     88                 /* We don't care about the quotient, store it above the remainder,
 89                  * at BP + MSIZE.  */              89                  * at BP + MSIZE.  */
 90                 mpihelp_divrem(bp + msize, 0,      90                 mpihelp_divrem(bp + msize, 0, bp, bsize, mp, msize);
 91                 bsize = msize;                     91                 bsize = msize;
 92                 /* Canonicalize the base, sinc     92                 /* Canonicalize the base, since we are going to multiply with it
 93                  * quite a few times.  */          93                  * quite a few times.  */
 94                 MPN_NORMALIZE(bp, bsize);          94                 MPN_NORMALIZE(bp, bsize);
 95         } else                                     95         } else
 96                 bp = base->d;                      96                 bp = base->d;
 97                                                    97 
 98         if (!bsize) {                              98         if (!bsize) {
 99                 res->nlimbs = 0;                   99                 res->nlimbs = 0;
100                 res->sign = 0;                    100                 res->sign = 0;
101                 goto leave;                       101                 goto leave;
102         }                                         102         }
103                                                   103 
104         if (res->alloced < size) {                104         if (res->alloced < size) {
105                 /* We have to allocate more sp    105                 /* We have to allocate more space for RES.  If any of the input
106                  * parameters are identical to    106                  * parameters are identical to RES, defer deallocation of the old
107                  * space.  */                     107                  * space.  */
108                 if (rp == ep || rp == mp || rp    108                 if (rp == ep || rp == mp || rp == bp) {
109                         rp = mpi_alloc_limb_sp    109                         rp = mpi_alloc_limb_space(size);
110                         if (!rp)                  110                         if (!rp)
111                                 goto enomem;      111                                 goto enomem;
112                         assign_rp = 1;            112                         assign_rp = 1;
113                 } else {                          113                 } else {
114                         if (mpi_resize(res, si    114                         if (mpi_resize(res, size) < 0)
115                                 goto enomem;      115                                 goto enomem;
116                         rp = res->d;              116                         rp = res->d;
117                 }                                 117                 }
118         } else {                /* Make BASE,     118         } else {                /* Make BASE, EXP and MOD not overlap with RES.  */
119                 if (rp == bp) {                   119                 if (rp == bp) {
120                         /* RES and BASE are id    120                         /* RES and BASE are identical.  Allocate temp. space for BASE.  */
121                         BUG_ON(bp_marker);        121                         BUG_ON(bp_marker);
122                         bp = bp_marker = mpi_a    122                         bp = bp_marker = mpi_alloc_limb_space(bsize);
123                         if (!bp)                  123                         if (!bp)
124                                 goto enomem;      124                                 goto enomem;
125                         MPN_COPY(bp, rp, bsize    125                         MPN_COPY(bp, rp, bsize);
126                 }                                 126                 }
127                 if (rp == ep) {                   127                 if (rp == ep) {
128                         /* RES and EXP are ide    128                         /* RES and EXP are identical.  Allocate temp. space for EXP.  */
129                         ep = ep_marker = mpi_a    129                         ep = ep_marker = mpi_alloc_limb_space(esize);
130                         if (!ep)                  130                         if (!ep)
131                                 goto enomem;      131                                 goto enomem;
132                         MPN_COPY(ep, rp, esize    132                         MPN_COPY(ep, rp, esize);
133                 }                                 133                 }
134                 if (rp == mp) {                   134                 if (rp == mp) {
135                         /* RES and MOD are ide    135                         /* RES and MOD are identical.  Allocate temporary space for MOD. */
136                         BUG_ON(mp_marker);        136                         BUG_ON(mp_marker);
137                         mp = mp_marker = mpi_a    137                         mp = mp_marker = mpi_alloc_limb_space(msize);
138                         if (!mp)                  138                         if (!mp)
139                                 goto enomem;      139                                 goto enomem;
140                         MPN_COPY(mp, rp, msize    140                         MPN_COPY(mp, rp, msize);
141                 }                                 141                 }
142         }                                         142         }
143                                                   143 
144         MPN_COPY(rp, bp, bsize);                  144         MPN_COPY(rp, bp, bsize);
145         rsize = bsize;                            145         rsize = bsize;
146         rsign = bsign;                            146         rsign = bsign;
147                                                   147 
148         {                                         148         {
149                 mpi_size_t i;                     149                 mpi_size_t i;
150                 mpi_ptr_t xp;                     150                 mpi_ptr_t xp;
151                 int c;                            151                 int c;
152                 mpi_limb_t e;                     152                 mpi_limb_t e;
153                 mpi_limb_t carry_limb;            153                 mpi_limb_t carry_limb;
154                                                   154 
155                 xp = xp_marker = mpi_alloc_lim    155                 xp = xp_marker = mpi_alloc_limb_space(2 * (msize + 1));
156                 if (!xp)                          156                 if (!xp)
157                         goto enomem;              157                         goto enomem;
158                                                   158 
159                 negative_result = (ep[0] & 1)     159                 negative_result = (ep[0] & 1) && base->sign;
160                                                   160 
161                 i = esize - 1;                    161                 i = esize - 1;
162                 e = ep[i];                        162                 e = ep[i];
163                 c = count_leading_zeros(e);       163                 c = count_leading_zeros(e);
164                 e = (e << c) << 1;      /* shi    164                 e = (e << c) << 1;      /* shift the exp bits to the left, lose msb */
165                 c = BITS_PER_MPI_LIMB - 1 - c;    165                 c = BITS_PER_MPI_LIMB - 1 - c;
166                                                   166 
167                 /* Main loop.                     167                 /* Main loop.
168                  *                                168                  *
169                  * Make the result be pointed     169                  * Make the result be pointed to alternately by XP and RP.  This
170                  * helps us avoid block copyin    170                  * helps us avoid block copying, which would otherwise be necessary
171                  * with the overlap restrictio    171                  * with the overlap restrictions of mpihelp_divmod. With 50% probability
172                  * the result after this loop     172                  * the result after this loop will be in the area originally pointed
173                  * by RP (==RES->d), and with     173                  * by RP (==RES->d), and with 50% probability in the area originally
174                  * pointed to by XP.              174                  * pointed to by XP.
175                  */                               175                  */
176                                                   176 
177                 for (;;) {                        177                 for (;;) {
178                         while (c) {               178                         while (c) {
179                                 mpi_size_t xsi    179                                 mpi_size_t xsize;
180                                                   180 
181                                 /*if (mpihelp_    181                                 /*if (mpihelp_mul_n(xp, rp, rp, rsize) < 0) goto enomem */
182                                 if (rsize < KA    182                                 if (rsize < KARATSUBA_THRESHOLD)
183                                         mpih_s    183                                         mpih_sqr_n_basecase(xp, rp, rsize);
184                                 else {            184                                 else {
185                                         if (!t    185                                         if (!tspace) {
186                                                   186                                                 tsize = 2 * rsize;
187                                                   187                                                 tspace =
188                                                   188                                                     mpi_alloc_limb_space(tsize);
189                                                   189                                                 if (!tspace)
190                                                   190                                                         goto enomem;
191                                         } else    191                                         } else if (tsize < (2 * rsize)) {
192                                                   192                                                 mpi_free_limb_space(tspace);
193                                                   193                                                 tsize = 2 * rsize;
194                                                   194                                                 tspace =
195                                                   195                                                     mpi_alloc_limb_space(tsize);
196                                                   196                                                 if (!tspace)
197                                                   197                                                         goto enomem;
198                                         }         198                                         }
199                                         mpih_s    199                                         mpih_sqr_n(xp, rp, rsize, tspace);
200                                 }                 200                                 }
201                                                   201 
202                                 xsize = 2 * rs    202                                 xsize = 2 * rsize;
203                                 if (xsize > ms    203                                 if (xsize > msize) {
204                                         mpihel    204                                         mpihelp_divrem(xp + msize, 0, xp, xsize,
205                                                   205                                                        mp, msize);
206                                         xsize     206                                         xsize = msize;
207                                 }                 207                                 }
208                                                   208 
209                                 swap(rp, xp);     209                                 swap(rp, xp);
210                                 rsize = xsize;    210                                 rsize = xsize;
211                                                   211 
212                                 if ((mpi_limb_    212                                 if ((mpi_limb_signed_t) e < 0) {
213                                         /*mpih    213                                         /*mpihelp_mul( xp, rp, rsize, bp, bsize ); */
214                                         if (bs    214                                         if (bsize < KARATSUBA_THRESHOLD) {
215                                                   215                                                 mpi_limb_t tmp;
216                                                   216                                                 if (mpihelp_mul
217                                                   217                                                     (xp, rp, rsize, bp, bsize,
218                                                   218                                                      &tmp) < 0)
219                                                   219                                                         goto enomem;
220                                         } else    220                                         } else {
221                                                   221                                                 if (mpihelp_mul_karatsuba_case
222                                                   222                                                     (xp, rp, rsize, bp, bsize,
223                                                   223                                                      &karactx) < 0)
224                                                   224                                                         goto enomem;
225                                         }         225                                         }
226                                                   226 
227                                         xsize     227                                         xsize = rsize + bsize;
228                                         if (xs    228                                         if (xsize > msize) {
229                                                   229                                                 mpihelp_divrem(xp + msize, 0,
230                                                   230                                                                xp, xsize, mp,
231                                                   231                                                                msize);
232                                                   232                                                 xsize = msize;
233                                         }         233                                         }
234                                                   234 
235                                         swap(r    235                                         swap(rp, xp);
236                                         rsize     236                                         rsize = xsize;
237                                 }                 237                                 }
238                                 e <<= 1;          238                                 e <<= 1;
239                                 c--;              239                                 c--;
240                                 cond_resched()    240                                 cond_resched();
241                         }                         241                         }
242                                                   242 
243                         i--;                      243                         i--;
244                         if (i < 0)                244                         if (i < 0)
245                                 break;            245                                 break;
246                         e = ep[i];                246                         e = ep[i];
247                         c = BITS_PER_MPI_LIMB;    247                         c = BITS_PER_MPI_LIMB;
248                 }                                 248                 }
249                                                   249 
250                 /* We shifted MOD, the modulo     250                 /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT
251                  * steps.  Adjust the result b    251                  * steps.  Adjust the result by reducing it with the original MOD.
252                  *                                252                  *
253                  * Also make sure the result i    253                  * Also make sure the result is put in RES->d (where it already
254                  * might be, see above).          254                  * might be, see above).
255                  */                               255                  */
256                 if (mod_shift_cnt) {              256                 if (mod_shift_cnt) {
257                         carry_limb =              257                         carry_limb =
258                             mpihelp_lshift(res    258                             mpihelp_lshift(res->d, rp, rsize, mod_shift_cnt);
259                         rp = res->d;              259                         rp = res->d;
260                         if (carry_limb) {         260                         if (carry_limb) {
261                                 rp[rsize] = ca    261                                 rp[rsize] = carry_limb;
262                                 rsize++;          262                                 rsize++;
263                         }                         263                         }
264                 } else {                          264                 } else {
265                         MPN_COPY(res->d, rp, r    265                         MPN_COPY(res->d, rp, rsize);
266                         rp = res->d;              266                         rp = res->d;
267                 }                                 267                 }
268                                                   268 
269                 if (rsize >= msize) {             269                 if (rsize >= msize) {
270                         mpihelp_divrem(rp + ms    270                         mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize);
271                         rsize = msize;            271                         rsize = msize;
272                 }                                 272                 }
273                                                   273 
274                 /* Remove any leading zero wor    274                 /* Remove any leading zero words from the result.  */
275                 if (mod_shift_cnt)                275                 if (mod_shift_cnt)
276                         mpihelp_rshift(rp, rp,    276                         mpihelp_rshift(rp, rp, rsize, mod_shift_cnt);
277                 MPN_NORMALIZE(rp, rsize);         277                 MPN_NORMALIZE(rp, rsize);
278         }                                         278         }
279                                                   279 
280         if (negative_result && rsize) {           280         if (negative_result && rsize) {
281                 if (mod_shift_cnt)                281                 if (mod_shift_cnt)
282                         mpihelp_rshift(mp, mp,    282                         mpihelp_rshift(mp, mp, msize, mod_shift_cnt);
283                 mpihelp_sub(rp, mp, msize, rp,    283                 mpihelp_sub(rp, mp, msize, rp, rsize);
284                 rsize = msize;                    284                 rsize = msize;
285                 rsign = msign;                    285                 rsign = msign;
286                 MPN_NORMALIZE(rp, rsize);         286                 MPN_NORMALIZE(rp, rsize);
287         }                                         287         }
288         res->nlimbs = rsize;                      288         res->nlimbs = rsize;
289         res->sign = rsign;                        289         res->sign = rsign;
290                                                   290 
291 leave:                                            291 leave:
292         rc = 0;                                   292         rc = 0;
293 enomem:                                           293 enomem:
294         mpihelp_release_karatsuba_ctx(&karactx    294         mpihelp_release_karatsuba_ctx(&karactx);
295         if (assign_rp)                            295         if (assign_rp)
296                 mpi_assign_limb_space(res, rp,    296                 mpi_assign_limb_space(res, rp, size);
297         if (mp_marker)                            297         if (mp_marker)
298                 mpi_free_limb_space(mp_marker)    298                 mpi_free_limb_space(mp_marker);
299         if (bp_marker)                            299         if (bp_marker)
300                 mpi_free_limb_space(bp_marker)    300                 mpi_free_limb_space(bp_marker);
301         if (ep_marker)                            301         if (ep_marker)
302                 mpi_free_limb_space(ep_marker)    302                 mpi_free_limb_space(ep_marker);
303         if (xp_marker)                            303         if (xp_marker)
304                 mpi_free_limb_space(xp_marker)    304                 mpi_free_limb_space(xp_marker);
305         if (tspace)                               305         if (tspace)
306                 mpi_free_limb_space(tspace);      306                 mpi_free_limb_space(tspace);
307         return rc;                                307         return rc;
308 }                                                 308 }
309 EXPORT_SYMBOL_GPL(mpi_powm);                      309 EXPORT_SYMBOL_GPL(mpi_powm);
310                                                   310 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php