aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/digest/argonish/internal/blake2b/blake2b.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/digest/argonish/internal/blake2b/blake2b.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/digest/argonish/internal/blake2b/blake2b.h')
-rw-r--r--library/cpp/digest/argonish/internal/blake2b/blake2b.h187
1 files changed, 187 insertions, 0 deletions
diff --git a/library/cpp/digest/argonish/internal/blake2b/blake2b.h b/library/cpp/digest/argonish/internal/blake2b/blake2b.h
new file mode 100644
index 0000000000..3dcfc3fc48
--- /dev/null
+++ b/library/cpp/digest/argonish/internal/blake2b/blake2b.h
@@ -0,0 +1,187 @@
+#pragma once
+
+#include <util/generic/yexception.h>
+#include <util/system/compiler.h>
+#include <library/cpp/digest/argonish/blake2b.h>
+
+namespace NArgonish {
+ const ui32 BLAKE2B_BLOCKBYTES = 128;
+ const ui32 BLAKE2B_BLOCKQWORDS = BLAKE2B_BLOCKBYTES / 8;
+ const ui32 BLAKE2B_OUTBYTES = 64;
+ const ui32 BLAKE2B_KEYBYTES = 64;
+ const ui32 BLAKE2B_SALTBYTES = 16;
+ const ui32 BLAKE2B_PERSONALBYTES = 16;
+
+ template <NArgonish::EInstructionSet instructionSet>
+ class TBlake2B final: public IBlake2Base {
+ public:
+ virtual ~TBlake2B<instructionSet>() {
+ SecureZeroMemory_((void*)&State_, sizeof(State_));
+ SecureZeroMemory_((void*)&Param_, sizeof(Param_));
+ }
+
+ EInstructionSet GetInstructionSet() {
+ return instructionSet;
+ }
+
+ protected:
+ struct TBlake2BState {
+ ui64 H[8];
+ ui64 T[2];
+ ui64 F[2];
+ ui64 Buf[BLAKE2B_BLOCKQWORDS];
+ size_t BufLen;
+ size_t OutLen;
+ ui8 LastNode;
+ };
+
+ struct TBlake2BParam {
+ ui8 DigestLen; /* 1 */
+ ui8 KeyLen; /* 2 */
+ ui8 Fanout; /* 3 */
+ ui8 Depth; /* 4 */
+ ui32 LeafLength; /* 8 */
+ ui32 NodeOffset; /* 12 */
+ ui32 XofLength; /* 16 */
+ ui8 NodeDepth; /* 17 */
+ ui8 InnerLength; /* 18 */
+ ui8 Reserved[14]; /* 32 */
+ ui8 Salt[BLAKE2B_SALTBYTES]; /* 48 */
+ ui8 Personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+ } Y_PACKED;
+
+ TBlake2BState State_;
+ TBlake2BParam Param_;
+
+ protected:
+ void Compress_(const ui64 block[BLAKE2B_BLOCKQWORDS]);
+ void InitialXor_(ui8* h, const ui8* p);
+ void* GetIV_() const;
+
+ static void SecureZeroMemory_(void* src, size_t len) {
+ static void* (*const volatile memsetv)(void*, int, size_t) = &memset;
+ memsetv(src, 0, len);
+ }
+
+ void InitParam_() {
+ memset(&State_, 0, sizeof(State_));
+ InitialXor_((ui8*)(State_.H), (const ui8*)(&Param_));
+ State_.OutLen = Param_.DigestLen;
+ }
+
+ void IncrementCounter_(const ui64 inc) {
+ State_.T[0] += inc;
+ State_.T[1] += (State_.T[0] < inc) ? 1 : 0;
+ }
+
+ bool IsLastBlock_() {
+ return State_.F[0] != 0;
+ }
+
+ void SetLastNode_() {
+ State_.F[1] = (ui64)-1;
+ }
+
+ void SetLastBlock_() {
+ if (State_.LastNode)
+ SetLastNode_();
+
+ State_.F[0] = (ui64)-1;
+ }
+
+ public:
+ TBlake2B(size_t outlen) {
+ /*
+ * Note that outlen check was moved to proxy class
+ */
+
+ Param_.DigestLen = (ui8)outlen;
+ Param_.KeyLen = 0;
+ Param_.Fanout = 1;
+ Param_.Depth = 1;
+ Param_.LeafLength = 0;
+ Param_.NodeOffset = 0;
+ Param_.XofLength = 0;
+ Param_.NodeDepth = 0;
+ Param_.InnerLength = 0;
+
+ memset(Param_.Reserved, 0, sizeof(Param_.Reserved));
+ memset(Param_.Salt, 0, sizeof(Param_.Salt));
+ memset(Param_.Personal, 0, sizeof(Param_.Personal));
+
+ InitParam_();
+ }
+
+ TBlake2B(size_t outlen, const void* key, size_t keylen) {
+ /**
+ * Note that key and outlen checks were moved to proxy classes
+ */
+ Param_.DigestLen = (ui8)outlen;
+ Param_.KeyLen = (ui8)keylen;
+ Param_.Fanout = 1;
+ Param_.Depth = 1;
+
+ Param_.LeafLength = 0;
+ Param_.NodeOffset = 0;
+ Param_.XofLength = 0;
+ Param_.NodeDepth = 0;
+ Param_.InnerLength = 0;
+
+ memset(Param_.Reserved, 0, sizeof(Param_.Reserved));
+ memset(Param_.Salt, 0, sizeof(Param_.Salt));
+ memset(Param_.Personal, 0, sizeof(Param_.Personal));
+
+ InitParam_();
+ ui8 block[BLAKE2B_BLOCKBYTES] = {0};
+ memcpy(block, key, keylen);
+ Update(block, BLAKE2B_BLOCKBYTES);
+ SecureZeroMemory_(block, BLAKE2B_BLOCKBYTES);
+ }
+
+ void Update(ui32 in) override {
+ Update((const void*)&in, sizeof(in));
+ }
+
+ void Update(const void* pin, size_t inlen) override {
+ const ui8* in = (ui8*)pin;
+ if (inlen > 0) {
+ size_t left = State_.BufLen;
+ size_t fill = BLAKE2B_BLOCKBYTES - left;
+ if (inlen > fill) {
+ State_.BufLen = 0;
+ memcpy((ui8*)State_.Buf + left, in, fill); /* Fill buffer */
+ IncrementCounter_(BLAKE2B_BLOCKBYTES);
+ Compress_(State_.Buf); /* Compress */
+ in += fill;
+ inlen -= fill;
+ while (inlen > BLAKE2B_BLOCKBYTES) {
+ /* to fix ubsan's unaligned report */
+ ui64 tmpbuf[BLAKE2B_BLOCKQWORDS];
+ memcpy(tmpbuf, in, BLAKE2B_BLOCKBYTES);
+
+ IncrementCounter_(BLAKE2B_BLOCKBYTES);
+ Compress_(tmpbuf);
+ in += BLAKE2B_BLOCKBYTES;
+ inlen -= BLAKE2B_BLOCKBYTES;
+ }
+ }
+ memcpy((ui8*)State_.Buf + State_.BufLen, in, inlen);
+ State_.BufLen += inlen;
+ }
+ }
+
+ void Final(void* out, size_t outlen) override {
+ if (out == nullptr || outlen < State_.OutLen)
+ ythrow yexception() << "out is null or outlen is too long";
+
+ if (IsLastBlock_())
+ ythrow yexception() << "Final can't be called several times";
+
+ IncrementCounter_(State_.BufLen);
+ SetLastBlock_();
+ memset((ui8*)State_.Buf + State_.BufLen, 0, BLAKE2B_BLOCKBYTES - State_.BufLen);
+ Compress_(State_.Buf);
+ memcpy(out, (void*)&State_.H[0], outlen);
+ }
+ };
+}