util-decode-der: code cleanup

pull/1997/head
Mats Klepsland 10 years ago committed by Victor Julien
parent e117461d4b
commit a985b450e3

@ -49,19 +49,45 @@
#define MAX_OID_LENGTH 256 #define MAX_OID_LENGTH 256
static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer,
static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); uint32_t size, uint8_t depth,
static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer,
static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); uint32_t size, uint8_t depth,
static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode); static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer,
static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); uint32_t size, uint8_t depth,
static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer,
static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); uint32_t size, uint8_t depth,
static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode); static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode);
static Asn1Generic * Asn1GenericNew(void) static Asn1Generic * Asn1GenericNew(void)
{ {
@ -98,7 +124,9 @@ static int Asn1SequenceAppend(Asn1Generic *seq, Asn1Generic *node)
return 0; return 0;
} }
static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t max_size, uint8_t depth, int seq_index, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
int seq_index, uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t numbytes, el_max_size; uint32_t numbytes, el_max_size;
@ -119,23 +147,26 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
switch (el.cls) { switch (el.cls) {
case ASN1_CLASS_CONTEXTSPEC: case ASN1_CLASS_CONTEXTSPEC:
/* get element type from definition /* get element type from definition, see:
* see http://www.ietf.org/rfc/rfc3280.txt) http://www.ietf.org/rfc/rfc3280.txt */
*/
if (depth == 2 && el.tag == 0) { if (depth == 2 && el.tag == 0) {
el_type = ASN1_SEQUENCE; /* TBSCertificate */ /* TBSCertificate */
el_type = ASN1_SEQUENCE;
break; break;
} }
if (depth == 2 && el.tag == 1) { if (depth == 2 && el.tag == 1) {
el_type = ASN1_BITSTRING; /* issuerUniqueID */ /* issuerUniqueID */
el_type = ASN1_BITSTRING;
break; break;
} }
if (depth == 2 && el.tag == 2) { if (depth == 2 && el.tag == 2) {
el_type = ASN1_BITSTRING; /* subjectUniqueID */ /* subjectUniqueID */
el_type = ASN1_BITSTRING;
break; break;
} }
if (depth == 2 && el.tag == 3) { if (depth == 2 && el.tag == 3) {
el_type = ASN1_SEQUENCE; /* extensions */ /* extensions */
el_type = ASN1_SEQUENCE;
break; break;
} }
/* unknown context specific value - do not decode */ /* unknown context specific value - do not decode */
@ -154,22 +185,27 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
child = DecodeAsn1DerNull(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerNull(d_ptr, el_max_size, depth+1, errcode);
break; break;
case ASN1_BITSTRING: case ASN1_BITSTRING:
child = DecodeAsn1DerBitstring(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerBitstring(d_ptr, el_max_size, depth+1,
errcode);
break; break;
case ASN1_OID: case ASN1_OID:
child = DecodeAsn1DerOid(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerOid(d_ptr, el_max_size, depth+1, errcode);
break; break;
case ASN1_IA5STRING: case ASN1_IA5STRING:
child = DecodeAsn1DerIA5String(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerIA5String(d_ptr, el_max_size, depth+1,
errcode);
break; break;
case ASN1_OCTETSTRING: case ASN1_OCTETSTRING:
child = DecodeAsn1DerOctetString(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerOctetString(d_ptr, el_max_size, depth+1,
errcode);
break; break;
case ASN1_UTF8STRING: case ASN1_UTF8STRING:
child = DecodeAsn1DerUTF8String(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerUTF8String(d_ptr, el_max_size, depth+1,
errcode);
break; break;
case ASN1_PRINTSTRING: case ASN1_PRINTSTRING:
child = DecodeAsn1DerPrintableString(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerPrintableString(d_ptr, el_max_size, depth+1,
errcode);
break; break;
case ASN1_SEQUENCE: case ASN1_SEQUENCE:
child = DecodeAsn1DerSequence(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerSequence(d_ptr, el_max_size, depth+1, errcode);
@ -178,7 +214,8 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
child = DecodeAsn1DerSet(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerSet(d_ptr, el_max_size, depth+1, errcode);
break; break;
case ASN1_T61STRING: case ASN1_T61STRING:
child = DecodeAsn1DerT61String(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerT61String(d_ptr, el_max_size, depth+1,
errcode);
break; break;
case ASN1_UTCTIME: case ASN1_UTCTIME:
child = DecodeAsn1DerUTCTime(d_ptr, el_max_size, depth+1, errcode); child = DecodeAsn1DerUTCTime(d_ptr, el_max_size, depth+1, errcode);
@ -189,15 +226,20 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
child = Asn1GenericNew(); child = Asn1GenericNew();
if (child == NULL) if (child == NULL)
break; break;
child->type = el.tag; child->type = el.tag;
/* total sequence length */ /* total sequence length */
const unsigned char * save_d_ptr = d_ptr; const unsigned char * save_d_ptr = d_ptr;
d_ptr++; d_ptr++;
c = d_ptr[0]; c = d_ptr[0];
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */
/* short form 8.1.3.4 */
if ((c & (1<<7))>>7 == 0) {
child->length = c; child->length = c;
d_ptr++; d_ptr++;
} else { /* long form 8.1.3.5 */ /* long form 8.1.3.5 */
} else {
numbytes = c & 0x7f; numbytes = c & 0x7f;
if (numbytes > el_max_size) { if (numbytes > el_max_size) {
SCFree(child); SCFree(child);
@ -212,9 +254,9 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
d_ptr++; d_ptr++;
} }
} }
/* fix the length for unknown objects, else
* sequence parsing will fail /* fix the length for unknown objects, else sequence parsing
*/ will fail */
child->length += (d_ptr - save_d_ptr); child->length += (d_ptr - save_d_ptr);
if (child->length > max_size - (d_ptr - buffer)) { if (child->length > max_size - (d_ptr - buffer)) {
@ -224,6 +266,7 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
break; break;
}; };
if (child == NULL) if (child == NULL)
return NULL; return NULL;
@ -231,7 +274,9 @@ static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, uint32_t
return child; return child;
} }
static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint8_t numbytes; uint8_t numbytes;
@ -250,6 +295,7 @@ static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t
d_ptr += 2; d_ptr += 2;
value = 0; value = 0;
/* Here we need to ensure that numbytes is less than 4 /* Here we need to ensure that numbytes is less than 4
so integer affectation is possible. We set the value so integer affectation is possible. We set the value
to 0xffffffff which is by convention the unknown value. to 0xffffffff which is by convention the unknown value.
@ -265,6 +311,7 @@ static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t
a = Asn1GenericNew(); a = Asn1GenericNew();
if (a == NULL) if (a == NULL)
return NULL; return NULL;
a->type = ASN1_INTEGER; a->type = ASN1_INTEGER;
a->length = (d_ptr - buffer) + numbytes; a->length = (d_ptr - buffer) + numbytes;
a->value = value; a->value = value;
@ -274,21 +321,25 @@ static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, uint32_t
SCFree(a); SCFree(a);
return NULL; return NULL;
} }
for (i=0; i<numbytes; i++) { for (i=0; i<numbytes; i++) {
snprintf(a->str + 2*i, 2*(numbytes-i)+1, "%02X", d_ptr[i]); snprintf(a->str + 2*i, 2*(numbytes-i)+1, "%02X", d_ptr[i]);
} }
a->str[2*numbytes]='\0'; a->str[2*numbytes]= '\0';
return a; return a;
} }
static int DecodeAsn1BuildValue(const unsigned char **d_ptr, uint32_t *val, uint8_t numbytes, uint32_t *errcode) static int DecodeAsn1BuildValue(const unsigned char **d_ptr, uint32_t *val,
uint8_t numbytes, uint32_t *errcode)
{ {
int i; int i;
uint32_t value = 0; uint32_t value = 0;
if (numbytes > 4) { if (numbytes > 4) {
if (errcode) if (errcode)
*errcode = ERR_DER_INVALID_SIZE; *errcode = ERR_DER_INVALID_SIZE;
/* too big won't fit: set it to 0xffffffff by convention */ /* too big won't fit: set it to 0xffffffff by convention */
value = 0xffffffff; value = 0xffffffff;
*val = value; *val = value;
@ -299,11 +350,14 @@ static int DecodeAsn1BuildValue(const unsigned char **d_ptr, uint32_t *val, uint
(*d_ptr)++; (*d_ptr)++;
} }
} }
*val = value; *val = value;
return 0; return 0;
} }
static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint8_t numbytes; uint8_t numbytes;
@ -316,9 +370,11 @@ static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t
if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) {
return NULL; return NULL;
} }
a = Asn1GenericNew(); a = Asn1GenericNew();
if (a == NULL) if (a == NULL)
return NULL; return NULL;
a->type = ASN1_BOOLEAN; a->type = ASN1_BOOLEAN;
a->length = (d_ptr - buffer); a->length = (d_ptr - buffer);
a->value = value; a->value = value;
@ -326,7 +382,9 @@ static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, uint32_t
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer,
uint32_t size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint8_t numbytes; uint8_t numbytes;
@ -335,12 +393,15 @@ static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t siz
numbytes = d_ptr[1]; numbytes = d_ptr[1];
d_ptr += 2; d_ptr += 2;
if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) {
return NULL; return NULL;
} }
a = Asn1GenericNew(); a = Asn1GenericNew();
if (a == NULL) if (a == NULL)
return NULL; return NULL;
a->type = ASN1_NULL; a->type = ASN1_NULL;
a->length = (d_ptr - buffer); a->length = (d_ptr - buffer);
a->value = 0; a->value = 0;
@ -348,7 +409,9 @@ static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, uint32_t siz
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t length; uint32_t length;
@ -359,24 +422,29 @@ static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_
/* size */ /* size */
c = d_ptr[0]; c = d_ptr[0];
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */ /* short form 8.1.3.4 */
if ((c & (1<<7))>>7 == 0) {
length = c; length = c;
d_ptr++; d_ptr++;
} else { /* long form 8.1.3.5 */ /* long form 8.1.3.5 */
} else {
numbytes = c & 0x7f; numbytes = c & 0x7f;
d_ptr++; d_ptr++;
if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
return NULL; return NULL;
} }
} }
if (length > max_size) if (length > max_size)
return NULL; return NULL;
a = Asn1GenericNew(); a = Asn1GenericNew();
if (a == NULL) if (a == NULL)
return NULL; return NULL;
a->type = ASN1_BITSTRING; a->type = ASN1_BITSTRING;
a->strlen = length; a->strlen = length;
a->str = SCMalloc(length); a->str = SCMalloc(length);
if (a->str == NULL) { if (a->str == NULL) {
SCFree(a); SCFree(a);
@ -390,7 +458,9 @@ static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, uint32_
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t oid_length, oid_value; uint32_t oid_length, oid_value;
@ -402,23 +472,28 @@ static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_
/* size */ /* size */
c = d_ptr[0]; c = d_ptr[0];
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */ /* short form 8.1.3.4 */
if ((c & (1<<7))>>7 == 0) {
oid_length = c; oid_length = c;
d_ptr++; d_ptr++;
} else { /* long form 8.1.3.5 */ /* long form 8.1.3.5 */
} else {
numbytes = c & 0x7f; numbytes = c & 0x7f;
d_ptr++; d_ptr++;
if (DecodeAsn1BuildValue(&d_ptr, &oid_length, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &oid_length, numbytes, errcode) == -1) {
return NULL; return NULL;
} }
} }
if (oid_length > max_size) if (oid_length > max_size)
return NULL; return NULL;
a = Asn1GenericNew(); a = Asn1GenericNew();
if (a == NULL) if (a == NULL)
return NULL; return NULL;
a->type = ASN1_OID; a->type = ASN1_OID;
a->str = SCMalloc(MAX_OID_LENGTH); a->str = SCMalloc(MAX_OID_LENGTH);
if (a->str == NULL) { if (a->str == NULL) {
SCFree(a); SCFree(a);
@ -429,8 +504,8 @@ static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_
snprintf(a->str, MAX_OID_LENGTH, "%d.%d", (d_ptr[0]/40), (d_ptr[0]%40)); snprintf(a->str, MAX_OID_LENGTH, "%d.%d", (d_ptr[0]/40), (d_ptr[0]%40));
d_ptr++; d_ptr++;
/* sub-identifiers are multi valued, coded and 7 bits, first bit of the 8bits is used /* sub-identifiers are multi-valued, coded and 7 bits, first bit of
to indicate, if a new value is starting */ the 8bits is used to indicate, if a new value is starting */
for (i=1; i<oid_length; ) { for (i=1; i<oid_length; ) {
int s = strlen(a->str); int s = strlen(a->str);
c = d_ptr[0]; c = d_ptr[0];
@ -451,7 +526,9 @@ static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, uint32_t max_
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t length, numbytes; uint32_t length, numbytes;
@ -462,16 +539,19 @@ static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_
/* total sequence length */ /* total sequence length */
c = d_ptr[0]; c = d_ptr[0];
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */ /* short form 8.1.3.4 */
if ((c & (1<<7))>>7 == 0) {
length = c; length = c;
d_ptr++; d_ptr++;
} else { /* long form 8.1.3.5 */ /* long form 8.1.3.5 */
} else {
numbytes = c & 0x7f; numbytes = c & 0x7f;
d_ptr++; d_ptr++;
if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
return NULL; return NULL;
} }
} }
if (length == UINT32_MAX || length > max_size) { if (length == UINT32_MAX || length > max_size) {
if (errcode) if (errcode)
*errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
@ -481,8 +561,10 @@ static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_
a = Asn1GenericNew(); a = Asn1GenericNew();
if (a == NULL) if (a == NULL)
return NULL; return NULL;
a->type = ASN1_IA5STRING; a->type = ASN1_IA5STRING;
a->strlen = length; a->strlen = length;
a->str = SCMalloc(length+1); a->str = SCMalloc(length+1);
if (a->str == NULL) { if (a->str == NULL) {
SCFree(a); SCFree(a);
@ -497,7 +579,9 @@ static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, uint32_
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t length, numbytes; uint32_t length, numbytes;
@ -508,16 +592,19 @@ static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint3
/* total sequence length */ /* total sequence length */
c = d_ptr[0]; c = d_ptr[0];
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */ /* short form 8.1.3.4 */
if ((c & (1<<7))>>7 == 0) {
length = c; length = c;
d_ptr++; d_ptr++;
} else { /* long form 8.1.3.5 */ /* long form 8.1.3.5 */
} else {
numbytes = c & 0x7f; numbytes = c & 0x7f;
d_ptr++; d_ptr++;
if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
return NULL; return NULL;
} }
} }
if (length == UINT32_MAX || length > max_size) { if (length == UINT32_MAX || length > max_size) {
if (errcode) if (errcode)
*errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
@ -527,10 +614,12 @@ static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint3
a = Asn1GenericNew(); a = Asn1GenericNew();
if (a == NULL) if (a == NULL)
return NULL; return NULL;
a->type = ASN1_OCTETSTRING; a->type = ASN1_OCTETSTRING;
a->strlen = length; a->strlen = length;
/* Add one to the octet string for the 0. This will then
* allow us to use the string in printf */ /* add one to the octet string for the 0. This will then allow us to
use the string in printf */
a->str = SCMalloc(length + 1); a->str = SCMalloc(length + 1);
if (a->str == NULL) { if (a->str == NULL) {
SCFree(a); SCFree(a);
@ -545,15 +634,21 @@ static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, uint3
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
Asn1Generic *a = DecodeAsn1DerOctetString(buffer, max_size, depth, errcode); Asn1Generic *a = DecodeAsn1DerOctetString(buffer, max_size, depth, errcode);
if (a != NULL) if (a != NULL)
a->type = ASN1_UTF8STRING; a->type = ASN1_UTF8STRING;
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer,
uint32_t max_size,
uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t length, numbytes; uint32_t length, numbytes;
@ -564,16 +659,19 @@ static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, u
/* total sequence length */ /* total sequence length */
c = d_ptr[0]; c = d_ptr[0];
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */ /* short form 8.1.3.4 */
if ((c & (1<<7))>>7 == 0) {
length = c; length = c;
d_ptr++; d_ptr++;
} else { /* long form 8.1.3.5 */ /* long form 8.1.3.5 */
} else {
numbytes = c & 0x7f; numbytes = c & 0x7f;
d_ptr++; d_ptr++;
if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) {
return NULL; return NULL;
} }
} }
if (length == UINT32_MAX || length > max_size) { if (length == UINT32_MAX || length > max_size) {
if (errcode) if (errcode)
*errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG;
@ -583,8 +681,10 @@ static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, u
a = Asn1GenericNew(); a = Asn1GenericNew();
if (a == NULL) if (a == NULL)
return NULL; return NULL;
a->type = ASN1_PRINTSTRING; a->type = ASN1_PRINTSTRING;
a->strlen = length; a->strlen = length;
a->str = SCMalloc(length+1); a->str = SCMalloc(length+1);
if (a->str == NULL) { if (a->str == NULL) {
SCFree(a); SCFree(a);
@ -599,7 +699,9 @@ static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, u
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t d_length, parsed_bytes, numbytes, el_max_size; uint32_t d_length, parsed_bytes, numbytes, el_max_size;
@ -612,14 +714,17 @@ static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t
node = Asn1GenericNew(); node = Asn1GenericNew();
if (node == NULL) if (node == NULL)
return NULL; return NULL;
node->type = ASN1_SEQUENCE; node->type = ASN1_SEQUENCE;
/* total sequence length */ /* total sequence length */
c = d_ptr[0]; c = d_ptr[0];
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */ /* short form 8.1.3.4 */
if ((c & (1<<7))>>7 == 0) {
d_length = c; d_length = c;
d_ptr++; d_ptr++;
} else { /* long form 8.1.3.5 */ /* long form 8.1.3.5 */
} else {
numbytes = c & 0x7f; numbytes = c & 0x7f;
d_ptr++; d_ptr++;
if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
@ -642,7 +747,8 @@ static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t
while (parsed_bytes < d_length) { while (parsed_bytes < d_length) {
el_max_size = max_size - (d_ptr-buffer); el_max_size = max_size - (d_ptr-buffer);
Asn1Generic *child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index, errcode); Asn1Generic *child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth,
seq_index, errcode);
if (child == NULL) { if (child == NULL) {
if (errcode && *errcode != 0) { if (errcode && *errcode != 0) {
DerFree(node); DerFree(node);
@ -660,13 +766,14 @@ static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, uint32_t
parsed_bytes += child->length; parsed_bytes += child->length;
d_ptr += child->length; d_ptr += child->length;
seq_index++; seq_index++;
} }
return (Asn1Generic *)node; return (Asn1Generic *)node;
} }
static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t d_length, numbytes, el_max_size; uint32_t d_length, numbytes, el_max_size;
@ -685,10 +792,12 @@ static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_
/* total sequence length */ /* total sequence length */
c = d_ptr[0]; c = d_ptr[0];
if ((c & (1<<7))>>7 == 0) { /* short form 8.1.3.4 */ /* short form 8.1.3.4 */
if ((c & (1<<7))>>7 == 0) {
d_length = c; d_length = c;
d_ptr++; d_ptr++;
} else { /* long form 8.1.3.5 */ /* long form 8.1.3.5 */
} else {
numbytes = c & 0x7f; numbytes = c & 0x7f;
d_ptr++; d_ptr++;
if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
@ -696,6 +805,7 @@ static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_
return NULL; return NULL;
} }
} }
node->length = d_length + (d_ptr - buffer); node->length = d_length + (d_ptr - buffer);
if (node->length > max_size || node->length < d_length /* wrap */) { if (node->length > max_size || node->length < d_length /* wrap */) {
@ -708,6 +818,7 @@ static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_
seq_index = 0; seq_index = 0;
el_max_size = max_size - (d_ptr-buffer); el_max_size = max_size - (d_ptr-buffer);
child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index, errcode); child = DecodeAsn1DerGeneric(d_ptr, el_max_size, depth, seq_index, errcode);
if (child == NULL) { if (child == NULL) {
DerFree(node); DerFree(node);
@ -719,7 +830,9 @@ static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, uint32_t max_
return (Asn1Generic *)node; return (Asn1Generic *)node;
} }
static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
Asn1Generic *a; Asn1Generic *a;
@ -730,7 +843,9 @@ static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, uint32_
return a; return a;
} }
static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t max_size, uint8_t depth, uint32_t *errcode) static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer,
uint32_t max_size, uint8_t depth,
uint32_t *errcode)
{ {
Asn1Generic *a; Asn1Generic *a;
@ -741,7 +856,8 @@ static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, uint32_t
return a; return a;
} }
Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size, uint32_t *errcode) Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size,
uint32_t *errcode)
{ {
const unsigned char *d_ptr = buffer; const unsigned char *d_ptr = buffer;
uint32_t d_length, numbytes; uint32_t d_length, numbytes;
@ -751,7 +867,7 @@ Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size, uint32_t *er
if (size < 2) if (size < 2)
return NULL; return NULL;
/* Check that buffer is an ASN.1 structure (basic checks) */ /* check that buffer is an ASN.1 structure (basic checks) */
if (d_ptr[0] != 0x30 && d_ptr[1] != 0x82) /* Sequence */ if (d_ptr[0] != 0x30 && d_ptr[1] != 0x82) /* Sequence */
return NULL; return NULL;
@ -764,6 +880,7 @@ Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size, uint32_t *er
if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) { if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) {
return NULL; return NULL;
} }
if (d_length+(d_ptr-buffer) != size) if (d_length+(d_ptr-buffer) != size)
return NULL; return NULL;

Loading…
Cancel
Save