LibCrypto: Make PKSystem methods return ErrorOr

Make `encrypt`, `decrypt`, `sign` and `verify` return `ErrorOr` for
better error propagation.
This commit is contained in:
devgianlu 2024-12-23 17:55:27 +01:00 committed by Ali Mohammad Pur
commit df05cc8478
Notes: github-actions[bot] 2025-01-12 00:14:44 +00:00
9 changed files with 68 additions and 82 deletions

View file

@ -136,25 +136,21 @@ ErrorOr<RSA::KeyPairType> RSA::generate_key_pair(size_t bits, IntegerType e)
return keys;
}
void RSA::encrypt(ReadonlyBytes in, Bytes& out)
ErrorOr<void> RSA::encrypt(ReadonlyBytes in, Bytes& out)
{
dbgln_if(CRYPTO_DEBUG, "in size: {}", in.size());
auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size());
if (!(in_integer < m_public_key.modulus())) {
dbgln("value too large for key");
out = {};
return;
}
if (in_integer >= m_public_key.modulus())
return Error::from_string_literal("Data too large for key");
auto exp = NumberTheory::ModularPower(in_integer, m_public_key.public_exponent(), m_public_key.modulus());
auto size = exp.export_data(out);
auto outsize = out.size();
if (size != outsize) {
dbgln("POSSIBLE RSA BUG!!! Size mismatch: {} requested but {} bytes generated", outsize, size);
out = out.slice(outsize - size, size);
}
VERIFY(size == outsize);
return {};
}
void RSA::decrypt(ReadonlyBytes in, Bytes& out)
ErrorOr<void> RSA::decrypt(ReadonlyBytes in, Bytes& out)
{
auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size());
@ -178,22 +174,25 @@ void RSA::decrypt(ReadonlyBytes in, Bytes& out)
for (auto i = size; i < aligned_size; ++i)
out[out.size() - i - 1] = 0; // zero the non-aligned values
out = out.slice(out.size() - aligned_size, aligned_size);
return {};
}
void RSA::sign(ReadonlyBytes in, Bytes& out)
ErrorOr<void> RSA::sign(ReadonlyBytes in, Bytes& out)
{
auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size());
auto exp = NumberTheory::ModularPower(in_integer, m_private_key.private_exponent(), m_private_key.modulus());
auto size = exp.export_data(out);
out = out.slice(out.size() - size, size);
return {};
}
void RSA::verify(ReadonlyBytes in, Bytes& out)
ErrorOr<void> RSA::verify(ReadonlyBytes in, Bytes& out)
{
auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size());
auto exp = NumberTheory::ModularPower(in_integer, m_public_key.public_exponent(), m_public_key.modulus());
auto size = exp.export_data(out);
out = out.slice(out.size() - size, size);
return {};
}
void RSA::import_private_key(ReadonlyBytes bytes, bool pem)
@ -258,19 +257,15 @@ void RSA::import_public_key(ReadonlyBytes bytes, bool pem)
m_public_key = maybe_key.release_value().public_key;
}
void RSA_PKCS1_EME::encrypt(ReadonlyBytes in, Bytes& out)
ErrorOr<void> RSA_PKCS1_EME::encrypt(ReadonlyBytes in, Bytes& out)
{
auto mod_len = (m_public_key.modulus().trimmed_length() * sizeof(u32) * 8 + 7) / 8;
dbgln_if(CRYPTO_DEBUG, "key size: {}", mod_len);
if (in.size() > mod_len - 11) {
dbgln("message too long :(");
out = out.trim(0);
return;
}
if (out.size() < mod_len) {
dbgln("output buffer too small");
return;
}
if (in.size() > mod_len - 11)
return Error::from_string_literal("Message too long");
if (out.size() < mod_len)
return Error::from_string_literal("Output buffer too small");
auto ps_length = mod_len - in.size() - 3;
Vector<u8, 8096> ps;
@ -294,60 +289,47 @@ void RSA_PKCS1_EME::encrypt(ReadonlyBytes in, Bytes& out)
dbgln_if(CRYPTO_DEBUG, "padded output size: {} buffer size: {}", 3 + ps_length + in.size(), out.size());
RSA::encrypt(out, out);
TRY(RSA::encrypt(out, out));
return {};
}
void RSA_PKCS1_EME::decrypt(ReadonlyBytes in, Bytes& out)
ErrorOr<void> RSA_PKCS1_EME::decrypt(ReadonlyBytes in, Bytes& out)
{
auto mod_len = (m_public_key.modulus().trimmed_length() * sizeof(u32) * 8 + 7) / 8;
if (in.size() != mod_len) {
dbgln("decryption error: wrong amount of data: {}", in.size());
out = out.trim(0);
return;
}
if (in.size() != mod_len)
return Error::from_string_literal("Invalid input size");
RSA::decrypt(in, out);
TRY(RSA::decrypt(in, out));
if (out.size() < RSA::output_size()) {
dbgln("decryption error: not enough data after decryption: {}", out.size());
out = out.trim(0);
return;
}
if (out.size() < RSA::output_size())
return Error::from_string_literal("Not enough data after decryption");
if (out[0] != 0x00) {
dbgln("invalid padding byte 0 : {}", out[0]);
return;
}
if (out[1] != 0x02) {
dbgln("invalid padding byte 1 : {}", out[1]);
return;
}
if (out[0] != 0x00 || out[1] != 0x02)
return Error::from_string_literal("Invalid padding");
size_t offset = 2;
while (offset < out.size() && out[offset])
++offset;
if (offset == out.size()) {
dbgln("garbage data, no zero to split padding");
return;
}
if (offset == out.size())
return Error::from_string_literal("Garbage data, no zero to split padding");
++offset;
if (offset - 3 < 8) {
dbgln("PS too small");
return;
}
if (offset - 3 < 8)
return Error::from_string_literal("PS too small");
out = out.slice(offset, out.size() - offset);
return {};
}
void RSA_PKCS1_EME::sign(ReadonlyBytes, Bytes&)
ErrorOr<void> RSA_PKCS1_EME::sign(ReadonlyBytes, Bytes&)
{
dbgln("FIXME: RSA_PKCS_EME::sign");
return Error::from_string_literal("FIXME: RSA_PKCS_EME::sign");
}
void RSA_PKCS1_EME::verify(ReadonlyBytes, Bytes&)
ErrorOr<void> RSA_PKCS1_EME::verify(ReadonlyBytes, Bytes&)
{
dbgln("FIXME: RSA_PKCS_EME::verify");
return Error::from_string_literal("FIXME: RSA_PKCS_EME::verify");
}
}