📄 asn1.c
字号:
}
/*
* asn_build_int - builds an ASN object containing an 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_int(
u_char *data IN - pointer to start of output buffer
int *datalength IN/OUT - number of valid bytes left in buffer
int type IN - asn type of object
long *intp IN - pointer to start of long integer
int intsize IN - size of input buffer
*/
u_char *
asn_build_int(u_char *data,
size_t *datalength,
u_char type,
long *intp,
size_t intsize)
{
/*
* ASN.1 integer ::= 0x02 asnlength byte {byte}*
*/
static const char *errpre = "build int";
register long integer;
register u_long mask;
if (intsize != sizeof (long)){
_asn_size_err(errpre, intsize, sizeof(long));
return NULL;
}
integer = *intp;
/*
* 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.
*/
mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
/* mask is 0xFF800000 on a big-endian machine */
while((((integer & mask) == 0) || ((integer & mask) == mask))
&& intsize > 1){
intsize--;
integer <<= 8;
}
data = asn_build_header(data, datalength, type, intsize);
if (_asn_build_header_check(errpre,data,*datalength,intsize))
return NULL;
*datalength -= intsize;
mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
/* mask is 0xFF000000 on a big-endian machine */
while(intsize--){
*data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1)));
integer <<= 8;
}
return data;
}
/*
* asn_build_unsigned_int - builds an ASN object containing an 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_int(
u_char *data IN - pointer to start of output buffer
int *datalength IN/OUT - number of valid bytes left in buffer
u_char type IN - asn type of object
u_long *intp IN - pointer to start of long integer
int intsize IN - size of input buffer
*/
u_char *
asn_build_unsigned_int(u_char *data,
size_t *datalength,
u_char type,
u_long *intp,
size_t intsize)
{
/*
* ASN.1 integer ::= 0x02 asnlength byte {byte}*
*/
static const char *errpre = "build uint";
register u_long integer;
register u_long mask;
int add_null_byte = 0;
if (intsize != sizeof (long)){
_asn_size_err(errpre, intsize, sizeof(long));
return NULL;
}
integer = *intp;
mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
/* mask is 0xFF000000 on a big-endian machine */
if ((u_char)((integer & 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.
*/
mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
/* mask is 0xFF800000 on a big-endian machine */
while((((integer & mask) == 0) || ((integer & mask) == mask)) && intsize > 1){
intsize--;
integer <<= 8;
}
}
data = asn_build_header(data, datalength, type, intsize);
if (_asn_build_header_check(errpre,data,*datalength,intsize))
return NULL;
*datalength -= intsize;
if (add_null_byte == 1){
*data++ = '\0';
intsize--;
}
mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
/* mask is 0xFF000000 on a big-endian machine */
while(intsize--){
*data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1)));
integer <<= 8;
}
return data;
}
/*
* asn_parse_string - pulls an octet string out of an ASN octet string 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 octet 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_string(
* 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 *string IN/OUT - pointer to start of output buffer
* int *strlength IN/OUT - size of output buffer
*
*
* ASN.1 octet string ::= primstring | cmpdstring
* primstring ::= 0x04 asnlength byte {byte}*
* cmpdstring ::= 0x24 asnlength string {string}*
*/
u_char *
asn_parse_string(u_char *data,
size_t *datalength,
u_char *type,
u_char *string,
size_t *strlength)
{
static const char *errpre = "parse string";
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 ((int)asn_length > *strlength){
_asn_length_err(errpre, (size_t)asn_length, *strlength);
return NULL;
}
DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length);
memmove(string, bufp, asn_length);
if (*strlength > (int)asn_length)
string[asn_length] = 0;
*strlength = (int)asn_length;
*datalength -= (int)asn_length + (bufp - data);
DEBUGIF("dump_recv") {
char *buf = (char *)malloc(1+asn_length);
sprint_asciistring(buf, string, asn_length);
DEBUGMSG(("dump_recv", " ASN String:\t%s\n", buf));
free (buf);
}
return bufp + asn_length;
}
/*
* asn_build_string - Builds an ASN octet 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_string(
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_string(u_char *data,
size_t *datalength,
u_char type,
const u_char *string,
size_t strlength)
{
/*
* ASN.1 octet string ::= primstring | cmpdstring
* primstring ::= 0x04 asnlength byte {byte}*
* cmpdstring ::= 0x24 asnlength string {string}*
* This code will never send a compound string.
*/
data = asn_build_header(data, datalength, type, strlength);
if (_asn_build_header_check("build string", data, *datalength, strlength))
return NULL;
if (strlength) {
if (string == NULL) {
memset(data, 0, strlength);
} else {
memmove(data, string, strlength);
}
}
*datalength -= strlength;
return data + strlength;
}
/*
* asn_parse_header - interprets the ID and length of the current 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
* in this object following the id and length.
*
* Returns a pointer to the first byte of the contents of this object.
* Returns NULL on any error.
u_char * asn_parse_header(
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_header(u_char *data,
size_t *datalength,
u_char *type)
{
register u_char *bufp;
u_long asn_length;
if (!data || !datalength || !type) {
ERROR_MSG("parse header: NULL pointer");
return NULL;
}
bufp = data;
/* this only works on data types < 30, i.e. no extension octets */
if (IS_EXTENSION_ID(*bufp)){
ERROR_MSG("can't process ID >= 30");
return NULL;
}
*type = *bufp;
bufp = asn_parse_length(bufp + 1, &asn_length);
if (_asn_parse_length_check("parse header", bufp, data, asn_length, *datalength))
return NULL;
DEBUGDUMPSETUP("dump_recv", data, (bufp-data));
DEBUGMSG(("dump_recv", " ASN Header: 0x%.2X, len = %d (0x%X)\n", *data,
asn_length, asn_length));
#ifdef OPAQUE_SPECIAL_TYPES
if ((*type == ASN_OPAQUE) &&
(*bufp == ASN_OPAQUE_TAG1)) {
DEBUGINDENTMORE();
DEBUGDUMPSETUP("dump_recv", data, 1);
DEBUGMSG(("dump_recv", "Opaque:\t%.2x\n", *bufp));
DEBUGINDENTLESS();
/* check if 64-but counter */
switch(*(bufp+1)) {
case ASN_OPAQUE_COUNTER64:
case ASN_OPAQUE_U64:
case ASN_OPAQUE_FLOAT:
case ASN_OPAQUE_DOUBLE:
case ASN_OPAQUE_I64:
*type = *(bufp+1);
break;
default:
/* just an Opaque */
*datalength = (int)asn_length;
return bufp;
}
/* value is encoded as special format */
bufp = asn_parse_length(bufp + 2, &asn_length);
if (_asn_parse_length_check("parse opaque header", bufp, data,
asn_length, *datalength))
return NULL;
}
#endif /* OPAQUE_SPECIAL_TYPES */
*datalength = (int)asn_length;
return bufp;
}
/*
* same as asn_parse_header with test for expected type.
*/
u_char *
asn_parse_sequence(u_char *data,
size_t *datalength,
u_char *type,
u_char expected_type, /* must be this type */
const char *estr) /* error message prefix */
{
data = asn_parse_header(data, datalength, type);
if (data && (*type != expected_type)) {
char ebuf[128];
sprintf(ebuf, "%s header type %02X: s/b %02X", estr,
(u_char)*type, (u_char)expected_type);
ERROR_MSG(ebuf);
return NULL;
}
return data;
}
/*
* asn_build_header - builds an ASN header for an object with the ID and
* length specified.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* in this object following the id and length.
*
* This only works on data types < 30, i.e. no extension octets.
* The maximum length is 0xFFFF;
*
* Returns a pointer to the first byte of the contents of this object.
* Returns NULL on any error.
u_char * asn_build_header(
u_char *data IN - pointer to start of object
size_t *datalength IN/OUT - number of valid bytes left in buffer
u_char type IN - asn type of object
size_t length IN - length of object
*/
u_char *
asn_build_header (u_char *data,
size_t *datalength,
u_char type,
size_t length)
{
char ebuf[128];
if (*datalength < 1){
sprintf(ebuf, "bad header length < 1 :%d, %d", *datalength, length);
ERROR_MSG(ebuf);
return NULL;
}
*data++ = type;
(*datalength)--;
return asn_build_length(data, datalength, length);
}
/*
* asn_build_sequence - builds an ASN header for a sequence with the ID and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -