view common/binverify.c @ 592:778f74d0706f

Verify the binary directly without relying on settings (which might differ)
author Andre Heinecke <aheinecke@intevation.de>
date Wed, 28 May 2014 08:36:05 +0000
parents 26a18e3c3db4
children facb13c578f1
line wrap: on
line source
/* 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"

bin_verify_result
verify_binary(const char *filename, size_t name_len) {
#ifdef WIN32
  return verify_binary_win(filename, name_len);
#else
  /* TODO */
  if (filename && name_len)
    return VerifyValid;
  return VerifyUnknownError;
#endif
}

#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 = VerifyUnknownError;
  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 VerifyUnknownError;
    }

  filenameW = utf8_to_wchar(filename, name_len);

  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 = VerifyReadFailed;
      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 = VerifyUnknownError;
      goto done;
    }

  if (!(CryptMsgGetParam(hMsg,
                         CMSG_SIGNER_CERT_INFO_PARAM,
                         0,
                         pSignerCert,
                         &dwSignerInfoSize)))
    {
      ERRORPRINTF ("Failed to get signer cert.");
      retval = VerifyUnknownError;
      goto done;
    }

  pSignerCertContext = CertGetSubjectCertificateFromStore(
          hStore,
          PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
          pSignerCert);

  if (!pSignerCertContext)
    {
      ERRORPRINTF ("Failed to find signer cert in store.");
      retval = VerifyUnknownError;
      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 = VerifyValid;
    } else {
      ERRORPRINTF ("The signature was not verified. \n");
      retval = VerifyInvalidSignature;
      goto done;
    }

done:
  xfree(filenameW);
  xfree(pSignerCert);

  if(pSignerCertContext)
    {
      CertFreeCertificateContext(pSignerCertContext);
    }
  if (hStore)
    {
      CertCloseStore(hStore, 0);
    }
  if (hMsg)
    {
      CryptMsgClose(hMsg);
    }
  return retval;
}
#endif /* WIN32 */

http://wald.intevation.org/projects/trustbridge/