aheinecke@579: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik aheinecke@579: * Software engineering by Intevation GmbH aheinecke@579: * aheinecke@579: * This file is Free Software under the GNU GPL (v>=2) aheinecke@579: * and comes with ABSOLUTELY NO WARRANTY! aheinecke@579: * See LICENSE.txt for details. aheinecke@579: */ aheinecke@579: aheinecke@579: #include "binverify.h" aheinecke@579: aheinecke@579: #include "strhelp.h" aheinecke@579: #include "logging.h" aheinecke@579: aheinecke@586: bin_verify_result aheinecke@586: verify_binary(const char *filename, size_t name_len) { aheinecke@586: #ifdef WIN32 aheinecke@586: return verify_binary_win(filename, name_len); aheinecke@586: #else aheinecke@586: /* TODO */ aheinecke@590: if (filename && name_len) aheinecke@590: return VerifyValid; aheinecke@590: return VerifyUnknownError; aheinecke@586: #endif aheinecke@586: } aheinecke@586: aheinecke@579: #ifdef WIN32 aheinecke@579: aheinecke@579: #include aheinecke@579: #include aheinecke@579: #include aheinecke@579: #include aheinecke@579: aheinecke@579: bin_verify_result aheinecke@579: verify_binary_win(const char *filename, size_t name_len) { aheinecke@586: bin_verify_result retval = VerifyUnknownError; aheinecke@579: WCHAR *filenameW = NULL; aheinecke@579: BOOL result = FALSE; aheinecke@579: DWORD dwEncoding = 0, aheinecke@579: dwContentType = 0, aheinecke@579: dwFormatType = 0, aheinecke@579: dwSignerInfoSize = 0; aheinecke@579: HCERTSTORE hStore = NULL; aheinecke@579: HCRYPTMSG hMsg = NULL; aheinecke@579: PCERT_INFO pSignerCert = NULL; aheinecke@579: PCCERT_CONTEXT pSignerCertContext = NULL; aheinecke@579: aheinecke@579: if (!filename || name_len > MAX_PATH || strlen(filename) != name_len) aheinecke@579: { aheinecke@579: ERRORPRINTF ("Invalid parameters\n"); aheinecke@586: return VerifyUnknownError; aheinecke@579: } aheinecke@579: aheinecke@579: filenameW = utf8_to_wchar(filename, strnlen(filename, MAX_PATH)); aheinecke@579: aheinecke@579: result = CryptQueryObject (CERT_QUERY_OBJECT_FILE, aheinecke@579: filenameW, aheinecke@579: CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, aheinecke@579: CERT_QUERY_FORMAT_FLAG_BINARY, aheinecke@579: 0, aheinecke@579: &dwEncoding, aheinecke@579: &dwContentType, aheinecke@579: &dwFormatType, aheinecke@579: &hStore, aheinecke@579: &hMsg, aheinecke@579: NULL); aheinecke@579: aheinecke@579: if (!result || !hMsg) aheinecke@579: { aheinecke@579: PRINTLASTERROR ("Failed to query crypto object"); aheinecke@586: retval = VerifyReadFailed; aheinecke@579: goto done; aheinecke@579: } aheinecke@579: aheinecke@579: /* Get the cert info so that we can look up the signer in the store later */ aheinecke@579: if (CryptMsgGetParam(hMsg, aheinecke@579: CMSG_SIGNER_CERT_INFO_PARAM, aheinecke@579: 0, aheinecke@579: NULL, aheinecke@579: &dwSignerInfoSize) && dwSignerInfoSize > 0) aheinecke@579: { aheinecke@579: pSignerCert = xmalloc (dwSignerInfoSize); aheinecke@579: } aheinecke@579: else aheinecke@579: { aheinecke@579: ERRORPRINTF ("Failed to get signer cert size."); aheinecke@586: retval = VerifyUnknownError; aheinecke@579: goto done; aheinecke@579: } aheinecke@579: aheinecke@579: if (!(CryptMsgGetParam(hMsg, aheinecke@579: CMSG_SIGNER_CERT_INFO_PARAM, aheinecke@579: 0, aheinecke@579: pSignerCert, aheinecke@579: &dwSignerInfoSize))) aheinecke@579: { aheinecke@579: ERRORPRINTF ("Failed to get signer cert."); aheinecke@586: retval = VerifyUnknownError; aheinecke@579: goto done; aheinecke@579: } aheinecke@579: aheinecke@579: pSignerCertContext = CertGetSubjectCertificateFromStore( aheinecke@579: hStore, aheinecke@579: PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, aheinecke@579: pSignerCert); aheinecke@579: aheinecke@579: if (!pSignerCertContext) aheinecke@579: { aheinecke@579: ERRORPRINTF ("Failed to find signer cert in store."); aheinecke@586: retval = VerifyUnknownError; aheinecke@579: goto done; aheinecke@579: } aheinecke@579: aheinecke@579: /* Verify that the signature is actually valid */ aheinecke@579: if(CryptMsgControl(hMsg, aheinecke@579: 0, aheinecke@579: CMSG_CTRL_VERIFY_SIGNATURE, aheinecke@579: pSignerCertContext->pCertInfo)) aheinecke@579: { aheinecke@579: DEBUGPRINTF ("Verify signature succeeded. \n"); aheinecke@579: /* TODO pinning*/ aheinecke@586: retval = VerifyValid; aheinecke@579: } else { aheinecke@579: ERRORPRINTF ("The signature was not verified. \n"); aheinecke@586: retval = VerifyInvalidSignature; aheinecke@579: goto done; aheinecke@579: } aheinecke@579: aheinecke@579: done: aheinecke@579: xfree(filenameW); aheinecke@579: xfree(pSignerCert); aheinecke@579: aheinecke@579: if(pSignerCertContext) aheinecke@579: { aheinecke@579: CertFreeCertificateContext(pSignerCertContext); aheinecke@579: } aheinecke@579: if (hStore) aheinecke@579: { aheinecke@579: CertCloseStore(hStore, 0); aheinecke@579: } aheinecke@579: if (hMsg) aheinecke@579: { aheinecke@579: CryptMsgClose(hMsg); aheinecke@579: } aheinecke@579: return retval; aheinecke@579: } aheinecke@579: #endif /* WIN32 */