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.
180 lines
4.5 KiB
180 lines
4.5 KiB
10 years ago
|
#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
|
||
|
|