This commit was generated by cvs2svn to track changes on a CVS vendor
[openssl.git] / crypto / bn / bn_print.c
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 "buffer.h"
63 #include "bn_lcl.h"
64
65 static char *Hex="0123456789ABCDEF";
66
67 /* Must 'Free' the returned data */
68 char *BN_bn2hex(a)
69 BIGNUM *a;
70         {
71         int i,j,v,z=0;
72         char *buf;
73         char *p;
74
75         buf=(char *)Malloc(a->top*BN_BYTES*2+2);
76         if (buf == NULL)
77                 {
78                 BNerr(BN_F_BN_BN2HEX,ERR_R_MALLOC_FAILURE);
79                 goto err;
80                 }
81         p=buf;
82         if (a->neg) *(p++)='-';
83         if (a->top == 0) *(p++)='0';
84         for (i=a->top-1; i >=0; i--)
85                 {
86                 for (j=BN_BITS2-8; j >= 0; j-=8)
87                         {
88                         /* strip leading zeros */
89                         v=((int)(a->d[i]>>(long)j))&0xff;
90                         if (z || (v != 0))
91                                 {
92                                 *(p++)=Hex[v>>4];
93                                 *(p++)=Hex[v&0x0f];
94                                 z=1;
95                                 }
96                         }
97                 }
98         *p='\0';
99 err:
100         return(buf);
101         }
102
103 /* Must 'Free' the returned data */
104 char *BN_bn2dec(a)
105 BIGNUM *a;
106         {
107         int i=0,num;
108         char *buf=NULL;
109         char *p;
110         BIGNUM *t=NULL;
111         BN_ULONG *bn_data=NULL,*lp;
112
113         i=BN_num_bits(a)*3;
114         num=(i/10+i/1000+3)+1;
115         bn_data=(BN_ULONG *)Malloc((num/BN_DEC_NUM+1)*sizeof(BN_ULONG));
116         buf=(char *)Malloc(num+3);
117         if ((buf == NULL) || (bn_data == NULL))
118                 {
119                 BNerr(BN_F_BN_BN2DEC,ERR_R_MALLOC_FAILURE);
120                 goto err;
121                 }
122         if ((t=BN_dup(a)) == NULL) goto err;
123
124         p=buf;
125         lp=bn_data;
126         if (t->neg) *(p++)='-';
127         if (t->top == 0)
128                 {
129                 *(p++)='0';
130                 *(p++)='\0';
131                 }
132         else
133                 {
134                 i=0;
135                 while (!BN_is_zero(t))
136                         {
137                         *lp=BN_div_word(t,BN_DEC_CONV);
138                         lp++;
139                         }
140                 lp--;
141                 /* We now have a series of blocks, BN_DEC_NUM chars
142                  * in length, where the last one needs trucation.
143                  * The blocks need to be reversed in order. */
144                 sprintf(p,BN_DEC_FMT1,*lp);
145                 while (*p) p++;
146                 while (lp != bn_data)
147                         {
148                         lp--;
149                         sprintf(p,BN_DEC_FMT2,*lp);
150                         while (*p) p++;
151                         }
152                 }
153 err:
154         if (bn_data != NULL) Free(bn_data);
155         if (t != NULL) BN_free(t);
156         return(buf);
157         }
158
159 int BN_hex2bn(bn,a)
160 BIGNUM **bn;
161 char *a;
162         {
163         BIGNUM *ret=NULL;
164         BN_ULONG l=0;
165         int neg=0,h,m,i,j,k,c;
166         int num;
167
168         if ((a == NULL) || (*a == '\0')) return(0);
169
170         if (*a == '-') { neg=1; a++; }
171
172         for (i=0; isxdigit(a[i]); i++)
173                 ;
174
175         num=i+neg;
176         if (bn == NULL) return(num);
177
178         /* a is the start of the hex digets, and it is 'i' long */
179         if (*bn == NULL)
180                 {
181                 if ((ret=BN_new()) == NULL) return(0);
182                 }
183         else
184                 {
185                 ret= *bn;
186                 BN_zero(ret);
187                 }
188
189         /* i is the number of hex digests; */
190         if (bn_expand(ret,i*4) == NULL) goto err;
191
192         j=i; /* least significate 'hex' */
193         m=0;
194         h=0;
195         while (j > 0)
196                 {
197                 m=((BN_BYTES*2) <= j)?(BN_BYTES*2):j;
198                 l=0;
199                 for (;;)
200                         {
201                         c=a[j-m];
202                         if ((c >= '0') && (c <= '9')) k=c-'0';
203                         else if ((c >= 'a') && (c <= 'f')) k=c-'a'+10;
204                         else if ((c >= 'A') && (c <= 'F')) k=c-'A'+10;
205                         else k=0; /* paranoia */
206                         l=(l<<4)|k;
207
208                         if (--m <= 0)
209                                 {
210                                 ret->d[h++]=l;
211                                 break;
212                                 }
213                         }
214                 j-=(BN_BYTES*2);
215                 }
216         ret->top=h;
217         bn_fix_top(ret);
218         ret->neg=neg;
219
220         *bn=ret;
221         return(num);
222 err:
223         if (*bn == NULL) BN_free(ret);
224         return(0);
225         }
226
227 int BN_dec2bn(bn,a)
228 BIGNUM **bn;
229 char *a;
230         {
231         BIGNUM *ret=NULL;
232         BN_ULONG l=0;
233         int neg=0,i,j;
234         int num;
235
236         if ((a == NULL) || (*a == '\0')) return(0);
237         if (*a == '-') { neg=1; a++; }
238
239         for (i=0; isdigit(a[i]); i++)
240                 ;
241
242         num=i+neg;
243         if (bn == NULL) return(num);
244
245         /* a is the start of the digets, and it is 'i' long.
246          * We chop it into BN_DEC_NUM digets at a time */
247         if (*bn == NULL)
248                 {
249                 if ((ret=BN_new()) == NULL) return(0);
250                 }
251         else
252                 {
253                 ret= *bn;
254                 BN_zero(ret);
255                 }
256
257         /* i is the number of digests, a bit of an over expand; */
258         if (bn_expand(ret,i*4) == NULL) goto err;
259
260         j=BN_DEC_NUM-(i%BN_DEC_NUM);
261         if (j == BN_DEC_NUM) j=0;
262         l=0;
263         while (*a)
264                 {
265                 l*=10;
266                 l+= *a-'0';
267                 a++;
268                 if (++j == BN_DEC_NUM)
269                         {
270                         BN_mul_word(ret,BN_DEC_CONV);
271                         BN_add_word(ret,l);
272                         l=0;
273                         j=0;
274                         }
275                 }
276         ret->neg=neg;
277
278         bn_fix_top(ret);
279         *bn=ret;
280         return(num);
281 err:
282         if (*bn == NULL) BN_free(ret);
283         return(0);
284         }
285
286 #ifndef NO_BIO
287
288 #ifndef NO_FP_API
289 int BN_print_fp(fp, a)
290 FILE *fp;
291 BIGNUM *a;
292         {
293         BIO *b;
294         int ret;
295
296         if ((b=BIO_new(BIO_s_file())) == NULL)
297                 return(0);
298         BIO_set_fp(b,fp,BIO_NOCLOSE);
299         ret=BN_print(b,a);
300         BIO_free(b);
301         return(ret);
302         }
303 #endif
304
305 int BN_print(bp, a)
306 BIO *bp;
307 BIGNUM *a;
308         {
309         int i,j,v,z=0;
310         int ret=0;
311
312         if ((a->neg) && (BIO_write(bp,"-",1) != 1)) goto end;
313         if ((a->top == 0) && (BIO_write(bp,"0",1) != 1)) goto end;
314         for (i=a->top-1; i >=0; i--)
315                 {
316                 for (j=BN_BITS2-4; j >= 0; j-=4)
317                         {
318                         /* strip leading zeros */
319                         v=((int)(a->d[i]>>(long)j))&0x0f;
320                         if (z || (v != 0))
321                                 {
322                                 if (BIO_write(bp,&(Hex[v]),1) != 1)
323                                         goto end;
324                                 z=1;
325                                 }
326                         }
327                 }
328         ret=1;
329 end:
330         return(ret);
331         }
332
333 #endif