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

📄 asn1.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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_sequence(
      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
      int         length       IN - length of object
 */
u_char *
asn_build_sequence(u_char *data,
		  size_t *datalength,
		  u_char type,
		  size_t length)
{
    static const char *errpre = "build seq";
    char ebuf[128];
    
    if (*datalength < 4){
	sprintf(ebuf, "%s: length %d < 4: PUNT", errpre, (int)*datalength);
	ERROR_MSG(ebuf);
	return NULL;
    }
    *datalength -= 4;
    *data++ = type;
    *data++ = (u_char)(0x02 | ASN_LONG_LEN);
    *data++ = (u_char)((length >> 8) & 0xFF);
    *data++ = (u_char)(length & 0xFF);
    return data;
}

/*
 * asn_parse_length - interprets the length of the current object.
 *  On exit, length contains the value of this length field.
 *
 *  Returns a pointer to the first byte after this length
 *  field (aka: the start of the data field).
 *  Returns NULL on any error.

  u_char * asn_parse_length(
      u_char     *data         IN - pointer to start of length field
      u_long     *length       OUT - value of length field
 */
u_char *
asn_parse_length(u_char  *data,
		 u_long  *length)
{
    static const char *errpre = "parse length";
    char ebuf[128];
    register u_char lengthbyte;
    
    if (!data || !length) {
	ERROR_MSG("parse length: NULL pointer");
	return NULL;
    }
    lengthbyte = *data;

    if (lengthbyte & ASN_LONG_LEN){
	lengthbyte &= ~ASN_LONG_LEN;	/* turn MSb off */
	if (lengthbyte == 0){
	    sprintf(ebuf, "%s: indefinite length not supported", errpre);
	    ERROR_MSG(ebuf);
	    return NULL;
	}
	if (lengthbyte > sizeof(long)){
	    sprintf(ebuf, "%s: data length %d > %d not supported", errpre,
                 lengthbyte, sizeof(long));
	    ERROR_MSG(ebuf);
	    return NULL;
	}
	data++;
	*length = 0;  /* protect against short lengths */
	while(lengthbyte--) {
		*length <<= 8;
		*length |= *data++;
	}
	return data;
    } else { /* short asnlength */
	*length = (long)lengthbyte;
	return data + 1;
    }
}

/*

  u_char * asn_build_length(
      u_char     *data         IN - pointer to start of object
      int        *datalength   IN/OUT - number of valid bytes left in buffer
      int         length       IN - length of object
 */
u_char *
asn_build_length(u_char *data,
		 size_t *datalength,
		 size_t length)
{
    static const char *errpre = "build length";
    char ebuf[128];
    
    u_char    *start_data = data;

    /* no indefinite lengths sent */
    if (length < 0x80){
	if (*datalength < 1){
	    sprintf(ebuf, "%s: bad length < 1 :%d, %d",errpre,*datalength,length);
	    ERROR_MSG(ebuf);
	    return NULL;
	}	    
	*data++ = (u_char)length;
    } else if (length <= 0xFF){
	if (*datalength < 2){
	    sprintf(ebuf, "%s: bad length < 2 :%d, %d",errpre,*datalength,length);
	    ERROR_MSG(ebuf);
	    return NULL;
	}	    
	*data++ = (u_char)(0x01 | ASN_LONG_LEN);
	*data++ = (u_char)length;
    } else { /* 0xFF < length <= 0xFFFF */
	if (*datalength < 3){
	    sprintf(ebuf, "%s: bad length < 3 :%d, %d",errpre,*datalength,length);
	    ERROR_MSG(ebuf);
	    return NULL;
	}	    
	*data++ = (u_char)(0x02 | ASN_LONG_LEN);
	*data++ = (u_char)((length >> 8) & 0xFF);
	*data++ = (u_char)(length & 0xFF);
    }
    *datalength -= (data - start_data);
    return data;

}

/*
 * asn_parse_objid - pulls an object indentifier out of an ASN object identifier 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.
 *
 *  "objid" is filled with the object identifier.
 *
 *  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_objid(
      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
      oid        *objid        IN/OUT - pointer to start of output buffer
      int        *objidlength  IN/OUT - number of sub-id's in objid
 */
u_char *
asn_parse_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
 */
    register u_char *bufp = data;
    register oid *oidp = objid + 1;
    register u_long subidentifier;
    register long   length;
    u_long	    asn_length;

    *type = *bufp++;
    bufp = asn_parse_length(bufp, &asn_length);
    if (_asn_parse_length_check("parse objid", bufp, data,
                    asn_length, *datalength))
	return NULL;

    *datalength -= (int)asn_length + (bufp - data);

    DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length);

    /* Handle invalid object identifier encodings of the form 06 00 robustly */
    if (asn_length == 0)
	objid[0] = objid[1] = 0;

    length = asn_length;
    (*objidlength)--;	/* account for expansion of first byte */

    while (length > 0 && (*objidlength)-- > 0){
	subidentifier = 0;
	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)

⌨️ 快捷键说明

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