Skip to content

Commit

Permalink
Simplify obtaining an existing signature and creating a new one
Browse files Browse the repository at this point in the history
  • Loading branch information
olszomal authored and mtrojnar committed Jan 23, 2024
1 parent 44ca1f3 commit f22c835
Show file tree
Hide file tree
Showing 9 changed files with 406 additions and 383 deletions.
115 changes: 55 additions & 60 deletions appx.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Copyright (C) 2023 Michał Trojnara <[email protected]>
* Author: Małgorzata Olszówka <[email protected]>
*
* APPX files do not support nesting (multiple signature)
*/

#define _FILE_OFFSET_BITS 64
Expand Down Expand Up @@ -241,7 +242,8 @@ static int appx_check_file(FILE_FORMAT_CTX *ctx, int detached);
static int appx_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
static PKCS7 *appx_pkcs7_extract(FILE_FORMAT_CTX *ctx);
static int appx_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
static PKCS7 *appx_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
static int appx_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
static PKCS7 *appx_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
static int appx_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
static BIO *appx_bio_free(BIO *hash, BIO *outdata);
static void appx_ctx_cleanup(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
Expand All @@ -256,7 +258,8 @@ FILE_FORMAT file_format_appx = {
.verify_digests = appx_verify_digests,
.pkcs7_extract = appx_pkcs7_extract,
.remove_pkcs7 = appx_remove_pkcs7,
.pkcs7_prepare = appx_pkcs7_prepare,
.process_data = appx_process_data,
.pkcs7_signature_new = appx_pkcs7_signature_new,
.append_pkcs7 = appx_append_pkcs7,
.bio_free = appx_bio_free,
.ctx_cleanup = appx_ctx_cleanup,
Expand Down Expand Up @@ -348,9 +351,6 @@ static FILE_FORMAT_CTX *appx_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *ou
if (zipGetCDEntryByName(zip, APPXBUNDLE_MANIFEST_FILENAME)) {
ctx->appx_ctx->isBundle = 1;
}
if (options->nest)
/* I've not tried using set_nested_signature as signtool won't do this */
printf("Warning: APPX files do not support nesting (multiple signature)\n");
if (options->cmd == CMD_SIGN || options->cmd==CMD_ATTACH
|| options->cmd==CMD_ADD || options->cmd == CMD_EXTRACT_DATA) {
printf("Warning: Ignore -h option, use the hash algorithm specified in AppxBlockMap.xml\n");
Expand Down Expand Up @@ -591,83 +591,78 @@ static int appx_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
}

/*
* Obtain an existing signature or create a new one.
* APPX files do not support nesting.
* Modify specific type data.
* [in, out] ctx: structure holds input and output data
* [out] hash: message digest BIO (unused)
* [out] outdata: outdata file BIO (unused)
* [returns] pointer to PKCS#7 structure
* [returns] 1 on error or 0 on success
*/
static PKCS7 *appx_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
static int appx_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
{
ZIP_CENTRAL_DIRECTORY_ENTRY *entry;
PKCS7 *p7 = NULL;

/* squash unused parameter warnings */
(void)outdata;
(void)hash;

if (ctx->options->cmd == CMD_ADD) {
/* Obtain an existing signature */
p7 = appx_pkcs7_extract(ctx);
if (!p7) {
printf("Unable to extract existing signature\n");
return NULL; /* FAILED */
}
return p7;
}

/* Create and append a new signature content types entry */
entry = zipGetCDEntryByName(ctx->appx_ctx->zip, CONTENT_TYPES_FILENAME);
if (!entry) {
printf("Not a valid .appx file: content types file missing\n");
return NULL; /* FAILED */
return 1; /* FAILED */
}
if (!appx_append_ct_signature_entry(ctx->appx_ctx->zip, entry)) {
return 1; /* FAILED */
}
return 0; /* OK */
}

/*
* Create a new PKCS#7 signature.
* [in, out] ctx: structure holds input and output data
* [out] hash: message digest BIO (unused)
* [returns] pointer to PKCS#7 structure
*/
static PKCS7 *appx_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
{
ASN1_OCTET_STRING *content;
PKCS7 *p7 = NULL;
BIO *hashes;

/* squash unused parameter warnings */
(void)hash;

/* Create hash blob from concatenated APPX hashes */
hashes = appx_calculate_hashes(ctx);
if (!hashes) {
return NULL; /* FAILED */
}
if (ctx->options->cmd == CMD_ATTACH) {
/* Obtain an existing PKCS#7 signature from a "sigin" file */
p7 = pkcs7_get_sigfile(ctx);
if (!p7) {
printf("Unable to extract valid signature\n");
return NULL; /* FAILED */
}
} else if (ctx->options->cmd == CMD_SIGN) {
ASN1_OCTET_STRING *content;
/* Create hash blob from concatenated APPX hashes */
BIO *hashes = appx_calculate_hashes(ctx);
if (!hashes) {
return NULL; /* FAILED */
}
/* Create a new PKCS#7 signature */
p7 = pkcs7_create(ctx);
if (!p7) {
printf("Creating a new signature failed\n");
BIO_free_all(hashes);
return NULL; /* FAILED */
}
if (!add_indirect_data_object(p7)) {
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
PKCS7_free(p7);
BIO_free_all(hashes);
return NULL; /* FAILED */
}
content = spc_indirect_data_content_get(hashes, ctx);
p7 = pkcs7_create(ctx);
if (!p7) {
printf("Creating a new signature failed\n");
BIO_free_all(hashes);
if (!content) {
printf("Failed to get spcIndirectDataContent\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
if (!sign_spc_indirect_data_content(p7, content)) {
printf("Failed to set signed content\n");
PKCS7_free(p7);
ASN1_OCTET_STRING_free(content);
return NULL; /* FAILED */
}
return NULL; /* FAILED */
}
if (!add_indirect_data_object(p7)) {
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
PKCS7_free(p7);
BIO_free_all(hashes);
return NULL; /* FAILED */
}
content = spc_indirect_data_content_get(hashes, ctx);
BIO_free_all(hashes);
if (!content) {
printf("Failed to get spcIndirectDataContent\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
if (!sign_spc_indirect_data_content(p7, content)) {
printf("Failed to set signed content\n");
PKCS7_free(p7);
ASN1_OCTET_STRING_free(content);
return NULL; /* FAILED */
}
ASN1_OCTET_STRING_free(content);
return p7; /* OK */
}

Expand Down
125 changes: 59 additions & 66 deletions cab.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ static int cab_check_file(FILE_FORMAT_CTX *ctx, int detached);
static u_char *cab_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
static int cab_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
static PKCS7 *cab_pkcs7_extract(FILE_FORMAT_CTX *ctx);
static PKCS7 *cab_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx);
static int cab_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
static PKCS7 *cab_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
static int cab_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
static PKCS7 *cab_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
static int cab_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
static void cab_update_data_size(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
static BIO *cab_bio_free(BIO *hash, BIO *outdata);
Expand All @@ -65,8 +67,10 @@ FILE_FORMAT file_format_cab = {
.digest_calc = cab_digest_calc,
.verify_digests = cab_verify_digests,
.pkcs7_extract = cab_pkcs7_extract,
.pkcs7_extract_to_nest = cab_pkcs7_extract_to_nest,
.remove_pkcs7 = cab_remove_pkcs7,
.pkcs7_prepare = cab_pkcs7_prepare,
.process_data = cab_process_data,
.pkcs7_signature_new = cab_pkcs7_signature_new,
.append_pkcs7 = cab_append_pkcs7,
.update_data_size = cab_update_data_size,
.bio_free = cab_bio_free,
Expand Down Expand Up @@ -401,6 +405,16 @@ static PKCS7 *cab_pkcs7_extract(FILE_FORMAT_CTX *ctx)
return d2i_PKCS7(NULL, &blob, ctx->cab_ctx->siglen);
}

/*
* Extract existing signature in DER format.
* [in] ctx: structure holds input and output data
* pointer to PKCS#7 structure
*/
static PKCS7 *cab_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx)
{
return cab_pkcs7_extract(ctx);
}

/*
* Remove existing signature.
* [in, out] ctx: structure holds input and output data
Expand Down Expand Up @@ -479,83 +493,62 @@ static int cab_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
}

/*
* Obtain an existing signature or create a new one.
* Modify specific type data and calculate a hash (message digest) of data.
* [in, out] ctx: structure holds input and output data
* [out] hash: message digest BIO
* [out] outdata: outdata file BIO
* [returns] pointer to PKCS#7 structure
* [returns] 1 on error or 0 on success
*/
static PKCS7 *cab_pkcs7_prepare(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
static int cab_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
{
PKCS7 *cursig = NULL, *p7 = NULL;

/* Strip current signature and modify header */
if (ctx->cab_ctx->header_size == 20) {
if (!cab_modify_header(ctx, hash, outdata))
return NULL; /* FAILED */
return 1; /* FAILED */
} else {
if (!cab_add_header(ctx, hash, outdata))
return NULL; /* FAILED */
return 1; /* FAILED */
}
/* Obtain a current signature from previously-signed file */
if ((ctx->options->cmd == CMD_SIGN && ctx->options->nest)
|| (ctx->options->cmd == CMD_ATTACH && ctx->options->nest)
|| ctx->options->cmd == CMD_ADD) {
cursig = cab_pkcs7_extract(ctx);
if (!cursig) {
printf("Unable to extract existing signature\n");
return NULL; /* FAILED */
}
ctx->options->nested_number = nested_signatures_number_get(cursig);
if (ctx->options->nested_number < 0) {
printf("Unable to get number of nested signatures\n");
PKCS7_free(cursig);
return NULL; /* FAILED */
}
if (ctx->options->cmd == CMD_ADD)
p7 = cursig;
}
if (ctx->options->cmd == CMD_ATTACH) {
/* Obtain an existing PKCS#7 signature */
p7 = pkcs7_get_sigfile(ctx);
if (!p7) {
printf("Unable to extract valid signature\n");
PKCS7_free(cursig);
return NULL; /* FAILED */
}
} else if (ctx->options->cmd == CMD_SIGN) {
ASN1_OCTET_STRING *content;
/* Create a new PKCS#7 signature */
p7 = pkcs7_create(ctx);
if (!p7) {
printf("Creating a new signature failed\n");
return NULL; /* FAILED */
}
if (ctx->options->jp >= 0 && !cab_add_jp_attribute(p7, ctx->options->jp)) {
printf("Adding jp attribute failed\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
if (!add_indirect_data_object(p7)) {
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
content = spc_indirect_data_content_get(hash, ctx);
if (!content) {
printf("Failed to get spcIndirectDataContent\n");
return NULL; /* FAILED */
}
if (!sign_spc_indirect_data_content(p7, content)) {
printf("Failed to set signed content\n");
PKCS7_free(p7);
ASN1_OCTET_STRING_free(content);
return NULL; /* FAILED */
}
return 0; /* OK */
}

/*
* Create a new PKCS#7 signature.
* [in, out] ctx: structure holds input and output data
* [out] hash: message digest BIO
* [returns] pointer to PKCS#7 structure
*/
static PKCS7 *cab_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
{
ASN1_OCTET_STRING *content;
PKCS7 *p7 = pkcs7_create(ctx);

if (!p7) {
printf("Creating a new signature failed\n");
return NULL; /* FAILED */
}
if (ctx->options->jp >= 0 && !cab_add_jp_attribute(p7, ctx->options->jp)) {
printf("Adding jp attribute failed\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
if (!add_indirect_data_object(p7)) {
printf("Adding SPC_INDIRECT_DATA_OBJID failed\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
content = spc_indirect_data_content_get(hash, ctx);
if (!content) {
printf("Failed to get spcIndirectDataContent\n");
return NULL; /* FAILED */
}
if (!sign_spc_indirect_data_content(p7, content)) {
printf("Failed to set signed content\n");
PKCS7_free(p7);
ASN1_OCTET_STRING_free(content);
return NULL; /* FAILED */
}
if (ctx->options->nest)
ctx->options->prevsig = cursig;
ASN1_OCTET_STRING_free(content);
return p7;
}

Expand Down
Loading

0 comments on commit f22c835

Please sign in to comment.