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.
29 // You may also want to look at cssmcontext.h in CSSM proper, where CSSM's internal Context
30 // objects are built on top of our Context class.
32 #include <Security/context.h>
36 // Delete a single attribute from a Context by type.
37 // We implement this by simply nulling out the slot - the memory is not released,
38 // and will not be reclaimed until the Context is deleted or reconstructed for some reason.
40 void Context::deleteAttribute(CSSM_ATTRIBUTE_TYPE type
)
42 for (uint32 n
= 0; n
< attributesInUse(); n
++)
43 if (ContextAttributes
[n
].AttributeType
== type
) {
44 ContextAttributes
[n
].AttributeType
= CSSM_ATTRIBUTE_NONE
;
45 ContextAttributes
[n
].AttributeLength
= 0;
49 CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT
);
54 // This swiss-army-knife function performs a deep copy of all of a Context's attributes,
55 // bundling them up into a single memory node and storing them into a pointer/count pair.
56 // It also returns the size of the memory block allocated, in case you care (IPC does).
58 size_t Context::copyAttributes(CSSM_CONTEXT_ATTRIBUTE
* &attrs
, uint32
&count
,
59 CssmAllocator
&alloc
) const
61 Context::Builder
builder(alloc
);
62 for (unsigned n
= 0; n
< attributesInUse(); n
++)
63 builder
.setup(ContextAttributes
[n
]);
64 size_t size
= builder
.make();
65 for (unsigned n
= 0; n
< attributesInUse(); n
++)
66 builder
.put(ContextAttributes
[n
]);
67 builder
.done(attrs
, count
);
73 // Locate attribute values by type.
74 // This function deals in attribute vectors, not contexts; hence the explicit count argument.
75 // Returns NULL for attribute not found.
77 Context::Attr
*Context::find(CSSM_ATTRIBUTE_TYPE theType
,
78 const CSSM_CONTEXT_ATTRIBUTE
*attrs
, unsigned int count
)
80 for (unsigned n
= 0; n
< count
; n
++)
81 if (attrs
[n
].AttributeType
== theType
)
82 return (Attr
*)&attrs
[n
];
88 // Post-IPC context fixup.
89 // A Context is transmitted via IPC as a two-element blob. The first is the Context
90 // structure itself, which is taken as flat. The second is the flattened attribute
91 // vector blob as produced by the Context::Builder class. Since IPC will relocate
92 // each blob, we need to offset all internal pointers to compensate.
94 void Context::postIPC(void *base
, CSSM_CONTEXT_ATTRIBUTE
*ipcAttributes
)
96 ReconstituteWalker
relocator(LowLevelMemoryUtilities::difference(ipcAttributes
, base
));
97 ContextAttributes
= ipcAttributes
; // fix context->attr vector link
98 for (uint32 n
= 0; n
< attributesInUse(); n
++)
99 walk(relocator
, (*this)[n
]);
106 size_t Context::Builder::make()
109 LowLevelMemoryUtilities::alignUp(slotCount
* sizeof(CSSM_CONTEXT_ATTRIBUTE
));
110 size_t totalSize
= vectorSize
+ sizer
;
111 attributes
= reinterpret_cast<Attr
*>(allocator
.malloc(totalSize
));
112 copier
= LowLevelMemoryUtilities::increment(attributes
, vectorSize
);
117 void Context::Builder::done(CSSM_CONTEXT_ATTRIBUTE
* &attributes
, uint32
&count
)
119 assert(slot
== slotCount
); // match pass profiles
120 attributes
= this->attributes
;
122 this->attributes
= NULL
; // delivered the goods, no longer our responsibility
129 #if defined(DEBUGDUMP)
131 static void dumpData(CSSM_DATA
*data
)
134 Debug::dump("[NULL]");
136 Debug::dump("[%p,%ld]@%p", data
->Data
, data
->Length
, data
);
139 void Context::Attr::dump() const
141 Debug::dump(" Attr{type=%x, size=%d, value=", int(AttributeType
), int(AttributeLength
));
142 switch (AttributeType
& CSSM_ATTRIBUTE_TYPE_MASK
) {
143 case CSSM_ATTRIBUTE_DATA_UINT32
:
144 Debug::dump("%ld", long(Attribute
.Uint32
)); break;
145 case CSSM_ATTRIBUTE_DATA_STRING
:
146 Debug::dump("%s@%p", Attribute
.String
, Attribute
.String
); break;
147 case CSSM_ATTRIBUTE_DATA_CSSM_DATA
:
148 dumpData(Attribute
.Data
);
150 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA
:
151 dumpData(&Attribute
.CryptoData
->Param
);
154 Debug::dump("%p", Attribute
.String
); break; // (slightly unclean)
159 void Context::dump(const char *title
, const CSSM_CONTEXT_ATTRIBUTE
*attrs
) const
162 attrs
= ContextAttributes
;
163 Debug::dump("Context %s{type=%d, alg=%d, CSP=%u, %d attributes@%p:\n",
165 int(ContextType
), int(AlgorithmType
), (unsigned int)CSPHandle
,
166 int(NumberOfAttributes
), attrs
);
167 for (unsigned int n
= 0; n
< NumberOfAttributes
; n
++)
168 Attr::overlay(attrs
[n
]).dump();
169 Debug::dump("} // end Context\n");