... | ... |
@@ -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)) |