mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-27 01:26:07 +00:00
ASN1 - Fix memory leaks, clean code and solve crash
This commit is contained in:
parent
0613dc677d
commit
eddf4ee678
@ -233,6 +233,7 @@ typedef void (*PrintfCallback)(const char *str, ...);
|
||||
#define R_NEW_COPY(x,y) x=(void*)malloc(sizeof(y));memcpy(x,y,sizeof(y))
|
||||
#define R_MEM_ALIGN(x) ((void *)(size_t)(((ut64)(size_t)x) & 0xfffffffffffff000LL))
|
||||
#define R_ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
|
||||
#define R_PTR_MOVE(d,s) d=s;s=NULL;
|
||||
|
||||
#define R_PTR_ALIGN(v,t) \
|
||||
((char *)(((size_t)(v) ) \
|
||||
|
@ -88,7 +88,7 @@ R_API RASN1String *r_asn1_stringify_oid (const ut8* buffer, ut32 length);
|
||||
R_API RASN1String *r_asn1_stringify_tag (RASN1Object *object);
|
||||
R_API RASN1String *r_asn1_stringify_object (RASN1Object *object);
|
||||
|
||||
void r_asn1_free_object (RASN1Object **object);
|
||||
void r_asn1_free_object (RASN1Object *object);
|
||||
void r_asn1_free_string (RASN1String *string);
|
||||
|
||||
|
||||
|
@ -304,7 +304,7 @@ static RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length) {
|
||||
RASN1Object *object;
|
||||
ut8 head, length8, byte;
|
||||
ut64 length64;
|
||||
if (!buffer || !length) {
|
||||
if (!buffer || length < 2) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -327,9 +327,9 @@ static RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length) {
|
||||
byte = buffer[2 + i8];
|
||||
length64 <<= 8;
|
||||
length64 |= byte;
|
||||
if (length64 > 0xffffffff) {
|
||||
if (length64 > length) {
|
||||
free (object);
|
||||
// Malformed object - overflow (128 bits instead of 32)
|
||||
// Malformed object - overflow
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -343,10 +343,10 @@ static RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length) {
|
||||
length64 <<= 8;
|
||||
length64 |= byte;
|
||||
from++;
|
||||
} while (from < end && length64 <= 0xffffffff && byte & 0x80);
|
||||
if (length64 > 0xffffffff) {
|
||||
} while (from < end && length64 <= length && byte & 0x80);
|
||||
if (length64 > length) {
|
||||
free (object);
|
||||
// Malformed object - overflow (4GB+ is really too much)
|
||||
// Malformed object - overflow
|
||||
return NULL;
|
||||
}
|
||||
object->sector = from;
|
||||
@ -399,54 +399,51 @@ RASN1Object *r_asn1_create_object (const ut8 *buffer, ut32 length) {
|
||||
RASN1Object *object = asn1_parse_header (buffer, length);
|
||||
if (object && (object->form == FORM_CONSTRUCTED || object->tag == TAG_BITSTRING || object->tag == TAG_OCTETSTRING)) {
|
||||
ut32 i, count;
|
||||
RASN1Object *inner;
|
||||
RASN1Object *inner = NULL;
|
||||
const ut8 *next = object->sector;
|
||||
const ut8 *end = next + object->length;
|
||||
if (end > buffer + length) {
|
||||
free (object);
|
||||
return NULL;
|
||||
}
|
||||
count = r_asn1_count_objects (object->sector, object->length);
|
||||
inner = NULL;
|
||||
object->list.length = count;
|
||||
if (count == 0) {
|
||||
object->list.objects = NULL;
|
||||
} else {
|
||||
object->list.objects = (RASN1Object**) calloc (count, sizeof (RASN1Object*));
|
||||
if (count > 0) {
|
||||
object->list.length = count;
|
||||
object->list.objects = R_NEWS0 (RASN1Object*, count);
|
||||
if (!object->list.objects) {
|
||||
r_asn1_free_object (&object);
|
||||
r_asn1_free_object (object);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; next >= buffer && next < end && i < count; ++i) {
|
||||
object->list.objects[i] = NULL;
|
||||
inner = r_asn1_create_object (next, end - next);
|
||||
if (!inner || next == inner->sector) {
|
||||
r_asn1_free_object (&inner);
|
||||
r_asn1_free_object (inner);
|
||||
break;
|
||||
}
|
||||
next = inner->sector + inner->length;
|
||||
object->list.objects[i] = inner;
|
||||
inner = NULL;
|
||||
R_PTR_MOVE (object->list.objects[i], inner);
|
||||
}
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
void r_asn1_free_object (RASN1Object **object) {
|
||||
void r_asn1_free_object (RASN1Object *object) {
|
||||
ut32 i;
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
if (*object) {
|
||||
//this shall not be freed. it's a pointer into the buffer.
|
||||
(*object)->sector = 0;
|
||||
if ((*object)->list.objects) {
|
||||
for (i = 0; i < (*object)->list.length; ++i) {
|
||||
r_asn1_free_object (&(*object)->list.objects[i]);
|
||||
}
|
||||
R_FREE ((*object)->list.objects);
|
||||
//this shall not be freed. it's a pointer into the buffer.
|
||||
object->sector = 0;
|
||||
if (object->list.objects) {
|
||||
for (i = 0; i < object->list.length; ++i) {
|
||||
r_asn1_free_object (object->list.objects[i]);
|
||||
}
|
||||
(*object)->list.objects = NULL;
|
||||
(*object)->list.length = 0;
|
||||
R_FREE ((*object));
|
||||
R_FREE (object->list.objects);
|
||||
}
|
||||
object->list.objects = NULL;
|
||||
object->list.length = 0;
|
||||
R_FREE (object);
|
||||
}
|
||||
|
||||
void r_asn1_free_string (RASN1String* str) {
|
||||
|
@ -118,8 +118,7 @@ bool r_pkcs7_parse_contentinfo (RPKCS7ContentInfo* ci, RASN1Object *object) {
|
||||
|
||||
ci->contentType = r_asn1_stringify_oid (object->list.objects[0]->sector, object->list.objects[0]->length);
|
||||
if (object->list.length == 2 || !object->list.objects[1]) {
|
||||
ci->content = object->list.objects[1];
|
||||
object->list.objects[1] = NULL;
|
||||
R_PTR_MOVE (ci->content, object->list.objects[1]);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -127,7 +126,7 @@ bool r_pkcs7_parse_contentinfo (RPKCS7ContentInfo* ci, RASN1Object *object) {
|
||||
|
||||
void r_pkcs7_free_contentinfo (RPKCS7ContentInfo* ci) {
|
||||
if (ci) {
|
||||
r_asn1_free_object (&ci->content);
|
||||
r_asn1_free_object (ci->content);
|
||||
r_asn1_free_string (ci->contentType);
|
||||
// Used internally pkcs #7, so it should't free ci.
|
||||
}
|
||||
@ -139,8 +138,7 @@ bool r_pkcs7_parse_issuerandserialnumber (RPKCS7IssuerAndSerialNumber* iasu, RAS
|
||||
}
|
||||
|
||||
r_x509_parse_name (&iasu->issuer, object->list.objects[0]);
|
||||
iasu->serialNumber = object->list.objects[1];
|
||||
object->list.objects[1] = NULL;
|
||||
R_PTR_MOVE (iasu->serialNumber, object->list.objects[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -148,7 +146,7 @@ bool r_pkcs7_parse_issuerandserialnumber (RPKCS7IssuerAndSerialNumber* iasu, RAS
|
||||
void r_pkcs7_free_issuerandserialnumber (RPKCS7IssuerAndSerialNumber* iasu) {
|
||||
if (iasu) {
|
||||
r_x509_free_name (&iasu->issuer);
|
||||
r_asn1_free_object (&iasu->serialNumber);
|
||||
r_asn1_free_object (iasu->serialNumber);
|
||||
// Used internally pkcs #7, so it should't free iasu.
|
||||
}
|
||||
}
|
||||
@ -180,8 +178,7 @@ bool r_pkcs7_parse_signerinfo (RPKCS7SignerInfo* si, RASN1Object *object) {
|
||||
shift++;
|
||||
}
|
||||
if (shift < object->list.length) {
|
||||
si->encryptedDigest = elems[shift];
|
||||
elems[shift] = NULL;
|
||||
R_PTR_MOVE (si->encryptedDigest, object->list.objects[shift]);
|
||||
shift++;
|
||||
}
|
||||
if (shift < object->list.length && elems[shift]->klass == CLASS_CONTEXT && elems[shift]->tag == 1) {
|
||||
@ -196,7 +193,7 @@ void r_pkcs7_free_signerinfo (RPKCS7SignerInfo* si) {
|
||||
r_x509_free_algorithmidentifier (&si->digestAlgorithm);
|
||||
r_pkcs7_free_attributes (&si->authenticatedAttributes);
|
||||
r_x509_free_algorithmidentifier (&si->digestEncryptionAlgorithm);
|
||||
r_asn1_free_object (&si->encryptedDigest);
|
||||
r_asn1_free_object (si->encryptedDigest);
|
||||
r_pkcs7_free_attributes (&si->unauthenticatedAttributes);
|
||||
free (si);
|
||||
}
|
||||
@ -288,13 +285,13 @@ RCMS *r_pkcs7_parse_cms (const ut8 *buffer, ut32 length) {
|
||||
}
|
||||
object = r_asn1_create_object (buffer, length);
|
||||
if (!object || object->list.length != 2 || !object->list.objects[0] || object->list.objects[1]->list.length != 1) {
|
||||
r_asn1_free_object (&object);
|
||||
r_asn1_free_object (object);
|
||||
free (container);
|
||||
return NULL;
|
||||
}
|
||||
container->contentType = r_asn1_stringify_oid (object->list.objects[0]->sector, object->list.objects[0]->length);
|
||||
r_pkcs7_parse_signeddata (&container->signedData, object->list.objects[1]->list.objects[0]);
|
||||
r_asn1_free_object (&object);
|
||||
r_asn1_free_object (object);
|
||||
return container;
|
||||
}
|
||||
|
||||
@ -318,8 +315,7 @@ RPKCS7Attribute* r_pkcs7_parse_attribute (RASN1Object *object) {
|
||||
memset (attribute, 0, sizeof (RPKCS7Attribute));
|
||||
attribute->oid = r_asn1_stringify_oid (object->list.objects[0]->sector, object->list.objects[0]->length);
|
||||
if (object->list.length == 2) {
|
||||
attribute->data = object->list.objects[1];
|
||||
object->list.objects[1] = NULL;
|
||||
R_PTR_MOVE (attribute->data, object->list.objects[1]);
|
||||
}
|
||||
|
||||
return attribute;
|
||||
@ -327,7 +323,7 @@ RPKCS7Attribute* r_pkcs7_parse_attribute (RASN1Object *object) {
|
||||
|
||||
void r_pkcs7_free_attribute (RPKCS7Attribute* attribute) {
|
||||
if (attribute) {
|
||||
r_asn1_free_object (&attribute->data);
|
||||
r_asn1_free_object (attribute->data);
|
||||
r_asn1_free_string (attribute->oid);
|
||||
free (attribute);
|
||||
}
|
||||
@ -341,13 +337,11 @@ bool r_pkcs7_parse_attributes (RPKCS7Attributes* attributes, RASN1Object *object
|
||||
|
||||
attributes->length = object->list.length;
|
||||
if (attributes->length > 0) {
|
||||
attributes->elements = (RPKCS7Attribute**) calloc (attributes->length, sizeof (RPKCS7Attribute*));
|
||||
attributes->elements = R_NEWS0(RPKCS7Attribute*, attributes->length);
|
||||
if (!attributes->elements) {
|
||||
attributes->length = 0;
|
||||
return false;
|
||||
}
|
||||
memset (attributes->elements, 0, attributes->length * sizeof (RPKCS7Attribute*));
|
||||
|
||||
for (i = 0; i < object->list.length; ++i) {
|
||||
attributes->elements[i] = r_pkcs7_parse_attribute (object->list.objects[i]);
|
||||
}
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include "r_x509_internal.h"
|
||||
|
||||
#define MOVE_PTR(dst, src) { ((dst) = (src)); (src) = NULL; }
|
||||
|
||||
bool r_x509_parse_validity (RX509Validity *validity, RASN1Object *object) {
|
||||
RASN1Object *o;
|
||||
if (!validity || !object || object->list.length != 2) {
|
||||
@ -57,7 +55,7 @@ bool r_x509_parse_subjectpublickeyinfo (RX509SubjectPublicKeyInfo * spki, RASN1O
|
||||
r_x509_parse_algorithmidentifier (&spki->algorithm, object->list.objects[0]);
|
||||
if (object->list.objects[1]) {
|
||||
o = object->list.objects[1];
|
||||
MOVE_PTR (spki->subjectPublicKey, object->list.objects[1]);
|
||||
R_PTR_MOVE (spki->subjectPublicKey, object->list.objects[1]);
|
||||
// spki->subjectPublicKey = object->list.objects[1];
|
||||
// object->list.objects[1] = NULL;
|
||||
// if (o->length > 32) {
|
||||
@ -68,7 +66,7 @@ bool r_x509_parse_subjectpublickeyinfo (RX509SubjectPublicKeyInfo * spki, RASN1O
|
||||
if (o->list.length == 1 && o->list.objects[0]->list.length == 2) {
|
||||
o = o->list.objects[0];
|
||||
if (o->list.objects[0]) {
|
||||
MOVE_PTR (spki->subjectPublicKeyExponent, o->list.objects[0]);
|
||||
R_PTR_MOVE (spki->subjectPublicKeyExponent, o->list.objects[0]);
|
||||
// o->list.objects[0] = NULL;
|
||||
// if (o->list.objects[0]->length > 32) {
|
||||
// spki->subjectPublicKeyExponent = asn1_stringify_bytes (o->list.objects[0]->sector, o->list.objects[0]->length);
|
||||
@ -77,7 +75,7 @@ bool r_x509_parse_subjectpublickeyinfo (RX509SubjectPublicKeyInfo * spki, RASN1O
|
||||
// }
|
||||
}
|
||||
if (o->list.objects[1]) {
|
||||
MOVE_PTR (spki->subjectPublicKeyModule, o->list.objects[1]);
|
||||
R_PTR_MOVE (spki->subjectPublicKeyModule, o->list.objects[1]);
|
||||
// spki->subjectPublicKeyModule = o->list.objects[1];
|
||||
// o->list.objects[1] = NULL;
|
||||
// spki->subjectPublicKeyModule = asn1_stringify_integer (o->list.objects[1]->sector, o->list.objects[1]->length);
|
||||
@ -120,7 +118,7 @@ bool r_x509_parse_name (RX509Name *name, RASN1Object * object) {
|
||||
o->list.objects[0]->tag == TAG_OID) {
|
||||
name->oids[i] = r_asn1_stringify_oid (o->list.objects[0]->sector, o->list.objects[0]->length);
|
||||
}
|
||||
if (o->list.objects[0]->klass == CLASS_UNIVERSAL) {
|
||||
if (o->list.objects[1]->klass == CLASS_UNIVERSAL) {
|
||||
name->names[i] = r_asn1_stringify_string (o->list.objects[1]->sector, o->list.objects[1]->length);
|
||||
}
|
||||
}
|
||||
@ -211,13 +209,13 @@ bool r_x509_parse_tbscertificate (RX509TBSCertificate *tbsc, RASN1Object * objec
|
||||
if (elems[i]->klass != CLASS_CONTEXT) continue;
|
||||
|
||||
if (elems[i]->tag == 1) {
|
||||
MOVE_PTR (tbsc->issuerUniqueID, object->list.objects[i]);
|
||||
R_PTR_MOVE (tbsc->issuerUniqueID, object->list.objects[i]);
|
||||
// tbsc->issuerUniqueID = elems[i];
|
||||
// elems[i] = NULL;
|
||||
}
|
||||
|
||||
if (elems[i]->tag == 2) {
|
||||
MOVE_PTR (tbsc->subjectUniqueID, object->list.objects[i]);
|
||||
R_PTR_MOVE (tbsc->subjectUniqueID, object->list.objects[i]);
|
||||
// tbsc->subjectUniqueID = elems[i];
|
||||
// elems[i] = NULL;
|
||||
}
|
||||
@ -245,28 +243,28 @@ RX509Certificate * r_x509_parse_certificate (RASN1Object *object) {
|
||||
if (object->klass != CLASS_UNIVERSAL || object->form != FORM_CONSTRUCTED || object->list.length != 3) {
|
||||
// Malformed certificate
|
||||
// It needs to have tbsCertificate, algorithmIdentifier and a signature
|
||||
r_asn1_free_object (&object);
|
||||
r_asn1_free_object (object);
|
||||
free (certificate);
|
||||
return NULL;
|
||||
}
|
||||
tmp = object->list.objects[2];
|
||||
if (tmp->klass != CLASS_UNIVERSAL || tmp->form != FORM_PRIMITIVE || tmp->tag != TAG_BITSTRING) {
|
||||
r_asn1_free_object (&object);
|
||||
r_asn1_free_object (object);
|
||||
free (certificate);
|
||||
return NULL;
|
||||
}
|
||||
MOVE_PTR (certificate->signature, object->list.objects[2]);
|
||||
R_PTR_MOVE (certificate->signature, object->list.objects[2]);
|
||||
// certificate->signature = object->list.objects[2];
|
||||
// object->list.objects[2] = NULL;
|
||||
|
||||
r_x509_parse_tbscertificate (&certificate->tbsCertificate, object->list.objects[0]);
|
||||
|
||||
if (!r_x509_parse_algorithmidentifier (&certificate->algorithmIdentifier, object->list.objects[1])) {
|
||||
r_asn1_free_object (&object);
|
||||
r_asn1_free_object (object);
|
||||
free (certificate);
|
||||
return NULL;
|
||||
}
|
||||
r_asn1_free_object (&object);
|
||||
r_asn1_free_object (object);
|
||||
return certificate;
|
||||
}
|
||||
|
||||
@ -365,7 +363,7 @@ void r_x509_free_name (RX509Name * name) {
|
||||
void r_x509_free_extension (RX509Extension * ex) {
|
||||
if (ex) {
|
||||
r_asn1_free_string (ex->extnID);
|
||||
r_asn1_free_object (&ex->extnValue);
|
||||
r_asn1_free_object (ex->extnValue);
|
||||
//this is allocated dinamically so, i'll free
|
||||
free (ex);
|
||||
}
|
||||
@ -388,9 +386,9 @@ void r_x509_free_extensions (RX509Extensions * ex) {
|
||||
void r_x509_free_subjectpublickeyinfo (RX509SubjectPublicKeyInfo * spki) {
|
||||
if (spki) {
|
||||
r_x509_free_algorithmidentifier (&spki->algorithm);
|
||||
r_asn1_free_object (&spki->subjectPublicKey);
|
||||
r_asn1_free_object (&spki->subjectPublicKeyExponent);
|
||||
r_asn1_free_object (&spki->subjectPublicKeyModule);
|
||||
r_asn1_free_object (spki->subjectPublicKey);
|
||||
r_asn1_free_object (spki->subjectPublicKeyExponent);
|
||||
r_asn1_free_object (spki->subjectPublicKeyModule);
|
||||
// No need to free spki, since it's a static variable.
|
||||
}
|
||||
}
|
||||
@ -404,8 +402,8 @@ void r_x509_free_tbscertificate (RX509TBSCertificate * tbsc) {
|
||||
r_x509_free_validity (&tbsc->validity);
|
||||
r_x509_free_name (&tbsc->subject);
|
||||
r_x509_free_subjectpublickeyinfo (&tbsc->subjectPublicKeyInfo);
|
||||
r_asn1_free_object (&tbsc->subjectUniqueID);
|
||||
r_asn1_free_object (&tbsc->issuerUniqueID);
|
||||
r_asn1_free_object (tbsc->subjectUniqueID);
|
||||
r_asn1_free_object (tbsc->issuerUniqueID);
|
||||
r_x509_free_extensions (&tbsc->extensions);
|
||||
//no need to free tbsc, since this functions is used internally
|
||||
}
|
||||
@ -413,7 +411,7 @@ void r_x509_free_tbscertificate (RX509TBSCertificate * tbsc) {
|
||||
|
||||
void r_x509_free_certificate (RX509Certificate * certificate) {
|
||||
if (certificate) {
|
||||
r_asn1_free_object (&certificate->signature);
|
||||
r_asn1_free_object (certificate->signature);
|
||||
r_x509_free_algorithmidentifier (&certificate->algorithmIdentifier);
|
||||
r_x509_free_tbscertificate (&certificate->tbsCertificate);
|
||||
free (certificate);
|
||||
@ -422,7 +420,7 @@ void r_x509_free_certificate (RX509Certificate * certificate) {
|
||||
|
||||
void r_x509_free_crlentry (RX509CRLEntry *entry) {
|
||||
if (entry) {
|
||||
r_asn1_free_object (&entry->userCertificate);
|
||||
r_asn1_free_object (entry->userCertificate);
|
||||
r_asn1_free_string (entry->revocationDate);
|
||||
free (entry);
|
||||
}
|
||||
@ -617,6 +615,7 @@ char* r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, char* buffer, ut32
|
||||
iid = r_asn1_stringify_integer (tbsc->issuerUniqueID->sector, tbsc->issuerUniqueID->length);
|
||||
if (iid) {
|
||||
if (length <= p) {
|
||||
r_asn1_free_string (iid);
|
||||
free (pad2);
|
||||
return NULL;
|
||||
}
|
||||
@ -626,11 +625,13 @@ char* r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, char* buffer, ut32
|
||||
free (pad2);
|
||||
return NULL;
|
||||
}
|
||||
r_asn1_free_string (iid);
|
||||
}
|
||||
if (tbsc->subjectUniqueID) {
|
||||
sid = r_asn1_stringify_integer (tbsc->subjectUniqueID->sector, tbsc->subjectUniqueID->length);
|
||||
if (sid) {
|
||||
if (length <= p) {
|
||||
r_asn1_free_string (sid);
|
||||
free (pad2);
|
||||
return NULL;
|
||||
}
|
||||
@ -640,6 +641,7 @@ char* r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, char* buffer, ut32
|
||||
free (pad2);
|
||||
return NULL;
|
||||
}
|
||||
r_asn1_free_string (sid);
|
||||
}
|
||||
if (r < 0 || length <= p) {
|
||||
free (pad2);
|
||||
@ -652,8 +654,6 @@ char* r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, char* buffer, ut32
|
||||
return NULL;
|
||||
}
|
||||
free (pad2);
|
||||
r_asn1_free_string (sid);
|
||||
r_asn1_free_string (iid);
|
||||
return buffer + p;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user