📄 asn1.c
字号:
*/ (*asn1_type)->data_len = 0; if(asn1_is_eoc(*asn1_type)) (*asn1_type)->eoc = 1; } goto valid; } return ASN1_ERR_INVALID_INDEF_LEN; } /* ** Set data ptr for asn1 types that have data. */ (*asn1_type)->data = asn1data.data; /* ** Check for the ASN.1 type being larger than we have room for. */ if(uiRawLen < (*asn1_type)->len.size) { (*asn1_type)->data_len = uiRawLen; /* ** If we're a construct, then don't skip over the data because ** we have to process it. */ if((*asn1_type)->ident.flag == SF_ASN1_FLAG_CONSTRUCT) goto valid; return ASN1_ERR_OOB; } /* ** We got enough data in the buffer for the true identifier size, so ** we set it. */ (*asn1_type)->data_len = (*asn1_type)->len.size; /* ** Only jump data that's not going to be decoded. That means jump ** over primitive data and decode construct data. */ if(!((*asn1_type)->ident.flag == SF_ASN1_FLAG_CONSTRUCT)) { asn1data.data += (*asn1_type)->len.size; }valid: /* ** Update data buffer, before we return. Depending on if we just decoded ** a zero length identifier and are on the last data byte, we could be at ** the end of our buffer. Otherwise, we're still in the buffer. */ *len = asn1data.end - asn1data.data; *data = asn1data.data; return ASN1_OK;}/*** NAME** asn1_decode::*//**** This function decodes an ASN.1 string and returns the decoded** structures. We BER encoding, which means we handle both** definite and indefinite length encodings (that was a B).**** @return integer**** @retval ASN1_OK function successful** @retval !ASN1_OK lots of error conditions, figure it out*/int asn1_decode(u_char *data, u_int len, ASN1_TYPE **asn1_type){ ASN1_TYPE *cur; ASN1_TYPE *child = NULL; ASN1_TYPE *indef; ASN1_TYPE *asnstack[ASN1_MAX_STACK]; u_char *end; u_int con_len; int index = 0; int iRet; if(!data || !len) return ASN1_ERR_NULL_MEM; asn1_init_node_index(); /* ** Keep track of where the end of the data buffer is so we can continue ** processing if there is a construct. */ end = data + len; iRet = asn1_decode_type(&data,&len,asn1_type); if(iRet || !(*asn1_type)) { //printf("** initial bad decode\n"); return iRet; } cur = *asn1_type; while(cur) { /* ** This is where we decode the ASN.1 constructs. We do while() ** because we may have back to back constructs. We bail on the ** first indentifier that isn't a construct. */ while(cur && cur->ident.flag == SF_ASN1_FLAG_CONSTRUCT) { if(index < ASN1_MAX_STACK) asnstack[index++] = cur; else return ASN1_ERR_STACK; /* ** We now set the current len for this constructs true length, ** or raw length if true length is past buffer. */ if(cur->len.type != SF_BER_LEN_INDEF) { if(len < cur->data_len) return ASN1_ERR_OVERLONG_LEN; len = cur->data_len; } iRet = asn1_decode_type(&data, &len, &cur->cnext); if(iRet) { return iRet; } /* ** Check next child for ending of indefinite encodings. */ if(cur->cnext && cur->cnext->eoc) { if(index && (indef = asnstack[--index])) { if(indef->len.type == SF_BER_LEN_INDEF) { indef->len.size = data - indef->data - 2; indef->data_len = indef->len.size; cur->cnext = NULL; cur = indef; break; } else { /* ** Not an EOC type, so it's just a strange child ** encoding. Put the construct back on the stack. */ asnstack[index++] = indef; } } } cur = cur->cnext; } /* ** If there is a node, then process any peers that this node has. */ if(cur) { iRet = asn1_decode_type(&data, &len, &cur->next); if(iRet) return iRet; /* ** Cycle through any eoc that might be back to back */ while(cur->next && cur->next->eoc) { if(index && (indef = asnstack[--index])) { if(indef->len.type == SF_BER_LEN_INDEF) { indef->len.size = data - indef->data - 2; indef->data_len = indef->len.size; cur->next = NULL; cur = indef; iRet = asn1_decode_type(&data, &len, &cur->next); if(iRet) { return iRet; } continue; } asnstack[index++] = indef; } break; } cur = cur->next; if(cur) continue; } /* ** We only get here if the peer decode fails. ** ** Traverse the stack and close off any constructs that we ** are done with. This gets a little trickier, because we have to ** check for additional peers for each construct, depending on the ** length of the parent construct. */ while(index && (cur = asnstack[--index])) { /* ** Get the construct length and set the length appropriately ** if there is more data in this construct. */ con_len = data - cur->data; if(cur->data_len > con_len) { len = cur->data_len - con_len; } /* ** If this construct has no more data left, then save it off as ** the last child of the previous construct. */ if(len == 0) { child = cur; } else if(child) { /* ** Means this construct has more data left, so if the child is set ** then we set it's next ptr. Otherwise, this means we are in ** an indeterminate construct, and need to check for eoc before we ** continue processing. */ asnstack[index++] = cur; cur = child; child = NULL; } iRet = asn1_decode_type(&data, &len, &cur->next); if(iRet) { return iRet; } if(cur->next && cur->next->eoc) { if(index && (indef = asnstack[--index])) { if(indef->len.type == SF_BER_LEN_INDEF) { indef->len.size = data - indef->data - 2; indef->data_len = indef->len.size; cur->next = NULL; cur = indef; } else { asnstack[index++] = indef; } } } /* ** This logic tell us that we are on the root construct, but there ** are additional peers because there is more data. We recalculate ** the length and continue on. ** ** NOTE: ** We may not want this because research may only be able to point ** us at the first sequence and it's anyone's guess after that. */ if(!index && !(cur->next) && (data < end)) { len = (end - data); iRet = asn1_decode_type(&data, &len, &cur->next); if(iRet) return iRet; } cur = cur->next; if(cur) break; } /* ** The loop logic bails us out if there is no cur. */ } return ASN1_OK;}/*** NAME** asn1_traverse::*//**** This function traverses a decoded ASN1 structure, applying a detection** function for the different types. This is just to make this user stack** generic AND easy.**** @return integer**** @retval 1 detection function successful** @retval 0 detection function unsuccessful*/int asn1_traverse(ASN1_TYPE *asn1, void *user, int (*DetectFunc)(ASN1_TYPE *, void *)){ ASN1_TYPE *asnstack[ASN1_MAX_STACK]; int index = 0; ASN1_TYPE *cur; int iRet; if(!asn1) return 0; cur = asn1; while(cur) { while(cur && cur->ident.flag == SF_ASN1_FLAG_CONSTRUCT) { if(index < ASN1_MAX_STACK) asnstack[index++] = cur; else return 0; iRet = DetectFunc(cur, user); if(iRet) return 1; cur = cur->cnext; } if(cur) { iRet = DetectFunc(cur, user); if(iRet) return 1; cur = cur->next; if(cur) continue; } while(index && (cur = asnstack[--index])) { cur = cur->next; if(cur) break; } } return 0;}/*** NAME** asn1_print_types::*//**** Print out the ASN.1 type.**** @return integer**** @retval 0 printed*/int asn1_print_types(ASN1_TYPE *asn1_type, void *user){ unsigned int iTabs = 0; unsigned int iCtr; if(user) iTabs = *((int *)user); for(iCtr = 0; iCtr < iTabs; iCtr++) printf(" "); printf("## PRINT ASN1_TYPE STRUCTURE ##\n"); for(iCtr = 0; iCtr < iTabs; iCtr++) printf(" "); printf("IDENT - class: %.2x | flag: %.2x | tag_type: %.2x | " "tag_num: %d\n", asn1_type->ident.class, asn1_type->ident.flag, asn1_type->ident.tag_type, asn1_type->ident.tag); for(iCtr = 0; iCtr < iTabs; iCtr++) printf(" "); printf("LEN - type: %d | size: %u\n", asn1_type->len.type, asn1_type->len.size); for(iCtr = 0; iCtr < iTabs; iCtr++) printf(" "); printf("DATA | data_len: %d | ", asn1_type->data_len); if(asn1_type->data) { for(iCtr = 0; iCtr < asn1_type->data_len; iCtr++) printf(" %.2x", asn1_type->data[iCtr]); } else { printf(" NULL"); } printf("\n\n"); /* printf("\n"); //if(BitStringOverflow(asn1_type)) //{ // printf("!! BITSTRING OVERFLOW\n"); //} printf("\n"); if(asn1_type->cnext) asn1_print_types(asn1_type->cnext, iTabs+1); if(asn1_type->next) asn1_print_types(asn1_type->next, iTabs); */ return 0;}#ifdef I_WANT_MAIN_DAMMITstatic int BitStringOverflow(ASN1_TYPE *asn1_type){ if(!asn1_type) return 0; if(asn1_type->ident.tag == SF_ASN1_TAG_BIT_STR && !asn1_type->ident.flag) { if(((asn1_type->len.size - 1)*8) < (u_int)asn1_type->data[0]) { return 1; } } return 0;}/*** Program reads from stdin and decodes the hexadecimal ASN.1 stream** into identifier,len,data.*/int main(int argc, char **argv){ ASN1_TYPE *asn1_type; char line[10000]; u_int ctmp; char *buf; int buf_size; int iCtr; int iRet; fgets(line, sizeof(line), stdin); buf_size = strlen(line); while(buf_size && line[buf_size-1] <= 0x20) { buf_size--; line[buf_size] = 0x00; } if(!buf_size) { printf("** No valid characters in data string.\n"); return 1; } if(buf_size % 2) { printf("** Data must be represent in hex, meaning that there is an " "odd number of characters in the data string.\n"); return 1; } buf_size >>= 1; buf = (char *)malloc(buf_size + 1); if(!buf) { printf("** Bad malloc\n"); return 1; } for(iCtr = 0; iCtr < buf_size; iCtr++) { if(!(isxdigit(line[iCtr*2]) && isxdigit(line[(iCtr*2)+1]))) { printf("** Data stream is not all hex digits.\n"); return 1; } sscanf(&line[iCtr*2], "%2x", &ctmp); buf[iCtr] = (char)ctmp; } buf[iCtr] = 0x00; if(asn1_init_mem(256)) { printf("** asn1_init_mem() failed\n"); return 1; } iRet = asn1_decode(buf, buf_size, &asn1_type); if(iRet && !asn1_type) { printf("** FAILED\n"); return 1; } printf("** iRet = %d\n", iRet); asn1_print_types(asn1_type, 0); free(buf); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -