X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_codesigning/lib/cdbuilder.cpp diff --git a/Security/libsecurity_codesigning/lib/cdbuilder.cpp b/Security/libsecurity_codesigning/lib/cdbuilder.cpp deleted file mode 100644 index 61900bc1..00000000 --- a/Security/libsecurity_codesigning/lib/cdbuilder.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2006-2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -// -// cdbuilder - constructor for CodeDirectories -// -#include "cdbuilder.h" -#include -#include - -using namespace UnixPlusPlus; -using LowLevelMemoryUtilities::alignUp; - - -namespace Security { -namespace CodeSigning { - - -// -// Create an (empty) builder -// -CodeDirectory::Builder::Builder(HashAlgorithm digestAlgorithm) - : mFlags(0), - mHashType(digestAlgorithm), - mSpecialSlots(0), - mCodeSlots(0), - mScatter(NULL), - mScatterSize(0), - mDir(NULL) -{ - mDigestLength = (uint32_t)MakeHash(this)->digestLength(); - mSpecial = (unsigned char *)calloc(cdSlotMax, mDigestLength); -} - -CodeDirectory::Builder::~Builder() -{ - ::free(mSpecial); - ::free(mScatter); -} - - -// -// Set the source of the main executable (i.e. the code pages) -// -void CodeDirectory::Builder::executable(string path, - size_t pagesize, size_t offset, size_t length) -{ - mExec.close(); // any previously opened one - mExec.open(path); - mPageSize = pagesize; - mExecOffset = offset; - mExecLength = length; -} - -void CodeDirectory::Builder::reopen(string path, size_t offset, size_t length) -{ - assert(mExec); // already called executable() - mExec.close(); - mExec.open(path); - mExecOffset = offset; - mExecLength = length; -} - - -// -// Set the source for one special slot -// -void CodeDirectory::Builder::specialSlot(SpecialSlot slot, CFDataRef data) -{ - assert(slot <= cdSlotMax); - MakeHash 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; -} - -// This calculates the fixed size of the code directory -// Because of , if the team ID -// field is not used, we leave out the team ID offset -// as well, to keep cd hashes consistent between -// versions. -const size_t CodeDirectory::Builder::fixedSize(const uint32_t version) -{ - size_t cdSize = sizeof(CodeDirectory); - if (version < supportsTeamID) - cdSize -= sizeof(mDir->teamIDOffset); - - return cdSize; -} - -// -// Calculate the size we'll need for the CodeDirectory as described so far -// -size_t CodeDirectory::Builder::size(const uint32_t version) -{ - assert(mExec); // must have called executable() - if (mExecLength == 0) - mExecLength = mExec.fileSize() - mExecOffset; - - // how many code pages? - if (mPageSize == 0) { // indefinite - one page - mCodeSlots = (mExecLength > 0); - } else { // finite - calculate from file size - mCodeSlots = (mExecLength + mPageSize - 1) / mPageSize; // round up - } - - size_t offset = fixedSize(version); - - offset += mScatterSize; // scatter vector - offset += mIdentifier.size() + 1; // size of identifier (with null byte) - if (mTeamID.size()) - offset += mTeamID.size() + 1; // size of teamID (with null byte) - offset += (mCodeSlots + mSpecialSlots) * mDigestLength; // hash vector - - return offset; -} - - -// -// Take everything added to date and wrap it up in a shiny new CodeDirectory. -// -// 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() -{ - assert(mExec); // must have (successfully) called executable() - uint32_t version; - - // size and allocate - size_t identLength = mIdentifier.size() + 1; - size_t teamIDLength = mTeamID.size() + 1; - - // Determine the version - if (mTeamID.size()) { - version = currentVersion; - } else { - version = supportsScatter; - } - - size_t total = size(version); - if (!(mDir = (CodeDirectory *)calloc(1, total))) // initialize to zero - UnixError::throwMe(ENOMEM); - - // fill header - mDir->initialize(total); - mDir->version = version; - mDir->flags = mFlags; - mDir->nSpecialSlots = (uint32_t)mSpecialSlots; - mDir->nCodeSlots = (uint32_t)mCodeSlots; - mDir->codeLimit = (uint32_t)mExecLength; - mDir->hashType = mHashType; - mDir->hashSize = mDigestLength; - if (mPageSize) { - int pglog; - assert(frexp(mPageSize, &pglog) == 0.5); // must be power of 2 - frexp(mPageSize, &pglog); - assert(pglog < 256); - mDir->pageSize = pglog - 1; - } else - mDir->pageSize = 0; // means infinite page size - - // locate and fill flex fields - size_t offset = fixedSize(mDir->version); - - if (mScatter) { - mDir->scatterOffset = (uint32_t)offset; - memcpy(mDir->scatterVector(), mScatter, mScatterSize); - offset += mScatterSize; - } - - mDir->identOffset = (uint32_t)offset; - memcpy(mDir->identifier(), mIdentifier.c_str(), identLength); - offset += identLength; - - if (mTeamID.size()) { - mDir->teamIDOffset = (uint32_t)offset; - memcpy(mDir->teamID(), mTeamID.c_str(), teamIDLength); - offset += teamIDLength; - } - // (add new flexibly-allocated fields here) - - mDir->hashOffset = (uint32_t)(offset + mSpecialSlots * mDigestLength); - offset += (mSpecialSlots + mCodeSlots) * mDigestLength; - assert(offset == total); // matches allocated size - - // fill special slots - memset((*mDir)[(int)-mSpecialSlots], 0, mDigestLength * mSpecialSlots); - for (size_t slot = 1; slot <= mSpecialSlots; ++slot) - memcpy((*mDir)[(int)-slot], specialSlot((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); - MakeHash hasher(this); - generateHash(hasher, mExec, (*mDir)[slot], thisPage); - remaining -= thisPage; - } - - // all done. Pass ownership to caller - return mDir; -} - - -} // CodeSigning -} // Security