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 // Construct Context objects
38 Context::Context(CSSM_CONTEXT_TYPE type
, CSSM_ALGORITHMS algorithmId
)
42 AlgorithmType
= algorithmId
;
47 // Delete a single attribute from a Context by type.
48 // We implement this by simply nulling out the slot - the memory is not released,
49 // and will not be reclaimed until the Context is deleted or reconstructed for some reason.
51 void Context::deleteAttribute(CSSM_ATTRIBUTE_TYPE type
)
53 for (uint32 n
= 0; n
< attributesInUse(); n
++)
54 if (ContextAttributes
[n
].AttributeType
== type
) {
55 ContextAttributes
[n
].AttributeType
= CSSM_ATTRIBUTE_NONE
;
56 ContextAttributes
[n
].AttributeLength
= 0;
60 CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT
);
65 // This swiss-army-knife function performs a deep copy of all of a Context's attributes,
66 // bundling them up into a single memory node and storing them into a pointer/count pair.
67 // It also returns the size of the memory block allocated, in case you care (IPC does).
69 size_t Context::copyAttributes(CSSM_CONTEXT_ATTRIBUTE
* &attrs
, uint32
&count
,
70 CssmAllocator
&alloc
) const
72 Context::Builder
builder(alloc
);
73 for (unsigned n
= 0; n
< attributesInUse(); n
++)
74 builder
.setup(ContextAttributes
[n
]);
75 size_t size
= builder
.make();
76 for (unsigned n
= 0; n
< attributesInUse(); n
++)
77 builder
.put(ContextAttributes
[n
]);
78 builder
.done(attrs
, count
);
84 // Locate attribute values by type.
85 // This function deals in attribute vectors, not contexts; hence the explicit count argument.
86 // Returns NULL for attribute not found.
88 Context::Attr
*Context::find(CSSM_ATTRIBUTE_TYPE theType
,
89 const CSSM_CONTEXT_ATTRIBUTE
*attrs
, unsigned int count
)
91 for (unsigned n
= 0; n
< count
; n
++)
92 if (attrs
[n
].AttributeType
== theType
)
93 return (Attr
*)&attrs
[n
];
99 // Post-IPC context fixup.
100 // A Context is transmitted via IPC as a two-element blob. The first is the Context
101 // structure itself, which is taken as flat. The second is the flattened attribute
102 // vector blob as produced by the Context::Builder class. Since IPC will relocate
103 // each blob, we need to offset all internal pointers to compensate.
105 void Context::postIPC(void *base
, CSSM_CONTEXT_ATTRIBUTE
*ipcAttributes
)
107 ReconstituteWalker
relocator(LowLevelMemoryUtilities::difference(ipcAttributes
, base
));
108 ContextAttributes
= ipcAttributes
; // fix context->attr vector link
109 for (uint32 n
= 0; n
< attributesInUse(); n
++)
110 walk(relocator
, (*this)[n
]);
117 size_t Context::Builder::make()
120 LowLevelMemoryUtilities::alignUp(slotCount
* sizeof(CSSM_CONTEXT_ATTRIBUTE
));
121 size_t totalSize
= vectorSize
+ sizer
;
122 attributes
= reinterpret_cast<Attr
*>(allocator
.malloc(totalSize
));
123 copier
= LowLevelMemoryUtilities::increment(attributes
, vectorSize
);
128 void Context::Builder::done(CSSM_CONTEXT_ATTRIBUTE
* &attributes
, uint32
&count
)
130 assert(slot
== slotCount
); // match pass profiles
131 attributes
= this->attributes
;
133 this->attributes
= NULL
; // delivered the goods, no longer our responsibility
140 #if defined(DEBUGDUMP)
142 static void dumpData(CSSM_DATA
*data
)
145 Debug::dump("[NULL]");
147 Debug::dump("[%p,%ld]@%p", data
->Data
, data
->Length
, data
);
150 void Context::Attr::dump() const
152 Debug::dump(" Attr{type=%x, size=%d, value=", int(AttributeType
), int(AttributeLength
));
153 switch (AttributeType
& CSSM_ATTRIBUTE_TYPE_MASK
) {
154 case CSSM_ATTRIBUTE_DATA_UINT32
:
155 Debug::dump("%ld", long(Attribute
.Uint32
)); break;
156 case CSSM_ATTRIBUTE_DATA_STRING
:
157 Debug::dump("%s@%p", Attribute
.String
, Attribute
.String
); break;
158 case CSSM_ATTRIBUTE_DATA_CSSM_DATA
:
159 dumpData(Attribute
.Data
);
161 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA
:
162 dumpData(&Attribute
.CryptoData
->Param
);
165 Debug::dump("%p", Attribute
.String
); break; // (slightly unclean)
170 void Context::dump(const char *title
, const CSSM_CONTEXT_ATTRIBUTE
*attrs
) const
173 attrs
= ContextAttributes
;
174 Debug::dump("Context %s{type=%d, alg=%d, CSP=%u, %d attributes@%p:\n",
176 int(ContextType
), int(AlgorithmType
), (unsigned int)CSPHandle
,
177 int(NumberOfAttributes
), attrs
);
178 for (unsigned int n
= 0; n
< NumberOfAttributes
; n
++)
179 Attr::overlay(attrs
[n
]).dump();
180 Debug::dump("} // end Context\n");