]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Magic numbers used by Code Signing | |
3 | */ | |
4 | enum { | |
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 | */ | |
18 | typedef struct __BlobIndex { | |
19 | uint32_t type; /* type of entry */ | |
20 | uint32_t offset; /* offset of entry */ | |
21 | } CS_BlobIndex; | |
22 | ||
23 | typedef 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 | */ | |
35 | typedef 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 | */ | |
57 | static 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 | */ | |
80 | static 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 | } |