]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2002,2004,2011,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 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 | // | |
26 | // context - manage CSSM (cryptographic) contexts every which way. | |
27 | // | |
28 | // A note on memory management: | |
29 | // Context attributes are allocated from application memory in big chunks comprising | |
30 | // many attributes as well as the attribute array itself. The CSSM_CONTEXT fields | |
31 | // NumberOfAttributes and ContextAttributes are handled as a group. Context::Builder | |
32 | // and Context::copyFrom assume these fields are undefined and fill them. Context::clear | |
33 | // assumes they are valid and invalides them, freeing memory. | |
34 | // | |
35 | #ifdef __MWERKS__ | |
36 | #define _CPP_CSSMCONTEXT | |
37 | #endif | |
38 | #include "cssmcontext.h" | |
39 | ||
40 | ||
41 | // | |
42 | // Destroy a HandleContext. | |
43 | // | |
44 | HandleContext::~HandleContext() | |
45 | { | |
46 | attachment.free(extent); | |
47 | attachment.free(ContextAttributes); | |
48 | } | |
49 | ||
50 | ||
51 | // | |
52 | // Locking protocol for HandleContexts | |
53 | // | |
54 | void HandleContext::lock() | |
55 | { attachment.enter(); } | |
56 | ||
57 | bool HandleContext::tryLock() | |
58 | { return attachment.tryEnter(); } | |
59 | ||
60 | ||
61 | // | |
62 | // Merge a new set of attributes into an existing HandleContext, copying | |
63 | // the new values deeply while releasing corresponding old values. | |
64 | // | |
65 | // NOTE: This is a HandleContext method; it does not work on bare Contexts. | |
66 | // | |
67 | void HandleContext::mergeAttributes(const CSSM_CONTEXT_ATTRIBUTE *attributes, uint32 count) | |
68 | { | |
69 | // attempt to fast-path some simple or frequent cases | |
70 | if (count == 1) { | |
71 | if (Attr *attr = find(attributes[0].AttributeType)) { | |
72 | if (attr->baseType() == CSSM_ATTRIBUTE_DATA_UINT32) { | |
73 | // try quick replacement | |
74 | Attr oldAttr = *attr; | |
75 | *attr = attributes[0]; | |
76 | if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { | |
77 | // roll back and fail | |
78 | *attr = oldAttr; | |
79 | CssmError::throwMe(err); | |
80 | } | |
81 | return; // all done | |
82 | } else { | |
83 | // pointer value - does it fit into the space of the current value? | |
84 | size_t oldSize = size(*attr); | |
85 | size_t newSize = size(attributes[0]); | |
86 | Attr oldAttr = *attr; | |
87 | if (newSize <= oldSize) { // give it a try... | |
88 | *attr = attributes[0]; | |
89 | // NOTE that the CSP is getting a "temporary" pointer set to validate; | |
90 | // If we commit, the final copy will be elsewhere. CSP writer beware! | |
91 | if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { | |
92 | // roll back and fail | |
93 | *attr = oldAttr; | |
94 | CssmError::throwMe(err); | |
95 | } | |
96 | // commit new value | |
97 | CopyWalker copier(oldAttr.Attribute.String); | |
98 | walk(copier, *attr); | |
99 | return; | |
100 | } | |
101 | } | |
102 | } else { // single change, new attribute | |
103 | if (Attr *slot = find(CSSM_ATTRIBUTE_NONE)) { | |
104 | const Attr *attr = static_cast<const Attr *>(&attributes[0]); | |
105 | if (attr->baseType() == CSSM_ATTRIBUTE_DATA_UINT32) { // trivial | |
106 | Attr oldSlot = *slot; | |
107 | *slot = *attr; | |
108 | if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { | |
109 | *slot = oldSlot; | |
110 | CssmError::throwMe(err); | |
111 | } | |
112 | // already ok | |
113 | return; | |
114 | } else if (extent == NULL) { // pointer value, allocate into extent | |
115 | void *data = attachment.malloc(size(*attr)); | |
116 | try { | |
117 | Attr oldSlot = *slot; | |
118 | *slot = attributes[0]; | |
119 | CopyWalker copier(data); | |
120 | walk(copier, *slot); | |
121 | if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { | |
122 | *slot = oldSlot; | |
123 | CssmError::throwMe(err); | |
124 | } | |
125 | } catch (...) { | |
126 | attachment.free(data); | |
127 | throw; | |
128 | } | |
129 | extent = data; | |
130 | return; | |
131 | } | |
132 | } | |
133 | } | |
134 | } | |
135 | ||
136 | // slow form: build a new value table and get rid of the old one | |
137 | Context::Builder builder(attachment); | |
138 | for (unsigned n = 0; n < count; n++) | |
139 | builder.setup(attributes[n]); | |
140 | for (unsigned n = 0; n < attributesInUse(); n++) | |
141 | if (!find(ContextAttributes[n].AttributeType, attributes, count)) | |
142 | builder.setup(ContextAttributes[n]); | |
143 | builder.make(); | |
144 | for (unsigned n = 0; n < count; n++) | |
145 | builder.put(attributes[n]); | |
146 | for (unsigned n = 0; n < attributesInUse(); n++) | |
147 | if (!find(ContextAttributes[n].AttributeType, attributes, count)) | |
148 | builder.put(ContextAttributes[n]); | |
149 | ||
150 | // Carefully, now! The CSP may yet tell us to back out. | |
151 | // First, save the old values... | |
152 | CSSM_CONTEXT_ATTRIBUTE *oldAttributes = ContextAttributes; | |
153 | uint32 oldCount = NumberOfAttributes; | |
154 | ||
155 | // ...install new blob into the context... | |
156 | builder.done(ContextAttributes, NumberOfAttributes); | |
157 | ||
158 | // ...and ask the CSP whether this is okay | |
159 | if (CSSM_RETURN err = validateChange(CSSM_CONTEXT_EVENT_UPDATE)) { | |
160 | // CSP refused; put everything back where it belongs | |
161 | attachment.free(ContextAttributes); | |
162 | ContextAttributes = oldAttributes; | |
163 | NumberOfAttributes = oldCount; | |
164 | CssmError::throwMe(err); | |
165 | } | |
166 | ||
167 | // we succeeded, so NOW delete the old attributes blob | |
168 | attachment.free(oldAttributes); | |
169 | } | |
170 | ||
171 | ||
172 | // | |
173 | // Ask the CSP to validate a proposed (and already implemented) change | |
174 | // | |
175 | CSSM_RETURN HandleContext::validateChange(CSSM_CONTEXT_EVENT event) | |
176 | { | |
177 | // lock down the module if it is not thread-safe | |
178 | StLock<Module, &Module::safeLock, &Module::safeUnlock> _(attachment.module); | |
179 | return attachment.downcalls.EventNotify(attachment.handle(), | |
180 | event, handle(), this); | |
181 | } | |
182 | ||
183 | ||
184 | // | |
185 | // Wrap up a deluxe context creation operation and return the new CC handle. | |
186 | // | |
187 | CSSM_CC_HANDLE HandleContext::Maker::operator () (CSSM_CONTEXT_TYPE type, | |
188 | CSSM_ALGORITHMS algorithm) | |
189 | { | |
190 | // construct the HandleContext object | |
191 | HandleContext &context = *new(attachment) HandleContext(attachment, type, algorithm); | |
192 | context.CSPHandle = attachment.handle(); | |
193 | done(context.ContextAttributes, context.NumberOfAttributes); | |
194 | ||
195 | // ask the CSP for consent | |
196 | if (CSSM_RETURN err = context.validateChange(CSSM_CONTEXT_EVENT_CREATE)) { | |
197 | // CSP refused; clean up and fail | |
198 | context.destroy(&context, context.attachment); | |
199 | CssmError::throwMe(err); | |
200 | } | |
201 | ||
202 | // return the new handle (we have succeeded) | |
203 | return context.handle(); | |
204 | } |