1/*
2 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <stdio.h>
11#include "crypto/ctype.h"
12#include "internal/cryptlib.h"
13#include <openssl/buffer.h>
14#include <openssl/asn1.h>
15
16int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type)
17{
18    int i, n = 0;
19    static const char *h = "0123456789ABCDEF";
20    char buf[2];
21
22    if (a == NULL)
23        return 0;
24
25    if (a->length == 0) {
26        if (BIO_write(bp, "0", 1) != 1)
27            goto err;
28        n = 1;
29    } else {
30        for (i = 0; i < a->length; i++) {
31            if ((i != 0) && (i % 35 == 0)) {
32                if (BIO_write(bp, "\\\n", 2) != 2)
33                    goto err;
34                n += 2;
35            }
36            buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
37            buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
38            if (BIO_write(bp, buf, 2) != 2)
39                goto err;
40            n += 2;
41        }
42    }
43    return n;
44 err:
45    return -1;
46}
47
48int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
49{
50    int i, j, k, m, n, again, bufsize;
51    unsigned char *s = NULL, *sp;
52    unsigned char *bufp;
53    int num = 0, slen = 0, first = 1;
54
55    bufsize = BIO_gets(bp, buf, size);
56    for (;;) {
57        if (bufsize < 1) {
58            if (first)
59                break;
60            else
61                goto err;
62        }
63        first = 0;
64
65        i = bufsize;
66        if (buf[i - 1] == '\n')
67            buf[--i] = '\0';
68        if (i == 0)
69            goto err;
70        if (buf[i - 1] == '\r')
71            buf[--i] = '\0';
72        if (i == 0)
73            goto err;
74        again = (buf[i - 1] == '\\');
75
76        for (j = i - 1; j > 0; j--) {
77            if (!ossl_isxdigit(buf[j])) {
78                i = j;
79                break;
80            }
81        }
82        buf[i] = '\0';
83        /*
84         * We have now cleared all the crap off the end of the line
85         */
86        if (i < 2)
87            goto err;
88
89        bufp = (unsigned char *)buf;
90
91        k = 0;
92        i -= again;
93        if (i % 2 != 0) {
94            ERR_raise(ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
95            OPENSSL_free(s);
96            return 0;
97        }
98        i /= 2;
99        if (num + i > slen) {
100            sp = OPENSSL_realloc(s, (unsigned int)num + i * 2);
101            if (sp == NULL) {
102                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
103                OPENSSL_free(s);
104                return 0;
105            }
106            s = sp;
107            slen = num + i * 2;
108        }
109        for (j = 0; j < i; j++, k += 2) {
110            for (n = 0; n < 2; n++) {
111                m = OPENSSL_hexchar2int(bufp[k + n]);
112                if (m < 0) {
113                    ERR_raise(ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS);
114                    OPENSSL_free(s);
115                    return 0;
116                }
117                s[num + j] <<= 4;
118                s[num + j] |= m;
119            }
120        }
121        num += i;
122        if (again)
123            bufsize = BIO_gets(bp, buf, size);
124        else
125            break;
126    }
127    bs->length = num;
128    bs->data = s;
129    return 1;
130
131 err:
132    ERR_raise(ERR_LIB_ASN1, ASN1_R_SHORT_LINE);
133    OPENSSL_free(s);
134    return 0;
135}
136