Cache.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. Copyright (c) 2018 tevador
  3. This file is part of RandomX.
  4. RandomX is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. RandomX is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with RandomX. If not, see<http://www.gnu.org/licenses/>.
  14. */
  15. #include <cstring>
  16. #include "Cache.hpp"
  17. #include "softAes.h"
  18. #include "argon2.h"
  19. #include "Pcg32.hpp"
  20. #include "argon2_core.h"
  21. namespace RandomX {
  22. static_assert(ArgonMemorySize % (ArgonLanes * ARGON2_SYNC_POINTS) == 0, "ArgonMemorySize - invalid value");
  23. // This will shift and xor tmp1 into itself as 4 32-bit vals such as
  24. // sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
  25. static inline __m128i sl_xor(__m128i tmp1) {
  26. __m128i tmp4;
  27. tmp4 = _mm_slli_si128(tmp1, 0x04);
  28. tmp1 = _mm_xor_si128(tmp1, tmp4);
  29. tmp4 = _mm_slli_si128(tmp4, 0x04);
  30. tmp1 = _mm_xor_si128(tmp1, tmp4);
  31. tmp4 = _mm_slli_si128(tmp4, 0x04);
  32. tmp1 = _mm_xor_si128(tmp1, tmp4);
  33. return tmp1;
  34. }
  35. template<uint8_t rcon, bool soft>
  36. static inline void aesGenKeys(__m128i* xout0, __m128i* xout2) {
  37. __m128i xout1 = soft ? soft_aeskeygenassist(*xout2, rcon) : _mm_aeskeygenassist_si128(*xout2, rcon);
  38. xout1 = _mm_shuffle_epi32(xout1, 0xFF);
  39. *xout0 = sl_xor(*xout0);
  40. *xout0 = _mm_xor_si128(*xout0, xout1);
  41. xout1 = soft ? soft_aeskeygenassist(*xout0, 0x00) : _mm_aeskeygenassist_si128(*xout0, 0x00);
  42. xout1 = _mm_shuffle_epi32(xout1, 0xAA);
  43. *xout2 = sl_xor(*xout2);
  44. *xout2 = _mm_xor_si128(*xout2, xout1);
  45. }
  46. template<bool soft>
  47. static inline void expandAesKeys(const __m128i* seed, __m128i* keys) {
  48. __m128i xout0, xout2;
  49. xout0 = _mm_load_si128(seed);
  50. xout2 = _mm_load_si128(seed + 1);
  51. *keys++ = xout0;
  52. *keys++ = xout2;
  53. aesGenKeys<0x01, soft>(&xout0, &xout2);
  54. *keys++ = xout0;
  55. *keys++ = xout2;
  56. aesGenKeys<0x02, soft>(&xout0, &xout2);
  57. *keys++ = xout0;
  58. *keys++ = xout2;
  59. aesGenKeys<0x04, soft>(&xout0, &xout2);
  60. *keys++ = xout0;
  61. *keys++ = xout2;
  62. aesGenKeys<0x08, soft>(&xout0, &xout2);
  63. *keys++ = xout0;
  64. *keys++ = xout2;
  65. }
  66. void Cache::argonFill(const void* seed, size_t seedSize) {
  67. uint32_t memory_blocks, segment_length;
  68. argon2_instance_t instance;
  69. argon2_context context;
  70. context.out = nullptr;
  71. context.outlen = 0;
  72. context.pwd = CONST_CAST(uint8_t *)seed;
  73. context.pwdlen = (uint32_t)seedSize;
  74. context.salt = CONST_CAST(uint8_t *)ArgonSalt;
  75. context.saltlen = (uint32_t)ArgonSaltSize;
  76. context.secret = NULL;
  77. context.secretlen = 0;
  78. context.ad = NULL;
  79. context.adlen = 0;
  80. context.t_cost = ArgonIterations;
  81. context.m_cost = ArgonMemorySize;
  82. context.lanes = ArgonLanes;
  83. context.threads = 1;
  84. context.allocate_cbk = NULL;
  85. context.free_cbk = NULL;
  86. context.flags = ARGON2_DEFAULT_FLAGS;
  87. context.version = ARGON2_VERSION_NUMBER;
  88. /* 2. Align memory size */
  89. /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
  90. memory_blocks = context.m_cost;
  91. segment_length = memory_blocks / (context.lanes * ARGON2_SYNC_POINTS);
  92. instance.version = context.version;
  93. instance.memory = NULL;
  94. instance.passes = context.t_cost;
  95. instance.memory_blocks = memory_blocks;
  96. instance.segment_length = segment_length;
  97. instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
  98. instance.lanes = context.lanes;
  99. instance.threads = context.threads;
  100. instance.type = Argon2_d;
  101. instance.memory = (block*)memory;
  102. if (instance.threads > instance.lanes) {
  103. instance.threads = instance.lanes;
  104. }
  105. /* 3. Initialization: Hashing inputs, allocating memory, filling first
  106. * blocks
  107. */
  108. argon_initialize(&instance, &context);
  109. fill_memory_blocks(&instance);
  110. }
  111. template<bool softAes>
  112. void Cache::initialize(const void* seed, size_t seedSize) {
  113. //Argon2d memory fill
  114. argonFill(seed, seedSize);
  115. //Circular shift of the cache buffer by 512 bytes
  116. //realized by copying the first 512 bytes to the back
  117. //of the buffer and shifting the start by 512 bytes
  118. memcpy(memory + CacheSize, memory, CacheShift);
  119. //AES keys
  120. expandAesKeys<softAes>((__m128i*)seed, keys.data());
  121. }
  122. template void Cache::initialize<true>(const void*, size_t);
  123. template void Cache::initialize<false>(const void*, size_t);
  124. }