proxy_macros.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #pragma once
  2. //
  3. // Created by Evgeny Sidorov on 12/04/17.
  4. //
  5. /**
  6. * ZEROUPPER macro is only used for AVX2 instruction set to clear up the upper half of YMM registers
  7. * It's done to avoid performance penalty when CPU switches to non-AVX2 code (according to Agner)
  8. * and the post at https://software.intel.com/en-us/articles/intel-avx-state-transitions-migrating-sse-code-to-avx
  9. */
  10. #define ARGON2_PROXY_CLASS_DECL(IS) \
  11. class TArgon2Proxy##IS final: public IArgon2Base { \
  12. public: \
  13. TArgon2Proxy##IS(EArgon2Type atype, ui32 tcost, ui32 mcost, ui32 threads, \
  14. const ui8* key = nullptr, ui32 keylen = 0); \
  15. virtual ~TArgon2Proxy##IS(); \
  16. \
  17. virtual void Hash(const ui8* pwd, ui32 pwdlen, const ui8* salt, ui32 saltlen, \
  18. ui8* out, ui32 outlen, const ui8* aad = nullptr, ui32 aadlen = 0) const override; \
  19. virtual bool Verify(const ui8* pwd, ui32 pwdlen, const ui8* salt, ui32 saltlen, \
  20. const ui8* hash, ui32 hashlen, const ui8* aad = nullptr, ui32 aadlen = 0) const override; \
  21. virtual void HashWithCustomMemory(ui8* memory, size_t mlen, const ui8* pwd, ui32 pwdlen, \
  22. const ui8* salt, ui32 saltlen, ui8* out, ui32 outlen, \
  23. const ui8* aad = nullptr, ui32 aadlen = 0) const override; \
  24. virtual bool VerifyWithCustomMemory(ui8* memory, size_t mlen, const ui8* pwd, ui32 pwdlen, \
  25. const ui8* salt, ui32 saltlen, const ui8* hash, ui32 hashlen, \
  26. const ui8* aad = nullptr, ui32 aadlen = 0) const override; \
  27. virtual size_t GetMemorySize() const override; \
  28. \
  29. protected: \
  30. THolder<IArgon2Base> argon2; \
  31. };
  32. #define ARGON2_INSTANCE_DECL(IS_val, mcost_val, threads_val) \
  33. if (mcost == mcost_val && threads == threads_val) { \
  34. argon2 = MakeHolder<TArgon2##IS_val<mcost_val, threads_val>>(atype, tcost, key, keylen); \
  35. return; \
  36. }
  37. #define ARGON2_PROXY_CLASS_IMPL(IS) \
  38. TArgon2Proxy##IS::TArgon2Proxy##IS(EArgon2Type atype, ui32 tcost, ui32 mcost, ui32 threads, \
  39. const ui8* key, ui32 keylen) { \
  40. if ((key == nullptr && keylen > 0) || keylen > ARGON2_SECRET_MAX_LENGTH) \
  41. ythrow yexception() << "key is null or keylen equals 0 or key is too long"; \
  42. \
  43. ARGON2_INSTANCE_DECL(IS, 1, 1) \
  44. ARGON2_INSTANCE_DECL(IS, 8, 1) \
  45. ARGON2_INSTANCE_DECL(IS, 16, 1) \
  46. ARGON2_INSTANCE_DECL(IS, 32, 1) \
  47. ARGON2_INSTANCE_DECL(IS, 64, 1) \
  48. ARGON2_INSTANCE_DECL(IS, 128, 1) \
  49. ARGON2_INSTANCE_DECL(IS, 256, 1) \
  50. ARGON2_INSTANCE_DECL(IS, 512, 1) \
  51. ARGON2_INSTANCE_DECL(IS, 1024, 1) \
  52. ARGON2_INSTANCE_DECL(IS, 2048, 1) \
  53. ARGON2_INSTANCE_DECL(IS, 4096, 1) \
  54. ARGON2_INSTANCE_DECL(IS, 8192, 1) \
  55. ARGON2_INSTANCE_DECL(IS, 16384, 1) \
  56. ARGON2_INSTANCE_DECL(IS, 32768, 1) \
  57. ARGON2_INSTANCE_DECL(IS, 65536, 1) \
  58. ARGON2_INSTANCE_DECL(IS, 131072, 1) \
  59. ARGON2_INSTANCE_DECL(IS, 262144, 1) \
  60. ARGON2_INSTANCE_DECL(IS, 524288, 1) \
  61. ARGON2_INSTANCE_DECL(IS, 1048576, 1) \
  62. ARGON2_INSTANCE_DECL(IS, 1, 2) \
  63. ARGON2_INSTANCE_DECL(IS, 32, 2) \
  64. ARGON2_INSTANCE_DECL(IS, 64, 2) \
  65. ARGON2_INSTANCE_DECL(IS, 512, 2) \
  66. ARGON2_INSTANCE_DECL(IS, 1024, 2) \
  67. ARGON2_INSTANCE_DECL(IS, 2048, 2) \
  68. ARGON2_INSTANCE_DECL(IS, 4096, 2) \
  69. ARGON2_INSTANCE_DECL(IS, 8192, 2) \
  70. ARGON2_INSTANCE_DECL(IS, 16384, 2) \
  71. ARGON2_INSTANCE_DECL(IS, 32768, 2) \
  72. ARGON2_INSTANCE_DECL(IS, 65536, 2) \
  73. ARGON2_INSTANCE_DECL(IS, 131072, 2) \
  74. ARGON2_INSTANCE_DECL(IS, 262144, 2) \
  75. ARGON2_INSTANCE_DECL(IS, 524288, 2) \
  76. ARGON2_INSTANCE_DECL(IS, 1048576, 2) \
  77. ARGON2_INSTANCE_DECL(IS, 1, 4) \
  78. ARGON2_INSTANCE_DECL(IS, 32, 4) \
  79. ARGON2_INSTANCE_DECL(IS, 64, 4) \
  80. ARGON2_INSTANCE_DECL(IS, 512, 4) \
  81. ARGON2_INSTANCE_DECL(IS, 1024, 4) \
  82. ARGON2_INSTANCE_DECL(IS, 2048, 4) \
  83. ARGON2_INSTANCE_DECL(IS, 4096, 4) \
  84. ARGON2_INSTANCE_DECL(IS, 8192, 4) \
  85. ARGON2_INSTANCE_DECL(IS, 16384, 4) \
  86. ARGON2_INSTANCE_DECL(IS, 32768, 4) \
  87. ARGON2_INSTANCE_DECL(IS, 65536, 4) \
  88. ARGON2_INSTANCE_DECL(IS, 131072, 4) \
  89. ARGON2_INSTANCE_DECL(IS, 262144, 4) \
  90. ARGON2_INSTANCE_DECL(IS, 524288, 4) \
  91. ARGON2_INSTANCE_DECL(IS, 1048576, 4) \
  92. \
  93. ythrow yexception() << "These parameters are not supported. Please add the corresponding ARGON2_INSTANCE_DECL macro"; \
  94. } \
  95. \
  96. TArgon2Proxy##IS::~TArgon2Proxy##IS() { \
  97. } \
  98. \
  99. void TArgon2Proxy##IS::Hash(const ui8* pwd, ui32 pwdlen, const ui8* salt, ui32 saltlen, \
  100. ui8* out, ui32 outlen, const ui8* aad, ui32 aadlen) const { \
  101. if (saltlen < ARGON2_SALT_MIN_LEN) \
  102. ythrow yexception() << "salt is too short"; \
  103. if (outlen < ARGON2_MIN_OUTLEN) \
  104. ythrow yexception() << "output length is too short"; \
  105. \
  106. argon2->Hash(pwd, pwdlen, salt, saltlen, out, outlen, aad, aadlen); \
  107. ZEROUPPER \
  108. } \
  109. \
  110. bool TArgon2Proxy##IS::Verify(const ui8* pwd, ui32 pwdlen, const ui8* salt, ui32 saltlen, \
  111. const ui8* hash, ui32 hashlen, const ui8* aad, ui32 aadlen) const { \
  112. if (saltlen < ARGON2_SALT_MIN_LEN) \
  113. ythrow yexception() << "salt is too short"; \
  114. if (hashlen < ARGON2_MIN_OUTLEN) \
  115. ythrow yexception() << "hash length is too short"; \
  116. \
  117. return argon2->Verify(pwd, pwdlen, salt, saltlen, hash, hashlen, aad, aadlen); \
  118. ZEROUPPER \
  119. } \
  120. \
  121. void TArgon2Proxy##IS::HashWithCustomMemory(ui8* memory, size_t mlen, const ui8* pwd, ui32 pwdlen, \
  122. const ui8* salt, ui32 saltlen, ui8* out, ui32 outlen, \
  123. const ui8* aad, ui32 aadlen) const { \
  124. if (saltlen < ARGON2_SALT_MIN_LEN) \
  125. ythrow yexception() << "salt is too short"; \
  126. if (outlen < ARGON2_MIN_OUTLEN) \
  127. ythrow yexception() << "output length is too short"; \
  128. \
  129. argon2->HashWithCustomMemory(memory, mlen, pwd, pwdlen, salt, saltlen, out, outlen, aad, aadlen); \
  130. ZEROUPPER \
  131. } \
  132. \
  133. bool TArgon2Proxy##IS::VerifyWithCustomMemory(ui8* memory, size_t mlen, const ui8* pwd, ui32 pwdlen, \
  134. const ui8* salt, ui32 saltlen, const ui8* hash, ui32 hashlen, \
  135. const ui8* aad, ui32 aadlen) const { \
  136. if (saltlen < ARGON2_SALT_MIN_LEN) \
  137. ythrow yexception() << "salt is too short"; \
  138. if (hashlen < ARGON2_MIN_OUTLEN) \
  139. ythrow yexception() << "hash length is too short"; \
  140. \
  141. return argon2->VerifyWithCustomMemory(memory, mlen, pwd, pwdlen, salt, saltlen, hash, hashlen, aad, aadlen); \
  142. ZEROUPPER \
  143. } \
  144. \
  145. size_t TArgon2Proxy##IS::GetMemorySize() const { \
  146. return argon2->GetMemorySize(); \
  147. }
  148. #define BLAKE2B_PROXY_CLASS_DECL(IS) \
  149. class TBlake2BProxy##IS final: public IBlake2Base { \
  150. public: \
  151. TBlake2BProxy##IS(size_t outlen, const void* key = nullptr, size_t keylen = 0); \
  152. virtual void Update(ui32 in) override; \
  153. virtual void Update(const void* pin, size_t inlen) override; \
  154. virtual void Final(void* out, size_t outlen) override; \
  155. \
  156. protected: \
  157. THolder<IBlake2Base> blake2; \
  158. };
  159. #define BLAKE2B_PROXY_CLASS_IMPL(IS) \
  160. TBlake2BProxy##IS::TBlake2BProxy##IS(size_t outlen, const void* key, size_t keylen) { \
  161. if (!outlen || outlen > BLAKE2B_OUTBYTES) \
  162. ythrow yexception() << "outlen equals 0 or too long"; \
  163. \
  164. if (key == nullptr) { \
  165. blake2 = MakeHolder<TBlake2B<EInstructionSet::IS>>(outlen); \
  166. return; \
  167. } \
  168. \
  169. if (!key || !keylen || keylen > BLAKE2B_KEYBYTES) \
  170. ythrow yexception() << "key is null or too long"; \
  171. \
  172. blake2 = MakeHolder<TBlake2B<EInstructionSet::IS>>(outlen, key, keylen); \
  173. } \
  174. \
  175. void TBlake2BProxy##IS::Update(ui32 in) { \
  176. blake2->Update(in); \
  177. ZEROUPPER \
  178. } \
  179. \
  180. void TBlake2BProxy##IS::Update(const void* pin, size_t inlen) { \
  181. blake2->Update(pin, inlen); \
  182. ZEROUPPER \
  183. } \
  184. \
  185. void TBlake2BProxy##IS::Final(void* out, size_t outlen) { \
  186. blake2->Final(out, outlen); \
  187. ZEROUPPER \
  188. }