ASN.1 BER support, with pF[apx] (#11517)

This commit is contained in:
Giovanni 2018-09-14 01:44:04 +02:00 committed by radare
parent d389cd4468
commit 899719389f
12 changed files with 382 additions and 417 deletions

View File

@ -113,7 +113,8 @@ static char *signature (RBinFile *bf, bool json) {
r_json_var_free (json);
return c;
}
return r_pkcs7_cms_dump (bin->cms);
r_pkcs7_cms_dump (bin->cms);
return NULL;
}
static RList *fields(RBinFile *bf) {

View File

@ -902,16 +902,25 @@ static void cmd_print_fromage(RCore *core, const char *input, const ut8* data, i
case '?': // "pF?"
r_core_cmd_help (core, help_msg_pF);
break;
case 'o': // "pFo" asn1 oid
case 'a':
{
RASN1Object *asn1 = r_asn1_create_object (data, size);
if (asn1) {
RASN1String *str1 = r_asn1_stringify_oid (data, size);
if (str1) {
r_cons_printf ("%s\n", str1->string);
r_asn1_free_string (str1);
}
r_asn1_print_object (asn1, 0);
r_asn1_free_object (asn1);
} else {
eprintf ("Malformed object: did you supply enough data?\ntry to change the block size (see b?)\n");
}
}
break;
case 'x': // "pFx" x509
{
RX509Certificate* x509 = r_x509_parse_certificate (r_asn1_create_object (data, size));
if (x509) {
r_x509_certificate_dump (x509, NULL);
r_x509_free_certificate (x509);
} else {
eprintf ("Malformed object: did you supply enough data?\ntry to change the block size (see b?)\n");
}
}
break;
@ -919,12 +928,10 @@ static void cmd_print_fromage(RCore *core, const char *input, const ut8* data, i
{
RCMS *cms = r_pkcs7_parse_cms (data, size);
if (cms) {
char* foo = r_pkcs7_cms_dump (cms);
if (foo) {
r_cons_printf ("%s\n", foo);
free (foo);
}
r_pkcs7_cms_dump (cms);
r_pkcs7_free_cms (cms);
} else {
eprintf ("Malformed object: did you supply enough data?\ntry to change the block size (see b?)\n");
}
}
break;

View File

@ -78,6 +78,7 @@ typedef struct r_asn1_object_t {
ut8 klass; /* class type */
ut8 form; /* defines if contains data or objects */
ut8 tag; /* tag type */
ut8 undefined; /* set to != 0 if len is undefined */
const ut8 *sector; /* Sector containg data */
ut32 length; /* Sector Length */
ASN1List list; /* List of objects contained in the sector */
@ -93,10 +94,9 @@ R_API RASN1String *r_asn1_stringify_string (const ut8 *buffer, ut32 length);
R_API RASN1String *r_asn1_stringify_bytes (const ut8 *buffer, ut32 length);
R_API RASN1String *r_asn1_stringify_boolean (const ut8 *buffer, ut32 length);
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);
R_API void r_asn1_free_object (RASN1Object *object);
R_API void r_asn1_print_object (RASN1Object *object, ut32 depth);
R_API void r_asn1_free_string (RASN1String *string);
R_API void r_asn1_free_binary (RASN1Binary *string);

View File

@ -71,7 +71,7 @@ typedef struct r_pkcs7_container_t {
R_API RCMS *r_pkcs7_parse_cms(const ut8 *buffer, ut32 length);
R_API void r_pkcs7_free_cms(RCMS* container);
R_API char* r_pkcs7_cms_dump(RCMS* container);
R_API void r_pkcs7_cms_dump(RCMS* container);
R_API RJSVar *r_pkcs7_cms_json(RCMS* container);
#ifdef __cplusplus

View File

@ -68,6 +68,7 @@ R_API char *r_str_new(const char *str);
R_API int r_snprintf (char *string, int len, const char *fmt, ...);
R_API bool r_str_is_ascii(const char *str);
R_API int r_str_is_printable(const char *str);
R_API int r_str_is_printable_limited(const char *str, int size);
R_API bool r_str_is_printable_incl_newlines(const char *str);
R_API char *r_str_appendlen(char *ptr, const char *string, int slen);
R_API char *r_str_newf(const char *fmt, ...);

View File

@ -106,13 +106,13 @@ typedef struct r_x509_certificaterevocationlist {
R_API RX509CertificateRevocationList* r_x509_parse_crl(RASN1Object *object);
R_API void r_x509_free_crl(RX509CertificateRevocationList *crl);
R_API char* r_x509_crl_dump(RX509CertificateRevocationList *crl, char* buffer, ut32 length, const char* pad);
R_API void r_x509_crl_dump(RX509CertificateRevocationList *crl, const char* pad);
R_API RJSVar *r_x509_crl_json(RX509CertificateRevocationList *crl);
R_API RX509Certificate *r_x509_parse_certificate(RASN1Object *object);
R_API RX509Certificate *r_x509_parse_certificate2(const ut8 *buffer, ut32 length);
R_API void r_x509_free_certificate(RX509Certificate* certificate);
R_API char* r_x509_certificate_dump(RX509Certificate* certificate, char* buffer, ut32 length, const char* pad);
R_API void r_x509_certificate_dump(RX509Certificate* certificate, const char* pad);
R_API RJSVar* r_x509_certificate_json(RX509Certificate *certificate);

View File

@ -1,11 +1,31 @@
/* radare2 - LGPL - Copyright 2017-2018 - wargio */
#include <r_util.h>
#include <r_cons.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length) {
static ut32 asn1_ber_indefinite (const ut8 *buffer, ut32 length) {
if (!length || !buffer) {
return 0;
}
const ut8* next = buffer + 2;
const ut8* end = buffer + (length - 3);
while (next < end) {
if (!next[0] && !next[1]) {
break;
}
if (next[0] == 0x80 && (next[-1] & ASN1_FORM) == FORM_CONSTRUCTED) {
next --;
next += asn1_ber_indefinite (next, end - next);
}
next ++;
}
return (next - buffer) + 2;
}
RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length) {
ut8 head, length8, byte;
ut64 length64;
if (!buffer || length < 2) {
@ -20,10 +40,12 @@ static RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length) {
object->klass = head & ASN1_CLASS;
object->form = head & ASN1_FORM;
object->tag = head & ASN1_TAG;
object->undefined = 0;
length8 = buffer[1];
if (length8 & ASN1_LENLONG) {
length64 = 0;
length8 &= ASN1_LENSHORT;
object->sector = buffer + 2;
if (length8 && length8 < length - 2) {
ut8 i8;
// can overflow.
@ -35,27 +57,16 @@ static RASN1Object *asn1_parse_header (const ut8 *buffer, ut32 length) {
goto out_error;
}
}
object->sector = buffer + 2 + length8;
object->sector += length8;
} else {
//indefinite
const ut8 *from = buffer + 2;
const ut8 *end = from + (length - 2);
do {
byte = *from;
length64 <<= 8;
length64 |= byte;
from++;
} while (from < end && length64 <= length && byte & 0x80);
if (length64 > length) {
goto out_error;
}
object->sector = from;
length64 = asn1_ber_indefinite (object->sector, length - 2);
}
object->length = (ut32) length64;
} else {
object->length = (ut32) length8;
object->sector = buffer + 2;
}
if (object->tag == TAG_BITSTRING && object->sector[0] == 0) {
if (object->length > 0){
object->sector++; //real sector starts +1
@ -149,6 +160,179 @@ R_API RASN1Binary *r_asn1_create_binary (const ut8 *buffer, ut32 length) {
return bin;
}
R_API void r_asn1_print_hex (RASN1Object *object, char* buffer, ut32 size) {
ut32 i;
if (!object || !object->sector) {
return;
}
char* p = buffer;
char* end = buffer + size;
for (i = 0; i < object->length && p < end; ++i) {
snprintf (p, end - p, "%02x", object->sector[i]);
p += 2;
}
if (p >= end) {
p -= 4;
snprintf (p, end - p, "...");
}
}
R_API void r_asn1_print_object (RASN1Object *object, ut32 depth) {
ut32 i;
if (!object) {
return;
}
//this shall not be freed. it's a pointer into the buffer.
RASN1String* asn1str = NULL;
static char temp_name[256] = {0};
const char* name = "";
const char* string = "";
memset (temp_name, 0, sizeof (temp_name));
switch (object->klass) {
case CLASS_UNIVERSAL: // universal
switch (object->tag) {
case TAG_EOC:
name = "EOC";
break;
case TAG_BOOLEAN:
name = "BOOLEAN";
if (object->sector) {
string = (object->sector[0] != 0) ? "true" : "false";
}
break;
case TAG_INTEGER:
name = "INTEGER";
r_asn1_print_hex (object, temp_name, 20);
string = temp_name;
break;
case TAG_BITSTRING:
name = "BIT_STRING";
r_asn1_print_hex (object, temp_name, 20);
string = temp_name;
break;
case TAG_OCTETSTRING:
name = "OCTET_STRING";
if (r_str_is_printable_limited (object->sector, object->length)) {
asn1str = r_asn1_stringify_string (object->sector, object->length);
} else if (!object->list.objects) {
r_asn1_print_hex (object, temp_name, 20);
string = temp_name;
}
break;
case TAG_NULL:
name = "NULL";
break;
case TAG_OID:
name = "OBJECT_IDENTIFIER";
asn1str = r_asn1_stringify_oid (object->sector, object->length);
break;
case TAG_OBJDESCRIPTOR:
name = "ObjectDescriptor";
break;
case TAG_EXTERNAL:
name = "EXTERNAL";
break;
case TAG_REAL:
name = "REAL";
r_asn1_print_hex (object, temp_name, 20);
string = temp_name;
break;
case TAG_ENUMERATED:
name = "ENUMERATED";
break;
case TAG_EMBEDDED_PDV:
name = "EMBEDDED_PDV";
break;
case TAG_UTF8STRING:
name = "UTF8String";
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_SEQUENCE:
name = "SEQUENCE";
break;
case TAG_SET:
name = "SET";
break;
case TAG_NUMERICSTRING:
name = "NumericString";
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_PRINTABLESTRING:
name = "PrintableString"; // ASCII subset
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_T61STRING:
name = "TeletexString"; // aka T61String
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_VIDEOTEXSTRING:
name = "VideotexString";
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_IA5STRING:
name = "IA5String"; // ASCII
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_UTCTIME:
name = "UTCTime";
asn1str = r_asn1_stringify_utctime (object->sector, object->length);
break;
case TAG_GENERALIZEDTIME:
name = "GeneralizedTime";
asn1str = r_asn1_stringify_time (object->sector, object->length);
break;
case TAG_GRAPHICSTRING:
name = "GraphicString";
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_VISIBLESTRING:
name = "VisibleString"; // ASCII subset
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_GENERALSTRING:
name = "GeneralString";
break;
case TAG_UNIVERSALSTRING:
name = "UniversalString";
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
case TAG_BMPSTRING:
name = "BMPString";
asn1str = r_asn1_stringify_string (object->sector, object->length);
break;
default:
snprintf (temp_name, sizeof (temp_name), "Universal_%u", object->tag);
name = temp_name;
break;
}
break;
case CLASS_APPLICATION:
snprintf (temp_name, sizeof (temp_name), "Application_%u", object->tag);
name = temp_name;
break;
case CLASS_CONTEXT:
snprintf (temp_name, sizeof (temp_name), "Context [%u]", object->tag); // Context
name = temp_name;
break;
case CLASS_PRIVATE:
snprintf (temp_name, sizeof (temp_name), "Private_%u", object->tag);
name = temp_name;
break;
}
if (asn1str) {
string = asn1str->string;
}
r_cons_printf ("%4u:%2d: %s %-20s: %s\n", object->length, depth, object->form ? "cons" : "prim", name, string);
r_asn1_free_string (asn1str);
if (object->list.objects) {
for (i = 0; i < object->list.length; ++i) {
r_asn1_print_object (object->list.objects[i], depth + 1);
}
}
}
R_API void r_asn1_free_object (RASN1Object *object) {
ut32 i;
if (!object) {

View File

@ -590,14 +590,14 @@ struct r_oid_list_t {
{"1.2.840.113549.1.5.13", "pkcs5PBES2"},
{"1.2.840.113549.1.5.14", "pkcs5PBMAC1"},
{"1.2.840.113549.1.7", "pkcs-7"},
{"1.2.840.113549.1.7.1", "data"},
{"1.2.840.113549.1.7.2", "signedData"},
{"1.2.840.113549.1.7.3", "envelopedData"},
{"1.2.840.113549.1.7.4", "signedAndEnvelopedData"},
{"1.2.840.113549.1.7.5", "digestedData"},
{"1.2.840.113549.1.7.6", "encryptedData"},
{"1.2.840.113549.1.7.7", "dataWithAttributes"},
{"1.2.840.113549.1.7.8", "encryptedPrivateKeyInfo"},
{"1.2.840.113549.1.7.1", "pkcs-7-data"},
{"1.2.840.113549.1.7.2", "pkcs-7-signedData"},
{"1.2.840.113549.1.7.3", "pkcs-7-envelopedData"},
{"1.2.840.113549.1.7.4", "pkcs-7-signedAndEnvelopedData"},
{"1.2.840.113549.1.7.5", "pkcs-7-digestedData"},
{"1.2.840.113549.1.7.6", "pkcs-7-encryptedData"},
{"1.2.840.113549.1.7.7", "pkcs-7-dataWithAttributes"},
{"1.2.840.113549.1.7.8", "pkcs-7-encryptedPrivateKeyInfo"},
{"1.2.840.113549.1.9", "pkcs-9"},
{"1.2.840.113549.1.9.1", "emailAddress"},
{"1.2.840.113549.1.9.2", "unstructuredName"},

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <r_util.h>
#include <r_cons.h>
#include "./x509.h"
extern RJSVar *r_x509_name_json (RX509Name* name);
@ -270,16 +271,18 @@ static bool r_pkcs7_parse_signeddata (RPKCS7SignedData *sd, RASN1Object *object)
memset (sd, 0, sizeof (RPKCS7SignedData));
RASN1Object **elems = object->list.objects;
//Following RFC
sd->version = (ut32) elems[0]->sector[0];
sd->version = (ut32) elems[0]->sector[0];
r_pkcs7_parse_digestalgorithmidentifier (&sd->digestAlgorithms, elems[1]);
r_pkcs7_parse_contentinfo (&sd->contentInfo, elems[2]);
//Optional
if (shift < object->list.length && elems[shift] && elems[shift]->klass == CLASS_CONTEXT && elems[shift]->tag == 0) {
if (object->list.length > 3 && shift < object->list.length && elems[shift] &&
elems[shift]->klass == CLASS_CONTEXT && elems[shift]->tag == 0) {
r_pkcs7_parse_extendedcertificatesandcertificates (&sd->certificates, elems[shift]);
shift++;
}
//Optional
if (shift < object->list.length && elems[shift] && elems[shift]->klass == CLASS_CONTEXT && elems[shift]->tag == 1) {
if (object->list.length > 3 && shift < object->list.length && elems[shift] &&
elems[shift]->klass == CLASS_CONTEXT && elems[shift]->tag == 1) {
r_pkcs7_parse_certificaterevocationlists (&sd->crls, elems[shift]);
shift++;
}
@ -311,9 +314,9 @@ R_API RCMS *r_pkcs7_parse_cms (const ut8 *buffer, ut32 length) {
return NULL;
}
object = r_asn1_create_object (buffer, length);
if (!object || object->list.length != 2 || !object->list.objects ||
if (!object || object->list.length < 2 || !object->list.objects ||
!object->list.objects[0] || !object->list.objects[1] ||
object->list.objects[1]->list.length != 1) {
object->list.objects[1]->list.length < 1) {
r_asn1_free_object (object);
free (container);
return NULL;
@ -377,252 +380,127 @@ static bool r_pkcs7_parse_attributes (RPKCS7Attributes* attributes, RASN1Object
return true;
}
char* r_pkcs7_signerinfos_dump (RX509CertificateRevocationList *crl, char* buffer, ut32 length, const char* pad) {
void r_pkcs7_signerinfos_dump (RX509CertificateRevocationList *crl, const char* pad) {
RASN1String *algo = NULL, *last = NULL, *next = NULL;
ut32 i, p;
int r;
char *tmp, *pad2, *pad3;
if (!crl || !buffer || !length) {
return NULL;
ut32 i;
char *pad2, *pad3;
if (!crl) {
return;
}
if (!pad) {
pad = "";
}
pad3 = r_str_newf ("%s ", pad);
if (!pad3) {
return NULL;
}
if (!pad3) return;
pad2 = pad3 + 2;
algo = crl->signature.algorithm;
last = crl->lastUpdate;
next = crl->nextUpdate;
r = snprintf (buffer, length, "%sCRL:\n%sSignature:\n%s%s\n%sIssuer\n",
pad, pad2, pad3, algo ? algo->string : "", pad2);
p = (ut32) r;
if (r < 0 || !(tmp = r_x509_name_dump (&crl->issuer, buffer + p, length - p, pad3))) {
free (pad3);
return NULL;
}
p = tmp - buffer;
if (length <= p) {
free (pad3);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sLast Update: %s\n%sNext Update: %s\n%sRevoked Certificates:\n",
r_cons_printf ("%sCRL:\n%sSignature:\n%s%s\n%sIssuer\n", pad, pad2, pad3, algo ? algo->string : "", pad2);
r_x509_name_dump (&crl->issuer, pad3);
r_cons_printf ("%sLast Update: %s\n%sNext Update: %s\n%sRevoked Certificates:\n",
pad2, last ? last->string : "Missing",
pad2, next ? next->string : "Missing", pad2);
p += (ut32) r;
if (r < 0) {
free (pad3);
return NULL;
}
for (i = 0; i < crl->length; ++i) {
if (length <= p || !(tmp = r_x509_crlentry_dump (crl->revokedCertificates[i], buffer + p, length - p, pad3))) {
free (pad3);
return NULL;
}
p = tmp - buffer;
r_x509_crlentry_dump (crl->revokedCertificates[i], pad3);
}
free (pad3);
return buffer + p;
}
static char* r_x509_signedinfo_dump (RPKCS7SignerInfo *si, char* buffer, ut32 length, const char* pad) {
static void r_x509_signedinfo_dump (RPKCS7SignerInfo *si, const char* pad) {
RASN1String *s = NULL;
RASN1Binary *o = NULL;
ut32 i, p;
int r;
char *tmp, *pad2, *pad3;
if (!si || !buffer || !length) {
return NULL;
ut32 i;
char *pad2, *pad3;
if (!si) {
return;
}
if (!pad) {
pad = "";
}
pad3 = r_str_newf ("%s ", pad);
if (!pad3) {
return NULL;
return;
}
pad2 = pad3 + 2;
r = snprintf (buffer, length, "%sSignerInfo:\n%sVersion: v%u\n%sIssuer\n", pad, pad2, si->version + 1, pad2);
p = (ut32) r;
if (r < 0) {
free (pad3);
return NULL;
}
if (length <= p || !(tmp = r_x509_name_dump (&si->issuerAndSerialNumber.issuer, buffer + p, length - p, pad3))) {
free (pad3);
return NULL;
}
p = tmp - buffer;
r_cons_printf ("%sSignerInfo:\n%sVersion: v%u\n%sIssuer\n", pad, pad2, si->version + 1, pad2);
r_x509_name_dump (&si->issuerAndSerialNumber.issuer, pad3);
if ((o = si->issuerAndSerialNumber.serialNumber)) {
s = r_asn1_stringify_integer (o->binary, o->length);
} else {
s = NULL;
}
if (length <= p) {
free (pad3);
r_asn1_free_string (s);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sSerial Number:\n%s%s\n", pad2, pad3, s ? s->string : "Missing");
p += (ut32) r;
r_cons_printf ("%sSerial Number:\n%s%s\n", pad2, pad3, s ? s->string : "Missing");
r_asn1_free_string (s);
if (r < 0 || length <= p) {
free (pad3);
return NULL;
}
s = si->digestAlgorithm.algorithm;
r = snprintf (buffer + p, length - p, "%sDigest Algorithm:\n%s%s\n%sAuthenticated Attributes:\n",
r_cons_printf ("%sDigest Algorithm:\n%s%s\n%sAuthenticated Attributes:\n",
pad2, pad3, s ? s->string : "Missing", pad2);
p += (ut32) r;
if (r < 0 || length <= p) {
free (pad3);
return NULL;
}
for (i = 0; i < si->authenticatedAttributes.length; ++i) {
RPKCS7Attribute* attr = si->authenticatedAttributes.elements[i];
if (!attr) {
continue;
}
r = snprintf (buffer + p, length - p, "%s%s: %u bytes\n",
pad3, attr->oid ? attr->oid->string : "Missing", attr->data ? attr->data->length : 0);
p += (ut32) r;
if (r < 0 || length <= p) {
free (pad3);
return NULL;
}
if (!attr) continue;
r_cons_printf ("%s%s: %u bytes\n", pad3, attr->oid ? attr->oid->string : "Missing",
attr->data ? attr->data->length : 0);
}
s = si->digestEncryptionAlgorithm.algorithm;
if (length <= p) {
free (pad3);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sDigest Encryption Algorithm\n%s%s\n",
pad2, pad3, s ? s->string : "Missing");
p += (ut32) r;
if (r < 0 || length <= p) {
free (pad3);
return NULL;
}
r_cons_printf ("%sDigest Encryption Algorithm\n%s%s\n", pad2, pad3, s ? s->string : "Missing");
// if ((o = si->encryptedDigest)) s = r_asn1_stringify_bytes (o->binary, o->length);
// else s = NULL;
// r = snprintf (buffer + p, length - p, "%sEncrypted Digest: %u bytes\n%s\n", pad2, o ? o->length : 0, s ? s->string : "Missing");
// p += (ut32) r;
// r_cons_printf ("%sEncrypted Digest: %u bytes\n%s\n", pad2, o ? o->length : 0, s ? s->string : "Missing");
// r_asn1_free_string (s);
r = snprintf (buffer + p, length - p, "%sEncrypted Digest: %u bytes\n", pad2, o ? o->length : 0);
if (r < 0 || length <= p) {
free (pad3);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sUnauthenticated Attributes:\n", pad2);
p += (ut32) r;
if (r < 0 || length <= p) {
free (pad3);
return NULL;
}
r_cons_printf ("%sEncrypted Digest: %u bytes\n", pad2, o ? o->length : 0);
r_cons_printf ("%sUnauthenticated Attributes:\n", pad2);
for (i = 0; i < si->unauthenticatedAttributes.length; ++i) {
RPKCS7Attribute* attr = si->unauthenticatedAttributes.elements[i];
if (!attr) {
continue;
}
o = attr->data;
r = snprintf (buffer + p, length - p, "%s%s: %u bytes\n",
pad3, attr->oid ? attr->oid->string : "Missing", o ? o->length : 0);
p += (ut32) r;
if (r < 0 || length <= p) {
free (pad3);
return NULL;
}
r_cons_printf ("%s%s: %u bytes\n", pad3, attr->oid ? attr->oid->string : "Missing",
o ? o->length : 0);
}
free (pad3);
return buffer + p;
}
char *r_pkcs7_cms_dump (RCMS* container) {
void r_pkcs7_cms_dump (RCMS* container) {
RPKCS7SignedData *sd;
ut32 i, length, p = 0;
int r;
char *buffer = NULL, *tmp = NULL;
ut32 i;
if (!container) {
return NULL;
return;
}
sd = &container->signedData;
length = 2048 + (container->signedData.certificates.length * 1024);
if(!length) {
return NULL;
}
buffer = (char*) calloc (1, length);
if (!buffer) {
return NULL;
}
r = snprintf (buffer, length, "signedData\n Version: %u\n Digest Algorithms:\n", sd->version);
p += (ut32) r;
if (r < 0 || length <= p) {
free (buffer);
return NULL;
}
r_cons_printf ("signedData\n Version: v%u\n Digest Algorithms:\n", sd->version);
if (container->signedData.digestAlgorithms.elements) {
eprintf("aaa\n");
for (i = 0; i < container->signedData.digestAlgorithms.length; ++i) {
if (container->signedData.digestAlgorithms.elements[i]) {
RASN1String *s = container->signedData.digestAlgorithms.elements[i]->algorithm;
r = snprintf (buffer + p, length - p, " %s\n", s ? s->string : "Missing");
p += (ut32) r;
if (r < 0 || length <= p) {
free (buffer);
return NULL;
}
r_cons_printf (" %s\n", s ? s->string : "Missing");
}
}
}
r = snprintf (buffer + p, length - p, " Certificates: %u\n", container->signedData.certificates.length);
p += (ut32) r;
if (r < 0 || length <= p) {
free (buffer);
return NULL;
}
r_cons_printf (" Certificates: %u\n", container->signedData.certificates.length);
for (i = 0; i < container->signedData.certificates.length; ++i) {
if (length <= p || !(tmp = r_x509_certificate_dump (container->signedData.certificates.elements[i], buffer + p, length - p, " "))) {
free (buffer);
return NULL;
}
p = tmp - buffer;
r_x509_certificate_dump (container->signedData.certificates.elements[i], " ");
}
for (i = 0; i < container->signedData.crls.length; ++i) {
if (length <= p || !(tmp = r_x509_crl_dump (container->signedData.crls.elements[i], buffer + p, length - p, " "))) {
free (buffer);
return NULL;
}
p = tmp - buffer;
}
p = tmp - buffer;
if (length <= p) {
free (buffer);
return NULL;
}
r = snprintf (buffer + p, length - p, " SignerInfos:\n");
p += (ut32) r;
if (r < 0 || length <= p) {
free (buffer);
return NULL;
r_x509_crl_dump (container->signedData.crls.elements[i], " ");
}
r_cons_printf (" SignerInfos:\n");
if (container->signedData.signerinfos.elements) {
for (i = 0; i < container->signedData.signerinfos.length; ++i) {
if (length <= p || !(tmp = r_x509_signedinfo_dump (container->signedData.signerinfos.elements[i], buffer + p, length - p, " "))) {
free (buffer);
return NULL;
}
p = tmp - buffer;
r_x509_signedinfo_dump (container->signedData.signerinfos.elements[i], " ");
}
}
return buffer;
}
RJSVar *r_x509_signedinfo_json (RPKCS7SignerInfo* si) {

View File

@ -1449,6 +1449,22 @@ R_API int r_str_is_printable(const char *str) {
return 1;
}
R_API int r_str_is_printable_limited(const char *str, int size) {
while (size > 0 && *str) {
int ulen = r_utf8_decode ((const ut8*)str, strlen (str), NULL);
if (ulen > 1) {
str += ulen;
continue;
}
if (!IS_PRINTABLE (*str)) {
return 0;
}
str++;
size--;
}
return 1;
}
R_API bool r_str_is_printable_incl_newlines(const char *str) {
while (*str) {
int ulen = r_utf8_decode ((const ut8*)str, strlen (str), NULL);

View File

@ -1,6 +1,7 @@
/* radare2 - LGPL - Copyright 2017-2018 - wargio */
#include <r_util.h>
#include <r_cons.h>
#include <stdlib.h>
#include <string.h>
#include "./x509.h"
@ -412,52 +413,38 @@ void r_x509_free_crl (RX509CertificateRevocationList *crl) {
}
}
char* r_x509_validity_dump (RX509Validity* validity, char* buffer, ut32 length, const char* pad) {
if (!validity || !buffer || !length) {
return NULL;
void r_x509_validity_dump (RX509Validity* validity, const char* pad) {
if (!validity) {
return;
}
if (!pad) {
pad = "";
}
const char* b = validity->notBefore ? validity->notBefore->string : "Missing";
const char* a = validity->notAfter ? validity->notAfter->string : "Missing";
int p = snprintf (buffer, length, "%sNot Before: %s\n%sNot After: %s\n", pad, b, pad, a);
return p < 0 ? NULL : buffer + (ut32) p;
r_cons_printf ("%sNot Before: %s\n%sNot After: %s\n", pad, b, pad, a);
}
char* r_x509_name_dump (RX509Name* name, char* buffer, ut32 length, const char* pad) {
ut32 i, p, len;
int r;
char* c;
if (!name || !buffer || !length) {
return NULL;
void r_x509_name_dump (RX509Name* name, const char* pad) {
ut32 i;
if (!name) {
return;
}
if (!pad) {
pad = "";
}
len = length;
c = buffer;
for (i = 0, p = 0; i < name->length; ++i) {
for (i = 0; i < name->length; ++i) {
if (!name->oids[i] || !name->names[i]) {
continue;
}
if (len <= p) {
return NULL;
}
r = snprintf (c + p, len - p, "%s%s: %s\n", pad, name->oids[i]->string, name->names[i]->string);
p += r;
if (r < 0 || len < p) {
return NULL;
}
r_cons_printf ("%s%s: %s\n", pad, name->oids[i]->string, name->names[i]->string);
}
return c + p;
}
char* r_x509_subjectpublickeyinfo_dump (RX509SubjectPublicKeyInfo* spki, char* buffer, ut32 length, const char* pad) {
int r;
void r_x509_subjectpublickeyinfo_dump (RX509SubjectPublicKeyInfo* spki, const char* pad) {
const char *a;
if (!spki || !buffer || !length) {
return NULL;
if (!spki) {
return;
}
if (!pad) {
pad = "";
@ -470,26 +457,21 @@ char* r_x509_subjectpublickeyinfo_dump (RX509SubjectPublicKeyInfo* spki, char* b
// RASN1String* e = r_asn1_stringify_bytes (spki->subjectPublicKeyExponent->sector, spki->subjectPublicKeyExponent->length);
// r = snprintf (buffer, length, "%sAlgorithm: %s\n%sModule: %s\n%sExponent: %u bytes\n%s\n", pad, a, pad, m->string,
// pad, spki->subjectPublicKeyExponent->length - 1, e->string);
r = snprintf (buffer, length, "%sAlgorithm: %s\n%sModule: %s\n%sExponent: %u bytes\n", pad, a, pad, m ? m->string : "Missing",
r_cons_printf ("%sAlgorithm: %s\n%sModule: %s\n%sExponent: %u bytes\n", pad, a, pad, m ? m->string : "Missing",
pad, spki->subjectPublicKeyExponent ? spki->subjectPublicKeyExponent->length - 1 : 0);
r_asn1_free_string (m);
// r_asn1_free_string (e);
return r < 0 ? NULL : buffer + (ut32) r;
}
char* r_x509_extensions_dump (RX509Extensions* exts, char* buffer, ut32 length, const char* pad) {
ut32 i, p, len;
int r;
char* c;
if (!exts || !buffer || !length) {
return NULL;
void r_x509_extensions_dump (RX509Extensions* exts, const char* pad) {
ut32 i;
if (!exts) {
return;
}
if (!pad) {
pad = "";
}
len = length;
c = buffer;
for (i = 0, p = 0, r = 0; i < exts->length; ++i) {
for (i = 0; i < exts->length; ++i) {
//RASN1String *s;
RX509Extension *e = exts->extensions[i];
if (!e) {
@ -497,38 +479,26 @@ char* r_x509_extensions_dump (RX509Extensions* exts, char* buffer, ut32 length,
}
//TODO handle extensions..
//s = r_asn1_stringify_bytes (e->extnValue->sector, e->extnValue->length);
if (len < p) {
return NULL;
}
r = snprintf (c + p, len - p, "%s%s: %s\n%s%u bytes\n", pad,
r_cons_printf ("%s%s: %s\n%s%u bytes\n", pad,
e->extnID ? e->extnID->string : "Missing",
e->critical ? "critical" : "",
pad, e->extnValue ? e->extnValue->length : 0);
p += r;
//r_asn1_free_string (s);
if (r < 0 || len <= p) {
return NULL;
}
}
return c + p;
}
char* r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, char* buffer, ut32 length, const char* pad) {
void r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, const char* pad) {
RASN1String *sid = NULL, *iid = NULL;
char *pad2, *tmp;
ut32 p;
int r;
if (!tbsc || !buffer || !length) {
return NULL;
char *pad2;
if (!tbsc) {
return;
}
if (!pad) {
pad = "";
}
pad2 = r_str_newf ("%s ", pad);
if (!pad2) {
return NULL;
}
r = snprintf (buffer, length, "%sVersion: v%u\n"
if (!pad2) return;
r_cons_printf ("%sVersion: v%u\n"
"%sSerial Number:\n%s %s\n"
"%sSignature Algorithm:\n%s %s\n"
"%sIssuer:\n",
@ -536,140 +506,69 @@ char* r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, char* buffer, ut32
pad, pad, tbsc->serialNumber ? tbsc->serialNumber->string : "Missing",
pad, pad, tbsc->signature.algorithm ? tbsc->signature.algorithm->string : "Missing",
pad);
p = (ut32) r;
if (r < 0 || length <= p || !(tmp = r_x509_name_dump (&tbsc->issuer, buffer + p, length - p, pad2))) {
free (pad2);
return NULL;
}
p = tmp - buffer;
if (length <= p) {
free (pad2);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sValidity:\n", pad);
p += r;
if (r < 0 || length <= p || !(tmp = r_x509_validity_dump (&tbsc->validity, buffer + p, length - p, pad2))) {
free (pad2);
return NULL;
}
p = tmp - buffer;
if (r < 0 || length <= p) {
free (pad2);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sSubject:\n", pad);
p += r;
if (r < 0 || length <= p || !(tmp = r_x509_name_dump (&tbsc->subject, buffer + p, length - p, pad2))) {
free (pad2);
return NULL;
}
p = tmp - buffer;
if (r < 0 || length <= p) {
free (pad2);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sSubject Public Key Info:\n", pad);
p += r;
if (r < 0 || length <= p ||
!(tmp = r_x509_subjectpublickeyinfo_dump (&tbsc->subjectPublicKeyInfo, buffer + p, length - p, pad2))) {
free (pad2);
return NULL;
}
p = tmp - buffer;
r_x509_name_dump (&tbsc->issuer, pad2);
r_cons_printf ("%sValidity:\n", pad);
r_x509_validity_dump (&tbsc->validity, pad2);
r_cons_printf ("%sSubject:\n", pad);
r_x509_name_dump (&tbsc->subject, pad2);
r_cons_printf ("%sSubject Public Key Info:\n", pad);
r_x509_subjectpublickeyinfo_dump (&tbsc->subjectPublicKeyInfo, pad2);
if (tbsc->issuerUniqueID) {
iid = r_asn1_stringify_integer (tbsc->issuerUniqueID->binary, tbsc->issuerUniqueID->length);
if (iid) {
if (length <= p) {
r_asn1_free_string (iid);
free (pad2);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sIssuer Unique ID:\n%s %s", pad, pad, iid->string);
p += r;
} else {
free (pad2);
return NULL;
r_cons_printf ("%sIssuer Unique ID:\n%s %s", pad, pad, iid->string);
r_asn1_free_string (iid);
}
r_asn1_free_string (iid);
}
if (tbsc->subjectUniqueID) {
sid = r_asn1_stringify_integer (tbsc->subjectUniqueID->binary, tbsc->subjectUniqueID->length);
if (sid) {
if (length <= p) {
r_asn1_free_string (sid);
free (pad2);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sSubject Unique ID:\n%s %s", pad, pad, sid->string);
p += r;
} else {
free (pad2);
return NULL;
r_cons_printf ("%sSubject Unique ID:\n%s %s", pad, pad, sid->string);
r_asn1_free_string (sid);
}
r_asn1_free_string (sid);
}
if (r < 0 || length <= p) {
free (pad2);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sExtensions:\n", pad);
p += r;
if (r < 0 || length <= p || !(tmp = r_x509_extensions_dump (&tbsc->extensions, buffer + p, length - p, pad2))) {
free (pad2);
return NULL;
}
r_cons_printf ("%sExtensions:\n", pad);
r_x509_extensions_dump (&tbsc->extensions, pad2);
free (pad2);
return buffer + p;
}
char* r_x509_certificate_dump (RX509Certificate* certificate, char* buffer, ut32 length, const char* pad) {
void r_x509_certificate_dump (RX509Certificate* certificate, const char* pad) {
// RASN1String *signature,
RASN1String *algo = NULL;
ut32 p;
int r;
char *tbsc, *pad2;
if (!certificate || !buffer || !length) {
return NULL;
char *pad2;
if (!certificate) {
return;
}
if (!pad) {
pad = "";
}
pad2 = r_str_newf ("%s ", pad);
if (!pad2) {
return NULL;
}
if ((r = snprintf (buffer, length, "%sTBSCertificate:\n", pad)) < 0) {
return NULL;
}
p = (ut32) r;
tbsc = r_x509_tbscertificate_dump (&certificate->tbsCertificate, buffer + p, length - p, pad2);
p = tbsc - buffer;
if (length <= p) {
free (pad2);
return NULL;
return;
}
r_cons_printf ("%sTBSCertificate:\n", pad);
r_x509_tbscertificate_dump (&certificate->tbsCertificate, pad2);
algo = certificate->algorithmIdentifier.algorithm;
// signature = r_asn1_stringify_bytes (certificate->signature->binary, certificate->signature->length);
// r = snprintf (buffer + p, length - p, "%sAlgorithm:\n%s%s\n%sSignature: %u bytes\n%s\n",
// r_cons_printf ("%sAlgorithm:\n%s%s\n%sSignature: %u bytes\n%s\n",
// pad, pad2, algo ? algo->string : "",
// pad, certificate->signature->length, signature ? signature->string : "");
r = snprintf (buffer + p, length - p, "%sAlgorithm:\n%s%s\n%sSignature: %u bytes\n",
r_cons_printf ("%sAlgorithm:\n%s%s\n%sSignature: %u bytes\n",
pad, pad2, algo ? algo->string : "", pad, certificate->signature->length);
if (r < 0) {
free (pad2);
return NULL;
}
p += (ut32) r;
free (pad2);
// r_asn1_free_string (signature);
return buffer + p;
}
char* r_x509_crlentry_dump (RX509CRLEntry *crle, char* buffer, ut32 length, const char* pad) {
void r_x509_crlentry_dump (RX509CRLEntry *crle, const char* pad) {
RASN1String *id = NULL, *utc = NULL;
int r;
if (!crle || !buffer || !length) {
return NULL;
if (!crle) {
return;
}
if (!pad) {
pad = "";
@ -679,64 +578,43 @@ char* r_x509_crlentry_dump (RX509CRLEntry *crle, char* buffer, ut32 length, cons
id = r_asn1_stringify_integer (crle->userCertificate->binary, crle->userCertificate->length);
}
r = snprintf (buffer, length, "%sUser Certificate:\n%s %s\n"
r_cons_printf ("%sUser Certificate:\n%s %s\n"
"%sRevocation Date:\n%s %s\n",
pad, pad, id ? id->string : "Missing",
pad, pad, utc ? utc->string : "Missing");
r_asn1_free_string (id);
return r < 0 ? NULL : buffer + (ut32) r;
}
char* r_x509_crl_dump (RX509CertificateRevocationList *crl, char* buffer, ut32 length, const char* pad) {
void r_x509_crl_dump (RX509CertificateRevocationList *crl, const char* pad) {
RASN1String *algo = NULL, *last = NULL, *next = NULL;
ut32 i, p;
int r;
char *tmp, *pad2, *pad3;
if (!crl || !buffer || !length) {
return NULL;
ut32 i;
char *pad2, *pad3;
if (!crl) {
return;
}
if (!pad) {
pad = "";
}
pad3 = r_str_newf ("%s ", pad);
if (!pad3) {
return NULL;
}
if (!pad3) return;
pad2 = pad3 + 2;
algo = crl->signature.algorithm;
last = crl->lastUpdate;
next = crl->nextUpdate;
r = snprintf (buffer, length, "%sCRL:\n%sSignature:\n%s%s\n%sIssuer\n",
pad, pad2, pad3, algo ? algo->string : "", pad2);
p = (ut32) r;
if (r < 0 || !(tmp = r_x509_name_dump (&crl->issuer, buffer + p, length - p, pad3))) {
free (pad3);
return NULL;
}
p = tmp - buffer;
if (length <= p) {
free (pad3);
return NULL;
}
r = snprintf (buffer + p, length - p, "%sLast Update: %s\n%sNext Update: %s\n%sRevoked Certificates:\n",
r_cons_printf ("%sCRL:\n%sSignature:\n%s%s\n%sIssuer\n", pad, pad2, pad3,
algo ? algo->string : "", pad2);
r_x509_name_dump (&crl->issuer, pad3);
r_cons_printf ("%sLast Update: %s\n%sNext Update: %s\n%sRevoked Certificates:\n",
pad2, last ? last->string : "Missing",
pad2, next ? next->string : "Missing", pad2);
p += (ut32) r;
if (r < 0) {
free (pad3);
return NULL;
}
for (i = 0; i < crl->length; ++i) {
if (length <= p || !(tmp = r_x509_crlentry_dump (crl->revokedCertificates[i], buffer + p, length - p, pad3))) {
free (pad3);
return NULL;
}
p = tmp - buffer;
r_x509_crlentry_dump (crl->revokedCertificates[i], pad3);
}
free (pad3);
return buffer + p;
}
RJSVar *r_x509_validity_json (RX509Validity* validity) {

View File

@ -22,12 +22,12 @@ R_API void r_x509_free_tbscertificate (RX509TBSCertificate * tbsc);
R_API RX509CRLEntry *r_x509_parse_crlentry (RASN1Object *object);
R_API void r_x509_free_crlentry (RX509CRLEntry *entry);
R_API char* r_x509_validity_dump (RX509Validity* validity, char* buffer, ut32 length, const char* pad);
R_API char* r_x509_name_dump (RX509Name* name, char* buffer, ut32 length, const char* pad);
R_API char* r_x509_subjectpublickeyinfo_dump (RX509SubjectPublicKeyInfo* spki, char* buffer, ut32 length, const char* pad);
R_API char* r_x509_extensions_dump (RX509Extensions* exts, char* buffer, ut32 length, const char* pad);
R_API char* r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, char* buffer, ut32 length, const char* pad);
R_API char* r_x509_crlentry_dump (RX509CRLEntry *crle, char* buffer, ut32 length, const char* pad);
R_API void r_x509_validity_dump (RX509Validity* validity, const char* pad);
R_API void r_x509_name_dump (RX509Name* name, const char* pad);
R_API void r_x509_subjectpublickeyinfo_dump (RX509SubjectPublicKeyInfo* spki, const char* pad);
R_API void r_x509_extensions_dump (RX509Extensions* exts, const char* pad);
R_API void r_x509_tbscertificate_dump (RX509TBSCertificate* tbsc, const char* pad);
R_API void r_x509_crlentry_dump (RX509CRLEntry *crle, const char* pad);
#endif /* R_X509_INTERNAL_H */