Mercurial > trustbridge
diff common/binverify.c @ 579:f4ce4eef3b38
Implement PKCS#7 embedded signature verfification for windows
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Tue, 27 May 2014 10:28:36 +0000 |
parents | |
children | ecfd77751daf |
line wrap: on
line diff
--- /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 */