?? asn1.c
字號:
do { /* shift and add in low order 7 bits */ subidentifier = (subidentifier << 7) + (*(u_char *)bufp & ~ASN_BIT8); length--; } while (*(u_char *)bufp++ & ASN_BIT8); /* last byte has high bit clear *//*?? note, this test will never be true, since the largest value of subidentifier is the value of MAX_SUBID! */ if (subidentifier > (u_long)MAX_SUBID){ ERROR_MSG("subidentifier too large"); return NULL; } *oidp++ = (oid)subidentifier; } /* * The first two subidentifiers are encoded into the first component * with the value (X * 40) + Y, where: * X is the value of the first subidentifier. * Y is the value of the second subidentifier. */ subidentifier = (u_long)objid[1]; if (subidentifier == 0x2B){ objid[0] = 1; objid[1] = 3; } else { if (subidentifier < 40) { objid[0] = 0; objid[1] = subidentifier; } else if (subidentifier < 80) { objid[0] = 1; objid[1] = subidentifier - 40; } else if (subidentifier < 120) { objid[0] = 2; objid[1] = subidentifier - 80; } else { objid[1] = (subidentifier % 40); objid[0] = ((subidentifier - objid[1]) / 40); } } *objidlength = (int)(oidp - objid); DEBUGMSG(("dump_recv", " ASN ObjID: ")); DEBUGMSGOID(("dump_recv", objid, *objidlength)); DEBUGMSG(("dump_recv", "\n")); return bufp;}/* * asn_build_objid - Builds an ASN object identifier object containing the * input string. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the beginning of the next object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_build_objid( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer int type IN - asn type of object oid *objid IN - pointer to start of input buffer int objidlength IN - number of sub-id's in objid */u_char *asn_build_objid(u_char *data, size_t *datalength, u_char type, oid *objid, size_t objidlength){/* * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* * subidentifier ::= {leadingbyte}* lastbyte * leadingbyte ::= 1 7bitvalue * lastbyte ::= 0 7bitvalue */ size_t asnlength; register oid *op = objid; u_char objid_size[MAX_OID_LEN]; register u_long objid_val; u_long first_objid_val; register int i; /* check if there are at least 2 sub-identifiers */ if (objidlength == 0){ /* there are not, so make OID have two with value of zero */ objid_val = 0; objidlength = 2; } else if (objidlength == 1){ /* encode the first value */ objid_val = (op[0] * 40); objidlength = 2; op++; } else { /* combine the first two values */ if ( op[1] > 40 ) { ERROR_MSG("build objid: bad second subidentifier"); return NULL; } objid_val = (op[0] * 40) + op[1]; op += 2; } first_objid_val = objid_val; /* calculate the number of bytes needed to store the encoded value */ for (i = 1, asnlength = 0;;) { if (objid_val < (unsigned)0x80) { objid_size[i] = 1; asnlength += 1; } else if (objid_val < (unsigned)0x4000) { objid_size[i] = 2; asnlength += 2; } else if (objid_val < (unsigned)0x200000) { objid_size[i] = 3; asnlength += 3; } else if (objid_val < (unsigned)0x10000000) { objid_size[i] = 4; asnlength += 4; } else { objid_size[i] = 5; asnlength += 5; } i++; if (i >= (int)objidlength) break; objid_val = *op++; } /* store the ASN.1 tag and length */ data = asn_build_header(data, datalength, type, asnlength); if (_asn_build_header_check("build objid", data, *datalength, asnlength)) return NULL; /* store the encoded OID value */ for (i = 1, objid_val = first_objid_val, op = objid+2; i < (int)objidlength; i++) { if (i != 1) objid_val = *op++; switch (objid_size[i]) { case 1: *data++ = (u_char)objid_val; break; case 2: *data++ = (u_char)((objid_val>>7) | 0x80); *data++ = (u_char)(objid_val & 0x07f); break; case 3: *data++ = (u_char)((objid_val>>14) | 0x80); *data++ = (u_char)((objid_val>>7 & 0x7f) | 0x80); *data++ = (u_char)(objid_val & 0x07f); break; case 4: *data++ = (u_char)((objid_val>>21) | 0x80); *data++ = (u_char)((objid_val>>14 & 0x7f) | 0x80); *data++ = (u_char)((objid_val>>7 & 0x7f) | 0x80); *data++ = (u_char)(objid_val & 0x07f); break; case 5: *data++ = (u_char)((objid_val>>28) | 0x80); *data++ = (u_char)((objid_val>>21 & 0x7f) | 0x80); *data++ = (u_char)((objid_val>>14 & 0x7f) | 0x80); *data++ = (u_char)((objid_val>>7 & 0x7f) | 0x80); *data++ = (u_char)(objid_val & 0x07f); break; } } /* return the length and data ptr */ *datalength -= asnlength; return data;}/* * asn_parse_null - Interprets an ASN null type. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the beginning of the next object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_parse_null( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer u_char *type OUT - asn type of object */u_char *asn_parse_null(u_char *data, size_t *datalength, u_char *type){/* * ASN.1 null ::= 0x05 0x00 */ register u_char *bufp = data; u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (bufp == NULL){ ERROR_MSG("parse null: bad length"); return NULL; } if (asn_length != 0){ ERROR_MSG("parse null: malformed ASN.1 null"); return NULL; } *datalength -= (bufp - data); DEBUGDUMPSETUP("dump_recv", data, bufp - data); DEBUGMSG(("dump_recv", " ASN NULL\n")); return bufp + asn_length;}/* * asn_build_null - Builds an ASN null object. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the beginning of the next object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_build_null( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer u_char type IN - asn type of object */u_char *asn_build_null(u_char *data, size_t *datalength, u_char type){/* * ASN.1 null ::= 0x05 0x00 */ return asn_build_header(data, datalength, type, 0);}/* * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the beginning of the next object. * * "string" is filled with the bit string. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_parse_bitstring( u_char *data IN - pointer to start of object size_t *datalength IN/OUT - number of valid bytes left in buffer u_char *type OUT - asn type of object u_char *string IN/OUT - pointer to start of output buffer size_t *strlength IN/OUT - size of output buffer */u_char *asn_parse_bitstring(u_char *data, size_t *datalength, u_char *type, u_char *string, size_t *strlength){/* * bitstring ::= 0x03 asnlength unused {byte}* */ static const char *errpre = "parse bitstring"; register u_char *bufp = data; u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (_asn_parse_length_check(errpre, bufp, data, asn_length, *datalength)) return NULL; if ((size_t)asn_length > *strlength){ _asn_length_err(errpre, (size_t)asn_length, *strlength); return NULL; } if (_asn_bitstring_check(errpre, asn_length, *bufp)) return NULL; DEBUGDUMPSETUP("dump_recv", data, bufp - data); DEBUGMSG(("dump_recv", " ASN Bitstring: ")); DEBUGMSGHEX(("dump_recv", data, asn_length)); memmove(string, bufp, asn_length); *strlength = (int)asn_length; *datalength -= (int)asn_length + (bufp - data); return bufp + asn_length;}/* * asn_build_bitstring - Builds an ASN bit string object containing the * input string. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the beginning of the next object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_build_bitstring( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer u_char type IN - asn type of object u_char *string IN - pointer to start of input buffer int strlength IN - size of input buffer */u_char *asn_build_bitstring(u_char *data, size_t *datalength, u_char type, u_char *string, size_t strlength){/* * ASN.1 bit string ::= 0x03 asnlength unused {byte}* */ static const char *errpre = "build bitstring"; if (_asn_bitstring_check(errpre, strlength, *string)) return NULL; data = asn_build_header(data, datalength, type, strlength); if (_asn_build_header_check(errpre,data,*datalength,strlength)) return NULL; memmove(data, string, strlength); *datalength -= strlength; return data + strlength;}/* * asn_parse_unsigned_int64 - pulls a 64 bit unsigned long out of an ASN int * type. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the end of this object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_parse_unsigned_int64( u_char *data IN - pointer to start of object int *datalength IN/OUT - number of valid bytes left in buffer u_char *type OUT - asn type of object struct counter64 *cp IN/OUT - pointer to counter struct int countersize IN - size of output buffer */u_char *asn_parse_unsigned_int64(u_char *data, size_t *datalength, u_char *type, struct counter64 *cp, size_t countersize){/* * ASN.1 integer ::= 0x02 asnlength byte {byte}* */ static const char *errpre = "parse uint64"; const int uint64sizelimit = (4 * 2) + 1; register u_char *bufp = data; u_long asn_length; register u_long low = 0, high = 0; if (countersize != sizeof(struct counter64)){ _asn_size_err(errpre, countersize, sizeof(struct counter64)); return NULL; } *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (_asn_parse_length_check(errpre, bufp, data, asn_length, *datalength)) return NULL; DEBUGDUMPSETUP("dump_recv", data, bufp - data);#ifdef OPAQUE_SPECIAL_TYPES/* 64 bit counters as opaque */ if ((*type == ASN_OPAQUE) && (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && (*bufp == ASN_OPAQUE_TAG1) && ((*(bufp+1) == ASN_OPAQUE_COUNTER64) || (*(bufp+1) == ASN_OPAQUE_U64))) { DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1))); /* change type to Counter64 or U64 */ *type = *(bufp+1); /* value is encoded as special format */ bufp = asn_parse_length(bufp + 2, &asn_length); if (_asn_parse_length_check("parse opaque uint64", bufp, data, asn_length, *datalength)) return NULL; }#endif /* OPAQUE_SPECIAL_TYPES */ if (((int)asn_length > uint64sizelimit) || (((int)asn_length == uint64sizelimit) && *bufp != 0x00)){ _asn_length_err(errpre, (size_t)asn_length, uint64sizelimit); return NULL; } *datalength -= (int)asn_length + (bufp - data); if (*bufp & 0x80){ low = ~low; /* integer is negative */ high = ~high; } while(asn_length--){ high = (high << 8) | ((low & 0xFF000000) >> 24); low = (low << 8) | *bufp++; } cp->low = low; cp->high = high; DEBUGIF("dump_recv") { char i64buf[I64CHARSZ+1]; printU64(i64buf, cp); } return bufp;}/* * asn_build_unsigned_int64 - builds an ASN object containing a 64 bit integer. * On entry, datalength is input as the number of valid bytes following * "data". On exit, it is returned as the number of valid bytes * following the end of this object. * * Returns a pointer to the first byte past the end * of this object (i.e. the start of the next object). * Returns NULL on any error. u_char * asn_build_unsigned_int64( u_char *data IN - pointer to start of output buffer size_t *datalength IN/OUT - number of valid bytes left in buffer u_char type IN - asn type of object struct counter64 *cp IN - pointer to counter struct size_t countersize IN - size of input buffer */u_char *asn_build_unsigned_int64(u_char *data, size_t *datalength, u_char type, struct counter64 *cp, size_t countersize){/* * ASN.1 integer ::= 0x02 asnlength byte {byte}* */ register u_long low, high; register u_long mask, mask2; int add_null_byte = 0; size_t intsize; if (countersize != sizeof(struct counter64)){ _asn_size_err("build uint64", countersize, sizeof(struct counter64)); return NULL; } intsize = 8; low = cp->low; high = cp->high; mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); /* mask is 0xFF000000 on a big-endian machine */ if ((u_char)((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80){ /* if MSB is set */ add_null_byte = 1; intsize++; } else { /* * Truncate "unnecessary" bytes off of the most significant end of this 2's * complement integer. * There should be no sequence of 9 consecutive 1's or 0's at the most * significant end of the integer.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -