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