]> git.saurik.com Git - apple/libsecurity_codesigning.git/blob - lib/csutilities.cpp
b33266d738e69ee23310bf17e216918b737a2425
[apple/libsecurity_codesigning.git] / lib / csutilities.cpp
1 /*
2 * Copyright (c) 2006-2007 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 // csutilities - miscellaneous utilities for the code signing implementation
26 //
27 #include "csutilities.h"
28 #include <Security/SecCertificatePriv.h>
29 #include <security_codesigning/requirement.h>
30 #include <security_utilities/debugging.h>
31 #include <security_utilities/errors.h>
32
33 namespace Security {
34 namespace CodeSigning {
35
36
37 //
38 // Calculate the canonical hash of a certificate, given its raw (DER) data.
39 //
40 void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest digest)
41 {
42 SHA1 hasher;
43 hasher(certData, certLength);
44 hasher.finish(digest);
45 }
46
47
48 //
49 // Ditto, given a SecCertificateRef
50 //
51 void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest)
52 {
53 assert(cert);
54 CSSM_DATA certData;
55 MacOSError::check(SecCertificateGetData(cert, &certData));
56 hashOfCertificate(certData.Data, certData.Length, digest);
57 }
58
59
60 //
61 // Calculate hashes of (a section of) a file.
62 // Starts at the current file position.
63 // Extends to end of file, or (if limit > 0) at most limit bytes.
64 //
65 size_t hashFileData(const char *path, SHA1 &hasher)
66 {
67 UnixPlusPlus::AutoFileDesc fd(path);
68 return hashFileData(fd, hasher);
69 }
70
71 size_t hashFileData(UnixPlusPlus::FileDesc fd, SHA1 &hasher, size_t limit /* = 0 */)
72 {
73 unsigned char buffer[4096];
74 size_t total = 0;
75 for (;;) {
76 size_t size = sizeof(buffer);
77 if (limit && limit < size)
78 size = limit;
79 size_t got = fd.read(buffer, size);
80 total += got;
81 if (fd.atEnd())
82 break;
83 hasher(buffer, got);
84 if (limit && (limit -= got) == 0)
85 break;
86 }
87 return total;
88 }
89
90
91
92 //
93 // Check to see if a certificate contains a particular field, by OID. This works for extensions,
94 // even ones not recognized by the local CL. It does not return any value, only presence.
95 //
96 bool certificateHasField(SecCertificateRef cert, const CssmOid &oid)
97 {
98 assert(cert);
99 CSSM_DATA *value;
100 switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) {
101 case noErr:
102 MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value));
103 return true; // extension found by oid
104 case CSSMERR_CL_UNKNOWN_TAG:
105 break; // oid not recognized by CL - continue below
106 default:
107 MacOSError::throwMe(rc); // error: fail
108 }
109
110 // check the CL's bag of unrecognized extensions
111 CSSM_DATA **values;
112 bool found = false;
113 if (SecCertificateCopyFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, &values))
114 return false; // no unrecognized extensions - no match
115 if (values)
116 for (CSSM_DATA **p = values; *p; p++) {
117 const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)(*p)->Data;
118 if (oid == ext->extnId) {
119 found = true;
120 break;
121 }
122 }
123 MacOSError::check(SecCertificateReleaseFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, values));
124 return found;
125 }
126
127
128 //
129 // Copyfile
130 //
131 Copyfile::Copyfile()
132 {
133 if (!(mState = copyfile_state_alloc()))
134 UnixError::throwMe();
135 }
136
137 void Copyfile::set(uint32_t flag, const void *value)
138 {
139 check(::copyfile_state_set(mState, flag, value));
140 }
141
142 void Copyfile::get(uint32_t flag, void *value)
143 {
144 check(::copyfile_state_set(mState, flag, value));
145 }
146
147 void Copyfile::operator () (const char *src, const char *dst, copyfile_flags_t flags)
148 {
149 check(::copyfile(src, dst, mState, flags));
150 }
151
152 void Copyfile::check(int rc)
153 {
154 if (rc < 0)
155 UnixError::throwMe();
156 }
157
158
159 } // end namespace CodeSigning
160 } // end namespace Security