xref: /openssl/crypto/asn1/f_string.c (revision 7ed6de99)
1 /*
2  * Copyright 1995-2024 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 
i2a_ASN1_STRING(BIO * bp,const ASN1_STRING * a,int type)16 int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type)
17 {
18     int i, n = 0;
19     char buf[2];
20 
21     if (a == NULL)
22         return 0;
23 
24     if (a->length == 0) {
25         if (BIO_write(bp, "0", 1) != 1)
26             goto err;
27         n = 1;
28     } else {
29         for (i = 0; i < a->length; i++) {
30             if ((i != 0) && (i % 35 == 0)) {
31                 if (BIO_write(bp, "\\\n", 2) != 2)
32                     goto err;
33                 n += 2;
34             }
35             ossl_to_hex(buf, a->data[i]);
36             if (BIO_write(bp, buf, 2) != 2)
37                 goto err;
38             n += 2;
39         }
40     }
41     return n;
42  err:
43     return -1;
44 }
45 
a2i_ASN1_STRING(BIO * bp,ASN1_STRING * bs,char * buf,int size)46 int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
47 {
48     int i, j, k, m, n, again, bufsize;
49     unsigned char *s = NULL, *sp;
50     unsigned char *bufp;
51     int num = 0, slen = 0, first = 1;
52 
53     bufsize = BIO_gets(bp, buf, size);
54     for (;;) {
55         if (bufsize < 1) {
56             if (first)
57                 break;
58             else
59                 goto err;
60         }
61         first = 0;
62 
63         i = bufsize;
64         if (buf[i - 1] == '\n')
65             buf[--i] = '\0';
66         if (i == 0)
67             goto err;
68         if (buf[i - 1] == '\r')
69             buf[--i] = '\0';
70         if (i == 0)
71             goto err;
72         again = (buf[i - 1] == '\\');
73 
74         for (j = i - 1; j > 0; j--) {
75             if (!ossl_isxdigit(buf[j])) {
76                 i = j;
77                 break;
78             }
79         }
80         buf[i] = '\0';
81         /*
82          * We have now cleared all the crap off the end of the line
83          */
84         if (i < 2)
85             goto err;
86 
87         bufp = (unsigned char *)buf;
88 
89         k = 0;
90         i -= again;
91         if (i % 2 != 0) {
92             ERR_raise(ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
93             OPENSSL_free(s);
94             return 0;
95         }
96         i /= 2;
97         if (num + i > slen) {
98             sp = OPENSSL_realloc(s, (unsigned int)num + i * 2);
99             if (sp == NULL) {
100                 OPENSSL_free(s);
101                 return 0;
102             }
103             s = sp;
104             slen = num + i * 2;
105         }
106         for (j = 0; j < i; j++, k += 2) {
107             for (n = 0; n < 2; n++) {
108                 m = OPENSSL_hexchar2int(bufp[k + n]);
109                 if (m < 0) {
110                     ERR_raise(ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS);
111                     OPENSSL_free(s);
112                     return 0;
113                 }
114                 s[num + j] <<= 4;
115                 s[num + j] |= m;
116             }
117         }
118         num += i;
119         if (again)
120             bufsize = BIO_gets(bp, buf, size);
121         else
122             break;
123     }
124     bs->length = num;
125     bs->data = s;
126     return 1;
127 
128  err:
129     ERR_raise(ERR_LIB_ASN1, ASN1_R_SHORT_LINE);
130     OPENSSL_free(s);
131     return 0;
132 }
133