[PATCH 4 of 6] (issue43) Add first draft of signature verification for GNU/Linux
Wald Commits
scm-commit at wald.intevation.org
Thu Jul 10 19:17:05 CEST 2014
# HG changeset patch
# User Andre Heinecke <andre.heinecke at intevation.de>
# Date 1405012522 -7200
# Node ID 2798f1869eee9b17697343533d4b17ec871964e7
# Parent 7861950f7637010c4c01a2d31d1f2c71ec3ae6ad
(issue43) Add first draft of signature verification for GNU/Linux
diff -r 7861950f7637 -r 2798f1869eee common/binverify.c
--- a/common/binverify.c Thu Jul 10 19:14:22 2014 +0200
+++ b/common/binverify.c Thu Jul 10 19:15:22 2014 +0200
@@ -19,13 +19,12 @@
bin_verify_result
verify_binary(const char *filename, size_t name_len) {
+ if (!filename || !name_len)
+ return VerifyUnknownError;
#ifdef WIN32
return verify_binary_win(filename, name_len);
#else
- /* TODO */
- if (filename && name_len)
- return VerifyValid;
- return VerifyUnknownError;
+ return verify_binary_linux(filename, name_len);
#endif
}
@@ -224,4 +223,103 @@
}
return retval;
}
+#else /* WIN32 */
+
+#include "listutil.h"
+
+#pragma GCC diagnostic ignored "-Wconversion"
+/* Polarssl mh.h contains a conversion which gcc warns about */
+#include <polarssl/pk.h>
+#include <polarssl/base64.h>
+#include <polarssl/sha256.h>
+#pragma GCC diagnostic pop
+
+bin_verify_result
+verify_binary_linux(const char *filename, size_t name_len)
+{
+ int ret = -1;
+ const size_t sig_b64_size = TRUSTBRIDGE_RSA_KEY_SIZE / 8 * 4 / 3;
+ char *data = NULL,
+ signature_b64[sig_b64_size + 1];
+ size_t data_size = 0,
+ sig_size = TRUSTBRIDGE_RSA_KEY_SIZE / 8;
+ unsigned char signature[sig_size],
+ hash[32];
+
+ bin_verify_result retval = VerifyUnknownError;
+ pk_context pub_key_ctx;
+
+ if (strnlen(filename, name_len + 1) != name_len || name_len == 0)
+ {
+ ERRORPRINTF ("Invalid call to verify_binary_linux\n");
+ return VerifyUnknownError;
+ }
+
+ ret = read_file(filename, &data, &data_size, MAX_VALID_BIN_SIZE);
+
+ if (ret != 0)
+ {
+ ERRORPRINTF ("Read file failed with error: %i\n", ret);
+ return VerifyReadFailed;
+ }
+
+ /* Fetch the signature from the end of data */
+ if (data_size < sig_b64_size + 4)
+ {
+ ERRORPRINTF ("File to small to contain a signature.\n");
+ retval = VerifyInvalidSignature;
+ goto done;
+ }
+
+ if (data[data_size - sig_b64_size - 1] != ':' ||
+ data[data_size - sig_b64_size - 2] != 'S' ||
+ data[data_size - sig_b64_size - 3] != '\n'||
+ data[data_size - sig_b64_size - 4] != '\r')
+ {
+ ERRORPRINTF ("Failed to find valid signature line.\n");
+ retval = VerifyInvalidSignature;
+ goto done;
+ }
+
+ strncpy(signature_b64, data - sig_b64_size, sig_b64_size);
+ signature_b64[sig_b64_size] = '\0';
+
+ ret = base64_decode(signature, &sig_size,
+ (unsigned char *)signature_b64, sig_b64_size);
+
+ if (ret != 0 || sig_size != TRUSTBRIDGE_RSA_KEY_SIZE / 8)
+ {
+ goto done;
+ }
+
+ /* Hash is calculated over the data without the signature at the end. */
+ sha256((unsigned char *)data, data_size - sig_b64_size - 4, hash, 0);
+
+ pk_init(&pub_key_ctx);
+
+ ret = pk_parse_public_key(&pub_key_ctx, public_key_codesign_pem,
+ public_key_codesign_pem_size);
+ if (ret != 0)
+ {
+ ERRORPRINTF ("pk_parse_public_key failed with -0x%04x\n\n", -ret);
+ pk_free(&pub_key_ctx);
+ return VerifyUnknownError;
+ }
+
+ ret = pk_verify(&pub_key_ctx, POLARSSL_MD_SHA256, hash, 0,
+ signature, sig_size);
+
+ if (ret != 0)
+ {
+ ERRORPRINTF ("pk_verify failed with -0x%04x\n\n", -ret);
+ }
+ pk_free(&pub_key_ctx);
+
+ return VerifyValid;
+
+done:
+ xfree (data);
+ return retval;
+}
+
#endif /* WIN32 */
diff -r 7861950f7637 -r 2798f1869eee common/binverify.h
--- a/common/binverify.h Thu Jul 10 19:14:22 2014 +0200
+++ b/common/binverify.h Thu Jul 10 19:15:22 2014 +0200
@@ -39,10 +39,15 @@
* 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
+ * Windows verification is done using Windows crypto API based on
* embedded PKCS 7 "authenticode" signatures embedded into the
* file.
*
+ * On Linux the last pattern of \r\nS: (0x0d0a533A) is looked up and
+ * afterwards a 3072 Bit Base64 encoded RSA signature is expected.
+ * The signature is verified against the built in codesigning key in
+ * the same certificate that is used for windows verification.
+ *
* @param[in] filename absolute null terminated UTF-8 encoded path to the file.
* @param[in] name_len length of the filename.
*
@@ -55,7 +60,15 @@
* @brief windows implementation of verify_binary
*/
bin_verify_result verify_binary_win(const char *filename, size_t name_len);
-#endif /* WIN32 */
+#else /* WIN32 */
+/**@def Max size of a valid binary in byte */
+#define MAX_VALID_BIN_SIZE (32 * 1024 * 1024)
+
+/**
+ * @brief linux implementation of verify_binary
+ */
+bin_verify_result verify_binary_linux(const char *filename, size_t name_len);
+#endif
#ifdef __cplusplus
}
More information about the Trustbridge-commits
mailing list