]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/hashing.h
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / hashing.h
1 /*
2 * Copyright (c) 2005-2012 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
36 namespace 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 //
43 class Hashing {
44 public:
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 //
57 template <uint32_t _size, class _HashType>
58 class Hash : public Hashing {
59 _HashType &_self() { return static_cast<_HashType &>(*this); } // "my real type"
60 public:
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 //
96 class DynamicHash : public Hashing {
97 public:
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 //
115 template <class _HashType>
116 class DynamicHashInstance : public DynamicHash, public _HashType {
117 public:
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 //
139 class CCHashInstance : public DynamicHash {
140 public:
141 CCHashInstance(CCDigestAlg alg, size_t truncate = 0);
142 ~CCHashInstance()
143 { CCDigestDestroy(mDigest); }
144
145 size_t digestLength() const
146 { return mTruncate ? mTruncate : CCDigestOutputSize(mDigest); }
147 void update(const void *data, size_t length)
148 { CCDigestUpdate(mDigest, data, length); }
149 void finish(unsigned char *digest);
150
151 private:
152 CCDigestRef mDigest;
153 size_t mTruncate;
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 //
161 template <class _Giver, DynamicHash *(_Giver::*_fetcher)() const = &_Giver::getHash>
162 class MakeHash : public std::auto_ptr<DynamicHash> {
163 public:
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 //
174 class SHA1 : public CC_SHA1_CTX, public Hash<CC_SHA1_DIGEST_LENGTH, SHA1> {
175 public:
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