]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_utilities/lib/hashing.h
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_utilities / lib / hashing.h
diff --git a/libsecurity_utilities/lib/hashing.h b/libsecurity_utilities/lib/hashing.h
new file mode 100644 (file)
index 0000000..da3780a
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2005-2010 Apple Inc. All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+//
+// Fast hash support
+//
+#ifndef _H_HASHING
+#define _H_HASHING
+
+#include <CommonCrypto/CommonDigest.h>
+#include <cstring>
+#include <memory>
+#include <sys/types.h>
+#include <CommonCrypto/CommonDigestSPI.h>      // SPI slated to become API
+
+namespace Security {
+
+
+//
+// An unconditional base class for all hash objects.
+// Not much in here; there's no point in declaring one yourself.
+//
+class Hashing {
+public:
+       typedef unsigned char Byte;
+};
+
+
+//
+// Common prefix for all static hashers.
+// There's no magic here; we're just setting up a regular framework for duck typing.
+//
+// If you write template code based on "any static hasher", you can directly tap here
+// (and learn the actual hash in use through the match on _HashType). But note that
+// a DynamicHash is not a subclass of Hash, though a DynamicHashInstance will be, duck-like.
+//
+template <uint32_t _size, class _HashType>
+class Hash : public Hashing {
+       _HashType &_self() { return static_cast<_HashType &>(*this); }  // "my real type"
+public:
+       static const size_t digestLength = _size;                       // how many bytes in my digest?
+       typedef Byte Digest[_size];                                                     // my digest as a Byte array
+       struct SDigest {                                                                        // my digest as a struct
+               Digest data;
+               
+               SDigest() { }
+               SDigest(const Byte *source) { ::memcpy(data, source, digestLength); }
+               friend bool operator < (const SDigest &x, const SDigest &y)     // usable as collection key
+                       { return ::memcmp(x.data, y.data, digestLength) < 0; }
+               bool operator == (const SDigest &other) const
+                       { return ::memcmp(this->data, other.data, digestLength) == 0; }
+               bool operator != (const SDigest &other) const
+                       { return ::memcmp(this->data, other.data, digestLength) != 0; }
+               bool operator == (const Byte *other) const
+                       { return ::memcmp(this->data, other, digestLength) == 0; }
+               bool operator != (const Byte *other) const
+                       { return ::memcmp(this->data, other, digestLength) != 0; }
+       };
+       
+       void operator () (const void *data, size_t length)      // just an alias for update()
+               { _self().update(data, length); }
+       
+       void finish(SDigest &digest)
+               { _self().finish(digest.data); }
+       
+       bool verify(const Byte *digest)
+               { Digest d; _self().finish(d); return memcmp(d, digest, digestLength) == 0; }
+};
+
+
+//
+// A dynamic switch for digest generators.
+// This isn't a subclass of Hash (which is static-fast), but it's duck-typed to it.
+// Note that digestLength is a function here, not a constant. Obviously.
+//
+class DynamicHash : public Hashing {
+public:
+       virtual ~DynamicHash();
+       
+       virtual size_t digestLength() const = 0;
+       virtual void update(const void *data, size_t length) = 0;
+       virtual void finish(Byte *digest) = 0;
+       
+       void operator () (const void *data, size_t length)
+               { return this->update(data, length); }
+
+       bool verify(const Byte *digest)
+               { Byte d[this->digestLength()]; this->finish(d); return memcmp(d, digest, this->digestLength()) == 0; }
+};
+
+
+//
+// Make a DynamicHash from a static Hash class.
+//
+template <class _HashType>
+class DynamicHashInstance : public DynamicHash, public _HashType {
+public:
+       // (wish we had C++0x already...)
+       DynamicHashInstance() { }
+       template <class Arg1>
+       DynamicHashInstance(const Arg1 &arg1) : _HashType(arg1) { }
+       template <class Arg1, class Arg2>
+       DynamicHashInstance(const Arg1 &arg1, const Arg2 &arg2) : _HashType(arg1, arg2) { }
+       template <class Arg1, class Arg2, class Arg3>
+       DynamicHashInstance(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) : _HashType(arg1, arg2, arg3) { }
+
+       size_t digestLength() const
+               { return _HashType::digestLength; }
+       void update(const void *data, size_t length)
+               { return _HashType::update(data, length); }
+       void finish(unsigned char *digest)
+               { return _HashType::finish(digest); }
+};
+
+
+//
+// Make a DynamicHash from a CommonCrypto hash algorithm identifier
+//
+class CCHashInstance : public DynamicHash {
+public:
+       CCHashInstance(CCDigestAlg alg);
+       ~CCHashInstance()
+               { CCDigestDestroy(mDigest); }
+       
+       size_t digestLength() const
+               { return CCDigestOutputSize(mDigest); }
+       void update(const void *data, size_t length)
+               { CCDigestUpdate(mDigest, data, length); }
+       void finish(unsigned char *digest)
+               { CCDigestFinal(mDigest, digest); }
+       
+private:
+       CCDigestRef mDigest;
+};
+
+
+//
+// A shorthand for holding a DynamicHash subclass we got from some
+// object out there by asking nicely (by default, calling its getHash() method).
+//
+template <class _Giver, DynamicHash *(_Giver::*_fetcher)() const = &_Giver::getHash>
+class MakeHash : public std::auto_ptr<DynamicHash> {
+public:
+       MakeHash(const _Giver *giver) : std::auto_ptr<DynamicHash>((giver->*_fetcher)()) { }
+       
+       operator DynamicHash *() const { return this->get(); }
+};
+
+
+//
+// A concrete SHA1 class, used in a very many different places.
+// Note that its digestLength is a constant (not a function).
+//
+class SHA1 : public CC_SHA1_CTX, public Hash<CC_SHA1_DIGEST_LENGTH, SHA1>      {
+public:
+       SHA1() { CC_SHA1_Init(this); }
+       void update(const void *data, size_t length)
+               { CC_SHA1_Update(this, data, length); }
+       void finish(Byte *digest) { CC_SHA1_Final(digest, this); }
+       using Hash<CC_SHA1_DIGEST_LENGTH, SHA1>::finish;
+};
+
+
+}      // Security
+
+#endif //_H_HASHING