X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..dd5fb164cf5b32c462296bc65e289e100f74b59a:/OSX/libsecurity_codesigning/lib/signerutils.cpp?ds=inline diff --git a/OSX/libsecurity_codesigning/lib/signerutils.cpp b/OSX/libsecurity_codesigning/lib/signerutils.cpp index eb19d2d3..855d1949 100644 --- a/OSX/libsecurity_codesigning/lib/signerutils.cpp +++ b/OSX/libsecurity_codesigning/lib/signerutils.cpp @@ -33,6 +33,7 @@ #include "csutilities.h" #include "drmaker.h" #include +#include #include #include @@ -76,14 +77,14 @@ void DetachedBlobWriter::flush() // // ArchEditor // -ArchEditor::ArchEditor(Universal &code, CodeDirectory::HashAlgorithm hashType, uint32_t attrs) +ArchEditor::ArchEditor(Universal &code, CodeDirectory::HashAlgorithms hashTypes, uint32_t attrs) : DiskRep::Writer(attrs) { Universal::Architectures archList; code.architectures(archList); for (Universal::Architectures::const_iterator it = archList.begin(); it != archList.end(); ++it) - architecture[*it] = new Arch(*it, hashType); + architecture[*it] = new Arch(*it, hashTypes); } @@ -92,13 +93,21 @@ ArchEditor::~ArchEditor() for (ArchMap::iterator it = begin(); it != end(); ++it) delete it->second; } + + +ArchEditor::Arch::Arch(const Architecture &arch, CodeDirectory::HashAlgorithms hashTypes) + : architecture(arch) +{ + for (auto type = hashTypes.begin(); type != hashTypes.end(); ++type) + cdBuilders.insert(make_pair(*type, new CodeDirectory::Builder(*type))); +} // // BlobEditor // BlobEditor::BlobEditor(Universal &fat, SecCodeSigner::Signer &s) - : ArchEditor(fat, s.digestAlgorithm(), 0), signer(s) + : ArchEditor(fat, s.digestAlgorithms(), 0), signer(s) { } @@ -130,11 +139,12 @@ void BlobEditor::commit() // "drill up" the Mach-O binary for insertion of Code Signing signature data. // After the tool succeeds, we open the new file and are ready to write it. // -MachOEditor::MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithm hashType, std::string srcPath) - : ArchEditor(code, hashType, w->attributes()), +MachOEditor::MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithms hashTypes, std::string srcPath) + : ArchEditor(code, hashTypes, w->attributes()), writer(w), sourcePath(srcPath), tempPath(srcPath + ".cstemp"), + mHashTypes(hashTypes), mNewCode(NULL), mTempMayExist(false) { @@ -235,15 +245,19 @@ void MachOEditor::childAction() if (mHelperOverridden) ::csops(0, CS_OPS_MARKKILL, NULL, 0); // force code integrity - ::seteuid(0); // activate privilege if caller has it; ignore error if not + (void)::seteuid(0); // activate privilege if caller has it; ignore error if not execv(mHelperPath, (char * const *)&arguments[0]); } void MachOEditor::reset(Arch &arch) { arch.source.reset(mNewCode->architecture(arch.architecture)); - arch.cdbuilder.reopen(tempPath, - arch.source->offset(), arch.source->signingOffset()); + + for (auto type = mHashTypes.begin(); type != mHashTypes.end(); ++type) { + arch.eachDigest(^(CodeDirectory::Builder& builder) { + builder.reopen(tempPath, arch.source->offset(), arch.source->signingOffset()); + }); + } } @@ -262,7 +276,7 @@ void MachOEditor::write(Arch &arch, EmbeddedSignatureBlob *blob) arch.source->writeAll(*blob); ::free(blob); // done with it } else { - secdebug("signer", "%p cannot find CODESIGNING section", this); + secinfo("signer", "%p cannot find CODESIGNING data in Mach-O", this); MacOSError::throwMe(errSecCSInternalError); } } @@ -288,7 +302,7 @@ void MachOEditor::commit() // perform copy under root or file-owner privileges if available UidGuard guard; if (!guard.seteuid(0)) - guard.seteuid(st.st_uid); + (void)guard.seteuid(st.st_uid); // copy metadata from original file... copy(sourcePath.c_str(), NULL, COPYFILE_SECURITY | COPYFILE_METADATA); @@ -302,6 +316,7 @@ void MachOEditor::commit() UnixError::check(::rename(tempPath.c_str(), sourcePath.c_str())); mTempMayExist = false; // we renamed it away } + this->writer->flush(); } @@ -355,6 +370,62 @@ PreSigningContext::PreSigningContext(const SecCodeSigner::Signer &signer) // other stuff this->identifier = signer.signingIdentifier(); } + + +// +// A collector of CodeDirectories for hash-agile construction of signatures. +// +CodeDirectorySet::~CodeDirectorySet() +{ + for (auto it = begin(); it != end(); ++it) + ::free(const_cast(it->second)); +} + + +void CodeDirectorySet::add(const Security::CodeSigning::CodeDirectory *cd) +{ + insert(make_pair(cd->hashType, cd)); + if (cd->hashType == kSecCodeSignatureHashSHA1) + mPrimary = cd; +} + + +void CodeDirectorySet::populate(DiskRep::Writer *writer) const +{ + assert(!empty()); + + if (mPrimary == NULL) // didn't add SHA-1; pick another occupant for this slot + mPrimary = begin()->second; + + // reserve slot zero for a SHA-1 digest if present; else pick something else + CodeDirectory::SpecialSlot nextAlternate = cdAlternateCodeDirectorySlots; + for (auto it = begin(); it != end(); ++it) { + if (it->second == mPrimary) { + writer->codeDirectory(it->second, cdCodeDirectorySlot); + } else { + writer->codeDirectory(it->second, nextAlternate++); + } + } +} + + +const CodeDirectory* CodeDirectorySet::primary() const +{ + if (mPrimary == NULL) + mPrimary = begin()->second; + return mPrimary; +} + + +CFArrayRef CodeDirectorySet::hashBag() const +{ + CFRef hashList = makeCFMutableArray(0); + for (auto it = begin(); it != end(); ++it) { + CFRef cdhash = it->second->cdhash(); + CFArrayAppendValue(hashList, cdhash); + } + return hashList.yield(); +} } // end namespace CodeSigning