summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_convert.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/bn/bn_convert.c183
1 files changed, 182 insertions, 1 deletions
diff --git a/src/lib/libcrypto/bn/bn_convert.c b/src/lib/libcrypto/bn/bn_convert.c
index 6fe30fdbb9..5df79fded6 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.4 2023/04/19 11:05:11 jsing Exp $ */ 1/* $OpenBSD: bn_convert.c,v 1.5 2023/04/19 11:12:43 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 *
@@ -59,6 +59,7 @@
59#include <ctype.h> 59#include <ctype.h>
60#include <limits.h> 60#include <limits.h>
61#include <stdio.h> 61#include <stdio.h>
62#include <string.h>
62 63
63#include <openssl/opensslconf.h> 64#include <openssl/opensslconf.h>
64 65
@@ -70,6 +71,186 @@
70 71
71static const char Hex[]="0123456789ABCDEF"; 72static const char Hex[]="0123456789ABCDEF";
72 73
74typedef enum {
75 big,
76 little,
77} endianness_t;
78
79/* ignore negative */
80static int
81bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness)
82{
83 int n;
84 size_t i, lasti, j, atop, mask;
85 BN_ULONG l;
86
87 /*
88 * In case |a| is fixed-top, BN_num_bytes can return bogus length,
89 * but it's assumed that fixed-top inputs ought to be "nominated"
90 * even for padded output, so it works out...
91 */
92 n = BN_num_bytes(a);
93 if (tolen == -1)
94 tolen = n;
95 else if (tolen < n) { /* uncommon/unlike case */
96 BIGNUM temp = *a;
97
98 bn_correct_top(&temp);
99
100 n = BN_num_bytes(&temp);
101 if (tolen < n)
102 return -1;
103 }
104
105 /* Swipe through whole available data and don't give away padded zero. */
106 atop = a->dmax * BN_BYTES;
107 if (atop == 0) {
108 explicit_bzero(to, tolen);
109 return tolen;
110 }
111
112 lasti = atop - 1;
113 atop = a->top * BN_BYTES;
114
115 if (endianness == big)
116 to += tolen; /* start from the end of the buffer */
117
118 for (i = 0, j = 0; j < (size_t)tolen; j++) {
119 unsigned char val;
120
121 l = a->d[i / BN_BYTES];
122 mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
123 val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
124
125 if (endianness == big)
126 *--to = val;
127 else
128 *to++ = val;
129
130 i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
131 }
132
133 return tolen;
134}
135
136int
137BN_bn2bin(const BIGNUM *a, unsigned char *to)
138{
139 return bn2binpad(a, to, -1, big);
140}
141
142int
143BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
144{
145 if (tolen < 0)
146 return -1;
147 return bn2binpad(a, to, tolen, big);
148}
149
150BIGNUM *
151BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
152{
153 unsigned int i, m;
154 unsigned int n;
155 BN_ULONG l;
156 BIGNUM *bn = NULL;
157
158 if (len < 0)
159 return (NULL);
160 if (ret == NULL)
161 ret = bn = BN_new();
162 if (ret == NULL)
163 return (NULL);
164 l = 0;
165 n = len;
166 if (n == 0) {
167 ret->top = 0;
168 return (ret);
169 }
170 i = ((n - 1) / BN_BYTES) + 1;
171 m = ((n - 1) % (BN_BYTES));
172 if (!bn_wexpand(ret, (int)i)) {
173 BN_free(bn);
174 return NULL;
175 }
176 ret->top = i;
177 ret->neg = 0;
178 while (n--) {
179 l = (l << 8L) | *(s++);
180 if (m-- == 0) {
181 ret->d[--i] = l;
182 l = 0;
183 m = BN_BYTES - 1;
184 }
185 }
186 /* need to call this due to clear byte at top if avoiding
187 * having the top bit set (-ve number) */
188 bn_correct_top(ret);
189 return (ret);
190}
191
192int
193BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
194{
195 if (tolen < 0)
196 return -1;
197
198 return bn2binpad(a, to, tolen, little);
199}
200
201BIGNUM *
202BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
203{
204 unsigned int i, m, n;
205 BN_ULONG l;
206 BIGNUM *bn = NULL;
207
208 if (ret == NULL)
209 ret = bn = BN_new();
210 if (ret == NULL)
211 return NULL;
212
213
214 s += len;
215 /* Skip trailing zeroes. */
216 for (; len > 0 && s[-1] == 0; s--, len--)
217 continue;
218
219 n = len;
220 if (n == 0) {
221 ret->top = 0;
222 return ret;
223 }
224
225 i = ((n - 1) / BN_BYTES) + 1;
226 m = (n - 1) % BN_BYTES;
227 if (!bn_wexpand(ret, (int)i)) {
228 BN_free(bn);
229 return NULL;
230 }
231
232 ret->top = i;
233 ret->neg = 0;
234 l = 0;
235 while (n-- > 0) {
236 s--;
237 l = (l << 8L) | *s;
238 if (m-- == 0) {
239 ret->d[--i] = l;
240 l = 0;
241 m = BN_BYTES - 1;
242 }
243 }
244
245 /*
246 * need to call this due to clear byte at top if avoiding having the
247 * top bit set (-ve number)
248 */
249 bn_correct_top(ret);
250
251 return ret;
252}
253
73int 254int
74BN_asc2bn(BIGNUM **bn, const char *a) 255BN_asc2bn(BIGNUM **bn, const char *a)
75{ 256{