155714Skris/* crypto/asn1/f_string.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296341Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296341Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296341Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296341Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296341Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include "cryptlib.h"
6155714Skris#include <openssl/buffer.h>
6255714Skris#include <openssl/asn1.h>
6355714Skris
6455714Skrisint i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
65296341Sdelphij{
66296341Sdelphij    int i, n = 0;
67296341Sdelphij    static const char *h = "0123456789ABCDEF";
68296341Sdelphij    char buf[2];
6955714Skris
70296341Sdelphij    if (a == NULL)
71296341Sdelphij        return (0);
7255714Skris
73296341Sdelphij    if (a->length == 0) {
74296341Sdelphij        if (BIO_write(bp, "0", 1) != 1)
75296341Sdelphij            goto err;
76296341Sdelphij        n = 1;
77296341Sdelphij    } else {
78296341Sdelphij        for (i = 0; i < a->length; i++) {
79296341Sdelphij            if ((i != 0) && (i % 35 == 0)) {
80296341Sdelphij                if (BIO_write(bp, "\\\n", 2) != 2)
81296341Sdelphij                    goto err;
82296341Sdelphij                n += 2;
83296341Sdelphij            }
84296341Sdelphij            buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
85296341Sdelphij            buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
86296341Sdelphij            if (BIO_write(bp, buf, 2) != 2)
87296341Sdelphij                goto err;
88296341Sdelphij            n += 2;
89296341Sdelphij        }
90296341Sdelphij    }
91296341Sdelphij    return (n);
92296341Sdelphij err:
93296341Sdelphij    return (-1);
94296341Sdelphij}
9555714Skris
9655714Skrisint a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
97296341Sdelphij{
98296341Sdelphij    int ret = 0;
99296341Sdelphij    int i, j, k, m, n, again, bufsize;
100296341Sdelphij    unsigned char *s = NULL, *sp;
101296341Sdelphij    unsigned char *bufp;
102296341Sdelphij    int num = 0, slen = 0, first = 1;
10355714Skris
104296341Sdelphij    bufsize = BIO_gets(bp, buf, size);
105296341Sdelphij    for (;;) {
106296341Sdelphij        if (bufsize < 1) {
107296341Sdelphij            if (first)
108296341Sdelphij                break;
109296341Sdelphij            else
110296341Sdelphij                goto err_sl;
111296341Sdelphij        }
112296341Sdelphij        first = 0;
11355714Skris
114296341Sdelphij        i = bufsize;
115296341Sdelphij        if (buf[i - 1] == '\n')
116296341Sdelphij            buf[--i] = '\0';
117296341Sdelphij        if (i == 0)
118296341Sdelphij            goto err_sl;
119296341Sdelphij        if (buf[i - 1] == '\r')
120296341Sdelphij            buf[--i] = '\0';
121296341Sdelphij        if (i == 0)
122296341Sdelphij            goto err_sl;
123296341Sdelphij        again = (buf[i - 1] == '\\');
12455714Skris
125296341Sdelphij        for (j = i - 1; j > 0; j--) {
12655714Skris#ifndef CHARSET_EBCDIC
127296341Sdelphij            if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
128296341Sdelphij                  ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
129296341Sdelphij                  ((buf[j] >= 'A') && (buf[j] <= 'F'))))
13055714Skris#else
131296341Sdelphij            /*
132296341Sdelphij             * This #ifdef is not strictly necessary, since the characters
133296341Sdelphij             * A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but
134296341Sdelphij             * not the whole alphabet). Nevertheless, isxdigit() is faster.
135296341Sdelphij             */
136296341Sdelphij            if (!isxdigit(buf[j]))
13755714Skris#endif
138296341Sdelphij            {
139296341Sdelphij                i = j;
140296341Sdelphij                break;
141296341Sdelphij            }
142296341Sdelphij        }
143296341Sdelphij        buf[i] = '\0';
144296341Sdelphij        /*
145296341Sdelphij         * We have now cleared all the crap off the end of the line
146296341Sdelphij         */
147296341Sdelphij        if (i < 2)
148296341Sdelphij            goto err_sl;
14955714Skris
150296341Sdelphij        bufp = (unsigned char *)buf;
15155714Skris
152296341Sdelphij        k = 0;
153296341Sdelphij        i -= again;
154296341Sdelphij        if (i % 2 != 0) {
155296341Sdelphij            ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS);
156296341Sdelphij            goto err;
157296341Sdelphij        }
158296341Sdelphij        i /= 2;
159296341Sdelphij        if (num + i > slen) {
160296341Sdelphij            if (s == NULL)
161296341Sdelphij                sp = (unsigned char *)OPENSSL_malloc((unsigned int)num +
162296341Sdelphij                                                     i * 2);
163296341Sdelphij            else
164296341Sdelphij                sp = (unsigned char *)OPENSSL_realloc(s,
165296341Sdelphij                                                      (unsigned int)num +
166296341Sdelphij                                                      i * 2);
167296341Sdelphij            if (sp == NULL) {
168296341Sdelphij                ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE);
169296341Sdelphij                if (s != NULL)
170296341Sdelphij                    OPENSSL_free(s);
171296341Sdelphij                goto err;
172296341Sdelphij            }
173296341Sdelphij            s = sp;
174296341Sdelphij            slen = num + i * 2;
175296341Sdelphij        }
176296341Sdelphij        for (j = 0; j < i; j++, k += 2) {
177296341Sdelphij            for (n = 0; n < 2; n++) {
178296341Sdelphij                m = bufp[k + n];
179296341Sdelphij                if ((m >= '0') && (m <= '9'))
180296341Sdelphij                    m -= '0';
181296341Sdelphij                else if ((m >= 'a') && (m <= 'f'))
182296341Sdelphij                    m = m - 'a' + 10;
183296341Sdelphij                else if ((m >= 'A') && (m <= 'F'))
184296341Sdelphij                    m = m - 'A' + 10;
185296341Sdelphij                else {
186296341Sdelphij                    ASN1err(ASN1_F_A2I_ASN1_STRING,
187296341Sdelphij                            ASN1_R_NON_HEX_CHARACTERS);
188296341Sdelphij                    goto err;
189296341Sdelphij                }
190296341Sdelphij                s[num + j] <<= 4;
191296341Sdelphij                s[num + j] |= m;
192296341Sdelphij            }
193296341Sdelphij        }
194296341Sdelphij        num += i;
195296341Sdelphij        if (again)
196296341Sdelphij            bufsize = BIO_gets(bp, buf, size);
197296341Sdelphij        else
198296341Sdelphij            break;
199296341Sdelphij    }
200296341Sdelphij    bs->length = num;
201296341Sdelphij    bs->data = s;
202296341Sdelphij    ret = 1;
203296341Sdelphij err:
204296341Sdelphij    if (0) {
205296341Sdelphij err_sl:
206296341Sdelphij        ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
207296341Sdelphij    }
208296341Sdelphij    return (ret);
209296341Sdelphij}
210