pesign/pesign-bnc805166-fix-signature-list.patch
Marcus Meissner 0b5d673ec8 Accepting request 156163 from home:joeyli:branches:openSUSE:Factory:bnc805166
Modified pesign-bnc805166-fix-signature-list.patch, block out the source code for find/attach Issuer certificate (bnc#805166 comment#13)

OBS-URL: https://build.opensuse.org/request/show/156163
OBS-URL: https://build.opensuse.org/package/show/Base:System/pesign?expand=0&rev=11
2013-02-24 11:07:40 +00:00

784 lines
22 KiB
Diff

commit 63c6ad572b3c1a7041dc581072421c2c94ff5d35
Author: Gary Ching-Pang Lin <chingpang@gmail.com>
Date: Fri Feb 22 15:13:08 2013 +0800
Backport patches to fix signature list
Get cms_context out of wincert functions.
ee357451be9968cedda57ce13b103eb82c590e67
Rework siglist to be somewhat more useful.
a5ec0d2cd06dec0961fc3fed680e7e385dc5bec8
Don't allow our signature list iterator to walk off the end of the file.
18980866e7952100d98510297c0e1cc25fca8fc8
Include old signatures in new space calculations.
77d334d77435d64e88fcc772b5b58440b394584a
Make implanting extracted certificates work again.
5ceddd2f80dfea70d211236190943746c2d2f77b
Add error handling macros to make code simpler.
0bafa814b49a9556550cfbc373e0ea5b9edb929e
Add is_issuer_of(cert, cert) helper function.
7750aaeceb2655807788f8e45417e84cb5404a8e
Add "find_named_certificate()" helper function.
c89c8dbf7929f8f8f36bc1c4045fcc17d5ce7e5c
Make generate_certificate_list include the issuing certificate.
8c3d82ceb5029bedfee1577682fec5ff3669ff3c
Fix a casting problem on 32-bit.
9eb2814858270af2d7ecfbfa5ca131e7be2f9f53
Index: pesign-0.99/libdpe/pe_addcert.c
===================================================================
--- pesign-0.99.orig/libdpe/pe_addcert.c
+++ pesign-0.99/libdpe/pe_addcert.c
@@ -59,7 +59,7 @@ pe_alloccert(Pe *pe, size_t size)
memset(addr, '\0', size);
dd->certs.virtual_address = compute_file_addr(pe, addr);
- dd->certs.size = size;
+ dd->certs.size += size;
#if 0
pe_set_image_size(pe);
Index: pesign-0.99/libdpe/pe_updatefile.c
===================================================================
--- pesign-0.99.orig/libdpe/pe_updatefile.c
+++ pesign-0.99/libdpe/pe_updatefile.c
@@ -24,6 +24,7 @@
#include <sys/mman.h>
static struct section_header *
+__attribute__((unused))
__get_last_section(Pe *pe)
{
Pe_Scn *scn = NULL;
@@ -79,6 +80,7 @@ compare_sections (const void *a, const v
}
static void
+__attribute__((unused))
sort_sections (Pe_Scn **scns, Pe_ScnList *list)
{
Pe_Scn **scnp = scns;
@@ -131,7 +133,16 @@ __pe_updatemmap(Pe *pe, size_t shnum)
msync(msync_start, msync_end - msync_start, MS_SYNC);
#warning this is not done yet.
- struct section_header *sh = __get_last_section(pe);
+ //struct section_header *sh = __get_last_section(pe);
+
+ size_t dd_size = sizeof (*dd) / sizeof (dd->exports);
+ data_dirent *dde = &dd->exports;
+ for (int i = 0; i < dd_size; i++, dde++) {
+ if (dde->size != 0) {
+ char *addr = compute_mem_addr(pe, dde->virtual_address);
+ msync(addr, dde->size, MS_SYNC);
+ }
+ }
return 0;
}
Index: pesign-0.99/src/actions.c
===================================================================
--- pesign-0.99.orig/src/actions.c
+++ pesign-0.99/src/actions.c
@@ -268,7 +268,7 @@ failure:
return ret;
}
-static void
+void
parse_signature(pesign_context *ctx)
{
int rc;
@@ -396,8 +396,6 @@ generate_sattr_blob(pesign_context *ctx)
void
check_signature_space(pesign_context *ctx)
{
- parse_signature(ctx);
-
ssize_t available = available_cert_space(ctx->outpe);
if (available < ctx->cms_ctx->newsig.len) {
@@ -406,14 +404,6 @@ check_signature_space(pesign_context *ct
}
}
-int
-import_signature(pesign_context *ctx)
-{
- insert_signature(ctx->cms_ctx, ctx->signum);
-
- return finalize_signatures(ctx->cms_ctx, ctx->outpe);
-}
-
void
allocate_signature_space(Pe *pe, ssize_t sigspace)
{
Index: pesign-0.99/src/actions.h
===================================================================
--- pesign-0.99.orig/src/actions.h
+++ pesign-0.99/src/actions.h
@@ -28,12 +28,12 @@ extern int list_signatures(pesign_contex
extern void check_signature_space(pesign_context *ctx);
extern void allocate_signature_space(Pe *pe, ssize_t sigspace);
extern off_t export_signature(cms_context *cms, int fd, int ascii_armor);
-extern int import_signature(pesign_context *ctx);
extern void import_raw_signature(pesign_context *pctx);
extern void remove_signature(pesign_context *ctx);
extern void export_pubkey(pesign_context *ctx);
extern void export_cert(pesign_context *ctx);
extern int generate_sattr_blob(pesign_context *pctx);
+extern void parse_signature(pesign_context *ctx);
extern void insert_signature(cms_context *cms, int signum);
#endif /* PESIGN_CRYPTO_H */
Index: pesign-0.99/src/cms_common.c
===================================================================
--- pesign-0.99.orig/src/cms_common.c
+++ pesign-0.99/src/cms_common.c
@@ -304,6 +304,17 @@ is_valid_cert(CERTCertificate *cert, voi
return SECFailure;
}
+int
+is_issuer_of(CERTCertificate *c0, CERTCertificate *c1)
+{
+ if (c0->derSubject.len != c1->derIssuer.len)
+ return 0;
+
+ if (memcmp(c0->derSubject.data, c1->derIssuer.data, c0->derSubject.len))
+ return 0;
+ return 1;
+}
+
/* This is the dumbest function ever, but we need it anyway, because nss
* is garbage. */
static void
@@ -443,6 +454,88 @@ err_slots:
PK11_DestroySlotListElement(slots, &psle);
PK11_FreeSlotList(slots);
+ CERT_DestroyCertList(certlist);
+
+ return 0;
+}
+
+int
+find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert)
+{
+ if (!name) {
+ cms->log(cms, LOG_ERR, "no certificate name specified");
+ return -1;
+ }
+
+ secuPWData pwdata_val = { 0, 0 };
+ void *pwdata = cms->pwdata ? cms->pwdata : &pwdata_val;
+ PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword);
+
+ PK11SlotList *slots = NULL;
+ slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, pwdata);
+ if (!slots)
+ cmsreterr(-1, cms, "could not get pk11 token list");
+
+ PK11SlotListElement *psle = NULL;
+ psle = PK11_GetFirstSafe(slots);
+ if (!psle) {
+ save_port_err(PK11_FreeSlotList(slots));
+ cmsreterr(-1, cms, "could not get pk11 safe");
+ }
+
+ while (psle) {
+ if (!strcmp(cms->tokenname, PK11_GetTokenName(psle->slot)))
+ break;
+
+ psle = PK11_GetNextSafe(slots, psle, PR_FALSE);
+ }
+
+ if (!psle) {
+ save_port_err(PK11_FreeSlotList(slots));
+ cms->log(cms, LOG_ERR, "could not find token \"%s\"",
+ cms->tokenname);
+ return -1;
+ }
+
+ SECStatus status;
+ if (PK11_NeedLogin(psle->slot) && !PK11_IsLoggedIn(psle->slot, pwdata)) {
+ status = PK11_Authenticate(psle->slot, PR_TRUE, pwdata);
+ if (status != SECSuccess) {
+ PK11_DestroySlotListElement(slots, &psle);
+ PK11_FreeSlotList(slots);
+ cms->log(cms, LOG_ERR, "authentication failed for "
+ "token \"%s\"", cms->tokenname);
+ return -1;
+ }
+ }
+
+ CERTCertList *certlist = NULL;
+ certlist = PK11_ListCertsInSlot(psle->slot);
+ if (!certlist) {
+ save_port_err(
+ PK11_DestroySlotListElement(slots, &psle);
+ PK11_FreeSlotList(slots));
+ cmsreterr(-1, cms, "could not get certificate list");
+ }
+
+ CERTCertListNode *node = NULL;
+ for (node = CERT_LIST_HEAD(certlist); !CERT_LIST_END(node,certlist);
+ node = CERT_LIST_NEXT(node)) {
+ if (!strcmp(node->cert->subjectName, name))
+ break;
+ }
+ if (!node) {
+ PK11_DestroySlotListElement(slots, &psle);
+ PK11_FreeSlotList(slots);
+ CERT_DestroyCertList(certlist);
+
+ return -1;
+ }
+
+ *cert = CERT_DupCertificate(node->cert);
+
+ PK11_DestroySlotListElement(slots, &psle);
+ PK11_FreeSlotList(slots);
CERT_DestroyCertList(certlist);
return 0;
Index: pesign-0.99/src/cms_common.h
===================================================================
--- pesign-0.99.orig/src/cms_common.h
+++ pesign-0.99/src/cms_common.h
@@ -19,9 +19,35 @@
#ifndef CMS_COMMON_H
#define CMS_COMMON_H 1
-#include <stdarg.h>
+#include <errno.h>
#include <nss3/cert.h>
#include <nss3/secpkcs7.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#define save_port_err(x) \
+ ({ \
+ int __saved_errno = PORT_GetError(); \
+ x; \
+ PORT_SetError(__saved_errno); \
+ })
+
+#define cmserr(rv, cms, fmt, args...) ({ \
+ (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ": %s", \
+ __FILE__, __func__, __LINE__, ## args, \
+ PORT_ErrorToString(PORT_GetError())); \
+ exit(rv); \
+ })
+#define cmsreterr(rv, cms, fmt, args...) ({ \
+ (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ": %s", \
+ __FILE__, __func__, __LINE__, ## args, \
+ PORT_ErrorToString(PORT_GetError())); \
+ return rv; \
+ })
+
struct digest {
PK11Context *pk11ctx;
@@ -109,6 +135,10 @@ extern int generate_digest(cms_context *
extern int generate_signature(cms_context *ctx);
extern int unlock_nss_token(cms_context *ctx);
extern int find_certificate(cms_context *ctx);
+extern int is_issuer_of(CERTCertificate *c0, CERTCertificate *c1);
+
+extern int find_named_certificate(cms_context *cms, char *name,
+ CERTCertificate **cert);
extern SECOidTag digest_get_digest_oid(cms_context *cms);
extern SECOidTag digest_get_encryption_oid(cms_context *cms);
Index: pesign-0.99/src/daemon.c
===================================================================
--- pesign-0.99.orig/src/daemon.c
+++ pesign-0.99/src/daemon.c
@@ -288,7 +288,8 @@ set_up_inpe(context *ctx, int fd, Pe **p
return -1;
}
- int rc = parse_signatures(ctx->cms, *pe);
+ int rc = parse_signatures(&ctx->cms->signatures,
+ &ctx->cms->num_signatures, *pe);
if (rc < 0) {
ctx->cms->log(ctx->cms, ctx->priority|LOG_ERR,
"pesignd: could not parse signature list");
@@ -454,7 +455,8 @@ err_attached:
if (rc < 0)
goto err_attached;
insert_signature(ctx->cms, ctx->cms->num_signatures);
- finalize_signatures(ctx->cms, outpe);
+ finalize_signatures(ctx->cms->signatures,
+ ctx->cms->num_signatures, outpe);
pe_end(outpe);
} else {
if (ftruncate(outfd, 0) != 0) {
Index: pesign-0.99/src/pesign.c
===================================================================
--- pesign-0.99.orig/src/pesign.c
+++ pesign-0.99/src/pesign.c
@@ -104,7 +104,8 @@ open_input(pesign_context *ctx)
exit(1);
}
- int rc = parse_signatures(ctx->cms_ctx, ctx->inpe);
+ int rc = parse_signatures(&ctx->cms_ctx->signatures,
+ &ctx->cms_ctx->num_signatures, ctx->inpe);
if (rc < 0) {
fprintf(stderr, "pesign: could not parse signature data\n");
exit(1);
@@ -126,7 +127,8 @@ close_output(pesign_context *ctx)
{
Pe_Cmd cmd = ctx->outfd == STDOUT_FILENO ? PE_C_RDWR : PE_C_RDWR_MMAP;
- finalize_signatures(ctx->cms_ctx, ctx->outpe);
+ finalize_signatures(ctx->cms_ctx->signatures,
+ ctx->cms_ctx->num_signatures, ctx->outpe);
pe_update(ctx->outpe, cmd);
pe_end(ctx->outpe);
ctx->outpe = NULL;
@@ -673,7 +675,9 @@ main(int argc, char *argv[])
allocate_signature_space(ctxp->outpe, sigspace);
generate_signature(ctxp->cms_ctx);
insert_signature(ctxp->cms_ctx, ctxp->signum);
- finalize_signatures(ctxp->cms_ctx, ctxp->outpe);
+ finalize_signatures(ctxp->cms_ctx->signatures,
+ ctxp->cms_ctx->num_signatures,
+ ctxp->outpe);
close_output(ctxp);
break;
case EXPORT_SATTRS:
@@ -687,12 +691,27 @@ main(int argc, char *argv[])
/* add a signature from a file */
case IMPORT_SIGNATURE:
check_inputs(ctxp);
+ if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) {
+ fprintf(stderr, "Invalid signature number.\n");
+ exit(1);
+ }
open_input(ctxp);
open_output(ctxp);
close_input(ctxp);
open_sig_input(ctxp);
+ parse_signature(ctxp);
+ sigspace =
+ calculate_signature_overhead(
+ ctxp->cms_ctx->newsig.len) +
+ ctxp->cms_ctx->newsig.len +
+ get_reserved_sig_space(ctxp->cms_ctx,
+ ctxp->outpe);
+ allocate_signature_space(ctxp->outpe, sigspace);
check_signature_space(ctxp);
- import_signature(ctxp);
+ insert_signature(ctxp->cms_ctx, ctxp->signum);
+ finalize_signatures(ctxp->cms_ctx->signatures,
+ ctxp->cms_ctx->num_signatures,
+ ctxp->outpe);
close_sig_input(ctxp);
close_output(ctxp);
break;
@@ -788,6 +807,10 @@ main(int argc, char *argv[])
ctxp->cms_ctx->certname);
exit(1);
}
+ if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) {
+ fprintf(stderr, "Invalid signature number.\n");
+ exit(1);
+ }
open_input(ctxp);
open_output(ctxp);
close_input(ctxp);
@@ -798,7 +821,9 @@ main(int argc, char *argv[])
generate_digest(ctxp->cms_ctx, ctxp->outpe);
generate_signature(ctxp->cms_ctx);
insert_signature(ctxp->cms_ctx, ctxp->signum);
- finalize_signatures(ctxp->cms_ctx, ctxp->outpe);
+ finalize_signatures(ctxp->cms_ctx->signatures,
+ ctxp->cms_ctx->num_signatures,
+ ctxp->outpe);
close_output(ctxp);
break;
case DAEMONIZE:
Index: pesign-0.99/src/peverify.c
===================================================================
--- pesign-0.99.orig/src/peverify.c
+++ pesign-0.99/src/peverify.c
@@ -55,9 +55,12 @@ open_input(peverify_context *ctx)
exit(1);
}
- int rc = parse_signatures(&ctx->cms_ctx, ctx->inpe);
+ int rc = parse_signatures(&ctx->cms_ctx->signatures,
+ &ctx->cms_ctx->num_signatures,
+ ctx->inpe);
if (rc < 0) {
- fprintf(stderr, "pesign: could not parse signature data\n");
+ fprintf(stderr, "pesign: could not parse signature list in "
+ "EFI binary\n");
exit(1);
}
}
Index: pesign-0.99/src/siglist.c
===================================================================
--- pesign-0.99.orig/src/siglist.c
+++ pesign-0.99/src/siglist.c
@@ -17,11 +17,15 @@
* Author(s): Peter Jones <pjones@redhat.com>
*/
+#include <stdlib.h>
#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/param.h>
#include <errno.h>
-#include "authvar.h"
+#include "efitypes.h"
+#include "siglist.h"
struct efi_signature_data {
efi_guid_t SignatureOwner;
@@ -135,7 +139,10 @@ signature_list_add_sig(signature_list *s
if (memcmp(&sl->SignatureType, &x509_guid, sizeof (efi_guid_t)) == 0) {
if (sigsize > sl->SignatureSize)
resize_entries(sl, sigsize);
- } else if (sigsize != sl->SignatureSize) {
+ } else if (sigsize != get_sig_type_size(sl->SignatureType)) {
+ fprintf(stderr, "sigsize: %d sl->SignatureSize: %d\n",
+ sigsize, sl->SignatureSize);
+ errno = EINVAL;
return -1;
}
@@ -162,11 +169,31 @@ signature_list_add_sig(signature_list *s
return 0;
}
-void *
-signature_list_realize(signature_list *sl)
+#if 0
+int
+signature_list_parse(signature_list *sl, uint8_t *data, size_t len)
+{
+ if (!sl)
+ return -1;
+
+ if (sl->realized) {
+ free(sl->realized);
+ sl->realized = NULL;
+ }
+
+ efi_signature_list *esl = data;
+ efi_signature_data *esd = NULL;
+
+}
+#endif
+
+int
+signature_list_realize(signature_list *sl, void **out, size_t *outsize)
{
- if (sl->realized)
- return sl->realized;
+ if (sl->realized) {
+ free(sl->realized);
+ sl->realized = NULL;
+ }
struct efi_signature_list *esl = NULL;
uint32_t size = sizeof (*esl) +
@@ -174,7 +201,7 @@ signature_list_realize(signature_list *s
void *ret = calloc(1, size);
if (!ret)
- return NULL;
+ return -1;
esl = ret;
memcpy(esl, sl, sizeof (*esl));
@@ -186,7 +213,10 @@ signature_list_realize(signature_list *s
}
sl->realized = ret;
- return ret;
+
+ *out = ret;
+ *outsize = size;
+ return 0;
}
void
Index: pesign-0.99/src/siglist.h
===================================================================
--- pesign-0.99.orig/src/siglist.h
+++ pesign-0.99/src/siglist.h
@@ -24,7 +24,8 @@ typedef struct signature_list signature_
extern signature_list *signature_list_new(efi_guid_t SignatureType);
extern int signature_list_add_sig(signature_list *sl, efi_guid_t owner,
uint8_t *sig, uint32_t sigsize);
-extern void *signature_list_realize(signature_list *sl);
+extern int signature_list_realize(signature_list *sl,
+ void **out, size_t *outsize);
extern void signature_list_free(signature_list *sl);
#endif /* SIGLIST_H */
Index: pesign-0.99/src/signed_data.c
===================================================================
--- pesign-0.99.orig/src/signed_data.c
+++ pesign-0.99/src/signed_data.c
@@ -76,20 +76,53 @@ static int
generate_certificate_list(cms_context *cms, SECItem ***certificate_list_p)
{
SECItem **certificates = NULL;
+ void *mark = PORT_ArenaMark(cms->arena);
- certificates = PORT_ArenaZAlloc(cms->arena, sizeof (SECItem *) * 2);
- if (!certificates)
- return -1;
-
- certificates[0] = PORT_ArenaZAlloc(cms->arena, sizeof (SECItem));
- if (!certificates[0]) {
- int err = PORT_GetError();
- PORT_ZFree(certificates, sizeof (SECItem) * 2);
- PORT_SetError(err);
- return -1;
+ certificates = PORT_ArenaZAlloc(cms->arena, sizeof (SECItem *) * 3);
+ if (!certificates) {
+ save_port_err(PORT_ArenaRelease(cms->arena, mark));
+ cmsreterr(-1, cms, "could not allocate certificate list");
}
+ int i = 0;
+
+ certificates[i] = PORT_ArenaZAlloc(cms->arena, sizeof (SECItem));
+ if (!certificates[i]) {
+ save_port_err(PORT_ArenaRelease(cms->arena, mark));
+ cmsreterr(-1, cms, "could not allocate certificate entry");
+ }
+ SECITEM_CopyItem(cms->arena, certificates[i++], &cms->cert->derCert);
+
+#if 0
+ if (!is_issuer_of(cms->cert, cms->cert)) {
+ CERTCertificate *signer = NULL;
+ int rc = find_named_certificate(cms, cms->cert->issuerName,
+ &signer);
+ if (rc < 0) {
+ PORT_ArenaRelease(cms->arena, mark);
+ return -1;
+ }
+
+ if (signer) {
+ if (signer->derCert.len != cms->cert->derCert.len ||
+ memcmp(signer->derCert.data,
+ cms->cert->derCert.data,
+ signer->derCert.len)) {
+ certificates[i] = PORT_ArenaZAlloc(cms->arena,
+ sizeof (SECItem));
+ if (!certificates[i]) {
+ save_port_err(
+ PORT_ArenaRelease(cms->arena, mark));
+ cmsreterr(-1, cms,"could not allocate "
+ "certificate entry");
+ }
+ SECITEM_CopyItem(cms->arena, certificates[i++],
+ &signer->derCert);
+ }
+ CERT_DestroyCertificate(signer);
+ }
+ }
+#endif
- SECITEM_CopyItem(cms->arena, certificates[0], &cms->cert->derCert);
*certificate_list_p = certificates;
return 0;
}
Index: pesign-0.99/src/wincert.c
===================================================================
--- pesign-0.99.orig/src/wincert.c
+++ pesign-0.99/src/wincert.c
@@ -25,13 +25,13 @@ struct cert_list_entry {
};
static int
-generate_cert_list(cms_context *cms, void **cert_list,
- size_t *cert_list_size)
+generate_cert_list(SECItem **signatures, int num_signatures,
+ void **cert_list, size_t *cert_list_size)
{
size_t cl_size = 0;
- for (int i = 0; i < cms->num_signatures; i++) {
+ for (int i = 0; i < num_signatures; i++) {
cl_size += sizeof (win_certificate);
- cl_size += cms->signatures[i]->len;
+ cl_size += signatures[i]->len;
}
uint8_t *data = malloc(cl_size);
@@ -41,15 +41,15 @@ generate_cert_list(cms_context *cms, voi
*cert_list = (void *)data;
*cert_list_size = cl_size;
- for (int i = 0; i < cms->num_signatures; i++) {
+ for (int i = 0; i < num_signatures; i++) {
struct cert_list_entry *cle = (struct cert_list_entry *)data;
- cle->wc.length = cms->signatures[i]->len +
+ cle->wc.length = signatures[i]->len +
sizeof (win_certificate);
cle->wc.revision = WIN_CERT_REVISION_2_0;
cle->wc.cert_type = WIN_CERT_TYPE_PKCS_SIGNED_DATA;
- memcpy(&cle->data[0], cms->signatures[i]->data,
- cms->signatures[i]->len);
- data += sizeof (win_certificate) + cms->signatures[i]->len;
+ memcpy(&cle->data[0], signatures[i]->data,
+ signatures[i]->len);
+ data += sizeof (win_certificate) + signatures[i]->len;
}
return 0;
@@ -62,12 +62,13 @@ implant_cert_list(Pe *pe, void *cert_lis
}
int
-finalize_signatures(cms_context *cms, Pe *pe)
+finalize_signatures(SECItem **sigs, int num_sigs, Pe *pe)
{
void *clist = NULL;
size_t clist_size = 0;
- if (generate_cert_list(cms, &clist, &clist_size) < 0)
+ if (generate_cert_list(sigs, num_sigs,
+ &clist, &clist_size) < 0)
return -1;
if (implant_cert_list(pe, clist, clist_size) < 0) {
@@ -126,6 +127,13 @@ done:
void *certs = iter->certs;
size_t size = iter->size;
+ void *map = NULL;
+ size_t map_size = 0;
+
+ map = pe_rawfile(iter->pe, &map_size);
+ if (!map || map_size < 1)
+ return 0;
+
while (1) {
win_certificate *tmpcert;
if (n + sizeof (*tmpcert) >= size)
@@ -133,6 +141,9 @@ done:
tmpcert = (win_certificate *)((uint8_t *)certs + n);
+ if ((intptr_t)tmpcert > (intptr_t)map + map_size)
+ return -1;
+
/* length _includes_ the size of the structure. */
uint32_t length = le32_to_cpu(tmpcert->length);
@@ -193,7 +204,23 @@ available_cert_space(Pe *pe)
return totalsize - foundsize;
}
-ssize_t calculate_signature_space(cms_context *cms, Pe *pe)
+size_t
+get_reserved_sig_space(cms_context *cms, Pe *pe)
+{
+ size_t ret = 0;
+ for (int i = 0; i < cms->num_signatures; i++)
+ ret += cms->signatures[i]->len + sizeof (win_certificate);
+ return ret;
+}
+
+ssize_t
+calculate_signature_overhead(ssize_t size)
+{
+ return sizeof(win_certificate);
+}
+
+ssize_t
+calculate_signature_space(cms_context *cms, Pe *pe)
{
int rc;
@@ -209,7 +236,9 @@ err:
if (rc < 0)
goto err;
- ssize_t ret = sig.len + dd->certs.size + sizeof(win_certificate) -
+ size_t res = get_reserved_sig_space(cms, pe);
+
+ ssize_t ret = res + sig.len + sizeof(win_certificate) -
available_cert_space(pe);
//free(sig.data);
@@ -218,7 +247,7 @@ err:
}
int
-parse_signatures(cms_context *cms, Pe *pe)
+parse_signatures(SECItem ***sigs, int *num_sigs, Pe *pe)
{
cert_iter iter;
int rc = cert_iter_init(&iter, pe);
@@ -238,8 +267,8 @@ parse_signatures(cms_context *cms, Pe *p
}
if (nsigs == 0) {
- cms->num_signatures = 0;
- cms->signatures = NULL;
+ *num_sigs = 0;
+ *sigs = NULL;
return 0;
}
@@ -271,8 +300,8 @@ parse_signatures(cms_context *cms, Pe *p
i++;
}
- cms->num_signatures = nsigs;
- cms->signatures = signatures;
+ *num_sigs = nsigs;
+ *sigs = signatures;
return 0;
err:
Index: pesign-0.99/src/wincert.h
===================================================================
--- pesign-0.99.orig/src/wincert.h
+++ pesign-0.99/src/wincert.h
@@ -32,8 +32,6 @@ typedef struct win_certificate {
uint16_t cert_type;
} win_certificate;
-extern int finalize_signatures(cms_context *cms, Pe *pe);
-
typedef struct cert_iter {
Pe *pe;
off_t n;
@@ -45,6 +43,10 @@ extern int cert_iter_init(cert_iter *ite
extern int next_cert(cert_iter *iter, void **cert, ssize_t *cert_size);
extern ssize_t available_cert_space(Pe *pe);
extern ssize_t calculate_signature_space(cms_context *cms, Pe *pe);
-extern int parse_signatures(cms_context *cms, Pe *pe);
+extern int parse_signatures(SECItem ***sigs, int *num_sigs, Pe *pe);
+extern int finalize_signatures(SECItem **sigs, int num_sigs, Pe *pe);
+extern size_t get_reserved_sig_space(cms_context *cms, Pe *pe);
+extern ssize_t calculate_signature_overhead(ssize_t size);
+
#endif /* PESIGN_WINCERT_H */