Line data Source code
1 : /**
2 : Copyright (c) 2021-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023-2924 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CORE_STRING_SPCRYPTO_H_
25 : #define STAPPLER_CORE_STRING_SPCRYPTO_H_
26 :
27 : #include "SPIO.h"
28 : #include "SPBytesView.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler {
31 :
32 : struct CoderSource {
33 : CoderSource(const uint8_t *d, size_t len);
34 : CoderSource(const char *d, size_t len);
35 : CoderSource(const char *d);
36 : CoderSource(const StringView &d);
37 :
38 : CoderSource(const typename memory::PoolInterface::BytesType &d);
39 : CoderSource(const typename memory::StandartInterface::BytesType &d);
40 :
41 : CoderSource(const typename memory::PoolInterface::StringType &d);
42 : CoderSource(const typename memory::StandartInterface::StringType &d);
43 :
44 : template <Endian Order>
45 : CoderSource(const BytesViewTemplate<Order> &d);
46 :
47 : CoderSource(const BytesReader<uint8_t> &d);
48 : CoderSource(const BytesReader<char> &d);
49 :
50 : template <size_t Size>
51 : CoderSource(const std::array<uint8_t, Size> &d);
52 :
53 : CoderSource();
54 :
55 : CoderSource(const CoderSource &) = delete;
56 : CoderSource(CoderSource &&) = delete;
57 :
58 : CoderSource& operator=(const CoderSource &) = delete;
59 : CoderSource& operator=(CoderSource &&) = delete;
60 :
61 : BytesViewTemplate<Endian::Network> _data;
62 : size_t _offset = 0;
63 :
64 : const uint8_t *data() const;
65 : size_t size() const;
66 : bool empty() const;
67 :
68 : BytesViewTemplate<Endian::Network> view() const;
69 :
70 : uint8_t operator[] (size_t s) const;
71 :
72 : size_t read(uint8_t *buf, size_t nbytes);
73 : size_t seek(int64_t offset, io::Seek s);
74 : size_t tell() const;
75 : };
76 :
77 : }
78 :
79 :
80 : namespace STAPPLER_VERSIONIZED stappler::crypto {
81 :
82 : constexpr uint8_t HMAC_I_PAD = 0x36;
83 : constexpr uint8_t HMAC_O_PAD = 0x5C;
84 :
85 : #ifndef SP_SECURE_KEY
86 : constexpr auto SP_SECURE_KEY = "Nev3rseenany0nesoequalinth1sscale";
87 : #endif
88 :
89 : /* SHA-1 160-bit context
90 : * designed for chain use: Sha1().update(input).final() */
91 : struct Sha1 {
92 : struct _Ctx {
93 : uint32_t digest[5];
94 : uint32_t count_lo, count_hi;
95 : uint32_t data[16];
96 : int32_t local;
97 : };
98 :
99 : constexpr static uint32_t Length = 20;
100 : using Buf = std::array<uint8_t, Length>;
101 :
102 : static Buf make(const CoderSource &, const StringView &salt = StringView());
103 : static Buf hmac(const CoderSource &data, const CoderSource &key);
104 :
105 : template <typename ... Args>
106 : static Buf perform(Args && ... args);
107 :
108 : Sha1();
109 : Sha1 & init();
110 :
111 : Sha1 & update(const uint8_t *, size_t);
112 : Sha1 & update(const CoderSource &);
113 :
114 : template <typename T, typename ... Args>
115 : void _update(T && t, Args && ... args);
116 :
117 : template <typename T>
118 : void _update(T && t);
119 :
120 : Buf final();
121 : void final(uint8_t *);
122 :
123 : _Ctx ctx;
124 : };
125 :
126 : /* SHA-2 512-bit context
127 : * designed for chain use: Sha512().update(input).final() */
128 : struct Sha512 {
129 : struct _Ctx {
130 : uint64_t length;
131 : uint64_t state[8];
132 : uint32_t curlen;
133 : uint8_t buf[128];
134 : };
135 :
136 : constexpr static uint32_t Length = 64;
137 : using Buf = std::array<uint8_t, Length>;
138 :
139 : static Buf make(const CoderSource &, const StringView &salt = StringView());
140 : static Buf hmac(const CoderSource &data, const CoderSource &key);
141 :
142 : template <typename ... Args>
143 : static Buf perform(Args && ... args);
144 :
145 : Sha512();
146 : Sha512 & init();
147 :
148 : Sha512 & update(const uint8_t *, size_t);
149 : Sha512 & update(const CoderSource &);
150 :
151 : template <typename T, typename ... Args>
152 : void _update(T && t, Args && ... args);
153 :
154 : template <typename T>
155 : void _update(T && t);
156 :
157 : Buf final();
158 : void final(uint8_t *);
159 :
160 : _Ctx ctx;
161 : };
162 :
163 : /* SHA-2 256-bit context
164 : * designed for chain use: Sha256().update(input).final() */
165 : struct Sha256 {
166 : struct _Ctx {
167 : uint64_t length;
168 : uint32_t state[8];
169 : uint32_t curlen;
170 : uint8_t buf[64];
171 : };
172 :
173 : constexpr static uint32_t Length = 32;
174 : using Buf = std::array<uint8_t, Length>;
175 :
176 : static Buf make(const CoderSource &, const StringView &salt = StringView());
177 : static Buf hmac(const CoderSource &data, const CoderSource &key);
178 :
179 : template <typename ... Args>
180 : static Buf perform(Args && ... args);
181 :
182 : Sha256();
183 : Sha256 & init();
184 :
185 : Sha256 & update(const uint8_t *, size_t);
186 : Sha256 & update(const CoderSource &);
187 :
188 : template <typename T, typename ... Args>
189 : void _update(T && t, Args && ... args);
190 :
191 : template <typename T>
192 : void _update(T && t);
193 :
194 : Buf final();
195 : void final(uint8_t *);
196 :
197 : _Ctx ctx;
198 : };
199 :
200 : union alignas(16) uint512_u {
201 : unsigned long long QWORD[8];
202 : unsigned char B[64];
203 : };
204 :
205 : /* GOST R 34.11-2012 hash context */
206 : struct Gost3411_Ctx {
207 : uint512_u buffer;
208 : uint512_u h;
209 : uint512_u N;
210 : uint512_u Sigma;
211 : size_t bufsize;
212 : unsigned int digest_size;
213 : };
214 :
215 : struct Gost3411_512 {
216 : using _Ctx = Gost3411_Ctx;
217 :
218 : constexpr static uint32_t Length = 64;
219 : using Buf = std::array<uint8_t, Length>;
220 :
221 : template <typename ... Args>
222 : static Buf perform(Args && ... args);
223 :
224 : static Buf make(const CoderSource &, const StringView &salt = StringView());
225 : static Buf hmac(const CoderSource &data, const CoderSource &key);
226 :
227 : Gost3411_512();
228 : Gost3411_512 & init();
229 :
230 : Gost3411_512 & update(const uint8_t *, size_t);
231 : Gost3411_512 & update(const CoderSource &);
232 :
233 : template <typename T, typename ... Args>
234 : void _update(T && t, Args && ... args);
235 :
236 : template <typename T>
237 : void _update(T && t);
238 :
239 : Buf final();
240 : void final(uint8_t *);
241 :
242 : _Ctx ctx;
243 : };
244 :
245 : struct Gost3411_256 {
246 : using _Ctx = Gost3411_Ctx;
247 :
248 : constexpr static uint32_t Length = 32;
249 : using Buf = std::array<uint8_t, Length>;
250 :
251 : template <typename ... Args>
252 : static Buf perform(Args && ... args);
253 :
254 : static Buf make(const CoderSource &, const StringView &salt = StringView());
255 : static Buf hmac(const CoderSource &data, const CoderSource &key);
256 :
257 : Gost3411_256();
258 : Gost3411_256 & init();
259 :
260 : Gost3411_256 & update(const uint8_t *, size_t);
261 : Gost3411_256 & update(const CoderSource &);
262 :
263 : template <typename T, typename ... Args>
264 : void _update(T && t, Args && ... args);
265 :
266 : template <typename T>
267 : void _update(T && t);
268 :
269 : Buf final();
270 : void final(uint8_t *);
271 :
272 : _Ctx ctx;
273 : };
274 :
275 : } // namespace stappler::crypto
276 :
277 :
278 : namespace STAPPLER_VERSIONIZED stappler {
279 :
280 18041 : inline CoderSource::CoderSource(const uint8_t *d, size_t len)
281 18041 : : _data(d, len) { }
282 :
283 50 : inline CoderSource::CoderSource(const char *d, size_t len)
284 50 : : _data((uint8_t *)d, len) { }
285 :
286 1575 : inline CoderSource::CoderSource(const char *d)
287 1575 : : _data((uint8_t *)d, strlen(d)) { }
288 :
289 8125 : inline CoderSource::CoderSource(const StringView &d)
290 8125 : : _data((uint8_t *)d.data(), d.size()) { }
291 :
292 5675 : inline CoderSource::CoderSource(const typename memory::PoolInterface::BytesType &d)
293 5675 : : _data(d.data(), d.size()) { }
294 :
295 3925 : inline CoderSource::CoderSource(const typename memory::StandartInterface::BytesType &d)
296 3925 : : _data(d.data(), d.size()) { }
297 :
298 525 : inline CoderSource::CoderSource(const typename memory::PoolInterface::StringType &d)
299 525 : : _data((const uint8_t *)d.data(), d.size()) { }
300 :
301 1000 : inline CoderSource::CoderSource(const typename memory::StandartInterface::StringType &d)
302 1000 : : _data((const uint8_t *)d.data(), d.size()) { }
303 :
304 : template <Endian Order>
305 7052 : inline CoderSource::CoderSource(const BytesViewTemplate<Order> &d)
306 7052 : : _data(d.data(), d.size()) { }
307 :
308 : inline CoderSource::CoderSource(const BytesReader<uint8_t> &d)
309 : : _data(d.data(), d.size()) { }
310 :
311 : inline CoderSource::CoderSource(const BytesReader<char> &d)
312 : : _data((const uint8_t *)d.data(), d.size()) { }
313 :
314 : template <size_t Size>
315 4875 : inline CoderSource::CoderSource(const std::array<uint8_t, Size> &d) : _data(d.data(), Size), _offset(0) { }
316 :
317 1525 : inline CoderSource::CoderSource() { }
318 :
319 49563 : inline const uint8_t* CoderSource::data() const {
320 49563 : return _data.data() + _offset;
321 : }
322 57864 : inline size_t CoderSource::size() const {
323 57864 : return _data.size() - _offset;
324 : }
325 1900 : inline bool CoderSource::empty() const {
326 1900 : return _data.empty() || _offset == _data.size();
327 : }
328 :
329 105 : inline BytesViewTemplate<Endian::Network> CoderSource::view() const {
330 105 : return _data;
331 : }
332 :
333 124450 : inline uint8_t CoderSource::operator[](size_t s) const {
334 124450 : return _data[s + _offset];
335 : }
336 :
337 397375 : inline size_t CoderSource::read(uint8_t *buf, size_t nbytes) {
338 397375 : const auto remains = _data.size() - _offset;
339 397375 : if (nbytes > remains) {
340 75 : nbytes = remains;
341 : }
342 397375 : memcpy(buf, _data.data() + _offset, nbytes);
343 397375 : _offset += nbytes;
344 397375 : return nbytes;
345 : }
346 :
347 1475 : inline size_t CoderSource::seek(int64_t offset, io::Seek s) {
348 1475 : switch (s) {
349 75 : case io::Seek::Current:
350 75 : if (offset + _offset > _data.size()) {
351 50 : _offset = _data.size();
352 25 : } else if (offset + int64_t(_offset) < 0) {
353 0 : _offset = 0;
354 : } else {
355 25 : _offset += offset;
356 : }
357 75 : break;
358 75 : case io::Seek::End:
359 75 : if (offset > 0) {
360 25 : _offset = _data.size();
361 50 : } else if (size_t(-offset) > _data.size()) {
362 25 : _offset = 0;
363 : } else {
364 25 : _offset = size_t(-offset);
365 : }
366 75 : break;
367 1325 : case io::Seek::Set:
368 1325 : if (offset < 0) {
369 25 : _offset = 0;
370 1300 : } else if (size_t(offset) <= _data.size()) {
371 1275 : _offset = size_t(offset);
372 : } else {
373 25 : _offset = _data.size();
374 : }
375 1325 : break;
376 : }
377 1475 : return _offset;
378 : }
379 :
380 25 : inline size_t CoderSource::tell() const {
381 25 : return _offset;
382 : }
383 :
384 : }
385 :
386 :
387 : namespace STAPPLER_VERSIONIZED stappler::crypto {
388 :
389 : template <typename ... Args>
390 : inline Sha512::Buf Sha512::perform(Args && ... args) {
391 : Sha512 ctx;
392 : ctx._update(std::forward<Args>(args)...);
393 : return ctx.final();
394 : }
395 :
396 : template <typename T, typename ... Args>
397 : inline void Sha512::_update(T && t, Args && ... args) {
398 : update(std::forward<T>(t));
399 : _update(std::forward<Args>(args)...);
400 : }
401 :
402 : template <typename T>
403 : inline void Sha512::_update(T && t) {
404 : update(std::forward<T>(t));
405 : }
406 :
407 : template <typename ... Args>
408 : inline Sha256::Buf Sha256::perform(Args && ... args) {
409 : Sha256 ctx;
410 : ctx._update(std::forward<Args>(args)...);
411 : return ctx.final();
412 : }
413 :
414 : template <typename T, typename ... Args>
415 : inline void Sha256::_update(T && t, Args && ... args) {
416 : update(std::forward<T>(t));
417 : _update(std::forward<Args>(args)...);
418 : }
419 :
420 : template <typename T>
421 : inline void Sha256::_update(T && t) {
422 : update(std::forward<T>(t));
423 : }
424 :
425 : template <typename ... Args>
426 : inline Gost3411_512::Buf Gost3411_512::perform(Args && ... args) {
427 : Gost3411_512 c;
428 : c._update(std::forward<Args>(args)...);
429 : return c.final();
430 : }
431 :
432 : template <typename T, typename ... Args>
433 : inline void Gost3411_512::_update(T && t, Args && ... args) {
434 : update(std::forward<T>(t));
435 : _update(std::forward<Args>(args)...);
436 : }
437 :
438 : template <typename T>
439 : inline void Gost3411_512::_update(T && t) {
440 : update(std::forward<T>(t));
441 : }
442 :
443 : template <typename ... Args>
444 : inline Gost3411_256::Buf Gost3411_256::perform(Args && ... args) {
445 : Gost3411_256 c;
446 : c._update(std::forward<Args>(args)...);
447 : return c.final();
448 : }
449 :
450 : template <typename T, typename ... Args>
451 : inline void Gost3411_256::_update(T && t, Args && ... args) {
452 : update(std::forward<T>(t));
453 : _update(std::forward<Args>(args)...);
454 : }
455 :
456 : template <typename T>
457 : inline void Gost3411_256::_update(T && t) {
458 : update(std::forward<T>(t));
459 : }
460 :
461 : }
462 :
463 :
464 : namespace STAPPLER_VERSIONIZED stappler::io {
465 :
466 : template <>
467 : struct ProducerTraits<CoderSource> {
468 : using type = CoderSource;
469 1275 : static size_t ReadFn(void *ptr, uint8_t *buf, size_t nbytes) {
470 1275 : return ((type *)ptr)->read(buf, nbytes);
471 : }
472 :
473 1225 : static size_t SeekFn(void *ptr, int64_t offset, Seek s) {
474 1225 : return ((type *)ptr)->seek(offset, s);
475 : }
476 0 : static size_t TellFn(void *ptr) {
477 0 : return ((type *)ptr)->tell();
478 : }
479 : };
480 :
481 : }
482 :
483 : #endif /* STAPPLER_CORE_STRING_SPCRYPTO_H_ */
|