--- yescrypt-0.4.8/yescrypt-ref.c 2014-03-30 04:14:23.701544856 +0400 +++ yescrypt-0.4.10/yescrypt-ref.c 2014-03-31 05:30:22.873634959 +0400 @@ -489,6 +488,16 @@ uint64_t NROM; size_t B_size, V_size; uint32_t * B, * V, * XY, * S; + uint32_t sha256[8]; + + /* + * YESCRYPT_PARALLEL_SMIX is a no-op at p = 1 for its intended purpose, + * so don't let it have side-effects. Without this adjustment, it'd + * enable the SHA-256 password pre-hashing and output post-hashing, + * because any deviation from classic scrypt implies those. + */ + if (p == 1) + flags &= ~YESCRYPT_PARALLEL_SMIX; /* Sanity-check parameters. */ if (flags & ~YESCRYPT_KNOWN_FLAGS) { @@ -586,10 +595,22 @@ goto free_XY; } + if (t || flags) { + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, passwd, passwdlen); + SHA256_Final((uint8_t *)sha256, &ctx); + passwd = (uint8_t *)sha256; + passwdlen = sizeof(sha256); + } + /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, (uint8_t *)B, B_size); + if (t || flags) + blkcpy(sha256, B, sizeof(sha256) / sizeof(sha256[0])); + if (flags & YESCRYPT_PARALLEL_SMIX) { smix(B, r, N, p, t, flags, V, NROM, shared, XY, S); } else { @@ -606,6 +627,30 @@ /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ PBKDF2_SHA256(passwd, passwdlen, (uint8_t *)B, B_size, 1, buf, buflen); + /* + * Except when computing classic scrypt, allow all computation so far + * to be performed on the client. The final steps below match those of + * SCRAM (RFC 5802), so that an extension of SCRAM (with the steps so + * far in place of SCRAM's use of PBKDF2 and with SHA-256 in place of + * SCRAM's use of SHA-1) would be usable with yescrypt hashes. + */ + if ((t || flags) && buflen == sizeof(sha256)) { + /* Compute ClientKey */ + { + HMAC_SHA256_CTX ctx; + HMAC_SHA256_Init(&ctx, buf, buflen); + HMAC_SHA256_Update(&ctx, "Client Key", 10); + HMAC_SHA256_Final((uint8_t *)sha256, &ctx); + } + /* Compute StoredKey */ + { + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, (uint8_t *)sha256, sizeof(sha256)); + SHA256_Final(buf, &ctx); + } + } + /* Success! */ retval = 0;