1/* 2 * Copyright (c) 2000-2001,2003-2004,2006 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// context - manage CSSM (cryptographic) contexts every which way. 27// 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. 34// 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. 37// 38#include <security_cdsa_utilities/context.h> 39 40 41// 42// Construct Context objects 43// 44Context::Context(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS algorithmId) 45{ 46 clearPod(); 47 ContextType = type; 48 AlgorithmType = algorithmId; 49} 50 51 52// 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. 56// 57void Context::deleteAttribute(CSSM_ATTRIBUTE_TYPE type) 58{ 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; 63 return; 64 } 65 // not found 66 CssmError::throwMe(CSSMERR_CSSM_ATTRIBUTE_NOT_IN_CONTEXT); 67} 68 69 70// 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). 74// 75size_t Context::copyAttributes(CSSM_CONTEXT_ATTRIBUTE * &attrs, uint32 &count, 76 Allocator &alloc) const 77{ 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); 85 return size; 86} 87 88 89// 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. 93// 94Context::Attr *Context::find(CSSM_ATTRIBUTE_TYPE theType, 95 const CSSM_CONTEXT_ATTRIBUTE *attrs, unsigned int count) 96{ 97 for (unsigned n = 0; n < count; n++) 98 if (attrs[n].AttributeType == theType) 99 return (Attr *)&attrs[n]; 100 return NULL; 101} 102 103 104// 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. 110// 111void Context::postIPC(void *base, CSSM_CONTEXT_ATTRIBUTE *ipcAttributes) 112{ 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]); 117} 118 119 120// 121// Context Builders 122// 123size_t Context::Builder::make() 124{ 125 size_t vectorSize = 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); 130 slot = 0; 131 return totalSize; 132} 133 134void Context::Builder::done(CSSM_CONTEXT_ATTRIBUTE * &attributes, uint32 &count) 135{ 136 assert(slot == slotCount); // match pass profiles 137 attributes = this->attributes; 138 count = slotCount; 139 this->attributes = NULL; // delivered the goods, no longer our responsibility 140} 141 142 143// 144// Debugging support 145// 146#if defined(DEBUGDUMP) 147 148static void dumpData(CSSM_DATA *data) 149{ 150 if (data == NULL) 151 Debug::dump("[NULL]"); 152 else 153 Debug::dump("[%p,%ld]@%p", data->Data, data->Length, data); 154} 155 156void Context::Attr::dump() const 157{ 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); 166 break; 167 case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA: 168 dumpData(&Attribute.CryptoData->Param); 169 break; 170 default: 171 Debug::dump("%p", Attribute.String); break; // (slightly unclean) 172 }; 173 Debug::dump("}\n"); 174} 175 176void Context::dump(const char *title, const CSSM_CONTEXT_ATTRIBUTE *attrs) const 177{ 178 if (attrs == NULL) 179 attrs = ContextAttributes; 180 Debug::dump("Context %s{type=%d, alg=%d, CSP=%u, %d attributes@%p:\n", 181 title ? title : "", 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"); 187} 188 189#endif //DEBUGDUMP 190