]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_codesigning/lib/codedirectory.h
Security-59306.11.20.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / codedirectory.h
index 9e074099b620d40d1401fc297a5e530289ff34c9..eae6649fe4022f43018d88287466a122135be1e1 100644 (file)
@@ -47,6 +47,7 @@
 #include <security_utilities/cfutilities.h>
 #include <security_utilities/hashing.h>
 #include <Security/CSCommonPriv.h>
+#include <set>
 
 
 namespace Security {
@@ -61,9 +62,10 @@ namespace CodeSigning {
 #define kSecCS_SIGNATUREFILE           "CodeSignature"         // CMS Signature
 #define kSecCS_REQUIREMENTSFILE                "CodeRequirements"      // internal requirements
 #define kSecCS_RESOURCEDIRFILE         "CodeResources"         // resource directory
-#define kSecCS_APPLICATIONFILE         "CodeApplication"       // application-specific resource
 #define kSecCS_ENTITLEMENTFILE         "CodeEntitlements"      // entitlement configuration
-
+#define kSecCS_REPSPECIFICFILE         "CodeRepSpecific"       // DiskRep-specific use slot
+#define kSecCS_TOPDIRECTORYFILE                "CodeTopDirectory"      // Top-level directory list
+#define kSecCS_ENTITLEMENTDERFILE      "CodeEntitlementDER" // DER entitlement representation
 
 //
 // Special hash slot values. In a CodeDirectory, these show up at negative slot
@@ -88,8 +90,10 @@ enum {
        cdInfoSlot = 1,                                         // Info.plist
        cdRequirementsSlot = 2,                         // internal requirements
        cdResourceDirSlot = 3,                          // resource directory
-       cdApplicationSlot = 4,                          // Application specific slot
+       cdTopDirectorySlot = 4,                         // Application specific slot
        cdEntitlementSlot = 5,                          // embedded entitlement configuration
+       cdRepSpecificSlot = 6,                          // for use by disk rep
+       cdEntitlementDERSlot = 7,                       // DER representation of entitlements
        // (add further primary slot numbers here)
 
        cdSlotCount,                                            // total number of special slots (+1 for slot 0)
@@ -105,8 +109,11 @@ enum {
        // It's okay to have large gaps in these assignments.
        //
        cdCodeDirectorySlot = 0,                        // CodeDirectory
+       cdAlternateCodeDirectorySlots = 0x1000, // alternate CodeDirectory array
+       cdAlternateCodeDirectoryLimit = 0x1005, // 5+1 hashes should be enough for everyone...
        cdSignatureSlot = 0x10000,                      // CMS signature
-       cdIdentificationSlot,                           // identification blob
+       cdIdentificationSlot,                           // identification blob (detached signatures only)
+       cdTicketSlot,                                           // ticket embedded in signature (DMG only)
        // (add further virtual slot numbers here)
 };
 
@@ -191,39 +198,64 @@ public:
        Endian<uint32_t> spare2;                // unused (must be zero)
        Endian<uint32_t> scatterOffset; // offset of optional scatter vector (zero if absent)
        Endian<uint32_t> teamIDOffset;  // offset of optional teamID string
-       
+       Endian<uint32_t> spare3;                // unused (most be zero)
+       Endian<uint64_t> codeLimit64;   // limit to main image signature range, 64 bits
+       Endian<uint64_t> execSegBase;   // offset of executable segment
+       Endian<uint64_t> execSegLimit;  // limit of executable segment
+       Endian<uint64_t> execSegFlags;  // exec segment flags
+
+       Endian<uint32_t> runtime;                       // Runtime version encoded as an unsigned int
+       Endian<uint32_t> preEncryptOffset;      // offset of pre-encrypt hash slots
+
        // works with the version field; see comments above
-       static const uint32_t currentVersion = 0x20200;         // "version 2.2"
+       static const uint32_t currentVersion = 0x20500;         // "version 2.5"
        static const uint32_t compatibilityLimit = 0x2F000;     // "version 3 with wiggle room"
        
        static const uint32_t earliestVersion = 0x20001;        // earliest supported version
        static const uint32_t supportsScatter = 0x20100;        // first version to support scatter option
-       static const uint32_t supportsTeamID = 0x20200; // first version to support team ID option
-       
+       static const uint32_t supportsTeamID = 0x20200;         // first version to support team ID option
+       static const uint32_t supportsCodeLimit64 = 0x20300; // first version to support codeLimit64
+       static const uint32_t supportsExecSegment = 0x20400; // first version to support exec base and limit
+       static const uint32_t supportsPreEncrypt = 0x20500; // first version to support pre-encrypt hashes and runtime version
+
        void checkIntegrity() const;    // throws if inconsistent or unsupported version
 
        typedef uint32_t HashAlgorithm; // types of internal glue hashes
+       typedef std::set<HashAlgorithm> HashAlgorithms;
        typedef int Slot;                               // slot index (negative for special slots)
        typedef unsigned int SpecialSlot; // positive special slot index (not for code slots)
        
        const char *identifier() const { return at<const char>(identOffset); }
        char *identifier() { return at<char>(identOffset); }
+       
+       size_t signingLimit() const
+               { return (version >= supportsCodeLimit64 && codeLimit64) ? size_t(codeLimit64) : size_t(codeLimit); }
     
        // main hash array access
        SpecialSlot maxSpecialSlot() const;
                
-       unsigned char *operator [] (Slot slot)
+       unsigned char *getSlotMutable (Slot slot, bool preEncrypt)
        {
                assert(slot >= int(-nSpecialSlots) && slot < int(nCodeSlots));
-               return at<unsigned char>(hashOffset) + hashSize * slot;
+
+               if (preEncrypt) {
+                       if (version >= supportsPreEncrypt && preEncryptOffset != 0) {
+                               assert(slot >= 0);
+                               return at<unsigned char>(preEncryptOffset) + hashSize * slot;
+                       } else {
+                               return NULL;
+                       }
+               } else {
+                       return at<unsigned char>(hashOffset) + hashSize * slot;
+               }
        }
-       
-       const unsigned char *operator [] (Slot slot) const
+
+       const unsigned char *getSlot (Slot slot, bool preEncrypt) const
        {
-               assert(slot >= int(-nSpecialSlots) && slot < int(nCodeSlots));
-               return at<unsigned char>(hashOffset) + hashSize * slot;
+               CodeDirectory *cd = const_cast<CodeDirectory *>(this);
+               return const_cast<const unsigned char *>(cd->getSlotMutable(slot, preEncrypt));
        }
-       
+
        //
        // The main page hash array can be "scattered" across the code file
        // by specifying an array of Scatter elements, terminated with an
@@ -245,10 +277,18 @@ public:
 
        const char *teamID() const { return version >= supportsTeamID && teamIDOffset ? at<const char>(teamIDOffset) : NULL; }
        char *teamID() { return version >= supportsTeamID && teamIDOffset ? at<char>(teamIDOffset) : NULL; }
-    
+
+       uint64_t execSegmentBase() const { return (version >= supportsExecSegment) ? execSegBase.get() : 0; }
+       uint64_t execSegmentLimit() const { return (version >= supportsExecSegment) ? execSegLimit.get() : 0; }
+       uint64_t execSegmentFlags() const { return (version >= supportsExecSegment) ? execSegFlags.get() : 0; }
+
+       const unsigned char *preEncryptHashes() const { return getSlot(0, true); }
+
+       uint32_t runtimeVersion() const {return (version >= supportsPreEncrypt) ? runtime.get() : 0; }
+
 public:
-       bool validateSlot(const void *data, size_t size, Slot slot) const;                      // validate memory buffer against page slot
-       bool validateSlot(UnixPlusPlus::FileDesc fd, size_t size, Slot slot) const;     // read and validate file
+       bool validateSlot(const void *data, size_t size, Slot slot, bool preEncrypted) const;                   // validate memory buffer against page slot
+       bool validateSlot(UnixPlusPlus::FileDesc fd, size_t size, Slot slot, bool preEncrypted) const;  // read and validate file
        bool slotIsPresent(Slot slot) const;
        
        class Builder;
@@ -256,7 +296,13 @@ public:
 public:
        static DynamicHash *hashFor(HashAlgorithm hashType);            // create a DynamicHash subclass for (hashType) digests
        DynamicHash *getHash() const { return hashFor(this->hashType); } // make one for me
-       CFDataRef cdhash() const;
+       CFDataRef cdhash(bool truncate = true) const;
+       
+       static void multipleHashFileData(UnixPlusPlus::FileDesc fd, size_t limit, HashAlgorithms types, void (^action)(HashAlgorithm type, DynamicHash* hasher));
+    bool verifyMemoryContent(CFDataRef data, const Byte* digest) const;
+
+       static bool viableHash(HashAlgorithm type);
+       static HashAlgorithm bestHashOf(const HashAlgorithms& types);
 
        std::string hexHash(const unsigned char *hash) const;           // encode any canonical-type hash as a hex string