Beispiel #1
0
/* Random oracles mix.
 * Based on RFC 7914: scrypt PBKDF.
 *
 * x  Data to mix.
 * v  Temporary buffer.
 * y  Temporary buffer for the block mix.
 * r  Block size parameter.
 * n  CPU/Memory cost parameter.
 */
static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n)
{
    word32 i;
    word32 j;
    word32 k;
    word32 bSz = 128 * r;
#ifdef WORD64_AVAILABLE
    word64* x64 = (word64*)x;
    word64* v64 = (word64*)v;
#else
    word32* x32 = (word32*)x;
    word32* v32 = (word32*)v;
#endif

    /* Step 1. X = B (B not needed therefore not implemented) */
    /* Step 2. */
    for (i = 0; i < n; i++)
    {
        XMEMCPY(v + i * bSz, x, bSz);
        scryptBlockMix(x, y, r);
    }

    /* Step 3. */
    for (i = 0; i < n; i++)
    {
#ifdef LITTLE_ENDIAN_ORDER
#ifdef WORD64_AVAILABLE
        j = *(word64*)(x + (2*r - 1) * 64) & (n-1);
#else
        j = *(word32*)(x + (2*r - 1) * 64) & (n-1);
#endif
#else
        byte* t = x + (2*r - 1) * 64;
        j = (t[0] | (t[1] << 8) | (t[2] << 16) | (t[3] << 24)) & (n-1);
#endif
#ifdef WORD64_AVAILABLE
        for (k = 0; k < bSz / 8; k++)
            x64[k] ^= v64[j * bSz / 8 + k];
#else
        for (k = 0; k < bSz / 4; k++)
            x32[k] ^= v32[j * bSz / 4 + k];
#endif
        scryptBlockMix(x, y, r);
    }
    /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */
}
Beispiel #2
0
// scryptROMix implements the function described in RFC 7914, section 5.  |B| is
// an scrypt block (2 * |r| Salsa20 blocks) and is modified in-place. |T| and
// |V| are scratch space allocated by the caller. |T| must have space for one
// scrypt block (2 * |r| Salsa20 blocks). |V| must have space for |N| scrypt
// blocks (2 * |r| * |N| Salsa20 blocks).
static void scryptROMix(block_t *B, uint64_t r, uint64_t N, block_t *T,
                        block_t *V) {
  // Steps 1 and 2.
  OPENSSL_memcpy(V, B, 2 * r * sizeof(block_t));
  for (uint64_t i = 1; i < N; i++) {
    scryptBlockMix(&V[2 * r * i /* scrypt block i */],
                   &V[2 * r * (i - 1) /* scrypt block i-1 */], r);
  }
  scryptBlockMix(B, &V[2 * r * (N - 1) /* scrypt block N-1 */], r);

  // Step 3.
  for (uint64_t i = 0; i < N; i++) {
    // Note this assumes |N| <= 2^32 and is a power of 2.
    uint32_t j = B[2 * r - 1].words[0] & (N - 1);
    for (size_t k = 0; k < 2 * r; k++) {
      xor_block(&T[k], &B[k], &V[2 * r * j + k]);
    }
    scryptBlockMix(B, T, r);
  }
}
Beispiel #3
0
static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
                        uint32_t *X, uint32_t *T, uint32_t *V)
{
    unsigned char *pB;
    uint32_t *pV;
    uint64_t i, k;

    /* Convert from little endian input */
    for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
        *pV = *pB++;
        *pV |= *pB++ << 8;
        *pV |= *pB++ << 16;
        *pV |= (uint32_t)*pB++ << 24;
    }

    for (i = 1; i < N; i++, pV += 32 * r)
        scryptBlockMix(pV, pV - 32 * r, r);

    scryptBlockMix(X, V + (N - 1) * 32 * r, r);

    for (i = 0; i < N; i++) {
        uint32_t j;
        j = X[16 * (2 * r - 1)] % N;
        pV = V + 32 * r * j;
        for (k = 0; k < 32 * r; k++)
            T[k] = X[k] ^ *pV++;
        scryptBlockMix(X, T, r);
    }
    /* Convert output to little endian */
    for (i = 0, pB = B; i < 32 * r; i++) {
        uint32_t xtmp = X[i];
        *pB++ = xtmp & 0xff;
        *pB++ = (xtmp >> 8) & 0xff;
        *pB++ = (xtmp >> 16) & 0xff;
        *pB++ = (xtmp >> 24) & 0xff;
    }
}