]> git.cameronkatri.com Git - trustcache.git/commitdiff
Add support for new version 2 trustcaches main
authorCameron Katri <me@cameronkatri.com>
Thu, 16 Jun 2022 14:17:00 +0000 (10:17 -0400)
committerCameron Katri <me@cameronkatri.com>
Thu, 16 Jun 2022 14:21:50 +0000 (10:21 -0400)
Thanks to Linus Henze for reversing the new format
https://gist.github.com/LinusHenze/4cd5d7ef057a144cda7234e2c247c056

.gitignore
README.txt
append.c
cache_from_tree.c
create.c
info.c
remove.c
trustcache.1
trustcache.c
trustcache.h

index 2ee8367d53752f7be5a152cd55e6e4923e6e9845..9e8345a3981c9b58814dd201e455e564b15e8398 100644 (file)
@@ -3,3 +3,5 @@ a.out
 *.bin
 trustcache
 .vscode
 *.bin
 trustcache
 .vscode
+*.tc
+linux-sysroot
index 12da2b39b47443b5a78f906b0f22239de216a1b7..3f81ef88afdb221fc964922ecfbdf65a2a846be5 100644 (file)
@@ -28,15 +28,16 @@ DESCRIPTION
              Create a trustcache at outfile.  Each Mach-O found in the
              specified inputs will be scanned for a code signature and hashed.
              Any malformed or unsigned Mach-O will be ignored.  Each slice of
              Create a trustcache at outfile.  Each Mach-O found in the
              specified inputs will be scanned for a code signature and hashed.
              Any malformed or unsigned Mach-O will be ignored.  Each slice of
-             a FAT binary will have its hash included.  Versions 0 and 1 are
-             supported, if not specified, 1 is assumed.  If uuid is specified,
-             that will be used instead of a randomly generated one.
+             a FAT binary will have its hash included.  Versions 0, 1, and 2
+             are supported, if not specified, 1 is assumed.  If uuid is
+             specified, that will be used instead of a randomly generated one.
 
      info [-c] [-h] [-e entrynum] file
              Print information about file.  The output for each hash will be
 
      info [-c] [-h] [-e entrynum] file
              Print information about file.  The output for each hash will be
-             in the format:
+             in one of these formats:
 
                    <cdhash> <flags> [<hash_type>]
 
                    <cdhash> <flags> [<hash_type>]
+                   <cdhash> <flags> [<hash_type>] [<category>]
 
              If the -c is given, only the hashes will be printed.  If -h is
              given, only the header will be printed.  If entrynum is
 
              If the -c is given, only the hashes will be printed.  If -h is
              given, only the header will be printed.  If entrynum is
@@ -57,4 +58,4 @@ HISTORY
      The trustcache utility was written by Cameron Katri
      <me@cameronkatri.com>.
 
      The trustcache utility was written by Cameron Katri
      <me@cameronkatri.com>.
 
-FreeBSD 14.0-CURRENT             May 19, 2022             FreeBSD 14.0-CURRENT
+FreeBSD 14.0-CURRENT             June 16, 2022            FreeBSD 14.0-CURRENT
index 5bc468d9146e4155f9d78a105650384ca237d3c8..fc0cb85e41873de94fd6e3924239868ff624990c 100644 (file)
--- a/append.c
+++ b/append.c
@@ -54,9 +54,10 @@ tcappend(int argc, char **argv)
        uuid_t uuid;
        const char *errstr = NULL;
        uint8_t flags = 0;
        uuid_t uuid;
        const char *errstr = NULL;
        uint8_t flags = 0;
+       uint16_t category = 0;
 
        int ch;
 
        int ch;
-       while ((ch = getopt(argc, argv, "u:f:")) != -1) {
+       while ((ch = getopt(argc, argv, "u:f:c:")) != -1) {
                switch (ch) {
                        case 'u':
                                if (strlen(optarg) == 1 && *optarg == '0') {
                switch (ch) {
                        case 'u':
                                if (strlen(optarg) == 1 && *optarg == '0') {
@@ -75,6 +76,13 @@ tcappend(int argc, char **argv)
                                        exit(1);
                                }
                                break;
                                        exit(1);
                                }
                                break;
+                       case 'c':
+                               category = strtonum(optarg, 0, UINT16_MAX, &errstr);
+                               if (errstr != NULL) {
+                                       fprintf(stderr, "category number is %s: %s\n", errstr, optarg);
+                                       exit(1);
+                               }
+                               break;
                }
        }
 
                }
        }
 
@@ -98,10 +106,14 @@ tcappend(int argc, char **argv)
                                append.hashes = calloc(1, sizeof(trust_cache_hash0));
                                for (size_t j = 0; j < CS_CDHASH_LEN; j++)
                                        sscanf(argv[i] + 2 * j, "%02hhx", &append.hashes[0][j]);
                                append.hashes = calloc(1, sizeof(trust_cache_hash0));
                                for (size_t j = 0; j < CS_CDHASH_LEN; j++)
                                        sscanf(argv[i] + 2 * j, "%02hhx", &append.hashes[0][j]);
-                       } else {
+                       } else if (append.version == 1) {
                                append.entries = calloc(1, sizeof(struct trust_cache_entry1));
                                for (size_t j = 0; j < CS_CDHASH_LEN; j++)
                                        sscanf(argv[i] + 2 * j, "%02hhx", &append.entries[0].cdhash[j]);
                                append.entries = calloc(1, sizeof(struct trust_cache_entry1));
                                for (size_t j = 0; j < CS_CDHASH_LEN; j++)
                                        sscanf(argv[i] + 2 * j, "%02hhx", &append.entries[0].cdhash[j]);
+                       } else if (append.version == 2) {
+                               append.entries2 = calloc(1, sizeof(struct trust_cache_entry2));
+                               for (size_t j = 0; j < CS_CDHASH_LEN; j++)
+                                       sscanf(argv[i] + 2 * j, "%02hhx", &append.entries2[0].cdhash[j]);
                        }
                } else {
                        append = cache_from_tree(argv[i], cache.version);
                        }
                } else {
                        append = cache_from_tree(argv[i], cache.version);
@@ -122,15 +134,27 @@ tcappend(int argc, char **argv)
                                cache.entries[cache.num_entries + j].flags = flags != 0 ? flags : append.entries[j].flags;
                                memcpy(cache.entries[cache.num_entries + j].cdhash, append.entries[j].cdhash, CS_CDHASH_LEN);
                        }
                                cache.entries[cache.num_entries + j].flags = flags != 0 ? flags : append.entries[j].flags;
                                memcpy(cache.entries[cache.num_entries + j].cdhash, append.entries[j].cdhash, CS_CDHASH_LEN);
                        }
+               } else if (append.version == 2) {
+                       if ((cache.entries2 = realloc(cache.entries, sizeof(struct trust_cache_entry2) *
+                                                       (cache.num_entries + append.num_entries))) == NULL)
+                               exit(1);
+                       for (uint32_t j = 0; j < append.num_entries; j++) {
+                               cache.entries2[cache.num_entries + j].hash_type = append.entries[j].hash_type;
+                               cache.entries2[cache.num_entries + j].flags = flags != 0 ? flags : append.entries[j].flags;
+                               cache.entries2[cache.num_entries + j].category = category != 0 ? category : append.entries2[j].category;
+                               memcpy(cache.entries2[cache.num_entries + j].cdhash, append.entries2[j].cdhash, CS_CDHASH_LEN);
+                       }
                }
                free(append.hashes);
                cache.num_entries += append.num_entries;
        }
 
                }
                free(append.hashes);
                cache.num_entries += append.num_entries;
        }
 
-       if (cache.version == 1)
-               qsort(cache.entries, cache.num_entries, sizeof(*cache.entries), ent_cmp);
-       else if (cache.version == 0)
+       if (cache.version == 0)
                qsort(cache.hashes, cache.num_entries, sizeof(*cache.hashes), hash_cmp);
                qsort(cache.hashes, cache.num_entries, sizeof(*cache.hashes), hash_cmp);
+       else if (cache.version == 1)
+               qsort(cache.entries, cache.num_entries, sizeof(*cache.entries), ent_cmp);
+       else if (cache.version == 2)
+               qsort(cache.entries, cache.num_entries, sizeof(*cache.entries2), ent_cmp);
 
        switch (keepuuid) {
                case 0:
 
        switch (keepuuid) {
                case 0:
index 610653c7743c4e0fe4e992ec0e03e2399709c6d0..723fbac3b85f83e4d09d1294f9b3d00ed52cb017 100644 (file)
@@ -60,6 +60,12 @@ tccallback(const char *path, const struct stat *sb, __attribute__((unused)) int
                        cache.entries[cache.num_entries].hash_type = c.h[i].hash_type;
                        cache.entries[cache.num_entries].flags = 0;
                        memcpy(cache.entries[cache.num_entries].cdhash, c.h[i].cdhash, CS_CDHASH_LEN);
                        cache.entries[cache.num_entries].hash_type = c.h[i].hash_type;
                        cache.entries[cache.num_entries].flags = 0;
                        memcpy(cache.entries[cache.num_entries].cdhash, c.h[i].cdhash, CS_CDHASH_LEN);
+               } else if (cache.version == 2) {
+                       if ((cache.entries2 = realloc(cache.entries, sizeof(struct trust_cache_entry2) * (cache.num_entries + 1))) == NULL)
+                               exit(1);
+                       cache.entries2[cache.num_entries].hash_type = c.h[i].hash_type;
+                       cache.entries2[cache.num_entries].category = 0;
+                       memcpy(cache.entries2[cache.num_entries].cdhash, c.h[i].cdhash, CS_CDHASH_LEN);
                }
                cache.num_entries++;
        }
                }
                cache.num_entries++;
        }
index c88abc48c8feb8cf220cd939473e89678adea867..7c73a05b3233c16490b10a8cb676fe7ac58a5602 100644 (file)
--- a/create.c
+++ b/create.c
@@ -56,7 +56,7 @@ tccreate(int argc, char **argv)
                                        fprintf(stderr, "Failed to parse %s as a UUID\n", optarg);
                                break;
                        case 'v':
                                        fprintf(stderr, "Failed to parse %s as a UUID\n", optarg);
                                break;
                        case 'v':
-                               if (strlen(optarg) != 1 || (optarg[0] != '0' && optarg[0] != '1')) {
+                               if (strlen(optarg) != 1 || (optarg[0] != '0' && optarg[0] != '1' && optarg[0] != '2')) {
                                        fprintf(stderr, "Unsupported trustcache version %s\n", optarg);
                                        return 1;
                                }
                                        fprintf(stderr, "Unsupported trustcache version %s\n", optarg);
                                        return 1;
                                }
@@ -64,6 +64,8 @@ tccreate(int argc, char **argv)
                                        cache.version = 0;
                                else if (optarg[0] == '1')
                                        cache.version = 1;
                                        cache.version = 0;
                                else if (optarg[0] == '1')
                                        cache.version = 1;
+                               else if (optarg[0] == '2')
+                                       cache.version = 2;
                                break;
                }
        }
                                break;
                }
        }
@@ -92,15 +94,27 @@ tccreate(int argc, char **argv)
                                cache.entries[cache.num_entries + j].flags = append.entries[j].flags;
                                memcpy(cache.entries[cache.num_entries + j].cdhash, append.entries[j].cdhash, CS_CDHASH_LEN);
                        }
                                cache.entries[cache.num_entries + j].flags = append.entries[j].flags;
                                memcpy(cache.entries[cache.num_entries + j].cdhash, append.entries[j].cdhash, CS_CDHASH_LEN);
                        }
+               } else if (append.version == 2) {
+                       if ((cache.entries2 = realloc(cache.entries2, sizeof(struct trust_cache_entry2) *
+                                                       (cache.num_entries + append.num_entries))) == NULL)
+                               exit(1);
+                       for (uint32_t j = 0; j < append.num_entries; j++) {
+                               cache.entries2[cache.num_entries + j].hash_type = append.entries2[j].hash_type;
+                               cache.entries2[cache.num_entries + j].flags = append.entries2[j].flags;
+                               cache.entries2[cache.num_entries + j].category = append.entries2[j].category;
+                               memcpy(cache.entries2[cache.num_entries + j].cdhash, append.entries2[j].cdhash, CS_CDHASH_LEN);
+                       }
                }
                free(append.hashes);
                cache.num_entries += append.num_entries;
        }
 
                }
                free(append.hashes);
                cache.num_entries += append.num_entries;
        }
 
-       if (cache.version == 1)
-               qsort(cache.entries, cache.num_entries, sizeof(*cache.entries), ent_cmp);
-       else if (cache.version == 0)
+       if (cache.version == 0)
                qsort(cache.hashes, cache.num_entries, sizeof(*cache.hashes), hash_cmp);
                qsort(cache.hashes, cache.num_entries, sizeof(*cache.hashes), hash_cmp);
+       else if (cache.version == 1)
+               qsort(cache.entries, cache.num_entries, sizeof(*cache.entries), ent_cmp);
+       else if (cache.version == 2)
+               qsort(cache.entries, cache.num_entries, sizeof(*cache.entries2), ent_cmp);
 
        if (writetrustcache(cache, argv[0]) == -1)
                return 1;
 
        if (writetrustcache(cache, argv[0]) == -1)
                return 1;
diff --git a/info.c b/info.c
index 4f74d62d9f0b94286789538531610cd06c60a548..b4249b11c5bc2305c54b063118657a065b824d8f 100644 (file)
--- a/info.c
+++ b/info.c
@@ -77,8 +77,10 @@ tcinfo(int argc, char **argv)
                        for (uint32_t i = 0; i < cache.num_entries; i++) {
                                if (cache.version == 0)
                                        print_hash(cache.hashes[i], true);
                        for (uint32_t i = 0; i < cache.num_entries; i++) {
                                if (cache.version == 0)
                                        print_hash(cache.hashes[i], true);
-                               else
+                               else if (cache.version == 1)
                                        print_hash(cache.entries[i].cdhash, true);
                                        print_hash(cache.entries[i].cdhash, true);
+                               else if (cache.version == 2)
+                                       print_hash(cache.entries2[i].cdhash, true);
                        }
                        goto done;
                }
                        }
                        goto done;
                }
@@ -87,10 +89,12 @@ tcinfo(int argc, char **argv)
                                fprintf(stderr, "no entry %i\n", entrynum);
                                exit(1);
                        }
                                fprintf(stderr, "no entry %i\n", entrynum);
                                exit(1);
                        }
-                       if (cache.version == 1) {
-                               print_entry(cache.entries[entrynum - 1]);
-                       } else if (cache.version == 0) {
+                       if (cache.version == 0) {
                                print_hash(cache.hashes[entrynum - 1], true);
                                print_hash(cache.hashes[entrynum - 1], true);
+                       } else if (cache.version == 1) {
+                               print_entry(cache.entries[entrynum - 1]);
+                       } else if (cache.version == 2) {
+                               print_entry2(cache.entries2[entrynum - 1]);
                        }
                } else {
                        print_entries(cache);
                        }
                } else {
                        print_entries(cache);
@@ -121,6 +125,8 @@ print_entries(struct trust_cache cache)
                        print_hash(cache.hashes[i], true);
                else if (cache.version == 1)
                        print_entry(cache.entries[i]);
                        print_hash(cache.hashes[i], true);
                else if (cache.version == 1)
                        print_entry(cache.entries[i]);
+               else if (cache.version == 2)
+                       print_entry2(cache.entries2[i]);
        }
 }
 
        }
 }
 
@@ -150,6 +156,32 @@ print_entry(struct trust_cache_entry1 entry)
        printf("[%i]\n", entry.hash_type);
 }
 
        printf("[%i]\n", entry.hash_type);
 }
 
+void
+print_entry2(struct trust_cache_entry2 entry)
+{
+       print_hash(entry.cdhash, false);
+
+       switch (entry.flags) {
+               case CS_TRUST_CACHE_AMFID:
+                       printf(" CS_TRUST_CACHE_AMFID ");
+                       break;
+               case CS_TRUST_CACHE_ANE:
+                       printf(" CS_TRUST_CACHE_ANE ");
+                       break;
+               case CS_TRUST_CACHE_AMFID|CS_TRUST_CACHE_ANE:
+                       printf(" CS_TRUST_CACHE_AMFID|CS_TRUST_CACHE_ANE ");
+                       break;
+               case 0:
+                       printf(" [none] ");
+                       break;
+               default:
+                       printf(" [%i] ", entry.flags);
+                       break;
+       }
+
+       printf("[%i] [%i]\n", entry.hash_type, entry.category);
+}
+
 void
 print_hash(uint8_t cdhash[CS_CDHASH_LEN], bool newline)
 {
 void
 print_hash(uint8_t cdhash[CS_CDHASH_LEN], bool newline)
 {
index 5f31848eacd2dba8674c0344742278a873eefe05..4f30f8a176598c7ebc70b6960e145fd622b595fd 100644 (file)
--- a/remove.c
+++ b/remove.c
@@ -89,6 +89,13 @@ tcremove(int argc, char **argv)
                                        numremoved++;
                                        continue;
                                }
                                        numremoved++;
                                        continue;
                                }
+                       } else if (cache.version == 2) {
+                               if (memcmp(cache.entries2[j].cdhash, hash, CS_CDHASH_LEN) == 0) {
+                                       memmove(&cache.entries2[j], &cache.entries2[j + 1], (cache.num_entries - j - 1) * sizeof(struct trust_cache_entry2));
+                                       cache.num_entries--;
+                                       numremoved++;
+                                       continue;
+                               }
                        }
                        j++;
                }
                        }
                        j++;
                }
index 68ec6e5e014afee8c9268e6b255d382a502ff8ba..f5aaf5f8cbfd2dd7338bdbf612d590a5d5d58116 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd May 19, 2022
+.Dd June 16, 2022
 .Dt TRUSTCACHE 1
 .Os
 .Sh NAME
 .Dt TRUSTCACHE 1
 .Os
 .Sh NAME
@@ -95,7 +95,7 @@ Each Mach-O found in the specified inputs will be scanned for
 a code signature and hashed.
 Any malformed or unsigned Mach-O will be ignored.
 Each slice of a FAT binary will have its hash included.
 a code signature and hashed.
 Any malformed or unsigned Mach-O will be ignored.
 Each slice of a FAT binary will have its hash included.
-Versions 0 and 1 are supported, if not specified, 1 is assumed.
+Versions 0, 1, and 2 are supported, if not specified, 1 is assumed.
 If
 .Ar uuid
 is specified, that will be used instead of a randomly generated one.
 If
 .Ar uuid
 is specified, that will be used instead of a randomly generated one.
@@ -108,9 +108,10 @@ is specified, that will be used instead of a randomly generated one.
 .Xc
 Print information about
 .Ar file .
 .Xc
 Print information about
 .Ar file .
-The output for each hash will be in the format:
+The output for each hash will be in one of these formats:
 .Pp
 .Dl <cdhash> <flags> [<hash_type>]
 .Pp
 .Dl <cdhash> <flags> [<hash_type>]
+.Dl <cdhash> <flags> [<hash_type>] [<category>]
 .Pp
 If the
 .Fl c
 .Pp
 If the
 .Fl c
index cb6c7b0e1565afc9c71752503a4217af584ad42d..f9de404b321e2ca2b91774ff02f0df55965bbe2d 100644 (file)
@@ -91,6 +91,10 @@ opentrustcache(const char *path)
                if ((cache.entries = calloc(cache.num_entries, sizeof(struct trust_cache_entry1))) == NULL)
                        exit(EX_OSERR);
                fread(cache.entries, sizeof(struct trust_cache_entry1), cache.num_entries, f);
                if ((cache.entries = calloc(cache.num_entries, sizeof(struct trust_cache_entry1))) == NULL)
                        exit(EX_OSERR);
                fread(cache.entries, sizeof(struct trust_cache_entry1), cache.num_entries, f);
+       } else if (cache.version == 2) {
+               if ((cache.entries = calloc(cache.num_entries, sizeof(struct trust_cache_entry2))) == NULL)
+                       exit(EX_OSERR);
+               fread(cache.entries, sizeof(struct trust_cache_entry2), cache.num_entries, f);
        } else {
                fprintf(stderr, "%s: Unsupported version %i\n", path, cache.version);
                exit(1);
        } else {
                fprintf(stderr, "%s: Unsupported version %i\n", path, cache.version);
                exit(1);
@@ -120,6 +124,8 @@ writetrustcache(struct trust_cache cache, const char *path)
                        fwrite(&cache.hashes[i], sizeof(trust_cache_hash0), 1, f);
                else if (cache.version == 1)
                        fwrite(&cache.entries[i], sizeof(struct trust_cache_entry1), 1, f);
                        fwrite(&cache.hashes[i], sizeof(trust_cache_hash0), 1, f);
                else if (cache.version == 1)
                        fwrite(&cache.entries[i], sizeof(struct trust_cache_entry1), 1, f);
+               else if (cache.version == 2)
+                       fwrite(&cache.entries2[i], sizeof(struct trust_cache_entry2), 1, f);
        }
 
        fclose(f);
        }
 
        fclose(f);
index 3b1696acce08e12c93bea0f22de5a8a50f77df22..2ac17462f898e2b487ea37d3c20e80c0615ad6a6 100644 (file)
 #include "machoparse/cs_blobs.h"
 #include "uuid/uuid.h"
 
 #include "machoparse/cs_blobs.h"
 #include "uuid/uuid.h"
 
+struct trust_cache_entry2 {
+       uint8_t cdhash[CS_CDHASH_LEN];
+       uint8_t hash_type;
+       uint8_t flags;
+       uint16_t category;
+} __attribute__((__packed__));
+
 struct trust_cache_entry1 {
        uint8_t cdhash[CS_CDHASH_LEN];
        uint8_t hash_type;
        uint8_t flags;
 struct trust_cache_entry1 {
        uint8_t cdhash[CS_CDHASH_LEN];
        uint8_t hash_type;
        uint8_t flags;
-};
+} __attribute__((__packed__));
 
 typedef uint8_t trust_cache_hash0[CS_CDHASH_LEN];
 
 
 typedef uint8_t trust_cache_hash0[CS_CDHASH_LEN];
 
@@ -30,6 +37,7 @@ struct trust_cache {
        uuid_t uuid;
        uint32_t num_entries;
        union {
        uuid_t uuid;
        uint32_t num_entries;
        union {
+               struct trust_cache_entry2 *entries2;
                struct trust_cache_entry1 *entries;
                trust_cache_hash0 *hashes;
        };
                struct trust_cache_entry1 *entries;
                trust_cache_hash0 *hashes;
        };
@@ -54,6 +62,7 @@ int hash_cmp(const void * vp1, const void * vp2);
 void print_header(struct trust_cache cache);
 void print_hash(uint8_t cdhash[CS_CDHASH_LEN], bool newline);
 void print_entry(struct trust_cache_entry1 entry);
 void print_header(struct trust_cache cache);
 void print_hash(uint8_t cdhash[CS_CDHASH_LEN], bool newline);
 void print_entry(struct trust_cache_entry1 entry);
+void print_entry2(struct trust_cache_entry2 entry);
 void print_entries(struct trust_cache cache);
 
 #endif
 void print_entries(struct trust_cache cache);
 
 #endif