1/*
2 * Magic numbers used by Code Signing
3 */
4enum {
5	CSMAGIC_REQUIREMENT	= 0xfade0c00,		/* single Requirement blob */
6	CSMAGIC_REQUIREMENTS = 0xfade0c01,		/* Requirements vector (internal requirements) */
7	CSMAGIC_CODEDIRECTORY = 0xfade0c02,		/* CodeDirectory blob */
8	CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0, /* embedded form of signature data */
9	CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1, /* multi-arch collection of embedded signatures */
10
11	CSSLOT_CODEDIRECTORY = 0,				/* slot index for CodeDirectory */
12};
13
14
15/*
16 * Structure of an embedded-signature SuperBlob
17 */
18typedef struct __BlobIndex {
19	uint32_t type;					/* type of entry */
20	uint32_t offset;				/* offset of entry */
21} CS_BlobIndex;
22
23typedef struct __SuperBlob {
24	uint32_t magic;					/* magic number */
25	uint32_t length;				/* total length of SuperBlob */
26	uint32_t count;					/* number of index entries following */
27	CS_BlobIndex index[];			/* (count) entries */
28	/* followed by Blobs in no particular order as indicated by offsets in index */
29} CS_SuperBlob;
30
31
32/*
33 * C form of a CodeDirectory.
34 */
35typedef struct __CodeDirectory {
36	uint32_t magic;					/* magic number (CSMAGIC_CODEDIRECTORY) */
37	uint32_t length;				/* total length of CodeDirectory blob */
38	uint32_t version;				/* compatibility version */
39	uint32_t flags;					/* setup and mode flags */
40	uint32_t hashOffset;			/* offset of hash slot element at index zero */
41	uint32_t identOffset;			/* offset of identifier string */
42	uint32_t nSpecialSlots;			/* number of special hash slots */
43	uint32_t nCodeSlots;			/* number of ordinary (code) hash slots */
44	uint32_t codeLimit;				/* limit to main image signature range */
45	uint8_t hashSize;				/* size of each hash in bytes */
46	uint8_t hashType;				/* type of hash (cdHashType* constants) */
47	uint8_t spare1;					/* unused (must be zero) */
48	uint8_t	pageSize;				/* log2(page size in bytes); 0 => infinite */
49	uint32_t spare2;				/* unused (must be zero) */
50	/* followed by dynamic content as located by offset fields above */
51} CS_CodeDirectory;
52
53
54/*
55 * Sample code to locate the CodeDirectory from an embedded signature blob
56 */
57static inline const CS_CodeDirectory *findCodeDirectory(const CS_SuperBlob *embedded)
58{
59	if (embedded && ntohl(embedded->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
60		const CS_BlobIndex *limit = &embedded->index[ntohl(embedded->count)];
61		const CS_BlobIndex *p;
62		for (p = embedded->index; p < limit; ++p)
63			if (ntohl(p->type) == CSSLOT_CODEDIRECTORY) {
64				const unsigned char *base = (const unsigned char *)embedded;
65				const CS_CodeDirectory *cd = (const CS_CodeDirectory *)(base + ntohl(p->offset));
66				if (cd->magic == CSMAGIC_CODEDIRECTORY)
67					return cd;
68				else
69					break;
70			}
71	}
72	// not found
73	return NULL;
74}
75
76
77/*
78 * Locating a page hash
79 */
80static inline const unsigned char *hashes(const CS_CodeDirectory *cd, unsigned page)
81{
82	const unsigned char *base = (const unsigned char *)cd;
83	assert(page < ntohl(cd->nCodeSlots));
84
85	// "20" below is the size of a SHA-1 hash. There's got to be a constant for that
86	// where you get your SHA-1 functions from. This can also be had as cd->hashSize
87	// (but the constant is marginally faster, I suppose)
88	return base + ntohl(cd->hashOffset) + page * 20;
89}
90