Branch data Line data Source code
1 : : /* crypto/bn/bn_print.c */
2 : : /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 : : * All rights reserved.
4 : : *
5 : : * This package is an SSL implementation written
6 : : * by Eric Young (eay@cryptsoft.com).
7 : : * The implementation was written so as to conform with Netscapes SSL.
8 : : *
9 : : * This library is free for commercial and non-commercial use as long as
10 : : * the following conditions are aheared to. The following conditions
11 : : * apply to all code found in this distribution, be it the RC4, RSA,
12 : : * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 : : * included with this distribution is covered by the same copyright terms
14 : : * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 : : *
16 : : * Copyright remains Eric Young's, and as such any Copyright notices in
17 : : * the code are not to be removed.
18 : : * If this package is used in a product, Eric Young should be given attribution
19 : : * as the author of the parts of the library used.
20 : : * This can be in the form of a textual message at program startup or
21 : : * in documentation (online or textual) provided with the package.
22 : : *
23 : : * Redistribution and use in source and binary forms, with or without
24 : : * modification, are permitted provided that the following conditions
25 : : * are met:
26 : : * 1. Redistributions of source code must retain the copyright
27 : : * notice, this list of conditions and the following disclaimer.
28 : : * 2. Redistributions in binary form must reproduce the above copyright
29 : : * notice, this list of conditions and the following disclaimer in the
30 : : * documentation and/or other materials provided with the distribution.
31 : : * 3. All advertising materials mentioning features or use of this software
32 : : * must display the following acknowledgement:
33 : : * "This product includes cryptographic software written by
34 : : * Eric Young (eay@cryptsoft.com)"
35 : : * The word 'cryptographic' can be left out if the rouines from the library
36 : : * being used are not cryptographic related :-).
37 : : * 4. If you include any Windows specific code (or a derivative thereof) from
38 : : * the apps directory (application code) you must include an acknowledgement:
39 : : * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 : : *
41 : : * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 : : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 : : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 : : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 : : * SUCH DAMAGE.
52 : : *
53 : : * The licence and distribution terms for any publically available version or
54 : : * derivative of this code cannot be changed. i.e. this code cannot simply be
55 : : * copied and put under another distribution licence
56 : : * [including the GNU Public Licence.]
57 : : */
58 : :
59 : : #include <stdio.h>
60 : : #include <ctype.h>
61 : : #include "cryptlib.h"
62 : : #include <openssl/buffer.h>
63 : : #include "bn_lcl.h"
64 : :
65 : : static const char Hex[]="0123456789ABCDEF";
66 : :
67 : : /* Must 'OPENSSL_free' the returned data */
68 : 24 : char *BN_bn2hex(const BIGNUM *a)
69 : : {
70 : 24 : int i,j,v,z=0;
71 : : char *buf;
72 : : char *p;
73 : :
74 : 24 : buf=(char *)OPENSSL_malloc(a->top*BN_BYTES*2+2);
75 [ - + ]: 24 : if (buf == NULL)
76 : : {
77 : 0 : BNerr(BN_F_BN_BN2HEX,ERR_R_MALLOC_FAILURE);
78 : 0 : goto err;
79 : : }
80 : 24 : p=buf;
81 [ - + ]: 24 : if (a->neg) *(p++)='-';
82 [ - + ]: 24 : if (BN_is_zero(a)) *(p++)='0';
83 [ + + ]: 48 : for (i=a->top-1; i >=0; i--)
84 : : {
85 [ + + ]: 216 : for (j=BN_BITS2-8; j >= 0; j-=8)
86 : : {
87 : : /* strip leading zeros */
88 : 192 : v=((int)(a->d[i]>>(long)j))&0xff;
89 [ + + ]: 192 : if (z || (v != 0))
90 : : {
91 : 57 : *(p++)=Hex[v>>4];
92 : 57 : *(p++)=Hex[v&0x0f];
93 : 57 : z=1;
94 : : }
95 : : }
96 : : }
97 : 24 : *p='\0';
98 : : err:
99 : 24 : return(buf);
100 : : }
101 : :
102 : : /* Must 'OPENSSL_free' the returned data */
103 : 3 : char *BN_bn2dec(const BIGNUM *a)
104 : : {
105 : 3 : int i=0,num, ok = 0;
106 : 3 : char *buf=NULL;
107 : : char *p;
108 : 3 : BIGNUM *t=NULL;
109 : 3 : BN_ULONG *bn_data=NULL,*lp;
110 : :
111 : : /* get an upper bound for the length of the decimal integer
112 : : * num <= (BN_num_bits(a) + 1) * log(2)
113 : : * <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1 (rounding error)
114 : : * <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1
115 : : */
116 : 3 : i=BN_num_bits(a)*3;
117 : 3 : num=(i/10+i/1000+1)+1;
118 : 3 : bn_data=(BN_ULONG *)OPENSSL_malloc((num/BN_DEC_NUM+1)*sizeof(BN_ULONG));
119 : 3 : buf=(char *)OPENSSL_malloc(num+3);
120 [ - + ]: 3 : if ((buf == NULL) || (bn_data == NULL))
121 : : {
122 : 0 : BNerr(BN_F_BN_BN2DEC,ERR_R_MALLOC_FAILURE);
123 : 0 : goto err;
124 : : }
125 [ + - ]: 3 : if ((t=BN_dup(a)) == NULL) goto err;
126 : :
127 : : #define BUF_REMAIN (num+3 - (size_t)(p - buf))
128 : 3 : p=buf;
129 : 3 : lp=bn_data;
130 [ - + ]: 3 : if (BN_is_zero(t))
131 : : {
132 : 0 : *(p++)='0';
133 : 0 : *(p++)='\0';
134 : : }
135 : : else
136 : : {
137 [ - + ]: 3 : if (BN_is_negative(t))
138 : 0 : *p++ = '-';
139 : :
140 : 3 : i=0;
141 [ + + ]: 6 : while (!BN_is_zero(t))
142 : : {
143 : 3 : *lp=BN_div_word(t,BN_DEC_CONV);
144 : 3 : lp++;
145 : : }
146 : 3 : lp--;
147 : : /* We now have a series of blocks, BN_DEC_NUM chars
148 : : * in length, where the last one needs truncation.
149 : : * The blocks need to be reversed in order. */
150 : 3 : BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT1,*lp);
151 [ + + ]: 6 : while (*p) p++;
152 [ - + ]: 3 : while (lp != bn_data)
153 : : {
154 : 0 : lp--;
155 : 0 : BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT2,*lp);
156 [ # # ]: 3 : while (*p) p++;
157 : : }
158 : : }
159 : : ok = 1;
160 : : err:
161 [ + - ]: 3 : if (bn_data != NULL) OPENSSL_free(bn_data);
162 [ + - ]: 3 : if (t != NULL) BN_free(t);
163 [ - + ]: 3 : if (!ok && buf)
164 : : {
165 : 0 : OPENSSL_free(buf);
166 : 0 : buf = NULL;
167 : : }
168 : :
169 : 3 : return(buf);
170 : : }
171 : :
172 : 160 : int BN_hex2bn(BIGNUM **bn, const char *a)
173 : : {
174 : 160 : BIGNUM *ret=NULL;
175 : 160 : BN_ULONG l=0;
176 : 160 : int neg=0,h,m,i,j,k,c;
177 : : int num;
178 : :
179 [ + - ][ + - ]: 160 : if ((a == NULL) || (*a == '\0')) return(0);
180 : :
181 [ - + ]: 160 : if (*a == '-') { neg=1; a++; }
182 : :
183 [ + + ]: 7283 : for (i=0; isxdigit((unsigned char) a[i]); i++)
184 : : ;
185 : :
186 : 160 : num=i+neg;
187 [ + - ]: 160 : if (bn == NULL) return(num);
188 : :
189 : : /* a is the start of the hex digits, and it is 'i' long */
190 [ + + ]: 160 : if (*bn == NULL)
191 : : {
192 [ + - ]: 44 : if ((ret=BN_new()) == NULL) return(0);
193 : : }
194 : : else
195 : : {
196 : 116 : ret= *bn;
197 : 116 : BN_zero(ret);
198 : : }
199 : :
200 : : /* i is the number of hex digests; */
201 [ + + ][ + - ]: 160 : if (bn_expand(ret,i*4) == NULL) goto err;
202 : :
203 : : j=i; /* least significant 'hex' */
204 : : m=0;
205 : : h=0;
206 [ + + ]: 688 : while (j > 0)
207 : : {
208 : 528 : m=((BN_BYTES*2) <= j)?(BN_BYTES*2):j;
209 : 528 : l=0;
210 : : for (;;)
211 : : {
212 : 7123 : c=a[j-m];
213 [ + + ]: 7123 : if ((c >= '0') && (c <= '9')) k=c-'0';
214 [ + + ]: 2740 : else if ((c >= 'a') && (c <= 'f')) k=c-'a'+10;
215 [ + - ]: 2590 : else if ((c >= 'A') && (c <= 'F')) k=c-'A'+10;
216 : : else k=0; /* paranoia */
217 : 7123 : l=(l<<4)|k;
218 : :
219 [ + + ]: 7123 : if (--m <= 0)
220 : : {
221 : 528 : ret->d[h++]=l;
222 : : break;
223 : : }
224 : : }
225 : 528 : j-=(BN_BYTES*2);
226 : : }
227 : 160 : ret->top=h;
228 [ + - ][ + + ]: 185 : bn_correct_top(ret);
[ + + ]
229 : 160 : ret->neg=neg;
230 : :
231 : 160 : *bn=ret;
232 : : bn_check_top(ret);
233 : 160 : return(num);
234 : : err:
235 [ # # ]: 0 : if (*bn == NULL) BN_free(ret);
236 : : return(0);
237 : : }
238 : :
239 : 24 : int BN_dec2bn(BIGNUM **bn, const char *a)
240 : : {
241 : 24 : BIGNUM *ret=NULL;
242 : 24 : BN_ULONG l=0;
243 : 24 : int neg=0,i,j;
244 : : int num;
245 : :
246 [ + - ][ + - ]: 24 : if ((a == NULL) || (*a == '\0')) return(0);
247 [ - + ]: 24 : if (*a == '-') { neg=1; a++; }
248 : :
249 [ + + ]: 1067 : for (i=0; isdigit((unsigned char) a[i]); i++)
250 : : ;
251 : :
252 : 24 : num=i+neg;
253 [ + - ]: 24 : if (bn == NULL) return(num);
254 : :
255 : : /* a is the start of the digits, and it is 'i' long.
256 : : * We chop it into BN_DEC_NUM digits at a time */
257 [ - + ]: 24 : if (*bn == NULL)
258 : : {
259 [ # # ]: 0 : if ((ret=BN_new()) == NULL) return(0);
260 : : }
261 : : else
262 : : {
263 : 24 : ret= *bn;
264 : 24 : BN_zero(ret);
265 : : }
266 : :
267 : : /* i is the number of digests, a bit of an over expand; */
268 [ + + ][ + - ]: 24 : if (bn_expand(ret,i*4) == NULL) goto err;
269 : :
270 : 24 : j=BN_DEC_NUM-(i%BN_DEC_NUM);
271 [ + + ]: 24 : if (j == BN_DEC_NUM) j=0;
272 : : l=0;
273 [ + + ]: 1067 : while (*a)
274 : : {
275 : 1043 : l*=10;
276 : 1043 : l+= *a-'0';
277 : 1043 : a++;
278 [ + + ]: 1043 : if (++j == BN_DEC_NUM)
279 : : {
280 : 69 : BN_mul_word(ret,BN_DEC_CONV);
281 : 69 : BN_add_word(ret,l);
282 : 69 : l=0;
283 : 1043 : j=0;
284 : : }
285 : : }
286 : 24 : ret->neg=neg;
287 : :
288 [ + + ][ - + ]: 24 : bn_correct_top(ret);
[ + - ]
289 : 24 : *bn=ret;
290 : : bn_check_top(ret);
291 : 24 : return(num);
292 : : err:
293 [ # # ]: 0 : if (*bn == NULL) BN_free(ret);
294 : : return(0);
295 : : }
296 : :
297 : 0 : int BN_asc2bn(BIGNUM **bn, const char *a)
298 : : {
299 : 0 : const char *p = a;
300 [ # # ]: 0 : if (*p == '-')
301 : 0 : p++;
302 : :
303 [ # # ][ # # ]: 0 : if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x'))
304 : : {
305 [ # # ]: 0 : if (!BN_hex2bn(bn, p + 2))
306 : : return 0;
307 : : }
308 : : else
309 : : {
310 [ # # ]: 0 : if (!BN_dec2bn(bn, p))
311 : : return 0;
312 : : }
313 [ # # ]: 0 : if (*a == '-')
314 : 0 : (*bn)->neg = 1;
315 : : return 1;
316 : : }
317 : :
318 : : #ifndef OPENSSL_NO_BIO
319 : : #ifndef OPENSSL_NO_FP_API
320 : 87 : int BN_print_fp(FILE *fp, const BIGNUM *a)
321 : : {
322 : : BIO *b;
323 : : int ret;
324 : :
325 [ + - ]: 87 : if ((b=BIO_new(BIO_s_file())) == NULL)
326 : : return(0);
327 : 87 : BIO_set_fp(b,fp,BIO_NOCLOSE);
328 : 87 : ret=BN_print(b,a);
329 : 87 : BIO_free(b);
330 : 87 : return(ret);
331 : : }
332 : : #endif
333 : :
334 : 6718 : int BN_print(BIO *bp, const BIGNUM *a)
335 : : {
336 : 6718 : int i,j,v,z=0;
337 : 6718 : int ret=0;
338 : :
339 [ + + ][ + - ]: 6718 : if ((a->neg) && (BIO_write(bp,"-",1) != 1)) goto end;
340 [ + + ][ + - ]: 6718 : if (BN_is_zero(a) && (BIO_write(bp,"0",1) != 1)) goto end;
341 [ + + ]: 59128 : for (i=a->top-1; i >=0; i--)
342 : : {
343 [ + + ]: 890970 : for (j=BN_BITS2-4; j >= 0; j-=4)
344 : : {
345 : : /* strip leading zeros */
346 : 838560 : v=((int)(a->d[i]>>(long)j))&0x0f;
347 [ + + ]: 838560 : if (z || (v != 0))
348 : : {
349 [ + - ]: 791912 : if (BIO_write(bp,&(Hex[v]),1) != 1)
350 : : goto end;
351 : : z=1;
352 : : }
353 : : }
354 : : }
355 : : ret=1;
356 : : end:
357 : 6718 : return(ret);
358 : : }
359 : : #endif
360 : :
361 : 1 : char *BN_options(void)
362 : : {
363 : : static int init=0;
364 : : static char data[16];
365 : :
366 [ + - ]: 1 : if (!init)
367 : : {
368 : 1 : init++;
369 : : #ifdef BN_LLONG
370 : : BIO_snprintf(data,sizeof data,"bn(%d,%d)",
371 : : (int)sizeof(BN_ULLONG)*8,(int)sizeof(BN_ULONG)*8);
372 : : #else
373 : 1 : BIO_snprintf(data,sizeof data,"bn(%d,%d)",
374 : : (int)sizeof(BN_ULONG)*8,(int)sizeof(BN_ULONG)*8);
375 : : #endif
376 : : }
377 : 1 : return(data);
378 : : }
|