diff --git a/src/libcalamares/utils/Entropy.cpp b/src/libcalamares/utils/Entropy.cpp index 21ee25115..643346855 100644 --- a/src/libcalamares/utils/Entropy.cpp +++ b/src/libcalamares/utils/Entropy.cpp @@ -26,7 +26,7 @@ CalamaresUtils::EntropySource CalamaresUtils::getEntropy( int size, QByteArray& b ) { b.clear(); - if ( size < 1) + if ( size < 1 ) { return EntropySource::None; } @@ -55,7 +55,6 @@ CalamaresUtils::getEntropy( int size, QByteArray& b ) std::mt19937_64 twister( seed ); std::uint64_t next = 0; - do { next = twister(); @@ -78,3 +77,48 @@ CalamaresUtils::getEntropy( int size, QByteArray& b ) return EntropySource::Twister; } + +CalamaresUtils::EntropySource +CalamaresUtils::getPrintableEntropy( int size, QString& s ) +{ + s.clear(); + if ( size < 1 ) + { + return EntropySource::None; + } + + static const char salt_chars[] = { '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + static_assert( sizeof( salt_chars ) == 64, "Missing salt_chars" ); + + // Number of bytes we're going to need + int byteSize = ( ( size * 6 ) / 8 ) + 1; + QByteArray b; + EntropySource r = getEntropy( byteSize, b ); + + int bitsLeft = 0; + int byteOffset = 0; + qint64 next = 0; + do + { + if ( bitsLeft < 6 ) + { + next = ( next << 8 ) | b.at( byteOffset++ ); + bitsLeft += 8; + } + char c = salt_chars[ next & 0b0111111 ]; + next >>= 6; + bitsLeft -= 6; + s.append( c ); + } while ( ( s.length() < size ) && ( byteOffset < b.size() ) ); + + if ( s.length() < size ) + { + // It's incomplete, not really no-entropy + return EntropySource::None; + } + + return r; +} diff --git a/src/libcalamares/utils/Entropy.h b/src/libcalamares/utils/Entropy.h index 2983e0e24..2ab7a609d 100644 --- a/src/libcalamares/utils/Entropy.h +++ b/src/libcalamares/utils/Entropy.h @@ -40,6 +40,14 @@ enum class EntropySource * bytes from a suitable source. Returns which source was used. */ DLLEXPORT EntropySource getEntropy( int size, QByteArray& b ); + +/** @brief Fill string @p s with exactly @p size random printable ASCII characters + * + * The characters are picked from a set of 64 (2^6). The string + * contains 6 * size bits of entropy. * Returns which source was used. + * @see getEntropy + */ +DLLEXPORT EntropySource getPrintableEntropy( int size, QString& s ); } // namespace CalamaresUtils #endif diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index 1ea50b2f2..81e1a9af6 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -185,18 +185,37 @@ LibCalamaresTests::testEntropy() auto r0 = CalamaresUtils::getEntropy( 0, data ); QCOMPARE( CalamaresUtils::EntropySource::None, r0 ); - QCOMPARE( 0, data.size() ); + QCOMPARE( data.size(), 0 ); auto r1 = CalamaresUtils::getEntropy( 16, data ); QVERIFY( r1 != CalamaresUtils::EntropySource::None ); - QCOMPARE( 16, data.size() ); + QCOMPARE( data.size(), 16 ); // This can randomly fail (but not often) QVERIFY( data.at( data.size() - 1 ) != char( 0xcb ) ); auto r2 = CalamaresUtils::getEntropy( 8, data ); QVERIFY( r2 != CalamaresUtils::EntropySource::None ); - QCOMPARE( 8, data.size() ); + QCOMPARE( data.size(), 8 ); QCOMPARE( r1, r2 ); // This can randomly fail (but not often) QVERIFY( data.at( data.size() - 1 ) != char( 0xcb ) ); } + +void +LibCalamaresTests::testPrintableEntropy() +{ + QString s; + + auto r0 = CalamaresUtils::getPrintableEntropy( 0, s ); + QCOMPARE( CalamaresUtils::EntropySource::None, r0 ); + QCOMPARE( s.length(), 0 ); + + auto r1 = CalamaresUtils::getPrintableEntropy( 16, s ); + QVERIFY( r1 != CalamaresUtils::EntropySource::None ); + QCOMPARE( s.length(), 16 ); + for ( QChar c : s ) + { + QVERIFY( c.isPrint() ); + QCOMPARE( c.cell(), 0 ); + } +} diff --git a/src/libcalamares/utils/Tests.h b/src/libcalamares/utils/Tests.h index d142152b1..d369ed4cb 100644 --- a/src/libcalamares/utils/Tests.h +++ b/src/libcalamares/utils/Tests.h @@ -42,6 +42,7 @@ private Q_SLOTS: /** @brief Tests the entropy functions. */ void testEntropy(); + void testPrintableEntropy(); }; #endif