/** * \brief Decode and check the identifier information of the * current node that we are parsing, also check invalid opts * * \param ac pointer to the ASN1 Context data * * \retval byte of the status of the parser */ uint8_t SCAsn1DecodeIdentifier(Asn1Ctx *ac) { uint8_t ret = 0; ret = SCAsn1CheckBounds(ac); if (ret == ASN1_PARSER_ERR) { ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; return ret; } Asn1Node *node = ASN1CTX_CUR_NODE(ac); /* Store the position */ node->id.ptr = ac->iter; //SCPrintByteBin(*ac->iter); node->id.class_tag = ASN1_BER_GET_CLASS_TAG(*ac->iter); node->id.tag_type = ASN1_BER_IS_CONSTRUCTED(*ac->iter); if (ASN1_BER_IS_HIGH_TAG(*ac->iter)) { return SCAsn1GetHighTagNumber(ac); } else { node->id.tag_num = ASN1_BER_GET_LOW_TAG_NUM(*ac->iter); ac->iter++; } return ASN1_PARSER_OK; }
/** * \brief Decode and check the length, of the current node * that we are parsing, also check invalid opts * * \param ac pointer to the ASN1 Context data * * \retval byte of the status of the parser */ uint8_t SCAsn1DecodeLength(Asn1Ctx *ac) { uint8_t ret = 0; ret = SCAsn1CheckBounds(ac); if (ret == ASN1_PARSER_ERR) { ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; return ASN1_PARSER_ERR; } Asn1Node *node = ASN1CTX_CUR_NODE(ac); /* Store the position */ node->len.ptr = ac->iter; uint8_t len_byte = *ac->iter; //SCPrintByteBin(len_byte); if (*node->id.ptr == 0 && len_byte == 0) { node->flags |= ASN1_NODE_IS_EOC; ac->iter++; return ASN1_PARSER_OK; } if (ASN1_BER_IS_INDEFINITE_LEN(len_byte)) { node->len.form = ASN1_BER_LEN_INDEFINITE; node->len.len = 0; ac->iter++; uint8_t *tmp_iter = ac->iter; /* Check that e-o-c is in bounds */ for (; tmp_iter < ac->end - 1; tmp_iter++) { if (ASN1_BER_IS_EOC(tmp_iter)) { node->data.len = tmp_iter - ac->iter; node->len.len = tmp_iter - ac->iter; return ASN1_PARSER_OK; } } /* EOC Not found */ ac->parser_status |= ASN1_STATUS_INVALID; node->flags |= ASN1_BER_EVENT_EOC_NOT_FOUND; return ASN1_PARSER_ERR; } else { /* Look which form we get (and if it apply to the id type) */ if (ASN1_BER_IS_SHORT_LEN(len_byte)) { node->len.form = ASN1_BER_LEN_SHORT; node->len.len = ASN1_BER_GET_SHORT_LEN(len_byte); ac->iter++; } else { node->len.form = ASN1_BER_LEN_LONG; /* Ok, let's parse the long form */ return SCAsn1GetLengthLongForm(ac); } } return ASN1_PARSER_OK; }
/** * \brief Check the content length and perform other inspections * and decodings if necessary * * \param ac pointer to the ASN1 Context data * * \retval byte of the status of the parser */ uint8_t SCAsn1DecodeContent(Asn1Ctx *ac) { Asn1Node *node = ASN1CTX_CUR_NODE(ac); /* Uops, if we are done, we break here */ if (node->flags & ASN1_NODE_IS_EOC) return ASN1_PARSER_OK; /* First check the form of length (BER, DER, CER) * and if we are on a zero length */ if (node->len.form != ASN1_BER_LEN_INDEFINITE && node->len.len == 0) { node->data.len = 0; return ASN1_PARSER_OK; } node->data.ptr = ac->iter; /* If we have a complete length, check that * it is in bounds */ if (ac->iter + node->len.len > ac->end) { /* We do not have all the content octets! */ node->data.len = ac->end - ac->iter; } else { /* We have all the content octets */ node->data.len = node->len.len; } return ASN1_PARSER_OK; }
/** * \brief Decode and check the identifier information of the * current node that is in extended format * * \param ac pointer to the ASN1 Context data * * \retval byte of the status of the parser */ uint8_t SCAsn1GetHighTagNumber(Asn1Ctx *ac) { uint8_t ret = 0; uint32_t tag_num = 0; /* If we have a high tag num, skip the id octet */ ac->iter++; Asn1Node *node = ASN1CTX_CUR_NODE(ac); ret = SCAsn1CheckBounds(ac); if (ret == ASN1_PARSER_ERR) { ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; return ret; } uint8_t raw_id = *ac->iter; tag_num += ASN1_BER_GET_HIGH_TAG_NUM(raw_id); if (ASN1_BER_GET_HIGH_TAG_NUM(raw_id) == 0) { /* Set event, invalid id */ node->flags |= ASN1_BER_EVENT_INVALID_ID; ac->parser_status |= ASN1_STATUS_INVALID; return ASN1_PARSER_ERR; } ac->iter++; if (!ASN1_BER_IS_HIGH_TAG_END(raw_id)) { do { ret = SCAsn1CheckBounds(ac); if (ret == ASN1_PARSER_ERR) { ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; return ret; } raw_id = *ac->iter; if ((uint64_t) ((uint64_t)tag_num + (uint64_t)ASN1_BER_GET_HIGH_TAG_NUM(raw_id)) > UINT32_MAX) { node->flags |= ASN1_BER_EVENT_ID_TOO_LONG; ac->parser_status |= ASN1_STATUS_INVALID; return ASN1_PARSER_ERR; } tag_num += ASN1_BER_GET_HIGH_TAG_NUM(raw_id); ac->iter++; } while (!ASN1_BER_IS_HIGH_TAG_END(raw_id)); } node->id.tag_num = tag_num; return ASN1_PARSER_OK; }
/** * \brief Decode and check the length, of the current node * in definite but extended format, that we are parsing, * checking invalid opts * * \param ac pointer to the ASN1 Context data * * \retval byte of the status of the parser */ uint32_t SCAsn1GetLengthLongForm(Asn1Ctx *ac) { uint8_t raw_len = *ac->iter; uint8_t ret = 0; uint32_t content_len = 0; uint8_t oct_len = ASN1_BER_GET_LONG_LEN_OCTETS(raw_len); uint8_t i = 0; Asn1Node *node = ASN1CTX_CUR_NODE(ac); for (; i < oct_len; i++) { ac->iter++; ret = SCAsn1CheckBounds(ac); if (ret == ASN1_PARSER_ERR) { ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; return ASN1_PARSER_ERR; } raw_len = *ac->iter; if (raw_len == 0xFF && ac->iter == node->len.ptr + 1) { /* 8.1.3.5, 0xFF shall not be used */ node->flags |= ASN1_BER_EVENT_INVALID_LEN; ac->parser_status = ASN1_STATUS_INVALID; return ASN1_PARSER_ERR; } if ((uint64_t) ((uint64_t)content_len + (uint64_t) ASN1_BER_GET_HIGH_TAG_NUM(raw_len)) > UINT32_MAX) { node->flags |= ASN1_BER_EVENT_LEN_TOO_LONG; ac->parser_status = ASN1_STATUS_INVALID; return ASN1_PARSER_ERR; } content_len += raw_len; } ac->iter++; node->len.len = content_len; return ASN1_PARSER_OK; }