]>
Commit | Line | Data |
---|---|---|
7d31e928 | 1 | /* |
f60086fc | 2 | * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. |
7d31e928 A |
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" | |
516ae477 | 28 | #include <Security/SecCertificatePriv.h> |
7d31e928 A |
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 | ||
516ae477 A |
60 | // |
61 | // Check to see if a certificate contains a particular field, by OID. This works for extensions, | |
62 | // even ones not recognized by the local CL. It does not return any value, only presence. | |
63 | // | |
64 | bool certificateHasField(SecCertificateRef cert, const CssmOid &oid) | |
65 | { | |
66 | assert(cert); | |
67 | CSSM_DATA *value; | |
68 | switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) { | |
69 | case noErr: | |
70 | MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value)); | |
71 | return true; // extension found by oid | |
f60086fc | 72 | case errSecUnknownTag: |
516ae477 A |
73 | break; // oid not recognized by CL - continue below |
74 | default: | |
75 | MacOSError::throwMe(rc); // error: fail | |
76 | } | |
77 | ||
78 | // check the CL's bag of unrecognized extensions | |
79 | CSSM_DATA **values; | |
80 | bool found = false; | |
81 | if (SecCertificateCopyFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, &values)) | |
82 | return false; // no unrecognized extensions - no match | |
83 | if (values) | |
84 | for (CSSM_DATA **p = values; *p; p++) { | |
85 | const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)(*p)->Data; | |
86 | if (oid == ext->extnId) { | |
87 | found = true; | |
88 | break; | |
89 | } | |
90 | } | |
91 | MacOSError::check(SecCertificateReleaseFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, values)); | |
92 | return found; | |
93 | } | |
f60086fc A |
94 | |
95 | ||
96 | // | |
97 | // Retrieve X.509 policy extension OIDs, if any. | |
98 | // This currently ignores policy qualifiers. | |
99 | // | |
100 | bool certificateHasPolicy(SecCertificateRef cert, const CssmOid &policyOid) | |
101 | { | |
102 | bool matched = false; | |
103 | assert(cert); | |
104 | CSSM_DATA *data; | |
105 | if (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_CertificatePolicies, &data)) | |
106 | MacOSError::throwMe(rc); | |
107 | if (data && data->Data && data->Length == sizeof(CSSM_X509_EXTENSION)) { | |
108 | const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)data->Data; | |
109 | assert(ext->format == CSSM_X509_DATAFORMAT_PARSED); | |
110 | const CE_CertPolicies *policies = (const CE_CertPolicies *)ext->value.parsedValue; | |
111 | if (policies) | |
112 | for (unsigned int n = 0; n < policies->numPolicies; n++) { | |
113 | const CE_PolicyInformation &cp = policies->policies[n]; | |
114 | if (cp.certPolicyId == policyOid) { | |
115 | matched = true; | |
116 | break; | |
117 | } | |
118 | } | |
119 | } | |
120 | SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_PolicyConstraints, data); | |
121 | return matched; | |
122 | } | |
d1c1ab47 A |
123 | |
124 | ||
125 | // | |
126 | // Copyfile | |
127 | // | |
128 | Copyfile::Copyfile() | |
129 | { | |
130 | if (!(mState = copyfile_state_alloc())) | |
131 | UnixError::throwMe(); | |
132 | } | |
133 | ||
134 | void Copyfile::set(uint32_t flag, const void *value) | |
135 | { | |
136 | check(::copyfile_state_set(mState, flag, value)); | |
137 | } | |
138 | ||
139 | void Copyfile::get(uint32_t flag, void *value) | |
140 | { | |
141 | check(::copyfile_state_set(mState, flag, value)); | |
142 | } | |
143 | ||
144 | void Copyfile::operator () (const char *src, const char *dst, copyfile_flags_t flags) | |
145 | { | |
146 | check(::copyfile(src, dst, mState, flags)); | |
147 | } | |
148 | ||
149 | void Copyfile::check(int rc) | |
150 | { | |
151 | if (rc < 0) | |
152 | UnixError::throwMe(); | |
153 | } | |
516ae477 A |
154 | |
155 | ||
f60086fc A |
156 | // |
157 | // MessageTracer support | |
158 | // | |
159 | MessageTrace::MessageTrace(const char *domain, const char *signature) | |
160 | { | |
161 | mAsl = asl_new(ASL_TYPE_MSG); | |
162 | if (domain) | |
163 | asl_set(mAsl, "com.apple.message.domain", domain); | |
164 | if (signature) | |
165 | asl_set(mAsl, "com.apple.message.signature", signature); | |
166 | } | |
167 | ||
168 | void MessageTrace::add(const char *key, const char *format, ...) | |
169 | { | |
170 | va_list args; | |
171 | va_start(args, format); | |
172 | char value[200]; | |
173 | vsnprintf(value, sizeof(value), format, args); | |
174 | va_end(args); | |
175 | asl_set(mAsl, (string("com.apple.message.") + key).c_str(), value); | |
176 | } | |
177 | ||
178 | void MessageTrace::send(const char *format, ...) | |
179 | { | |
180 | va_list args; | |
181 | va_start(args, format); | |
182 | asl_vlog(NULL, mAsl, ASL_LEVEL_NOTICE, format, args); | |
183 | va_end(args); | |
184 | } | |
185 | ||
186 | ||
7d31e928 A |
187 | } // end namespace CodeSigning |
188 | } // end namespace Security |