diff options
author | jsing <> | 2024-11-08 14:18:44 +0000 |
---|---|---|
committer | jsing <> | 2024-11-08 14:18:44 +0000 |
commit | 7bfb9335fb0ae857523adc3e3686eeb719aafd2e (patch) | |
tree | b0fb987a81953a29921d5ec19c5d224d718bc994 /src/lib | |
parent | 124eef3044ec1877d9304efc8ffd43fa27cc0dab (diff) | |
download | openbsd-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.c | 102 |
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 | ||
73 | static int bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs); | 74 | static int bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs); |
74 | static int bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs); | 75 | static int bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs); |
75 | 76 | ||
76 | static const char hex_digits[] = "0123456789ABCDEF"; | 77 | static const char hex_digits[] = "0123456789ABCDEF"; |
77 | 78 | ||
78 | typedef enum { | ||
79 | big, | ||
80 | little, | ||
81 | } endianness_t; | ||
82 | |||
83 | /* ignore negative */ | ||
84 | static int | 79 | static int |
85 | bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness) | 80 | bn_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 | ||
140 | int | 125 | int |
141 | BN_bn2bin(const BIGNUM *a, unsigned char *to) | 126 | BN_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 | } |
145 | LCRYPTO_ALIAS(BN_bn2bin); | 130 | LCRYPTO_ALIAS(BN_bn2bin); |
146 | 131 | ||
147 | int | 132 | int |
148 | BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) | 133 | BN_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 | } |
154 | LCRYPTO_ALIAS(BN_bn2binpad); | 140 | LCRYPTO_ALIAS(BN_bn2binpad); |
155 | 141 | ||
@@ -225,12 +211,12 @@ BN_bin2bn(const unsigned char *d, int len, BIGNUM *bn) | |||
225 | LCRYPTO_ALIAS(BN_bin2bn); | 211 | LCRYPTO_ALIAS(BN_bin2bn); |
226 | 212 | ||
227 | int | 213 | int |
228 | BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen) | 214 | BN_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 | } |
235 | LCRYPTO_ALIAS(BN_bn2lebinpad); | 221 | LCRYPTO_ALIAS(BN_bn2lebinpad); |
236 | 222 | ||