You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
4.5 KiB
179 lines
4.5 KiB
#if !defined(SCRYPT_CHOOSE_COMPILETIME) || !defined(SCRYPT_HAVE_ROMIX) |
|
|
|
#if defined(SCRYPT_CHOOSE_COMPILETIME) |
|
#undef SCRYPT_ROMIX_FN |
|
#define SCRYPT_ROMIX_FN scrypt_ROMix |
|
#endif |
|
|
|
#undef SCRYPT_HAVE_ROMIX |
|
#define SCRYPT_HAVE_ROMIX |
|
|
|
#if !defined(SCRYPT_CHUNKMIX_FN) |
|
|
|
#define SCRYPT_CHUNKMIX_FN scrypt_ChunkMix_basic |
|
|
|
/* |
|
Bout = ChunkMix(Bin) |
|
|
|
2*r: number of blocks in the chunk |
|
*/ |
|
static void asm_calling_convention |
|
SCRYPT_CHUNKMIX_FN(scrypt_mix_word_t *Bout/*[chunkWords]*/, scrypt_mix_word_t *Bin/*[chunkWords]*/, scrypt_mix_word_t *Bxor/*[chunkWords]*/, uint32_t r) { |
|
scrypt_mix_word_t MM16 X[SCRYPT_BLOCK_WORDS], *block; |
|
uint32_t i, j, blocksPerChunk = r * 2, half = 0; |
|
|
|
/* 1: X = B_{2r - 1} */ |
|
block = scrypt_block(Bin, blocksPerChunk - 1); |
|
for (i = 0; i < SCRYPT_BLOCK_WORDS; i++) |
|
X[i] = block[i]; |
|
|
|
if (Bxor) { |
|
block = scrypt_block(Bxor, blocksPerChunk - 1); |
|
for (i = 0; i < SCRYPT_BLOCK_WORDS; i++) |
|
X[i] ^= block[i]; |
|
} |
|
|
|
/* 2: for i = 0 to 2r - 1 do */ |
|
for (i = 0; i < blocksPerChunk; i++, half ^= r) { |
|
/* 3: X = H(X ^ B_i) */ |
|
block = scrypt_block(Bin, i); |
|
for (j = 0; j < SCRYPT_BLOCK_WORDS; j++) |
|
X[j] ^= block[j]; |
|
|
|
if (Bxor) { |
|
block = scrypt_block(Bxor, i); |
|
for (j = 0; j < SCRYPT_BLOCK_WORDS; j++) |
|
X[j] ^= block[j]; |
|
} |
|
SCRYPT_MIX_FN(X); |
|
|
|
/* 4: Y_i = X */ |
|
/* 6: B'[0..r-1] = Y_even */ |
|
/* 6: B'[r..2r-1] = Y_odd */ |
|
block = scrypt_block(Bout, (i / 2) + half); |
|
for (j = 0; j < SCRYPT_BLOCK_WORDS; j++) |
|
block[j] = X[j]; |
|
} |
|
} |
|
#endif |
|
|
|
/* |
|
X = ROMix(X) |
|
|
|
X: chunk to mix |
|
Y: scratch chunk |
|
N: number of rounds |
|
V[N]: array of chunks to randomly index in to |
|
2*r: number of blocks in a chunk |
|
*/ |
|
|
|
static void NOINLINE FASTCALL |
|
SCRYPT_ROMIX_FN(scrypt_mix_word_t *X/*[chunkWords]*/, scrypt_mix_word_t *Y/*[chunkWords]*/, scrypt_mix_word_t *V/*[N * chunkWords]*/, uint32_t N, uint32_t r) { |
|
uint32_t i, j, chunkWords = SCRYPT_BLOCK_WORDS * r * 2; |
|
scrypt_mix_word_t *block = V; |
|
|
|
SCRYPT_ROMIX_TANGLE_FN(X, r * 2); |
|
|
|
/* 1: X = B */ |
|
/* implicit */ |
|
|
|
/* 2: for i = 0 to N - 1 do */ |
|
memcpy(block, X, chunkWords * sizeof(scrypt_mix_word_t)); |
|
for (i = 0; i < N - 1; i++, block += chunkWords) { |
|
/* 3: V_i = X */ |
|
/* 4: X = H(X) */ |
|
SCRYPT_CHUNKMIX_FN(block + chunkWords, block, NULL, r); |
|
} |
|
SCRYPT_CHUNKMIX_FN(X, block, NULL, r); |
|
|
|
/* 6: for i = 0 to N - 1 do */ |
|
for (i = 0; i < N; i += 2) { |
|
/* 7: j = Integerify(X) % N */ |
|
j = X[chunkWords - SCRYPT_BLOCK_WORDS] & (N - 1); |
|
|
|
/* 8: X = H(Y ^ V_j) */ |
|
SCRYPT_CHUNKMIX_FN(Y, X, scrypt_item(V, j, chunkWords), r); |
|
|
|
/* 7: j = Integerify(Y) % N */ |
|
j = Y[chunkWords - SCRYPT_BLOCK_WORDS] & (N - 1); |
|
|
|
/* 8: X = H(Y ^ V_j) */ |
|
SCRYPT_CHUNKMIX_FN(X, Y, scrypt_item(V, j, chunkWords), r); |
|
} |
|
|
|
/* 10: B' = X */ |
|
/* implicit */ |
|
|
|
SCRYPT_ROMIX_UNTANGLE_FN(X, r * 2); |
|
} |
|
|
|
/* |
|
* Special version with hard-coded r = 1 |
|
* - mikaelh |
|
*/ |
|
static void NOINLINE FASTCALL |
|
scrypt_ROMix_1(scrypt_mix_word_t *X/*[chunkWords]*/, scrypt_mix_word_t *Y/*[chunkWords]*/, scrypt_mix_word_t *V/*[N * chunkWords]*/, uint32_t N) { |
|
const uint32_t r = 1; |
|
uint32_t i, j, chunkWords = SCRYPT_BLOCK_WORDS * r * 2; |
|
scrypt_mix_word_t *block = V; |
|
|
|
SCRYPT_ROMIX_TANGLE_FN(X, r * 2); |
|
|
|
/* 1: X = B */ |
|
/* implicit */ |
|
|
|
/* 2: for i = 0 to N - 1 do */ |
|
memcpy(block, X, chunkWords * sizeof(scrypt_mix_word_t)); |
|
for (i = 0; i < N - 1; i++, block += chunkWords) { |
|
/* 3: V_i = X */ |
|
/* 4: X = H(X) */ |
|
#ifdef SCRYPT_CHUNKMIX_1_FN |
|
SCRYPT_CHUNKMIX_1_FN(block + chunkWords, block); |
|
#else |
|
SCRYPT_CHUNKMIX_FN(block + chunkWords, block, NULL, r); |
|
#endif |
|
} |
|
#ifdef SCRYPT_CHUNKMIX_1_FN |
|
SCRYPT_CHUNKMIX_1_FN(X, block); |
|
#else |
|
SCRYPT_CHUNKMIX_FN(X, block, NULL, r); |
|
#endif |
|
|
|
/* 6: for i = 0 to N - 1 do */ |
|
for (i = 0; i < N; i += 2) { |
|
/* 7: j = Integerify(X) % N */ |
|
j = X[chunkWords - SCRYPT_BLOCK_WORDS] & (N - 1); |
|
|
|
/* 8: X = H(Y ^ V_j) */ |
|
#ifdef SCRYPT_CHUNKMIX_1_XOR_FN |
|
SCRYPT_CHUNKMIX_1_XOR_FN(Y, X, scrypt_item(V, j, chunkWords)); |
|
#else |
|
SCRYPT_CHUNKMIX_FN(Y, X, scrypt_item(V, j, chunkWords), r); |
|
#endif |
|
|
|
/* 7: j = Integerify(Y) % N */ |
|
j = Y[chunkWords - SCRYPT_BLOCK_WORDS] & (N - 1); |
|
|
|
/* 8: X = H(Y ^ V_j) */ |
|
#ifdef SCRYPT_CHUNKMIX_1_XOR_FN |
|
SCRYPT_CHUNKMIX_1_XOR_FN(X, Y, scrypt_item(V, j, chunkWords)); |
|
#else |
|
SCRYPT_CHUNKMIX_FN(X, Y, scrypt_item(V, j, chunkWords), r); |
|
#endif |
|
} |
|
|
|
/* 10: B' = X */ |
|
/* implicit */ |
|
|
|
SCRYPT_ROMIX_UNTANGLE_FN(X, r * 2); |
|
} |
|
|
|
#endif /* !defined(SCRYPT_CHOOSE_COMPILETIME) || !defined(SCRYPT_HAVE_ROMIX) */ |
|
|
|
|
|
#undef SCRYPT_CHUNKMIX_FN |
|
#undef SCRYPT_ROMIX_FN |
|
#undef SCRYPT_MIX_FN |
|
#undef SCRYPT_ROMIX_TANGLE_FN |
|
#undef SCRYPT_ROMIX_UNTANGLE_FN |
|
|
|
|