To run scrypt encryption using OpenSSL 3.0 I'm using the code below. It runs fine with OpenSSL 3.0 with no FIPS. But the same code fails when FIPS is enabled. The reason being EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, e) returns NULL.
string scrypt_hashing(string sPassword, string sSalt, int iN, int iR, int iP) {
EVP_PKEY_CTX *pctx;
unsigned char out[64];
size_t outlen = sizeof(out);
ENGINE *e = NULL;
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, e);
if (EVP_PKEY_derive_init(pctx) <= 0) {
error("EVP_PKEY_derive_init");
}
if (EVP_PKEY_CTX_set1_pbe_pass(pctx, sPassword.c_str(), sPassword.size()) <= 0) {
error("EVP_PKEY_CTX_set1_pbe_pass");
}
if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, reinterpret_cast<const unsigned char*>(sSalt.c_str()), sSalt.size()) <= 0) {
error("EVP_PKEY_CTX_set1_scrypt_salt");
}
if (EVP_PKEY_CTX_set_scrypt_N(pctx, iN) <= 0) {
error("EVP_PKEY_CTX_set_scrypt_N");
}
if (EVP_PKEY_CTX_set_scrypt_r(pctx, iR) <= 0) {
error("EVP_PKEY_CTX_set_scrypt_r");
}
if (EVP_PKEY_CTX_set_scrypt_p(pctx, iP) <= 0) {
error("EVP_PKEY_CTX_set_scrypt_p");
}
if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
error("EVP_PKEY_derive");
}
EVP_PKEY_CTX_free(pctx);
std::stringstream ss;
ss << std::hex << std::setfill('0');
for (int i = 0; i < 64; ++i) {
ss << std::setw(2) << (int)out[i];
}
string sEncoded = ss.str();
return sEncoded;}
Is there any alternative approach to run the same?
I'm afraid you're out of luck: in FIPS mode OpenSSL only includes code that was validated according to FIPS 140-2 (see the OpenSSL documentation for more details), and that doesn't include the SCrypt algorithm.
If you look at the source code, the default provider will include SCrypt, but the FIPS provider won't.
There's nothing you can do about that: OpenSSL in FIPS mode simply doesn't support SCrypt (at the moment at least).
In general: the only reason to use OpenSSL in FIPS mode is if there's a regulatory requirement for that. From a technical standpoint FIPS makes no sense. The OpenSSL developers even mention this in their own Wiki. So if you do have to follow some regulatory requirement: you're out of luck, you simply can't use SCrypt. (Choose another KDF; PBKDF2 is a good choice as far as I am aware, but I'm not a cryptographer, so take this recommendation with a huge grain of salt.) If you don't have such a requirement, then just don't use FIPS.