--- /dev/null
+/*
+ * Copyright (c) 2006-2012 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@
+ */
+
+//
+// signerutils - utilities for signature generation
+//
+#ifndef _H_SIGNERUTILS
+#define _H_SIGNERUTILS
+
+#include "CodeSigner.h"
+#include "sigblob.h"
+#include "cdbuilder.h"
+#include <security_utilities/utilities.h>
+#include <security_utilities/blob.h>
+#include <security_utilities/unix++.h>
+#include <security_utilities/unixchild.h>
+
+namespace Security {
+namespace CodeSigning {
+
+
+//
+// A helper to deal with the magic merger logic of internal requirements
+//
+class InternalRequirements : public Requirements::Maker {
+public:
+ InternalRequirements() : mReqs(NULL) { }
+ ~InternalRequirements() { ::free((void *)mReqs); }
+ void operator () (const Requirements *given, const Requirements *defaulted, const Requirement::Context &context);
+ operator const Requirements * () const { return mReqs; }
+
+private:
+ const Requirements *mReqs;
+};
+
+
+//
+// A DiskRep::Writer that assembles data in a SuperBlob (in memory)
+//
+class BlobWriter : public DiskRep::Writer, public EmbeddedSignatureBlob::Maker {
+public:
+ void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
+};
+
+
+class DetachedBlobWriter : public BlobWriter {
+public:
+ DetachedBlobWriter(SecCodeSigner::Signer &s) : signer(s) { }
+
+ SecCodeSigner::Signer &signer;
+
+ void flush();
+};
+
+
+//
+// A multi-architecture editing assistant.
+// ArchEditor collects (Mach-O) architectures in use, and maintains per-archtitecture
+// data structures. It must be subclassed to express a particular way to handle the signing
+// data.
+//
+class ArchEditor : public DiskRep::Writer {
+public:
+ ArchEditor(Universal &fat, CodeDirectory::HashAlgorithm hashType, uint32_t attrs);
+ virtual ~ArchEditor();
+
+public:
+ //
+ // One architecture's signing construction element.
+ // This also implements DispRep::Writer so generic writing code
+ // can work with both Mach-O and other files.
+ //
+ struct Arch : public BlobWriter {
+ Architecture architecture; // our architecture
+ auto_ptr<MachO> source; // Mach-O object to be signed
+ CodeDirectory::Builder cdbuilder; // builder for CodeDirectory
+ InternalRequirements ireqs; // consolidated internal requirements
+ size_t blobSize; // calculated SuperBlob size
+
+ Arch(const Architecture &arch, CodeDirectory::HashAlgorithm hashType)
+ : architecture(arch), cdbuilder(hashType) { }
+ };
+
+ //
+ // Our callers access the architectural universe through a map
+ // from Architectures to Arch objects.
+ //
+ typedef std::map<Architecture, Arch *> ArchMap;
+ typedef ArchMap::iterator Iterator;
+ ArchMap::iterator begin() { return architecture.begin(); }
+ ArchMap::iterator end() { return architecture.end(); }
+ unsigned count() const { return (unsigned)architecture.size(); }
+
+ // methods needed for an actual implementation
+ virtual void allocate() = 0; // interpass allocations
+ virtual void reset(Arch &arch) = 0; // pass 2 prep
+ virtual void write(Arch &arch, EmbeddedSignatureBlob *blob) = 0; // takes ownership of blob
+ virtual void commit() = 0; // write/flush result
+
+protected:
+ ArchMap architecture;
+};
+
+
+//
+// An ArchEditor that collects all architectures into a single SuperBlob,
+// usually for writing a detached multi-architecture signature.
+//
+class BlobEditor : public ArchEditor {
+public:
+ BlobEditor(Universal &fat, SecCodeSigner::Signer &s);
+
+ SecCodeSigner::Signer &signer;
+
+ void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
+ void allocate() { }
+ void reset(Arch &arch) { }
+ void write(Arch &arch, EmbeddedSignatureBlob *blob);
+ void commit();
+
+private:
+ DetachedSignatureBlob::Maker mMaker;
+ EmbeddedSignatureBlob::Maker mGlobal;
+};
+
+
+//
+// An ArchEditor that writes its signatures into a (fat) binary file.
+// We do this by forking a helper tool (codesign_allocate) and asking
+// it to make a copy with suitable space "opened up" in the right spots.
+//
+class MachOEditor : public ArchEditor, private UnixPlusPlus::Child {
+public:
+ MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithm hashType, std::string srcPath);
+ ~MachOEditor();
+
+ const RefPointer<DiskRep::Writer> writer;
+ const std::string sourcePath;
+ const std::string tempPath;
+
+ void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
+ void allocate();
+ void reset(Arch &arch);
+ void write(Arch &arch, EmbeddedSignatureBlob *blob);
+ void commit();
+
+private:
+ // fork operation
+ void childAction();
+ void parentAction();
+
+ // controlling the temporary file copy
+ Universal *mNewCode;
+ UnixPlusPlus::AutoFileDesc mFd;
+ bool mTempMayExist;
+
+ // finding and managing the helper tool
+ const char *mHelperPath;
+ bool mHelperOverridden;
+};
+
+
+//
+// A Requirement::Context populated from a signing request.
+// We use this to help generate the explicit Designated Requirement
+// during signing ops, and thus this must be constructed BEFORE we
+// actually have a signed object.
+//
+class PreSigningContext : public Requirement::Context {
+public:
+ PreSigningContext(const SecCodeSigner::Signer &signer);
+
+private:
+ CFRef<CFArrayRef> mCerts; // hold cert chain
+};
+
+
+} // end namespace CodeSigning
+} // end namespace Security
+
+#endif // !_H_SIGNERUTILS