1 | // |
2 | // HMACEngine.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Crypt |
6 | // Module: HMACEngine |
7 | // |
8 | // Definition of the HMACEngine class. |
9 | // |
10 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_HMACEngine_INCLUDED |
18 | #define Foundation_HMACEngine_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/DigestEngine.h" |
23 | #include <cstring> |
24 | |
25 | |
26 | namespace Poco { |
27 | |
28 | |
29 | template <class Engine> |
30 | class HMACEngine: public DigestEngine |
31 | /// This class implements the HMAC message |
32 | /// authentication code algorithm, as specified |
33 | /// in RFC 2104. The underlying DigestEngine |
34 | /// (MD5Engine, SHA1Engine, etc.) must be given as |
35 | /// template argument. |
36 | /// Since the HMACEngine is a DigestEngine, it can |
37 | /// be used with the DigestStream class to create |
38 | /// a HMAC for a stream. |
39 | { |
40 | public: |
41 | enum |
42 | { |
43 | BLOCK_SIZE = Engine::BLOCK_SIZE, |
44 | DIGEST_SIZE = Engine::DIGEST_SIZE |
45 | }; |
46 | |
47 | HMACEngine(const std::string& passphrase) |
48 | { |
49 | init(passphrase.data(), passphrase.length()); |
50 | } |
51 | |
52 | HMACEngine(const char* passphrase, std::size_t length) |
53 | { |
54 | poco_check_ptr (passphrase); |
55 | |
56 | init(passphrase, length); |
57 | } |
58 | |
59 | ~HMACEngine() |
60 | { |
61 | std::memset(_ipad, 0, BLOCK_SIZE); |
62 | std::memset(_opad, 0, BLOCK_SIZE); |
63 | delete [] _ipad; |
64 | delete [] _opad; |
65 | } |
66 | |
67 | std::size_t digestLength() const |
68 | { |
69 | return DIGEST_SIZE; |
70 | } |
71 | |
72 | void reset() |
73 | { |
74 | _engine.reset(); |
75 | _engine.update(_ipad, BLOCK_SIZE); |
76 | } |
77 | |
78 | const DigestEngine::Digest& digest() |
79 | { |
80 | const DigestEngine::Digest& d = _engine.digest(); |
81 | char db[DIGEST_SIZE]; |
82 | char* pdb = db; |
83 | for (DigestEngine::Digest::const_iterator it = d.begin(); it != d.end(); ++it) |
84 | *pdb++ = *it; |
85 | _engine.reset(); |
86 | _engine.update(_opad, BLOCK_SIZE); |
87 | _engine.update(db, DIGEST_SIZE); |
88 | const DigestEngine::Digest& result = _engine.digest(); |
89 | reset(); |
90 | return result; |
91 | } |
92 | |
93 | protected: |
94 | void init(const char* passphrase, std::size_t length) |
95 | { |
96 | _ipad = new char[BLOCK_SIZE]; |
97 | _opad = new char[BLOCK_SIZE]; |
98 | std::memset(_ipad, 0, BLOCK_SIZE); |
99 | std::memset(_opad, 0, BLOCK_SIZE); |
100 | if (length > BLOCK_SIZE) |
101 | { |
102 | _engine.reset(); |
103 | _engine.update(passphrase, length); |
104 | const DigestEngine::Digest& d = _engine.digest(); |
105 | char* ipad = _ipad; |
106 | char* opad = _opad; |
107 | int n = BLOCK_SIZE; |
108 | for (DigestEngine::Digest::const_iterator it = d.begin(); it != d.end() && n-- > 0; ++it) |
109 | { |
110 | *ipad++ = *it; |
111 | *opad++ = *it; |
112 | } |
113 | } |
114 | else |
115 | { |
116 | std::memcpy(_ipad, passphrase, length); |
117 | std::memcpy(_opad, passphrase, length); |
118 | } |
119 | for (int i = 0; i < BLOCK_SIZE; ++i) |
120 | { |
121 | _ipad[i] ^= 0x36; |
122 | _opad[i] ^= 0x5c; |
123 | } |
124 | reset(); |
125 | } |
126 | |
127 | void updateImpl(const void* data, std::size_t length) |
128 | { |
129 | _engine.update(data, length); |
130 | } |
131 | |
132 | private: |
133 | HMACEngine(); |
134 | HMACEngine(const HMACEngine&); |
135 | HMACEngine& operator = (const HMACEngine&); |
136 | |
137 | Engine _engine; |
138 | char* _ipad; |
139 | char* _opad; |
140 | }; |
141 | |
142 | |
143 | } // namespace Poco |
144 | |
145 | |
146 | #endif // Foundation_HMACEngine_INCLUDED |
147 | |