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

📄 asn1.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}


/*
 * 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 + -