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