scrypt.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* ===================================================================
  2. *
  3. * Copyright (c) 2015, Legrandin <helderijs@gmail.com>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in
  14. * the documentation and/or other materials provided with the
  15. * distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. * ===================================================================
  30. */
  31. #include "common.h"
  32. #include "endianess.h"
  33. FAKE_INIT(scrypt)
  34. /** Return 1 if the pointer is aligned to the 64-bit boundary **/
  35. static inline int aligned64(const uint8_t *p)
  36. {
  37. if ((uintptr_t)p % 8 == 0)
  38. return 1;
  39. else
  40. return 0;
  41. }
  42. static inline void strxor_inplace(uint8_t *in_out, const uint8_t *in, size_t data_len)
  43. {
  44. size_t i;
  45. if (!aligned64(in_out) || !aligned64(in) || (data_len%8)!=0) {
  46. for (i=0; i<data_len; i++) {
  47. *in_out++ ^= *in++;
  48. }
  49. } else {
  50. uint64_t *in_out64 = (uint64_t*)in_out;
  51. uint64_t *in64 = (uint64_t*)in;
  52. data_len /= 8;
  53. for (i=0; i<data_len; i++) {
  54. *in_out64++ ^= *in64++;
  55. }
  56. }
  57. }
  58. typedef int (core_t)(const uint8_t [64], const uint8_t [64], uint8_t [64]);
  59. /**
  60. * scrypt BlockMix function
  61. *
  62. * @in: input, a sequence of blocks, each 64 bytes long
  63. * @out: output, a sequence of blocks, each 64 bytes long
  64. * @two_r: the number of 64 bytes blocks in input and output (even)
  65. * @core: the Salsa20 core hashing function (with xor)
  66. *
  67. * @in and @out may not overlap.
  68. */
  69. static void scryptBlockMix(const uint8_t in[][64], uint8_t out[][64], size_t two_r,
  70. core_t *core)
  71. {
  72. unsigned i;
  73. const uint8_t (*x)[64];
  74. size_t r = two_r / 2;
  75. assert((void*)in != (void*)out);
  76. x = &in[two_r-1]; /* Last 64 byte block */
  77. for (i=0; i<two_r; i++) {
  78. uint8_t (*y)[64];
  79. y = &out[(i/2) + (i & 1)*r];
  80. (*core)(*x, in[i], *y);
  81. x = y;
  82. }
  83. }
  84. /**
  85. * scrypt ROMix function
  86. *
  87. * @data_in: input
  88. * @data_out: output
  89. * @data_len: Length in bytes of the two buffers `data_in` and `data_out`.
  90. * It is a multiple of 128.
  91. * @N: Memory/CPU cost. It must be a power of 2.
  92. *
  93. * @data_in and @data_out may overlap.
  94. */
  95. EXPORT_SYM int scryptROMix(const uint8_t *data_in, uint8_t *data_out,
  96. size_t data_len, unsigned N, core_t *core)
  97. {
  98. size_t two_r;
  99. uint8_t (*v)[64], (*x)[64];
  100. unsigned i;
  101. if (NULL==data_in || NULL==data_out || NULL==core) {
  102. return ERR_NULL;
  103. }
  104. two_r = data_len / 64;
  105. if ((two_r*64 != data_len) || (two_r & 1)) {
  106. return ERR_BLOCK_SIZE;
  107. }
  108. /** Allocate a possibly gigantic amount of memory **/
  109. /* It takes in total (N+1) * (128r) bytes */
  110. v = calloc(N + 1, data_len);
  111. if (NULL == v) {
  112. return ERR_MEMORY;
  113. }
  114. memmove(&v[0], data_in, data_len);
  115. /** Create the V array **/
  116. /* The size of each element of V is 64 bytes, so
  117. * you need to add `two_r` (not 1) to move forward.
  118. */
  119. x = v;
  120. for (i=0; i<N; i++) {
  121. scryptBlockMix(x, &x[two_r], two_r, core);
  122. x += two_r;
  123. }
  124. /** Mix via a pseudo random sequence **/
  125. x = &v[N * two_r];
  126. for (i=0; i<N; i++) {
  127. uint32_t index;
  128. index = LOAD_U32_LITTLE(&x[two_r - 1][0]) & (N - 1); /* Extract pseudo
  129. random index
  130. from last element
  131. */
  132. strxor_inplace(*x, v[index * two_r], data_len);
  133. scryptBlockMix(x, (uint8_t (*)[64])data_out, two_r, core);
  134. memmove(x, data_out, data_len);
  135. }
  136. /** Outro **/
  137. /** data_out already contains the right value **/
  138. free(v);
  139. return 0;
  140. }