1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 ASN.1 utility functions
4 Copyright 2012-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
5 Copyright 2017 Alexander Zakharov <uglym8@gmail.com>
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <gnutls/gnutls.h>
22 #include <libtasn1.h>
23 #include <stdlib.h>
24
25 #include "rdesktop.h"
26 #include "asn.h"
27
28 // Generated by asn1Parser
29 #include "pkix_asn1_tab.c"
30
31 static asn1_node *asn_defs = NULL;
32
33 #define MAX_ERROR_DESCRIPTION_SIZE 1024
34 char errstr[MAX_ERROR_DESCRIPTION_SIZE];
35
36 /* Parse an ASN.1 BER header */
37 RD_BOOL
ber_parse_header(STREAM s,int tagval,uint32 * length)38 ber_parse_header(STREAM s, int tagval, uint32 *length)
39 {
40 int tag, len;
41
42 if (tagval > 0xff)
43 {
44 if (!s_check_rem(s, 2)) {
45 return False;
46 }
47 in_uint16_be(s, tag);
48 }
49 else
50 {
51 if (!s_check_rem(s, 1)) {
52 return False;
53 }
54 in_uint8(s, tag);
55 }
56
57 if (tag != tagval)
58 {
59 logger(Core, Error, "ber_parse_header(), expected tag %d, got %d", tagval, tag);
60 return False;
61 }
62
63 if (!s_check_rem(s, 1)) {
64 return False;
65 }
66 in_uint8(s, len);
67
68 if (len & 0x80)
69 {
70 len &= ~0x80;
71 if (!s_check_rem(s, len)) {
72 return False;
73 }
74 *length = 0;
75 while (len--)
76 next_be(s, *length);
77 }
78 else
79 *length = len;
80
81 return True;
82 }
83
84 void
ber_out_sequence(STREAM out,STREAM content)85 ber_out_sequence(STREAM out, STREAM content)
86 {
87 size_t length;
88 length = (content ? s_length(content) : 0);
89 ber_out_header(out, BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, length);
90 if (content)
91 out_stream(out, content);
92 }
93
94
95 /* Output an ASN.1 BER header */
96 void
ber_out_header(STREAM s,int tagval,int length)97 ber_out_header(STREAM s, int tagval, int length)
98 {
99 if (tagval > 0xff)
100 {
101 out_uint16_be(s, tagval);
102 }
103 else
104 {
105 out_uint8(s, tagval);
106 }
107
108 if (length >= 0x80)
109 {
110 out_uint8(s, 0x82);
111 out_uint16_be(s, length);
112 }
113 else
114 out_uint8(s, length);
115 }
116
117 /* Output an ASN.1 BER integer */
118 void
ber_out_integer(STREAM s,int value)119 ber_out_integer(STREAM s, int value)
120 {
121 ber_out_header(s, BER_TAG_INTEGER, 2);
122 out_uint16_be(s, value);
123 }
124
125 RD_BOOL
ber_in_header(STREAM s,int * tagval,int * decoded_len)126 ber_in_header(STREAM s, int *tagval, int *decoded_len)
127 {
128 in_uint8(s, *tagval);
129 in_uint8(s, *decoded_len);
130
131 if (*decoded_len < 0x80)
132 return True;
133 else if (*decoded_len == 0x81)
134 {
135 in_uint8(s, *decoded_len);
136 return True;
137 }
138 else if (*decoded_len == 0x82)
139 {
140 in_uint16_be(s, *decoded_len);
141 return True;
142 }
143
144 return False;
145 }
146
147
init_asn1_lib(void)148 int init_asn1_lib(void)
149 {
150 int asn1_rv;
151
152 if (asn_defs) {
153 return 0;
154 }
155
156 asn_defs = malloc(sizeof(*asn_defs));
157
158 if (!asn_defs) {
159 logger(Core, Error, "%s:%s:%d Failed to allocate memory for ASN.1 parser\n",
160 __FILE__, __func__, __LINE__);
161 return 1;
162 }
163
164 *asn_defs = NULL;
165
166 if (ASN1_SUCCESS != (asn1_rv = asn1_array2tree(pkix_asn1_tab, asn_defs, errstr))) {
167 logger(Core, Error, "%s:%s:%d Failed to init ASN.1 parser. Error = 0x%x (%s)\n",
168 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
169
170 return 1;
171 }
172
173 return 0;
174 }
175
176 /* Encode RSA public key into DER PKCS#1 */
177 /* Returns; 0 - success, 1 - fatal error, 2 - insufficient space in buffer */
write_pkcs1_der_pubkey(const gnutls_datum_t * m,const gnutls_datum_t * e,uint8_t * out,int * out_len)178 int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uint8_t *out, int *out_len)
179 {
180 int asn1_rv;
181 asn1_node asn_cert;
182
183 if (!asn_defs) {
184 if (init_asn1_lib() != 0) {
185 return 1;
186 }
187 }
188
189 if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.RSAPublicKey", &asn_cert))) {
190 logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element for RSAPublicKey. Error = 0x%x (%s)\n",
191 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
192 return 1;
193 }
194
195 if (ASN1_SUCCESS != (asn1_rv = asn1_write_value(asn_cert, "modulus", m->data, m->size))) {
196 logger(Core, Error, "%s:%s:%d Failed to write modulus. Error = 0x%x (%s)\n",
197 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
198
199 return 1;
200 }
201
202 if (ASN1_SUCCESS != (asn1_rv = asn1_write_value(asn_cert, "publicExponent", e->data, e->size))) {
203 logger(Core, Error, "%s:%s:%d Failed to write publicExponent. Error = 0x%x (%s)\n",
204 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
205 return 1;
206 }
207
208 if (ASN1_SUCCESS != (asn1_rv = asn1_der_coding(asn_cert, "", out, out_len, errstr))) {
209 logger(Core, Error, "%s:%s:%d Failed to encode PKIX1Implicit88.RSAPublicKey. Error = 0x%x (%s)\n",
210 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
211
212 if (asn1_rv == ASN1_MEM_ERROR) {
213 return 2;
214 }
215
216 return 1;
217 }
218
219 return 0;
220 }
221
libtasn_read_cert_pk_oid(uint8_t * data,size_t len,char * oid,size_t * oid_size)222 int libtasn_read_cert_pk_oid(uint8_t *data, size_t len, char *oid, size_t *oid_size)
223 {
224 int asn1_rv;
225 asn1_node asn_cert;
226
227 /* Parse DER encoded x.509 certificate */
228 if (!asn_defs) {
229 if (init_asn1_lib() != 0) {
230 return 1;
231 }
232 }
233
234 if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.Certificate", &asn_cert))) {
235 logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n",
236 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
237 return 1;
238 }
239
240 if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_cert, data, len, errstr))) {
241 logger(Core, Error, "%s:%s:%d Failed to decode certificate object. Error = 0x%x (%s)\n",
242 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
243 return 1;
244 }
245
246 if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",
247 oid, (int *)oid_size)))
248 {
249 logger(Core, Error, "%s:%s:%d Failed to get cert's public key algorithm. Error = 0x%x (%s)\n",
250 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
251 return 1;
252 }
253
254 return 0;
255 }
256
libtasn_read_cert_pk_parameters(uint8_t * data,size_t len,gnutls_datum_t * m,gnutls_datum_t * e)257 int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e)
258 {
259 int asn1_rv;
260 asn1_node asn_cert;
261
262 int buflen;
263 uint8_t buf[16384];
264
265 asn1_node asn_key;
266 int nblen;
267 uint8_t newbuf[16384];
268
269 /* Parse DER encoded x.509 certificate */
270 init_asn1_lib();
271
272 if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.Certificate", &asn_cert))) {
273 logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n",
274 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
275 return 1;
276 }
277
278 if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_cert, data, len, errstr))) {
279 logger(Core, Error, "%s:%s:%d Failed to decode certificate object. Error = 0x%x (%s)\n",
280 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
281 return 1;
282 }
283
284 buflen = sizeof(buf) - 1;
285 if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", buf, &buflen))) {
286 logger(Core, Error, "%s:%s:%d Failed to get cert's public key. Error = 0x%x (%s)\n",
287 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
288 return 1;
289 }
290
291 if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.RSAPublicKey", &asn_key))) {
292 logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n",
293 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
294 return 1;
295 }
296
297 // As it' a BIT STRING the len constitutes the number of BITS, not BYTES
298 if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_key, buf, buflen / 8, errstr))) {
299 logger(Core, Error, "%s:%s:%d Failed to decode public key object. Error = 0x%x (%s)\n",
300 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
301 return 1;
302 }
303
304 /* Get RSA public key's modulus and exponent */
305 nblen = sizeof(newbuf);
306
307 if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_key, "modulus", newbuf, &nblen))) {
308 logger(Core, Error, "%s:%s:%d Failed to get RSA public key's modulus. Error = 0x%x (%s)\n",
309 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
310 return 1;
311 }
312
313 m->size = nblen;
314
315 if (!(m->data = malloc(m->size))) {
316 logger(Core, Error, "%s:%s:%d Failed to allocate memory for modulus.\n", __FILE__, __func__, __LINE__);
317 return 1;
318 }
319
320 memcpy((void *)m->data, newbuf, m->size);
321
322 nblen = sizeof(newbuf);
323
324 if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_key, "publicExponent", newbuf, &nblen))) {
325 logger(Core, Error, "%s:%s:%d Failed to get RSA public key's exponent. Error = 0x%x (%s)\n",
326 __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv));
327 return 1;
328 }
329
330 e->size = nblen;
331
332 if (!(e->data = malloc(e->size))) {
333 logger(Core, Error, "%s:%s:%d Failed to allocate memory for exponent.\n", __FILE__, __func__, __LINE__);
334 if (m->data) {
335 free(m->data);
336 }
337 return 1;
338 }
339
340 memcpy((void *)e->data, newbuf, e->size);
341
342 return 0;
343 }
344