2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // context - manage CSSM (cryptographic) contexts every which way.
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.
30 #define _CPP_CSSMCONTEXT
32 #include "cssmcontext.h"
36 // Destroy a HandleContext.
38 HandleContext::~HandleContext()
40 attachment
.free(extent
);
41 attachment
.free(ContextAttributes
);
46 // Locking protocol for HandleContexts
48 void HandleContext::lock()
49 { attachment
.enter(); }
51 bool HandleContext::tryLock()
52 { return attachment
.tryEnter(); }
56 // Merge a new set of attributes into an existing HandleContext, copying
57 // the new values deeply while releasing corresponding old values.
59 // NOTE: This is a HandleContext method; it does not work on bare Contexts.
61 void HandleContext::mergeAttributes(const CSSM_CONTEXT_ATTRIBUTE
*attributes
, uint32 count
)
63 // attempt to fast-path some simple or frequent cases
65 if (Attr
*attr
= find(attributes
[0].AttributeType
)) {
66 if (attr
->baseType() == CSSM_ATTRIBUTE_DATA_UINT32
) {
67 // try quick replacement
69 *attr
= attributes
[0];
70 if (CSSM_RETURN err
= validateChange(CSSM_CONTEXT_EVENT_UPDATE
)) {
73 CssmError::throwMe(err
);
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]);
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
)) {
88 CssmError::throwMe(err
);
91 CopyWalker
copier(oldAttr
.Attribute
.String
);
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
;
102 if (CSSM_RETURN err
= validateChange(CSSM_CONTEXT_EVENT_UPDATE
)) {
104 CssmError::throwMe(err
);
108 } else if (extent
== NULL
) { // pointer value, allocate into extent
109 void *data
= attachment
.malloc(size(*attr
));
111 Attr oldSlot
= *slot
;
112 *slot
= attributes
[0];
113 CopyWalker
copier(data
);
115 if (CSSM_RETURN err
= validateChange(CSSM_CONTEXT_EVENT_UPDATE
)) {
117 attachment
.free(data
);
118 CssmError::throwMe(err
);
121 attachment
.free(data
);
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
]);
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
]);
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
;
150 // ...install new blob into the context...
151 builder
.done(ContextAttributes
, NumberOfAttributes
);
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
);
162 // we succeeded, so NOW delete the old attributes blob
163 attachment
.free(oldAttributes
);
168 // Ask the CSP to validate a proposed (and already implemented) change
170 CSSM_RETURN
HandleContext::validateChange(CSSM_CONTEXT_EVENT event
)
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);
180 // Wrap up a deluxe context creation operation and return the new CC handle.
182 CSSM_CC_HANDLE
HandleContext::Maker::operator () (CSSM_CONTEXT_TYPE type
,
183 CSSM_ALGORITHMS algorithm
)
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
);
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
);
197 // return the new handle (we have succeeded)
198 return context
.handle();