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