changeset 1364:28885e8c891f

(issue177) Read signature time from PKCS#7 object in selftest and binverify
author Andre Heinecke <andre.heinecke@intevation.de>
date Fri, 21 Nov 2014 18:33:31 +0100
parents 3d6faded03dd
children 3d7ddf698480
files common/binverify.c common/binverify.h common/selftest.c common/selftest.h
diffstat 4 files changed, 108 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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 <stdbool.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <time.h>
 
 #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;
 
--- 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
--- 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 <stdbool.h>
+#include <time.h>
 
 #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
 }

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