summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2023-05-09 05:12:49 +0000
committerjsing <>2023-05-09 05:12:49 +0000
commit0397bb0dc2794656636489f8fb435e461785f245 (patch)
tree87467e361b40b5d3ce452f90b0b48bdf34d552cc /src/lib
parent3d8c174bc6a25e6d0edc3db05de93421dbf040a6 (diff)
downloadopenbsd-0397bb0dc2794656636489f8fb435e461785f245.tar.gz
openbsd-0397bb0dc2794656636489f8fb435e461785f245.tar.bz2
openbsd-0397bb0dc2794656636489f8fb435e461785f245.zip
Rewrite BN_bn2dec() using CBB/CBS.
ok tb@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/bn/bn_convert.c124
1 files changed, 61 insertions, 63 deletions
diff --git a/src/lib/libcrypto/bn/bn_convert.c b/src/lib/libcrypto/bn/bn_convert.c
index bfb5a566a6..673db093d8 100644
--- a/src/lib/libcrypto/bn/bn_convert.c
+++ b/src/lib/libcrypto/bn/bn_convert.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_convert.c,v 1.6 2023/04/19 11:14:04 jsing Exp $ */ 1/* $OpenBSD: bn_convert.c,v 1.7 2023/05/09 05:12:49 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -68,6 +68,7 @@
68#include <openssl/err.h> 68#include <openssl/err.h>
69 69
70#include "bn_local.h" 70#include "bn_local.h"
71#include "bytestring.h"
71 72
72static const char hex_digits[] = "0123456789ABCDEF"; 73static const char hex_digits[] = "0123456789ABCDEF";
73 74
@@ -270,85 +271,82 @@ BN_asc2bn(BIGNUM **bn, const char *a)
270 return 1; 271 return 1;
271} 272}
272 273
273/* Must 'free' the returned data */
274char * 274char *
275BN_bn2dec(const BIGNUM *a) 275BN_bn2dec(const BIGNUM *bn)
276{ 276{
277 int i = 0, num, bn_data_num, ok = 0; 277 int started = 0;
278 char *buf = NULL; 278 BIGNUM *tmp = NULL;
279 char *p; 279 uint8_t *data = NULL;
280 BIGNUM *t = NULL; 280 size_t data_len = 0;
281 BN_ULONG *bn_data = NULL, *lp; 281 uint8_t *s = NULL;
282 size_t s_len;
283 BN_ULONG v, w;
284 uint8_t c;
285 CBB cbb;
286 CBS cbs;
287 int i;
288
289 if (!CBB_init(&cbb, 0))
290 goto err;
282 291
283 if (BN_is_zero(a)) { 292 if ((tmp = BN_dup(bn)) == NULL)
284 buf = malloc(BN_is_negative(a) + 2); 293 goto err;
285 if (buf == NULL) { 294
286 BNerror(ERR_R_MALLOC_FAILURE); 295 /*
296 * Divide the BIGNUM by a large multiple of 10, then break the remainder
297 * into decimal digits. This produces a reversed string of digits,
298 * potentially with leading zeroes.
299 */
300 while (!BN_is_zero(tmp)) {
301 if ((w = BN_div_word(tmp, BN_DEC_CONV)) == -1)
287 goto err; 302 goto err;
303 for (i = 0; i < BN_DEC_NUM; i++) {
304 v = w % 10;
305 if (!CBB_add_u8(&cbb, '0' + v))
306 goto err;
307 w /= 10;
288 } 308 }
289 p = buf;
290 if (BN_is_negative(a))
291 *p++ = '-';
292 *p++ = '0';
293 *p++ = '\0';
294 return (buf);
295 } 309 }
310 if (!CBB_finish(&cbb, &data, &data_len))
311 goto err;
296 312
297 /* get an upper bound for the length of the decimal integer 313 if (data_len > SIZE_MAX - 3)
298 * num <= (BN_num_bits(a) + 1) * log(2)
299 * <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1 (rounding error)
300 * <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1
301 */
302 i = BN_num_bits(a) * 3;
303 num = (i / 10 + i / 1000 + 1) + 1;
304 bn_data_num = num / BN_DEC_NUM + 1;
305 bn_data = reallocarray(NULL, bn_data_num, sizeof(BN_ULONG));
306 buf = malloc(num + 3);
307 if ((buf == NULL) || (bn_data == NULL)) {
308 BNerror(ERR_R_MALLOC_FAILURE);
309 goto err; 314 goto err;
310 } 315 if (!CBB_init(&cbb, data_len + 3))
311 if ((t = BN_dup(a)) == NULL)
312 goto err; 316 goto err;
313 317
314#define BUF_REMAIN (num+3 - (size_t)(p - buf)) 318 if (BN_is_negative(bn)) {
315 p = buf; 319 if (!CBB_add_u8(&cbb, '-'))
316 lp = bn_data; 320 goto err;
317 if (BN_is_negative(t)) 321 }
318 *p++ = '-';
319 322
320 while (!BN_is_zero(t)) { 323 /* Reverse digits and trim leading zeroes. */
321 if (lp - bn_data >= bn_data_num) 324 CBS_init(&cbs, data, data_len);
325 while (CBS_len(&cbs) > 0) {
326 if (!CBS_get_last_u8(&cbs, &c))
322 goto err; 327 goto err;
323 *lp = BN_div_word(t, BN_DEC_CONV); 328 if (!started && c == '0')
324 if (*lp == (BN_ULONG)-1) 329 continue;
330 if (!CBB_add_u8(&cbb, c))
325 goto err; 331 goto err;
326 lp++; 332 started = 1;
327 }
328 lp--;
329 /* We now have a series of blocks, BN_DEC_NUM chars
330 * in length, where the last one needs truncation.
331 * The blocks need to be reversed in order. */
332 snprintf(p, BUF_REMAIN, BN_DEC_FMT1, *lp);
333 while (*p)
334 p++;
335 while (lp != bn_data) {
336 lp--;
337 snprintf(p, BUF_REMAIN, BN_DEC_FMT2, *lp);
338 while (*p)
339 p++;
340 } 333 }
341 ok = 1;
342 334
343err: 335 if (!started) {
344 free(bn_data); 336 if (!CBB_add_u8(&cbb, '0'))
345 BN_free(t); 337 goto err;
346 if (!ok && buf) {
347 free(buf);
348 buf = NULL;
349 } 338 }
339 if (!CBB_add_u8(&cbb, '\0'))
340 goto err;
341 if (!CBB_finish(&cbb, &s, &s_len))
342 goto err;
350 343
351 return (buf); 344 err:
345 BN_free(tmp);
346 CBB_cleanup(&cbb);
347 freezero(data, data_len);
348
349 return s;
352} 350}
353 351
354int 352int