summaryrefslogtreecommitdiff
path: root/includes/BHashes.h
blob: 3d7be493a53e69ce363aea86b50d3ade8f0a7d7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#pragma once

#include <Exceptions.h>
#include <tomcrypt.h>

#undef max

namespace Balau {

template<const struct ltc_hash_descriptor * desc>
class Hash {
  public:
      Hash() { reset(); }
    void reset() {
        int r = desc->init(&m_state);
        IAssert(r == CRYPT_OK, "init for %s returned %i", desc->name, r);
    }
    void update(const uint8_t * data, size_t len) {
        while (len) {
            unsigned long blockLen = std::numeric_limits<unsigned long>::max();
            if (blockLen > len)
                blockLen = (unsigned long) len;
            int r = desc->process(&m_state, data, blockLen);
            data += blockLen;
            len -= blockLen;
            IAssert(r == CRYPT_OK, "process for %s returned %i", desc->name, r);
        }
    }
    unsigned final(void * digest, unsigned outlen) {
        AAssert(outlen >= digestSize(), "digest size too small being passed on for %s: %u instead of %u", name(), outlen, digestSize());
        int r = desc->done(&m_state, (uint8_t *) digest);
        IAssert(r == CRYPT_OK, "done for %s returned %i", desc->name, r);
        return digestSize();
    }

    void update(const String & data) { update((uint8_t *) data.to_charp(), data.strlen()); }
    template<size_t L>
    void update(const char (&str)[L]) { update((uint8_t *) str, L - 1); }
    template<size_t L>
    unsigned final(uint8_t (&digest)[L]) { return final(digest, L); }

    static const unsigned digestSize() { return desc->hashsize; }
    static const unsigned blockSize() { return desc->blocksize; }
    static const char * name() { return desc->name; }
    static char hashID() { return desc->ID; }

  private:
    hash_state m_state;
};

template<class Hash>
class HMAC {
  public:
    void prepare(const uint8_t * key, const size_t len) {
        int r = hmac_init(&m_state, find_hash_id(Hash::hashID()), key, len);
        IAssert(r == CRYPT_OK, "hmac_init for %s returned %i", Hash::name(), r);
    }
    void update(const uint8_t * data, const size_t len) {
        int r = hmac_process(&m_state, data, len);
        IAssert(r == CRYPT_OK, "hmac_process for %s returned %i", Hash::name(), r);
    }
    unsigned long final(void * digest, unsigned long outlen) {
        int r = hmac_done(&m_state, (uint8_t *) digest, &outlen);
        IAssert(r == CRYPT_OK, "hmac_done for %s returned %i", Hash::name(), r);
        return outlen;
    }

    void prepare(const String & data) { prepare((uint8_t *)data.to_charp(), data.strlen()); }
    template<size_t L>
    void prepare(const char (&str)[L]) { prepare((uint8_t *) str, L - 1); }
    void update(const String & data) { update((uint8_t *) data.to_charp(), data.strlen()); }
    template<size_t L>
    void update(const char (&str)[L]) { update((uint8_t *) str, L - 1); }
    template<size_t L>
    unsigned final(uint8_t(&digest)[L]) { return final(digest, L); }

    static const unsigned digestSize() { return Hash::digestSize(); }
    static const unsigned blockSize() { return Hash::blockSize(); }

  private:
    hmac_state m_state;
};

typedef Hash<&chc_desc>       CHC;
typedef Hash<&whirlpool_desc> Whirlpool;
typedef Hash<&sha512_desc>    SHA512;
typedef Hash<&sha384_desc>    SHA384;
typedef Hash<&sha256_desc>    SHA256;
typedef Hash<&sha224_desc>    SHA224;
typedef Hash<&sha1_desc>      SHA1;
typedef Hash<&md5_desc>       MD5;
typedef Hash<&md4_desc>       MD4;
typedef Hash<&md2_desc>       MD2;
typedef Hash<&tiger_desc>     Tiger;
typedef Hash<&rmd128_desc>    RMD128;
typedef Hash<&rmd160_desc>    RMD160;
typedef Hash<&rmd256_desc>    RMD256;
typedef Hash<&rmd320_desc>    RMD320;

};