]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/utilities.h
Security-54.1.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
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
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;
113 virtual const char *what () const throw ();
114
115 static CSSM_RETURN merge(CSSM_RETURN error, CSSM_RETURN base);
116
117 static void check(CSSM_RETURN error) { if (error != CSSM_OK) throwMe(error); }
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;
129 virtual const char *what () const throw ();
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);
136
137 private:
138 IFDEBUG(void debugDiagnose(const void *id) const);
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;
148 virtual const char *what () const throw ();
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); } \
168 catch (const std::bad_alloc &) { return CssmError::merge(CSSM_ERRCODE_MEMORY_ERROR, CSSM_ ## base ## _BASE_ERROR); } \
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); }
217
218 // general helpers for all PodWrappers
219 void clearPod()
220 { memset(static_cast<POD *>(this), 0, sizeof(POD)); }
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
381 string toString () const; // convert to string type (no trailing null)
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 &param, CSSM_CALLBACK callback = NULL, void *ctx = NULL)
441 { Param = const_cast<CssmData &>(param); Callback = callback; CallerCtx = ctx; }
442
443 CssmCryptoData(const CssmData &param, 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 &param() { return CssmData::overlay(Param); }
454 const CssmData &param() 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 //
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
617 class QuerySizeData : public PodWrapper<QuerySizeData, CSSM_QUERY_SIZE_DATA> {
618 public:
619 QuerySizeData() { }
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
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
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
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
704 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
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
743
744 } // end namespace Security
745
746
747 //
748 // Strictly as a transition measure, include cfutilities.h here
749 //
750 #include "cfutilities.h"
751
752
753 #endif //_H_UTILITIES