]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_utilities / lib / osxverifier.cpp
1 /*
2 * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // osxsigner - MacOS X's standard code signing algorithm.
21 //
22 #include <security_cdsa_utilities/osxverifier.h>
23 #include <security_utilities/unix++.h>
24 #include <security_utilities/hashing.h>
25 #include <security_utilities/memutils.h>
26 #include <security_utilities/debugging.h>
27 #include <security_codesigning/requirement.h>
28 #include <security_codesigning/reqdumper.h> // debug only
29
30
31 using namespace CodeSigning;
32
33
34 namespace Security {
35
36
37 //
38 // Create a Verifier from a code object.
39 //
40 // This does not add any auxiliary information blobs. You can do that
41 // by calling add() after construction, of course.
42 //
43 OSXVerifier::OSXVerifier(OSXCode *code)
44 {
45 mPath = code->canonicalPath();
46 secinfo("codesign", "building verifier for %s", mPath.c_str());
47
48 // build new-style verifier
49 CFRef<SecStaticCodeRef> staticCode = code->codeRef();
50 switch (OSStatus rc = SecCodeCopyDesignatedRequirement(staticCode,
51 kSecCSDefaultFlags, &mRequirement.aref())) {
52 case errSecSuccess:
53 secinfo("codesign", " is signed; canonical requirement loaded");
54 break;
55 case errSecCSUnsigned:
56 secinfo("codesign", " is unsigned; no requirement");
57 break;
58 default:
59 MacOSError::throwMe(rc);
60 }
61
62 // build old-style verifier
63 makeLegacyHash(code, mLegacyHash);
64 secinfo("codesign", " hash generated");
65 }
66
67
68 //
69 // Create a Verifier from hash, path, and requirement.
70 // Again, this has no auxiliary data when constructed.
71 //
72 OSXVerifier::OSXVerifier(const SHA1::Byte *hash, const std::string &path)
73 : mPath(path)
74 {
75 secinfo("codesign", "building verifier from hash %p and path=%s", hash, path.c_str());
76 if (hash)
77 memcpy(mLegacyHash, hash, sizeof(mLegacyHash));
78 else
79 memset(mLegacyHash, 0, sizeof(mLegacyHash));
80 }
81
82
83 OSXVerifier::~OSXVerifier()
84 {
85 secinfo("codesign", "%p verifier destroyed", this);
86 }
87
88
89 //
90 // Add an auxiliary comment blob.
91 // Note that we only allow one auxiliary blob for each magic number.
92 //
93 void OSXVerifier::add(const BlobCore *blob)
94 {
95 if (blob->is<Requirement>()) {
96 #if defined(NDEBUG)
97 secinfo("codesign", "%p verifier adds requirement", this);
98 #else
99 secinfo("codesign", "%p verifier adds requirement %s", this,
100 Dumper::dump(Requirement::specific(blob), true).c_str());
101 #endif //NDEBUG
102 MacOSError::check(SecRequirementCreateWithData(CFTempData(*blob),
103 kSecCSDefaultFlags, &mRequirement.aref()));
104 } else {
105 secinfo("codesign", "%p verifier adds blob (0x%x,%zd)",
106 this, blob->magic(), blob->length());
107 BlobCore * &slot = mAuxiliary[blob->magic()];
108 if (slot)
109 ::free(slot);
110 slot = blob->clone();
111 }
112 }
113
114
115 //
116 // Find a comment blob, by magic number
117 //
118 const BlobCore *OSXVerifier::find(BlobCore::Magic magic)
119 {
120 AuxMap::const_iterator it = mAuxiliary.find(magic);
121 return (it == mAuxiliary.end()) ? NULL : it->second;
122 }
123
124
125 void OSXVerifier::makeLegacyHash(OSXCode *code, SHA1::Digest digest)
126 {
127 secinfo("codesign", "calculating legacy hash for %s", code->canonicalPath().c_str());
128 UnixPlusPlus::AutoFileDesc fd(code->executablePath(), O_RDONLY);
129 char buffer[legacyHashLimit];
130 size_t size = fd.read(buffer, legacyHashLimit);
131 SHA1 hash;
132 hash(buffer, size);
133 hash.finish(digest);
134 }
135
136
137 //
138 // The AuxMap helper class provides a map-to-Blob-pointers with automatic memory management.
139 //
140 OSXVerifier::AuxMap::AuxMap(const OSXVerifier::AuxMap &src)
141 {
142 for (const_iterator it = src.begin(); it != src.end(); it++)
143 this->insert(*it);
144 }
145
146 OSXVerifier::AuxMap::~AuxMap()
147 {
148 for (const_iterator it = this->begin(); it != this->end(); ++it)
149 ::free(it->second);
150 }
151
152
153 #if DEBUGDUMP
154
155 void OSXVerifier::dump() const
156 {
157 static const SHA1::Digest nullDigest = { 0 };
158 if (!memcmp(mLegacyHash, nullDigest, sizeof(mLegacyHash))) {
159 Debug::dump("(no hash)");
160 } else {
161 Debug::dump("oldHash=");
162 Debug::dumpData(mLegacyHash, sizeof(mLegacyHash));
163 }
164 if (mRequirement) {
165 CFRef<CFDataRef> reqData;
166 if (!SecRequirementCopyData(mRequirement, 0, &reqData.aref())) {
167 Debug::dump(" Requirement =>");
168 ((const Requirement *)CFDataGetBytePtr(reqData))->dump();
169 }
170 } else {
171 Debug::dump(" NO REQ");
172 }
173 }
174
175 #endif //DEBUGDUMP
176
177 } // end namespace Security