# HG changeset patch # User Andre Heinecke # Date 1416591211 -3600 # Node ID 28885e8c891f21dad2ecf3f66d4d9b82117b12fb # Parent 3d6faded03dd25d79e58bd665159a574c25079ef (issue177) Read signature time from PKCS#7 object in selftest and binverify diff -r 3d6faded03dd -r 28885e8c891f common/binverify.c --- a/common/binverify.c Fri Nov 21 18:32:35 2014 +0100 +++ b/common/binverify.c Fri Nov 21 18:33:31 2014 +0100 @@ -24,6 +24,7 @@ bin_verify_result retval; retval.fptr = NULL; retval.result = VerifyUnknownError; + retval.sig_time = 0; return retval; } @@ -104,6 +105,97 @@ return retval; } +time_t +systemtime_to_time_t (SYSTEMTIME *systemTime) + +{ + LARGE_INTEGER jan1970FT = {{0}}; + jan1970FT.QuadPart = 116444736000000000LL; // january 1st 1970 well known value + LARGE_INTEGER utcFT = {{0}}; + + SystemTimeToFileTime(systemTime, (FILETIME*)&utcFT); + + __int64 utcDosTime = (utcFT.QuadPart - jan1970FT.QuadPart)/10000000; + + return (time_t)utcDosTime; +} + + +time_t +get_signature_time (HCRYPTMSG hMsg) +{ + FILETIME lft, ft; + SYSTEMTIME st; + DWORD dwData = 0, + n = 0, + dwSignerInfo = 0; + PCMSG_SIGNER_INFO pSignerInfo = NULL; + + time_t ret = -1; + + if (!hMsg) + { + return -1; + } + + // Get signer information size. + if (!CryptMsgGetParam(hMsg, + CMSG_SIGNER_INFO_PARAM, + 0, + NULL, + &dwSignerInfo)) + { + ERRORPRINTF ("Failed to get signer info size."); + return -1; + } + pSignerInfo = xmalloc (dwSignerInfo); + + if (!CryptMsgGetParam(hMsg, + CMSG_SIGNER_INFO_PARAM, + 0, + (PVOID)pSignerInfo, + &dwSignerInfo)) + { + ERRORPRINTF ("Failed to get signer info."); + goto done; + } + + + // Loop through authenticated attributes and find + // szOID_RSA_signingTime OID. + for (n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++) + { + if (lstrcmpA(szOID_RSA_signingTime, + pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0) + { + dwData = sizeof(ft); + if (!CryptDecodeObject((X509_ASN_ENCODING | PKCS_7_ASN_ENCODING), + szOID_RSA_signingTime, + pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData, + pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData, + 0, + (PVOID)&ft, + &dwData)) + { + PRINTLASTERROR ("Failed to decode time: "); + break; + } + + // Convert to local time. + FileTimeToLocalFileTime(&ft, &lft); + FileTimeToSystemTime(&lft, &st); + + ret = systemtime_to_time_t(&st); + break; + } + } + +done: + xfree(pSignerInfo); + + return ret; +} + bin_verify_result verify_binary_win(const char *filename, size_t name_len) { @@ -219,6 +311,7 @@ DEBUGPRINTF ("Valid signature with pinned certificate."); retval.result = VerifyValid; retval.fptr = fptr; + retval.sig_time = get_signature_time (hMsg); goto done; } else diff -r 3d6faded03dd -r 28885e8c891f common/binverify.h --- a/common/binverify.h Fri Nov 21 18:32:35 2014 +0100 +++ b/common/binverify.h Fri Nov 21 18:33:31 2014 +0100 @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -47,6 +48,7 @@ FILE *fptr; /**< Pointer to the open file struct of the verified file The ptr is only valid if verify_result is VerifyValid and needs to be closed by the caller in that case.*/ + time_t sig_time; /** < Time of the signature. */ /*@}*/ } bin_verify_result; diff -r 3d6faded03dd -r 28885e8c891f common/selftest.c --- a/common/selftest.c Fri Nov 21 18:32:35 2014 +0100 +++ b/common/selftest.c Fri Nov 21 18:33:31 2014 +0100 @@ -12,7 +12,7 @@ #include "logging.h" bool -selftest() +selftest(time_t *sig_time) { bin_verify_result res; #ifdef WIN32 @@ -45,6 +45,10 @@ return false; } + if (sig_time) + { + *sig_time = res.sig_time; + } fclose(res.fptr); xfree(utf8path); return true; @@ -55,6 +59,10 @@ syslog_error_printf ("Integrity check failed."); return false; } + if (sig_time) + { + *sig_time = res.sig_time; + } fclose(res.fptr); return true; #endif diff -r 3d6faded03dd -r 28885e8c891f common/selftest.h --- a/common/selftest.h Fri Nov 21 18:32:35 2014 +0100 +++ b/common/selftest.h Fri Nov 21 18:33:31 2014 +0100 @@ -19,6 +19,7 @@ */ #include +#include #ifdef __cplusplus extern "C" { @@ -28,9 +29,11 @@ * Checks that the certificate is signed with a valid signature and the * builtin public certificate. * + * @param[out] sig_time point this to a time_t to get the signature timestamp + * * @returns true if the selftest is successful. false on error. */ -bool selftest(); +bool selftest(time_t *sig_time); #ifdef __cplusplus }