]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2005-2012 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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> | |
e3d460c9 | 34 | #include <security_utilities/refcount.h> |
b1ab9ed8 A |
35 | #include <CommonCrypto/CommonDigestSPI.h> // SPI slated to become API |
36 | ||
37 | namespace Security { | |
38 | ||
39 | ||
40 | // | |
41 | // An unconditional base class for all hash objects. | |
42 | // Not much in here; there's no point in declaring one yourself. | |
43 | // | |
44 | class Hashing { | |
45 | public: | |
46 | typedef unsigned char Byte; | |
47 | }; | |
48 | ||
49 | ||
50 | // | |
51 | // Common prefix for all static hashers. | |
52 | // There's no magic here; we're just setting up a regular framework for duck typing. | |
53 | // | |
54 | // If you write template code based on "any static hasher", you can directly tap here | |
55 | // (and learn the actual hash in use through the match on _HashType). But note that | |
e3d460c9 | 56 | // a DynamicHash is not a subclass of Hash. |
b1ab9ed8 A |
57 | // |
58 | template <uint32_t _size, class _HashType> | |
59 | class Hash : public Hashing { | |
60 | _HashType &_self() { return static_cast<_HashType &>(*this); } // "my real type" | |
61 | public: | |
62 | static const size_t digestLength = _size; // how many bytes in my digest? | |
63 | typedef Byte Digest[_size]; // my digest as a Byte array | |
64 | struct SDigest { // my digest as a struct | |
65 | Digest data; | |
66 | ||
67 | SDigest() { } | |
68 | SDigest(const Byte *source) { ::memcpy(data, source, digestLength); } | |
69 | friend bool operator < (const SDigest &x, const SDigest &y) // usable as collection key | |
70 | { return ::memcmp(x.data, y.data, digestLength) < 0; } | |
71 | bool operator == (const SDigest &other) const | |
72 | { return ::memcmp(this->data, other.data, digestLength) == 0; } | |
73 | bool operator != (const SDigest &other) const | |
74 | { return ::memcmp(this->data, other.data, digestLength) != 0; } | |
75 | bool operator == (const Byte *other) const | |
76 | { return ::memcmp(this->data, other, digestLength) == 0; } | |
77 | bool operator != (const Byte *other) const | |
78 | { return ::memcmp(this->data, other, digestLength) != 0; } | |
79 | }; | |
80 | ||
81 | void operator () (const void *data, size_t length) // just an alias for update() | |
82 | { _self().update(data, length); } | |
83 | ||
84 | void finish(SDigest &digest) | |
85 | { _self().finish(digest.data); } | |
86 | ||
87 | bool verify(const Byte *digest) | |
88 | { Digest d; _self().finish(d); return memcmp(d, digest, digestLength) == 0; } | |
89 | }; | |
90 | ||
91 | ||
92 | // | |
93 | // A dynamic switch for digest generators. | |
94 | // This isn't a subclass of Hash (which is static-fast), but it's duck-typed to it. | |
95 | // Note that digestLength is a function here, not a constant. Obviously. | |
96 | // | |
e3d460c9 | 97 | class DynamicHash : public RefCount, public Hashing { |
b1ab9ed8 A |
98 | public: |
99 | virtual ~DynamicHash(); | |
100 | ||
101 | virtual size_t digestLength() const = 0; | |
102 | virtual void update(const void *data, size_t length) = 0; | |
e3d460c9 A |
103 | template<typename _Dataoid> |
104 | void update(const _Dataoid &doid) { this->update(doid.data(), doid.length()); } | |
b1ab9ed8 A |
105 | virtual void finish(Byte *digest) = 0; |
106 | ||
107 | void operator () (const void *data, size_t length) | |
108 | { return this->update(data, length); } | |
109 | ||
110 | bool verify(const Byte *digest) | |
111 | { Byte d[this->digestLength()]; this->finish(d); return memcmp(d, digest, this->digestLength()) == 0; } | |
112 | }; | |
113 | ||
114 | ||
b1ab9ed8 A |
115 | // |
116 | // Make a DynamicHash from a CommonCrypto hash algorithm identifier | |
117 | // | |
118 | class CCHashInstance : public DynamicHash { | |
119 | public: | |
5c19dc3a | 120 | CCHashInstance(CCDigestAlg alg, size_t truncate = 0); |
b1ab9ed8 A |
121 | ~CCHashInstance() |
122 | { CCDigestDestroy(mDigest); } | |
123 | ||
124 | size_t digestLength() const | |
5c19dc3a | 125 | { return mTruncate ? mTruncate : CCDigestOutputSize(mDigest); } |
b1ab9ed8 A |
126 | void update(const void *data, size_t length) |
127 | { CCDigestUpdate(mDigest, data, length); } | |
5c19dc3a | 128 | void finish(unsigned char *digest); |
b1ab9ed8 A |
129 | |
130 | private: | |
131 | CCDigestRef mDigest; | |
5c19dc3a | 132 | size_t mTruncate; |
b1ab9ed8 A |
133 | }; |
134 | ||
135 | ||
136 | // | |
137 | // A shorthand for holding a DynamicHash subclass we got from some | |
138 | // object out there by asking nicely (by default, calling its getHash() method). | |
139 | // | |
140 | template <class _Giver, DynamicHash *(_Giver::*_fetcher)() const = &_Giver::getHash> | |
e3d460c9 | 141 | class MakeHash : public RefPointer<DynamicHash> { |
b1ab9ed8 | 142 | public: |
e3d460c9 | 143 | MakeHash(const _Giver *giver) : RefPointer<DynamicHash>((giver->*_fetcher)()) { } |
b1ab9ed8 A |
144 | |
145 | operator DynamicHash *() const { return this->get(); } | |
146 | }; | |
147 | ||
148 | ||
149 | // | |
150 | // A concrete SHA1 class, used in a very many different places. | |
151 | // Note that its digestLength is a constant (not a function). | |
152 | // | |
153 | class SHA1 : public CC_SHA1_CTX, public Hash<CC_SHA1_DIGEST_LENGTH, SHA1> { | |
154 | public: | |
155 | SHA1() { CC_SHA1_Init(this); } | |
156 | void update(const void *data, size_t length) | |
427c49bc | 157 | { CC_SHA1_Update(this, data, (CC_LONG)length); } |
b1ab9ed8 A |
158 | void finish(Byte *digest) { CC_SHA1_Final(digest, this); } |
159 | using Hash<CC_SHA1_DIGEST_LENGTH, SHA1>::finish; | |
160 | }; | |
161 | ||
162 | ||
163 | } // Security | |
164 | ||
165 | #endif //_H_HASHING |