Add OpenSSL 0.9.7d.
[dragonfly.git] / crypto / openssl-0.9.7d / 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 'OPENSSL_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 *)OPENSSL_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 'OPENSSL_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 *)OPENSSL_malloc((num/BN_DEC_NUM+1)*sizeof(BN_ULONG));
114         buf=(char *)OPENSSL_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 #define BUF_REMAIN (num+3 - (size_t)(p - buf))
123         p=buf;
124         lp=bn_data;
125         if (t->neg) *(p++)='-';
126         if (t->top == 0)
127                 {
128                 *(p++)='0';
129                 *(p++)='\0';
130                 }
131         else
132                 {
133                 i=0;
134                 while (!BN_is_zero(t))
135                         {
136                         *lp=BN_div_word(t,BN_DEC_CONV);
137                         lp++;
138                         }
139                 lp--;
140                 /* We now have a series of blocks, BN_DEC_NUM chars
141                  * in length, where the last one needs truncation.
142                  * The blocks need to be reversed in order. */
143                 BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT1,*lp);
144                 while (*p) p++;
145                 while (lp != bn_data)
146                         {
147                         lp--;
148                         BIO_snprintf(p,BUF_REMAIN,BN_DEC_FMT2,*lp);
149                         while (*p) p++;
150                         }
151                 }
152 err:
153         if (bn_data != NULL) OPENSSL_free(bn_data);
154         if (t != NULL) BN_free(t);
155         return(buf);
156         }
157
158 int BN_hex2bn(BIGNUM **bn, const char *a)
159         {
160         BIGNUM *ret=NULL;
161         BN_ULONG l=0;
162         int neg=0,h,m,i,j,k,c;
163         int num;
164
165         if ((a == NULL) || (*a == '\0')) return(0);
166
167         if (*a == '-') { neg=1; a++; }
168
169         for (i=0; isxdigit((unsigned char) a[i]); i++)
170                 ;
171
172         num=i+neg;
173         if (bn == NULL) return(num);
174
175         /* a is the start of the hex digits, and it is 'i' long */
176         if (*bn == NULL)
177                 {
178                 if ((ret=BN_new()) == NULL) return(0);
179                 }
180         else
181                 {
182                 ret= *bn;
183                 BN_zero(ret);
184                 }
185
186         /* i is the number of hex digests; */
187         if (bn_expand(ret,i*4) == NULL) goto err;
188
189         j=i; /* least significant 'hex' */
190         m=0;
191         h=0;
192         while (j > 0)
193                 {
194                 m=((BN_BYTES*2) <= j)?(BN_BYTES*2):j;
195                 l=0;
196                 for (;;)
197                         {
198                         c=a[j-m];
199                         if ((c >= '0') && (c <= '9')) k=c-'0';
200                         else if ((c >= 'a') && (c <= 'f')) k=c-'a'+10;
201                         else if ((c >= 'A') && (c <= 'F')) k=c-'A'+10;
202                         else k=0; /* paranoia */
203                         l=(l<<4)|k;
204
205                         if (--m <= 0)
206                                 {
207                                 ret->d[h++]=l;
208                                 break;
209                                 }
210                         }
211                 j-=(BN_BYTES*2);
212                 }
213         ret->top=h;
214         bn_fix_top(ret);
215         ret->neg=neg;
216
217         *bn=ret;
218         return(num);
219 err:
220         if (*bn == NULL) BN_free(ret);
221         return(0);
222         }
223
224 int BN_dec2bn(BIGNUM **bn, const char *a)
225         {
226         BIGNUM *ret=NULL;
227         BN_ULONG l=0;
228         int neg=0,i,j;
229         int num;
230
231         if ((a == NULL) || (*a == '\0')) return(0);
232         if (*a == '-') { neg=1; a++; }
233
234         for (i=0; isdigit((unsigned char) a[i]); i++)
235                 ;
236
237         num=i+neg;
238         if (bn == NULL) return(num);
239
240         /* a is the start of the digits, and it is 'i' long.
241          * We chop it into BN_DEC_NUM digits at a time */
242         if (*bn == NULL)
243                 {
244                 if ((ret=BN_new()) == NULL) return(0);
245                 }
246         else
247                 {
248                 ret= *bn;
249                 BN_zero(ret);
250                 }
251
252         /* i is the number of digests, a bit of an over expand; */
253         if (bn_expand(ret,i*4) == NULL) goto err;
254
255         j=BN_DEC_NUM-(i%BN_DEC_NUM);
256         if (j == BN_DEC_NUM) j=0;
257         l=0;
258         while (*a)
259                 {
260                 l*=10;
261                 l+= *a-'0';
262                 a++;
263                 if (++j == BN_DEC_NUM)
264                         {
265                         BN_mul_word(ret,BN_DEC_CONV);
266                         BN_add_word(ret,l);
267                         l=0;
268                         j=0;
269                         }
270                 }
271         ret->neg=neg;
272
273         bn_fix_top(ret);
274         *bn=ret;
275         return(num);
276 err:
277         if (*bn == NULL) BN_free(ret);
278         return(0);
279         }
280
281 #ifndef OPENSSL_NO_BIO
282 #ifndef OPENSSL_NO_FP_API
283 int BN_print_fp(FILE *fp, const BIGNUM *a)
284         {
285         BIO *b;
286         int ret;
287
288         if ((b=BIO_new(BIO_s_file())) == NULL)
289                 return(0);
290         BIO_set_fp(b,fp,BIO_NOCLOSE);
291         ret=BN_print(b,a);
292         BIO_free(b);
293         return(ret);
294         }
295 #endif
296
297 int BN_print(BIO *bp, const BIGNUM *a)
298         {
299         int i,j,v,z=0;
300         int ret=0;
301
302         if ((a->neg) && (BIO_write(bp,"-",1) != 1)) goto end;
303         if ((a->top == 0) && (BIO_write(bp,"0",1) != 1)) goto end;
304         for (i=a->top-1; i >=0; i--)
305                 {
306                 for (j=BN_BITS2-4; j >= 0; j-=4)
307                         {
308                         /* strip leading zeros */
309                         v=((int)(a->d[i]>>(long)j))&0x0f;
310                         if (z || (v != 0))
311                                 {
312                                 if (BIO_write(bp,&(Hex[v]),1) != 1)
313                                         goto end;
314                                 z=1;
315                                 }
316                         }
317                 }
318         ret=1;
319 end:
320         return(ret);
321         }
322 #endif
323
324 #ifdef BN_DEBUG
325 void bn_dump1(FILE *o, const char *a, const BN_ULONG *b,int n)
326         {
327         int i;
328         fprintf(o, "%s=", a);
329         for (i=n-1;i>=0;i--)
330                 fprintf(o, "%08lX", b[i]); /* assumes 32-bit BN_ULONG */
331         fprintf(o, "\n");
332         }
333 #endif