From f4ca0bfbd97dcc91fd067d5399908753fa4d4629f6bc8d157817ee607ff1bfec Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Wed, 29 Oct 2014 08:11:07 +0000 Subject: [PATCH] Accepting request 258749 from home:gary_lin:branches:Base:System - Update to version 0.110 - Enable aarch64 OBS-URL: https://build.opensuse.org/request/show/258749 OBS-URL: https://build.opensuse.org/package/show/Base:System/pesign?expand=0&rev=29 --- pesign-0.109.tar.gz | 3 - pesign-0.110.tar.bz2 | 3 + pesign-clear-padding-bits.patch | 28 - pesign-enable-supplementary-programs.patch | 4776 ------------------- pesign-fix-authvar-write-loop.patch | 72 + pesign-fix-build-errors.patch | 54 +- pesign-install-supplementary-programs.patch | 23 + pesign-no-db.patch | 142 - pesign-run.patch | 46 +- pesign-suse-build.patch | 26 +- pesign.changes | 18 + pesign.spec | 25 +- 12 files changed, 179 insertions(+), 5037 deletions(-) delete mode 100644 pesign-0.109.tar.gz create mode 100644 pesign-0.110.tar.bz2 delete mode 100644 pesign-clear-padding-bits.patch delete mode 100644 pesign-enable-supplementary-programs.patch create mode 100644 pesign-fix-authvar-write-loop.patch create mode 100644 pesign-install-supplementary-programs.patch delete mode 100644 pesign-no-db.patch diff --git a/pesign-0.109.tar.gz b/pesign-0.109.tar.gz deleted file mode 100644 index 7143b9a..0000000 --- a/pesign-0.109.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff7ee256ae615646fde1b542fe3ac1133a69a0542b1bd92e5a2e7ae6c550f545 -size 96921 diff --git a/pesign-0.110.tar.bz2 b/pesign-0.110.tar.bz2 new file mode 100644 index 0000000..d25c011 --- /dev/null +++ b/pesign-0.110.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a03499ffa181fea6086e1966476eccc05e3e014761ac300de1da27a44dba2281 +size 87420 diff --git a/pesign-clear-padding-bits.patch b/pesign-clear-padding-bits.patch deleted file mode 100644 index cad6d7c..0000000 --- a/pesign-clear-padding-bits.patch +++ /dev/null @@ -1,28 +0,0 @@ -From edd9cc0e677b35498e974d9a4137feac5bd4b323 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 26 Mar 2013 18:30:58 +0800 -Subject: [PATCH] Clear the space for the certificate list - -Make sure the aligned bytes are '\0' - -Signed-off-by: Gary Ching-Pang Lin ---- - src/wincert.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/wincert.c b/src/wincert.c -index 942fa26..5e23b04 100644 ---- a/src/wincert.c -+++ b/src/wincert.c -@@ -37,7 +37,7 @@ generate_cert_list(SECItem **signatures, int num_signatures, - cl_size += ALIGNMENT_PADDING(cl_size, 8); - } - -- uint8_t *data = malloc(cl_size); -+ uint8_t *data = calloc(1, cl_size); - if (!data) - return -1; - --- -1.8.1.4 - diff --git a/pesign-enable-supplementary-programs.patch b/pesign-enable-supplementary-programs.patch deleted file mode 100644 index fa807da..0000000 --- a/pesign-enable-supplementary-programs.patch +++ /dev/null @@ -1,4776 +0,0 @@ -From 4d80fec4a38b5cb1a63262a323353c23b0172b77 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 24 Dec 2013 11:33:26 +0800 -Subject: [PATCH 01/31] Allocate cms_context for peverify_context - -This avoids the crash while freeing cms_context. - -Signed-off-by: Gary Ching-Pang Lin ---- - src/peverify.c | 6 +++--- - src/peverify_context.c | 4 ++-- - src/peverify_context.h | 2 +- - 3 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/peverify.c b/src/peverify.c -index fc6de05..62e9995 100644 ---- a/src/peverify.c -+++ b/src/peverify.c -@@ -55,8 +55,8 @@ open_input(peverify_context *ctx) - exit(1); - } - -- int rc = parse_signatures(&ctx->cms_ctx.signatures, -- &ctx->cms_ctx.num_signatures, -+ 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 list in " -@@ -99,7 +99,7 @@ check_signature(peverify_context *ctx) - - cert_iter iter; - -- generate_digest(&ctx->cms_ctx, ctx->inpe, 1); -+ generate_digest(ctx->cms_ctx, ctx->inpe, 1); - - if (check_db_hash(DBX, ctx) == FOUND) - return -1; -diff --git a/src/peverify_context.c b/src/peverify_context.c -index 2e59f74..44fc442 100644 ---- a/src/peverify_context.c -+++ b/src/peverify_context.c -@@ -54,7 +54,7 @@ peverify_context_init(peverify_context *ctx) - - ctx->infd = -1; - -- int rc = cms_context_init(&ctx->cms_ctx); -+ int rc = cms_context_alloc(&ctx->cms_ctx); - if (rc < 0) - return rc; - -@@ -67,7 +67,7 @@ peverify_context_fini(peverify_context *ctx) - if (!ctx) - return; - -- cms_context_fini(&ctx->cms_ctx); -+ cms_context_fini(ctx->cms_ctx); - - xfree(ctx->infile); - -diff --git a/src/peverify_context.h b/src/peverify_context.h -index f9b0083..8599357 100644 ---- a/src/peverify_context.h -+++ b/src/peverify_context.h -@@ -57,7 +57,7 @@ typedef struct peverify_context { - dblist *db; - dblist *dbx; - -- cms_context cms_ctx; -+ cms_context *cms_ctx; - } peverify_context; - - extern int peverify_context_new(peverify_context **ctx); --- -1.8.4.5 - - -From b6e40af634aa0b10f59b5936727ccfc260f3dcf0 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 24 Dec 2013 11:48:08 +0800 -Subject: [PATCH 02/31] Calculate the dbsize to avoid the infinite loop - -Signed-off-by: Gary Ching-Pang Lin ---- - src/certdb.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/certdb.c b/src/certdb.c -index 5ef3ffe..b6e7c20 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -144,6 +144,10 @@ check_db(db_specifier which, peverify_context *ctx, checkfn check) - if (found == FOUND) - return FOUND; - } -+ -+ dbsize -= certlist->SignatureListSize; -+ certlist = (EFI_SIGNATURE_LIST *)((uint8_t *)certlist + -+ certlist->SignatureListSize); - } - dbl = dbl->next; - } --- -1.8.4.5 - - -From cab9f9ff4737be3e3607caa6dd7f945c50fe64fa Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 24 Dec 2013 12:35:02 +0800 -Subject: [PATCH 03/31] Update the pathes of db, MokListRT, and dbx - -Signed-off-by: Gary Ching-Pang Lin ---- - src/certdb.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/certdb.c b/src/certdb.c -index b6e7c20..f6f52bc 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -75,9 +75,9 @@ add_cert_dbx(peverify_context *ctx, const char *filename) - return add_db_file(ctx, DBX, filename); - } - --#define DB_PATH "/sys/firmware/efi/vars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f/data" --#define MOK_PATH "/sys/firmware/efi/vars/fixmefixmefixme/data" --#define DBX_PATH "/sys/firmware/efi/vars/dbx-d719b2cb-3d3a-4596-a3bc-dad00e67656f/data" -+#define DB_PATH "/sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f" -+#define MOK_PATH "/sys/firmware/efi/efivars/MokListRT-605dab50-e046-4300-abb6-3dd810dd8b23" -+#define DBX_PATH "/sys/firmware/efi/efivars/dbx-d719b2cb-3d3a-4596-a3bc-dad00e67656f" - - void - init_cert_db(peverify_context *ctx, int use_system_dbs) -@@ -97,7 +97,7 @@ init_cert_db(peverify_context *ctx, int use_system_dbs) - rc = add_db_file(ctx, DB, MOK_PATH); - if (rc < 0 && errno != ENOENT) { - fprintf(stderr, "peverify: Could not add key database " -- "\"%s\": %m\n", DB_PATH); -+ "\"%s\": %m\n", MOK_PATH); - exit(1); - } - --- -1.8.4.5 - - -From 200bff332ee34de2e2679cfdddd8d09a78b536f7 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 24 Dec 2013 14:53:58 +0800 -Subject: [PATCH 04/31] Skip the first 4 bytes in the efi variables - -The first 4 bytes store the attributes of the efi variable. - -Signed-off-by: Gary Ching-Pang Lin ---- - src/certdb.c | 25 +++++++++++++++++-------- - src/peverify_context.h | 2 ++ - 2 files changed, 19 insertions(+), 8 deletions(-) - -diff --git a/src/certdb.c b/src/certdb.c -index f6f52bc..d9d4dea 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -26,7 +26,7 @@ - #include "peverify.h" - - static int --add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile) -+add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile, int efivar) - { - dblist *db = calloc(1, sizeof (dblist)); - -@@ -55,6 +55,15 @@ add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile) - return -1; - } - -+ /* skip the first 4 bytes (EFI attributes) in the efi variable */ -+ if (efivar == 1) { -+ db->data = db->map + 4; -+ db->datalen = db->size - 4; -+ } else { -+ db->data = db->map; -+ db->datalen = db->size; -+ } -+ - dblist **tmp = which == DB ? &ctx->db : &ctx->dbx; - - db->next = *tmp; -@@ -66,13 +75,13 @@ add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile) - int - add_cert_db(peverify_context *ctx, const char *filename) - { -- return add_db_file(ctx, DB, filename); -+ return add_db_file(ctx, DB, filename, 0); - } - - int - add_cert_dbx(peverify_context *ctx, const char *filename) - { -- return add_db_file(ctx, DBX, filename); -+ return add_db_file(ctx, DBX, filename, 0); - } - - #define DB_PATH "/sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f" -@@ -87,14 +96,14 @@ init_cert_db(peverify_context *ctx, int use_system_dbs) - if (!use_system_dbs) - return; - -- rc = add_db_file(ctx, DB, DB_PATH); -+ rc = add_db_file(ctx, DB, DB_PATH, 1); - if (rc < 0 && errno != ENOENT) { - fprintf(stderr, "peverify: Could not add key database " - "\"%s\": %m\n", DB_PATH); - exit(1); - } - -- rc = add_db_file(ctx, DB, MOK_PATH); -+ rc = add_db_file(ctx, DB, MOK_PATH, 1); - if (rc < 0 && errno != ENOENT) { - fprintf(stderr, "peverify: Could not add key database " - "\"%s\": %m\n", MOK_PATH); -@@ -106,7 +115,7 @@ init_cert_db(peverify_context *ctx, int use_system_dbs) - "No key database available\n"); - } - -- rc = add_db_file(ctx, DBX, DBX_PATH); -+ rc = add_db_file(ctx, DBX, DBX_PATH, 1); - if (rc < 0 && errno != ENOENT) { - fprintf(stderr, "peverify: Could not add revocation " - "database \"%s\": %m\n", DBX_PATH); -@@ -126,10 +135,10 @@ check_db(db_specifier which, peverify_context *ctx, checkfn check) - while (dbl) { - EFI_SIGNATURE_LIST *certlist; - EFI_SIGNATURE_DATA *cert; -- size_t dbsize = dbl->size; -+ size_t dbsize = dbl->datalen; - unsigned long certcount; - -- certlist = dbl->map; -+ certlist = dbl->data; - while (dbsize > 0 && dbsize >= certlist->SignatureListSize) { - certcount = (certlist->SignatureListSize - - certlist->SignatureHeaderSize) -diff --git a/src/peverify_context.h b/src/peverify_context.h -index 8599357..37f415b 100644 ---- a/src/peverify_context.h -+++ b/src/peverify_context.h -@@ -31,6 +31,8 @@ struct dblist { - struct dblist *next; - size_t size; - void *map; -+ size_t datalen; -+ void *data; - }; - - typedef struct dblist dblist; --- -1.8.4.5 - - -From 237e983fe11800e36074c2a50d6468b7ac45ef12 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 25 Dec 2013 14:14:48 +0800 -Subject: [PATCH 05/31] Match the hashes in the db list - -Signed-off-by: Gary Ching-Pang Lin ---- - src/certdb.c | 19 ++++++++++++++++++- - 1 file changed, 18 insertions(+), 1 deletion(-) - -diff --git a/src/certdb.c b/src/certdb.c -index d9d4dea..470f7f3 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -144,7 +144,8 @@ check_db(db_specifier which, peverify_context *ctx, checkfn check) - certlist->SignatureHeaderSize) - / certlist->SignatureSize; - cert = (EFI_SIGNATURE_DATA *)((uint8_t *)certlist + -- sizeof(*cert) + certlist->SignatureHeaderSize); -+ sizeof(EFI_SIGNATURE_LIST) + -+ certlist->SignatureHeaderSize); - - for (int i = 0; i < certcount; i++) { - found = check(ctx, -@@ -152,6 +153,8 @@ check_db(db_specifier which, peverify_context *ctx, checkfn check) - &certlist->SignatureType); - if (found == FOUND) - return FOUND; -+ cert = (EFI_SIGNATURE_DATA *)((uint8_t *)cert + -+ certlist->SignatureSize); - } - - dbsize -= certlist->SignatureListSize; -@@ -166,6 +169,20 @@ check_db(db_specifier which, peverify_context *ctx, checkfn check) - static db_status - check_hash(peverify_context *ctx, void *sigdata, efi_guid_t *sigtype) - { -+ efi_guid_t efi_sha256 = EFI_CERT_SHA256_GUID; -+ efi_guid_t efi_sha1 = EFI_CERT_SHA1_GUID; -+ void *digest; -+ -+ if (memcmp(sigtype, &efi_sha256, sizeof(efi_guid_t)) == 0) { -+ digest = ctx->cms_ctx->digests[0].pe_digest->data; -+ if (memcmp (digest, sigdata, 32) == 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, sigdata, 20) == 0) -+ return FOUND; -+ } -+ - return NOT_FOUND; - } - --- -1.8.4.5 - - -From 135a083d0e648255096128a67463bc2191f4ac4a Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 24 Dec 2013 11:47:14 +0800 -Subject: [PATCH 06/31] Verify the signature with the certs in the dblist - -Signed-off-by: Gary Ching-Pang Lin ---- - src/certdb.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++------ - src/peverify.c | 66 +++++++++++++++++++++++++++++- - 2 files changed, 179 insertions(+), 14 deletions(-) - -diff --git a/src/certdb.c b/src/certdb.c -index 470f7f3..4937c44 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -23,6 +23,12 @@ - #include - #include - -+#include -+#include -+#include -+#include -+#include -+ - #include "peverify.h" - - static int -@@ -123,15 +129,23 @@ init_cert_db(peverify_context *ctx, int use_system_dbs) - } - } - --typedef db_status (*checkfn)(peverify_context *ctx, void *sigdata, -- efi_guid_t *sigtype); -+typedef db_status (*checkfn)(peverify_context *ctx, SECItem *sig, -+ efi_guid_t *sigtype, SECItem *pkcs7sig); - - static db_status --check_db(db_specifier which, peverify_context *ctx, checkfn check) -+check_db(db_specifier which, peverify_context *ctx, checkfn check, -+ void *data, ssize_t datalen) - { -+ SECItem pkcs7sig, sig; - dblist *dbl = which == DB ? ctx->db : ctx->dbx; - db_status found = NOT_FOUND; - -+ pkcs7sig.data = data; -+ pkcs7sig.len = datalen; -+ pkcs7sig.type = siBuffer; -+ -+ sig.type = siBuffer; -+ - while (dbl) { - EFI_SIGNATURE_LIST *certlist; - EFI_SIGNATURE_DATA *cert; -@@ -148,9 +162,10 @@ check_db(db_specifier which, peverify_context *ctx, checkfn check) - certlist->SignatureHeaderSize); - - for (int i = 0; i < certcount; i++) { -- found = check(ctx, -- cert->SignatureData, -- &certlist->SignatureType); -+ sig.data = cert->SignatureData; -+ sig.len = certlist->SignatureSize - sizeof(efi_guid_t); -+ found = check(ctx, &sig, &certlist->SignatureType, -+ &pkcs7sig); - if (found == FOUND) - return FOUND; - cert = (EFI_SIGNATURE_DATA *)((uint8_t *)cert + -@@ -167,7 +182,8 @@ check_db(db_specifier which, peverify_context *ctx, checkfn check) - } - - static db_status --check_hash(peverify_context *ctx, void *sigdata, efi_guid_t *sigtype) -+check_hash(peverify_context *ctx, SECItem *sig, efi_guid_t *sigtype, -+ SECItem *pkcs7sig) - { - efi_guid_t efi_sha256 = EFI_CERT_SHA256_GUID; - efi_guid_t efi_sha1 = EFI_CERT_SHA1_GUID; -@@ -175,11 +191,11 @@ check_hash(peverify_context *ctx, void *sigdata, efi_guid_t *sigtype) - - if (memcmp(sigtype, &efi_sha256, sizeof(efi_guid_t)) == 0) { - digest = ctx->cms_ctx->digests[0].pe_digest->data; -- if (memcmp (digest, sigdata, 32) == 0) -+ if (memcmp (digest, sig->data, 32) == 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, sigdata, 20) == 0) -+ if (memcmp (digest, sig->data, 20) == 0) - return FOUND; - } - -@@ -189,17 +205,102 @@ check_hash(peverify_context *ctx, void *sigdata, efi_guid_t *sigtype) - db_status - check_db_hash(db_specifier which, peverify_context *ctx) - { -- return check_db(which, ctx, check_hash); -+ return check_db(which, ctx, check_hash, NULL, 0); - } - - static db_status --check_cert(peverify_context *ctx, void *sigdata, efi_guid_t *sigtype) -+check_cert(peverify_context *ctx, SECItem *sig, efi_guid_t *sigtype, -+ SECItem *pkcs7sig) - { -- return NOT_FOUND; -+ SEC_PKCS7ContentInfo *cinfo = NULL; -+ CERTCertificate *cert = NULL; -+ CERTCertTrust trust; -+ SECItem *content, *digest = NULL; -+ PK11Context *pk11ctx = NULL; -+ SECOidData *oid; -+ PRBool result; -+ SECStatus rv; -+ db_status status = NOT_FOUND; -+ -+ efi_guid_t efi_x509 = EFI_CERT_X509_GUID; -+ -+ if (memcmp(sigtype, &efi_x509, sizeof(efi_guid_t)) != 0) -+ return NOT_FOUND; -+ -+ cinfo = SEC_PKCS7DecodeItem(pkcs7sig, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL); -+ if (!cinfo) -+ goto out; -+ -+ /* Generate the digest of contentInfo */ -+ /* XXX support only sha256 for now */ -+ digest = SECITEM_AllocItem(NULL, NULL, 32); -+ if (digest == NULL) -+ goto out; -+ -+ content = cinfo->content.signedData->contentInfo.content.data; -+ oid = SECOID_FindOIDByTag(SEC_OID_SHA256); -+ if (oid == NULL) -+ goto out; -+ pk11ctx = PK11_CreateDigestContext(oid->offset); -+ if (ctx == NULL) -+ goto out; -+ if (PK11_DigestBegin(pk11ctx) != SECSuccess) -+ goto out; -+ /* Skip the SEQUENCE tag */ -+ if (PK11_DigestOp(pk11ctx, content->data + 2, content->len - 2) != SECSuccess) -+ goto out; -+ if (PK11_DigestFinal(pk11ctx, digest->data, &digest->len, 32) != SECSuccess) -+ goto out; -+ -+ /* Import the trusted certificate */ -+ cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), sig, "Temp CA", -+ PR_FALSE, PR_TRUE); -+ if (!cert) { -+ fprintf(stderr, "Unable to create cert: %s\n", -+ PORT_ErrorToString(PORT_GetError())); -+ goto out; -+ } -+ -+ rv = CERT_DecodeTrustString(&trust, ",,P"); -+ if (rv != SECSuccess) { -+ fprintf(stderr, "Unable to decode trust string: %s\n", -+ PORT_ErrorToString(PORT_GetError())); -+ goto out; -+ } -+ -+ rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust); -+ if (rv != SECSuccess) { -+ fprintf(stderr, "Failed to change cert trust: %s\n", -+ PORT_ErrorToString(PORT_GetError())); -+ goto out; -+ } -+ -+ /* Verify the signature */ -+ result = SEC_PKCS7VerifyDetachedSignature(cinfo, certUsageObjectSigner, -+ digest, HASH_AlgSHA256, -+ PR_FALSE); -+ if (!result) { -+ fprintf(stderr, "%s\n", PORT_ErrorToString(PORT_GetError())); -+ goto out; -+ } -+ -+ status = FOUND; -+out: -+ if (cinfo) -+ SEC_PKCS7DestroyContentInfo(cinfo); -+ if (cert) -+ CERT_DestroyCertificate(cert); -+ if (pk11ctx) -+ PK11_DestroyContext(pk11ctx, PR_TRUE); -+ if (digest) -+ SECITEM_FreeItem(digest, PR_FALSE); -+ -+ return status; - } - - db_status - check_db_cert(db_specifier which, peverify_context *ctx, void *data, ssize_t datalen) - { -- return check_db(which, ctx, check_cert); -+ return check_db(which, ctx, check_cert, data, datalen); - } -diff --git a/src/peverify.c b/src/peverify.c -index 62e9995..47d7ee1 100644 ---- a/src/peverify.c -+++ b/src/peverify.c -@@ -24,11 +24,15 @@ - #include - #include - #include -+#include -+#include - - #include - -+#include - #include - #include -+#include - - #include "peverify.h" - -@@ -87,7 +91,34 @@ check_inputs(peverify_context *ctx) - static int - cert_matches_digest(peverify_context *ctx, void *data, ssize_t datalen) - { -- return -1; -+ SECItem sig, *pe_digest, *content; -+ uint8_t *digest; -+ SEC_PKCS7ContentInfo *cinfo = NULL; -+ int ret = -1; -+ -+ sig.data = data; -+ sig.len = datalen; -+ sig.type = siBuffer; -+ -+ cinfo = SEC_PKCS7DecodeItem(&sig, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL); -+ -+ if (!SEC_PKCS7ContentIsSigned(cinfo)) -+ goto out; -+ -+ /* TODO Find out the digest type in spc_content */ -+ pe_digest = ctx->cms_ctx->digests[0].pe_digest; -+ content = cinfo->content.signedData->contentInfo.content.data; -+ digest = content->data + content->len - pe_digest->len; -+ if (memcmp(pe_digest->data, digest, pe_digest->len) != 0) -+ goto out; -+ -+ ret = 0; -+out: -+ if (cinfo) -+ SEC_PKCS7DestroyContentInfo(cinfo); -+ -+ return ret; - } - - static int -@@ -164,6 +195,23 @@ callback(poptContext con, enum poptCallbackReason reason, - } - } - -+static int -+delete_files(const char *fpath, const struct stat *sb, int typeflag) -+{ -+ if (typeflag == FTW_F) -+ remove(fpath); -+ -+ return 0; -+} -+ -+static void -+remove_certdir(const char *certdir) -+{ -+ ftw(certdir, delete_files, 3); -+ -+ remove(certdir); -+} -+ - int - main(int argc, char *argv[]) - { -@@ -175,6 +223,10 @@ main(int argc, char *argv[]) - char *dbxfile = NULL; - int use_system_dbs = 1; - -+ char template[] = "/tmp/peverify-XXXXXX"; -+ char *certdir = NULL; -+ SECStatus status; -+ - poptContext optCon; - struct poptOption options[] = { - {"dbfile", 'D', POPT_ARG_CALLBACK|POPT_CBFLAG_POST, (void *)callback, 0, (void *)ctxp, NULL }, -@@ -226,6 +278,14 @@ main(int argc, char *argv[]) - - init_cert_db(ctxp, use_system_dbs); - -+ certdir = mkdtemp(template); -+ status = NSS_InitReadWrite(certdir); -+ if (status != SECSuccess) { -+ fprintf(stderr, "Could not initialize nss: %s\n", -+ PORT_ErrorToString(PORT_GetError())); -+ exit(1); -+ } -+ - rc = check_signature(ctxp); - - close_input(ctxp); -@@ -233,5 +293,9 @@ main(int argc, char *argv[]) - printf("peverify: \"%s\" is %s.\n", ctx.infile, - rc >= 0 ? "valid" : "invalid"); - peverify_context_fini(&ctx); -+ -+ NSS_Shutdown(); -+ remove_certdir(certdir); -+ - return (rc < 0); - } --- -1.8.4.5 - - -From 35746653e0af5b129dfdfd33e9954ff5c47062aa Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 27 Dec 2013 17:42:19 +0800 -Subject: [PATCH 07/31] Verify the PE image with a certificate - -Signed-off-by: Gary Ching-Pang Lin ---- - src/certdb.c | 57 ++++++++++++++++++++++++++++++++++++++++---------- - src/certdb.h | 1 + - src/peverify.c | 5 +++++ - src/peverify_context.c | 4 ++++ - src/peverify_context.h | 7 +++++++ - 5 files changed, 63 insertions(+), 11 deletions(-) - -diff --git a/src/certdb.c b/src/certdb.c -index 4937c44..922b783 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -32,13 +33,16 @@ - #include "peverify.h" - - static int --add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile, int efivar) -+add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile, -+ db_f_type type) - { - dblist *db = calloc(1, sizeof (dblist)); - - if (!db) - return -1; - -+ db->type = type; -+ - db->fd = open(dbfile, O_RDONLY); - if (db->fd < 0) { - save_errno(free(db)); -@@ -61,13 +65,38 @@ add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile, int e - return -1; - } - -- /* skip the first 4 bytes (EFI attributes) in the efi variable */ -- if (efivar == 1) { -- db->data = db->map + 4; -- db->datalen = db->size - 4; -- } else { -+ EFI_SIGNATURE_LIST *certlist; -+ EFI_SIGNATURE_DATA *cert; -+ efi_guid_t efi_x509 = EFI_CERT_X509_GUID; -+ -+ switch (type) { -+ case DB_FILE: - db->data = db->map; - db->datalen = db->size; -+ break; -+ case DB_EFIVAR: -+ /* skip the first 4 bytes (EFI attributes) */ -+ db->data = db->map + 4; -+ db->datalen = db->size - 4; -+ break; -+ case DB_CERT: -+ db->datalen = db->size + sizeof(EFI_SIGNATURE_LIST) + -+ sizeof(efi_guid_t); -+ db->data = calloc(1, db->datalen); -+ if (!db->data) -+ return -1; -+ -+ certlist = (EFI_SIGNATURE_LIST *)db->data; -+ memcpy((void *)&certlist->SignatureType, &efi_x509, sizeof(efi_guid_t)); -+ certlist->SignatureListSize = db->datalen; -+ certlist->SignatureHeaderSize = 0; -+ certlist->SignatureSize = db->size + sizeof(efi_guid_t); -+ -+ cert = (EFI_SIGNATURE_DATA *)(db->data + sizeof(EFI_SIGNATURE_LIST)); -+ memcpy((void *)cert->SignatureData, db->map, db->size); -+ break; -+ default: -+ break; - } - - dblist **tmp = which == DB ? &ctx->db : &ctx->dbx; -@@ -81,13 +110,19 @@ add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile, int e - int - add_cert_db(peverify_context *ctx, const char *filename) - { -- return add_db_file(ctx, DB, filename, 0); -+ return add_db_file(ctx, DB, filename, DB_FILE); - } - - int - add_cert_dbx(peverify_context *ctx, const char *filename) - { -- return add_db_file(ctx, DBX, filename, 0); -+ return add_db_file(ctx, DBX, filename, DB_FILE); -+} -+ -+int -+add_cert_file(peverify_context *ctx, const char *filename) -+{ -+ return add_db_file(ctx, DB, filename, DB_CERT); - } - - #define DB_PATH "/sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f" -@@ -102,14 +137,14 @@ init_cert_db(peverify_context *ctx, int use_system_dbs) - if (!use_system_dbs) - return; - -- rc = add_db_file(ctx, DB, DB_PATH, 1); -+ rc = add_db_file(ctx, DB, DB_PATH, DB_EFIVAR); - if (rc < 0 && errno != ENOENT) { - fprintf(stderr, "peverify: Could not add key database " - "\"%s\": %m\n", DB_PATH); - exit(1); - } - -- rc = add_db_file(ctx, DB, MOK_PATH, 1); -+ rc = add_db_file(ctx, DB, MOK_PATH, DB_EFIVAR); - if (rc < 0 && errno != ENOENT) { - fprintf(stderr, "peverify: Could not add key database " - "\"%s\": %m\n", MOK_PATH); -@@ -121,7 +156,7 @@ init_cert_db(peverify_context *ctx, int use_system_dbs) - "No key database available\n"); - } - -- rc = add_db_file(ctx, DBX, DBX_PATH, 1); -+ rc = add_db_file(ctx, DBX, DBX_PATH, DB_EFIVAR); - if (rc < 0 && errno != ENOENT) { - fprintf(stderr, "peverify: Could not add revocation " - "database \"%s\": %m\n", DBX_PATH); -diff --git a/src/certdb.h b/src/certdb.h -index ee70ba6..d64494d 100644 ---- a/src/certdb.h -+++ b/src/certdb.h -@@ -48,5 +48,6 @@ extern db_status check_db_cert(db_specifier which, peverify_context *ctx, - extern void init_cert_db(peverify_context *ctx, int use_system_dbs); - extern int add_cert_db(peverify_context *ctx, const char *filename); - extern int add_cert_dbx(peverify_context *ctx, const char *filename); -+extern int add_cert_file(peverify_context *ctx, const char *filename); - - #endif /* CERTDB_H */ -diff --git a/src/peverify.c b/src/peverify.c -index 47d7ee1..e4c3e13 100644 ---- a/src/peverify.c -+++ b/src/peverify.c -@@ -187,6 +187,8 @@ callback(poptContext con, enum poptCallbackReason reason, - rc = add_cert_db(ctx, arg); - } else if (opt->shortName == 'X') { - rc = add_cert_dbx(ctx, arg); -+ } else if (opt->shortName == 'c') { -+ rc = add_cert_file(ctx, arg); - } - if (rc != 0) { - fprintf(stderr, "Could not add %s from file \"%s\": %m\n", -@@ -221,6 +223,7 @@ main(int argc, char *argv[]) - - char *dbfile = NULL; - char *dbxfile = NULL; -+ char *certfile = NULL; - int use_system_dbs = 1; - - char template[] = "/tmp/peverify-XXXXXX"; -@@ -242,6 +245,8 @@ main(int argc, char *argv[]) - "use file for allowed certificate list", "" }, - {"dbxfile", 'X', POPT_ARG_STRING, &dbxfile, 0, - "use file for disallowed certificate list",""}, -+ {"certfile", 'c', POPT_ARG_STRING, &certfile, 0, -+ "the certificate (in DER form) for verification ",""}, - POPT_AUTOALIAS - POPT_AUTOHELP - POPT_TABLEEND -diff --git a/src/peverify_context.c b/src/peverify_context.c -index 44fc442..d3aa53e 100644 ---- a/src/peverify_context.c -+++ b/src/peverify_context.c -@@ -82,6 +82,8 @@ peverify_context_fini(peverify_context *ctx) - while (ctx->db) { - dblist *db = ctx->db; - -+ if (db->type == DB_CERT) -+ free(db->data); - munmap(db->map, db->size); - close(db->fd); - ctx->db = db->next; -@@ -90,6 +92,8 @@ peverify_context_fini(peverify_context *ctx) - while (ctx->dbx) { - dblist *db = ctx->dbx; - -+ if (db->type == DB_CERT) -+ free(db->data); - munmap(db->map, db->size); - close(db->fd); - ctx->dbx = db->next; -diff --git a/src/peverify_context.h b/src/peverify_context.h -index 37f415b..7e26d06 100644 ---- a/src/peverify_context.h -+++ b/src/peverify_context.h -@@ -26,7 +26,14 @@ enum { - PEVERIFY_C_ALLOCATED = 1, - }; - -+typedef enum { -+ DB_FILE, -+ DB_EFIVAR, -+ DB_CERT, -+} db_f_type; -+ - struct dblist { -+ db_f_type type; - int fd; - struct dblist *next; - size_t size; --- -1.8.4.5 - - -From 23295225a732058edabc58ede7e863d347d2ac47 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 27 Dec 2013 17:43:32 +0800 -Subject: [PATCH 08/31] It's peverify, not pesign :) - -Signed-off-by: Gary Ching-Pang Lin ---- - src/peverify.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/peverify.c b/src/peverify.c -index e4c3e13..ebd7ee7 100644 ---- a/src/peverify.c -+++ b/src/peverify.c -@@ -40,21 +40,21 @@ static void - open_input(peverify_context *ctx) - { - if (!ctx->infile) { -- fprintf(stderr, "pesign: No input file specified.\n"); -+ fprintf(stderr, "peverify: No input file specified.\n"); - exit(1); - } - - ctx->infd = open(ctx->infile, O_RDONLY|O_CLOEXEC); - - if (ctx->infd < 0) { -- fprintf(stderr, "pesign: Error opening input: %m\n"); -+ fprintf(stderr, "peverify: Error opening input: %m\n"); - exit(1); - } - - Pe_Cmd cmd = ctx->infd == STDIN_FILENO ? PE_C_READ : PE_C_READ_MMAP; - ctx->inpe = pe_begin(ctx->infd, cmd, NULL); - if (!ctx->inpe) { -- fprintf(stderr, "pesign: could not load input file: %s\n", -+ fprintf(stderr, "peverify: could not load input file: %s\n", - pe_errmsg(pe_errno())); - exit(1); - } -@@ -63,7 +63,7 @@ open_input(peverify_context *ctx) - &ctx->cms_ctx->num_signatures, - ctx->inpe); - if (rc < 0) { -- fprintf(stderr, "pesign: could not parse signature list in " -+ fprintf(stderr, "peverify: could not parse signature list in " - "EFI binary\n"); - exit(1); - } --- -1.8.4.5 - - -From b431e22f0e02e282ece114e1829575e7eedfcfb5 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 6 Jan 2014 14:11:34 -0500 -Subject: [PATCH 09/31] Rename peverify to pesigcheck - -Signed-off-by: Peter Jones ---- - src/.gitignore | 2 +- - src/Makefile | 16 +-- - src/certdb.c | 32 ++--- - src/certdb.h | 12 +- - src/pesigcheck.1 | 25 ++++ - src/pesigcheck.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++ - src/pesigcheck.h | 39 ++++++ - src/pesigcheck_context.c | 122 +++++++++++++++++++ - src/pesigcheck_context.h | 78 ++++++++++++ - src/peverify.1 | 25 ---- - src/peverify.c | 306 ----------------------------------------------- - src/peverify.h | 39 ------ - src/peverify_context.c | 122 ------------------- - src/peverify_context.h | 78 ------------ - 14 files changed, 601 insertions(+), 601 deletions(-) - create mode 100644 src/pesigcheck.1 - create mode 100644 src/pesigcheck.c - create mode 100644 src/pesigcheck.h - create mode 100644 src/pesigcheck_context.c - create mode 100644 src/pesigcheck_context.h - delete mode 100644 src/peverify.1 - delete mode 100644 src/peverify.c - delete mode 100644 src/peverify.h - delete mode 100644 src/peverify_context.c - delete mode 100644 src/peverify_context.h - -diff --git a/src/.gitignore b/src/.gitignore -index fec12ae..7215f64 100644 ---- a/src/.gitignore -+++ b/src/.gitignore -@@ -12,4 +12,4 @@ ms - client - efikeygen - efisiglist --peverify -+pesigcheck -diff --git a/src/Makefile b/src/Makefile -index f478aa6..0aa13a1 100644 ---- a/src/Makefile -+++ b/src/Makefile -@@ -10,7 +10,7 @@ LDFLAGS = - CCLDFLAGS = -L../libdpe $(foreach pklib,$(PKLIBS), $(shell pkg-config --libs-only-L $(pklib))) - CFLAGS += -I../include/ $(foreach pklib,$(PKLIBS), $(shell pkg-config --cflags $(pklib))) -Werror - --TARGETS = pesign authvar client efisiglist efikeygen peverify -+TARGETS = pesign authvar client efisiglist efikeygen pesigcheck - - all : $(TARGETS) - -@@ -29,10 +29,10 @@ pesign_OBJECTS = $(foreach source,$(pesign_SOURCES),$(patsubst %.c,%,$(source)). - pesign_DEPS = $(foreach source,$(pesign_SOURCES),.$(patsubst %.c,%,$(source)).P) - pesign : $(pesign_OBJECTS) $(STATIC_LIBS) - --peverify_SOURCES = peverify.c peverify_context.c certdb.c --peverify_OBJECTS = $(foreach source,$(peverify_SOURCES),$(patsubst %.c,%,$(source)).o) generic.a --peverify_DEPS = $(foreach source,$(peverify_SOURCES),.$(patsubst %.c,%,$(source)).P) --peverify : $(peverify_OBJECTS) $(STATIC_LIBS) -+pesigcheck_SOURCES = pesigcheck.c pesigcheck_context.c certdb.c -+pesigcheck_OBJECTS = $(foreach source,$(pesigcheck_SOURCES),$(patsubst %.c,%,$(source)).o) generic.a -+pesigcheck_DEPS = $(foreach source,$(pesigcheck_SOURCES),.$(patsubst %.c,%,$(source)).P) -+pesigcheck : $(pesigcheck_OBJECTS) $(STATIC_LIBS) - - client_SOURCES = pesign_context.c actions.c client.c - client_OBJECTS = $(foreach source,$(client_SOURCES),$(patsubst %.c,%,$(source)).o) generic.a -@@ -55,7 +55,7 @@ fuzzsocket_DEPS = $(foreach source,$(fuzzsocket_SOURCES),.$(patsubst %.c,%,$(sou - fuzzsocket : $(fuzzsocket_OBJECTS) -lrt - - DEPS = $(generic_DEPS) $(authvar_DEPS) $(pesign_DEPS) $(client_DEPS) \ -- $(peverify_DEPS) $(efisiglist_DEPS) $(efikeygen_DEPS) -+ $(pesigcheck_DEPS) $(efisiglist_DEPS) $(efikeygen_DEPS) - - deps : $(DEPS) - -@@ -84,14 +84,14 @@ install : - $(INSTALL) -m 755 pesign $(INSTALLROOT)$(PREFIX)/bin/ - $(INSTALL) -m 755 client $(INSTALLROOT)$(PREFIX)/bin/pesign-client - $(INSTALL) -m 755 efikeygen $(INSTALLROOT)$(PREFIX)/bin/ -- #$(INSTALL) -m 755 peverify $(INSTALLROOT)$(PREFIX)/bin/ -+ #$(INSTALL) -m 755 pesigcheck $(INSTALLROOT)$(PREFIX)/bin/ - $(INSTALL) -d -m 755 $(INSTALLROOT)/etc/popt.d/ - $(INSTALL) -m 644 pesign.popt $(INSTALLROOT)/etc/popt.d/ - $(INSTALL) -d -m 755 $(INSTALLROOT)/usr/share/man/man1/ - $(INSTALL) -m 644 pesign.1 $(INSTALLROOT)/usr/share/man/man1/ - $(INSTALL) -m 644 pesign-client.1 $(INSTALLROOT)/usr/share/man/man1/ - $(INSTALL) -m 644 efikeygen.1 $(INSTALLROOT)/usr/share/man/man1/ -- #$(INSTALL) -m 644 peverify.1 $(INSTALLROOT)/usr/share/man/man1/ -+ #$(INSTALL) -m 644 pesigcheck.1 $(INSTALLROOT)/usr/share/man/man1/ - $(INSTALL) -d -m 755 $(INSTALLROOT)/etc/rpm/ - $(INSTALL) -m 644 macros.pesign $(INSTALLROOT)/etc/rpm/ - -diff --git a/src/certdb.c b/src/certdb.c -index 922b783..24c319b 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -30,10 +30,10 @@ - #include - #include - --#include "peverify.h" -+#include "pesigcheck.h" - - static int --add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile, -+add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, - db_f_type type) - { - dblist *db = calloc(1, sizeof (dblist)); -@@ -108,19 +108,19 @@ add_db_file(peverify_context *ctx, db_specifier which, const char *dbfile, - } - - int --add_cert_db(peverify_context *ctx, const char *filename) -+add_cert_db(pesigcheck_context *ctx, const char *filename) - { - return add_db_file(ctx, DB, filename, DB_FILE); - } - - int --add_cert_dbx(peverify_context *ctx, const char *filename) -+add_cert_dbx(pesigcheck_context *ctx, const char *filename) - { - return add_db_file(ctx, DBX, filename, DB_FILE); - } - - int --add_cert_file(peverify_context *ctx, const char *filename) -+add_cert_file(pesigcheck_context *ctx, const char *filename) - { - return add_db_file(ctx, DB, filename, DB_CERT); - } -@@ -130,7 +130,7 @@ add_cert_file(peverify_context *ctx, const char *filename) - #define DBX_PATH "/sys/firmware/efi/efivars/dbx-d719b2cb-3d3a-4596-a3bc-dad00e67656f" - - void --init_cert_db(peverify_context *ctx, int use_system_dbs) -+init_cert_db(pesigcheck_context *ctx, int use_system_dbs) - { - int rc = 0; - -@@ -139,36 +139,36 @@ init_cert_db(peverify_context *ctx, int use_system_dbs) - - rc = add_db_file(ctx, DB, DB_PATH, DB_EFIVAR); - if (rc < 0 && errno != ENOENT) { -- fprintf(stderr, "peverify: Could not add key database " -+ fprintf(stderr, "pesigcheck: Could not add key database " - "\"%s\": %m\n", DB_PATH); - exit(1); - } - - rc = add_db_file(ctx, DB, MOK_PATH, DB_EFIVAR); - if (rc < 0 && errno != ENOENT) { -- fprintf(stderr, "peverify: Could not add key database " -+ fprintf(stderr, "pesigcheck: Could not add key database " - "\"%s\": %m\n", MOK_PATH); - exit(1); - } - - if (ctx->db == NULL) { -- fprintf(stderr, "peverify: warning: " -+ fprintf(stderr, "pesigcheck: warning: " - "No key database available\n"); - } - - rc = add_db_file(ctx, DBX, DBX_PATH, DB_EFIVAR); - if (rc < 0 && errno != ENOENT) { -- fprintf(stderr, "peverify: Could not add revocation " -+ fprintf(stderr, "pesigcheck: Could not add revocation " - "database \"%s\": %m\n", DBX_PATH); - exit(1); - } - } - --typedef db_status (*checkfn)(peverify_context *ctx, SECItem *sig, -+typedef db_status (*checkfn)(pesigcheck_context *ctx, SECItem *sig, - efi_guid_t *sigtype, SECItem *pkcs7sig); - - static db_status --check_db(db_specifier which, peverify_context *ctx, checkfn check, -+check_db(db_specifier which, pesigcheck_context *ctx, checkfn check, - void *data, ssize_t datalen) - { - SECItem pkcs7sig, sig; -@@ -217,7 +217,7 @@ check_db(db_specifier which, peverify_context *ctx, checkfn check, - } - - static db_status --check_hash(peverify_context *ctx, SECItem *sig, efi_guid_t *sigtype, -+check_hash(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - SECItem *pkcs7sig) - { - efi_guid_t efi_sha256 = EFI_CERT_SHA256_GUID; -@@ -238,13 +238,13 @@ check_hash(peverify_context *ctx, SECItem *sig, efi_guid_t *sigtype, - } - - db_status --check_db_hash(db_specifier which, peverify_context *ctx) -+check_db_hash(db_specifier which, pesigcheck_context *ctx) - { - return check_db(which, ctx, check_hash, NULL, 0); - } - - static db_status --check_cert(peverify_context *ctx, SECItem *sig, efi_guid_t *sigtype, -+check_cert(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - SECItem *pkcs7sig) - { - SEC_PKCS7ContentInfo *cinfo = NULL; -@@ -335,7 +335,7 @@ out: - } - - db_status --check_db_cert(db_specifier which, peverify_context *ctx, void *data, ssize_t datalen) -+check_db_cert(db_specifier which, pesigcheck_context *ctx, void *data, ssize_t datalen) - { - return check_db(which, ctx, check_cert, data, datalen); - } -diff --git a/src/certdb.h b/src/certdb.h -index d64494d..ccf3c87 100644 ---- a/src/certdb.h -+++ b/src/certdb.h -@@ -41,13 +41,13 @@ typedef struct { - uint32_t SignatureSize; - } EFI_SIGNATURE_LIST; - --extern db_status check_db_hash(db_specifier which, peverify_context *ctx); --extern db_status check_db_cert(db_specifier which, peverify_context *ctx, -+extern db_status check_db_hash(db_specifier which, pesigcheck_context *ctx); -+extern db_status check_db_cert(db_specifier which, pesigcheck_context *ctx, - void *data, ssize_t datalen); - --extern void init_cert_db(peverify_context *ctx, int use_system_dbs); --extern int add_cert_db(peverify_context *ctx, const char *filename); --extern int add_cert_dbx(peverify_context *ctx, const char *filename); --extern int add_cert_file(peverify_context *ctx, const char *filename); -+extern void init_cert_db(pesigcheck_context *ctx, int use_system_dbs); -+extern int add_cert_db(pesigcheck_context *ctx, const char *filename); -+extern int add_cert_dbx(pesigcheck_context *ctx, const char *filename); -+extern int add_cert_file(pesigcheck_context *ctx, const char *filename); - - #endif /* CERTDB_H */ -diff --git a/src/pesigcheck.1 b/src/pesigcheck.1 -new file mode 100644 -index 0000000..55101ab ---- /dev/null -+++ b/src/pesigcheck.1 -@@ -0,0 +1,25 @@ -+.TH pesigcheck 1 "Mon Sep 10 2012" -+.SH NAME -+pesign \- command line tool for verifying UEFI applications -+ -+.SH SYNOPSIS -+\fBpesign\fR [--in=\fIinfile\fR | -i \fIinfile\fR] [--quiet | -q ] -+ [--db=\fIdbfile\fR | -D \fIdbfile\fR ] -+ [--dbx=\fIdbxfile\fR | -X \fIdbxfile\fR ] -+ -+.SH DESCRIPTION -+\fBpesigcheck\fR is a command line tool for verifying the signature of UEFI -+applications. -+ -+.SH OPTIONS -+.TP -+\fB-\-in\fR=\fIinfile\fR -+Specify input binary. -+ -+.SH "SEE ALSO" -+.BR pesigcheck (1) -+ -+.SH AUTHORS -+.nf -+Peter Jones -+.fi -diff --git a/src/pesigcheck.c b/src/pesigcheck.c -new file mode 100644 -index 0000000..7cd98c9 ---- /dev/null -+++ b/src/pesigcheck.c -@@ -0,0 +1,306 @@ -+/* -+ * Copyright 2011-2012 Red Hat, Inc. -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ * Author(s): Peter Jones -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "pesigcheck.h" -+ -+static void -+open_input(pesigcheck_context *ctx) -+{ -+ if (!ctx->infile) { -+ fprintf(stderr, "pesigcheck: No input file specified.\n"); -+ exit(1); -+ } -+ -+ ctx->infd = open(ctx->infile, O_RDONLY|O_CLOEXEC); -+ -+ if (ctx->infd < 0) { -+ fprintf(stderr, "pesigcheck: Error opening input: %m\n"); -+ exit(1); -+ } -+ -+ Pe_Cmd cmd = ctx->infd == STDIN_FILENO ? PE_C_READ : PE_C_READ_MMAP; -+ ctx->inpe = pe_begin(ctx->infd, cmd, NULL); -+ if (!ctx->inpe) { -+ fprintf(stderr, "pesigcheck: could not load input file: %s\n", -+ pe_errmsg(pe_errno())); -+ exit(1); -+ } -+ -+ int rc = parse_signatures(&ctx->cms_ctx->signatures, -+ &ctx->cms_ctx->num_signatures, -+ ctx->inpe); -+ if (rc < 0) { -+ fprintf(stderr, "pesigcheck: could not parse signature list in " -+ "EFI binary\n"); -+ exit(1); -+ } -+} -+ -+static void -+close_input(pesigcheck_context *ctx) -+{ -+ pe_end(ctx->inpe); -+ ctx->inpe = NULL; -+ -+ close(ctx->infd); -+ ctx->infd = -1; -+} -+ -+static void -+check_inputs(pesigcheck_context *ctx) -+{ -+ if (!ctx->infile) { -+ fprintf(stderr, "pesign: No input file specified.\n"); -+ exit(1); -+ } -+} -+ -+static int -+cert_matches_digest(pesigcheck_context *ctx, void *data, ssize_t datalen) -+{ -+ SECItem sig, *pe_digest, *content; -+ uint8_t *digest; -+ SEC_PKCS7ContentInfo *cinfo = NULL; -+ int ret = -1; -+ -+ sig.data = data; -+ sig.len = datalen; -+ sig.type = siBuffer; -+ -+ cinfo = SEC_PKCS7DecodeItem(&sig, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL); -+ -+ if (!SEC_PKCS7ContentIsSigned(cinfo)) -+ goto out; -+ -+ /* TODO Find out the digest type in spc_content */ -+ pe_digest = ctx->cms_ctx->digests[0].pe_digest; -+ content = cinfo->content.signedData->contentInfo.content.data; -+ digest = content->data + content->len - pe_digest->len; -+ if (memcmp(pe_digest->data, digest, pe_digest->len) != 0) -+ goto out; -+ -+ ret = 0; -+out: -+ if (cinfo) -+ SEC_PKCS7DestroyContentInfo(cinfo); -+ -+ return ret; -+} -+ -+static int -+check_signature(pesigcheck_context *ctx) -+{ -+ int has_valid_cert = 0; -+ int has_invalid_cert = 0; -+ int rc = 0; -+ -+ cert_iter iter; -+ -+ generate_digest(ctx->cms_ctx, ctx->inpe, 1); -+ -+ if (check_db_hash(DBX, ctx) == FOUND) -+ return -1; -+ -+ if (check_db_hash(DB, ctx) == FOUND) -+ has_valid_cert = 1; -+ -+ rc = cert_iter_init(&iter, ctx->inpe); -+ if (rc < 0) -+ goto err; -+ -+ void *data; -+ ssize_t datalen; -+ -+ while (1) { -+ rc = next_cert(&iter, &data, &datalen); -+ if (rc <= 0) -+ break; -+ -+ if (cert_matches_digest(ctx, data, datalen) < 0) { -+ has_invalid_cert = 1; -+ break; -+ } -+ -+ if (check_db_cert(DBX, ctx, data, datalen) == FOUND) { -+ has_invalid_cert = 1; -+ break; -+ } -+ -+ if (check_db_cert(DB, ctx, data, datalen) == FOUND) -+ has_valid_cert = 1; -+ } -+ -+err: -+ if (has_invalid_cert) -+ return -1; -+ -+ if (has_valid_cert) -+ return 0; -+ -+ return -1; -+} -+ -+void -+callback(poptContext con, enum poptCallbackReason reason, -+ const struct poptOption *opt, -+ const char *arg, const void *data) -+{ -+ pesigcheck_context *ctx = (pesigcheck_context *)data; -+ int rc = 0; -+ if (!opt) -+ return; -+ if (opt->shortName == 'D') { -+ rc = add_cert_db(ctx, arg); -+ } else if (opt->shortName == 'X') { -+ rc = add_cert_dbx(ctx, arg); -+ } else if (opt->shortName == 'c') { -+ rc = add_cert_file(ctx, arg); -+ } -+ if (rc != 0) { -+ fprintf(stderr, "Could not add %s from file \"%s\": %m\n", -+ opt->shortName == 'D' ? "DB" : "DBX", arg); -+ exit(1); -+ } -+} -+ -+static int -+delete_files(const char *fpath, const struct stat *sb, int typeflag) -+{ -+ if (typeflag == FTW_F) -+ remove(fpath); -+ -+ return 0; -+} -+ -+static void -+remove_certdir(const char *certdir) -+{ -+ ftw(certdir, delete_files, 3); -+ -+ remove(certdir); -+} -+ -+int -+main(int argc, char *argv[]) -+{ -+ int rc; -+ -+ pesigcheck_context ctx, *ctxp = &ctx; -+ -+ char *dbfile = NULL; -+ char *dbxfile = NULL; -+ char *certfile = NULL; -+ int use_system_dbs = 1; -+ -+ char template[] = "/tmp/pesigcheck-XXXXXX"; -+ char *certdir = NULL; -+ SECStatus status; -+ -+ poptContext optCon; -+ struct poptOption options[] = { -+ {"dbfile", 'D', POPT_ARG_CALLBACK|POPT_CBFLAG_POST, (void *)callback, 0, (void *)ctxp, NULL }, -+ {NULL, '\0', POPT_ARG_INTL_DOMAIN, "pesign" }, -+ {"in", 'i', POPT_ARG_STRING, &ctx.infile, 0, -+ "specify input file", ""}, -+ {"quiet", 'q', POPT_BIT_SET, &ctx.quiet, 1, -+ "return only; no text output.", NULL }, -+ {"no-system-db", 'n', POPT_ARG_INT, &use_system_dbs, 0, -+ "inhibit the use of DB and DBX from the running system", -+ NULL }, -+ {"dbfile", 'D', POPT_ARG_STRING, &dbfile, 0, -+ "use file for allowed certificate list", "" }, -+ {"dbxfile", 'X', POPT_ARG_STRING, &dbxfile, 0, -+ "use file for disallowed certificate list",""}, -+ {"certfile", 'c', POPT_ARG_STRING, &certfile, 0, -+ "the certificate (in DER form) for verification ",""}, -+ POPT_AUTOALIAS -+ POPT_AUTOHELP -+ POPT_TABLEEND -+ }; -+ -+ rc = pesigcheck_context_init(ctxp); -+ if (rc < 0) { -+ fprintf(stderr, "pesigcheck: Could not initialize context: %m\n"); -+ exit(1); -+ } -+ -+ optCon = poptGetContext("pesigcheck", argc, (const char **)argv, -+ options,0); -+ -+ while ((rc = poptGetNextOpt(optCon)) > 0) -+ ; -+ -+ if (rc < -1) { -+ fprintf(stderr, "pesigcheck: Invalid argument: %s: %s\n", -+ poptBadOption(optCon, 0), poptStrerror(rc)); -+ exit(1); -+ } -+ -+ if (poptPeekArg(optCon)) { -+ fprintf(stderr, "pesigcheck: Invalid Argument: \"%s\"\n", -+ poptPeekArg(optCon)); -+ exit(1); -+ } -+ -+ poptFreeContext(optCon); -+ -+ check_inputs(ctxp); -+ open_input(ctxp); -+ -+ init_cert_db(ctxp, use_system_dbs); -+ -+ certdir = mkdtemp(template); -+ status = NSS_InitReadWrite(certdir); -+ if (status != SECSuccess) { -+ fprintf(stderr, "Could not initialize nss: %s\n", -+ PORT_ErrorToString(PORT_GetError())); -+ exit(1); -+ } -+ -+ rc = check_signature(ctxp); -+ -+ close_input(ctxp); -+ if (!ctx.quiet) -+ printf("pesigcheck: \"%s\" is %s.\n", ctx.infile, -+ rc >= 0 ? "valid" : "invalid"); -+ pesigcheck_context_fini(&ctx); -+ -+ NSS_Shutdown(); -+ remove_certdir(certdir); -+ -+ return (rc < 0); -+} -diff --git a/src/pesigcheck.h b/src/pesigcheck.h -new file mode 100644 -index 0000000..ee0b63c ---- /dev/null -+++ b/src/pesigcheck.h -@@ -0,0 +1,39 @@ -+/* -+ * Copyright 2011 Red Hat, Inc. -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ * Author(s): Peter Jones -+ */ -+#ifndef PESIGN_H -+#define PESIGN_H 1 -+ -+#include -+#include -+ -+#include "efitypes.h" -+#include "cms_common.h" -+#include "pesigcheck_context.h" -+#include "certdb.h" -+ -+#include "util.h" -+#include "endian.h" -+#include "oid.h" -+#include "wincert.h" -+#include "content_info.h" -+#include "signer_info.h" -+#include "signed_data.h" -+#include "password.h" -+ -+#endif /* PESIGN_H */ -diff --git a/src/pesigcheck_context.c b/src/pesigcheck_context.c -new file mode 100644 -index 0000000..b934cbe ---- /dev/null -+++ b/src/pesigcheck_context.c -@@ -0,0 +1,122 @@ -+/* -+ * Copyright 2012 Red Hat, Inc. -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ * Author(s): Peter Jones -+ */ -+ -+#include -+#include -+ -+#include "pesigcheck.h" -+ -+#include -+#include -+ -+int -+pesigcheck_context_new(pesigcheck_context **ctx) -+{ -+ pesigcheck_context *context = NULL; -+ int rc = 0; -+ -+ if (ctx == NULL) -+ return -1; -+ -+ context = malloc(sizeof (*context)); -+ if (!context) -+ return -1; -+ -+ pesigcheck_context_init(context); -+ context->flags |= pesigcheck_C_ALLOCATED; -+ -+ *ctx = context; -+ return rc; -+} -+ -+int -+pesigcheck_context_init(pesigcheck_context *ctx) -+{ -+ if (!ctx) -+ return -1; -+ memset(ctx, '\0', sizeof (*ctx)); -+ -+ ctx->infd = -1; -+ -+ int rc = cms_context_alloc(&ctx->cms_ctx); -+ if (rc < 0) -+ return rc; -+ -+ return 0; -+} -+ -+void -+pesigcheck_context_fini(pesigcheck_context *ctx) -+{ -+ if (!ctx) -+ return; -+ -+ cms_context_fini(ctx->cms_ctx); -+ -+ xfree(ctx->infile); -+ -+ if (ctx->inpe) { -+ pe_end(ctx->inpe); -+ ctx->inpe = NULL; -+ } -+ -+ if (!(ctx->flags & pesigcheck_C_ALLOCATED)) -+ pesigcheck_context_init(ctx); -+ -+ while (ctx->db) { -+ dblist *db = ctx->db; -+ -+ if (db->type == DB_CERT) -+ free(db->data); -+ munmap(db->map, db->size); -+ close(db->fd); -+ ctx->db = db->next; -+ free(db); -+ } -+ while (ctx->dbx) { -+ dblist *db = ctx->dbx; -+ -+ if (db->type == DB_CERT) -+ free(db->data); -+ munmap(db->map, db->size); -+ close(db->fd); -+ ctx->dbx = db->next; -+ free(db); -+ } -+ while (ctx->hashes) { -+ hashlist *hashes = ctx->hashes; -+ free(hashes->data); -+ ctx->hashes = hashes->next; -+ free(hashes); -+ } -+} -+ -+void -+pesigcheck_context_free_private(pesigcheck_context **ctx_ptr) -+{ -+ pesigcheck_context *ctx; -+ if (!ctx_ptr || !*ctx_ptr) -+ return; -+ -+ ctx = *ctx_ptr; -+ pesigcheck_context_fini(ctx); -+ -+ if (ctx->flags & pesigcheck_C_ALLOCATED) -+ xfree(*ctx_ptr); -+} -diff --git a/src/pesigcheck_context.h b/src/pesigcheck_context.h -new file mode 100644 -index 0000000..1b916e3 ---- /dev/null -+++ b/src/pesigcheck_context.h -@@ -0,0 +1,78 @@ -+/* -+ * Copyright 2012 Red Hat, Inc. -+ * All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ * -+ * Author(s): Peter Jones -+ */ -+#ifndef pesigcheck_CONTEXT_H -+#define pesigcheck_CONTEXT_H 1 -+ -+#include -+#include -+ -+enum { -+ pesigcheck_C_ALLOCATED = 1, -+}; -+ -+typedef enum { -+ DB_FILE, -+ DB_EFIVAR, -+ DB_CERT, -+} db_f_type; -+ -+struct dblist { -+ db_f_type type; -+ int fd; -+ struct dblist *next; -+ size_t size; -+ void *map; -+ size_t datalen; -+ void *data; -+}; -+ -+typedef struct dblist dblist; -+ -+struct hashlist { -+ efi_guid_t *hash_type; -+ void *data; -+ size_t datalen; -+ struct hashlist *next; -+}; -+typedef struct hashlist hashlist; -+ -+typedef struct pesigcheck_context { -+ int flags; -+ -+ char *infile; -+ int infd; -+ Pe *inpe; -+ -+ int quiet; -+ -+ hashlist *hashes; -+ -+ dblist *db; -+ dblist *dbx; -+ -+ cms_context *cms_ctx; -+} pesigcheck_context; -+ -+extern int pesigcheck_context_new(pesigcheck_context **ctx); -+extern void pesigcheck_context_free_private(pesigcheck_context **ctx_ptr); -+extern int pesigcheck_context_init(pesigcheck_context *ctx); -+extern void pesigcheck_context_fini(pesigcheck_context *ctx); -+#define pesigcheck_context_free(ctx) pesigcheck_context_free_private(&(ctx)) -+ -+#endif /* pesigcheck_CONTEXT_H */ -diff --git a/src/peverify.1 b/src/peverify.1 -deleted file mode 100644 -index ce8da2a..0000000 ---- a/src/peverify.1 -+++ /dev/null -@@ -1,25 +0,0 @@ --.TH PEVERIFY 1 "Mon Sep 10 2012" --.SH NAME --pesign \- command line tool for verifying UEFI applications -- --.SH SYNOPSIS --\fBpesign\fR [--in=\fIinfile\fR | -i \fIinfile\fR] [--quiet | -q ] -- [--db=\fIdbfile\fR | -D \fIdbfile\fR ] -- [--dbx=\fIdbxfile\fR | -X \fIdbxfile\fR ] -- --.SH DESCRIPTION --\fBpeverify\fR is a command line tool for verifying the signature of UEFI --applications. -- --.SH OPTIONS --.TP --\fB-\-in\fR=\fIinfile\fR --Specify input binary. -- --.SH "SEE ALSO" --.BR peverify (1) -- --.SH AUTHORS --.nf --Peter Jones --.fi -diff --git a/src/peverify.c b/src/peverify.c -deleted file mode 100644 -index ebd7ee7..0000000 ---- a/src/peverify.c -+++ /dev/null -@@ -1,306 +0,0 @@ --/* -- * Copyright 2011-2012 Red Hat, Inc. -- * All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; version 2 of the License. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program. If not, see . -- * -- * Author(s): Peter Jones -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include --#include --#include --#include -- --#include "peverify.h" -- --static void --open_input(peverify_context *ctx) --{ -- if (!ctx->infile) { -- fprintf(stderr, "peverify: No input file specified.\n"); -- exit(1); -- } -- -- ctx->infd = open(ctx->infile, O_RDONLY|O_CLOEXEC); -- -- if (ctx->infd < 0) { -- fprintf(stderr, "peverify: Error opening input: %m\n"); -- exit(1); -- } -- -- Pe_Cmd cmd = ctx->infd == STDIN_FILENO ? PE_C_READ : PE_C_READ_MMAP; -- ctx->inpe = pe_begin(ctx->infd, cmd, NULL); -- if (!ctx->inpe) { -- fprintf(stderr, "peverify: could not load input file: %s\n", -- pe_errmsg(pe_errno())); -- exit(1); -- } -- -- int rc = parse_signatures(&ctx->cms_ctx->signatures, -- &ctx->cms_ctx->num_signatures, -- ctx->inpe); -- if (rc < 0) { -- fprintf(stderr, "peverify: could not parse signature list in " -- "EFI binary\n"); -- exit(1); -- } --} -- --static void --close_input(peverify_context *ctx) --{ -- pe_end(ctx->inpe); -- ctx->inpe = NULL; -- -- close(ctx->infd); -- ctx->infd = -1; --} -- --static void --check_inputs(peverify_context *ctx) --{ -- if (!ctx->infile) { -- fprintf(stderr, "pesign: No input file specified.\n"); -- exit(1); -- } --} -- --static int --cert_matches_digest(peverify_context *ctx, void *data, ssize_t datalen) --{ -- SECItem sig, *pe_digest, *content; -- uint8_t *digest; -- SEC_PKCS7ContentInfo *cinfo = NULL; -- int ret = -1; -- -- sig.data = data; -- sig.len = datalen; -- sig.type = siBuffer; -- -- cinfo = SEC_PKCS7DecodeItem(&sig, NULL, NULL, NULL, NULL, NULL, -- NULL, NULL); -- -- if (!SEC_PKCS7ContentIsSigned(cinfo)) -- goto out; -- -- /* TODO Find out the digest type in spc_content */ -- pe_digest = ctx->cms_ctx->digests[0].pe_digest; -- content = cinfo->content.signedData->contentInfo.content.data; -- digest = content->data + content->len - pe_digest->len; -- if (memcmp(pe_digest->data, digest, pe_digest->len) != 0) -- goto out; -- -- ret = 0; --out: -- if (cinfo) -- SEC_PKCS7DestroyContentInfo(cinfo); -- -- return ret; --} -- --static int --check_signature(peverify_context *ctx) --{ -- int has_valid_cert = 0; -- int has_invalid_cert = 0; -- int rc = 0; -- -- cert_iter iter; -- -- generate_digest(ctx->cms_ctx, ctx->inpe, 1); -- -- if (check_db_hash(DBX, ctx) == FOUND) -- return -1; -- -- if (check_db_hash(DB, ctx) == FOUND) -- has_valid_cert = 1; -- -- rc = cert_iter_init(&iter, ctx->inpe); -- if (rc < 0) -- goto err; -- -- void *data; -- ssize_t datalen; -- -- while (1) { -- rc = next_cert(&iter, &data, &datalen); -- if (rc <= 0) -- break; -- -- if (cert_matches_digest(ctx, data, datalen) < 0) { -- has_invalid_cert = 1; -- break; -- } -- -- if (check_db_cert(DBX, ctx, data, datalen) == FOUND) { -- has_invalid_cert = 1; -- break; -- } -- -- if (check_db_cert(DB, ctx, data, datalen) == FOUND) -- has_valid_cert = 1; -- } -- --err: -- if (has_invalid_cert) -- return -1; -- -- if (has_valid_cert) -- return 0; -- -- return -1; --} -- --void --callback(poptContext con, enum poptCallbackReason reason, -- const struct poptOption *opt, -- const char *arg, const void *data) --{ -- peverify_context *ctx = (peverify_context *)data; -- int rc = 0; -- if (!opt) -- return; -- if (opt->shortName == 'D') { -- rc = add_cert_db(ctx, arg); -- } else if (opt->shortName == 'X') { -- rc = add_cert_dbx(ctx, arg); -- } else if (opt->shortName == 'c') { -- rc = add_cert_file(ctx, arg); -- } -- if (rc != 0) { -- fprintf(stderr, "Could not add %s from file \"%s\": %m\n", -- opt->shortName == 'D' ? "DB" : "DBX", arg); -- exit(1); -- } --} -- --static int --delete_files(const char *fpath, const struct stat *sb, int typeflag) --{ -- if (typeflag == FTW_F) -- remove(fpath); -- -- return 0; --} -- --static void --remove_certdir(const char *certdir) --{ -- ftw(certdir, delete_files, 3); -- -- remove(certdir); --} -- --int --main(int argc, char *argv[]) --{ -- int rc; -- -- peverify_context ctx, *ctxp = &ctx; -- -- char *dbfile = NULL; -- char *dbxfile = NULL; -- char *certfile = NULL; -- int use_system_dbs = 1; -- -- char template[] = "/tmp/peverify-XXXXXX"; -- char *certdir = NULL; -- SECStatus status; -- -- poptContext optCon; -- struct poptOption options[] = { -- {"dbfile", 'D', POPT_ARG_CALLBACK|POPT_CBFLAG_POST, (void *)callback, 0, (void *)ctxp, NULL }, -- {NULL, '\0', POPT_ARG_INTL_DOMAIN, "pesign" }, -- {"in", 'i', POPT_ARG_STRING, &ctx.infile, 0, -- "specify input file", ""}, -- {"quiet", 'q', POPT_BIT_SET, &ctx.quiet, 1, -- "return only; no text output.", NULL }, -- {"no-system-db", 'n', POPT_ARG_INT, &use_system_dbs, 0, -- "inhibit the use of DB and DBX from the running system", -- NULL }, -- {"dbfile", 'D', POPT_ARG_STRING, &dbfile, 0, -- "use file for allowed certificate list", "" }, -- {"dbxfile", 'X', POPT_ARG_STRING, &dbxfile, 0, -- "use file for disallowed certificate list",""}, -- {"certfile", 'c', POPT_ARG_STRING, &certfile, 0, -- "the certificate (in DER form) for verification ",""}, -- POPT_AUTOALIAS -- POPT_AUTOHELP -- POPT_TABLEEND -- }; -- -- rc = peverify_context_init(ctxp); -- if (rc < 0) { -- fprintf(stderr, "peverify: Could not initialize context: %m\n"); -- exit(1); -- } -- -- optCon = poptGetContext("peverify", argc, (const char **)argv, -- options,0); -- -- while ((rc = poptGetNextOpt(optCon)) > 0) -- ; -- -- if (rc < -1) { -- fprintf(stderr, "peverify: Invalid argument: %s: %s\n", -- poptBadOption(optCon, 0), poptStrerror(rc)); -- exit(1); -- } -- -- if (poptPeekArg(optCon)) { -- fprintf(stderr, "peverify: Invalid Argument: \"%s\"\n", -- poptPeekArg(optCon)); -- exit(1); -- } -- -- poptFreeContext(optCon); -- -- check_inputs(ctxp); -- open_input(ctxp); -- -- init_cert_db(ctxp, use_system_dbs); -- -- certdir = mkdtemp(template); -- status = NSS_InitReadWrite(certdir); -- if (status != SECSuccess) { -- fprintf(stderr, "Could not initialize nss: %s\n", -- PORT_ErrorToString(PORT_GetError())); -- exit(1); -- } -- -- rc = check_signature(ctxp); -- -- close_input(ctxp); -- if (!ctx.quiet) -- printf("peverify: \"%s\" is %s.\n", ctx.infile, -- rc >= 0 ? "valid" : "invalid"); -- peverify_context_fini(&ctx); -- -- NSS_Shutdown(); -- remove_certdir(certdir); -- -- return (rc < 0); --} -diff --git a/src/peverify.h b/src/peverify.h -deleted file mode 100644 -index 572c3ef..0000000 ---- a/src/peverify.h -+++ /dev/null -@@ -1,39 +0,0 @@ --/* -- * Copyright 2011 Red Hat, Inc. -- * All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; version 2 of the License. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program. If not, see . -- * -- * Author(s): Peter Jones -- */ --#ifndef PESIGN_H --#define PESIGN_H 1 -- --#include --#include -- --#include "efitypes.h" --#include "cms_common.h" --#include "peverify_context.h" --#include "certdb.h" -- --#include "util.h" --#include "endian.h" --#include "oid.h" --#include "wincert.h" --#include "content_info.h" --#include "signer_info.h" --#include "signed_data.h" --#include "password.h" -- --#endif /* PESIGN_H */ -diff --git a/src/peverify_context.c b/src/peverify_context.c -deleted file mode 100644 -index d3aa53e..0000000 ---- a/src/peverify_context.c -+++ /dev/null -@@ -1,122 +0,0 @@ --/* -- * Copyright 2012 Red Hat, Inc. -- * All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; version 2 of the License. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program. If not, see . -- * -- * Author(s): Peter Jones -- */ -- --#include --#include -- --#include "peverify.h" -- --#include --#include -- --int --peverify_context_new(peverify_context **ctx) --{ -- peverify_context *context = NULL; -- int rc = 0; -- -- if (ctx == NULL) -- return -1; -- -- context = malloc(sizeof (*context)); -- if (!context) -- return -1; -- -- peverify_context_init(context); -- context->flags |= PEVERIFY_C_ALLOCATED; -- -- *ctx = context; -- return rc; --} -- --int --peverify_context_init(peverify_context *ctx) --{ -- if (!ctx) -- return -1; -- memset(ctx, '\0', sizeof (*ctx)); -- -- ctx->infd = -1; -- -- int rc = cms_context_alloc(&ctx->cms_ctx); -- if (rc < 0) -- return rc; -- -- return 0; --} -- --void --peverify_context_fini(peverify_context *ctx) --{ -- if (!ctx) -- return; -- -- cms_context_fini(ctx->cms_ctx); -- -- xfree(ctx->infile); -- -- if (ctx->inpe) { -- pe_end(ctx->inpe); -- ctx->inpe = NULL; -- } -- -- if (!(ctx->flags & PEVERIFY_C_ALLOCATED)) -- peverify_context_init(ctx); -- -- while (ctx->db) { -- dblist *db = ctx->db; -- -- if (db->type == DB_CERT) -- free(db->data); -- munmap(db->map, db->size); -- close(db->fd); -- ctx->db = db->next; -- free(db); -- } -- while (ctx->dbx) { -- dblist *db = ctx->dbx; -- -- if (db->type == DB_CERT) -- free(db->data); -- munmap(db->map, db->size); -- close(db->fd); -- ctx->dbx = db->next; -- free(db); -- } -- while (ctx->hashes) { -- hashlist *hashes = ctx->hashes; -- free(hashes->data); -- ctx->hashes = hashes->next; -- free(hashes); -- } --} -- --void --peverify_context_free_private(peverify_context **ctx_ptr) --{ -- peverify_context *ctx; -- if (!ctx_ptr || !*ctx_ptr) -- return; -- -- ctx = *ctx_ptr; -- peverify_context_fini(ctx); -- -- if (ctx->flags & PEVERIFY_C_ALLOCATED) -- xfree(*ctx_ptr); --} -diff --git a/src/peverify_context.h b/src/peverify_context.h -deleted file mode 100644 -index 7e26d06..0000000 ---- a/src/peverify_context.h -+++ /dev/null -@@ -1,78 +0,0 @@ --/* -- * Copyright 2012 Red Hat, Inc. -- * All rights reserved. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; version 2 of the License. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program. If not, see . -- * -- * Author(s): Peter Jones -- */ --#ifndef PEVERIFY_CONTEXT_H --#define PEVERIFY_CONTEXT_H 1 -- --#include --#include -- --enum { -- PEVERIFY_C_ALLOCATED = 1, --}; -- --typedef enum { -- DB_FILE, -- DB_EFIVAR, -- DB_CERT, --} db_f_type; -- --struct dblist { -- db_f_type type; -- int fd; -- struct dblist *next; -- size_t size; -- void *map; -- size_t datalen; -- void *data; --}; -- --typedef struct dblist dblist; -- --struct hashlist { -- efi_guid_t *hash_type; -- void *data; -- size_t datalen; -- struct hashlist *next; --}; --typedef struct hashlist hashlist; -- --typedef struct peverify_context { -- int flags; -- -- char *infile; -- int infd; -- Pe *inpe; -- -- int quiet; -- -- hashlist *hashes; -- -- dblist *db; -- dblist *dbx; -- -- cms_context *cms_ctx; --} peverify_context; -- --extern int peverify_context_new(peverify_context **ctx); --extern void peverify_context_free_private(peverify_context **ctx_ptr); --extern int peverify_context_init(peverify_context *ctx); --extern void peverify_context_fini(peverify_context *ctx); --#define peverify_context_free(ctx) peverify_context_free_private(&(ctx)) -- --#endif /* PEVERIFY_CONTEXT_H */ --- -1.8.4.5 - - -From 4191f24b18f1bf2a7be5da498b36f016bf115919 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 7 Jan 2014 12:02:47 +0800 -Subject: [PATCH 10/31] Drop the temporary nss dir in pesigcheck - -I thought we need a "physical" database for the certificates but -it's actually not necessary. Drop the nss dir creation/deletion -code to avoid the extra file system access. - -Signed-off-by: Gary Ching-Pang Lin ---- - src/pesigcheck.c | 24 +----------------------- - 1 file changed, 1 insertion(+), 23 deletions(-) - -diff --git a/src/pesigcheck.c b/src/pesigcheck.c -index 7cd98c9..9cf33be 100644 ---- a/src/pesigcheck.c -+++ b/src/pesigcheck.c -@@ -24,7 +24,6 @@ - #include - #include - #include --#include - #include - - #include -@@ -197,23 +196,6 @@ callback(poptContext con, enum poptCallbackReason reason, - } - } - --static int --delete_files(const char *fpath, const struct stat *sb, int typeflag) --{ -- if (typeflag == FTW_F) -- remove(fpath); -- -- return 0; --} -- --static void --remove_certdir(const char *certdir) --{ -- ftw(certdir, delete_files, 3); -- -- remove(certdir); --} -- - int - main(int argc, char *argv[]) - { -@@ -226,8 +208,6 @@ main(int argc, char *argv[]) - char *certfile = NULL; - int use_system_dbs = 1; - -- char template[] = "/tmp/pesigcheck-XXXXXX"; -- char *certdir = NULL; - SECStatus status; - - poptContext optCon; -@@ -283,8 +263,7 @@ main(int argc, char *argv[]) - - init_cert_db(ctxp, use_system_dbs); - -- certdir = mkdtemp(template); -- status = NSS_InitReadWrite(certdir); -+ status = NSS_NoDB_Init(NULL); - if (status != SECSuccess) { - fprintf(stderr, "Could not initialize nss: %s\n", - PORT_ErrorToString(PORT_GetError())); -@@ -300,7 +279,6 @@ main(int argc, char *argv[]) - pesigcheck_context_fini(&ctx); - - NSS_Shutdown(); -- remove_certdir(certdir); - - return (rc < 0); - } --- -1.8.4.5 - - -From c61386706b169ec02f55880a11dd8097b68d6180 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 8 Jan 2014 14:17:30 +0800 -Subject: [PATCH 11/31] efisiglist: convert the hex array properly - -Signed-off-by: Gary Ching-Pang Lin ---- - src/efisiglist.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/efisiglist.c b/src/efisiglist.c -index b7190cb..e01ab73 100644 ---- a/src/efisiglist.c -+++ b/src/efisiglist.c -@@ -70,9 +70,9 @@ static int8_t hexchar_to_bin(char hex) - if (hex >= '0' && hex <= '9') - return hex - '0'; - if (hex >= 'A' && hex <= 'F') -- return hex - 'A'; -+ return hex - 'A' + 10; - if (hex >= 'a' && hex <= 'f') -- return hex - 'a'; -+ return hex - 'a' + 10; - return -1; - } - -@@ -83,7 +83,7 @@ hex_to_bin(char *hex, size_t size) - if (!ret) - return NULL; - -- for (int i = 0, j = 0; i < size; i+= 2, j++) { -+ for (int i = 0, j = 0; i < size*2; i+= 2, j++) { - uint8_t val; - - val = hexchar_to_bin(hex[i]); -@@ -94,7 +94,7 @@ out_of_range: - return NULL; - } - ret[j] = (val & 0xf) << 4; -- val = hexchar_to_bin(hex[i]); -+ val = hexchar_to_bin(hex[i+1]); - if (val < 0) - goto out_of_range; - ret[j] |= val & 0xf; --- -1.8.4.5 - - -From 65b8b80de336920cb464d5b5881a66bbeebaa343 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 8 Jan 2014 14:20:38 +0800 -Subject: [PATCH 12/31] efisiglist: Correct the calulation of SignatureListSize - -Signed-off-by: Gary Ching-Pang Lin ---- - src/siglist.c | 25 +++++++++++++++---------- - 1 file changed, 15 insertions(+), 10 deletions(-) - -diff --git a/src/siglist.c b/src/siglist.c -index ca097e6..0457208 100644 ---- a/src/siglist.c -+++ b/src/siglist.c -@@ -100,6 +100,7 @@ signature_list_new(efi_guid_t SignatureType) - - sl->SignatureType = SignatureType; - sl->SignatureSize = size + sizeof (efi_guid_t); -+ sl->SignatureListSize = sizeof (struct efi_signature_list); - - return sl; - } -@@ -107,7 +108,8 @@ signature_list_new(efi_guid_t SignatureType) - static int - resize_entries(signature_list *sl, uint32_t newsize) - { -- for (int i = 0; i < sl->SignatureListSize; i++) { -+ int count = (sl->SignatureListSize - sizeof (struct efi_signature_list)) / sl->SignatureSize; -+ for (int i = 0; i < count; i++) { - struct efi_signature_data *sd = sl->Signatures[i]; - struct efi_signature_data *new_sd = calloc(1, newsize); - -@@ -118,7 +120,8 @@ resize_entries(signature_list *sl, uint32_t newsize) - free(sd); - sl->Signatures[i] = sd; - } -- sl->SignatureListSize = newsize; -+ sl->SignatureSize = newsize; -+ sl->SignatureListSize = sizeof (struct efi_signature_list) + count * newsize; - return 0; - } - -@@ -151,17 +154,17 @@ signature_list_add_sig(signature_list *sl, efi_guid_t owner, - memcpy(sd->SignatureData, sig, sl->SignatureSize - - sizeof (efi_guid_t)); - -- struct efi_signature_data **sdl = calloc(sl->SignatureListSize+1, -+ int count = (sl->SignatureListSize - sizeof (struct efi_signature_list)) / sl->SignatureSize; -+ struct efi_signature_data **sdl = calloc(count+1, - sizeof (struct efi_signature_data *)); - if (!sdl) { - free(sd); - return -1; - } - -- memcpy(sdl, sl->Signatures, sl->SignatureListSize * -- sizeof (struct efi_signature_data *)); -- sdl[sl->SignatureListSize] = sd; -- sl->SignatureListSize++; -+ memcpy(sdl, sl->Signatures, count * sl->SignatureSize); -+ sdl[count] = sd; -+ sl->SignatureListSize += sl->SignatureSize; - - free(sl->Signatures); - sl->Signatures = sdl; -@@ -195,9 +198,10 @@ signature_list_realize(signature_list *sl, void **out, size_t *outsize) - sl->realized = NULL; - } - -+ int count = (sl->SignatureListSize - sizeof (struct efi_signature_list)) / sl->SignatureSize; - struct efi_signature_list *esl = NULL; - uint32_t size = sizeof (*esl) + -- + sl->SignatureListSize * sl->SignatureSize; -+ + count * sl->SignatureSize; - - void *ret = calloc(1, size); - if (!ret) -@@ -207,7 +211,7 @@ signature_list_realize(signature_list *sl, void **out, size_t *outsize) - memcpy(esl, sl, sizeof (*esl)); - - uint8_t *pos = ret + sizeof (*esl); -- for (int i = 0; i < sl->SignatureListSize; i++) { -+ for (int i = 0; i < count; i++) { - memcpy(pos, sl->Signatures[i], sl->SignatureSize); - pos += sl->SignatureSize; - } -@@ -225,7 +229,8 @@ signature_list_free(signature_list *sl) - if (sl->realized) - free(sl->realized); - -- for (int i = 0; i < sl->SignatureListSize; i++) -+ int count = (sl->SignatureListSize - sizeof (struct efi_signature_list)) / sl->SignatureSize; -+ for (int i = 0; i < count; i++) - free(sl->Signatures[i]); - - free(sl); --- -1.8.4.5 - - -From b51e250f52fe599cf1713c3c91a4b29f0b73fc4c Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 8 Jan 2014 15:10:18 +0800 -Subject: [PATCH 13/31] efisiglist: support adding a certificate in DER form - -Signed-off-by: Gary Ching-Pang Lin ---- - src/efisiglist.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 70 insertions(+), 2 deletions(-) - -diff --git a/src/efisiglist.c b/src/efisiglist.c -index e01ab73..b96553b 100644 ---- a/src/efisiglist.c -+++ b/src/efisiglist.c -@@ -23,6 +23,9 @@ - #include - #include - #include -+#include -+#include -+#include - - #include "efitypes.h" - #include "siglist.h" -@@ -106,11 +109,15 @@ int - main(int argc, char *argv[]) - { - poptContext optCon; -+ efi_guid_t owner = RH_GUID; - int rc; - char *outfile = NULL; - char *hash = NULL; - char *hash_type = "sha256"; - char *certfile = NULL; -+ int certfd = -1; -+ void *cert_data = NULL; -+ size_t cert_size = 0; - - int add = 1; - -@@ -126,7 +133,7 @@ main(int argc, char *argv[]) - "hash value to add", "" }, - {"hash-type", 't', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, - &hash_type, 0, "hash type to add", "" }, -- {"certificate", 'c', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, -+ {"certificate", 'c', POPT_ARG_STRING, - &certfile, 0, "certificate to add", "" }, - POPT_AUTOALIAS - POPT_AUTOHELP -@@ -197,6 +204,29 @@ main(int argc, char *argv[]) - hash_params[hash_index].size * 8, x * 4); - exit(1); - } -+ } else if (certfile) { -+ certfd = open(certfile, O_RDONLY, 0644); -+ if (certfd < 0) { -+ fprintf(stderr, "efisiglist: could not open \"%s\": " -+ "%m\n", certfile); -+ exit(1); -+ } -+ -+ struct stat sb; -+ if (fstat(certfd, &sb) < 0) { -+ fprintf(stderr, "efisiglist: could not get the size " -+ "of \"%s\": %m\n", certfile); -+ exit(1); -+ } -+ cert_size = sb.st_size; -+ -+ cert_data = mmap(NULL, cert_size, PROT_READ, MAP_PRIVATE, -+ certfd, 0); -+ if (cert_data == MAP_FAILED) { -+ fprintf(stderr, "efisiglist: could not map \"%s\": " -+ "%m\n", certfile); -+ exit(1); -+ } - } - - if (add) { -@@ -209,7 +239,6 @@ main(int argc, char *argv[]) - unlink(outfile); - exit(1); - } -- efi_guid_t owner = RH_GUID; - uint8_t *binary_hash = hex_to_bin(hash, - hash_params[hash_index].size); - if (!binary_hash) { -@@ -245,6 +274,45 @@ main(int argc, char *argv[]) - } - close(outfd); - exit(0); -+ } else if (certfile) { -+ efi_guid_t sig_type = EFI_CERT_X509_GUID; -+ signature_list *sl = signature_list_new(sig_type); -+ if (!sl) { -+ fprintf(stderr, "efisiglist: could not " -+ "allocate signature list: %m\n"); -+ unlink(outfile); -+ exit(1); -+ } -+ rc = signature_list_add_sig(sl, owner, cert_data, -+ cert_size); -+ if (rc < 0) { -+ fprintf(stderr,"efisiglist: could not add " -+ "cert to list: %m\n"); -+ unlink(outfile); -+ exit(1); -+ } -+ -+ void *blah; -+ size_t size = 0; -+ rc = signature_list_realize(sl, &blah, &size); -+ if (rc < 0) { -+ fprintf(stderr, "efisiglist: Could not realize " -+ "signature list: %m\n"); -+ unlink(outfile); -+ exit(1); -+ } -+ rc = write(outfd, blah, size); -+ if (rc < 0) { -+ fprintf(stderr, "efisiglist: Could not write " -+ "signature list: %m\n"); -+ unlink(outfile); -+ exit(1); -+ } -+ -+ munmap(cert_data, cert_size); -+ close(certfd); -+ close(outfd); -+ exit(0); - } - } - exit(1); --- -1.8.4.5 - - -From a2a7e57e1786a65bac95d1ce03ceda0487c9c2bf Mon Sep 17 00:00:00 2001 -From: Michael Scherer -Date: Mon, 6 Jan 2014 00:48:54 +0100 -Subject: [PATCH 14/31] Fix incorrect assignation, and fix memleak ( since - new_sd is allocated and never used ) - ---- - src/siglist.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/siglist.c b/src/siglist.c -index 0457208..e001493 100644 ---- a/src/siglist.c -+++ b/src/siglist.c -@@ -118,7 +118,7 @@ resize_entries(signature_list *sl, uint32_t newsize) - - memcpy(new_sd, sd, sl->SignatureSize); - free(sd); -- sl->Signatures[i] = sd; -+ sl->Signatures[i] = new_sd; - } - sl->SignatureSize = newsize; - sl->SignatureListSize = sizeof (struct efi_signature_list) + count * newsize; --- -1.8.4.5 - - -From 3e3f152387dfc54598c29b5db7540fad9a9043d8 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 30 May 2014 18:16:53 +0800 -Subject: [PATCH 15/31] authvar: fill some baisc functions - -Signed-off-by: Gary Ching-Pang Lin ---- - src/authvar.c | 223 ++++++++++++++++++++++++++++++++++++++++++++------ - src/authvar.h | 1 + - src/authvar_context.c | 148 ++++++++++++++++++++++++++++++++- - src/authvar_context.h | 20 ++++- - src/efitypes.h | 4 +- - src/wincert.h | 13 +++ - 6 files changed, 375 insertions(+), 34 deletions(-) - -diff --git a/src/authvar.c b/src/authvar.c -index 1a05e6b..cfa9de3 100644 ---- a/src/authvar.c -+++ b/src/authvar.c -@@ -19,6 +19,17 @@ - - #include - #include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include - - #include "authvar.h" - -@@ -86,6 +97,75 @@ check_value(authvar_context *ctx, int needed) - "authvar: command does not take a value.\n"); - exit(1); - } -+ -+ if (ctx->value) { -+ ctx->value_size = strlen(ctx->value); -+ } -+} -+ -+static void -+open_input(authvar_context *ctx) -+{ -+ struct stat sb; -+ -+ if (!ctx->valuefile) -+ return; -+ -+ ctx->valuefd = open(ctx->valuefile, O_RDONLY|O_CLOEXEC); -+ if (ctx->valuefd < 0) { -+ fprintf(stderr, "authvar: Error opening valuefile: %m\n"); -+ exit(1); -+ } -+ -+ if (fstat(ctx->valuefd, &sb) < 0) { -+ fprintf(stderr, "authvar: Error mapping valuefile: %m\n"); -+ exit(1); -+ } -+ ctx->value_size = sb.st_size; -+ -+ ctx->value = (char *)mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, -+ ctx->valuefd, 0); -+ if (ctx->value == MAP_FAILED) { -+ fprintf(stderr, "authvar: Error mapping valuefile: %m\n"); -+ exit(1); -+ } -+} -+ -+#define EFIVAR_DIR "/sys/firmware/efi/efivars/" -+ -+static void -+generate_efivars_filename(authvar_context *ctx) -+{ -+ efi_guid_t guid = ctx->guid; -+ size_t length; -+ -+ length = strlen(EFIVAR_DIR) + strlen(ctx->name) + 38; -+ ctx->exportfile = (char *)malloc(length); -+ -+ sprintf(ctx->exportfile, "%s%s-%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", -+ EFIVAR_DIR, ctx->name, guid.data1, guid.data2, guid.data3, -+ guid.data4[0], guid.data4[1], guid.data4[2], -+ guid.data4[3], guid.data4[4], guid.data4[5], -+ guid.data4[6], guid.data4[7]); -+} -+ -+static void -+open_output(authvar_context *ctx) -+{ -+ int flags; -+ mode_t mode; -+ -+ if (!ctx->exportfile) { -+ generate_efivars_filename(ctx); -+ } -+ -+ flags = O_CREAT|O_RDWR|O_CLOEXEC; -+ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; -+ ctx->exportfd = open(ctx->exportfile, flags, mode); -+ if (ctx->exportfd < 0) { -+ fprintf(stderr, "authvar: Error opening exportfile: %m\n"); -+ exit(1); -+ } - } - - static int -@@ -163,11 +243,41 @@ find_namespace_guid(authvar_context *ctx) - return parse_guid(ctx->namespace, &ctx->guid); - } - -+static void -+set_timestamp(authvar_context *ctx, const char *time_str) -+{ -+ time_t t; -+ struct tm *tm; -+ -+ if (time_str) { -+ /* TODO parse the string */ -+ } else { -+ time(&t); -+ tm = gmtime(&t); -+ } -+ -+ ctx->timestamp.year = tm->tm_year + 1900; -+ ctx->timestamp.month = tm->tm_mon + 1; -+ ctx->timestamp.day = tm->tm_mday; -+ ctx->timestamp.hour = tm->tm_hour; -+ ctx->timestamp.minute = tm->tm_min; -+ ctx->timestamp.second = tm->tm_sec; -+ -+ ctx->timestamp.pad1 = 0; -+ ctx->timestamp.nanosecond = 0; -+ ctx->timestamp.timezone = 0; -+ ctx->timestamp.daylight = 0; -+ ctx->timestamp.pad2 = 0; -+} -+ - int main(int argc, char *argv[]) - { - int rc; - authvar_context ctx = { 0, }; - authvar_context *ctxp = &ctx; -+ char *time_str = NULL; -+ char *certdir = "/etc/pki/pesign"; -+ SECStatus status; - - int action = 0; - -@@ -182,6 +292,10 @@ int main(int argc, char *argv[]) - { NULL, '\0', POPT_ARG_INTL_DOMAIN, "pesign" }, - { "append", 'a', POPT_ARG_VAL|POPT_ARGFLAG_OR, &action, - GENERATE_APPEND, "append to variable" }, -+ {"certdir", 'd', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, -+ &certdir, 0, -+ "specify nss certificate database directory", -+ "" }, - { "clear", 'c', POPT_ARG_VAL|POPT_ARGFLAG_OR, &action, - GENERATE_CLEAR, "clear variable" }, - { "set", 's', POPT_ARG_VAL|POPT_ARGFLAG_OR, &action, -@@ -192,6 +306,8 @@ int main(int argc, char *argv[]) - "{|}" }, - { "name", 'n', POPT_ARG_STRING, &ctx.name, 0, "variable name", - "" }, -+ { "timestamp", 't', POPT_ARG_STRING, &time_str, 0, -+ "timestamp for the variable", "