]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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); | |
427c49bc A |
123 | unsigned long q1 = min(oid1 / 40, 2ul); |
124 | snprintf(buffer, sizeof(buffer), "%lu.%lu", q1, oid1 - q1 * 40); | |
b1ab9ed8 A |
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 |