[PATCH 4 of 5] Implement PKCS#7 embedded signature verfification for windows
Wald Commits
scm-commit at wald.intevation.org
Tue May 27 12:29:12 CEST 2014
# HG changeset patch
# User Andre Heinecke <aheinecke at intevation.de>
# Date 1401186516 0
# Node ID f4ce4eef3b389e77a0e419a40baa3e768612494f
# Parent bf54c9fc0d630aa9bcf1051cd059dbdfbe0433d9
Implement PKCS#7 embedded signature verfification for windows
diff -r bf54c9fc0d63 -r f4ce4eef3b38 common/CMakeLists.txt
--- a/common/CMakeLists.txt Tue May 27 10:27:35 2014 +0000
+++ b/common/CMakeLists.txt Tue May 27 10:28:36 2014 +0000
@@ -12,6 +12,7 @@
portpath.c
strhelp.c
util.c
+ binverify.c
)
add_library(trustbridge_common STATIC ${trustbridge_common_src})
diff -r bf54c9fc0d63 -r f4ce4eef3b38 common/binverify.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/common/binverify.c Tue May 27 10:28:36 2014 +0000
@@ -0,0 +1,134 @@
+/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#include "binverify.h"
+
+#include "strhelp.h"
+#include "logging.h"
+
+#ifdef WIN32
+
+#include <windows.h>
+#include <wincrypt.h>
+#include <wintrust.h>
+#include <stdio.h>
+
+bin_verify_result
+verify_binary_win(const char *filename, size_t name_len) {
+ bin_verify_result retval = UnknownError;
+ WCHAR *filenameW = NULL;
+ BOOL result = FALSE;
+ DWORD dwEncoding = 0,
+ dwContentType = 0,
+ dwFormatType = 0,
+ dwSignerInfoSize = 0;
+ HCERTSTORE hStore = NULL;
+ HCRYPTMSG hMsg = NULL;
+ PCERT_INFO pSignerCert = NULL;
+ PCCERT_CONTEXT pSignerCertContext = NULL;
+
+ if (!filename || name_len > MAX_PATH || strlen(filename) != name_len)
+ {
+ ERRORPRINTF ("Invalid parameters\n");
+ return UnknownError;
+ }
+
+ filenameW = utf8_to_wchar(filename, strnlen(filename, MAX_PATH));
+
+ result = CryptQueryObject (CERT_QUERY_OBJECT_FILE,
+ filenameW,
+ CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
+ CERT_QUERY_FORMAT_FLAG_BINARY,
+ 0,
+ &dwEncoding,
+ &dwContentType,
+ &dwFormatType,
+ &hStore,
+ &hMsg,
+ NULL);
+
+ if (!result || !hMsg)
+ {
+ PRINTLASTERROR ("Failed to query crypto object");
+ retval = ReadFailed;
+ goto done;
+ }
+
+ /* Get the cert info so that we can look up the signer in the store later */
+ if (CryptMsgGetParam(hMsg,
+ CMSG_SIGNER_CERT_INFO_PARAM,
+ 0,
+ NULL,
+ &dwSignerInfoSize) && dwSignerInfoSize > 0)
+ {
+ pSignerCert = xmalloc (dwSignerInfoSize);
+ }
+ else
+ {
+ ERRORPRINTF ("Failed to get signer cert size.");
+ retval = UnknownError;
+ goto done;
+ }
+
+ if (!(CryptMsgGetParam(hMsg,
+ CMSG_SIGNER_CERT_INFO_PARAM,
+ 0,
+ pSignerCert,
+ &dwSignerInfoSize)))
+ {
+ ERRORPRINTF ("Failed to get signer cert.");
+ retval = UnknownError;
+ goto done;
+ }
+
+ pSignerCertContext = CertGetSubjectCertificateFromStore(
+ hStore,
+ PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+ pSignerCert);
+
+ if (!pSignerCertContext)
+ {
+ ERRORPRINTF ("Failed to find signer cert in store.");
+ retval = UnknownError;
+ goto done;
+ }
+
+ /* Verify that the signature is actually valid */
+ if(CryptMsgControl(hMsg,
+ 0,
+ CMSG_CTRL_VERIFY_SIGNATURE,
+ pSignerCertContext->pCertInfo))
+ {
+ DEBUGPRINTF ("Verify signature succeeded. \n");
+ /* TODO pinning*/
+ retval = Valid;
+ } else {
+ ERRORPRINTF ("The signature was not verified. \n");
+ retval = InvalidSignature;
+ goto done;
+ }
+
+done:
+ xfree(filenameW);
+ xfree(pSignerCert);
+
+ if(pSignerCertContext)
+ {
+ CertFreeCertificateContext(pSignerCertContext);
+ }
+ if (hStore)
+ {
+ CertCloseStore(hStore, 0);
+ }
+ if (hMsg)
+ {
+ CryptMsgClose(hMsg);
+ }
+ return retval;
+}
+#endif /* WIN32 */
diff -r bf54c9fc0d63 -r f4ce4eef3b38 common/binverify.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/common/binverify.h Tue May 27 10:28:36 2014 +0000
@@ -0,0 +1,58 @@
+/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#ifndef BINVERIFY_H
+#define BINVERIFY_H
+/* @file binverify.h
+ * @brief Verification of binary files
+ */
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @enum bin_verify_result
+ * @brief Result of a verification
+ */
+typedef enum {
+ Valid = 100, /*! Could be read and signature matched */
+ UnknownError = 1, /*! The expected unexpected */
+ InvalidSignature = 4, /*! Signature was invalid */
+ ReadFailed = 6, /*! File exists but could not read the file */
+} bin_verify_result;
+
+#ifdef WIN32
+/**
+ * @brief verify a binary
+ *
+ * This function checks that a binary is signed by a built
+ * in certificate.
+ *
+ * Caution: This function works on file names only which could
+ * be modified after this check.
+ *
+ * The verification is done using Windows crypto API based on
+ * embedded PKCS 7 "authenticode" signatures embedded into the
+ * file.
+ *
+ * @param[in] filename absolute null terminated UTF-8 encoded path to the file.
+ * @param[in] name_len length of the filename.
+ *
+ * @returns the verification result.
+ */
+bin_verify_result verify_binary_win(const char *filename, size_t name_len);
+#endif /* WIN32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BINVERIFY_H */
More information about the Trustbridge-commits
mailing list