Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated authenticode-parser to version from 2024-02-14 #1193

Merged
merged 1 commit into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ typedef struct {
char* digest_alg; /* Name of the digest algorithm used */
ByteArray digest; /* Stored message digest */
CertificateArray* chain; /* Certificate chain of the signer */
CertificateArray* certs; /* All certs stored inside Countersignature, this can be superset
of chain in case of non PKCS9 countersignature*/
} Countersignature;

typedef struct {
Expand Down
47 changes: 5 additions & 42 deletions deps/authenticode-parser/src/authenticode.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,23 +114,6 @@ static char* parse_program_name(ASN1_TYPE* spcAttr)
return result;
}

/* Parses X509* certs into internal representation and inserts into CertificateArray
* Array is assumed to have enough space to hold all certificates storted in the STACK */
static void parse_certificates(const STACK_OF(X509) * certs, CertificateArray* result)
{
int certCount = sk_X509_num(certs);
int i = 0;
for (; i < certCount; ++i) {
Certificate* cert = certificate_new(sk_X509_value(certs, i));
if (!cert)
break;

/* Write to the result */
result->certs[i] = cert;
}
result->count = i;
}

static void parse_nested_authenticode(PKCS7_SIGNER_INFO* si, AuthenticodeArray* result)
{
STACK_OF(X509_ATTRIBUTE)* attrs = PKCS7_get_attributes(si);
Expand Down Expand Up @@ -190,26 +173,6 @@ static void parse_pkcs9_countersig(PKCS7* p7, Authenticode* auth)
}
}

/* Extracts X509 certificates from MS countersignature and stores them into result */
static void extract_ms_counter_certs(const uint8_t* data, int len, CertificateArray* result)
{
PKCS7* p7 = d2i_PKCS7(NULL, &data, len);
if (!p7)
return;

STACK_OF(X509)* certs = p7->d.sign->cert;
CertificateArray* certArr = certificate_array_new(sk_X509_num(certs));
if (!certArr) {
PKCS7_free(p7);
return;
}
parse_certificates(certs, certArr);
certificate_array_move(result, certArr);
certificate_array_free(certArr);

PKCS7_free(p7);
}

static void parse_ms_countersig(PKCS7* p7, Authenticode* auth)
{
PKCS7_SIGNER_INFO* si = sk_PKCS7_SIGNER_INFO_value(PKCS7_get_signer_info(p7), 0);
Expand All @@ -233,14 +196,14 @@ static void parse_ms_countersig(PKCS7* p7, Authenticode* auth)
int len = nested->value.sequence->length;
const uint8_t* data = nested->value.sequence->data;

Countersignature* sig = ms_countersig_new(data, len, si->enc_digest);
if (!sig)
Countersignature* csig = ms_countersig_new(data, len, si->enc_digest);
if (!csig)
return;

countersignature_array_insert(auth->countersigs, csig);
/* Because MS TimeStamp countersignature has it's own SET of certificates
* extract it back into parent signature for consistency with PKCS9 */
countersignature_array_insert(auth->countersigs, sig);
extract_ms_counter_certs(data, len, auth->certs);
certificate_array_append(auth->certs, csig->certs);
}
}

Expand Down Expand Up @@ -338,7 +301,7 @@ AuthenticodeArray* authenticode_new(const uint8_t* data, int32_t len)
auth->verify_flags = AUTHENTICODE_VFY_INTERNAL_ERROR;
goto end;
}
parse_certificates(certs, auth->certs);
parse_x509_certificates(certs, auth->certs);

/* Get Signature content that contains the message digest and it's algorithm */
SpcIndirectDataContent* dataContent = get_content(p7data->contents);
Expand Down
98 changes: 98 additions & 0 deletions deps/authenticode-parser/src/certificate.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,82 @@ Certificate* certificate_new(X509* x509)
return result;
}

void attributes_copy(Attributes* dst, Attributes* src)
{
byte_array_init(&dst->country, src->country.data, src->country.len);
byte_array_init(&dst->organization, src->organization.data, src->organization.len);
byte_array_init(
&dst->organizationalUnit, src->organizationalUnit.data, src->organizationalUnit.len);
byte_array_init(&dst->nameQualifier, src->nameQualifier.data, src->nameQualifier.len);
byte_array_init(&dst->state, src->state.data, src->state.len);
byte_array_init(&dst->commonName, src->commonName.data, src->commonName.len);
byte_array_init(&dst->serialNumber, src->serialNumber.data, src->serialNumber.len);
byte_array_init(&dst->locality, src->locality.data, src->locality.len);
byte_array_init(&dst->title, src->title.data, src->title.len);
byte_array_init(&dst->surname, src->surname.data, src->surname.len);
byte_array_init(&dst->givenName, src->givenName.data, src->givenName.len);
byte_array_init(&dst->initials, src->initials.data, src->initials.len);
byte_array_init(&dst->pseudonym, src->pseudonym.data, src->pseudonym.len);
byte_array_init(
&dst->generationQualifier, src->generationQualifier.data, src->generationQualifier.len);
byte_array_init(&dst->emailAddress, src->emailAddress.data, src->emailAddress.len);
}

/* Parses X509* certs into internal representation and inserts into CertificateArray
* Array is assumed to have enough space to hold all certificates storted in the STACK */
void parse_x509_certificates(const STACK_OF(X509) * certs, CertificateArray* result)
{
int certCount = sk_X509_num(certs);
int i = 0;
for (; i < certCount; ++i) {
Certificate* cert = certificate_new(sk_X509_value(certs, i));
if (!cert)
break;

/* Write to the result */
result->certs[i] = cert;
}
result->count = i;
}

/* Creates deep copy of a certificate */
Certificate* certificate_copy(Certificate* cert)
{
if (!cert)
return NULL;

Certificate* result = (Certificate*)calloc(1, sizeof(*result));
if (!result)
return NULL;

result->version = cert->version;
result->issuer = strdup(cert->issuer);
result->subject = strdup(cert->subject);
result->serial = strdup(cert->serial);
result->not_after = cert->not_after;
result->not_before = cert->not_before;
result->sig_alg = strdup(cert->sig_alg);
result->sig_alg_oid = strdup(cert->sig_alg_oid);
result->key_alg = strdup(cert->key_alg);
result->key = strdup(cert->key);
byte_array_init(&result->sha1, cert->sha1.data, cert->sha1.len);
byte_array_init(&result->sha256, cert->sha256.data, cert->sha256.len);
attributes_copy(&result->issuer_attrs, &cert->issuer_attrs);
attributes_copy(&result->subject_attrs, &cert->subject_attrs);

return result;
}

/* Moves certificates from src to dst, returns 0 on success,
* else 1. If error occurs, arguments are unchanged */
int certificate_array_move(CertificateArray* dst, CertificateArray* src)
{
if (!dst || !src)
return 1;

if (!src->certs || !src->count)
return 0;

size_t newCount = dst->count + src->count;

Certificate** tmp = (Certificate**)realloc(dst->certs, newCount * sizeof(Certificate*));
Expand All @@ -354,6 +426,32 @@ int certificate_array_move(CertificateArray* dst, CertificateArray* src)
return 0;
}

/* Copies certificates from src and appends to dst, returns 0 on success,
* else 1. If error occurs, arguments are unchanged */
int certificate_array_append(CertificateArray* dst, CertificateArray* src)
{
if (!dst || !src)
return 1;

if (!src->certs || !src->count)
return 0;

size_t newCount = dst->count + src->count;

Certificate** tmp = (Certificate**)realloc(dst->certs, newCount * sizeof(Certificate*));
if (!tmp)
return 1;

dst->certs = tmp;

for (size_t i = 0; i < src->count; ++i)
dst->certs[i + dst->count] = certificate_copy(src->certs[i]);

dst->count = newCount;

return 0;
}

/* Allocates empty certificate array with reserved space for certCount certs */
CertificateArray* certificate_array_new(int certCount)
{
Expand Down
4 changes: 4 additions & 0 deletions deps/authenticode-parser/src/certificate.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ extern "C" {
#endif

Certificate* certificate_new(X509* x509);
Certificate* certificate_copy(Certificate* cert);
void certificate_free(Certificate* cert);

void parse_x509_certificates(const STACK_OF(X509) * certs, CertificateArray* result);

CertificateArray* parse_signer_chain(X509* signer_cert, STACK_OF(X509) * certs);
int certificate_array_move(CertificateArray* dst, CertificateArray* src);
int certificate_array_append(CertificateArray* dst, CertificateArray* src);
CertificateArray* certificate_array_new(int certCount);
void certificate_array_free(CertificateArray* arr);

Expand Down
14 changes: 14 additions & 0 deletions deps/authenticode-parser/src/countersignature.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,9 @@ CountersignatureImpl* ms_countersig_impl_new(const uint8_t* data, long size)
result->funcs = &FUNC_ARRAY_NAME_FOR_IMPL(pkcs7);
result->pkcs7 = p7;
return result;
} else if (p7) {
PKCS7_free(p7);
return NULL;
}

d = data;
Expand Down Expand Up @@ -527,6 +530,16 @@ Countersignature* ms_countersig_new(const uint8_t* data, long size, ASN1_STRING*
}

STACK_OF(X509)* certs = impl->funcs->get_certs(impl);

/* MS Counter signatures (PKCS7/CMS) can have extra certificates that are not part of a chain */
result->certs = certificate_array_new(sk_X509_num(certs));
if (!result->certs) {
result->verify_flags = AUTHENTICODE_VFY_INTERNAL_ERROR;
goto end;
}

parse_x509_certificates(certs, result->certs);

result->chain = parse_signer_chain(signCert, certs);

/* Imprint == digest */
Expand Down Expand Up @@ -642,6 +655,7 @@ void countersignature_free(Countersignature* sig)
free(sig->digest_alg);
free(sig->digest.data);
certificate_array_free(sig->chain);
certificate_array_free(sig->certs);
free(sig);
}
}
Expand Down
Loading