]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/utilities.cpp
Security-54.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / utilities.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // Utilities
21 //
22 #include <Security/utilities.h>
23
24 #include <Security/cssmerrno.h>
25 #include <Security/debugging.h>
26 #include <typeinfo>
27 #include <stdio.h>
28
29
30 //
31 // The base of the exception hierarchy.
32 // Note that the debug output here depends on a particular
33 // implementation feature of gcc; to wit, that the exception object
34 // is created and then copied (at least once) via its copy constructor.
35 // If your compiler does not invoke the copy constructor, you won't get
36 // debug output, but nothing worse should happen.
37 //
38 CssmCommonError::CssmCommonError()
39 IFDEBUG(: mCarrier(true))
40 {
41 }
42
43 CssmCommonError::CssmCommonError(const CssmCommonError &source)
44 {
45 #if !defined(NDEBUG)
46 source.debugDiagnose(this);
47 mCarrier = source.mCarrier;
48 source.mCarrier = false;
49 #endif //NDEBUG
50 }
51
52 CssmCommonError::~CssmCommonError() throw ()
53 {
54 #if !defined(NDEBUG)
55 if (mCarrier)
56 debug("exception", "%p handled", this);
57 #endif //NDEBUG
58 }
59
60 OSStatus CssmCommonError::osStatus() const
61 { return cssmError(); }
62
63 CSSM_RETURN CssmCommonError::cssmError(CSSM_RETURN base) const
64 { return CssmError::merge(cssmError(), base); }
65
66 // default debugDiagnose gets what it can (virtually)
67 void CssmCommonError::debugDiagnose(const void *id) const
68 {
69 #if !defined(NDEBUG)
70 debug("exception", "%p %s %s/0x%lx osstatus %ld",
71 id, Debug::typeName(*this).c_str(),
72 cssmErrorString(cssmError()).c_str(), cssmError(),
73 osStatus());
74 #endif //NDEBUG
75 }
76
77
78 //
79 // CssmError exceptions
80 //
81 CssmError::CssmError(CSSM_RETURN err) : error(err) { }
82
83 const char *CssmError::what() const throw ()
84 { return "CSSM exception"; }
85
86 CSSM_RETURN CssmError::cssmError() const { return error; }
87
88 OSStatus CssmError::osStatus() const { return error; }
89
90 void CssmError::throwMe(CSSM_RETURN err) { throw CssmError(err); }
91
92
93 //
94 // UnixError exceptions
95 //
96 UnixError::UnixError() : error(errno) { }
97
98 UnixError::UnixError(int err) : error(err) { }
99
100 const char *UnixError::what() const throw ()
101 { return "UNIX error exception"; }
102
103 CSSM_RETURN UnixError::cssmError() const
104 {
105 // @@@ this is a sample - go through and map errnos better
106 switch (error) {
107 #if defined(ENOMEM)
108 case ENOMEM:
109 return CSSM_ERRCODE_MEMORY_ERROR;
110 #endif
111 #if defined(ENOSYS)
112 case ENOSYS:
113 return CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED;
114 #endif
115 #if defined(ENOSPC)
116 case ENOSPC:
117 return CSSMERR_APPLEDL_DISK_FULL;
118 #endif
119 #if defined(EDQUOT)
120 case EDQUOT:
121 return CSSMERR_APPLEDL_QUOTA_EXCEEDED;
122 #endif
123 #if defined(EFBIG)
124 case EFBIG:
125 return CSSMERR_APPLEDL_FILE_TOO_BIG;
126 #endif
127 default:
128 return CSSM_ERRCODE_INTERNAL_ERROR;
129 }
130 }
131
132 OSStatus UnixError::osStatus() const { return cssmError(); }
133
134 void UnixError::throwMe(int err) { throw UnixError(err); }
135
136 // @@@ This is a hack for the Network protocol state machine
137 UnixError UnixError::make(int err) { return UnixError(err); }
138
139 #if !defined(NDEBUG)
140 void UnixError::debugDiagnose(const void *id) const
141 {
142 debug("exception", "%p UnixError %s (%d) osStatus %ld",
143 id, strerror(error), error, osStatus());
144 }
145 #endif //NDEBUG
146
147
148 //
149 // MacOSError exceptions
150 //
151 MacOSError::MacOSError(int err) : error(err) { }
152
153 const char *MacOSError::what() const throw ()
154 { return "MacOS error"; }
155
156 CSSM_RETURN MacOSError::cssmError() const
157 { return error; } // @@@ eventually...
158
159 OSStatus MacOSError::osStatus() const
160 { return error; }
161
162 void MacOSError::throwMe(int error)
163 { throw MacOSError(error); }
164
165
166 //
167 // Manage CSSM errors
168 //
169 CSSM_RETURN CssmError::merge(CSSM_RETURN error, CSSM_RETURN base)
170 {
171 if (0 < error && error < CSSM_ERRORCODE_COMMON_EXTENT) {
172 return base + error;
173 } else {
174 return error;
175 }
176 }
177
178
179 //
180 // CssmData out of line members
181 //
182 string CssmData::toString() const
183 {
184 return data() ?
185 string(reinterpret_cast<const char *>(data()), length())
186 :
187 string();
188 }
189
190
191 //
192 // GUID <-> string conversions.
193 // Note that we DO check for {} on input and insist on rigid formatting.
194 // We don't require a terminating null byte on input, but generate it on output.
195 //
196 char *Guid::toString(char buffer[stringRepLength+1]) const
197 {
198 sprintf(buffer, "{%8.8lx-%4.4x-%4.4x-",
199 (unsigned long)Data1, unsigned(Data2), unsigned(Data3));
200 for (int n = 0; n < 2; n++)
201 sprintf(buffer + 20 + 2*n, "%2.2x", Data4[n]);
202 buffer[24] = '-';
203 for (int n = 2; n < 8; n++)
204 sprintf(buffer + 21 + 2*n, "%2.2x", Data4[n]);
205 buffer[37] = '}';
206 buffer[38] = '\0';
207 return buffer;
208 }
209
210 Guid::Guid(const char *string)
211 {
212 // Arguably, we should be more flexible on input. But exactly what
213 // padding rules should we follow, and how should we try to interprete
214 // "doubtful" variations? Given that GUIDs are essentially magic
215 // cookies, everybody's better off if we just cut-and-paste them
216 // around the universe...
217 unsigned long d1;
218 unsigned int d2, d3;
219 if (sscanf(string, "{%lx-%x-%x-", &d1, &d2, &d3) != 3)
220 CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID);
221 Data1 = d1; Data2 = d2; Data3 = d3;
222 // once, we did not expect the - after byte 2 of Data4
223 bool newForm = string[24] == '-';
224 for (int n = 0; n < 8; n++) {
225 unsigned int dn;
226 if (sscanf(string + 20 + 2*n + (newForm && n >= 2), "%2x", &dn) != 1)
227 CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID);
228 Data4[n] = dn;
229 }
230 if (string[37 - !newForm] != '}')
231 CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID);
232 }
233
234
235 //
236 // Methods for the CssmKey class
237 //
238 CssmKey::CssmKey(CSSM_KEY &key)
239 {
240 KeyHeader = key.KeyHeader;
241 KeyData = key.KeyData;
242 key.KeyData.Length = 0;
243 key.KeyData.Data = NULL;
244 }
245
246 CssmKey::CssmKey(CSSM_DATA &keyData)
247 {
248 memset(this, 0, sizeof(*this));
249 KeyData = keyData;
250 keyData.Length = 0;
251 keyData.Data = NULL;
252 KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
253 KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
254 KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
255 }
256
257 CssmKey::CssmKey(uint32 length, uint8 *data)
258 {
259 memset(this, 0, sizeof(*this));
260 KeyData.Length = length;
261 KeyData.Data = data;
262 KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
263 KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
264 KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
265 }
266
267 CryptoDataClass::~CryptoDataClass()
268 {
269 }
270
271 //
272 // Debug support
273 //
274 #if !defined(NDEBUG)
275
276 #endif //NDEBUG