/*
 * Special version where N = 1
 *  - mikaelh
 */
static void
scrypt_pbkdf2_1(const uint8_t *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint8_t *out, size_t bytes) {
	scrypt_hmac_state hmac_pw, hmac_pw_salt, work;
	scrypt_hash_digest ti, u;
	uint8_t be[4];
	uint32_t i, /*j,*/ blocks;
//	uint64_t c;
	
	/* bytes must be <= (0xffffffff - (SCRYPT_HASH_DIGEST_SIZE - 1)), which they will always be under scrypt */

	/* hmac(password, ...) */
	scrypt_hmac_init(&hmac_pw, password, password_len);

	/* hmac(password, salt...) */
	hmac_pw_salt = hmac_pw;
	scrypt_hmac_update(&hmac_pw_salt, salt, salt_len);

	blocks = ((uint32_t)bytes + (SCRYPT_HASH_DIGEST_SIZE - 1)) / SCRYPT_HASH_DIGEST_SIZE;
	for (i = 1; i <= blocks; i++) {
		/* U1 = hmac(password, salt || be(i)) */
		U32TO8_BE(be, i);
		work = hmac_pw_salt;
		scrypt_hmac_update(&work, be, 4);
		scrypt_hmac_finish(&work, ti);
		memcpy(u, ti, sizeof(u));

		memcpy(out, ti, (bytes > SCRYPT_HASH_DIGEST_SIZE) ? SCRYPT_HASH_DIGEST_SIZE : bytes);
		out += SCRYPT_HASH_DIGEST_SIZE;
		bytes -= SCRYPT_HASH_DIGEST_SIZE;
	}
}
Example #2
0
void scrypt_pbkdf2_sha256(const uint8_t* password,
                          size_t password_len,
                          const uint8_t* salt,
                          size_t salt_len,
                          unsigned int c,
                          uint8_t* out,
                          size_t out_len) {
  /*
   * Terminology:
   *   P = password
   *   S = salt
   *   DK = out
   *   dkLen = out_len
   */

  /* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop. */
  /* (skip) */

  /* 2. Let l be the number of hLen-octet blocks in the derived key,
   *    rounding up, and let r be the number of octets in the last
   *    block:
   *
   *               l = CEIL (dkLen / hLen) ,
   *               r = dkLen - (l - 1) * hLen .
   *
   *    Here, CEIL (x) is the "ceiling" function, i.e. the smallest
   *    integer greater than, or equal to, x.
   */
  size_t i;
  size_t l;
  size_t r;

  l = (out_len + kSha256DigestSize - 1) / kSha256DigestSize;
  r = out_len - (l - 1) * kSha256DigestSize;

  /* 3. For each block of the derived key apply the function F defined
   *    below to the password P, the salt S, the iteration count c, and
   *    the block index to compute the block:
   *
   *               T_1 = F (P, S, c, 1) ,
   *               T_2 = F (P, S, c, 2) ,
   *               ...
   *               T_l = F (P, S, c, l) ,
   *
   *    where the function F is defined as the exclusive-or sum of the
   *    first c iterates of the underlying pseudorandom function PRF
   *    applied to the password P and the concatenation of the salt S
   *    and the block index i:
   *
   *               F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
   *
   *    where
   *
   *               U_1 = PRF (P, S || INT (i)) ,
   *               U_2 = PRF (P, U_1) ,
   *               ...
   *               U_c = PRF (P, U_{c-1}) .
   *
   *    Here, INT (i) is a four-octet encoding of the integer i, most
   *    significant octet first.
   */
  for (i = 1; i <= l; i++) {
    unsigned int j;
    uint8_t t[kSha256DigestSize];
    uint8_t u[kSha256DigestSize];
    uint8_t ctr[4];
    scrypt_hmac_t hmac;

    ctr[0] = i >> 24;
    ctr[1] = i >> 16;
    ctr[2] = i >> 8;
    ctr[3] = i;

    /* U_1 = PRF (P, S || INT (i)) */
    scrypt_hmac_init(&hmac, password, password_len);
    scrypt_hmac_update(&hmac, salt, salt_len);
    scrypt_hmac_update(&hmac, ctr, sizeof(ctr));
    scrypt_hmac_digest(&hmac, u);
    memcpy(t, u, sizeof(u));

    for (j = 2; j <= c; j++) {
      size_t u_len;
      size_t k;

      u_len = sizeof(u);

      /* U_c = PRF (P, U_{c-1}) */
      scrypt_hmac_init(&hmac, password, password_len);
      scrypt_hmac_update(&hmac, u, u_len);
      scrypt_hmac_digest(&hmac, u);

      /* Xor Us */
      for (k = 0; k < kSha256DigestSize; k++)
        t[k] ^= u[k];
    }

    /* Copy out the results */
    memcpy(&out[(i - 1) * kSha256DigestSize],
           t,
           MIN(out_len - (i - 1) * kSha256DigestSize, kSha256DigestSize));
  }
}