]> git.saurik.com Git - apple/libsecurity_codesigning.git/blobdiff - lib/cdbuilder.cpp
libsecurity_codesigning-55037.6.tar.gz
[apple/libsecurity_codesigning.git] / lib / cdbuilder.cpp
index eac0a4254ad0c6127ed000b1896d05c134ff44d5..ac17edbc4229db9fe62943c63404bd5c1887f028 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
+ * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved.
  * 
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -39,10 +39,23 @@ namespace CodeSigning {
 //
 // Create an (empty) builder
 //
-CodeDirectory::Builder::Builder()
-       : mFlags(0), mSpecialSlots(0), mCodeSlots(0), mDir(NULL)
+CodeDirectory::Builder::Builder(HashAlgorithm digestAlgorithm)
+       : mFlags(0),
+         mHashType(digestAlgorithm),
+         mSpecialSlots(0),
+         mCodeSlots(0),
+         mScatter(NULL),
+         mScatterSize(0),
+         mDir(NULL)
 {
-       memset(mSpecial, 0, sizeof(mSpecial));
+       mDigestLength = MakeHash<Builder>(this)->digestLength();
+       mSpecial = (unsigned char *)calloc(cdSlotMax, mDigestLength);
+}
+
+CodeDirectory::Builder::~Builder()
+{
+       ::free(mSpecial);
+       ::free(mScatter);
 }
 
 
@@ -72,17 +85,33 @@ void CodeDirectory::Builder::reopen(string path, size_t offset, size_t length)
 //
 // Set the source for one special slot
 //
-void CodeDirectory::Builder::special(size_t slot, CFDataRef data)
+void CodeDirectory::Builder::specialSlot(SpecialSlot slot, CFDataRef data)
 {
        assert(slot <= cdSlotMax);
-       Hash hash;
-       hash(CFDataGetBytePtr(data), CFDataGetLength(data));
-       hash.finish(mSpecial[slot]);
+       MakeHash<Builder> hash(this);
+       hash->update(CFDataGetBytePtr(data), CFDataGetLength(data));
+       hash->finish(specialSlot(slot));
        if (slot >= mSpecialSlots)
                mSpecialSlots = slot;
 }
 
 
+//
+// Allocate a Scatter vector
+//
+CodeDirectory::Scatter *CodeDirectory::Builder::scatter(unsigned count)
+{
+       mScatterSize = (count + 1) * sizeof(Scatter);
+       if (!(mScatter = (Scatter *)::realloc(mScatter, mScatterSize)))
+               UnixError::throwMe(ENOMEM);
+       ::memset(mScatter, 0, mScatterSize);
+       return mScatter;
+}
+
+
+//
+// Calculate the size we'll need for the CodeDirectory as described so far
+//
 size_t CodeDirectory::Builder::size()
 {
        assert(mExec);                  // must have called executable()
@@ -97,8 +126,9 @@ size_t CodeDirectory::Builder::size()
        }
                
        size_t offset = sizeof(CodeDirectory);
+       offset += mScatterSize;                         // scatter vector
        offset += mIdentifier.size() + 1;       // size of identifier (with null byte)
-       offset += (mCodeSlots + mSpecialSlots) * Hash::digestLength; // hash vector
+       offset += (mCodeSlots + mSpecialSlots) * mDigestLength; // hash vector
        return offset;
 }
 
@@ -106,9 +136,15 @@ size_t CodeDirectory::Builder::size()
 //
 // Take everything added to date and wrap it up in a shiny new CodeDirectory.
 //
-// Note that this doesn't include or generate the signature. You're free to
-// modify the result. But this function determines the memory layout, so the
-// sizes and counts should be correct on entry.
+// Note that this only constructs a CodeDirectory; it does not touch any subsidiary
+// structures (resource tables, etc.), nor does it create any signature to secure
+// the CodeDirectory.
+// The returned CodeDirectory object is yours, and you may modify it as desired.
+// But the memory layout is set here, so the various sizes and counts should be good
+// when you call build().
+// It's up to us to order the dynamic fields as we wish; but note that we currently
+// don't pad them, and so they should be allocated in non-increasing order of required
+// alignment. Make sure to keep the code here in sync with the size-calculating code above.
 //
 CodeDirectory *CodeDirectory::Builder::build()
 {
@@ -127,8 +163,8 @@ CodeDirectory *CodeDirectory::Builder::build()
        mDir->nSpecialSlots = mSpecialSlots;
        mDir->nCodeSlots = mCodeSlots;
        mDir->codeLimit = mExecLength;
-       mDir->hashSize = Hash::digestLength;
-       mDir->hashType = cdHashTypeDefault;
+       mDir->hashType = mHashType;
+       mDir->hashSize = mDigestLength;
        if (mPageSize) {
                int pglog;
                assert(frexp(mPageSize, &pglog) == 0.5); // must be power of 2
@@ -140,27 +176,35 @@ CodeDirectory *CodeDirectory::Builder::build()
 
        // locate and fill flex fields
        size_t offset = sizeof(CodeDirectory);
+
+       if (mScatter) {
+               mDir->scatterOffset = offset;
+               memcpy(mDir->scatterVector(), mScatter, mScatterSize);
+               offset += mScatterSize;
+       }
+
        mDir->identOffset = offset;
        memcpy(mDir->identifier(), mIdentifier.c_str(), identLength);
        offset += identLength;
 
        // (add new flexibly-allocated fields here)
 
-       mDir->hashOffset = offset + mSpecialSlots * Hash::digestLength;
-       offset += (mSpecialSlots + mCodeSlots) * Hash::digestLength;
+       mDir->hashOffset = offset + mSpecialSlots * mDigestLength;
+       offset += (mSpecialSlots + mCodeSlots) * mDigestLength;
        assert(offset == total);        // matches allocated size
        
        // fill special slots
-       memset((*mDir)[-mSpecialSlots], 0, mDir->hashSize * mSpecialSlots);
+       memset((*mDir)[-mSpecialSlots], 0, mDigestLength * mSpecialSlots);
        for (size_t slot = 1; slot <= mSpecialSlots; ++slot)
-               memcpy((*mDir)[-slot], &mSpecial[slot], Hash::digestLength);
+               memcpy((*mDir)[-slot], specialSlot(slot), mDigestLength);
        
        // fill code slots
        mExec.seek(mExecOffset);
        size_t remaining = mExecLength;
        for (unsigned int slot = 0; slot < mCodeSlots; ++slot) {
                size_t thisPage = min(mPageSize, remaining);
-               hash(mExec, (*mDir)[slot], thisPage);
+               MakeHash<Builder> hasher(this);
+               generateHash(hasher, mExec, (*mDir)[slot], thisPage);
                remaining -= thisPage;
        }