⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn1.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{
/*
 * 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.
	 */
	mask2 = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
	/* mask2 is 0xFF800000 on a big-endian machine */
	while((((high & mask2) == 0) || ((high & mask2) == mask2)) && intsize > 1){
	    intsize--;
	    high = (high << 8)
		| ((low & mask) >> (8 * (sizeof(long) - 1)));
	    low <<= 8;
	}
    }
#ifdef OPAQUE_SPECIAL_TYPES
/* encode a Counter64 as an opaque (it also works in SNMPv1) */
    /* turn into Opaque holding special tagged value */
    if (type == ASN_OPAQUE_COUNTER64) {
        /* put the tag and length for the Opaque wrapper */
        data = asn_build_header(data, datalength, ASN_OPAQUE, intsize+3);
    if (_asn_build_header_check("build counter u64", data, *datalength, intsize+3))
	return NULL;

	/* put the special tag and length */
	*data++ = ASN_OPAQUE_TAG1;
	*data++ = ASN_OPAQUE_COUNTER64;
	*data++ = (u_char)intsize;
	*datalength = *datalength - 3;
    }
    else
/* Encode the Unsigned int64 in an opaque */
    /* turn into Opaque holding special tagged value */
    if (type == ASN_OPAQUE_U64) {
        /* put the tag and length for the Opaque wrapper */
        data = asn_build_header(data, datalength, ASN_OPAQUE, intsize+3);
    if (_asn_build_header_check("build opaque u64", data, *datalength, intsize+3))
	return NULL;

	/* put the special tag and length */
	*data++ = ASN_OPAQUE_TAG1;
	*data++ = ASN_OPAQUE_U64;
	*data++ = (u_char)intsize;
	*datalength = *datalength - 3;
    }
    else
    {
#endif /* OPAQUE_SPECIAL_TYPES */
    data = asn_build_header(data, datalength, type, intsize);
    if (_asn_build_header_check("build uint64", data, *datalength, intsize))
	return NULL;

#ifdef OPAQUE_SPECIAL_TYPES
    }
#endif /* OPAQUE_SPECIAL_TYPES */
    *datalength -= intsize;
    if (add_null_byte == 1){
	*data++ = '\0';
	intsize--;
    }
    while(intsize--){
	*data++ = (u_char)((high & mask) >> (8 * (sizeof(long) - 1)));
	high = (high << 8)
	    | ((low & mask) >> (8 * (sizeof(long) - 1)));
	low <<= 8;
	
    }
    return data;
}

#ifdef OPAQUE_SPECIAL_TYPES

/*

  u_char * asn_parse_signed_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_signed_int64(u_char *data,
		       size_t *datalength,
		       u_char *type,
		       struct counter64 *cp,
		       size_t countersize)
{
  static const char *errpre = "parse int64";
  const int int64sizelimit = (4 * 2) + 1;
  char ebuf[128];
  register u_char *bufp = data;
  u_long	    asn_length;
  register u_int 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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -