1/* 2 * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// 25// signerutils - utilities for signature generation 26// 27#ifndef _H_SIGNERUTILS 28#define _H_SIGNERUTILS 29 30#include "CodeSigner.h" 31#include "sigblob.h" 32#include "cdbuilder.h" 33#include <security_utilities/utilities.h> 34#include <security_utilities/blob.h> 35#include <security_utilities/unix++.h> 36#include <security_utilities/unixchild.h> 37 38namespace Security { 39namespace CodeSigning { 40 41 42// 43// A helper to deal with the magic merger logic of internal requirements 44// 45class InternalRequirements : public Requirements::Maker { 46public: 47 InternalRequirements() : mReqs(NULL) { } 48 ~InternalRequirements() { ::free((void *)mReqs); } 49 void operator () (const Requirements *given, const Requirements *defaulted, const Requirement::Context &context); 50 operator const Requirements * () const { return mReqs; } 51 52private: 53 const Requirements *mReqs; 54}; 55 56 57// 58// A DiskRep::Writer that assembles data in a SuperBlob (in memory) 59// 60class BlobWriter : public DiskRep::Writer, public EmbeddedSignatureBlob::Maker { 61public: 62 void component(CodeDirectory::SpecialSlot slot, CFDataRef data); 63}; 64 65 66class DetachedBlobWriter : public BlobWriter { 67public: 68 DetachedBlobWriter(SecCodeSigner::Signer &s) : signer(s) { } 69 70 SecCodeSigner::Signer &signer; 71 72 void flush(); 73}; 74 75 76// 77// A multi-architecture editing assistant. 78// ArchEditor collects (Mach-O) architectures in use, and maintains per-archtitecture 79// data structures. It must be subclassed to express a particular way to handle the signing 80// data. 81// 82class ArchEditor : public DiskRep::Writer { 83public: 84 ArchEditor(Universal &fat, CodeDirectory::HashAlgorithm hashType, uint32_t attrs); 85 virtual ~ArchEditor(); 86 87public: 88 // 89 // One architecture's signing construction element. 90 // This also implements DispRep::Writer so generic writing code 91 // can work with both Mach-O and other files. 92 // 93 struct Arch : public BlobWriter { 94 Architecture architecture; // our architecture 95 auto_ptr<MachO> source; // Mach-O object to be signed 96 CodeDirectory::Builder cdbuilder; // builder for CodeDirectory 97 InternalRequirements ireqs; // consolidated internal requirements 98 size_t blobSize; // calculated SuperBlob size 99 100 Arch(const Architecture &arch, CodeDirectory::HashAlgorithm hashType) 101 : architecture(arch), cdbuilder(hashType) { } 102 }; 103 104 // 105 // Our callers access the architectural universe through a map 106 // from Architectures to Arch objects. 107 // 108 typedef std::map<Architecture, Arch *> ArchMap; 109 typedef ArchMap::iterator Iterator; 110 ArchMap::iterator begin() { return architecture.begin(); } 111 ArchMap::iterator end() { return architecture.end(); } 112 unsigned count() const { return (unsigned)architecture.size(); } 113 114 // methods needed for an actual implementation 115 virtual void allocate() = 0; // interpass allocations 116 virtual void reset(Arch &arch) = 0; // pass 2 prep 117 virtual void write(Arch &arch, EmbeddedSignatureBlob *blob) = 0; // takes ownership of blob 118 virtual void commit() = 0; // write/flush result 119 120protected: 121 ArchMap architecture; 122}; 123 124 125// 126// An ArchEditor that collects all architectures into a single SuperBlob, 127// usually for writing a detached multi-architecture signature. 128// 129class BlobEditor : public ArchEditor { 130public: 131 BlobEditor(Universal &fat, SecCodeSigner::Signer &s); 132 133 SecCodeSigner::Signer &signer; 134 135 void component(CodeDirectory::SpecialSlot slot, CFDataRef data); 136 void allocate() { } 137 void reset(Arch &arch) { } 138 void write(Arch &arch, EmbeddedSignatureBlob *blob); 139 void commit(); 140 141private: 142 DetachedSignatureBlob::Maker mMaker; 143 EmbeddedSignatureBlob::Maker mGlobal; 144}; 145 146 147// 148// An ArchEditor that writes its signatures into a (fat) binary file. 149// We do this by forking a helper tool (codesign_allocate) and asking 150// it to make a copy with suitable space "opened up" in the right spots. 151// 152class MachOEditor : public ArchEditor, private UnixPlusPlus::Child { 153public: 154 MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithm hashType, std::string srcPath); 155 ~MachOEditor(); 156 157 const RefPointer<DiskRep::Writer> writer; 158 const std::string sourcePath; 159 const std::string tempPath; 160 161 void component(CodeDirectory::SpecialSlot slot, CFDataRef data); 162 void allocate(); 163 void reset(Arch &arch); 164 void write(Arch &arch, EmbeddedSignatureBlob *blob); 165 void commit(); 166 167private: 168 // fork operation 169 void childAction(); 170 void parentAction(); 171 172 // controlling the temporary file copy 173 Universal *mNewCode; 174 UnixPlusPlus::AutoFileDesc mFd; 175 bool mTempMayExist; 176 177 // finding and managing the helper tool 178 const char *mHelperPath; 179 bool mHelperOverridden; 180}; 181 182 183// 184// A Requirement::Context populated from a signing request. 185// We use this to help generate the explicit Designated Requirement 186// during signing ops, and thus this must be constructed BEFORE we 187// actually have a signed object. 188// 189class PreSigningContext : public Requirement::Context { 190public: 191 PreSigningContext(const SecCodeSigner::Signer &signer); 192 193private: 194 CFRef<CFArrayRef> mCerts; // hold cert chain 195}; 196 197 198} // end namespace CodeSigning 199} // end namespace Security 200 201#endif // !_H_SIGNERUTILS 202