1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* egg-asn1x.c - ASN.1/DER parse and coding routines
3 
4    Copyright (C) 2009 Stefan Walter
5 
6    The Gnome Keyring Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    The Gnome Keyring Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public
17    License along with the Gnome Library; see the file COPYING.LIB.  If not,
18    <http://www.gnu.org/licenses/>.
19 
20    Author: Stef Walter <stef@memberwebs.com>
21 */
22 
23 /*
24  * Some portions are:
25  *
26  *      Copyright (C) 2004, 2006, 2008, 2009 Free Software Foundation
27  *      Copyright (C) 2002 Fabio Fiorina
28  *
29  * This file is part of LIBTASN1.
30  *
31  * The LIBTASN1 library is free software; you can redistribute it
32  * and/or modify it under the terms of the GNU Lesser General Public
33  * License as published by the Free Software Foundation; either
34  * version 2.1 of the License, or (at your option) any later version.
35  *
36  * This library is distributed in the hope that it will be useful, but
37  * WITHOUT ANY WARRANTY; without even the implied warranty of
38  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39  * Lesser General Public License for more details.
40  *
41  * You should have received a copy of the GNU Lesser General Public
42  * License along with this library; if not, see
43  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
44  * 02110-1301, USA
45  */
46 
47 #include "config.h"
48 
49 #include "egg-asn1x.h"
50 #include "egg-asn1-defs.h"
51 #include "egg-timegm.h"
52 
53 #include <stdlib.h>
54 #include <string.h>
55 
56 /* From libtasn1's libtasn.h */
57 
58 enum {
59 	ASN1_CLASS_UNIVERSAL = 0x00,
60 	ASN1_CLASS_APPLICATION = 0x40,
61 	ASN1_CLASS_CONTEXT_SPECIFIC = 0x80,
62 	ASN1_CLASS_PRIVATE = 0xC0,
63 	ASN1_CLASS_STRUCTURED = 0x20,
64 };
65 
66 enum {
67 	ASN1_TAG_BOOLEAN = 0x01,
68 	ASN1_TAG_INTEGER = 0x02,
69 	ASN1_TAG_SEQUENCE = 0x10,
70 	ASN1_TAG_SET = 0x11,
71 	ASN1_TAG_OCTET_STRING = 0x04,
72 	ASN1_TAG_BIT_STRING = 0x03,
73 	ASN1_TAG_UTC_TIME = 0x17,
74 	ASN1_TAG_GENERALIZED_TIME = 0x18,
75 	ASN1_TAG_OBJECT_ID = 0x06,
76 	ASN1_TAG_ENUMERATED = 0x0A,
77 	ASN1_TAG_NULL = 0x05,
78 	ASN1_TAG_GENERAL_STRING = 0x1B,
79 	ASN1_TAG_NUMERIC_STRING = 0x12,
80 	ASN1_TAG_IA5_STRING = 0x16,
81 	ASN1_TAG_TELETEX_STRING = 0x14,
82 	ASN1_TAG_PRINTABLE_STRING = 0x13,
83 	ASN1_TAG_UNIVERSAL_STRING = 0x1C,
84 	ASN1_TAG_BMP_STRING = 0x1E,
85 	ASN1_TAG_UTF8_STRING = 0x0C,
86 	ASN1_TAG_VISIBLE_STRING = 0x1A,
87 };
88 
89 /* From libtasn1's int.h */
90 
91 enum {
92 	FLAG_UNIVERSAL = (1<<8),
93 	FLAG_PRIVATE = (1<<9),
94 	FLAG_APPLICATION = (1<<10),
95 	FLAG_EXPLICIT = (1<<11),
96 	FLAG_IMPLICIT = (1<<12),
97 	FLAG_TAG = (1<<13),
98 	FLAG_OPTION = (1<<14),
99 	FLAG_DEFAULT = (1<<15),
100 	FLAG_TRUE = (1<<16),
101 	FLAG_FALSE = (1<<17),
102 	FLAG_LIST = (1<<18),
103 	FLAG_MIN_MAX = (1<<19),
104 	FLAG_1_PARAM = (1<<20),
105 	FLAG_SIZE = (1<<21),
106 	FLAG_DEFINED_BY = (1<<22),
107 	FLAG_GENERALIZED = (1<<23),
108 	FLAG_UTC = (1<<24),
109 	FLAG_IMPORTS = (1<<25),
110 	FLAG_NOT_USED = (1<<26),
111 	FLAG_SET = (1<<27),
112 	FLAG_ASSIGN = (1<<28),
113 	FLAG_DOWN = (1<<29),
114 	FLAG_RIGHT = (1<<30),
115 };
116 
117 typedef struct _Atlv Atlv;
118 typedef struct _Anode Anode;
119 
120 struct _Atlv {
121 	guchar cls;
122 	gulong tag;
123 	gint off;
124 	gint len;
125 
126 	/* An actual value here */
127 	GBytes *value;
128 
129 	/* Reference to what was decoded */
130 	GBytes *decoded;
131 
132 	/* Chain this into a tree */
133 	struct _Atlv *child;
134 	struct _Atlv *next;
135 
136 	/* Used during encoding */
137 
138 	/* Encoding: for bitstring, the number of empty bits at end */
139 	guint bits_empty : 3;
140 
141 	/* Encoding: tell us whether we're dealing with a bit string */
142 	guint prefix_for_bit_string : 1;
143 
144 	/* Encoding: prefix a zero byte for unsigned integers */
145 	guint prefix_with_zero_byte : 1;
146 
147 	/* Encoding: sort children of this tlv (ie: SETOF) */
148 	guint sorted : 1;
149 };
150 
151 struct _Anode {
152 	const EggAsn1xDef *def;
153 	const EggAsn1xDef *join;
154 	GList *opts;
155 
156 	GBytes *value;
157 	Atlv *parsed;
158 
159 	gchar* failure;
160 
161 	/* If this node was chosen out of a choice */
162 	guint chosen : 1;
163 
164 	/* For bitstring the number of empty bits */
165 	guint bits_empty : 3;
166 
167 	/* Whether we need to prefix a zero byte to make unsigned */
168 	guint guarantee_unsigned : 1;
169 };
170 
171 /* Forward Declarations */
172 static gboolean anode_decode_anything (GNode *, Atlv *);
173 static gboolean anode_decode_one (GNode *, Atlv *);
174 static GBytes * anode_default_boolean (GNode *node);
175 static GBytes * anode_default_integer (GNode *node);
176 static gboolean anode_validate_anything (GNode *, gboolean);
177 static Atlv * anode_build_anything (GNode*, gboolean want);
178 
179 static gint
atoin(const char * p,gint digits)180 atoin (const char *p, gint digits)
181 {
182 	gint ret = 0, base = 1;
183 	while(--digits >= 0) {
184 		if (p[digits] < '0' || p[digits] > '9')
185 			return -1;
186 		ret += (p[digits] - '0') * base;
187 		base *= 10;
188 	}
189 	return ret;
190 }
191 
192 static const guchar *
bytes_get_end(GBytes * data)193 bytes_get_end (GBytes *data)
194 {
195 	const guchar *beg;
196 	gsize size;
197 	beg = g_bytes_get_data (data, &size);
198 	return beg + size;
199 }
200 
201 typedef struct {
202 	EggAllocator allocator;
203 	gpointer allocated;
204 } AllocatorClosure;
205 
206 static void
allocator_closure_free(gpointer data)207 allocator_closure_free (gpointer data)
208 {
209 	AllocatorClosure *closure = data;
210 	g_assert (closure->allocator);
211 	(closure->allocator) (closure->allocated, 0);
212 	g_slice_free (AllocatorClosure, closure);
213 }
214 
215 static GBytes *
bytes_new_with_allocator(EggAllocator allocator,guchar ** data,gsize length)216 bytes_new_with_allocator (EggAllocator allocator,
217                           guchar **data,
218                           gsize length)
219 {
220 	AllocatorClosure *closure;
221 
222 	if (allocator == g_realloc)
223 		allocator = NULL;
224 
225 	if (allocator) {
226 		*data = (allocator) (NULL, length + 1);
227 		g_return_val_if_fail (*data != NULL, NULL);
228 		closure = g_slice_new (AllocatorClosure);
229 		closure->allocated = *data;
230 		closure->allocator = allocator;
231 		return g_bytes_new_with_free_func (*data, length,
232 		                                   allocator_closure_free,
233 		                                   closure);
234 	} else {
235 		*data = g_malloc (length);
236 		return g_bytes_new_take (*data, length);
237 	}
238 }
239 
240 static GNode*
anode_new(const EggAsn1xDef * def)241 anode_new (const EggAsn1xDef *def)
242 {
243 	Anode *an = g_slice_new0 (Anode);
244 	an->def = def;
245 	return g_node_new (an);
246 }
247 
248 static gpointer
anode_copy_func(gconstpointer src,gpointer unused)249 anode_copy_func (gconstpointer src, gpointer unused)
250 {
251 	const Anode *san = src;
252 	Anode *an = g_slice_new0 (Anode);
253 	an->def = san->def;
254 	an->join = san->join;
255 	an->opts = g_list_copy (san->opts);
256 	return an;
257 }
258 
259 static GNode*
anode_clone(GNode * node)260 anode_clone (GNode *node)
261 {
262 	return g_node_copy_deep (node, anode_copy_func, NULL);
263 }
264 
265 static int
anode_def_type(GNode * node)266 anode_def_type (GNode *node)
267 {
268 	Anode *an = node->data;
269 	gint type = an->join ? an->join->type : an->def->type;
270 	return type & 0xFF;
271 }
272 
273 static gboolean
anode_def_type_is_real(GNode * node)274 anode_def_type_is_real (GNode *node)
275 {
276 	switch (anode_def_type (node)) {
277 	case EGG_ASN1X_INTEGER:
278 	case EGG_ASN1X_BOOLEAN:
279 	case EGG_ASN1X_BIT_STRING:
280 	case EGG_ASN1X_OCTET_STRING:
281 	case EGG_ASN1X_OBJECT_ID:
282 	case EGG_ASN1X_TIME:
283 	case EGG_ASN1X_UTC_TIME:
284 	case EGG_ASN1X_GENERALIZED_TIME:
285 	case EGG_ASN1X_NULL:
286 	case EGG_ASN1X_ENUMERATED:
287 	case EGG_ASN1X_GENERAL_STRING:
288 	case EGG_ASN1X_NUMERIC_STRING:
289 	case EGG_ASN1X_IA5_STRING:
290 	case EGG_ASN1X_TELETEX_STRING:
291 	case EGG_ASN1X_PRINTABLE_STRING:
292 	case EGG_ASN1X_UNIVERSAL_STRING:
293 	case EGG_ASN1X_BMP_STRING:
294 	case EGG_ASN1X_UTF8_STRING:
295 	case EGG_ASN1X_VISIBLE_STRING:
296 		return TRUE;
297 	case EGG_ASN1X_SEQUENCE:
298 	case EGG_ASN1X_SEQUENCE_OF:
299 	case EGG_ASN1X_ANY:
300 	case EGG_ASN1X_SET:
301 	case EGG_ASN1X_SET_OF:
302 	case EGG_ASN1X_CHOICE:
303 		return TRUE;
304 	case EGG_ASN1X_CONSTANT:
305 	case EGG_ASN1X_IDENTIFIER:
306 	case EGG_ASN1X_TAG:
307 	case EGG_ASN1X_DEFAULT:
308 	case EGG_ASN1X_SIZE:
309 	case EGG_ASN1X_DEFINITIONS:
310 	case EGG_ASN1X_IMPORTS:
311 		return FALSE;
312 	}
313 
314 	g_return_val_if_reached (FALSE);
315 }
316 
317 static int
anode_def_flags(GNode * node)318 anode_def_flags (GNode *node)
319 {
320 	Anode *an = node->data;
321 	gint type = an->def->type;
322 	if (an->join)
323 		type |= an->join->type;
324 	return type & 0xFFFFFF00;
325 }
326 
327 static const gchar*
anode_def_name(GNode * node)328 anode_def_name (GNode *node)
329 {
330 	Anode *an = node->data;
331 	return an->def->name;
332 }
333 
334 static const gchar*
anode_def_value(GNode * node)335 anode_def_value (GNode *node)
336 {
337 	Anode *an = node->data;
338 	return an->def->value;
339 }
340 
341 static gulong
anode_def_value_as_ulong(const EggAsn1xDef * def)342 anode_def_value_as_ulong (const EggAsn1xDef *def)
343 {
344 	gchar *end = NULL;
345 	gulong lval;
346 
347 	g_return_val_if_fail (def->value, G_MAXULONG);
348 	lval = strtoul (def->value, &end, 10);
349 	g_return_val_if_fail (end && !end[0], G_MAXULONG);
350 	return lval;
351 }
352 
353 static GNode*
anode_child_with_name(GNode * node,const gchar * name)354 anode_child_with_name (GNode *node, const gchar *name)
355 {
356 	GNode *child;
357 
358 	for (child = node->children; child; child = child->next) {
359 		if (g_str_equal (name, anode_def_name (child)))
360 			return child;
361 	}
362 
363 	return NULL;
364 }
365 
366 static void
anode_opt_add(GNode * node,const EggAsn1xDef * def)367 anode_opt_add (GNode *node,
368                const EggAsn1xDef *def)
369 {
370 	Anode *an = node->data;
371 	an->opts = g_list_append (an->opts, (gpointer)def);
372 }
373 
374 static EggAsn1xDef *
anode_opt_lookup(GNode * node,gint type,const gchar * name)375 anode_opt_lookup (GNode *node,
376                   gint type,
377                   const gchar *name)
378 {
379 	Anode *an = node->data;
380 	EggAsn1xDef *def;
381 	GList *l;
382 
383 	for (l = an->opts; l; l = g_list_next (l)) {
384 		def = l->data;
385 		if (name && def->name && !g_str_equal (name, def->name))
386 			continue;
387 		if ((def->type & 0xFF) == type)
388 			return def;
389 	}
390 
391 	return NULL;
392 }
393 
394 static EggAsn1xDef *
anode_opt_lookup_value(GNode * node,gint type,const gchar * value)395 anode_opt_lookup_value (GNode *node,
396                         gint type,
397                         const gchar *value)
398 {
399 	Anode *an = node->data;
400 	EggAsn1xDef *def;
401 	GList *l;
402 
403 	for (l = an->opts; l; l = g_list_next (l)) {
404 		def = l->data;
405 		if (value && def->value && !g_str_equal (value, def->value))
406 			continue;
407 		if ((def->type & 0xFF) == type)
408 			return def;
409 	}
410 
411 	return NULL;
412 }
413 
414 static GList*
anode_opts_lookup(GNode * node,gint type,const gchar * name)415 anode_opts_lookup (GNode *node, gint type, const gchar *name)
416 {
417 	Anode *an = node->data;
418 	EggAsn1xDef *def;
419 	GList *l, *res = NULL;
420 
421 	for (l = an->opts; l; l = g_list_next (l)) {
422 		def = l->data;
423 		if (name && def->name && !g_str_equal (name, def->name))
424 			continue;
425 		if ((def->type & 0xFF) == type)
426 			res = g_list_prepend (res, def);
427 	}
428 
429 	return g_list_reverse (res);
430 }
431 
432 static Atlv *
atlv_new(void)433 atlv_new (void)
434 {
435 	return g_slice_new0 (Atlv);
436 }
437 
438 static void
atlv_free(Atlv * tlv)439 atlv_free (Atlv *tlv)
440 {
441 	if (!tlv)
442 		return;
443 
444 	/* Free attached TLVs */
445 	atlv_free (tlv->child);
446 	atlv_free (tlv->next);
447 
448 	/* Free the TLV */
449 	if (tlv->decoded)
450 		g_bytes_unref (tlv->decoded);
451 	if (tlv->value)
452 		g_bytes_unref (tlv->value);
453 
454 	g_slice_free (Atlv, tlv);
455 }
456 
457 static Atlv *
atlv_dup(Atlv * tlv,gboolean siblings)458 atlv_dup (Atlv *tlv,
459           gboolean siblings)
460 {
461 	Atlv *copy;
462 
463 	if (!tlv)
464 		return NULL;
465 
466 	copy = g_slice_new0 (Atlv);
467 	memcpy (copy, tlv, sizeof (Atlv));
468 
469 	if (tlv->value != NULL)
470 		copy->value = g_bytes_ref (tlv->value);
471 	if (tlv->decoded != NULL)
472 		copy->decoded = g_bytes_ref (tlv->decoded);
473 
474 	copy->child = atlv_dup (tlv->child, TRUE);
475 	if (siblings)
476 		copy->next = atlv_dup (tlv->next, TRUE);
477 	else
478 		copy->next = NULL;
479 
480 	return copy;
481 }
482 
483 static inline GBytes *
anode_get_value(GNode * node)484 anode_get_value (GNode *node)
485 {
486 	Anode *an = node->data;
487 	return an->value;
488 }
489 
490 static inline void
anode_clr_value(GNode * node)491 anode_clr_value (GNode *node)
492 {
493 	Anode *an = node->data;
494 	if (an->value)
495 		g_bytes_unref (an->value);
496 	an->value = NULL;
497 
498 	atlv_free (an->parsed);
499 	an->parsed = NULL;
500 }
501 
502 static inline void
anode_take_value(GNode * node,GBytes * value)503 anode_take_value (GNode *node,
504                   GBytes *value)
505 {
506 	Anode *an = node->data;
507 	anode_clr_value (node);
508 	an->value = value;
509 }
510 
511 static inline void
anode_set_value(GNode * node,GBytes * value)512 anode_set_value (GNode *node,
513                  GBytes *value)
514 {
515 	anode_take_value (node, g_bytes_ref (value));
516 }
517 
518 static inline Atlv *
anode_get_parsed(GNode * node)519 anode_get_parsed (GNode *node)
520 {
521 	Anode *an = node->data;
522 	return an->parsed;
523 }
524 
525 static gboolean
anode_failure(GNode * node,const gchar * failure)526 anode_failure (GNode *node, const gchar *failure)
527 {
528 	Anode *an = node->data;
529 	const gchar *prefix = an->def->name;
530 	if (!prefix && an->join)
531 		prefix = an->join->name;
532 	if (!prefix)
533 		prefix = an->def->value;
534 	if (!prefix && an->join)
535 		prefix = an->join->value;
536 	if (!prefix)
537 		prefix = "unknown";
538 
539 	g_free (an->failure);
540 	an->failure = g_strdup_printf ("%s: %s", prefix, failure);
541 	g_debug ("%s %s", prefix, an->failure);
542 	return FALSE; /* So this can be chained */
543 }
544 
545 static const gchar*
anode_failure_get(GNode * node)546 anode_failure_get (GNode *node)
547 {
548 	Anode *an = node->data;
549 	return an->failure;
550 }
551 
552 static void
anode_clear(GNode * node)553 anode_clear (GNode *node)
554 {
555 	Anode *an = node->data;
556 	anode_clr_value (node);
557 	g_free (an->failure);
558 	an->failure = NULL;
559 }
560 
561 static gboolean
anode_free_func(GNode * node,gpointer unused)562 anode_free_func (GNode *node, gpointer unused)
563 {
564 	Anode *an = node->data;
565 	anode_clear (node);
566 	g_list_free (an->opts);
567 	g_slice_free (Anode, an);
568 	return FALSE;
569 }
570 
571 static void
anode_destroy(GNode * node)572 anode_destroy (GNode *node)
573 {
574 	if (!G_NODE_IS_ROOT (node))
575 		g_node_unlink (node);
576 	g_node_traverse (node, G_IN_ORDER, G_TRAVERSE_ALL, -1, anode_free_func, NULL);
577 	g_node_destroy (node);
578 }
579 
580 static gulong
anode_calc_tag_for_flags(GNode * node,gint flags)581 anode_calc_tag_for_flags (GNode *node, gint flags)
582 {
583 	EggAsn1xDef *def;
584 
585 	/* A context specific tag */
586 	if (flags & FLAG_TAG) {
587 		def = anode_opt_lookup (node, EGG_ASN1X_TAG, NULL);
588 		g_return_val_if_fail (def, G_MAXULONG);
589 		return anode_def_value_as_ulong (def);
590 	}
591 
592 	/* A tag from the universal set */
593 	switch (anode_def_type (node)) {
594 	case EGG_ASN1X_INTEGER:
595 		return ASN1_TAG_INTEGER;
596 	case EGG_ASN1X_ENUMERATED:
597 		return ASN1_TAG_ENUMERATED;
598 	case EGG_ASN1X_BOOLEAN:
599 		return ASN1_TAG_BOOLEAN;
600 	case EGG_ASN1X_BIT_STRING:
601 		return ASN1_TAG_BIT_STRING;
602 	case EGG_ASN1X_OCTET_STRING:
603 		return ASN1_TAG_OCTET_STRING;
604 	case EGG_ASN1X_OBJECT_ID:
605 		return ASN1_TAG_OBJECT_ID;
606 	case EGG_ASN1X_NULL:
607 		return ASN1_TAG_NULL;
608 	case EGG_ASN1X_GENERAL_STRING:
609 		return ASN1_TAG_GENERAL_STRING;
610 	case EGG_ASN1X_NUMERIC_STRING:
611 		return ASN1_TAG_NUMERIC_STRING;
612 	case EGG_ASN1X_IA5_STRING:
613 		return ASN1_TAG_IA5_STRING;
614 	case EGG_ASN1X_TELETEX_STRING:
615 		return ASN1_TAG_TELETEX_STRING;
616 	case EGG_ASN1X_PRINTABLE_STRING:
617 		return ASN1_TAG_PRINTABLE_STRING;
618 	case EGG_ASN1X_UNIVERSAL_STRING:
619 		return ASN1_TAG_UNIVERSAL_STRING;
620 	case EGG_ASN1X_BMP_STRING:
621 		return ASN1_TAG_BMP_STRING;
622 	case EGG_ASN1X_UTF8_STRING:
623 		return ASN1_TAG_UTF8_STRING;
624 	case EGG_ASN1X_VISIBLE_STRING:
625 		return ASN1_TAG_VISIBLE_STRING;
626 	case EGG_ASN1X_TIME:
627 		if (flags & FLAG_GENERALIZED)
628 			return ASN1_TAG_GENERALIZED_TIME;
629 		else if (flags & FLAG_UTC)
630 			return ASN1_TAG_UTC_TIME;
631 		else
632 			g_return_val_if_reached (G_MAXULONG);
633 	case EGG_ASN1X_UTC_TIME:
634 		return ASN1_TAG_UTC_TIME;
635 	case EGG_ASN1X_GENERALIZED_TIME:
636 		return ASN1_TAG_GENERALIZED_TIME;
637 	case EGG_ASN1X_SEQUENCE:
638 	case EGG_ASN1X_SEQUENCE_OF:
639 		return ASN1_TAG_SEQUENCE;
640 	case EGG_ASN1X_SET:
641 	case EGG_ASN1X_SET_OF:
642 		return ASN1_TAG_SET;
643 
644 	/* These should be handled specially */
645 	case EGG_ASN1X_ANY:
646 	case EGG_ASN1X_CHOICE:
647 		return G_MAXULONG;
648 
649 	/* These are not real nodes */
650 	case EGG_ASN1X_CONSTANT:
651 	case EGG_ASN1X_IDENTIFIER:
652 	case EGG_ASN1X_TAG:
653 	case EGG_ASN1X_DEFAULT:
654 	case EGG_ASN1X_SIZE:
655 	case EGG_ASN1X_DEFINITIONS:
656 	case EGG_ASN1X_IMPORTS:
657 		g_return_val_if_reached (G_MAXULONG);
658 	}
659 
660 	g_return_val_if_reached (G_MAXULONG);
661 }
662 
663 static gulong
anode_calc_tag(GNode * node)664 anode_calc_tag (GNode *node)
665 {
666 	return anode_calc_tag_for_flags (node, anode_def_flags (node));
667 }
668 
669 static gboolean
anode_calc_explicit_for_flags(GNode * node,gint flags,guchar * cls_type)670 anode_calc_explicit_for_flags (GNode *node,
671                                gint flags,
672                                guchar *cls_type)
673 {
674 	const EggAsn1xDef *opt;
675 	if ((flags & FLAG_TAG) != FLAG_TAG)
676 		return FALSE;
677 	opt = anode_opt_lookup (node, EGG_ASN1X_TAG, NULL);
678 	g_return_val_if_fail (opt, FALSE);
679 	if (cls_type) {
680 		if (opt->type & FLAG_UNIVERSAL)
681 			*cls_type = ASN1_CLASS_UNIVERSAL;
682 		else if (opt->type & FLAG_APPLICATION)
683 			*cls_type = ASN1_CLASS_APPLICATION;
684 		else if (opt->type & FLAG_PRIVATE)
685 			*cls_type = ASN1_CLASS_PRIVATE;
686 		else
687 			*cls_type = ASN1_CLASS_CONTEXT_SPECIFIC;
688 	}
689 	if ((opt->type & FLAG_IMPLICIT) == FLAG_IMPLICIT)
690 		return FALSE;
691 	return TRUE;
692 }
693 
694 /* -------------------------------------------------------------------------
695  * PARSING
696  */
697 
698 static gboolean
atlv_parse_cls_tag(const guchar * at,const guchar * end,guchar * cls,gulong * tag,gint * off)699 atlv_parse_cls_tag (const guchar *at,
700                     const guchar *end,
701                     guchar *cls,
702                     gulong *tag,
703                     gint *off)
704 {
705 	gint punt, ris, last;
706 	gint n_data;
707 	guchar val;
708 
709 	g_assert (end >= at);
710 	g_assert (cls != NULL);
711 	g_assert (off != NULL);
712 
713 	n_data = end - at;
714 
715 	if (n_data < 2)
716 		return FALSE;
717 
718 	*cls = at[0] & 0xE0;
719 
720 	/* short form */
721 	if ((at[0] & 0x1F) != 0x1F) {
722 		*off = 1;
723 		ris = at[0] & 0x1F;
724 
725 	/* Long form */
726 	} else {
727 		punt = 1;
728 		ris = 0;
729 		while (punt <= n_data) {
730 			val = at[punt++];
731 			last = ris;
732 			ris = ris * 128;
733 
734 			/* wrapper around, and no bignums... */
735 			if (ris < last)
736 				return FALSE;
737 
738 			last = ris;
739 			ris += (val & 0x7F);
740 
741 			/* wrapper around, and no bignums... */
742 			if (ris < last)
743 				return FALSE;
744 
745 			if ((val & 0x7F) == val)
746 				break;
747 		}
748 
749 		if (punt >= n_data)
750 			return FALSE;
751 
752 		*off = punt;
753 	}
754 
755 	if (tag)
756 		*tag = ris;
757 
758 	return TRUE;
759 }
760 
761 static gint
atlv_parse_length(const guchar * at,const guchar * end,gint * off)762 atlv_parse_length (const guchar *at,
763                    const guchar *end,
764                    gint *off)
765 {
766 	gint ans;
767 	gint k, punt;
768 	gint n_data;
769 
770 	g_assert (at != NULL);
771 	g_assert (end != NULL);
772 	g_assert (end > at);
773 	g_assert (off != NULL);
774 
775 	*off = 0;
776 	n_data = end - at;
777 
778 	/* short form */
779 	if (!(at[0] & 128)) {
780 		*off = 1;
781 		return at[0];
782 
783 	/* Long form */
784 	} else {
785 		k = at[0] & 0x7F;
786 		punt = 1;
787 
788 		/* definite length method */
789 		if (k) {
790 			ans = 0;
791 			while (punt <= k && punt < n_data) {
792 				/* we wrapped around, no bignum support... */
793 				if (ans > G_MAXINT / 256)
794 					return -2;
795 				ans = ans * 256;
796 
797 				/* we wrapped around, no bignum support... */
798 				if (ans > G_MAXINT - at[punt])
799 					return -2;
800 				ans += at[punt++];
801 			}
802 
803 		/* indefinite length method */
804 		} else {
805 			ans = -1;
806 		}
807 
808 		*off = punt;
809 		return ans;
810 	}
811 }
812 
813 static gboolean
atlv_parse_cls_tag_len(const guchar * at,const guchar * end,guchar * cls,gulong * tag,gint * off,gint * len)814 atlv_parse_cls_tag_len (const guchar *at,
815                         const guchar *end,
816                         guchar *cls,
817                         gulong *tag,
818                         gint *off,
819                         gint *len)
820 {
821 	gint cb1, cb2;
822 
823 	g_assert (at != NULL);
824 	g_assert (end != NULL);
825 	g_assert (end >= at);
826 	g_assert (off != NULL);
827 	g_assert (len != NULL);
828 
829 	if (!atlv_parse_cls_tag (at, end, cls, tag, &cb1))
830 		return FALSE;
831 	*len = atlv_parse_length (at + cb1, end, &cb2);
832 	if (*len < -1)
833 		return FALSE;
834 	*off = cb1 + cb2;
835 	if (*len >= 0 && at + *off + *len > end)
836 		return FALSE;
837 	return TRUE;
838 }
839 
840 static const gchar *
atlv_parse_der_tag(guchar cls,gulong tag,gint off,gint len,GBytes * data,const guchar ** at,Atlv * tlv)841 atlv_parse_der_tag (guchar cls,
842                     gulong tag,
843                     gint off,
844                     gint len,
845                     GBytes *data,
846                     const guchar **at,
847                     Atlv *tlv)
848 {
849 	const guchar *end;
850 	const gchar *ret;
851 	const guchar *beg;
852 	guchar ccls;
853 	gulong ctag;
854 	gint clen;
855 	gint coff;
856 	Atlv *child;
857 	Atlv *last;
858 
859 	g_assert (at != NULL);
860 	g_assert (tlv != NULL);
861 
862 	end = bytes_get_end (data);
863 	g_assert (*at <= end);
864 
865 	g_return_val_if_fail (*at + off + len <= end, "invalid length of tlv");
866 	if (len < 0 && !(cls & ASN1_CLASS_STRUCTURED))
867 		return "indefinite length on non-structured type";
868 
869 	beg = *at;
870 
871 	tlv->cls = cls;
872 	tlv->tag = tag;
873 	tlv->off = off;
874 	tlv->len = len;
875 	(*at) += off;
876 
877 	/* Structured TLV, with further TLVs inside */
878 	if (cls & ASN1_CLASS_STRUCTURED) {
879 		/* If not indefinite length, then calculate end up front */
880 		if (len >= 0)
881 			end = (*at) + len;
882 		last = NULL;
883 		while (*at < end) {
884 			if (!atlv_parse_cls_tag_len (*at, end, &ccls, &ctag, &coff, &clen))
885 				return "content is not encoded properly";
886 
887 			/* End if indefinite length? */
888 			if (len < 0 && ccls == ASN1_CLASS_UNIVERSAL && ctag == 0 && clen == 0) {
889 				(*at) += coff;
890 				break;
891 			}
892 
893 			/* Parse the child */
894 			child = atlv_new ();
895 			ret = atlv_parse_der_tag (ccls, ctag, coff, clen, data, at, child);
896 			if (ret != NULL) {
897 				atlv_free (child);
898 				return ret;
899 			}
900 
901 			/* Add the child to the right place */
902 			if (last == NULL)
903 				tlv->child = child;
904 			else
905 				last->next = child;
906 			last = child;
907 		}
908 
909 	/* Non-structured TLV, just a value */
910 	} else {
911 		tlv->value = g_bytes_new_with_free_func (*at, len,
912 		                                         (GDestroyNotify)g_bytes_unref,
913 		                                         g_bytes_ref (data));
914 		(*at) += len;
915 	}
916 
917 	/* Note the actual DER that we decoded */
918 	tlv->decoded = g_bytes_new_with_free_func (beg, *at - beg,
919 	                                           (GDestroyNotify)g_bytes_unref,
920 	                                           g_bytes_ref (data));
921 
922 	return NULL; /* Success */
923 }
924 
925 static const gchar *
atlv_parse_der(GBytes * data,Atlv * tlv)926 atlv_parse_der (GBytes *data,
927                 Atlv *tlv)
928 {
929 	const guchar *end;
930 	const guchar *at;
931 	const gchar *ret;
932 	guchar cls;
933 	gulong tag;
934 	gint off;
935 	gint len;
936 	gsize size;
937 
938 	at = g_bytes_get_data (data, &size);
939 	g_return_val_if_fail (at != NULL, FALSE);
940 	end = at + size;
941 
942 	if (!atlv_parse_cls_tag_len (at, end, &cls, &tag, &off, &len))
943 		return "content is not encoded properly";
944 
945 	ret = atlv_parse_der_tag (cls, tag, off, len, data, &at, tlv);
946 	if (ret != NULL)
947 		return ret;
948 
949 	if (at != end)
950 		return "extra unexpected trailing data";
951 
952 	return NULL; /* Success */
953 }
954 
955 /* -------------------------------------------------------------------------
956  * DECODING
957  */
958 
959 static gboolean
anode_decode_choice(GNode * node,Atlv * tlv)960 anode_decode_choice (GNode *node,
961                      Atlv *tlv)
962 {
963 	gboolean have = FALSE;
964 	GNode *child;
965 	Anode *an;
966 
967 	for (child = node->children; child; child = child->next) {
968 		an = (Anode*)child->data;
969 		if (anode_decode_one (child, tlv)) {
970 			an->chosen = 1;
971 			have = TRUE;
972 		} else {
973 			an->chosen = 0;
974 		}
975 	}
976 
977 	if (!have)
978 		return anode_failure (node, "no choice is present");
979 
980 	return TRUE;
981 }
982 
983 static gboolean
anode_decode_sequence_or_set(GNode * node,Atlv * tlv)984 anode_decode_sequence_or_set (GNode *node,
985                               Atlv *tlv)
986 {
987 	Atlv *ctlv;
988 	gulong tag;
989 	gint i;
990 
991 	/*
992 	 * The reason we can parse a set just like a sequence, is because in DER,
993 	 * the order of the SET is predefined by the tags. In addition the definitions
994 	 * we have are sorted.
995 	 */
996 
997 	/* Tags must be in ascending order */
998 	if (anode_def_type (node) == EGG_ASN1X_SET) {
999 		for (ctlv = tlv->child, i = 0; ctlv != NULL; ctlv = ctlv->next, i++) {
1000 			if (i > 0 && tag > ctlv->tag)
1001 				return anode_failure (node, "content must be in ascending order");
1002 			tag = ctlv->tag;
1003 		}
1004 	}
1005 
1006 	return anode_decode_anything (node->children, tlv->child);
1007 }
1008 
1009 static gboolean
anode_decode_sequence_or_set_of(GNode * node,Atlv * tlv)1010 anode_decode_sequence_or_set_of (GNode *node,
1011                                  Atlv *tlv)
1012 {
1013 	Atlv *ctlv;
1014 	GNode *child, *other;
1015 	gulong tag;
1016 	gint i;
1017 
1018 	/* The first child */
1019 	child = node->children;
1020 	g_return_val_if_fail (child, FALSE);
1021 
1022 	for (ctlv = tlv->child, i = 0; ctlv != NULL; ctlv = ctlv->next, i++) {
1023 
1024 		/* Tag must have same tag as top */
1025 		if (i == 0)
1026 			tag = anode_calc_tag (child);
1027 		else if (tag != G_MAXULONG && ctlv->tag != tag)
1028 			return anode_failure (node, "invalid mismatched content");
1029 
1030 		/* TODO: Set of must be in ascending order in DER encoding */
1031 
1032 		if (i == 0) {
1033 			other = child;
1034 		} else {
1035 			other = anode_clone (child);
1036 			g_node_append (node, other);
1037 		}
1038 
1039 		if (!anode_decode_one (other, ctlv))
1040 			return FALSE;
1041 	}
1042 
1043 	return TRUE;
1044 }
1045 
1046 static gboolean
anode_decode_bit_string(GNode * node,Atlv * tlv)1047 anode_decode_bit_string (GNode *node,
1048                          Atlv *tlv)
1049 {
1050 	Anode *an = node->data;
1051 	guchar empty, mask;
1052 	GBytes *value;
1053 	const guchar *buf;
1054 	gsize len;
1055 
1056 	buf = g_bytes_get_data (tlv->value, &len);
1057 	if (len == 0)
1058 		return anode_failure (node, "invalid length bit string");
1059 
1060 	/* The first byte is the number of empty bits */
1061 	empty = buf[0];
1062 	if (empty >= 8)
1063 		return anode_failure (node, "invalid number of empty bits");
1064 
1065 	/* Free bits at end must be zero */
1066 	mask = 0xFF >> (8 - empty);
1067 	if (len > 1 && buf[len - 1] & mask)
1068 		return anode_failure (node, "bit string has invalid trailing bits");
1069 
1070 	value = g_bytes_new_from_bytes (tlv->value, 1, len - 1);
1071 	anode_take_value (node, value);
1072 	an = node->data;
1073 	an->bits_empty = empty;
1074 	return TRUE;
1075 }
1076 
1077 static gboolean
anode_decode_primitive(GNode * node,Atlv * tlv,gint flags)1078 anode_decode_primitive (GNode *node,
1079                         Atlv *tlv,
1080                         gint flags)
1081 {
1082 	/* Must not have any tlv children */
1083 	g_assert (tlv->child == NULL);
1084 
1085 	switch (anode_def_type (node)) {
1086 
1087 	/* Handle bit strings specially */
1088 	case EGG_ASN1X_BIT_STRING:
1089 		return anode_decode_bit_string (node, tlv);
1090 
1091 	/* The primitive value types */
1092 	case EGG_ASN1X_INTEGER:
1093 	case EGG_ASN1X_ENUMERATED:
1094 	case EGG_ASN1X_BOOLEAN:
1095 	case EGG_ASN1X_OCTET_STRING:
1096 	case EGG_ASN1X_OBJECT_ID:
1097 	case EGG_ASN1X_NULL:
1098 	case EGG_ASN1X_TIME:
1099 	case EGG_ASN1X_UTC_TIME:
1100 	case EGG_ASN1X_GENERALIZED_TIME:
1101 	case EGG_ASN1X_GENERAL_STRING:
1102 	case EGG_ASN1X_NUMERIC_STRING:
1103 	case EGG_ASN1X_IA5_STRING:
1104 	case EGG_ASN1X_TELETEX_STRING:
1105 	case EGG_ASN1X_PRINTABLE_STRING:
1106 	case EGG_ASN1X_UNIVERSAL_STRING:
1107 	case EGG_ASN1X_BMP_STRING:
1108 	case EGG_ASN1X_UTF8_STRING:
1109 	case EGG_ASN1X_VISIBLE_STRING:
1110 		anode_set_value (node, tlv->value);
1111 		return TRUE;
1112 
1113 	/* Just use the 'parsed' which is automatically set */
1114 	case EGG_ASN1X_ANY:
1115 		return TRUE;
1116 
1117 	case EGG_ASN1X_CHOICE:
1118 		return anode_decode_choice (node, tlv);
1119 	}
1120 
1121 	return anode_failure (node, "primitive value of an unexpected type"); /* UNREACHABLE: tag validation? */
1122 }
1123 
1124 static gboolean
anode_decode_structured(GNode * node,Atlv * tlv,gint flags)1125 anode_decode_structured (GNode *node,
1126                          Atlv *tlv,
1127                          gint flags)
1128 {
1129 	switch (anode_def_type (node)) {
1130 
1131 	/* Just use the 'parsed' which is automatically set */
1132 	case EGG_ASN1X_ANY:
1133 	case EGG_ASN1X_GENERAL_STRING:
1134 	case EGG_ASN1X_OCTET_STRING:
1135 	case EGG_ASN1X_NUMERIC_STRING:
1136 	case EGG_ASN1X_IA5_STRING:
1137 	case EGG_ASN1X_TELETEX_STRING:
1138 	case EGG_ASN1X_PRINTABLE_STRING:
1139 	case EGG_ASN1X_UNIVERSAL_STRING:
1140 	case EGG_ASN1X_BMP_STRING:
1141 	case EGG_ASN1X_UTF8_STRING:
1142 	case EGG_ASN1X_VISIBLE_STRING:
1143 		return TRUE;
1144 
1145 	case EGG_ASN1X_CHOICE:
1146 		return anode_decode_choice (node, tlv);
1147 
1148 	case EGG_ASN1X_SEQUENCE:
1149 	case EGG_ASN1X_SET:
1150 		return anode_decode_sequence_or_set (node, tlv);
1151 
1152 	case EGG_ASN1X_SEQUENCE_OF:
1153 	case EGG_ASN1X_SET_OF:
1154 		return anode_decode_sequence_or_set_of (node, tlv);
1155 
1156 	default:
1157 		return anode_failure (node, "structured value of an unexpected type"); /* UNREACHABLE: tag validation? */
1158 	}
1159 }
1160 
1161 static gboolean
anode_decode_one_without_tag(GNode * node,Atlv * tlv,gint flags)1162 anode_decode_one_without_tag (GNode *node,
1163                               Atlv *tlv,
1164                               gint flags)
1165 {
1166 	gboolean ret;
1167 	Anode *an;
1168 
1169 	/* An explicit, wrapped tag */
1170 	if (anode_calc_explicit_for_flags (node, flags, NULL)) {
1171 		if ((tlv->cls & ASN1_CLASS_CONTEXT_SPECIFIC) == 0)
1172 			return anode_failure (node, "missing context specific tag");
1173 		if (tlv->child == NULL)
1174 			return anode_failure (node, "missing context specific child");
1175 		if (tlv->child->next != NULL)
1176 			return anode_failure (node, "multiple context specific children");
1177 		flags &= ~FLAG_TAG;
1178 		ret = anode_decode_one_without_tag (node, tlv->child, flags);
1179 
1180 	/* Structured value */
1181 	} else if (tlv->cls & ASN1_CLASS_STRUCTURED) {
1182 		ret = anode_decode_structured (node, tlv, flags);
1183 
1184 	/* A primitive simple value */
1185 	} else {
1186 		ret = anode_decode_primitive (node, tlv, flags);
1187 	}
1188 
1189 	/* Mark which tlv we used for this node */
1190 	if (ret) {
1191 		an = node->data;
1192 		atlv_free (an->parsed);
1193 		an->parsed = atlv_dup (tlv, FALSE);
1194 	}
1195 
1196 	return ret;
1197 }
1198 
1199 static gboolean
anode_decode_one(GNode * node,Atlv * tlv)1200 anode_decode_one (GNode *node,
1201                   Atlv *tlv)
1202 {
1203 	gint flags = anode_def_flags (node);
1204 	gulong tag;
1205 
1206 	tag = anode_calc_tag_for_flags (node, flags);
1207 
1208 	/* We don't know what the tag is supposed to be */
1209 	if (tag == G_MAXULONG)
1210 		tag = tlv->tag;
1211 
1212 	/* We have no match */
1213 	if (tag != tlv->tag)
1214 		return anode_failure (node, "decoded tag did not match expected");
1215 
1216 	return anode_decode_one_without_tag (node, tlv, flags);
1217 }
1218 
1219 static gboolean
anode_decode_option_or_default(GNode * node)1220 anode_decode_option_or_default (GNode *node)
1221 {
1222 	gint flags = anode_def_flags (node);
1223 
1224 	if (flags & FLAG_OPTION || flags & FLAG_DEFAULT) {
1225 		anode_clr_value (node);
1226 		return TRUE;
1227 	}
1228 
1229 	return FALSE;
1230 }
1231 
1232 static gboolean
anode_decode_anything(GNode * node,Atlv * tlv)1233 anode_decode_anything (GNode *node,
1234                        Atlv *tlv)
1235 {
1236 	GNode *prev = NULL;
1237 	GNode *next;
1238 	gulong tag;
1239 	gint flags;
1240 
1241 	g_assert (node != NULL);
1242 
1243 	while (tlv != NULL) {
1244 		if (node == NULL)
1245 			return anode_failure (prev, "encountered extra tag");
1246 
1247 		flags = anode_def_flags (node);
1248 		tag = anode_calc_tag_for_flags (node, flags);
1249 
1250 		/* We don't know what the tag is supposed to be */
1251 		if (tag == G_MAXULONG)
1252 			tag = tlv->tag;
1253 
1254 		/* We have no match */
1255 		if (tag != tlv->tag) {
1256 
1257 			/* See if we can skip this node */
1258 			if (anode_decode_option_or_default (node))
1259 				next = g_node_next_sibling (node);
1260 			else
1261 				next = NULL;
1262 
1263 			if (next == NULL)
1264 				return anode_failure (node, "decoded tag did not match expected");
1265 
1266 			prev = node;
1267 			node = next;
1268 			continue;
1269 		}
1270 
1271 		if (!anode_decode_one_without_tag (node, tlv, flags))
1272 			return FALSE;
1273 
1274 		/* Next node and tag */
1275 		prev = node;
1276 		node = g_node_next_sibling (node);
1277 		tlv = tlv->next;
1278 	}
1279 
1280 	/* We have no values for these nodes */
1281 	while (node != NULL) {
1282 		if (anode_decode_option_or_default (node))
1283 			node = g_node_next_sibling (node);
1284 		else
1285 			return anode_failure (node, "no decoded value");
1286 	}
1287 
1288 	return TRUE;
1289 }
1290 
1291 gboolean
egg_asn1x_decode_full(GNode * asn,GBytes * data,gint options)1292 egg_asn1x_decode_full (GNode *asn,
1293                        GBytes *data,
1294                        gint options)
1295 {
1296 	const gchar *msg;
1297 	gboolean ret;
1298 	Anode *an;
1299 	Atlv *tlv;
1300 
1301 	g_return_val_if_fail (asn != NULL, FALSE);
1302 	g_return_val_if_fail (data != NULL, FALSE);
1303 
1304 	egg_asn1x_clear (asn);
1305 
1306 	tlv = atlv_new ();
1307 	msg = atlv_parse_der (data, tlv);
1308 	if (msg == NULL) {
1309 		ret = anode_decode_anything (asn, tlv);
1310 
1311 	/* A failure, set the message manually so it doesn't get a prefix */
1312 	} else {
1313 		an = asn->data;
1314 		g_free (an->failure);
1315 		an->failure = g_strdup (msg);
1316 		ret = FALSE;
1317 	}
1318 
1319 	atlv_free (tlv);
1320 	if (ret == FALSE)
1321 		return FALSE;
1322 
1323 	return egg_asn1x_validate (asn, !(options & EGG_ASN1X_NO_STRICT));
1324 }
1325 
1326 gboolean
egg_asn1x_decode(GNode * asn,GBytes * data)1327 egg_asn1x_decode (GNode *asn,
1328                   GBytes *data)
1329 {
1330 	g_return_val_if_fail (asn != NULL, FALSE);
1331 	g_return_val_if_fail (data != NULL, FALSE);
1332 
1333 	return egg_asn1x_decode_full (asn, data, 0);
1334 }
1335 
1336 /* -----------------------------------------------------------------------------------
1337  * UNPARSE
1338  */
1339 
1340 static void
atlv_unparse_len(gulong len,guchar * ans,gint * cb)1341 atlv_unparse_len (gulong len,
1342                   guchar *ans,
1343                   gint *cb)
1344 {
1345 	guchar temp[sizeof (gulong)];
1346 	gint k;
1347 
1348 	g_assert (cb);
1349 
1350 	/* short form */
1351 	if (len < 128) {
1352 		if (ans != NULL)
1353 			ans[0] = (unsigned char)len;
1354 		*cb = 1;
1355 
1356 	/* Long form */
1357 	} else {
1358 		k = 0;
1359 		while (len) {
1360 			temp[k++] = len & 0xFF;
1361 			len = len >> 8;
1362 		}
1363 		*cb = k + 1;
1364 		if (ans != NULL) {
1365 			ans[0] = ((unsigned char) k & 0x7F) + 128;
1366 			while (k--)
1367 				ans[*cb - 1 - k] = temp[k];
1368 		}
1369 	}
1370 }
1371 
1372 static gint
atlv_unparse_cls_tag_len(guchar * data,gsize n_data,guchar cls,gulong tag,gint len)1373 atlv_unparse_cls_tag_len (guchar *data,
1374                           gsize n_data,
1375                           guchar cls,
1376                           gulong tag,
1377                           gint len)
1378 {
1379 	guchar temp[sizeof(gulong)];
1380 	gint cb;
1381 	gint off = 0;
1382 	gint k;
1383 
1384 	/* Short form */
1385 	if (tag < 31) {
1386 		off += 1;
1387 		if (data) {
1388 			g_assert (n_data >= off);
1389 			data[0] = (cls & 0xE0) + ((guchar) (tag & 0x1F));
1390 		}
1391 	/* Long form */
1392 	} else {
1393 		k = 0;
1394 		while (tag) {
1395 			temp[k++] = tag & 0x7F;
1396 			tag = tag >> 7;
1397 		}
1398 		off = k + 1;
1399 		if (data) {
1400 			g_assert (n_data >= off);
1401 			data[0] = (cls & 0xE0) + 31;
1402 			while (data && k--)
1403 				data[off - 1 - k] = temp[k] + 128;
1404 			data[off - 1] -= 128;
1405 		}
1406 	}
1407 
1408 	/* And now the length */
1409 	cb = n_data - off;
1410 	atlv_unparse_len (len, data ? data + off : NULL, &cb);
1411 	off += cb;
1412 
1413 	g_assert (!data || n_data >= off);
1414 	return off;
1415 }
1416 
1417 static void
atlv_unparse_der(Atlv * tlv,guchar ** at,guchar * end)1418 atlv_unparse_der (Atlv *tlv,
1419                   guchar **at,
1420                   guchar *end)
1421 {
1422 	const guchar *exp;
1423 	const guchar *buf;
1424 	guchar *p;
1425 	guchar mask;
1426 	Atlv *ctlv;
1427 	gint off;
1428 	gsize len;
1429 
1430 	g_assert (*at <= end);
1431 
1432 	off = atlv_unparse_cls_tag_len (*at, end - *at, tlv->cls,
1433 	                                tlv->tag, tlv->len);
1434 	g_assert (off == tlv->off);
1435 	(*at) += off;
1436 
1437 	/* Write a value */
1438 	if (tlv->value) {
1439 		buf = g_bytes_get_data (tlv->value, &len);
1440 		p = *at;
1441 
1442 		/* Special behavior for bit strings */
1443 		if (tlv->prefix_for_bit_string) {
1444 			g_assert (len + 1 == tlv->len);
1445 			p[0] = (guchar)tlv->bits_empty;
1446 			memcpy (p + 1, buf, len);
1447 
1448 			/* Set the extra bits to zero */
1449 			if (len && tlv->bits_empty) {
1450 				mask = 0xFF >> (8 - tlv->bits_empty);
1451 				p[len] &= ~mask;
1452 			}
1453 			p += len + 1;
1454 
1455 		/* Special behavior for prefixed integers */
1456 		} else if (tlv->prefix_with_zero_byte) {
1457 			g_assert (len + 1 == tlv->len);
1458 			p[0] = 0;
1459 			memcpy (p + 1, buf, len);
1460 			p += len + 1;
1461 
1462 		/* Standard behavior */
1463 		} else {
1464 			g_assert (len == tlv->len);
1465 			memcpy (p, buf, len);
1466 			p += len;
1467 		}
1468 
1469 		*at = p;
1470 
1471 	/* Write a bunch of child TLV's */
1472 	} else {
1473 		for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next) {
1474 			exp = *at + ctlv->len + ctlv->off;
1475 			atlv_unparse_der (ctlv, at, end);
1476 			g_assert (exp == *at);
1477 		}
1478 	}
1479 
1480 	g_assert (*at <= end);
1481 }
1482 
1483 static GBytes *
atlv_unparse_to_bytes(Atlv * tlv,EggAllocator allocator)1484 atlv_unparse_to_bytes (Atlv *tlv,
1485                        EggAllocator allocator)
1486 {
1487 	GBytes *bytes;
1488 	guchar *data;
1489 	guchar *at;
1490 	gint len;
1491 
1492 	/* Allocate enough memory for entire thingy */
1493 	len = tlv->off + tlv->len;
1494 	g_return_val_if_fail (len != 0, NULL);
1495 
1496 	bytes = bytes_new_with_allocator (allocator, &data, len);
1497 	g_return_val_if_fail (bytes != NULL, NULL);
1498 
1499 	at = data;
1500 	atlv_unparse_der (tlv, &at, data + len);
1501 	g_assert (at == data + len);
1502 
1503 	return bytes;
1504 }
1505 
1506 typedef struct {
1507 	GBytes *bytes;
1508 	Atlv *tlv;
1509 } SortPair;
1510 
1511 static gint
compare_sort_pair(gconstpointer a,gconstpointer b)1512 compare_sort_pair (gconstpointer a,
1513                    gconstpointer b)
1514 {
1515 	const SortPair *sa = a;
1516 	const SortPair *sb = b;
1517 	return g_bytes_compare (sa->bytes, sb->bytes);
1518 }
1519 
1520 static void
atlv_sort_perform(Atlv * tlv,EggAllocator allocator)1521 atlv_sort_perform (Atlv *tlv,
1522                    EggAllocator allocator)
1523 {
1524 	GList *pairs, *l;
1525 	SortPair *pair;
1526 	GBytes *bytes;
1527 	Atlv *ctlv;
1528 	Atlv *last;
1529 	gboolean sort;
1530 
1531 	for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next)
1532 		atlv_sort_perform (ctlv, allocator);
1533 
1534 	if (!tlv->sorted)
1535 		return;
1536 
1537 	pairs = NULL;
1538 	for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next) {
1539 		bytes = atlv_unparse_to_bytes (ctlv, allocator);
1540 		g_return_if_fail (bytes != NULL);
1541 
1542 		pair = g_slice_new0 (SortPair);
1543 		pair->bytes = bytes;
1544 		pair->tlv = ctlv;
1545 		pairs = g_list_prepend (pairs, pair);
1546 	}
1547 
1548 	/* Only sort of the above unparse completed for all */
1549 	sort = ctlv == NULL;
1550 	last = NULL;
1551 
1552 	pairs = g_list_sort (pairs, compare_sort_pair);
1553 	for (l = pairs; l != NULL; l = g_list_next (l)) {
1554 		pair = l->data;
1555 
1556 		/* Only if the sort completed */
1557 		if (sort) {
1558 			if (last == NULL)
1559 				tlv->child = pair->tlv;
1560 			else
1561 				last->next = pair->tlv;
1562 			last = pair->tlv;
1563 		}
1564 
1565 		g_bytes_unref (pair->bytes);
1566 		g_slice_free (SortPair, pair);
1567 	}
1568 
1569 	g_list_free (pairs);
1570 }
1571 
1572 static void
anode_build_cls_tag_len(GNode * node,Atlv * tlv,gint len)1573 anode_build_cls_tag_len (GNode *node,
1574                          Atlv *tlv,
1575                          gint len)
1576 {
1577 	gboolean explicit = FALSE;
1578 	guchar cls_type;
1579 	gint flags;
1580 
1581 	/* One for the prefix character */
1582 	if (tlv->prefix_for_bit_string ||
1583 	    tlv->prefix_with_zero_byte)
1584 		len += 1;
1585 
1586 	/* Figure out the basis if the class */
1587 	switch (anode_def_type (node)) {
1588 	case EGG_ASN1X_INTEGER:
1589 	case EGG_ASN1X_BOOLEAN:
1590 	case EGG_ASN1X_BIT_STRING:
1591 	case EGG_ASN1X_OCTET_STRING:
1592 	case EGG_ASN1X_OBJECT_ID:
1593 	case EGG_ASN1X_TIME:
1594 	case EGG_ASN1X_UTC_TIME:
1595 	case EGG_ASN1X_GENERALIZED_TIME:
1596 	case EGG_ASN1X_ENUMERATED:
1597 	case EGG_ASN1X_GENERAL_STRING:
1598 	case EGG_ASN1X_NUMERIC_STRING:
1599 	case EGG_ASN1X_IA5_STRING:
1600 	case EGG_ASN1X_TELETEX_STRING:
1601 	case EGG_ASN1X_PRINTABLE_STRING:
1602 	case EGG_ASN1X_UNIVERSAL_STRING:
1603 	case EGG_ASN1X_BMP_STRING:
1604 	case EGG_ASN1X_UTF8_STRING:
1605 	case EGG_ASN1X_VISIBLE_STRING:
1606 	case EGG_ASN1X_NULL:
1607 		tlv->cls = ASN1_CLASS_UNIVERSAL;
1608 		break;
1609 	/* Container types */
1610 	case EGG_ASN1X_SEQUENCE:
1611 	case EGG_ASN1X_SET:
1612 	case EGG_ASN1X_SEQUENCE_OF:
1613 	case EGG_ASN1X_SET_OF:
1614 		tlv->cls = (ASN1_CLASS_STRUCTURED | ASN1_CLASS_UNIVERSAL);
1615 		break;
1616 
1617 	/* Transparent types shouldn't get here */
1618 	case EGG_ASN1X_ANY:
1619 	case EGG_ASN1X_CHOICE:
1620 	default:
1621 		g_assert_not_reached ();
1622 	};
1623 
1624 	flags = anode_def_flags (node);
1625 
1626 	/* Build up the class */
1627 	if (flags & FLAG_TAG) {
1628 		explicit = anode_calc_explicit_for_flags (node, flags, &cls_type);
1629 		if (explicit)
1630 			flags &= ~FLAG_TAG;
1631 		else
1632 			tlv->cls |= cls_type;
1633 	}
1634 
1635 	/* Setup the class */
1636 	tlv->tag = anode_calc_tag_for_flags (node, flags);
1637 
1638 	/* The offset and length */
1639 	tlv->len = len;
1640 	tlv->off = atlv_unparse_cls_tag_len (NULL, 0, tlv->cls, tlv->tag, len);
1641 }
1642 
1643 static Atlv *
anode_build_value(GNode * node)1644 anode_build_value (GNode *node)
1645 {
1646 	Anode *an = node->data;
1647 	Atlv *tlv;
1648 	gsize len;
1649 
1650 	/* Fill this in based on the value */
1651 	if (an->value == NULL)
1652 		return NULL;
1653 
1654 	tlv = atlv_new ();
1655 	tlv->value = g_bytes_ref (an->value);
1656 
1657 	len = g_bytes_get_size (an->value);
1658 	anode_build_cls_tag_len (node, tlv, len);
1659 	return tlv;
1660 }
1661 
1662 static Atlv *
anode_build_bit_string(GNode * node)1663 anode_build_bit_string (GNode *node)
1664 {
1665 	Anode *an = node->data;
1666 	Atlv *tlv;
1667 	gsize len;
1668 
1669 	if (an->value == NULL)
1670 		return NULL;
1671 
1672 	tlv = atlv_new ();
1673 	tlv->value = g_bytes_ref (an->value);
1674 	tlv->bits_empty = an->bits_empty;
1675 	tlv->prefix_for_bit_string = 1;
1676 
1677 	len = g_bytes_get_size (an->value);
1678 	anode_build_cls_tag_len (node, tlv, len);
1679 	return tlv;
1680 }
1681 
1682 static Atlv *
anode_build_integer(GNode * node)1683 anode_build_integer (GNode *node)
1684 {
1685 	Anode *an = node->data;
1686 	const guchar *buf;
1687 	gboolean sign;
1688 	gsize len;
1689 	Atlv *tlv;
1690 
1691 	if (an->value == NULL)
1692 		return NULL;
1693 
1694 	tlv = atlv_new ();
1695 	tlv->value = g_bytes_ref (an->value);
1696 
1697 	buf = g_bytes_get_data (an->value, &len);
1698 	if (an->guarantee_unsigned) {
1699 
1700 		/*
1701 		 * In two's complement (which DER is) this would be negative, add a zero
1702 		 * byte so that it isn't. Here we just note that the result will be one
1703 		 * byte longer.
1704 		 */
1705 		sign = !!(buf[0] & 0x80);
1706 		if (sign)
1707 			tlv->prefix_with_zero_byte = 1;
1708 	}
1709 
1710 	anode_build_cls_tag_len (node, tlv, len);
1711 	return tlv;
1712 }
1713 
1714 static Atlv *
anode_build_any(GNode * node)1715 anode_build_any (GNode *node)
1716 {
1717 	Atlv *parsed;
1718 
1719 	/*
1720 	 * Fill this in based on already parsed TLVs. It is assumed
1721 	 * that any explicit tags are already present, and the functions
1722 	 * for managing ANY try to enforce this.
1723 	 */
1724 
1725 	parsed = anode_get_parsed (node);
1726 	if (parsed != NULL)
1727 		return atlv_dup (parsed, FALSE);
1728 
1729 	return NULL;
1730 }
1731 
1732 static Atlv *
anode_build_choice(GNode * node,gboolean want)1733 anode_build_choice (GNode *node,
1734                     gboolean want)
1735 {
1736 	GNode *child;
1737 
1738 	g_assert (anode_def_type (node) == EGG_ASN1X_CHOICE);
1739 
1740 	child = egg_asn1x_get_choice (node);
1741 
1742 	/* Should have been checked by a previous validate */
1743 	g_return_val_if_fail (child != NULL, NULL);
1744 
1745 	return anode_build_anything (child, want);
1746 }
1747 
1748 static Atlv *
anode_build_structured(GNode * node,gboolean want)1749 anode_build_structured (GNode *node,
1750                         gboolean want)
1751 {
1752 	gboolean child_want;
1753 	Atlv *last;
1754 	Atlv *ctlv;
1755 	Atlv *tlv;
1756 	GNode *child;
1757 	gint type;
1758 	gint len;
1759 
1760 	type = anode_def_type (node);
1761 	child_want = want;
1762 	last = NULL;
1763 	len = 0;
1764 
1765 	if (type == EGG_ASN1X_SEQUENCE_OF || type == EGG_ASN1X_SET_OF)
1766 		child_want = FALSE;
1767 	if (anode_def_flags (node) & FLAG_OPTION)
1768 		want = FALSE;
1769 
1770 	tlv = atlv_new ();
1771 	for (child = node->children; child != NULL; child = child->next) {
1772 		ctlv = anode_build_anything (child, child_want);
1773 		if (ctlv != NULL) {
1774 			if (last == NULL)
1775 				tlv->child = ctlv;
1776 			else
1777 				last->next = ctlv;
1778 			last = ctlv;
1779 			len += ctlv->off + ctlv->len;
1780 		}
1781 	}
1782 
1783 	if (last == NULL) {
1784 		/* See if we should encode an empty set or seq of */
1785 		if (type == EGG_ASN1X_SEQUENCE_OF || type == EGG_ASN1X_SET_OF) {
1786 			if (!want) {
1787 				atlv_free (tlv);
1788 				return NULL;
1789 			}
1790 		} else if (!want) {
1791 			atlv_free (tlv);
1792 			return NULL;
1793 		}
1794 	}
1795 
1796 	anode_build_cls_tag_len (node, tlv, len);
1797 
1798 	if (type == EGG_ASN1X_SET_OF)
1799 		tlv->sorted = 1;
1800 
1801 	return tlv;
1802 }
1803 
1804 static Atlv *
anode_build_maybe_explicit(GNode * node,Atlv * tlv,gint flags)1805 anode_build_maybe_explicit (GNode *node,
1806                             Atlv *tlv,
1807                             gint flags)
1808 {
1809 	guchar cls_type;
1810 	Atlv *wrap;
1811 
1812 	/* Now wrap in explicit tag if that's the case */
1813 	if (anode_calc_explicit_for_flags (node, flags, &cls_type)) {
1814 		wrap = atlv_new ();
1815 		wrap->cls = (ASN1_CLASS_STRUCTURED | cls_type);
1816 		wrap->tag = anode_calc_tag (node);
1817 		wrap->len = tlv->off + tlv->len;
1818 		wrap->off = atlv_unparse_cls_tag_len (NULL, 0, wrap->cls, wrap->tag, wrap->len);
1819 		wrap->child = tlv;
1820 		tlv = wrap;
1821 	}
1822 
1823 	return tlv;
1824 }
1825 
1826 static Atlv *
anode_build_anything_for_flags(GNode * node,gboolean want,gint flags)1827 anode_build_anything_for_flags (GNode *node,
1828                                 gboolean want,
1829                                 gint flags)
1830 {
1831 	Atlv *tlv;
1832 
1833 	switch (anode_def_type (node)) {
1834 	case EGG_ASN1X_BIT_STRING:
1835 		tlv = anode_build_bit_string (node);
1836 		break;
1837 	case EGG_ASN1X_INTEGER:
1838 		tlv = anode_build_integer (node);
1839 		break;
1840 	case EGG_ASN1X_BOOLEAN:
1841 	case EGG_ASN1X_OCTET_STRING:
1842 	case EGG_ASN1X_OBJECT_ID:
1843 	case EGG_ASN1X_TIME:
1844 	case EGG_ASN1X_UTC_TIME:
1845 	case EGG_ASN1X_GENERALIZED_TIME:
1846 	case EGG_ASN1X_ENUMERATED:
1847 	case EGG_ASN1X_GENERAL_STRING:
1848 	case EGG_ASN1X_NUMERIC_STRING:
1849 	case EGG_ASN1X_IA5_STRING:
1850 	case EGG_ASN1X_TELETEX_STRING:
1851 	case EGG_ASN1X_PRINTABLE_STRING:
1852 	case EGG_ASN1X_UNIVERSAL_STRING:
1853 	case EGG_ASN1X_BMP_STRING:
1854 	case EGG_ASN1X_UTF8_STRING:
1855 	case EGG_ASN1X_VISIBLE_STRING:
1856 	case EGG_ASN1X_NULL:
1857 		tlv = anode_build_value (node);
1858 		break;
1859 
1860 	/* Any should already have explicit tagging, so just return */
1861 	case EGG_ASN1X_ANY:
1862 		return anode_build_any (node);
1863 
1864 	case EGG_ASN1X_SEQUENCE:
1865 	case EGG_ASN1X_SEQUENCE_OF:
1866 	case EGG_ASN1X_SET:
1867 	case EGG_ASN1X_SET_OF:
1868 		tlv = anode_build_structured (node, want);
1869 		break;
1870 
1871 	case EGG_ASN1X_CHOICE:
1872 		tlv = anode_build_choice (node, want);
1873 		break;
1874 
1875 	default:
1876 		g_assert_not_reached ();
1877 	}
1878 
1879 	if (tlv == NULL)
1880 		return NULL;
1881 
1882 	/* Now wrap in explicit tag if that's the case */
1883 	return anode_build_maybe_explicit (node, tlv, flags);
1884 }
1885 
1886 static Atlv *
anode_build_anything(GNode * node,gboolean want)1887 anode_build_anything (GNode *node,
1888                       gboolean want)
1889 {
1890 	return anode_build_anything_for_flags (node, want,
1891 	                                       anode_def_flags (node));
1892 }
1893 
1894 GBytes *
egg_asn1x_encode(GNode * asn,EggAllocator allocator)1895 egg_asn1x_encode (GNode *asn,
1896                   EggAllocator allocator)
1897 {
1898 	GBytes *bytes;
1899 	Atlv *tlv;
1900 
1901 	g_return_val_if_fail (asn != NULL, NULL);
1902 	g_return_val_if_fail (anode_def_type_is_real (asn), NULL);
1903 
1904 	if (!egg_asn1x_validate (asn, TRUE))
1905 		return NULL;
1906 
1907 	tlv = anode_build_anything (asn, TRUE);
1908 
1909 	/* The above validate should cause build not to return NULL */
1910 	g_return_val_if_fail (tlv != NULL, NULL);
1911 
1912 	atlv_sort_perform (tlv, allocator);
1913 
1914 	bytes = atlv_unparse_to_bytes (tlv, allocator);
1915 	atlv_free (tlv);
1916 	return bytes;
1917 }
1918 
1919 /* ----------------------------------------------------------------------------
1920  * VALUE READ/WRITE
1921  */
1922 
1923 static int
two_to_four_digit_year(int year)1924 two_to_four_digit_year (int year)
1925 {
1926 	time_t now;
1927 	struct tm tm;
1928 	int century, current;
1929 
1930 	g_return_val_if_fail (year >= 0 && year <= 99, -1);
1931 
1932 	/* Get the current year */
1933 	now = time (NULL);
1934 	g_return_val_if_fail (now >= 0, -1);
1935 	if (!gmtime_r (&now, &tm))
1936 		g_return_val_if_reached (-1);
1937 
1938 	current = (tm.tm_year % 100);
1939 	century = (tm.tm_year + 1900) - current;
1940 
1941 	/*
1942 	 * Check if it's within 40 years before the
1943 	 * current date.
1944 	 */
1945 	if (current < 40) {
1946 		if (year < current)
1947 			return century + year;
1948 		if (year > 100 - (40 - current))
1949 			return (century - 100) + year;
1950 	} else {
1951 		if (year < current && year > (current - 40))
1952 			return century + year;
1953 	}
1954 
1955 	/*
1956 	 * If it's after then adjust for overflows to
1957 	 * the next century.
1958 	 */
1959 	if (year < current)
1960 		return century + 100 + year;
1961 	else
1962 		return century + year;
1963 }
1964 
1965 static gboolean
parse_utc_time(const gchar * time,gsize n_time,struct tm * when,gint * offset)1966 parse_utc_time (const gchar *time, gsize n_time,
1967                 struct tm* when, gint *offset)
1968 {
1969 	const char *p, *e;
1970 	int year;
1971 
1972 	g_assert (when);
1973 	g_assert (time);
1974 	g_assert (offset);
1975 
1976 	/* YYMMDDhhmmss.ffff Z | +0000 */
1977 	if (n_time < 6 || n_time >= 28)
1978 		return FALSE;
1979 
1980 	/* Reset everything to default legal values */
1981 	memset (when, 0, sizeof (*when));
1982 	*offset = 0;
1983 	when->tm_mday = 1;
1984 
1985 	/* Select the digits part of it */
1986 	p = time;
1987 	for (e = p; *e >= '0' && *e <= '9'; ++e);
1988 
1989 	if (p + 2 <= e) {
1990 		year = atoin (p, 2);
1991 		p += 2;
1992 
1993 		/*
1994 		 * 40 years in the past is our century. 60 years
1995 		 * in the future is the next century.
1996 		 */
1997 		when->tm_year = two_to_four_digit_year (year) - 1900;
1998 	}
1999 	if (p + 2 <= e) {
2000 		when->tm_mon = atoin (p, 2) - 1;
2001 		p += 2;
2002 	}
2003 	if (p + 2 <= e) {
2004 		when->tm_mday = atoin (p, 2);
2005 		p += 2;
2006 	}
2007 	if (p + 2 <= e) {
2008 		when->tm_hour = atoin (p, 2);
2009 		p += 2;
2010 	}
2011 	if (p + 2 <= e) {
2012 		when->tm_min = atoin (p, 2);
2013 		p += 2;
2014 	}
2015 	if (p + 2 <= e) {
2016 		when->tm_sec = atoin (p, 2);
2017 		p += 2;
2018 	}
2019 
2020 	if (when->tm_year < 0 || when->tm_year > 9999 ||
2021 	    when->tm_mon < 0 || when->tm_mon > 11 ||
2022 	    when->tm_mday < 1 || when->tm_mday > 31 ||
2023 	    when->tm_hour < 0 || when->tm_hour > 23 ||
2024 	    when->tm_min < 0 || when->tm_min > 59 ||
2025 	    when->tm_sec < 0 || when->tm_sec > 59)
2026 		return FALSE;
2027 
2028 	/* Make sure all that got parsed */
2029 	if (p != e)
2030 		return FALSE;
2031 
2032 	/* Now the remaining optional stuff */
2033 	e = time + n_time;
2034 
2035 	/* See if there's a fraction, and discard it if so */
2036 	if (p < e && *p == '.' && p + 5 <= e)
2037 		p += 5;
2038 
2039 	/* See if it's UTC */
2040 	if (p < e && *p == 'Z') {
2041 		p += 1;
2042 
2043 	/* See if it has a timezone */
2044 	} else if ((*p == '-' || *p == '+') && p + 3 <= e) {
2045 		int off, neg;
2046 
2047 		neg = *p == '-';
2048 		++p;
2049 
2050 		off = atoin (p, 2) * 3600;
2051 		if (off < 0 || off > 86400)
2052 			return -1;
2053 		p += 2;
2054 
2055 		if (p + 2 <= e) {
2056 			off += atoin (p, 2) * 60;
2057 			p += 2;
2058 		}
2059 
2060 		/* Use TZ offset */
2061 		if (neg)
2062 			*offset = 0 - off;
2063 		else
2064 			*offset = off;
2065 	}
2066 
2067 	/* Make sure everything got parsed */
2068 	if (p != e)
2069 		return FALSE;
2070 
2071 	return TRUE;
2072 }
2073 
2074 static gboolean
parse_general_time(const gchar * time,gsize n_time,struct tm * when,gint * offset)2075 parse_general_time (const gchar *time, gsize n_time,
2076                     struct tm* when, gint *offset)
2077 {
2078 	const char *p, *e;
2079 
2080 	g_assert (time);
2081 	g_assert (when);
2082 	g_assert (offset);
2083 
2084 	/* YYYYMMDDhhmmss.ffff Z | +0000 */
2085 	if (n_time < 8 || n_time >= 30)
2086 		return FALSE;
2087 
2088 	/* Reset everything to default legal values */
2089 	memset (when, 0, sizeof (*when));
2090 	*offset = 0;
2091 	when->tm_mday = 1;
2092 
2093 	/* Select the digits part of it */
2094 	p = time;
2095 	for (e = p; *e >= '0' && *e <= '9'; ++e);
2096 
2097 	if (p + 4 <= e) {
2098 		when->tm_year = atoin (p, 4) - 1900;
2099 		p += 4;
2100 	}
2101 	if (p + 2 <= e) {
2102 		when->tm_mon = atoin (p, 2) - 1;
2103 		p += 2;
2104 	}
2105 	if (p + 2 <= e) {
2106 		when->tm_mday = atoin (p, 2);
2107 		p += 2;
2108 	}
2109 	if (p + 2 <= e) {
2110 		when->tm_hour = atoin (p, 2);
2111 		p += 2;
2112 	}
2113 	if (p + 2 <= e) {
2114 		when->tm_min = atoin (p, 2);
2115 		p += 2;
2116 	}
2117 	if (p + 2 <= e) {
2118 		when->tm_sec = atoin (p, 2);
2119 		p += 2;
2120 	}
2121 
2122 	if (when->tm_year < 0 || when->tm_year > 9999 ||
2123 	    when->tm_mon < 0 || when->tm_mon > 11 ||
2124 	    when->tm_mday < 1 || when->tm_mday > 31 ||
2125 	    when->tm_hour < 0 || when->tm_hour > 23 ||
2126 	    when->tm_min < 0 || when->tm_min > 59 ||
2127 	    when->tm_sec < 0 || when->tm_sec > 59)
2128 		return FALSE;
2129 
2130 	/* Make sure all that got parsed */
2131 	if (p != e)
2132 		return FALSE;
2133 
2134 	/* Now the remaining optional stuff */
2135 	e = time + n_time;
2136 
2137 	/* See if there's a fraction, and discard it if so */
2138 	if (p < e && *p == '.' && p + 5 <= e)
2139 		p += 5;
2140 
2141 	/* See if it's UTC */
2142 	if (p < e && *p == 'Z') {
2143 		p += 1;
2144 
2145 	/* See if it has a timezone */
2146 	} else if ((*p == '-' || *p == '+') && p + 3 <= e) {
2147 		int off, neg;
2148 
2149 		neg = *p == '-';
2150 		++p;
2151 
2152 		off = atoin (p, 2) * 3600;
2153 		if (off < 0 || off > 86400)
2154 			return -1;
2155 		p += 2;
2156 
2157 		if (p + 2 <= e) {
2158 			off += atoin (p, 2) * 60;
2159 			p += 2;
2160 		}
2161 
2162 		/* Use TZ offset */
2163 		if (neg)
2164 			*offset = 0 - off;
2165 		else
2166 			*offset = off;
2167 	}
2168 
2169 	/* Make sure everything got parsed */
2170 	if (p != e)
2171 		return FALSE;
2172 
2173 	return TRUE;
2174 }
2175 
2176 static gboolean
anode_read_time(GNode * node,GBytes * data,struct tm * when,glong * value)2177 anode_read_time (GNode *node,
2178                  GBytes *data,
2179                  struct tm *when,
2180                  glong *value)
2181 {
2182 	const gchar *buf;
2183 	gboolean ret;
2184 	gint offset = 0;
2185 	gint flags;
2186 	gint type;
2187 	gsize len;
2188 
2189 	g_assert (data != NULL);
2190 	g_assert (when != NULL);
2191 	g_assert (value != NULL);
2192 
2193 	flags = anode_def_flags (node);
2194 	type = anode_def_type (node);
2195 	buf = g_bytes_get_data (data, &len);
2196 
2197 	if (type == EGG_ASN1X_GENERALIZED_TIME)
2198 		ret = parse_general_time (buf, len, when, &offset);
2199 	else if (type == EGG_ASN1X_UTC_TIME)
2200 		ret = parse_utc_time (buf, len, when, &offset);
2201 	else if (flags & FLAG_GENERALIZED)
2202 		ret = parse_general_time (buf, len, when, &offset);
2203 	else if (flags & FLAG_UTC)
2204 		ret = parse_utc_time (buf, len, when, &offset);
2205 	else
2206 		g_return_val_if_reached (FALSE);
2207 
2208 	if (!ret)
2209 		return anode_failure (node, "invalid time content");
2210 
2211 	/* In order to work with 32 bit time_t. */
2212 	if (sizeof (time_t) <= 4 && when->tm_year >= 2038) {
2213 		*value = (time_t)2145914603;  /* 2037-12-31 23:23:23 */
2214 
2215 	/* Convert to seconds since epoch */
2216 	} else {
2217 		*value = timegm (when);
2218 		g_return_val_if_fail (*value >= 0, FALSE);
2219 		*value += offset;
2220 	}
2221 
2222 	return TRUE;
2223 }
2224 
2225 static gboolean
anode_read_integer_ulong(GNode * node,GBytes * data,gulong * value)2226 anode_read_integer_ulong (GNode *node,
2227                           GBytes *data,
2228                           gulong *value)
2229 {
2230 	const guchar *p;
2231 	gsize len;
2232 	gsize k;
2233 
2234 	p = g_bytes_get_data (data, &len);
2235 	if (len < 1 || len > sizeof (gulong))
2236 		return FALSE;
2237 
2238 	*value = 0;
2239 	for (k = 0; k < len; ++k)
2240 		*value |= p[k] << (8 * ((len - 1) - k));
2241 
2242 	return TRUE;
2243 }
2244 
2245 static void
anode_write_integer_ulong(gulong value,guchar * data,gsize * n_data)2246 anode_write_integer_ulong (gulong value,
2247                            guchar *data,
2248                            gsize *n_data)
2249 {
2250 	guchar buf[sizeof (gulong)];
2251 	gint bytes, i, off;
2252 	guchar *at;
2253 	gboolean sign;
2254 	gsize len;
2255 
2256 	for (i = 0; i < sizeof (gulong); ++i) {
2257 		off = sizeof (gulong) - (i + 1);
2258 		buf[i] = (value >> (off * 8)) & 0xFF;
2259 	}
2260 
2261 	for (bytes = sizeof (gulong) - 1; bytes >= 0; --bytes)
2262 		if (!buf[bytes])
2263 			break;
2264 
2265 	bytes = sizeof (gulong) - (bytes + 1);
2266 	if (bytes == 0)
2267 		bytes = 1;
2268 
2269 	/* If the first byte would make this negative, then add a zero */
2270 	at = buf + (sizeof (gulong) - bytes);
2271 	sign = !!(at[0] & 0x80);
2272 	len = bytes + (sign ? 1 : 0);
2273 
2274 	if (data) {
2275 		g_assert (*n_data >= len);
2276 		if (sign) {
2277 			data[0] = 0;
2278 			data++;
2279 		}
2280 		memcpy (data, at, bytes);
2281 	}
2282 
2283 	*n_data = len;
2284 }
2285 
2286 static GBytes *
anode_default_integer(GNode * node)2287 anode_default_integer (GNode *node)
2288 {
2289 	const gchar *defval;
2290 	EggAsn1xDef *opt;
2291 	gchar *end;
2292 	gulong value;
2293 	guchar *data;
2294 	gsize len;
2295 
2296 	if (!(anode_def_flags (node) & FLAG_DEFAULT))
2297 		return NULL;
2298 
2299 	/* Try to get a default */
2300 	opt = anode_opt_lookup (node, EGG_ASN1X_DEFAULT, NULL);
2301 	g_return_val_if_fail (opt != NULL, NULL);
2302 	g_return_val_if_fail (opt->value != NULL, NULL);
2303 	defval = opt->value;
2304 
2305 	opt = anode_opt_lookup (node, EGG_ASN1X_CONSTANT, defval);
2306 	if (opt != NULL) {
2307 		g_return_val_if_fail (opt->value != NULL, NULL);
2308 		defval = opt->value;
2309 	}
2310 
2311 	/* Parse out the default value */
2312 	value = strtoul (defval, &end, 10);
2313 	g_return_val_if_fail (end && !end[0], NULL);
2314 
2315 	anode_write_integer_ulong (value, NULL, &len);
2316 	data = g_malloc (len);
2317 	anode_write_integer_ulong (value, data, &len);
2318 	return g_bytes_new_take (data, len);
2319 }
2320 
2321 static gboolean
anode_read_string_struct(GNode * node,Atlv * tlv,gpointer value,gsize * n_value)2322 anode_read_string_struct (GNode *node,
2323                           Atlv *tlv,
2324                           gpointer value,
2325                           gsize *n_value)
2326 {
2327 	const guchar *buf;
2328 	gsize len;
2329 	Atlv *ctlv;
2330 	guchar *at;
2331 	gint remaining;
2332 
2333 	g_assert (tlv != NULL);
2334 	g_assert (tlv->cls & ASN1_CLASS_STRUCTURED);
2335 	g_assert (n_value != NULL);
2336 
2337 	at = value;
2338 	remaining = *n_value;
2339 	*n_value = 0;
2340 
2341 	for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next) {
2342 		if (ctlv->cls & ASN1_CLASS_STRUCTURED ||
2343 		    ctlv->value == NULL)
2344 			return FALSE;
2345 		buf = g_bytes_get_data (ctlv->value, &len);
2346 		*n_value += len;
2347 		if (value) {
2348 			if (remaining >= len)
2349 				memcpy (at, buf, len);
2350 			at += len;
2351 			remaining -= len;
2352 		}
2353 	}
2354 
2355 	if (value)
2356 		g_return_val_if_fail (remaining >= 0, FALSE);
2357 
2358 	return TRUE;
2359 }
2360 
2361 static gboolean
anode_read_string_simple(GNode * node,GBytes * data,gpointer value,gsize * n_value)2362 anode_read_string_simple (GNode *node,
2363                           GBytes *data,
2364                           gpointer value,
2365                           gsize *n_value)
2366 {
2367 	const guchar *buf;
2368 	gsize len;
2369 
2370 	g_assert (data != NULL);
2371 	g_assert (n_value != NULL);
2372 
2373 	buf = g_bytes_get_data (data, &len);
2374 	if (value) {
2375 		g_return_val_if_fail (*n_value >= len, FALSE);
2376 		memcpy (value, buf, len);
2377 	}
2378 
2379 	*n_value = len;
2380 	return TRUE;
2381 }
2382 
2383 static gboolean
anode_read_boolean(GNode * node,GBytes * data,gboolean * value)2384 anode_read_boolean (GNode *node,
2385                     GBytes *data,
2386                     gboolean *value)
2387 {
2388 	const guchar *buf;
2389 	gsize len;
2390 
2391 	g_assert (node != NULL);
2392 	g_assert (data != NULL);
2393 	g_assert (value != NULL);
2394 
2395 	buf = g_bytes_get_data (data, &len);
2396 	g_return_val_if_fail (len == 1, FALSE);
2397 	if (buf[0] == 0x00)
2398 		*value = FALSE;
2399 	else if (buf[0] == 0xFF)
2400 		*value = TRUE;
2401 	else
2402 		g_return_val_if_reached (FALSE);
2403 	return TRUE;
2404 }
2405 
2406 static void
anode_write_boolean(gboolean value,guchar * data,gsize * n_data)2407 anode_write_boolean (gboolean value,
2408                      guchar *data,
2409                      gsize *n_data)
2410 {
2411 	if (data) {
2412 		g_assert (*n_data >= 1);
2413 		if (value)
2414 			data[0] = 0xFF;
2415 		else
2416 			data[0] = 0x00;
2417 	}
2418 	*n_data = 1;
2419 }
2420 
2421 static GBytes *
anode_default_boolean(GNode * node)2422 anode_default_boolean (GNode *node)
2423 {
2424 	EggAsn1xDef *opt;
2425 	gboolean value;
2426 	guchar *data;
2427 	gsize len;
2428 
2429 	if (!(anode_def_flags (node) & FLAG_DEFAULT))
2430 		return NULL;
2431 
2432 	/* Try to get a default */
2433 	opt = anode_opt_lookup (node, EGG_ASN1X_DEFAULT, NULL);
2434 	g_return_val_if_fail (opt != NULL, NULL);
2435 
2436 	/* Parse out the default value */
2437 	if ((opt->type & FLAG_TRUE) == FLAG_TRUE)
2438 		value = TRUE;
2439 	else if ((opt->type & FLAG_FALSE) == FLAG_FALSE)
2440 		value = FALSE;
2441 	else
2442 		g_return_val_if_reached (FALSE);
2443 
2444 	anode_write_boolean (value, NULL, &len);
2445 	data = g_malloc (len);
2446 	anode_write_boolean (value, data, &len);
2447 	return g_bytes_new_take (data, len);
2448 }
2449 
2450 static gboolean
anode_read_object_id(GNode * node,GBytes * data,gchar ** oid)2451 anode_read_object_id (GNode *node,
2452                       GBytes *data,
2453                       gchar **oid)
2454 {
2455 	GString *result = NULL;
2456 	const guchar *p;
2457 	gboolean lead;
2458 	guint val, pval;
2459 	gsize len;
2460 	gint k;
2461 
2462 	g_assert (data != NULL);
2463 	p = g_bytes_get_data (data, &len);
2464 
2465 	if (oid)
2466 		result = g_string_sized_new (32);
2467 
2468 	pval = p[0] / 40;
2469 	val = p[0] - pval * 40;
2470 
2471 	if (result)
2472 		g_string_append_printf (result, "%u.%u", pval, val);
2473 
2474 	/* TODO: Validate first byte? */
2475 	for (k = 1, lead = 1, val = 0, pval = 0; k < len; ++k) {
2476 		/* X.690: the leading byte must never be 0x80 */
2477 		if (lead && p[k] == 0x80) {
2478 			anode_failure (node, "object id encoding is invalid");
2479 			break;
2480 		}
2481 		val = val << 7;
2482 		val |= p[k] & 0x7F;
2483 		/* Check for wrap around */
2484 		if (val < pval) {
2485 			anode_failure (node, "object id encoding is invalid");
2486 			break;
2487 		}
2488 		pval = val;
2489 		if (!(p[k] & 0x80)) {
2490 			if (result)
2491 				g_string_append_printf (result, ".%u", val);
2492 			pval = val = 0;
2493 			lead = 1;
2494 		}
2495 	}
2496 
2497 	if (k < len) {
2498 		if (result)
2499 			g_string_free (result, TRUE); /* UNREACHABLE: caught by validation */
2500 		return FALSE;
2501 	}
2502 
2503 	if (result)
2504 		*oid = g_string_free (result, FALSE);
2505 	return TRUE;
2506 }
2507 
2508 static gboolean
anode_write_object_id(const gchar * oid,guchar * data,gsize * n_data)2509 anode_write_object_id (const gchar *oid,
2510                        guchar *data,
2511                        gsize *n_data)
2512 {
2513 	const gchar *p, *next;
2514 	gint num, num1;
2515 	guchar bit7;
2516 	gboolean had;
2517 	gint i, k, at;
2518 
2519 	at = 0;
2520 	num1 = 0;
2521 
2522 	for (i = 0; oid[0]; ++i, oid = next) {
2523 		p = strchr (oid, '.');
2524 		if (p == NULL)
2525 			next = p = oid + strlen (oid);
2526 		else
2527 			next = p + 1;
2528 		if (p == oid)
2529 			return FALSE;
2530 		num = atoin (oid, p - oid);
2531 		if (num < 0)
2532 			return FALSE;
2533 		if (i == 0) {
2534 			num1 = num;
2535 		} else if (i == 1) {
2536 			if (data) {
2537 				g_assert (*n_data > at);
2538 				data[at] = 40 * num1 + num;
2539 			}
2540 			++at;
2541 		} else {
2542 			for (had = FALSE, k = 4; k >= 0; k--) {
2543 				bit7 = (num >> (k * 7)) & 0x7F;
2544 				if (bit7 || had || !k) {
2545 					if (k)
2546 						bit7 |= 0x80;
2547 					if (data) {
2548 						g_assert (*n_data > at);
2549 						data[at] = bit7;
2550 					}
2551 					++at;
2552 					had = 1;
2553 				}
2554 			}
2555 		}
2556 	}
2557 
2558 	if (at < 2)
2559 		return FALSE;
2560 	if (data)
2561 		g_assert (*n_data >= at);
2562 	*n_data = at;
2563 	return TRUE;
2564 }
2565 
2566 /* -----------------------------------------------------------------------------------
2567  * GETTING, SETTING
2568  */
2569 
2570 GNode*
egg_asn1x_node(GNode * asn,...)2571 egg_asn1x_node (GNode *asn, ...)
2572 {
2573 	GNode *node = asn;
2574 	const gchar *name;
2575 	va_list va;
2576 	gint type;
2577 	gint index;
2578 
2579 	g_return_val_if_fail (asn, NULL);
2580 	va_start (va, asn);
2581 
2582 	for (;;) {
2583 		type = anode_def_type (node);
2584 
2585 		/* Use integer indexes for these */
2586 		if (type == EGG_ASN1X_SEQUENCE_OF || type == EGG_ASN1X_SET_OF) {
2587 			index = va_arg (va, gint);
2588 			if (index == 0)
2589 				return node;
2590 
2591 			/* Only consider nodes that have data */
2592 			node = g_node_nth_child (node, 0);
2593 			while (node) {
2594 				if (egg_asn1x_have (node)) {
2595 					--index;
2596 					if (index == 0)
2597 						break;
2598 				}
2599 				node = g_node_next_sibling (node);
2600 			}
2601 
2602 			if (node == NULL)
2603 				return NULL;
2604 
2605 		/* Use strings for these */
2606 		} else {
2607 			name = va_arg (va, const gchar*);
2608 			if (name == NULL)
2609 				return node;
2610 			/* Warn if they're using indexes here */
2611 			if (name <= (const gchar*)4096) {
2612 				g_warning ("possible misuse of egg_asn1x_node, expected a string, but got an index");
2613 				return NULL;
2614 			}
2615 			node = anode_child_with_name (node, name);
2616 			if (node == NULL)
2617 				return NULL;
2618 		}
2619 	}
2620 }
2621 
2622 const gchar*
egg_asn1x_name(GNode * node)2623 egg_asn1x_name (GNode *node)
2624 {
2625 	g_return_val_if_fail (node != NULL, NULL);
2626 	return anode_def_name (node);
2627 }
2628 
2629 EggAsn1xType
egg_asn1x_type(GNode * node)2630 egg_asn1x_type (GNode *node)
2631 {
2632 	g_return_val_if_fail (node != NULL, 0);
2633 	return anode_def_type (node);
2634 }
2635 
2636 guint
egg_asn1x_count(GNode * node)2637 egg_asn1x_count (GNode *node)
2638 {
2639 	guint result = 0;
2640 	GNode *child;
2641 	gint type;
2642 
2643 	g_return_val_if_fail (node, 0);
2644 
2645 	type = anode_def_type (node);
2646 	if (type != EGG_ASN1X_SEQUENCE_OF && type != EGG_ASN1X_SET_OF) {
2647 		g_warning ("node passed to egg_asn1x_count was not a sequence of or set of");
2648 		return 0;
2649 	}
2650 
2651 	for (child = node->children; child; child = child->next) {
2652 		if (egg_asn1x_have (child))
2653 			++result;
2654 	}
2655 
2656 	return result;
2657 }
2658 
2659 GNode*
egg_asn1x_append(GNode * node)2660 egg_asn1x_append (GNode *node)
2661 {
2662 	GNode *child;
2663 	gint type;
2664 
2665 	g_return_val_if_fail (node, NULL);
2666 
2667 	type = anode_def_type (node);
2668 	if (type != EGG_ASN1X_SEQUENCE_OF && type != EGG_ASN1X_SET_OF) {
2669 		g_warning ("node passed to egg_asn1x_append was not a sequence of or set of");
2670 		return NULL;
2671 	}
2672 
2673 	/* There must be at least one child */
2674 	child = node->children;
2675 	g_return_val_if_fail (child, NULL);
2676 
2677 	child = anode_clone (child);
2678 	anode_clear (child);
2679 	g_node_append (node, child);
2680 
2681 	return child;
2682 }
2683 
2684 gboolean
egg_asn1x_have(GNode * node)2685 egg_asn1x_have (GNode *node)
2686 {
2687 	GNode *child;
2688 
2689 	g_return_val_if_fail (node, FALSE);
2690 
2691 	if (anode_get_value (node) || anode_get_parsed (node))
2692 		return TRUE;
2693 
2694 	for (child = node->children; child != NULL; child = child->next) {
2695 		if (egg_asn1x_have (child))
2696 			return TRUE;
2697 	}
2698 
2699 	return FALSE;
2700 }
2701 
2702 gboolean
egg_asn1x_get_boolean(GNode * node,gboolean * value)2703 egg_asn1x_get_boolean (GNode *node,
2704                        gboolean *value)
2705 {
2706 	gboolean ret;
2707 	GBytes *data;
2708 
2709 	g_return_val_if_fail (node != NULL, FALSE);
2710 	g_return_val_if_fail (value != NULL, FALSE);
2711 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_BOOLEAN, FALSE);
2712 
2713 	data = anode_get_value (node);
2714 	if (data == NULL)
2715 		data = anode_default_boolean (node);
2716 	else
2717 		g_bytes_ref (data);
2718 	if (data == NULL)
2719 		return FALSE;
2720 
2721 	ret = anode_read_boolean (node, data, value);
2722 	g_bytes_unref (data);
2723 	return ret;
2724 }
2725 
2726 void
egg_asn1x_set_boolean(GNode * node,gboolean value)2727 egg_asn1x_set_boolean (GNode *node, gboolean value)
2728 {
2729 	GBytes *data, *def;
2730 	guchar *buf;
2731 	gsize len;
2732 
2733 	g_return_if_fail (node != NULL);
2734 	g_return_if_fail (anode_def_type (node) == EGG_ASN1X_BOOLEAN);
2735 
2736 	len = 1;
2737 	buf = g_malloc0 (1);
2738 	anode_write_boolean (value, buf, &len);
2739 	data = g_bytes_new_take (buf, len);
2740 
2741 	/* If it's equal to default, then clear */
2742 	def = anode_default_boolean (node);
2743 	if (def) {
2744 		if (g_bytes_equal (def, data)) {
2745 			anode_clr_value (node);
2746 			g_bytes_unref (data);
2747 			data = NULL;
2748 		}
2749 		g_bytes_unref (def);
2750 	}
2751 
2752 	if (data != NULL)
2753 		anode_take_value (node, data);
2754 }
2755 
2756 void
egg_asn1x_set_null(GNode * node)2757 egg_asn1x_set_null (GNode *node)
2758 {
2759 	g_return_if_fail (node != NULL);
2760 	g_return_if_fail (anode_def_type (node) == EGG_ASN1X_NULL);
2761 
2762 	/* Encode zero characters */
2763 	anode_clr_value (node);
2764 	anode_take_value (node, g_bytes_new_static ("", 0));
2765 }
2766 
2767 GQuark
egg_asn1x_get_enumerated(GNode * node)2768 egg_asn1x_get_enumerated (GNode *node)
2769 {
2770 	gchar buf[sizeof (gulong) * 3];
2771 	EggAsn1xDef *opt;
2772 	gulong val;
2773 	GBytes *data;
2774 
2775 	g_return_val_if_fail (node != NULL, 0);
2776 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_ENUMERATED, 0);
2777 
2778 	data = anode_get_value (node);
2779 	if (data == NULL)
2780 		return 0;
2781 
2782 	if (!anode_read_integer_ulong (node, data, &val))
2783 		g_return_val_if_reached (0);
2784 
2785 	/* Format that as a string */
2786 	if (g_snprintf (buf, sizeof (buf), "%lu", val) < 0)
2787 		g_return_val_if_reached (0);
2788 
2789 	/* Lookup that value in our table */
2790 	opt = anode_opt_lookup_value (node, EGG_ASN1X_CONSTANT, buf);
2791 	if (opt == NULL || opt->name == NULL)
2792 		return 0;
2793 
2794 	return g_quark_from_static_string (opt->name);
2795 }
2796 
2797 void
egg_asn1x_set_enumerated(GNode * node,GQuark value)2798 egg_asn1x_set_enumerated (GNode *node,
2799                           GQuark value)
2800 {
2801 	EggAsn1xDef *opt;
2802 	const gchar *name;
2803 	gpointer data;
2804 	gsize n_data;
2805 	gulong val;
2806 
2807 	g_return_if_fail (node != NULL);
2808 	g_return_if_fail (value != 0);
2809 	g_return_if_fail (anode_def_type (node) == EGG_ASN1X_ENUMERATED);
2810 
2811 	name = g_quark_to_string (value);
2812 	g_return_if_fail (name != NULL);
2813 
2814 	opt = anode_opt_lookup (node, EGG_ASN1X_CONSTANT, name);
2815 	g_return_if_fail (opt && opt->value);
2816 
2817 	/* TODO: Signed values */
2818 
2819 	val = anode_def_value_as_ulong (opt);
2820 	g_return_if_fail (val != G_MAXULONG);
2821 
2822 	n_data = sizeof (gulong) + 1;
2823 	data = g_malloc0 (n_data);
2824 	anode_write_integer_ulong (val, data, &n_data);
2825 
2826 	anode_clr_value (node);
2827 	anode_take_value (node, g_bytes_new_take (data, n_data));
2828 }
2829 
2830 gboolean
egg_asn1x_get_integer_as_ulong(GNode * node,gulong * value)2831 egg_asn1x_get_integer_as_ulong (GNode *node,
2832                                 gulong *value)
2833 {
2834 	gboolean ret;
2835 	GBytes *data;
2836 
2837 	g_return_val_if_fail (node != NULL, FALSE);
2838 	g_return_val_if_fail (value != NULL, FALSE);
2839 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER, FALSE);
2840 
2841 	data = anode_get_value (node);
2842 	if (data == NULL)
2843 		data = anode_default_integer (node);
2844 	else
2845 		g_bytes_ref (data);
2846 	if (data == NULL)
2847 		return FALSE;
2848 
2849 	ret = anode_read_integer_ulong (node, data, value);
2850 	g_bytes_unref (data);
2851 	return ret;
2852 }
2853 
2854 void
egg_asn1x_set_integer_as_ulong(GNode * node,gulong value)2855 egg_asn1x_set_integer_as_ulong (GNode *node,
2856                                 gulong value)
2857 {
2858 	GBytes *data, *def;
2859 	guchar *buf;
2860 	gsize len;
2861 
2862 	g_return_if_fail (node != NULL);
2863 	g_return_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER);
2864 
2865 	len = sizeof (gulong) + 1;
2866 	buf = g_malloc0 (len);
2867 	anode_write_integer_ulong (value, buf, &len);
2868 	data = g_bytes_new_take (buf, len);
2869 
2870 	/* If it's equal to default, then clear */
2871 	def = anode_default_integer (node);
2872 	if (def) {
2873 		if (g_bytes_equal (def, data)) {
2874 			anode_clr_value (node);
2875 			g_bytes_unref (data);
2876 			data = NULL;
2877 		}
2878 		g_bytes_unref (def);
2879 	}
2880 
2881 	if (data != NULL)
2882 		anode_take_value (node, data);
2883 }
2884 
2885 GBytes *
egg_asn1x_get_integer_as_raw(GNode * node)2886 egg_asn1x_get_integer_as_raw (GNode *node)
2887 {
2888 	Anode *an;
2889 	GBytes *raw;
2890 
2891 	g_return_val_if_fail (node != NULL, NULL);
2892 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER, NULL);
2893 
2894 	an = node->data;
2895 	if (an->guarantee_unsigned) {
2896 		g_warning ("cannot read integer set with "        /* UNREACHABLE: */
2897 		           "egg_asn1x_set_integer_as_raw() "      /* UNREACHABLE: */
2898 		           "via egg_asn1x_get_integer_as_raw()"); /* UNREACHABLE: */
2899 		return NULL;  /* UNREACHABLE: unreachable by coverage testing */
2900 	}
2901 
2902 	raw = anode_get_value (node);
2903 	if (raw != NULL)
2904 		g_bytes_ref (raw);
2905 	return raw;
2906 }
2907 
2908 GBytes *
egg_asn1x_get_integer_as_usg(GNode * node)2909 egg_asn1x_get_integer_as_usg (GNode *node)
2910 {
2911 	const guchar *p;
2912 	Anode *an;
2913 	gboolean sign;
2914 	gsize len;
2915 
2916 	g_return_val_if_fail (node != NULL, FALSE);
2917 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER, FALSE);
2918 
2919 	an = node->data;
2920 	if (an->value == NULL)
2921 		return NULL;
2922 
2923 	p = g_bytes_get_data (an->value, &len);
2924 
2925 	if (!an->guarantee_unsigned) {
2926 		sign = !!(p[0] & 0x80);
2927 		if (sign) {
2928 			g_warning ("invalid two's complement integer"); /* UNREACHABLE: */
2929 			return NULL; /* UNREACHABLE: by coverage testing */
2930 		}
2931 
2932 		/* Strip off the extra zero byte that was preventing it from being negative */
2933 		if (p[0] == 0 && len > 1) {
2934 			sign = !!(p[1] & 0x80);
2935 			if (sign) {
2936 				p++;
2937 				len--;
2938 			}
2939 		}
2940 	}
2941 
2942 	return g_bytes_new_with_free_func (p, len,
2943 	                                   (GDestroyNotify)g_bytes_unref,
2944 	                                   g_bytes_ref (an->value));
2945 }
2946 
2947 void
egg_asn1x_set_integer_as_raw(GNode * node,GBytes * value)2948 egg_asn1x_set_integer_as_raw (GNode *node,
2949                               GBytes *value)
2950 {
2951 	g_return_if_fail (value != NULL);
2952 	egg_asn1x_take_integer_as_raw (node, g_bytes_ref (value));
2953 }
2954 
2955 void
egg_asn1x_take_integer_as_raw(GNode * node,GBytes * value)2956 egg_asn1x_take_integer_as_raw (GNode *node,
2957                                GBytes *value)
2958 {
2959 	gboolean sign;
2960 	const guchar *p;
2961 	Anode *an;
2962 
2963 	g_return_if_fail (node != NULL);
2964 	g_return_if_fail (value != NULL);
2965 	g_return_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER);
2966 
2967 	/* Make sure the integer is properly encoded in twos complement*/
2968 	p = g_bytes_get_data (value, NULL);
2969 	g_return_if_fail (p != NULL);
2970 
2971 	sign = !!(p[0] & 0x80);
2972 	if (sign) {
2973 		g_warning ("integer is not two's complement"); /* UNREACHABLE: */
2974 		return; /* UNREACHABLE: unless warning */
2975 	}
2976 
2977 	anode_clr_value (node);
2978 	anode_take_value (node, value);
2979 
2980 	an = node->data;
2981 	an->guarantee_unsigned = 0;
2982 }
2983 
2984 void
egg_asn1x_set_integer_as_usg(GNode * node,GBytes * value)2985 egg_asn1x_set_integer_as_usg (GNode *node,
2986                               GBytes *value)
2987 {
2988 	g_return_if_fail (value != NULL);
2989 	egg_asn1x_take_integer_as_usg (node, g_bytes_ref (value));
2990 }
2991 
2992 void
egg_asn1x_take_integer_as_usg(GNode * node,GBytes * value)2993 egg_asn1x_take_integer_as_usg (GNode *node,
2994                                GBytes *value)
2995 {
2996 	Anode *an;
2997 
2998 	g_return_if_fail (node != NULL);
2999 	g_return_if_fail (value != NULL);
3000 	g_return_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER);
3001 
3002 	anode_take_value (node, value);
3003 	an = node->data;
3004 	an->guarantee_unsigned = 1;
3005 }
3006 
3007 GNode *
egg_asn1x_get_any_as(GNode * node,const EggAsn1xDef * defs,const gchar * type)3008 egg_asn1x_get_any_as (GNode *node,
3009                       const EggAsn1xDef *defs,
3010                       const gchar *type)
3011 {
3012 	g_return_val_if_fail (node != NULL, NULL);
3013 	g_return_val_if_fail (type != NULL, NULL);
3014 	g_return_val_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY, NULL);
3015 
3016 	return egg_asn1x_get_any_as_full (node, defs, type, 0);
3017 }
3018 
3019 GNode *
egg_asn1x_get_any_as_full(GNode * node,const EggAsn1xDef * defs,const gchar * type,gint options)3020 egg_asn1x_get_any_as_full (GNode *node,
3021                            const EggAsn1xDef *defs,
3022                            const gchar *type,
3023                            gint options)
3024 {
3025 	GNode *asn;
3026 
3027 	g_return_val_if_fail (node != NULL, NULL);
3028 	g_return_val_if_fail (type != NULL, NULL);
3029 	g_return_val_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY, NULL);
3030 
3031 	asn = egg_asn1x_create (defs, type);
3032 	g_return_val_if_fail (asn != NULL, NULL);
3033 
3034 	if (!egg_asn1x_get_any_into_full (node, asn, options)) {
3035 		egg_asn1x_destroy (asn);
3036 		return NULL;
3037 	}
3038 
3039 	return asn;
3040 }
3041 
3042 gboolean
egg_asn1x_get_any_into(GNode * node,GNode * into)3043 egg_asn1x_get_any_into  (GNode *node,
3044                          GNode *into)
3045 {
3046 	g_return_val_if_fail (node != NULL, FALSE);
3047 	g_return_val_if_fail (into != NULL, FALSE);
3048 	g_return_val_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY, FALSE);
3049 
3050 	return egg_asn1x_get_any_into_full (node, into, 0);
3051 }
3052 
3053 gboolean
egg_asn1x_get_any_into_full(GNode * node,GNode * into,gint options)3054 egg_asn1x_get_any_into_full (GNode *node,
3055                              GNode *into,
3056                              gint options)
3057 {
3058 	Atlv *tlv;
3059 
3060 	g_return_val_if_fail (node != NULL, FALSE);
3061 	g_return_val_if_fail (into != NULL, FALSE);
3062 	g_return_val_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY, FALSE);
3063 
3064 	tlv = anode_get_parsed (node);
3065 	if (tlv == NULL)
3066 		return FALSE;
3067 
3068 	/* If this node is explicit, then just get the contents */
3069 	if (anode_calc_explicit_for_flags (node, anode_def_flags (node), NULL)) {
3070 		tlv = tlv->child;
3071 		g_return_val_if_fail (tlv != NULL, FALSE);
3072 	}
3073 
3074 	if (!anode_decode_anything (into, tlv))
3075 		return FALSE;
3076 
3077 	return egg_asn1x_validate (into, !(options & EGG_ASN1X_NO_STRICT));
3078 }
3079 
3080 void
egg_asn1x_set_any_from(GNode * node,GNode * from)3081 egg_asn1x_set_any_from (GNode *node,
3082                         GNode *from)
3083 {
3084 	Anode *an;
3085 	Atlv *tlv;
3086 
3087 	g_return_if_fail (node != NULL);
3088 	g_return_if_fail (from != NULL);
3089 	g_return_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY);
3090 
3091 	tlv = anode_build_anything (from, TRUE);
3092 	g_return_if_fail (tlv != NULL);
3093 
3094 	/* Wrap this in an explicit tag if necessary */
3095 	tlv = anode_build_maybe_explicit (node, tlv, anode_def_flags (node));
3096 
3097 	/* Mark down the tlvs for this node */
3098 	an = node->data;
3099 	atlv_free (an->parsed);
3100 	an->parsed = tlv;
3101 }
3102 
3103 GBytes *
egg_asn1x_get_any_raw(GNode * node,EggAllocator allocator)3104 egg_asn1x_get_any_raw (GNode *node,
3105                        EggAllocator allocator)
3106 {
3107 	GBytes *bytes;
3108 	Atlv *tlv;
3109 
3110 	g_return_val_if_fail (node != NULL, NULL);
3111 
3112 	tlv = anode_build_anything (node, TRUE);
3113 	if (tlv == NULL) {
3114 		anode_failure (node, "missing value(s)");
3115 		return NULL;
3116 	}
3117 
3118 	atlv_sort_perform (tlv, allocator);
3119 
3120 	bytes = atlv_unparse_to_bytes (tlv, allocator);
3121 	atlv_free (tlv);
3122 	return bytes;
3123 }
3124 
3125 gboolean
egg_asn1x_set_any_raw(GNode * node,GBytes * raw)3126 egg_asn1x_set_any_raw (GNode *node,
3127                        GBytes *raw)
3128 {
3129 	const gchar *msg;
3130 	Anode *an;
3131 	Atlv *tlv;
3132 
3133 	g_return_val_if_fail (node != NULL, FALSE);
3134 	g_return_val_if_fail (raw != NULL, FALSE);
3135 
3136 	an = node->data;
3137 	tlv = atlv_new ();
3138 	msg = atlv_parse_der (raw, tlv);
3139 	if (msg == NULL) {
3140 
3141 		/* Wrap this in an explicit tag if necessary */
3142 		tlv = anode_build_maybe_explicit (node, tlv, anode_def_flags (node));
3143 
3144 		atlv_free (an->parsed);
3145 		an->parsed = tlv;
3146 		return TRUE;
3147 
3148 	/* A failure, set the message manually so it doesn't get a prefix */
3149 	} else {
3150 		atlv_free (tlv);
3151 		an = node->data;
3152 		g_free (an->failure);
3153 		an->failure = g_strdup (msg);
3154 		return FALSE;
3155 	}
3156 }
3157 
3158 GBytes *
egg_asn1x_get_element_raw(GNode * node)3159 egg_asn1x_get_element_raw (GNode *node)
3160 {
3161 	Anode *an;
3162 	Atlv *tlv;
3163 
3164 	g_return_val_if_fail (node != NULL, NULL);
3165 
3166 	an = node->data;
3167 	tlv = an->parsed;
3168 
3169 	/* If this node is explicit, then just get the contents */
3170 	if (tlv && anode_calc_explicit_for_flags (node, anode_def_flags (node), NULL))
3171 		tlv = tlv->child;
3172 
3173 	if (!tlv || !tlv->decoded)
3174 		return NULL;
3175 
3176 	return g_bytes_ref (tlv->decoded);
3177 }
3178 
3179 GBytes *
egg_asn1x_get_value_raw(GNode * node)3180 egg_asn1x_get_value_raw (GNode *node)
3181 {
3182 	GBytes *raw;
3183 
3184 	g_return_val_if_fail (node != NULL, NULL);
3185 	raw = anode_get_value (node);
3186 	if (raw != NULL)
3187 		g_bytes_ref (raw);
3188 	return raw;
3189 }
3190 
3191 guchar *
egg_asn1x_get_string_as_raw(GNode * node,EggAllocator allocator,gsize * n_string)3192 egg_asn1x_get_string_as_raw (GNode *node,
3193                              EggAllocator allocator,
3194                              gsize *n_string)
3195 {
3196 	gsize length;
3197 	guchar *string;
3198 	GBytes *data;
3199 	Atlv *tlv;
3200 	gint type;
3201 
3202 	g_return_val_if_fail (node, NULL);
3203 	g_return_val_if_fail (n_string, NULL);
3204 
3205 	if (!allocator)
3206 		allocator = g_realloc;
3207 
3208 	type = anode_def_type (node);
3209 	g_return_val_if_fail (type == EGG_ASN1X_OCTET_STRING ||
3210 	                      type == EGG_ASN1X_GENERAL_STRING ||
3211 	                      type == EGG_ASN1X_NUMERIC_STRING ||
3212 	                      type == EGG_ASN1X_IA5_STRING ||
3213 	                      type == EGG_ASN1X_TELETEX_STRING ||
3214 	                      type == EGG_ASN1X_PRINTABLE_STRING ||
3215 	                      type == EGG_ASN1X_UNIVERSAL_STRING ||
3216 	                      type == EGG_ASN1X_BMP_STRING ||
3217 	                      type == EGG_ASN1X_UTF8_STRING ||
3218 	                      type == EGG_ASN1X_VISIBLE_STRING, NULL);
3219 
3220 	data = anode_get_value (node);
3221 	if (data != NULL) {
3222 		if (!anode_read_string_simple (node, data, NULL, &length))
3223 			g_return_val_if_reached (NULL);
3224 
3225 		string = (allocator) (NULL, length + 1);
3226 		if (string == NULL)
3227 			return NULL; /* UNREACHABLE: unless odd allocator */
3228 
3229 		if (!anode_read_string_simple (node, data, string, &length))
3230 			g_return_val_if_reached (NULL);
3231 
3232 		/* Courtesy null termination, string must however be validated! */
3233 		string[length] = 0;
3234 		*n_string = length;
3235 		return string;
3236 	}
3237 
3238 	tlv = anode_get_parsed (node);
3239 	if (tlv != NULL) {
3240 		if (!anode_read_string_struct (node, tlv, NULL, &length))
3241 			return NULL;
3242 
3243 		string = (allocator) (NULL, length + 1);
3244 		if (string == NULL)
3245 			return NULL; /* UNREACHABLE: unless odd allocator */
3246 
3247 		if (!anode_read_string_struct (node, tlv, string, &length))
3248 			g_return_val_if_reached (NULL); /* should have failed above */
3249 
3250 		/* Courtesy null termination, string must however be validated! */
3251 		string[length] = 0;
3252 		*n_string = length;
3253 		return string;
3254 	}
3255 
3256 	return NULL;
3257 }
3258 
3259 void
egg_asn1x_set_string_as_raw(GNode * node,guchar * data,gsize n_data,GDestroyNotify destroy)3260 egg_asn1x_set_string_as_raw (GNode *node,
3261                              guchar *data,
3262                              gsize n_data,
3263                              GDestroyNotify destroy)
3264 {
3265 	gint type;
3266 
3267 	g_return_if_fail (node != NULL);
3268 	g_return_if_fail (data != NULL);
3269 
3270 	type = anode_def_type (node);
3271 	g_return_if_fail (type == EGG_ASN1X_OCTET_STRING ||
3272 	                  type == EGG_ASN1X_GENERAL_STRING ||
3273 	                  type == EGG_ASN1X_NUMERIC_STRING ||
3274 	                  type == EGG_ASN1X_IA5_STRING ||
3275 	                  type == EGG_ASN1X_TELETEX_STRING ||
3276 	                  type == EGG_ASN1X_PRINTABLE_STRING ||
3277 	                  type == EGG_ASN1X_UNIVERSAL_STRING ||
3278 	                  type == EGG_ASN1X_BMP_STRING ||
3279 	                  type == EGG_ASN1X_UTF8_STRING ||
3280 	                  type == EGG_ASN1X_VISIBLE_STRING);
3281 
3282 	anode_take_value (node, g_bytes_new_with_free_func (data, n_data,
3283 	                                                    destroy, data));
3284 }
3285 
3286 void
egg_asn1x_set_string_as_bytes(GNode * node,GBytes * bytes)3287 egg_asn1x_set_string_as_bytes (GNode *node,
3288                                GBytes *bytes)
3289 {
3290 	gint type;
3291 
3292 	g_return_if_fail (node != NULL);
3293 	g_return_if_fail (bytes != NULL);
3294 
3295 	type = anode_def_type (node);
3296 	g_return_if_fail (type == EGG_ASN1X_OCTET_STRING ||
3297 	                  type == EGG_ASN1X_GENERAL_STRING ||
3298 	                  type == EGG_ASN1X_NUMERIC_STRING ||
3299 	                  type == EGG_ASN1X_IA5_STRING ||
3300 	                  type == EGG_ASN1X_TELETEX_STRING ||
3301 	                  type == EGG_ASN1X_PRINTABLE_STRING ||
3302 	                  type == EGG_ASN1X_UNIVERSAL_STRING ||
3303 	                  type == EGG_ASN1X_BMP_STRING ||
3304 	                  type == EGG_ASN1X_UTF8_STRING ||
3305 	                  type == EGG_ASN1X_VISIBLE_STRING);
3306 
3307 	anode_set_value (node, bytes);
3308 }
3309 
3310 GBytes *
egg_asn1x_get_string_as_bytes(GNode * node)3311 egg_asn1x_get_string_as_bytes (GNode *node)
3312 {
3313 	gpointer raw;
3314 	gsize length;
3315 
3316 	g_return_val_if_fail (node != NULL, NULL);
3317 
3318 	raw = egg_asn1x_get_string_as_raw (node, NULL, &length);
3319 	if (raw == NULL)
3320 		return NULL;
3321 
3322 	return g_bytes_new_take (raw, length);
3323 }
3324 
3325 gchar *
egg_asn1x_get_bmpstring_as_utf8(GNode * node)3326 egg_asn1x_get_bmpstring_as_utf8 (GNode *node)
3327 {
3328 	gchar *string;
3329 	gsize n_string;
3330 	gchar *utf8;
3331 
3332 	g_return_val_if_fail (node, NULL);
3333 
3334 	string = (gchar*)egg_asn1x_get_string_as_raw (node, NULL, &n_string);
3335 	if (!string)
3336 		return NULL;
3337 
3338 	utf8 = g_convert (string, n_string, "UTF-8", "UTF-16BE", NULL, NULL, NULL);
3339 	g_free (string);
3340 
3341 	return utf8;
3342 }
3343 
3344 gchar*
egg_asn1x_get_string_as_utf8(GNode * node,EggAllocator allocator)3345 egg_asn1x_get_string_as_utf8 (GNode *node,
3346                               EggAllocator allocator)
3347 {
3348 	gchar *string;
3349 	gsize n_string;
3350 
3351 	g_return_val_if_fail (node, NULL);
3352 
3353 	if (allocator == NULL)
3354 		allocator = g_realloc;
3355 
3356 	string = (gchar*)egg_asn1x_get_string_as_raw (node, allocator, &n_string);
3357 	if (!string)
3358 		return NULL;
3359 
3360 	if (!g_utf8_validate (string, n_string, NULL)) {
3361 		(allocator) (string, 0);
3362 		return NULL;
3363 	}
3364 
3365 	return string;
3366 }
3367 
3368 gboolean
egg_asn1x_set_string_as_utf8(GNode * node,gchar * data,GDestroyNotify destroy)3369 egg_asn1x_set_string_as_utf8 (GNode *node,
3370                               gchar *data,
3371                               GDestroyNotify destroy)
3372 {
3373 	gsize n_data;
3374 
3375 	g_return_val_if_fail (node != NULL, FALSE);
3376 	g_return_val_if_fail (data != NULL, FALSE);
3377 
3378 	n_data = strlen (data);
3379 	if (!g_utf8_validate (data, n_data, NULL))
3380 		return FALSE;
3381 
3382 	egg_asn1x_set_string_as_raw (node, (guchar*)data, n_data, destroy);
3383 	return TRUE;
3384 }
3385 
3386 GBytes *
egg_asn1x_get_bits_as_raw(GNode * node,guint * n_bits)3387 egg_asn1x_get_bits_as_raw (GNode *node,
3388                            guint *n_bits)
3389 {
3390 	gsize len;
3391 	GBytes *data;
3392 	Anode *an;
3393 
3394 	g_return_val_if_fail (node != NULL, NULL);
3395 	g_return_val_if_fail (n_bits != NULL, NULL);
3396 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_BIT_STRING, NULL);
3397 
3398 	data = anode_get_value (node);
3399 	if (data == NULL)
3400 		return NULL;
3401 
3402 	len = g_bytes_get_size (data);
3403 	an = node->data;
3404 
3405 	*n_bits = (len * 8) - an->bits_empty;
3406 	return g_bytes_ref (data);
3407 }
3408 
3409 void
egg_asn1x_set_bits_as_raw(GNode * node,GBytes * value,guint n_bits)3410 egg_asn1x_set_bits_as_raw (GNode *node,
3411                            GBytes *value,
3412                            guint n_bits)
3413 {
3414 	g_return_if_fail (node != NULL);
3415 	g_return_if_fail (value != NULL);
3416 
3417 	egg_asn1x_take_bits_as_raw (node, g_bytes_ref (value), n_bits);
3418 }
3419 
3420 void
egg_asn1x_take_bits_as_raw(GNode * node,GBytes * value,guint n_bits)3421 egg_asn1x_take_bits_as_raw (GNode *node,
3422                             GBytes *value,
3423                             guint n_bits)
3424 {
3425 	Anode *an;
3426 	gint type;
3427 	gsize len;
3428 	guchar empty;
3429 
3430 	g_return_if_fail (node != NULL);
3431 	g_return_if_fail (value != NULL);
3432 
3433 	type = anode_def_type (node);
3434 	g_return_if_fail (type == EGG_ASN1X_BIT_STRING);
3435 
3436 	len = (n_bits / 8);
3437 	if (n_bits % 8)
3438 		len += 1;
3439 
3440 	empty = n_bits % 8;
3441 	if (empty > 0)
3442 		empty = 8 - empty;
3443 
3444 	anode_take_value (node, value);
3445 	an = node->data;
3446 	an->bits_empty = empty;
3447 }
3448 
3449 gboolean
egg_asn1x_get_bits_as_ulong(GNode * node,gulong * bits,guint * n_bits)3450 egg_asn1x_get_bits_as_ulong (GNode *node,
3451                              gulong *bits,
3452                              guint *n_bits)
3453 {
3454 	GBytes *data;
3455 	const guchar *buf;
3456 	gsize len;
3457 	guint i, length;
3458 	guchar empty;
3459 	const guchar *p;
3460 	gulong value;
3461 	Anode *an;
3462 
3463 	g_return_val_if_fail (node != NULL, FALSE);
3464 	g_return_val_if_fail (bits != NULL, FALSE);
3465 	g_return_val_if_fail (n_bits != NULL, FALSE);
3466 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_BIT_STRING, FALSE);
3467 
3468 	data = anode_get_value (node);
3469 	if (data == NULL)
3470 		return FALSE;
3471 
3472 	buf = g_bytes_get_data (data, &len);
3473 	an = node->data;
3474 	empty = an->bits_empty;
3475 
3476 	length = (len * 8) - empty;
3477 	if (length > sizeof (gulong) * 8)
3478 		return FALSE;
3479 
3480 	value = 0;
3481 	p = buf;
3482 
3483 	for (i = 0; i < len; ++i)
3484 		value = value << 8 | p[i];
3485 
3486 	*bits = value >> empty;
3487 	*n_bits = length;
3488 	return TRUE;
3489 }
3490 
3491 void
egg_asn1x_set_bits_as_ulong(GNode * node,gulong bits,guint n_bits)3492 egg_asn1x_set_bits_as_ulong (GNode *node,
3493                              gulong bits,
3494                              guint n_bits)
3495 {
3496 	guchar *data;
3497 	gulong value;
3498 	gsize i, len;
3499 	guchar empty;
3500 	Anode *an;
3501 	gint type;
3502 
3503 	g_return_if_fail (node != NULL);
3504 	g_return_if_fail (n_bits <= sizeof (gulong) * 8);
3505 
3506 	type = anode_def_type (node);
3507 	g_return_if_fail (type == EGG_ASN1X_BIT_STRING);
3508 
3509 	empty = n_bits % 8;
3510 	if (empty > 0)
3511 		empty = 8 - empty;
3512 	len = (n_bits / 8) + (empty ? 1 : 0);
3513 
3514 	data = g_malloc0 (sizeof (gulong));
3515 	value = bits << empty;
3516 
3517 	for (i = 0; i < len; ++i)
3518 		data[len - i - 1] = (value >> i * 8) & 0xFF;
3519 
3520 	an = node->data;
3521 	an->bits_empty = empty;
3522 	anode_take_value (node, g_bytes_new_take (data, len));
3523 }
3524 
3525 glong
egg_asn1x_get_time_as_long(GNode * node)3526 egg_asn1x_get_time_as_long (GNode *node)
3527 {
3528 	struct tm when;
3529 	GBytes *data;
3530 	glong time;
3531 	gint type;
3532 
3533 	g_return_val_if_fail (node, -1);
3534 	type = anode_def_type (node);
3535 
3536 	/* Time is often represented as a choice, so work than in here */
3537 	if (type == EGG_ASN1X_CHOICE) {
3538 		node = egg_asn1x_get_choice (node);
3539 		if (node == NULL)
3540 			return -1;
3541 		g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_TIME ||
3542 		                      anode_def_type (node) == EGG_ASN1X_UTC_TIME ||
3543 		                      anode_def_type (node) == EGG_ASN1X_GENERALIZED_TIME, -1);
3544 		return egg_asn1x_get_time_as_long (node);
3545 	}
3546 
3547 	g_return_val_if_fail (type == EGG_ASN1X_TIME ||
3548 	                      type == EGG_ASN1X_UTC_TIME ||
3549 	                      type == EGG_ASN1X_GENERALIZED_TIME, -1);
3550 
3551 	data = anode_get_value (node);
3552 	if (data == NULL)
3553 		return -1;
3554 
3555 	if (!anode_read_time (node, data, &when, &time))
3556 		g_return_val_if_reached (-1); /* already validated */
3557 	return time;
3558 }
3559 
3560 gboolean
egg_asn1x_get_time_as_date(GNode * node,GDate * date)3561 egg_asn1x_get_time_as_date (GNode *node,
3562                             GDate *date)
3563 {
3564 	struct tm when;
3565 	GBytes *data;
3566 	glong time;
3567 	gint type;
3568 
3569 	g_return_val_if_fail (node, FALSE);
3570 	type = anode_def_type (node);
3571 
3572 	/* Time is often represented as a choice, so work than in here */
3573 	if (type == EGG_ASN1X_CHOICE) {
3574 		node = egg_asn1x_get_choice (node);
3575 		if (node == NULL)
3576 			return FALSE;
3577 		g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_TIME ||
3578 		                      anode_def_type (node) == EGG_ASN1X_UTC_TIME ||
3579 		                      anode_def_type (node) == EGG_ASN1X_GENERALIZED_TIME, FALSE);
3580 		return egg_asn1x_get_time_as_date (node, date);
3581 	}
3582 
3583 	g_return_val_if_fail (type == EGG_ASN1X_TIME ||
3584 	                      type == EGG_ASN1X_UTC_TIME ||
3585 	                      type == EGG_ASN1X_GENERALIZED_TIME, FALSE);
3586 
3587 	data = anode_get_value (node);
3588 	if (data == NULL)
3589 		return FALSE;
3590 
3591 	if (!anode_read_time (node, data, &when, &time))
3592 		g_return_val_if_reached (FALSE); /* already validated */
3593 
3594 	g_date_set_dmy (date, when.tm_mday, when.tm_mon + 1, when.tm_year + 1900);
3595 	return TRUE;
3596 }
3597 
3598 gchar*
egg_asn1x_get_oid_as_string(GNode * node)3599 egg_asn1x_get_oid_as_string (GNode *node)
3600 {
3601 	GBytes *data;
3602 	gchar *oid;
3603 
3604 	g_return_val_if_fail (node, NULL);
3605 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_OBJECT_ID, NULL);
3606 
3607 	data = anode_get_value (node);
3608 	if (data == NULL)
3609 		return NULL;
3610 
3611 	if (!anode_read_object_id (node, data, &oid))
3612 		g_return_val_if_reached (NULL); /* should have been validated */
3613 
3614 	return oid;
3615 }
3616 
3617 gboolean
egg_asn1x_set_oid_as_string(GNode * node,const gchar * oid)3618 egg_asn1x_set_oid_as_string (GNode *node,
3619                              const gchar *oid)
3620 {
3621 	guchar *data;
3622 	gsize n_data;
3623 
3624 	g_return_val_if_fail (oid != NULL, FALSE);
3625 	g_return_val_if_fail (node != NULL, FALSE);
3626 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_OBJECT_ID, FALSE);
3627 
3628 	/* Encoding will always be shorter than string */
3629 	n_data = strlen (oid);
3630 	data = g_malloc0 (n_data);
3631 
3632 	if (!anode_write_object_id (oid, data, &n_data)) {
3633 		g_free (data);
3634 		return FALSE;
3635 	}
3636 
3637 	anode_take_value (node, g_bytes_new_take (data, n_data));
3638 	return TRUE;
3639 }
3640 
3641 GQuark
egg_asn1x_get_oid_as_quark(GNode * node)3642 egg_asn1x_get_oid_as_quark (GNode *node)
3643 {
3644 	GQuark quark;
3645 	gchar *oid;
3646 
3647 	oid = egg_asn1x_get_oid_as_string (node);
3648 	if (!oid)
3649 		return 0;
3650 	quark = g_quark_from_string (oid);
3651 	g_free (oid);
3652 	return quark;
3653 }
3654 
3655 gboolean
egg_asn1x_set_oid_as_quark(GNode * node,GQuark oid)3656 egg_asn1x_set_oid_as_quark (GNode *node,
3657                             GQuark oid)
3658 {
3659 	const gchar *str;
3660 
3661 	g_return_val_if_fail (oid != 0, FALSE);
3662 
3663 	str = g_quark_to_string (oid);
3664 	g_return_val_if_fail (str != NULL, FALSE);
3665 
3666 	return egg_asn1x_set_oid_as_string (node, str);
3667 }
3668 
3669 GNode*
egg_asn1x_get_choice(GNode * node)3670 egg_asn1x_get_choice (GNode *node)
3671 {
3672 	GNode *child;
3673 	Anode *an;
3674 
3675 	g_return_val_if_fail (node, NULL);
3676 
3677 	/* One and only one of the children must be set */
3678 	for (child = node->children; child; child = child->next) {
3679 		an = (Anode*)child->data;
3680 		if (an->chosen)
3681 			return child;
3682 	}
3683 
3684 	return NULL;
3685 }
3686 
3687 gboolean
egg_asn1x_set_choice(GNode * node,GNode * choice)3688 egg_asn1x_set_choice (GNode *node,
3689                       GNode *choice)
3690 {
3691 	GNode *child;
3692 	Anode *an;
3693 
3694 	g_return_val_if_fail (node != NULL, FALSE);
3695 	g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_CHOICE, FALSE);
3696 
3697 	/* One and only one of the children must be set */
3698 	for (child = node->children; child; child = child->next) {
3699 		an = (Anode*)child->data;
3700 		if (child == choice) {
3701 			an->chosen = 1;
3702 			choice = NULL;
3703 		} else {
3704 			an->chosen = 0;
3705 		}
3706 	}
3707 
3708 	/* The choice is not one of the child nodes */
3709 	g_return_val_if_fail (!choice, FALSE);
3710 
3711 	return TRUE;
3712 }
3713 
3714 /* -----------------------------------------------------------------------------------
3715  * VALIDATION
3716  */
3717 
3718 static gboolean
anode_parse_size(GNode * node,const gchar * text,gulong * value)3719 anode_parse_size (GNode *node,
3720                   const gchar *text,
3721                   gulong *value)
3722 {
3723 	EggAsn1xDef *def;
3724 	gchar *end = NULL;
3725 
3726 	if (text == NULL) {
3727 		*value = 0;
3728 		return FALSE;
3729 	} else if (g_str_equal (text, "MAX")) {
3730 		*value = G_MAXULONG;
3731 		return TRUE;
3732 	} else if (g_ascii_isalpha (text[0])) {
3733 		def = anode_opt_lookup (node, EGG_ASN1X_INTEGER, text);
3734 		g_return_val_if_fail (def, FALSE);
3735 		return anode_parse_size (node, def->value, value);
3736 	}
3737 
3738 	*value = strtoul (text, &end, 10);
3739 	g_return_val_if_fail (end && !end[0], FALSE);
3740 	return TRUE;
3741 }
3742 
3743 
3744 static gboolean
anode_validate_size(GNode * node,gulong length)3745 anode_validate_size (GNode *node,
3746                      gulong length)
3747 {
3748 	EggAsn1xDef *size;
3749 	gulong value1 = 0;
3750 	gulong value2 = G_MAXULONG;
3751 
3752 	if (anode_def_flags (node) & FLAG_SIZE) {
3753 		size = anode_opt_lookup (node, EGG_ASN1X_SIZE, NULL);
3754 		g_return_val_if_fail (size, FALSE);
3755 		if (!anode_parse_size (node, size->value, &value1))
3756 			g_return_val_if_reached (FALSE);
3757 		if (size->type & FLAG_MIN_MAX) {
3758 			if (!anode_parse_size (node, size->name, &value2))
3759 				g_return_val_if_reached (FALSE);
3760 			if (length < value1 || length >= value2)
3761 				return anode_failure (node, "content size is out of bounds");
3762 		} else {
3763 			if (length != value1)
3764 				return anode_failure (node, "content size is not correct");
3765 		}
3766 	}
3767 
3768 	return TRUE;
3769 }
3770 
3771 static gboolean
anode_validate_integer(GNode * node,GBytes * value)3772 anode_validate_integer (GNode *node,
3773                         GBytes *value)
3774 {
3775 	GList *constants, *l;
3776 	gulong val, check;
3777 	gsize len;
3778 	gboolean found;
3779 	gint flags;
3780 
3781 	g_assert (value != NULL);
3782 	len = g_bytes_get_size (value);
3783 
3784 	/* Integers must be at least one byte long */
3785 	if (len == 0)
3786 		return anode_failure (node, "zero length integer");
3787 
3788 	flags = anode_def_flags (node);
3789 	if (flags & FLAG_LIST) {
3790 		/* Parse out the value, we only support small integers*/
3791 		if (!anode_read_integer_ulong (node, value, &val))
3792 			return anode_failure (node, "integer not part of list");
3793 
3794 		/* Look through the list of constants */
3795 		found = FALSE;
3796 		constants = anode_opts_lookup (node, EGG_ASN1X_CONSTANT, NULL);
3797 		for (l = constants; l; l = g_list_next (l)) {
3798 			check = anode_def_value_as_ulong (l->data);
3799 			g_return_val_if_fail (check != G_MAXULONG, FALSE);
3800 			if (check == val) {
3801 				found = TRUE;
3802 				break;
3803 			}
3804 		}
3805 		g_list_free (constants);
3806 
3807 		if (!found)
3808 			return anode_failure (node, "integer not part of listed set");
3809 	}
3810 
3811 	return TRUE;
3812 }
3813 
3814 static gboolean
anode_validate_enumerated(GNode * node,GBytes * value)3815 anode_validate_enumerated (GNode *node,
3816                            GBytes *value)
3817 {
3818 	const guchar *buf;
3819 	gsize length;
3820 
3821 	g_assert (value != NULL);
3822 
3823 	buf = g_bytes_get_data (value, &length);
3824 
3825 	/* Enumerated must be positive */
3826 	if (length > 0 && (buf[0] & 0x80))
3827 		return anode_failure (node, "enumerated must be positive");
3828 
3829 	return anode_validate_integer (node, value);
3830 }
3831 
3832 static gboolean
anode_validate_boolean(GNode * node,GBytes * value)3833 anode_validate_boolean (GNode *node,
3834                         GBytes *value)
3835 {
3836 	const guchar *buf;
3837 	gsize len;
3838 
3839 	g_assert (value != NULL);
3840 	buf = g_bytes_get_data (value, &len);
3841 
3842 	/* Must one byte, and zero or all ones */
3843 	if (len != 1)
3844 		return anode_failure (node, "invalid length boolean");
3845 	if (buf[0] != 0x00 && buf[0] != 0xFF)
3846 		return anode_failure (node, "boolean must be true or false");
3847 	return TRUE;
3848 }
3849 
3850 static gboolean
anode_validate_bit_string(GNode * node,GBytes * value)3851 anode_validate_bit_string (GNode *node,
3852                            GBytes *value)
3853 {
3854 	g_assert (value != NULL);
3855 
3856 	/* All the decode validation done in anode_decode_bit_string */
3857 	return TRUE;
3858 }
3859 
3860 static gboolean
anode_validate_string(GNode * node,GBytes * value)3861 anode_validate_string (GNode *node,
3862                        GBytes *value)
3863 {
3864 	gsize length;
3865 
3866 	if (!anode_read_string_simple (node, value, NULL, &length))
3867 		g_return_val_if_reached (FALSE);
3868 
3869 	return anode_validate_size (node, (gulong)length);
3870 }
3871 
3872 static gboolean
anode_validate_object_id(GNode * node,GBytes * value)3873 anode_validate_object_id (GNode *node,
3874                           GBytes *value)
3875 {
3876 	return anode_read_object_id (node, value, NULL);
3877 }
3878 
3879 static gboolean
anode_validate_null(GNode * node,GBytes * value)3880 anode_validate_null (GNode *node,
3881                      GBytes *value)
3882 {
3883 	g_assert (value != NULL);
3884 	return (g_bytes_get_size (value) == 0);
3885 }
3886 
3887 static gboolean
anode_validate_time(GNode * node,GBytes * value)3888 anode_validate_time (GNode *node,
3889                      GBytes *value)
3890 {
3891 	glong time;
3892 	struct tm when;
3893 	return anode_read_time (node, value, &when, &time);
3894 }
3895 
3896 static gboolean
anode_validate_choice(GNode * node,gboolean strict)3897 anode_validate_choice (GNode *node,
3898                        gboolean strict)
3899 {
3900 	GNode *child, *choice;
3901 	Anode *an;
3902 
3903 	/* One and only one of the children must be set */
3904 	choice = egg_asn1x_get_choice (node);
3905 	if (!choice)
3906 		return anode_failure (node, "one choice must be set");
3907 
3908 	if (!anode_validate_anything (choice, strict))
3909 		return FALSE;
3910 
3911 	for (child = node->children; child; child = child->next) {
3912 		if (child != choice) {
3913 			an = (Anode*)child->data;
3914 			if (an->chosen)
3915 				return anode_failure (node, "only one choice may be set");
3916 		}
3917 	}
3918 
3919 	return TRUE;
3920 }
3921 
3922 static gboolean
anode_validate_sequence_or_set(GNode * node,gboolean strict)3923 anode_validate_sequence_or_set (GNode *node,
3924                                 gboolean strict)
3925 {
3926 	GNode *child;
3927 
3928 	/* If this is optional, and has no values, then that's all good */
3929 	if (anode_def_flags (node) & FLAG_OPTION) {
3930 		if (!egg_asn1x_have (node))
3931 			return TRUE;
3932 	}
3933 
3934 	/* All of the children must validate properly */
3935 	for (child = node->children; child; child = child->next) {
3936 		if (!anode_validate_anything (child, strict))
3937 			return FALSE;
3938 	}
3939 
3940 	return TRUE;
3941 }
3942 
3943 static gboolean
anode_validate_sequence_or_set_of(GNode * node,gboolean strict)3944 anode_validate_sequence_or_set_of (GNode *node,
3945                                    gboolean strict)
3946 {
3947 	GNode *child;
3948 	gulong count;
3949 
3950 	count = 0;
3951 
3952 	/* All the children must validate properly */
3953 	for (child = node->children; child; child = child->next) {
3954 		if (egg_asn1x_have (child)) {
3955 			if (!anode_validate_anything (child, strict))
3956 				return FALSE;
3957 			count++;
3958 		}
3959 	}
3960 
3961 	if (count == 0 && anode_def_flags (node) & FLAG_OPTION)
3962 		return TRUE;
3963 
3964 	return anode_validate_size (node, count);
3965 }
3966 
3967 static gboolean
anode_validate_anything(GNode * node,gboolean strict)3968 anode_validate_anything (GNode *node,
3969                          gboolean strict)
3970 {
3971 	GBytes *value;
3972 	Atlv *tlv;
3973 	gint type;
3974 	gint flags;
3975 
3976 	type = anode_def_type (node);
3977 	flags = anode_def_flags (node);
3978 
3979 	/* Handle these specially */
3980 	switch (type) {
3981 	case EGG_ASN1X_CHOICE:
3982 		return anode_validate_choice (node, strict);
3983 
3984 	case EGG_ASN1X_SEQUENCE:
3985 	case EGG_ASN1X_SET:
3986 		return anode_validate_sequence_or_set (node, strict);
3987 
3988 	case EGG_ASN1X_SEQUENCE_OF:
3989 	case EGG_ASN1X_SET_OF:
3990 		return anode_validate_sequence_or_set_of (node, strict);
3991 
3992 	default:
3993 		break;
3994 	}
3995 
3996 	/* Values that have been configured */
3997 	value = anode_get_value (node);
3998 	if (value) {
3999 		switch (type) {
4000 		case EGG_ASN1X_INTEGER:
4001 			return anode_validate_integer (node, value);
4002 		case EGG_ASN1X_ENUMERATED:
4003 			return anode_validate_enumerated (node, value);
4004 		case EGG_ASN1X_BOOLEAN:
4005 			return anode_validate_boolean (node, value);
4006 		case EGG_ASN1X_BIT_STRING:
4007 			return anode_validate_bit_string (node, value);
4008 		case EGG_ASN1X_OCTET_STRING:
4009 		case EGG_ASN1X_GENERAL_STRING:
4010 		case EGG_ASN1X_NUMERIC_STRING:
4011 		case EGG_ASN1X_IA5_STRING:
4012 		case EGG_ASN1X_TELETEX_STRING:
4013 		case EGG_ASN1X_PRINTABLE_STRING:
4014 		case EGG_ASN1X_UTF8_STRING:
4015 		case EGG_ASN1X_VISIBLE_STRING:
4016 			return anode_validate_string (node, value);
4017 		case EGG_ASN1X_BMP_STRING:
4018 		case EGG_ASN1X_UNIVERSAL_STRING:
4019 			return TRUE; /* TODO: Need to validate strings more completely */
4020 		case EGG_ASN1X_OBJECT_ID:
4021 			return anode_validate_object_id (node, value);
4022 		case EGG_ASN1X_NULL:
4023 			return anode_validate_null (node, value);
4024 		case EGG_ASN1X_TIME:
4025 		case EGG_ASN1X_UTC_TIME:
4026 		case EGG_ASN1X_GENERALIZED_TIME:
4027 			return anode_validate_time (node, value);
4028 		default:
4029 			g_assert_not_reached ();
4030 		}
4031 	}
4032 
4033 	/* See if there's a tlv parsed */
4034 	tlv = anode_get_parsed (node);
4035 	if (tlv) {
4036 		switch (type) {
4037 		case EGG_ASN1X_ANY:
4038 		case EGG_ASN1X_GENERAL_STRING:
4039 		case EGG_ASN1X_OCTET_STRING:
4040 		case EGG_ASN1X_NUMERIC_STRING:
4041 		case EGG_ASN1X_IA5_STRING:
4042 		case EGG_ASN1X_TELETEX_STRING:
4043 		case EGG_ASN1X_PRINTABLE_STRING:
4044 		case EGG_ASN1X_UTF8_STRING:
4045 		case EGG_ASN1X_VISIBLE_STRING:
4046 		case EGG_ASN1X_BMP_STRING:
4047 		case EGG_ASN1X_UNIVERSAL_STRING:
4048 			return TRUE;
4049 		default:
4050 			break; /* UNREACHABLE: fix compiler warning */
4051 		}
4052 	}
4053 
4054 	if (flags & FLAG_OPTION)
4055 		return TRUE;
4056 	if (flags & FLAG_DEFAULT)
4057 		return TRUE;
4058 	return anode_failure (node, "missing value");
4059 }
4060 
4061 gboolean
egg_asn1x_validate(GNode * asn,gboolean strict)4062 egg_asn1x_validate (GNode *asn,
4063                     gboolean strict)
4064 {
4065 	g_return_val_if_fail (asn, FALSE);
4066 	return anode_validate_anything (asn, strict);
4067 }
4068 
4069 /* -----------------------------------------------------------------------------------
4070  * TREE CREATION
4071  */
4072 
4073 static gint
compare_nodes_by_tag(gconstpointer a,gconstpointer b)4074 compare_nodes_by_tag (gconstpointer a, gconstpointer b)
4075 {
4076 	GNode *na = (gpointer)a;
4077 	GNode *nb = (gpointer)b;
4078 	gulong taga, tagb;
4079 
4080 	g_return_val_if_fail (anode_def_flags (na) & FLAG_TAG, 0);
4081 	g_return_val_if_fail (anode_def_flags (nb) & FLAG_TAG, 0);
4082 
4083 	taga = anode_calc_tag (na);
4084 	g_return_val_if_fail (taga != G_MAXULONG, 0);
4085 
4086 	tagb = anode_calc_tag (nb);
4087 	g_return_val_if_fail (tagb != G_MAXULONG, 0);
4088 
4089 	if (taga == tagb)
4090 		return 0;
4091 	return (taga < tagb) ? -1 : 1;
4092 }
4093 
4094 static const EggAsn1xDef *
adef_next_sibling(const EggAsn1xDef * def)4095 adef_next_sibling (const EggAsn1xDef *def)
4096 {
4097 	int depth = 0;
4098 
4099 	g_assert (def);
4100 	g_assert (def->value || def->type || def->name);
4101 
4102 	if ((def->type & FLAG_RIGHT) == 0)
4103 		return NULL;
4104 
4105 	/* Skip past any children */
4106 	if ((def->type & FLAG_DOWN) == FLAG_DOWN) {
4107 		depth += 1;
4108 		while (depth > 0) {
4109 			++def;
4110 			if ((def->type & FLAG_DOWN) == FLAG_DOWN)
4111 				depth += 1;
4112 			if ((def->type & FLAG_RIGHT) == 0)
4113 				depth -= 1;
4114 		}
4115 	}
4116 
4117 	++def;
4118 	g_return_val_if_fail (def->value || def->type || def->name, NULL);
4119 	return def;
4120 }
4121 
4122 static const EggAsn1xDef *
adef_first_child(const EggAsn1xDef * def)4123 adef_first_child (const EggAsn1xDef *def)
4124 {
4125 	g_assert (def);
4126 	g_assert (def->value || def->type || def->name);
4127 
4128 	if ((def->type & FLAG_DOWN) == 0)
4129 		return NULL;
4130 
4131 	++def;
4132 	g_return_val_if_fail (def->value || def->type || def->name, NULL);
4133 	return def;
4134 }
4135 
4136 static const EggAsn1xDef *
lookup_def_of_type(const EggAsn1xDef * defs,const gchar * name,gint type)4137 lookup_def_of_type (const EggAsn1xDef *defs,
4138                     const gchar *name,
4139                     gint type)
4140 {
4141 	const EggAsn1xDef *def;
4142 
4143 	g_assert (defs);
4144 	g_assert (defs->value || defs->type || defs->name);
4145 
4146 	for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
4147 		if ((def->type & 0xFF) == type && def->name && g_str_equal (name, def->name))
4148 			return def;
4149 	}
4150 
4151 	return NULL;
4152 }
4153 
4154 static gboolean
traverse_and_prepare(GNode * node,gpointer data)4155 traverse_and_prepare (GNode *node, gpointer data)
4156 {
4157 	const EggAsn1xDef *defs = data;
4158 	const EggAsn1xDef *def;
4159 	const gchar *identifier;
4160 	Anode *an, *anj;
4161 	GNode *join = NULL;
4162 	GNode *child, *next;
4163 	GList *list = NULL, *l;
4164 
4165 	/* A while, because the stuff we join, could also be an identifier */
4166 	while (anode_def_type (node) == EGG_ASN1X_IDENTIFIER) {
4167 		an = node->data;
4168 		identifier = an->join ? an->join->value : an->def->value;
4169 		g_return_val_if_fail (identifier, TRUE);
4170 		egg_asn1x_destroy (join);
4171 		join = egg_asn1x_create (defs, identifier);
4172 		g_return_val_if_fail (join, TRUE);
4173 		anj = join->data;
4174 		an->join = anj->def;
4175 	}
4176 
4177 	/* Move all the children of join node into our node */
4178 	if (join) {
4179 		list = NULL;
4180 		for (child = join->children, list = NULL; child; child = child->next)
4181 			list = g_list_prepend (list, child);
4182 		list = g_list_reverse (list);
4183 		for (l = list; l; l = g_list_next (l)) {
4184 			child = l->data;
4185 			g_node_unlink (child);
4186 			g_node_append (node, child);
4187 		}
4188 		g_list_free (list);
4189 		list = NULL;
4190 	}
4191 
4192 	/* Lookup the max set size */
4193 	if (anode_def_type (node) == EGG_ASN1X_SIZE) {
4194 		identifier = anode_def_name (node);
4195 		if (identifier && !g_str_equal (identifier, "MAX") &&
4196 		    g_ascii_isalpha (identifier[0])) {
4197 			def = lookup_def_of_type (defs, identifier, EGG_ASN1X_INTEGER);
4198 			g_return_val_if_fail (def, TRUE);
4199 			anode_opt_add (node, def);
4200 		}
4201 	}
4202 
4203 	/* Anything child not a real node, we put into opts */
4204 	if (anode_def_type_is_real (node)) {
4205 		child = node->children;
4206 		while (child) {
4207 			next = child->next;
4208 			if (!anode_def_type_is_real (child)) {
4209 				an = child->data;
4210 				anode_opt_add (node, an->def);
4211 				for (l = an->opts; l; l = g_list_next (l))
4212 					anode_opt_add (node, l->data);
4213 				g_node_unlink (child);
4214 				anode_destroy (child);
4215 			}
4216 			child = next;
4217 		}
4218 	}
4219 
4220 	if (join) {
4221 		an = join->data;
4222 		for (l = an->opts; l; l = g_list_next (l))
4223 			anode_opt_add (node, l->data);
4224 		egg_asn1x_destroy (join);
4225 	}
4226 
4227 	/* Sort the children of any sets */
4228 	if (anode_def_type (node) == EGG_ASN1X_SET) {
4229 		for (child = node->children; child; child = child->next)
4230 			list = g_list_prepend (list, child);
4231 		list = g_list_sort (list, compare_nodes_by_tag);
4232 		for (l = list; l; l = g_list_next (l))
4233 			g_node_unlink (l->data);
4234 		for (l = list; l; l = g_list_next (l))
4235 			g_node_append (node, l->data);
4236 		g_list_free (list);
4237 		list = NULL;
4238 	}
4239 
4240 	/* Continue traversal */
4241 	return FALSE;
4242 }
4243 
4244 static const EggAsn1xDef *
match_oid_in_definition(const EggAsn1xDef * def,GHashTable * names,const gchar * match,const gchar ** problem)4245 match_oid_in_definition (const EggAsn1xDef *def,
4246                          GHashTable *names,
4247                          const gchar *match,
4248                          const gchar **problem)
4249 {
4250 	const EggAsn1xDef *result = NULL;
4251 	const EggAsn1xDef *odef;
4252 	const gchar *value;
4253 	GString *oid = NULL;
4254 
4255 	g_assert (match);
4256 	g_assert (problem);
4257 	g_assert (names);
4258 
4259 	for (odef = adef_first_child (def); odef; odef = adef_next_sibling (odef)) {
4260 		if ((odef->type & 0xFF) != EGG_ASN1X_CONSTANT)
4261 			continue;
4262 
4263 		g_return_val_if_fail (odef->value, NULL);
4264 		if (strspn (odef->value, "01234567890") == strlen (odef->value)) {
4265 			value = odef->value;
4266 
4267 		} else {
4268 			value = g_hash_table_lookup (names, odef->value);
4269 
4270 			/* A name resolution problem */
4271 			if (!value) {
4272 				if (oid)
4273 					g_string_free (oid, TRUE);
4274 				*problem = odef->value;
4275 				return NULL;
4276 			}
4277 		}
4278 
4279 		if (oid) {
4280 			g_string_append_c (oid, '.');
4281 			g_string_append (oid, value);
4282 		} else {
4283 			oid = g_string_new (value);
4284 		}
4285 	}
4286 
4287 	if (oid != NULL) {
4288 		if (g_str_equal (oid->str, match))
4289 			result = adef_next_sibling (def);
4290 		g_assert (def->name);
4291 		g_hash_table_insert (names, (gchar*)def->name, g_string_free (oid, FALSE));
4292 	}
4293 
4294 	return result;
4295 }
4296 
4297 static const EggAsn1xDef *
match_oid_in_definitions(const EggAsn1xDef * defs,const gchar * match)4298 match_oid_in_definitions (const EggAsn1xDef *defs,
4299                           const gchar *match)
4300 {
4301 	const EggAsn1xDef *def;
4302 	const EggAsn1xDef *result;
4303 	GHashTable *names;
4304 	gboolean progress;
4305 	const gchar *problem;
4306 
4307 	names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
4308 	result = NULL;
4309 
4310 	for (;;) {
4311 		progress = FALSE;
4312 		problem = NULL;
4313 
4314 		for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
4315 
4316 			/* Only work with object ids, and ones with names */
4317 			if ((def->type & 0xFF) != EGG_ASN1X_OBJECT_ID || !def->name)
4318 				continue;
4319 
4320 			/* If we've already seen this one, skip */
4321 			if (g_hash_table_lookup (names, def->name))
4322 				continue;
4323 
4324 			progress = TRUE;
4325 			result = match_oid_in_definition (def, names, match, &problem);
4326 			if (result != NULL)
4327 				break;
4328 		}
4329 
4330 		if (!problem || result) {
4331 			break;
4332 		} else if (problem && !progress) {
4333 			g_warning ("couldn't find oid definition in ASN.1 for: %s", problem);
4334 			g_return_val_if_reached (NULL);
4335 		}
4336 	}
4337 
4338 	g_hash_table_destroy (names);
4339 	return result;
4340 }
4341 
4342 static gboolean
is_oid_number(const gchar * p)4343 is_oid_number (const gchar *p)
4344 {
4345 	gboolean must = TRUE;
4346 	gint i;
4347 
4348 	for (i = 0; p[i] != '\0'; i++) {
4349 		if (g_ascii_isdigit (p[i])) {
4350 			must = FALSE;
4351 		} else if (must) {
4352 			return FALSE;
4353 		} else {
4354 			if (p[i] != '.')
4355 				return FALSE;
4356 			must = TRUE;
4357 		}
4358 	}
4359 
4360 	return !must;
4361 }
4362 
4363 GNode*
egg_asn1x_create(const EggAsn1xDef * defs,const gchar * type)4364 egg_asn1x_create (const EggAsn1xDef *defs,
4365                   const gchar *type)
4366 {
4367 	const EggAsn1xDef *def;
4368 	GNode *root, *parent, *node;
4369 	int flags;
4370 
4371 	g_return_val_if_fail (defs, NULL);
4372 	g_return_val_if_fail (type, NULL);
4373 
4374 	/* An OID */
4375 	if (is_oid_number (type)) {
4376 		def = match_oid_in_definitions (defs, type);
4377 
4378 	/* An Identifier */
4379 	} else {
4380 		for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
4381 			if (def->name && g_str_equal (type, def->name))
4382 				break;
4383 		}
4384 	}
4385 
4386 	if (def == NULL || !def->name || !def->type)
4387 		return NULL;
4388 
4389 	/* The node for this item */
4390 	root = anode_new (def);
4391 
4392 	/* Build up nodes for underlying level */
4393 	if (def->type & FLAG_DOWN) {
4394 		node = root;
4395 		for (;;) {
4396 			if (def->type & FLAG_DOWN) {
4397 				parent = node;
4398 			} else if (def->type & FLAG_RIGHT) {
4399 				g_assert (node->parent);
4400 				parent = node->parent;
4401 			} else {
4402 				parent = node->parent;
4403 				while (parent) {
4404 					flags = anode_def_flags (parent);
4405 					parent = parent->parent;
4406 					if (flags & FLAG_RIGHT)
4407 						break;
4408 				}
4409 			}
4410 
4411 			if (!parent)
4412 				break;
4413 
4414 			++def;
4415 			node = anode_new (def);
4416 			g_node_append (parent, node);
4417 		}
4418 	}
4419 
4420 	/* Load up sub identifiers */
4421 	g_node_traverse (root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
4422 	                 traverse_and_prepare, (gpointer)defs);
4423 
4424 	return root;
4425 }
4426 
4427 GNode*
egg_asn1x_create_quark(const EggAsn1xDef * defs,GQuark type)4428 egg_asn1x_create_quark (const EggAsn1xDef *defs,
4429                         GQuark type)
4430 {
4431 	g_return_val_if_fail (type, NULL);
4432 	return egg_asn1x_create (defs, g_quark_to_string (type));
4433 }
4434 
4435 GNode *
egg_asn1x_create_and_decode_full(const EggAsn1xDef * defs,const gchar * identifier,GBytes * data,gint options)4436 egg_asn1x_create_and_decode_full (const EggAsn1xDef *defs,
4437                                   const gchar *identifier,
4438                                   GBytes *data,
4439                                   gint options)
4440 {
4441 	GNode *asn;
4442 
4443 	g_return_val_if_fail (defs != NULL, NULL);
4444 	g_return_val_if_fail (identifier != NULL, NULL);
4445 	g_return_val_if_fail (data != NULL, NULL);
4446 
4447 	asn = egg_asn1x_create (defs, identifier);
4448 	g_return_val_if_fail (asn, NULL);
4449 
4450 	if (!egg_asn1x_decode_full (asn, data, options)) {
4451 		egg_asn1x_destroy (asn);
4452 		return NULL;
4453 	}
4454 
4455 	return asn;
4456 
4457 }
4458 
4459 GNode*
egg_asn1x_create_and_decode(const EggAsn1xDef * defs,const gchar * identifier,GBytes * data)4460 egg_asn1x_create_and_decode (const EggAsn1xDef *defs,
4461                              const gchar *identifier,
4462                              GBytes *data)
4463 {
4464 	g_return_val_if_fail (defs != NULL, NULL);
4465 	g_return_val_if_fail (identifier != NULL, NULL);
4466 	g_return_val_if_fail (data != NULL, NULL);
4467 
4468 	return egg_asn1x_create_and_decode_full (defs, identifier, data, 0);
4469 }
4470 
4471 /* -----------------------------------------------------------------------------------
4472  * DUMPING and MESSAGES
4473  */
4474 
4475 static void
dump_append_type(GString * output,gint type)4476 dump_append_type (GString *output, gint type)
4477 {
4478 	#define XX(x) if (type == EGG_ASN1X_##x) g_string_append (output, #x " ")
4479 	XX(CONSTANT); XX(IDENTIFIER); XX(INTEGER); XX(BOOLEAN); XX(SEQUENCE); XX(BIT_STRING);
4480 	XX(OCTET_STRING); XX(TAG); XX(DEFAULT); XX(SIZE); XX(SEQUENCE_OF); XX(OBJECT_ID); XX(ANY);
4481 	XX(SET); XX(SET_OF); XX(DEFINITIONS); XX(TIME); XX(UTC_TIME); XX(GENERALIZED_TIME); XX(CHOICE); XX(IMPORTS); XX(NULL);
4482 	XX(ENUMERATED); XX(GENERAL_STRING); XX(NUMERIC_STRING); XX(IA5_STRING); XX(TELETEX_STRING);
4483 	XX(PRINTABLE_STRING); XX(UNIVERSAL_STRING); XX(BMP_STRING); XX(UTF8_STRING); XX(VISIBLE_STRING);
4484 
4485 	if (output->len == 0)
4486 		g_string_printf (output, "%d ", (int)type);
4487 	#undef XX
4488 }
4489 
4490 static void
dump_append_flags(GString * output,gint flags)4491 dump_append_flags (GString *output, gint flags)
4492 {
4493 	#define XX(x) if ((FLAG_##x & flags) == FLAG_##x) g_string_append (output, #x " ")
4494 	XX(UNIVERSAL); XX(PRIVATE); XX(APPLICATION); XX(EXPLICIT); XX(IMPLICIT); XX(TAG); XX(OPTION);
4495 	XX(DEFAULT); XX(TRUE); XX(FALSE); XX(LIST); XX(MIN_MAX); XX(1_PARAM); XX(SIZE); XX(DEFINED_BY);
4496 	XX(GENERALIZED); XX(UTC); XX(IMPORTS); XX(NOT_USED); XX(SET); XX(ASSIGN);
4497 	/* XX(DOWN); XX(RIGHT); */
4498 	#undef XX
4499 }
4500 
4501 static gboolean
traverse_and_dump(GNode * node,gpointer unused)4502 traverse_and_dump (GNode *node, gpointer unused)
4503 {
4504 	EggAsn1xDef *def;
4505 	guint i, depth;
4506 	GString *output;
4507 	gchar *string;
4508 	Anode *an;
4509 	GList *l;
4510 
4511 	depth = g_node_depth (node);
4512 	for (i = 0; i < depth - 1; ++i)
4513 		g_print ("    ");
4514 
4515 	an = node->data;
4516 	output = g_string_new ("");
4517 	dump_append_type (output, anode_def_type (node));
4518 	dump_append_flags (output, anode_def_flags (node));
4519 	string = g_utf8_casefold (output->str, output->len - 1);
4520 	g_string_free (output, TRUE);
4521 	g_print ("+ %s: %s [%s]%s\n", anode_def_name (node), anode_def_value (node),
4522 	            string, an->parsed || an->value ? " *" : "");
4523 	g_free (string);
4524 
4525 	/* Print out all the options */
4526 	for (l = an->opts; l; l = g_list_next (l)) {
4527 		for (i = 0; i < depth; ++i)
4528 			g_print ("    ");
4529 
4530 		def = l->data;
4531 		output = g_string_new ("");
4532 		dump_append_type (output, def->type & 0xFF);
4533 		dump_append_flags (output, def->type);
4534 		string = g_utf8_casefold (output->str, output->len - 1);
4535 		g_string_free (output, TRUE);
4536 		g_print ("- %s: %s [%s]\n", def->name, (const gchar*)def->value, string);
4537 		g_free (string);
4538 	}
4539 
4540 	return FALSE;
4541 }
4542 
4543 void
egg_asn1x_dump(GNode * asn)4544 egg_asn1x_dump (GNode *asn)
4545 {
4546 	g_return_if_fail (asn);
4547 	g_node_traverse (asn, G_PRE_ORDER, G_TRAVERSE_ALL, -1, traverse_and_dump, NULL);
4548 }
4549 
4550 static gboolean
traverse_and_get_failure(GNode * node,gpointer user_data)4551 traverse_and_get_failure (GNode *node, gpointer user_data)
4552 {
4553 	const gchar **failure = user_data;
4554 	g_assert (!*failure);
4555 	*failure = anode_failure_get (node);
4556 	return (*failure != NULL);
4557 }
4558 
4559 const gchar*
egg_asn1x_message(GNode * asn)4560 egg_asn1x_message (GNode *asn)
4561 {
4562 	const gchar *failure = NULL;
4563 	g_return_val_if_fail (asn, NULL);
4564 	g_node_traverse (asn, G_POST_ORDER, G_TRAVERSE_ALL, -1, traverse_and_get_failure, &failure);
4565 	return failure;
4566 }
4567 
4568 /* -----------------------------------------------------------------------------------
4569  * CLEARING and DESTROYING
4570  */
4571 
4572 static gboolean
traverse_and_clear(GNode * node,gpointer unused)4573 traverse_and_clear (GNode *node, gpointer unused)
4574 {
4575 	GNode *child, *next;
4576 	gint type;
4577 
4578 	anode_clear (node);
4579 
4580 	type = anode_def_type (node);
4581 	if (type == EGG_ASN1X_SET_OF || type == EGG_ASN1X_SEQUENCE_OF) {
4582 
4583 		/* The first 'real' child is the template */
4584 		child = node->children;
4585 		g_return_val_if_fail (child, TRUE);
4586 
4587 		/* And any others are extras */
4588 		child = child->next;
4589 		while (child) {
4590 			next = child->next;
4591 			anode_destroy (child);
4592 			child = next;
4593 		}
4594 	}
4595 
4596 	/* Don't stop traversal */
4597 	return FALSE;
4598 }
4599 
4600 void
egg_asn1x_clear(GNode * asn)4601 egg_asn1x_clear (GNode *asn)
4602 {
4603 	g_return_if_fail (asn);
4604 	g_node_traverse (asn, G_POST_ORDER, G_TRAVERSE_ALL, -1, traverse_and_clear, NULL);
4605 }
4606 
4607 void
egg_asn1x_destroy(gpointer data)4608 egg_asn1x_destroy (gpointer data)
4609 {
4610 	GNode *node = data;
4611 
4612 	if (node != NULL) {
4613 		g_return_if_fail (G_NODE_IS_ROOT (node));
4614 		anode_destroy (node);
4615 	}
4616 }
4617 
4618 /* --------------------------------------------------------------------------------
4619  * TIME PARSING
4620  */
4621 
4622 glong
egg_asn1x_parse_time_general(const gchar * time,gssize n_time)4623 egg_asn1x_parse_time_general (const gchar *time, gssize n_time)
4624 {
4625 	gboolean ret;
4626 	glong value;
4627 	struct tm when;
4628 	gint offset = 0;
4629 
4630 	g_return_val_if_fail (time, -1);
4631 
4632 	if (n_time < 0)
4633 		n_time = strlen (time);
4634 
4635 	ret = parse_general_time (time, n_time, &when, &offset);
4636 	if (!ret)
4637 		return -1;
4638 
4639 	/* In order to work with 32 bit time_t. */
4640 	if (sizeof (time_t) <= 4 && when.tm_year >= 2038) {
4641 		value = (time_t)2145914603;  /* 2037-12-31 23:23:23 */
4642 
4643 	/* Convert to seconds since epoch */
4644 	} else {
4645 		value = timegm (&when);
4646 		g_return_val_if_fail (*time >= 0, FALSE);
4647 		value += offset;
4648 	}
4649 
4650 	return value;
4651 }
4652 
4653 glong
egg_asn1x_parse_time_utc(const gchar * time,gssize n_time)4654 egg_asn1x_parse_time_utc (const gchar *time, gssize n_time)
4655 {
4656 	gboolean ret;
4657 	glong value;
4658 	struct tm when;
4659 	gint offset = 0;
4660 
4661 	g_return_val_if_fail (time, -1);
4662 
4663 	if (n_time < 0)
4664 		n_time = strlen (time);
4665 
4666 	ret = parse_utc_time (time, n_time, &when, &offset);
4667 	if (!ret)
4668 		return -1;
4669 
4670 	/* In order to work with 32 bit time_t. */
4671 	if (sizeof (time_t) <= 4 && when.tm_year >= 2038) {
4672 		value = (time_t)2145914603;  /* 2037-12-31 23:23:23 */
4673 
4674 	/* Convert to seconds since epoch */
4675 	} else {
4676 		value = timegm (&when);
4677 		g_return_val_if_fail (*time >= 0, FALSE);
4678 		value += offset;
4679 	}
4680 
4681 	return value;
4682 }
4683 
4684 /* --------------------------------------------------------------------------------
4685  * BASIC RAW ELEMENT INFO
4686  */
4687 
4688 gssize
egg_asn1x_element_length(const guchar * data,gsize n_data)4689 egg_asn1x_element_length (const guchar *data,
4690                           gsize n_data)
4691 {
4692 	guchar cls;
4693 	int counter = 0;
4694 	int cb, len;
4695 	gulong tag;
4696 
4697 	if (atlv_parse_cls_tag (data, data + n_data, &cls, &tag, &cb)) {
4698 		counter += cb;
4699 		len = atlv_parse_length (data + cb, data + n_data, &cb);
4700 		counter += cb;
4701 		if (len >= 0) {
4702 			len += counter;
4703 			if (n_data >= len)
4704 				return len;
4705 		}
4706 	}
4707 
4708 	return -1;
4709 }
4710 
4711 gconstpointer
egg_asn1x_element_content(const guchar * data,gsize n_data,gsize * n_content)4712 egg_asn1x_element_content (const guchar *data,
4713                            gsize n_data,
4714                            gsize *n_content)
4715 {
4716 	int counter = 0;
4717 	guchar cls;
4718 	gulong tag;
4719 	int cb, len;
4720 
4721 	g_return_val_if_fail (data != NULL, NULL);
4722 	g_return_val_if_fail (n_content != NULL, NULL);
4723 
4724 	/* Now get the data out of this element */
4725 	if (!atlv_parse_cls_tag (data, data + n_data, &cls, &tag, &cb))
4726 		return NULL;
4727 
4728 	counter += cb;
4729 	len = atlv_parse_length (data + cb, data + n_data, &cb);
4730 	if (len < 0)
4731 		return NULL;
4732 	counter += cb;
4733 
4734 	*n_content = len;
4735 	return (const guchar*)data + counter;
4736 }
4737