]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_cdsa_utilities / lib / cssmdata.cpp
diff --git a/Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp b/Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp
new file mode 100644 (file)
index 0000000..5dec094
--- /dev/null
@@ -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 <security_cdsa_utilities/cssmdata.h>
+#include <security_utilities/utilities.h>
+#include <cstring>
+#include <algorithm>
+
+
+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<const char *>(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