summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2024-11-08 14:18:44 +0000
committerjsing <>2024-11-08 14:18:44 +0000
commit7bfb9335fb0ae857523adc3e3686eeb719aafd2e (patch)
treeb0fb987a81953a29921d5ec19c5d224d718bc994 /src/lib
parent124eef3044ec1877d9304efc8ffd43fa27cc0dab (diff)
downloadopenbsd-7bfb9335fb0ae857523adc3e3686eeb719aafd2e.tar.gz
openbsd-7bfb9335fb0ae857523adc3e3686eeb719aafd2e.tar.bz2
openbsd-7bfb9335fb0ae857523adc3e3686eeb719aafd2e.zip
Rewrite bn2binpad.
Rewrite bn2binpad, removing some OpenSSL specific behaviour and unnecessary complexity. Our BN_num_bytes() does not return bogus lengths, so we don't need to see if things work out with nominated outputs. Swipe away some endianness_t, but continue to ignore negatives and don't dare give away padded zeroes. Implement a more readable constant time conversion. In particular, the little endian is the less common use case, which we can implement by reversing the padded output in place, rather than complicating all of the conversion code. ok beck@ tb@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/bn/bn_convert.c102
1 files changed, 44 insertions, 58 deletions
diff --git a/src/lib/libcrypto/bn/bn_convert.c b/src/lib/libcrypto/bn/bn_convert.c
index d38747e017..6a6354f44e 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.22 2024/06/22 16:33:00 jsing Exp $ */ 1/* $OpenBSD: bn_convert.c,v 1.23 2024/11/08 14:18:44 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 *
@@ -69,87 +69,73 @@
69 69
70#include "bn_local.h" 70#include "bn_local.h"
71#include "bytestring.h" 71#include "bytestring.h"
72#include "crypto_internal.h"
72 73
73static int bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs); 74static int bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs);
74static int bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs); 75static int bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs);
75 76
76static const char hex_digits[] = "0123456789ABCDEF"; 77static const char hex_digits[] = "0123456789ABCDEF";
77 78
78typedef enum {
79 big,
80 little,
81} endianness_t;
82
83/* ignore negative */
84static int 79static int
85bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness) 80bn_bn2binpad_internal(const BIGNUM *bn, uint8_t *out, int out_len,
81 int little_endian)
86{ 82{
87 int n; 83 uint8_t mask, v;
88 size_t i, lasti, j, atop, mask; 84 BN_ULONG w;
89 BN_ULONG l; 85 int i, j;
90 86 int b, n;
91 /*
92 * In case |a| is fixed-top, BN_num_bytes can return bogus length,
93 * but it's assumed that fixed-top inputs ought to be "nominated"
94 * even for padded output, so it works out...
95 */
96 n = BN_num_bytes(a);
97 if (tolen == -1)
98 tolen = n;
99 else if (tolen < n) { /* uncommon/unlike case */
100 BIGNUM temp = *a;
101 87
102 bn_correct_top(&temp); 88 n = BN_num_bytes(bn);
103 89
104 n = BN_num_bytes(&temp); 90 if (out_len == -1)
105 if (tolen < n) 91 out_len = n;
106 return -1; 92 if (out_len < n)
107 } 93 return -1;
108 94
109 /* Swipe through whole available data and don't give away padded zero. */ 95 if (bn->dmax == 0) {
110 atop = a->dmax * BN_BYTES; 96 explicit_bzero(out, out_len);
111 if (atop == 0) { 97 return out_len;
112 explicit_bzero(to, tolen);
113 return tolen;
114 } 98 }
115 99
116 lasti = atop - 1; 100 mask = 0;
117 atop = a->top * BN_BYTES; 101 b = BN_BITS2;
118 102 j = 0;
119 if (endianness == big)
120 to += tolen; /* start from the end of the buffer */
121 103
122 for (i = 0, j = 0; j < (size_t)tolen; j++) { 104 for (i = out_len - 1; i >= 0; i--) {
123 unsigned char val; 105 if (b == BN_BITS2) {
124 106 mask = crypto_ct_lt_mask(j, bn->top);
125 l = a->d[i / BN_BYTES]; 107 w = bn->d[j++ % bn->dmax];
126 mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1)); 108 b = 0;
127 val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask); 109 }
128 110 out[i] = (w >> b) & mask;
129 if (endianness == big) 111 b += 8;
130 *--to = val; 112 }
131 else
132 *to++ = val;
133 113
134 i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */ 114 if (little_endian) {
115 for (i = 0, j = out_len - 1; i < out_len / 2; i++, j--) {
116 v = out[i];
117 out[i] = out[j];
118 out[j] = v;
119 }
135 } 120 }
136 121
137 return tolen; 122 return out_len;
138} 123}
139 124
140int 125int
141BN_bn2bin(const BIGNUM *a, unsigned char *to) 126BN_bn2bin(const BIGNUM *bn, unsigned char *to)
142{ 127{
143 return bn2binpad(a, to, -1, big); 128 return bn_bn2binpad_internal(bn, to, -1, 0);
144} 129}
145LCRYPTO_ALIAS(BN_bn2bin); 130LCRYPTO_ALIAS(BN_bn2bin);
146 131
147int 132int
148BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) 133BN_bn2binpad(const BIGNUM *bn, unsigned char *to, int to_len)
149{ 134{
150 if (tolen < 0) 135 if (to_len < 0)
151 return -1; 136 return -1;
152 return bn2binpad(a, to, tolen, big); 137
138 return bn_bn2binpad_internal(bn, to, to_len, 0);
153} 139}
154LCRYPTO_ALIAS(BN_bn2binpad); 140LCRYPTO_ALIAS(BN_bn2binpad);
155 141
@@ -225,12 +211,12 @@ BN_bin2bn(const unsigned char *d, int len, BIGNUM *bn)
225LCRYPTO_ALIAS(BN_bin2bn); 211LCRYPTO_ALIAS(BN_bin2bn);
226 212
227int 213int
228BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen) 214BN_bn2lebinpad(const BIGNUM *bn, unsigned char *to, int to_len)
229{ 215{
230 if (tolen < 0) 216 if (to_len < 0)
231 return -1; 217 return -1;
232 218
233 return bn2binpad(a, to, tolen, little); 219 return bn_bn2binpad_internal(bn, to, to_len, 1);
234} 220}
235LCRYPTO_ALIAS(BN_bn2lebinpad); 221LCRYPTO_ALIAS(BN_bn2lebinpad);
236 222