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. 
  25 #include <Security/cssm.h> 
  26 #include <Security/utility_config.h> 
  41 // Elementary debugging support. 
  42 // #include <debugging.h> for more debugging facilities. 
  46 # define safe_cast      static_cast 
  47 # define safer_cast     static_cast 
  49 # define IFDEBUG(it)    /* do nothing */ 
  50 # define IFNDEBUG(it)   it 
  54 template <class Derived
, class Base
> 
  55 inline Derived 
safer_cast(Base 
&base
) 
  57     return dynamic_cast<Derived
>(base
); 
  60 template <class Derived
, class Base
> 
  61 inline Derived 
safe_cast(Base 
*base
) 
  64         return NULL
;    // okay to cast NULL to NULL 
  65     Derived p 
= dynamic_cast<Derived
>(base
); 
  70 # define IFDEBUG(it)    it 
  71 # define IFNDEBUG(it)   /* do nothing */ 
  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. 
  82 #define NOCOPY(Type)    private: Type(const Type &); void operator = (const Type &); 
  86 // Exception hierarchy 
  88 class CssmCommonError 
: public std::exception 
{ 
  91     CssmCommonError(const CssmCommonError 
&source
); 
  93     virtual ~CssmCommonError() throw (); 
  95     virtual CSSM_RETURN 
cssmError() const = 0; 
  96     virtual CSSM_RETURN 
cssmError(CSSM_RETURN base
) const; 
  97     virtual OSStatus 
osStatus() const; 
 100         virtual void debugDiagnose(const void *id
) const;       // used internally for debug logging 
 103         IFDEBUG(mutable bool mCarrier
); // primary carrier of exception flow 
 106 class CssmError 
: public CssmCommonError 
{ 
 108     CssmError(CSSM_RETURN err
); 
 110     const CSSM_RETURN error
; 
 111     virtual CSSM_RETURN 
cssmError() const; 
 112     virtual OSStatus 
osStatus() const; 
 113     virtual const char *what () const throw (); 
 115     static CSSM_RETURN 
merge(CSSM_RETURN error
, CSSM_RETURN base
); 
 117         static void check(CSSM_RETURN error
)    { if (error 
!= CSSM_OK
) throwMe(error
); } 
 118     static void throwMe(CSSM_RETURN error
) __attribute__((noreturn
)); 
 121 class UnixError 
: public CssmCommonError 
{ 
 127     virtual CSSM_RETURN 
cssmError() const; 
 128     virtual OSStatus 
osStatus() const; 
 129     virtual const char *what () const throw (); 
 131     static void check(int result
)               { if (result 
== -1) throwMe(); } 
 132     static void throwMe(int err 
= errno
) __attribute__((noreturn
)); 
 134     // @@@ This is a hack for the Network protocol state machine 
 135     static UnixError 
make(int err 
= errno
); 
 138         IFDEBUG(void debugDiagnose(const void *id
) const); 
 141 class MacOSError 
: public CssmCommonError 
{ 
 146     virtual CSSM_RETURN 
cssmError() const; 
 147     virtual OSStatus 
osStatus() const; 
 148     virtual const char *what () const throw (); 
 150     static void check(OSStatus status
)  { if (status 
!= noErr
) throwMe(status
); } 
 151     static void throwMe(int err
) __attribute__((noreturn
)); 
 156 // API boilerplate macros. These provide a frame for C++ code that is impermeable to exceptions. 
 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 
 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); } \ 
 171 #define END_API0                } catch (...) { return; } 
 172 #define END_API1(bad)   } catch (...) { return bad; } 
 176 // Helpers for memory pointer validation 
 179 inline T 
&Required(T 
*ptr
, CSSM_RETURN err 
= CSSM_ERRCODE_INVALID_POINTER
) 
 182         CssmError::throwMe(err
); 
 188 // Tools to build POD wrapper classes 
 190 template <class Wrapper
, class POD
> 
 191 class PodWrapper 
: public POD 
{ 
 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
); } 
 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
); } 
 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
); } 
 218     // general helpers for all PodWrappers 
 220     { memset(static_cast<POD 
*>(this), 0, sizeof(POD
)); } 
 225 // Template builder support 
 233 struct Nonconst
<const U
> { 
 239 // User-friendly GUIDs 
 241 class Guid 
: public PodWrapper
<Guid
, CSSM_GUID
> { 
 243     Guid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } 
 244     Guid(const CSSM_GUID 
&rGuid
) { memcpy(this, &rGuid
, sizeof(*this)); } 
 246     Guid 
&operator = (const CSSM_GUID 
&rGuid
) 
 247     { memcpy(this, &rGuid
, sizeof(CSSM_GUID
)); return *this; } 
 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; 
 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
); 
 266 // User-friendly CSSM_SUBSERVICE_UIDs 
 268 class CssmSubserviceUid 
: public PodWrapper
<CssmSubserviceUid
, CSSM_SUBSERVICE_UID
> { 
 270     CssmSubserviceUid() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } 
 271     CssmSubserviceUid(const CSSM_SUBSERVICE_UID 
&rSSuid
) { memcpy(this, &rSSuid
, sizeof(*this)); } 
 273     CssmSubserviceUid 
&operator = (const CSSM_SUBSERVICE_UID 
&rSSuid
) 
 274     { memcpy(this, &rSSuid
, sizeof(CSSM_SUBSERVICE_UID
)); return *this; } 
 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; } 
 283     CssmSubserviceUid(const CSSM_GUID 
&guid
, const CSSM_VERSION 
*version 
= NULL
, 
 284                 uint32 subserviceId 
= 0, 
 285         CSSM_SERVICE_TYPE subserviceType 
= CSSM_SERVICE_DL
) 
 287         Guid
=guid
;SubserviceId
=subserviceId
;SubserviceType
=subserviceType
; 
 291         { Version
.Major
=0; Version
.Minor
=0; } 
 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
; } 
 302 // User-friendlier CSSM_DATA thingies. 
 303 // CssmData is a PODWrapper and has no memory allocation features. 
 305 class CssmData 
: public PodWrapper
<CssmData
, CSSM_DATA
> { 
 307     CssmData() { Data 
= 0; Length 
= 0; } 
 309     size_t length() const { return Length
; } 
 310     void *data() const { return Data
; } 
 311     void *end() const { return Data 
+ Length
; } 
 314         // Create a CssmData from any pointer-to-byte-sized-object and length. 
 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
; } 
 325         // the void * form accepts too much; explicitly deny all other types 
 326         private: template <class T
> CssmData(T 
*, size_t); public: 
 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. 
 334         static CssmData 
wrap(const T 
&it
) 
 335         { return CssmData(const_cast<void *>(reinterpret_cast<const void *>(&it
)), sizeof(it
)); } 
 338         static CssmData 
wrap(T 
*data
, size_t length
) 
 339         { return CssmData(static_cast<void *>(data
), length
); } 
 342         // Automatically convert a CssmData to any pointer-to-byte-sized-type. 
 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
); } 
 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. 
 355         T 
*interpretedAs() const                { return reinterpret_cast<T 
*>(Data
); } 
 358         T 
*interpretedAs(size_t len
, CSSM_RETURN error 
= CSSM_ERRCODE_INVALID_DATA
) const 
 360                 if (length() != len
) CssmError::throwMe(error
); 
 361                 return interpretedAs
<T
>(); 
 365     void length(size_t newLength
)       // shorten only 
 366     { assert(newLength 
<= Length
); Length 
= newLength
; } 
 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
; } 
 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
; } 
 379         { Data 
= NULL
; Length 
= 0; } 
 381     string 
toString () const;   // convert to string type (no trailing null) 
 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
); } 
 391     // Extract fixed-format data from a CssmData. Fixes any alignment trouble for you. 
 393     void extract(T 
&destination
, CSSM_RETURN error 
= CSSM_ERRCODE_INVALID_DATA
) const 
 395         if (length() != sizeof(destination
) || data() == NULL
) 
 396             CssmError::throwMe(error
); 
 397         memcpy(&destination
, data(), sizeof(destination
)); 
 402 inline bool CssmData::operator < (const CssmData 
&other
) const 
 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. 
 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. 
 415 // User-friendler CSSM_CRYPTO_DATA objects 
 417 class CryptoCallback 
{ 
 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
; } 
 423         CssmData 
operator () () const 
 426                 if (CSSM_RETURN err 
= mFunction(&output
, mCtx
)) 
 427                         CssmError::throwMe(err
); 
 432         CSSM_CALLBACK mFunction
; 
 436 class CssmCryptoData 
: public PodWrapper
<CssmCryptoData
, CSSM_CRYPTO_DATA
> { 
 440         CssmCryptoData(const CssmData 
¶m
, CSSM_CALLBACK callback 
= NULL
, void *ctx 
= NULL
) 
 441         { Param 
= const_cast<CssmData 
&>(param
); Callback 
= callback
; CallerCtx 
= ctx
; } 
 443         CssmCryptoData(const CssmData 
¶m
, CryptoCallback 
&cb
) 
 444         { Param 
= const_cast<CssmData 
&>(param
); Callback 
= cb
.function(); CallerCtx 
= cb
.context(); } 
 446         CssmCryptoData(CSSM_CALLBACK callback
, void *ctx 
= NULL
) 
 447         { /* ignore Param */ Callback 
= callback
; CallerCtx 
= ctx
; } 
 449         explicit CssmCryptoData(CryptoCallback 
&cb
) 
 450         { /* ignore Param */ Callback 
= cb
.function(); CallerCtx 
= cb
.context(); } 
 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
); } 
 458         // get the value, whichever way is appropriate 
 459         CssmData 
operator () () const 
 460         { return hasCallback() ? callback() () : param(); } 
 463 // a CssmCryptoContext whose callback is a virtual class member 
 464 class CryptoDataClass 
: public CssmCryptoData 
{ 
 466         CryptoDataClass() : CssmCryptoData(callbackShim
, this) { } 
 467         virtual ~CryptoDataClass(); 
 470         virtual CssmData 
yield() = 0;   // must subclass and implement this 
 473         static CSSM_RETURN 
callbackShim(CSSM_DATA 
*output
, void *ctx
) 
 476                 *output 
= reinterpret_cast<CryptoDataClass 
*>(ctx
)->yield(); 
 483 // CSSM_OIDs are CSSM_DATAs but will probably have different wrapping characteristics. 
 485 typedef CssmData CssmOid
; 
 489 // User-friendlier CSSM_KEY objects 
 491 class CssmKey 
: public PodWrapper
<CssmKey
, CSSM_KEY
> { 
 493     CssmKey() { KeyHeader
.HeaderVersion 
= CSSM_KEYHEADER_VERSION
; } 
 494     CssmKey(CSSM_KEY 
&key
); 
 495     CssmKey(CSSM_DATA 
&keyData
); 
 496     CssmKey(uint32 length
, uint8 
*data
); 
 499     class Header 
: public PodWrapper
<Header
, CSSM_KEYHEADER
> { 
 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
; } 
 505                 CSSM_KEYBLOB_FORMAT 
blobFormat() const { return Format
; } 
 506                 void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat
) { Format 
= blobFormat
; } 
 508                 CSSM_KEYCLASS 
keyClass() const { return KeyClass
; } 
 509                 void keyClass(CSSM_KEYCLASS keyClass
) { KeyClass 
= keyClass
; } 
 511                 CSSM_KEY_TYPE 
algorithm() const { return AlgorithmId
; } 
 512                 void algorithm(CSSM_KEY_TYPE algorithm
) { AlgorithmId 
= algorithm
; } 
 514                 CSSM_KEY_TYPE 
wrapAlgorithm() const { return WrapAlgorithmId
; } 
 515                 void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm
) { WrapAlgorithmId 
= wrapAlgorithm
; } 
 517         CSSM_ENCRYPT_MODE 
wrapMode() const { return WrapMode
; } 
 518         void wrapMode(CSSM_ENCRYPT_MODE mode
) { WrapMode 
= mode
; } 
 520                 bool isWrapped() const { return WrapAlgorithmId 
!= CSSM_ALGID_NONE
; } 
 522                 const Guid 
&cspGuid() const { return Guid::overlay(CspId
); } 
 523                 void cspGuid(const Guid 
&guid
) { Guid::overlay(CspId
) = guid
; } 
 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
; } 
 530                 uint32 
usage() const { return KeyUsage
; } 
 531                 bool useFor(uint32 u
) const { return KeyUsage 
& u
; } 
 533                 void usage(uint32 u
) { KeyUsage 
|= u
; } 
 534                 void clearUsage(uint32 u
) { u 
&= ~u
; } 
 538    // access to the key header 
 539    Header 
&header() { return Header::overlay(KeyHeader
); } 
 540         const Header 
&header() const { return Header::overlay(KeyHeader
); } 
 542         CSSM_KEYBLOB_TYPE 
blobType() const      { return header().blobType(); } 
 543         void blobType(CSSM_KEYBLOB_TYPE blobType
) { header().blobType(blobType
); } 
 545         CSSM_KEYBLOB_FORMAT 
blobFormat() const { return header().blobFormat(); } 
 546         void blobFormat(CSSM_KEYBLOB_FORMAT blobFormat
) { header().blobFormat(blobFormat
); } 
 548         CSSM_KEYCLASS 
keyClass() const          { return header().keyClass(); } 
 549         void keyClass(CSSM_KEYCLASS keyClass
) { header().keyClass(keyClass
); } 
 551         CSSM_KEY_TYPE 
algorithm() const         { return header().algorithm(); } 
 552         void algorithm(CSSM_KEY_TYPE algorithm
) { header().algorithm(algorithm
); } 
 554         CSSM_KEY_TYPE 
wrapAlgorithm() const     { return header().wrapAlgorithm(); } 
 555         void wrapAlgorithm(CSSM_KEY_TYPE wrapAlgorithm
) { header().wrapAlgorithm(wrapAlgorithm
); } 
 557     CSSM_ENCRYPT_MODE 
wrapMode() const  { return header().wrapMode(); } 
 558     void wrapMode(CSSM_ENCRYPT_MODE mode
) { header().wrapMode(mode
); } 
 560         bool isWrapped() const                          { return header().isWrapped(); } 
 561         const Guid 
&cspGuid() const                     { return header().cspGuid(); } 
 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
); } 
 568         uint32 
usage() const                            { return header().usage(); } 
 569         bool useFor(uint32 u
) const                     { return header().useFor(u
); } 
 571         void usage(uint32 u
) { header().usage(u
); } 
 572         void clearUsage(uint32 u
) { header().clearUsage(u
); } 
 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
; } 
 587 // Wrapped keys are currently identically structured to normal keys. 
 588 // But perhaps in the future... 
 590 typedef CssmKey CssmWrappedKey
; 
 594 // Other PodWrappers for stuff that is barely useful... 
 596 class CssmKeySize 
: public PodWrapper
<CssmKeySize
, CSSM_KEY_SIZE
> { 
 599     CssmKeySize(uint32 nom
, uint32 eff
) { LogicalKeySizeInBits 
= nom
; EffectiveKeySizeInBits 
= eff
; } 
 600     CssmKeySize(uint32 size
) { LogicalKeySizeInBits 
= EffectiveKeySizeInBits 
= size
; } 
 602     uint32 
logical() const              { return LogicalKeySizeInBits
; } 
 603     uint32 
effective() const    { return EffectiveKeySizeInBits
; } 
 604     operator uint32 () const    { return effective(); } 
 607 inline bool operator == (const CSSM_KEY_SIZE 
&s1
, const CSSM_KEY_SIZE 
&s2
) 
 609     return s1
.LogicalKeySizeInBits 
== s2
.LogicalKeySizeInBits
 
 610         && s1
.EffectiveKeySizeInBits 
== s2
.EffectiveKeySizeInBits
; 
 613 inline bool operator != (const CSSM_KEY_SIZE 
&s1
, const CSSM_KEY_SIZE 
&s2
) 
 614 { return !(s1 
== s2
); } 
 617 class QuerySizeData 
: public PodWrapper
<QuerySizeData
, CSSM_QUERY_SIZE_DATA
> { 
 620         QuerySizeData(uint32 in
) { SizeInputBlock 
= in
; SizeOutputBlock 
= 0; } 
 622         uint32 
inputSize() const { return SizeInputBlock
; } 
 623         uint32 
inputSize(uint32 size
) { return SizeInputBlock 
= size
; } 
 624         uint32 
outputSize() const { return SizeOutputBlock
; } 
 627 inline bool operator == (const CSSM_QUERY_SIZE_DATA 
&s1
, const CSSM_QUERY_SIZE_DATA 
&s2
) 
 629     return s1
.SizeInputBlock 
== s2
.SizeInputBlock
 
 630         && s1
.SizeOutputBlock 
== s2
.SizeOutputBlock
; 
 633 inline bool operator != (const CSSM_QUERY_SIZE_DATA 
&s1
, const CSSM_QUERY_SIZE_DATA 
&s2
) 
 634 { return !(s1 
== s2
); } 
 637 class CSPOperationalStatistics 
:  
 638         public PodWrapper
<CSPOperationalStatistics
, CSSM_CSP_OPERATIONAL_STATISTICS
> { 
 644 // User-friendli(er) DL queries. 
 645 // @@@ Preliminary (flesh out as needed) 
 647 class DLQuery 
: public PodWrapper
<DLQuery
, CSSM_QUERY
> { 
 649     DLQuery() { /*IFDEBUG(*/ memset(this, 0, sizeof(*this)) /*)*/ ; } 
 650     DLQuery(const CSSM_QUERY 
&q
) { memcpy(this, &q
, sizeof(*this)); } 
 652     DLQuery 
&operator = (const CSSM_QUERY 
&q
) 
 653     { memcpy(this, &q
, sizeof(*this)); return *this; } 
 657 // Help with container of something->pointer cleanup 
 659 static inline void for_each_delete(In first
, In last
) 
 661     while (first 
!= last
) 
 665 // Help with map of something->pointer cleanup 
 667 static inline void for_each_map_delete(In first
, In last
) 
 669     while (first 
!= last
) 
 670         delete (first
++)->second
; 
 673 // Quick and dirty template for a (temporary) array of something 
 674 // Usage example auto_array<uint32> anArray(20); 
 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
; } 
 690 // Template for a vector-like class that takes a c-array as it's 
 691 // underlying storage without making a copy. 
 695     NOCOPY(constVector
<_Tp
>) 
 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
; 
 704     typedef std::reverse_iterator
<const_iterator
> const_reverse_iterator
; 
 706     const_iterator 
begin() const { return _M_start
; } 
 707     const_iterator 
end() const { return _M_finish
; } 
 709     const_reverse_iterator 
rbegin() const 
 710     { return const_reverse_iterator(end()); } 
 711     const_reverse_iterator 
rend() const 
 712     { return const_reverse_iterator(begin()); } 
 714     size_type 
size() const 
 715     { return size_type(end() - begin()); } 
 717     { return begin() == end(); } 
 719     const_reference 
operator[](size_type __n
) const { return *(begin() + __n
); } 
 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
]; } 
 725     constVector(size_type __n
, const _Tp
* __value
) 
 726     : _M_start(__value
), _M_finish(__value 
+ __n
) 
 729         constVector() : _M_start(NULL
), _M_finish(NULL
) {} 
 731         void overlay(size_type __n
, const _Tp
* __value
) { 
 733                 _M_finish 
= __value 
+ __n
; 
 736     const_reference 
front() const { return *begin(); } 
 737     const_reference 
back() const { return *(end() - 1); } 
 740     const _Tp 
*_M_finish
; 
 744 } // end namespace Security 
 748 // Strictly as a transition measure, include cfutilities.h here 
 750 #include "cfutilities.h" 
 753 #endif //_H_UTILITIES