1 /*
2  * Copyright (C) 2012 Red Hat Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * 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  *     * Redistributions in binary form must reproduce the
12  *       above copyright notice, this list of conditions and
13  *       the following disclaimer in the documentation and/or
14  *       other materials provided with the distribution.
15  *     * The names of contributors to this software may not be
16  *       used to endorse or promote products derived from this
17  *       software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30  * DAMAGE.
31  *
32  * Author: Stef Walter <stefw@redhat.com>
33  */
34 
35 #include "config.h"
36 
37 #include "asn1.h"
38 #define P11_DEBUG_FLAG P11_DEBUG_TRUST
39 #include "debug.h"
40 #include "oid.h"
41 
42 #include "openssl.asn.h"
43 #include "pkix.asn.h"
44 
45 #include <assert.h>
46 #include <stdlib.h>
47 #include <string.h>
48 
49 static void
free_asn1_def(void * data)50 free_asn1_def (void *data)
51 {
52 	node_asn *def = data;
53 	asn1_delete_structure (&def);
54 }
55 
56 struct {
57 	const ASN1_ARRAY_TYPE* tab;
58 	const char *prefix;
59 	int prefix_len;
60 } asn1_tabs[] = {
61 	{ pkix_asn1_tab, "PKIX1.", 6 },
62 	{ openssl_asn1_tab, "OPENSSL.", 8 },
63 	{ NULL, },
64 };
65 
66 p11_dict *
p11_asn1_defs_load(void)67 p11_asn1_defs_load (void)
68 {
69 	char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, };
70 	node_asn *def;
71 	p11_dict *defs;
72 	int ret;
73 	int i;
74 
75 	defs = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, free_asn1_def);
76 
77 	for (i = 0; asn1_tabs[i].tab != NULL; i++) {
78 
79 		def = NULL;
80 		ret = asn1_array2tree (asn1_tabs[i].tab, &def, message);
81 		if (ret != ASN1_SUCCESS) {
82 			p11_debug_precond ("failed to load %s* definitions: %s: %s\n",
83 			                   asn1_tabs[i].prefix, asn1_strerror (ret), message);
84 			return NULL;
85 		}
86 
87 		if (!p11_dict_set (defs, (void *)asn1_tabs[i].prefix, def))
88 			return_val_if_reached (NULL);
89 	}
90 
91 	return defs;
92 }
93 
94 static node_asn *
lookup_def(p11_dict * asn1_defs,const char * struct_name)95 lookup_def (p11_dict *asn1_defs,
96             const char *struct_name)
97 {
98 	int i;
99 
100 	for (i = 0; asn1_tabs[i].tab != NULL; i++) {
101 		if (strncmp (struct_name, asn1_tabs[i].prefix, asn1_tabs[i].prefix_len) == 0)
102 			return p11_dict_get (asn1_defs, asn1_tabs[i].prefix);
103 	}
104 
105 	p11_debug_precond ("unknown prefix for element: %s\n", struct_name);
106 	return NULL;
107 }
108 
109 node_asn *
p11_asn1_create(p11_dict * asn1_defs,const char * struct_name)110 p11_asn1_create (p11_dict *asn1_defs,
111                  const char *struct_name)
112 {
113 	node_asn *def;
114 	node_asn *asn;
115 	int ret;
116 
117 	return_val_if_fail (asn1_defs != NULL, NULL);
118 
119 	def = lookup_def (asn1_defs, struct_name);
120 	return_val_if_fail (def != NULL, NULL);
121 
122 	ret = asn1_create_element (def, struct_name, &asn);
123 	if (ret != ASN1_SUCCESS) {
124 		p11_debug_precond ("failed to create element %s: %s\n",
125 		                   struct_name, asn1_strerror (ret));
126 		return NULL;
127 	}
128 
129 	return asn;
130 }
131 
132 node_asn *
p11_asn1_decode(p11_dict * asn1_defs,const char * struct_name,const unsigned char * der,size_t der_len,char * message)133 p11_asn1_decode (p11_dict *asn1_defs,
134                  const char *struct_name,
135                  const unsigned char *der,
136                  size_t der_len,
137                  char *message)
138 {
139 	char msg[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
140 	node_asn *asn = NULL;
141 	int ret;
142 
143 	return_val_if_fail (asn1_defs != NULL, NULL);
144 
145 	asn = p11_asn1_create (asn1_defs, struct_name);
146 	return_val_if_fail (asn != NULL, NULL);
147 
148 	/* asn1_der_decoding destroys the element if fails */
149 	ret = asn1_der_decoding (&asn, der, der_len, message ? message : msg);
150 
151 	if (ret != ASN1_SUCCESS) {
152 		/* If caller passed in a message buffer, assume they're logging */
153 		if (!message) {
154 			p11_debug ("couldn't parse %s: %s: %s",
155 			           struct_name, asn1_strerror (ret), msg);
156 		}
157 		return NULL;
158 	}
159 
160 	return asn;
161 }
162 
163 unsigned char *
p11_asn1_encode(node_asn * asn,size_t * der_len)164 p11_asn1_encode (node_asn *asn,
165                  size_t *der_len)
166 {
167 	char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
168 	unsigned char *der;
169 	int len;
170 	int ret;
171 
172 	return_val_if_fail (der_len != NULL, NULL);
173 
174 	len = 0;
175 	ret = asn1_der_coding (asn, "", NULL, &len, message);
176 	return_val_if_fail (ret != ASN1_SUCCESS, NULL);
177 
178 	if (ret == ASN1_MEM_ERROR) {
179 		der = malloc (len);
180 		return_val_if_fail (der != NULL, NULL);
181 
182 		ret = asn1_der_coding (asn, "", der, &len, message);
183 	}
184 
185 	if (ret != ASN1_SUCCESS) {
186 		p11_debug_precond ("failed to encode: %s\n", message);
187 		return NULL;
188 	}
189 
190 	if (der_len)
191 		*der_len = len;
192 	return der;
193 }
194 
195 void *
p11_asn1_read(node_asn * asn,const char * field,size_t * length)196 p11_asn1_read (node_asn *asn,
197                const char *field,
198                size_t *length)
199 {
200 	unsigned char *value;
201 	int len;
202 	int ret;
203 
204 	return_val_if_fail (asn != NULL, NULL);
205 	return_val_if_fail (field != NULL, NULL);
206 	return_val_if_fail (length != NULL, NULL);
207 
208 	len = 0;
209 	ret = asn1_read_value (asn, field, NULL, &len);
210 	if (ret == ASN1_ELEMENT_NOT_FOUND)
211 		return NULL;
212 
213 	return_val_if_fail (ret == ASN1_MEM_ERROR, NULL);
214 
215 	value = malloc (len + 1);
216 	return_val_if_fail (value != NULL, NULL);
217 
218 	ret = asn1_read_value (asn, field, value, &len);
219 	return_val_if_fail (ret == ASN1_SUCCESS, NULL);
220 
221 	/* Courtesy zero terminated */
222 	value[len] = '\0';
223 
224 	*length = len;
225 	return value;
226 }
227 
228 void
p11_asn1_free(void * asn)229 p11_asn1_free (void *asn)
230 {
231 	node_asn *node = asn;
232 	if (node != NULL)
233 		asn1_delete_structure (&node);
234 }
235 
236 ssize_t
p11_asn1_tlv_length(const unsigned char * data,size_t length)237 p11_asn1_tlv_length (const unsigned char *data,
238                      size_t length)
239 {
240 	unsigned char cls;
241 	int counter = 0;
242 	int cb, len;
243 	unsigned long tag;
244 
245 	if (asn1_get_tag_der (data, length, &cls, &cb, &tag) == ASN1_SUCCESS) {
246 		counter += cb;
247 		len = asn1_get_length_der (data + cb, length - cb, &cb);
248 		counter += cb;
249 		if (len >= 0) {
250 			len += counter;
251 			if (length >= len)
252 				return len;
253 		}
254 	}
255 
256 	return -1;
257 }
258 
259 typedef struct {
260 	node_asn *node;
261 	char *struct_name;
262 	size_t length;
263 } asn1_item;
264 
265 static void
free_asn1_item(void * data)266 free_asn1_item (void *data)
267 {
268 	asn1_item *item = data;
269 	free (item->struct_name);
270 	asn1_delete_structure (&item->node);
271 	free (item);
272 }
273 
274 struct _p11_asn1_cache {
275 	p11_dict *defs;
276 	p11_dict *items;
277 };
278 
279 p11_asn1_cache *
p11_asn1_cache_new(void)280 p11_asn1_cache_new (void)
281 {
282 	p11_asn1_cache *cache;
283 
284 	cache = calloc (1, sizeof (p11_asn1_cache));
285 	return_val_if_fail (cache != NULL, NULL);
286 
287 	cache->defs = p11_asn1_defs_load ();
288 	if (cache->defs == NULL) {
289 		p11_asn1_cache_free (cache);
290 		return_val_if_reached (NULL);
291 	}
292 
293 	cache->items = p11_dict_new (p11_dict_direct_hash, p11_dict_direct_equal,
294 	                             NULL, free_asn1_item);
295 	if (cache->items == NULL) {
296 		p11_asn1_cache_free (cache);
297 		return_val_if_reached (NULL);
298 	}
299 
300 	return cache;
301 }
302 
303 node_asn *
p11_asn1_cache_get(p11_asn1_cache * cache,const char * struct_name,const unsigned char * der,size_t der_len)304 p11_asn1_cache_get (p11_asn1_cache *cache,
305                     const char *struct_name,
306                     const unsigned char *der,
307                     size_t der_len)
308 {
309 	asn1_item *item;
310 
311 	if (cache == NULL)
312 		return NULL;
313 
314 	return_val_if_fail (struct_name != NULL, NULL);
315 	return_val_if_fail (der != NULL, NULL);
316 
317 	item = p11_dict_get (cache->items, der);
318 	if (item != NULL) {
319 		return_val_if_fail (item->length == der_len, NULL);
320 		return_val_if_fail (strcmp (item->struct_name, struct_name) == 0, NULL);
321 		return item->node;
322 	}
323 
324 	return NULL;
325 }
326 
327 void
p11_asn1_cache_take(p11_asn1_cache * cache,node_asn * node,const char * struct_name,const unsigned char * der,size_t der_len)328 p11_asn1_cache_take (p11_asn1_cache *cache,
329                      node_asn *node,
330                      const char *struct_name,
331                      const unsigned char *der,
332                      size_t der_len)
333 {
334 	asn1_item *item;
335 
336 	if (cache == NULL) {
337 		asn1_delete_structure (&node);
338 		return;
339 	}
340 
341 	return_if_fail (struct_name != NULL);
342 	return_if_fail (der != NULL);
343 	return_if_fail (der_len != 0);
344 
345 	item = calloc (1, sizeof (asn1_item));
346 	return_if_fail (item != NULL);
347 
348 	item->length = der_len;
349 	item->node = node;
350 	item->struct_name = strdup (struct_name);
351 	if (item->struct_name == NULL) {
352 		free_asn1_item (item);
353 		return_if_reached ();
354 	}
355 
356 	if (!p11_dict_set (cache->items, (void *)der, item))
357 		return_if_reached ();
358 }
359 
360 void
p11_asn1_cache_flush(p11_asn1_cache * cache)361 p11_asn1_cache_flush (p11_asn1_cache *cache)
362 {
363 	if (cache == NULL)
364 		return;
365 	p11_dict_clear (cache->items);
366 }
367 
368 p11_dict *
p11_asn1_cache_defs(p11_asn1_cache * cache)369 p11_asn1_cache_defs (p11_asn1_cache *cache)
370 {
371 	return_val_if_fail (cache != NULL, NULL);
372 	return cache->defs;
373 }
374 
375 void
p11_asn1_cache_free(p11_asn1_cache * cache)376 p11_asn1_cache_free (p11_asn1_cache *cache)
377 {
378 	if (!cache)
379 		return;
380 	p11_dict_free (cache->items);
381 	p11_dict_free (cache->defs);
382 	free (cache);
383 }
384