Extend ASN.1/PKCS7/X.509 to dump structures (#5656)

This commit is contained in:
Giovanni 2025-12-22 09:41:56 +08:00 committed by GitHub
parent 8ca45d1ea5
commit 99c1a22d69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 2315 additions and 1055 deletions

View file

@ -119,15 +119,21 @@ static char *pe_signature(RzBinFile *bf, bool json) {
return NULL;
}
struct PE_(rz_bin_pe_obj_t) *bin = bf->o->bin_obj;
if (json) {
PJ *pj = pj_new();
if (!pj) {
return rz_str_dup("{}");
}
rz_pkcs7_cms_json(bin->cms, pj);
return pj_drain(pj);
RzStructuredData *pe_cms = rz_pkcs7_cms_to_structure(bin->cms);
if (!pe_cms) {
return rz_str_dup(json ? "{}" : "");
}
return rz_pkcs7_cms_to_string(bin->cms);
char *value = NULL;
if (json) {
value = rz_structured_data_to_json(pe_cms);
} else {
value = rz_structured_data_to_yaml(pe_cms);
}
rz_structured_data_free(pe_cms);
return value;
}
static RzPVector /*<RzBinField *>*/ *pe_fields(RzBinFile *bf) {
@ -510,6 +516,16 @@ static RzStructuredData *pe_structure(RzBinFile *bf) {
rz_structured_data_map_add_unsigned(image, "Size", bin->nt_headers->optional_header.DataDirectory[i].Size, false);
}
if (bin->cms) {
RzStructuredData *pe_cms = rz_pkcs7_cms_to_structure(bin->cms);
rz_structured_data_map_add(pe32, "CryptographicMessageSyntax", pe_cms);
}
if (bin->spcinfo) {
RzStructuredData *pe_auth = rz_pkcs7_spcinfo_to_structure(bin->spcinfo);
rz_structured_data_map_add(pe32, "Authenticode", pe_auth);
}
return info;
}

View file

@ -3628,7 +3628,7 @@ RZ_IPI RzCmdStatus rz_cmd_print_asn1_handler(RzCore *core, int argc, const char
RZ_LOG_ERROR("core: Malformed object: did you supply enough data?\ntry to change the block size (see b? or @!<size>)\n");
return RZ_CMD_STATUS_ERROR;
}
char *res = rz_asn1_to_string(asn1, 0, mode == RZ_OUTPUT_MODE_STANDARD);
char *res = rz_asn1_to_string(asn1);
rz_asn1_object_free(asn1);
if (!res) {
return RZ_CMD_STATUS_ERROR;
@ -3638,6 +3638,37 @@ RZ_IPI RzCmdStatus rz_cmd_print_asn1_handler(RzCore *core, int argc, const char
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_print_asn1_structure_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
RzASN1Object *asn1 = rz_asn1_object_parse(core->block, core->blocksize);
if (!asn1) {
RZ_LOG_ERROR("core: Malformed object: did you supply enough data?\ntry to change the block size (see b? or @!<size>)\n");
return RZ_CMD_STATUS_ERROR;
}
RzStructuredData *sd = rz_asn1_to_structure(asn1, state->mode == RZ_OUTPUT_MODE_QUIET);
rz_asn1_object_free(asn1);
if (!sd) {
RZ_LOG_ERROR("core: failed to create RzStructuredData from ASN1 data.\n");
return RZ_CMD_STATUS_ERROR;
}
switch (state->mode) {
case RZ_OUTPUT_MODE_JSON:
rz_structured_data_to_pj(sd, state->d.pj);
break;
default: {
char *res = rz_structured_data_to_yaml(sd);
if (res) {
rz_cons_println(res);
free(res);
}
break;
}
}
rz_structured_data_free(sd);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_print_protobuf_standard_handler(RzCore *core, int argc, const char **argv) {
char *s = rz_protobuf_decode(core->block, core->blocksize, false);
if (!s) {
@ -3661,89 +3692,97 @@ RZ_IPI RzCmdStatus rz_cmd_print_protobuf_verbose_handler(RzCore *core, int argc,
}
RZ_IPI RzCmdStatus rz_cmd_print_pkcs7_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
char *res = NULL;
RzCMS *cms = rz_pkcs7_cms_parse(core->block, core->blocksize);
if (!cms) {
RZ_LOG_ERROR("core: Malformed object: did you supply enough data?\ntry to change the block size (see b? or @!<size>)\n");
return RZ_CMD_STATUS_ERROR;
}
RzStructuredData *sd = rz_pkcs7_cms_to_structure(cms);
rz_pkcs7_cms_free(cms);
if (!sd) {
RZ_LOG_ERROR("core: failed to create RzStructuredData from CMS data.\n");
return RZ_CMD_STATUS_ERROR;
}
switch (state->mode) {
case RZ_OUTPUT_MODE_JSON:
rz_pkcs7_cms_json(cms, state->d.pj);
rz_structured_data_to_pj(sd, state->d.pj);
break;
default:
res = rz_pkcs7_cms_to_string(cms);
default: {
char *res = rz_structured_data_to_yaml(sd);
if (res) {
rz_cons_printf("%s", res);
rz_cons_println(res);
free(res);
}
break;
}
rz_pkcs7_cms_free(cms);
}
rz_structured_data_free(sd);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_print_x509_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
char *res = NULL;
RzStrBuf *sb = NULL;
RzX509Certificate *x509 = rz_x509_certificate_parse2(core->block, core->blocksize);
if (!x509) {
RZ_LOG_ERROR("core: Malformed object: did you supply enough data?\ntry to change the block size (see b? or @!<size>)\n");
return RZ_CMD_STATUS_ERROR;
}
RzStructuredData *sd = rz_x509_certificate_to_structure(x509);
rz_x509_certificate_free(x509);
if (!sd) {
RZ_LOG_ERROR("core: failed to create RzStructuredData from x509 data.\n");
return RZ_CMD_STATUS_ERROR;
}
switch (state->mode) {
case RZ_OUTPUT_MODE_JSON:
rz_x509_certificate_json(state->d.pj, x509);
rz_structured_data_to_pj(sd, state->d.pj);
break;
default:
sb = rz_strbuf_new(NULL);
if (!sb) {
RZ_LOG_ERROR("core: failed to allocate RzStrBuf\n");
rz_x509_certificate_free(x509);
return RZ_CMD_STATUS_ERROR;
}
rz_x509_certificate_dump(x509, NULL, sb);
res = rz_strbuf_drain(sb);
default: {
char *res = rz_structured_data_to_yaml(sd);
if (res) {
rz_cons_printf("%s", res);
rz_cons_println(res);
free(res);
}
break;
}
rz_x509_certificate_free(x509);
}
rz_structured_data_free(sd);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_print_pkcs8_pkey_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
char *output = NULL;
RzPrivateKeyInfo *pki = rz_pkcs8_private_key_info_parse(core->block, core->blocksize);
if (!pki) {
RZ_LOG_ERROR("core: Malformed object: did you supply enough data?\ntry to change the block size (see b? or @!<size>)\n");
return RZ_CMD_STATUS_ERROR;
}
RzStructuredData *res = rz_pkcs8_private_key_info_to_structure(pki);
RzStructuredData *sd = rz_pkcs8_private_key_info_to_structure(pki);
rz_pkcs8_private_key_info_free(pki);
if (!sd) {
RZ_LOG_ERROR("core: failed to create RzStructuredData from PrivateKeyInfo data.\n");
return RZ_CMD_STATUS_ERROR;
}
switch (state->mode) {
case RZ_OUTPUT_MODE_JSON:
output = rz_structured_data_to_json(res);
if (output) {
pj_j(state->d.pj, output);
free(output);
}
rz_structured_data_to_pj(sd, state->d.pj);
break;
default:
output = rz_structured_data_to_yaml(res);
if (output) {
rz_cons_printf("%s", output);
free(output);
default: {
char *res = rz_structured_data_to_yaml(sd);
if (res) {
rz_cons_println(res);
free(res);
}
break;
}
rz_structured_data_free(res);
}
rz_structured_data_free(sd);
return RZ_CMD_STATUS_OK;
}

View file

@ -15776,24 +15776,35 @@ static const RzCmdDescHelp cmd_print_format_write_help = {
};
static const RzCmdDescHelp pF_help = {
.summary = "Print parsed ASN.1, PKCS, X509, ProtoBuf, AXML, etc.. formats",
.summary = "Deserializes ASN.1, PKCS, X509, ProtoBuf, AXML, etc.. formats",
};
static const RzCmdDescHelp pFa_help = {
.summary = "Deserializes the ASN.1 DER structure from the current block",
};
static const RzCmdDescArg cmd_print_asn1_args[] = {
{ 0 },
};
static const RzCmdDescHelp cmd_print_asn1_help = {
.summary = "Decode ASN.1 from current block",
.summary = "Deserializes the ASN.1 DER structure from the current block as a hexdump.",
.args = cmd_print_asn1_args,
};
static const RzCmdDescArg cmd_print_asn1_structure_args[] = {
{ 0 },
};
static const RzCmdDescHelp cmd_print_asn1_structure_help = {
.summary = "Deserializes the ASN.1 DER structure from the current block as a structured data format.",
.args = cmd_print_asn1_structure_args,
};
static const RzCmdDescHelp cmd_print_protobuf_help = {
.summary = "Decode raw protobuf from current block",
.summary = "Deserializes raw protobuf from current block as a hexdump.",
};
static const RzCmdDescArg cmd_print_protobuf_standard_args[] = {
{ 0 },
};
static const RzCmdDescHelp cmd_print_protobuf_standard_help = {
.summary = "Decode raw protobuf from current block",
.summary = "Deserializes raw protobuf from current block as a hexdump.",
.args = cmd_print_protobuf_standard_args,
};
@ -15801,7 +15812,7 @@ static const RzCmdDescArg cmd_print_protobuf_verbose_args[] = {
{ 0 },
};
static const RzCmdDescHelp cmd_print_protobuf_verbose_help = {
.summary = "Decode raw protobuf from current block (verbose)",
.summary = "Deserializes raw protobuf from current block as a hexdump(verbose).",
.args = cmd_print_protobuf_verbose_args,
};
@ -15809,7 +15820,7 @@ static const RzCmdDescArg cmd_print_pkcs7_args[] = {
{ 0 },
};
static const RzCmdDescHelp cmd_print_pkcs7_help = {
.summary = "Decode PKCS7 from current block",
.summary = "Deserializes PKCS7 from current block as a structured data format.",
.args = cmd_print_pkcs7_args,
};
@ -15817,7 +15828,7 @@ static const RzCmdDescArg cmd_print_x509_args[] = {
{ 0 },
};
static const RzCmdDescHelp cmd_print_x509_help = {
.summary = "Decode X.509 from current block",
.summary = "Deserializes X.509 from current block as a structured data format.",
.args = cmd_print_x509_args,
};
@ -15825,7 +15836,7 @@ static const RzCmdDescArg cmd_print_pkcs8_pkey_args[] = {
{ 0 },
};
static const RzCmdDescHelp cmd_print_pkcs8_pkey_help = {
.summary = "Decode PKCS#8 private keys from current block",
.summary = "Deserializes PKCS#8 private keys from current block as a structured data format.",
.args = cmd_print_pkcs8_pkey_args,
};
@ -15833,7 +15844,7 @@ static const RzCmdDescArg cmd_print_axml_args[] = {
{ 0 },
};
static const RzCmdDescHelp cmd_print_axml_help = {
.summary = "Decode Android Binary XML from current block",
.summary = "Deserializes Android Binary XML from current block as XML format.",
.args = cmd_print_axml_args,
};
@ -24417,8 +24428,10 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) {
RzCmdDesc *pF_cd = rz_cmd_desc_group_new(core->rcmd, cmd_print_cd, "pF", NULL, NULL, &pF_help);
rz_warn_if_fail(pF_cd);
RzCmdDesc *cmd_print_asn1_cd = rz_cmd_desc_argv_modes_new(core->rcmd, pF_cd, "pFa", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_QUIET, rz_cmd_print_asn1_handler, &cmd_print_asn1_help);
rz_warn_if_fail(cmd_print_asn1_cd);
RzCmdDesc *pFa_cd = rz_cmd_desc_group_modes_new(core->rcmd, pF_cd, "pFa", RZ_OUTPUT_MODE_STANDARD, rz_cmd_print_asn1_handler, &cmd_print_asn1_help, &pFa_help);
rz_warn_if_fail(pFa_cd);
RzCmdDesc *cmd_print_asn1_structure_cd = rz_cmd_desc_argv_state_new(core->rcmd, pFa_cd, "pFas", RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_JSON | RZ_OUTPUT_MODE_QUIET, rz_cmd_print_asn1_structure_handler, &cmd_print_asn1_structure_help);
rz_warn_if_fail(cmd_print_asn1_structure_cd);
RzCmdDesc *cmd_print_protobuf_cd = rz_cmd_desc_group_new(core->rcmd, pF_cd, "pFb", rz_cmd_print_protobuf_standard_handler, &cmd_print_protobuf_standard_help, &cmd_print_protobuf_help);
rz_warn_if_fail(cmd_print_protobuf_cd);

View file

@ -2063,6 +2063,8 @@ RZ_IPI RzCmdStatus rz_cmd_print_format_value_handler(RzCore *core, int argc, con
RZ_IPI RzCmdStatus rz_cmd_print_format_write_handler(RzCore *core, int argc, const char **argv);
// "pFa"
RZ_IPI RzCmdStatus rz_cmd_print_asn1_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode);
// "pFas"
RZ_IPI RzCmdStatus rz_cmd_print_asn1_structure_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
// "pFb"
RZ_IPI RzCmdStatus rz_cmd_print_protobuf_standard_handler(RzCore *core, int argc, const char **argv);
// "pFbv"

View file

@ -662,29 +662,40 @@ commands:
- text: "pf 'tt troll plop'"
comment: "Print time stamps with labels 'troll' and 'plop'"
- name: pF
summary: Print parsed ASN.1, PKCS, X509, ProtoBuf, AXML, etc.. formats
summary: Deserializes ASN.1, PKCS, X509, ProtoBuf, AXML, etc.. formats
subcommands:
- name: pFa
summary: Decode ASN.1 from current block
cname: cmd_print_asn1
modes:
- RZ_OUTPUT_MODE_STANDARD
- RZ_OUTPUT_MODE_QUIET
args: []
summary: Deserializes the ASN.1 DER structure from the current block
subcommands:
- name: pFa
summary: Deserializes the ASN.1 DER structure from the current block as a hexdump.
cname: cmd_print_asn1
modes:
- RZ_OUTPUT_MODE_STANDARD
args: []
- name: pFas
summary: Deserializes the ASN.1 DER structure from the current block as a structured data format.
cname: cmd_print_asn1_structure
type: RZ_CMD_DESC_TYPE_ARGV_STATE
modes:
- RZ_OUTPUT_MODE_STANDARD
- RZ_OUTPUT_MODE_JSON
- RZ_OUTPUT_MODE_QUIET
args: []
- name: pFb
summary: Decode raw protobuf from current block
summary: Deserializes raw protobuf from current block as a hexdump.
cname: cmd_print_protobuf
subcommands:
- name: pFb
summary: Decode raw protobuf from current block
summary: Deserializes raw protobuf from current block as a hexdump.
cname: cmd_print_protobuf_standard
args: []
- name: pFbv
summary: Decode raw protobuf from current block (verbose)
summary: Deserializes raw protobuf from current block as a hexdump(verbose).
cname: cmd_print_protobuf_verbose
args: []
- name: pFp
summary: Decode PKCS7 from current block
summary: Deserializes PKCS7 from current block as a structured data format.
cname: cmd_print_pkcs7
type: RZ_CMD_DESC_TYPE_ARGV_STATE
modes:
@ -692,7 +703,7 @@ commands:
- RZ_OUTPUT_MODE_JSON
args: []
- name: pFx
summary: Decode X.509 from current block
summary: Deserializes X.509 from current block as a structured data format.
cname: cmd_print_x509
type: RZ_CMD_DESC_TYPE_ARGV_STATE
modes:
@ -700,7 +711,7 @@ commands:
- RZ_OUTPUT_MODE_JSON
args: []
- name: pF8
summary: Decode PKCS#8 private keys from current block
summary: Deserializes PKCS#8 private keys from current block as a structured data format.
cname: cmd_print_pkcs8_pkey
type: RZ_CMD_DESC_TYPE_ARGV_STATE
modes:
@ -708,7 +719,7 @@ commands:
- RZ_OUTPUT_MODE_JSON
args: []
- name: pFA
summary: Decode Android Binary XML from current block
summary: Deserializes Android Binary XML from current block as XML format.
cname: cmd_print_axml
args: []
- name: ph

View file

@ -2,8 +2,8 @@
#define RZ_ASN1_H
#include <rz_types.h>
#include <stdint.h>
#include <rz_util/rz_strbuf.h>
#include <rz_util/rz_structured_data.h>
#ifdef __cplusplus
extern "C" {
@ -101,8 +101,8 @@ RZ_API RZ_OWN RzASN1String *rz_asn1_stringify_boolean(RZ_NULLABLE const ut8 *buf
RZ_API RZ_OWN RzASN1String *rz_asn1_stringify_oid(RZ_NULLABLE const ut8 *buffer, ut32 length);
RZ_API void rz_asn1_object_free(RZ_NULLABLE RzASN1Object *object);
RZ_API void rz_asn1_to_strbuf(RZ_NULLABLE RzASN1Object *object, ut32 depth, bool structured, RZ_NONNULL RzStrBuf *sb);
RZ_API RZ_OWN char *rz_asn1_to_string(RZ_NULLABLE RzASN1Object *object, ut32 depth, bool structured);
RZ_API RZ_OWN char *rz_asn1_to_string(RZ_NULLABLE RzASN1Object *object);
RZ_API RZ_OWN RzStructuredData *rz_asn1_to_structure(RZ_NULLABLE RzASN1Object *object, bool simplified);
RZ_API void rz_asn1_string_free(RZ_NULLABLE RzASN1String *string);
RZ_API void rz_asn1_binary_free(RZ_NULLABLE RzASN1Binary *string);

View file

@ -88,10 +88,10 @@ typedef struct rz_cms_indirect_data_content_t {
RZ_API RZ_OWN RzCMS *rz_pkcs7_cms_parse(RZ_NULLABLE const ut8 *buffer, ut32 length);
RZ_API void rz_pkcs7_cms_free(RZ_NULLABLE RzCMS *container);
RZ_API RZ_OWN char *rz_pkcs7_cms_to_string(RZ_NULLABLE RzCMS *container);
RZ_API void rz_pkcs7_cms_json(RZ_NULLABLE RzCMS *container, RZ_NONNULL PJ *pj);
RZ_API RZ_OWN RzStructuredData *rz_pkcs7_cms_to_structure(RZ_NULLABLE RzCMS *container);
RZ_API RZ_OWN RzSpcIndirectDataContent *rz_pkcs7_spcinfo_parse(RZ_NONNULL RzCMS *cms);
RZ_API void rz_pkcs7_spcinfo_free(RZ_NULLABLE RzSpcIndirectDataContent *spcinfo);
RZ_API RZ_OWN RzStructuredData *rz_pkcs7_spcinfo_to_structure(RZ_NULLABLE RzSpcIndirectDataContent *spcinfo);
#ifdef __cplusplus
}

View file

@ -146,7 +146,7 @@ RZ_API bool rz_str_is_ascii(const char *str);
RZ_API bool rz_str_is_utf8(RZ_NONNULL const char *str);
RZ_API char *rz_str_nextword(char *s, char ch);
RZ_API bool rz_str_is_printable(const char *str);
RZ_API bool rz_str_is_printable_limited(const char *str, int size);
RZ_API bool rz_str_is_printable_limited(RZ_NONNULL const char *str, size_t size);
RZ_API bool rz_str_is_printable_incl_newlines(const char *str);
RZ_API char *rz_str_appendlen(char *ptr, const char *string, int slen);
RZ_API char *rz_str_newf(const char *fmt, ...) RZ_PRINTF_CHECK(1, 2);

View file

@ -63,6 +63,7 @@ RZ_API bool rz_structured_data_array_add_boolean(RZ_NONNULL RzStructuredData *pa
RZ_API bool rz_structured_data_array_add_string(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *v);
RZ_API void rz_structured_data_iterate(RZ_NONNULL const RzStructuredData *sd, RZ_NONNULL const RzStructuredDataIterator *iterator, RZ_NULLABLE void *user);
RZ_API void rz_structured_data_to_pj(RZ_NONNULL const RzStructuredData *sd, RZ_NONNULL PJ *pj);
RZ_API RZ_OWN char *rz_structured_data_to_json(RZ_NONNULL const RzStructuredData *sd);
RZ_API RZ_OWN char *rz_structured_data_to_yaml(RZ_NONNULL const RzStructuredData *sd);

View file

@ -2,7 +2,7 @@
#define RZ_X509_H
#include <rz_util/rz_asn1.h>
#include <rz_util/rz_pj.h>
#include <rz_util/rz_structured_data.h>
#ifdef __cplusplus
extern "C" {
@ -25,7 +25,7 @@ typedef struct rz_x509_name_t {
typedef struct rz_x509_algorithmidentifier_t {
RzASN1String *algorithm; // OBJECT IDENTIFIER
RzASN1String *parameters; // OPTIONAL
RzASN1Binary *parameters; // OPTIONAL
} RzX509AlgorithmIdentifier;
typedef struct rz_x509_authoritykeyidentifier_t {
@ -90,14 +90,12 @@ typedef struct rz_x509_certificaterevocationlist {
} RzX509CertificateRevocationList;
RZ_API RZ_OWN RzX509CertificateRevocationList *rz_x509_crl_parse(RZ_NULLABLE RzASN1Object *object);
RZ_API RZ_OWN char *rz_x509_crl_to_string(RZ_NULLABLE RzX509CertificateRevocationList *crl, RZ_NULLABLE const char *pad);
RZ_API void rz_x509_crl_json(RZ_NONNULL PJ *pj, RZ_NULLABLE RzX509CertificateRevocationList *crl);
RZ_API RZ_OWN RzStructuredData *rz_x509_crl_to_structure(RZ_NULLABLE RzX509CertificateRevocationList *crl);
RZ_API RZ_OWN RzX509Certificate *rz_x509_certificate_parse(RZ_NULLABLE RzASN1Object *object);
RZ_API RZ_OWN RzX509Certificate *rz_x509_certificate_parse2(RZ_NULLABLE const ut8 *buffer, ut32 length);
RZ_API void rz_x509_certificate_free(RZ_NULLABLE RzX509Certificate *certificate);
RZ_API void rz_x509_certificate_json(RZ_NONNULL PJ *pj, RZ_NULLABLE RzX509Certificate *certificate);
RZ_API void rz_x509_certificate_dump(RZ_NULLABLE RzX509Certificate *cert, RZ_NULLABLE const char *pad, RZ_NONNULL RzStrBuf *sb);
RZ_API RZ_OWN RzStructuredData *rz_x509_certificate_to_structure(RZ_NULLABLE RzX509Certificate *certificate);
#ifdef __cplusplus
}

View file

@ -207,18 +207,12 @@ RZ_API RZ_OWN RzASN1Binary *rz_asn1_binary_parse(RZ_NULLABLE const ut8 *buffer,
return bin;
}
static void asn1_print_hex(RzASN1Object *object, char *buffer, ut32 size, ut32 depth, bool structured) {
static void asn1_print_hex(RzASN1Object *object, char *buffer, ut32 size, ut32 depth) {
if (!object || !object->sector) {
return;
}
char *p = buffer;
char *end = buffer + size;
if (depth > 0 && !structured) {
char *pad = rz_str_pad(' ', (depth * 2) - 2);
snprintf(p, end - p, "%s", pad);
p += strlen(pad);
free(pad);
}
for (ut32 i = 0; i < object->length && p < end; i++) {
snprintf(p, end - p, "%02x", object->sector[i]);
p += 2;
@ -229,49 +223,16 @@ static void asn1_print_hex(RzASN1Object *object, char *buffer, ut32 size, ut32 d
}
}
static void asn1_print_padded(RzStrBuf *sb, RzASN1Object *object, int depth, const char *k, const char *v) {
if (object->form && !*v) {
return;
}
switch (object->tag) {
case RZ_ASN1_TAG_NULL:
case RZ_ASN1_TAG_EOC:
break;
case RZ_ASN1_TAG_INTEGER:
case RZ_ASN1_TAG_REAL:
if (*rz_str_trim_head_ro(v)) {
char *pad = rz_str_pad(' ', (depth * 2) - 2);
rz_strbuf_appendf(sb, "%s%s\n%s%s\n", pad, k, pad, v);
free(pad);
}
break;
case RZ_ASN1_TAG_BITSTRING:
default:
if (*rz_str_trim_head_ro(v)) {
char *pad = rz_str_pad(' ', (depth * 2) - 2);
rz_strbuf_appendf(sb, "%s%s\n", pad, v);
free(pad);
}
break;
}
}
static RzASN1String *asn1_print_hexdump_padded(RzASN1Object *object, ut32 depth, bool structured) {
static RzASN1String *asn1_print_hexdump_padded(RzASN1Object *object, ut32 depth) {
const char *pad = NULL;
ut32 i = 0, j = 0;
char *allocated = NULL;
ut32 i, j;
char readable[20] = { 0 };
if (!object || !object->sector || object->length < 1) {
return NULL;
}
RzStrBuf *sb = rz_strbuf_new("");
if (structured) {
pad = " : ";
} else {
pad = allocated = rz_str_pad(' ', depth * 2);
rz_strbuf_appendf(sb, " ");
}
pad = " : ";
for (i = 0, j = 0; i < object->length; i++, j++) {
ut8 c = object->sector[i];
if (i > 0 && (i % 16) == 0) {
@ -292,22 +253,12 @@ static RzASN1String *asn1_print_hexdump_padded(RzASN1Object *object, ut32 depth,
char *text = rz_strbuf_drain(sb);
RzASN1String *asn1str = rz_asn1_string_parse(text, true, strlen(text) + 1);
if (!asn1str) {
/* no memory left.. */
free(text);
}
return asn1str;
}
/**
* \brief Converts an the ASN1 structure to a human readable string
*
* \param object The ASN1 object
* \param[in] depth The padding depth
* \param[in] structured Indicates if to print its structures or not
* \param sb The RzStrBuf to write to
*/
RZ_API void rz_asn1_to_strbuf(RZ_NULLABLE RzASN1Object *object, ut32 depth, bool structured, RZ_NONNULL RzStrBuf *sb) {
rz_return_if_fail(sb);
static void asn1_to_strbuf(RzASN1Object *object, ut32 depth, RzStrBuf *sb) {
if (!object) {
return;
}
@ -332,35 +283,25 @@ RZ_API void rz_asn1_to_strbuf(RZ_NULLABLE RzASN1Object *object, ut32 depth, bool
case RZ_ASN1_TAG_INTEGER:
name = "INTEGER";
if (object->length < 16) {
asn1_print_hex(object, temp_name, sizeof(temp_name), depth, structured);
asn1_print_hex(object, temp_name, sizeof(temp_name), depth);
string = temp_name;
} else {
asn1str = asn1_print_hexdump_padded(object, depth, structured);
asn1str = asn1_print_hexdump_padded(object, depth);
}
break;
case RZ_ASN1_TAG_BITSTRING:
name = "BIT_STRING";
if (!object->list.objects) {
if (object->length < 16) {
asn1_print_hex(object, temp_name, sizeof(temp_name), depth, structured);
asn1_print_hex(object, temp_name, sizeof(temp_name), depth);
string = temp_name;
} else {
asn1str = asn1_print_hexdump_padded(object, depth, structured);
asn1str = asn1_print_hexdump_padded(object, depth);
}
}
break;
case RZ_ASN1_TAG_OCTETSTRING:
name = "OCTET_STRING";
if (rz_str_is_printable_limited((const char *)object->sector, object->length)) {
asn1str = rz_asn1_stringify_string(object->sector, object->length);
} else if (!object->list.objects) {
if (object->length < 16) {
asn1_print_hex(object, temp_name, sizeof(temp_name), depth, structured);
string = temp_name;
} else {
asn1str = asn1_print_hexdump_padded(object, depth, structured);
}
}
break;
case RZ_ASN1_TAG_NULL:
name = "NULL";
@ -377,7 +318,7 @@ RZ_API void rz_asn1_to_strbuf(RZ_NULLABLE RzASN1Object *object, ut32 depth, bool
break;
case RZ_ASN1_TAG_REAL:
name = "REAL";
asn1str = asn1_print_hexdump_padded(object, depth, structured);
asn1str = asn1_print_hexdump_padded(object, depth);
break;
case RZ_ASN1_TAG_ENUMERATED:
name = "ENUMERATED";
@ -443,45 +384,42 @@ RZ_API void rz_asn1_to_strbuf(RZ_NULLABLE RzASN1Object *object, ut32 depth, bool
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
default:
snprintf(temp_name, sizeof(temp_name), "Universal_%u", object->tag);
rz_strf(temp_name, "Universal_%u", object->tag);
name = temp_name;
break;
}
break;
case RZ_ASN1_CLASS_APPLICATION:
snprintf(temp_name, sizeof(temp_name), "Application_%u", object->tag);
rz_strf(temp_name, "Application_%u", object->tag);
name = temp_name;
break;
case RZ_ASN1_CLASS_CONTEXT:
snprintf(temp_name, sizeof(temp_name), "Context [%u]", object->tag); // Context
rz_strf(temp_name, "Context [%u]", object->tag); // Context
name = temp_name;
break;
case RZ_ASN1_CLASS_PRIVATE:
snprintf(temp_name, sizeof(temp_name), "Private_%u", object->tag);
rz_strf(temp_name, "Private_%u", object->tag);
name = temp_name;
break;
}
if (!object->list.objects && !asn1str && RZ_STR_ISEMPTY(string)) {
if (rz_str_is_printable_limited((const char *)object->sector, object->length)) {
asn1str = rz_asn1_stringify_string(object->sector, object->length);
} else {
asn1str = asn1_print_hexdump_padded(object, depth);
}
}
if (asn1str) {
string = asn1str->string;
}
if (structured) {
rz_strbuf_appendf(sb, "%4" PFMT64d " ", object->offset);
rz_strbuf_appendf(sb, "%4u:%2d: %s %-20s: %s\n", object->length,
depth, object->form ? "cons" : "prim", name, string);
rz_asn1_string_free(asn1str);
if (object->list.objects) {
for (ut32 i = 0; i < object->list.length; i++) {
rz_asn1_to_strbuf(object->list.objects[i], depth + 1, structured, sb);
}
}
} else {
asn1_print_padded(sb, object, depth, name, string);
rz_asn1_string_free(asn1str);
if (object->list.objects) {
for (ut32 i = 0; i < object->list.length; i++) {
RzASN1Object *obj = object->list.objects[i];
rz_asn1_to_strbuf(obj, depth + 1, structured, sb);
}
rz_strbuf_appendf(sb, "%4" PFMT64d " ", object->offset);
rz_strbuf_appendf(sb, "%4u:%2d: %s %-20s: %s\n", object->length,
depth, object->form ? "cons" : "prim", name, string);
rz_asn1_string_free(asn1str);
if (object->list.objects) {
for (ut32 i = 0; i < object->list.length; i++) {
asn1_to_strbuf(object->list.objects[i], depth + 1, sb);
}
}
}
@ -490,12 +428,10 @@ RZ_API void rz_asn1_to_strbuf(RZ_NULLABLE RzASN1Object *object, ut32 depth, bool
* \brief Converts an the ASN1 structure to a human readable string
*
* \param object The ASN1 object
* \param[in] depth The padding depth
* \param[in] structured Indicates if to print its structures or not
*
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API RZ_OWN char *rz_asn1_to_string(RZ_NULLABLE RzASN1Object *object, ut32 depth, bool structured) {
RZ_API RZ_OWN char *rz_asn1_to_string(RZ_NULLABLE RzASN1Object *object) {
if (!object) {
return NULL;
}
@ -503,10 +439,199 @@ RZ_API RZ_OWN char *rz_asn1_to_string(RZ_NULLABLE RzASN1Object *object, ut32 dep
if (!sb) {
return NULL;
}
rz_asn1_to_strbuf(object, depth, structured, sb);
asn1_to_strbuf(object, 0, sb);
return rz_strbuf_drain(sb);
}
static void asn1_to_structure(RzASN1Object *object, RzStructuredData *parent, bool simplified) {
if (!object || !parent) {
return;
}
// this shall not be freed. it's a pointer into the buffer.
RzASN1String *asn1str = NULL;
char temp_name[4096] = { 0 };
const char *name = "";
const char *string = "";
switch (object->klass) {
case RZ_ASN1_CLASS_UNIVERSAL: // universal
switch (object->tag) {
case RZ_ASN1_TAG_EOC:
name = "EOC";
break;
case RZ_ASN1_TAG_BOOLEAN:
name = "BOOLEAN";
if (object->sector) {
string = (object->sector[0] != 0) ? "true" : "false";
}
break;
case RZ_ASN1_TAG_INTEGER:
name = "INTEGER";
if (object->length < 20) {
asn1str = rz_asn1_stringify_integer(object->sector, object->length);
} else {
asn1str = rz_asn1_stringify_bytes(object->sector, object->length);
}
break;
case RZ_ASN1_TAG_BITSTRING:
name = "BIT_STRING";
if (!object->list.objects) {
if (object->length > 0 && object->length < 20) {
asn1str = rz_asn1_stringify_bits(object->sector, object->length);
} else {
asn1str = rz_asn1_stringify_bytes(object->sector, object->length);
}
}
break;
case RZ_ASN1_TAG_OCTETSTRING:
name = "OCTET_STRING";
break;
case RZ_ASN1_TAG_NULL:
name = "NULL";
break;
case RZ_ASN1_TAG_OID:
name = "OBJECT_IDENTIFIER";
asn1str = rz_asn1_stringify_oid(object->sector, object->length);
break;
case RZ_ASN1_TAG_OBJDESCRIPTOR:
name = "OBJECT_DESCRIPTOR";
break;
case RZ_ASN1_TAG_EXTERNAL:
name = "EXTERNAL";
break;
case RZ_ASN1_TAG_REAL:
name = "REAL";
asn1str = rz_asn1_stringify_bytes(object->sector, object->length);
break;
case RZ_ASN1_TAG_ENUMERATED:
name = "ENUMERATED";
break;
case RZ_ASN1_TAG_EMBEDDED_PDV:
name = "EMBEDDED_PDV";
break;
case RZ_ASN1_TAG_UTF8STRING:
name = "UTF8String";
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_SEQUENCE:
name = "SEQUENCE";
break;
case RZ_ASN1_TAG_SET:
name = "SET";
break;
case RZ_ASN1_TAG_NUMERICSTRING:
name = "NumericString";
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_PRINTABLESTRING:
name = "PrintableString"; // ASCII subset
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_T61STRING:
name = "TeletexString"; // aka T61String
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_VIDEOTEXSTRING:
name = "VideotexString";
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_IA5STRING:
name = "IA5String"; // ASCII
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_UTCTIME:
name = "UTCTime";
asn1str = rz_asn1_stringify_utctime(object->sector, object->length);
break;
case RZ_ASN1_TAG_GENERALIZEDTIME:
name = "GeneralizedTime";
asn1str = rz_asn1_stringify_time(object->sector, object->length);
break;
case RZ_ASN1_TAG_GRAPHICSTRING:
name = "GraphicString";
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_VISIBLESTRING:
name = "VisibleString"; // ASCII subset
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_GENERALSTRING:
name = "GeneralString";
break;
case RZ_ASN1_TAG_UNIVERSALSTRING:
name = "UniversalString";
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
case RZ_ASN1_TAG_BMPSTRING:
name = "BMPString";
asn1str = rz_asn1_stringify_string(object->sector, object->length);
break;
default:
rz_strf(temp_name, "Universal_%u", object->tag);
name = temp_name;
break;
}
break;
case RZ_ASN1_CLASS_APPLICATION:
rz_strf(temp_name, "Application_%u", object->tag);
name = temp_name;
break;
case RZ_ASN1_CLASS_CONTEXT:
rz_strf(temp_name, "Context [%u]", object->tag); // Context
name = temp_name;
break;
case RZ_ASN1_CLASS_PRIVATE:
rz_strf(temp_name, "Private_%u", object->tag);
name = temp_name;
break;
}
if (!object->list.objects && !asn1str && RZ_STR_ISEMPTY(string)) {
if (rz_str_is_printable_limited((const char *)object->sector, object->length)) {
asn1str = rz_asn1_stringify_string(object->sector, object->length);
} else {
asn1str = rz_asn1_stringify_bytes(object->sector, object->length);
}
}
if (asn1str) {
string = asn1str->string;
}
if (!simplified) {
rz_structured_data_map_add_unsigned(parent, "offset", object->offset, true);
rz_structured_data_map_add_unsigned(parent, "length", object->length, false);
rz_structured_data_map_add_string(parent, "form", object->form ? "cons" : "prim");
}
rz_structured_data_map_add_string(parent, "type", name);
if (!object->list.objects) {
if (RZ_STR_ISNOTEMPTY(string)) {
rz_structured_data_map_add_string(parent, "value", string);
}
rz_asn1_string_free(asn1str);
return;
}
rz_asn1_string_free(asn1str);
RzStructuredData *children = rz_structured_data_map_add_array(parent, "value");
for (ut32 i = 0; i < object->list.length; i++) {
RzStructuredData *child = rz_structured_data_array_add_map(children);
asn1_to_structure(object->list.objects[i], child, simplified);
}
}
RZ_API RZ_OWN RzStructuredData *rz_asn1_to_structure(RZ_NULLABLE RzASN1Object *object, bool simplified) {
if (!object) {
return NULL;
}
RzStructuredData *root = rz_structured_data_new_map();
if (!root) {
return NULL;
}
asn1_to_structure(object, root, simplified);
return root;
}
/**
* \brief Frees an RzASN1Object structure
*

View file

@ -1688,6 +1688,10 @@ ASN1OidListEntry known_oid_list[] = {
DEFINE_OID("1.3.6.1.4.1.8231.1", "rolUnicoNacional"),
DEFINE_OID("1.3.6.1.4.1.8301.3.5.1", "validityModelChain"),
DEFINE_OID("1.3.6.1.4.1.8301.3.5.2", "validityModelShell"),
DEFINE_OID("1.3.6.1.4.1.44947", "isrg"),
DEFINE_OID("1.3.6.1.4.1.44947.1", "letsEncrypt"),
DEFINE_OID("1.3.6.1.4.1.44947.1.1", "certificatePolicies"),
DEFINE_OID("1.3.6.1.4.1.44947.1.1.1", "isrgDomainValidated"),
DEFINE_OID("1.3.6.1.5.5.1.1", "SPKM1"),
DEFINE_OID("1.3.6.1.5.5.1.2", "SPKM2"),
DEFINE_OID("1.3.6.1.5.5.7", "pkix"),

View file

@ -167,21 +167,17 @@ RZ_API RZ_OWN RzASN1String *rz_asn1_stringify_time(RZ_NULLABLE const ut8 *buffer
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API RZ_OWN RzASN1String *rz_asn1_stringify_bits(RZ_NULLABLE const ut8 *buffer, ut32 length) {
ut32 i, j, k;
ut64 size;
ut8 c;
char *str;
if (!buffer || !length) {
if (!buffer || length < 1 || buffer[0] > length) {
return NULL;
}
size = 1 + ((length - 1) * 8) - buffer[0];
str = (char *)malloc(size);
ut64 size = 1 + ((length - 1) * 8) - buffer[0];
char *str = (char *)malloc(size);
if (!str) {
return NULL;
}
for (i = 1, j = 0; i < length && j < size; i++) {
c = buffer[i];
for (k = 0; k < 8 && j < size; k++, j++) {
for (ut32 i = 1, j = 0; i < length && j < size; i++) {
ut8 c = buffer[i];
for (ut32 k = 0; k < 8 && j < size; k++, j++) {
str[size - j - 1] = c & 0x80 ? '1' : '0';
c <<= 1;
}
@ -282,6 +278,8 @@ RZ_API RZ_OWN RzASN1String *rz_asn1_stringify_bytes(RZ_NULLABLE const ut8 *buffe
}
}
str[size - 1] = '\0';
str = rz_str_trim_tail(str);
RzASN1String *asn1str = rz_asn1_string_parse(str, true, size);
if (!asn1str) {
free(str);
@ -469,11 +467,11 @@ RZ_API RzASN1String *asn1_stringify_sector(RzASN1Object *object) {
return rz_asn1_stringify_bytes(object->sector, object->length);
}
case RZ_ASN1_TAG_BITSTRING:
// if (object->length < 8) {
return rz_asn1_stringify_bits(object->sector, object->length);
//} else {
// return asn1_stringify_bytes (object->sector, object->length);
//}
if (object->length > 0 && object->length < 20) {
return rz_asn1_stringify_bits(object->sector, object->length);
} else {
return rz_asn1_stringify_bytes(object->sector, object->length);
}
case RZ_ASN1_TAG_OCTETSTRING:
return rz_asn1_stringify_bytes(object->sector, object->length);
case RZ_ASN1_TAG_NULL:

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2017-2018 deroad <wargio@libero.it>
// SPDX-FileCopyrightText: 2017-2025 deroad <deroad@kumo.xn--q9jyb4c>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stdlib.h>
@ -343,11 +343,13 @@ RZ_API RZ_OWN RzCMS *rz_pkcs7_cms_parse(RZ_NULLABLE const ut8 *buffer, ut32 leng
* \param container The container to free
*/
RZ_API void rz_pkcs7_cms_free(RZ_NULLABLE RzCMS *container) {
if (container) {
rz_asn1_string_free(container->contentType);
pkcs7_signeddata_fini(&container->signedData);
free(container);
if (!container) {
return;
}
rz_asn1_string_free(container->contentType);
pkcs7_signeddata_fini(&container->signedData);
free(container);
}
static RzPKCS7Attribute *pkcs7_attribute_parse(RzASN1Object *object) {
@ -390,233 +392,139 @@ static bool pkcs7_attributes_parse(RzPKCS7Attributes *attributes, RzASN1Object *
return true;
}
static void pkcs7_signedinfo_dump(RzPKCS7SignerInfo *si, const char *pad, RzStrBuf *sb) {
RzASN1String *s = NULL;
RzASN1Binary *o = NULL;
char *pad2, *pad3;
static void pkcs7_attributes_to_structure(RzStructuredData *array, RzPKCS7Attribute *attribute) {
if (!attribute || !attribute->oid) {
return;
}
RzStructuredData *attr = rz_structured_data_array_add_map(array);
if (!attribute->data) {
rz_structured_data_map_add_string(attr, attribute->oid->string, "");
return;
}
RzASN1String *bytes = rz_asn1_stringify_bytes(attribute->data->binary, attribute->data->length);
if (bytes) {
rz_structured_data_map_add_string(attr, attribute->oid->string, bytes->string);
}
rz_asn1_string_free(bytes);
}
static RzStructuredData *pkcs7_signedinfo_to_structure(RzPKCS7SignerInfo *si) {
if (!si) {
return;
return NULL;
}
if (!pad) {
pad = "";
}
pad3 = rz_str_newf("%s ", pad);
if (!pad3) {
return;
}
pad2 = pad3 + 2;
rz_strbuf_appendf(sb, "%sSignerInfo:\n%sVersion: v%u\n%sIssuer\n", pad, pad2, si->version + 1, pad2);
rz_x509_name_dump(&si->issuerAndSerialNumber.issuer, pad3, sb);
if ((o = si->issuerAndSerialNumber.serialNumber)) {
s = rz_asn1_stringify_integer(o->binary, o->length);
RzStructuredData *root = rz_structured_data_new_map();
if (!root) {
return NULL;
}
rz_strbuf_appendf(sb, "%sSerial Number:\n%s%s\n", pad2, pad3, s ? s->string : "Missing");
rz_asn1_string_free(s);
s = si->digestAlgorithm.algorithm;
rz_strbuf_appendf(sb, "%sDigest Algorithm:\n%s%s\n%sAuthenticated Attributes:\n",
pad2, pad3, s ? s->string : "Missing", pad2);
rz_structured_data_map_add_signed(root, "version", si->version + 1);
for (ut32 i = 0; i < si->authenticatedAttributes.length; i++) {
RzPKCS7Attribute *attr = si->authenticatedAttributes.elements[i];
if (!attr) {
continue;
RzStructuredData *issuer = rz_structured_data_map_add_array(root, "issuer");
rz_x509_name_to_structure(issuer, &si->issuerAndSerialNumber.issuer);
if (si->issuerAndSerialNumber.serialNumber) {
RzASN1Binary *o = si->issuerAndSerialNumber.serialNumber;
RzASN1String *serial = rz_asn1_stringify_integer(o->binary, o->length);
rz_structured_data_map_add_string(root, "serialNumber", serial ? serial->string : "");
rz_asn1_string_free(serial);
}
RzStructuredData *digest_algorithm = rz_structured_data_map_add_map(root, "digestAlgorithm");
rz_x509_algorithmidentifier_to_structure(digest_algorithm, &si->digestAlgorithm);
if (si->authenticatedAttributes.length) {
RzStructuredData *authAttrbs = rz_structured_data_map_add_array(root, "authenticatedAttributes");
for (ut32 i = 0; i < si->authenticatedAttributes.length; i++) {
pkcs7_attributes_to_structure(authAttrbs, si->authenticatedAttributes.elements[i]);
}
rz_strbuf_appendf(sb, "%s%s: %u bytes\n", pad3, attr->oid ? attr->oid->string : "Missing",
attr->data ? attr->data->length : 0);
}
s = si->digestEncryptionAlgorithm.algorithm;
rz_strbuf_appendf(sb, "%sDigest Encryption Algorithm\n%s%s\n", pad2, pad3, s ? s->string : "Missing");
// if ((o = si->encryptedDigest)) s = rz_asn1_stringify_bytes (o->binary, o->length);
// else s = NULL;
// eprintf ("%sEncrypted Digest: %u bytes\n%s\n", pad2, o ? o->length : 0, s ? s->string : "Missing");
// rz_asn1_string_free (s);
rz_strbuf_appendf(sb, "%sEncrypted Digest: %u bytes\n", pad2, o ? o->length : 0);
rz_strbuf_appendf(sb, "%sUnauthenticated Attributes:\n", pad2);
for (ut32 i = 0; i < si->unauthenticatedAttributes.length; i++) {
RzPKCS7Attribute *attr = si->unauthenticatedAttributes.elements[i];
if (!attr) {
continue;
}
o = attr->data;
eprintf("%s%s: %u bytes\n", pad3, attr->oid ? attr->oid->string : "Missing",
o ? o->length : 0);
RzStructuredData *digest_enc_algo = rz_structured_data_map_add_map(root, "digestEncryptionAlgorithm");
rz_x509_algorithmidentifier_to_structure(digest_enc_algo, &si->digestEncryptionAlgorithm);
if (si->encryptedDigest) {
RzASN1String *bytes = rz_asn1_stringify_bytes(si->encryptedDigest->binary, si->encryptedDigest->length);
rz_structured_data_map_add_string(root, "encryptedDigest", bytes->string);
rz_asn1_string_free(bytes);
}
free(pad3);
if (si->unauthenticatedAttributes.length) {
RzStructuredData *unauthAttrbs = rz_structured_data_map_add_array(root, "unauthenticatedAttributes");
for (ut32 i = 0; i < si->unauthenticatedAttributes.length; i++) {
pkcs7_attributes_to_structure(unauthAttrbs, si->unauthenticatedAttributes.elements[i]);
}
}
return root;
}
/**
* \brief Converts a Cryptographic Message Syntax (or CMS) into a human readable string
* \brief Returns the Cryptographic Message Syntax (or CMS) as RzStructuredData
*
* \param container The container to be converted to string
* \param container The container to be converted to RzStructuredData
*
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API RZ_OWN char *rz_pkcs7_cms_to_string(RZ_NULLABLE RzCMS *container) {
RZ_API RZ_OWN RzStructuredData *rz_pkcs7_cms_to_structure(RZ_NULLABLE RzCMS *container) {
if (!container) {
return NULL;
}
RzPKCS7SignedData *sd = &container->signedData;
RzStrBuf *sb = rz_strbuf_new("");
rz_strbuf_appendf(sb, "signedData\n Version: v%u\n Digest Algorithms:\n", sd->version);
RzStructuredData *root = rz_structured_data_new_map();
if (!root) {
return NULL;
}
RzStructuredData *signed_data = rz_structured_data_map_add_map(root, "signedData");
rz_structured_data_map_add_signed(signed_data, "version", sd->version);
if (container->signedData.digestAlgorithms.elements) {
RzStructuredData *digest_algos = rz_structured_data_map_add_array(signed_data, "digestAlgorithms");
for (ut32 i = 0; i < container->signedData.digestAlgorithms.length; i++) {
if (container->signedData.digestAlgorithms.elements[i]) {
RzASN1String *s = container->signedData.digestAlgorithms.elements[i]->algorithm;
rz_strbuf_appendf(sb, " %s\n", s ? s->string : "Missing");
if (!container->signedData.digestAlgorithms.elements[i]) {
continue;
}
RzStructuredData *digest = rz_structured_data_array_add_map(digest_algos);
rz_x509_algorithmidentifier_to_structure(digest, container->signedData.digestAlgorithms.elements[i]);
}
}
rz_strbuf_appendf(sb, " Certificates: %u\n", container->signedData.certificates.length);
for (ut32 i = 0; i < container->signedData.certificates.length; i++) {
rz_x509_certificate_dump(container->signedData.certificates.elements[i], " ", sb);
}
for (ut32 i = 0; i < container->signedData.crls.length; i++) {
char *res = rz_x509_crl_to_string(container->signedData.crls.elements[i], " ");
if (res) {
rz_strbuf_append(sb, res);
free(res);
}
}
rz_strbuf_appendf(sb, " SignerInfos:\n");
if (container->signedData.signerinfos.elements) {
for (ut32 i = 0; i < container->signedData.signerinfos.length; i++) {
pkcs7_signedinfo_dump(container->signedData.signerinfos.elements[i], " ", sb);
}
}
return rz_strbuf_drain(sb);
}
static void pkcs7_signedinfo_json(PJ *pj, RzPKCS7SignerInfo *si) {
if (!si) {
return;
}
pj_o(pj);
pj_ki(pj, "Version", si->version + 1);
pj_k(pj, "Issuer");
pj_o(pj);
rz_x509_name_json(pj, &si->issuerAndSerialNumber.issuer);
pj_end(pj);
if (si->issuerAndSerialNumber.serialNumber) {
RzASN1Binary *o = si->issuerAndSerialNumber.serialNumber;
RzASN1String *s = rz_asn1_stringify_integer(o->binary, o->length);
if (s) {
pj_ks(pj, "SerialNumber", s->string);
}
rz_asn1_string_free(s);
}
if (si->digestAlgorithm.algorithm) {
pj_ks(pj, "DigestAlgorithm", si->digestAlgorithm.algorithm->string);
}
pj_k(pj, "AuthenticatedAttributes");
pj_a(pj);
for (ut32 i = 0; i < si->authenticatedAttributes.length; i++) {
RzPKCS7Attribute *attr = si->authenticatedAttributes.elements[i];
if (!attr) {
continue;
}
pj_o(pj);
if (attr->oid) {
pj_ks(pj, "oid", attr->oid->string);
}
if (attr->data) {
pj_ki(pj, "length", attr->data->length);
}
pj_end(pj);
}
pj_end(pj);
if (si->digestEncryptionAlgorithm.algorithm) {
pj_ks(pj, "DigestEncryptionAlgorithm", si->digestEncryptionAlgorithm.algorithm->string);
}
if (si->encryptedDigest) {
RzASN1Binary *o = si->encryptedDigest;
RzASN1String *s = rz_asn1_stringify_integer(o->binary, o->length);
if (s) {
pj_ks(pj, "EncryptedDigest", s->string);
}
rz_asn1_string_free(s);
}
pj_k(pj, "UnauthenticatedAttributes");
pj_a(pj);
for (ut32 i = 0; i < si->unauthenticatedAttributes.length; i++) {
RzPKCS7Attribute *attr = si->unauthenticatedAttributes.elements[i];
if (!attr) {
continue;
}
pj_o(pj);
if (attr->oid) {
pj_ks(pj, "oid", attr->oid->string);
}
if (attr->data) {
pj_ki(pj, "length", attr->data->length);
}
pj_end(pj);
}
pj_end(pj);
pj_end(pj);
}
/**
* \brief Converts a Cryptographic Message Syntax (or CMS) into a JSON object
*
* \param container The container to be converted to json
*/
RZ_API void rz_pkcs7_cms_json(RZ_NULLABLE RzCMS *container, RZ_NONNULL PJ *pj) {
rz_return_if_fail(pj);
if (!container) {
return;
}
pj_o(pj);
pj_kn(pj, "Version", container->signedData.version);
if (container->signedData.digestAlgorithms.elements) {
pj_k(pj, "DigestAlgorithms");
pj_a(pj);
for (ut32 i = 0; i < container->signedData.digestAlgorithms.length; i++) {
if (container->signedData.digestAlgorithms.elements[i]) {
RzASN1String *s = container->signedData.digestAlgorithms.elements[i]->algorithm;
if (s) {
pj_s(pj, s->string);
}
if (container->signedData.certificates.length) {
RzStructuredData *certificates = rz_structured_data_map_add_array(signed_data, "certificates");
for (ut32 i = 0; i < container->signedData.certificates.length; i++) {
RzStructuredData *cert = rz_x509_certificate_to_structure(container->signedData.certificates.elements[i]);
if (!cert) {
continue;
}
rz_structured_data_array_add(certificates, cert);
}
pj_end(pj);
}
pj_k(pj, "Certificates");
pj_a(pj);
for (ut32 i = 0; i < container->signedData.certificates.length; i++) {
rz_x509_certificate_json(pj, container->signedData.certificates.elements[i]);
if (container->signedData.crls.length) {
RzStructuredData *crls = rz_structured_data_map_add_array(signed_data, "crls");
for (ut32 i = 0; i < container->signedData.crls.length; i++) {
RzStructuredData *crl = rz_x509_crl_to_structure(container->signedData.crls.elements[i]);
if (!crl) {
continue;
}
rz_structured_data_array_add(crls, crl);
}
}
pj_end(pj);
pj_k(pj, "CRL");
pj_a(pj);
for (ut32 i = 0; i < container->signedData.crls.length; i++) {
rz_x509_crl_json(pj, container->signedData.crls.elements[i]);
}
pj_end(pj);
pj_k(pj, "SignerInfos");
pj_a(pj);
if (container->signedData.signerinfos.elements) {
RzStructuredData *sig_infos = rz_structured_data_map_add_array(signed_data, "signerInfos");
for (ut32 i = 0; i < container->signedData.signerinfos.length; i++) {
pkcs7_signedinfo_json(pj, container->signedData.signerinfos.elements[i]);
RzStructuredData *sig_info = pkcs7_signedinfo_to_structure(container->signedData.signerinfos.elements[i]);
if (!sig_info) {
continue;
}
rz_structured_data_array_add(sig_infos, sig_info);
}
}
pj_end(pj);
pj_end(pj);
return root;
}
static bool pkcs7_spcdata_parse(RzSpcAttributeTypeAndOptionalValue *data, RzASN1Object *object) {
@ -727,3 +635,54 @@ RZ_API void rz_pkcs7_spcinfo_free(RZ_NULLABLE RzSpcIndirectDataContent *spcinfo)
pkcs7_spcmessagedigest_fini(&spcinfo->messageDigest);
free(spcinfo);
}
/**
* \brief Returns the SPC structure as RzStructuredData
*
* \param container The container to be converted to RzStructuredData
*
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API RZ_OWN RzStructuredData *rz_pkcs7_spcinfo_to_structure(RZ_NULLABLE RzSpcIndirectDataContent *spcinfo) {
if (!spcinfo) {
return NULL;
}
RzStructuredData *root = rz_structured_data_new_map();
if (!root) {
return NULL;
}
RzStructuredData *spc_attribute = rz_structured_data_map_add_map(root, "spcAttribute");
if (spcinfo->data.type) {
rz_structured_data_map_add_string(spc_attribute, "type", spcinfo->data.type->string);
}
if (spcinfo->data.data) {
RzASN1Binary *opt = spcinfo->data.data;
RzASN1String *asn1str = NULL;
if (rz_str_is_printable_limited((const char *)opt->binary, opt->length)) {
asn1str = rz_asn1_stringify_string(opt->binary, opt->length);
} else {
asn1str = rz_asn1_stringify_bytes(opt->binary, opt->length);
}
if (asn1str) {
rz_structured_data_map_add_string(spc_attribute, "data", asn1str->string);
rz_asn1_string_free(asn1str);
}
}
RzStructuredData *message_digest = rz_structured_data_map_add_map(root, "messageDigest");
RzStructuredData *digest_algorithm = rz_structured_data_map_add_map(message_digest, "digestAlgorithm");
rz_x509_algorithmidentifier_to_structure(digest_algorithm, &spcinfo->messageDigest.digestAlgorithm);
if (spcinfo->messageDigest.digest) {
RzASN1Binary *opt = spcinfo->messageDigest.digest;
RzASN1String *asn1str = rz_asn1_stringify_bytes(opt->binary, opt->length);
if (asn1str) {
rz_structured_data_map_add_string(message_digest, "digest", asn1str->string);
rz_asn1_string_free(asn1str);
}
}
return root;
}

View file

@ -2153,9 +2153,11 @@ RZ_API bool rz_str_is_printable(const char *str) {
return true;
}
RZ_API bool rz_str_is_printable_limited(const char *str, int size) {
RZ_API bool rz_str_is_printable_limited(RZ_NONNULL const char *str, size_t size) {
rz_return_val_if_fail(str, false);
while (size > 0 && *str) {
int ulen = rz_utf8_decode((const ut8 *)str, strlen(str), NULL, true);
int ulen = rz_utf8_decode((const ut8 *)str, size, NULL, true);
if (ulen > 1) {
str += ulen;
continue;

View file

@ -550,6 +550,18 @@ RZ_API void rz_structured_data_iterate(RZ_NONNULL const RzStructuredData *sd, RZ
structured_data_iterate_over(&sdio, sd);
}
/**
* \brief Iterates over a given RzStructuredData and generates a json string
*
* \param[in] sd The RzStructuredData to iterate over
* \param[in] pj The PJ to write into
*/
RZ_API void rz_structured_data_to_pj(RZ_NONNULL const RzStructuredData *sd, RZ_NONNULL PJ *pj) {
rz_return_if_fail(sd && pj);
rz_structured_data_iterate(sd, &builder_json_iterator, pj);
}
/**
* \brief Iterates over a given RzStructuredData and generates a json string
*

View file

@ -42,14 +42,16 @@ static void builder_yaml_new_struct(RZ_NULLABLE void *user, RzStructuredDataBloc
if (yaml->depth > 0) {
if (n_elems < 1) {
rz_strbuf_append(&yaml->sb, block == RZ_STRUCTURED_DATA_BLOCK_ARRAY ? " []\n" : " {}\n");
yaml->first = false;
} else if (builder_yaml_is_array(yaml)) {
builder_yaml_add_padding(yaml);
rz_strbuf_append(&yaml->sb, "-");
yaml->first = true;
} else {
rz_strbuf_append(&yaml->sb, "\n");
yaml->first = true;
}
}
yaml->first = true;
yaml->depth++;
yaml->stack[yaml->depth - 1] = (ut8)block;
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2017-2018 deroad <wargio@libero.it>
// SPDX-FileCopyrightText: 2017-2025 deroad <deroad@kumo.xn--q9jyb4c>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_util.h>
@ -41,7 +41,7 @@ static inline bool is_oid_object(RzASN1Object *object) {
object->list.objects[0]->tag == RZ_ASN1_TAG_OID;
}
RZ_IPI bool rz_x509_algorithmidentifier_parse(RzX509AlgorithmIdentifier *ai, RzASN1Object *object) {
RZ_IPI bool rz_x509_algorithmidentifier_parse(RZ_NONNULL RzX509AlgorithmIdentifier *ai, RZ_NONNULL RzASN1Object *object) {
rz_return_val_if_fail(ai && object, false);
if (object->list.length < 1 || !object->list.objects || !is_oid_object(object)) {
@ -49,8 +49,11 @@ RZ_IPI bool rz_x509_algorithmidentifier_parse(RzX509AlgorithmIdentifier *ai, RzA
}
ai->algorithm = rz_asn1_stringify_oid(object->list.objects[0]->sector, object->list.objects[0]->length);
ai->parameters = NULL; // TODO
// ai->parameters = asn1_stringify_sector (object->list.objects[1]);
if (object->list.length < 2 || !object->list.objects[1]) {
return true;
}
ai->parameters = rz_asn1_binary_parse(object->list.objects[1]->sector, object->list.objects[1]->length);
return true;
}
@ -76,8 +79,7 @@ static bool x509_subjectpublickeyinfo_parse(RzX509SubjectPublicKeyInfo *spki, Rz
return true;
}
RZ_IPI bool rz_x509_name_parse(RzX509Name *name, RzASN1Object *object) {
ut32 i;
RZ_IPI bool rz_x509_name_parse(RZ_NULLABLE RzX509Name *name, RZ_NULLABLE RzASN1Object *object) {
if (!name || !object || !object->list.length) {
return false;
}
@ -94,7 +96,7 @@ RZ_IPI bool rz_x509_name_parse(RzX509Name *name, RzASN1Object *object) {
RZ_FREE(name->names);
return false;
}
for (i = 0; i < object->list.length; i++) {
for (ut32 i = 0; i < object->list.length; i++) {
RzASN1Object *o = object->list.objects[i];
if (o && o->klass == RZ_ASN1_CLASS_UNIVERSAL &&
o->tag == RZ_ASN1_TAG_SET &&
@ -146,12 +148,11 @@ static void x509_extension_free(RzX509Extension *ex) {
}
rz_asn1_string_free(ex->extnID);
rz_asn1_binary_free(ex->extnValue);
// this is allocated dinamically so, i'll free
// this is allocated dynamically so, i'll free
free(ex);
}
static bool x509_extensions_parse(RzX509Extensions *ext, RzASN1Object *object) {
ut32 i;
if (!ext || !object || object->list.length != 1 || !object->list.objects[0]->length) {
return false;
}
@ -161,7 +162,7 @@ static bool x509_extensions_parse(RzX509Extensions *ext, RzASN1Object *object) {
return false;
}
ext->length = object->list.length;
for (i = 0; i < object->list.length; i++) {
for (ut32 i = 0; i < object->list.length; i++) {
ext->extensions[i] = RZ_NEW0(RzX509Extension);
if (!x509_extension_parse(ext->extensions[i], object->list.objects[i])) {
x509_extension_free(ext->extensions[i]);
@ -173,7 +174,6 @@ static bool x509_extensions_parse(RzX509Extensions *ext, RzASN1Object *object) {
static bool x509_tbscertificate_parse(RzX509TBSCertificate *tbsc, RzASN1Object *object) {
RzASN1Object **elems;
ut32 i;
ut32 shift = 0;
if (!tbsc || !object || object->list.length < 6) {
return false;
@ -205,20 +205,23 @@ static bool x509_tbscertificate_parse(RzX509TBSCertificate *tbsc, RzASN1Object *
rz_x509_validity_parse(&tbsc->validity, elems[shift + 3]);
rz_x509_name_parse(&tbsc->subject, elems[shift + 4]);
x509_subjectpublickeyinfo_parse(&tbsc->subjectPublicKeyInfo, elems[shift + 5]);
if (tbsc->version > 0) {
for (i = shift + 6; i < object->list.length; i++) {
if (!elems[i] || elems[i]->klass != RZ_ASN1_CLASS_CONTEXT) {
continue;
}
if (elems[i]->tag == 1) {
tbsc->issuerUniqueID = rz_asn1_binary_parse(elems[i]->sector, elems[i]->length);
}
if (elems[i]->tag == 2) {
tbsc->subjectUniqueID = rz_asn1_binary_parse(elems[i]->sector, elems[i]->length);
}
if (tbsc->version == 2 && elems[i]->tag == 3 && elems[i]->form == RZ_ASN1_FORM_CONSTRUCTED) {
x509_extensions_parse(&tbsc->extensions, elems[i]);
}
if (tbsc->version < 1) {
return true;
}
for (ut32 i = shift + 6; i < object->list.length; i++) {
if (!elems[i] || elems[i]->klass != RZ_ASN1_CLASS_CONTEXT) {
continue;
}
if (elems[i]->tag == 1) {
tbsc->issuerUniqueID = rz_asn1_binary_parse(elems[i]->sector, elems[i]->length);
}
if (elems[i]->tag == 2) {
tbsc->subjectUniqueID = rz_asn1_binary_parse(elems[i]->sector, elems[i]->length);
}
if (tbsc->version == 2 && elems[i]->tag == 3 && elems[i]->form == RZ_ASN1_FORM_CONSTRUCTED) {
x509_extensions_parse(&tbsc->extensions, elems[i]);
}
}
return true;
@ -333,60 +336,57 @@ RZ_API RZ_OWN RzX509CertificateRevocationList *rz_x509_crl_parse(RZ_NULLABLE RzA
crl->lastUpdate = rz_asn1_stringify_utctime(elems[2]->sector, elems[2]->length);
crl->nextUpdate = rz_asn1_stringify_utctime(elems[3]->sector, elems[3]->length);
if (object->list.length > 4 && object->list.objects[4]) {
ut32 i;
crl->revokedCertificates = calloc(object->list.objects[4]->list.length, sizeof(RzX509CRLEntry *));
if (!crl->revokedCertificates) {
free(crl);
return NULL;
}
crl->length = object->list.objects[4]->list.length;
for (i = 0; i < object->list.objects[4]->list.length; i++) {
for (ut32 i = 0; i < object->list.objects[4]->list.length; i++) {
crl->revokedCertificates[i] = x509_crlentry_parse(object->list.objects[4]->list.objects[i]);
}
}
return crl;
}
RZ_IPI void rz_x509_algorithmidentifier_fini(RzX509AlgorithmIdentifier *ai) {
if (ai) {
// no need to free ai, since this functions is used internally
rz_asn1_string_free(ai->algorithm);
rz_asn1_string_free(ai->parameters);
RZ_IPI void rz_x509_algorithmidentifier_fini(RZ_NULLABLE RzX509AlgorithmIdentifier *ai) {
if (!ai) {
return;
}
// no need to free ai, since this functions is used internally
rz_asn1_string_free(ai->algorithm);
rz_asn1_binary_free(ai->parameters);
}
static void x509_validity_fini(RzX509Validity *validity) {
if (!validity) {
return;
}
// not freeing validity since it's not allocated dinamically
// not freeing validity since it's not allocated dynamically
rz_asn1_string_free(validity->notAfter);
rz_asn1_string_free(validity->notBefore);
}
RZ_IPI void rz_x509_name_fini(RzX509Name *name) {
ut32 i;
if (!name) {
RZ_IPI void rz_x509_name_fini(RZ_NULLABLE RzX509Name *name) {
// not freeing name since it's not allocated dynamically
if (!name || !name->names) {
return;
}
if (name->names) {
for (i = 0; i < name->length; i++) {
rz_asn1_string_free(name->oids[i]);
rz_asn1_string_free(name->names[i]);
}
RZ_FREE(name->names);
RZ_FREE(name->oids);
for (ut32 i = 0; i < name->length; i++) {
rz_asn1_string_free(name->oids[i]);
rz_asn1_string_free(name->names[i]);
}
// not freeing name since it's not allocated dinamically
RZ_FREE(name->names);
RZ_FREE(name->oids);
}
static void x509_extensions_fini(RzX509Extensions *ex) {
ut32 i;
if (!ex) {
return;
}
if (ex->extensions) {
for (i = 0; i < ex->length; i++) {
for (ut32 i = 0; i < ex->length; i++) {
x509_extension_free(ex->extensions[i]);
}
free(ex->extensions);
@ -446,8 +446,7 @@ static void x509_crlentry_free(RzX509CRLEntry *entry) {
free(entry);
}
RZ_IPI void rz_x509_crl_free(RzX509CertificateRevocationList *crl) {
ut32 i;
RZ_IPI void rz_x509_crl_free(RZ_NULLABLE RzX509CertificateRevocationList *crl) {
if (!crl) {
return;
}
@ -456,7 +455,7 @@ RZ_IPI void rz_x509_crl_free(RzX509CertificateRevocationList *crl) {
rz_asn1_string_free(crl->nextUpdate);
rz_asn1_string_free(crl->lastUpdate);
if (crl->revokedCertificates) {
for (i = 0; i < crl->length; i++) {
for (ut32 i = 0; i < crl->length; i++) {
x509_crlentry_free(crl->revokedCertificates[i]);
crl->revokedCertificates[i] = NULL;
}
@ -465,303 +464,7 @@ RZ_IPI void rz_x509_crl_free(RzX509CertificateRevocationList *crl) {
free(crl);
}
static void x509_validity_dump(RzX509Validity *validity, const char *pad, RzStrBuf *sb) {
if (!validity) {
return;
}
if (!pad) {
pad = "";
}
const char *b = validity->notBefore ? validity->notBefore->string : "Missing";
const char *a = validity->notAfter ? validity->notAfter->string : "Missing";
rz_strbuf_appendf(sb, "%sNot Before: %s\n%sNot After: %s\n", pad, b, pad, a);
}
RZ_IPI void rz_x509_name_dump(RzX509Name *name, const char *pad, RzStrBuf *sb) {
ut32 i;
if (!name) {
return;
}
if (!pad) {
pad = "";
}
for (i = 0; i < name->length; i++) {
if (!name->oids[i] || !name->names[i]) {
continue;
}
rz_strbuf_appendf(sb, "%s%s: %s\n", pad, name->oids[i]->string, name->names[i]->string);
}
}
static void x509_subjectpublickeyinfo_dump(RzX509SubjectPublicKeyInfo *spki, const char *pad, RzStrBuf *sb) {
const char *a;
if (!spki) {
return;
}
if (!pad) {
pad = "";
}
a = spki->algorithm.algorithm ? spki->algorithm.algorithm->string : "Missing";
RzASN1String *m = NULL;
if (spki->subjectPublicKeyModule) {
m = rz_asn1_stringify_integer(spki->subjectPublicKeyModule->binary, spki->subjectPublicKeyModule->length);
}
// RzASN1String* e = rz_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);
rz_strbuf_appendf(sb, "%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);
rz_asn1_string_free(m);
// rz_asn1_string_free (e);
}
static void x509_extensions_dump(RzX509Extensions *exts, const char *pad, RzStrBuf *sb) {
ut32 i;
if (!exts) {
return;
}
if (!pad) {
pad = "";
}
for (i = 0; i < exts->length; i++) {
RzX509Extension *e = exts->extensions[i];
if (!e) {
continue;
}
// TODO handle extensions..
// s = rz_asn1_stringify_bytes (e->extnValue->sector, e->extnValue->length);
rz_strbuf_appendf(sb, "%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);
// rz_asn1_string_free (s);
}
}
static void x509_tbscertificate_dump(RzX509TBSCertificate *tbsc, const char *pad, RzStrBuf *sb) {
RzASN1String *sid = NULL, *iid = NULL;
if (!tbsc) {
return;
}
if (!pad) {
pad = "";
}
char *pad2 = rz_str_newf("%s ", pad);
if (!pad2) {
return;
}
rz_strbuf_appendf(sb, "%sVersion: v%u\n"
"%sSerial Number:\n%s %s\n"
"%sSignature Algorithm:\n%s %s\n"
"%sIssuer:\n",
pad, tbsc->version + 1,
pad, pad, tbsc->serialNumber ? tbsc->serialNumber->string : "Missing",
pad, pad, tbsc->signature.algorithm ? tbsc->signature.algorithm->string : "Missing",
pad);
rz_x509_name_dump(&tbsc->issuer, pad2, sb);
rz_strbuf_appendf(sb, "%sValidity:\n", pad);
x509_validity_dump(&tbsc->validity, pad2, sb);
rz_strbuf_appendf(sb, "%sSubject:\n", pad);
rz_x509_name_dump(&tbsc->subject, pad2, sb);
rz_strbuf_appendf(sb, "%sSubject Public Key Info:\n", pad);
x509_subjectpublickeyinfo_dump(&tbsc->subjectPublicKeyInfo, pad2, sb);
if (tbsc->issuerUniqueID) {
iid = rz_asn1_stringify_integer(tbsc->issuerUniqueID->binary, tbsc->issuerUniqueID->length);
if (iid) {
rz_strbuf_appendf(sb, "%sIssuer Unique ID:\n%s %s", pad, pad, iid->string);
rz_asn1_string_free(iid);
}
}
if (tbsc->subjectUniqueID) {
sid = rz_asn1_stringify_integer(tbsc->subjectUniqueID->binary, tbsc->subjectUniqueID->length);
if (sid) {
rz_strbuf_appendf(sb, "%sSubject Unique ID:\n%s %s", pad, pad, sid->string);
rz_asn1_string_free(sid);
}
}
rz_strbuf_appendf(sb, "%sExtensions:\n", pad);
x509_extensions_dump(&tbsc->extensions, pad2, sb);
free(pad2);
}
/**
* \brief Converts a certificate into a human readable string
*
* \param cert The certificate to convert
* \param[in] pad The padding to use for the string
* \param sb The RzStrBuf to write to
*/
RZ_API void rz_x509_certificate_dump(RZ_NULLABLE RzX509Certificate *cert, RZ_NULLABLE const char *pad, RZ_NONNULL RzStrBuf *sb) {
rz_return_if_fail(sb);
RzASN1String *algo = NULL;
char *pad2;
if (!cert) {
return;
}
if (!pad) {
pad = "";
}
pad2 = rz_str_newf("%s ", pad);
if (!pad2) {
return;
}
rz_strbuf_appendf(sb, "%sTBSCertificate:\n", pad);
x509_tbscertificate_dump(&cert->tbsCertificate, pad2, sb);
algo = cert->algorithmIdentifier.algorithm;
rz_strbuf_appendf(sb, "%sAlgorithm:\n%s%s\n%sSignature: %u bytes\n",
pad, pad2, algo ? algo->string : "", pad, cert->signature->length);
free(pad2);
}
static void x509_crlentry_dump(RzX509CRLEntry *crle, const char *pad, RzStrBuf *sb) {
RzASN1String *id = NULL, *utc = NULL;
if (!crle) {
return;
}
if (!pad) {
pad = "";
}
utc = crle->revocationDate;
if (crle->userCertificate) {
id = rz_asn1_stringify_integer(crle->userCertificate->binary, crle->userCertificate->length);
}
rz_strbuf_appendf(sb, "%sUser Certificate:\n%s %s\n"
"%sRevocation Date:\n%s %s\n",
pad, pad, id ? id->string : "Missing",
pad, pad, utc ? utc->string : "Missing");
rz_asn1_string_free(id);
}
/**
* \brief Converts a certificate revocation list (or CRL) into human readable string
*
* \param crl The crl to convert to a string
* \param[in] pad The padding to use for the spacing
*
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API RZ_OWN char *rz_x509_crl_to_string(RZ_NULLABLE RzX509CertificateRevocationList *crl, RZ_NULLABLE const char *pad) {
RzASN1String *algo = NULL, *last = NULL, *next = NULL;
ut32 i;
char *pad2, *pad3;
if (!crl) {
return NULL;
}
if (!pad) {
pad = "";
}
pad3 = rz_str_newf("%s ", pad);
if (!pad3) {
return NULL;
}
pad2 = pad3 + 2;
algo = crl->signature.algorithm;
last = crl->lastUpdate;
next = crl->nextUpdate;
RzStrBuf *sb = rz_strbuf_new("");
rz_strbuf_appendf(sb, "%sCRL:\n%sSignature:\n%s%s\n%sIssuer\n", pad, pad2, pad3,
algo ? algo->string : "", pad2);
rz_x509_name_dump(&crl->issuer, pad3, sb);
rz_strbuf_appendf(sb, "%sLast Update: %s\n%sNext Update: %s\n%sRevoked Certificates:\n",
pad2, last ? last->string : "Missing",
pad2, next ? next->string : "Missing", pad2);
for (i = 0; i < crl->length; i++) {
x509_crlentry_dump(crl->revokedCertificates[i], pad3, sb);
}
free(pad3);
return rz_strbuf_drain(sb);
}
static void x509_validity_json(PJ *pj, RzX509Validity *validity) {
if (!validity) {
return;
}
if (validity->notBefore) {
pj_ks(pj, "NotBefore", validity->notBefore->string);
}
if (validity->notAfter) {
pj_ks(pj, "NotAfter", validity->notAfter->string);
}
}
RZ_IPI void rz_x509_name_json(PJ *pj, RzX509Name *name) {
ut32 i;
for (i = 0; i < name->length; i++) {
if (!name->oids[i] || !name->names[i]) {
continue;
}
pj_ks(pj, name->oids[i]->string, name->names[i]->string);
}
}
static void x509_subjectpublickeyinfo_json(PJ *pj, RzX509SubjectPublicKeyInfo *spki) {
RzASN1String *m = NULL;
if (!spki) {
return;
}
if (spki->algorithm.algorithm) {
pj_ks(pj, "Algorithm", spki->algorithm.algorithm->string);
}
if (spki->subjectPublicKeyModule) {
m = rz_asn1_stringify_integer(spki->subjectPublicKeyModule->binary, spki->subjectPublicKeyModule->length);
if (m) {
pj_ks(pj, "Module", m->string);
}
rz_asn1_string_free(m);
}
if (spki->subjectPublicKeyExponent) {
m = rz_asn1_stringify_integer(spki->subjectPublicKeyExponent->binary, spki->subjectPublicKeyExponent->length);
if (m) {
pj_ks(pj, "Exponent", m->string);
}
rz_asn1_string_free(m);
}
}
static void x509_extensions_json(PJ *pj, RzX509Extensions *exts) {
if (!exts) {
return;
}
RzASN1String *m = NULL;
ut32 i;
pj_a(pj);
for (i = 0; i < exts->length; i++) {
RzX509Extension *e = exts->extensions[i];
if (!e) {
continue;
}
pj_o(pj);
if (e->extnID) {
pj_ks(pj, "OID", e->extnID->string);
}
if (e->critical) {
pj_kb(pj, "Critical", e->critical);
}
// TODO handle extensions correctly..
if (e->extnValue) {
m = rz_asn1_stringify_integer(e->extnValue->binary, e->extnValue->length);
if (m) {
pj_ks(pj, "Value", m->string);
}
rz_asn1_string_free(m);
}
pj_end(pj);
}
pj_end(pj);
pj_end(pj);
}
static void x509_crlentry_json(PJ *pj, RzX509CRLEntry *crle) {
static void x509_crlentry_to_structure(RzStructuredData *parent, RzX509CRLEntry *crle) {
RzASN1String *m = NULL;
if (!crle) {
return;
@ -770,121 +473,265 @@ static void x509_crlentry_json(PJ *pj, RzX509CRLEntry *crle) {
if (crle->userCertificate) {
m = rz_asn1_stringify_integer(crle->userCertificate->binary, crle->userCertificate->length);
if (m) {
pj_ks(pj, "UserCertificate", m->string);
rz_structured_data_map_add_string(parent, "userCertificate", m->string);
}
rz_asn1_string_free(m);
}
if (crle->revocationDate) {
pj_ks(pj, "RevocationDate", crle->revocationDate->string);
rz_structured_data_map_add_string(parent, "revocationDate", crle->revocationDate->string);
}
}
/**
* \brief Converts a certificate revocation list (or CRL) into a json structure
*
* \param pj The PJ pointer to write to
* \param crl The crl to convert to json
*/
RZ_API void rz_x509_crl_json(RZ_NONNULL PJ *pj, RZ_NULLABLE RzX509CertificateRevocationList *crl) {
rz_return_if_fail(pj);
ut32 i;
if (!crl) {
RZ_IPI void rz_x509_algorithmidentifier_to_structure(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const RzX509AlgorithmIdentifier *ai) {
rz_return_if_fail(parent && ai);
if (ai->algorithm) {
rz_structured_data_map_add_string(parent, "algorithm", ai->algorithm->string);
}
if (!ai->parameters) {
return;
}
RzASN1Object *object = rz_asn1_object_parse(ai->parameters->binary, ai->parameters->length);
if (object) {
RzStructuredData *params = rz_asn1_to_structure(object, true);
rz_asn1_object_free(object);
rz_structured_data_map_add(parent, "parameters", params);
return;
}
if (crl->signature.algorithm) {
pj_ks(pj, "Signature", crl->signature.algorithm->string);
RzASN1String *params = NULL;
if (rz_str_is_printable_limited((const char *)ai->parameters->binary, ai->parameters->length)) {
params = rz_asn1_stringify_string(ai->parameters->binary, ai->parameters->length);
} else {
params = rz_asn1_stringify_bytes(ai->parameters->binary, ai->parameters->length);
}
pj_k(pj, "Issuer");
pj_o(pj);
rz_x509_name_json(pj, &crl->issuer);
pj_end(pj);
if (crl->lastUpdate) {
pj_ks(pj, "LastUpdate", crl->lastUpdate->string);
}
if (crl->nextUpdate) {
pj_ks(pj, "NextUpdate", crl->nextUpdate->string);
}
pj_k(pj, "RevokedCertificates");
pj_a(pj);
for (i = 0; i < crl->length; i++) {
x509_crlentry_json(pj, crl->revokedCertificates[i]);
}
pj_end(pj);
rz_structured_data_map_add_string(parent, "parameters", params->string);
rz_asn1_string_free(params);
}
static void x509_tbscertificate_json(PJ *pj, RzX509TBSCertificate *tbsc) {
pj_o(pj);
/**
* \brief Converts a certificate revocation list (or CRL) into RzStructuredData
*
* \param crl The crl to convert to a RzStructuredData
*
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API RZ_OWN RzStructuredData *rz_x509_crl_to_structure(RZ_NULLABLE RzX509CertificateRevocationList *crl) {
if (!crl) {
return NULL;
}
RzStructuredData *root = rz_structured_data_new_map();
if (!root) {
return NULL;
}
RzASN1String *lastUpdate = crl->lastUpdate;
RzASN1String *nextUpdate = crl->nextUpdate;
RzStructuredData *signature = rz_structured_data_map_add_map(root, "signature");
rz_x509_algorithmidentifier_to_structure(signature, &crl->signature);
RzStructuredData *issuer = rz_structured_data_map_add_array(root, "issuer");
rz_x509_name_to_structure(issuer, &crl->issuer);
if (lastUpdate) {
rz_structured_data_map_add_string(root, "lastUpdate", lastUpdate->string);
}
if (nextUpdate) {
rz_structured_data_map_add_string(root, "nextUpdate", nextUpdate->string);
}
RzStructuredData *revokedCerts = rz_structured_data_map_add_array(root, "revokedCertificates");
for (ut32 i = 0; i < crl->length; i++) {
RzStructuredData *revoked = rz_structured_data_array_add_map(revokedCerts);
x509_crlentry_to_structure(revoked, crl->revokedCertificates[i]);
}
return root;
}
static void x509_validity_to_structure(RzStructuredData *parent, RzX509Validity *validity) {
if (!validity) {
return;
}
if (validity->notBefore) {
rz_structured_data_map_add_string(parent, "notBefore", validity->notBefore->string);
}
if (validity->notAfter) {
rz_structured_data_map_add_string(parent, "notAfter", validity->notAfter->string);
}
}
RZ_IPI void rz_x509_name_to_structure(RZ_NULLABLE RzStructuredData *array, RZ_NULLABLE RzX509Name *name) {
if (!array || !name) {
return;
}
for (ut32 i = 0; i < name->length; i++) {
if (!name->oids[i] || !name->names[i]) {
continue;
}
RzStructuredData *entry = rz_structured_data_array_add_map(array);
rz_structured_data_map_add_string(entry, "oid", name->oids[i]->string);
rz_structured_data_map_add_string(entry, "value", name->names[i]->string);
}
}
static void x509_subjectpublickeyinfo_to_structure(RzStructuredData *parent, RzX509SubjectPublicKeyInfo *spki) {
RzASN1String *m = NULL;
if (!spki) {
return;
}
if (spki->algorithm.algorithm) {
rz_structured_data_map_add_string(parent, "algorithm", spki->algorithm.algorithm->string);
}
if (spki->subjectPublicKeyModule && spki->subjectPublicKeyExponent) {
RzStructuredData *subjectPublicKey = rz_structured_data_map_add_map(parent, "subjectPublicKey");
m = rz_asn1_stringify_bytes(spki->subjectPublicKeyExponent->binary, spki->subjectPublicKeyExponent->length);
if (m) {
rz_structured_data_map_add_string(subjectPublicKey, "exponent", m->string);
}
rz_asn1_string_free(m);
m = rz_asn1_stringify_integer(spki->subjectPublicKeyModule->binary, spki->subjectPublicKeyModule->length);
if (m) {
rz_structured_data_map_add_string(subjectPublicKey, "module", m->string);
}
rz_asn1_string_free(m);
} else if (spki->subjectPublicKey) {
m = rz_asn1_stringify_bytes(spki->subjectPublicKeyExponent->binary, spki->subjectPublicKeyExponent->length);
if (m) {
rz_structured_data_map_add_string(parent, "subjectPublicKey", m->string);
}
rz_asn1_string_free(m);
}
}
static void x509_extensions_to_structure(RzStructuredData *parent, RzX509Extensions *exts) {
if (!exts) {
return;
}
RzASN1String *m = NULL;
RzStructuredData *extensions = rz_structured_data_map_add_array(parent, "extensions");
for (ut32 i = 0; i < exts->length; i++) {
RzX509Extension *e = exts->extensions[i];
if (!e) {
continue;
}
RzStructuredData *extension = rz_structured_data_array_add_map(extensions);
if (e->extnID) {
rz_structured_data_map_add_string(extension, "extnID", e->extnID->string);
}
if (e->critical) {
rz_structured_data_map_add_boolean(extension, "critical", e->critical);
}
if (e->extnValue) {
if (rz_str_is_printable_limited((const char *)e->extnValue->binary, e->extnValue->length)) {
m = rz_asn1_stringify_string(e->extnValue->binary, e->extnValue->length);
} else if (e->extnValue->length > 3) {
RzASN1Object *obj = rz_asn1_object_parse(e->extnValue->binary, e->extnValue->length);
if (obj) {
RzStructuredData *sd = rz_asn1_to_structure(obj, true);
rz_asn1_object_free(obj);
rz_structured_data_map_add(extension, "extnValue", sd);
continue;
}
}
if (!m && e->extnValue->length < 20) {
m = rz_asn1_stringify_integer(e->extnValue->binary, e->extnValue->length);
} else if (!m) {
m = rz_asn1_stringify_bytes(e->extnValue->binary, e->extnValue->length);
}
if (m) {
rz_structured_data_map_add_string(extension, "extnValue", m->string);
}
rz_asn1_string_free(m);
}
}
}
static void x509_tbscertificate_to_structure(RzStructuredData *parent, RzX509TBSCertificate *tbsc) {
if (!tbsc) {
return;
}
pj_ki(pj, "Version", tbsc->version + 1);
RzStructuredData *tbs_cert = rz_structured_data_map_add_map(parent, "tbsCertificate");
if (!tbs_cert) {
return;
}
rz_structured_data_map_add_signed(tbs_cert, "version", tbsc->version + 1);
if (tbsc->serialNumber) {
pj_ks(pj, "SerialNumber", tbsc->serialNumber->string);
rz_structured_data_map_add_string(tbs_cert, "serialNumber", tbsc->serialNumber->string);
}
if (tbsc->signature.algorithm) {
pj_ks(pj, "SignatureAlgorithm", tbsc->signature.algorithm->string);
}
pj_k(pj, "Issuer");
pj_o(pj);
rz_x509_name_json(pj, &tbsc->issuer);
pj_end(pj);
pj_k(pj, "Validity");
pj_o(pj);
x509_validity_json(pj, &tbsc->validity);
pj_end(pj);
pj_k(pj, "Subject");
pj_o(pj);
rz_x509_name_json(pj, &tbsc->subject);
pj_end(pj);
pj_k(pj, "SubjectPublicKeyInfo");
pj_o(pj);
x509_subjectpublickeyinfo_json(pj, &tbsc->subjectPublicKeyInfo);
pj_end(pj);
RzStructuredData *signature = rz_structured_data_map_add_map(tbs_cert, "signature");
rz_x509_algorithmidentifier_to_structure(signature, &tbsc->signature);
RzStructuredData *issuer = rz_structured_data_map_add_array(tbs_cert, "issuer");
rz_x509_name_to_structure(issuer, &tbsc->issuer);
RzStructuredData *validity = rz_structured_data_map_add_map(tbs_cert, "validity");
x509_validity_to_structure(validity, &tbsc->validity);
RzStructuredData *subject = rz_structured_data_map_add_array(tbs_cert, "subject");
rz_x509_name_to_structure(subject, &tbsc->subject);
RzStructuredData *subjectPki = rz_structured_data_map_add_map(tbs_cert, "subjectPublicKeyInfo");
x509_subjectpublickeyinfo_to_structure(subjectPki, &tbsc->subjectPublicKeyInfo);
if (tbsc->issuerUniqueID) {
m = rz_asn1_stringify_integer(tbsc->issuerUniqueID->binary, tbsc->issuerUniqueID->length);
RzASN1String *m = rz_asn1_stringify_integer(tbsc->issuerUniqueID->binary, tbsc->issuerUniqueID->length);
if (m) {
pj_ks(pj, "IssuerUniqueID", m->string);
rz_structured_data_map_add_string(tbs_cert, "issuerUniqueID", m->string);
}
rz_asn1_string_free(m);
}
if (tbsc->subjectUniqueID) {
m = rz_asn1_stringify_integer(tbsc->subjectUniqueID->binary, tbsc->subjectUniqueID->length);
RzASN1String *m = rz_asn1_stringify_integer(tbsc->subjectUniqueID->binary, tbsc->subjectUniqueID->length);
if (m) {
pj_ks(pj, "SubjectUniqueID", m->string);
rz_structured_data_map_add_string(tbs_cert, "subjectUniqueID", m->string);
}
rz_asn1_string_free(m);
}
pj_k(pj, "Extensions");
x509_extensions_json(pj, &tbsc->extensions);
x509_extensions_to_structure(tbs_cert, &tbsc->extensions);
}
/**
* \brief Converts a certificate into a json structure
* \brief Converts a certificate to a RzStructuredData
*
* \param pj The PJ pointer to write to
* \param certificate The certificate to convert to json
* \param certificate The certificate to convert to RzStructuredData
*
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API void rz_x509_certificate_json(RZ_NONNULL PJ *pj, RZ_NULLABLE RzX509Certificate *certificate) {
rz_return_if_fail(pj);
RZ_API RZ_OWN RzStructuredData *rz_x509_certificate_to_structure(RZ_NULLABLE RzX509Certificate *certificate) {
if (!certificate) {
return;
return NULL;
}
RzStructuredData *root = rz_structured_data_new_map();
if (!root) {
return NULL;
}
RzASN1String *m = NULL;
pj_o(pj);
pj_k(pj, "TBSCertificate");
x509_tbscertificate_json(pj, &certificate->tbsCertificate);
if (certificate->algorithmIdentifier.algorithm) {
pj_ks(pj, "Algorithm", certificate->algorithmIdentifier.algorithm->string);
}
x509_tbscertificate_to_structure(root, &certificate->tbsCertificate);
RzStructuredData *algorithm_identifier = rz_structured_data_map_add_map(root, "algorithmIdentifier");
rz_x509_algorithmidentifier_to_structure(algorithm_identifier, &certificate->algorithmIdentifier);
if (certificate->signature) {
m = rz_asn1_stringify_integer(certificate->signature->binary, certificate->signature->length);
m = rz_asn1_stringify_bytes(certificate->signature->binary, certificate->signature->length);
if (m) {
pj_ks(pj, "Signature", m->string);
rz_structured_data_map_add_string(root, "signature", m->string);
}
rz_asn1_string_free(m);
}
pj_end(pj);
return root;
}

View file

@ -1,18 +1,15 @@
// SPDX-FileCopyrightText: 2017-2018 deroad <wargio@libero.it>
// SPDX-FileCopyrightText: 2017-2025 deroad <deroad@kumo.xn--q9jyb4c>
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef RZ_X509_INTERNAL_H
#define RZ_X509_INTERNAL_H
RZ_IPI bool rz_x509_algorithmidentifier_parse(RzX509AlgorithmIdentifier *ai, RzASN1Object *object);
RZ_IPI void rz_x509_algorithmidentifier_fini(RzX509AlgorithmIdentifier *ai);
RZ_IPI bool rz_x509_name_parse(RzX509Name *name, RzASN1Object *object);
RZ_IPI void rz_x509_name_fini(RzX509Name *name);
RZ_IPI void rz_x509_name_dump(RzX509Name *name, const char *pad, RzStrBuf *sb);
RZ_IPI void rz_x509_name_json(PJ *pj, RzX509Name *name);
RZ_IPI void rz_x509_crl_free(RzX509CertificateRevocationList *crl);
RZ_IPI void rz_x509_crlentry_dump(RzX509CRLEntry *crle, const char *pad, RzStrBuf *sb);
RZ_IPI bool rz_x509_algorithmidentifier_parse(RZ_NONNULL RzX509AlgorithmIdentifier *ai, RZ_NONNULL RzASN1Object *object);
RZ_IPI void rz_x509_algorithmidentifier_to_structure(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const RzX509AlgorithmIdentifier *ai);
RZ_IPI bool rz_x509_name_parse(RZ_NULLABLE RzX509Name *name, RZ_NULLABLE RzASN1Object *object);
RZ_IPI void rz_x509_algorithmidentifier_fini(RZ_NULLABLE RzX509AlgorithmIdentifier *ai);
RZ_IPI void rz_x509_name_fini(RZ_NULLABLE RzX509Name *name);
RZ_IPI void rz_x509_crl_free(RZ_NULLABLE RzX509CertificateRevocationList *crl);
RZ_IPI void rz_x509_name_to_structure(RZ_NULLABLE RzStructuredData *parent, RZ_NULLABLE RzX509Name *name);
#endif /* RZ_X509_INTERNAL_H */

File diff suppressed because one or more lines are too long

View file

@ -275,6 +275,7 @@ PrivateKeyInfo:
a3 10 b1 42 7e 8c 17 8b 2f 83 9c af 90 9b 0c a8 ...B~.../.......
f6 55 10 d1 f4 33 af d2 ce 6e 69 00 63 1a 0e 0b .U...3...ni.c...
f4 38 85 7c 56 d3 c7 97 8e 8b c9 .8.|V......
{
"PrivateKeyInfo": {
"privateKeyAlgorithm": {
@ -297,37 +298,91 @@ EXPECT=<<EOF
offset size flag detail
------------------------------------
0x2f 0x0000034d hit.x509.0
TBSCertificate:
Version: v3
Serial Number:
53:2a:e3:b1:e9:ef:4e:87:2a:ea:c3:5b:32:8f:7d:95:71:16:bd:39
Signature Algorithm:
sha256WithRSAEncryption (1.2.840.113549.1.1.11)
Issuer:
countryName (2.5.4.6): ZA
stateOrProvinceName (2.5.4.8): Some-State
organizationName (2.5.4.10): Radare2
Validity:
Not Before: 27/11/2019 18:09:20 GMT
Not After: 26/11/2020 18:09:20 GMT
Subject:
countryName (2.5.4.6): ZA
stateOrProvinceName (2.5.4.8): Some-State
organizationName (2.5.4.10): Radare2
Subject Public Key Info:
Algorithm: rsaEncryption (1.2.840.113549.1.1.1)
Module: 01:00:01
Exponent: 256 bytes
Extensions:
subjectKeyIdentifier (2.5.29.14):
22 bytes
authorityKeyIdentifier (2.5.29.35):
24 bytes
basicConstraints (2.5.29.19): critical
5 bytes
Algorithm:
sha256WithRSAEncryption (1.2.840.113549.1.1.11)
Signature: 256 bytes
tbsCertificate:
version: 3
serialNumber: "53:2a:e3:b1:e9:ef:4e:87:2a:ea:c3:5b:32:8f:7d:95:71:16:bd:39"
signature:
algorithm: "sha256WithRSAEncryption (1.2.840.113549.1.1.11)"
issuer:
- oid: "countryName (2.5.4.6)"
value: "ZA"
- oid: "stateOrProvinceName (2.5.4.8)"
value: "Some-State"
- oid: "organizationName (2.5.4.10)"
value: "Radare2"
validity:
notBefore: "27/11/2019 18:09:20 GMT"
notAfter: "26/11/2020 18:09:20 GMT"
subject:
- oid: "countryName (2.5.4.6)"
value: "ZA"
- oid: "stateOrProvinceName (2.5.4.8)"
value: "Some-State"
- oid: "organizationName (2.5.4.10)"
value: "Radare2"
subjectPublicKeyInfo:
algorithm: "rsaEncryption (1.2.840.113549.1.1.1)"
subjectPublicKey:
exponent: |
00 d3 ef ec 08 5a 38 90 10 80 e6 9e 2a 6e 36 ab .....Z8.....*n6.
f3 a4 d1 e8 17 55 60 30 40 40 55 44 80 3d c0 c2 .....U`0@@UD.=..
f1 31 2c a4 f5 25 ef 4e f5 68 de a1 15 31 7d 72 .1,..%.N.h...1}r
0d 40 e9 2c f3 a6 56 2c 2a f9 a9 bf 4c 8a 64 0f .@.,..V,*...L.d.
05 55 67 4a 93 3d 5a d6 0f 44 69 0b c7 24 78 0a .UgJ.=Z..Di..$x.
e4 c3 4a 83 ec 65 81 11 1d a7 18 d0 28 05 ea c2 ..J..e......(...
f3 b6 34 d6 90 7b a8 28 fe 3c a6 7f 7c a7 1a 1e ..4..{.(.<..|...
99 90 84 c2 97 9e b9 4f 59 a9 5b 9a 3c f9 15 77 .......OY.[.<..w
84 19 b2 19 6f c8 f6 4c bc 2d 8b 0b e3 3c 59 a6 ....o..L.-...<Y.
0f 15 0d 08 95 ce 82 8f df e4 58 3d 34 35 62 6c ..........X=45bl
71 8d 26 40 39 4e 4d b0 3c 0b f2 42 e4 b8 92 23 q.&@9NM.<..B...#
f4 33 63 bf ee 18 d2 b8 c7 de dd a6 27 cb 7c 01 .3c.........'.|.
68 a8 56 f7 f7 d8 69 7b 4a 65 7d 19 f1 ce 21 97 h.V...i{Je}...!.
3b df a3 21 84 9b fa e8 8c 51 0d 8c 23 06 f6 b8 ;..!.....Q..#...
6e 37 60 9d b7 ba 43 59 c8 af 51 f4 5f d3 39 82 n7`...CY..Q._.9.
4f e3 92 46 67 e0 20 24 1a 72 fd ca dd 32 ba 8f O..Fg. $.r...2..
module: "01:00:01"
extensions:
- extnID: "subjectKeyIdentifier (2.5.29.14)"
extnValue:
type: "OCTET_STRING"
value: |
ee 47 24 5c f5 07 df c6 28 ef 02 2b f3 b5 88 a8 .G$\....(..+....
d5 cd 9f a8 ....
- extnID: "authorityKeyIdentifier (2.5.29.35)"
extnValue:
type: "SEQUENCE"
value:
- type: "Context [0]"
value: |
ee 47 24 5c f5 07 df c6 28 ef 02 2b f3 b5 88 a8 .G$\....(..+....
d5 cd 9f a8 ....
- extnID: "basicConstraints (2.5.29.19)"
critical: true
extnValue:
type: "SEQUENCE"
value:
- type: "BOOLEAN"
value: "true"
algorithmIdentifier:
algorithm: "sha256WithRSAEncryption (1.2.840.113549.1.1.11)"
signature: |
c0 a9 ff 81 60 9b d3 c3 ed 45 3e 9b 8c 8a dd 91 ....`....E>.....
9d e8 72 62 a8 30 ed 01 54 96 20 76 54 e2 9f 01 ..rb.0..T. vT...
9f 05 e0 7b 84 7e 50 26 c6 4d fa 0d b4 de c1 5c ...{.~P&.M.....\
62 d3 5f 75 e6 71 ce 39 94 c7 d9 38 0b 69 d0 12 b._u.q.9...8.i..
ab 16 b8 b8 cb e1 57 83 e3 04 3b 36 c9 eb 92 89 ......W...;6....
f4 ed 27 69 f3 5a ee b0 10 03 c0 92 47 39 7e 7e ..'i.Z......G9~~
71 21 a0 d6 6a 70 30 26 0c e3 df ac f3 bc 59 f9 q!..jp0&......Y.
18 c7 8e 93 b8 18 45 ba 4f e8 04 4f 5f 92 6e 79 ......E.O..O_.ny
56 1a 08 cd 04 28 a5 db 14 32 39 a6 3a ed 63 25 V....(...29.:.c%
f3 e0 df 45 ee 5b 30 dd 11 4f ad aa 46 06 6b 6e ...E.[0..O..F.kn
05 17 a5 9b 26 d6 11 81 c6 8c 7e ec ad 99 2b f2 ....&.....~...+.
00 c9 e1 20 ad 4c 27 27 e9 b4 1d a7 c9 4c 52 17 ... .L''.....LR.
3b 6a 1b 4c 5d 59 55 46 8a b5 46 f2 30 10 56 25 ;j.L]YUF..F.0.V%
8b 62 ae 40 65 ba 0f ae 5f 17 eb 72 d6 c2 de a2 .b.@e..._..r....
8e d2 8f a5 06 a9 54 d3 9e 02 47 9a c9 6b c3 38 ......T...G..k.8
aa 79 14 35 74 de 3a 7a 59 05 dc d0 69 57 88 93 .y.5t.:zY...iW..
EOF
RUN
@ -470,6 +525,7 @@ PrivateKeyInfo:
41 5f 4e bc d7 29 67 ad 2e e3 e1 cd b4 d7 dc 59 A_N..)g........Y
cf 70 66 75 67 16 7d ec 57 3c f7 28 db 27 30 eb .pfug.}.W<.(.'0.
5b df b0 8b df 79 d8 3c c1 17 95 dd 22 f5 c9 bc [....y.<...."...
rsaEncryption
PrivateKeyInfo:
privateKeyAlgorithm:
@ -512,6 +568,7 @@ PrivateKeyInfo:
60 45 ff 8b f9 ed 3e c3 43 08 d8 b4 5f b4 69 6a `E....>.C..._.ij
27 7c 0b f8 78 84 40 a2 b3 7b 63 47 40 2d 5b 13 '|..x.@..{cG@-[.
9e 76 fd aa 86 1e c5 cb 39 13 98 c3 58 dc ce 5c .v......9...X..\
secp256k1
PrivateKeyInfo:
privateKeyAlgorithm:
@ -525,6 +582,7 @@ PrivateKeyInfo:
cd 39 8c 9e e6 dc 8e 2b 66 35 60 d2 5c a6 5a ff .9.....+f5`.\.Z.
bf ec 80 3b 7c 37 3a 2c 65 44 c8 e8 df df f6 fe ...;|7:,eD......
ed 99 8a ce 1e 99 b7 a4 d7 0f .........
secp384r1
PrivateKeyInfo:
privateKeyAlgorithm:
@ -541,6 +599,7 @@ PrivateKeyInfo:
6e 6e ee a7 a0 db 33 c5 52 62 0b a8 8e b8 47 ec nn....3.Rb....G.
d1 a5 44 47 30 2c 22 3b 57 1f a1 7c 96 9b d4 23 ..DG0,";W..|...#
ba 00 38 01 36 60 74 ..8.6`
ml-dsa-87
PrivateKeyInfo:
privateKeyAlgorithm:
@ -850,6 +909,7 @@ PrivateKeyInfo:
1f af c9 c3 10 61 c2 4e 8c d0 2a 54 23 91 65 02 .....a.N..*T#.e.
8c e4 84 84 e7 93 23 9c 79 b0 2a a1 23 3a 64 3a ......#.y.*.#:d:
c6 88 2e 41 c3 56 f1 71 19 de 1a 7e 4d 23 6b e6 ...A.V.q...~M#k.
secp521r1
PrivateKeyInfo:
privateKeyAlgorithm:
@ -870,5 +930,6 @@ PrivateKeyInfo:
8a 8e f9 73 15 15 50 ed b9 f0 74 9a d1 3d 00 ac ...s..P...t..=..
73 ef f3 e8 e7 f8 f1 38 72 20 8d f4 ff 1c 71 62 s......8r ....qb
75 e5 b6 u.
EOF
RUN

File diff suppressed because one or more lines are too long