]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_cdsa_utilities/lib/cssmdata.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_cdsa_utilities / lib / cssmdata.cpp
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
34 namespace Security {
35
36
37 //
38 // Comparing raw CSSM_DATA things
39 //
40 bool 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 //
55 string 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 //
69 string 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
81 static 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
90 void 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 //
104 static 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
113 string 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
136 static 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 //
152 void 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 //
172 CssmManagedData::~CssmManagedData()
173 { }
174
175
176 //
177 // CssmOwnedData
178 //
179 void 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 //
200 CssmData CssmAutoData::release()
201 {
202 CssmData result = mData;
203 mData.clear();
204 return result;
205 }
206
207 void CssmAutoData::reset()
208 {
209 allocator.free(mData);
210 mData.clear();
211 }
212
213
214 //
215 // CssmRemoteData
216 //
217 CssmData CssmRemoteData::release()
218 {
219 iOwnTheData = false;
220 return referent;
221 }
222
223 void CssmRemoteData::reset()
224 {
225 if (iOwnTheData)
226 allocator.free(referent);
227 referent.clear();
228 }
229
230
231 //
232 // Date stuff
233 //
234 CssmDateData::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
243 CssmData& CssmOwnedData::get() const throw()
244 {
245 return referent;
246 }
247
248 } // end namespace Security