Browse code

Allow the countersignature to exist anywhere in unauthAttrs

The diff is confusing, but basically I moved the countersignature
verification code into it's own function and then in asn1_parse_mscat
we now loop through the unauthenticatedAttributes to find the
counterSignature attribute (instead of assuming it's the first
attribute in the list.)

We also now do time-validation in the case where an unauthAttrs
section exists but doesn't include a counterSignature

Andrew authored on 2018/09/01 06:02:51
Showing 1 changed files
... ...
@@ -873,11 +873,291 @@ static int asn1_get_x509(fmap_t *map, const void **asn1data, unsigned int *size,
873 873
     return ret;
874 874
 }
875 875
 
876
+static int asn1_parse_countersignature(fmap_t *map, const void **asn1data, unsigned int *size, crtmgr *cmgr, const uint8_t *message, const unsigned int message_size, time_t not_before, time_t not_after) {
877
+
878
+    struct cli_asn1 asn1, deep, deeper;
879
+    uint8_t issuer[SHA1_HASH_SIZE], serial[SHA1_HASH_SIZE];
880
+    const uint8_t *attrs;
881
+    unsigned int dsize, attrs_size;
882
+    unsigned int avail;
883
+    uint8_t hash[SHA256_HASH_SIZE];
884
+    cli_crt_hashtype hashtype;
885
+    unsigned int hashsize;
886
+    uint8_t md[SHA256_HASH_SIZE];
887
+    int result;
888
+    void *ctx;
889
+
890
+    do {
891
+        if(asn1_expect_objtype(map, *asn1data, size, &asn1, ASN1_TYPE_SEQUENCE)) {
892
+            cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE inside counterSignature SET\n");
893
+            break;
894
+        }
895
+
896
+        avail = asn1.size;
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");
899
+            break;
900
+        }
901
+
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");
904
+            break;
905
+        }
906
+
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");
909
+            break;
910
+        }
911
+        // Compute the hash of the issuer section
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");
914
+            break;
915
+        }
916
+
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");
919
+            break;
920
+        }
921
+
922
+        // Compute the hash of the serial INTEGER
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");
925
+            break;
926
+        }
927
+
928
+        if(asn1.size) {
929
+            cli_dbgmsg("asn1_parse_mscat: extra data inside counterSignature issuer\n");
930
+            break;
931
+        }
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");
947
+            break;
948
+        }
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");
973
+            break;
974
+        }
975
+
976
+        attrs = asn1.next;
977
+        if(asn1_expect_objtype(map, asn1.next, &avail, &asn1, 0xa0)) { /* authenticatedAttributes */
978
+            cli_dbgmsg("asn1_parse_mscat: unable to parse counterSignature authenticatedAttributes section\n");
979
+            break;
980
+        }
981
+        attrs_size = (uint8_t *)(asn1.next) - attrs;
982
+        if(asn1.next == NULL && attrs_size < 2) {
983
+            cli_dbgmsg("asn1_parse_mscat: counterSignature authenticatedAttributes are too small\n");
984
+            break;
985
+        }
986
+        result = 0;
987
+        dsize = asn1.size;
988
+        deep.next = asn1.content;
989
+        while(dsize) {
990
+            int content;
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");
993
+                dsize = 1;
994
+                break;
995
+            }
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");
998
+                dsize = 1;
999
+                break;
1000
+            }
1001
+            if(deeper.size != lenof(OID_contentType)) /* lenof(contentType) = lenof(messageDigest) = lenof(signingTime) = 9 */
1002
+                continue;
1003
+
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");
1006
+                dsize = 1;
1007
+                break;
1008
+            }
1009
+            if(!memcmp(deeper.content, OID_contentType, lenof(OID_contentType)))
1010
+                content = 0; /* contentType */
1011
+            else if(!memcmp(deeper.content, OID_messageDigest, lenof(OID_messageDigest)))
1012
+                content = 1; /* messageDigest */
1013
+            else if(!memcmp(deeper.content, OID_signingTime, lenof(OID_signingTime)))
1014
+                content = 2; /* signingTime */
1015
+            else
1016
+                continue;
1017
+            if(result & (1<<content)) {
1018
+                cli_dbgmsg("asn1_parse_mscat: duplicate field in countersignature\n");
1019
+                dsize = 1;
1020
+                break;
1021
+            }
1022
+            result |= (1<<content);
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");
1025
+                dsize = 1;
1026
+                break;
1027
+            }
1028
+            if(deep.size) {
1029
+                cli_dbgmsg("asn1_parse_mscat: extra data in countersignature value\n");
1030
+                dsize = 1;
1031
+                break;
1032
+            }
1033
+            deep.size = deeper.size;
1034
+            switch(content) {
1035
+            case 0:  /* contentType = pkcs7-data */
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");
1038
+                    deep.size = 1;
1039
+                } else if(deep.size)
1040
+                    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature content-type\n");
1041
+                break;
1042
+            case 1:  /* messageDigest */
1043
+                if(asn1_expect_obj(map, &deeper.content, &deep.size, ASN1_TYPE_OCTET_STRING, hashsize, md)) {
1044
+                    deep.size = 1;
1045
+                    cli_dbgmsg("asn1_parse_mscat: countersignature hash mismatch\n");
1046
+                } else if(deep.size)
1047
+                    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature message-digest\n");
1048
+                break;
1049
+            case 2:  /* signingTime */
1050
+                {
1051
+                    time_t sigdate; /* FIXME shall i use it?! */
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");
1054
+                        deep.size = 1;
1055
+                    } else if(deep.size)
1056
+                        cli_dbgmsg("asn1_parse_mscat: extra data in countersignature signing-time\n");
1057
+                    else if(sigdate < not_before || sigdate > not_after) {
1058
+                        cli_dbgmsg("asn1_parse_mscat: countersignature timestamp outside cert validity\n");
1059
+                        deep.size = 1;
1060
+                    }
1061
+                    break;
1062
+                }
1063
+            }
1064
+            if(deep.size) {
1065
+                dsize = 1;
1066
+                break;
1067
+            }
1068
+        }
1069
+        if(dsize)
1070
+            break;
1071
+        if(result != 7) {
1072
+            cli_dbgmsg("asn1_parse_mscat: some important attributes are missing in countersignature\n");
1073
+            break;
1074
+        }
1075
+
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");
1078
+            break;
1079
+        }
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");
1082
+            break;
1083
+        }
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");
1086
+            break;
1087
+        }
1088
+        if(!fmap_need_ptr_once(map, deep.content, lenof(OID_rsaEncryption))) {
1089
+            cli_dbgmsg("asn1_parse_mscat: cannot read digestEncryptionAlgorithm in countersignature\n");
1090
+            break;
1091
+        }
1092
+        /* rsaEncryption or sha1withRSAEncryption */
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");
1095
+            break;
1096
+        }
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");
1099
+            break;
1100
+        }
1101
+        if(asn1.size) {
1102
+            cli_dbgmsg("asn1_parse_mscat: extra data in digestEncryptionAlgorithm in countersignature\n");
1103
+            break;
1104
+        }
1105
+
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");
1108
+            break;
1109
+        }
1110
+        if(asn1.size > 513) {
1111
+            cli_dbgmsg("asn1_parse_mscat: countersignature encryptedDigest too long\n");
1112
+            break;
1113
+        }
1114
+        if(avail) {
1115
+            cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature\n");
1116
+            break;
1117
+        }
1118
+        if(!fmap_need_ptr_once(map, attrs, attrs_size)) {
1119
+            cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n");
1120
+            break;
1121
+        }
1122
+
1123
+        if(hashtype == CLI_SHA1RSA) {
1124
+            ctx = cl_hash_init("sha1");
1125
+        } else if (hashtype == CLI_MD5RSA) {
1126
+            ctx = cl_hash_init("md5");
1127
+        } else {
1128
+            break;
1129
+        }
1130
+
1131
+        if (!(ctx))
1132
+            break;
1133
+
1134
+        cl_update_hash(ctx, "\x31", 1);
1135
+        cl_update_hash(ctx, (void *)(attrs + 1), attrs_size - 1);
1136
+        cl_finish_hash(ctx, hash);
1137
+
1138
+        if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) {
1139
+            cli_dbgmsg("asn1_parse_mscat: failed to read countersignature encryptedDigest\n");
1140
+            break;
1141
+        }
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");
1144
+            break;
1145
+        }
1146
+
1147
+        cli_dbgmsg("asn1_parse_mscat: countersignature verification completed successfully\n");
1148
+
1149
+        return 0;
1150
+
1151
+    } while(0);
1152
+
1153
+    return 1;
1154
+}
1155
+
876 1156
 static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmgr *cmgr, int embedded, const void **hashes, unsigned int *hashes_size, struct cl_engine *engine) {
877 1157
     struct cli_asn1 asn1, deep, deeper;
878 1158
     uint8_t issuer[SHA1_HASH_SIZE], serial[SHA1_HASH_SIZE];
879
-    const uint8_t *message, *attrs, *nested;
880
-    unsigned int dsize, message_size, attrs_size, nested_size;
1159
+    const uint8_t *message, *attrs;
1160
+    unsigned int dsize, message_size, attrs_size;
881 1161
     // hash is used to hold the hashes we compute as part of sig verification
882 1162
     uint8_t hash[SHA256_HASH_SIZE];
883 1163
     cli_crt_hashtype hashtype;
... ...
@@ -929,6 +1209,7 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg
929 929
             cli_dbgmsg("asn1_parse_mscat: found extra data in signedData\n");
930 930
             break;
931 931
         }
932
+
932 933
         size = asn1.size;
933 934
         if(asn1_expect_obj(map, &asn1.content, &size, ASN1_TYPE_INTEGER, 1, "\x01")){ /* INTEGER - VERSION 1 */
934 935
             cli_dbgmsg("asn1_parse_mscat: expected 'INTEGER - VERSION 1' for signedData version\n");
... ...
@@ -1473,18 +1754,16 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg
1473 1473
         if(!size) {
1474 1474
             time_t now;
1475 1475
 
1476
-            cli_dbgmsg("asn1_parse_mscat: unauthenticatedAttributes section is missing\n");
1477
-
1478 1476
             // No countersignature, so judge validity based on time
1479 1477
             now = time(NULL);
1480 1478
 
1481 1479
             if(now < x509->not_before || now > x509->not_after) {
1482
-                cli_dbgmsg("asn1_parse_mscat: no countersignature and signing certificate has expired\n");
1480
+                cli_dbgmsg("asn1_parse_mscat: no countersignature (unauthAttrs missing) and signing certificate has expired\n");
1483 1481
                 break;
1484 1482
             }
1485 1483
 
1486
-            cli_dbgmsg("asn1_parse_mscat: no countersignature but the signing certificate is still valid\n");
1487
-            return 0;
1484
+            cli_dbgmsg("asn1_parse_mscat: no countersignature (unauthAttrs missing) but the signing certificate is still valid\n");
1485
+            goto finish;
1488 1486
         }
1489 1487
 
1490 1488
         if(size && asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa1)) { /* unauthenticatedAttributes */
... ...
@@ -1497,320 +1776,110 @@ static int asn1_parse_mscat(fmap_t *map, size_t offset, unsigned int size, crtmg
1497 1497
             break;
1498 1498
         }
1499 1499
 
1500
-        size = asn1.size;
1501
-        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, ASN1_TYPE_SEQUENCE)) {
1502
-            cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE in unauthenticated data section\n");
1503
-            break;
1504
-        }
1505
-
1506
-        /* Older authenticode sigs only contain one SEQUENCE in the unauth
1507
-         * attribs section, but newer ones can have an additional one
1508
-         * containing nested signatures.  Save off a pointer to the
1509
-         * additional SEQUENCE, if present, so we can parse it after we
1510
-         * verify the counter signature. */
1511
-        nested = asn1.next;
1512
-        nested_size = size;
1513
-
1514
-        size = asn1.size;
1515
-        /* 1.2.840.113549.1.9.6 - counterSignature */
1516
-        if(asn1_expect_obj(map, &asn1.content, &size, ASN1_TYPE_OBJECT_ID, lenof(OID_countersignature), OID_countersignature)) {
1517
-            cli_dbgmsg("asn1_parse_mscat: expected countersignature OID in the first unauthenticatedAttributes SEQUENCE\n");
1518
-            break;
1519
-        }
1520
-        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, ASN1_TYPE_SET)) {
1521
-            cli_dbgmsg("asn1_parse_mscat: expected SET following counterSignature OID\n");
1522
-            break;
1523
-        }
1524
-        if(size) {
1525
-            cli_dbgmsg("asn1_parse_mscat: extra data inside counterSignature SEQUENCE\n");
1526
-            break;
1527
-        }
1528
-
1529
-        size = asn1.size;
1530
-        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, ASN1_TYPE_SEQUENCE)) {
1531
-            cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE inside counterSignature SET\n");
1532
-            break;
1533
-        }
1534
-        if(size) {
1535
-            cli_dbgmsg("asn1_parse_mscat: extra data inside counterSignature SET\n");
1536
-            break;
1537
-        }
1538
-
1539
-        size = asn1.size;
1540
-        if(asn1_expect_obj(map, &asn1.content, &size, ASN1_TYPE_INTEGER, 1, "\x01")) { /* Version = 1*/
1541
-            cli_dbgmsg("asn1_parse_mscat: expected counterSignature version to be 1\n");
1542
-            break;
1543
-        }
1544
-
1545
-        if(asn1_expect_objtype(map, asn1.content, &size, &asn1, ASN1_TYPE_SEQUENCE)) { /* issuerAndSerialNumber */
1546
-            cli_dbgmsg("asn1_parse_mscat: unable to parse issuerAndSerialNumber SEQUENCE in counterSignature\n");
1547
-            break;
1548
-        }
1549
-
1550
-        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, ASN1_TYPE_SEQUENCE)) { /* issuer */
1551
-            cli_dbgmsg("asn1_parse_mscat: unable to parse issuer SEQUENCE in counterSignature\n");
1552
-            break;
1553
-        }
1554
-        // Compute the hash of the issuer section
1555
-        if(map_sha1(map, deep.content, deep.size, issuer)) {
1556
-            cli_dbgmsg("asn1_parse_mscat: error in call to map_sha1 for counterSignature issuer\n");
1557
-            break;
1558
-        }
1559
-
1560
-        if(asn1_expect_objtype(map, deep.next, &asn1.size, &deep, ASN1_TYPE_INTEGER)) { /* serial */
1561
-            cli_dbgmsg("asn1_parse_mscat: expected ASN1_TYPE_INTEGER serial for counterSignature\n");
1562
-            break;
1563
-        }
1564
-
1565
-        // Compute the hash of the serial INTEGER
1566
-        if(map_sha1(map, deep.content, deep.size, serial)) {
1567
-            cli_dbgmsg("asn1_parse_mscat: error in call to map_sha1 for counterSignature serial\n");
1568
-            break;
1569
-        }
1570
-
1571
-        if(asn1.size) {
1572
-            cli_dbgmsg("asn1_parse_mscat: extra data inside counterSignature issuer\n");
1573
-            break;
1574
-        }
1575
-
1576
-        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, ASN1_TYPE_SEQUENCE)) { /* digestAlgorithm */
1577
-            cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE to start digestAlgorithm counterSignature section\n");
1578
-            break;
1579
-        }
1580
-        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, ASN1_TYPE_OBJECT_ID)) {
1581
-            cli_dbgmsg("asn1_parse_mscat: unexpected value when parsing counterSignature\n");
1582
-            break;
1583
-        }
1584
-        if(deep.size != lenof(OID_sha1) && deep.size != lenof(OID_md5)) {
1585
-            cli_dbgmsg("asn1_parse_mscat: wrong digestAlgorithm size in counterSignature\n");
1586
-            break;
1587
-        }
1588
-        if(!fmap_need_ptr_once(map, deep.content, deep.size)) {
1589
-            cli_dbgmsg("asn1_parse_mscat: failed to read digestAlgorithm OID\n");
1590
-            break;
1591
-        }
1592
-        if(deep.size == lenof(OID_sha1) && !memcmp(deep.content, OID_sha1, lenof(OID_sha1))) {
1593
-            hashtype = CLI_SHA1RSA;
1594
-            hashsize = SHA1_HASH_SIZE;
1595
-            if(map_sha1(map, message, message_size, md)) {
1596
-                cli_dbgmsg("asn1_parse_mscat: map_sha1 for counterSignature verification failed\n");
1597
-                break;
1598
-            }
1599
-        } else if(deep.size == lenof(OID_md5) && !memcmp(deep.content, OID_md5, lenof(OID_md5))) {
1600
-            hashtype = CLI_MD5RSA;
1601
-            hashsize = MD5_HASH_SIZE;
1602
-            if(map_md5(map, message, message_size, md)) {
1603
-                cli_dbgmsg("asn1_parse_mscat: map_md5 for counterSignature verification failed\n");
1604
-                break;
1605
-            }
1606
-        } else {
1607
-            cli_dbgmsg("asn1_parse_mscat: unknown digest OID in counterSignature\n");
1608
-            break;
1609
-        }
1610
-        if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, ASN1_TYPE_NULL, 0, NULL)) {
1611
-            cli_dbgmsg("asn1_parse_mscat: unexpected value after counterSignature digestAlgorithm\n");
1612
-            break;
1613
-        }
1614
-        if(asn1.size) {
1615
-            cli_dbgmsg("asn1_parse_mscat: extra data in counterSignature OID\n");
1616
-            break;
1617
-        }
1500
+        // Parse the unauthenticated attributes
1618 1501
 
1619
-        attrs = asn1.next;
1620
-        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) { /* authenticatedAttributes */
1621
-            cli_dbgmsg("asn1_parse_mscat: unable to parse counterSignature authenticatedAttributes section\n");
1622
-            break;
1623
-        }
1624
-        attrs_size = (uint8_t *)(asn1.next) - attrs;
1625
-        if(asn1.next == NULL && attrs_size < 2) {
1626
-            cli_dbgmsg("asn1_parse_mscat: counterSignature authenticatedAttributes are too small\n");
1627
-            break;
1628
-        }
1629
-        result = 0;
1630 1502
         dsize = asn1.size;
1631 1503
         deep.next = asn1.content;
1504
+        result = 0;
1632 1505
         while(dsize) {
1506
+            struct cli_asn1 cobj;
1633 1507
             int content;
1634
-            if(asn1_expect_objtype(map, deep.next, &dsize, &deep, ASN1_TYPE_SEQUENCE)) { /* attribute */
1635
-                cli_dbgmsg("asn1_parse_mscat: expected counterSignature attribute SEQUENCE\n");
1508
+            if(asn1_expect_objtype(map, deep.next, &dsize, &deep, ASN1_TYPE_SEQUENCE)) {
1509
+                cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE starting an unauthenticatedAttribute\n");
1636 1510
                 dsize = 1;
1637 1511
                 break;
1638 1512
             }
1639
-            if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, ASN1_TYPE_OBJECT_ID)) { /* attribute type */
1640
-                cli_dbgmsg("asn1_parse_mscat: expected attribute type inside counterSignature attribute SEQUENCE\n");
1513
+            if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, ASN1_TYPE_OBJECT_ID)) {
1514
+                cli_dbgmsg("asn1_parse_mscat: expected OID inside unauthenticatedAttribute SEQUENCE\n");
1641 1515
                 dsize = 1;
1642 1516
                 break;
1643 1517
             }
1644
-            if(deeper.size != lenof(OID_contentType)) /* lenof(contentType) = lenof(messageDigest) = lenof(signingTime) = 9 */
1518
+            // Supported OIDs include:
1519
+            // - 1.2.840.113549.1.9.6 - counterSignature
1520
+            // - 1.3.6.1.4.1.311.2.4.1 - nested signatures
1521
+
1522
+            // I've seen some other ones like 1.3.6.1.4.1.3845.3.9876.1.1.1,
1523
+            // and the presence of those doesn't seem to mess up verification
1524
+            // through the Windows API, so just skip those
1525
+
1526
+            if(deeper.size != lenof(OID_countersignature) && deeper.size != lenof(OID_nestedSignatures)) {
1645 1527
                 continue;
1528
+            }
1646 1529
 
1647
-            if(!fmap_need_ptr_once(map, deeper.content, lenof(OID_contentType))) {
1648
-                cli_dbgmsg("asn1_parse_mscat: failed to read counterSignature authenticated attribute\n");
1530
+            if(!fmap_need_ptr_once(map, deeper.content, deeper.size)) {
1531
+                cli_dbgmsg("asn1_parse_mscat: failed to read unauthenticated attribute OID\n");
1649 1532
                 dsize = 1;
1650 1533
                 break;
1651 1534
             }
1652
-            if(!memcmp(deeper.content, OID_contentType, lenof(OID_contentType)))
1653
-                content = 0; /* contentType */
1654
-            else if(!memcmp(deeper.content, OID_messageDigest, lenof(OID_messageDigest)))
1655
-                content = 1; /* messageDigest */
1656
-            else if(!memcmp(deeper.content, OID_signingTime, lenof(OID_signingTime)))
1657
-                content = 2; /* signingTime */
1658
-            else
1535
+
1536
+            if(!memcmp(deeper.content, OID_countersignature, deeper.size))
1537
+                content = 0; /* counterSignature */
1538
+            else if(!memcmp(deeper.content, OID_nestedSignatures, deeper.size))
1539
+                content = 1; /* nested */
1540
+            else {
1659 1541
                 continue;
1660
-            if(result & (1<<content)) {
1661
-                cli_dbgmsg("asn1_parse_mscat: duplicate field in countersignature\n");
1662
-                dsize = 1;
1663
-                break;
1664 1542
             }
1665
-            result |= (1<<content);
1543
+
1666 1544
             if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, ASN1_TYPE_SET)) { /* set - contents */
1667
-                cli_dbgmsg("asn1_parse_mscat: failed to read counterSignature authenticated attribute\n");
1545
+                cli_dbgmsg("asn1_parse_mscat: expected 'set - contents' inside unauthenticated attribute\n");
1668 1546
                 dsize = 1;
1669 1547
                 break;
1670 1548
             }
1671 1549
             if(deep.size) {
1672
-                cli_dbgmsg("asn1_parse_mscat: extra data in countersignature value\n");
1550
+                cli_dbgmsg("asn1_parse_mscat: extra data in unauthenticated attribute\n");
1673 1551
                 dsize = 1;
1674 1552
                 break;
1675 1553
             }
1676
-            deep.size = deeper.size;
1677
-            switch(content) {
1678
-            case 0:  /* contentType = pkcs7-data */
1679
-                if(asn1_expect_obj(map, &deeper.content, &deep.size, ASN1_TYPE_OBJECT_ID, lenof(OID_pkcs7_data), OID_pkcs7_data)) {
1680
-                    cli_dbgmsg("asn1_parse_mscat: contentType != pkcs7-data\n");
1681
-                    deep.size = 1;
1682
-                } else if(deep.size)
1683
-                    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature content-type\n");
1684
-                break;
1685
-            case 1:  /* messageDigest */
1686
-                if(asn1_expect_obj(map, &deeper.content, &deep.size, ASN1_TYPE_OCTET_STRING, hashsize, md)) {
1687
-                    deep.size = 1;
1688
-                    cli_dbgmsg("asn1_parse_mscat: countersignature hash mismatch\n");
1689
-                } else if(deep.size)
1690
-                    cli_dbgmsg("asn1_parse_mscat: extra data in countersignature message-digest\n");
1691
-                break;
1692
-            case 2:  /* signingTime */
1693
-                {
1694
-                    time_t sigdate; /* FIXME shall i use it?! */
1695
-                    if(asn1_get_time(map, &deeper.content, &deep.size, &sigdate)) {
1696
-                        cli_dbgmsg("asn1_parse_mscat: an error occurred when getting the time\n");
1697
-                        deep.size = 1;
1698
-                    } else if(deep.size)
1699
-                        cli_dbgmsg("asn1_parse_mscat: extra data in countersignature signing-time\n");
1700
-                    else if(sigdate < x509->not_before || sigdate > x509->not_after) {
1701
-                        cli_dbgmsg("asn1_parse_mscat: countersignature timestamp outside cert validity\n");
1702
-                        deep.size = 1;
1703
-                    }
1704
-                    break;
1705
-                }
1706
-            }
1707
-            if(deep.size) {
1554
+
1555
+            if(result & (1<<content)) {
1556
+                cli_dbgmsg("asn1_parse_mscat: counterSignature or nestedSignature appear twice\n");
1708 1557
                 dsize = 1;
1709 1558
                 break;
1710 1559
             }
1711
-        }
1712
-        if(dsize)
1713
-            break;
1714
-        if(result != 7) {
1715
-            cli_dbgmsg("asn1_parse_mscat: some important attributes are missing in countersignature\n");
1716
-            break;
1717
-        }
1718 1560
 
1719
-        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, ASN1_TYPE_SEQUENCE)) { /* digestEncryptionAlgorithm == sha1 */
1720
-            cli_dbgmsg("asn1_parse_mscat: expected to parse SEQUENCE after counterSignature attributes\n");
1721
-            break;
1722
-        }
1723
-        if(asn1_expect_objtype(map, asn1.content, &asn1.size, &deep, ASN1_TYPE_OBJECT_ID)) {/* digestEncryptionAlgorithm == sha1 */
1724
-            cli_dbgmsg("asn1_parse_mscat: unexpected value when parsing counterSignature digestEncryptionAlgorithm\n");
1725
-            break;
1726
-        }
1727
-        if(deep.size != lenof(OID_rsaEncryption)) { /* lenof(OID_rsaEncryption) = lenof(OID_sha1WithRSAEncryption) = 9 */
1728
-            cli_dbgmsg("asn1_parse_mscat: wrong digestEncryptionAlgorithm size in countersignature\n");
1729
-            break;
1730
-        }
1731
-        if(!fmap_need_ptr_once(map, deep.content, lenof(OID_rsaEncryption))) {
1732
-            cli_dbgmsg("asn1_parse_mscat: cannot read digestEncryptionAlgorithm in countersignature\n");
1733
-            break;
1734
-        }
1735
-        /* rsaEncryption or sha1withRSAEncryption */
1736
-        if(memcmp(deep.content, OID_rsaEncryption, lenof(OID_rsaEncryption)) && memcmp(deep.content, OID_sha1WithRSAEncryption, lenof(OID_sha1WithRSAEncryption))) {
1737
-            cli_dbgmsg("asn1_parse_mscat: digestEncryptionAlgorithm in countersignature is not sha1\n");
1738
-            break;
1739
-        }
1740
-        if(asn1.size && asn1_expect_obj(map, &deep.next, &asn1.size, ASN1_TYPE_NULL, 0, NULL)) {
1741
-            cli_dbgmsg("asn1_parse_mscat: unexpected value after counterSignature digestEncryptionAlgorithm\n");
1742
-            break;
1743
-        }
1744
-        if(asn1.size) {
1745
-            cli_dbgmsg("asn1_parse_mscat: extra data in digestEncryptionAlgorithm in countersignature\n");
1746
-            break;
1747
-        }
1561
+            if(content == 0) { /* counterSignature */
1748 1562
 
1749
-        if(asn1_expect_objtype(map, asn1.next, &size, &asn1, ASN1_TYPE_OCTET_STRING)) { /* encryptedDigest */
1750
-            cli_dbgmsg("asn1_parse_mscat: unexpected encryptedDigest value in counterSignature\n");
1751
-            break;
1752
-        }
1753
-        if(asn1.size > 513) {
1754
-            cli_dbgmsg("asn1_parse_mscat: countersignature encryptedDigest too long\n");
1755
-            break;
1756
-        }
1757
-        if(size) {
1758
-            cli_dbgmsg("asn1_parse_mscat: extra data inside countersignature\n");
1759
-            break;
1760
-        }
1761
-        if(!fmap_need_ptr_once(map, attrs, attrs_size)) {
1762
-            cli_dbgmsg("asn1_parse_mscat: failed to read authenticatedAttributes\n");
1763
-            break;
1764
-        }
1563
+                if(asn1_parse_countersignature(map, &deeper.content, &deeper.size, cmgr, message, message_size, x509->not_before, x509->not_after)) {
1564
+                    dsize = 1;
1565
+                    break;
1566
+                }
1765 1567
 
1766
-        if(hashtype == CLI_SHA1RSA) {
1767
-            ctx = cl_hash_init("sha1");
1768
-        } else if (hashtype == CLI_MD5RSA) {
1769
-            ctx = cl_hash_init("md5");
1770
-        } else {
1771
-            break;
1772
-        }
1568
+                result |= 1;
1773 1569
 
1774
-        if (!(ctx))
1775
-            break;
1570
+            } else { /* nestedSignature */
1776 1571
 
1777
-        cl_update_hash(ctx, "\x31", 1);
1778
-        cl_update_hash(ctx, (void *)(attrs + 1), attrs_size - 1);
1779
-        cl_finish_hash(ctx, hash);
1572
+                // TODO Support parsing these out in the future
1573
+                cli_dbgmsg("asn1_parse_mscat: nested signatures detected but parsing them is not currently supported\n");
1780 1574
 
1781
-        if(!fmap_need_ptr_once(map, asn1.content, asn1.size)) {
1782
-            cli_dbgmsg("asn1_parse_mscat: failed to read countersignature encryptedDigest\n");
1783
-            break;
1575
+                deeper.size = 0;
1576
+                result |= 2;
1577
+            }
1578
+            if(deeper.size) {
1579
+                cli_dbgmsg("asn1_parse_mscat: extra data in unauthenticated attribute\n");
1580
+                dsize = 1;
1581
+                break;
1582
+            }
1784 1583
         }
1785
-        if(!crtmgr_verify_pkcs7(cmgr, issuer, serial, asn1.content, asn1.size, hashtype, hash, VRFY_TIME)) {
1786
-            cli_dbgmsg("asn1_parse_mscat: pkcs7 countersignature verification failed\n");
1584
+        if(dsize)
1787 1585
             break;
1788
-        }
1789
-
1790
-        if(nested) {
1791 1586
 
1792
-            if (asn1_expect_objtype(map, nested, &nested_size, &asn1, ASN1_TYPE_SEQUENCE)) {
1793
-                cli_dbgmsg("asn1_parse_mscat: expected SEQUENCE in unauthenticatedAttributes following the counterSignature\n");
1794
-                break;
1795
-            }
1587
+        if (2 != (result & 2)) {
1588
+            time_t now;
1796 1589
 
1797
-            if (nested_size) {
1798
-                cli_dbgmsg("asn1_parse_mscat: extra data inside unauthenticatedAttributes\n");
1799
-                break;
1800
-            }
1590
+            // No countersignature, so judge validity based on time
1591
+            now = time(NULL);
1801 1592
 
1802
-            /* 1.3.6.1.4.1.311.2.4.1 - nested signatures */
1803
-            if(asn1_expect_obj(map, &asn1.content, &asn1.size, ASN1_TYPE_OBJECT_ID, lenof(OID_nestedSignatures), OID_nestedSignatures)) {
1804
-                cli_dbgmsg("asn1_parse_mscat: expected nested signature OID in the second unauthenticatedAttributes SEQUENCE\n");
1593
+            if(now < x509->not_before || now > x509->not_after) {
1594
+                cli_dbgmsg("asn1_parse_mscat: no countersignature and signing certificate has expired\n");
1805 1595
                 break;
1806 1596
             }
1807 1597
 
1808
-            // TODO Support parsing these out in the future
1809
-            cli_dbgmsg("asn1_parse_mscat: nested signatures detected but parsing them is not currently supported\n");
1598
+            cli_dbgmsg("asn1_parse_mscat: no countersignature but the signing certificate is still valid\n");
1810 1599
         }
1811 1600
 
1812 1601
         cli_dbgmsg("asn1_parse_mscat: unauthenticatedAttributes successfully parsed\n");
1813 1602
 
1603
+finish:
1814 1604
         if (isBlacklisted) {
1815 1605
             return 1;
1816 1606
         }