2 * Copyright (c) 2000-2001,2003-2004,2006,2011,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // context - manage CSSM (cryptographic) contexts every which way.
28 // A note on memory management:
29 // Context attributes are allocated from application memory in big chunks comprising
30 // many attributes as well as the attribute array itself. The CSSM_CONTEXT fields
31 // NumberOfAttributes and ContextAttributes are handled as a group. Context::Builder
32 // and Context::copyFrom assume these fields are undefined and fill them. Context::clear
33 // assumes they are valid and invalides them, freeing memory.
35 // You may also want to look at cssmcontext.h in CSSM proper, where CSSM's internal Context
36 // objects are built on top of our Context class.
38 #include <security_cdsa_utilities/context.h>
42 // Construct Context objects
44 Context::Context(CSSM_CONTEXT_TYPE type
, CSSM_ALGORITHMS algorithmId
)
48 AlgorithmType
= algorithmId
;
53 // Delete a single attribute from a Context by type.
54 // We implement this by simply nulling out the slot - the memory is not released,
55 // and will not be reclaimed until the Context is deleted or reconstructed for some reason.
57 void Context::deleteAttribute(CSSM_ATTRIBUTE_TYPE type
)
59 for (uint32 n
= 0; n
< attributesInUse(); n
++)
60 if (ContextAttributes
[n
].AttributeType
== type
) {
61 ContextAttributes
[n
].AttributeType
= CSSM_ATTRIBUTE_NONE
;
62 ContextAttributes
[n
].AttributeLength
= 0;
66 CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT
);
71 // This swiss-army-knife function performs a deep copy of all of a Context's attributes,
72 // bundling them up into a single memory node and storing them into a pointer/count pair.
73 // It also returns the size of the memory block allocated, in case you care (IPC does).
75 size_t Context::copyAttributes(CSSM_CONTEXT_ATTRIBUTE
* &attrs
, uint32
&count
,
76 Allocator
&alloc
) const
78 Context::Builder
builder(alloc
);
79 for (unsigned n
= 0; n
< attributesInUse(); n
++)
80 builder
.setup(ContextAttributes
[n
]);
81 size_t size
= builder
.make();
82 for (unsigned n
= 0; n
< attributesInUse(); n
++)
83 builder
.put(ContextAttributes
[n
]);
84 builder
.done(attrs
, count
);
90 // Locate attribute values by type.
91 // This function deals in attribute vectors, not contexts; hence the explicit count argument.
92 // Returns NULL for attribute not found.
94 Context::Attr
*Context::find(CSSM_ATTRIBUTE_TYPE theType
,
95 const CSSM_CONTEXT_ATTRIBUTE
*attrs
, unsigned int count
)
97 for (unsigned n
= 0; n
< count
; n
++)
98 if (attrs
[n
].AttributeType
== theType
)
99 return (Attr
*)&attrs
[n
];
105 // Post-IPC context fixup.
106 // A Context is transmitted via IPC as a two-element blob. The first is the Context
107 // structure itself, which is taken as flat. The second is the flattened attribute
108 // vector blob as produced by the Context::Builder class. Since IPC will relocate
109 // each blob, we need to offset all internal pointers to compensate.
111 void Context::postIPC(void *base
, CSSM_CONTEXT_ATTRIBUTE
*ipcAttributes
)
113 ReconstituteWalker
relocator(LowLevelMemoryUtilities::difference(ipcAttributes
, base
));
114 ContextAttributes
= ipcAttributes
; // fix context->attr vector link
115 for (uint32 n
= 0; n
< attributesInUse(); n
++)
116 walk(relocator
, (*this)[n
]);
123 size_t Context::Builder::make()
126 LowLevelMemoryUtilities::alignUp(slotCount
* sizeof(CSSM_CONTEXT_ATTRIBUTE
));
127 size_t totalSize
= vectorSize
+ sizer
;
128 attributes
= reinterpret_cast<Attr
*>(allocator
.malloc(totalSize
));
129 copier
= LowLevelMemoryUtilities::increment(attributes
, vectorSize
);
134 void Context::Builder::done(CSSM_CONTEXT_ATTRIBUTE
* &attributes
, uint32
&count
)
136 assert(slot
== slotCount
); // match pass profiles
137 attributes
= this->attributes
;
139 this->attributes
= NULL
; // delivered the goods, no longer our responsibility
146 #if defined(DEBUGDUMP)
148 static void dumpData(CSSM_DATA
*data
)
151 Debug::dump("[NULL]");
153 Debug::dump("[%p,%ld]@%p", data
->Data
, data
->Length
, data
);
156 void Context::Attr::dump() const
158 Debug::dump(" Attr{type=%x, size=%d, value=", int(AttributeType
), int(AttributeLength
));
159 switch (AttributeType
& CSSM_ATTRIBUTE_TYPE_MASK
) {
160 case CSSM_ATTRIBUTE_DATA_UINT32
:
161 Debug::dump("%ld", long(Attribute
.Uint32
)); break;
162 case CSSM_ATTRIBUTE_DATA_STRING
:
163 Debug::dump("%s@%p", Attribute
.String
, Attribute
.String
); break;
164 case CSSM_ATTRIBUTE_DATA_CSSM_DATA
:
165 dumpData(Attribute
.Data
);
167 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA
:
168 dumpData(&Attribute
.CryptoData
->Param
);
171 Debug::dump("%p", Attribute
.String
); break; // (slightly unclean)
176 void Context::dump(const char *title
, const CSSM_CONTEXT_ATTRIBUTE
*attrs
) const
179 attrs
= ContextAttributes
;
180 Debug::dump("Context %s{type=%d, alg=%d, CSP=%u, %d attributes@%p:\n",
182 int(ContextType
), int(AlgorithmType
), (unsigned int)CSPHandle
,
183 int(NumberOfAttributes
), attrs
);
184 for (unsigned int n
= 0; n
< NumberOfAttributes
; n
++)
185 Attr::overlay(attrs
[n
]).dump();
186 Debug::dump("} // end Context\n");