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