/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- BN_new
- BN_free
- BN_clear
- BN_clear_free
- BN_dup
- BN_num_bits
- BN_num_bytes
- BN_bin2bn
- BN_bn2bin
- BN_hex2bn
- BN_bn2hex
- BN_cmp
- BN_set_negative
- BN_is_negative
- BN_is_bit_set
- BN_set_bit
- BN_clear_bit
- BN_set_word
- BN_get_word
- BN_rand
- BN_uadd
- BN_GENCB_set
- BN_GENCB_call
1 /*
2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 RCSID("$Id$");
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <limits.h>
44
45 #include <krb5-types.h>
46 #include <rfc2459_asn1.h> /* XXX */
47 #include <der.h>
48
49 #include <bn.h>
50 #include <rand.h>
51 #include <hex.h>
52
53 BIGNUM *
54 BN_new(void)
/* [<][>][^][v][top][bottom][index][help] */
55 {
56 heim_integer *hi;
57 hi = calloc(1, sizeof(*hi));
58 return (BIGNUM *)hi;
59 }
60
61 void
62 BN_free(BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
63 {
64 BN_clear(bn);
65 free(bn);
66 }
67
68 void
69 BN_clear(BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
70 {
71 heim_integer *hi = (heim_integer *)bn;
72 if (hi->data) {
73 memset(hi->data, 0, hi->length);
74 free(hi->data);
75 }
76 memset(hi, 0, sizeof(*hi));
77 }
78
79 void
80 BN_clear_free(BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
81 {
82 BN_free(bn);
83 }
84
85 BIGNUM *
86 BN_dup(const BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
87 {
88 BIGNUM *b = BN_new();
89 if (der_copy_heim_integer((const heim_integer *)bn, (heim_integer *)b)) {
90 BN_free(b);
91 return NULL;
92 }
93 return b;
94 }
95
96 /*
97 * If the caller really want to know the number of bits used, subtract
98 * one from the length, multiply by 8, and then lookup in the table
99 * how many bits the hightest byte uses.
100 */
101 int
102 BN_num_bits(const BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
103 {
104 static unsigned char num2bits[256] = {
105 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
106 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
107 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
108 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
109 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
110 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
111 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
112 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
113 };
114 const heim_integer *i = (const void *)bn;
115 if (i->length == 0)
116 return 0;
117 return (i->length - 1) * 8 + num2bits[((unsigned char *)i->data)[0]];
118 }
119
120 int
121 BN_num_bytes(const BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
122 {
123 return ((const heim_integer *)bn)->length;
124 }
125
126 /*
127 * Ignore negative flag.
128 */
129
130 BIGNUM *
131 BN_bin2bn(const void *s, int len, BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
132 {
133 heim_integer *hi = (void *)bn;
134
135 if (len < 0)
136 return NULL;
137
138 if (hi == NULL) {
139 hi = (heim_integer *)BN_new();
140 if (hi == NULL)
141 return NULL;
142 }
143 if (hi->data)
144 BN_clear((BIGNUM *)hi);
145 hi->negative = 0;
146 hi->data = malloc(len);
147 if (hi->data == NULL && len != 0) {
148 if (bn == NULL)
149 BN_free((BIGNUM *)hi);
150 return NULL;
151 }
152 hi->length = len;
153 memcpy(hi->data, s, len);
154 return (BIGNUM *)hi;
155 }
156
157 int
158 BN_bn2bin(const BIGNUM *bn, void *to)
/* [<][>][^][v][top][bottom][index][help] */
159 {
160 const heim_integer *hi = (const void *)bn;
161 memcpy(to, hi->data, hi->length);
162 return hi->length;
163 }
164
165 int
166 BN_hex2bn(BIGNUM **bnp, const char *in)
/* [<][>][^][v][top][bottom][index][help] */
167 {
168 int negative;
169 ssize_t ret;
170 size_t len;
171 void *data;
172
173 len = strlen(in);
174 data = malloc(len);
175 if (data == NULL)
176 return 0;
177
178 if (*in == '-') {
179 negative = 1;
180 in++;
181 } else
182 negative = 0;
183
184 ret = hex_decode(in, data, len);
185 if (ret < 0) {
186 free(data);
187 return 0;
188 }
189
190 *bnp = BN_bin2bn(data, ret, NULL);
191 free(data);
192 if (*bnp == NULL)
193 return 0;
194 BN_set_negative(*bnp, negative);
195 return 1;
196 }
197
198 char *
199 BN_bn2hex(const BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
200 {
201 ssize_t ret;
202 size_t len;
203 void *data;
204 char *str;
205
206 len = BN_num_bytes(bn);
207 data = malloc(len);
208 if (data == NULL)
209 return 0;
210
211 len = BN_bn2bin(bn, data);
212
213 ret = hex_encode(data, len, &str);
214 free(data);
215 if (ret < 0)
216 return 0;
217
218 return str;
219 }
220
221 int
222 BN_cmp(const BIGNUM *bn1, const BIGNUM *bn2)
/* [<][>][^][v][top][bottom][index][help] */
223 {
224 return der_heim_integer_cmp((const heim_integer *)bn1,
225 (const heim_integer *)bn2);
226 }
227
228 void
229 BN_set_negative(BIGNUM *bn, int flag)
/* [<][>][^][v][top][bottom][index][help] */
230 {
231 ((heim_integer *)bn)->negative = (flag ? 1 : 0);
232 }
233
234 int
235 BN_is_negative(const BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
236 {
237 return ((const heim_integer *)bn)->negative ? 1 : 0;
238 }
239
240 static const unsigned char is_set[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
241
242 int
243 BN_is_bit_set(const BIGNUM *bn, int bit)
/* [<][>][^][v][top][bottom][index][help] */
244 {
245 heim_integer *hi = (heim_integer *)bn;
246 unsigned char *p = hi->data;
247
248 if ((bit / 8) > hi->length || hi->length == 0)
249 return 0;
250
251 return p[hi->length - 1 - (bit / 8)] & is_set[bit % 8];
252 }
253
254 int
255 BN_set_bit(BIGNUM *bn, int bit)
/* [<][>][^][v][top][bottom][index][help] */
256 {
257 heim_integer *hi = (heim_integer *)bn;
258 unsigned char *p;
259
260 if ((bit / 8) > hi->length || hi->length == 0) {
261 size_t len = (bit + 7) / 8;
262 void *d = realloc(hi->data, len);
263 if (d == NULL)
264 return 0;
265 hi->data = d;
266 p = hi->data;
267 memset(&p[hi->length], 0, len);
268 hi->length = len;
269 } else
270 p = hi->data;
271
272 p[hi->length - 1 - (bit / 8)] |= is_set[bit % 8];
273 return 1;
274 }
275
276 int
277 BN_clear_bit(BIGNUM *bn, int bit)
/* [<][>][^][v][top][bottom][index][help] */
278 {
279 heim_integer *hi = (heim_integer *)bn;
280 unsigned char *p = hi->data;
281
282 if ((bit / 8) > hi->length || hi->length == 0)
283 return 0;
284
285 p[hi->length - 1 - (bit / 8)] &= (unsigned char)(~(is_set[bit % 8]));
286
287 return 1;
288 }
289
290 int
291 BN_set_word(BIGNUM *bn, unsigned long num)
/* [<][>][^][v][top][bottom][index][help] */
292 {
293 unsigned char p[sizeof(num)];
294 unsigned long num2;
295 int i, len;
296
297 for (num2 = num, i = 0; num2 > 0; i++)
298 num2 = num2 >> 8;
299
300 len = i;
301 for (; i > 0; i--) {
302 p[i - 1] = (num & 0xff);
303 num = num >> 8;
304 }
305
306 bn = BN_bin2bn(p, len, bn);
307 return bn != NULL;
308 }
309
310 unsigned long
311 BN_get_word(const BIGNUM *bn)
/* [<][>][^][v][top][bottom][index][help] */
312 {
313 heim_integer *hi = (heim_integer *)bn;
314 unsigned long num = 0;
315 int i;
316
317 if (hi->negative || hi->length > sizeof(num))
318 return ULONG_MAX;
319
320 for (i = 0; i < hi->length; i++)
321 num = ((unsigned char *)hi->data)[i] | (num << 8);
322 return num;
323 }
324
325 int
326 BN_rand(BIGNUM *bn, int bits, int top, int bottom)
/* [<][>][^][v][top][bottom][index][help] */
327 {
328 size_t len = (bits + 7) / 8;
329 heim_integer *i = (heim_integer *)bn;
330
331 BN_clear(bn);
332
333 i->negative = 0;
334 i->data = malloc(len);
335 if (i->data == NULL && len != 0)
336 return 0;
337 i->length = len;
338
339 if (RAND_bytes(i->data, i->length) != 1) {
340 free(i->data);
341 i->data = NULL;
342 return 0;
343 }
344
345 {
346 size_t j = len * 8;
347 while(j > bits) {
348 BN_clear_bit(bn, j - 1);
349 j--;
350 }
351 }
352
353 if (top == -1) {
354 ;
355 } else if (top == 0 && bits > 0) {
356 BN_set_bit(bn, bits - 1);
357 } else if (top == 1 && bits > 1) {
358 BN_set_bit(bn, bits - 1);
359 BN_set_bit(bn, bits - 2);
360 } else {
361 BN_clear(bn);
362 return 0;
363 }
364
365 if (bottom && bits > 0)
366 BN_set_bit(bn, 0);
367
368 return 1;
369 }
370
371 /*
372 *
373 */
374
375 int
376 BN_uadd(BIGNUM *res, const BIGNUM *a, const BIGNUM *b)
/* [<][>][^][v][top][bottom][index][help] */
377 {
378 const heim_integer *ai = (const heim_integer *)a;
379 const heim_integer *bi = (const heim_integer *)b;
380 const unsigned char *ap, *bp;
381 unsigned char *cp;
382 heim_integer ci;
383 int carry = 0;
384 ssize_t len;
385
386 if (ai->negative && bi->negative)
387 return 0;
388 if (ai->length < bi->length) {
389 const heim_integer *si = bi;
390 bi = ai; ai = si;
391 }
392
393 ci.negative = 0;
394 ci.length = ai->length + 1;
395 ci.data = malloc(ci.length);
396 if (ci.data == NULL)
397 return 0;
398
399 ap = &((const unsigned char *)ai->data)[ai->length - 1];
400 bp = &((const unsigned char *)bi->data)[bi->length - 1];
401 cp = &((unsigned char *)ci.data)[ci.length - 1];
402
403 for (len = bi->length; len > 0; len--) {
404 carry = *ap + *bp + carry;
405 *cp = carry & 0xff;
406 carry = (carry & ~0xff) ? 1 : 0;
407 ap--; bp--; cp--;
408 }
409 for (len = ai->length - bi->length; len > 0; len--) {
410 carry = *ap + carry;
411 *cp = carry & 0xff;
412 carry = (carry & ~0xff) ? 1 : 0;
413 ap--; cp--;
414 }
415 if (!carry)
416 memmove(cp, cp + 1, --ci.length);
417 else
418 *cp = carry;
419
420 BN_clear(res);
421 *((heim_integer *)res) = ci;
422
423 return 1;
424 }
425
426
427 /*
428 * Callback when doing slow generation of numbers, like primes.
429 */
430
431 void
432 BN_GENCB_set(BN_GENCB *gencb, int (*cb_2)(int, int, BN_GENCB *), void *ctx)
/* [<][>][^][v][top][bottom][index][help] */
433 {
434 gencb->ver = 2;
435 gencb->cb.cb_2 = cb_2;
436 gencb->arg = ctx;
437 }
438
439 int
440 BN_GENCB_call(BN_GENCB *cb, int a, int b)
/* [<][>][^][v][top][bottom][index][help] */
441 {
442 if (cb == NULL || cb->cb.cb_2 == NULL)
443 return 1;
444 return cb->cb.cb_2(a, b, cb);
445 }