diff options
author | jsing <> | 2023-05-09 05:12:49 +0000 |
---|---|---|
committer | jsing <> | 2023-05-09 05:12:49 +0000 |
commit | 0397bb0dc2794656636489f8fb435e461785f245 (patch) | |
tree | 87467e361b40b5d3ce452f90b0b48bdf34d552cc /src/lib | |
parent | 3d8c174bc6a25e6d0edc3db05de93421dbf040a6 (diff) | |
download | openbsd-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.c | 124 |
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 | ||
72 | static const char hex_digits[] = "0123456789ABCDEF"; | 73 | static 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 */ | ||
274 | char * | 274 | char * |
275 | BN_bn2dec(const BIGNUM *a) | 275 | BN_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 | ||
343 | err: | 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 | ||
354 | int | 352 | int |