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