]>
Commit | Line | Data |
---|---|---|
bac41a7b A |
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 | * cssm utilities | |
21 | */ | |
22 | #ifndef _H_UTILITIES | |
23 | #define _H_UTILITIES | |
24 | ||
25 | #include <Security/cssm.h> | |
26 | #include <Security/utility_config.h> | |
27 | #include <exception> | |
28 | #include <new> | |
29 | #include <string> | |
30 | #include <errno.h> | |
31 | #include <string.h> | |
32 | ||
33 | #ifdef _CPP_UTILITIES | |
34 | #pragma export on | |
35 | #endif | |
36 | ||
37 | namespace Security | |
38 | { | |
39 | ||
40 | // | |
41 | // Elementary debugging support. | |
42 | // #include <debugging.h> for more debugging facilities. | |
43 | // | |
44 | #if defined(NDEBUG) | |
45 | ||
46 | # define safe_cast static_cast | |
47 | # define safer_cast static_cast | |
48 | ||
49 | # define IFDEBUG(it) /* do nothing */ | |
50 | # define IFNDEBUG(it) it | |
51 | ||
52 | #else | |
53 | ||
54 | template <class Derived, class Base> | |
55 | inline Derived safer_cast(Base &base) | |
56 | { | |
57 | return dynamic_cast<Derived>(base); | |
58 | } | |
59 | ||
60 | template <class Derived, class Base> | |
61 | inline Derived safe_cast(Base *base) | |
62 | { | |
63 | if (base == NULL) | |
64 | return NULL; // okay to cast NULL to NULL | |
65 | Derived p = dynamic_cast<Derived>(base); | |
66 | assert(p); | |
67 | return p; | |
68 | } | |
69 | ||
70 | # define IFDEBUG(it) it | |
71 | # define IFNDEBUG(it) /* do nothing */ | |
72 | ||
73 | #endif //NDEBUG | |
74 | ||
75 | ||
76 | // | |
77 | // Place this into your class definition if you don't want it to be copyable | |
78 | // or asignable. This will not prohibit allocation on the stack or in static | |
79 | // memory, but it will make anything derived from it, and anything containing | |
80 | // it, fixed-once-created. A proper object, I suppose. | |
81 | // | |
82 | #define NOCOPY(Type) private: Type(const Type &); void operator = (const Type &); | |
83 | ||
84 | ||
85 | // | |
86 | // Exception hierarchy | |
87 | // | |
29654253 | 88 | class CssmCommonError : public std::exception { |
bac41a7b A |
89 | protected: |
90 | CssmCommonError(); | |
91 | CssmCommonError(const CssmCommonError &source); | |
92 | public: | |
29654253 | 93 | virtual ~CssmCommonError() throw (); |
bac41a7b A |
94 | |
95 | virtual CSSM_RETURN cssmError() const = 0; | |
96 | virtual CSSM_RETURN cssmError(CSSM_RETURN base) const; | |
97 | virtual OSStatus osStatus() const; | |
29654253 A |
98 | |
99 | protected: | |
100 | virtual void debugDiagnose(const void *id) const; // used internally for debug logging | |
101 | ||
102 | private: | |
103 | IFDEBUG(mutable bool mCarrier); // primary carrier of exception flow | |
bac41a7b A |
104 | }; |
105 | ||
106 | class CssmError : public CssmCommonError { | |
107 | protected: | |
108 | CssmError(CSSM_RETURN err); | |
109 | public: | |
110 | const CSSM_RETURN error; | |
111 | virtual CSSM_RETURN cssmError() const; | |
112 | virtual OSStatus osStatus() const; | |
29654253 | 113 | virtual const char *what () const throw (); |
bac41a7b A |
114 | |
115 | static CSSM_RETURN merge(CSSM_RETURN error, CSSM_RETURN base); | |
116 | ||
29654253 | 117 | static void check(CSSM_RETURN error) { if (error != CSSM_OK) throwMe(error); } |
bac41a7b A |
118 | static void throwMe(CSSM_RETURN error) __attribute__((noreturn)); |
119 | }; | |
120 | ||
121 | class UnixError : public CssmCommonError { | |
122 | protected: | |
123 | UnixError(); | |
124 | UnixError(int err); | |
125 | public: | |
126 | const int error; | |
127 | virtual CSSM_RETURN cssmError() const; | |
128 | virtual OSStatus osStatus() const; | |
29654253 | 129 | virtual const char *what () const throw (); |
bac41a7b A |
130 | |
131 | static void check(int result) { if (result == -1) throwMe(); } | |
132 | static void throwMe(int err = errno) __attribute__((noreturn)); | |
133 | ||
134 | // @@@ This is a hack for the Network protocol state machine | |
135 | static UnixError make(int err = errno); | |
29654253 A |
136 | |
137 | private: | |
138 | IFDEBUG(void debugDiagnose(const void *id) const); | |
bac41a7b A |
139 | }; |
140 | ||
141 | class MacOSError : public CssmCommonError { | |
142 | protected: | |
143 | MacOSError(int err); | |
144 | public: | |
145 | const int error; | |
146 | virtual CSSM_RETURN cssmError() const; | |
147 | virtual OSStatus osStatus() const; | |
29654253 | 148 | virtual const char *what () const throw (); |
bac41a7b A |
149 | |
150 | static void check(OSStatus status) { if (status != noErr) throwMe(status); } | |
151 | static void throwMe(int err) __attribute__((noreturn)); | |
152 | }; | |
153 | ||
154 | ||
155 | // | |
156 | // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions. | |
157 | // Usage: | |
158 | // BEGIN_API | |
159 | // ... your C++ code here ... | |
160 | // END_API(base) // returns CSSM_RETURN on exception; complete it to 'base' (DL, etc.) class; | |
161 | // // returns CSSM_OK on fall-through | |
162 | // END_API0 // completely ignores exceptions; falls through in all cases | |
163 | // END_API1(bad) // return (bad) on exception; fall through on success | |
164 | // | |
165 | #define BEGIN_API try { | |
166 | #define END_API(base) } \ | |
167 | catch (const CssmCommonError &err) { return err.cssmError(CSSM_ ## base ## _BASE_ERROR); } \ | |
29654253 | 168 | catch (const std::bad_alloc &) { return CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ |
bac41a7b A |
169 | catch (...) { return CssmError::merge(CSSM_ERRCODE_INTERNAL_ERROR, CSSM_ ## base ## _BASE_ERROR); } \ |
170 | return CSSM_OK; | |
171 | #define END_API0 } catch (...) { return; } | |
172 | #define END_API1(bad) } catch (...) { return bad; } | |
173 | ||
174 | ||
175 | // | |
176 | // Helpers for memory pointer validation | |
177 | // | |
178 | template <class T> | |
179 | inline T &Required(T *ptr, CSSM_RETURN err = CSSM_ERRCODE_INVALID_POINTER) | |
180 | { | |
181 | if (ptr == NULL) | |
182 | CssmError::throwMe(err); | |
183 | return *ptr; | |
184 | } | |
185 | ||
186 | ||
187 | // | |
188 | // Tools to build POD wrapper classes | |
189 | // | |
190 | template <class Wrapper, class POD> | |
191 | class PodWrapper : public POD { | |
192 | public: | |
193 | // pure typecasts | |
194 | static Wrapper * &overlayVar(POD * &data) | |
195 | { return reinterpret_cast<Wrapper * &>(data); } | |
196 | static const Wrapper * &overlayVar(const POD * &data) | |
197 | { return reinterpret_cast<const Wrapper * &>(data); } | |
198 | ||
199 | static Wrapper *overlay(POD *data) | |
200 | { return static_cast<Wrapper *>(data); } | |
201 | static const Wrapper *overlay(const POD *data) | |
202 | { return static_cast<const Wrapper *>(data); } | |
203 | static Wrapper &overlay(POD &data) | |
204 | { return static_cast<Wrapper &>(data); } | |
205 | static const Wrapper &overlay(const POD &data) | |
206 | { return static_cast<const Wrapper &>(data); } | |
207 | ||
208 | // optional/required forms | |
209 | static Wrapper &required(POD *data) | |
210 | { return overlay(Required(data)); } | |
211 | static const Wrapper &required(const POD *data) | |
212 | { return overlay(Required(data)); } | |
213 | static Wrapper *optional(POD *data) | |
214 | { return overlay(data); } | |
215 | static const Wrapper *optional(const POD *data) | |
216 | { return overlay(data); } | |
29654253 A |
217 | |
218 | // general helpers for all PodWrappers | |
219 | void clearPod() | |
220 | { memset(static_cast<POD *>(this), 0, sizeof(POD)); } | |
bac41a7b A |
221 | }; |
222 | ||
223 | ||
224 | // | |
225 | // Template builder support | |
226 | // | |
227 | template <class T> | |
228 | struct Nonconst { | |
229 | typedef T Type; | |
230 | }; | |
231 | ||
232 | template <class U> | |
233 | struct Nonconst<const U> { | |
234 | typedef U Type; | |
235 | }; | |
236 | ||
237 | ||
238 | // | |
239 | // User-friendly GUIDs | |
240 | // | |
241 | class Guid : public PodWrapper<Guid, CSSM_GUID> { | |
242 | public: | |
243 | Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } | |
244 | Guid(const CSSM_GUID &rGuid) { memcpy(this, &rGuid, sizeof(*this)); } | |
245 | ||
246 | Guid &operator = (const CSSM_GUID &rGuid) | |
247 | { memcpy(this, &rGuid, sizeof(CSSM_GUID)); return *this; } | |
248 | ||
249 | bool operator == (const CSSM_GUID &other) const | |
250 | { return (this == &other) || !memcmp(this, &other, sizeof(CSSM_GUID)); } | |
251 | bool operator != (const CSSM_GUID &other) const | |
252 | { return (this != &other) && memcmp(this, &other, sizeof(CSSM_GUID)); } | |
253 | bool operator < (const CSSM_GUID &other) const | |
254 | { return memcmp(this, &other, sizeof(CSSM_GUID)) < 0; } | |
255 | size_t hash() const { //@@@ revisit this hash | |
256 | return Data1 + Data2 << 3 + Data3 << 11 + Data4[3] + Data4[6] << 22; | |
257 | } | |
258 | ||
259 | static const unsigned stringRepLength = 38; // "{x8-x4-x4-x4-x12}" | |
260 | char *toString(char buffer[stringRepLength+1]) const; // will append \0 | |
261 | Guid(const char *string); | |
262 | }; | |
263 | ||
264 | ||
265 | // | |
266 | // User-friendly CSSM_SUBSERVICE_UIDs | |
267 | // | |
268 | class CssmSubserviceUid : public PodWrapper<CssmSubserviceUid, CSSM_SUBSERVICE_UID> { | |
269 | public: | |
270 | CssmSubserviceUid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } | |
271 | CssmSubserviceUid(const CSSM_SUBSERVICE_UID &rSSuid) { memcpy(this, &rSSuid, sizeof(*this)); } | |
272 | ||
273 | CssmSubserviceUid &operator = (const CSSM_SUBSERVICE_UID &rSSuid) | |
274 | { memcpy(this, &rSSuid, sizeof(CSSM_SUBSERVICE_UID)); return *this; } | |
275 | ||
276 | bool operator == (const CSSM_SUBSERVICE_UID &other) const | |
277 | { return (this == &other) || !memcmp(this, &other, sizeof(CSSM_SUBSERVICE_UID)); } | |
278 | bool operator != (const CSSM_SUBSERVICE_UID &other) const | |
279 | { return (this != &other) && memcmp(this, &other, sizeof(CSSM_SUBSERVICE_UID)); } | |
280 | bool operator < (const CSSM_SUBSERVICE_UID &other) const | |
281 | { return memcmp(this, &other, sizeof(CSSM_SUBSERVICE_UID)) < 0; } | |
282 | ||
283 | CssmSubserviceUid(const CSSM_GUID &guid, const CSSM_VERSION *version = NULL, | |
284 | uint32 subserviceId = 0, | |
285 | CSSM_SERVICE_TYPE subserviceType = CSSM_SERVICE_DL) | |
286 | { | |
287 | Guid=guid;SubserviceId=subserviceId;SubserviceType=subserviceType; | |
288 | if (version) | |
289 | Version=*version; | |
290 | else | |
291 | { Version.Major=0; Version.Minor=0; } | |
292 | } | |
293 | ||
294 | const ::Guid &guid() const { return ::Guid::overlay(Guid); } | |
295 | uint32 subserviceId() const { return SubserviceId; } | |
296 | CSSM_SERVICE_TYPE subserviceType() const { return SubserviceType; } | |
297 | CSSM_VERSION version() const { return Version; } | |
298 | }; | |
299 | ||
300 | ||
301 | // | |
302 | // User-friendlier CSSM_DATA thingies. | |
303 | // CssmData is a PODWrapper and has no memory allocation features. | |
304 | // | |
305 | class CssmData : public PodWrapper<CssmData, CSSM_DATA> { | |
306 | public: | |
307 | CssmData() { Data = 0; Length = 0; } | |
308 | ||
309 | size_t length() const { return Length; } | |
310 | void *data() const { return Data; } | |
311 | void *end() const { return Data + Length; } | |
312 | ||
313 | // | |
314 | // Create a CssmData from any pointer-to-byte-sized-object and length. | |
315 | // | |
316 | CssmData(void *data, size_t length) | |
317 | { Data = reinterpret_cast<UInt8 *>(data); Length = length; } | |
318 | CssmData(char *data, size_t length) | |
319 | { Data = reinterpret_cast<UInt8 *>(data); Length = length; } | |
320 | CssmData(unsigned char *data, size_t length) | |
321 | { Data = reinterpret_cast<UInt8 *>(data); Length = length; } | |
322 | CssmData(signed char *data, size_t length) | |
323 | { Data = reinterpret_cast<UInt8 *>(data); Length = length; } | |
324 | ||
325 | // the void * form accepts too much; explicitly deny all other types | |
326 | private: template <class T> CssmData(T *, size_t); public: | |
327 | ||
328 | // | |
329 | // Do allow generic "wrapping" of any data structure, but make it conspicuous | |
330 | // since it's not necessarily the Right Thing (alignment and byte order wise). | |
331 | // Also note that the T & form removes const-ness, since there is no ConstCssmData. | |
332 | // | |
333 | template <class T> | |
334 | static CssmData wrap(const T &it) | |
335 | { return CssmData(const_cast<void *>(reinterpret_cast<const void *>(&it)), sizeof(it)); } | |
336 | ||
337 | template <class T> | |
338 | static CssmData wrap(T *data, size_t length) | |
339 | { return CssmData(static_cast<void *>(data), length); } | |
340 | ||
341 | // | |
342 | // Automatically convert a CssmData to any pointer-to-byte-sized-type. | |
343 | // | |
344 | operator signed char * () const { return reinterpret_cast<signed char *>(Data); } | |
345 | operator unsigned char * () const { return reinterpret_cast<unsigned char *>(Data); } | |
346 | operator char * () const { return reinterpret_cast<char *>(Data); } | |
347 | operator void * () const { return reinterpret_cast<void *>(Data); } | |
348 | ||
349 | // | |
350 | // If you want to interprete the contents of a CssmData blob as a particular | |
351 | // type, you have to be more explicit to show that you know what you're doing. | |
352 | // See wrap() above. | |
353 | // | |
354 | template <class T> | |
355 | T *interpretedAs() const { return reinterpret_cast<T *>(Data); } | |
356 | ||
357 | template <class T> | |
358 | T *interpretedAs(size_t len, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) const | |
359 | { | |
360 | if (length() != len) CssmError::throwMe(error); | |
361 | return interpretedAs<T>(); | |
362 | } | |
363 | ||
364 | public: | |
365 | void length(size_t newLength) // shorten only | |
366 | { assert(newLength <= Length); Length = newLength; } | |
367 | ||
368 | void *at(off_t offset) const | |
369 | { assert(offset >= 0 && offset <= Length); return Data + offset; } | |
370 | void *at(off_t offset, size_t size) const // length-checking version | |
371 | { assert(offset >= 0 && offset + size <= Length); return Data + offset; } | |
372 | ||
373 | unsigned char operator [] (size_t pos) const | |
374 | { assert(pos < Length); return Data[pos]; } | |
375 | void *use(size_t taken) // logically remove some bytes | |
376 | { assert(taken <= Length); void *r = Data; Length -= taken; Data += taken; return r; } | |
377 | ||
378 | void clear() | |
379 | { Data = NULL; Length = 0; } | |
380 | ||
29654253 | 381 | string toString () const; // convert to string type (no trailing null) |
bac41a7b A |
382 | |
383 | operator bool () const { return Data != NULL; } | |
384 | bool operator ! () const { return Data == NULL; } | |
385 | bool operator < (const CssmData &other) const; | |
386 | bool operator == (const CssmData &other) const | |
387 | { return length() == other.length() && !memcmp(data(), other.data(), length()); } | |
388 | bool operator != (const CssmData &other) const | |
389 | { return !(*this == other); } | |
390 | ||
391 | // Extract fixed-format data from a CssmData. Fixes any alignment trouble for you. | |
392 | template <class T> | |
393 | void extract(T &destination, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) const | |
394 | { | |
395 | if (length() != sizeof(destination) || data() == NULL) | |
396 | CssmError::throwMe(error); | |
397 | memcpy(&destination, data(), sizeof(destination)); | |
398 | } | |
399 | }; | |
400 | ||
401 | ||
402 | inline bool CssmData::operator < (const CssmData &other) const | |
403 | { | |
404 | if (Length != other.Length) // If lengths are not equal the shorter data is smaller. | |
405 | return Length < other.Length; | |
406 | if (Length == 0) // If lengths are both zero ignore the Data. | |
407 | return false; | |
408 | if (Data == NULL || other.Data == NULL) // arbitrary (but consistent) ordering | |
409 | return Data < other.Data; | |
410 | return memcmp(Data, other.Data, Length) < 0; // Do a lexicographic compare on equal sized Data. | |
411 | } | |
412 | ||
413 | ||
414 | // | |
415 | // User-friendler CSSM_CRYPTO_DATA objects | |
416 | // | |
417 | class CryptoCallback { | |
418 | public: | |
419 | CryptoCallback(CSSM_CALLBACK func, void *ctx = NULL) : mFunction(func), mCtx(ctx) { } | |
420 | CSSM_CALLBACK function() const { return mFunction; } | |
421 | void *context() const { return mCtx; } | |
422 | ||
423 | CssmData operator () () const | |
424 | { | |
425 | CssmData output; | |
426 | if (CSSM_RETURN err = mFunction(&output, mCtx)) | |
427 | CssmError::throwMe(err); | |
428 | return output; | |
429 | } | |
430 | ||
431 | private: | |
432 | CSSM_CALLBACK mFunction; | |
433 | void *mCtx; | |
434 | }; | |
435 | ||
436 | class CssmCryptoData : public PodWrapper<CssmCryptoData, CSSM_CRYPTO_DATA> { | |
437 | public: | |
438 | CssmCryptoData() { } | |
439 | ||
440 | CssmCryptoData(const CssmData ¶m, CSSM_CALLBACK callback = NULL, void *ctx = NULL) | |
441 | { Param = const_cast<CssmData &>(param); Callback = callback; CallerCtx = ctx; } | |
442 | ||
443 | CssmCryptoData(const CssmData ¶m, CryptoCallback &cb) | |
444 | { Param = const_cast<CssmData &>(param); Callback = cb.function(); CallerCtx = cb.context(); } | |
445 | ||
446 | CssmCryptoData(CSSM_CALLBACK callback, void *ctx = NULL) | |
447 | { /* ignore Param */ Callback = callback; CallerCtx = ctx; } | |
448 | ||
449 | explicit CssmCryptoData(CryptoCallback &cb) | |
450 | { /* ignore Param */ Callback = cb.function(); CallerCtx = cb.context(); } | |
451 | ||
452 | // member access | |
453 | CssmData ¶m() { return CssmData::overlay(Param); } | |
454 | const CssmData ¶m() const { return CssmData::overlay(Param); } | |
455 | bool hasCallback() const { return Callback != NULL; } | |
456 | CryptoCallback callback() const { return CryptoCallback(Callback, CallerCtx); } | |
457 | ||
458 | // get the value, whichever way is appropriate | |
459 | CssmData operator () () const | |
460 | { return hasCallback() ? callback() () : param(); } | |
461 | }; | |
462 | ||
463 | // a CssmCryptoContext whose callback is a virtual class member | |
464 | class CryptoDataClass : public CssmCryptoData { | |
465 | public: | |
466 | CryptoDataClass() : CssmCryptoData(callbackShim, this) { } | |
467 | virtual ~CryptoDataClass(); | |
468 | ||
469 | protected: | |
470 | virtual CssmData yield() = 0; // must subclass and implement this | |
471 | ||
472 | private: | |
473 | static CSSM_RETURN callbackShim(CSSM_DATA *output, void *ctx) | |
474 | { | |
475 | BEGIN_API | |
476 | *output = reinterpret_cast<CryptoDataClass *>(ctx)->yield(); | |
477 | END_API(CSSM) | |
478 | } | |
479 | }; | |
480 | ||
481 | ||
482 | // | |
483 | // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics. | |
484 | // | |
485 | typedef CssmData CssmOid; | |
486 | ||
487 | ||
488 | // | |
489 | // User-friendlier CSSM_KEY objects | |
490 | // | |
491 | class CssmKey : public PodWrapper<CssmKey, CSSM_KEY> { | |
492 | public: | |
493 | CssmKey() { KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; } | |
494 | CssmKey(CSSM_KEY &key); | |
495 | CssmKey(CSSM_DATA &keyData); | |
496 | CssmKey(uint32 length, uint8 *data); | |
497 | ||
498 | public: | |
499 | class Header : public PodWrapper<Header, CSSM_KEYHEADER> { | |
500 | public: | |
501 | // access to components of the key header | |
502 | CSSM_KEYBLOB_TYPE blobType() const { return BlobType; } | |
503 | void blobType(CSSM_KEYBLOB_TYPE blobType) { BlobType = blobType; } | |
504 | ||
505 | CSSM_KEYBLOB_FORMAT blobFormat() const { return Format; } | |
506 | void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat) { Format = blobFormat; } | |
507 | ||
508 | CSSM_KEYCLASS keyClass() const { return KeyClass; } | |
509 | void keyClass(CSSM_KEYCLASS keyClass) { KeyClass = keyClass; } | |
510 | ||
511 | CSSM_KEY_TYPE algorithm() const { return AlgorithmId; } | |
512 | void algorithm(CSSM_KEY_TYPE algorithm) { AlgorithmId = algorithm; } | |
513 | ||
514 | CSSM_KEY_TYPE wrapAlgorithm() const { return WrapAlgorithmId; } | |
515 | void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm) { WrapAlgorithmId = wrapAlgorithm; } | |
516 | ||
517 | CSSM_ENCRYPT_MODE wrapMode() const { return WrapMode; } | |
518 | void wrapMode(CSSM_ENCRYPT_MODE mode) { WrapMode = mode; } | |
519 | ||
520 | bool isWrapped() const { return WrapAlgorithmId != CSSM_ALGID_NONE; } | |
521 | ||
522 | const Guid &cspGuid() const { return Guid::overlay(CspId); } | |
523 | void cspGuid(const Guid &guid) { Guid::overlay(CspId) = guid; } | |
524 | ||
525 | uint32 attributes() const { return KeyAttr; } | |
526 | bool attribute(uint32 attr) const { return KeyAttr & attr; } | |
527 | void setAttribute(uint32 attr) { KeyAttr |= attr; } | |
528 | void clearAttribute(uint32 attr) { KeyAttr &= ~attr; } | |
529 | ||
530 | uint32 usage() const { return KeyUsage; } | |
531 | bool useFor(uint32 u) const { return KeyUsage & u; } | |
532 | ||
533 | void usage(uint32 u) { KeyUsage |= u; } | |
534 | void clearUsage(uint32 u) { u &= ~u; } | |
535 | ||
536 | }; | |
537 | ||
538 | // access to the key header | |
539 | Header &header() { return Header::overlay(KeyHeader); } | |
540 | const Header &header() const { return Header::overlay(KeyHeader); } | |
541 | ||
542 | CSSM_KEYBLOB_TYPE blobType() const { return header().blobType(); } | |
543 | void blobType(CSSM_KEYBLOB_TYPE blobType) { header().blobType(blobType); } | |
544 | ||
545 | CSSM_KEYBLOB_FORMAT blobFormat() const { return header().blobFormat(); } | |
546 | void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat) { header().blobFormat(blobFormat); } | |
547 | ||
548 | CSSM_KEYCLASS keyClass() const { return header().keyClass(); } | |
549 | void keyClass(CSSM_KEYCLASS keyClass) { header().keyClass(keyClass); } | |
550 | ||
551 | CSSM_KEY_TYPE algorithm() const { return header().algorithm(); } | |
552 | void algorithm(CSSM_KEY_TYPE algorithm) { header().algorithm(algorithm); } | |
553 | ||
554 | CSSM_KEY_TYPE wrapAlgorithm() const { return header().wrapAlgorithm(); } | |
555 | void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm) { header().wrapAlgorithm(wrapAlgorithm); } | |
556 | ||
557 | CSSM_ENCRYPT_MODE wrapMode() const { return header().wrapMode(); } | |
558 | void wrapMode(CSSM_ENCRYPT_MODE mode) { header().wrapMode(mode); } | |
559 | ||
560 | bool isWrapped() const { return header().isWrapped(); } | |
561 | const Guid &cspGuid() const { return header().cspGuid(); } | |
562 | ||
563 | uint32 attributes() const { return header().attributes(); } | |
564 | bool attribute(uint32 a) const { return header().attribute(a); } | |
565 | void setAttribute(uint32 attr) { header().setAttribute(attr); } | |
566 | void clearAttribute(uint32 attr) { header().clearAttribute(attr); } | |
567 | ||
568 | uint32 usage() const { return header().usage(); } | |
569 | bool useFor(uint32 u) const { return header().useFor(u); } | |
570 | ||
571 | void usage(uint32 u) { header().usage(u); } | |
572 | void clearUsage(uint32 u) { header().clearUsage(u); } | |
573 | ||
574 | public: | |
575 | // access to the key data | |
576 | size_t length() const { return KeyData.Length; } | |
577 | void *data() const { return KeyData.Data; } | |
578 | operator void * () const { return data(); } | |
579 | operator CssmData & () { return CssmData::overlay(KeyData); } | |
580 | operator const CssmData & () const { return static_cast<const CssmData &>(KeyData); } | |
581 | operator bool () const { return KeyData.Data != NULL; } | |
582 | void operator = (const CssmData &data) { KeyData = data; } | |
583 | }; | |
584 | ||
585 | ||
586 | // | |
587 | // Wrapped keys are currently identically structured to normal keys. | |
588 | // But perhaps in the future... | |
589 | // | |
590 | typedef CssmKey CssmWrappedKey; | |
591 | ||
592 | ||
593 | // | |
594 | // Other PodWrappers for stuff that is barely useful... | |
595 | // | |
29654253 A |
596 | class CssmKeySize : public PodWrapper<CssmKeySize, CSSM_KEY_SIZE> { |
597 | public: | |
598 | CssmKeySize() { } | |
599 | CssmKeySize(uint32 nom, uint32 eff) { LogicalKeySizeInBits = nom; EffectiveKeySizeInBits = eff; } | |
600 | CssmKeySize(uint32 size) { LogicalKeySizeInBits = EffectiveKeySizeInBits = size; } | |
601 | ||
602 | uint32 logical() const { return LogicalKeySizeInBits; } | |
603 | uint32 effective() const { return EffectiveKeySizeInBits; } | |
604 | operator uint32 () const { return effective(); } | |
605 | }; | |
606 | ||
607 | inline bool operator == (const CSSM_KEY_SIZE &s1, const CSSM_KEY_SIZE &s2) | |
608 | { | |
609 | return s1.LogicalKeySizeInBits == s2.LogicalKeySizeInBits | |
610 | && s1.EffectiveKeySizeInBits == s2.EffectiveKeySizeInBits; | |
611 | } | |
612 | ||
613 | inline bool operator != (const CSSM_KEY_SIZE &s1, const CSSM_KEY_SIZE &s2) | |
614 | { return !(s1 == s2); } | |
615 | ||
616 | ||
bac41a7b A |
617 | class QuerySizeData : public PodWrapper<QuerySizeData, CSSM_QUERY_SIZE_DATA> { |
618 | public: | |
29654253 | 619 | QuerySizeData() { } |
bac41a7b A |
620 | QuerySizeData(uint32 in) { SizeInputBlock = in; SizeOutputBlock = 0; } |
621 | ||
622 | uint32 inputSize() const { return SizeInputBlock; } | |
623 | uint32 inputSize(uint32 size) { return SizeInputBlock = size; } | |
624 | uint32 outputSize() const { return SizeOutputBlock; } | |
625 | }; | |
626 | ||
29654253 A |
627 | inline bool operator == (const CSSM_QUERY_SIZE_DATA &s1, const CSSM_QUERY_SIZE_DATA &s2) |
628 | { | |
629 | return s1.SizeInputBlock == s2.SizeInputBlock | |
630 | && s1.SizeOutputBlock == s2.SizeOutputBlock; | |
631 | } | |
632 | ||
633 | inline bool operator != (const CSSM_QUERY_SIZE_DATA &s1, const CSSM_QUERY_SIZE_DATA &s2) | |
634 | { return !(s1 == s2); } | |
635 | ||
636 | ||
bac41a7b A |
637 | class CSPOperationalStatistics : |
638 | public PodWrapper<CSPOperationalStatistics, CSSM_CSP_OPERATIONAL_STATISTICS> { | |
639 | public: | |
640 | }; | |
641 | ||
642 | ||
643 | // | |
644 | // User-friendli(er) DL queries. | |
645 | // @@@ Preliminary (flesh out as needed) | |
646 | // | |
647 | class DLQuery : public PodWrapper<DLQuery, CSSM_QUERY> { | |
648 | public: | |
649 | DLQuery() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } | |
650 | DLQuery(const CSSM_QUERY &q) { memcpy(this, &q, sizeof(*this)); } | |
651 | ||
652 | DLQuery &operator = (const CSSM_QUERY &q) | |
653 | { memcpy(this, &q, sizeof(*this)); return *this; } | |
654 | }; | |
655 | ||
656 | ||
bac41a7b A |
657 | // Help with container of something->pointer cleanup |
658 | template <class In> | |
659 | static inline void for_each_delete(In first, In last) | |
660 | { | |
661 | while (first != last) | |
662 | delete *(first++); | |
663 | } | |
664 | ||
665 | // Help with map of something->pointer cleanup | |
666 | template <class In> | |
667 | static inline void for_each_map_delete(In first, In last) | |
668 | { | |
669 | while (first != last) | |
670 | delete (first++)->second; | |
671 | } | |
672 | ||
673 | // Quick and dirty template for a (temporary) array of something | |
674 | // Usage example auto_array<uint32> anArray(20); | |
675 | template <class T> | |
676 | class auto_array | |
677 | { | |
678 | public: | |
679 | auto_array() : mArray(NULL) {} | |
680 | auto_array(size_t inSize) : mArray(new T[inSize]) {} | |
681 | ~auto_array() { if (mArray) delete[] mArray; } | |
682 | T &operator[](size_t inIndex) { return mArray[inIndex]; } | |
683 | void allocate(size_t inSize) { if (mArray) delete[] mArray; mArray = new T[inSize]; } | |
684 | T *get() { return mArray; } | |
685 | T *release() { T *anArray = mArray; mArray = NULL; return anArray; } | |
686 | private: | |
687 | T *mArray; | |
688 | }; | |
689 | ||
690 | // Template for a vector-like class that takes a c-array as it's | |
691 | // underlying storage without making a copy. | |
692 | template <class _Tp> | |
693 | class constVector | |
694 | { | |
695 | NOCOPY(constVector<_Tp>) | |
696 | public: | |
697 | typedef _Tp value_type; | |
698 | typedef const value_type* const_pointer; | |
699 | typedef const value_type* const_iterator; | |
700 | typedef const value_type& const_reference; | |
701 | typedef size_t size_type; | |
702 | typedef ptrdiff_t difference_type; | |
703 | ||
29654253 | 704 | typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
bac41a7b A |
705 | public: |
706 | const_iterator begin() const { return _M_start; } | |
707 | const_iterator end() const { return _M_finish; } | |
708 | ||
709 | const_reverse_iterator rbegin() const | |
710 | { return const_reverse_iterator(end()); } | |
711 | const_reverse_iterator rend() const | |
712 | { return const_reverse_iterator(begin()); } | |
713 | ||
714 | size_type size() const | |
715 | { return size_type(end() - begin()); } | |
716 | bool empty() const | |
717 | { return begin() == end(); } | |
718 | ||
719 | const_reference operator[](size_type __n) const { return *(begin() + __n); } | |
720 | ||
721 | // "at" will eventually have range checking, once we have the | |
722 | // infrastructure to be able to throw stl range errors. | |
723 | const_reference at(size_type n) const { return (*this)[n]; } | |
724 | ||
725 | constVector(size_type __n, const _Tp* __value) | |
726 | : _M_start(__value), _M_finish(__value + __n) | |
727 | {} | |
728 | ||
729 | constVector() : _M_start(NULL), _M_finish(NULL) {} | |
730 | ||
731 | void overlay(size_type __n, const _Tp* __value) { | |
732 | _M_start = __value; | |
733 | _M_finish = __value + __n; | |
734 | } | |
735 | ||
736 | const_reference front() const { return *begin(); } | |
737 | const_reference back() const { return *(end() - 1); } | |
738 | private: | |
739 | const _Tp *_M_start; | |
740 | const _Tp *_M_finish; | |
741 | }; | |
742 | ||
29654253 | 743 | |
bac41a7b A |
744 | } // end namespace Security |
745 | ||
29654253 A |
746 | |
747 | // | |
748 | // Strictly as a transition measure, include cfutilities.h here | |
749 | // | |
750 | #include "cfutilities.h" | |
751 | ||
bac41a7b A |
752 | |
753 | #endif //_H_UTILITIES |