suricata
util-decode-asn1.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
22  *
23  * Implements ASN1 decoding (needed for the asn1 keyword, BER, CER & DER)
24  */
25 
26 #include "suricata.h"
27 #include "suricata-common.h"
28 #include "decode.h"
29 #include "util-debug.h"
30 #include "util-unittest.h"
31 #include "util-print.h"
32 
33 #include "util-decode-asn1.h"
34 #include "conf.h"
35 
37 
39 {
40  intmax_t value = 0;
41 
42  /** set config defaults */
43  if ((ConfGetInt("asn1-max-frames", &value)) == 1) {
44  asn1_max_frames_config = (uint16_t)value;
45  SCLogDebug("Max stack frame set to %"PRIu16, asn1_max_frames_config);
46  }
47 
48 }
49 
50 /**
51  * \brief Decode and check the identifier information of the
52  * current node that is in extended format
53  *
54  * \param ac pointer to the ASN1 Context data
55  *
56  * \retval byte of the status of the parser
57  */
58 static uint8_t SCAsn1GetHighTagNumber(Asn1Ctx *ac)
59 {
60  uint8_t ret = 0;
61  uint32_t tag_num = 0;
62 
63  /* If we have a high tag num, skip the id octet */
64  ac->iter++;
65 
66  Asn1Node *node = ASN1CTX_CUR_NODE(ac);
67 
68  ret = SCAsn1CheckBounds(ac);
69  if (ret == ASN1_PARSER_ERR) {
71  return ret;
72  }
73 
74  uint8_t raw_id = *ac->iter;
75 
76  tag_num += ASN1_BER_GET_HIGH_TAG_NUM(raw_id);
77 
78  if (ASN1_BER_GET_HIGH_TAG_NUM(raw_id) == 0) {
79  /* Set event, invalid id */
82  return ASN1_PARSER_ERR;
83  }
84 
85  ac->iter++;
86  if (!ASN1_BER_IS_HIGH_TAG_END(raw_id)) {
87  do {
88  ret = SCAsn1CheckBounds(ac);
89  if (ret == ASN1_PARSER_ERR) {
91  return ret;
92  }
93 
94  raw_id = *ac->iter;
95 
96  if ((uint64_t) ((uint64_t)tag_num +
97  (uint64_t)ASN1_BER_GET_HIGH_TAG_NUM(raw_id)) > UINT32_MAX)
98  {
101  return ASN1_PARSER_ERR;
102  }
103 
104  tag_num += ASN1_BER_GET_HIGH_TAG_NUM(raw_id);
105  ac->iter++;
106  } while (!ASN1_BER_IS_HIGH_TAG_END(raw_id));
107  }
108  node->id.tag_num = tag_num;
109 
110  return ASN1_PARSER_OK;
111 }
112 
113 /**
114  * \brief Decode and check the length, of the current node
115  * in definite but extended format, that we are parsing,
116  * checking invalid opts
117  *
118  * \param ac pointer to the ASN1 Context data
119  *
120  * \retval byte of the status of the parser
121  */
122 static uint32_t SCAsn1GetLengthLongForm(Asn1Ctx *ac)
123 {
124  uint8_t raw_len = *ac->iter;
125  uint8_t ret = 0;
126  uint32_t content_len = 0;
127  uint8_t oct_len = ASN1_BER_GET_LONG_LEN_OCTETS(raw_len);
128  uint8_t i = 0;
129 
130  Asn1Node *node = ASN1CTX_CUR_NODE(ac);
131 
132  for (; i < oct_len; i++) {
133  ac->iter++;
134 
135  ret = SCAsn1CheckBounds(ac);
136  if (ret == ASN1_PARSER_ERR) {
138  return ASN1_PARSER_ERR;
139  }
140 
141  raw_len = *ac->iter;
142  if (raw_len == 0xFF && ac->iter == node->len.ptr + 1) {
143  /* 8.1.3.5, 0xFF shall not be used */
146  return ASN1_PARSER_ERR;
147  }
148 
149  if ((uint64_t) ((uint64_t)content_len +
150  (uint64_t) ASN1_BER_GET_HIGH_TAG_NUM(raw_len)) > UINT32_MAX)
151  {
154  return ASN1_PARSER_ERR;
155  }
156 
157  content_len += raw_len;
158  }
159 
160  ac->iter++;
161 
162  node->len.len = content_len;
163  return ASN1_PARSER_OK;
164 }
165 
166 
167 /**
168  * \brief Check the content length and perform other inspections
169  * and decodings if necessary
170  *
171  * \param ac pointer to the ASN1 Context data
172  *
173  * \retval byte of the status of the parser
174  */
176 {
177 
178  Asn1Node *node = ASN1CTX_CUR_NODE(ac);
179 
180  /* Uops, if we are done, we break here */
181  if (node->flags & ASN1_NODE_IS_EOC)
182  return ASN1_PARSER_OK;
183 
184  /* First check the form of length (BER, DER, CER)
185  * and if we are on a zero length */
186  if (node->len.form != ASN1_BER_LEN_INDEFINITE &&
187  node->len.len == 0)
188  {
189  node->data.len = 0;
190  return ASN1_PARSER_OK;
191  }
192 
193  node->data.ptr = ac->iter;
194  /* If we have a complete length, check that
195  * it is in bounds */
196  if (ac->iter + node->len.len > ac->end) {
197  /* We do not have all the content octets! */
198  node->data.len = ac->end - ac->iter;
199  } else {
200  /* We have all the content octets */
201  node->data.len = node->len.len;
202  }
203 
204  return ASN1_PARSER_OK;
205 }
206 
207 /**
208  * \brief Decode and check the length, of the current node
209  * that we are parsing, also check invalid opts
210  *
211  * \param ac pointer to the ASN1 Context data
212  *
213  * \retval byte of the status of the parser
214  */
216 {
217  uint8_t ret = 0;
218  ret = SCAsn1CheckBounds(ac);
219  if (ret == ASN1_PARSER_ERR) {
221  return ASN1_PARSER_ERR;
222  }
223 
224  Asn1Node *node = ASN1CTX_CUR_NODE(ac);
225  /* Store the position */
226  node->len.ptr = ac->iter;
227 
228  uint8_t len_byte = *ac->iter;
229 
230  //SCPrintByteBin(len_byte);
231 
232  if (*node->id.ptr == 0 && len_byte == 0) {
233  node->flags |= ASN1_NODE_IS_EOC;
234  ac->iter++;
235  return ASN1_PARSER_OK;
236  }
237 
238  if (ASN1_BER_IS_INDEFINITE_LEN(len_byte)) {
240  node->len.len = 0;
241  ac->iter++;
242 
243  uint8_t *tmp_iter = ac->iter;
244 
245  /* Check that e-o-c is in bounds */
246  for (; tmp_iter < ac->end - 1; tmp_iter++) {
247  if (ASN1_BER_IS_EOC(tmp_iter)) {
248  node->data.len = tmp_iter - ac->iter;
249  node->len.len = tmp_iter - ac->iter;
250  return ASN1_PARSER_OK;
251  }
252  }
253 
254  /* EOC Not found */
257 
258  return ASN1_PARSER_ERR;
259 
260  } else {
261  /* Look which form we get (and if it apply to the id type) */
262  if (ASN1_BER_IS_SHORT_LEN(len_byte)) {
263  node->len.form = ASN1_BER_LEN_SHORT;
264  node->len.len = ASN1_BER_GET_SHORT_LEN(len_byte);
265  ac->iter++;
266  } else {
267  node->len.form = ASN1_BER_LEN_LONG;
268 
269  /* Ok, let's parse the long form */
270  return SCAsn1GetLengthLongForm(ac);
271  }
272 
273  }
274  return ASN1_PARSER_OK;
275 }
276 
277 /**
278  * \brief Decode and check the identifier information of the
279  * current node that we are parsing, also check invalid opts
280  *
281  * \param ac pointer to the ASN1 Context data
282  *
283  * \retval byte of the status of the parser
284  */
286 {
287  uint8_t ret = 0;
288  ret = SCAsn1CheckBounds(ac);
289  if (ret == ASN1_PARSER_ERR) {
291  return ret;
292  }
293 
294  Asn1Node *node = ASN1CTX_CUR_NODE(ac);
295  /* Store the position */
296  node->id.ptr = ac->iter;
297 
298  //SCPrintByteBin(*ac->iter);
299 
300  node->id.class_tag = ASN1_BER_GET_CLASS_TAG(*ac->iter);
301  node->id.tag_type = ASN1_BER_IS_CONSTRUCTED(*ac->iter);
302 
303  if (ASN1_BER_IS_HIGH_TAG(*ac->iter)) {
304  return SCAsn1GetHighTagNumber(ac);
305  } else {
306  node->id.tag_num = ASN1_BER_GET_LOW_TAG_NUM(*ac->iter);
307  ac->iter++;
308  }
309 
310  return ASN1_PARSER_OK;
311 }
312 
313 /**
314  * \brief Helper function that print the bits of a byte
315  * to check encoding internals
316  * \param byte value of the byte
317  */
318 void SCPrintByteBin(uint8_t byte)
319 {
320  uint8_t i = 0;
321  for (i = 8; i > 0; i--) {
322  printf("%"PRIu8, (uint8_t)((byte >> (i - 1)) & 0x01));
323  if (i == 5)
324  printf(" ");
325  }
326  printf("\n");
327 }
328 
329 /**
330  * \brief check if we have remaining data available,
331  * otherwise the parser should stop
332  * \param ac Asn1Ctx pointer initialized
333  * \retval 1 if we are out of bounds, 0 if not
334  */
336 {
337  return (ac->iter < ac->end && ac->iter >= ac->data)? ASN1_PARSER_OK : ASN1_PARSER_ERR;
338 }
339 
340 
341 /**
342  * \brief Create a new ASN1 Parsing context
343  *
344  * \retval Asn1Ctx pointer to the new ctx
345  */
347 {
348  Asn1Ctx *ac = SCMalloc(sizeof(Asn1Ctx));
349 
350  if (unlikely(ac == NULL)) {
351  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
352  return NULL;
353  }
354  memset(ac, 0, sizeof(Asn1Ctx));
355 
357  if (ac->asn1_stack == NULL) {
358  SCFree(ac);
359  return NULL;
360  }
361  memset(ac->asn1_stack, 0, sizeof(Asn1Node *) * asn1_max_frames_config);
362 
363  return ac;
364 }
365 
366 /**
367  * \brief Destroy an ASN1 Parsing context
368  *
369  * \param Asn1Ctx pointer to the new ctx
370  */
372 {
373  if (ac == NULL)
374  return;
375 
376  for (uint16_t i = 0; i < asn1_max_frames_config; i++) {
377  Asn1Node *node = ASN1CTX_GET_NODE(ac, i);
378  if (node == NULL) {
379  break;
380  }
381  SCFree(node);
382  }
383 
384  SCFree(ac->asn1_stack);
385  SCFree(ac);
386 }
387 
388 /**
389  * \brief Create a new node at the array stack of frames in the ctx
390  *
391  * \param ac pointer to the ASN1 ctx
392  * \param node index of the frame that we are going to allocate
393  * at the asn1 stack in the parser
394  *
395  * \retval Asn1Node pointer to the new node allocated
396  */
397 static Asn1Node *SCAsn1CtxNewFrame(Asn1Ctx *ac, uint16_t node)
398 {
399  if (node >= asn1_max_frames_config) {
400  return NULL;
401  }
402 
403  if (ac->asn1_stack[node] == NULL)
404  ac->asn1_stack[node] = SCMalloc(sizeof(Asn1Node));
405 
406  if (ac->asn1_stack[node] == NULL)
407  return NULL;
408 
409  memset(ac->asn1_stack[node], 0, sizeof(Asn1Node));
410  return ac->asn1_stack[node];
411 }
412 
413 /**
414  * \brief Initialize the data of the ASN1 parser ctx with the asn1 raw buffer
415  *
416  * \param ac pointer to the ASN1 ctx
417  * \param data pointer to the data to process (binary raw of asn1)
418  * \param length length of the asn1 raw buffer
419  *
420  * \retval void
421  */
422 void SCAsn1CtxInit(Asn1Ctx *ac, uint8_t *data, uint16_t length)
423 {
424  ac->data = data;
425  ac->iter = data;
426  ac->len = length;
427  ac->end = data + length;
429 }
430 
431 /**
432  * \brief Decode the nodes/frames located at certain position/level
433  *
434  * \param ac pointer to the ASN1 ctx
435  * \param node_id node index at the asn1 stack of the ctx
436  *
437  * \retval byte of parser status
438  */
439 uint8_t SCAsn1Decode(Asn1Ctx *ac, uint16_t node_id)
440 {
441  Asn1Node *node = NULL;
442  uint8_t ret = 0;
443 
444  /* while remaining data, and no fatal error, or end, or max stack frames */
445  while (ac->iter < ac->end
446  && !(ac->parser_status & ASN1_STATUS_DONE)
448  {
449  /* Prepare a new frame */
450  if (SCAsn1CtxNewFrame(ac, node_id) == NULL)
451  break;
452 
453  ac->cur_frame = node_id;
454  node = ASN1CTX_GET_NODE(ac, node_id);
455 
456  SCLogDebug("ASN1 Getting ID, cur:%x remaining %"PRIu32, (uint8_t)*ac->iter, (uint32_t)(ac->end - ac->iter));
457 
458  /* Get identifier/tag */
459  ret = SCAsn1DecodeIdentifier(ac);
460  if (ret == ASN1_PARSER_ERR) {
461  SCLogDebug("Error parsing identifier");
462 
464  ac->ctx_flags |= node->flags;
465 
466  break;
467  }
468 
469  SCLogDebug("ASN1 Getting LEN");
470 
471  /* Get length of content */
472  ret = SCAsn1DecodeLength(ac);
473  if (ret == ASN1_PARSER_ERR) {
474  SCLogDebug("Error parsing length");
475 
477  ac->ctx_flags |= node->flags;
478 
479  break;
480  }
481 
482  if ( !(node->flags & ASN1_NODE_IS_EOC)) {
483  SCLogDebug("ASN1 Getting CONTENT");
484 
485  /* Inspect content */
486  ret = SCAsn1DecodeContent(ac);
487  if (ret == ASN1_PARSER_ERR) {
488  SCLogDebug("Error parsing content");
489 
490  break;
491  }
492 
493  /* Skip to the next record (if any) */
495  /* Is primitive, skip it all (no need to decode it)*/
496  ac->iter += node->data.len;
497  }
498 
499  /* Check if we are done with data */
500  ret = SCAsn1CheckBounds(ac);
501  if (ret == ASN1_PARSER_ERR) {
502 
504  /* There's no more data available */
505  ret = ASN1_PARSER_OK;
506 
507  break;
508  }
509 #if 0
510  printf("Tag Num: %"PRIu32", Tag Type: %"PRIu8", Class:%"PRIu8", Length: %"PRIu32"\n", node->id.tag_num, node->id.tag_type, node->id.class_tag, node->len.len);
511  printf("Data: \n");
512  PrintRawDataFp(stdout, node->data.ptr, node->len.len);
513  printf(" -- EOD --\n");
514 #endif
515 
516  /* Stack flags/events here, so we have the resume at the ctx flags */
517  ac->ctx_flags |= node->flags;
518 
519  /* Check if it's not a primitive type,
520  * then we need to decode contents */
521  if (node->id.tag_type == ASN1_TAG_TYPE_CONSTRUCTED) {
522  ret = SCAsn1Decode(ac, node_id + 1);
523  } /* Else we have reached a primitive type and stop the recursion,
524  * look if we have other branches at the same level */
525 
526  /* But first check if it's a constructed node, and the sum of child
527  * lengths was more than the length of this frame
528  * this would mean that we have an overflow at the attributes */
529  if (ac->iter > node->data.ptr + node->data.len + 1) {
530  /* We decoded more length on this frame */
531  }
532 
533  node_id = ac->cur_frame + 1;
534  }
535 
536  return ret;
537 }
538 
539 /* ----------------------- Unit tests ------------------------ */
540 #ifdef UNITTESTS
541 
542 /**
543  * \test Check we handle extended identifiers correctly
544  */
545 static int DecodeAsn1Test01(void)
546 {
547  uint8_t *str = (uint8_t *) "\x3F\x84\x06";
548 
549  Asn1Ctx *ac = SCAsn1CtxNew();
550  if (ac == NULL)
551  return 0;
552  uint8_t ret = 1;
553 
554  uint16_t len = 3;
555 
556  SCAsn1CtxInit(ac, str, len);
557 
558  SCAsn1Decode(ac, ac->cur_frame);
559  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
560  if (node->id.tag_num != 10) {
561  ret = 0;
562  printf("Error, expected tag_num 10, got %"PRIu32" :", node->id.tag_num);
563  goto end;
564  }
565 
566 end:
567  SCAsn1CtxDestroy(ac);
568  return ret;
569 }
570 
571 /**
572  * \test Check we handle extended identifiers correctly
573  */
574 static int DecodeAsn1Test02(void)
575 {
576  uint8_t *str = (uint8_t *) "\x3F\x81\x81\x81\x81\x06";
577 
578  Asn1Ctx *ac = SCAsn1CtxNew();
579  if (ac == NULL)
580  return 0;
581  uint8_t ret = 1;
582 
583  uint16_t len = 6;
584 
585  SCAsn1CtxInit(ac, str, len);
586 
587  SCAsn1Decode(ac, ac->cur_frame);
588  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
589  if (node->id.tag_num != 10) {
590  ret = 0;
591  printf("Error, expected tag_num 10, got %"PRIu32": ", node->id.tag_num);
592  goto end;
593  }
594 
595 end:
596  SCAsn1CtxDestroy(ac);
597  return ret;
598 }
599 
600 /**
601  * \test Check we handle short identifiers correctly
602  */
603 static int DecodeAsn1Test03(void)
604 {
605  uint8_t *str = (uint8_t *) "\x28";
606 
607  Asn1Ctx *ac = SCAsn1CtxNew();
608  if (ac == NULL)
609  return 0;
610  uint8_t ret = 1;
611 
612  uint16_t len = 1;
613 
614  SCAsn1CtxInit(ac, str, len);
615 
616  SCAsn1Decode(ac, ac->cur_frame);
617  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
618  if (node->id.tag_num != 8) {
619  ret = 0;
620  printf("Error, expected tag_num 10, got %"PRIu32": ", node->id.tag_num);
621  goto end;
622  }
623 
624 end:
625  SCAsn1CtxDestroy(ac);
626  return ret;
627 }
628 
629 /**
630  * \test Check we handle extended lengths correctly with indefinite form
631  */
632 static int DecodeAsn1Test04(void)
633 {
634  uint8_t *str = (uint8_t *) "\x3F\x84\x06\x80\x12\x12\x12\x00\x00";
635 
636  Asn1Ctx *ac = SCAsn1CtxNew();
637  if (ac == NULL)
638  return 0;
639  uint8_t ret = 1;
640 
641  uint16_t len = 9;
642 
643  SCAsn1CtxInit(ac, str, len);
644 
645  SCAsn1Decode(ac, ac->cur_frame);
646  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
647  if (node->len.len != 3) {
648  ret = 0;
649  printf("Error, expected length 3, got %"PRIu32": ", node->len.len);
650  goto end;
651  }
652 
653 end:
654  SCAsn1CtxDestroy(ac);
655  return ret;
656 }
657 
658 /**
659  * \test Check we handle extended lengths correctly
660  * in the definite form
661  */
662 static int DecodeAsn1Test05(void)
663 {
664  uint8_t *str = (uint8_t *) "\x3F\x84\x06\x82\x10\x10";
665 
666  Asn1Ctx *ac = SCAsn1CtxNew();
667  if (ac == NULL)
668  return 0;
669  uint8_t ret = 1;
670 
671  uint16_t len = 6;
672 
673  SCAsn1CtxInit(ac, str, len);
674 
675  SCAsn1Decode(ac, ac->cur_frame);
676  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
677  if (node->len.len!= 32) {
678  ret = 0;
679  printf("Error, expected length 10, got %"PRIu32": ", node->len.len);
680  goto end;
681  }
682 
683 end:
684  SCAsn1CtxDestroy(ac);
685  return ret;
686 }
687 
688 /**
689  * \test Check we handle short lengths correctly
690  */
691 static int DecodeAsn1Test06(void)
692 {
693  uint8_t *str = (uint8_t *) "\x3F\x84\x06\x26";
694 
695  Asn1Ctx *ac = SCAsn1CtxNew();
696  if (ac == NULL)
697  return 0;
698  uint8_t ret = 1;
699 
700  uint16_t len = 4;
701 
702  SCAsn1CtxInit(ac, str, len);
703 
704  SCAsn1Decode(ac, ac->cur_frame);
705  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
706  if (node->len.len != 38) {
707  ret = 0;
708  printf("Error, expected length 10, got %"PRIu32": ", node->len.len);
709  goto end;
710  }
711 
712 end:
713  SCAsn1CtxDestroy(ac);
714  return ret;
715 }
716 
717 /**
718  * \test Check we handle events correctly
719  */
720 static int DecodeAsn1Test07(void)
721 {
722  uint8_t *str = (uint8_t *) "\x3F\x00\x84\x06";
723 
724  Asn1Ctx *ac = SCAsn1CtxNew();
725  if (ac == NULL)
726  return 0;
727  uint8_t ret = 1;
728 
729  uint16_t len = 4;
730 
731  SCAsn1CtxInit(ac, str, len);
732 
733  SCAsn1Decode(ac, ac->cur_frame);
734  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
736  || !(node->flags & ASN1_BER_EVENT_INVALID_ID))
737  {
738  ret = 0;
739  printf("Error, expected invalid id, got flags %"PRIu8": ", ac->ctx_flags);
740  goto end;
741  }
742 
743 end:
744  SCAsn1CtxDestroy(ac);
745  return ret;
746 }
747 
748 /**
749  * \test Check we handle events correctly
750  */
751 static int DecodeAsn1Test08(void)
752 {
753  uint8_t *str = (uint8_t *) "\x3F\x84\x06\x81\xFF";
754 
755  Asn1Ctx *ac = SCAsn1CtxNew();
756  if (ac == NULL)
757  return 0;
758  uint8_t ret = 1;
759 
760  uint16_t len = 5;
761 
762  SCAsn1CtxInit(ac, str, len);
763 
764  SCAsn1Decode(ac, ac->cur_frame);
765  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
767  || !(node->flags & ASN1_BER_EVENT_INVALID_LEN))
768  {
769  ret = 0;
770  printf("Error, expected invalid length, got flags %"PRIu8": ", ac->ctx_flags);
771  goto end;
772  }
773 
774 end:
775  SCAsn1CtxDestroy(ac);
776  return ret;
777 }
778 
779 /**
780  * \test Check we handle events correctly
781  */
782 static int DecodeAsn1Test09(void)
783 {
784  uint8_t *str = (uint8_t *) "\x3F\x84\x06\x80\xAB\xCD\xEF";
785 
786  Asn1Ctx *ac = SCAsn1CtxNew();
787  if (ac == NULL)
788  return 0;
789  uint8_t ret = 1;
790 
791  uint16_t len = 7;
792 
793  SCAsn1CtxInit(ac, str, len);
794 
795  SCAsn1Decode(ac, ac->cur_frame);
796  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
798  || !(node->flags & ASN1_BER_EVENT_EOC_NOT_FOUND))
799  {
800  ret = 0;
801  printf("Error, expected eoc not found, got flags %"PRIu8": ", ac->ctx_flags);
802  goto end;
803  }
804 
805 end:
806  SCAsn1CtxDestroy(ac);
807  return ret;
808 }
809 
810 /**
811  * \test Decode a big chunk of data
812  */
813 static int DecodeAsn1Test10(void)
814 {
815  // Example from the specification X.690-0207 Appendix A.3
816  uint8_t *str = (uint8_t *) "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01"
817  "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
818  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
819  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
820  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
821  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111"
822  "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05"
823  "Jones""\xA0\x0A\x43\x08""19590717"
824  "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P"
825  "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director"
826  "\x42\x01\x33\xA1\x0A\x43\x08""19710917"
827  "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05"
828  "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01"
829  "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F"
830  "\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05""Jones"
831  "\xA0\x0A\x43\x08""19590717";
832 
833  Asn1Ctx *ac = SCAsn1CtxNew();
834  if (ac == NULL)
835  return 0;
836  uint8_t ret = 1;
837 
838  uint16_t len = strlen((char *)str)-1;
839 
840  SCAsn1CtxInit(ac, str, len);
841 
842  ret = SCAsn1Decode(ac, ac->cur_frame);
843 
844  /* General checks */
845  if (ret != ASN1_PARSER_OK) {
846  printf("Error decoding asn1 data: ");
847  ret = 0;
848  goto end;
849  }
850 
851  if (ac->cur_frame != 59) {
852  printf("Error decoding asn1 data, not all the nodes"
853  "were correctly decoded: ");
854  ret = 0;
855  goto end;
856  }
857 
858  if (ac->iter != ac->end) {
859  printf("Error decoding asn1 data, not all the nodes"
860  "were correctly decoded: ");
861  ret = 0;
862  goto end;
863  }
864 
865  Asn1Node *node = ASN1CTX_GET_NODE(ac, 0);
866  if (node->len.len != 133) {
867  printf("Error decoding asn1 data, not all the nodes"
868  "were correctly decoded: ");
869  ret = 0;
870  goto end;
871  }
872 
873  node = ASN1CTX_GET_NODE(ac, 30);
874  if (node->len.len != 133) {
875  printf("Error decoding asn1 data, not all the nodes"
876  "were correctly decoded: ");
877  ret = 0;
878  goto end;
879  }
880 
881 end:
882  SCAsn1CtxDestroy(ac);
883  return ret;
884 }
885 
886 #endif
887 
889 {
890 #ifdef UNITTESTS
891  UtRegisterTest("DecodeAsn1Test01", DecodeAsn1Test01);
892  UtRegisterTest("DecodeAsn1Test02", DecodeAsn1Test02);
893  UtRegisterTest("DecodeAsn1Test03", DecodeAsn1Test03);
894 
895  UtRegisterTest("DecodeAsn1Test04", DecodeAsn1Test04);
896  UtRegisterTest("DecodeAsn1Test05", DecodeAsn1Test05);
897  UtRegisterTest("DecodeAsn1Test06", DecodeAsn1Test06);
898 
899  UtRegisterTest("DecodeAsn1Test07", DecodeAsn1Test07);
900  UtRegisterTest("DecodeAsn1Test08", DecodeAsn1Test08);
901  UtRegisterTest("DecodeAsn1Test09", DecodeAsn1Test09);
902 
903  UtRegisterTest("DecodeAsn1Test10", DecodeAsn1Test10);
904 #endif
905 }
906 
#define SCLogDebug(...)
Definition: util-debug.h:335
Asn1Data data
#define ASN1_BER_LEN_LONG
uint8_t SCAsn1Decode(Asn1Ctx *ac, uint16_t node_id)
Decode the nodes/frames located at certain position/level.
#define ASN1_BER_IS_SHORT_LEN(id_octet)
#define unlikely(expr)
Definition: util-optimize.h:35
#define ASN1_PARSER_ERR
uint16_t len
uint32_t tag_num
#define ASN1_BER_EVENT_LEN_TOO_LONG
uint32_t len
#define ASN1_PARSER_OK
#define ASN1_BER_IS_CONSTRUCTED(id_octet)
#define ASN1_STATUS_OOB
#define ASN1_BER_EVENT_ID_TOO_LONG
#define ASN1_BER_GET_LONG_LEN_OCTETS(id_octet)
uint8_t parser_status
uint8_t form
#define ASN1_BER_GET_HIGH_TAG_NUM(id_octet)
#define ASN1CTX_GET_NODE(ac, node)
#define str(s)
#define ASN1_BER_IS_HIGH_TAG_END(id_octet)
uint8_t * data
uint8_t SCAsn1DecodeIdentifier(Asn1Ctx *ac)
Decode and check the identifier information of the current node that we are parsing, also check invalid opts.
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
uint8_t class_tag
#define ASN1_BER_LEN_INDEFINITE
#define ASN1_STATUS_OK
uint8_t SCAsn1CheckBounds(Asn1Ctx *ac)
check if we have remaining data available, otherwise the parser should stop
#define ASN1_NODE_IS_EOC
Asn1Node ** asn1_stack
uint8_t * ptr
#define ASN1_BER_LEN_SHORT
#define ASN1_BER_GET_CLASS_TAG(id_octet)
#define ASN1_BER_EVENT_EOC_NOT_FOUND
uint16_t asn1_max_frames_config
uint8_t * ptr
uint8_t * ptr
#define SCMalloc(a)
Definition: util-mem.h:174
#define ASN1_BER_EVENT_INVALID_LEN
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:141
#define ASN1_BER_EVENT_INVALID_ID
#define SCFree(a)
Definition: util-mem.h:236
uint8_t ctx_flags
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:437
void SCAsn1CtxDestroy(Asn1Ctx *ac)
Destroy an ASN1 Parsing context.
#define ASN1CTX_CUR_NODE(ac)
#define ASN1_STATUS_DONE
uint16_t cur_frame
void DecodeAsn1RegisterTests(void)
Asn1Ctx * SCAsn1CtxNew(void)
Create a new ASN1 Parsing context.
void SCAsn1LoadConfig()
#define ASN1_MAX_FRAMES
#define ASN1_TAG_TYPE_CONSTRUCTED
uint16_t length
#define ASN1_STATUS_INVALID
uint32_t len
uint8_t tag_type
#define ASN1_BER_GET_SHORT_LEN(id_octet)
uint8_t len
uint8_t SCAsn1DecodeLength(Asn1Ctx *ac)
Decode and check the length, of the current node that we are parsing, also check invalid opts...
uint8_t SCAsn1DecodeContent(Asn1Ctx *ac)
Check the content length and perform other inspections and decodings if necessary.
#define ASN1_BER_IS_EOC(tmp_iter)
void SCAsn1CtxInit(Asn1Ctx *ac, uint8_t *data, uint16_t length)
Initialize the data of the ASN1 parser ctx with the asn1 raw buffer.
uint8_t * iter
#define ASN1_BER_IS_HIGH_TAG(id_octet)
#define ASN1_BER_IS_INDEFINITE_LEN(id_octet)
uint8_t * end
void SCPrintByteBin(uint8_t byte)
Helper function that print the bits of a byte to check encoding internals.
#define ASN1_BER_GET_LOW_TAG_NUM(id_octet)