Browse code

Add support for MD5 and SHA256 hash-based validation of the exe code Also refactors the code a bit to consolidate some duplicate functionality

Andrew authored on 2018/09/02 12:29:45
Showing 4 changed files
... ...
@@ -116,6 +116,8 @@
116 116
 #define ASN1_TYPE_SEQUENCE 0x30
117 117
 #define ASN1_TYPE_SET 0x31
118 118
 
119
+#define MAX_HASH_SIZE SHA512_HASH_SIZE
120
+
119 121
 struct cli_asn1 {
120 122
     uint8_t type;
121 123
     unsigned int size;
... ...
@@ -160,6 +162,27 @@ static int map_md5(fmap_t *map, const void *data, unsigned int len, uint8_t *md5
160 160
     return (cl_hash_data("md5", data, len, md5, NULL) == NULL);
161 161
 }
162 162
 
163
+static int map_hash(fmap_t *map, const void *data, unsigned int len, uint8_t *out_hash, cli_crt_hashtype hashtype) {
164
+
165
+    if(hashtype == CLI_SHA1RSA) {
166
+        if(map_sha1(map, data, len, out_hash)) {
167
+            return 1;
168
+        }
169
+    } else if(hashtype == CLI_MD5RSA) {
170
+        if(map_md5(map, data, len, out_hash)) {
171
+            return 1;
172
+        }
173
+    } else if(hashtype == CLI_SHA256RSA) {
174
+        if(map_sha256(map, data, len, out_hash)) {
175
+            return 1;
176
+        }
177
+    } else {
178
+        cli_dbgmsg("asn1_map_hash: unsupported hashtype\n");
179
+        return 1;
180
+    }
181
+    return 0;
182
+}
183
+
163 184
 
164 185
 static int asn1_get_obj(fmap_t *map, const void *asn1data, unsigned int *asn1len, struct cli_asn1 *obj) {
165 186
     unsigned int asn1_sz = *asn1len;
... ...
@@ -268,6 +291,53 @@ static int asn1_expect_algo(fmap_t *map, const void **asn1data, unsigned int *as
268 268
     return 0;
269 269
 }
270 270
 
271
+static int asn1_expect_hash_algo(fmap_t *map, const void **asn1data, unsigned int *asn1len, cli_crt_hashtype *hashtype, unsigned int *hashsize) {
272
+    struct cli_asn1 obj;
273
+    unsigned int avail;
274
+    int ret;
275
+
276
+    if(ret = asn1_expect_objtype(map, *asn1data, asn1len, &obj, ASN1_TYPE_SEQUENCE)) {
277
+        cli_dbgmsg("asn1_expect_hash_algo: expected SEQUENCE to start AlgorithmIdentifier\n");
278
+        return ret;
279
+    }
280
+    avail = obj.size;
281
+    *asn1data = obj.next;
282
+    if(ret = asn1_expect_objtype(map, obj.content, &avail, &obj, ASN1_TYPE_OBJECT_ID)) {
283
+        cli_dbgmsg("asn1_expect_hash_algo: unexpected object type inside AlgorithmIdentifier SET\n");
284
+        return ret;
285
+    }
286
+    if(obj.size != lenof(OID_sha1) && obj.size != lenof(OID_md5) && obj.size != lenof(OID_sha256)) {
287
+        cli_dbgmsg("asn1_expect_hash_algo: unsupported algorithm OID size for AlgorithmIdentifier\n");
288
+        return 1;
289
+    }
290
+    if(!fmap_need_ptr_once(map, obj.content, obj.size)) {
291
+        cli_dbgmsg("asn1_expect_hash_algo: failed to get AlgorithmIdentifier OID\n");
292
+        return 1;
293
+    }
294
+    if(obj.size == lenof(OID_sha1) && !memcmp(obj.content, OID_sha1, lenof(OID_sha1))) {
295
+        *hashtype = CLI_SHA1RSA;
296
+        *hashsize = SHA1_HASH_SIZE;
297
+    } else if(obj.size == lenof(OID_md5) && !memcmp(obj.content, OID_md5, lenof(OID_md5))) {
298
+        *hashtype = CLI_MD5RSA;
299
+        *hashsize = MD5_HASH_SIZE;
300
+    } else if(obj.size == lenof(OID_sha256) && !memcmp(obj.content, OID_sha256, lenof(OID_sha256))) {
301
+        *hashtype = CLI_SHA256RSA;
302
+        *hashsize = SHA256_HASH_SIZE;
303
+    } else {
304
+        cli_dbgmsg("asn1_expect_hash_algo: unknown digest OID in AlgorithmIdentifier\n");
305
+        return 1;
306
+    }
307
+    if(ret = asn1_expect_obj(map, &obj.next, &avail, ASN1_TYPE_NULL, 0, NULL)) {
308
+        cli_dbgmsg("asn1_expect_hash_algo: unexpected value after AlgorithmIdentifier OID\n");
309
+        return ret;
310
+    }
311
+    if(avail) {
312
+        cli_dbgmsg("asn1_expect_hash_algo: extra data in AlgorithmIdentifier\n");
313
+        return 1;
314
+    }
315
+    return 0;
316
+}
317
+
271 318
 
272 319
 static int asn1_expect_rsa(fmap_t *map, const void **asn1data, unsigned int *asn1len, cli_crt_hashtype *hashtype) {
273 320
     struct cli_asn1 obj;
... ...
@@ -857,11 +927,10 @@ static int asn1_get_x509(fmap_t *map, const void **asn1data, unsigned int *size,
857 857
             break;
858 858
         }
859 859
 
860
-        if((x509.hashtype == CLI_SHA1RSA && map_sha1(map, tbsdata, tbssize, x509.tbshash)) || \
861
-           (x509.hashtype == CLI_MD5RSA && map_md5(map, tbsdata, tbssize, x509.tbshash)) || \
862
-           (x509.hashtype == CLI_SHA256RSA && map_sha256(map, tbsdata, tbssize, x509.tbshash))) {
860
+        if(map_hash(map, tbsdata, tbssize, x509.tbshash, x509.hashtype)) {
863 861
             cli_dbgmsg("asn1_get_x509: Unsupported hashtype or hash computation failed\n");
864 862
             break;
863
+
865 864
         }
866 865
 
867 866
         if(crtmgr_add(other, &x509))
... ...
@@ -880,107 +949,75 @@ static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsig
880 880
     const uint8_t *attrs;
881 881
     unsigned int dsize, attrs_size;
882 882
     unsigned int avail;
883
-    uint8_t hash[SHA256_HASH_SIZE];
883
+    uint8_t hash[MAX_HASH_SIZE];
884 884
     cli_crt_hashtype hashtype;
885 885
     unsigned int hashsize;
886
-    uint8_t md[SHA256_HASH_SIZE];
886
+    uint8_t md[MAX_HASH_SIZE];
887 887
     int result;
888 888
     void *ctx;
889 889
 
890 890
     do {
891 891
         if(asn1_expect_objtype(map, *asn1data, size, &asn1, ASN1_TYPE_SEQUENCE)) {
892
-            cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE inside counterSignature SET\n");
892
+            cli_dbgmsg("asn1_parse_countersignature: expected SEQUENCE inside counterSignature SET\n");
893 893
             break;
894 894
         }
895 895
 
896 896
         avail = asn1.size;
897 897
         if(asn1_expect_obj(map, &asn1.content, &avail, ASN1_TYPE_INTEGER, 1, "\x01")) { /* Version = 1*/
898
-            cli_dbgmsg("asn1_parse_mscat: expected counterSignature version to be 1\n");
898
+            cli_dbgmsg("asn1_parse_countersignature: expected counterSignature version to be 1\n");
899 899
             break;
900 900
         }
901 901
 
902 902
         if(asn1_expect_objtype(map, asn1.content, &avail, &asn1, ASN1_TYPE_SEQUENCE)) { /* issuerAndSerialNumber */
903
-            cli_dbgmsg("asn1_parse_mscat: unable to parse issuerAndSerialNumber SEQUENCE in counterSignature\n");
903
+            cli_dbgmsg("asn1_parse_countersignature: unable to parse issuerAndSerialNumber SEQUENCE in counterSignature\n");
904 904
             break;
905 905
         }
906 906
 
907 907
         if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, ASN1_TYPE_SEQUENCE)) { /* issuer */
908
-            cli_dbgmsg("asn1_parse_mscat: unable to parse issuer SEQUENCE in counterSignature\n");
908
+            cli_dbgmsg("asn1_parse_countersignature: unable to parse issuer SEQUENCE in counterSignature\n");
909 909
             break;
910 910
         }
911 911
         // Compute the hash of the issuer section
912 912
         if(map_sha1(map, deep.content, deep.size, issuer)) {
913
-            cli_dbgmsg("asn1_parse_mscat: error in call to map_sha1 for counterSignature issuer\n");
913
+            cli_dbgmsg("asn1_parse_countersignature: error in call to map_sha1 for counterSignature issuer\n");
914 914
             break;
915 915
         }
916 916
 
917 917
         if(asn1_expect_objtype(map, deep.next, &asn1.size, &deep, ASN1_TYPE_INTEGER)) { /* serial */
918
-            cli_dbgmsg("asn1_parse_mscat: expected ASN1_TYPE_INTEGER serial for counterSignature\n");
918
+            cli_dbgmsg("asn1_parse_countersignature: expected ASN1_TYPE_INTEGER serial for counterSignature\n");
919 919
             break;
920 920
         }
921 921
 
922 922
         // Compute the hash of the serial INTEGER
923 923
         if(map_sha1(map, deep.content, deep.size, serial)) {
924
-            cli_dbgmsg("asn1_parse_mscat: error in call to map_sha1 for counterSignature serial\n");
924
+            cli_dbgmsg("asn1_parse_countersignature: error in call to map_sha1 for counterSignature serial\n");
925 925
             break;
926 926
         }
927 927
 
928 928
         if(asn1.size) {
929
-            cli_dbgmsg("asn1_parse_mscat: extra data inside counterSignature issuer\n");
929
+            cli_dbgmsg("asn1_parse_countersignature: extra data inside counterSignature issuer\n");
930 930
             break;
931 931
         }
932 932
 
933
-        if(asn1_expect_objtype(map, asn1.next, &avail, &asn1, ASN1_TYPE_SEQUENCE)) { /* digestAlgorithm */
934
-            cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE to start digestAlgorithm counterSignature section\n");
935
-            break;
936
-        }
937
-        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, ASN1_TYPE_OBJECT_ID)) {
938
-            cli_dbgmsg("asn1_parse_mscat: unexpected value when parsing counterSignature\n");
939
-            break;
940
-        }
941
-        if(deep.size != lenof(OID_sha1) && deep.size != lenof(OID_md5)) {
942
-            cli_dbgmsg("asn1_parse_mscat: wrong digestAlgorithm size in counterSignature\n");
943
-            break;
944
-        }
945
-        if(!fmap_need_ptr_once(map, deep.content, deep.size)) {
946
-            cli_dbgmsg("asn1_parse_mscat: failed to read digestAlgorithm OID\n");
933
+        if(asn1_expect_hash_algo(map, &asn1.next, &avail, &hashtype, &hashsize)) {
934
+            cli_dbgmsg("asn1_parse_countersignature: error parsing counterSignature digestAlgorithm\n");
947 935
             break;
948 936
         }
949
-        if(deep.size == lenof(OID_sha1) && !memcmp(deep.content, OID_sha1, lenof(OID_sha1))) {
950
-            hashtype = CLI_SHA1RSA;
951
-            hashsize = SHA1_HASH_SIZE;
952
-            if(map_sha1(map, message, message_size, md)) {
953
-                cli_dbgmsg("asn1_parse_mscat: map_sha1 for counterSignature verification failed\n");
954
-                break;
955
-            }
956
-        } else if(deep.size == lenof(OID_md5) && !memcmp(deep.content, OID_md5, lenof(OID_md5))) {
957
-            hashtype = CLI_MD5RSA;
958
-            hashsize = MD5_HASH_SIZE;
959
-            if(map_md5(map, message, message_size, md)) {
960
-                cli_dbgmsg("asn1_parse_mscat: map_md5 for counterSignature verification failed\n");
961
-                break;
962
-            }
963
-        } else {
964
-            cli_dbgmsg("asn1_parse_mscat: unknown digest OID in counterSignature\n");
965
-            break;
966
-        }
967
-        if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, ASN1_TYPE_NULL, 0, NULL)) {
968
-            cli_dbgmsg("asn1_parse_mscat: unexpected value after counterSignature digestAlgorithm\n");
969
-            break;
970
-        }
971
-        if(asn1.size) {
972
-            cli_dbgmsg("asn1_parse_mscat: extra data in counterSignature OID\n");
937
+
938
+        if(map_hash(map, message, message_size, md, hashtype)) {
939
+            cli_dbgmsg("asn1_parse_countersignature: failed to map in message/compute countersignature hash\n");
973 940
             break;
941
+
974 942
         }
975 943
 
976 944
         attrs = asn1.next;
977 945
         if(asn1_expect_objtype(map, asn1.next, &avail, &asn1, 0xa0)) { /* authenticatedAttributes */
978
-            cli_dbgmsg("asn1_parse_mscat: unable to parse counterSignature authenticatedAttributes section\n");
946
+            cli_dbgmsg("asn1_parse_countersignature: unable to parse counterSignature authenticatedAttributes section\n");
979 947
             break;
980 948
         }
981 949
         attrs_size = (uint8_t *)(asn1.next) - attrs;
982 950
         if(asn1.next == NULL && attrs_size < 2) {
983
-            cli_dbgmsg("asn1_parse_mscat: counterSignature authenticatedAttributes are too small\n");
951
+            cli_dbgmsg("asn1_parse_countersignature: counterSignature authenticatedAttributes are too small\n");
984 952
             break;
985 953
         }
986 954
         result = 0;
... ...
@@ -989,12 +1026,12 @@ static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsig
989 989
         while(dsize) {
990 990
             int content;
991 991
             if(asn1_expect_objtype(map, deep.next, &dsize, &deep, ASN1_TYPE_SEQUENCE)) { /* attribute */
992
-                cli_dbgmsg("asn1_parse_mscat: expected counterSignature attribute SEQUENCE\n");
992
+                cli_dbgmsg("asn1_parse_countersignature: expected counterSignature attribute SEQUENCE\n");
993 993
                 dsize = 1;
994 994
                 break;
995 995
             }
996 996
             if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, ASN1_TYPE_OBJECT_ID)) { /* attribute type */
997
-                cli_dbgmsg("asn1_parse_mscat: expected attribute type inside counterSignature attribute SEQUENCE\n");
997
+                cli_dbgmsg("asn1_parse_countersignature: expected attribute type inside counterSignature attribute SEQUENCE\n");
998 998
                 dsize = 1;
999 999
                 break;
1000 1000
             }
... ...
@@ -1002,7 +1039,7 @@ static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsig
1002 1002
                 continue;
1003 1003
 
1004 1004
             if(!fmap_need_ptr_once(map, deeper.content, lenof(OID_contentType))) {
1005
-                cli_dbgmsg("asn1_parse_mscat: failed to read counterSignature authenticated attribute\n");
1005
+                cli_dbgmsg("asn1_parse_countersignature: failed to read counterSignature authenticated attribute\n");
1006 1006
                 dsize = 1;
1007 1007
                 break;
1008 1008
             }
... ...
@@ -1015,18 +1052,18 @@ static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsig
1015 1015
             else
1016 1016
                 continue;
1017 1017
             if(result & (1<<content)) {
1018
-                cli_dbgmsg("asn1_parse_mscat: duplicate field in countersignature\n");
1018
+                cli_dbgmsg("asn1_parse_countersignature: duplicate field in countersignature\n");
1019 1019
                 dsize = 1;
1020 1020
                 break;
1021 1021
             }
1022 1022
             result |= (1<<content);
1023 1023
             if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, ASN1_TYPE_SET)) { /* set - contents */
1024
-                cli_dbgmsg("asn1_parse_mscat: failed to read counterSignature authenticated attribute\n");
1024
+                cli_dbgmsg("asn1_parse_countersignature: failed to read counterSignature authenticated attribute\n");
1025 1025
                 dsize = 1;
1026 1026
                 break;
1027 1027
             }
1028 1028
             if(deep.size) {
1029
-                cli_dbgmsg("asn1_parse_mscat: extra data in countersignature value\n");
1029
+                cli_dbgmsg("asn1_parse_countersignature: extra data in countersignature value\n");
1030 1030
                 dsize = 1;
1031 1031
                 break;
1032 1032
             }
... ...
@@ -1034,28 +1071,28 @@ static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsig
1034 1034
             switch(content) {
1035 1035
             case 0:  /* contentType = pkcs7-data */
1036 1036
                 if(asn1_expect_obj(map, &deeper.content, &deep.size, ASN1_TYPE_OBJECT_ID, lenof(OID_pkcs7_data), OID_pkcs7_data)) {
1037
-                    cli_dbgmsg("asn1_parse_mscat: contentType != pkcs7-data\n");
1037
+                    cli_dbgmsg("asn1_parse_countersignature: contentType != pkcs7-data\n");
1038 1038
                     deep.size = 1;
1039 1039
                 } else if(deep.size)
1040
-                    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature content-type\n");
1040
+                    cli_dbgmsg("asn1_parse_countersignature: extra data in countersignature content-type\n");
1041 1041
                 break;
1042 1042
             case 1:  /* messageDigest */
1043 1043
                 if(asn1_expect_obj(map, &deeper.content, &deep.size, ASN1_TYPE_OCTET_STRING, hashsize, md)) {
1044 1044
                     deep.size = 1;
1045
-                    cli_dbgmsg("asn1_parse_mscat: countersignature hash mismatch\n");
1045
+                    cli_dbgmsg("asn1_parse_countersignature: countersignature hash mismatch\n");
1046 1046
                 } else if(deep.size)
1047
-                    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature message-digest\n");
1047
+                    cli_dbgmsg("asn1_parse_countersignature: extra data in countersignature message-digest\n");
1048 1048
                 break;
1049 1049
             case 2:  /* signingTime */
1050 1050
                 {
1051 1051
                     time_t sigdate; /* FIXME shall i use it?! */
1052 1052
                     if(asn1_get_time(map, &deeper.content, &deep.size, &sigdate)) {
1053
-                        cli_dbgmsg("asn1_parse_mscat: an error occurred when getting the time\n");
1053
+                        cli_dbgmsg("asn1_parse_countersignature: an error occurred when getting the time\n");
1054 1054
                         deep.size = 1;
1055 1055
                     } else if(deep.size)
1056
-                        cli_dbgmsg("asn1_parse_mscat: extra data in countersignature signing-time\n");
1056
+                        cli_dbgmsg("asn1_parse_countersignature: extra data in countersignature signing-time\n");
1057 1057
                     else if(sigdate < not_before || sigdate > not_after) {
1058
-                        cli_dbgmsg("asn1_parse_mscat: countersignature timestamp outside cert validity\n");
1058
+                        cli_dbgmsg("asn1_parse_countersignature: countersignature timestamp outside cert validity\n");
1059 1059
                         deep.size = 1;
1060 1060
                     }
1061 1061
                     break;
... ...
@@ -1069,54 +1106,54 @@ static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsig
1069 1069
         if(dsize)
1070 1070
             break;
1071 1071
         if(result != 7) {
1072
-            cli_dbgmsg("asn1_parse_mscat: some important attributes are missing in countersignature\n");
1072
+            cli_dbgmsg("asn1_parse_countersignature: some important attributes are missing in countersignature\n");
1073 1073
             break;
1074 1074
         }
1075 1075
 
1076 1076
         if(asn1_expect_objtype(map, asn1.next, &avail, &asn1, ASN1_TYPE_SEQUENCE)) { /* digestEncryptionAlgorithm == sha1 */
1077
-            cli_dbgmsg("asn1_parse_mscat: expected to parse SEQUENCE after counterSignature attributes\n");
1077
+            cli_dbgmsg("asn1_parse_countersignature: expected to parse SEQUENCE after counterSignature attributes\n");
1078 1078
             break;
1079 1079
         }
1080 1080
         if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, ASN1_TYPE_OBJECT_ID)) {/* digestEncryptionAlgorithm == sha1 */
1081
-            cli_dbgmsg("asn1_parse_mscat: unexpected value when parsing counterSignature digestEncryptionAlgorithm\n");
1081
+            cli_dbgmsg("asn1_parse_countersignature: unexpected value when parsing counterSignature digestEncryptionAlgorithm\n");
1082 1082
             break;
1083 1083
         }
1084 1084
         if(deep.size != lenof(OID_rsaEncryption)) { /* lenof(OID_rsaEncryption) = lenof(OID_sha1WithRSAEncryption) = 9 */
1085
-            cli_dbgmsg("asn1_parse_mscat: wrong digestEncryptionAlgorithm size in countersignature\n");
1085
+            cli_dbgmsg("asn1_parse_countersignature: wrong digestEncryptionAlgorithm size in countersignature\n");
1086 1086
             break;
1087 1087
         }
1088 1088
         if(!fmap_need_ptr_once(map, deep.content, lenof(OID_rsaEncryption))) {
1089
-            cli_dbgmsg("asn1_parse_mscat: cannot read digestEncryptionAlgorithm in countersignature\n");
1089
+            cli_dbgmsg("asn1_parse_countersignature: cannot read digestEncryptionAlgorithm in countersignature\n");
1090 1090
             break;
1091 1091
         }
1092 1092
         /* rsaEncryption or sha1withRSAEncryption */
1093 1093
         if(memcmp(deep.content, OID_rsaEncryption, lenof(OID_rsaEncryption)) && memcmp(deep.content, OID_sha1WithRSAEncryption, lenof(OID_sha1WithRSAEncryption))) {
1094
-            cli_dbgmsg("asn1_parse_mscat: digestEncryptionAlgorithm in countersignature is not sha1\n");
1094
+            cli_dbgmsg("asn1_parse_countersignature: digestEncryptionAlgorithm in countersignature is not sha1\n");
1095 1095
             break;
1096 1096
         }
1097 1097
         if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, ASN1_TYPE_NULL, 0, NULL)) {
1098
-            cli_dbgmsg("asn1_parse_mscat: unexpected value after counterSignature digestEncryptionAlgorithm\n");
1098
+            cli_dbgmsg("asn1_parse_countersignature: unexpected value after counterSignature digestEncryptionAlgorithm\n");
1099 1099
             break;
1100 1100
         }
1101 1101
         if(asn1.size) {
1102
-            cli_dbgmsg("asn1_parse_mscat: extra data in digestEncryptionAlgorithm in countersignature\n");
1102
+            cli_dbgmsg("asn1_parse_countersignature: extra data in digestEncryptionAlgorithm in countersignature\n");
1103 1103
             break;
1104 1104
         }
1105 1105
 
1106 1106
         if(asn1_expect_objtype(map, asn1.next, &avail, &asn1, ASN1_TYPE_OCTET_STRING)) { /* encryptedDigest */
1107
-            cli_dbgmsg("asn1_parse_mscat: unexpected encryptedDigest value in counterSignature\n");
1107
+            cli_dbgmsg("asn1_parse_countersignature: unexpected encryptedDigest value in counterSignature\n");
1108 1108
             break;
1109 1109
         }
1110 1110
         if(asn1.size > 513) {
1111
-            cli_dbgmsg("asn1_parse_mscat: countersignature encryptedDigest too long\n");
1111
+            cli_dbgmsg("asn1_parse_countersignature: countersignature encryptedDigest too long\n");
1112 1112
             break;
1113 1113
         }
1114 1114
         if(avail) {
1115
-            cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature\n");
1115
+            cli_dbgmsg("asn1_parse_countersignature: extra data inside countersignature\n");
1116 1116
             break;
1117 1117
         }
1118 1118
         if(!fmap_need_ptr_once(map, attrs, attrs_size)) {
1119
-            cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n");
1119
+            cli_dbgmsg("asn1_parse_countersignature: failed to read authenticatedAttributes\n");
1120 1120
             break;
1121 1121
         }
1122 1122
 
... ...
@@ -1124,6 +1161,8 @@ static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsig
1124 1124
             ctx = cl_hash_init("sha1");
1125 1125
         } else if (hashtype == CLI_MD5RSA) {
1126 1126
             ctx = cl_hash_init("md5");
1127
+        } else if (hashtype == CLI_SHA256RSA) {
1128
+            ctx = cl_hash_init("sha256");
1127 1129
         } else {
1128 1130
             break;
1129 1131
         }
... ...
@@ -1136,15 +1175,15 @@ static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsig
1136 1136
         cl_finish_hash(ctx, hash);
1137 1137
 
1138 1138
         if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) {
1139
-            cli_dbgmsg("asn1_parse_mscat: failed to read countersignature encryptedDigest\n");
1139
+            cli_dbgmsg("asn1_parse_countersignature: failed to read countersignature encryptedDigest\n");
1140 1140
             break;
1141 1141
         }
1142 1142
         if(!crtmgr_verify_pkcs7(cmgr, issuer, serial, asn1.content, asn1.size, hashtype, hash, VRFY_TIME)) {
1143
-            cli_dbgmsg("asn1_parse_mscat: pkcs7 countersignature verification failed\n");
1143
+            cli_dbgmsg("asn1_parse_countersignature: pkcs7 countersignature verification failed\n");
1144 1144
             break;
1145 1145
         }
1146 1146
 
1147
-        cli_dbgmsg("asn1_parse_mscat: countersignature verification completed successfully\n");
1147
+        cli_dbgmsg("asn1_parse_countersignature: countersignature verification completed successfully\n");
1148 1148
 
1149 1149
         return 0;
1150 1150
 
... ...
@@ -1159,11 +1198,11 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg
1159 1159
     const uint8_t *message, *attrs;
1160 1160
     unsigned int dsize, message_size, attrs_size;
1161 1161
     // hash is used to hold the hashes we compute as part of sig verification
1162
-    uint8_t hash[SHA256_HASH_SIZE];
1163
-    cli_crt_hashtype hashtype;
1162
+    uint8_t hash[MAX_HASH_SIZE];
1163
+    cli_crt_hashtype hashtype, hashtype2;
1164 1164
     unsigned int hashsize;
1165 1165
     // md is used to hold the message digest we extract from the signature
1166
-    uint8_t md[SHA256_HASH_SIZE];
1166
+    uint8_t md[MAX_HASH_SIZE];
1167 1167
     cli_crt *x509;
1168 1168
     void *ctx;
1169 1169
     int result;
... ...
@@ -1225,52 +1264,17 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg
1225 1225
         // DigestAlgorithmIdentifier SET, so we'll want to preserve it so
1226 1226
         // we can continue parsing laterally.  We also want to preserve
1227 1227
         // size, since it tracks how much is left in the SignedData section.
1228
-        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, ASN1_TYPE_SEQUENCE)) { /* digestAlgorithm */
1229
-            cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE to start SignerInfo digestAlgorithm\n");
1228
+        if (asn1_expect_hash_algo(map, &asn1.content, &asn1.size, &hashtype, &hashsize)) {
1229
+            cli_dbgmsg("asn1_parse_mscat: error parsing SignedData digestAlgorithm\n");
1230 1230
             break;
1231 1231
         }
1232 1232
         if (asn1.size) {
1233
-            cli_dbgmsg("asn1_parse_mscat: found extra data in the SignerInfo digestAlgorithm SET\n");
1234
-            break;
1235
-        }
1236
-        dsize = deep.size;
1237
-        if(asn1_expect_objtype(map, deep.content, &dsize, &deep, ASN1_TYPE_OBJECT_ID)) {
1238
-            cli_dbgmsg("asn1_parse_mscat: unexpected object type inside DigestAlgorithmIdentifier SET\n");
1239
-            break;
1240
-        }
1241
-        if(deep.size != lenof(OID_sha1) && deep.size != lenof(OID_md5) && deep.size != lenof(OID_sha256)) {
1242
-            cli_dbgmsg("asn1_parse_mscat: wrong digestAlgorithm size for DigestAlgorithmIdentifier\n");
1243
-            break;
1244
-        }
1245
-        if(!fmap_need_ptr_once(map, deep.content, deep.size)) {
1246
-            cli_dbgmsg("asn1_parse_mscat: failed to read digestAlgorithm OID\n");
1247
-            break;
1248
-        }
1249
-        if(deep.size == lenof(OID_sha1) && !memcmp(deep.content, OID_sha1, lenof(OID_sha1))) {
1250
-            hashtype = CLI_SHA1RSA;
1251
-            hashsize = SHA1_HASH_SIZE;
1252
-        } else if(deep.size == lenof(OID_md5) && !memcmp(deep.content, OID_md5, lenof(OID_md5))) {
1253
-            hashtype = CLI_MD5RSA;
1254
-            hashsize = MD5_HASH_SIZE;
1255
-        } else if(deep.size == lenof(OID_sha256) && !memcmp(deep.content, OID_sha256, lenof(OID_sha256))) {
1256
-            hashtype = CLI_SHA256RSA;
1257
-            hashsize = SHA256_HASH_SIZE;
1258
-        } else {
1259
-            cli_dbgmsg("asn1_parse_mscat: unknown digest OID in DigestAlgorithmIdentifier\n");
1260
-            break;
1261
-        }
1262
-        if(asn1_expect_obj(map, &deep.next, &dsize, ASN1_TYPE_NULL, 0, NULL)) {
1263
-            cli_dbgmsg("asn1_parse_mscat: unexpected value after DigestAlgorithmIdentifier OID\n");
1264
-            break;
1265
-        }
1266
-        if(dsize) {
1267
-            cli_dbgmsg("asn1_parse_mscat: extra data in DigestAlgorithmIdentifier\n");
1233
+            cli_dbgmsg("asn1_parse_mscat: found extra data in the SignerData digestAlgorithm SET\n");
1268 1234
             break;
1269 1235
         }
1270 1236
 
1271 1237
         // We've finished parsing the DigestAlgorithmIdentifiers SET, so start
1272 1238
         // back parsing the SignedData
1273
-
1274 1239
         if(asn1_expect_objtype(map, asn1.next, &size, &asn1, ASN1_TYPE_SEQUENCE)){ /* SEQUENCE - contentInfo */
1275 1240
             cli_dbgmsg("asn1_parse_mscat: expected 'SEQUENCE - contentInfo' inside SignedData following DigestAlgorithmIdentifiers\n");
1276 1241
             break;
... ...
@@ -1520,52 +1524,15 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg
1520 1520
         }
1521 1521
 
1522 1522
         // Resume parsing the SignerInfos using asn1.next and size
1523
-
1524
-        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, ASN1_TYPE_SEQUENCE)) { /* digestAlgorithm */
1525
-            cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE to start SignerInfo digestAlgorithm\n");
1523
+        if (asn1_expect_hash_algo(map, &asn1.next, &size, &hashtype2, &hashsize)) {
1524
+            cli_dbgmsg("asn1_parse_mscat: error parsing SignerInfo digestAlgorithm\n");
1526 1525
             break;
1527 1526
         }
1528 1527
 
1529
-        dsize = asn1.size;
1530
-        if(asn1_expect_objtype(map, asn1.content, &dsize, &deep, ASN1_TYPE_OBJECT_ID)) {
1531
-            cli_dbgmsg("asn1_parse_mscat: unexpected object type inside SignerInfo DigestAlgorithmIdentifier\n");
1532
-            break;
1533
-        }
1534
-        if(deep.size != lenof(OID_sha1) && deep.size != lenof(OID_md5) && deep.size != lenof(OID_sha256)) {
1535
-            cli_dbgmsg("asn1_parse_mscat: wrong digestAlgorithm size for SignerInfo DigestAlgorithmIdentifier\n");
1536
-            break;
1537
-        }
1538
-        if(!fmap_need_ptr_once(map, deep.content, deep.size)) {
1539
-            cli_dbgmsg("asn1_parse_mscat: failed to read SignerInfo digestAlgorithm OID\n");
1540
-            break;
1541
-        }
1542 1528
         // Verify that the SignerInfo digestAlgorithm matches the one from the SignedData section
1543
-        if(deep.size == lenof(OID_sha1) && !memcmp(deep.content, OID_sha1, lenof(OID_sha1))) {
1544
-            if (hashtype != CLI_SHA1RSA) {
1545
-                cli_dbgmsg("asn1_parse_mscat: SignerInfo digestAlgorithm is not SHA1RSA like in SignedData\n");
1546
-                break;
1547
-            }
1548
-        } else if(deep.size == lenof(OID_md5) && !memcmp(deep.content, OID_md5, lenof(OID_md5))) {
1549
-            if (hashtype != CLI_MD5RSA) {
1550
-                cli_dbgmsg("asn1_parse_mscat: SignerInfo digestAlgorithm is not MD5RSA like in SignedData\n");
1529
+        if (hashtype != hashtype2) {
1530
+                cli_dbgmsg("asn1_parse_mscat: SignerInfo digestAlgorithm is not the same as the algorithm in SignedData\n");
1551 1531
                 break;
1552
-            }
1553
-        } else if(deep.size == lenof(OID_sha256) && !memcmp(deep.content, OID_sha256, lenof(OID_sha256))) {
1554
-            if (hashtype != CLI_SHA256RSA) {
1555
-                cli_dbgmsg("asn1_parse_mscat: SignerInfo digestAlgorithm is not SHA256RSA like in SignedData\n");
1556
-                break;
1557
-            }
1558
-        } else {
1559
-            cli_dbgmsg("asn1_parse_mscat: unknown digest OID in SignerInfo DigestAlgorithmIdentifier\n");
1560
-            break;
1561
-        }
1562
-        if(asn1.size && asn1_expect_obj(map, &deep.next, &dsize, ASN1_TYPE_NULL, 0, NULL)) {
1563
-            cli_dbgmsg("asn1_parse_mscat: unexpected value after SignerInfo DigestAlgorithmIdentifier OID\n");
1564
-            break;
1565
-        }
1566
-        if(dsize) {
1567
-            cli_dbgmsg("asn1_parse_mscat: extra data in SignerInfo DigestAlgorithmIdentifier\n");
1568
-            break;
1569 1532
         }
1570 1533
 
1571 1534
         // Continue on to the authenticatedAttributes section within SignerInfo
... ...
@@ -1684,23 +1651,10 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg
1684 1684
             break;
1685 1685
         }
1686 1686
 
1687
-        if (hashtype == CLI_SHA1RSA) {
1688
-            if(map_sha1(map, *hashes, *hashes_size, hash)) {
1689
-                cli_dbgmsg("asn1_parse_mscat: error in call to map_sha1 for computing the message digest\n");
1690
-                break;
1691
-            }
1692
-        } else if (hashtype == CLI_MD5RSA) {
1693
-            if(map_md5(map, *hashes, *hashes_size, hash)) {
1694
-                cli_dbgmsg("asn1_parse_mscat: error in call to map_md5 for computing the message digest\n");
1695
-                break;
1696
-            }
1697
-        } else if (hashtype == CLI_SHA256RSA) {
1698
-            if(map_sha256(map, *hashes, *hashes_size, hash)) {
1699
-                cli_dbgmsg("asn1_parse_mscat: error in call to map_sha256 for computing the message digest\n");
1700
-                break;
1701
-            }
1702
-        } else {
1687
+        if(map_hash(map, *hashes, *hashes_size, hash, hashtype)) {
1688
+            cli_dbgmsg("asn1_parse_mscat: failed to map in message/compute message digest\n");
1703 1689
             break;
1690
+
1704 1691
         }
1705 1692
 
1706 1693
         if(memcmp(hash, md, hashsize)) {
... ...
@@ -2037,12 +1991,16 @@ int asn1_load_mscat(fmap_t *map, struct cl_engine *engine) {
2037 2037
     return 0;
2038 2038
 }
2039 2039
 
2040
-int asn1_check_mscat(struct cl_engine *engine, fmap_t *map, size_t offset, unsigned int size, uint8_t *computed_sha1) {
2040
+int asn1_check_mscat(struct cl_engine *engine, fmap_t *map, size_t offset, unsigned int size, struct cli_mapped_region *regions, uint32_t nregions) {
2041 2041
     unsigned int content_size;
2042 2042
     struct cli_asn1 c;
2043
+    cli_crt_hashtype hashtype;
2044
+    uint8_t hash[MAX_HASH_SIZE];
2045
+    unsigned int hashsize;
2043 2046
     const void *content;
2044 2047
     crtmgr certs;
2045 2048
     int ret;
2049
+    void *ctx;
2046 2050
 
2047 2051
     if (!(engine->dconf->pe & PE_CONF_CERTS))
2048 2052
         return CL_VIRUS;
... ...
@@ -2082,12 +2040,42 @@ int asn1_check_mscat(struct cl_engine *engine, fmap_t *map, size_t offset, unsig
2082 2082
         return CL_VIRUS;
2083 2083
     }
2084 2084
 
2085
-    if(asn1_expect_algo(map, &c.content, &c.size, lenof(OID_sha1), OID_sha1)) {
2086
-        cli_dbgmsg("asn1_check_mscat: expected SHA1 for the file hash algo\n");
2085
+    if(asn1_expect_hash_algo(map, &c.content, &c.size, &hashtype, &hashsize)) {
2086
+        cli_dbgmsg("asn1_check_mscat: unexpected file hash algo\n");
2087
+        return CL_VIRUS;
2088
+    }
2089
+
2090
+    // TODO Move into common a function
2091
+    if(hashtype == CLI_SHA1RSA) {
2092
+        ctx = cl_hash_init("sha1");
2093
+    } else if (hashtype == CLI_MD5RSA) {
2094
+        ctx = cl_hash_init("md5");
2095
+    } else if (hashtype == CLI_SHA256RSA) {
2096
+        ctx = cl_hash_init("sha256");
2097
+    } else {
2087 2098
         return CL_VIRUS;
2088 2099
     }
2089 2100
 
2090
-    if(asn1_expect_obj(map, &c.content, &c.size, ASN1_TYPE_OCTET_STRING, SHA1_HASH_SIZE, computed_sha1)) {
2101
+    if (!(ctx))
2102
+        return CL_VIRUS;
2103
+
2104
+    // Now that we know the hash algorithm, compute the authenticode hash
2105
+    // across the required regions of memory.
2106
+    // NOTE: section[i].ptr points to an already mapped region of memory
2107
+    for(int i = 0; i < nregions; i++) {
2108
+        cl_update_hash(ctx, regions[i].ptr, regions[i].size);
2109
+    }
2110
+
2111
+    cl_finish_hash(ctx, hash);
2112
+
2113
+    if(cli_debug_flag) {
2114
+        char hashtxt[MAX_HASH_SIZE*2+1];
2115
+        for(int i=0; i<hashsize; i++)
2116
+            sprintf(&hashtxt[i*2], "%02x", hash[i]);
2117
+        cli_dbgmsg("Authenticode: %s\n", hashtxt);
2118
+    }
2119
+
2120
+    if(asn1_expect_obj(map, &c.content, &c.size, ASN1_TYPE_OCTET_STRING, hashsize, hash)) {
2091 2121
         cli_dbgmsg("asn1_check_mscat: computed authenticode hash did not match stored value\n");
2092 2122
         return CL_VIRUS;
2093 2123
     }
... ...
@@ -25,7 +25,12 @@
25 25
 #include "others.h"
26 26
 #include "fmap.h"
27 27
 
28
+struct cli_mapped_region {
29
+    const unsigned char *ptr;
30
+    unsigned int size;
31
+};
32
+
28 33
 int asn1_load_mscat(fmap_t *map, struct cl_engine *engine);
29
-int asn1_check_mscat(struct cl_engine *engine, fmap_t *map, size_t offset, unsigned int size, uint8_t *computed_sha1);
34
+int asn1_check_mscat(struct cl_engine *engine, fmap_t *map, size_t offset, unsigned int size, struct cli_mapped_region *regions, uint32_t nregions);
30 35
 
31 36
 #endif
... ...
@@ -579,6 +579,7 @@ extern int cl_scanmap_callback(cl_fmap_t *map, const char *filename, const char
579 579
 #define SHA1_HASH_SIZE 20
580 580
 #define SHA256_HASH_SIZE 32
581 581
 #define SHA384_HASH_SIZE 48
582
+#define SHA512_HASH_SIZE 64
582 583
 
583 584
 /** Generate a hash of data.
584 585
  @param[in] alg The hashing algorithm to use
... ...
@@ -109,6 +109,9 @@
109 109
 
110 110
 #define PE_MAXNAMESIZE 256
111 111
 #define PE_MAXIMPORTS  1024
112
+// TODO On Vista and above, up to 65535 sections are allowed.  Make sure
113
+// that using this lower limit from XP is acceptable in all cases
114
+#define PE_MAXSECTIONS  96
112 115
 
113 116
 #define EC64(x) ((uint64_t)cli_readint64(&(x))) /* Convert little endian to host */
114 117
 #define EC32(x) ((uint32_t)cli_readint32(&(x)))
... ...
@@ -2922,7 +2925,7 @@ int cli_scanpe(cli_ctx *ctx)
2922 2922
     }
2923 2923
 
2924 2924
     nsections = EC16(file_hdr.NumberOfSections);
2925
-    if(nsections < 1 || nsections > 96) {
2925
+    if(nsections < 1 || nsections > PE_MAXSECTIONS) {
2926 2926
 #if HAVE_JSON
2927 2927
         pe_add_heuristic_property(ctx, "BadNumberOfSections");
2928 2928
 #endif
... ...
@@ -5083,7 +5086,7 @@ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
5083 5083
         return -1;
5084 5084
     }
5085 5085
 
5086
-    if ( (peinfo->nsections = EC16(file_hdr.NumberOfSections)) < 1 || peinfo->nsections > 96 ) return -1;
5086
+    if ( (peinfo->nsections = EC16(file_hdr.NumberOfSections)) < 1 || peinfo->nsections > PE_MAXSECTIONS ) return -1;
5087 5087
 
5088 5088
     if (EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32)) {
5089 5089
         cli_dbgmsg("SizeOfOptionalHeader too small\n");
... ...
@@ -5404,8 +5407,10 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uin
5404 5404
     struct cli_exe_section *exe_sections;
5405 5405
     struct pe_image_data_dir *dirs;
5406 5406
     fmap_t *map = *ctx->fmap;
5407
-    void *hashctx=NULL;
5408 5407
     struct pe_certificate_hdr cert_hdr;
5408
+    struct cli_mapped_region *regions;
5409
+    unsigned int nregions;
5410
+    int ret;
5409 5411
 
5410 5412
     if (flags & CL_CHECKFP_PE_FLAG_STATS)
5411 5413
         if (!(hashes))
... ...
@@ -5437,7 +5442,7 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uin
5437 5437
         return CL_EFORMAT;
5438 5438
 
5439 5439
     nsections = EC16(file_hdr.NumberOfSections);
5440
-    if(nsections < 1 || nsections > 96)
5440
+    if(nsections < 1 || nsections > PE_MAXSECTIONS)
5441 5441
         return CL_EFORMAT;
5442 5442
 
5443 5443
     // TODO the pe_image_optional_hdr32 structure includes space for all 16
... ...
@@ -5563,11 +5568,6 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uin
5563 5563
     }
5564 5564
 
5565 5565
     cli_qsort(exe_sections, nsections, sizeof(*exe_sections), sort_sects);
5566
-    hashctx = cl_hash_init("sha1");
5567
-    if (!(hashctx)) {
5568
-        if (flags & CL_CHECKFP_PE_FLAG_AUTHENTICODE)
5569
-            flags ^= CL_CHECKFP_PE_FLAG_AUTHENTICODE;
5570
-    }
5571 5566
 
5572 5567
     if (flags & CL_CHECKFP_PE_FLAG_AUTHENTICODE) {
5573 5568
         /* Check to see if we have a security section. */
... ...
@@ -5577,8 +5577,6 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uin
5577 5577
                 flags ^= CL_CHECKFP_PE_FLAG_AUTHENTICODE;
5578 5578
             } else {
5579 5579
                 free(exe_sections);
5580
-                if (hashctx)
5581
-                    cl_hash_destroy(hashctx);
5582 5580
                 return CL_BREAK;
5583 5581
             }
5584 5582
         }
... ...
@@ -5593,30 +5591,41 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uin
5593 5593
                 flags ^= CL_CHECKFP_PE_FLAG_AUTHENTICODE;
5594 5594
             } else {
5595 5595
                 free(exe_sections);
5596
-                if (hashctx)
5597
-                    cl_hash_destroy(hashctx);
5598 5596
                 return CL_EFORMAT;
5599 5597
             }
5600 5598
         }
5601 5599
     }
5602 5600
 
5603
-#define hash_chunk(where, size, isStatAble, section) \
5601
+    // We'll build a list of the regions that need to be hashed and pass it to
5602
+    // asn1_check_mscat to do hash verification there (the hash algorithm is
5603
+    // specified in the PCKS7 structure).  We need to hash up to 4 regions + the
5604
+    // data associated with each section.
5605
+    regions = (struct cli_mapped_region *) cli_calloc(nsections+4, sizeof(struct cli_mapped_region));
5606
+    if(!regions) {
5607
+        free(exe_sections);
5608
+        return CL_EMEM;
5609
+    }
5610
+    nregions = 0;
5611
+
5612
+#define hash_chunk(where, _size, isStatAble, section) \
5604 5613
     do { \
5605 5614
         const uint8_t *hptr; \
5606
-        if(!(size)) break; \
5607
-        if(!(hptr = fmap_need_off_once(map, where, size))){ \
5615
+        if(!(_size)) break; \
5616
+        if(!(hptr = fmap_need_off_once(map, where, _size))){ \
5608 5617
             free(exe_sections); \
5609
-            if (hashctx) \
5610
-                cl_hash_destroy(hashctx); \
5618
+            free(regions); \
5611 5619
             return CL_EFORMAT; \
5612 5620
         } \
5613
-        if (flags & CL_CHECKFP_PE_FLAG_AUTHENTICODE && hashctx) \
5614
-            cl_update_hash(hashctx, (void *)hptr, size); \
5621
+        if (flags & CL_CHECKFP_PE_FLAG_AUTHENTICODE) { \
5622
+            regions[nregions].ptr = hptr; \
5623
+            regions[nregions].size = _size; \
5624
+            nregions++; \
5625
+        } \
5615 5626
         if (isStatAble && flags & CL_CHECKFP_PE_FLAG_STATS) { \
5616 5627
             void *md5ctx; \
5617 5628
             md5ctx = cl_hash_init("md5"); \
5618 5629
             if (md5ctx) { \
5619
-                cl_update_hash(md5ctx, (void *)hptr, size); \
5630
+                cl_update_hash(md5ctx, (void *)hptr, _size); \
5620 5631
                 cl_finish_hash(md5ctx, hashes->sections[section].md5); \
5621 5632
             } \
5622 5633
         } \
... ...
@@ -5643,8 +5652,7 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uin
5643 5643
                 break;
5644 5644
             } else {
5645 5645
                 free(exe_sections);
5646
-                if (hashctx)
5647
-                    cl_hash_destroy(hashctx);
5646
+                free(regions);
5648 5647
                 return CL_EFORMAT;
5649 5648
             }
5650 5649
         }
... ...
@@ -5679,28 +5687,24 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uin
5679 5679
 
5680 5680
     free(exe_sections);
5681 5681
 
5682
-    if (flags & CL_CHECKFP_PE_FLAG_AUTHENTICODE && hashctx) {
5683
-        cl_finish_hash(hashctx, authsha1);
5684
-
5685
-        if(cli_debug_flag) {
5686
-            char shatxt[SHA1_HASH_SIZE*2+1];
5687
-            for(i=0; i<SHA1_HASH_SIZE; i++)
5688
-                sprintf(&shatxt[i*2], "%02x", authsha1[i]);
5689
-            cli_dbgmsg("Authenticode: %s\n", shatxt);
5690
-        }
5682
+    if (flags & CL_CHECKFP_PE_FLAG_AUTHENTICODE) {
5691 5683
 
5692 5684
         hlen = EC32(dirs[4].Size);
5693 5685
 
5694
-        if(fmap_readn(map, &cert_hdr, EC32(dirs[4].VirtualAddress), sizeof(cert_hdr)) != sizeof(cert_hdr))
5686
+        if(fmap_readn(map, &cert_hdr, EC32(dirs[4].VirtualAddress), sizeof(cert_hdr)) != sizeof(cert_hdr)) {
5687
+            free(regions);
5695 5688
             return CL_EFORMAT;
5689
+        }
5696 5690
 
5697 5691
         if (EC16(cert_hdr.revision) != WIN_CERT_REV_2) {
5698 5692
             cli_dbgmsg("cli_checkfp_pe: unsupported authenticode data revision\n");
5693
+            free(regions);
5699 5694
             return CL_VIRUS;
5700 5695
         }
5701 5696
 
5702 5697
         if (EC16(cert_hdr.type) != WIN_CERT_TYPE_PKCS7) {
5703 5698
             cli_dbgmsg("cli_checkfp_pe: unsupported authenticode data type\n");
5699
+            free(regions);
5704 5700
             return CL_VIRUS;
5705 5701
         }
5706 5702
 
... ...
@@ -5719,10 +5723,14 @@ int cli_checkfp_pe(cli_ctx *ctx, uint8_t *authsha1, stats_section_t *hashes, uin
5719 5719
         at = EC32(dirs[4].VirtualAddress) + sizeof(cert_hdr);
5720 5720
         hlen -= sizeof(cert_hdr);
5721 5721
 
5722
-        return asn1_check_mscat((struct cl_engine *)(ctx->engine), map, at, hlen, authsha1);
5722
+        ret = asn1_check_mscat((struct cl_engine *)(ctx->engine), map, at, hlen, regions, nregions);
5723
+
5724
+        free(regions);
5725
+
5726
+        return ret;
5727
+
5723 5728
     } else {
5724
-        if (hashctx)
5725
-            cl_hash_destroy(hashctx);
5729
+        free(regions);
5726 5730
         return CL_VIRUS;
5727 5731
     }
5728 5732
 }
... ...
@@ -5773,7 +5781,7 @@ int cli_genhash_pe(cli_ctx *ctx, unsigned int class, int type)
5773 5773
         return CL_EFORMAT;
5774 5774
 
5775 5775
     nsections = EC16(file_hdr.NumberOfSections);
5776
-    if(nsections < 1 || nsections > 96)
5776
+    if(nsections < 1 || nsections > PE_MAXSECTIONS)
5777 5777
         return CL_EFORMAT;
5778 5778
 
5779 5779
     if(EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32))