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