Mercurial > trustbridge
view common/binverify.c @ 647:51830f4912c2
Minor style fix
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Wed, 25 Jun 2014 10:56:31 +0200 |
parents | be30d50bc4f0 |
children | 2798f1869eee |
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" #ifdef RELEASE_BUILD #include "pubkey-release.h" #else #include "pubkey-test.h" #endif 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 <polarssl/x509_crt.h> #include <windows.h> #include <wincrypt.h> #include <wintrust.h> #include <stdio.h> /** @brief Check if the certificate @a pCCertContext is pinned * * Compares the certificate's binary data (public key and attributes) * with each other to validate that the certificate pCCertContext has * exactly the same data as the builtin public certificate. * * @param[in] pCCertContext pointer to the certificate to check * * @returns true if the certificate matches, false otherwise. */ static bool check_certificate (PCCERT_CONTEXT pCCertContext) { x509_crt codesign_cert; int ret = 0; DWORD dwI = 0; bool retval = false; if (pCCertContext == NULL) { ERRORPRINTF ("Invalid call to check_certificate"); return false; } x509_crt_init(&codesign_cert); /* Parse the pinned certificate */ ret = x509_crt_parse(&codesign_cert, public_key_codesign_pem, public_key_codesign_pem_size); if (ret != 0) { ERRORPRINTF ("x509_crt_parse failed with -0x%04x\n\n", -ret); goto done; } if (codesign_cert.raw.len != pCCertContext->cbCertEncoded || codesign_cert.raw.len <= 0) { ERRORPRINTF ("Certificate size mismatch"); goto done; } /* Check that the certificate is exactly the same as the pinned one */ for (dwI = 0; dwI < pCCertContext->cbCertEncoded; dwI++) { if (pCCertContext->pbCertEncoded[dwI] != codesign_cert.raw.p[dwI]) { ERRORPRINTF ("Certificate content mismatch"); goto done; } } retval = true; done: x509_crt_free(&codesign_cert); return retval; } 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)) { ERRORPRINTF ("The signature is invalid. \n"); retval = VerifyInvalidSignature; syslog_error_printf ("Software update embedded signature is invalid."); goto done; } if(check_certificate(pSignerCertContext)) { DEBUGPRINTF ("Valid signature with pinned certificate."); retval = VerifyValid; goto done; } else { ERRORPRINTF ("Certificate mismatch. \n"); retval = VerifyInvalidCertificate; syslog_error_printf ("Software update embedded signature " "created with wrong certificate."); goto done; } done: xfree(filenameW); xfree(pSignerCert); if(pSignerCertContext) { CertFreeCertificateContext(pSignerCertContext); } if (hStore) { CertCloseStore(hStore, 0); } if (hMsg) { CryptMsgClose(hMsg); } return retval; } #endif /* WIN32 */