We now build libssh2 in Xcode and it's a much better UB/10.4 citizen
[printdrop.git] / Vendor / libssh2 / Source / pem.c
1 /* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
2 * Author: Simon Josefsson
3 *
4 * Redistribution and use in source and binary forms,
5 * with or without modification, are permitted provided
6 * that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 *
17 * Neither the name of the copyright holder nor the names
18 * of any other contributors may be used to endorse or
19 * promote products derived from this software without
20 * specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 * OF SUCH DAMAGE.
36 */
37
38 #include "libssh2_priv.h"
39
40 static int
41 readline(char *line, int line_size, FILE * fp)
42 {
43 if (!fgets(line, line_size, fp)) {
44 return -1;
45 }
46 if (*line && line[strlen(line) - 1] == '\n') {
47 line[strlen(line) - 1] = '\0';
48 }
49 if (*line && line[strlen(line) - 1] == '\r') {
50 line[strlen(line) - 1] = '\0';
51 }
52 return 0;
53 }
54
55 #define LINE_SIZE 128
56
57 int
58 _libssh2_pem_parse(LIBSSH2_SESSION * session,
59 const char *headerbegin,
60 const char *headerend,
61 FILE * fp, char **data, unsigned int *datalen)
62 {
63 char line[LINE_SIZE];
64 char *b64data = NULL;
65 unsigned int b64datalen = 0;
66 int ret;
67
68 do {
69 if (readline(line, LINE_SIZE, fp)) {
70 return -1;
71 }
72 }
73 while (strcmp(line, headerbegin) != 0);
74
75 *line = '\0';
76
77 do {
78 if (*line) {
79 char *tmp;
80 size_t linelen;
81
82 linelen = strlen(line);
83 tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
84 if (!tmp) {
85 ret = -1;
86 goto out;
87 }
88 memcpy(tmp + b64datalen, line, linelen);
89 b64data = tmp;
90 b64datalen += linelen;
91 }
92
93 if (readline(line, LINE_SIZE, fp)) {
94 ret = -1;
95 goto out;
96 }
97 } while (strcmp(line, headerend) != 0);
98
99 if (libssh2_base64_decode(session, data, datalen, b64data, b64datalen)) {
100 ret = -1;
101 goto out;
102 }
103
104 ret = 0;
105 out:
106 if (b64data) {
107 LIBSSH2_FREE(session, b64data);
108 }
109 return ret;
110 }
111
112 static int
113 read_asn1_length(const unsigned char *data,
114 unsigned int datalen, unsigned int *len)
115 {
116 unsigned int lenlen;
117 int nextpos;
118
119 if (datalen < 1) {
120 return -1;
121 }
122 *len = data[0];
123
124 if (*len >= 0x80) {
125 lenlen = *len & 0x7F;
126 *len = data[1];
127 if (1 + lenlen > datalen) {
128 return -1;
129 }
130 if (lenlen > 1) {
131 *len <<= 8;
132 *len |= data[2];
133 }
134 } else {
135 lenlen = 0;
136 }
137
138 nextpos = 1 + lenlen;
139 if (lenlen > 2 || 1 + lenlen + *len > datalen) {
140 return -1;
141 }
142
143 return nextpos;
144 }
145
146 int
147 _libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen)
148 {
149 unsigned int len;
150 int lenlen;
151
152 if (*datalen < 1) {
153 return -1;
154 }
155
156 if ((*data)[0] != '\x30') {
157 return -1;
158 }
159
160 (*data)++;
161 (*datalen)--;
162
163 lenlen = read_asn1_length(*data, *datalen, &len);
164 if (lenlen < 0 || lenlen + len != *datalen) {
165 return -1;
166 }
167
168 *data += lenlen;
169 *datalen -= lenlen;
170
171 return 0;
172 }
173
174 int
175 _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
176 unsigned char **i, unsigned int *ilen)
177 {
178 unsigned int len;
179 int lenlen;
180
181 if (*datalen < 1) {
182 return -1;
183 }
184
185 if ((*data)[0] != '\x02') {
186 return -1;
187 }
188
189 (*data)++;
190 (*datalen)--;
191
192 lenlen = read_asn1_length(*data, *datalen, &len);
193 if (lenlen < 0 || lenlen + len > *datalen) {
194 return -1;
195 }
196
197 *data += lenlen;
198 *datalen -= lenlen;
199
200 *i = *data;
201 *ilen = len;
202
203 *data += len;
204 *datalen -= len;
205
206 return 0;
207 }