- if (NULL == start && NULL == embedded_hash) {
- error = 0;
- goto out;
- } else if (NULL == start || NULL == embedded_hash) {
- error = EBADEXEC;
- goto out;
- }
- if (NULL == (computed_hash = kalloc(hash_size))) {
- error = ENOMEM;
- goto out;
- }
- SHA1Init(&context);
- SHA1Update(&context, start, length);
- SHA1Final(computed_hash, &context);
- if (0 != memcmp(computed_hash, embedded_hash, hash_size)) {
- error = EBADEXEC;
- goto out;
- }
- error = 0;
-out:
- if (NULL != computed_hash)
- kfree(computed_hash, hash_size);
- if (0 == error) {
- *out_start = start;
- *out_length = length;
+
+ if (*rcd == NULL)
+ return EBADEXEC;
+
+ return 0;
+}
+
+/*
+ * cs_find_blob_bytes
+ *
+ * Find an blob from the superblob/code directory. The blob must have
+ * been been validated by cs_validate_csblob() before calling
+ * this. Use csblob_find_blob() instead.
+ *
+ * Will also find a "raw" code directory if its stored as well as
+ * searching the superblob.
+ *
+ * Parameters: buffer Pointer to code signature
+ * length Length of buffer
+ * type type of blob to find
+ * magic the magic number for that blob
+ *
+ * Returns: pointer Success
+ * NULL Buffer not found
+ */
+
+const CS_GenericBlob *
+csblob_find_blob_bytes(const uint8_t *addr, size_t length, uint32_t type, uint32_t magic)
+{
+ const CS_GenericBlob *blob = (const CS_GenericBlob *)(const void *)addr;
+
+ if (ntohl(blob->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
+ const CS_SuperBlob *sb = (const CS_SuperBlob *)blob;
+ size_t n, count = ntohl(sb->count);
+
+ for (n = 0; n < count; n++) {
+ if (ntohl(sb->index[n].type) != type)
+ continue;
+ uint32_t offset = ntohl(sb->index[n].offset);
+ if (length - sizeof(const CS_GenericBlob) < offset)
+ return NULL;
+ blob = (const CS_GenericBlob *)(const void *)(addr + offset);
+ if (ntohl(blob->magic) != magic)
+ continue;
+ return blob;
+ }
+ } else if (type == CSSLOT_CODEDIRECTORY
+ && ntohl(blob->magic) == CSMAGIC_CODEDIRECTORY
+ && magic == CSMAGIC_CODEDIRECTORY)
+ return blob;
+ return NULL;
+}
+
+
+const CS_GenericBlob *
+csblob_find_blob(struct cs_blob *csblob, uint32_t type, uint32_t magic)
+{
+ if ((csblob->csb_flags & CS_VALID) == 0)
+ return NULL;
+ return csblob_find_blob_bytes((const uint8_t *)csblob->csb_mem_kaddr, csblob->csb_mem_size, type, magic);
+}
+
+static const uint8_t *
+find_special_slot(const CS_CodeDirectory *cd, size_t slotsize, uint32_t slot)
+{
+ /* there is no zero special slot since that is the first code slot */
+ if (ntohl(cd->nSpecialSlots) < slot || slot == 0)
+ return NULL;
+
+ return ((const uint8_t *)cd + ntohl(cd->hashOffset) - (slotsize * slot));
+}
+
+static uint8_t cshash_zero[CS_HASH_MAX_SIZE] = { 0 };
+
+int
+csblob_get_entitlements(struct cs_blob *csblob, void **out_start, size_t *out_length)
+{
+ uint8_t computed_hash[CS_HASH_MAX_SIZE];
+ const CS_GenericBlob *entitlements;
+ const CS_CodeDirectory *code_dir;
+ const uint8_t *embedded_hash;
+ union cs_hash_union context;
+
+ *out_start = NULL;
+ *out_length = 0;
+
+ if (csblob->csb_hashtype == NULL || csblob->csb_hashtype->cs_digest_size > sizeof(computed_hash))
+ return EBADEXEC;
+
+ code_dir = csblob->csb_cd;
+
+ entitlements = csblob_find_blob(csblob, CSSLOT_ENTITLEMENTS, CSMAGIC_EMBEDDED_ENTITLEMENTS);
+ embedded_hash = find_special_slot(code_dir, csblob->csb_hashtype->cs_size, CSSLOT_ENTITLEMENTS);
+
+ if (embedded_hash == NULL) {
+ if (entitlements)
+ return EBADEXEC;
+ return 0;
+ } else if (entitlements == NULL) {
+ if (memcmp(embedded_hash, cshash_zero, csblob->csb_hashtype->cs_size) != 0) {
+ return EBADEXEC;
+ } else {
+ return 0;
+ }