X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp?ds=sidebyside diff --git a/Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp new file mode 100644 index 00000000..5dec094e --- /dev/null +++ b/Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +// +// cssmdata.cpp -- Manager different CssmData types +// +#include +#include +#include +#include + + +namespace Security { + + +// +// Comparing raw CSSM_DATA things +// +bool operator == (const CSSM_DATA &d1, const CSSM_DATA &d2) +{ + if (&d1 == &d2) + return true; // identical + if (d1.Length != d2.Length) + return false; // can't be + if (d1.Data == d2.Data) + return true; // points to same data + return !memcmp(d1.Data, d2.Data, d1.Length); +} + + +// +// CssmData out of line members +// +string CssmData::toString() const +{ + return data() ? + string(reinterpret_cast(data()), length()) + : + string(); +} + + +// +// Conversion from/to hex digits. +// This could be separate functions, or Rep templates, but we just hang +// it onto generic CssmData. +// +string CssmData::toHex() const +{ + static const char digits[] = "0123456789abcdef"; + string result; + unsigned char *p = Data; + for (uint32 n = 0; n < length(); n++) { + result.push_back(digits[p[n] >> 4]); + result.push_back(digits[p[n] & 0xf]); + } + return result; +} + +static unsigned char hexValue(char c) +{ + static const char digits[] = "0123456789abcdef"; + if (const char *p = strchr(digits, tolower(c))) + return p - digits; + else + return 0; +} + +void CssmData::fromHex(const char *hexDigits) +{ + size_t bytes = strlen(hexDigits) / 2; // (discards malformed odd end) + length(bytes); // (will assert if we try to grow it) + for (size_t n = 0; n < bytes; n++) { + Data[n] = hexValue(hexDigits[2*n]) << 4 | hexValue(hexDigits[2*n+1]); + } +} + + +// +// Conversion from/to OID strings. +// These are not strict; invalid inputs are not necessarily flagged as errors. +// +static unsigned long getOid(const CssmData &data, unsigned int &pos) +{ + unsigned long q = 0; + do { + q = q * 128 + (data.byte(pos) & ~0x80); + } while (pos < data.length() && data.byte(pos++) & 0x80); + return q; +} + +string CssmData::toOid() const +{ + if (length() == 0) + return ""; + + unsigned int pos = 0; + + // first byte is composite (q1,q2) + char buffer[10]; + unsigned long oid1 = getOid(*this, pos); + unsigned long q1 = min(oid1 / 40, 2ul); + snprintf(buffer, sizeof(buffer), "%lu.%lu", q1, oid1 - q1 * 40); + string s = buffer; + + // now for the rest + while (pos < length()) { + char buffer[20]; + snprintf(buffer, sizeof(buffer), ".%lu", getOid(*this, pos)); + s += buffer; + } + return s; +} + +static void putOid(CssmOwnedData &data, unsigned long id) +{ + unsigned char buffer[sizeof(unsigned long) * 2]; // * (8/7) + 1, conservative + unsigned char *p = buffer + sizeof(buffer); + do { + *--p = 0x80 | (id & 0x7F); // last 7 bits, high bit set + } while ((id >>= 7) > 0); + buffer[sizeof(buffer) - 1] &= ~0x80; // clear last high bit (end of number) + data.append(p, buffer + sizeof(buffer) - p); // append generated byte string +} + +// +// Convert OID string (1.2.3...) into CssmOid form. +// Allocates the data, replacing current contents. +// Will not process oid elements out of unsigned long range. +// +void CssmOwnedData::fromOid(const char *oid) +{ + this->length(0); // make empty + + // first two elements get combined in weird&wacky ways + unsigned long q1 = strtoul(oid, (char **)&oid, 10); + if (*oid++ != '.') + return; + unsigned long q2 = strtoul(oid, (char **)&oid, 10); + putOid(*this, 40 * q1 + q2); + while (oid[0] == '.') { + oid++; + putOid(*this, strtoul(oid, (char **)&oid, 10)); + } +} + + +// +// Managed data objects +// +CssmManagedData::~CssmManagedData() +{ } + + +// +// CssmOwnedData +// +void CssmOwnedData::set(CssmManagedData &source) +{ + if (source.length() == 0) { // source is empty + reset(); // so just clear old data + } else if (allocator == source.allocator) { // compatible allocators + if (referent.data() == source.data()) { // same data *and* we own it?! + assert(this == &source); // this better *be* me! + } else { // different data + reset(); // give up our old data + referent = source.release(); // take over source's data + } + } else { // different allocators + copy(source); // make a copy with our allocator + source.reset(); // release source's data + } +} + + +// +// CssmAutoData +// +CssmData CssmAutoData::release() +{ + CssmData result = mData; + mData.clear(); + return result; +} + +void CssmAutoData::reset() +{ + allocator.free(mData); + mData.clear(); +} + + +// +// CssmRemoteData +// +CssmData CssmRemoteData::release() +{ + iOwnTheData = false; + return referent; +} + +void CssmRemoteData::reset() +{ + if (iOwnTheData) + allocator.free(referent); + referent.clear(); +} + + +// +// Date stuff +// +CssmDateData::CssmDateData(const CSSM_DATE &date) +: CssmData(buffer, sizeof(buffer)) +{ + memcpy(buffer, date.Year, 4); + memcpy(buffer + 4, date.Month, 2); + memcpy(buffer + 6, date.Day, 2); +} + + +CssmData& CssmOwnedData::get() const throw() +{ + return referent; +} + +} // end namespace Security