]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/signerutils.h
c4cb1238d5cec9c008270c9e7a8f234e634ea422
[apple/security.git] / OSX / libsecurity_codesigning / lib / signerutils.h
1 /*
2 * Copyright (c) 2006-2012 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
34 #include <Security/SecCmsBase.h>
35
36 #include <security_utilities/utilities.h>
37 #include <security_utilities/blob.h>
38 #include <security_utilities/unix++.h>
39 #include <security_utilities/unixchild.h>
40
41 namespace Security {
42 namespace CodeSigning {
43
44
45 //
46 // A helper to deal with the magic merger logic of internal requirements
47 //
48 class InternalRequirements : public Requirements::Maker {
49 public:
50 InternalRequirements() : mReqs(NULL) { }
51 ~InternalRequirements() { ::free((void *)mReqs); }
52 void operator () (const Requirements *given, const Requirements *defaulted, const Requirement::Context &context);
53 operator const Requirements * () const { return mReqs; }
54
55 private:
56 const Requirements *mReqs;
57 };
58
59
60 //
61 // A DiskRep::Writer that assembles data in a SuperBlob (in memory)
62 //
63 class BlobWriter : public DiskRep::Writer, public EmbeddedSignatureBlob::Maker {
64 public:
65 void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
66 };
67
68
69 class DetachedBlobWriter : public BlobWriter {
70 public:
71 DetachedBlobWriter(SecCodeSigner::Signer &s) : signer(s) { }
72
73 SecCodeSigner::Signer &signer;
74
75 void flush();
76 };
77
78
79 //
80 // A multi-architecture editing assistant.
81 // ArchEditor collects (Mach-O) architectures in use, and maintains per-archtitecture
82 // data structures. It must be subclassed to express a particular way to handle the signing
83 // data.
84 //
85 class ArchEditor : public DiskRep::Writer {
86 public:
87 ArchEditor(Universal &fat, CodeDirectory::HashAlgorithms hashTypes, uint32_t attrs);
88 virtual ~ArchEditor();
89
90 public:
91 //
92 // One architecture's signing construction element.
93 // This also implements DispRep::Writer so generic writing code
94 // can work with both Mach-O and other files.
95 //
96 struct Arch : public BlobWriter {
97 Architecture architecture; // our architecture
98 auto_ptr<MachO> source; // Mach-O object to be signed
99 std::map<CodeDirectory::HashAlgorithm, RefPointer<CodeDirectory::Builder> > cdBuilders;
100 InternalRequirements ireqs; // consolidated internal requirements
101 size_t blobSize; // calculated SuperBlob size
102
103 Arch(const Architecture &arch, CodeDirectory::HashAlgorithms hashTypes);
104
105 void eachDigest(void (^op)(CodeDirectory::Builder& builder))
106 {
107 for (auto type = cdBuilders.begin(); type != cdBuilders.end(); ++type)
108 op(*type->second);
109 }
110 };
111
112 //
113 // Our callers access the architectural universe through a map
114 // from Architectures to Arch objects.
115 //
116 typedef std::map<Architecture, Arch *> ArchMap;
117 typedef ArchMap::iterator Iterator;
118 ArchMap::iterator begin() { return architecture.begin(); }
119 ArchMap::iterator end() { return architecture.end(); }
120 unsigned count() const { return (unsigned)architecture.size(); }
121
122 // methods needed for an actual implementation
123 virtual void allocate() = 0; // interpass allocations
124 virtual void reset(Arch &arch) = 0; // pass 2 prep
125 virtual void write(Arch &arch, EmbeddedSignatureBlob *blob) = 0; // takes ownership of blob
126 virtual void commit() = 0; // write/flush result
127
128 protected:
129 ArchMap architecture;
130 };
131
132
133 //
134 // An ArchEditor that collects all architectures into a single SuperBlob,
135 // usually for writing a detached multi-architecture signature.
136 //
137 class BlobEditor : public ArchEditor {
138 public:
139 BlobEditor(Universal &fat, SecCodeSigner::Signer &s);
140
141 SecCodeSigner::Signer &signer;
142
143 void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
144 void allocate() { }
145 void reset(Arch &arch) { }
146 void write(Arch &arch, EmbeddedSignatureBlob *blob);
147 void commit();
148
149 private:
150 DetachedSignatureBlob::Maker mMaker;
151 EmbeddedSignatureBlob::Maker mGlobal;
152 };
153
154
155 //
156 // An ArchEditor that writes its signatures into a (fat) binary file.
157 // We do this by forking a helper tool (codesign_allocate) and asking
158 // it to make a copy with suitable space "opened up" in the right spots.
159 //
160 class MachOEditor : public ArchEditor, private UnixPlusPlus::Child {
161 public:
162 MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithms hashTypes, std::string srcPath);
163 ~MachOEditor();
164
165 const RefPointer<DiskRep::Writer> writer;
166 const std::string sourcePath;
167 const std::string tempPath;
168
169 void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
170 void allocate();
171 void reset(Arch &arch);
172 void write(Arch &arch, EmbeddedSignatureBlob *blob);
173 void commit();
174
175 private:
176 CodeDirectory::HashAlgorithms mHashTypes;
177
178 // fork operation
179 void childAction();
180 void parentAction();
181
182 // controlling the temporary file copy
183 Universal *mNewCode;
184 UnixPlusPlus::AutoFileDesc mFd;
185 bool mTempMayExist;
186
187 // finding and managing the helper tool
188 const char *mHelperPath;
189 bool mHelperOverridden;
190 };
191
192
193 //
194 // A Requirement::Context populated from a signing request.
195 // We use this to help generate the explicit Designated Requirement
196 // during signing ops, and thus this must be constructed BEFORE we
197 // actually have a signed object.
198 //
199 class PreSigningContext : public Requirement::Context {
200 public:
201 PreSigningContext(const SecCodeSigner::Signer &signer);
202
203 private:
204 CFRef<CFArrayRef> mCerts; // hold cert chain
205 };
206
207
208 //
209 // A collector of CodeDirectories for hash-agile construction of signatures.
210 //
211 class CodeDirectorySet : public std::map<CodeDirectory::HashAlgorithm, const CodeDirectory *> {
212 public:
213 CodeDirectorySet() { mPrimary = NULL; }
214 ~CodeDirectorySet();
215
216 void add(const CodeDirectory* cd);
217 void populate(DiskRep::Writer* writer) const;
218
219 const CodeDirectory* primary() const;
220
221 // Note that the order of the hashList is relevant.
222 // (Which is also why there are separate methods, CFDictionary is not ordered.)
223 CFArrayRef hashList() const;
224 CFDictionaryRef hashDict() const;
225
226 static SECOidTag SECOidTagForAlgorithm(CodeDirectory::HashAlgorithm algorithm);
227
228 private:
229 mutable const CodeDirectory* mPrimary;
230 };
231
232
233 } // end namespace CodeSigning
234 } // end namespace Security
235
236 #endif // !_H_SIGNERUTILS