Line data Source code
1 : /* mpi-bit.c - MPI bit level functions
2 : * Copyright (C) 1998, 1999, 2001, 2002, 2006 Free Software Foundation, Inc.
3 : * Copyright (C) 2013 g10 Code GmbH
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 :
22 : #include <config.h>
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include "mpi-internal.h"
26 : #include "longlong.h"
27 :
28 :
29 : #ifdef MPI_INTERNAL_NEED_CLZ_TAB
30 : #ifdef __STDC__
31 : const
32 : #endif
33 : unsigned char
34 : _gcry_clz_tab[] =
35 : {
36 : 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
37 : 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
38 : 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
39 : 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
40 : 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
41 : 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
42 : 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
43 : 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
44 : };
45 : #endif
46 :
47 :
48 : #define A_LIMB_1 ((mpi_limb_t)1)
49 :
50 :
51 : /****************
52 : * Sometimes we have MSL (most significant limbs) which are 0;
53 : * this is for some reasons not good, so this function removes them.
54 : */
55 : void
56 0 : _gcry_mpi_normalize( gcry_mpi_t a )
57 : {
58 0 : if( mpi_is_opaque(a) )
59 0 : return;
60 :
61 0 : for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- )
62 : ;
63 : }
64 :
65 :
66 :
67 : /****************
68 : * Return the number of bits in A.
69 : */
70 : unsigned int
71 0 : _gcry_mpi_get_nbits (gcry_mpi_t a)
72 : {
73 : unsigned n;
74 :
75 0 : if( mpi_is_opaque(a) ) {
76 0 : return a->sign; /* which holds the number of bits */
77 : }
78 :
79 0 : _gcry_mpi_normalize( a );
80 0 : if( a->nlimbs ) {
81 0 : mpi_limb_t alimb = a->d[a->nlimbs-1];
82 0 : if( alimb )
83 0 : count_leading_zeros( n, alimb );
84 : else
85 0 : n = BITS_PER_MPI_LIMB;
86 0 : n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB;
87 : }
88 : else
89 0 : n = 0;
90 0 : return n;
91 : }
92 :
93 :
94 : /****************
95 : * Test whether bit N is set.
96 : */
97 : int
98 0 : _gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n )
99 : {
100 : unsigned int limbno, bitno;
101 : mpi_limb_t limb;
102 :
103 0 : limbno = n / BITS_PER_MPI_LIMB;
104 0 : bitno = n % BITS_PER_MPI_LIMB;
105 :
106 0 : if( limbno >= a->nlimbs )
107 0 : return 0; /* too far left: this is a 0 */
108 0 : limb = a->d[limbno];
109 0 : return (limb & (A_LIMB_1 << bitno))? 1: 0;
110 : }
111 :
112 :
113 : /****************
114 : * Set bit N of A.
115 : */
116 : void
117 0 : _gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n )
118 : {
119 : unsigned int i, limbno, bitno;
120 :
121 0 : if (mpi_is_immutable (a))
122 : {
123 0 : mpi_immutable_failed ();
124 0 : return;
125 : }
126 :
127 0 : limbno = n / BITS_PER_MPI_LIMB;
128 0 : bitno = n % BITS_PER_MPI_LIMB;
129 :
130 0 : if ( limbno >= a->nlimbs )
131 : {
132 0 : for (i=a->nlimbs; i < a->alloced; i++)
133 0 : a->d[i] = 0;
134 0 : mpi_resize (a, limbno+1 );
135 0 : a->nlimbs = limbno+1;
136 : }
137 0 : a->d[limbno] |= (A_LIMB_1<<bitno);
138 : }
139 :
140 : /****************
141 : * Set bit N of A. and clear all bits above
142 : */
143 : void
144 0 : _gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n )
145 : {
146 : unsigned int i, limbno, bitno;
147 :
148 0 : if (mpi_is_immutable (a))
149 : {
150 0 : mpi_immutable_failed ();
151 0 : return;
152 : }
153 :
154 0 : limbno = n / BITS_PER_MPI_LIMB;
155 0 : bitno = n % BITS_PER_MPI_LIMB;
156 :
157 0 : if ( limbno >= a->nlimbs )
158 : {
159 0 : for (i=a->nlimbs; i < a->alloced; i++)
160 0 : a->d[i] = 0;
161 0 : mpi_resize (a, limbno+1 );
162 0 : a->nlimbs = limbno+1;
163 : }
164 0 : a->d[limbno] |= (A_LIMB_1<<bitno);
165 0 : for ( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
166 0 : a->d[limbno] &= ~(A_LIMB_1 << bitno);
167 0 : a->nlimbs = limbno+1;
168 : }
169 :
170 : /****************
171 : * clear bit N of A and all bits above
172 : */
173 : void
174 0 : _gcry_mpi_clear_highbit( gcry_mpi_t a, unsigned int n )
175 : {
176 : unsigned int limbno, bitno;
177 :
178 0 : if (mpi_is_immutable (a))
179 : {
180 0 : mpi_immutable_failed ();
181 0 : return;
182 : }
183 :
184 0 : limbno = n / BITS_PER_MPI_LIMB;
185 0 : bitno = n % BITS_PER_MPI_LIMB;
186 :
187 0 : if( limbno >= a->nlimbs )
188 0 : return; /* not allocated, therefore no need to clear bits :-) */
189 :
190 0 : for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
191 0 : a->d[limbno] &= ~(A_LIMB_1 << bitno);
192 0 : a->nlimbs = limbno+1;
193 : }
194 :
195 : /****************
196 : * Clear bit N of A.
197 : */
198 : void
199 0 : _gcry_mpi_clear_bit( gcry_mpi_t a, unsigned int n )
200 : {
201 : unsigned int limbno, bitno;
202 :
203 0 : if (mpi_is_immutable (a))
204 : {
205 0 : mpi_immutable_failed ();
206 0 : return;
207 : }
208 :
209 0 : limbno = n / BITS_PER_MPI_LIMB;
210 0 : bitno = n % BITS_PER_MPI_LIMB;
211 :
212 0 : if (limbno >= a->nlimbs)
213 0 : return; /* Don't need to clear this bit, it's far too left. */
214 0 : a->d[limbno] &= ~(A_LIMB_1 << bitno);
215 : }
216 :
217 :
218 : /****************
219 : * Shift A by COUNT limbs to the right
220 : * This is used only within the MPI library
221 : */
222 : void
223 0 : _gcry_mpi_rshift_limbs( gcry_mpi_t a, unsigned int count )
224 : {
225 0 : mpi_ptr_t ap = a->d;
226 0 : mpi_size_t n = a->nlimbs;
227 : unsigned int i;
228 :
229 0 : if (mpi_is_immutable (a))
230 : {
231 0 : mpi_immutable_failed ();
232 0 : return;
233 : }
234 :
235 0 : if (count >= n)
236 : {
237 0 : a->nlimbs = 0;
238 0 : return;
239 : }
240 :
241 0 : for( i = 0; i < n - count; i++ )
242 0 : ap[i] = ap[i+count];
243 0 : ap[i] = 0;
244 0 : a->nlimbs -= count;
245 : }
246 :
247 :
248 : /*
249 : * Shift A by N bits to the right.
250 : */
251 : void
252 0 : _gcry_mpi_rshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
253 : {
254 : mpi_size_t xsize;
255 : unsigned int i;
256 0 : unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
257 0 : unsigned int nbits = (n%BITS_PER_MPI_LIMB);
258 :
259 0 : if (mpi_is_immutable (x))
260 : {
261 0 : mpi_immutable_failed ();
262 0 : return;
263 : }
264 :
265 0 : if ( x == a )
266 : {
267 : /* In-place operation. */
268 0 : if ( nlimbs >= x->nlimbs )
269 : {
270 0 : x->nlimbs = 0;
271 0 : return;
272 : }
273 :
274 0 : if (nlimbs)
275 : {
276 0 : for (i=0; i < x->nlimbs - nlimbs; i++ )
277 0 : x->d[i] = x->d[i+nlimbs];
278 0 : x->d[i] = 0;
279 0 : x->nlimbs -= nlimbs;
280 :
281 : }
282 0 : if ( x->nlimbs && nbits )
283 0 : _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits );
284 : }
285 0 : else if ( nlimbs )
286 : {
287 : /* Copy and shift by more or equal bits than in a limb. */
288 0 : xsize = a->nlimbs;
289 0 : x->sign = a->sign;
290 0 : RESIZE_IF_NEEDED (x, xsize);
291 0 : x->nlimbs = xsize;
292 0 : for (i=0; i < a->nlimbs; i++ )
293 0 : x->d[i] = a->d[i];
294 0 : x->nlimbs = i;
295 :
296 0 : if ( nlimbs >= x->nlimbs )
297 : {
298 0 : x->nlimbs = 0;
299 0 : return;
300 : }
301 :
302 0 : if (nlimbs)
303 : {
304 0 : for (i=0; i < x->nlimbs - nlimbs; i++ )
305 0 : x->d[i] = x->d[i+nlimbs];
306 0 : x->d[i] = 0;
307 0 : x->nlimbs -= nlimbs;
308 : }
309 :
310 0 : if ( x->nlimbs && nbits )
311 0 : _gcry_mpih_rshift ( x->d, x->d, x->nlimbs, nbits );
312 : }
313 : else
314 : {
315 : /* Copy and shift by less than bits in a limb. */
316 0 : xsize = a->nlimbs;
317 0 : x->sign = a->sign;
318 0 : RESIZE_IF_NEEDED (x, xsize);
319 0 : x->nlimbs = xsize;
320 :
321 0 : if ( xsize )
322 : {
323 0 : if (nbits )
324 0 : _gcry_mpih_rshift (x->d, a->d, x->nlimbs, nbits );
325 : else
326 : {
327 : /* The rshift helper function is not specified for
328 : NBITS==0, thus we do a plain copy here. */
329 0 : for (i=0; i < x->nlimbs; i++ )
330 0 : x->d[i] = a->d[i];
331 : }
332 : }
333 : }
334 0 : MPN_NORMALIZE (x->d, x->nlimbs);
335 : }
336 :
337 :
338 : /****************
339 : * Shift A by COUNT limbs to the left
340 : * This is used only within the MPI library
341 : */
342 : void
343 0 : _gcry_mpi_lshift_limbs (gcry_mpi_t a, unsigned int count)
344 : {
345 : mpi_ptr_t ap;
346 0 : int n = a->nlimbs;
347 : int i;
348 :
349 0 : if (!count || !n)
350 0 : return;
351 :
352 0 : RESIZE_IF_NEEDED (a, n+count);
353 :
354 0 : ap = a->d;
355 0 : for (i = n-1; i >= 0; i--)
356 0 : ap[i+count] = ap[i];
357 0 : for (i=0; i < count; i++ )
358 0 : ap[i] = 0;
359 0 : a->nlimbs += count;
360 : }
361 :
362 :
363 : /*
364 : * Shift A by N bits to the left.
365 : */
366 : void
367 0 : _gcry_mpi_lshift ( gcry_mpi_t x, gcry_mpi_t a, unsigned int n )
368 : {
369 0 : unsigned int nlimbs = (n/BITS_PER_MPI_LIMB);
370 0 : unsigned int nbits = (n%BITS_PER_MPI_LIMB);
371 :
372 0 : if (mpi_is_immutable (x))
373 : {
374 0 : mpi_immutable_failed ();
375 0 : return;
376 : }
377 :
378 0 : if (x == a && !n)
379 0 : return; /* In-place shift with an amount of zero. */
380 :
381 0 : if ( x != a )
382 : {
383 : /* Copy A to X. */
384 0 : unsigned int alimbs = a->nlimbs;
385 0 : int asign = a->sign;
386 : mpi_ptr_t xp, ap;
387 :
388 0 : RESIZE_IF_NEEDED (x, alimbs+nlimbs+1);
389 0 : xp = x->d;
390 0 : ap = a->d;
391 0 : MPN_COPY (xp, ap, alimbs);
392 0 : x->nlimbs = alimbs;
393 0 : x->flags = a->flags;
394 0 : x->sign = asign;
395 : }
396 :
397 0 : if (nlimbs && !nbits)
398 : {
399 : /* Shift a full number of limbs. */
400 0 : _gcry_mpi_lshift_limbs (x, nlimbs);
401 : }
402 0 : else if (n)
403 : {
404 : /* We use a very dump approach: Shift left by the number of
405 : limbs plus one and than fix it up by an rshift. */
406 0 : _gcry_mpi_lshift_limbs (x, nlimbs+1);
407 0 : mpi_rshift (x, x, BITS_PER_MPI_LIMB - nbits);
408 : }
409 :
410 0 : MPN_NORMALIZE (x->d, x->nlimbs);
411 : }
|