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