bn_print.c revision 306336
1168404Spjd/* crypto/bn/bn_print.c */
2168404Spjd/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3168404Spjd * All rights reserved.
4168404Spjd *
5168404Spjd * This package is an SSL implementation written
6168404Spjd * by Eric Young (eay@cryptsoft.com).
7168404Spjd * The implementation was written so as to conform with Netscapes SSL.
8168404Spjd *
9168404Spjd * This library is free for commercial and non-commercial use as long as
10168404Spjd * the following conditions are aheared to.  The following conditions
11168404Spjd * apply to all code found in this distribution, be it the RC4, RSA,
12168404Spjd * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13168404Spjd * included with this distribution is covered by the same copyright terms
14168404Spjd * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15168404Spjd *
16168404Spjd * Copyright remains Eric Young's, and as such any Copyright notices in
17168404Spjd * the code are not to be removed.
18168404Spjd * If this package is used in a product, Eric Young should be given attribution
19168404Spjd * as the author of the parts of the library used.
20168404Spjd * This can be in the form of a textual message at program startup or
21168404Spjd * in documentation (online or textual) provided with the package.
22219089Spjd *
23226707Spjd * Redistribution and use in source and binary forms, with or without
24226707Spjd * modification, are permitted provided that the following conditions
25168404Spjd * are met:
26168404Spjd * 1. Redistributions of source code must retain the copyright
27168962Spjd *    notice, this list of conditions and the following disclaimer.
28168404Spjd * 2. Redistributions in binary form must reproduce the above copyright
29168404Spjd *    notice, this list of conditions and the following disclaimer in the
30168404Spjd *    documentation and/or other materials provided with the distribution.
31168404Spjd * 3. All advertising materials mentioning features or use of this software
32168404Spjd *    must display the following acknowledgement:
33168404Spjd *    "This product includes cryptographic software written by
34168404Spjd *     Eric Young (eay@cryptsoft.com)"
35168404Spjd *    The word 'cryptographic' can be left out if the rouines from the library
36168404Spjd *    being used are not cryptographic related :-).
37168404Spjd * 4. If you include any Windows specific code (or a derivative thereof) from
38168962Spjd *    the apps directory (application code) you must include an acknowledgement:
39168404Spjd *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40168404Spjd *
41168404Spjd * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44168404Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45209962Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46185029Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47168404Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51168404Spjd * SUCH DAMAGE.
52168404Spjd *
53168404Spjd * The licence and distribution terms for any publically available version or
54168404Spjd * derivative of this code cannot be changed.  i.e. this code cannot simply be
55185029Spjd * copied and put under another distribution licence
56185029Spjd * [including the GNU Public Licence.]
57168962Spjd */
58168962Spjd
59168962Spjd#include <stdio.h>
60168404Spjd#include <ctype.h>
61168404Spjd#include <limits.h>
62168404Spjd#include "cryptlib.h"
63168404Spjd#include <openssl/buffer.h>
64168404Spjd#include "bn_lcl.h"
65168404Spjd
66168404Spjdstatic const char Hex[] = "0123456789ABCDEF";
67185029Spjd
68219089Spjd/* Must 'OPENSSL_free' the returned data */
69168404Spjdchar *BN_bn2hex(const BIGNUM *a)
70219089Spjd{
71185029Spjd    int i, j, v, z = 0;
72168404Spjd    char *buf;
73168404Spjd    char *p;
74168404Spjd
75185029Spjd    if (a->neg && BN_is_zero(a)) {
76219089Spjd        /* "-0" == 3 bytes including NULL terminator */
77219089Spjd        buf = OPENSSL_malloc(3);
78168404Spjd    } else {
79219089Spjd        buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
80168404Spjd    }
81168404Spjd    if (buf == NULL) {
82168404Spjd        BNerr(BN_F_BN_BN2HEX, ERR_R_MALLOC_FAILURE);
83168404Spjd        goto err;
84168404Spjd    }
85168404Spjd    p = buf;
86168404Spjd    if (a->neg)
87185029Spjd        *(p++) = '-';
88168404Spjd    if (BN_is_zero(a))
89209962Smm        *(p++) = '0';
90209962Smm    for (i = a->top - 1; i >= 0; i--) {
91209962Smm        for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
92209962Smm            /* strip leading zeros */
93209962Smm            v = ((int)(a->d[i] >> (long)j)) & 0xff;
94209962Smm            if (z || (v != 0)) {
95168404Spjd                *(p++) = Hex[v >> 4];
96168404Spjd                *(p++) = Hex[v & 0x0f];
97168404Spjd                z = 1;
98209962Smm            }
99185029Spjd        }
100209962Smm    }
101168404Spjd    *p = '\0';
102168404Spjd err:
103209962Smm    return (buf);
104209962Smm}
105209962Smm
106209962Smm/* Must 'OPENSSL_free' the returned data */
107209962Smmchar *BN_bn2dec(const BIGNUM *a)
108209962Smm{
109209962Smm    int i = 0, num, ok = 0;
110209962Smm    char *buf = NULL;
111209962Smm    char *p;
112219089Spjd    BIGNUM *t = NULL;
113219089Spjd    BN_ULONG *bn_data = NULL, *lp;
114219089Spjd    int bn_data_num;
115219089Spjd
116185029Spjd    /*-
117185029Spjd     * get an upper bound for the length of the decimal integer
118219089Spjd     * num <= (BN_num_bits(a) + 1) * log(2)
119219089Spjd     *     <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1     (rounding error)
120219089Spjd     *     <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1
121185029Spjd     */
122168404Spjd    i = BN_num_bits(a) * 3;
123168404Spjd    num = (i / 10 + i / 1000 + 1) + 1;
124168404Spjd    bn_data_num = num / BN_DEC_NUM + 1;
125168404Spjd    bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG));
126168404Spjd    buf = (char *)OPENSSL_malloc(num + 3);
127219089Spjd    if ((buf == NULL) || (bn_data == NULL)) {
128168404Spjd        BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE);
129168404Spjd        goto err;
130168404Spjd    }
131168404Spjd    if ((t = BN_dup(a)) == NULL)
132168404Spjd        goto err;
133168404Spjd
134168404Spjd#define BUF_REMAIN (num+3 - (size_t)(p - buf))
135168404Spjd    p = buf;
136168404Spjd    lp = bn_data;
137168404Spjd    if (BN_is_zero(t)) {
138168404Spjd        *(p++) = '0';
139168404Spjd        *(p++) = '\0';
140168404Spjd    } else {
141168404Spjd        if (BN_is_negative(t))
142168404Spjd            *p++ = '-';
143168404Spjd
144168404Spjd        while (!BN_is_zero(t)) {
145168404Spjd            if (lp - bn_data >= bn_data_num)
146168404Spjd                goto err;
147168404Spjd            *lp = BN_div_word(t, BN_DEC_CONV);
148168404Spjd            if (*lp == (BN_ULONG)-1)
149168404Spjd                goto err;
150168404Spjd            lp++;
151168404Spjd        }
152168404Spjd        lp--;
153168404Spjd        /*
154168404Spjd         * We now have a series of blocks, BN_DEC_NUM chars in length, where
155168404Spjd         * the last one needs truncation. The blocks need to be reversed in
156168404Spjd         * order.
157168404Spjd         */
158185029Spjd        BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT1, *lp);
159185029Spjd        while (*p)
160185029Spjd            p++;
161185029Spjd        while (lp != bn_data) {
162185029Spjd            lp--;
163185029Spjd            BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT2, *lp);
164185029Spjd            while (*p)
165185029Spjd                p++;
166185029Spjd        }
167185029Spjd    }
168185029Spjd    ok = 1;
169185029Spjd err:
170185029Spjd    if (bn_data != NULL)
171185029Spjd        OPENSSL_free(bn_data);
172185029Spjd    if (t != NULL)
173185029Spjd        BN_free(t);
174185029Spjd    if (!ok && buf) {
175185029Spjd        OPENSSL_free(buf);
176185029Spjd        buf = NULL;
177185029Spjd    }
178185029Spjd
179185029Spjd    return (buf);
180185029Spjd}
181185029Spjd
182185029Spjdint BN_hex2bn(BIGNUM **bn, const char *a)
183185029Spjd{
184168404Spjd    BIGNUM *ret = NULL;
185185029Spjd    BN_ULONG l = 0;
186185029Spjd    int neg = 0, h, m, i, j, k, c;
187185029Spjd    int num;
188185029Spjd
189185029Spjd    if ((a == NULL) || (*a == '\0'))
190219089Spjd        return (0);
191185029Spjd
192219089Spjd    if (*a == '-') {
193219089Spjd        neg = 1;
194219089Spjd        a++;
195219089Spjd    }
196219089Spjd
197185029Spjd    for (i = 0; i <= (INT_MAX/4) && isxdigit((unsigned char)a[i]); i++)
198219089Spjd        continue;
199185029Spjd
200185029Spjd    if (i > INT_MAX/4)
201185029Spjd        goto err;
202185029Spjd
203185029Spjd    num = i + neg;
204185029Spjd    if (bn == NULL)
205185029Spjd        return (num);
206185029Spjd
207185029Spjd    /* a is the start of the hex digits, and it is 'i' long */
208185029Spjd    if (*bn == NULL) {
209185029Spjd        if ((ret = BN_new()) == NULL)
210185029Spjd            return (0);
211185029Spjd    } else {
212185029Spjd        ret = *bn;
213185029Spjd        BN_zero(ret);
214185029Spjd    }
215185029Spjd
216185029Spjd    /* i is the number of hex digits */
217185029Spjd    if (bn_expand(ret, i * 4) == NULL)
218185029Spjd        goto err;
219185029Spjd
220185029Spjd    j = i;                      /* least significant 'hex' */
221185029Spjd    m = 0;
222185029Spjd    h = 0;
223185029Spjd    while (j > 0) {
224185029Spjd        m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j;
225185029Spjd        l = 0;
226185029Spjd        for (;;) {
227185029Spjd            c = a[j - m];
228185029Spjd            if ((c >= '0') && (c <= '9'))
229185029Spjd                k = c - '0';
230185029Spjd            else if ((c >= 'a') && (c <= 'f'))
231185029Spjd                k = c - 'a' + 10;
232219089Spjd            else if ((c >= 'A') && (c <= 'F'))
233185029Spjd                k = c - 'A' + 10;
234185029Spjd            else
235219089Spjd                k = 0;          /* paranoia */
236219089Spjd            l = (l << 4) | k;
237219089Spjd
238219089Spjd            if (--m <= 0) {
239219089Spjd                ret->d[h++] = l;
240185029Spjd                break;
241185029Spjd            }
242219089Spjd        }
243185029Spjd        j -= (BN_BYTES * 2);
244185029Spjd    }
245185029Spjd    ret->top = h;
246185029Spjd    bn_correct_top(ret);
247185029Spjd    ret->neg = neg;
248185029Spjd
249185029Spjd    *bn = ret;
250185029Spjd    bn_check_top(ret);
251185029Spjd    return (num);
252185029Spjd err:
253185029Spjd    if (*bn == NULL)
254185029Spjd        BN_free(ret);
255185029Spjd    return (0);
256185029Spjd}
257185029Spjd
258185029Spjdint BN_dec2bn(BIGNUM **bn, const char *a)
259185029Spjd{
260185029Spjd    BIGNUM *ret = NULL;
261185029Spjd    BN_ULONG l = 0;
262185029Spjd    int neg = 0, i, j;
263185029Spjd    int num;
264185029Spjd
265168404Spjd    if ((a == NULL) || (*a == '\0'))
266168404Spjd        return (0);
267168404Spjd    if (*a == '-') {
268168404Spjd        neg = 1;
269168404Spjd        a++;
270185029Spjd    }
271168404Spjd
272168404Spjd    for (i = 0; i <= (INT_MAX/4) && isdigit((unsigned char)a[i]); i++)
273168404Spjd        continue;
274168404Spjd
275168404Spjd    if (i > INT_MAX/4)
276168404Spjd        goto err;
277168404Spjd
278168404Spjd    num = i + neg;
279168404Spjd    if (bn == NULL)
280168404Spjd        return (num);
281185029Spjd
282168404Spjd    /*
283185029Spjd     * a is the start of the digits, and it is 'i' long. We chop it into
284185029Spjd     * BN_DEC_NUM digits at a time
285168404Spjd     */
286168404Spjd    if (*bn == NULL) {
287168404Spjd        if ((ret = BN_new()) == NULL)
288168404Spjd            return (0);
289168404Spjd    } else {
290168404Spjd        ret = *bn;
291219089Spjd        BN_zero(ret);
292168404Spjd    }
293168404Spjd
294168404Spjd    /* i is the number of digits, a bit of an over expand */
295168404Spjd    if (bn_expand(ret, i * 4) == NULL)
296168404Spjd        goto err;
297168404Spjd
298168404Spjd    j = BN_DEC_NUM - (i % BN_DEC_NUM);
299185029Spjd    if (j == BN_DEC_NUM)
300168404Spjd        j = 0;
301168404Spjd    l = 0;
302168404Spjd    while (*a) {
303185029Spjd        l *= 10;
304168404Spjd        l += *a - '0';
305168404Spjd        a++;
306168404Spjd        if (++j == BN_DEC_NUM) {
307168404Spjd            BN_mul_word(ret, BN_DEC_CONV);
308168404Spjd            BN_add_word(ret, l);
309168404Spjd            l = 0;
310168404Spjd            j = 0;
311168404Spjd        }
312168404Spjd    }
313168404Spjd    ret->neg = neg;
314168404Spjd
315168404Spjd    bn_correct_top(ret);
316168404Spjd    *bn = ret;
317168404Spjd    bn_check_top(ret);
318168404Spjd    return (num);
319168404Spjd err:
320168404Spjd    if (*bn == NULL)
321168404Spjd        BN_free(ret);
322168404Spjd    return (0);
323168404Spjd}
324219089Spjd
325219089Spjdint BN_asc2bn(BIGNUM **bn, const char *a)
326219089Spjd{
327219089Spjd    const char *p = a;
328219089Spjd    if (*p == '-')
329219089Spjd        p++;
330219089Spjd
331219089Spjd    if (p[0] == '0' && (p[1] == 'X' || p[1] == 'x')) {
332219089Spjd        if (!BN_hex2bn(bn, p + 2))
333219089Spjd            return 0;
334219089Spjd    } else {
335219089Spjd        if (!BN_dec2bn(bn, p))
336219089Spjd            return 0;
337219089Spjd    }
338219089Spjd    if (*a == '-')
339219089Spjd        (*bn)->neg = 1;
340219089Spjd    return 1;
341219089Spjd}
342219089Spjd
343219089Spjd#ifndef OPENSSL_NO_BIO
344219089Spjd# ifndef OPENSSL_NO_FP_API
345219089Spjdint BN_print_fp(FILE *fp, const BIGNUM *a)
346219089Spjd{
347219089Spjd    BIO *b;
348219089Spjd    int ret;
349219089Spjd
350168404Spjd    if ((b = BIO_new(BIO_s_file())) == NULL)
351185029Spjd        return (0);
352168404Spjd    BIO_set_fp(b, fp, BIO_NOCLOSE);
353168404Spjd    ret = BN_print(b, a);
354168404Spjd    BIO_free(b);
355185029Spjd    return (ret);
356185029Spjd}
357185029Spjd# endif
358185029Spjd
359185029Spjdint BN_print(BIO *bp, const BIGNUM *a)
360185029Spjd{
361185029Spjd    int i, j, v, z = 0;
362185029Spjd    int ret = 0;
363185029Spjd
364219089Spjd    if ((a->neg) && (BIO_write(bp, "-", 1) != 1))
365219089Spjd        goto end;
366219089Spjd    if (BN_is_zero(a) && (BIO_write(bp, "0", 1) != 1))
367219089Spjd        goto end;
368219089Spjd    for (i = a->top - 1; i >= 0; i--) {
369219089Spjd        for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
370219089Spjd            /* strip leading zeros */
371219089Spjd            v = ((int)(a->d[i] >> (long)j)) & 0x0f;
372219089Spjd            if (z || (v != 0)) {
373219089Spjd                if (BIO_write(bp, &(Hex[v]), 1) != 1)
374219089Spjd                    goto end;
375219089Spjd                z = 1;
376219089Spjd            }
377219089Spjd        }
378219089Spjd    }
379219089Spjd    ret = 1;
380219089Spjd end:
381219089Spjd    return (ret);
382219089Spjd}
383219089Spjd#endif
384219089Spjd
385185029Spjdchar *BN_options(void)
386219089Spjd{
387185029Spjd    static int init = 0;
388219089Spjd    static char data[16];
389219089Spjd
390219089Spjd    if (!init) {
391219089Spjd        init++;
392219089Spjd#ifdef BN_LLONG
393219089Spjd        BIO_snprintf(data, sizeof data, "bn(%d,%d)",
394219089Spjd                     (int)sizeof(BN_ULLONG) * 8, (int)sizeof(BN_ULONG) * 8);
395219089Spjd#else
396219089Spjd        BIO_snprintf(data, sizeof data, "bn(%d,%d)",
397219089Spjd                     (int)sizeof(BN_ULONG) * 8, (int)sizeof(BN_ULONG) * 8);
398219089Spjd#endif
399219089Spjd    }
400219089Spjd    return (data);
401219089Spjd}
402219089Spjd