1/* 2 * Copyright (c) 2005-2010 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// 25// Fast hash support 26// 27#ifndef _H_HASHING 28#define _H_HASHING 29 30#include <CommonCrypto/CommonDigest.h> 31#include <cstring> 32#include <memory> 33#include <sys/types.h> 34#include <CommonCrypto/CommonDigestSPI.h> // SPI slated to become API 35 36namespace Security { 37 38 39// 40// An unconditional base class for all hash objects. 41// Not much in here; there's no point in declaring one yourself. 42// 43class Hashing { 44public: 45 typedef unsigned char Byte; 46}; 47 48 49// 50// Common prefix for all static hashers. 51// There's no magic here; we're just setting up a regular framework for duck typing. 52// 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. 56// 57template <uint32_t _size, class _HashType> 58class Hash : public Hashing { 59 _HashType &_self() { return static_cast<_HashType &>(*this); } // "my real type" 60public: 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 64 Digest data; 65 66 SDigest() { } 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; } 78 }; 79 80 void operator () (const void *data, size_t length) // just an alias for update() 81 { _self().update(data, length); } 82 83 void finish(SDigest &digest) 84 { _self().finish(digest.data); } 85 86 bool verify(const Byte *digest) 87 { Digest d; _self().finish(d); return memcmp(d, digest, digestLength) == 0; } 88}; 89 90 91// 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. 95// 96class DynamicHash : public Hashing { 97public: 98 virtual ~DynamicHash(); 99 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; 103 104 void operator () (const void *data, size_t length) 105 { return this->update(data, length); } 106 107 bool verify(const Byte *digest) 108 { Byte d[this->digestLength()]; this->finish(d); return memcmp(d, digest, this->digestLength()) == 0; } 109}; 110 111 112// 113// Make a DynamicHash from a static Hash class. 114// 115template <class _HashType> 116class DynamicHashInstance : public DynamicHash, public _HashType { 117public: 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) { } 126 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); } 133}; 134 135 136// 137// Make a DynamicHash from a CommonCrypto hash algorithm identifier 138// 139class CCHashInstance : public DynamicHash { 140public: 141 CCHashInstance(CCDigestAlg alg); 142 ~CCHashInstance() 143 { CCDigestDestroy(mDigest); } 144 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); } 151 152private: 153 CCDigestRef mDigest; 154}; 155 156 157// 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). 160// 161template <class _Giver, DynamicHash *(_Giver::*_fetcher)() const = &_Giver::getHash> 162class MakeHash : public std::auto_ptr<DynamicHash> { 163public: 164 MakeHash(const _Giver *giver) : std::auto_ptr<DynamicHash>((giver->*_fetcher)()) { } 165 166 operator DynamicHash *() const { return this->get(); } 167}; 168 169 170// 171// A concrete SHA1 class, used in a very many different places. 172// Note that its digestLength is a constant (not a function). 173// 174class SHA1 : public CC_SHA1_CTX, public Hash<CC_SHA1_DIGEST_LENGTH, SHA1> { 175public: 176 SHA1() { CC_SHA1_Init(this); } 177 void update(const void *data, size_t length) 178 { CC_SHA1_Update(this, data, (CC_LONG)length); } 179 void finish(Byte *digest) { CC_SHA1_Final(digest, this); } 180 using Hash<CC_SHA1_DIGEST_LENGTH, SHA1>::finish; 181}; 182 183 184} // Security 185 186#endif //_H_HASHING 187