1*80ab493cSjsing /* $OpenBSD: bn_convert.c,v 1.23 2024/11/08 14:18:44 jsing Exp $ */ 20f500281Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 30f500281Sjsing * All rights reserved. 40f500281Sjsing * 50f500281Sjsing * This package is an SSL implementation written 60f500281Sjsing * by Eric Young (eay@cryptsoft.com). 70f500281Sjsing * The implementation was written so as to conform with Netscapes SSL. 80f500281Sjsing * 90f500281Sjsing * This library is free for commercial and non-commercial use as long as 100f500281Sjsing * the following conditions are aheared to. The following conditions 110f500281Sjsing * apply to all code found in this distribution, be it the RC4, RSA, 120f500281Sjsing * lhash, DES, etc., code; not just the SSL code. The SSL documentation 130f500281Sjsing * included with this distribution is covered by the same copyright terms 140f500281Sjsing * except that the holder is Tim Hudson (tjh@cryptsoft.com). 150f500281Sjsing * 160f500281Sjsing * Copyright remains Eric Young's, and as such any Copyright notices in 170f500281Sjsing * the code are not to be removed. 180f500281Sjsing * If this package is used in a product, Eric Young should be given attribution 190f500281Sjsing * as the author of the parts of the library used. 200f500281Sjsing * This can be in the form of a textual message at program startup or 210f500281Sjsing * in documentation (online or textual) provided with the package. 220f500281Sjsing * 230f500281Sjsing * Redistribution and use in source and binary forms, with or without 240f500281Sjsing * modification, are permitted provided that the following conditions 250f500281Sjsing * are met: 260f500281Sjsing * 1. Redistributions of source code must retain the copyright 270f500281Sjsing * notice, this list of conditions and the following disclaimer. 280f500281Sjsing * 2. Redistributions in binary form must reproduce the above copyright 290f500281Sjsing * notice, this list of conditions and the following disclaimer in the 300f500281Sjsing * documentation and/or other materials provided with the distribution. 310f500281Sjsing * 3. All advertising materials mentioning features or use of this software 320f500281Sjsing * must display the following acknowledgement: 330f500281Sjsing * "This product includes cryptographic software written by 340f500281Sjsing * Eric Young (eay@cryptsoft.com)" 350f500281Sjsing * The word 'cryptographic' can be left out if the rouines from the library 360f500281Sjsing * being used are not cryptographic related :-). 370f500281Sjsing * 4. If you include any Windows specific code (or a derivative thereof) from 380f500281Sjsing * the apps directory (application code) you must include an acknowledgement: 390f500281Sjsing * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 400f500281Sjsing * 410f500281Sjsing * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 420f500281Sjsing * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 430f500281Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 440f500281Sjsing * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 450f500281Sjsing * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 460f500281Sjsing * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 470f500281Sjsing * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 480f500281Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 490f500281Sjsing * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 500f500281Sjsing * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 510f500281Sjsing * SUCH DAMAGE. 520f500281Sjsing * 530f500281Sjsing * The licence and distribution terms for any publically available version or 540f500281Sjsing * derivative of this code cannot be changed. i.e. this code cannot simply be 550f500281Sjsing * copied and put under another distribution licence 560f500281Sjsing * [including the GNU Public Licence.] 570f500281Sjsing */ 580f500281Sjsing 590f500281Sjsing #include <ctype.h> 600f500281Sjsing #include <limits.h> 610f500281Sjsing #include <stdio.h> 628eccbb36Sjsing #include <string.h> 630f500281Sjsing 640f500281Sjsing #include <openssl/opensslconf.h> 650f500281Sjsing 660f500281Sjsing #include <openssl/bio.h> 670f500281Sjsing #include <openssl/buffer.h> 680f500281Sjsing #include <openssl/err.h> 690f500281Sjsing 700f500281Sjsing #include "bn_local.h" 71ec8311b4Sjsing #include "bytestring.h" 72*80ab493cSjsing #include "crypto_internal.h" 730f500281Sjsing 746603e997Sjsing static int bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs); 756603e997Sjsing static int bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs); 766603e997Sjsing 77055a47c2Sjsing static const char hex_digits[] = "0123456789ABCDEF"; 780f500281Sjsing 798eccbb36Sjsing static int 80*80ab493cSjsing bn_bn2binpad_internal(const BIGNUM *bn, uint8_t *out, int out_len, 81*80ab493cSjsing int little_endian) 828eccbb36Sjsing { 83*80ab493cSjsing uint8_t mask, v; 84*80ab493cSjsing BN_ULONG w; 85*80ab493cSjsing int i, j; 86*80ab493cSjsing int b, n; 878eccbb36Sjsing 88*80ab493cSjsing n = BN_num_bytes(bn); 898eccbb36Sjsing 90*80ab493cSjsing if (out_len == -1) 91*80ab493cSjsing out_len = n; 92*80ab493cSjsing if (out_len < n) 938eccbb36Sjsing return -1; 94*80ab493cSjsing 95*80ab493cSjsing if (bn->dmax == 0) { 96*80ab493cSjsing explicit_bzero(out, out_len); 97*80ab493cSjsing return out_len; 988eccbb36Sjsing } 998eccbb36Sjsing 100*80ab493cSjsing mask = 0; 101*80ab493cSjsing b = BN_BITS2; 102*80ab493cSjsing j = 0; 103*80ab493cSjsing 104*80ab493cSjsing for (i = out_len - 1; i >= 0; i--) { 105*80ab493cSjsing if (b == BN_BITS2) { 106*80ab493cSjsing mask = crypto_ct_lt_mask(j, bn->top); 107*80ab493cSjsing w = bn->d[j++ % bn->dmax]; 108*80ab493cSjsing b = 0; 109*80ab493cSjsing } 110*80ab493cSjsing out[i] = (w >> b) & mask; 111*80ab493cSjsing b += 8; 1128eccbb36Sjsing } 1138eccbb36Sjsing 114*80ab493cSjsing if (little_endian) { 115*80ab493cSjsing for (i = 0, j = out_len - 1; i < out_len / 2; i++, j--) { 116*80ab493cSjsing v = out[i]; 117*80ab493cSjsing out[i] = out[j]; 118*80ab493cSjsing out[j] = v; 119*80ab493cSjsing } 1208eccbb36Sjsing } 1218eccbb36Sjsing 122*80ab493cSjsing return out_len; 1238eccbb36Sjsing } 1248eccbb36Sjsing 1258eccbb36Sjsing int 126*80ab493cSjsing BN_bn2bin(const BIGNUM *bn, unsigned char *to) 1278eccbb36Sjsing { 128*80ab493cSjsing return bn_bn2binpad_internal(bn, to, -1, 0); 1298eccbb36Sjsing } 130ca1d80d6Sbeck LCRYPTO_ALIAS(BN_bn2bin); 1318eccbb36Sjsing 1328eccbb36Sjsing int 133*80ab493cSjsing BN_bn2binpad(const BIGNUM *bn, unsigned char *to, int to_len) 1348eccbb36Sjsing { 135*80ab493cSjsing if (to_len < 0) 1368eccbb36Sjsing return -1; 137*80ab493cSjsing 138*80ab493cSjsing return bn_bn2binpad_internal(bn, to, to_len, 0); 1398eccbb36Sjsing } 140ca1d80d6Sbeck LCRYPTO_ALIAS(BN_bn2binpad); 1418eccbb36Sjsing 142be929329Sjsing static int 1430a50a6dbSjsing bn_bin2bn_cbs(BIGNUM **bnp, CBS *cbs, int lebin) 1448eccbb36Sjsing { 1458eccbb36Sjsing BIGNUM *bn = NULL; 146be929329Sjsing BN_ULONG w; 147be929329Sjsing uint8_t v; 148be929329Sjsing int b, i; 149be929329Sjsing 150be929329Sjsing if ((bn = *bnp) == NULL) 151be929329Sjsing bn = BN_new(); 152be929329Sjsing if (bn == NULL) 153be929329Sjsing goto err; 154be929329Sjsing if (!bn_expand_bytes(bn, CBS_len(cbs))) 155be929329Sjsing goto err; 156be929329Sjsing 1576895ff70Sjsing b = 0; 158be929329Sjsing i = 0; 159be929329Sjsing w = 0; 160be929329Sjsing 161be929329Sjsing while (CBS_len(cbs) > 0) { 1620a50a6dbSjsing if (lebin) { 1630a50a6dbSjsing if (!CBS_get_u8(cbs, &v)) 1640a50a6dbSjsing goto err; 1650a50a6dbSjsing } else { 166be929329Sjsing if (!CBS_get_last_u8(cbs, &v)) 167be929329Sjsing goto err; 1680a50a6dbSjsing } 169be929329Sjsing 1706895ff70Sjsing w |= (BN_ULONG)v << b; 1716895ff70Sjsing b += 8; 172be929329Sjsing 1736895ff70Sjsing if (b == BN_BITS2 || CBS_len(cbs) == 0) { 1746895ff70Sjsing b = 0; 175be929329Sjsing bn->d[i++] = w; 176be929329Sjsing w = 0; 177be929329Sjsing } 178be929329Sjsing } 179be929329Sjsing 180be929329Sjsing bn->neg = 0; 181be929329Sjsing bn->top = i; 182be929329Sjsing 183be929329Sjsing bn_correct_top(bn); 184be929329Sjsing 185be929329Sjsing *bnp = bn; 186be929329Sjsing 187be929329Sjsing return 1; 188be929329Sjsing 189be929329Sjsing err: 190be929329Sjsing if (*bnp == NULL) 191be929329Sjsing BN_free(bn); 192be929329Sjsing 193be929329Sjsing return 0; 194be929329Sjsing } 195be929329Sjsing 196be929329Sjsing BIGNUM * 197be929329Sjsing BN_bin2bn(const unsigned char *d, int len, BIGNUM *bn) 198be929329Sjsing { 199be929329Sjsing CBS cbs; 2008eccbb36Sjsing 2018eccbb36Sjsing if (len < 0) 2028eccbb36Sjsing return NULL; 203be929329Sjsing 204be929329Sjsing CBS_init(&cbs, d, len); 205be929329Sjsing 2060a50a6dbSjsing if (!bn_bin2bn_cbs(&bn, &cbs, 0)) 207be929329Sjsing return NULL; 208be929329Sjsing 209be929329Sjsing return bn; 2108eccbb36Sjsing } 211ca1d80d6Sbeck LCRYPTO_ALIAS(BN_bin2bn); 2128eccbb36Sjsing 2138eccbb36Sjsing int 214*80ab493cSjsing BN_bn2lebinpad(const BIGNUM *bn, unsigned char *to, int to_len) 2158eccbb36Sjsing { 216*80ab493cSjsing if (to_len < 0) 2178eccbb36Sjsing return -1; 2188eccbb36Sjsing 219*80ab493cSjsing return bn_bn2binpad_internal(bn, to, to_len, 1); 2208eccbb36Sjsing } 221ca1d80d6Sbeck LCRYPTO_ALIAS(BN_bn2lebinpad); 2228eccbb36Sjsing 2238eccbb36Sjsing BIGNUM * 2240a50a6dbSjsing BN_lebin2bn(const unsigned char *d, int len, BIGNUM *bn) 2258eccbb36Sjsing { 2260a50a6dbSjsing CBS cbs; 2278eccbb36Sjsing 2280a50a6dbSjsing if (len < 0) 2298eccbb36Sjsing return NULL; 2308eccbb36Sjsing 2310a50a6dbSjsing CBS_init(&cbs, d, len); 2328eccbb36Sjsing 2330a50a6dbSjsing if (!bn_bin2bn_cbs(&bn, &cbs, 1)) 2348eccbb36Sjsing return NULL; 2358eccbb36Sjsing 2360a50a6dbSjsing return bn; 2378eccbb36Sjsing } 238ca1d80d6Sbeck LCRYPTO_ALIAS(BN_lebin2bn); 2398eccbb36Sjsing 240a2b49ab6Sjsing int 2416603e997Sjsing BN_asc2bn(BIGNUM **bnp, const char *s) 2420f500281Sjsing { 2436603e997Sjsing CBS cbs, cbs_hex; 2446603e997Sjsing size_t s_len; 2456603e997Sjsing uint8_t v; 2466603e997Sjsing int neg; 2470f500281Sjsing 2486603e997Sjsing if (bnp != NULL && *bnp != NULL) 2496603e997Sjsing BN_zero(*bnp); 2506603e997Sjsing 2516603e997Sjsing if (s == NULL) 252a2b49ab6Sjsing return 0; 2536603e997Sjsing if ((s_len = strlen(s)) == 0) 2546603e997Sjsing return 0; 2556603e997Sjsing 2566603e997Sjsing CBS_init(&cbs, s, s_len); 2576603e997Sjsing 2586603e997Sjsing /* Handle negative sign. */ 2596603e997Sjsing if (!CBS_peek_u8(&cbs, &v)) 2606603e997Sjsing return 0; 2616603e997Sjsing if ((neg = (v == '-'))) { 2626603e997Sjsing if (!CBS_skip(&cbs, 1)) 263a2b49ab6Sjsing return 0; 2640f500281Sjsing } 2656603e997Sjsing 2663145afc7Stb /* Try parsing as hexadecimal with a 0x prefix. */ 2676603e997Sjsing CBS_dup(&cbs, &cbs_hex); 2686603e997Sjsing if (!CBS_get_u8(&cbs_hex, &v)) 2696603e997Sjsing goto decimal; 2706603e997Sjsing if (v != '0') 2716603e997Sjsing goto decimal; 2726603e997Sjsing if (!CBS_get_u8(&cbs_hex, &v)) 2736603e997Sjsing goto decimal; 2746603e997Sjsing if (v != 'X' && v != 'x') 2756603e997Sjsing goto decimal; 27653924480Stb if (bn_hex2bn_cbs(bnp, &cbs_hex) == 0) 2776603e997Sjsing return 0; 2786603e997Sjsing 2796603e997Sjsing goto done; 2806603e997Sjsing 2816603e997Sjsing decimal: 28253924480Stb if (bn_dec2bn_cbs(bnp, &cbs) == 0) 2836603e997Sjsing return 0; 2846603e997Sjsing 2856603e997Sjsing done: 2867b63f630Stb if (bnp != NULL && *bnp != NULL) 2876603e997Sjsing BN_set_negative(*bnp, neg); 2886603e997Sjsing 289a2b49ab6Sjsing return 1; 2900f500281Sjsing } 291ca1d80d6Sbeck LCRYPTO_ALIAS(BN_asc2bn); 2920f500281Sjsing 2930f500281Sjsing char * 294ec8311b4Sjsing BN_bn2dec(const BIGNUM *bn) 2950f500281Sjsing { 296ec8311b4Sjsing int started = 0; 297ec8311b4Sjsing BIGNUM *tmp = NULL; 298ec8311b4Sjsing uint8_t *data = NULL; 299ec8311b4Sjsing size_t data_len = 0; 300ec8311b4Sjsing uint8_t *s = NULL; 301ec8311b4Sjsing size_t s_len; 302ec8311b4Sjsing BN_ULONG v, w; 303ec8311b4Sjsing uint8_t c; 304ec8311b4Sjsing CBB cbb; 305ec8311b4Sjsing CBS cbs; 306ec8311b4Sjsing int i; 3070f500281Sjsing 308ec8311b4Sjsing if (!CBB_init(&cbb, 0)) 3090f500281Sjsing goto err; 3100f500281Sjsing 311ec8311b4Sjsing if ((tmp = BN_dup(bn)) == NULL) 312ec8311b4Sjsing goto err; 313ec8311b4Sjsing 314ec8311b4Sjsing /* 315ec8311b4Sjsing * Divide the BIGNUM by a large multiple of 10, then break the remainder 316ec8311b4Sjsing * into decimal digits. This produces a reversed string of digits, 317ec8311b4Sjsing * potentially with leading zeroes. 3180f500281Sjsing */ 319ec8311b4Sjsing while (!BN_is_zero(tmp)) { 320ec8311b4Sjsing if ((w = BN_div_word(tmp, BN_DEC_CONV)) == -1) 3210f500281Sjsing goto err; 322ec8311b4Sjsing for (i = 0; i < BN_DEC_NUM; i++) { 323ec8311b4Sjsing v = w % 10; 324ec8311b4Sjsing if (!CBB_add_u8(&cbb, '0' + v)) 325ec8311b4Sjsing goto err; 326ec8311b4Sjsing w /= 10; 3270f500281Sjsing } 328ec8311b4Sjsing } 329ec8311b4Sjsing if (!CBB_finish(&cbb, &data, &data_len)) 3300f500281Sjsing goto err; 3310f500281Sjsing 332ec8311b4Sjsing if (data_len > SIZE_MAX - 3) 333ec8311b4Sjsing goto err; 334ec8311b4Sjsing if (!CBB_init(&cbb, data_len + 3)) 335ec8311b4Sjsing goto err; 3360f500281Sjsing 337ec8311b4Sjsing if (BN_is_negative(bn)) { 338ec8311b4Sjsing if (!CBB_add_u8(&cbb, '-')) 3390f500281Sjsing goto err; 340ec8311b4Sjsing } 341ec8311b4Sjsing 342ec8311b4Sjsing /* Reverse digits and trim leading zeroes. */ 343ec8311b4Sjsing CBS_init(&cbs, data, data_len); 344ec8311b4Sjsing while (CBS_len(&cbs) > 0) { 345ec8311b4Sjsing if (!CBS_get_last_u8(&cbs, &c)) 3460f500281Sjsing goto err; 347ec8311b4Sjsing if (!started && c == '0') 348ec8311b4Sjsing continue; 349ec8311b4Sjsing if (!CBB_add_u8(&cbb, c)) 350ec8311b4Sjsing goto err; 351ec8311b4Sjsing started = 1; 3520f500281Sjsing } 353ec8311b4Sjsing 354ec8311b4Sjsing if (!started) { 355ec8311b4Sjsing if (!CBB_add_u8(&cbb, '0')) 356ec8311b4Sjsing goto err; 3570f500281Sjsing } 358ec8311b4Sjsing if (!CBB_add_u8(&cbb, '\0')) 359ec8311b4Sjsing goto err; 360ec8311b4Sjsing if (!CBB_finish(&cbb, &s, &s_len)) 361ec8311b4Sjsing goto err; 3620f500281Sjsing 3630f500281Sjsing err: 364ec8311b4Sjsing BN_free(tmp); 365ec8311b4Sjsing CBB_cleanup(&cbb); 366ec8311b4Sjsing freezero(data, data_len); 3670f500281Sjsing 368ec8311b4Sjsing return s; 3690f500281Sjsing } 370ca1d80d6Sbeck LCRYPTO_ALIAS(BN_bn2dec); 3710f500281Sjsing 3726603e997Sjsing static int 3736603e997Sjsing bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs) 374a2b49ab6Sjsing { 3756603e997Sjsing CBS cbs_digits; 3766603e997Sjsing BIGNUM *bn = NULL; 3776603e997Sjsing int d, neg, num; 3786603e997Sjsing size_t digits = 0; 3796603e997Sjsing BN_ULONG w; 3806603e997Sjsing uint8_t v; 381a2b49ab6Sjsing 3826603e997Sjsing /* Handle negative sign. */ 3836603e997Sjsing if (!CBS_peek_u8(cbs, &v)) 3846603e997Sjsing goto err; 3856603e997Sjsing if ((neg = (v == '-'))) { 3866603e997Sjsing if (!CBS_skip(cbs, 1)) 3876603e997Sjsing goto err; 388a2b49ab6Sjsing } 389a2b49ab6Sjsing 3906603e997Sjsing /* Scan to find last decimal digit. */ 3916603e997Sjsing CBS_dup(cbs, &cbs_digits); 3926603e997Sjsing while (CBS_len(&cbs_digits) > 0) { 3936603e997Sjsing if (!CBS_get_u8(&cbs_digits, &v)) 3946603e997Sjsing goto err; 3956603e997Sjsing if (!isdigit(v)) 3966603e997Sjsing break; 3976603e997Sjsing digits++; 3986603e997Sjsing } 3996603e997Sjsing if (digits > INT_MAX / 4) 4006603e997Sjsing goto err; 401a2b49ab6Sjsing 4026603e997Sjsing num = digits + neg; 4036603e997Sjsing 4046603e997Sjsing if (bnp == NULL) 4056603e997Sjsing return num; 4066603e997Sjsing 4076603e997Sjsing if ((bn = *bnp) == NULL) 4086603e997Sjsing bn = BN_new(); 409a2b49ab6Sjsing if (bn == NULL) 4106603e997Sjsing goto err; 411f89a836aSjsing if (!bn_expand_bits(bn, digits * 4)) 412a2b49ab6Sjsing goto err; 413a2b49ab6Sjsing 4146603e997Sjsing if ((d = digits % BN_DEC_NUM) == 0) 4156603e997Sjsing d = BN_DEC_NUM; 4166603e997Sjsing 4176603e997Sjsing w = 0; 4186603e997Sjsing 4196603e997Sjsing /* Work forwards from most significant digit. */ 4206603e997Sjsing while (digits-- > 0) { 4216603e997Sjsing if (!CBS_get_u8(cbs, &v)) 422a2b49ab6Sjsing goto err; 4236603e997Sjsing 4246603e997Sjsing if (v < '0' || v > '9') 425a2b49ab6Sjsing goto err; 4266603e997Sjsing 4276603e997Sjsing v -= '0'; 4286603e997Sjsing w = w * 10 + v; 4296603e997Sjsing d--; 4306603e997Sjsing 4316603e997Sjsing if (d == 0) { 4326603e997Sjsing if (!BN_mul_word(bn, BN_DEC_CONV)) 4336603e997Sjsing goto err; 4346603e997Sjsing if (!BN_add_word(bn, w)) 4356603e997Sjsing goto err; 4366603e997Sjsing 4376603e997Sjsing d = BN_DEC_NUM; 4386603e997Sjsing w = 0; 439a2b49ab6Sjsing } 440a2b49ab6Sjsing } 441a2b49ab6Sjsing 4426603e997Sjsing bn_correct_top(bn); 443a2b49ab6Sjsing 4446603e997Sjsing BN_set_negative(bn, neg); 445a2b49ab6Sjsing 4466603e997Sjsing *bnp = bn; 4476603e997Sjsing 4486603e997Sjsing return num; 449a2b49ab6Sjsing 450a2b49ab6Sjsing err: 4516603e997Sjsing if (bnp != NULL && *bnp == NULL) 4526603e997Sjsing BN_free(bn); 4536603e997Sjsing 4546603e997Sjsing return 0; 4556603e997Sjsing } 4566603e997Sjsing 4576603e997Sjsing int 4586603e997Sjsing BN_dec2bn(BIGNUM **bnp, const char *s) 4596603e997Sjsing { 4606603e997Sjsing size_t s_len; 4616603e997Sjsing CBS cbs; 4626603e997Sjsing 4636603e997Sjsing if (bnp != NULL && *bnp != NULL) 4646603e997Sjsing BN_zero(*bnp); 4656603e997Sjsing 4666603e997Sjsing if (s == NULL) 4676603e997Sjsing return 0; 4686603e997Sjsing if ((s_len = strlen(s)) == 0) 4696603e997Sjsing return 0; 4706603e997Sjsing 4716603e997Sjsing CBS_init(&cbs, s, s_len); 4726603e997Sjsing 4736603e997Sjsing return bn_dec2bn_cbs(bnp, &cbs); 474a2b49ab6Sjsing } 475ca1d80d6Sbeck LCRYPTO_ALIAS(BN_dec2bn); 476a2b49ab6Sjsing 477beecfe2bStb static int 478beecfe2bStb bn_bn2hex_internal(const BIGNUM *bn, int include_sign, int nibbles_only, 479beecfe2bStb char **out, size_t *out_len) 480a2b49ab6Sjsing { 4815a06967dSjsing int started = 0; 4825a06967dSjsing uint8_t *s = NULL; 483beecfe2bStb size_t s_len = 0; 4845a06967dSjsing BN_ULONG v, w; 4855a06967dSjsing int i, j; 4865a06967dSjsing CBB cbb; 487beecfe2bStb CBS cbs; 488beecfe2bStb uint8_t nul; 489beecfe2bStb int ret = 0; 490beecfe2bStb 491beecfe2bStb *out = NULL; 492beecfe2bStb *out_len = 0; 493a2b49ab6Sjsing 4945a06967dSjsing if (!CBB_init(&cbb, 0)) 4955a06967dSjsing goto err; 4965a06967dSjsing 497beecfe2bStb if (BN_is_negative(bn) && include_sign) { 4985a06967dSjsing if (!CBB_add_u8(&cbb, '-')) 499a2b49ab6Sjsing goto err; 500a2b49ab6Sjsing } 5015a06967dSjsing if (BN_is_zero(bn)) { 5025a06967dSjsing if (!CBB_add_u8(&cbb, '0')) 5035a06967dSjsing goto err; 5045a06967dSjsing } 5055a06967dSjsing for (i = bn->top - 1; i >= 0; i--) { 5065a06967dSjsing w = bn->d[i]; 507a2b49ab6Sjsing for (j = BN_BITS2 - 8; j >= 0; j -= 8) { 5085a06967dSjsing v = (w >> j) & 0xff; 5095a06967dSjsing if (!started && v == 0) 5105a06967dSjsing continue; 511beecfe2bStb if (started || !nibbles_only || (v >> 4) != 0) { 5125a06967dSjsing if (!CBB_add_u8(&cbb, hex_digits[v >> 4])) 5135a06967dSjsing goto err; 514beecfe2bStb } 5155a06967dSjsing if (!CBB_add_u8(&cbb, hex_digits[v & 0xf])) 5165a06967dSjsing goto err; 5175a06967dSjsing started = 1; 518a2b49ab6Sjsing } 519a2b49ab6Sjsing } 5205a06967dSjsing if (!CBB_add_u8(&cbb, '\0')) 5215a06967dSjsing goto err; 5225a06967dSjsing if (!CBB_finish(&cbb, &s, &s_len)) 5235a06967dSjsing goto err; 524a2b49ab6Sjsing 525beecfe2bStb /* The length of a C string does not include the terminating NUL. */ 526beecfe2bStb CBS_init(&cbs, s, s_len); 527beecfe2bStb if (!CBS_get_last_u8(&cbs, &nul)) 528beecfe2bStb goto err; 529beecfe2bStb 530beecfe2bStb *out = (char *)CBS_data(&cbs); 531beecfe2bStb *out_len = CBS_len(&cbs); 532beecfe2bStb s = NULL; 533beecfe2bStb s_len = 0; 534beecfe2bStb 535beecfe2bStb ret = 1; 536beecfe2bStb 537a2b49ab6Sjsing err: 5385a06967dSjsing CBB_cleanup(&cbb); 539beecfe2bStb freezero(s, s_len); 540beecfe2bStb 541beecfe2bStb return ret; 542beecfe2bStb } 543beecfe2bStb 544beecfe2bStb int 545beecfe2bStb bn_bn2hex_nosign(const BIGNUM *bn, char **out, size_t *out_len) 546beecfe2bStb { 547beecfe2bStb return bn_bn2hex_internal(bn, 0, 0, out, out_len); 548beecfe2bStb } 549beecfe2bStb 550beecfe2bStb int 551beecfe2bStb bn_bn2hex_nibbles(const BIGNUM *bn, char **out, size_t *out_len) 552beecfe2bStb { 553beecfe2bStb return bn_bn2hex_internal(bn, 1, 1, out, out_len); 554beecfe2bStb } 555beecfe2bStb 556beecfe2bStb char * 557beecfe2bStb BN_bn2hex(const BIGNUM *bn) 558beecfe2bStb { 559beecfe2bStb char *s; 560beecfe2bStb size_t s_len; 561beecfe2bStb 562beecfe2bStb if (!bn_bn2hex_internal(bn, 1, 0, &s, &s_len)) 563beecfe2bStb return NULL; 5645a06967dSjsing 5655a06967dSjsing return s; 566a2b49ab6Sjsing } 567ca1d80d6Sbeck LCRYPTO_ALIAS(BN_bn2hex); 568a2b49ab6Sjsing 5696603e997Sjsing static int 5706603e997Sjsing bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs) 5710f500281Sjsing { 5726603e997Sjsing CBS cbs_digits; 5736603e997Sjsing BIGNUM *bn = NULL; 5746603e997Sjsing int b, i, neg, num; 5756603e997Sjsing size_t digits = 0; 5766603e997Sjsing BN_ULONG w; 5776603e997Sjsing uint8_t v; 5780f500281Sjsing 5796603e997Sjsing /* Handle negative sign. */ 5806603e997Sjsing if (!CBS_peek_u8(cbs, &v)) 5816603e997Sjsing goto err; 5826603e997Sjsing if ((neg = (v == '-'))) { 5836603e997Sjsing if (!CBS_skip(cbs, 1)) 5846603e997Sjsing goto err; 5850f500281Sjsing } 5860f500281Sjsing 5876603e997Sjsing /* Scan to find last hexadecimal digit. */ 5886603e997Sjsing CBS_dup(cbs, &cbs_digits); 5896603e997Sjsing while (CBS_len(&cbs_digits) > 0) { 5906603e997Sjsing if (!CBS_get_u8(&cbs_digits, &v)) 5916603e997Sjsing goto err; 5926603e997Sjsing if (!isxdigit(v)) 5936603e997Sjsing break; 5946603e997Sjsing digits++; 5950f500281Sjsing } 5966603e997Sjsing if (digits > INT_MAX / 4) 5970f500281Sjsing goto err; 5980f500281Sjsing 5996603e997Sjsing num = digits + neg; 6006603e997Sjsing 6016603e997Sjsing if (bnp == NULL) 6026603e997Sjsing return num; 6036603e997Sjsing 6046603e997Sjsing if ((bn = *bnp) == NULL) 6056603e997Sjsing bn = BN_new(); 6066603e997Sjsing if (bn == NULL) 6076603e997Sjsing goto err; 608f89a836aSjsing if (!bn_expand_bits(bn, digits * 4)) 6096603e997Sjsing goto err; 6106603e997Sjsing 6116603e997Sjsing if (!CBS_get_bytes(cbs, cbs, digits)) 6126603e997Sjsing goto err; 6136603e997Sjsing 6146895ff70Sjsing b = 0; 6156603e997Sjsing i = 0; 6166603e997Sjsing w = 0; 6176603e997Sjsing 6186603e997Sjsing /* Work backwards from least significant digit. */ 6196603e997Sjsing while (digits-- > 0) { 6206603e997Sjsing if (!CBS_get_last_u8(cbs, &v)) 6216603e997Sjsing goto err; 6226603e997Sjsing 6236603e997Sjsing if (v >= '0' && v <= '9') 6246603e997Sjsing v -= '0'; 6256603e997Sjsing else if (v >= 'a' && v <= 'f') 6266603e997Sjsing v -= 'a' - 10; 6276603e997Sjsing else if (v >= 'A' && v <= 'F') 6286603e997Sjsing v -= 'A' - 10; 6290f500281Sjsing else 6306603e997Sjsing goto err; 6310f500281Sjsing 6326895ff70Sjsing w |= (BN_ULONG)v << b; 6336895ff70Sjsing b += 4; 6346603e997Sjsing 6356895ff70Sjsing if (b == BN_BITS2 || digits == 0) { 6366895ff70Sjsing b = 0; 6376603e997Sjsing bn->d[i++] = w; 6386603e997Sjsing w = 0; 6390f500281Sjsing } 6400f500281Sjsing } 6410f500281Sjsing 6426603e997Sjsing bn->top = i; 6436603e997Sjsing bn_correct_top(bn); 6440f500281Sjsing 6456603e997Sjsing BN_set_negative(bn, neg); 6466603e997Sjsing 6476603e997Sjsing *bnp = bn; 6486603e997Sjsing 6496603e997Sjsing return num; 6500f500281Sjsing 6510f500281Sjsing err: 6526603e997Sjsing if (bnp != NULL && *bnp == NULL) 6536603e997Sjsing BN_free(bn); 6546603e997Sjsing 6556603e997Sjsing return 0; 6566603e997Sjsing } 6576603e997Sjsing 6586603e997Sjsing int 6596603e997Sjsing BN_hex2bn(BIGNUM **bnp, const char *s) 6606603e997Sjsing { 6616603e997Sjsing size_t s_len; 6626603e997Sjsing CBS cbs; 6636603e997Sjsing 6646603e997Sjsing if (bnp != NULL && *bnp != NULL) 6656603e997Sjsing BN_zero(*bnp); 6666603e997Sjsing 6676603e997Sjsing if (s == NULL) 6686603e997Sjsing return 0; 6696603e997Sjsing if ((s_len = strlen(s)) == 0) 6706603e997Sjsing return 0; 6716603e997Sjsing 6726603e997Sjsing CBS_init(&cbs, s, s_len); 6736603e997Sjsing 6746603e997Sjsing return bn_hex2bn_cbs(bnp, &cbs); 6750f500281Sjsing } 676ca1d80d6Sbeck LCRYPTO_ALIAS(BN_hex2bn); 6770f500281Sjsing 6780f500281Sjsing int 67944db6463Sjsing BN_bn2mpi(const BIGNUM *bn, unsigned char *d) 680fc83660bSjsing { 68144db6463Sjsing uint8_t *out_bin; 68244db6463Sjsing size_t out_len, out_bin_len; 68344db6463Sjsing int bits, bytes; 68444db6463Sjsing int extend; 68544db6463Sjsing CBB cbb, cbb_bin; 686fc83660bSjsing 68744db6463Sjsing bits = BN_num_bits(bn); 68844db6463Sjsing bytes = (bits + 7) / 8; 68944db6463Sjsing extend = (bits != 0) && (bits % 8 == 0); 69044db6463Sjsing out_bin_len = extend + bytes; 69144db6463Sjsing out_len = 4 + out_bin_len; 69244db6463Sjsing 693fc83660bSjsing if (d == NULL) 69444db6463Sjsing return out_len; 695fc83660bSjsing 69644db6463Sjsing if (!CBB_init_fixed(&cbb, d, out_len)) 69744db6463Sjsing goto err; 69844db6463Sjsing if (!CBB_add_u32_length_prefixed(&cbb, &cbb_bin)) 69944db6463Sjsing goto err; 70044db6463Sjsing if (!CBB_add_space(&cbb_bin, &out_bin, out_bin_len)) 70144db6463Sjsing goto err; 70244db6463Sjsing if (BN_bn2binpad(bn, out_bin, out_bin_len) != out_bin_len) 70344db6463Sjsing goto err; 70444db6463Sjsing if (!CBB_finish(&cbb, NULL, NULL)) 70544db6463Sjsing goto err; 70644db6463Sjsing 70744db6463Sjsing if (bn->neg) 708fc83660bSjsing d[4] |= 0x80; 70944db6463Sjsing 71044db6463Sjsing return out_len; 71144db6463Sjsing 71244db6463Sjsing err: 71344db6463Sjsing CBB_cleanup(&cbb); 71444db6463Sjsing 71544db6463Sjsing return -1; 716fc83660bSjsing } 717ca1d80d6Sbeck LCRYPTO_ALIAS(BN_bn2mpi); 718fc83660bSjsing 719fc83660bSjsing BIGNUM * 7202018d106Sjsing BN_mpi2bn(const unsigned char *d, int n, BIGNUM *bn_in) 721fc83660bSjsing { 7222018d106Sjsing BIGNUM *bn = bn_in; 7232018d106Sjsing uint32_t mpi_len; 7242018d106Sjsing uint8_t v; 725fc83660bSjsing int neg = 0; 7262018d106Sjsing CBS cbs; 727fc83660bSjsing 7282018d106Sjsing if (n < 0) 7292018d106Sjsing return NULL; 7302018d106Sjsing 7312018d106Sjsing CBS_init(&cbs, d, n); 7322018d106Sjsing 7332018d106Sjsing if (!CBS_get_u32(&cbs, &mpi_len)) { 734fc83660bSjsing BNerror(BN_R_INVALID_LENGTH); 7352018d106Sjsing return NULL; 736fc83660bSjsing } 7372018d106Sjsing if (CBS_len(&cbs) != mpi_len) { 738fc83660bSjsing BNerror(BN_R_ENCODING_ERROR); 7392018d106Sjsing return NULL; 7402018d106Sjsing } 7412018d106Sjsing if (CBS_len(&cbs) > 0) { 7422018d106Sjsing if (!CBS_peek_u8(&cbs, &v)) 7432018d106Sjsing return NULL; 7442018d106Sjsing neg = (v >> 7) & 1; 745fc83660bSjsing } 746fc83660bSjsing 7472018d106Sjsing if (!bn_bin2bn_cbs(&bn, &cbs, 0)) 7482018d106Sjsing return NULL; 749fc83660bSjsing 7502018d106Sjsing if (neg) 7512018d106Sjsing BN_clear_bit(bn, BN_num_bits(bn) - 1); 7522018d106Sjsing 7532018d106Sjsing BN_set_negative(bn, neg); 7542018d106Sjsing 7552018d106Sjsing return bn; 756fc83660bSjsing } 757ca1d80d6Sbeck LCRYPTO_ALIAS(BN_mpi2bn); 758