]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp
Security-58286.41.2.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_utilities / lib / osxverifier.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2000-2001,2011,2013-2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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
31using namespace CodeSigning;
32
33
34namespace 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//
43OSXVerifier::OSXVerifier(OSXCode *code)
44{
45 mPath = code->canonicalPath();
fa7225c8 46 secinfo("codesign", "building verifier for %s", mPath.c_str());
b1ab9ed8
A
47
48 // build new-style verifier
49 CFRef<SecStaticCodeRef> staticCode = code->codeRef();
50 switch (OSStatus rc = SecCodeCopyDesignatedRequirement(staticCode,
51 kSecCSDefaultFlags, &mRequirement.aref())) {
427c49bc 52 case errSecSuccess:
fa7225c8 53 secinfo("codesign", " is signed; canonical requirement loaded");
b1ab9ed8
A
54 break;
55 case errSecCSUnsigned:
fa7225c8 56 secinfo("codesign", " is unsigned; no requirement");
b1ab9ed8
A
57 break;
58 default:
59 MacOSError::throwMe(rc);
60 }
61
62 // build old-style verifier
63 makeLegacyHash(code, mLegacyHash);
fa7225c8 64 secinfo("codesign", " hash generated");
b1ab9ed8
A
65}
66
67
68//
69// Create a Verifier from hash, path, and requirement.
70// Again, this has no auxiliary data when constructed.
71//
72OSXVerifier::OSXVerifier(const SHA1::Byte *hash, const std::string &path)
73 : mPath(path)
74{
fa7225c8 75 secinfo("codesign", "building verifier from hash %p and path=%s", hash, path.c_str());
b1ab9ed8
A
76 if (hash)
77 memcpy(mLegacyHash, hash, sizeof(mLegacyHash));
78 else
79 memset(mLegacyHash, 0, sizeof(mLegacyHash));
80}
81
82
83OSXVerifier::~OSXVerifier()
84{
fa7225c8 85 secinfo("codesign", "%p verifier destroyed", this);
b1ab9ed8
A
86}
87
88
89//
90// Add an auxiliary comment blob.
91// Note that we only allow one auxiliary blob for each magic number.
92//
93void OSXVerifier::add(const BlobCore *blob)
94{
95 if (blob->is<Requirement>()) {
96#if defined(NDEBUG)
fa7225c8 97 secinfo("codesign", "%p verifier adds requirement", this);
b1ab9ed8 98#else
fa7225c8 99 secinfo("codesign", "%p verifier adds requirement %s", this,
b1ab9ed8
A
100 Dumper::dump(Requirement::specific(blob), true).c_str());
101#endif //NDEBUG
102 MacOSError::check(SecRequirementCreateWithData(CFTempData(*blob),
103 kSecCSDefaultFlags, &mRequirement.aref()));
104 } else {
fa7225c8 105 secinfo("codesign", "%p verifier adds blob (0x%x,%zd)",
b1ab9ed8
A
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//
118const 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
125void OSXVerifier::makeLegacyHash(OSXCode *code, SHA1::Digest digest)
126{
fa7225c8 127 secinfo("codesign", "calculating legacy hash for %s", code->canonicalPath().c_str());
b1ab9ed8
A
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//
140OSXVerifier::AuxMap::AuxMap(const OSXVerifier::AuxMap &src)
141{
142 for (const_iterator it = src.begin(); it != src.end(); it++)
143 this->insert(*it);
144}
145
146OSXVerifier::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
155void 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