Skip to content

Commit

Permalink
Fixup hkdfSha256()
Browse files Browse the repository at this point in the history
1. Replace the magic number returned when outputLength is not 64, with
   an assertion; it's never supposed to be different from 64. Maybe
   we should even `std::terminate` here?
2. Swallow the repetitive code into a macro and clear the SSL context
   in that macro - previously the code leaked the context every time
   it finished with an error. (Those errors are usually unrecoverable
   but it's good to manage resources carefully anyway.)
  • Loading branch information
Alexey Rusakov committed Dec 15, 2023
1 parent 8a845c5 commit ae888a9
Showing 1 changed file with 25 additions and 35 deletions.
60 changes: 25 additions & 35 deletions Quotient/e2ee/cryptoutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,51 +82,41 @@ SslExpected<QByteArray> Quotient::aesCtr256Encrypt(const QByteArray& plaintext,
return encrypted;
}

#define CALL_OPENSSL(Call_) \
do { \
if (Call_ != 1) { \
qWarning() << ERR_error_string(ERR_get_error(), nullptr); \
EVP_PKEY_CTX_free(context); \
return ERR_get_error(); \
} \
} while (false) // End of macro

SslExpected<HkdfKeys> Quotient::hkdfSha256(const QByteArray& key,
const QByteArray& salt,
const QByteArray& info)
{
QByteArray result(64, u'\0');
auto context = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);

int status = EVP_PKEY_derive_init(context);
if (status != 1) {
qWarning() << ERR_error_string(ERR_get_error(), nullptr);
return ERR_get_error();
}
status = EVP_PKEY_CTX_set_hkdf_md(context, EVP_sha256());
if (status != 1) {
qWarning() << ERR_error_string(ERR_get_error(), nullptr);
return ERR_get_error();
}
status = EVP_PKEY_CTX_set1_hkdf_salt(context, reinterpret_cast<const unsigned char *>(salt.data()), salt.size());
if (status != 1) {
qWarning() << ERR_error_string(ERR_get_error(), nullptr);
return ERR_get_error();
}
status = EVP_PKEY_CTX_set1_hkdf_key(context, reinterpret_cast<const unsigned char *>(key.data()), key.size());
if (status != 1) {
qWarning() << ERR_error_string(ERR_get_error(), nullptr);
return ERR_get_error();
}
status = EVP_PKEY_CTX_add1_hkdf_info(context, reinterpret_cast<const unsigned char *>(info.data()), info.size());
if (status != 1) {
qWarning() << ERR_error_string(ERR_get_error(), nullptr);
return ERR_get_error();
}
std::size_t outputLength = result.size();
status = EVP_PKEY_derive(context, reinterpret_cast<unsigned char *>(result.data()), &outputLength);
if (status != 1) {
qWarning() << ERR_error_string(ERR_get_error(), nullptr);
return ERR_get_error();
}
CALL_OPENSSL(EVP_PKEY_derive_init(context));
CALL_OPENSSL(EVP_PKEY_CTX_set_hkdf_md(context, EVP_sha256()));
CALL_OPENSSL(EVP_PKEY_CTX_set1_hkdf_salt(
context, reinterpret_cast<const unsigned char*>(salt.data()),
salt.size()));
CALL_OPENSSL(EVP_PKEY_CTX_set1_hkdf_key(
context, reinterpret_cast<const unsigned char*>(key.data()),
key.size()));
CALL_OPENSSL(EVP_PKEY_CTX_add1_hkdf_info(
context, reinterpret_cast<const unsigned char*>(info.data()),
info.size()));
auto outputLength = unsignedSize(result);
CALL_OPENSSL(EVP_PKEY_derive(context, reinterpret_cast<unsigned char *>(result.data()), &outputLength));

EVP_PKEY_CTX_free(context);

if (outputLength != 64) {
return static_cast<uint64_t>(1);
}
Q_ASSERT(outputLength != 64);

QByteArray macKey = result.mid(32);
auto macKey = result.mid(32);
result.resize(32);
return HkdfKeys{std::move(result), std::move(macKey)};
}
Expand Down

0 comments on commit ae888a9

Please sign in to comment.