1/* 2 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <openssl/err.h> 11#include "crypto/ctype.h" 12#include "bn_local.h" 13 14static const char Hex[] = "0123456789ABCDEF"; 15 16/* Must 'OPENSSL_free' the returned data */ 17char *BN_bn2hex(const BIGNUM *a) 18{ 19 int i, j, v, z = 0; 20 char *buf; 21 char *p; 22 23 if (BN_is_zero(a)) 24 return OPENSSL_strdup("0"); 25 buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); 26 if (buf == NULL) { 27 ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); 28 goto err; 29 } 30 p = buf; 31 if (a->neg) 32 *p++ = '-'; 33 for (i = a->top - 1; i >= 0; i--) { 34 for (j = BN_BITS2 - 8; j >= 0; j -= 8) { 35 /* strip leading zeros */ 36 v = (int)((a->d[i] >> j) & 0xff); 37 if (z || v != 0) { 38 *p++ = Hex[v >> 4]; 39 *p++ = Hex[v & 0x0f]; 40 z = 1; 41 } 42 } 43 } 44 *p = '\0'; 45 err: 46 return buf; 47} 48 49#ifndef FIPS_MODULE 50/* No BIO_snprintf in FIPS_MODULE */ 51/* Must 'OPENSSL_free' the returned data */ 52char *BN_bn2dec(const BIGNUM *a) 53{ 54 int i = 0, num, ok = 0, n, tbytes; 55 char *buf = NULL; 56 char *p; 57 BIGNUM *t = NULL; 58 BN_ULONG *bn_data = NULL, *lp; 59 int bn_data_num; 60 61 /*- 62 * get an upper bound for the length of the decimal integer 63 * num <= (BN_num_bits(a) + 1) * log(2) 64 * <= 3 * BN_num_bits(a) * 0.101 + log(2) + 1 (rounding error) 65 * <= 3 * BN_num_bits(a) / 10 + 3 * BN_num_bits / 1000 + 1 + 1 66 */ 67 i = BN_num_bits(a) * 3; 68 num = (i / 10 + i / 1000 + 1) + 1; 69 tbytes = num + 3; /* negative and terminator and one spare? */ 70 bn_data_num = num / BN_DEC_NUM + 1; 71 bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG)); 72 buf = OPENSSL_malloc(tbytes); 73 if (buf == NULL || bn_data == NULL) { 74 ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); 75 goto err; 76 } 77 if ((t = BN_dup(a)) == NULL) 78 goto err; 79 80 p = buf; 81 lp = bn_data; 82 if (BN_is_zero(t)) { 83 *p++ = '0'; 84 *p++ = '\0'; 85 } else { 86 if (BN_is_negative(t)) 87 *p++ = '-'; 88 89 while (!BN_is_zero(t)) { 90 if (lp - bn_data >= bn_data_num) 91 goto err; 92 *lp = BN_div_word(t, BN_DEC_CONV); 93 if (*lp == (BN_ULONG)-1) 94 goto err; 95 lp++; 96 } 97 lp--; 98 /* 99 * We now have a series of blocks, BN_DEC_NUM chars in length, where 100 * the last one needs truncation. The blocks need to be reversed in 101 * order. 102 */ 103 n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT1, *lp); 104 if (n < 0) 105 goto err; 106 p += n; 107 while (lp != bn_data) { 108 lp--; 109 n = BIO_snprintf(p, tbytes - (size_t)(p - buf), BN_DEC_FMT2, *lp); 110 if (n < 0) 111 goto err; 112 p += n; 113 } 114 } 115 ok = 1; 116 err: 117 OPENSSL_free(bn_data); 118 BN_free(t); 119 if (ok) 120 return buf; 121 OPENSSL_free(buf); 122 return NULL; 123} 124#endif 125 126int BN_hex2bn(BIGNUM **bn, const char *a) 127{ 128 BIGNUM *ret = NULL; 129 BN_ULONG l = 0; 130 int neg = 0, h, m, i, j, k, c; 131 int num; 132 133 if (a == NULL || *a == '\0') 134 return 0; 135 136 if (*a == '-') { 137 neg = 1; 138 a++; 139 } 140 141 for (i = 0; i <= INT_MAX / 4 && ossl_isxdigit(a[i]); i++) 142 continue; 143 144 if (i == 0 || i > INT_MAX / 4) 145 return 0; 146 147 num = i + neg; 148 if (bn == NULL) 149 return num; 150 151 /* a is the start of the hex digits, and it is 'i' long */ 152 if (*bn == NULL) { 153 if ((ret = BN_new()) == NULL) 154 return 0; 155 } else { 156 ret = *bn; 157 if (BN_get_flags(ret, BN_FLG_STATIC_DATA)) { 158 ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT); 159 return 0; 160 } 161 BN_zero(ret); 162 } 163 164 /* i is the number of hex digits */ 165 if (bn_expand(ret, i * 4) == NULL) 166 goto err; 167 168 j = i; /* least significant 'hex' */ 169 m = 0; 170 h = 0; 171 while (j > 0) { 172 m = (BN_BYTES * 2 <= j) ? BN_BYTES * 2 : j; 173 l = 0; 174 for (;;) { 175 c = a[j - m]; 176 k = OPENSSL_hexchar2int(c); 177 if (k < 0) 178 k = 0; /* paranoia */ 179 l = (l << 4) | k; 180 181 if (--m <= 0) { 182 ret->d[h++] = l; 183 break; 184 } 185 } 186 j -= BN_BYTES * 2; 187 } 188 ret->top = h; 189 bn_correct_top(ret); 190 191 *bn = ret; 192 bn_check_top(ret); 193 /* Don't set the negative flag if it's zero. */ 194 if (ret->top != 0) 195 ret->neg = neg; 196 return num; 197 err: 198 if (*bn == NULL) 199 BN_free(ret); 200 return 0; 201} 202 203int BN_dec2bn(BIGNUM **bn, const char *a) 204{ 205 BIGNUM *ret = NULL; 206 BN_ULONG l = 0; 207 int neg = 0, i, j; 208 int num; 209 210 if (a == NULL || *a == '\0') 211 return 0; 212 if (*a == '-') { 213 neg = 1; 214 a++; 215 } 216 217 for (i = 0; i <= INT_MAX / 4 && ossl_isdigit(a[i]); i++) 218 continue; 219 220 if (i == 0 || i > INT_MAX / 4) 221 goto err; 222 223 num = i + neg; 224 if (bn == NULL) 225 return num; 226 227 /* 228 * a is the start of the digits, and it is 'i' long. We chop it into 229 * BN_DEC_NUM digits at a time 230 */ 231 if (*bn == NULL) { 232 if ((ret = BN_new()) == NULL) 233 return 0; 234 } else { 235 ret = *bn; 236 BN_zero(ret); 237 } 238 239 /* i is the number of digits, a bit of an over expand */ 240 if (bn_expand(ret, i * 4) == NULL) 241 goto err; 242 243 j = BN_DEC_NUM - i % BN_DEC_NUM; 244 if (j == BN_DEC_NUM) 245 j = 0; 246 l = 0; 247 while (--i >= 0) { 248 l *= 10; 249 l += *a - '0'; 250 a++; 251 if (++j == BN_DEC_NUM) { 252 if (!BN_mul_word(ret, BN_DEC_CONV) 253 || !BN_add_word(ret, l)) 254 goto err; 255 l = 0; 256 j = 0; 257 } 258 } 259 260 bn_correct_top(ret); 261 *bn = ret; 262 bn_check_top(ret); 263 /* Don't set the negative flag if it's zero. */ 264 if (ret->top != 0) 265 ret->neg = neg; 266 return num; 267 err: 268 if (*bn == NULL) 269 BN_free(ret); 270 return 0; 271} 272 273int BN_asc2bn(BIGNUM **bn, const char *a) 274{ 275 const char *p = a; 276 277 if (*p == '-') 278 p++; 279 280 if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) { 281 if (!BN_hex2bn(bn, p + 2)) 282 return 0; 283 } else { 284 if (!BN_dec2bn(bn, p)) 285 return 0; 286 } 287 /* Don't set the negative flag if it's zero. */ 288 if (*a == '-' && (*bn)->top != 0) 289 (*bn)->neg = 1; 290 return 1; 291} 292