Skip to content

Commit 373c654

Browse files
authored
Merge pull request #1193 from avast/2024-02-14/update-authenticode-parser
Updated authenticode-parser to version from 2024-02-14
2 parents f4c9304 + 2921f93 commit 373c654

File tree

5 files changed

+123
-42
lines changed

5 files changed

+123
-42
lines changed

deps/authenticode-parser/include/authenticode-parser/authenticode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ typedef struct {
124124
char* digest_alg; /* Name of the digest algorithm used */
125125
ByteArray digest; /* Stored message digest */
126126
CertificateArray* chain; /* Certificate chain of the signer */
127+
CertificateArray* certs; /* All certs stored inside Countersignature, this can be superset
128+
of chain in case of non PKCS9 countersignature*/
127129
} Countersignature;
128130

129131
typedef struct {

deps/authenticode-parser/src/authenticode.c

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -114,23 +114,6 @@ static char* parse_program_name(ASN1_TYPE* spcAttr)
114114
return result;
115115
}
116116

117-
/* Parses X509* certs into internal representation and inserts into CertificateArray
118-
* Array is assumed to have enough space to hold all certificates storted in the STACK */
119-
static void parse_certificates(const STACK_OF(X509) * certs, CertificateArray* result)
120-
{
121-
int certCount = sk_X509_num(certs);
122-
int i = 0;
123-
for (; i < certCount; ++i) {
124-
Certificate* cert = certificate_new(sk_X509_value(certs, i));
125-
if (!cert)
126-
break;
127-
128-
/* Write to the result */
129-
result->certs[i] = cert;
130-
}
131-
result->count = i;
132-
}
133-
134117
static void parse_nested_authenticode(PKCS7_SIGNER_INFO* si, AuthenticodeArray* result)
135118
{
136119
STACK_OF(X509_ATTRIBUTE)* attrs = PKCS7_get_attributes(si);
@@ -190,26 +173,6 @@ static void parse_pkcs9_countersig(PKCS7* p7, Authenticode* auth)
190173
}
191174
}
192175

193-
/* Extracts X509 certificates from MS countersignature and stores them into result */
194-
static void extract_ms_counter_certs(const uint8_t* data, int len, CertificateArray* result)
195-
{
196-
PKCS7* p7 = d2i_PKCS7(NULL, &data, len);
197-
if (!p7)
198-
return;
199-
200-
STACK_OF(X509)* certs = p7->d.sign->cert;
201-
CertificateArray* certArr = certificate_array_new(sk_X509_num(certs));
202-
if (!certArr) {
203-
PKCS7_free(p7);
204-
return;
205-
}
206-
parse_certificates(certs, certArr);
207-
certificate_array_move(result, certArr);
208-
certificate_array_free(certArr);
209-
210-
PKCS7_free(p7);
211-
}
212-
213176
static void parse_ms_countersig(PKCS7* p7, Authenticode* auth)
214177
{
215178
PKCS7_SIGNER_INFO* si = sk_PKCS7_SIGNER_INFO_value(PKCS7_get_signer_info(p7), 0);
@@ -233,14 +196,14 @@ static void parse_ms_countersig(PKCS7* p7, Authenticode* auth)
233196
int len = nested->value.sequence->length;
234197
const uint8_t* data = nested->value.sequence->data;
235198

236-
Countersignature* sig = ms_countersig_new(data, len, si->enc_digest);
237-
if (!sig)
199+
Countersignature* csig = ms_countersig_new(data, len, si->enc_digest);
200+
if (!csig)
238201
return;
239202

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

@@ -338,7 +301,7 @@ AuthenticodeArray* authenticode_new(const uint8_t* data, int32_t len)
338301
auth->verify_flags = AUTHENTICODE_VFY_INTERNAL_ERROR;
339302
goto end;
340303
}
341-
parse_certificates(certs, auth->certs);
304+
parse_x509_certificates(certs, auth->certs);
342305

343306
/* Get Signature content that contains the message digest and it's algorithm */
344307
SpcIndirectDataContent* dataContent = get_content(p7data->contents);

deps/authenticode-parser/src/certificate.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,82 @@ Certificate* certificate_new(X509* x509)
330330
return result;
331331
}
332332

333+
void attributes_copy(Attributes* dst, Attributes* src)
334+
{
335+
byte_array_init(&dst->country, src->country.data, src->country.len);
336+
byte_array_init(&dst->organization, src->organization.data, src->organization.len);
337+
byte_array_init(
338+
&dst->organizationalUnit, src->organizationalUnit.data, src->organizationalUnit.len);
339+
byte_array_init(&dst->nameQualifier, src->nameQualifier.data, src->nameQualifier.len);
340+
byte_array_init(&dst->state, src->state.data, src->state.len);
341+
byte_array_init(&dst->commonName, src->commonName.data, src->commonName.len);
342+
byte_array_init(&dst->serialNumber, src->serialNumber.data, src->serialNumber.len);
343+
byte_array_init(&dst->locality, src->locality.data, src->locality.len);
344+
byte_array_init(&dst->title, src->title.data, src->title.len);
345+
byte_array_init(&dst->surname, src->surname.data, src->surname.len);
346+
byte_array_init(&dst->givenName, src->givenName.data, src->givenName.len);
347+
byte_array_init(&dst->initials, src->initials.data, src->initials.len);
348+
byte_array_init(&dst->pseudonym, src->pseudonym.data, src->pseudonym.len);
349+
byte_array_init(
350+
&dst->generationQualifier, src->generationQualifier.data, src->generationQualifier.len);
351+
byte_array_init(&dst->emailAddress, src->emailAddress.data, src->emailAddress.len);
352+
}
353+
354+
/* Parses X509* certs into internal representation and inserts into CertificateArray
355+
* Array is assumed to have enough space to hold all certificates storted in the STACK */
356+
void parse_x509_certificates(const STACK_OF(X509) * certs, CertificateArray* result)
357+
{
358+
int certCount = sk_X509_num(certs);
359+
int i = 0;
360+
for (; i < certCount; ++i) {
361+
Certificate* cert = certificate_new(sk_X509_value(certs, i));
362+
if (!cert)
363+
break;
364+
365+
/* Write to the result */
366+
result->certs[i] = cert;
367+
}
368+
result->count = i;
369+
}
370+
371+
/* Creates deep copy of a certificate */
372+
Certificate* certificate_copy(Certificate* cert)
373+
{
374+
if (!cert)
375+
return NULL;
376+
377+
Certificate* result = (Certificate*)calloc(1, sizeof(*result));
378+
if (!result)
379+
return NULL;
380+
381+
result->version = cert->version;
382+
result->issuer = strdup(cert->issuer);
383+
result->subject = strdup(cert->subject);
384+
result->serial = strdup(cert->serial);
385+
result->not_after = cert->not_after;
386+
result->not_before = cert->not_before;
387+
result->sig_alg = strdup(cert->sig_alg);
388+
result->sig_alg_oid = strdup(cert->sig_alg_oid);
389+
result->key_alg = strdup(cert->key_alg);
390+
result->key = strdup(cert->key);
391+
byte_array_init(&result->sha1, cert->sha1.data, cert->sha1.len);
392+
byte_array_init(&result->sha256, cert->sha256.data, cert->sha256.len);
393+
attributes_copy(&result->issuer_attrs, &cert->issuer_attrs);
394+
attributes_copy(&result->subject_attrs, &cert->subject_attrs);
395+
396+
return result;
397+
}
398+
333399
/* Moves certificates from src to dst, returns 0 on success,
334400
* else 1. If error occurs, arguments are unchanged */
335401
int certificate_array_move(CertificateArray* dst, CertificateArray* src)
336402
{
403+
if (!dst || !src)
404+
return 1;
405+
406+
if (!src->certs || !src->count)
407+
return 0;
408+
337409
size_t newCount = dst->count + src->count;
338410

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

429+
/* Copies certificates from src and appends to dst, returns 0 on success,
430+
* else 1. If error occurs, arguments are unchanged */
431+
int certificate_array_append(CertificateArray* dst, CertificateArray* src)
432+
{
433+
if (!dst || !src)
434+
return 1;
435+
436+
if (!src->certs || !src->count)
437+
return 0;
438+
439+
size_t newCount = dst->count + src->count;
440+
441+
Certificate** tmp = (Certificate**)realloc(dst->certs, newCount * sizeof(Certificate*));
442+
if (!tmp)
443+
return 1;
444+
445+
dst->certs = tmp;
446+
447+
for (size_t i = 0; i < src->count; ++i)
448+
dst->certs[i + dst->count] = certificate_copy(src->certs[i]);
449+
450+
dst->count = newCount;
451+
452+
return 0;
453+
}
454+
357455
/* Allocates empty certificate array with reserved space for certCount certs */
358456
CertificateArray* certificate_array_new(int certCount)
359457
{

deps/authenticode-parser/src/certificate.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,14 @@ extern "C" {
3131
#endif
3232

3333
Certificate* certificate_new(X509* x509);
34+
Certificate* certificate_copy(Certificate* cert);
3435
void certificate_free(Certificate* cert);
3536

37+
void parse_x509_certificates(const STACK_OF(X509) * certs, CertificateArray* result);
38+
3639
CertificateArray* parse_signer_chain(X509* signer_cert, STACK_OF(X509) * certs);
3740
int certificate_array_move(CertificateArray* dst, CertificateArray* src);
41+
int certificate_array_append(CertificateArray* dst, CertificateArray* src);
3842
CertificateArray* certificate_array_new(int certCount);
3943
void certificate_array_free(CertificateArray* arr);
4044

deps/authenticode-parser/src/countersignature.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@ CountersignatureImpl* ms_countersig_impl_new(const uint8_t* data, long size)
457457
result->funcs = &FUNC_ARRAY_NAME_FOR_IMPL(pkcs7);
458458
result->pkcs7 = p7;
459459
return result;
460+
} else if (p7) {
461+
PKCS7_free(p7);
462+
return NULL;
460463
}
461464

462465
d = data;
@@ -527,6 +530,16 @@ Countersignature* ms_countersig_new(const uint8_t* data, long size, ASN1_STRING*
527530
}
528531

529532
STACK_OF(X509)* certs = impl->funcs->get_certs(impl);
533+
534+
/* MS Counter signatures (PKCS7/CMS) can have extra certificates that are not part of a chain */
535+
result->certs = certificate_array_new(sk_X509_num(certs));
536+
if (!result->certs) {
537+
result->verify_flags = AUTHENTICODE_VFY_INTERNAL_ERROR;
538+
goto end;
539+
}
540+
541+
parse_x509_certificates(certs, result->certs);
542+
530543
result->chain = parse_signer_chain(signCert, certs);
531544

532545
/* Imprint == digest */
@@ -642,6 +655,7 @@ void countersignature_free(Countersignature* sig)
642655
free(sig->digest_alg);
643656
free(sig->digest.data);
644657
certificate_array_free(sig->chain);
658+
certificate_array_free(sig->certs);
645659
free(sig);
646660
}
647661
}

0 commit comments

Comments
 (0)