]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_utilities/lib/hashing.h
Security-59306.140.5.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / hashing.h
CommitLineData
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
37namespace 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//
44class Hashing {
45public:
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//
58template <uint32_t _size, class _HashType>
59class Hash : public Hashing {
60 _HashType &_self() { return static_cast<_HashType &>(*this); } // "my real type"
61public:
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 97class DynamicHash : public RefCount, public Hashing {
b1ab9ed8
A
98public:
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//
118class CCHashInstance : public DynamicHash {
119public:
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
130private:
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//
140template <class _Giver, DynamicHash *(_Giver::*_fetcher)() const = &_Giver::getHash>
e3d460c9 141class MakeHash : public RefPointer<DynamicHash> {
b1ab9ed8 142public:
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//
153class SHA1 : public CC_SHA1_CTX, public Hash<CC_SHA1_DIGEST_LENGTH, SHA1> {
154public:
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