summaryrefslogtreecommitdiffabout
path: root/pwmanager/libcrypt/mpi/mpi-div.c
Unidiff
Diffstat (limited to 'pwmanager/libcrypt/mpi/mpi-div.c') (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/libcrypt/mpi/mpi-div.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/mpi/mpi-div.c b/pwmanager/libcrypt/mpi/mpi-div.c
new file mode 100644
index 0000000..6172eb4
--- a/dev/null
+++ b/pwmanager/libcrypt/mpi/mpi-div.c
@@ -0,0 +1,364 @@
1/* mpi-div.c - MPI functions
2 * Copyright (C) 1994, 1996, 1998, 2001, 2002,
3 * 2003 Free Software Foundation, Inc.
4 *
5 * This file is part of Libgcrypt.
6 *
7 * Libgcrypt is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * Libgcrypt is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 *
21 * Note: This code is heavily based on the GNU MP Library.
22 * Actually it's the same code with only minor changes in the
23 * way the data is stored; this is to support the abstraction
24 * of an optional secure memory allocation which may be used
25 * to avoid revealing of sensitive data due to paging etc.
26 */
27
28#include <config.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include "mpi-internal.h"
32#include "longlong.h"
33#include "g10lib.h"
34
35
36void
37_gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
38{
39 int divisor_sign = divisor->sign;
40 gcry_mpi_t temp_divisor = NULL;
41
42 /* We need the original value of the divisor after the remainder has been
43 * preliminary calculated.We have to copy it to temporary space if it's
44 * the same variable as REM. */
45 if( rem == divisor ) {
46 temp_divisor = mpi_copy( divisor );
47 divisor = temp_divisor;
48 }
49
50 _gcry_mpi_tdiv_r( rem, dividend, divisor );
51
52 if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
53 gcry_mpi_add( rem, rem, divisor);
54
55 if( temp_divisor )
56 mpi_free(temp_divisor);
57}
58
59
60
61/****************
62 * Division rounding the quotient towards -infinity.
63 * The remainder gets the same sign as the denominator.
64 * rem is optional
65 */
66
67ulong
68_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor )
69{
70 mpi_limb_t rlimb;
71
72 rlimb = _gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
73 if( rlimb && dividend->sign )
74 rlimb = divisor - rlimb;
75
76 if( rem ) {
77 rem->d[0] = rlimb;
78 rem->nlimbs = rlimb? 1:0;
79 }
80 return rlimb;
81}
82
83
84void
85_gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor )
86{
87 gcry_mpi_t tmp = mpi_alloc( mpi_get_nlimbs(quot) );
88 _gcry_mpi_fdiv_qr( quot, tmp, dividend, divisor);
89 mpi_free(tmp);
90}
91
92void
93_gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
94{
95 int divisor_sign = divisor->sign;
96 gcry_mpi_t temp_divisor = NULL;
97
98 if( quot == divisor || rem == divisor ) {
99 temp_divisor = mpi_copy( divisor );
100 divisor = temp_divisor;
101 }
102
103 _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor );
104
105 if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
106 gcry_mpi_sub_ui( quot, quot, 1 );
107 gcry_mpi_add( rem, rem, divisor);
108 }
109
110 if( temp_divisor )
111 mpi_free(temp_divisor);
112}
113
114
115/* If den == quot, den needs temporary storage.
116 * If den == rem, den needs temporary storage.
117 * If num == quot, num needs temporary storage.
118 * If den has temporary storage, it can be normalized while being copied,
119 * i.e no extra storage should be allocated.
120 */
121
122void
123_gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
124{
125 _gcry_mpi_tdiv_qr(NULL, rem, num, den );
126}
127
128void
129_gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
130{
131 mpi_ptr_t np, dp;
132 mpi_ptr_t qp, rp;
133 mpi_size_t nsize = num->nlimbs;
134 mpi_size_t dsize = den->nlimbs;
135 mpi_size_t qsize, rsize;
136 mpi_size_t sign_remainder = num->sign;
137 mpi_size_t sign_quotient = num->sign ^ den->sign;
138 unsigned normalization_steps;
139 mpi_limb_t q_limb;
140 mpi_ptr_t marker[5];
141 unsigned int marker_nlimbs[5];
142 int markidx=0;
143
144 /* Ensure space is enough for quotient and remainder.
145 * We need space for an extra limb in the remainder, because it's
146 * up-shifted (normalized) below. */
147 rsize = nsize + 1;
148 mpi_resize( rem, rsize);
149
150 qsize = rsize - dsize; /* qsize cannot be bigger than this.*/
151 if( qsize <= 0 ) {
152 if( num != rem ) {
153 rem->nlimbs = num->nlimbs;
154 rem->sign = num->sign;
155 MPN_COPY(rem->d, num->d, nsize);
156 }
157 if( quot ) {
158 /* This needs to follow the assignment to rem, in case the
159 * numerator and quotient are the same. */
160 quot->nlimbs = 0;
161 quot->sign = 0;
162 }
163 return;
164 }
165
166 if( quot )
167 mpi_resize( quot, qsize);
168
169 /* Read pointers here, when reallocation is finished. */
170 np = num->d;
171 dp = den->d;
172 rp = rem->d;
173
174 /* Optimize division by a single-limb divisor. */
175 if( dsize == 1 ) {
176 mpi_limb_t rlimb;
177 if( quot ) {
178 qp = quot->d;
179 rlimb = _gcry_mpih_divmod_1( qp, np, nsize, dp[0] );
180 qsize -= qp[qsize - 1] == 0;
181 quot->nlimbs = qsize;
182 quot->sign = sign_quotient;
183 }
184 else
185 rlimb = _gcry_mpih_mod_1( np, nsize, dp[0] );
186 rp[0] = rlimb;
187 rsize = rlimb != 0?1:0;
188 rem->nlimbs = rsize;
189 rem->sign = sign_remainder;
190 return;
191 }
192
193
194 if( quot ) {
195 qp = quot->d;
196 /* Make sure QP and NP point to different objects. Otherwise the
197 * numerator would be gradually overwritten by the quotient limbs. */
198 if(qp == np) { /* Copy NP object to temporary space. */
199 marker_nlimbs[markidx] = nsize;
200 np = marker[markidx++] = mpi_alloc_limb_space(nsize,
201 mpi_is_secure(quot));
202 MPN_COPY(np, qp, nsize);
203 }
204 }
205 else /* Put quotient at top of remainder. */
206 qp = rp + dsize;
207
208 count_leading_zeros( normalization_steps, dp[dsize - 1] );
209
210 /* Normalize the denominator, i.e. make its most significant bit set by
211 * shifting it NORMALIZATION_STEPS bits to the left. Also shift the
212 * numerator the same number of steps (to keep the quotient the same!).
213 */
214 if( normalization_steps ) {
215 mpi_ptr_t tp;
216 mpi_limb_t nlimb;
217
218 /* Shift up the denominator setting the most significant bit of
219 * the most significant word. Use temporary storage not to clobber
220 * the original contents of the denominator. */
221 marker_nlimbs[markidx] = dsize;
222 tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
223 _gcry_mpih_lshift( tp, dp, dsize, normalization_steps );
224 dp = tp;
225
226 /* Shift up the numerator, possibly introducing a new most
227 * significant word. Move the shifted numerator in the remainder
228 * meanwhile. */
229 nlimb = _gcry_mpih_lshift(rp, np, nsize, normalization_steps);
230 if( nlimb ) {
231 rp[nsize] = nlimb;
232 rsize = nsize + 1;
233 }
234 else
235 rsize = nsize;
236 }
237 else {
238 /* The denominator is already normalized, as required.Copy it to
239 * temporary space if it overlaps with the quotient or remainder. */
240 if( dp == rp || (quot && (dp == qp))) {
241 mpi_ptr_t tp;
242
243 marker_nlimbs[markidx] = dsize;
244 tp = marker[markidx++] = mpi_alloc_limb_space(dsize,
245 mpi_is_secure(den));
246 MPN_COPY( tp, dp, dsize );
247 dp = tp;
248 }
249
250 /* Move the numerator to the remainder. */
251 if( rp != np )
252 MPN_COPY(rp, np, nsize);
253
254 rsize = nsize;
255 }
256
257 q_limb = _gcry_mpih_divrem( qp, 0, rp, rsize, dp, dsize );
258
259 if( quot ) {
260 qsize = rsize - dsize;
261 if(q_limb) {
262 qp[qsize] = q_limb;
263 qsize += 1;
264 }
265
266 quot->nlimbs = qsize;
267 quot->sign = sign_quotient;
268 }
269
270 rsize = dsize;
271 MPN_NORMALIZE (rp, rsize);
272
273 if( normalization_steps && rsize ) {
274 _gcry_mpih_rshift(rp, rp, rsize, normalization_steps);
275 rsize -= rp[rsize - 1] == 0?1:0;
276 }
277
278 rem->nlimbs = rsize;
279 rem->sign= sign_remainder;
280 while( markidx )
281 {
282 markidx--;
283 _gcry_mpi_free_limb_space (marker[markidx], marker_nlimbs[markidx]);
284 }
285}
286
287void
288_gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned int count )
289{
290 mpi_size_t usize, wsize;
291 mpi_size_t limb_cnt;
292
293 usize = u->nlimbs;
294 limb_cnt = count / BITS_PER_MPI_LIMB;
295 wsize = usize - limb_cnt;
296 if( limb_cnt >= usize )
297 w->nlimbs = 0;
298 else {
299 mpi_ptr_t wp;
300 mpi_ptr_t up;
301
302 RESIZE_IF_NEEDED( w, wsize );
303 wp = w->d;
304 up = u->d;
305
306 count %= BITS_PER_MPI_LIMB;
307 if( count ) {
308 _gcry_mpih_rshift( wp, up + limb_cnt, wsize, count );
309 wsize -= !wp[wsize - 1];
310 }
311 else {
312 MPN_COPY_INCR( wp, up + limb_cnt, wsize);
313 }
314
315 w->nlimbs = wsize;
316 }
317}
318
319/****************
320 * Check whether dividend is divisible by divisor
321 * (note: divisor must fit into a limb)
322 */
323int
324_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor )
325{
326 return !_gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
327}
328
329
330void
331gcry_mpi_div (gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor, int round)
332{
333 if (!round)
334 {
335 if (!rem)
336 {
337 gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs(quot));
338 _gcry_mpi_tdiv_qr (quot, tmp, dividend, divisor);
339 mpi_free (tmp);
340 }
341 else
342 _gcry_mpi_tdiv_qr (quot, rem, dividend, divisor);
343 }
344 else if (round < 0)
345 {
346 if (!rem)
347 _gcry_mpi_fdiv_q (quot, dividend, divisor);
348 else if (!quot)
349 _gcry_mpi_fdiv_r (rem, dividend, divisor);
350 else
351 _gcry_mpi_fdiv_qr (quot, rem, dividend, divisor);
352 }
353 else
354 log_bug ("mpi rounding to ceiling not yet implemented\n");
355}
356
357
358void
359gcry_mpi_mod (gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor)
360{
361 _gcry_mpi_fdiv_r (rem, dividend, divisor);
362 rem->sign = 0;
363}
364