]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/ubc_subr.c
xnu-3248.50.21.tar.gz
[apple/xnu.git] / bsd / kern / ubc_subr.c
index 83785b788edc58ffd4c50e91333403ea8bfc5a57..3e4353a97071cc952f11470e917fcca342aa805e 100644 (file)
@@ -69,6 +69,7 @@
 #include <vm/vm_protos.h> /* last */
 
 #include <libkern/crypto/sha1.h>
 #include <vm/vm_protos.h> /* last */
 
 #include <libkern/crypto/sha1.h>
+#include <libkern/crypto/sha2.h>
 #include <libkern/libkern.h>
 
 #include <security/mac_framework.h>
 #include <libkern/libkern.h>
 
 #include <security/mac_framework.h>
@@ -144,62 +145,99 @@ cs_valid_range(
        return TRUE;
 }
 
        return TRUE;
 }
 
-/*
- * Locate the CodeDirectory from an embedded signature blob
- */
-const 
-CS_CodeDirectory *findCodeDirectory(
-       const CS_SuperBlob *embedded,
-       char *lower_bound,
-       char *upper_bound)
-{
-       const CS_CodeDirectory *cd = NULL;
+typedef void (*cs_md_init)(void *ctx);
+typedef void (*cs_md_update)(void *ctx, const void *data, size_t size);
+typedef void (*cs_md_final)(void *hash, void *ctx);
+
+struct cs_hash {
+    uint8_t            cs_type;        /* type code as per code signing */
+    size_t             cs_size;        /* size of effective hash (may be truncated) */
+    size_t             cs_digest_size; /* size of native hash */
+    cs_md_init         cs_init;
+    cs_md_update       cs_update;
+    cs_md_final                cs_final;
+};
+
+static struct cs_hash cs_hash_sha1 = {
+    .cs_type = CS_HASHTYPE_SHA1,
+    .cs_size = CS_SHA1_LEN,
+    .cs_digest_size = SHA_DIGEST_LENGTH,
+    .cs_init = (cs_md_init)SHA1Init,
+    .cs_update = (cs_md_update)SHA1Update,
+    .cs_final = (cs_md_final)SHA1Final,
+};
+#if CRYPTO_SHA2
+static struct cs_hash cs_hash_sha256 = {
+    .cs_type = CS_HASHTYPE_SHA256,
+    .cs_size = SHA256_DIGEST_LENGTH,
+    .cs_digest_size = SHA256_DIGEST_LENGTH,
+    .cs_init = (cs_md_init)SHA256_Init,
+    .cs_update = (cs_md_update)SHA256_Update,
+    .cs_final = (cs_md_final)SHA256_Final,
+};
+static struct cs_hash cs_hash_sha256_truncate = {
+    .cs_type = CS_HASHTYPE_SHA256_TRUNCATED,
+    .cs_size = CS_SHA256_TRUNCATED_LEN,
+    .cs_digest_size = SHA256_DIGEST_LENGTH,
+    .cs_init = (cs_md_init)SHA256_Init,
+    .cs_update = (cs_md_update)SHA256_Update,
+    .cs_final = (cs_md_final)SHA256_Final,
+};
+static struct cs_hash cs_hash_sha384 = {
+    .cs_type = CS_HASHTYPE_SHA384,
+    .cs_size = SHA384_DIGEST_LENGTH,
+    .cs_digest_size = SHA384_DIGEST_LENGTH,
+    .cs_init = (cs_md_init)SHA384_Init,
+    .cs_update = (cs_md_update)SHA384_Update,
+    .cs_final = (cs_md_final)SHA384_Final,
+};
+#endif
+    
+static struct cs_hash *
+cs_find_md(uint8_t type)
+{
+       if (type == CS_HASHTYPE_SHA1) {
+               return &cs_hash_sha1;
+#if CRYPTO_SHA2
+       } else if (type == CS_HASHTYPE_SHA256) {
+               return &cs_hash_sha256;
+       } else if (type == CS_HASHTYPE_SHA256_TRUNCATED) {
+               return &cs_hash_sha256_truncate;
+       } else if (type == CS_HASHTYPE_SHA384) {
+               return &cs_hash_sha384;
+#endif
+       }
+       return NULL;
+}
 
 
-       if (embedded &&
-           cs_valid_range(embedded, embedded + 1, lower_bound, upper_bound) &&
-           ntohl(embedded->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
-               const CS_BlobIndex *limit;
-               const CS_BlobIndex *p;
+union cs_hash_union {
+       SHA1_CTX                sha1ctxt;
+       SHA256_CTX              sha256ctx;
+       SHA384_CTX              sha384ctx;
+};
 
 
-               limit = &embedded->index[ntohl(embedded->count)];
-               if (!cs_valid_range(&embedded->index[0], limit,
-                                   lower_bound, upper_bound)) {
-                       return NULL;
-               }
-               for (p = embedded->index; p < limit; ++p) {
-                       if (ntohl(p->type) == CSSLOT_CODEDIRECTORY) {
-                               const unsigned char *base;
 
 
-                               base = (const unsigned char *)embedded;
-                               cd = (const CS_CodeDirectory *)(base + ntohl(p->offset));
-                               break;
-                       }
-               }
-       } else {
-               /*
-                * Detached signatures come as a bare CS_CodeDirectory,
-                * without a blob.
-                */
-               cd = (const CS_CodeDirectory *) embedded;
-       }
+/*
+ * Choose among different hash algorithms.
+ * Higher is better, 0 => don't use at all.
+ */
+static uint32_t hashPriorities[] = {
+       CS_HASHTYPE_SHA1,
+       CS_HASHTYPE_SHA256_TRUNCATED,
+       CS_HASHTYPE_SHA256,
+       CS_HASHTYPE_SHA384,
+};
 
 
-       if (cd &&
-           cs_valid_range(cd, cd + 1, lower_bound, upper_bound) &&
-           cs_valid_range(cd, (const char *) cd + ntohl(cd->length),
-                          lower_bound, upper_bound) &&
-           cs_valid_range(cd, (const char *) cd + ntohl(cd->hashOffset),
-                          lower_bound, upper_bound) &&
-           cs_valid_range(cd, (const char *) cd +
-                          ntohl(cd->hashOffset) +
-                          (ntohl(cd->nCodeSlots) * SHA1_RESULTLEN),
-                          lower_bound, upper_bound) &&
-           
-           ntohl(cd->magic) == CSMAGIC_CODEDIRECTORY) {
-               return cd;
-       }
+static unsigned int
+hash_rank(const CS_CodeDirectory *cd)
+{
+       uint32_t type = cd->hashType;
+       unsigned int n;
 
 
-       // not found or not a valid code directory
-       return NULL;
+       for (n = 0; n < sizeof(hashPriorities) / sizeof(hashPriorities[0]); ++n)
+               if (hashPriorities[n] == type)
+                       return n + 1;
+       return 0;       /* not supported */
 }
 
 
 }
 
 
@@ -209,9 +247,10 @@ CS_CodeDirectory *findCodeDirectory(
 static const unsigned char *
 hashes(
        const CS_CodeDirectory *cd,
 static const unsigned char *
 hashes(
        const CS_CodeDirectory *cd,
-       unsigned page,
-       char *lower_bound,
-       char *upper_bound)
+       uint32_t page,
+       size_t hash_len,
+       const char *lower_bound,
+       const char *upper_bound)
 {
        const unsigned char *base, *top, *hash;
        uint32_t nCodeSlots = ntohl(cd->nCodeSlots);
 {
        const unsigned char *base, *top, *hash;
        uint32_t nCodeSlots = ntohl(cd->nCodeSlots);
@@ -260,9 +299,9 @@ hashes(
 
                                /* base = address of first hash covered by scatter */
                                base = (const unsigned char *)cd + ntohl(cd->hashOffset) + 
 
                                /* base = address of first hash covered by scatter */
                                base = (const unsigned char *)cd + ntohl(cd->hashOffset) + 
-                                       hashindex * SHA1_RESULTLEN;
+                                       hashindex * hash_len;
                                /* top = address of first hash after this scatter */
                                /* top = address of first hash after this scatter */
-                               top = base + scount * SHA1_RESULTLEN;
+                               top = base + scount * hash_len;
                                if (!cs_valid_range(base, top, lower_bound, 
                                                    upper_bound) ||
                                    hashindex > nCodeSlots) {
                                if (!cs_valid_range(base, top, lower_bound, 
                                                    upper_bound) ||
                                    hashindex > nCodeSlots) {
@@ -278,20 +317,20 @@ hashes(
                        scatter++;
                } while(1);
                
                        scatter++;
                } while(1);
                
-               hash = base + (page - sbase) * SHA1_RESULTLEN;
+               hash = base + (page - sbase) * hash_len;
        } else {
                base = (const unsigned char *)cd + ntohl(cd->hashOffset);
        } else {
                base = (const unsigned char *)cd + ntohl(cd->hashOffset);
-               top = base + nCodeSlots * SHA1_RESULTLEN;
+               top = base + nCodeSlots * hash_len;
                if (!cs_valid_range(base, top, lower_bound, upper_bound) ||
                    page > nCodeSlots) {
                        return NULL;
                }
                assert(page < nCodeSlots);
 
                if (!cs_valid_range(base, top, lower_bound, upper_bound) ||
                    page > nCodeSlots) {
                        return NULL;
                }
                assert(page < nCodeSlots);
 
-               hash = base + page * SHA1_RESULTLEN;
+               hash = base + page * hash_len;
        }
        
        }
        
-       if (!cs_valid_range(hash, hash + SHA1_RESULTLEN,
+       if (!cs_valid_range(hash, hash + hash_len,
                            lower_bound, upper_bound)) {
                hash = NULL;
        }
                            lower_bound, upper_bound)) {
                hash = NULL;
        }
@@ -315,27 +354,30 @@ hashes(
 static int
 cs_validate_codedirectory(const CS_CodeDirectory *cd, size_t length)
 {
 static int
 cs_validate_codedirectory(const CS_CodeDirectory *cd, size_t length)
 {
+       struct cs_hash *hashtype;
 
        if (length < sizeof(*cd))
                return EBADEXEC;
        if (ntohl(cd->magic) != CSMAGIC_CODEDIRECTORY)
                return EBADEXEC;
 
        if (length < sizeof(*cd))
                return EBADEXEC;
        if (ntohl(cd->magic) != CSMAGIC_CODEDIRECTORY)
                return EBADEXEC;
-       if (cd->hashSize != SHA1_RESULTLEN)
-               return EBADEXEC;
        if (cd->pageSize != PAGE_SHIFT_4K)
                return EBADEXEC;
        if (cd->pageSize != PAGE_SHIFT_4K)
                return EBADEXEC;
-       if (cd->hashType != CS_HASHTYPE_SHA1)
+       hashtype = cs_find_md(cd->hashType);
+       if (hashtype == NULL)
+               return EBADEXEC;
+
+       if (cd->hashSize != hashtype->cs_size)
                return EBADEXEC;
 
        if (length < ntohl(cd->hashOffset))
                return EBADEXEC;
 
        /* check that nSpecialSlots fits in the buffer in front of hashOffset */
                return EBADEXEC;
 
        if (length < ntohl(cd->hashOffset))
                return EBADEXEC;
 
        /* check that nSpecialSlots fits in the buffer in front of hashOffset */
-       if (ntohl(cd->hashOffset) / SHA1_RESULTLEN < ntohl(cd->nSpecialSlots))
+       if (ntohl(cd->hashOffset) / hashtype->cs_size < ntohl(cd->nSpecialSlots))
                return EBADEXEC;
 
        /* check that codeslots fits in the buffer */
                return EBADEXEC;
 
        /* check that codeslots fits in the buffer */
-       if ((length - ntohl(cd->hashOffset)) / SHA1_RESULTLEN <  ntohl(cd->nCodeSlots))
+       if ((length - ntohl(cd->hashOffset)) / hashtype->cs_size <  ntohl(cd->nCodeSlots))
                return EBADEXEC;
        
        if (ntohl(cd->version) >= CS_SUPPORTSSCATTER && cd->scatterOffset) {
                return EBADEXEC;
        
        if (ntohl(cd->version) >= CS_SUPPORTSSCATTER && cd->scatterOffset) {
@@ -343,8 +385,8 @@ cs_validate_codedirectory(const CS_CodeDirectory *cd, size_t length)
                if (length < ntohl(cd->scatterOffset))
                        return EBADEXEC;
 
                if (length < ntohl(cd->scatterOffset))
                        return EBADEXEC;
 
-               SC_Scatter *scatter = (SC_Scatter *)
-                       (((uint8_t *)cd) + ntohl(cd->scatterOffset));
+               const SC_Scatter *scatter = (const SC_Scatter *)
+                       (((const uint8_t *)cd) + ntohl(cd->scatterOffset));
                uint32_t nPages = 0;
 
                /*
                uint32_t nPages = 0;
 
                /*
@@ -378,7 +420,7 @@ cs_validate_codedirectory(const CS_CodeDirectory *cd, size_t length)
 
        /* identifier is NUL terminated string */
        if (cd->identOffset) {
 
        /* identifier is NUL terminated string */
        if (cd->identOffset) {
-               uint8_t *ptr = (uint8_t *)cd + ntohl(cd->identOffset);
+               const uint8_t *ptr = (const uint8_t *)cd + ntohl(cd->identOffset);
                if (memchr(ptr, 0, length - ntohl(cd->identOffset)) == NULL)
                        return EBADEXEC;
        }
                if (memchr(ptr, 0, length - ntohl(cd->identOffset)) == NULL)
                        return EBADEXEC;
        }
@@ -388,7 +430,7 @@ cs_validate_codedirectory(const CS_CodeDirectory *cd, size_t length)
                if (length < ntohl(cd->teamOffset))
                        return EBADEXEC;
 
                if (length < ntohl(cd->teamOffset))
                        return EBADEXEC;
 
-               uint8_t *ptr = (uint8_t *)cd + ntohl(cd->teamOffset);
+               const uint8_t *ptr = (const uint8_t *)cd + ntohl(cd->teamOffset);
                if (memchr(ptr, 0, length - ntohl(cd->teamOffset)) == NULL)
                        return EBADEXEC;
        }
                if (memchr(ptr, 0, length - ntohl(cd->teamOffset)) == NULL)
                        return EBADEXEC;
        }
@@ -429,7 +471,7 @@ static int
 cs_validate_csblob(const uint8_t *addr, size_t length,
                   const CS_CodeDirectory **rcd)
 {
 cs_validate_csblob(const uint8_t *addr, size_t length,
                   const CS_CodeDirectory **rcd)
 {
-       const CS_GenericBlob *blob = (const CS_GenericBlob *)(void *)addr;
+       const CS_GenericBlob *blob = (const CS_GenericBlob *)(const void *)addr;
        int error;
 
        *rcd = NULL;
        int error;
 
        *rcd = NULL;
@@ -441,12 +483,17 @@ cs_validate_csblob(const uint8_t *addr, size_t length,
        length = ntohl(blob->length);
 
        if (ntohl(blob->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
        length = ntohl(blob->length);
 
        if (ntohl(blob->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
-               const CS_SuperBlob *sb = (const CS_SuperBlob *)blob;
-               uint32_t n, count = ntohl(sb->count);
+               const CS_SuperBlob *sb;
+               uint32_t n, count;
+               const CS_CodeDirectory *best_cd = NULL;
+               unsigned int best_rank = 0;
 
                if (length < sizeof(CS_SuperBlob))
                        return EBADEXEC;
 
 
                if (length < sizeof(CS_SuperBlob))
                        return EBADEXEC;
 
+               sb = (const CS_SuperBlob *)blob;
+               count = ntohl(sb->count);
+
                /* check that the array of BlobIndex fits in the rest of the data */
                if ((length - sizeof(CS_SuperBlob)) / sizeof(CS_BlobIndex) < count)
                        return EBADEXEC;
                /* check that the array of BlobIndex fits in the rest of the data */
                if ((length - sizeof(CS_SuperBlob)) / sizeof(CS_BlobIndex) < count)
                        return EBADEXEC;
@@ -454,30 +501,45 @@ cs_validate_csblob(const uint8_t *addr, size_t length,
                /* now check each BlobIndex */
                for (n = 0; n < count; n++) {
                        const CS_BlobIndex *blobIndex = &sb->index[n];
                /* now check each BlobIndex */
                for (n = 0; n < count; n++) {
                        const CS_BlobIndex *blobIndex = &sb->index[n];
-                       if (length < ntohl(blobIndex->offset))
+                       uint32_t type = ntohl(blobIndex->type);
+                       uint32_t offset = ntohl(blobIndex->offset);
+                       if (length < offset)
                                return EBADEXEC;
 
                        const CS_GenericBlob *subBlob =
                                return EBADEXEC;
 
                        const CS_GenericBlob *subBlob =
-                               (const CS_GenericBlob *)(void *)(addr + ntohl(blobIndex->offset));
+                               (const CS_GenericBlob *)(const void *)(addr + offset);
 
 
-                       size_t subLength = length - ntohl(blobIndex->offset);
+                       size_t subLength = length - offset;
 
                        if ((error = cs_validate_blob(subBlob, subLength)) != 0)
                                return error;
                        subLength = ntohl(subBlob->length);
 
                        /* extra validation for CDs, that is also returned */
 
                        if ((error = cs_validate_blob(subBlob, subLength)) != 0)
                                return error;
                        subLength = ntohl(subBlob->length);
 
                        /* extra validation for CDs, that is also returned */
-                       if (ntohl(blobIndex->type) == CSSLOT_CODEDIRECTORY) {
-                               const CS_CodeDirectory *cd = (const CS_CodeDirectory *)subBlob;
-                               if ((error = cs_validate_codedirectory(cd, subLength)) != 0)
+                       if (type == CSSLOT_CODEDIRECTORY || (type >= CSSLOT_ALTERNATE_CODEDIRECTORIES && type < CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT)) {
+                               const CS_CodeDirectory *candidate = (const CS_CodeDirectory *)subBlob;
+                               if ((error = cs_validate_codedirectory(candidate, subLength)) != 0)
                                        return error;
                                        return error;
-                               *rcd = cd;
+                               unsigned int rank = hash_rank(candidate);
+                               if (cs_debug > 3)
+                                       printf("CodeDirectory type %d rank %d at slot 0x%x index %d\n", candidate->hashType, (int)rank, (int)type, (int)n);
+                               if (best_cd == NULL || rank > best_rank) {
+                                       best_cd = candidate;
+                                       best_rank = rank;
+                               } else if (best_cd != NULL && rank == best_rank) {
+                                       /* repeat of a hash type (1:1 mapped to ranks), illegal and suspicious */
+                                       printf("multiple hash=%d CodeDirectories in signature; rejecting", best_cd->hashType);
+                                       return EBADEXEC;
+                               }
                        }
                        }
+                       if (best_cd && cs_debug > 2)
+                               printf("using CodeDirectory type %d (rank %d)\n", (int)best_cd->hashType, best_rank);
+                       *rcd = best_cd;
                }
 
        } else if (ntohl(blob->magic) == CSMAGIC_CODEDIRECTORY) {
 
                }
 
        } else if (ntohl(blob->magic) == CSMAGIC_CODEDIRECTORY) {
 
-               if ((error = cs_validate_codedirectory((const CS_CodeDirectory *)(void *)addr, length)) != 0)
+               if ((error = cs_validate_codedirectory((const CS_CodeDirectory *)(const void *)addr, length)) != 0)
                        return error;
                *rcd = (const CS_CodeDirectory *)blob;
        } else {
                        return error;
                *rcd = (const CS_CodeDirectory *)blob;
        } else {
@@ -495,7 +557,7 @@ cs_validate_csblob(const uint8_t *addr, size_t length,
  *
  * Find an blob from the superblob/code directory. The blob must have
  * been been validated by cs_validate_csblob() before calling
  *
  * Find an blob from the superblob/code directory. The blob must have
  * been been validated by cs_validate_csblob() before calling
- * this. Use cs_find_blob() instead.
+ * this. Use csblob_find_blob() instead.
  * 
  * Will also find a "raw" code directory if its stored as well as
  * searching the superblob.
  * 
  * Will also find a "raw" code directory if its stored as well as
  * searching the superblob.
@@ -509,10 +571,10 @@ cs_validate_csblob(const uint8_t *addr, size_t length,
  *             NULL                    Buffer not found
  */
 
  *             NULL                    Buffer not found
  */
 
-static const CS_GenericBlob *
-cs_find_blob_bytes(const uint8_t *addr, size_t length, uint32_t type, uint32_t magic)
+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 *)(void *)addr;
+       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;
 
        if (ntohl(blob->magic) == CSMAGIC_EMBEDDED_SIGNATURE) {
                const CS_SuperBlob *sb = (const CS_SuperBlob *)blob;
@@ -524,7 +586,7 @@ cs_find_blob_bytes(const uint8_t *addr, size_t length, uint32_t type, uint32_t m
                        uint32_t offset = ntohl(sb->index[n].offset);
                        if (length - sizeof(const CS_GenericBlob) < offset)
                                return NULL;
                        uint32_t offset = ntohl(sb->index[n].offset);
                        if (length - sizeof(const CS_GenericBlob) < offset)
                                return NULL;
-                       blob = (const CS_GenericBlob *)(void *)(addr + offset);
+                       blob = (const CS_GenericBlob *)(const void *)(addr + offset);
                        if (ntohl(blob->magic) != magic)
                                continue;
                        return blob;
                        if (ntohl(blob->magic) != magic)
                                continue;
                        return blob;
@@ -538,167 +600,73 @@ cs_find_blob_bytes(const uint8_t *addr, size_t length, uint32_t type, uint32_t m
 
 
 const CS_GenericBlob *
 
 
 const CS_GenericBlob *
-cs_find_blob(struct cs_blob *csblob, uint32_t type, uint32_t magic)
+csblob_find_blob(struct cs_blob *csblob, uint32_t type, uint32_t magic)
 {
        if ((csblob->csb_flags & CS_VALID) == 0)
                return NULL;
 {
        if ((csblob->csb_flags & CS_VALID) == 0)
                return NULL;
-       return cs_find_blob_bytes((const uint8_t *)csblob->csb_mem_kaddr, csblob->csb_mem_size, type, magic);
+       return csblob_find_blob_bytes((const uint8_t *)csblob->csb_mem_kaddr, csblob->csb_mem_size, type, magic);
 }
 
 static const uint8_t *
 }
 
 static const uint8_t *
-cs_find_special_slot(const CS_CodeDirectory *cd, uint32_t slot)
+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;
 
 {
        /* 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) - (SHA1_RESULTLEN * slot));
+       return ((const uint8_t *)cd + ntohl(cd->hashOffset) - (slotsize * slot));
 }
 
 }
 
-/*
- * CODESIGNING
- * End of routines to navigate code signing data structures in the kernel.
- */
-
-/*
- * ENTITLEMENTS
- * Routines to navigate entitlements in the kernel.
- */
-
-/* Retrieve the entitlements blob for a process.
- * Returns:
- *   EINVAL    no text vnode associated with the process
- *   EBADEXEC   invalid code signing data
- *   0         no error occurred
- *
- * On success, out_start and out_length will point to the
- * entitlements blob if found; or will be set to NULL/zero
- * if there were no entitlements.
- */
-
-static uint8_t sha1_zero[SHA1_RESULTLEN] = { 0 };
+static uint8_t cshash_zero[CS_HASH_MAX_SIZE] = { 0 };
 
 int
 
 int
-cs_entitlements_blob_get(proc_t p, void **out_start, size_t *out_length)
+csblob_get_entitlements(struct cs_blob *csblob, void **out_start, size_t *out_length)
 {
 {
-       uint8_t computed_hash[SHA1_RESULTLEN];
+       uint8_t computed_hash[CS_HASH_MAX_SIZE];
        const CS_GenericBlob *entitlements;
        const CS_CodeDirectory *code_dir;
        const CS_GenericBlob *entitlements;
        const CS_CodeDirectory *code_dir;
-       struct cs_blob *csblob;
        const uint8_t *embedded_hash;
        const uint8_t *embedded_hash;
-       SHA1_CTX context;
+       union cs_hash_union context;
 
        *out_start = NULL;
        *out_length = 0;
 
 
        *out_start = NULL;
        *out_length = 0;
 
-       if (NULL == p->p_textvp)
-               return EINVAL;
-
-       if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL)
-               return 0;
+       if (csblob->csb_hashtype == NULL || csblob->csb_hashtype->cs_digest_size > sizeof(computed_hash))
+           return EBADEXEC;
 
 
-       if ((code_dir = (const CS_CodeDirectory *)cs_find_blob(csblob, CSSLOT_CODEDIRECTORY, CSMAGIC_CODEDIRECTORY)) == NULL)
-               return 0;
+       code_dir = csblob->csb_cd;
 
 
-       entitlements = cs_find_blob(csblob, CSSLOT_ENTITLEMENTS, CSMAGIC_EMBEDDED_ENTITLEMENTS);
-       embedded_hash = cs_find_special_slot(code_dir, CSSLOT_ENTITLEMENTS);
+       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;
 
        if (embedded_hash == NULL) {
                if (entitlements)
                        return EBADEXEC;
                return 0;
-       } else if (entitlements == NULL && memcmp(embedded_hash, sha1_zero, SHA1_RESULTLEN) != 0) {
-               return EBADEXEC;
+       } else if (entitlements == NULL) {
+               if (memcmp(embedded_hash, cshash_zero, csblob->csb_hashtype->cs_size) != 0) {
+                       return EBADEXEC;
+               } else {
+                       return 0;
+               }
        }
 
        }
 
-       SHA1Init(&context);
-       SHA1Update(&context, entitlements, ntohl(entitlements->length));
-       SHA1Final(computed_hash, &context);
-       if (memcmp(computed_hash, embedded_hash, SHA1_RESULTLEN) != 0)
+       csblob->csb_hashtype->cs_init(&context);
+       csblob->csb_hashtype->cs_update(&context, entitlements, ntohl(entitlements->length));
+       csblob->csb_hashtype->cs_final(computed_hash, &context);
+
+       if (memcmp(computed_hash, embedded_hash, csblob->csb_hashtype->cs_size) != 0)
                return EBADEXEC;
 
                return EBADEXEC;
 
-       *out_start = (void *)entitlements;
+       *out_start = __DECONST(void *, entitlements);
        *out_length = ntohl(entitlements->length);
 
        return 0;
 }
 
        *out_length = ntohl(entitlements->length);
 
        return 0;
 }
 
-/* Retrieve the codesign identity for a process.
- * Returns:
- *   NULL      an error occured
- *   string    the cs_identity
- */
-
-const char *
-cs_identity_get(proc_t p)
-{
-       const CS_CodeDirectory *code_dir;
-       struct cs_blob *csblob;
-
-       if (NULL == p->p_textvp)
-               return NULL;
-
-       if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL)
-               return NULL;
-
-       if ((code_dir = (const CS_CodeDirectory *)cs_find_blob(csblob, CSSLOT_CODEDIRECTORY, CSMAGIC_CODEDIRECTORY)) == NULL)
-               return NULL;
-
-       if (code_dir->identOffset == 0)
-               return NULL;
-
-       return ((const char *)code_dir) + ntohl(code_dir->identOffset);
-}
-
-
-
-/* Retrieve the codesign blob for a process.
- * Returns:
- *   EINVAL    no text vnode associated with the process
- *   0         no error occurred
- *
- * On success, out_start and out_length will point to the
- * cms blob if found; or will be set to NULL/zero
- * if there were no blob.
- */
-
-int
-cs_blob_get(proc_t p, void **out_start, size_t *out_length)
-{
-       struct cs_blob *csblob;
-
-       *out_start = NULL;
-       *out_length = 0;
-
-       if (NULL == p->p_textvp)
-               return EINVAL;
-
-       if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL)
-               return 0;
-
-       *out_start = (void *)csblob->csb_mem_kaddr;
-       *out_length = csblob->csb_mem_size;
-
-       return 0;
-}
-
-uint8_t *
-cs_get_cdhash(struct proc *p)
-{
-       struct cs_blob *csblob;
-
-       if (NULL == p->p_textvp)
-               return NULL;
-
-       if ((csblob = ubc_cs_blob_get(p->p_textvp, -1, p->p_textoff)) == NULL)
-               return NULL;
-
-       return csblob->csb_sha1;
-}
-
 /*
 /*
- * ENTITLEMENTS
- * End of routines to navigate entitlements in the kernel.
+ * CODESIGNING
+ * End of routines to navigate code signing data structures in the kernel.
  */
 
 
  */
 
 
@@ -921,11 +889,7 @@ ubc_info_deallocate(struct ubc_info *uip)
         ubc_info_free(uip);
 }
 
         ubc_info_free(uip);
 }
 
-/* 
- * This should be public but currently it is only used below so we
- * defer making that change.
- */
-static errno_t mach_to_bsd_errno(kern_return_t mach_err)
+errno_t mach_to_bsd_errno(kern_return_t mach_err)
 {
        switch (mach_err) {
        case KERN_SUCCESS:
 {
        switch (mach_err) {
        case KERN_SUCCESS:
@@ -2725,17 +2689,44 @@ static SInt32 cs_blob_size_peak = 0;
 static UInt32 cs_blob_size_max = 0;
 static SInt32 cs_blob_count_peak = 0;
 
 static UInt32 cs_blob_size_max = 0;
 static SInt32 cs_blob_count_peak = 0;
 
-int cs_validation = 1;
-
-#ifndef SECURE_KERNEL
-SYSCTL_INT(_vm, OID_AUTO, cs_validation, CTLFLAG_RW | CTLFLAG_LOCKED, &cs_validation, 0, "Do validate code signatures");
-#endif
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_count, CTLFLAG_RD | CTLFLAG_LOCKED, (int *)(uintptr_t)&cs_blob_count, 0, "Current number of code signature blobs");
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_size, CTLFLAG_RD | CTLFLAG_LOCKED, (int *)(uintptr_t)&cs_blob_size, 0, "Current size of all code signature blobs");
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_count_peak, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_count_peak, 0, "Peak number of code signature blobs");
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_size_peak, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size_peak, 0, "Peak size of code signature blobs");
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_size_max, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size_max, 0, "Size of biggest code signature blob");
 
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_count, CTLFLAG_RD | CTLFLAG_LOCKED, (int *)(uintptr_t)&cs_blob_count, 0, "Current number of code signature blobs");
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_size, CTLFLAG_RD | CTLFLAG_LOCKED, (int *)(uintptr_t)&cs_blob_size, 0, "Current size of all code signature blobs");
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_count_peak, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_count_peak, 0, "Peak number of code signature blobs");
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_size_peak, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size_peak, 0, "Peak size of code signature blobs");
 SYSCTL_INT(_vm, OID_AUTO, cs_blob_size_max, CTLFLAG_RD | CTLFLAG_LOCKED, &cs_blob_size_max, 0, "Size of biggest code signature blob");
 
+/*
+ * Function: csblob_parse_teamid
+ *
+ * Description: This function returns a pointer to the team id
+               stored within the codedirectory of the csblob.
+               If the codedirectory predates team-ids, it returns
+               NULL.
+               This does not copy the name but returns a pointer to
+               it within the CD. Subsequently, the CD must be
+               available when this is used.
+*/
+
+static const char *
+csblob_parse_teamid(struct cs_blob *csblob)
+{
+       const CS_CodeDirectory *cd;
+
+       cd = csblob->csb_cd;
+
+       if (ntohl(cd->version) < CS_SUPPORTSTEAMID)
+               return NULL;
+
+       if (cd->teamOffset == 0)
+               return NULL;
+
+       const char *name = ((const char *)cd) + ntohl(cd->teamOffset);
+       if (cs_debug > 1)
+               printf("found team-id %s in cdblob\n", name);
+
+       return name;
+}
+
 
 kern_return_t
 ubc_cs_blob_allocate(
 
 kern_return_t
 ubc_cs_blob_allocate(
@@ -2746,9 +2737,9 @@ ubc_cs_blob_allocate(
 
 #if CS_BLOB_PAGEABLE
        *blob_size_p = round_page(*blob_size_p);
 
 #if CS_BLOB_PAGEABLE
        *blob_size_p = round_page(*blob_size_p);
-       kr = kmem_alloc(kernel_map, blob_addr_p, *blob_size_p);
+       kr = kmem_alloc(kernel_map, blob_addr_p, *blob_size_p, VM_KERN_MEMORY_SECURITY);
 #else  /* CS_BLOB_PAGEABLE */
 #else  /* CS_BLOB_PAGEABLE */
-       *blob_addr_p = (vm_offset_t) kalloc(*blob_size_p);
+       *blob_addr_p = (vm_offset_t) kalloc_tag(*blob_size_p, VM_KERN_MEMORY_SECURITY);
        if (*blob_addr_p == 0) {
                kr = KERN_NO_SPACE;
        } else {
        if (*blob_addr_p == 0) {
                kr = KERN_NO_SPACE;
        } else {
@@ -2769,120 +2760,6 @@ ubc_cs_blob_deallocate(
        kfree((void *) blob_addr, blob_size);
 #endif /* CS_BLOB_PAGEABLE */
 }
        kfree((void *) blob_addr, blob_size);
 #endif /* CS_BLOB_PAGEABLE */
 }
-       
-int
-ubc_cs_sigpup_add(
-       struct vnode    *vp,
-       vm_address_t    address,
-       vm_size_t       size)
-{
-       kern_return_t           kr;
-       struct ubc_info         *uip;
-       struct cs_blob          *blob;
-       memory_object_control_t control;
-       const CS_CodeDirectory *cd;
-       int                     error;
-
-       control = ubc_getobject(vp, UBC_FLAGS_NONE);
-       if (control == MEMORY_OBJECT_CONTROL_NULL)
-               return KERN_INVALID_ARGUMENT;
-
-       if (memory_object_is_signed(control))
-               return 0;
-
-       blob = (struct cs_blob *) kalloc(sizeof (struct cs_blob));
-       if (blob == NULL)
-               return ENOMEM;
-
-       /* fill in the new blob */
-       blob->csb_cpu_type = CPU_TYPE_ANY;
-       blob->csb_base_offset = 0;
-       blob->csb_mem_size = size;
-       blob->csb_mem_offset = 0;
-       blob->csb_mem_handle = IPC_PORT_NULL;
-       blob->csb_mem_kaddr = address;
-       blob->csb_sigpup = 1;
-       blob->csb_platform_binary = 0;
-       blob->csb_teamid = NULL;
-       
-       /*
-        * Validate the blob's contents
-        */
-       cd = findCodeDirectory(
-               (const CS_SuperBlob *) address, 
-               (char *) address, 
-               (char *) address + blob->csb_mem_size);
-       if (cd == NULL) {
-               /* no code directory => useless blob ! */
-               error = EINVAL;
-               goto out;
-       }
-
-       blob->csb_flags = ntohl(cd->flags) | CS_VALID;
-       blob->csb_end_offset = round_page_4K(ntohl(cd->codeLimit));
-       if((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) {
-               const SC_Scatter *scatter = (const SC_Scatter*)
-                   ((const char*)cd + ntohl(cd->scatterOffset));
-               blob->csb_start_offset = ntohl(scatter->base) * PAGE_SIZE_4K;
-       } else {
-               blob->csb_start_offset = (blob->csb_end_offset - (ntohl(cd->nCodeSlots) * PAGE_SIZE_4K));
-       }
-
-       /* 
-        * We don't need to check with the policy module, since the input data is supposed to be already checked
-        */
-       
-       vnode_lock(vp);
-       if (! UBCINFOEXISTS(vp)) {
-               vnode_unlock(vp);
-               if (cs_debug)
-                       printf("out ubc object\n");
-               error = ENOENT;
-               goto out;
-       }
-       uip = vp->v_ubcinfo;
-
-       /* someone raced us to adding the code directory */
-       if (uip->cs_blobs != NULL) {
-               if (cs_debug)
-                       printf("sigpup: vnode already have CD ?\n");
-               vnode_unlock(vp);
-               error = EEXIST;
-               goto out;
-       }
-
-       blob->csb_next = uip->cs_blobs;
-       uip->cs_blobs = blob;
-
-       OSAddAtomic(+1, &cs_blob_count);
-       OSAddAtomic((SInt32) +blob->csb_mem_size, &cs_blob_size);
-
-       /* mark this vnode's VM object as having "signed pages" */
-       kr = memory_object_signed(uip->ui_control, TRUE);
-       if (kr != KERN_SUCCESS) {
-               vnode_unlock(vp);
-               if (cs_debug)
-                       printf("sigpup: not signable ?\n");
-               error = ENOENT;
-               goto out;
-       }
-
-       vnode_unlock(vp);
-
-       error = 0;
-out:
-       if (error) {
-               if (cs_debug)
-                       printf("sigpup: not signable ?\n");
-               /* we failed; release what we allocated */
-               if (blob) {
-                       kfree(blob, sizeof (*blob));
-                       blob = NULL;
-               }
-       }
-
-       return error;
-}
 
 int
 ubc_cs_blob_add(
 
 int
 ubc_cs_blob_add(
@@ -2891,7 +2768,8 @@ ubc_cs_blob_add(
        off_t           base_offset,
        vm_address_t    addr,
        vm_size_t       size,
        off_t           base_offset,
        vm_address_t    addr,
        vm_size_t       size,
-       __unused int flags)
+       __unused int    flags,
+       struct cs_blob  **ret_blob)
 {
        kern_return_t           kr;
        struct ubc_info         *uip;
 {
        kern_return_t           kr;
        struct ubc_info         *uip;
@@ -2901,12 +2779,14 @@ ubc_cs_blob_add(
        memory_object_size_t    blob_size;
        const CS_CodeDirectory *cd;
        off_t                   blob_start_offset, blob_end_offset;
        memory_object_size_t    blob_size;
        const CS_CodeDirectory *cd;
        off_t                   blob_start_offset, blob_end_offset;
-       SHA1_CTX                sha1ctxt;
+       union cs_hash_union     mdctx;
        boolean_t               record_mtime;
        boolean_t               record_mtime;
-       int                     is_platform_binary;
+       int                     cs_flags;
 
        record_mtime = FALSE;
 
        record_mtime = FALSE;
-       is_platform_binary = 0;
+       cs_flags = 0;
+       if (ret_blob)
+           *ret_blob = NULL;
 
        blob_handle = IPC_PORT_NULL;
 
 
        blob_handle = IPC_PORT_NULL;
 
@@ -2943,7 +2823,6 @@ ubc_cs_blob_add(
 
        /* fill in the new blob */
        blob->csb_cpu_type = cputype;
 
        /* fill in the new blob */
        blob->csb_cpu_type = cputype;
-       blob->csb_sigpup = 0;
        blob->csb_base_offset = base_offset;
        blob->csb_mem_size = size;
        blob->csb_mem_offset = 0;
        blob->csb_base_offset = base_offset;
        blob->csb_mem_size = size;
        blob->csb_mem_offset = 0;
@@ -2951,6 +2830,7 @@ ubc_cs_blob_add(
        blob->csb_mem_kaddr = addr;
        blob->csb_flags = 0;
        blob->csb_platform_binary = 0;
        blob->csb_mem_kaddr = addr;
        blob->csb_flags = 0;
        blob->csb_platform_binary = 0;
+       blob->csb_platform_path = 0;
        blob->csb_teamid = NULL;
        
        /*
        blob->csb_teamid = NULL;
        
        /*
@@ -2959,17 +2839,25 @@ ubc_cs_blob_add(
 
        error = cs_validate_csblob((const uint8_t *)addr, size, &cd);
        if (error) {
 
        error = cs_validate_csblob((const uint8_t *)addr, size, &cd);
        if (error) {
-               if (cs_debug)
+
+        if (cs_debug)
                        printf("CODESIGNING: csblob invalid: %d\n", error);
                        printf("CODESIGNING: csblob invalid: %d\n", error);
-               blob->csb_flags = 0;
-               blob->csb_start_offset = 0;
-               blob->csb_end_offset = 0;
-               memset(blob->csb_sha1, 0, SHA1_RESULTLEN);
-               /* let the vnode checker determine if the signature is valid or not */
+        /* The vnode checker can't make the rest of this function succeed if csblob validation failed, so bail */
+        goto out;
+
        } else {
        } else {
-               const unsigned char *sha1_base;
-               int sha1_size;
+               const unsigned char *md_base;
+               uint8_t hash[CS_HASH_MAX_SIZE];
+               int md_size;
 
 
+#if CS_BLOB_PAGEABLE
+#error "cd might move under CS_BLOB_PAGEABLE; reconsider this code"
+#endif
+               blob->csb_cd = cd;
+               blob->csb_hashtype = cs_find_md(cd->hashType);
+               if (blob->csb_hashtype == NULL || blob->csb_hashtype->cs_digest_size > sizeof(hash))
+                       panic("validated CodeDirectory but unsupported type");
+                   
                blob->csb_flags = (ntohl(cd->flags) & CS_ALLOWED_MACHO) | CS_VALID;
                blob->csb_end_offset = round_page_4K(ntohl(cd->codeLimit));
                if((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) {
                blob->csb_flags = (ntohl(cd->flags) & CS_ALLOWED_MACHO) | CS_VALID;
                blob->csb_end_offset = round_page_4K(ntohl(cd->codeLimit));
                if((ntohl(cd->version) >= CS_SUPPORTSSCATTER) && (ntohl(cd->scatterOffset))) {
@@ -2977,15 +2865,17 @@ ubc_cs_blob_add(
                                ((const char*)cd + ntohl(cd->scatterOffset));
                        blob->csb_start_offset = ntohl(scatter->base) * PAGE_SIZE_4K;
                } else {
                                ((const char*)cd + ntohl(cd->scatterOffset));
                        blob->csb_start_offset = ntohl(scatter->base) * PAGE_SIZE_4K;
                } else {
-                       blob->csb_start_offset = (blob->csb_end_offset -
-                                                 (ntohl(cd->nCodeSlots) * PAGE_SIZE_4K));
+                       blob->csb_start_offset = 0;
                }
                }
-               /* compute the blob's SHA1 hash */
-               sha1_base = (const unsigned char *) cd;
-               sha1_size = ntohl(cd->length);
-               SHA1Init(&sha1ctxt);
-               SHA1Update(&sha1ctxt, sha1_base, sha1_size);
-               SHA1Final(blob->csb_sha1, &sha1ctxt);
+               /* compute the blob's cdhash */
+               md_base = (const unsigned char *) cd;
+               md_size = ntohl(cd->length);
+
+               blob->csb_hashtype->cs_init(&mdctx);
+               blob->csb_hashtype->cs_update(&mdctx, md_base, md_size);
+               blob->csb_hashtype->cs_final(hash, &mdctx);
+
+               memcpy(blob->csb_cdhash, hash, CS_CDHASH_LEN);
        }
 
        /* 
        }
 
        /* 
@@ -2994,16 +2884,15 @@ ubc_cs_blob_add(
 #if CONFIG_MACF
        error = mac_vnode_check_signature(vp, 
                                          base_offset, 
 #if CONFIG_MACF
        error = mac_vnode_check_signature(vp, 
                                          base_offset, 
-                                         blob->csb_sha1, 
-                                         (const void*)cd,
-                                         size, flags, 
-                                         &is_platform_binary);
+                                         blob->csb_cdhash, 
+                                         (const void*)addr, size,
+                                         flags, &cs_flags);
        if (error) {
                if (cs_debug) 
                        printf("check_signature[pid: %d], error = %d\n", current_proc()->p_pid, error);
                goto out;
        }
        if (error) {
                if (cs_debug) 
                        printf("check_signature[pid: %d], error = %d\n", current_proc()->p_pid, error);
                goto out;
        }
-       if ((flags & MAC_VNODE_CHECK_DYLD_SIM) && !is_platform_binary) {
+       if ((flags & MAC_VNODE_CHECK_DYLD_SIM) && !(cs_flags & CS_PLATFORM_BINARY)) {
                if (cs_debug)
                        printf("check_signature[pid: %d], is not apple signed\n", current_proc()->p_pid);
                error = EPERM;
                if (cs_debug)
                        printf("check_signature[pid: %d], is not apple signed\n", current_proc()->p_pid);
                error = EPERM;
@@ -3011,13 +2900,15 @@ ubc_cs_blob_add(
        }
 #endif 
        
        }
 #endif 
        
-       if (is_platform_binary) {
+       if (cs_flags & CS_PLATFORM_BINARY) {
                if (cs_debug > 1)
                        printf("check_signature[pid: %d]: platform binary\n", current_proc()->p_pid);
                blob->csb_platform_binary = 1;
                if (cs_debug > 1)
                        printf("check_signature[pid: %d]: platform binary\n", current_proc()->p_pid);
                blob->csb_platform_binary = 1;
+               blob->csb_platform_path = !!(cs_flags & CS_PLATFORM_PATH);
        } else {
                blob->csb_platform_binary = 0;
        } else {
                blob->csb_platform_binary = 0;
-               blob->csb_teamid = csblob_get_teamid(blob);
+               blob->csb_platform_path = 0;
+               blob->csb_teamid = csblob_parse_teamid(blob);
                if (cs_debug > 1) {
                        if (blob->csb_teamid)
                                printf("check_signature[pid: %d]: team-id is %s\n", current_proc()->p_pid, blob->csb_teamid);
                if (cs_debug > 1) {
                        if (blob->csb_teamid)
                                printf("check_signature[pid: %d]: team-id is %s\n", current_proc()->p_pid, blob->csb_teamid);
@@ -3094,9 +2985,9 @@ ubc_cs_blob_add(
                             (blob->csb_cpu_type == CPU_TYPE_ANY ||
                              oblob->csb_cpu_type == CPU_TYPE_ANY ||
                              blob->csb_cpu_type == oblob->csb_cpu_type) &&
                             (blob->csb_cpu_type == CPU_TYPE_ANY ||
                              oblob->csb_cpu_type == CPU_TYPE_ANY ||
                              blob->csb_cpu_type == oblob->csb_cpu_type) &&
-                            !bcmp(blob->csb_sha1,
-                                  oblob->csb_sha1,
-                                  SHA1_RESULTLEN)) {
+                            !bcmp(blob->csb_cdhash,
+                                  oblob->csb_cdhash,
+                                  CS_CDHASH_LEN)) {
                                 /*
                                  * We already have this blob:
                                  * we'll return success but
                                 /*
                                  * We already have this blob:
                                  * we'll return success but
@@ -3112,6 +3003,8 @@ ubc_cs_blob_add(
                                         oblob->csb_cpu_type = cputype;
                                 }
                                 vnode_unlock(vp);
                                         oblob->csb_cpu_type = cputype;
                                 }
                                 vnode_unlock(vp);
+                                if (ret_blob)
+                                        *ret_blob = oblob;
                                 error = EAGAIN;
                                 goto out;
                         } else {
                                 error = EAGAIN;
                                 goto out;
                         } else {
@@ -3185,6 +3078,9 @@ ubc_cs_blob_add(
                vnode_mtime(vp, &uip->cs_mtime, vfs_context_current());
        }
 
                vnode_mtime(vp, &uip->cs_mtime, vfs_context_current());
        }
 
+       if (ret_blob)
+               *ret_blob = blob;
+
        error = 0;      /* success ! */
 
 out:
        error = 0;      /* success ! */
 
 out:
@@ -3219,6 +3115,42 @@ out:
        return error;
 }
 
        return error;
 }
 
+void
+csvnode_print_debug(struct vnode *vp)
+{
+       const char      *name = NULL;
+       struct ubc_info *uip;
+       struct cs_blob *blob;
+
+       name = vnode_getname_printable(vp);
+       if (name) {
+               printf("csvnode: name: %s\n", name);
+               vnode_putname_printable(name);
+       }
+
+       vnode_lock_spin(vp);
+
+       if (! UBCINFOEXISTS(vp)) {
+               blob = NULL;
+               goto out;
+       }
+
+       uip = vp->v_ubcinfo;
+       for (blob = uip->cs_blobs; blob != NULL; blob = blob->csb_next) {
+               printf("csvnode: range: %lu -> %lu flags: 0x%08x platform: %s path: %s team: %s\n",
+                      (unsigned long)blob->csb_start_offset,
+                      (unsigned long)blob->csb_end_offset,
+                      blob->csb_flags,
+                      blob->csb_platform_binary ? "yes" : "no",
+                      blob->csb_platform_path ? "yes" : "no",
+                      blob->csb_teamid ? blob->csb_teamid : "<NO-TEAM>");
+       }
+
+out:
+       vnode_unlock(vp);
+
+}
+
 struct cs_blob *
 ubc_cs_blob_get(
        struct vnode    *vp,
 struct cs_blob *
 ubc_cs_blob_get(
        struct vnode    *vp,
@@ -3253,10 +3185,6 @@ ubc_cs_blob_get(
                }
        }
 
                }
        }
 
-       if (cs_debug && blob != NULL && blob->csb_sigpup) {
-               printf("found sig pup blob\n");
-       }
-
 out:
        vnode_unlock(vp);
 
 out:
        vnode_unlock(vp);
 
@@ -3273,7 +3201,7 @@ ubc_cs_free(
             blob != NULL;
             blob = next_blob) {
                next_blob = blob->csb_next;
             blob != NULL;
             blob = next_blob) {
                next_blob = blob->csb_next;
-               if (blob->csb_mem_kaddr != 0 && !blob->csb_sigpup) {
+               if (blob->csb_mem_kaddr != 0) {
                        ubc_cs_blob_deallocate(blob->csb_mem_kaddr,
                                               blob->csb_mem_size);
                        blob->csb_mem_kaddr = 0;
                        ubc_cs_blob_deallocate(blob->csb_mem_kaddr,
                                               blob->csb_mem_size);
                        blob->csb_mem_kaddr = 0;
@@ -3322,7 +3250,7 @@ ubc_cs_blob_revalidate(
 {
        int error = 0;
 #if CONFIG_MACF
 {
        int error = 0;
 #if CONFIG_MACF
-       int is_platform_binary = 0;
+       int cs_flags = 0;
 #endif
        const CS_CodeDirectory *cd = NULL;
        
 #endif
        const CS_CodeDirectory *cd = NULL;
        
@@ -3339,7 +3267,9 @@ ubc_cs_blob_revalidate(
 
        /* callout to mac_vnode_check_signature */
 #if CONFIG_MACF
 
        /* callout to mac_vnode_check_signature */
 #if CONFIG_MACF
-       error = mac_vnode_check_signature(vp, blob->csb_base_offset, blob->csb_sha1, (const void*)cd, blob->csb_cpu_type, flags, &is_platform_binary);
+       error = mac_vnode_check_signature(vp, blob->csb_base_offset, blob->csb_cdhash,
+                                         (const void*)blob->csb_mem_kaddr, (int)blob->csb_mem_size,
+                                         flags, &cs_flags);
        if (cs_debug && error) {
                        printf("revalidate: check_signature[pid: %d], error = %d\n", current_proc()->p_pid, error);
        }
        if (cs_debug && error) {
                        printf("revalidate: check_signature[pid: %d], error = %d\n", current_proc()->p_pid, error);
        }
@@ -3430,19 +3360,19 @@ cs_validate_page(
        const void              *data,
        unsigned                *tainted)
 {
        const void              *data,
        unsigned                *tainted)
 {
-       SHA1_CTX                sha1ctxt;
-       unsigned char           actual_hash[SHA1_RESULTLEN];
-       unsigned char           expected_hash[SHA1_RESULTLEN];
+       union cs_hash_union     mdctx;
+       struct cs_hash          *hashtype = NULL;
+       unsigned char           actual_hash[CS_HASH_MAX_SIZE];
+       unsigned char           expected_hash[CS_HASH_MAX_SIZE];
        boolean_t               found_hash;
        struct cs_blob          *blobs, *blob;
        const CS_CodeDirectory  *cd;
        boolean_t               found_hash;
        struct cs_blob          *blobs, *blob;
        const CS_CodeDirectory  *cd;
-       const CS_SuperBlob      *embedded;
        const unsigned char     *hash;
        boolean_t               validated;
        off_t                   offset; /* page offset in the file */
        size_t                  size;
        off_t                   codeLimit = 0;
        const unsigned char     *hash;
        boolean_t               validated;
        off_t                   offset; /* page offset in the file */
        size_t                  size;
        off_t                   codeLimit = 0;
-       char                    *lower_bound, *upper_bound;
+       const char              *lower_bound, *upper_bound;
        vm_offset_t             kaddr, blob_addr;
        vm_size_t               ksize;
        kern_return_t           kr;
        vm_offset_t             kaddr, blob_addr;
        vm_size_t               ksize;
        kern_return_t           kr;
@@ -3487,54 +3417,39 @@ cs_validate_page(
                                break;
                        }
                }
                                break;
                        }
                }
-               if (blob->csb_sigpup && cs_debug)
-                       printf("checking for a sigpup CD\n");
 
                blob_addr = kaddr + blob->csb_mem_offset;
 
                blob_addr = kaddr + blob->csb_mem_offset;
-               
                lower_bound = CAST_DOWN(char *, blob_addr);
                upper_bound = lower_bound + blob->csb_mem_size;
                lower_bound = CAST_DOWN(char *, blob_addr);
                upper_bound = lower_bound + blob->csb_mem_size;
-
-               embedded = (const CS_SuperBlob *) blob_addr;
-               cd = findCodeDirectory(embedded, lower_bound, upper_bound);
+               
+               cd = blob->csb_cd;
                if (cd != NULL) {
                if (cd != NULL) {
-                       if (cd->pageSize != PAGE_SHIFT_4K ||
-                           cd->hashType != CS_HASHTYPE_SHA1 ||
-                           cd->hashSize != SHA1_RESULTLEN) {
-                               /* bogus blob ? */
-                               if (blob->csb_sigpup && cs_debug)
-                                       printf("page foo bogus sigpup CD\n");
-                               continue;
-                       }
+                       /* all CD's that have been injected is already validated */
 
                        offset = page_offset - blob->csb_base_offset;
                        if (offset < blob->csb_start_offset ||
                            offset >= blob->csb_end_offset) {
                                /* our page is not covered by this blob */
 
                        offset = page_offset - blob->csb_base_offset;
                        if (offset < blob->csb_start_offset ||
                            offset >= blob->csb_end_offset) {
                                /* our page is not covered by this blob */
-                               if (blob->csb_sigpup && cs_debug)
-                                       printf("OOB sigpup CD\n");
                                continue;
                        }
 
                                continue;
                        }
 
+                       hashtype = blob->csb_hashtype;
+                       if (hashtype == NULL)
+                               panic("unknown hash type ?");
+                       if (hashtype->cs_digest_size > sizeof(actual_hash))
+                               panic("hash size too large");
+
                        codeLimit = ntohl(cd->codeLimit);
                        codeLimit = ntohl(cd->codeLimit);
-                       if (blob->csb_sigpup && cs_debug)
-                               printf("sigpup codesize %d\n", (int)codeLimit);
 
 
-                       hash = hashes(cd, (unsigned)(offset>>PAGE_SHIFT_4K),
+                       hash = hashes(cd, (uint32_t)(offset>>PAGE_SHIFT_4K),
+                                     hashtype->cs_size,
                                      lower_bound, upper_bound);
                        if (hash != NULL) {
                                      lower_bound, upper_bound);
                        if (hash != NULL) {
-                               bcopy(hash, expected_hash,
-                                     sizeof (expected_hash));
+                               bcopy(hash, expected_hash, hashtype->cs_size);
                                found_hash = TRUE;
                                found_hash = TRUE;
-                               if (blob->csb_sigpup && cs_debug)
-                                       printf("sigpup hash\n");
                        }
 
                        break;
                        }
 
                        break;
-               } else {
-                       if (blob->csb_sigpup && cs_debug)
-                               printf("sig pup had no valid CD\n");
-
                }
        }
 
                }
        }
 
@@ -3567,15 +3482,15 @@ cs_validate_page(
                        size = (size_t) (codeLimit & PAGE_MASK_4K);
                        *tainted |= CS_VALIDATE_NX;
                }
                        size = (size_t) (codeLimit & PAGE_MASK_4K);
                        *tainted |= CS_VALIDATE_NX;
                }
-               /* compute the actual page's SHA1 hash */
-               SHA1Init(&sha1ctxt);
-               SHA1UpdateUsePhysicalAddress(&sha1ctxt, data, size);
-               SHA1Final(actual_hash, &sha1ctxt);
+
+               hashtype->cs_init(&mdctx);
+               hashtype->cs_update(&mdctx, data, size);
+               hashtype->cs_final(actual_hash, &mdctx);
 
                asha1 = (const uint32_t *) actual_hash;
                esha1 = (const uint32_t *) expected_hash;
 
 
                asha1 = (const uint32_t *) actual_hash;
                esha1 = (const uint32_t *) expected_hash;
 
-               if (bcmp(expected_hash, actual_hash, SHA1_RESULTLEN) != 0) {
+               if (bcmp(expected_hash, actual_hash, hashtype->cs_size) != 0) {
                        if (cs_debug) {
                                printf("CODE SIGNING: cs_validate_page: "
                                       "mobj %p off 0x%llx size 0x%lx: "
                        if (cs_debug) {
                                printf("CODE SIGNING: cs_validate_page: "
                                       "mobj %p off 0x%llx size 0x%lx: "
@@ -3633,7 +3548,7 @@ ubc_cs_getcdhash(
                ret = EBADEXEC; /* XXX any better error ? */
        } else {
                /* get the SHA1 hash of that blob */
                ret = EBADEXEC; /* XXX any better error ? */
        } else {
                /* get the SHA1 hash of that blob */
-               bcopy(blob->csb_sha1, cdhash, sizeof (blob->csb_sha1));
+               bcopy(blob->csb_cdhash, cdhash, sizeof (blob->csb_cdhash));
                ret = 0;
        }
 
                ret = 0;
        }