Mercurial > trustbridge
diff common/binverify.c @ 1081:edbf5e5e88f4
(issue118) Extend verify_binary to carry an open file
* binverify.c: Change result to a structure containing an open fptr
Use in Memory data for windows verification.
* mainwindow.cpp, selftest.c: Handle the returend structure
* binverifytest.cpp: Test for the exclusive read and update signature.
* listutil.c: Add optional fptr parameter to read_file
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Thu, 11 Sep 2014 12:05:24 +0200 |
parents | 698b6a9bd75e |
children | 3cd8dd706aaa |
line wrap: on
line diff
--- a/common/binverify.c Thu Sep 11 12:00:10 2014 +0200 +++ b/common/binverify.c Thu Sep 11 12:05:24 2014 +0200 @@ -10,6 +10,7 @@ #include "strhelp.h" #include "logging.h" +#include "listutil.h" #ifdef RELEASE_BUILD #include "pubkey-release.h" #else @@ -19,8 +20,13 @@ bin_verify_result verify_binary(const char *filename, size_t name_len) { - if (!filename || !name_len) - return VerifyUnknownError; + if (!filename || !name_len) { + bin_verify_result retval; + retval.fptr = NULL; + retval.result = VerifyUnknownError; + return retval; + } + #ifdef WIN32 return verify_binary_win(filename, name_len); #else @@ -101,7 +107,7 @@ bin_verify_result verify_binary_win(const char *filename, size_t name_len) { - bin_verify_result retval = VerifyUnknownError; + bin_verify_result retval; WCHAR *filenameW = NULL; BOOL result = FALSE; DWORD dwEncoding = 0, @@ -112,17 +118,34 @@ HCRYPTMSG hMsg = NULL; PCERT_INFO pSignerCert = NULL; PCCERT_CONTEXT pSignerCertContext = NULL; + FILE *fptr = NULL; + size_t data_size = 0; + char *data = NULL; + int ret = -1; + CRYPT_INTEGER_BLOB blob; + + retval.result = VerifyUnknownError; + retval.fptr = NULL; if (!filename || name_len > MAX_PATH || strlen(filename) != name_len) { ERRORPRINTF ("Invalid parameters\n"); - return VerifyUnknownError; + return retval; } - filenameW = utf8_to_wchar(filename, name_len); + ret = read_file(filename, &data, &data_size, MAX_VALID_BIN_SIZE, &fptr); - result = CryptQueryObject (CERT_QUERY_OBJECT_FILE, - filenameW, + if (ret != 0) + { + ERRORPRINTF ("Read file failed with error: %i\n", ret); + retval.result = VerifyReadFailed; + return retval; + } + blob.cbData = (DWORD) data_size; + blob.pbData = (PBYTE) data; + + result = CryptQueryObject (CERT_QUERY_OBJECT_BLOB, + &blob, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0, @@ -136,7 +159,7 @@ if (!result || !hMsg) { PRINTLASTERROR ("Failed to query crypto object"); - retval = VerifyReadFailed; + retval.result = VerifyReadFailed; goto done; } @@ -152,7 +175,7 @@ else { ERRORPRINTF ("Failed to get signer cert size."); - retval = VerifyUnknownError; + retval.result = VerifyUnknownError; goto done; } @@ -163,7 +186,7 @@ &dwSignerInfoSize))) { ERRORPRINTF ("Failed to get signer cert."); - retval = VerifyUnknownError; + retval.result = VerifyUnknownError; goto done; } @@ -175,7 +198,7 @@ if (!pSignerCertContext) { ERRORPRINTF ("Failed to find signer cert in store."); - retval = VerifyUnknownError; + retval.result = VerifyUnknownError; goto done; } @@ -186,7 +209,7 @@ pSignerCertContext->pCertInfo)) { ERRORPRINTF ("The signature is invalid. \n"); - retval = VerifyInvalidSignature; + retval.result = VerifyInvalidSignature; syslog_error_printf ("Software update embedded signature is invalid."); goto done; } @@ -194,22 +217,29 @@ if(check_certificate(pSignerCertContext)) { DEBUGPRINTF ("Valid signature with pinned certificate."); - retval = VerifyValid; + retval.result = VerifyValid; + retval.fptr = fptr; goto done; } else { ERRORPRINTF ("Certificate mismatch. \n"); - retval = VerifyInvalidCertificate; + retval.result = VerifyInvalidCertificate; syslog_error_printf ("Software update embedded signature " "created with wrong certificate."); goto done; } done: + xfree(data); xfree(filenameW); xfree(pSignerCert); + if (retval.result != VerifyValid) + { + fclose(fptr); + } + if(pSignerCertContext) { CertFreeCertificateContext(pSignerCertContext); @@ -226,8 +256,6 @@ } #else /* WIN32 */ -#include "listutil.h" - #pragma GCC diagnostic ignored "-Wconversion" /* Polarssl mh.h contains a conversion which gcc warns about */ #include <polarssl/pk.h> @@ -248,29 +276,34 @@ sig_size = TRUSTBRIDGE_RSA_KEY_SIZE / 8; unsigned char signature[sig_size], hash[32]; + FILE *fptr = NULL; - bin_verify_result retval = VerifyUnknownError; + bin_verify_result retval; + retval.result = VerifyUnknownError; + retval.fptr = NULL; x509_crt codesign_cert; if (strnlen(filename, name_len + 1) != name_len || name_len == 0) { ERRORPRINTF ("Invalid call to verify_binary_linux\n"); - return VerifyUnknownError; + retval.result = VerifyUnknownError; + return retval; } - ret = read_file(filename, &data, &data_size, MAX_VALID_BIN_SIZE); + ret = read_file(filename, &data, &data_size, MAX_VALID_BIN_SIZE, &fptr); if (ret != 0) { ERRORPRINTF ("Read file failed with error: %i\n", ret); - return VerifyReadFailed; + retval.result = VerifyReadFailed; + return retval; } /* Fetch the signature from the end of data */ if (data_size < sig_b64_size + 5) { ERRORPRINTF ("File to small to contain a signature.\n"); - retval = VerifyInvalidSignature; + retval.result = VerifyInvalidSignature; goto done; } @@ -280,7 +313,7 @@ data[data_size - sig_b64_size - 5] != '\r') { ERRORPRINTF ("Failed to find valid signature line.\n"); - retval = VerifyInvalidSignature; + retval.result = VerifyInvalidSignature; goto done; } @@ -312,7 +345,8 @@ errbuf[1019] = '\0'; /* Just to be sure */ ERRORPRINTF ("x509_crt_parse failed with -0x%04x\n%s\n", -ret, errbuf); x509_crt_free(&codesign_cert); - return VerifyUnknownError; + retval.result = VerifyUnknownError; + goto done; } ret = pk_verify(&codesign_cert.pk, POLARSSL_MD_SHA256, hash, 0, @@ -325,14 +359,22 @@ errbuf[1019] = '\0'; /* Just to be sure */ ERRORPRINTF ("pk_verify failed with -0x%04x\n %s\n", -ret, errbuf); x509_crt_free(&codesign_cert); - retval = VerifyInvalidSignature; + retval.result = VerifyInvalidSignature; goto done; } x509_crt_free(&codesign_cert); - retval = VerifyValid; + retval.result = VerifyValid; + retval.fptr = fptr; done: + if (retval.result != VerifyValid) + { + if (fptr) + { + fclose(fptr); + } + } xfree (data); return retval; }