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 CssmError::throwMe(err
);
120 attachment
.free(data
);
130 // slow form: build a new value table and get rid of the old one
131 Context::Builder
builder(attachment
);
132 for (unsigned n
= 0; n
< count
; n
++)
133 builder
.setup(attributes
[n
]);
134 for (unsigned n
= 0; n
< attributesInUse(); n
++)
135 if (!find(ContextAttributes
[n
].AttributeType
, attributes
, count
))
136 builder
.setup(ContextAttributes
[n
]);
138 for (unsigned n
= 0; n
< count
; n
++)
139 builder
.put(attributes
[n
]);
140 for (unsigned n
= 0; n
< attributesInUse(); n
++)
141 if (!find(ContextAttributes
[n
].AttributeType
, attributes
, count
))
142 builder
.put(ContextAttributes
[n
]);
144 // Carefully, now! The CSP may yet tell us to back out.
145 // First, save the old values...
146 CSSM_CONTEXT_ATTRIBUTE
*oldAttributes
= ContextAttributes
;
147 uint32 oldCount
= NumberOfAttributes
;
149 // ...install new blob into the context...
150 builder
.done(ContextAttributes
, NumberOfAttributes
);
152 // ...and ask the CSP whether this is okay
153 if (CSSM_RETURN err
= validateChange(CSSM_CONTEXT_EVENT_UPDATE
)) {
154 // CSP refused; put everything back where it belongs
155 attachment
.free(ContextAttributes
);
156 ContextAttributes
= oldAttributes
;
157 NumberOfAttributes
= oldCount
;
158 CssmError::throwMe(err
);
161 // we succeeded, so NOW delete the old attributes blob
162 attachment
.free(oldAttributes
);
167 // Ask the CSP to validate a proposed (and already implemented) change
169 CSSM_RETURN
HandleContext::validateChange(CSSM_CONTEXT_EVENT event
)
171 // lock down the module if it is not thread-safe
172 StLock
<Module
, &Module::safeLock
, &Module::safeUnlock
> _(attachment
.module);
173 return attachment
.downcalls
.EventNotify(attachment
.handle(),
174 event
, handle(), this);
179 // Wrap up a deluxe context creation operation and return the new CC handle.
181 CSSM_CC_HANDLE
HandleContext::Maker::operator () (CSSM_CONTEXT_TYPE type
,
182 CSSM_ALGORITHMS algorithm
)
184 // construct the HandleContext object
185 HandleContext
&context
= *new(attachment
) HandleContext(attachment
, type
, algorithm
);
186 context
.CSPHandle
= attachment
.handle();
187 done(context
.ContextAttributes
, context
.NumberOfAttributes
);
189 // ask the CSP for consent
190 if (CSSM_RETURN err
= context
.validateChange(CSSM_CONTEXT_EVENT_CREATE
)) {
191 // CSP refused; clean up and fail
192 context
.destroy(&context
, context
.attachment
);
193 CssmError::throwMe(err
);
196 // return the new handle (we have succeeded)
197 return context
.handle();