273 lines
8.0 KiB
Diff
273 lines
8.0 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Robbie Harwood <rharwood@redhat.com>
|
||
|
Date: Fri, 10 Jun 2022 14:40:33 -0400
|
||
|
Subject: [PATCH] cms: store digest as pointer instead of index
|
||
|
|
||
|
Storage as an index is problematic because the sentinel value -1 was
|
||
|
used, but accesses were unchecked, leading to crashes like that in
|
||
|
3b1031a6b779cb80c11b34eec84c5a0cc215efed ("pesigcheck: Fix crash on
|
||
|
digest match"). By storing a pointer, we get an explicit NULL
|
||
|
dereference: still a crash, but preferred since it's clearer.
|
||
|
|
||
|
Since the index was previously also used for retrieving digest
|
||
|
parameters, include a pointer to the relevant struct digest_param in the
|
||
|
struct digest.
|
||
|
|
||
|
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
|
||
|
---
|
||
|
src/certdb.c | 15 ++++++++-------
|
||
|
src/cms_common.c | 34 ++++++++++------------------------
|
||
|
src/content_info.c | 4 ++--
|
||
|
src/file_kmod.c | 2 +-
|
||
|
src/file_pe.c | 9 +++++----
|
||
|
src/pesigcheck.c | 4 +---
|
||
|
src/cms_common.h | 13 ++++++++++++-
|
||
|
7 files changed, 39 insertions(+), 42 deletions(-)
|
||
|
|
||
|
diff --git a/src/certdb.c b/src/certdb.c
|
||
|
index 69d5daf..f512824 100644
|
||
|
--- a/src/certdb.c
|
||
|
+++ b/src/certdb.c
|
||
|
@@ -263,18 +263,19 @@ check_hash(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype,
|
||
|
{
|
||
|
efi_guid_t efi_sha256 = efi_guid_sha256;
|
||
|
efi_guid_t efi_sha1 = efi_guid_sha1;
|
||
|
- void *digest;
|
||
|
+ void *digest_data;
|
||
|
+ struct digest *digests = ctx->cms_ctx->digests;
|
||
|
|
||
|
if (memcmp(sigtype, &efi_sha256, sizeof(efi_guid_t)) == 0) {
|
||
|
- digest = ctx->cms_ctx->digests[0].pe_digest->data;
|
||
|
- if (memcmp (digest, sig->data, 32) == 0) {
|
||
|
- ctx->cms_ctx->selected_digest = 0;
|
||
|
+ digest_data = digests[0].pe_digest->data;
|
||
|
+ if (memcmp (digest_data, sig->data, 32) == 0) {
|
||
|
+ ctx->cms_ctx->selected_digest = &digests[0];
|
||
|
return FOUND;
|
||
|
}
|
||
|
} else if (memcmp(sigtype, &efi_sha1, sizeof(efi_guid_t)) == 0) {
|
||
|
- digest = ctx->cms_ctx->digests[1].pe_digest->data;
|
||
|
- if (memcmp (digest, sig->data, 20) == 0) {
|
||
|
- ctx->cms_ctx->selected_digest = 1;
|
||
|
+ digest_data = digests[1].pe_digest->data;
|
||
|
+ if (memcmp (digest_data, sig->data, 20) == 0) {
|
||
|
+ ctx->cms_ctx->selected_digest = &digests[1];
|
||
|
return FOUND;
|
||
|
}
|
||
|
}
|
||
|
diff --git a/src/cms_common.c b/src/cms_common.c
|
||
|
index 86341ca..2275f67 100644
|
||
|
--- a/src/cms_common.c
|
||
|
+++ b/src/cms_common.c
|
||
|
@@ -33,15 +33,6 @@
|
||
|
|
||
|
#include "hex.h"
|
||
|
|
||
|
-struct digest_param {
|
||
|
- char *name;
|
||
|
- SECOidTag digest_tag;
|
||
|
- SECOidTag signature_tag;
|
||
|
- SECOidTag digest_encryption_tag;
|
||
|
- const efi_guid_t *efi_guid;
|
||
|
- int size;
|
||
|
-};
|
||
|
-
|
||
|
static struct digest_param digest_params[] = {
|
||
|
{.name = "sha256",
|
||
|
.digest_tag = SEC_OID_SHA256,
|
||
|
@@ -65,29 +56,25 @@ static int n_digest_params = sizeof (digest_params) / sizeof (digest_params[0]);
|
||
|
SECOidTag
|
||
|
digest_get_digest_oid(cms_context *cms)
|
||
|
{
|
||
|
- int i = cms->selected_digest;
|
||
|
- return digest_params[i].digest_tag;
|
||
|
+ return cms->selected_digest->digest_params->digest_tag;
|
||
|
}
|
||
|
|
||
|
SECOidTag
|
||
|
digest_get_encryption_oid(cms_context *cms)
|
||
|
{
|
||
|
- int i = cms->selected_digest;
|
||
|
- return digest_params[i].digest_encryption_tag;
|
||
|
+ return cms->selected_digest->digest_params->digest_encryption_tag;
|
||
|
}
|
||
|
|
||
|
SECOidTag
|
||
|
digest_get_signature_oid(cms_context *cms)
|
||
|
{
|
||
|
- int i = cms->selected_digest;
|
||
|
- return digest_params[i].signature_tag;
|
||
|
+ return cms->selected_digest->digest_params->signature_tag;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
digest_get_digest_size(cms_context *cms)
|
||
|
{
|
||
|
- int i = cms->selected_digest;
|
||
|
- return digest_params[i].size;
|
||
|
+ return cms->selected_digest->digest_params->size;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
@@ -142,8 +129,6 @@ cms_context_init(cms_context *cms)
|
||
|
if (!cms->arena)
|
||
|
cnreterr(-1, cms, "could not create cryptographic arena");
|
||
|
|
||
|
- cms->selected_digest = -1;
|
||
|
-
|
||
|
INIT_LIST_HEAD(&cms->pk12_ins);
|
||
|
cms->pk12_out.fd = -1;
|
||
|
cms->db_out = cms->dbx_out = cms->dbt_out = -1;
|
||
|
@@ -226,7 +211,7 @@ cms_context_fini(cms_context *cms)
|
||
|
memset(&cms->newsig, '\0', sizeof (cms->newsig));
|
||
|
}
|
||
|
|
||
|
- cms->selected_digest = -1;
|
||
|
+ cms->selected_digest = NULL;
|
||
|
|
||
|
if (cms->ci_digest) {
|
||
|
free_poison(cms->ci_digest->data, cms->ci_digest->len);
|
||
|
@@ -351,7 +336,7 @@ set_digest_parameters(cms_context *cms, char *name)
|
||
|
if (strcmp(name, "help")) {
|
||
|
for (int i = 0; i < n_digest_params; i++) {
|
||
|
if (!strcmp(name, digest_params[i].name)) {
|
||
|
- cms->selected_digest = i;
|
||
|
+ cms->selected_digest = &cms->digests[i];
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
@@ -1279,6 +1264,7 @@ generate_digest_begin(cms_context *cms)
|
||
|
cngotoerr(err, cms, "could not create digest context");
|
||
|
|
||
|
PK11_DigestBegin(digests[i].pk11ctx);
|
||
|
+ digests[i].digest_params = &digest_params[i];
|
||
|
}
|
||
|
|
||
|
cms->digests = digests;
|
||
|
@@ -1351,11 +1337,11 @@ generate_signature(cms_context *cms)
|
||
|
{
|
||
|
int rc = 0;
|
||
|
|
||
|
- if (cms->digests[cms->selected_digest].pe_digest == NULL)
|
||
|
+ if (cms->selected_digest->pe_digest == NULL)
|
||
|
cnreterr(-1, cms, "PE digest has not been allocated");
|
||
|
|
||
|
- if (content_is_empty(cms->digests[cms->selected_digest].pe_digest->data,
|
||
|
- cms->digests[cms->selected_digest].pe_digest->len))
|
||
|
+ if (content_is_empty(cms->selected_digest->pe_digest->data,
|
||
|
+ cms->selected_digest->pe_digest->len))
|
||
|
cnreterr(-1, cms, "PE binary has not been digested");
|
||
|
|
||
|
SECItem sd_der;
|
||
|
diff --git a/src/content_info.c b/src/content_info.c
|
||
|
index 9684850..777aa28 100644
|
||
|
--- a/src/content_info.c
|
||
|
+++ b/src/content_info.c
|
||
|
@@ -181,8 +181,8 @@ generate_spc_digest_info(cms_context *cms, SECItem *dip)
|
||
|
if (generate_algorithm_id(cms, &di.digestAlgorithm,
|
||
|
digest_get_digest_oid(cms)) < 0)
|
||
|
return -1;
|
||
|
- int i = cms->selected_digest;
|
||
|
- memcpy(&di.digest, cms->digests[i].pe_digest, sizeof (di.digest));
|
||
|
+ memcpy(&di.digest, cms->selected_digest->pe_digest,
|
||
|
+ sizeof(di.digest));
|
||
|
|
||
|
if (content_is_empty(di.digest.data, di.digest.len)) {
|
||
|
cms->log(cms, LOG_ERR, "got empty digest");
|
||
|
diff --git a/src/file_kmod.c b/src/file_kmod.c
|
||
|
index 6880cda..c8875fc 100644
|
||
|
--- a/src/file_kmod.c
|
||
|
+++ b/src/file_kmod.c
|
||
|
@@ -60,7 +60,7 @@ ssize_t
|
||
|
kmod_write_signature(cms_context *cms, int outfd)
|
||
|
{
|
||
|
SEC_PKCS7ContentInfo *cinfo;
|
||
|
- SECItem *digest = cms->digests[cms->selected_digest].pe_digest;
|
||
|
+ SECItem *digest = cms->selected_digest->pe_digest;
|
||
|
SECStatus rv;
|
||
|
struct write_sig_info info = {
|
||
|
.outfd = outfd,
|
||
|
diff --git a/src/file_pe.c b/src/file_pe.c
|
||
|
index 805e614..c22b2af 100644
|
||
|
--- a/src/file_pe.c
|
||
|
+++ b/src/file_pe.c
|
||
|
@@ -114,6 +114,8 @@ check_inputs(pesign_context *ctx)
|
||
|
static void
|
||
|
print_digest(pesign_context *pctx)
|
||
|
{
|
||
|
+ unsigned int i;
|
||
|
+
|
||
|
if (!pctx)
|
||
|
return;
|
||
|
|
||
|
@@ -121,10 +123,9 @@ print_digest(pesign_context *pctx)
|
||
|
if (!ctx)
|
||
|
return;
|
||
|
|
||
|
- int j = ctx->selected_digest;
|
||
|
- for (unsigned int i = 0; i < ctx->digests[j].pe_digest->len; i++)
|
||
|
- printf("%02x",
|
||
|
- (unsigned char)ctx->digests[j].pe_digest->data[i]);
|
||
|
+ unsigned char *ddata = ctx->selected_digest->pe_digest->data;
|
||
|
+ for (i = 0; i < ctx->selected_digest->pe_digest->len; i++)
|
||
|
+ printf("%02x", ddata[i]);
|
||
|
printf(" %s\n", pctx->infile);
|
||
|
}
|
||
|
|
||
|
diff --git a/src/pesigcheck.c b/src/pesigcheck.c
|
||
|
index 6dc67f7..ebb404d 100644
|
||
|
--- a/src/pesigcheck.c
|
||
|
+++ b/src/pesigcheck.c
|
||
|
@@ -221,9 +221,7 @@ static void
|
||
|
get_digest(pesigcheck_context *ctx, SECItem *digest)
|
||
|
{
|
||
|
struct cms_context *cms = ctx->cms_ctx;
|
||
|
- struct digest *cms_digest = &cms->digests[cms->selected_digest];
|
||
|
-
|
||
|
- memcpy(digest, cms_digest->pe_digest, sizeof (*digest));
|
||
|
+ memcpy(digest, cms->selected_digest->pe_digest, sizeof(*digest));
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
diff --git a/src/cms_common.h b/src/cms_common.h
|
||
|
index c7acbcf..c7d4f69 100644
|
||
|
--- a/src/cms_common.h
|
||
|
+++ b/src/cms_common.h
|
||
|
@@ -12,6 +12,7 @@
|
||
|
#include <secpkcs7.h>
|
||
|
|
||
|
#include <errno.h>
|
||
|
+#include <efivar.h>
|
||
|
#include <signal.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <sys/types.h>
|
||
|
@@ -57,9 +58,19 @@
|
||
|
goto errlabel; \
|
||
|
})
|
||
|
|
||
|
+struct digest_param {
|
||
|
+ char *name;
|
||
|
+ SECOidTag digest_tag;
|
||
|
+ SECOidTag signature_tag;
|
||
|
+ SECOidTag digest_encryption_tag;
|
||
|
+ const efi_guid_t *efi_guid;
|
||
|
+ int size;
|
||
|
+};
|
||
|
+
|
||
|
struct digest {
|
||
|
PK11Context *pk11ctx;
|
||
|
SECItem *pe_digest;
|
||
|
+ struct digest_param *digest_params;
|
||
|
};
|
||
|
|
||
|
typedef struct pk12_file {
|
||
|
@@ -133,7 +144,7 @@ typedef struct cms_context {
|
||
|
int db_out, dbx_out, dbt_out;
|
||
|
|
||
|
struct digest *digests;
|
||
|
- int selected_digest;
|
||
|
+ struct digest *selected_digest;
|
||
|
int omit_vendor_cert;
|
||
|
|
||
|
SECItem newsig;
|