bn_print.c revision 306336
1168404Spjd/* crypto/bn/bn_print.c */ 2168404Spjd/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3168404Spjd * All rights reserved. 4168404Spjd * 5168404Spjd * This package is an SSL implementation written 6168404Spjd * by Eric Young (eay@cryptsoft.com). 7168404Spjd * The implementation was written so as to conform with Netscapes SSL. 8168404Spjd * 9168404Spjd * This library is free for commercial and non-commercial use as long as 10168404Spjd * the following conditions are aheared to. The following conditions 11168404Spjd * apply to all code found in this distribution, be it the RC4, RSA, 12168404Spjd * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13168404Spjd * included with this distribution is covered by the same copyright terms 14168404Spjd * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15168404Spjd * 16168404Spjd * Copyright remains Eric Young's, and as such any Copyright notices in 17168404Spjd * the code are not to be removed. 18168404Spjd * If this package is used in a product, Eric Young should be given attribution 19168404Spjd * as the author of the parts of the library used. 20168404Spjd * This can be in the form of a textual message at program startup or 21168404Spjd * in documentation (online or textual) provided with the package. 22219089Spjd * 23226707Spjd * Redistribution and use in source and binary forms, with or without 24226707Spjd * modification, are permitted provided that the following conditions 25168404Spjd * are met: 26168404Spjd * 1. Redistributions of source code must retain the copyright 27168962Spjd * notice, this list of conditions and the following disclaimer. 28168404Spjd * 2. Redistributions in binary form must reproduce the above copyright 29168404Spjd * notice, this list of conditions and the following disclaimer in the 30168404Spjd * documentation and/or other materials provided with the distribution. 31168404Spjd * 3. All advertising materials mentioning features or use of this software 32168404Spjd * must display the following acknowledgement: 33168404Spjd * "This product includes cryptographic software written by 34168404Spjd * Eric Young (eay@cryptsoft.com)" 35168404Spjd * The word 'cryptographic' can be left out if the rouines from the library 36168404Spjd * being used are not cryptographic related :-). 37168404Spjd * 4. If you include any Windows specific code (or a derivative thereof) from 38168962Spjd * the apps directory (application code) you must include an acknowledgement: 39168404Spjd * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40168404Spjd * 41168404Spjd * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44168404Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45209962Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46185029Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47168404Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51168404Spjd * SUCH DAMAGE. 52168404Spjd * 53168404Spjd * The licence and distribution terms for any publically available version or 54168404Spjd * derivative of this code cannot be changed. i.e. this code cannot simply be 55185029Spjd * copied and put under another distribution licence 56185029Spjd * [including the GNU Public Licence.] 57168962Spjd */ 58168962Spjd 59168962Spjd#include <stdio.h> 60168404Spjd#include <ctype.h> 61168404Spjd#include <limits.h> 62168404Spjd#include "cryptlib.h" 63168404Spjd#include <openssl/buffer.h> 64168404Spjd#include "bn_lcl.h" 65168404Spjd 66168404Spjdstatic const char Hex[] = "0123456789ABCDEF"; 67185029Spjd 68219089Spjd/* Must 'OPENSSL_free' the returned data */ 69168404Spjdchar *BN_bn2hex(const BIGNUM *a) 70219089Spjd{ 71185029Spjd int i, j, v, z = 0; 72168404Spjd char *buf; 73168404Spjd char *p; 74168404Spjd 75185029Spjd if (a->neg && BN_is_zero(a)) { 76219089Spjd /* "-0" == 3 bytes including NULL terminator */ 77219089Spjd buf = OPENSSL_malloc(3); 78168404Spjd } else { 79219089Spjd buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); 80168404Spjd } 81168404Spjd if (buf == NULL) { 82168404Spjd BNerr(BN_F_BN_BN2HEX, ERR_R_MALLOC_FAILURE); 83168404Spjd goto err; 84168404Spjd } 85168404Spjd p = buf; 86168404Spjd if (a->neg) 87185029Spjd *(p++) = '-'; 88168404Spjd if (BN_is_zero(a)) 89209962Smm *(p++) = '0'; 90209962Smm for (i = a->top - 1; i >= 0; i--) { 91209962Smm for (j = BN_BITS2 - 8; j >= 0; j -= 8) { 92209962Smm /* strip leading zeros */ 93209962Smm v = ((int)(a->d[i] >> (long)j)) & 0xff; 94209962Smm if (z || (v != 0)) { 95168404Spjd *(p++) = Hex[v >> 4]; 96168404Spjd *(p++) = Hex[v & 0x0f]; 97168404Spjd z = 1; 98209962Smm } 99185029Spjd } 100209962Smm } 101168404Spjd *p = '\0'; 102168404Spjd err: 103209962Smm return (buf); 104209962Smm} 105209962Smm 106209962Smm/* Must 'OPENSSL_free' the returned data */ 107209962Smmchar *BN_bn2dec(const BIGNUM *a) 108209962Smm{ 109209962Smm int i = 0, num, ok = 0; 110209962Smm char *buf = NULL; 111209962Smm char *p; 112219089Spjd BIGNUM *t = NULL; 113219089Spjd BN_ULONG *bn_data = NULL, *lp; 114219089Spjd int bn_data_num; 115219089Spjd 116185029Spjd /*- 117185029Spjd * get an upper bound for the length of the decimal integer 118219089Spjd * num <= (BN_num_bits(a) + 1) * log(2) 119219089Spjd * <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1 (rounding error) 120219089Spjd * <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1 121185029Spjd */ 122168404Spjd i = BN_num_bits(a) * 3; 123168404Spjd num = (i / 10 + i / 1000 + 1) + 1; 124168404Spjd bn_data_num = num / BN_DEC_NUM + 1; 125168404Spjd bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG)); 126168404Spjd buf = (char *)OPENSSL_malloc(num + 3); 127219089Spjd if ((buf == NULL) || (bn_data == NULL)) { 128168404Spjd BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE); 129168404Spjd goto err; 130168404Spjd } 131168404Spjd if ((t = BN_dup(a)) == NULL) 132168404Spjd goto err; 133168404Spjd 134168404Spjd#define BUF_REMAIN (num+3 - (size_t)(p - buf)) 135168404Spjd p = buf; 136168404Spjd lp = bn_data; 137168404Spjd if (BN_is_zero(t)) { 138168404Spjd *(p++) = '0'; 139168404Spjd *(p++) = '\0'; 140168404Spjd } else { 141168404Spjd if (BN_is_negative(t)) 142168404Spjd *p++ = '-'; 143168404Spjd 144168404Spjd while (!BN_is_zero(t)) { 145168404Spjd if (lp - bn_data >= bn_data_num) 146168404Spjd goto err; 147168404Spjd *lp = BN_div_word(t, BN_DEC_CONV); 148168404Spjd if (*lp == (BN_ULONG)-1) 149168404Spjd goto err; 150168404Spjd lp++; 151168404Spjd } 152168404Spjd lp--; 153168404Spjd /* 154168404Spjd * We now have a series of blocks, BN_DEC_NUM chars in length, where 155168404Spjd * the last one needs truncation. The blocks need to be reversed in 156168404Spjd * order. 157168404Spjd */ 158185029Spjd BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT1, *lp); 159185029Spjd while (*p) 160185029Spjd p++; 161185029Spjd while (lp != bn_data) { 162185029Spjd lp--; 163185029Spjd BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT2, *lp); 164185029Spjd while (*p) 165185029Spjd p++; 166185029Spjd } 167185029Spjd } 168185029Spjd ok = 1; 169185029Spjd err: 170185029Spjd if (bn_data != NULL) 171185029Spjd OPENSSL_free(bn_data); 172185029Spjd if (t != NULL) 173185029Spjd BN_free(t); 174185029Spjd if (!ok && buf) { 175185029Spjd OPENSSL_free(buf); 176185029Spjd buf = NULL; 177185029Spjd } 178185029Spjd 179185029Spjd return (buf); 180185029Spjd} 181185029Spjd 182185029Spjdint BN_hex2bn(BIGNUM **bn, const char *a) 183185029Spjd{ 184168404Spjd BIGNUM *ret = NULL; 185185029Spjd BN_ULONG l = 0; 186185029Spjd int neg = 0, h, m, i, j, k, c; 187185029Spjd int num; 188185029Spjd 189185029Spjd if ((a == NULL) || (*a == '\0')) 190219089Spjd return (0); 191185029Spjd 192219089Spjd if (*a == '-') { 193219089Spjd neg = 1; 194219089Spjd a++; 195219089Spjd } 196219089Spjd 197185029Spjd for (i = 0; i <= (INT_MAX/4) && isxdigit((unsigned char)a[i]); i++) 198219089Spjd continue; 199185029Spjd 200185029Spjd if (i > INT_MAX/4) 201185029Spjd goto err; 202185029Spjd 203185029Spjd num = i + neg; 204185029Spjd if (bn == NULL) 205185029Spjd return (num); 206185029Spjd 207185029Spjd /* a is the start of the hex digits, and it is 'i' long */ 208185029Spjd if (*bn == NULL) { 209185029Spjd if ((ret = BN_new()) == NULL) 210185029Spjd return (0); 211185029Spjd } else { 212185029Spjd ret = *bn; 213185029Spjd BN_zero(ret); 214185029Spjd } 215185029Spjd 216185029Spjd /* i is the number of hex digits */ 217185029Spjd if (bn_expand(ret, i * 4) == NULL) 218185029Spjd goto err; 219185029Spjd 220185029Spjd j = i; /* least significant 'hex' */ 221185029Spjd m = 0; 222185029Spjd h = 0; 223185029Spjd while (j > 0) { 224185029Spjd m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j; 225185029Spjd l = 0; 226185029Spjd for (;;) { 227185029Spjd c = a[j - m]; 228185029Spjd if ((c >= '0') && (c <= '9')) 229185029Spjd k = c - '0'; 230185029Spjd else if ((c >= 'a') && (c <= 'f')) 231185029Spjd k = c - 'a' + 10; 232219089Spjd else if ((c >= 'A') && (c <= 'F')) 233185029Spjd k = c - 'A' + 10; 234185029Spjd else 235219089Spjd k = 0; /* paranoia */ 236219089Spjd l = (l << 4) | k; 237219089Spjd 238219089Spjd if (--m <= 0) { 239219089Spjd ret->d[h++] = l; 240185029Spjd break; 241185029Spjd } 242219089Spjd } 243185029Spjd j -= (BN_BYTES * 2); 244185029Spjd } 245185029Spjd ret->top = h; 246185029Spjd bn_correct_top(ret); 247185029Spjd ret->neg = neg; 248185029Spjd 249185029Spjd *bn = ret; 250185029Spjd bn_check_top(ret); 251185029Spjd return (num); 252185029Spjd err: 253185029Spjd if (*bn == NULL) 254185029Spjd BN_free(ret); 255185029Spjd return (0); 256185029Spjd} 257185029Spjd 258185029Spjdint BN_dec2bn(BIGNUM **bn, const char *a) 259185029Spjd{ 260185029Spjd BIGNUM *ret = NULL; 261185029Spjd BN_ULONG l = 0; 262185029Spjd int neg = 0, i, j; 263185029Spjd int num; 264185029Spjd 265168404Spjd if ((a == NULL) || (*a == '\0')) 266168404Spjd return (0); 267168404Spjd if (*a == '-') { 268168404Spjd neg = 1; 269168404Spjd a++; 270185029Spjd } 271168404Spjd 272168404Spjd for (i = 0; i <= (INT_MAX/4) && isdigit((unsigned char)a[i]); i++) 273168404Spjd continue; 274168404Spjd 275168404Spjd if (i > INT_MAX/4) 276168404Spjd goto err; 277168404Spjd 278168404Spjd num = i + neg; 279168404Spjd if (bn == NULL) 280168404Spjd return (num); 281185029Spjd 282168404Spjd /* 283185029Spjd * a is the start of the digits, and it is 'i' long. We chop it into 284185029Spjd * BN_DEC_NUM digits at a time 285168404Spjd */ 286168404Spjd if (*bn == NULL) { 287168404Spjd if ((ret = BN_new()) == NULL) 288168404Spjd return (0); 289168404Spjd } else { 290168404Spjd ret = *bn; 291219089Spjd BN_zero(ret); 292168404Spjd } 293168404Spjd 294168404Spjd /* i is the number of digits, a bit of an over expand */ 295168404Spjd if (bn_expand(ret, i * 4) == NULL) 296168404Spjd goto err; 297168404Spjd 298168404Spjd j = BN_DEC_NUM - (i % BN_DEC_NUM); 299185029Spjd if (j == BN_DEC_NUM) 300168404Spjd j = 0; 301168404Spjd l = 0; 302168404Spjd while (*a) { 303185029Spjd l *= 10; 304168404Spjd l += *a - '0'; 305168404Spjd a++; 306168404Spjd if (++j == BN_DEC_NUM) { 307168404Spjd BN_mul_word(ret, BN_DEC_CONV); 308168404Spjd BN_add_word(ret, l); 309168404Spjd l = 0; 310168404Spjd j = 0; 311168404Spjd } 312168404Spjd } 313168404Spjd ret->neg = neg; 314168404Spjd 315168404Spjd bn_correct_top(ret); 316168404Spjd *bn = ret; 317168404Spjd bn_check_top(ret); 318168404Spjd return (num); 319168404Spjd err: 320168404Spjd if (*bn == NULL) 321168404Spjd BN_free(ret); 322168404Spjd return (0); 323168404Spjd} 324219089Spjd 325219089Spjdint BN_asc2bn(BIGNUM **bn, const char *a) 326219089Spjd{ 327219089Spjd const char *p = a; 328219089Spjd if (*p == '-') 329219089Spjd p++; 330219089Spjd 331219089Spjd if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) { 332219089Spjd if (!BN_hex2bn(bn, p + 2)) 333219089Spjd return 0; 334219089Spjd } else { 335219089Spjd if (!BN_dec2bn(bn, p)) 336219089Spjd return 0; 337219089Spjd } 338219089Spjd if (*a == '-') 339219089Spjd (*bn)->neg = 1; 340219089Spjd return 1; 341219089Spjd} 342219089Spjd 343219089Spjd#ifndef OPENSSL_NO_BIO 344219089Spjd# ifndef OPENSSL_NO_FP_API 345219089Spjdint BN_print_fp(FILE *fp, const BIGNUM *a) 346219089Spjd{ 347219089Spjd BIO *b; 348219089Spjd int ret; 349219089Spjd 350168404Spjd if ((b = BIO_new(BIO_s_file())) == NULL) 351185029Spjd return (0); 352168404Spjd BIO_set_fp(b, fp, BIO_NOCLOSE); 353168404Spjd ret = BN_print(b, a); 354168404Spjd BIO_free(b); 355185029Spjd return (ret); 356185029Spjd} 357185029Spjd# endif 358185029Spjd 359185029Spjdint BN_print(BIO *bp, const BIGNUM *a) 360185029Spjd{ 361185029Spjd int i, j, v, z = 0; 362185029Spjd int ret = 0; 363185029Spjd 364219089Spjd if ((a->neg) && (BIO_write(bp, "-", 1) != 1)) 365219089Spjd goto end; 366219089Spjd if (BN_is_zero(a) && (BIO_write(bp, "0", 1) != 1)) 367219089Spjd goto end; 368219089Spjd for (i = a->top - 1; i >= 0; i--) { 369219089Spjd for (j = BN_BITS2 - 4; j >= 0; j -= 4) { 370219089Spjd /* strip leading zeros */ 371219089Spjd v = ((int)(a->d[i] >> (long)j)) & 0x0f; 372219089Spjd if (z || (v != 0)) { 373219089Spjd if (BIO_write(bp, &(Hex[v]), 1) != 1) 374219089Spjd goto end; 375219089Spjd z = 1; 376219089Spjd } 377219089Spjd } 378219089Spjd } 379219089Spjd ret = 1; 380219089Spjd end: 381219089Spjd return (ret); 382219089Spjd} 383219089Spjd#endif 384219089Spjd 385185029Spjdchar *BN_options(void) 386219089Spjd{ 387185029Spjd static int init = 0; 388219089Spjd static char data[16]; 389219089Spjd 390219089Spjd if (!init) { 391219089Spjd init++; 392219089Spjd#ifdef BN_LLONG 393219089Spjd BIO_snprintf(data, sizeof data, "bn(%d,%d)", 394219089Spjd (int)sizeof(BN_ULLONG) * 8, (int)sizeof(BN_ULONG) * 8); 395219089Spjd#else 396219089Spjd BIO_snprintf(data, sizeof data, "bn(%d,%d)", 397219089Spjd (int)sizeof(BN_ULONG) * 8, (int)sizeof(BN_ULONG) * 8); 398219089Spjd#endif 399219089Spjd } 400219089Spjd return (data); 401219089Spjd} 402219089Spjd