Index: /trunk/include/iprt/crypto/applecodesign.h
===================================================================
--- /trunk/include/iprt/crypto/applecodesign.h	(revision 74725)
+++ /trunk/include/iprt/crypto/applecodesign.h	(revision 74726)
@@ -63,6 +63,9 @@
  *       greater-than and less-than comparisons works correctly.
  * @{  */
+#define RTCRAPLCS_VER_2_0                               UINT32_C(0x00020000)
 #define RTCRAPLCS_VER_SUPPORTS_SCATTER                  UINT32_C(0x00020100)
 #define RTCRAPLCS_VER_SUPPORTS_TEAMID                   UINT32_C(0x00020200)
+#define RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64            UINT32_C(0x00020300)
+#define RTCRAPLCS_VER_SUPPORTS_EXEC_SEG                 UINT32_C(0x00020400)
 /** @} */
 
@@ -78,4 +81,5 @@
 #define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES        RT_N2H_U32_C(UINT32_C(0x00001000))
 #define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_END    RT_N2H_U32_C(UINT32_C(0x00001005))
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_COUNT  UINT32_C(0x00000005)
 #define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORY_INC      RT_N2H_U32_C(UINT32_C(0x00000001))
 /** The signature.
@@ -162,5 +166,6 @@
     /** 0x0c: Flags & mode, RTCRAPLCS_???.  (Big endian. ) */
     uint32_t        fFlags;
-    /** 0x10: Offset of the hash slots.  Big endian. */
+    /** 0x10: Offset of the hash slots.  Big endian.
+     * Special slots found below this offset, code slots at and after.  */
     uint32_t        offHashSlots;
     /** 0x14: Offset of the identifier string.  Big endian. */
@@ -170,6 +175,6 @@
     /** 0x1c: Number of code hash slots.  Big endian. */
     uint32_t        cCodeSlots;
-    /** 0x20: Number of bytes of code that's covered.  Big endian. */
-    uint32_t        cbCodeLimit;
+    /** 0x20: Number of bytes of code that's covered, 32-bit wide.  Big endian. */
+    uint32_t        cbCodeLimit32;
     /** 0x24: The hash size. */
     uint8_t         cbHash;
@@ -181,13 +186,29 @@
     uint8_t         cPageShift;
     /** 0x28: Spare field, MBZ. */
-    uint32_t        uUnused;
+    uint32_t        uUnused1;
     /** 0x2c: Offset of scatter vector (optional).  Big endian.
      * @since RTCRAPLCS_VER_SUPPORTS_SCATTER */
     uint32_t        offScatter;
     /** 0x30: Offset of team identifier (optional).  Big endian.
-     * @since RTCRAPLCS_VER_SUPPORTS_TEAM */
-    uint32_t        offTeam;
+     * @since RTCRAPLCS_VER_SUPPORTS_TEAMID */
+    uint32_t        offTeamId;
+    /** 0x34: Unused field, MBZ.
+     * @since RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 */
+    uint32_t        uUnused2;
+    /** 0x38: Number of bytes of code that's covered, 64-bit wide.  Big endian.
+     * @since RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 */
+    uint64_t        cbCodeLimit64;
+    /** 0x40: File offset of the first segment.  Big endian.
+     * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG
+     * @note  Would be better to just sign the exe header + load commands. */
+    uint64_t        offExecSeg;
+    /** 0x48: The size of the first segment.  Big endian.
+     * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG */
+    uint64_t        cbExecSeg;
+    /** 0x50: Flags for the first segment.  Big endian.
+     * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG */
+    uint64_t        fExecSeg;
 } RTCRAPLCSCODEDIRECTORY;
-AssertCompileSize(RTCRAPLCSCODEDIRECTORY, 0x34);
+AssertCompileSize(RTCRAPLCSCODEDIRECTORY, 0x58);
 /** Pointer to a CS code directory. */
 typedef RTCRAPLCSCODEDIRECTORY *PRTCRAPLCSCODEDIRECTORY;
Index: /trunk/src/VBox/Runtime/common/ldr/ldrMachO.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/ldr/ldrMachO.cpp	(revision 74725)
+++ /trunk/src/VBox/Runtime/common/ldr/ldrMachO.cpp	(revision 74726)
@@ -65,4 +65,6 @@
 #include <iprt/mem.h>
 #include <iprt/string.h>
+#include <iprt/sha.h>
+#include <iprt/crypto/digest.h>
 
 #include <iprt/formats/mach-o.h>
@@ -234,4 +236,10 @@
         PCRTCRAPLCSSUPERBLOB    pSuper;
     }                       PtrCodeSignature;
+    /** File offset of segment 0 (relative to Mach-O header). */
+    uint64_t                offSeg0ForCodeSign;
+    /** File size of segment 0. */
+    uint64_t                cbSeg0ForCodeSign;
+    /** Segment 0 flags. */
+    uint64_t                fSeg0ForCodeSign;
 
     /** The RVA of the Global Offset Table. */
@@ -261,4 +269,6 @@
     /** The naturalized size. */
     uint32_t                    cb;
+    /** The digest type. */
+    RTDIGESTTYPE                enmDigest;
 } RTLDRMACHCODEDIR;
 /** Pointer to code directory data. */
@@ -1166,4 +1176,5 @@
     const uint32_t cSegments = pThis->cSegments;
     PRTLDRMODMACHOSEG pSegItr;
+    bool fFirstSeg = true;
     RT_NOREF(cbStringPool);
 
@@ -1315,5 +1326,14 @@
                     if (fAddSegOuter) \
                         CLOSE_SEGMENT(); \
-                } while (0) /* ADD_SEGMENT_AND_ITS_SECTIONS */
+                    \
+                    /* Take down 'execSeg' info for signing */ \
+                    if (fFirstSeg) \
+                    { \
+                        fFirstSeg = false; \
+                        pThis->offSeg0ForCodeSign = pSrcSeg->fileoff; \
+                        pThis->cbSeg0ForCodeSign  = pSrcSeg->filesize; /** @todo file or vm size? */ \
+                        pThis->fSeg0ForCodeSign   = pSrcSeg->flags; \
+                    } \
+            } while (0) /* ADD_SEGMENT_AND_ITS_SECTIONS */
 
                 ADD_SEGMENT_AND_ITS_SECTIONS(32);
@@ -4049,5 +4069,5 @@
         if (   offData < offFirst
             || offData > cbBlob - sizeof(RTCRAPLCSHDR)
-            || !(offData & 3))
+            || (offData & 3))
             return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
                                  "Slot #%u has an invalid data offset: %#x (min %#x, max %#x-4)",
@@ -4056,47 +4076,7 @@
 
         /*
-         * Code directories.
-         */
-        if (   pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_CODEDIRECTORY
-            || (   pSuper->aSlots[iSlot].uType >= RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES
-                && pSuper->aSlots[iSlot].uType < RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_END))
-        {
-            if (pSignature->cCodeDirs >= RT_ELEMENTS(pSignature->aCodeDirs))
-                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
-                                     "Slot #%u: Too many code directory slots (%u found thus far)",
-                                     iSlot, pSignature->cCodeDirs + 1);
-            if (   pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_CODEDIRECTORY
-                && pSignature->cCodeDirs > 0)
-                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
-                                     "Slot #%u: Already have primary code directory in slot #%u",
-                                     iSlot, pSignature->aCodeDirs[0].uSlot);
-            if (   pSuper->aSlots[iSlot].uType != RTCRAPLCS_SLOT_CODEDIRECTORY /* lazy bird */
-                && pSignature->cCodeDirs == 0)
-                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
-                                     "Slot #%u: Expected alternative code directory after the primary one", iSlot);
-            if (cbMaxData < RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, uUnused))
-                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
-                                     "Slot #%u: Insufficient data vailable for code directory (max %#x)", iSlot, cbMaxData);
-
-            PCRTCRAPLCSCODEDIRECTORY pCodeDir = (PCRTCRAPLCSCODEDIRECTORY)&pThis->PtrCodeSignature.pb[offData];
-            if (pCodeDir->Hdr.uMagic != RTCRAPLCS_MAGIC_CODEDIRECTORY)
-                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
-                                     "Slot #%u: Invalid code directory magic: %#x", iSlot, RT_BE2H_U32(pCodeDir->Hdr.uMagic));
-            uint32_t const cb = RT_BE2H_U32(pCodeDir->Hdr.cb);
-            if (cb > cbMaxData || cb < RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, offScatter))
-                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
-                                     "Slot #%u: Code directory size is out of bound: %#x (min %#x, max %#x)",
-                                     iSlot, cb, RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, offScatter), cbMaxData);
-/** @todo validate all the fields we wish to use here. */
-
-            pSignature->aCodeDirs[pSignature->cCodeDirs].pCodeDir = pCodeDir;
-            pSignature->aCodeDirs[pSignature->cCodeDirs].uSlot    = iSlot;
-            pSignature->aCodeDirs[pSignature->cCodeDirs].cb       = cb;
-            pSignature->cCodeDirs++;
-        }
-        /*
          * PKCS#7/CMS signature.
          */
-        else if (pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_SIGNATURE)
+        if (pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_SIGNATURE)
         {
             if (pSignature->idxPkcs7 != UINT32_MAX)
@@ -4115,4 +4095,206 @@
             pSignature->pbPkcs7  = (uint8_t const *)(pHdr + 1);
             pSignature->cbPkcs7  = cb - sizeof(*pHdr);
+        }
+        /*
+         * Code directories.
+         */
+        else if (   pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_CODEDIRECTORY
+                 || (  RT_BE2H_U32(pSuper->aSlots[iSlot].uType) - RT_BE2H_U32_C(RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES)
+                     < RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_COUNT))
+        {
+            /* Make sure we don't get too many code directories and that the first one is a regular one. */
+            if (pSignature->cCodeDirs >= RT_ELEMENTS(pSignature->aCodeDirs))
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Too many code directory slots (%u found thus far)",
+                                     iSlot, pSignature->cCodeDirs + 1);
+            if (   pSuper->aSlots[iSlot].uType == RTCRAPLCS_SLOT_CODEDIRECTORY
+                && pSignature->cCodeDirs > 0)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Already have primary code directory in slot #%u",
+                                     iSlot, pSignature->aCodeDirs[0].uSlot);
+            if (   pSuper->aSlots[iSlot].uType != RTCRAPLCS_SLOT_CODEDIRECTORY /* lazy bird */
+                && pSignature->cCodeDirs == 0)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Expected alternative code directory after the primary one", iSlot);
+
+            /* Check data header: */
+            if (cbMaxData < RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, uUnused1))
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Insufficient data vailable for code directory (max %#x)", iSlot, cbMaxData);
+
+            PCRTCRAPLCSCODEDIRECTORY pCodeDir = (PCRTCRAPLCSCODEDIRECTORY)&pThis->PtrCodeSignature.pb[offData];
+            if (pCodeDir->Hdr.uMagic != RTCRAPLCS_MAGIC_CODEDIRECTORY)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Invalid code directory magic: %#x", iSlot, RT_BE2H_U32(pCodeDir->Hdr.uMagic));
+            uint32_t const cbCodeDir = RT_BE2H_U32(pCodeDir->Hdr.cb);
+            if (cbCodeDir > cbMaxData || cbCodeDir < RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, offScatter))
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Code directory size is out of bound: %#x (min %#x, max %#x)",
+                                     iSlot, cbCodeDir, RT_UOFFSETOF(RTCRAPLCSCODEDIRECTORY, offScatter), cbMaxData);
+            pSignature->aCodeDirs[pSignature->cCodeDirs].pCodeDir = pCodeDir;
+            pSignature->aCodeDirs[pSignature->cCodeDirs].cb       = cbCodeDir;
+
+            /* Check Version: */
+            uint32_t const uVersion = RT_BE2H_U32(pCodeDir->uVersion);
+            if (   uVersion < RTCRAPLCS_VER_2_0
+                || uVersion >= RT_MAKE_U32(0, 3))
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Code directory version is out of bounds: %#07x", iSlot, uVersion);
+            uint32_t cbSelf = uVersion >= RTCRAPLCS_VER_SUPPORTS_EXEC_SEG      ? RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, fExecSeg)
+                            : uVersion >= RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 ? RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, cbCodeLimit64)
+                            : uVersion >= RTCRAPLCS_VER_SUPPORTS_TEAMID        ? RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, offTeamId)
+                            : uVersion >= RTCRAPLCS_VER_SUPPORTS_SCATTER       ? RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, offScatter)
+                            :                                                    RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, uUnused1);
+            if (cbSelf > cbCodeDir)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Code directory size is out of bound: %#x (min %#x, max %#x)",
+                                     iSlot, cbCodeDir, cbSelf, cbCodeDir);
+
+            /* hash type and size. */
+            uint8_t      cbHash;
+            RTDIGESTTYPE enmDigest;
+            switch (pCodeDir->bHashType)
+            {
+                case RTCRAPLCS_HASHTYPE_SHA1:
+                    enmDigest = RTDIGESTTYPE_SHA1;
+                    cbHash    = RTSHA1_HASH_SIZE;
+                    break;
+                case RTCRAPLCS_HASHTYPE_SHA256:
+                    enmDigest = RTDIGESTTYPE_SHA256;
+                    cbHash    = RTSHA256_HASH_SIZE;
+                    break;
+                case RTCRAPLCS_HASHTYPE_SHA256_TRUNCATED:
+                    enmDigest = RTDIGESTTYPE_SHA256;
+                    cbHash    = RTSHA1_HASH_SIZE; /* truncated to SHA-1 size. */
+                    break;
+                case RTCRAPLCS_HASHTYPE_SHA384:
+                    enmDigest = RTDIGESTTYPE_SHA384;
+                    cbHash    = RTSHA384_HASH_SIZE;
+                    break;
+                default:
+                    return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT, "Slot #%u: Unknown hash type %#x (LB %#x)",
+                                         iSlot, pCodeDir->bHashType, pCodeDir->cbHash);
+            }
+            pSignature->aCodeDirs[pSignature->cCodeDirs].enmDigest = enmDigest;
+            if (pCodeDir->cbHash != cbHash)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Unexpected hash size for %s: %#x, expected %#x",
+                                     iSlot, RTCrDigestTypeToName(enmDigest), pCodeDir->cbHash, cbHash);
+
+            /* Hash slot offset and counts. Special slots are counted backwards from offHashSlots. */
+            uint32_t const cSpecialSlots = RT_BE2H_U32(pCodeDir->cSpecialSlots);
+            if (cSpecialSlots > 256)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Too many special slots: %#x", iSlot, cSpecialSlots);
+            uint32_t const cCodeSlots = RT_BE2H_U32(pCodeDir->cCodeSlots);
+            if (   cCodeSlots >= UINT32_MAX / 2
+                || cCodeSlots + cSpecialSlots > (cbCodeDir - cbHash) / cbHash)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT, "Slot #%u: Too many code slots: %#x + %#x (max %#x)",
+                                     iSlot, cCodeSlots, cSpecialSlots, (cbCodeDir - cbHash) / cbHash);
+            uint32_t const offHashSlots = RT_BE2H_U32(pCodeDir->offHashSlots);
+            if (   offHashSlots > cbCodeDir - cCodeSlots * cbHash
+                || offHashSlots < cbSelf + cSpecialSlots * cbHash)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Code directory hash offset is out of bounds: %#x (min: %#x, max: %#x)",
+                                     iSlot, offHashSlots, cbSelf + cSpecialSlots * cbHash, cbCodeDir - cCodeSlots * cbHash);
+
+            /* page shift */
+            if (pCodeDir->cPageShift == 0)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Unsupported page shift of zero in code directory", iSlot);
+            uint32_t cMaxPageShift;
+            if (   pThis->Core.enmArch == RTLDRARCH_AMD64
+                || pThis->Core.enmArch == RTLDRARCH_X86_32
+                || pThis->Core.enmArch == RTLDRARCH_ARM32)
+                cMaxPageShift = 12;
+            else if (pThis->Core.enmArch == RTLDRARCH_ARM64)
+                cMaxPageShift = 16; /* 16KB */
+            else
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT, "Unsupported architecture: %d", pThis->Core.enmArch);
+            if (   pCodeDir->cPageShift < 12 /* */
+                || pCodeDir->cPageShift > cMaxPageShift)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Page shift in code directory is out of range: %d (min: 12, max: %d)",
+                                     iSlot, pCodeDir->cPageShift, cMaxPageShift);
+
+            /* code limit vs page shift and code hash slots */
+            uint32_t const cbCodeLimit32       = RT_BE2H_U32(pCodeDir->cbCodeLimit32);
+            uint32_t const cExpectedCodeHashes = pCodeDir->cPageShift == 0 ? 1
+                                               : (cbCodeLimit32 + RT_BIT_32(pCodeDir->cPageShift) - 1) >> pCodeDir->cPageShift;
+            if (cExpectedCodeHashes != cCodeSlots)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Code limit and page shift value does not match code hash slots: cbCodeLimit32=%#x cPageShift=%u -> %#x; cCodeSlots=%#x",
+                                     iSlot, cbCodeLimit32, pCodeDir->cPageShift, cExpectedCodeHashes, cCodeSlots);
+
+            /* Identifier offset: */
+            if (pCodeDir->offIdentifier)
+            {
+                uint32_t const offIdentifier = RT_BE2H_U32(pCodeDir->offIdentifier);
+                if (   offIdentifier < cbSelf
+                    || offIdentifier >= cbCodeDir)
+                    return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                         "Slot #%u: Identifier offset is out of bounds: %#x (min: %#x, max: %#x)",
+                                         iSlot, offIdentifier, cbSelf, cbCodeDir - 1);
+                int rc = RTStrValidateEncodingEx((char const *)pCodeDir + offIdentifier, cbCodeDir - offIdentifier,
+                                                 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+                if (RT_FAILURE(rc))
+                    return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                         "Slot #%u: Malformed identifier string: %Rrc", iSlot, rc);
+            }
+
+            /* Team identifier: */
+            if (cbSelf >= RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, offTeamId) && pCodeDir->offTeamId)
+            {
+                uint32_t const offTeamId = RT_BE2H_U32(pCodeDir->offTeamId);
+                if (   offTeamId < cbSelf
+                    || offTeamId >= cbCodeDir)
+                    return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                         "Slot #%u: Team identifier offset is out of bounds: %#x (min: %#x, max: %#x)",
+                                         iSlot, offTeamId, cbSelf, cbCodeDir - 1);
+                int rc = RTStrValidateEncodingEx((char const *)pCodeDir + offTeamId, cbCodeDir - offTeamId,
+                                                 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+                if (RT_FAILURE(rc))
+                    return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                         "Slot #%u: Malformed team identifier string: %Rrc", iSlot, rc);
+            }
+
+            /* We don't support scatter. */
+            if (cbSelf >= RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, offScatter) && pCodeDir->offScatter)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Scatter not supported.", iSlot);
+
+            /* We don't really support the 64-bit code limit either: */
+            if (   cbSelf >= RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, cbCodeLimit64)
+                && pCodeDir->cbCodeLimit64
+                && RT_BE2H_U64(pCodeDir->cbCodeLimit64) != cbCodeLimit32)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: 64-bit code limit does not match 32-bit: %#RX64 vs %#RX32",
+                                     iSlot, RT_BE2H_U64(pCodeDir->cbCodeLimit64), cbCodeLimit32);
+
+            /* Check executable segment info if present: */
+            if (   cbSelf >= RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, fExecSeg)
+                && (   pThis->offSeg0ForCodeSign != RT_BE2H_U64(pCodeDir->offExecSeg)
+                    || pThis->cbSeg0ForCodeSign != RT_BE2H_U64(pCodeDir->cbExecSeg)
+                    || pThis->fSeg0ForCodeSign != RT_BE2H_U64(pCodeDir->fFlags)) )
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Segment #0 info mismatch: @%#RX64 LB %#RX64 flags=%#RX64; expected @%#RX64 LB %#RX64 flags=%#RX64",
+                                     iSlot, RT_BE2H_U64(pCodeDir->offExecSeg), RT_BE2H_U64(pCodeDir->cbExecSeg),
+                                     RT_BE2H_U64(pCodeDir->fExecSeg), pThis->offSeg0ForCodeSign, pThis->cbSeg0ForCodeSign,
+                                     pThis->fSeg0ForCodeSign);
+
+            /* Check fields that must be zero (don't want anyone to use them to counter changes): */
+            if (pCodeDir->uUnused1 != 0)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Unused field #1 is non-zero: %#x", iSlot, RT_BE2H_U32(pCodeDir->uUnused1));
+            if (   cbSelf >= RT_UOFFSET_AFTER(RTCRAPLCSCODEDIRECTORY, uUnused2)
+                && pCodeDir->uUnused2 != 0)
+                return RTErrInfoSetF(pErrInfo, VERR_LDRVI_BAD_CERT_FORMAT,
+                                     "Slot #%u: Unused field #2 is non-zero: %#x", iSlot, RT_BE2H_U32(pCodeDir->uUnused2));
+
+            /** @todo idPlatform values.   */
+
+
+            /* Commit the code dir entry: */
+            pSignature->aCodeDirs[pSignature->cCodeDirs++].uSlot = iSlot;
         }
     }
