1/* 2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 3 * 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 8 * using this file. 9 * 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. 16 */ 17 18 19// 20// csputilities - utility classes for CSP implementation 21// 22#include <security_cdsa_plugin/CSPsession.h> 23#include <security_cdsa_plugin/cssmplugin.h> 24#include <security_utilities/memutils.h> 25#include <security_cdsa_utilities/cssmdates.h> 26 27using LowLevelMemoryUtilities::increment; 28 29 30// 31// Writer objects 32// 33CSPFullPluginSession::Writer::Writer(CssmData *v, uint32 n, CssmData *rem) 34: vec(v), firstVec(v), lastVec(v + n - 1), remData(rem) 35{ 36 if (vec == NULL || n == 0) 37 CssmError::throwMe(CSSMERR_CSP_INVALID_OUTPUT_VECTOR); // CDSA p.253, amended 38 useData(vec); 39 written = 0; 40} 41 42void CSPFullPluginSession::Writer::allocate(size_t needed, Allocator &alloc) 43{ 44 if (!needed) 45 return; // No output buffer space needed so we're done. 46 else if (vec == firstVec && !*vec) { // initial null vector element, wants allocation there 47 *vec = makeBuffer(needed, alloc); 48 lastVec = vec; // ignore all subsequent buffers in vector 49 useData(vec); 50 } else { 51 // how much output space do we have left? 52 size_t size = currentSize; 53 for (CssmData *v = vec + 1; v <= lastVec; v++) 54 size += v->length(); 55 if (size >= needed) 56 return; // we're fine 57 if (remData) { 58 if (!*remData) { // have overflow, can allocate 59 *remData = makeBuffer(needed - size, alloc); 60 return; // got it 61 } 62 if (size + remData->length() >= needed) 63 return; // will fit into overflow 64 } 65 // not enough buffer space, and can't allocate 66 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); 67 } 68} 69 70void CSPFullPluginSession::Writer::nextBlock(void * &ptr, size_t &size) 71{ 72 ptr = currentBuffer; 73 size = currentSize; 74} 75 76void CSPFullPluginSession::Writer::use(size_t used) 77{ 78 assert(used <= currentSize); 79 written += used; 80 if (used < currentSize) { 81 currentBuffer = increment(currentBuffer, used); 82 currentSize -= used; 83 } else { 84 if (vec < lastVec) { 85 useData(vec++); // use next vector buffer 86 } else if (vec == lastVec && remData) { 87 useData(remData); // use remainder buffer 88 vec++; // mark used 89#if !defined(NDEBUG) && 0 90 } else if (vec == lastVec) { 91 vec++; 92 } else if (vec > lastVec) { 93 assert(false); // 2nd try to overflow end 94#endif /* !NDEBUG */ 95 } else { 96 currentBuffer = NULL; // no more output buffer 97 currentSize = 0; 98 } 99 } 100} 101 102void CSPFullPluginSession::Writer::put(void *addr, size_t size) 103{ 104 while (size > 0) { 105 void *p; size_t sz; 106 nextBlock(p, sz); 107 if (size < sz) 108 sz = size; // cap transfer 109 memcpy(p, addr, sz); 110 use(sz); 111 addr = increment(addr, sz); 112 size -= sz; 113 } 114} 115 116size_t CSPFullPluginSession::Writer::close() 117{ 118 return written; 119} 120 121 122// 123// Common algorithm utilities 124// 125void CSPFullPluginSession::setKey(CssmKey &key, 126 const Context &context, CSSM_KEYCLASS keyClass, 127 CSSM_KEYATTR_FLAGS attrs, CSSM_KEYUSE use) 128{ 129 // general setup 130 memset(&key.KeyHeader, 0, sizeof(key.KeyHeader)); 131 key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; 132 key.KeyHeader.CspId = plugin.myGuid(); 133 key.KeyHeader.AlgorithmId = context.algorithm(); 134 key.KeyHeader.KeyClass = keyClass; 135 key.KeyHeader.KeyUsage = use; 136 key.KeyHeader.KeyAttr = attrs; 137 138 CssmDate *theDate = context.get<CssmDate>(CSSM_ATTRIBUTE_START_DATE); 139 if(theDate) { 140 key.KeyHeader.StartDate = *theDate; 141 } 142 theDate = context.get<CssmDate>(CSSM_ATTRIBUTE_END_DATE); 143 if(theDate) { 144 key.KeyHeader.EndDate = *theDate; 145 } 146 147 // defaults (change as needed) 148 key.KeyHeader.WrapAlgorithmId = CSSM_ALGID_NONE; 149 150 // clear key data (standard says, "Always allocate this, ignore prior contents.") 151 key = CssmData(); 152} 153