LibCrypto: Do not trim leading zeros in export_data by default

This fixes the issue with the exported data having a leading zero,
causing RSA::encrypt to trim the block down, and ruining the encryption.

Fixes #2691 :^)
This commit is contained in:
AnotherTest 2020-07-31 13:33:14 +04:30 committed by Andreas Kling
parent 180207062c
commit b00ffc860b
Notes: sideshowbarker 2024-07-19 04:26:38 +09:00
6 changed files with 27 additions and 19 deletions

View file

@ -36,11 +36,15 @@ SignedBigInteger SignedBigInteger::import_data(const u8* ptr, size_t length)
return { move(unsigned_data), sign }; return { move(unsigned_data), sign };
} }
size_t SignedBigInteger::export_data(Bytes data) const size_t SignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) const
{ {
// FIXME: Support this:
// m <0XX> -> m <XX> (if remove_leading_zeros)
ASSERT(!remove_leading_zeros);
data[0] = m_sign; data[0] = m_sign;
auto bytes_view = data.slice(1, data.size() - 1); auto bytes_view = data.slice(1, data.size() - 1);
return m_unsigned_data.export_data(bytes_view) + 1; return m_unsigned_data.export_data(bytes_view, remove_leading_zeros) + 1;
} }
SignedBigInteger SignedBigInteger::from_base10(StringView str) SignedBigInteger SignedBigInteger::from_base10(StringView str)

View file

@ -67,7 +67,7 @@ public:
static SignedBigInteger import_data(const AK::StringView& data) { return import_data((const u8*)data.characters_without_null_termination(), data.length()); } static SignedBigInteger import_data(const AK::StringView& data) { return import_data((const u8*)data.characters_without_null_termination(), data.length()); }
static SignedBigInteger import_data(const u8* ptr, size_t length); static SignedBigInteger import_data(const u8* ptr, size_t length);
size_t export_data(Bytes) const; size_t export_data(Bytes, bool remove_leading_zeros = false) const;
static SignedBigInteger from_base10(StringView str); static SignedBigInteger from_base10(StringView str);
String to_base10() const; String to_base10() const;

View file

@ -55,21 +55,23 @@ UnsignedBigInteger UnsignedBigInteger::create_invalid()
return invalid; return invalid;
} }
size_t UnsignedBigInteger::export_data(Bytes data) const size_t UnsignedBigInteger::export_data(Bytes data, bool remove_leading_zeros) const
{ {
size_t word_count = trimmed_length(); size_t word_count = trimmed_length();
size_t out = 0; size_t out = 0;
if (word_count > 0) { if (word_count > 0) {
ssize_t leading_zeros = -1; ssize_t leading_zeros = -1;
u32 word = m_words[word_count - 1]; if (remove_leading_zeros) {
for (size_t i = 0; i < sizeof(u32); i++) { u32 word = m_words[word_count - 1];
u8 byte = (u8)(word >> ((sizeof(u32) - i - 1) * 8)); for (size_t i = 0; i < sizeof(u32); i++) {
data[out++] = byte; u8 byte = (u8)(word >> ((sizeof(u32) - i - 1) * 8));
if (leading_zeros < 0 && byte != 0) data[out++] = byte;
leading_zeros = (int)i; if (leading_zeros < 0 && byte != 0)
leading_zeros = (int)i;
}
} }
for (size_t i = word_count - 1; i > 0; i--) { for (size_t i = word_count - (remove_leading_zeros ? 1 : 0); i > 0; i--) {
word = m_words[i - 1]; auto word = m_words[i - 1];
data[out++] = (u8)(word >> 24); data[out++] = (u8)(word >> 24);
data[out++] = (u8)(word >> 16); data[out++] = (u8)(word >> 16);
data[out++] = (u8)(word >> 8); data[out++] = (u8)(word >> 8);

View file

@ -59,7 +59,7 @@ public:
return UnsignedBigInteger(ptr, length); return UnsignedBigInteger(ptr, length);
} }
size_t export_data(Bytes) const; size_t export_data(Bytes, bool remove_leading_zeros = false) const;
static UnsignedBigInteger from_base10(const String& str); static UnsignedBigInteger from_base10(const String& str);
String to_base10() const; String to_base10() const;

View file

@ -126,9 +126,11 @@ void RSA::encrypt(const ByteBuffer& in, ByteBuffer& out)
} }
auto exp = NumberTheory::ModularPower(in_integer, m_public_key.public_exponent(), m_public_key.modulus()); auto exp = NumberTheory::ModularPower(in_integer, m_public_key.public_exponent(), m_public_key.modulus());
auto size = exp.export_data(out.span()); auto size = exp.export_data(out.span());
// FIXME: We should probably not do this... auto outsize = out.size();
if (size != out.size()) if (size != outsize) {
out = out.slice(out.size() - size, size); dbg() << "POSSIBLE RSA BUG!!! Size mismatch: " << outsize << " requested but " << size << " bytes generated";
out = out.slice(outsize - size, size);
}
} }
void RSA::decrypt(const ByteBuffer& in, ByteBuffer& out) void RSA::decrypt(const ByteBuffer& in, ByteBuffer& out)
@ -252,8 +254,8 @@ void RSA_PKCS1_EME::encrypt(const ByteBuffer& in, ByteBuffer& out)
// since arc4random can create zeros (shocking!) // since arc4random can create zeros (shocking!)
// we have to go through and un-zero the zeros // we have to go through and un-zero the zeros
for (size_t i = 0; i < ps_length; ++i) for (size_t i = 0; i < ps_length; ++i)
if (!ps[i]) while (!ps[i])
ps[i] = 0xfe; AK::fill_with_random(ps + i, 1);
u8 paddings[] { 0x00, 0x02 }; u8 paddings[] { 0x00, 0x02 };

View file

@ -1933,7 +1933,7 @@ void bigint_import_export()
I_TEST((BigInteger | BigEndian Export)); I_TEST((BigInteger | BigEndian Export));
auto number = "448378203247"_bigint; auto number = "448378203247"_bigint;
char exported[8] { 0 }; char exported[8] { 0 };
auto exported_length = number.export_data({ exported, 8 }); auto exported_length = number.export_data({ exported, 8 }, true);
if (exported_length == 5 && memcmp(exported + 3, "hello", 5) == 0) { if (exported_length == 5 && memcmp(exported + 3, "hello", 5) == 0) {
PASS; PASS;
} else { } else {