Simplify obtaining an existing signature and creating a new one

This commit is contained in:
olszomal
2024-01-23 15:13:21 +01:00
committed by Michał Trojnara
parent 44ca1f38e6
commit f22c83514c
9 changed files with 406 additions and 383 deletions

123
cab.c
View File

@ -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);
@ -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,
@ -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
@ -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;
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->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 */
}
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;
}