📄 asn1_erl_driver.c
字号:
} return form;}/* * decode_value decodes the BER encoded length and value fields in the * in_buf and puts the value part in the decode_buf as an Erlang term * encoded by the Erlang extern format */int decode_value(int *ei_index,unsigned char *in_buf, int *ib_index,ErlDrvBinary **drv_binary,int form, int in_buf_len){ int maybe_ret; char *decode_buf = (*drv_binary)->orig_bytes; int len, lenoflen; int indef = 0; #ifdef ASN1_DEBUG printf("decode_value1:ib_index=%d\n\r",*ib_index);#endif if (((in_buf[*ib_index]) & 0x80) == ASN1_SHORT_DEFINITE_LENGTH) { len = in_buf[*ib_index]; if (len > (in_buf_len - (*ib_index + 1))) return ASN1_LEN_ERROR; } else if (in_buf[*ib_index] == ASN1_INDEFINITE_LENGTH) indef = 1; else /* long definite length */ { lenoflen = (in_buf[*ib_index] & 0x7f); /*length of length */#ifdef ASN1_DEBUG printf("decode_value,lenoflen:%d\r\n",lenoflen);#endif len = 0; while (lenoflen-- && (*ib_index <= in_buf_len)) { (*ib_index)++;#ifdef ASN1_DEBUG printf("decode_value1:ii=%d.\r\n",*ib_index);#endif len = (len << 8) + in_buf[*ib_index]; } if (len > (in_buf_len - (*ib_index + 1))) return ASN1_LEN_ERROR; } (*ib_index)++;#ifdef ASN1_DEBUG printf("decode_value2:ii=%d.\r\n",*ib_index);#endif if (indef == 1) { /* in this case it is desireably to check that indefinite length end bytes exist in inbuffer */ while (!(in_buf[*ib_index]==0 && in_buf[*ib_index + 1]==0)) {#ifdef ASN1_DEBUG printf("decode_value while:ib_index=%d in_buf_len=%d\n\r", *ib_index,in_buf_len);#endif if(*ib_index >= in_buf_len) return ASN1_INDEF_LEN_ERROR; ei_encode_list_header(decode_buf,ei_index,1); /* 5 bytes */ if((maybe_ret=decode(drv_binary,ei_index,in_buf, ib_index,in_buf_len)) <= ASN1_ERROR) return maybe_ret; decode_buf = (*drv_binary)->orig_bytes; } (*ib_index) += 2; /* skip the indefinite length end bytes */#ifdef ASN1_DEBUG printf("decode_value3:ii=%d.\r\n",*ib_index);#endif ei_encode_empty_list(decode_buf,ei_index); /* 1 byte */ } else if (form == ASN1_CONSTRUCTED) { int end_index = *ib_index + len; if(end_index > in_buf_len) return ASN1_LEN_ERROR; while (*ib_index < end_index) {#ifdef ASN1_DEBUG printf("decode_value3:*ib_index=%d, end_index=%d\n\r",*ib_index,end_index);#endif ei_encode_list_header(decode_buf,ei_index,1); /* 5 bytes */ if((maybe_ret=decode(drv_binary,ei_index,in_buf, ib_index,in_buf_len))<=ASN1_ERROR) return maybe_ret; decode_buf = (*drv_binary)->orig_bytes; } ei_encode_empty_list(decode_buf,ei_index); /* 1 byte */ } else { if (((*drv_binary)->orig_size - *ei_index) < 10+len) { /* 5+len for the binary*/ if (realloc_decode_buf(drv_binary,(*drv_binary)->orig_size * 2) == ASN1_ERROR) return ASN1_ERROR; decode_buf = (*drv_binary)->orig_bytes; } if((*ib_index + len) > in_buf_len) return ASN1_LEN_ERROR; ei_encode_binary(decode_buf,ei_index,&in_buf[*ib_index],len); *ib_index = *ib_index + len;#ifdef ASN1_DEBUG printf("decode_value4:ii=%d.\r\n",*ib_index);#endif } return ASN1_OK;}int realloc_decode_buf(ErlDrvBinary **drv_binary,int amount) { ErlDrvBinary *tmp_bin; if ((tmp_bin=driver_realloc_binary(*drv_binary,amount)) == NULL) return ASN1_ERROR; *drv_binary = tmp_bin; return ASN1_OK;}/* * int decode_partial(drv_binary,in_buf,in_buf_len) *//* * The in_buf contains two parts: first information about which value * will be decoded, as a sequence of tags and tag codes, then the * encoded BER value. First of all comes a length field that tells how * many following bytes contains the sequence of tags. Then starts the * BER encoded message. The tag sequence length field is a single * byte. The sequence of tags/tag codes may be one of the codes * ASN1_SKIPPED, ASN1_CHOOSEN and a tag or ASN1_OPTIONAL and a * tag. ASN1_SKIPPED means that the following tag is mandatory and is * skipped. ASN1_CHOOSEN means that the value of this tag shall, if * this was the last tag in tag sequence, be returned or be searched * in for the next tag. ASN1_OPTIONAL means that this tag shall be * skipped but it may be missing. Each tag in the tag sequence * correspond to a tag in the BER encoded message. If the decode * arives to a position where there is no matching tag, an error is * returned (if it wasn't the last tag and it was OPTIONAL). After the * right value has been detected it is returned in the out_buf. * */int decode_partial(ErlDrvBinary **drv_binary,unsigned char *in_buf, int in_buf_len){ char *out_buf = (*drv_binary)->orig_bytes; int tag_index_val = 1; int msg_index_val; int *msg_index, *tag_index, tmp_index; int tag_seq_length; char tag_code; /* one of ASN1_SKIPPED, ASN1_OPTIONAL, ASN1_CHOOSEN */ int wanted_tag, next_tag; int buf_end_index = in_buf_len; int ret = 0, length, old_index; tag_index = &tag_index_val; tag_seq_length = in_buf[0]; msg_index = &msg_index_val; *msg_index = tag_seq_length + 1;/* printf("decode_partial 1: in_buf_len=%d, tag_index=%d, msg_index=%d\r\n,tag_seq_length=%d\r\n",in_buf_len,*tag_index,*msg_index,tag_seq_length); */ while(*tag_index < tag_seq_length) { switch(in_buf[*tag_index]) { case ASN1_SKIPPED:/* printf("decode_partial ASN1_SKIPPED: in_buf[*msg_index]=%d\r\n",in_buf[*msg_index]); */ (*tag_index)++;/* printf("decode_partial ASN1_SKIPPED 2: *msg_index=%d\r\n",*msg_index); */ skip_tag(in_buf,msg_index,buf_end_index);/* printf("decode_partial ASN1_SKIPPED 3: *msg_index=%d\r\n",*msg_index); */ skip_length_and_value(in_buf,msg_index,buf_end_index);/* printf("decode_partial ASN1_SKIPPED 4: *msg_index=%d\r\n",*msg_index); */ break; case ASN1_OPTIONAL: (*tag_index)++;/* printf("decode_partial ASN1_OPTIONAL: in_buf[*tag_index]=%d\r\n",in_buf[*tag_index]); */ wanted_tag = in_buf[*tag_index]; (*tag_index)++; tmp_index = *msg_index; next_tag = get_tag(in_buf,msg_index,buf_end_index); if (wanted_tag != next_tag) { *msg_index = tmp_index; } else skip_length_and_value(in_buf,msg_index,buf_end_index); break; case ASN1_CHOOSEN:/* printf("decode_partial ASN1_CHOOSEN: in_buf[*msg_index]=%d, *msg_index=%d\r\n",in_buf[*msg_index],*msg_index); */ (*tag_index)++; wanted_tag = in_buf[*tag_index]; (*tag_index)++; old_index = *msg_index;/* printf("decode_partial ASN1_CHOOSEN 2: *msg_index=%d\r\n",*msg_index); */ next_tag = get_tag(in_buf,msg_index,buf_end_index);/* printf("decode_partial ASN1_CHOOSEN 3: *msg_index=%d\r\n,wanted_tag=%d, next_tag=%d\r\n",*msg_index,wanted_tag,next_tag); */ if (wanted_tag != next_tag) return ASN1_NOVALUE; /* an empty binary will be returned to Erlang */ if (*tag_index == (tag_seq_length + 1)) { /* get the value and return*/ if((ret = get_value(out_buf,in_buf,msg_index,buf_end_index)) <= ASN1_ERROR) return ASN1_ERROR; return ret; } else { /* calculate the length of the sub buffer and let *msg_index be at the value part of this BER encoded type*/ int indef; indef = 0; length = get_length(in_buf,msg_index,&indef,buf_end_index);/* printf("decode_partial ASN1_CHOOSEN 4: length=%d, *msg_index=%d\r\n",length,*msg_index); */ if ((length == 0) && (indef == 1)) { /* indefinite length of value */ old_index = *msg_index; length = skip_length_and_value(in_buf,msg_index,buf_end_index); *msg_index = old_index; buf_end_index = *msg_index + length - 2; /* remove two bytes due to indefinete length end zeros */ } else buf_end_index = (*msg_index + length); } break; default: return ASN1_ERROR; } } return ASN1_ERROR;}/* * int skip_tag(unsigned char *in_buf,int *index,int buf_len) * steps past the BER encoded tag in in_buf and updates *index. * Returns the number of skipped bytes. */int skip_tag(unsigned char *in_buf,int *index,int buf_len){ int start_index = *index; if ((MASK(in_buf[*index],ASN1_TAG)) == 31){ do { (*index)++; if (*index >= buf_len) return ASN1_ERROR; } while(in_buf[*index] >=128); } (*index)++; return (*index - start_index);}/* * int skip_length_and_value(unsigned char *in_buf,int *index,int buf_len) * steps past the BER encoded length and value in in_buf and updates *index. * returns the length if the skipped "length value". * Returns the number of skipped bytes. */int skip_length_and_value(unsigned char *in_buf,int *index,int buf_len){ long len; int indef = 0, lenoflen; int start_index = *index; if ((MASK(in_buf[*index],0x80)) == ASN1_SHORT_DEFINITE_LENGTH){ len = in_buf[*index]; if (len > (buf_len - (*index + 1))) return ASN1_LEN_ERROR; } else if (in_buf[*index] == ASN1_INDEFINITE_LENGTH) indef = 1; else /* long definite length */ { lenoflen = (in_buf[*index] & 0x7f); /*length of length */ len = 0; while (lenoflen--) { (*index)++; len = (len << 8) + in_buf[*index]; } if (len > (buf_len - (*index + 1))) return ASN1_LEN_ERROR; } (*index)++; if (indef == 1) { while(!(in_buf[*index]==0 && in_buf[*index + 1]==0)) { skip_tag(in_buf,index,buf_len); skip_length_and_value(in_buf,index,buf_len); } (*index) += 2; } else (*index) += len; return (*index - start_index);}/* int get_tag(unsigned char *in_buf,int *index) * * assumes next byte/bytes in in_buf is an encoded BER tag. A tag * number has theoretically no upper limit in size. Here the tag * number is assumed to be less than 64K. Returns an integer value * on the format: * xxxxxxxx xxxxxxcc tttttttt tttttttt * the x-bits are 0 (insignificant) * the c-bits are the class of the tag * the t-bits are the tag number. This implies that the tag number * is limited to 64K-1 * */int get_tag(unsigned char *in_buf,int *index,int buf_len){ int tag_no = 0,tmp_tag = 0; tag_no = (MASK(in_buf[*index],ASN1_CLASSFORM)); if ((MASK(in_buf[*index],ASN1_TAG)) == ASN1_TAG) { /* long form of tag */ do { (*index)++; if (*index >= buf_len) return ASN1_TAG_ERROR; tmp_tag = tmp_tag << 7; tmp_tag += (MASK(in_buf[*index],ASN1_LONG_TAG)); } while (in_buf[*index] >= 128); (*index)++; tag_no = tag_no + tmp_tag; } else { tag_no += (MASK(in_buf[*index],ASN1_TAG)); (*index)++; } if (*index >= buf_len) return ASN1_TAG_ERROR; return tag_no;}/* * int get_value(char *out_buf,unsigned char *in_buf, * int *msg_index,int in_buf_len) *//* assumes next byte/bytes in in_buf is an encoded BER value preceeded by a BER encoded length. Puts value in out_buf. */int get_value(char *out_buf, unsigned char *in_buf, int *msg_index, int in_buf_len){ int len, lenoflen, indef=0, skip_len; int ret=0; int start_index, out_index = 0; /* printf("get_value 1\n\r"); */ if (in_buf[*msg_index] < 0x80){ /* short definite length */ len = in_buf[*msg_index];/* printf("short definite length\r\n"); */ } else if (in_buf[*msg_index] > 0x80) { /* long definite length */ lenoflen = (in_buf[*msg_index] & 0x7f); /*length of length */ len = 0; while (lenoflen--) { (*msg_index)++; len = (len << 8) + in_buf[*msg_index]; } if (len > (in_buf_len - (*msg_index + 1))) return ASN1_LEN_ERROR; } else indef = 1; (*msg_index)++;/* printf("get_value 2: len = %d, *msg_index = %d\r\n",len,*msg_index); */ if (indef == 1) { while(!(in_buf[*msg_index]==0 && in_buf[*msg_index + 1]==0)) { start_index = *msg_index; skip_len = skip_tag(in_buf,msg_index,in_buf_len);/* printf("get_value 3: skip_len=%d,start_index=%d,*msg_index=%d\n\r", *//* skip_len,start_index,*msg_index); */ memcpy(&out_buf[ret],&in_buf[start_index],skip_len); ret += skip_len; start_index = *msg_index; skip_len = skip_length_and_value(in_buf,msg_index,in_buf_len);/* printf("get_value 4: skip_len=%d,start_index=%d,*msg_index=%d\n\r", *//* skip_len,start_index,*msg_index); */ memcpy(&out_buf[ret],&in_buf[start_index],skip_len); ret += skip_len; } return ret; } else memcpy(&out_buf[ret],&in_buf[*msg_index],len); return len;}/* * int get_length(unsigned char *in_buf,int *msg_index) * assumes next byte/bytes contain a BER encoded length field, * which is decoded. The value of the length is returned. If it * is an indefinite length the *indef is set to one. */int get_length(unsigned char *in_buf,int *msg_index, int *indef,int in_buf_len){ int len=0, lenoflen; if (in_buf[*msg_index] < 0x80) /* short definite length */ len = in_buf[*msg_index]; else if (in_buf[*msg_index] > 0x80) { /* long definite length */ lenoflen = (in_buf[*msg_index] & 0x7f); /*length of length */ len = 0; while (lenoflen--) { (*msg_index)++; len = (len << 8) + in_buf[*msg_index]; } if (len > (in_buf_len - (*msg_index + 1))) return ASN1_LEN_ERROR; } else *indef = 1; (*msg_index)++; return len;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -