2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
22 #include <Security/utilities.h>
24 #include <Security/cssmerrno.h>
25 #include <Security/debugging.h>
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.
38 CssmCommonError::CssmCommonError()
39 IFDEBUG(: mCarrier(true))
43 CssmCommonError::CssmCommonError(const CssmCommonError
&source
)
46 source
.debugDiagnose(this);
47 mCarrier
= source
.mCarrier
;
48 source
.mCarrier
= false;
52 CssmCommonError::~CssmCommonError() throw ()
56 secdebug("exception", "%p handled", this);
60 OSStatus
CssmCommonError::osStatus() const
61 { return cssmError(); }
63 int CssmCommonError::unixError() const
65 OSStatus err
= osStatus();
67 // embedded UNIX errno values are returned verbatim
68 if (err
>= errSecErrnoBase
&& err
<= errSecErrnoLimit
)
69 return err
- errSecErrnoBase
;
71 // re-map certain CSSM errors
73 case CSSM_ERRCODE_MEMORY_ERROR
:
75 case CSSMERR_APPLEDL_DISK_FULL
:
77 case CSSMERR_APPLEDL_QUOTA_EXCEEDED
:
79 case CSSMERR_APPLEDL_FILE_TOO_BIG
:
82 // cannot map this to errno space
87 CSSM_RETURN
CssmCommonError::cssmError(CSSM_RETURN base
) const
88 { return CssmError::merge(cssmError(), base
); }
90 // default debugDiagnose gets what it can (virtually)
91 void CssmCommonError::debugDiagnose(const void *id
) const
94 secdebug("exception", "%p %s %s/0x%lx osstatus %ld",
95 id
, Debug::typeName(*this).c_str(),
96 cssmErrorString(cssmError()).c_str(), cssmError(),
103 // CssmError exceptions
105 CssmError::CssmError(CSSM_RETURN err
) : error(err
) { }
107 const char *CssmError::what() const throw ()
108 { return "CSSM exception"; }
110 CSSM_RETURN
CssmError::cssmError() const { return error
; }
112 OSStatus
CssmError::osStatus() const { return error
; }
114 void CssmError::throwMe(CSSM_RETURN err
) { throw CssmError(err
); }
118 // UnixError exceptions
120 UnixError::UnixError() : error(errno
) { }
122 UnixError::UnixError(int err
) : error(err
) { }
124 const char *UnixError::what() const throw ()
125 { return "UNIX error exception"; }
127 CSSM_RETURN
UnixError::cssmError() const
129 // map some UNIX errors to well defined CSSM codes; embed the rest
133 return CSSM_ERRCODE_MEMORY_ERROR
;
137 return CSSMERR_APPLEDL_DISK_FULL
;
141 return CSSMERR_APPLEDL_QUOTA_EXCEEDED
;
145 return CSSMERR_APPLEDL_FILE_TOO_BIG
;
148 return errSecErrnoBase
+ error
;
152 OSStatus
UnixError::osStatus() const
153 { return error
+ errSecErrnoBase
; }
155 int UnixError::unixError() const
158 void UnixError::throwMe(int err
) { throw UnixError(err
); }
160 // @@@ This is a hack for the Network protocol state machine
161 UnixError
UnixError::make(int err
) { return UnixError(err
); }
164 void UnixError::debugDiagnose(const void *id
) const
166 secdebug("exception", "%p UnixError %s (%d) osStatus %ld",
167 id
, strerror(error
), error
, osStatus());
173 // MacOSError exceptions
175 MacOSError::MacOSError(int err
) : error(err
) { }
177 const char *MacOSError::what() const throw ()
178 { return "MacOS error"; }
180 CSSM_RETURN
MacOSError::cssmError() const
181 { return error
; } // @@@ eventually...
183 OSStatus
MacOSError::osStatus() const
186 void MacOSError::throwMe(int error
)
187 { throw MacOSError(error
); }
191 // Manage CSSM errors
193 CSSM_RETURN
CssmError::merge(CSSM_RETURN error
, CSSM_RETURN base
)
195 if (0 < error
&& error
< CSSM_ERRORCODE_COMMON_EXTENT
) {
204 // CssmData out of line members
206 string
CssmData::toString() const
209 string(reinterpret_cast<const char *>(data()), length())
216 // GUID <-> string conversions.
217 // Note that we DO check for {} on input and insist on rigid formatting.
218 // We don't require a terminating null byte on input, but generate it on output.
220 char *Guid::toString(char buffer
[stringRepLength
+1]) const
222 sprintf(buffer
, "{%8.8lx-%4.4x-%4.4x-",
223 (unsigned long)Data1
, unsigned(Data2
), unsigned(Data3
));
224 for (int n
= 0; n
< 2; n
++)
225 sprintf(buffer
+ 20 + 2*n
, "%2.2x", Data4
[n
]);
227 for (int n
= 2; n
< 8; n
++)
228 sprintf(buffer
+ 21 + 2*n
, "%2.2x", Data4
[n
]);
234 Guid::Guid(const char *string
)
236 // Arguably, we should be more flexible on input. But exactly what
237 // padding rules should we follow, and how should we try to interprete
238 // "doubtful" variations? Given that GUIDs are essentially magic
239 // cookies, everybody's better off if we just cut-and-paste them
240 // around the universe...
243 if (sscanf(string
, "{%lx-%x-%x-", &d1
, &d2
, &d3
) != 3)
244 CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID
);
245 Data1
= d1
; Data2
= d2
; Data3
= d3
;
246 // once, we did not expect the - after byte 2 of Data4
247 bool newForm
= string
[24] == '-';
248 for (int n
= 0; n
< 8; n
++) {
250 if (sscanf(string
+ 20 + 2*n
+ (newForm
&& n
>= 2), "%2x", &dn
) != 1)
251 CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID
);
254 if (string
[37 - !newForm
] != '}')
255 CssmError::throwMe(CSSM_ERRCODE_INVALID_GUID
);
260 // CssmSubserviceUids.
261 // Note that for comparison, we ignore the version field.
262 // This is not necessarily the Right Choice, but suits certain
263 // constraints in the Sec* layer. Perhaps we might reconsider
264 // this after a thorough code review to determine the intended
265 // (by the standard) semantics and proper use. Yeah, right.
267 CssmSubserviceUid::CssmSubserviceUid(const CSSM_GUID
&guid
,
268 const CSSM_VERSION
*version
, uint32 subserviceId
, CSSM_SERVICE_TYPE subserviceType
)
271 SubserviceId
= subserviceId
;
272 SubserviceType
= subserviceType
;
276 Version
.Major
= Version
.Minor
= 0;
280 bool CssmSubserviceUid::operator == (const CSSM_SUBSERVICE_UID
&otherUid
) const
282 const CssmSubserviceUid
&other
= CssmSubserviceUid::overlay(otherUid
);
283 return subserviceId() == other
.subserviceId()
284 && subserviceType() == other
.subserviceType()
285 && guid() == other
.guid();
288 bool CssmSubserviceUid::operator < (const CSSM_SUBSERVICE_UID
&otherUid
) const
290 const CssmSubserviceUid
&other
= CssmSubserviceUid::overlay(otherUid
);
291 if (subserviceId() < other
.subserviceId())
293 if (subserviceId() > other
.subserviceId())
295 if (subserviceType() < other
.subserviceType())
297 if (subserviceType() > other
.subserviceType())
299 return guid() < other
.guid();
304 // Methods for the CssmKey class
306 CssmKey::CssmKey(const CSSM_KEY
&key
)
308 KeyHeader
= key
.KeyHeader
;
309 KeyData
= key
.KeyData
;
312 CssmKey::CssmKey(const CSSM_DATA
&keyData
)
316 KeyHeader
.HeaderVersion
= CSSM_KEYHEADER_VERSION
;
317 KeyHeader
.BlobType
= CSSM_KEYBLOB_RAW
;
318 KeyHeader
.Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
321 CssmKey::CssmKey(uint32 length
, void *data
)
324 KeyData
= CssmData(data
, length
);
325 KeyHeader
.HeaderVersion
= CSSM_KEYHEADER_VERSION
;
326 KeyHeader
.BlobType
= CSSM_KEYBLOB_RAW
;
327 KeyHeader
.Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
330 CryptoDataClass::~CryptoDataClass()