1/*
2 * Copyright 1995-2017 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 ASN1err(ASN1_F_A2I_ASN1_STRING, 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 ASN1err(ASN1_F_A2I_ASN1_STRING, 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 ASN1err(ASN1_F_A2I_ASN1_STRING,
114 ASN1_R_NON_HEX_CHARACTERS);
115 OPENSSL_free(s);
116 return 0;
117 }
118 s[num + j] <<= 4;
119 s[num + j] |= m;
120 }
121 }
122 num += i;
123 if (again)
124 bufsize = BIO_gets(bp, buf, size);
125 else
126 break;
127 }
128 bs->length = num;
129 bs->data = s;
130 return 1;
131
132 err:
133 ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
134 OPENSSL_free(s);
135 return 0;
136}
137