Blob PBKDF2(PseudoRandomFunction& prf, const ConstBuf& password, const ConstBuf& salt, uint32_t c, size_t dkLen) { size_t hlen = prf.HashSize(); if (dkLen > uint64_t(hlen) * uint32_t(0xFFFFFFFF)) Throw(ExtErr::DerivedKeyTooLong); uint32_t iBe = 0; Blob salt_i = salt + ConstBuf(&iBe, 4); Blob r(nullptr, dkLen); for (uint32_t i=1, n=uint32_t((dkLen + hlen - 1) / hlen); i<=n; ++i) { memcpy(salt_i.data()+salt.Size, &(iBe = htobe(i)), 4); hashval u = prf(password, salt_i), rh = u; for (uint32_t j=1; j<c; ++j) VectorXor(rh.data(), (u = prf(password, u)).data(), hlen); memcpy(r.data() + (i-1)*hlen, rh.data(), (min)(hlen, r.Size - (i-1)*hlen)); } return r; }
bool CPU_ProbeAltivec() { #if defined(CRYPTOPP_NO_CPU_FEATURE_PROBES) return false; #elif (CRYPTOPP_ALTIVEC_AVAILABLE) # if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY) // longjmp and clobber warnings. Volatile is required. // http://github.com/weidai11/cryptopp/issues/24 and http://stackoverflow.com/q/7721854 volatile int result = true; volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler); if (oldHandler == SIG_ERR) return false; volatile sigset_t oldMask; if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask)) return false; if (setjmp(s_jmpSIGILL)) result = false; else { const byte b1[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; const byte b2[16] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; byte b3[16]; const uint8x16_p v1 = (uint8x16_p)VectorLoad(0, b1); const uint8x16_p v2 = (uint8x16_p)VectorLoad(0, b2); const uint8x16_p v3 = (uint8x16_p)VectorXor(v1, v2); VectorStore(v3, b3); result = (0 == std::memcmp(b2, b3, 16)); } sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR); signal(SIGILL, oldHandler); return result; # endif #else return false; #endif // CRYPTOPP_ALTIVEC_AVAILABLE }
Blob Scrypt(const ConstBuf& password, const ConstBuf& salt, int n, int r, int p, size_t dkLen) { HmacPseudoRandomFunction<SHA256> prf; const size_t mfLen = r*128; Blob bb = PBKDF2(prf, password, salt, 1, p*mfLen); AlignedMem am((n+1)*r*128, 128); uint32_t *v = (uint32_t*)am.get(); SalsaBlockPtr tmp = (SalsaBlockPtr)alloca(r*128); for (int i=0; i<p; ++i) { SalsaBlockPtr x = (SalsaBlockPtr)(bb.data()+i*mfLen); for (int i=0; i<n; ++i) { memcpy(&v[i * 32 * r], x, 2*r * sizeof(x[0])); VectorMix(Salsa20Core, x, tmp, r, 8); } for (int i=0; i<n; ++i) { int j = 32*r * (x[2 * r - 1][0] & (n - 1)); VectorXor(x[0], &v[j], 2*r*16); VectorMix(Salsa20Core, x, tmp, r, 8); } } return PBKDF2(prf, password, bb, 1, dkLen); }