/** * \test Check we handle events correctly */ int DecodeAsn1Test09(void) { uint8_t *str = (uint8_t *) "\x3F\x84\x06\x80\xAB\xCD\xEF"; Asn1Ctx *ac = SCAsn1CtxNew(); if (ac == NULL) return 0; uint8_t ret = 1; uint16_t len = 7; SCAsn1CtxInit(ac, str, len); SCAsn1Decode(ac, ac->cur_frame); Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); if ( !(ac->ctx_flags & ASN1_BER_EVENT_EOC_NOT_FOUND) || !(node->flags & ASN1_BER_EVENT_EOC_NOT_FOUND)) { ret = 0; printf("Error, expected eoc not found, got flags %"PRIu8": ", ac->ctx_flags); goto end; } end: SCAsn1CtxDestroy(ac); return ret; }
/** * \test Check we handle events correctly */ int DecodeAsn1Test08(void) { uint8_t *str = (uint8_t *) "\x3F\x84\x06\x81\xFF"; Asn1Ctx *ac = SCAsn1CtxNew(); if (ac == NULL) return 0; uint8_t ret = 1; uint16_t len = 5; SCAsn1CtxInit(ac, str, len); SCAsn1Decode(ac, ac->cur_frame); Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); if ( !(ac->ctx_flags & ASN1_BER_EVENT_INVALID_LEN) || !(node->flags & ASN1_BER_EVENT_INVALID_LEN)) { ret = 0; printf("Error, expected invalid length, got flags %"PRIu8": ", ac->ctx_flags); goto end; } end: SCAsn1CtxDestroy(ac); return ret; }
/** * \test Check we handle short lengths correctly */ int DecodeAsn1Test06(void) { uint8_t *str = (uint8_t *) "\x3F\x84\x06\x26"; Asn1Ctx *ac = SCAsn1CtxNew(); if (ac == NULL) return 0; uint8_t ret = 1; uint16_t len = 4; SCAsn1CtxInit(ac, str, len); SCAsn1Decode(ac, ac->cur_frame); Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); if (node->len.len != 38) { ret = 0; printf("Error, expected length 10, got %"PRIu32": ", node->len.len); goto end; } end: SCAsn1CtxDestroy(ac); return ret; }
/** * \test Check we handle short identifiers correctly */ int DecodeAsn1Test03(void) { uint8_t *str = (uint8_t *) "\x28"; Asn1Ctx *ac = SCAsn1CtxNew(); if (ac == NULL) return 0; uint8_t ret = 1; uint16_t len = 1; SCAsn1CtxInit(ac, str, len); SCAsn1Decode(ac, ac->cur_frame); Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); if (node->id.tag_num != 8) { ret = 0; printf("Error, expected tag_num 10, got %"PRIu32": ", node->id.tag_num); goto end; } end: SCAsn1CtxDestroy(ac); return ret; }
/** * \brief Destroy an ASN1 Parsing context * * \param Asn1Ctx pointer to the new ctx */ void SCAsn1CtxDestroy(Asn1Ctx *ac) { if (ac == NULL) return; uint16_t i = 0; for (; i < ac->cur_frame; i++) { Asn1Node *node = ASN1CTX_GET_NODE(ac, i); if (node != NULL) { SCFree(node); } } SCFree(ac); }
/** * \test Decode a big chunk of data */ int DecodeAsn1Test10(void) { // Example from the specification X.690-0207 Appendix A.3 uint8_t *str = (uint8_t *) "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01" "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director" "\x42\x01\x33\xA1\x0A\x43\x08""19710917" "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05" "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01" "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111" "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05" "Jones""\xA0\x0A\x43\x08""19590717" "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P" "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director" "\x42\x01\x33\xA1\x0A\x43\x08""19710917" "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05" "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01" "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F" "\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05""Jones" "\xA0\x0A\x43\x08""19590717"; Asn1Ctx *ac = SCAsn1CtxNew(); if (ac == NULL) return 0; uint8_t ret = 1; uint16_t len = strlen((char *)str)-1; SCAsn1CtxInit(ac, str, len); ret = SCAsn1Decode(ac, ac->cur_frame); /* General checks */ if (ret != ASN1_PARSER_OK) { printf("Error decoding asn1 data: "); ret = 0; goto end; } if (ac->cur_frame != 59) { printf("Error decoding asn1 data, not all the nodes" "were correctly decoded: "); ret = 0; goto end; } if (ac->iter != ac->end) { printf("Error decoding asn1 data, not all the nodes" "were correctly decoded: "); ret = 0; goto end; } Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); if (node->len.len != 133) { printf("Error decoding asn1 data, not all the nodes" "were correctly decoded: "); ret = 0; goto end; } node = ASN1CTX_GET_NODE(ac, 30); if (node->len.len != 133) { printf("Error decoding asn1 data, not all the nodes" "were correctly decoded: "); ret = 0; goto end; } end: SCAsn1CtxDestroy(ac); return ret; }
/** * \brief Decode the nodes/frames located at certain position/level * * \param ac pointer to the ASN1 ctx * \param node_id node index at the asn1 stack of the ctx * * \retval byte of parser status */ uint8_t SCAsn1Decode(Asn1Ctx *ac, uint16_t node_id) { Asn1Node *node = NULL; uint8_t ret = 0; /* while remaining data, and no fatal error, or end, or max stack frames */ while (ac->iter < ac->end && !(ac->parser_status & ASN1_STATUS_DONE) && ac->cur_frame < asn1_max_frames_config) { /* Prepare a new frame */ if (SCAsn1CtxNewFrame(ac, node_id) == NULL) break; ac->cur_frame = node_id; node = ASN1CTX_GET_NODE(ac, node_id); SCLogDebug("ASN1 Getting ID, cur:%x remaining %"PRIu32, (uint8_t)*ac->iter, (uint32_t)(ac->end - ac->iter)); /* Get identifier/tag */ ret = SCAsn1DecodeIdentifier(ac); if (ret == ASN1_PARSER_ERR) { SCLogDebug("Error parsing identifier"); node->flags |= ASN1_BER_EVENT_INVALID_ID; ac->ctx_flags |= node->flags; break; } SCLogDebug("ASN1 Getting LEN"); /* Get length of content */ ret = SCAsn1DecodeLength(ac); if (ret == ASN1_PARSER_ERR) { SCLogDebug("Error parsing length"); node->flags |= ASN1_BER_EVENT_INVALID_LEN; ac->ctx_flags |= node->flags; break; } if ( !(node->flags & ASN1_NODE_IS_EOC)) { SCLogDebug("ASN1 Getting CONTENT"); /* Inspect content */ ret = SCAsn1DecodeContent(ac); if (ret == ASN1_PARSER_ERR) { SCLogDebug("Error parsing content"); break; } /* Skip to the next record (if any) */ if (node->id.tag_type != ASN1_TAG_TYPE_CONSTRUCTED) /* Is primitive, skip it all (no need to decode it)*/ ac->iter += node->data.len; } /* Check if we are done with data */ ret = SCAsn1CheckBounds(ac); if (ret == ASN1_PARSER_ERR) { ac->parser_status |= ASN1_STATUS_DONE; /* There's no more data available */ ret = ASN1_PARSER_OK; break; } #if 0 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); printf("Data: \n"); PrintRawDataFp(stdout, node->data.ptr, node->len.len); printf(" -- EOD --\n"); #endif /* Stack flags/events here, so we have the resume at the ctx flags */ ac->ctx_flags |= node->flags; /* Check if it's not a primitive type, * then we need to decode contents */ if (node->id.tag_type == ASN1_TAG_TYPE_CONSTRUCTED) { ret = SCAsn1Decode(ac, node_id + 1); } /* Else we have reached a primitive type and stop the recursion, * look if we have other branches at the same level */ /* But first check if it's a constructed node, and the sum of child * lengths was more than the length of this frame * this would mean that we have an overflow at the attributes */ if (ac->iter > node->data.ptr + node->data.len + 1) { /* We decoded more length on this frame */ } node_id = ac->cur_frame + 1; } return ret; }