1 /* mpi-scan.c  -  MPI functions
2  * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20 
21 #include "mpi-internal.h"
22 #include "longlong.h"
23 
24 /****************
25  * Scan through an mpi and return byte for byte. a -1 is returned to indicate
26  * the end of the mpi. Scanning is done from the lsb to the msb, returned
27  * values are in the range of 0 .. 255.
28  *
29  * FIXME: This code is VERY ugly!
30  */
mpi_getbyte(const MPI a,unsigned idx)31 int mpi_getbyte(const MPI a, unsigned idx)
32 {
33 	int i, j;
34 	unsigned n;
35 	mpi_ptr_t ap;
36 	mpi_limb_t limb;
37 
38 	ap = a->d;
39 	for (n = 0, i = 0; i < a->nlimbs; i++) {
40 		limb = ap[i];
41 		for (j = 0; j < BYTES_PER_MPI_LIMB; j++, n++)
42 			if (n == idx)
43 				return (limb >> j * 8) & 0xff;
44 	}
45 	return -1;
46 }
47 
48 /****************
49  * Put a value at position IDX into A. idx counts from lsb to msb
50  */
mpi_putbyte(MPI a,unsigned idx,int xc)51 void mpi_putbyte(MPI a, unsigned idx, int xc)
52 {
53 	int i, j;
54 	unsigned n;
55 	mpi_ptr_t ap;
56 	mpi_limb_t limb, c;
57 
58 	c = xc & 0xff;
59 	ap = a->d;
60 	for (n = 0, i = 0; i < a->alloced; i++) {
61 		limb = ap[i];
62 		for (j = 0; j < BYTES_PER_MPI_LIMB; j++, n++)
63 			if (n == idx) {
64 #if BYTES_PER_MPI_LIMB == 4
65 				if (j == 0)
66 					limb = (limb & 0xffffff00) | c;
67 				else if (j == 1)
68 					limb = (limb & 0xffff00ff) | (c << 8);
69 				else if (j == 2)
70 					limb = (limb & 0xff00ffff) | (c << 16);
71 				else
72 					limb = (limb & 0x00ffffff) | (c << 24);
73 #elif BYTES_PER_MPI_LIMB == 8
74 				if (j == 0)
75 					limb = (limb & 0xffffffffffffff00) | c;
76 				else if (j == 1)
77 					limb =
78 					    (limb & 0xffffffffffff00ff) | (c <<
79 									   8);
80 				else if (j == 2)
81 					limb =
82 					    (limb & 0xffffffffff00ffff) | (c <<
83 									   16);
84 				else if (j == 3)
85 					limb =
86 					    (limb & 0xffffffff00ffffff) | (c <<
87 									   24);
88 				else if (j == 4)
89 					limb =
90 					    (limb & 0xffffff00ffffffff) | (c <<
91 									   32);
92 				else if (j == 5)
93 					limb =
94 					    (limb & 0xffff00ffffffffff) | (c <<
95 									   40);
96 				else if (j == 6)
97 					limb =
98 					    (limb & 0xff00ffffffffffff) | (c <<
99 									   48);
100 				else
101 					limb =
102 					    (limb & 0x00ffffffffffffff) | (c <<
103 									   56);
104 #else
105 #error please enhance this function, its ugly - i know.
106 #endif
107 				if (a->nlimbs <= i)
108 					a->nlimbs = i + 1;
109 				ap[i] = limb;
110 				return;
111 			}
112 	}
113 	log_bug("index out of range\n");
114 }
115 
116 /****************
117  * Count the number of zerobits at the low end of A
118  */
mpi_trailing_zeros(const MPI a)119 unsigned mpi_trailing_zeros(const MPI a)
120 {
121 	unsigned n, count = 0;
122 
123 	for (n = 0; n < a->nlimbs; n++) {
124 		if (a->d[n]) {
125 			unsigned nn;
126 			mpi_limb_t alimb = a->d[n];
127 
128 			count_trailing_zeros(nn, alimb);
129 			count += nn;
130 			break;
131 		}
132 		count += BITS_PER_MPI_LIMB;
133 	}
134 	return count;
135 
136 }
137