X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cdsa_utilities/lib/osxverifier.cpp?ds=inline diff --git a/Security/libsecurity_cdsa_utilities/lib/osxverifier.cpp b/Security/libsecurity_cdsa_utilities/lib/osxverifier.cpp new file mode 100644 index 00000000..3bf4520b --- /dev/null +++ b/Security/libsecurity_cdsa_utilities/lib/osxverifier.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved. + * + * The contents of this file constitute Original Code as defined in and are + * subject to the Apple Public Source License Version 1.2 (the 'License'). + * You may not use this file except in compliance with the License. Please obtain + * a copy of the License at http://www.apple.com/publicsource and read it before + * using this file. + * + * This 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. + */ + + +// +// osxsigner - MacOS X's standard code signing algorithm. +// +#include +#include +#include +#include +#include +#include +#include // debug only + + +using namespace CodeSigning; + + +namespace Security { + + +// +// Create a Verifier from a code object. +// +// This does not add any auxiliary information blobs. You can do that +// by calling add() after construction, of course. +// +OSXVerifier::OSXVerifier(OSXCode *code) +{ + mPath = code->canonicalPath(); + secdebug("codesign", "building verifier for %s", mPath.c_str()); + + // build new-style verifier + CFRef staticCode = code->codeRef(); + switch (OSStatus rc = SecCodeCopyDesignatedRequirement(staticCode, + kSecCSDefaultFlags, &mRequirement.aref())) { + case errSecSuccess: + secdebug("codesign", " is signed; canonical requirement loaded"); + break; + case errSecCSUnsigned: + secdebug("codesign", " is unsigned; no requirement"); + break; + default: + MacOSError::throwMe(rc); + } + + // build old-style verifier + makeLegacyHash(code, mLegacyHash); + secdebug("codesign", " hash generated"); +} + + +// +// Create a Verifier from hash, path, and requirement. +// Again, this has no auxiliary data when constructed. +// +OSXVerifier::OSXVerifier(const SHA1::Byte *hash, const std::string &path) + : mPath(path) +{ + secdebug("codesign", "building verifier from hash %p and path=%s", hash, path.c_str()); + if (hash) + memcpy(mLegacyHash, hash, sizeof(mLegacyHash)); + else + memset(mLegacyHash, 0, sizeof(mLegacyHash)); +} + + +OSXVerifier::~OSXVerifier() +{ + secdebug("codesign", "%p verifier destroyed", this); +} + + +// +// Add an auxiliary comment blob. +// Note that we only allow one auxiliary blob for each magic number. +// +void OSXVerifier::add(const BlobCore *blob) +{ + if (blob->is()) { +#if defined(NDEBUG) + secdebug("codesign", "%p verifier adds requirement", this); +#else + secdebug("codesign", "%p verifier adds requirement %s", this, + Dumper::dump(Requirement::specific(blob), true).c_str()); +#endif //NDEBUG + MacOSError::check(SecRequirementCreateWithData(CFTempData(*blob), + kSecCSDefaultFlags, &mRequirement.aref())); + } else { + secdebug("codesign", "%p verifier adds blob (0x%x,%zd)", + this, blob->magic(), blob->length()); + BlobCore * &slot = mAuxiliary[blob->magic()]; + if (slot) + ::free(slot); + slot = blob->clone(); + } +} + + +// +// Find a comment blob, by magic number +// +const BlobCore *OSXVerifier::find(BlobCore::Magic magic) +{ + AuxMap::const_iterator it = mAuxiliary.find(magic); + return (it == mAuxiliary.end()) ? NULL : it->second; +} + + +void OSXVerifier::makeLegacyHash(OSXCode *code, SHA1::Digest digest) +{ + secdebug("codesign", "calculating legacy hash for %s", code->canonicalPath().c_str()); + UnixPlusPlus::AutoFileDesc fd(code->executablePath(), O_RDONLY); + char buffer[legacyHashLimit]; + size_t size = fd.read(buffer, legacyHashLimit); + SHA1 hash; + hash(buffer, size); + hash.finish(digest); +} + + +// +// The AuxMap helper class provides a map-to-Blob-pointers with automatic memory management. +// +OSXVerifier::AuxMap::AuxMap(const OSXVerifier::AuxMap &src) +{ + for (const_iterator it = src.begin(); it != src.end(); it++) + this->insert(*it); +} + +OSXVerifier::AuxMap::~AuxMap() +{ + for (const_iterator it = this->begin(); it != this->end(); ++it) + ::free(it->second); +} + + +#if DEBUGDUMP + +void OSXVerifier::dump() const +{ + static const SHA1::Digest nullDigest = { 0 }; + if (!memcmp(mLegacyHash, nullDigest, sizeof(mLegacyHash))) { + Debug::dump("(no hash)"); + } else { + Debug::dump("oldHash="); + Debug::dumpData(mLegacyHash, sizeof(mLegacyHash)); + } + if (mRequirement) { + CFRef reqData; + if (!SecRequirementCopyData(mRequirement, 0, &reqData.aref())) { + Debug::dump(" Requirement =>"); + ((const Requirement *)CFDataGetBytePtr(reqData))->dump(); + } + } else { + Debug::dump(" NO REQ"); + } +} + +#endif //DEBUGDUMP + +} // end namespace Security