asn1.cpp

来自「JdonFramework need above jdk 1.4.0 This」· C++ 代码 · 共 1,759 行 · 第 1/4 页

CPP
1,759
字号
/* * asn_build_sequence - builds an ASN header for a sequence 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. */unsigned char * asn_build_sequence( unsigned char *data,                                    int *datalength,                                    unsigned char type,                                    int length){  *datalength -= 4;  if (*datalength < 0){    *datalength += 4;	/* fix up before punting */    return NULL;  }  *data++ = type;  *data++ = (unsigned char)(0x02 | ASN_LONG_LEN);  *data++ = (unsigned char)((length >> 8) & 0xFF);  *data++ = (unsigned 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. */unsigned char * asn_parse_length( unsigned char *data,                                  unsigned long  *length){  unsigned char lengthbyte = *data;  if (lengthbyte & ASN_LONG_LEN){    lengthbyte &= ~ASN_LONG_LEN;	/* turn MSb off */    if (lengthbyte == 0){      ASNERROR("We don't support indefinite lengths");      return NULL;    }    if (lengthbyte > sizeof(long)){      ASNERROR("we can't support data lengths that long");      return NULL;    }    // fixed    memcpy((char *)length, (char *)data + 1, (int)lengthbyte);    *length = ntohl(*length);    // ntohl even on 64bit platforms works on 32bit int,     // whereas long is 64bit - therefore:    *length >>= (8 * ((sizeof(int)) - lengthbyte));    return data + lengthbyte + 1;  } else { /* short asnlength */    *length = (long)lengthbyte;    return data + 1;  }};unsigned char *asn_build_length( unsigned char *data,                                 int *datalength,                                 int length){  unsigned char    *start_data = data;  /* no indefinite lengths sent */  if (length < 0x80){    if (*datalength < 1){      ASNERROR("build_length");      return NULL;    }	        *data++ = (unsigned char)length;  } else if (length <= 0xFF){    if (*datalength < 2){      ASNERROR("build_length");      return NULL;    }	        *data++ = (unsigned char)(0x01 | ASN_LONG_LEN);    *data++ = (unsigned char)length;  } else { /* 0xFF < length <= 0xFFFF */    if (*datalength < 3){      ASNERROR("build_length");      return NULL;    }	        *data++ = (unsigned char)(0x02 | ASN_LONG_LEN);    *data++ = (unsigned char)((length >> 8) & 0xFF);    *data++ = (unsigned 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. */unsigned char *asn_parse_objid( unsigned char *data,                                int *datalength,                                unsigned char *type,                                oid *objid,                                int *objidlength){  /*   * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*   * subidentifier ::= {leadingbyte}* lastbyte   * leadingbyte ::= 1 7bitvalue   * lastbyte ::= 0 7bitvalue   */  unsigned char *bufp = data;  oid *oidp = objid + 1;  unsigned long subidentifier;  long   length;  unsigned long	    asn_length;  *type = *bufp++;  bufp = asn_parse_length(bufp, &asn_length);  if (bufp == NULL)    return NULL;  if ((int)asn_length + (bufp - data) > *datalength){    ASNERROR("overflow of message");    return NULL;  }  *datalength -= (int)asn_length + (bufp - data);    /* 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) + (*(unsigned char *)bufp & ~ASN_BIT8);      length--;    } while (*(unsigned char *)bufp++ & ASN_BIT8);	/* last byte has high bit clear */    if (subidentifier > (unsigned long)MAX_SUBID){      ASNERROR("subidentifier too long");      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 = (unsigned long)objid[1];  if (subidentifier == 0x2B){    objid[0] = 1;    objid[1] = 3;  } else {    objid[1] = (unsigned char)(subidentifier % 40);    objid[0] = (unsigned char)((subidentifier - objid[1]) / 40);  }  *objidlength = (int)(oidp - objid);  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. */unsigned char *asn_build_objid( unsigned char *data,                                int *datalength,                                unsigned char type,                                oid *objid,                                int objidlength){  /*   * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*   * subidentifier ::= {leadingbyte}* lastbyte   * leadingbyte ::= 1 7bitvalue   * lastbyte ::= 0 7bitvalue   */  unsigned char buf[MAX_OID_LEN*4];  unsigned char *bp = buf;  oid *op = objid;  int    asnlength;  unsigned long subid, mask, testmask;  int bits, testbits;  if (objidlength < 2){    *bp++ = 0;    objidlength = 0;  } else {    *bp++ = (unsigned char) (op[1] + (op[0] * 40));    objidlength -= 2;    op += 2;  }  while(objidlength-- > 0){    subid = *op++;    if (subid < 127){ /* off by one? */      *bp++ = (unsigned char )subid;    } else {      mask = 0x7F; /* handle subid == 0 case */      bits = 0;      /* testmask *MUST* !!!! be of an unsigned type */      for(testmask = 0x7F, testbits = 0; testmask != 0;	  testmask <<= 7, testbits += 7){	if (subid & testmask){	/* if any bits set */	  mask = testmask;	  bits = testbits;	}      }      /* mask can't be zero here */      for(;mask != 0x7F; mask >>= 7, bits -= 7){	/* fix a mask that got truncated above */	if (mask == 0x1E00000)  	  mask = 0xFE00000;	*bp++ = (unsigned char)(((subid & mask) >> bits) | ASN_BIT8);      }      *bp++ = (unsigned char)(subid & mask);    }  }  asnlength = bp - buf;  data = asn_build_header(data, datalength, type, asnlength);  if (data == NULL)    return NULL;  if (*datalength < asnlength)    return NULL;  // fixed  memcpy((char *)data, (char *)buf,  asnlength);  *datalength -= asnlength;  return data + asnlength;};/* * 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. */unsigned char *asn_parse_null(unsigned char	*data,                              int *datalength,                              unsigned char *type){  /*   * ASN.1 null ::= 0x05 0x00   */  unsigned char   *bufp = data;  unsigned long	    asn_length;  *type = *bufp++;  bufp = asn_parse_length(bufp, &asn_length);  if (bufp == NULL)    return NULL;  if (asn_length != 0){    ASNERROR("Malformed NULL");    return NULL;  }  *datalength -= (bufp - data);  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. */unsigned char *asn_build_null( unsigned char *data,                               int *datalength,                               unsigned 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. */unsigned char *asn_parse_bitstring( unsigned char *data,                                    int *datalength,                                    unsigned char *type,                                    unsigned char *string,                                    int *strlength){  /*   * bitstring ::= 0x03 asnlength unused {byte}* */  unsigned char *bufp = data;  unsigned long	    asn_length;  *type = *bufp++;  bufp = asn_parse_length(bufp, &asn_length);  if (bufp == NULL)    return NULL;  if ((int)(asn_length + (bufp - data)) > *datalength){    ASNERROR("overflow of message");    return NULL;  }  if ((int) asn_length > *strlength){    ASNERROR("I don't support such long bitstrings");    return NULL;  }  if (asn_length < 1){    ASNERROR("Invalid bitstring");    return NULL;  }  if (*bufp > 7){    ASNERROR("Invalid bitstring");    return NULL;  }  // fixed  memcpy((char *)string,(char *)bufp,  (int)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. */unsigned char *asn_build_bitstring( unsigned char *data,                                    int *datalength,                                    unsigned char type,	                                    unsigned char *string,                                    int strlength){  /*   * ASN.1 bit string ::= 0x03 asnlength unused {byte}* */  if (strlength < 1 || *string > 7){    ASNERROR("Building invalid bitstring");    return NULL;  }  data = asn_build_header(data, datalength, type, strlength);  if (data == NULL)    return NULL;  if (*datalength < strlength)    return NULL;  // fixed  memcpy((char *)data,(char *)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. */unsigned char * asn_parse_unsigned_int64(  unsigned char *data,                                           int *datalength,                                           unsigned char *type,                                           struct counter64 *cp,                                           int countersize){  /*   * ASN.1 integer ::= 0x02 asnlength byte {byte}* */  unsigned char *bufp = data;  unsigned long	    asn_length;  unsigned long low = 0, high = 0;  int intsize = 4;      if (countersize != sizeof(struct counter64)){    ASNERROR("not right size");    return NULL;  }  *type = *bufp++;  bufp = asn_parse_length(bufp, &asn_length);  if (bufp == NULL){    ASNERROR("bad length");    return NULL;  }  if ((int)(asn_length + (bufp - data)) > *datalength){    ASNERROR("overflow of message");    return NULL;  }  if (((int)asn_length > (intsize * 2 + 1)) ||      (((int)asn_length == (intsize * 2) + 1) && *bufp != 0x00)){    ASNERROR("I don't support such large integers");    return NULL;

⌨️ 快捷键说明

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