]>
git.saurik.com Git - apple/security.git/blob - libsecurity_utilities/lib/hashing.h
da3780a23d65da814234f1c57e1ee68b9e9b9aad
   2  * Copyright (c) 2005-2010 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  30 #include <CommonCrypto/CommonDigest.h> 
  33 #include <sys/types.h> 
  34 #include <CommonCrypto/CommonDigestSPI.h>       // SPI slated to become API 
  40 // An unconditional base class for all hash objects. 
  41 // Not much in here; there's no point in declaring one yourself. 
  45         typedef unsigned char Byte
; 
  50 // Common prefix for all static hashers. 
  51 // There's no magic here; we're just setting up a regular framework for duck typing. 
  53 // If you write template code based on "any static hasher", you can directly tap here 
  54 // (and learn the actual hash in use through the match on _HashType). But note that 
  55 // a DynamicHash is not a subclass of Hash, though a DynamicHashInstance will be, duck-like. 
  57 template <uint32_t _size
, class _HashType
> 
  58 class Hash 
: public Hashing 
{ 
  59         _HashType 
&_self() { return static_cast<_HashType 
&>(*this); }  // "my real type" 
  61         static const size_t digestLength 
= _size
;                       // how many bytes in my digest? 
  62         typedef Byte Digest
[_size
];                                                     // my digest as a Byte array 
  63         struct SDigest 
{                                                                        // my digest as a struct 
  67                 SDigest(const Byte 
*source
) { ::memcpy(data
, source
, digestLength
); } 
  68                 friend bool operator < (const SDigest 
&x
, const SDigest 
&y
)     // usable as collection key 
  69                         { return ::memcmp(x
.data
, y
.data
, digestLength
) < 0; } 
  70                 bool operator == (const SDigest 
&other
) const 
  71                         { return ::memcmp(this->data
, other
.data
, digestLength
) == 0; } 
  72                 bool operator != (const SDigest 
&other
) const 
  73                         { return ::memcmp(this->data
, other
.data
, digestLength
) != 0; } 
  74                 bool operator == (const Byte 
*other
) const 
  75                         { return ::memcmp(this->data
, other
, digestLength
) == 0; } 
  76                 bool operator != (const Byte 
*other
) const 
  77                         { return ::memcmp(this->data
, other
, digestLength
) != 0; } 
  80         void operator () (const void *data
, size_t length
)      // just an alias for update() 
  81                 { _self().update(data
, length
); } 
  83         void finish(SDigest 
&digest
) 
  84                 { _self().finish(digest
.data
); } 
  86         bool verify(const Byte 
*digest
) 
  87                 { Digest d
; _self().finish(d
); return memcmp(d
, digest
, digestLength
) == 0; } 
  92 // A dynamic switch for digest generators. 
  93 // This isn't a subclass of Hash (which is static-fast), but it's duck-typed to it. 
  94 // Note that digestLength is a function here, not a constant. Obviously. 
  96 class DynamicHash 
: public Hashing 
{ 
  98         virtual ~DynamicHash(); 
 100         virtual size_t digestLength() const = 0; 
 101         virtual void update(const void *data
, size_t length
) = 0; 
 102         virtual void finish(Byte 
*digest
) = 0; 
 104         void operator () (const void *data
, size_t length
) 
 105                 { return this->update(data
, length
); } 
 107         bool verify(const Byte 
*digest
) 
 108                 { Byte d
[this->digestLength()]; this->finish(d
); return memcmp(d
, digest
, this->digestLength()) == 0; } 
 113 // Make a DynamicHash from a static Hash class. 
 115 template <class _HashType
> 
 116 class DynamicHashInstance 
: public DynamicHash
, public _HashType 
{ 
 118         // (wish we had C++0x already...) 
 119         DynamicHashInstance() { } 
 120         template <class Arg1
> 
 121         DynamicHashInstance(const Arg1 
&arg1
) : _HashType(arg1
) { } 
 122         template <class Arg1
, class Arg2
> 
 123         DynamicHashInstance(const Arg1 
&arg1
, const Arg2 
&arg2
) : _HashType(arg1
, arg2
) { } 
 124         template <class Arg1
, class Arg2
, class Arg3
> 
 125         DynamicHashInstance(const Arg1 
&arg1
, const Arg2 
&arg2
, const Arg3 
&arg3
) : _HashType(arg1
, arg2
, arg3
) { } 
 127         size_t digestLength() const 
 128                 { return _HashType::digestLength
; } 
 129         void update(const void *data
, size_t length
) 
 130                 { return _HashType::update(data
, length
); } 
 131         void finish(unsigned char *digest
) 
 132                 { return _HashType::finish(digest
); } 
 137 // Make a DynamicHash from a CommonCrypto hash algorithm identifier 
 139 class CCHashInstance 
: public DynamicHash 
{ 
 141         CCHashInstance(CCDigestAlg alg
); 
 143                 { CCDigestDestroy(mDigest
); } 
 145         size_t digestLength() const 
 146                 { return CCDigestOutputSize(mDigest
); } 
 147         void update(const void *data
, size_t length
) 
 148                 { CCDigestUpdate(mDigest
, data
, length
); } 
 149         void finish(unsigned char *digest
) 
 150                 { CCDigestFinal(mDigest
, digest
); } 
 158 // A shorthand for holding a DynamicHash subclass we got from some 
 159 // object out there by asking nicely (by default, calling its getHash() method). 
 161 template <class _Giver
, DynamicHash 
*(_Giver::*_fetcher
)() const = &_Giver::getHash
> 
 162 class MakeHash 
: public std::auto_ptr
<DynamicHash
> { 
 164         MakeHash(const _Giver 
*giver
) : std::auto_ptr
<DynamicHash
>((giver
->*_fetcher
)()) { } 
 166         operator DynamicHash 
*() const { return this->get(); } 
 171 // A concrete SHA1 class, used in a very many different places. 
 172 // Note that its digestLength is a constant (not a function). 
 174 class SHA1 
: public CC_SHA1_CTX
, public Hash
<CC_SHA1_DIGEST_LENGTH
, SHA1
>       { 
 176         SHA1() { CC_SHA1_Init(this); } 
 177         void update(const void *data
, size_t length
) 
 178                 { CC_SHA1_Update(this, data
, length
); } 
 179         void finish(Byte 
*digest
) { CC_SHA1_Final(digest
, this); } 
 180         using Hash
<CC_SHA1_DIGEST_LENGTH
, SHA1
>::finish
;