1/* 2 * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple 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// cssmdata.cpp -- Manager different CssmData types 27// 28#include <security_cdsa_utilities/cssmdata.h> 29#include <security_utilities/utilities.h> 30#include <cstring> 31#include <algorithm> 32 33 34namespace Security { 35 36 37// 38// Comparing raw CSSM_DATA things 39// 40bool operator == (const CSSM_DATA &d1, const CSSM_DATA &d2) 41{ 42 if (&d1 == &d2) 43 return true; // identical 44 if (d1.Length != d2.Length) 45 return false; // can't be 46 if (d1.Data == d2.Data) 47 return true; // points to same data 48 return !memcmp(d1.Data, d2.Data, d1.Length); 49} 50 51 52// 53// CssmData out of line members 54// 55string CssmData::toString() const 56{ 57 return data() ? 58 string(reinterpret_cast<const char *>(data()), length()) 59 : 60 string(); 61} 62 63 64// 65// Conversion from/to hex digits. 66// This could be separate functions, or Rep templates, but we just hang 67// it onto generic CssmData. 68// 69string CssmData::toHex() const 70{ 71 static const char digits[] = "0123456789abcdef"; 72 string result; 73 unsigned char *p = Data; 74 for (uint32 n = 0; n < length(); n++) { 75 result.push_back(digits[p[n] >> 4]); 76 result.push_back(digits[p[n] & 0xf]); 77 } 78 return result; 79} 80 81static unsigned char hexValue(char c) 82{ 83 static const char digits[] = "0123456789abcdef"; 84 if (const char *p = strchr(digits, tolower(c))) 85 return p - digits; 86 else 87 return 0; 88} 89 90void CssmData::fromHex(const char *hexDigits) 91{ 92 size_t bytes = strlen(hexDigits) / 2; // (discards malformed odd end) 93 length(bytes); // (will assert if we try to grow it) 94 for (size_t n = 0; n < bytes; n++) { 95 Data[n] = hexValue(hexDigits[2*n]) << 4 | hexValue(hexDigits[2*n+1]); 96 } 97} 98 99 100// 101// Conversion from/to OID strings. 102// These are not strict; invalid inputs are not necessarily flagged as errors. 103// 104static unsigned long getOid(const CssmData &data, unsigned int &pos) 105{ 106 unsigned long q = 0; 107 do { 108 q = q * 128 + (data.byte(pos) & ~0x80); 109 } while (pos < data.length() && data.byte(pos++) & 0x80); 110 return q; 111} 112 113string CssmData::toOid() const 114{ 115 if (length() == 0) 116 return ""; 117 118 unsigned int pos = 0; 119 120 // first byte is composite (q1,q2) 121 char buffer[10]; 122 unsigned long oid1 = getOid(*this, pos); 123 unsigned long q1 = min(oid1 / 40, 2ul); 124 snprintf(buffer, sizeof(buffer), "%lu.%lu", q1, oid1 - q1 * 40); 125 string s = buffer; 126 127 // now for the rest 128 while (pos < length()) { 129 char buffer[20]; 130 snprintf(buffer, sizeof(buffer), ".%lu", getOid(*this, pos)); 131 s += buffer; 132 } 133 return s; 134} 135 136static void putOid(CssmOwnedData &data, unsigned long id) 137{ 138 unsigned char buffer[sizeof(unsigned long) * 2]; // * (8/7) + 1, conservative 139 unsigned char *p = buffer + sizeof(buffer); 140 do { 141 *--p = 0x80 | (id & 0x7F); // last 7 bits, high bit set 142 } while ((id >>= 7) > 0); 143 buffer[sizeof(buffer) - 1] &= ~0x80; // clear last high bit (end of number) 144 data.append(p, buffer + sizeof(buffer) - p); // append generated byte string 145} 146 147// 148// Convert OID string (1.2.3...) into CssmOid form. 149// Allocates the data, replacing current contents. 150// Will not process oid elements out of unsigned long range. 151// 152void CssmOwnedData::fromOid(const char *oid) 153{ 154 this->length(0); // make empty 155 156 // first two elements get combined in weird&wacky ways 157 unsigned long q1 = strtoul(oid, (char **)&oid, 10); 158 if (*oid++ != '.') 159 return; 160 unsigned long q2 = strtoul(oid, (char **)&oid, 10); 161 putOid(*this, 40 * q1 + q2); 162 while (oid[0] == '.') { 163 oid++; 164 putOid(*this, strtoul(oid, (char **)&oid, 10)); 165 } 166} 167 168 169// 170// Managed data objects 171// 172CssmManagedData::~CssmManagedData() 173{ } 174 175 176// 177// CssmOwnedData 178// 179void CssmOwnedData::set(CssmManagedData &source) 180{ 181 if (source.length() == 0) { // source is empty 182 reset(); // so just clear old data 183 } else if (allocator == source.allocator) { // compatible allocators 184 if (referent.data() == source.data()) { // same data *and* we own it?! 185 assert(this == &source); // this better *be* me! 186 } else { // different data 187 reset(); // give up our old data 188 referent = source.release(); // take over source's data 189 } 190 } else { // different allocators 191 copy(source); // make a copy with our allocator 192 source.reset(); // release source's data 193 } 194} 195 196 197// 198// CssmAutoData 199// 200CssmData CssmAutoData::release() 201{ 202 CssmData result = mData; 203 mData.clear(); 204 return result; 205} 206 207void CssmAutoData::reset() 208{ 209 allocator.free(mData); 210 mData.clear(); 211} 212 213 214// 215// CssmRemoteData 216// 217CssmData CssmRemoteData::release() 218{ 219 iOwnTheData = false; 220 return referent; 221} 222 223void CssmRemoteData::reset() 224{ 225 if (iOwnTheData) 226 allocator.free(referent); 227 referent.clear(); 228} 229 230 231// 232// Date stuff 233// 234CssmDateData::CssmDateData(const CSSM_DATE &date) 235: CssmData(buffer, sizeof(buffer)) 236{ 237 memcpy(buffer, date.Year, 4); 238 memcpy(buffer + 4, date.Month, 2); 239 memcpy(buffer + 6, date.Day, 2); 240} 241 242 243CssmData& CssmOwnedData::get() const throw() 244{ 245 return referent; 246} 247 248} // end namespace Security 249