mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:22:43 +00:00 
			
		
		
		
	LibCrypto: Move each subsection into its own namespace
This commit is contained in:
		
							parent
							
								
									96dd7c2996
								
							
						
					
					
						commit
						4f89a377a4
					
				
					 9 changed files with 3256 additions and 3228 deletions
				
			
		|  | @ -28,395 +28,399 @@ | ||||||
| #include <LibCrypto/Cipher/AES.h> | #include <LibCrypto/Cipher/AES.h> | ||||||
| 
 | 
 | ||||||
| namespace Crypto { | namespace Crypto { | ||||||
|  | namespace Cipher { | ||||||
| 
 | 
 | ||||||
| template <typename T> |     template <typename T> | ||||||
| constexpr u32 get_key(T pt) |     constexpr u32 get_key(T pt) | ||||||
| { |     { | ||||||
|     return ((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]); |         return ((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]); | ||||||
| } |  | ||||||
| 
 |  | ||||||
| constexpr void swap_keys(u32* keys, size_t i, size_t j) |  | ||||||
| { |  | ||||||
|     u32 temp = keys[i]; |  | ||||||
|     keys[i] = keys[j]; |  | ||||||
|     keys[j] = temp; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| String AESCipherBlock::to_string() const |  | ||||||
| { |  | ||||||
|     StringBuilder builder; |  | ||||||
|     for (size_t i = 0; i < BLOCK_SIZE / 8; ++i) |  | ||||||
|         builder.appendf("%02x", m_data[i]); |  | ||||||
|     return builder.build(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| String AESCipherKey::to_string() const |  | ||||||
| { |  | ||||||
|     StringBuilder builder; |  | ||||||
|     for (size_t i = 0; i < (rounds() + 1) * 4; ++i) |  | ||||||
|         builder.appendf("%02x", m_rd_keys[i]); |  | ||||||
|     return builder.build(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AESCipherKey::expand_encrypt_key(const StringView& user_key, size_t bits) |  | ||||||
| { |  | ||||||
|     u32* round_key; |  | ||||||
|     u32 temp; |  | ||||||
|     size_t i { 0 }; |  | ||||||
| 
 |  | ||||||
|     ASSERT(!user_key.is_null()); |  | ||||||
|     ASSERT(is_valid_key_size(bits)); |  | ||||||
| 
 |  | ||||||
|     round_key = round_keys(); |  | ||||||
| 
 |  | ||||||
|     if (bits == 128) { |  | ||||||
|         m_rounds = 10; |  | ||||||
|     } else if (bits == 192) { |  | ||||||
|         m_rounds = 12; |  | ||||||
|     } else { |  | ||||||
|         m_rounds = 14; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     round_key[0] = get_key(user_key.substring_view(0, 4).characters_without_null_termination()); |     constexpr void swap_keys(u32* keys, size_t i, size_t j) | ||||||
|     round_key[1] = get_key(user_key.substring_view(4, 4).characters_without_null_termination()); |     { | ||||||
|     round_key[2] = get_key(user_key.substring_view(8, 4).characters_without_null_termination()); |         u32 temp = keys[i]; | ||||||
|     round_key[3] = get_key(user_key.substring_view(12, 4).characters_without_null_termination()); |         keys[i] = keys[j]; | ||||||
|     if (bits == 128) { |         keys[j] = temp; | ||||||
|         for (;;) { |     } | ||||||
|             temp = round_key[3]; | 
 | ||||||
|             // clang-format off
 |     String AESCipherBlock::to_string() const | ||||||
|  |     { | ||||||
|  |         StringBuilder builder; | ||||||
|  |         for (size_t i = 0; i < BLOCK_SIZE / 8; ++i) | ||||||
|  |             builder.appendf("%02x", m_data[i]); | ||||||
|  |         return builder.build(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     String AESCipherKey::to_string() const | ||||||
|  |     { | ||||||
|  |         StringBuilder builder; | ||||||
|  |         for (size_t i = 0; i < (rounds() + 1) * 4; ++i) | ||||||
|  |             builder.appendf("%02x", m_rd_keys[i]); | ||||||
|  |         return builder.build(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void AESCipherKey::expand_encrypt_key(const StringView& user_key, size_t bits) | ||||||
|  |     { | ||||||
|  |         u32* round_key; | ||||||
|  |         u32 temp; | ||||||
|  |         size_t i { 0 }; | ||||||
|  | 
 | ||||||
|  |         ASSERT(!user_key.is_null()); | ||||||
|  |         ASSERT(is_valid_key_size(bits)); | ||||||
|  | 
 | ||||||
|  |         round_key = round_keys(); | ||||||
|  | 
 | ||||||
|  |         if (bits == 128) { | ||||||
|  |             m_rounds = 10; | ||||||
|  |         } else if (bits == 192) { | ||||||
|  |             m_rounds = 12; | ||||||
|  |         } else { | ||||||
|  |             m_rounds = 14; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         round_key[0] = get_key(user_key.substring_view(0, 4).characters_without_null_termination()); | ||||||
|  |         round_key[1] = get_key(user_key.substring_view(4, 4).characters_without_null_termination()); | ||||||
|  |         round_key[2] = get_key(user_key.substring_view(8, 4).characters_without_null_termination()); | ||||||
|  |         round_key[3] = get_key(user_key.substring_view(12, 4).characters_without_null_termination()); | ||||||
|  |         if (bits == 128) { | ||||||
|  |             for (;;) { | ||||||
|  |                 temp = round_key[3]; | ||||||
|  |                 // clang-format off
 | ||||||
|             round_key[4] = round_key[0] ^ |             round_key[4] = round_key[0] ^ | ||||||
|                     (Tables::Encode2[(temp >> 16) & 0xff] & 0xff000000) ^ |                     (AESTables::Encode2[(temp >> 16) & 0xff] & 0xff000000) ^ | ||||||
|                     (Tables::Encode3[(temp >>  8) & 0xff] & 0x00ff0000) ^ |                     (AESTables::Encode3[(temp >>  8) & 0xff] & 0x00ff0000) ^ | ||||||
|                     (Tables::Encode0[(temp      ) & 0xff] & 0x0000ff00) ^ |                     (AESTables::Encode0[(temp      ) & 0xff] & 0x0000ff00) ^ | ||||||
|                     (Tables::Encode1[(temp >> 24)       ] & 0x000000ff) ^ Tables::RCON[i]; |                     (AESTables::Encode1[(temp >> 24)       ] & 0x000000ff) ^ AESTables::RCON[i]; | ||||||
|             // clang-format on
 |                 // clang-format on
 | ||||||
|             round_key[5] = round_key[1] ^ round_key[4]; |                 round_key[5] = round_key[1] ^ round_key[4]; | ||||||
|             round_key[6] = round_key[2] ^ round_key[5]; |                 round_key[6] = round_key[2] ^ round_key[5]; | ||||||
|             round_key[7] = round_key[3] ^ round_key[6]; |                 round_key[7] = round_key[3] ^ round_key[6]; | ||||||
|             ++i; |                 ++i; | ||||||
|             if (i == 10) |                 if (i == 10) | ||||||
|                 break; |                     break; | ||||||
|             round_key += 4; |                 round_key += 4; | ||||||
|  |             } | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     round_key[4] = get_key(user_key.substring_view(16, 4).characters_without_null_termination()); |         round_key[4] = get_key(user_key.substring_view(16, 4).characters_without_null_termination()); | ||||||
|     round_key[5] = get_key(user_key.substring_view(20, 4).characters_without_null_termination()); |         round_key[5] = get_key(user_key.substring_view(20, 4).characters_without_null_termination()); | ||||||
|     if (bits == 192) { |         if (bits == 192) { | ||||||
|         for (;;) { |             for (;;) { | ||||||
|             temp = round_key[5]; |                 temp = round_key[5]; | ||||||
|             // clang-format off
 |                 // clang-format off
 | ||||||
|             round_key[6] = round_key[0] ^ |             round_key[6] = round_key[0] ^ | ||||||
|                     (Tables::Encode2[(temp >> 16) & 0xff] & 0xff000000) ^ |                     (AESTables::Encode2[(temp >> 16) & 0xff] & 0xff000000) ^ | ||||||
|                     (Tables::Encode3[(temp >>  8) & 0xff] & 0x00ff0000) ^ |                     (AESTables::Encode3[(temp >>  8) & 0xff] & 0x00ff0000) ^ | ||||||
|                     (Tables::Encode0[(temp      ) & 0xff] & 0x0000ff00) ^ |                     (AESTables::Encode0[(temp      ) & 0xff] & 0x0000ff00) ^ | ||||||
|                     (Tables::Encode1[(temp >> 24)       ] & 0x000000ff) ^ Tables::RCON[i]; |                     (AESTables::Encode1[(temp >> 24)       ] & 0x000000ff) ^ AESTables::RCON[i]; | ||||||
|             // clang-format on
 |                 // clang-format on
 | ||||||
|             round_key[7] = round_key[1] ^ round_key[6]; |                 round_key[7] = round_key[1] ^ round_key[6]; | ||||||
|             round_key[8] = round_key[2] ^ round_key[7]; |                 round_key[8] = round_key[2] ^ round_key[7]; | ||||||
|             round_key[9] = round_key[3] ^ round_key[8]; |                 round_key[9] = round_key[3] ^ round_key[8]; | ||||||
| 
 | 
 | ||||||
|             ++i; |                 ++i; | ||||||
|             if (i == 8) |                 if (i == 8) | ||||||
|                 break; |                     break; | ||||||
| 
 | 
 | ||||||
|             round_key[10] = round_key[4] ^ round_key[9]; |                 round_key[10] = round_key[4] ^ round_key[9]; | ||||||
|             round_key[11] = round_key[5] ^ round_key[10]; |                 round_key[11] = round_key[5] ^ round_key[10]; | ||||||
| 
 | 
 | ||||||
|             round_key += 6; |                 round_key += 6; | ||||||
|  |             } | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     round_key[6] = get_key(user_key.substring_view(24, 4).characters_without_null_termination()); |         round_key[6] = get_key(user_key.substring_view(24, 4).characters_without_null_termination()); | ||||||
|     round_key[7] = get_key(user_key.substring_view(28, 4).characters_without_null_termination()); |         round_key[7] = get_key(user_key.substring_view(28, 4).characters_without_null_termination()); | ||||||
|     if (true) { // bits == 256
 |         if (true) { // bits == 256
 | ||||||
|         for (;;) { |             for (;;) { | ||||||
|             temp = round_key[7]; |                 temp = round_key[7]; | ||||||
|             // clang-format off
 |                 // clang-format off
 | ||||||
|             round_key[8] = round_key[0] ^ |             round_key[8] = round_key[0] ^ | ||||||
|                     (Tables::Encode2[(temp >> 16) & 0xff] & 0xff000000) ^ |                     (AESTables::Encode2[(temp >> 16) & 0xff] & 0xff000000) ^ | ||||||
|                     (Tables::Encode3[(temp >>  8) & 0xff] & 0x00ff0000) ^ |                     (AESTables::Encode3[(temp >>  8) & 0xff] & 0x00ff0000) ^ | ||||||
|                     (Tables::Encode0[(temp      ) & 0xff] & 0x0000ff00) ^ |                     (AESTables::Encode0[(temp      ) & 0xff] & 0x0000ff00) ^ | ||||||
|                     (Tables::Encode1[(temp >> 24)       ] & 0x000000ff) ^ Tables::RCON[i]; |                     (AESTables::Encode1[(temp >> 24)       ] & 0x000000ff) ^ AESTables::RCON[i]; | ||||||
|             // clang-format on
 |                 // clang-format on
 | ||||||
|             round_key[9] = round_key[1] ^ round_key[8]; |                 round_key[9] = round_key[1] ^ round_key[8]; | ||||||
|             round_key[10] = round_key[2] ^ round_key[9]; |                 round_key[10] = round_key[2] ^ round_key[9]; | ||||||
|             round_key[11] = round_key[3] ^ round_key[10]; |                 round_key[11] = round_key[3] ^ round_key[10]; | ||||||
| 
 | 
 | ||||||
|  |                 ++i; | ||||||
|  |                 if (i == 7) | ||||||
|  |                     break; | ||||||
|  | 
 | ||||||
|  |                 temp = round_key[11]; | ||||||
|  |                 // clang-format off
 | ||||||
|  |             round_key[12] = round_key[4] ^ | ||||||
|  |                     (AESTables::Encode2[(temp >> 24)       ] & 0xff000000) ^ | ||||||
|  |                     (AESTables::Encode3[(temp >> 16) & 0xff] & 0x00ff0000) ^ | ||||||
|  |                     (AESTables::Encode0[(temp >>  8) & 0xff] & 0x0000ff00) ^ | ||||||
|  |                     (AESTables::Encode1[(temp      ) & 0xff] & 0x000000ff) ; | ||||||
|  |                 // clang-format on
 | ||||||
|  |                 round_key[13] = round_key[5] ^ round_key[12]; | ||||||
|  |                 round_key[14] = round_key[6] ^ round_key[13]; | ||||||
|  |                 round_key[15] = round_key[7] ^ round_key[14]; | ||||||
|  | 
 | ||||||
|  |                 round_key += 8; | ||||||
|  |             } | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void AESCipherKey::expand_decrypt_key(const StringView& user_key, size_t bits) | ||||||
|  |     { | ||||||
|  |         u32* round_key; | ||||||
|  | 
 | ||||||
|  |         expand_encrypt_key(user_key, bits); | ||||||
|  | 
 | ||||||
|  |         round_key = round_keys(); | ||||||
|  | 
 | ||||||
|  |         // reorder round keys
 | ||||||
|  |         for (size_t i = 0, j = 4 * rounds(); i < j; i += 4, j -= 4) { | ||||||
|  |             swap_keys(round_key, i, j); | ||||||
|  |             swap_keys(round_key, i + 1, j + 1); | ||||||
|  |             swap_keys(round_key, i + 2, j + 2); | ||||||
|  |             swap_keys(round_key, i + 3, j + 3); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // apply inverse mix-column to middle rounds
 | ||||||
|  |         for (size_t i = 1; i < rounds(); ++i) { | ||||||
|  |             round_key += 4; | ||||||
|  |             // clang-format off
 | ||||||
|  |         round_key[0] = | ||||||
|  |                 AESTables::Decode0[AESTables::Encode1[(round_key[0] >> 24)       ] & 0xff] ^ | ||||||
|  |                 AESTables::Decode1[AESTables::Encode1[(round_key[0] >> 16) & 0xff] & 0xff] ^ | ||||||
|  |                 AESTables::Decode2[AESTables::Encode1[(round_key[0] >>  8) & 0xff] & 0xff] ^ | ||||||
|  |                 AESTables::Decode3[AESTables::Encode1[(round_key[0]      ) & 0xff] & 0xff] ; | ||||||
|  |         round_key[1] = | ||||||
|  |                 AESTables::Decode0[AESTables::Encode1[(round_key[1] >> 24)       ] & 0xff] ^ | ||||||
|  |                 AESTables::Decode1[AESTables::Encode1[(round_key[1] >> 16) & 0xff] & 0xff] ^ | ||||||
|  |                 AESTables::Decode2[AESTables::Encode1[(round_key[1] >>  8) & 0xff] & 0xff] ^ | ||||||
|  |                 AESTables::Decode3[AESTables::Encode1[(round_key[1]      ) & 0xff] & 0xff] ; | ||||||
|  |         round_key[2] = | ||||||
|  |                 AESTables::Decode0[AESTables::Encode1[(round_key[2] >> 24)       ] & 0xff] ^ | ||||||
|  |                 AESTables::Decode1[AESTables::Encode1[(round_key[2] >> 16) & 0xff] & 0xff] ^ | ||||||
|  |                 AESTables::Decode2[AESTables::Encode1[(round_key[2] >>  8) & 0xff] & 0xff] ^ | ||||||
|  |                 AESTables::Decode3[AESTables::Encode1[(round_key[2]      ) & 0xff] & 0xff] ; | ||||||
|  |         round_key[3] = | ||||||
|  |                 AESTables::Decode0[AESTables::Encode1[(round_key[3] >> 24)       ] & 0xff] ^ | ||||||
|  |                 AESTables::Decode1[AESTables::Encode1[(round_key[3] >> 16) & 0xff] & 0xff] ^ | ||||||
|  |                 AESTables::Decode2[AESTables::Encode1[(round_key[3] >>  8) & 0xff] & 0xff] ^ | ||||||
|  |                 AESTables::Decode3[AESTables::Encode1[(round_key[3]      ) & 0xff] & 0xff] ; | ||||||
|  |             // clang-format on
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void AESCipher::encrypt_block(const AESCipherBlock& in, AESCipherBlock& out) | ||||||
|  |     { | ||||||
|  |         u32 s0, s1, s2, s3, t0, t1, t2, t3; | ||||||
|  |         size_t r { 0 }; | ||||||
|  | 
 | ||||||
|  |         const auto& dec_key = key(); | ||||||
|  |         const auto* round_keys = dec_key.round_keys(); | ||||||
|  | 
 | ||||||
|  |         s0 = get_key(in.data().offset_pointer(0)) ^ round_keys[0]; | ||||||
|  |         s1 = get_key(in.data().offset_pointer(4)) ^ round_keys[1]; | ||||||
|  |         s2 = get_key(in.data().offset_pointer(8)) ^ round_keys[2]; | ||||||
|  |         s3 = get_key(in.data().offset_pointer(12)) ^ round_keys[3]; | ||||||
|  | 
 | ||||||
|  |         r = dec_key.rounds() >> 1; | ||||||
|  | 
 | ||||||
|  |         // apply the first |r - 1| rounds
 | ||||||
|  |         auto i { 0 }; | ||||||
|  |         for (;;) { | ||||||
|             ++i; |             ++i; | ||||||
|             if (i == 7) |             // clang-format off
 | ||||||
|  |         t0 = AESTables::Encode0[(s0 >> 24)       ] ^ | ||||||
|  |              AESTables::Encode1[(s1 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Encode2[(s2 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Encode3[(s3      ) & 0xff] ^ round_keys[4]; | ||||||
|  |         t1 = AESTables::Encode0[(s1 >> 24)       ] ^ | ||||||
|  |              AESTables::Encode1[(s2 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Encode2[(s3 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Encode3[(s0      ) & 0xff] ^ round_keys[5]; | ||||||
|  |         t2 = AESTables::Encode0[(s2 >> 24)       ] ^ | ||||||
|  |              AESTables::Encode1[(s3 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Encode2[(s0 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Encode3[(s1      ) & 0xff] ^ round_keys[6]; | ||||||
|  |         t3 = AESTables::Encode0[(s3 >> 24)       ] ^ | ||||||
|  |              AESTables::Encode1[(s0 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Encode2[(s1 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Encode3[(s2      ) & 0xff] ^ round_keys[7]; | ||||||
|  |             // clang-format on
 | ||||||
|  | 
 | ||||||
|  |             round_keys += 8; | ||||||
|  |             --r; | ||||||
|  |             ++i; | ||||||
|  |             if (r == 0) | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             temp = round_key[11]; |  | ||||||
|             // clang-format off
 |             // clang-format off
 | ||||||
|             round_key[12] = round_key[4] ^ |         s0 = AESTables::Encode0[(t0 >> 24)       ] ^ | ||||||
|                     (Tables::Encode2[(temp >> 24)       ] & 0xff000000) ^ |              AESTables::Encode1[(t1 >> 16) & 0xff] ^ | ||||||
|                     (Tables::Encode3[(temp >> 16) & 0xff] & 0x00ff0000) ^ |              AESTables::Encode2[(t2 >>  8) & 0xff] ^ | ||||||
|                     (Tables::Encode0[(temp >>  8) & 0xff] & 0x0000ff00) ^ |              AESTables::Encode3[(t3      ) & 0xff] ^ round_keys[0]; | ||||||
|                     (Tables::Encode1[(temp      ) & 0xff] & 0x000000ff) ; |         s1 = AESTables::Encode0[(t1 >> 24)       ] ^ | ||||||
|  |              AESTables::Encode1[(t2 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Encode2[(t3 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Encode3[(t0      ) & 0xff] ^ round_keys[1]; | ||||||
|  |         s2 = AESTables::Encode0[(t2 >> 24)       ] ^ | ||||||
|  |              AESTables::Encode1[(t3 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Encode2[(t0 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Encode3[(t1      ) & 0xff] ^ round_keys[2]; | ||||||
|  |         s3 = AESTables::Encode0[(t3 >> 24)       ] ^ | ||||||
|  |              AESTables::Encode1[(t0 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Encode2[(t1 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Encode3[(t2      ) & 0xff] ^ round_keys[3]; | ||||||
|             // clang-format on
 |             // clang-format on
 | ||||||
|             round_key[13] = round_key[5] ^ round_key[12]; |  | ||||||
|             round_key[14] = round_key[6] ^ round_key[13]; |  | ||||||
|             round_key[15] = round_key[7] ^ round_key[14]; |  | ||||||
| 
 |  | ||||||
|             round_key += 8; |  | ||||||
|         } |         } | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void AESCipherKey::expand_decrypt_key(const StringView& user_key, size_t bits) |         // apply the last round and put the encrypted data into out
 | ||||||
| { |  | ||||||
|     u32* round_key; |  | ||||||
| 
 |  | ||||||
|     expand_encrypt_key(user_key, bits); |  | ||||||
| 
 |  | ||||||
|     round_key = round_keys(); |  | ||||||
| 
 |  | ||||||
|     // reorder round keys
 |  | ||||||
|     for (size_t i = 0, j = 4 * rounds(); i < j; i += 4, j -= 4) { |  | ||||||
|         swap_keys(round_key, i, j); |  | ||||||
|         swap_keys(round_key, i + 1, j + 1); |  | ||||||
|         swap_keys(round_key, i + 2, j + 2); |  | ||||||
|         swap_keys(round_key, i + 3, j + 3); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // apply inverse mix-column to middle rounds
 |  | ||||||
|     for (size_t i = 1; i < rounds(); ++i) { |  | ||||||
|         round_key += 4; |  | ||||||
|         // clang-format off
 |         // clang-format off
 | ||||||
|         round_key[0] = |     s0 = (AESTables::Encode2[(t0 >> 24)       ] & 0xff000000) ^ | ||||||
|                 Tables::Decode0[Tables::Encode1[(round_key[0] >> 24)       ] & 0xff] ^ |          (AESTables::Encode3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ | ||||||
|                 Tables::Decode1[Tables::Encode1[(round_key[0] >> 16) & 0xff] & 0xff] ^ |          (AESTables::Encode0[(t2 >>  8) & 0xff] & 0x0000ff00) ^ | ||||||
|                 Tables::Decode2[Tables::Encode1[(round_key[0] >>  8) & 0xff] & 0xff] ^ |          (AESTables::Encode1[(t3      ) & 0xff] & 0x000000ff) ^ round_keys[0]; | ||||||
|                 Tables::Decode3[Tables::Encode1[(round_key[0]      ) & 0xff] & 0xff] ; |  | ||||||
|         round_key[1] = |  | ||||||
|                 Tables::Decode0[Tables::Encode1[(round_key[1] >> 24)       ] & 0xff] ^ |  | ||||||
|                 Tables::Decode1[Tables::Encode1[(round_key[1] >> 16) & 0xff] & 0xff] ^ |  | ||||||
|                 Tables::Decode2[Tables::Encode1[(round_key[1] >>  8) & 0xff] & 0xff] ^ |  | ||||||
|                 Tables::Decode3[Tables::Encode1[(round_key[1]      ) & 0xff] & 0xff] ; |  | ||||||
|         round_key[2] = |  | ||||||
|                 Tables::Decode0[Tables::Encode1[(round_key[2] >> 24)       ] & 0xff] ^ |  | ||||||
|                 Tables::Decode1[Tables::Encode1[(round_key[2] >> 16) & 0xff] & 0xff] ^ |  | ||||||
|                 Tables::Decode2[Tables::Encode1[(round_key[2] >>  8) & 0xff] & 0xff] ^ |  | ||||||
|                 Tables::Decode3[Tables::Encode1[(round_key[2]      ) & 0xff] & 0xff] ; |  | ||||||
|         round_key[3] = |  | ||||||
|                 Tables::Decode0[Tables::Encode1[(round_key[3] >> 24)       ] & 0xff] ^ |  | ||||||
|                 Tables::Decode1[Tables::Encode1[(round_key[3] >> 16) & 0xff] & 0xff] ^ |  | ||||||
|                 Tables::Decode2[Tables::Encode1[(round_key[3] >>  8) & 0xff] & 0xff] ^ |  | ||||||
|                 Tables::Decode3[Tables::Encode1[(round_key[3]      ) & 0xff] & 0xff] ; |  | ||||||
|         // clang-format on
 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AESCipher::encrypt_block(const AESCipherBlock& in, AESCipherBlock& out) |  | ||||||
| { |  | ||||||
|     u32 s0, s1, s2, s3, t0, t1, t2, t3; |  | ||||||
|     size_t r { 0 }; |  | ||||||
| 
 |  | ||||||
|     const auto& dec_key = key(); |  | ||||||
|     const auto* round_keys = dec_key.round_keys(); |  | ||||||
| 
 |  | ||||||
|     s0 = get_key(in.data().offset_pointer(0)) ^ round_keys[0]; |  | ||||||
|     s1 = get_key(in.data().offset_pointer(4)) ^ round_keys[1]; |  | ||||||
|     s2 = get_key(in.data().offset_pointer(8)) ^ round_keys[2]; |  | ||||||
|     s3 = get_key(in.data().offset_pointer(12)) ^ round_keys[3]; |  | ||||||
| 
 |  | ||||||
|     r = dec_key.rounds() >> 1; |  | ||||||
| 
 |  | ||||||
|     // apply the first |r - 1| rounds
 |  | ||||||
|     auto i { 0 }; |  | ||||||
|     for (;;) { |  | ||||||
|         ++i; |  | ||||||
|         // clang-format off
 |  | ||||||
|         t0 = Tables::Encode0[(s0 >> 24)       ] ^ |  | ||||||
|              Tables::Encode1[(s1 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Encode2[(s2 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Encode3[(s3      ) & 0xff] ^ round_keys[4]; |  | ||||||
|         t1 = Tables::Encode0[(s1 >> 24)       ] ^ |  | ||||||
|              Tables::Encode1[(s2 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Encode2[(s3 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Encode3[(s0      ) & 0xff] ^ round_keys[5]; |  | ||||||
|         t2 = Tables::Encode0[(s2 >> 24)       ] ^ |  | ||||||
|              Tables::Encode1[(s3 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Encode2[(s0 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Encode3[(s1      ) & 0xff] ^ round_keys[6]; |  | ||||||
|         t3 = Tables::Encode0[(s3 >> 24)       ] ^ |  | ||||||
|              Tables::Encode1[(s0 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Encode2[(s1 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Encode3[(s2      ) & 0xff] ^ round_keys[7]; |  | ||||||
|         // clang-format on
 |  | ||||||
| 
 |  | ||||||
|         round_keys += 8; |  | ||||||
|         --r; |  | ||||||
|         ++i; |  | ||||||
|         if (r == 0) |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         // clang-format off
 |  | ||||||
|         s0 = Tables::Encode0[(t0 >> 24)       ] ^ |  | ||||||
|              Tables::Encode1[(t1 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Encode2[(t2 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Encode3[(t3      ) & 0xff] ^ round_keys[0]; |  | ||||||
|         s1 = Tables::Encode0[(t1 >> 24)       ] ^ |  | ||||||
|              Tables::Encode1[(t2 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Encode2[(t3 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Encode3[(t0      ) & 0xff] ^ round_keys[1]; |  | ||||||
|         s2 = Tables::Encode0[(t2 >> 24)       ] ^ |  | ||||||
|              Tables::Encode1[(t3 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Encode2[(t0 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Encode3[(t1      ) & 0xff] ^ round_keys[2]; |  | ||||||
|         s3 = Tables::Encode0[(t3 >> 24)       ] ^ |  | ||||||
|              Tables::Encode1[(t0 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Encode2[(t1 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Encode3[(t2      ) & 0xff] ^ round_keys[3]; |  | ||||||
|         // clang-format on
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // apply the last round and put the encrypted data into out
 |  | ||||||
|     // clang-format off
 |  | ||||||
|     s0 = (Tables::Encode2[(t0 >> 24)       ] & 0xff000000) ^ |  | ||||||
|          (Tables::Encode3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ |  | ||||||
|          (Tables::Encode0[(t2 >>  8) & 0xff] & 0x0000ff00) ^ |  | ||||||
|          (Tables::Encode1[(t3      ) & 0xff] & 0x000000ff) ^ round_keys[0]; |  | ||||||
|     out.put(0, s0); |     out.put(0, s0); | ||||||
| 
 | 
 | ||||||
|     s1 = (Tables::Encode2[(t1 >> 24)       ] & 0xff000000) ^ |     s1 = (AESTables::Encode2[(t1 >> 24)       ] & 0xff000000) ^ | ||||||
|          (Tables::Encode3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ |          (AESTables::Encode3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ | ||||||
|          (Tables::Encode0[(t3 >>  8) & 0xff] & 0x0000ff00) ^ |          (AESTables::Encode0[(t3 >>  8) & 0xff] & 0x0000ff00) ^ | ||||||
|          (Tables::Encode1[(t0      ) & 0xff] & 0x000000ff) ^ round_keys[1]; |          (AESTables::Encode1[(t0      ) & 0xff] & 0x000000ff) ^ round_keys[1]; | ||||||
|     out.put(4, s1); |     out.put(4, s1); | ||||||
| 
 | 
 | ||||||
|     s2 = (Tables::Encode2[(t2 >> 24)       ] & 0xff000000) ^ |     s2 = (AESTables::Encode2[(t2 >> 24)       ] & 0xff000000) ^ | ||||||
|          (Tables::Encode3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ |          (AESTables::Encode3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ | ||||||
|          (Tables::Encode0[(t0 >>  8) & 0xff] & 0x0000ff00) ^ |          (AESTables::Encode0[(t0 >>  8) & 0xff] & 0x0000ff00) ^ | ||||||
|          (Tables::Encode1[(t1      ) & 0xff] & 0x000000ff) ^ round_keys[2]; |          (AESTables::Encode1[(t1      ) & 0xff] & 0x000000ff) ^ round_keys[2]; | ||||||
|     out.put(8, s2); |     out.put(8, s2); | ||||||
| 
 | 
 | ||||||
|     s3 = (Tables::Encode2[(t3 >> 24)       ] & 0xff000000) ^ |     s3 = (AESTables::Encode2[(t3 >> 24)       ] & 0xff000000) ^ | ||||||
|          (Tables::Encode3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ |          (AESTables::Encode3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ | ||||||
|          (Tables::Encode0[(t1 >>  8) & 0xff] & 0x0000ff00) ^ |          (AESTables::Encode0[(t1 >>  8) & 0xff] & 0x0000ff00) ^ | ||||||
|          (Tables::Encode1[(t2      ) & 0xff] & 0x000000ff) ^ round_keys[3]; |          (AESTables::Encode1[(t2      ) & 0xff] & 0x000000ff) ^ round_keys[3]; | ||||||
|     out.put(12, s3); |     out.put(12, s3); | ||||||
|     // clang-format on
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AESCipher::decrypt_block(const AESCipherBlock& in, AESCipherBlock& out) |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
|     u32 s0, s1, s2, s3, t0, t1, t2, t3; |  | ||||||
|     size_t r { 0 }; |  | ||||||
| 
 |  | ||||||
|     const auto& dec_key = key(); |  | ||||||
|     const auto* round_keys = dec_key.round_keys(); |  | ||||||
| 
 |  | ||||||
|     s0 = get_key(in.data().offset_pointer(0)) ^ round_keys[0]; |  | ||||||
|     s1 = get_key(in.data().offset_pointer(4)) ^ round_keys[1]; |  | ||||||
|     s2 = get_key(in.data().offset_pointer(8)) ^ round_keys[2]; |  | ||||||
|     s3 = get_key(in.data().offset_pointer(12)) ^ round_keys[3]; |  | ||||||
| 
 |  | ||||||
|     r = dec_key.rounds() >> 1; |  | ||||||
| 
 |  | ||||||
|     // apply the first |r - 1| rounds
 |  | ||||||
|     for (;;) { |  | ||||||
|         // clang-format off
 |  | ||||||
|         t0 = Tables::Decode0[(s0 >> 24)       ] ^ |  | ||||||
|              Tables::Decode1[(s3 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Decode2[(s2 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Decode3[(s1      ) & 0xff] ^ round_keys[4]; |  | ||||||
|         t1 = Tables::Decode0[(s1 >> 24)       ] ^ |  | ||||||
|              Tables::Decode1[(s0 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Decode2[(s3 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Decode3[(s2      ) & 0xff] ^ round_keys[5]; |  | ||||||
|         t2 = Tables::Decode0[(s2 >> 24)       ] ^ |  | ||||||
|              Tables::Decode1[(s1 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Decode2[(s0 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Decode3[(s3      ) & 0xff] ^ round_keys[6]; |  | ||||||
|         t3 = Tables::Decode0[(s3 >> 24)       ] ^ |  | ||||||
|              Tables::Decode1[(s2 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Decode2[(s1 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Decode3[(s0      ) & 0xff] ^ round_keys[7]; |  | ||||||
|         // clang-format on
 |  | ||||||
| 
 |  | ||||||
|         round_keys += 8; |  | ||||||
|         --r; |  | ||||||
|         if (r == 0) |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         // clang-format off
 |  | ||||||
|         s0 = Tables::Decode0[(t0 >> 24)       ] ^ |  | ||||||
|              Tables::Decode1[(t3 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Decode2[(t2 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Decode3[(t1      ) & 0xff] ^ round_keys[0]; |  | ||||||
|         s1 = Tables::Decode0[(t1 >> 24)       ] ^ |  | ||||||
|              Tables::Decode1[(t0 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Decode2[(t3 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Decode3[(t2      ) & 0xff] ^ round_keys[1]; |  | ||||||
|         s2 = Tables::Decode0[(t2 >> 24)       ] ^ |  | ||||||
|              Tables::Decode1[(t1 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Decode2[(t0 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Decode3[(t3      ) & 0xff] ^ round_keys[2]; |  | ||||||
|         s3 = Tables::Decode0[(t3 >> 24)       ] ^ |  | ||||||
|              Tables::Decode1[(t2 >> 16) & 0xff] ^ |  | ||||||
|              Tables::Decode2[(t1 >>  8) & 0xff] ^ |  | ||||||
|              Tables::Decode3[(t0      ) & 0xff] ^ round_keys[3]; |  | ||||||
|         // clang-format on
 |         // clang-format on
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // apply the last round and put the decrypted data into out
 |     void AESCipher::decrypt_block(const AESCipherBlock& in, AESCipherBlock& out) | ||||||
|     // clang-format off
 |     { | ||||||
|     s0 = ((u32)Tables::Decode4[(t0 >> 24)       ] << 24) ^ | 
 | ||||||
|          ((u32)Tables::Decode4[(t3 >> 16) & 0xff] << 16) ^ |         u32 s0, s1, s2, s3, t0, t1, t2, t3; | ||||||
|          ((u32)Tables::Decode4[(t2 >>  8) & 0xff] <<  8) ^ |         size_t r { 0 }; | ||||||
|          ((u32)Tables::Decode4[(t1      ) & 0xff]      ) ^ round_keys[0]; | 
 | ||||||
|  |         const auto& dec_key = key(); | ||||||
|  |         const auto* round_keys = dec_key.round_keys(); | ||||||
|  | 
 | ||||||
|  |         s0 = get_key(in.data().offset_pointer(0)) ^ round_keys[0]; | ||||||
|  |         s1 = get_key(in.data().offset_pointer(4)) ^ round_keys[1]; | ||||||
|  |         s2 = get_key(in.data().offset_pointer(8)) ^ round_keys[2]; | ||||||
|  |         s3 = get_key(in.data().offset_pointer(12)) ^ round_keys[3]; | ||||||
|  | 
 | ||||||
|  |         r = dec_key.rounds() >> 1; | ||||||
|  | 
 | ||||||
|  |         // apply the first |r - 1| rounds
 | ||||||
|  |         for (;;) { | ||||||
|  |             // clang-format off
 | ||||||
|  |         t0 = AESTables::Decode0[(s0 >> 24)       ] ^ | ||||||
|  |              AESTables::Decode1[(s3 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Decode2[(s2 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Decode3[(s1      ) & 0xff] ^ round_keys[4]; | ||||||
|  |         t1 = AESTables::Decode0[(s1 >> 24)       ] ^ | ||||||
|  |              AESTables::Decode1[(s0 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Decode2[(s3 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Decode3[(s2      ) & 0xff] ^ round_keys[5]; | ||||||
|  |         t2 = AESTables::Decode0[(s2 >> 24)       ] ^ | ||||||
|  |              AESTables::Decode1[(s1 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Decode2[(s0 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Decode3[(s3      ) & 0xff] ^ round_keys[6]; | ||||||
|  |         t3 = AESTables::Decode0[(s3 >> 24)       ] ^ | ||||||
|  |              AESTables::Decode1[(s2 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Decode2[(s1 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Decode3[(s0      ) & 0xff] ^ round_keys[7]; | ||||||
|  |             // clang-format on
 | ||||||
|  | 
 | ||||||
|  |             round_keys += 8; | ||||||
|  |             --r; | ||||||
|  |             if (r == 0) | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             // clang-format off
 | ||||||
|  |         s0 = AESTables::Decode0[(t0 >> 24)       ] ^ | ||||||
|  |              AESTables::Decode1[(t3 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Decode2[(t2 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Decode3[(t1      ) & 0xff] ^ round_keys[0]; | ||||||
|  |         s1 = AESTables::Decode0[(t1 >> 24)       ] ^ | ||||||
|  |              AESTables::Decode1[(t0 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Decode2[(t3 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Decode3[(t2      ) & 0xff] ^ round_keys[1]; | ||||||
|  |         s2 = AESTables::Decode0[(t2 >> 24)       ] ^ | ||||||
|  |              AESTables::Decode1[(t1 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Decode2[(t0 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Decode3[(t3      ) & 0xff] ^ round_keys[2]; | ||||||
|  |         s3 = AESTables::Decode0[(t3 >> 24)       ] ^ | ||||||
|  |              AESTables::Decode1[(t2 >> 16) & 0xff] ^ | ||||||
|  |              AESTables::Decode2[(t1 >>  8) & 0xff] ^ | ||||||
|  |              AESTables::Decode3[(t0      ) & 0xff] ^ round_keys[3]; | ||||||
|  |             // clang-format on
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // apply the last round and put the decrypted data into out
 | ||||||
|  |         // clang-format off
 | ||||||
|  |     s0 = ((u32)AESTables::Decode4[(t0 >> 24)       ] << 24) ^ | ||||||
|  |          ((u32)AESTables::Decode4[(t3 >> 16) & 0xff] << 16) ^ | ||||||
|  |          ((u32)AESTables::Decode4[(t2 >>  8) & 0xff] <<  8) ^ | ||||||
|  |          ((u32)AESTables::Decode4[(t1      ) & 0xff]      ) ^ round_keys[0]; | ||||||
|     out.put(0, s0); |     out.put(0, s0); | ||||||
| 
 | 
 | ||||||
|     s1 = ((u32)Tables::Decode4[(t1 >> 24)       ] << 24) ^ |     s1 = ((u32)AESTables::Decode4[(t1 >> 24)       ] << 24) ^ | ||||||
|          ((u32)Tables::Decode4[(t0 >> 16) & 0xff] << 16) ^ |          ((u32)AESTables::Decode4[(t0 >> 16) & 0xff] << 16) ^ | ||||||
|          ((u32)Tables::Decode4[(t3 >>  8) & 0xff] <<  8) ^ |          ((u32)AESTables::Decode4[(t3 >>  8) & 0xff] <<  8) ^ | ||||||
|          ((u32)Tables::Decode4[(t2      ) & 0xff]      ) ^ round_keys[1]; |          ((u32)AESTables::Decode4[(t2      ) & 0xff]      ) ^ round_keys[1]; | ||||||
|     out.put(4, s1); |     out.put(4, s1); | ||||||
| 
 | 
 | ||||||
|     s2 = ((u32)Tables::Decode4[(t2 >> 24)       ] << 24) ^ |     s2 = ((u32)AESTables::Decode4[(t2 >> 24)       ] << 24) ^ | ||||||
|          ((u32)Tables::Decode4[(t1 >> 16) & 0xff] << 16) ^ |          ((u32)AESTables::Decode4[(t1 >> 16) & 0xff] << 16) ^ | ||||||
|          ((u32)Tables::Decode4[(t0 >>  8) & 0xff] <<  8) ^ |          ((u32)AESTables::Decode4[(t0 >>  8) & 0xff] <<  8) ^ | ||||||
|          ((u32)Tables::Decode4[(t3      ) & 0xff]      ) ^ round_keys[2]; |          ((u32)AESTables::Decode4[(t3      ) & 0xff]      ) ^ round_keys[2]; | ||||||
|     out.put(8, s2); |     out.put(8, s2); | ||||||
| 
 | 
 | ||||||
|     s3 = ((u32)Tables::Decode4[(t3 >> 24)       ] << 24) ^ |     s3 = ((u32)AESTables::Decode4[(t3 >> 24)       ] << 24) ^ | ||||||
|          ((u32)Tables::Decode4[(t2 >> 16) & 0xff] << 16) ^ |          ((u32)AESTables::Decode4[(t2 >> 16) & 0xff] << 16) ^ | ||||||
|          ((u32)Tables::Decode4[(t1 >>  8) & 0xff] <<  8) ^ |          ((u32)AESTables::Decode4[(t1 >>  8) & 0xff] <<  8) ^ | ||||||
|          ((u32)Tables::Decode4[(t0      ) & 0xff]      ) ^ round_keys[3]; |          ((u32)AESTables::Decode4[(t0      ) & 0xff]      ) ^ round_keys[3]; | ||||||
|     out.put(12, s3); |     out.put(12, s3); | ||||||
|     // clang-format on
 |         // clang-format on
 | ||||||
| } |     } | ||||||
| 
 | 
 | ||||||
| void AESCipherBlock::overwrite(const ByteBuffer& buffer) |     void AESCipherBlock::overwrite(const ByteBuffer& buffer) | ||||||
| { |     { | ||||||
|     overwrite(buffer.data(), buffer.size()); |         overwrite(buffer.data(), buffer.size()); | ||||||
| } |     } | ||||||
| 
 | 
 | ||||||
| void AESCipherBlock::overwrite(const u8* data, size_t length) |     void AESCipherBlock::overwrite(const u8* data, size_t length) | ||||||
| { |     { | ||||||
|     ASSERT(length <= m_data.size()); |         ASSERT(length <= m_data.size()); | ||||||
|     m_data.overwrite(0, data, length); |         m_data.overwrite(0, data, length); | ||||||
|     if (length < m_data.size()) { |         if (length < m_data.size()) { | ||||||
|         switch (padding_mode()) { |             switch (padding_mode()) { | ||||||
|         case PaddingMode::Null: |             case PaddingMode::Null: | ||||||
|             // fill with zeros
 |                 // fill with zeros
 | ||||||
|             __builtin_memset(m_data.data() + length, 0, m_data.size() - length); |                 __builtin_memset(m_data.data() + length, 0, m_data.size() - length); | ||||||
|             break; |                 break; | ||||||
|         case PaddingMode::CMS: |             case PaddingMode::CMS: | ||||||
|             // fill with the length of the padding bytes
 |                 // fill with the length of the padding bytes
 | ||||||
|             __builtin_memset(m_data.data() + length, m_data.size() - length, m_data.size() - length); |                 __builtin_memset(m_data.data() + length, m_data.size() - length, m_data.size() - length); | ||||||
|             break; |                 break; | ||||||
|         default: |             default: | ||||||
|             // FIXME: We should handle the rest of the common padding modes
 |                 // FIXME: We should handle the rest of the common padding modes
 | ||||||
|             ASSERT_NOT_REACHED(); |                 ASSERT_NOT_REACHED(); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -28,109 +28,110 @@ | ||||||
| 
 | 
 | ||||||
| #include <AK/ByteBuffer.h> | #include <AK/ByteBuffer.h> | ||||||
| #include <AK/Optional.h> | #include <AK/Optional.h> | ||||||
| #include <AK/RefPtr.h> |  | ||||||
| #include <AK/Types.h> | #include <AK/Types.h> | ||||||
| 
 | 
 | ||||||
| namespace Crypto { | namespace Crypto { | ||||||
|  | namespace Cipher { | ||||||
| 
 | 
 | ||||||
| enum class Intent { |     enum class Intent { | ||||||
|     Encryption, |         Encryption, | ||||||
|     Decryption, |         Decryption, | ||||||
| }; |     }; | ||||||
| 
 | 
 | ||||||
| enum class PaddingMode { |     enum class PaddingMode { | ||||||
|     CMS, // RFC 1423
 |         CMS, // RFC 1423
 | ||||||
|     Null, |         Null, | ||||||
|     // FIXME: We do not implement these yet
 |         // FIXME: We do not implement these yet
 | ||||||
|     Bit, |         Bit, | ||||||
|     Random, |         Random, | ||||||
|     Space, |         Space, | ||||||
|     ZeroLength, |         ZeroLength, | ||||||
| }; |     }; | ||||||
| 
 | 
 | ||||||
| template <typename B, typename T> |     template <typename B, typename T> | ||||||
| class Cipher; |     class Cipher; | ||||||
| 
 | 
 | ||||||
| struct CipherBlock { |     struct CipherBlock { | ||||||
| public: |     public: | ||||||
|     explicit CipherBlock(PaddingMode mode) |         explicit CipherBlock(PaddingMode mode) | ||||||
|         : m_padding_mode(mode) |             : m_padding_mode(mode) | ||||||
|     { |         { | ||||||
|     } |         } | ||||||
| 
 | 
 | ||||||
|     static size_t block_size() { ASSERT_NOT_REACHED(); } |         static size_t block_size() { ASSERT_NOT_REACHED(); } | ||||||
| 
 | 
 | ||||||
|     virtual ByteBuffer get() const = 0; |         virtual ByteBuffer get() const = 0; | ||||||
|     virtual const ByteBuffer& data() const = 0; |         virtual const ByteBuffer& data() const = 0; | ||||||
| 
 | 
 | ||||||
|     virtual void overwrite(const ByteBuffer&) = 0; |         virtual void overwrite(const ByteBuffer&) = 0; | ||||||
|     virtual void overwrite(const u8*, size_t) = 0; |         virtual void overwrite(const u8*, size_t) = 0; | ||||||
| 
 | 
 | ||||||
|     virtual void apply_initialization_vector(const u8* ivec) = 0; |         virtual void apply_initialization_vector(const u8* ivec) = 0; | ||||||
| 
 | 
 | ||||||
|     PaddingMode padding_mode() const { return m_padding_mode; } |         PaddingMode padding_mode() const { return m_padding_mode; } | ||||||
| 
 | 
 | ||||||
|     template <typename T> |         template <typename T> | ||||||
|     void put(size_t offset, T value) |         void put(size_t offset, T value) | ||||||
|     { |         { | ||||||
|         ASSERT(offset + sizeof(T) <= data().size()); |             ASSERT(offset + sizeof(T) <= data().size()); | ||||||
|         auto* ptr = data().data() + offset; |             auto* ptr = data().data() + offset; | ||||||
|         auto index { 0 }; |             auto index { 0 }; | ||||||
| 
 | 
 | ||||||
|         ASSERT(sizeof(T) <= 4); |             ASSERT(sizeof(T) <= 4); | ||||||
| 
 | 
 | ||||||
|         if constexpr (sizeof(T) > 3) |             if constexpr (sizeof(T) > 3) | ||||||
|             ptr[index++] = (u8)(value >> 24); |                 ptr[index++] = (u8)(value >> 24); | ||||||
| 
 | 
 | ||||||
|         if constexpr (sizeof(T) > 2) |             if constexpr (sizeof(T) > 2) | ||||||
|             ptr[index++] = (u8)(value >> 16); |                 ptr[index++] = (u8)(value >> 16); | ||||||
| 
 | 
 | ||||||
|         if constexpr (sizeof(T) > 1) |             if constexpr (sizeof(T) > 1) | ||||||
|             ptr[index++] = (u8)(value >> 8); |                 ptr[index++] = (u8)(value >> 8); | ||||||
| 
 | 
 | ||||||
|         ptr[index] = (u8)value; |             ptr[index] = (u8)value; | ||||||
|     } |         } | ||||||
| 
 | 
 | ||||||
| private: |     private: | ||||||
|     virtual ByteBuffer& data() = 0; |         virtual ByteBuffer& data() = 0; | ||||||
|     PaddingMode m_padding_mode; |         PaddingMode m_padding_mode; | ||||||
| }; |     }; | ||||||
| 
 | 
 | ||||||
| struct CipherKey { |     struct CipherKey { | ||||||
|     virtual ByteBuffer data() const = 0; |         virtual ByteBuffer data() const = 0; | ||||||
|     static bool is_valid_key_size(size_t) { return false; }; |         static bool is_valid_key_size(size_t) { return false; }; | ||||||
| 
 | 
 | ||||||
|     virtual ~CipherKey() { } |         virtual ~CipherKey() { } | ||||||
| 
 | 
 | ||||||
| protected: |     protected: | ||||||
|     virtual void expand_encrypt_key(const ByteBuffer& user_key, size_t bits) = 0; |         virtual void expand_encrypt_key(const ByteBuffer& user_key, size_t bits) = 0; | ||||||
|     virtual void expand_decrypt_key(const ByteBuffer& user_key, size_t bits) = 0; |         virtual void expand_decrypt_key(const ByteBuffer& user_key, size_t bits) = 0; | ||||||
|     size_t bits { 0 }; |         size_t bits { 0 }; | ||||||
| }; |     }; | ||||||
| 
 | 
 | ||||||
| template <typename KeyT = CipherKey, typename BlockT = CipherBlock> |     template <typename KeyT = CipherKey, typename BlockT = CipherBlock> | ||||||
| class Cipher { |     class Cipher { | ||||||
| public: |     public: | ||||||
|     using KeyType = KeyT; |         using KeyType = KeyT; | ||||||
|     using BlockType = BlockT; |         using BlockType = BlockT; | ||||||
| 
 | 
 | ||||||
|     explicit Cipher<KeyT, BlockT>(PaddingMode mode) |         explicit Cipher<KeyT, BlockT>(PaddingMode mode) | ||||||
|         : m_padding_mode(mode) |             : m_padding_mode(mode) | ||||||
|     { |         { | ||||||
|     } |         } | ||||||
| 
 | 
 | ||||||
|     virtual const KeyType& key() const = 0; |         virtual const KeyType& key() const = 0; | ||||||
|     virtual KeyType& key() = 0; |         virtual KeyType& key() = 0; | ||||||
| 
 | 
 | ||||||
|     static size_t block_size() { return BlockType::block_size(); } |         static size_t block_size() { return BlockType::block_size(); } | ||||||
| 
 | 
 | ||||||
|     PaddingMode padding_mode() const { return m_padding_mode; } |         PaddingMode padding_mode() const { return m_padding_mode; } | ||||||
| 
 | 
 | ||||||
|     virtual void encrypt_block(const BlockType& in, BlockType& out) = 0; |         virtual void encrypt_block(const BlockType& in, BlockType& out) = 0; | ||||||
|     virtual void decrypt_block(const BlockType& in, BlockType& out) = 0; |         virtual void decrypt_block(const BlockType& in, BlockType& out) = 0; | ||||||
| 
 | 
 | ||||||
| private: |     private: | ||||||
|     PaddingMode m_padding_mode { PaddingMode::CMS }; |         PaddingMode m_padding_mode; | ||||||
| }; |     }; | ||||||
| } | } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -29,86 +29,89 @@ | ||||||
| #include <LibCrypto/Cipher/Mode/Mode.h> | #include <LibCrypto/Cipher/Mode/Mode.h> | ||||||
| 
 | 
 | ||||||
| namespace Crypto { | namespace Crypto { | ||||||
|  | namespace Cipher { | ||||||
| 
 | 
 | ||||||
| template <typename T> |     template <typename T> | ||||||
| class CBC : public Mode<T> { |     class CBC : public Mode<T> { | ||||||
| public: |     public: | ||||||
|     template <typename... Args> |         template <typename... Args> | ||||||
|     explicit constexpr CBC<T>(Args... args) |         explicit constexpr CBC<T>(Args... args) | ||||||
|         : Mode<T>(args...) |             : Mode<T>(args...) | ||||||
|     { |         { | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     virtual Optional<ByteBuffer> encrypt(const ByteBuffer& in, ByteBuffer& out, Optional<ByteBuffer> ivec = {}) override |  | ||||||
|     { |  | ||||||
|         auto length = in.size(); |  | ||||||
|         if (length == 0) |  | ||||||
|             return {}; |  | ||||||
| 
 |  | ||||||
|         auto& cipher = this->cipher(); |  | ||||||
| 
 |  | ||||||
|         // FIXME: We should have two of these encrypt/decrypt functions that
 |  | ||||||
|         //        we SFINAE out based on whether the Cipher mode needs an ivec
 |  | ||||||
|         ASSERT(ivec.has_value()); |  | ||||||
|         const auto* iv = ivec.value().data(); |  | ||||||
| 
 |  | ||||||
|         typename T::BlockType block { cipher.padding_mode() }; |  | ||||||
|         size_t offset { 0 }; |  | ||||||
|         auto block_size = cipher.block_size(); |  | ||||||
| 
 |  | ||||||
|         while (length >= block_size) { |  | ||||||
|             block.overwrite(in.slice_view(offset, block_size)); |  | ||||||
|             block.apply_initialization_vector(iv); |  | ||||||
|             cipher.encrypt_block(block, block); |  | ||||||
|             out.overwrite(offset, block.get().data(), block_size); |  | ||||||
|             iv = out.offset_pointer(offset); |  | ||||||
|             length -= block_size; |  | ||||||
|             offset += block_size; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (length > 0) { |         virtual Optional<ByteBuffer> encrypt(const ByteBuffer& in, ByteBuffer& out, Optional<ByteBuffer> ivec = {}) override | ||||||
|             block.overwrite(in.slice_view(offset, length)); |         { | ||||||
|             block.apply_initialization_vector(iv); |             auto length = in.size(); | ||||||
|             cipher.encrypt_block(block, block); |             if (length == 0) | ||||||
|             out.overwrite(offset, block.get().data(), block_size); |                 return {}; | ||||||
|             iv = out.offset_pointer(offset); | 
 | ||||||
|  |             auto& cipher = this->cipher(); | ||||||
|  | 
 | ||||||
|  |             // FIXME: We should have two of these encrypt/decrypt functions that
 | ||||||
|  |             //        we SFINAE out based on whether the Cipher mode needs an ivec
 | ||||||
|  |             ASSERT(ivec.has_value()); | ||||||
|  |             const auto* iv = ivec.value().data(); | ||||||
|  | 
 | ||||||
|  |             typename T::BlockType block { cipher.padding_mode() }; | ||||||
|  |             size_t offset { 0 }; | ||||||
|  |             auto block_size = cipher.block_size(); | ||||||
|  | 
 | ||||||
|  |             while (length >= block_size) { | ||||||
|  |                 block.overwrite(in.slice_view(offset, block_size)); | ||||||
|  |                 block.apply_initialization_vector(iv); | ||||||
|  |                 cipher.encrypt_block(block, block); | ||||||
|  |                 out.overwrite(offset, block.get().data(), block_size); | ||||||
|  |                 iv = out.offset_pointer(offset); | ||||||
|  |                 length -= block_size; | ||||||
|  |                 offset += block_size; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (length > 0) { | ||||||
|  |                 block.overwrite(in.slice_view(offset, length)); | ||||||
|  |                 block.apply_initialization_vector(iv); | ||||||
|  |                 cipher.encrypt_block(block, block); | ||||||
|  |                 out.overwrite(offset, block.get().data(), block_size); | ||||||
|  |                 iv = out.offset_pointer(offset); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return ByteBuffer::copy(iv, block_size); | ||||||
|         } |         } | ||||||
|  |         virtual void decrypt(const ByteBuffer& in, ByteBuffer& out, Optional<ByteBuffer> ivec = {}) override | ||||||
|  |         { | ||||||
|  |             auto length = in.size(); | ||||||
|  |             if (length == 0) | ||||||
|  |                 return; | ||||||
| 
 | 
 | ||||||
|         return ByteBuffer::copy(iv, block_size); |             auto& cipher = this->cipher(); | ||||||
|     } |  | ||||||
|     virtual void decrypt(const ByteBuffer& in, ByteBuffer& out, Optional<ByteBuffer> ivec = {}) override |  | ||||||
|     { |  | ||||||
|         auto length = in.size(); |  | ||||||
|         if (length == 0) |  | ||||||
|             return; |  | ||||||
| 
 | 
 | ||||||
|         auto& cipher = this->cipher(); |             ASSERT(ivec.has_value()); | ||||||
|  |             const auto* iv = ivec.value().data(); | ||||||
| 
 | 
 | ||||||
|         ASSERT(ivec.has_value()); |             auto block_size = cipher.block_size(); | ||||||
|         const auto* iv = ivec.value().data(); |  | ||||||
| 
 | 
 | ||||||
|         auto block_size = cipher.block_size(); |             // if the data is not aligned, it's not correct encrypted data
 | ||||||
|  |             // FIXME (ponder): Should we simply decrypt as much as we can?
 | ||||||
|  |             ASSERT(length % block_size == 0); | ||||||
| 
 | 
 | ||||||
|         // if the data is not aligned, it's not correct encrypted data
 |             typename T::BlockType block { cipher.padding_mode() }; | ||||||
|         // FIXME (ponder): Should we simply decrypt as much as we can?
 |             size_t offset { 0 }; | ||||||
|         ASSERT(length % block_size == 0); |  | ||||||
| 
 | 
 | ||||||
|         typename T::BlockType block { cipher.padding_mode() }; |             while (length > 0) { | ||||||
|         size_t offset { 0 }; |                 auto* slice = in.offset_pointer(offset); | ||||||
| 
 |                 block.overwrite(slice, block_size); | ||||||
|         while (length > 0) { |                 cipher.decrypt_block(block, block); | ||||||
|             auto* slice = in.offset_pointer(offset); |                 block.apply_initialization_vector(iv); | ||||||
|             block.overwrite(slice, block_size); |                 auto decrypted = block.get(); | ||||||
|             cipher.decrypt_block(block, block); |                 out.overwrite(offset, decrypted.data(), decrypted.size()); | ||||||
|             block.apply_initialization_vector(iv); |                 iv = slice; | ||||||
|             auto decrypted = block.get(); |                 length -= block_size; | ||||||
|             out.overwrite(offset, decrypted.data(), decrypted.size()); |                 offset += block_size; | ||||||
|             iv = slice; |             } | ||||||
|             length -= block_size; |             this->prune_padding(out); | ||||||
|             offset += block_size; |  | ||||||
|         } |         } | ||||||
|         this->prune_padding(out); |     }; | ||||||
|     } | 
 | ||||||
| }; | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -30,68 +30,71 @@ | ||||||
| #include <LibCrypto/Cipher/Cipher.h> | #include <LibCrypto/Cipher/Cipher.h> | ||||||
| 
 | 
 | ||||||
| namespace Crypto { | namespace Crypto { | ||||||
|  | namespace Cipher { | ||||||
| 
 | 
 | ||||||
| template <typename T> |     template <typename T> | ||||||
| class Mode { |     class Mode { | ||||||
| public: |     public: | ||||||
|     // FIXME: Somehow communicate that encrypt returns the last initialization vector (if the mode supports it)
 |         // FIXME: Somehow communicate that encrypt returns the last initialization vector (if the mode supports it)
 | ||||||
|     virtual Optional<ByteBuffer> encrypt(const ByteBuffer& in, ByteBuffer& out, Optional<ByteBuffer> ivec = {}) = 0; |         virtual Optional<ByteBuffer> encrypt(const ByteBuffer& in, ByteBuffer& out, Optional<ByteBuffer> ivec = {}) = 0; | ||||||
|     virtual void decrypt(const ByteBuffer& in, ByteBuffer& out, Optional<ByteBuffer> ivec = {}) = 0; |         virtual void decrypt(const ByteBuffer& in, ByteBuffer& out, Optional<ByteBuffer> ivec = {}) = 0; | ||||||
| 
 | 
 | ||||||
|     const T& cipher() const { return m_cipher; } |         const T& cipher() const { return m_cipher; } | ||||||
| 
 | 
 | ||||||
|     ByteBuffer create_aligned_buffer(size_t input_size) const |         ByteBuffer create_aligned_buffer(size_t input_size) const | ||||||
|     { |         { | ||||||
|         size_t remainder = (input_size + T::block_size()) % T::block_size(); |             size_t remainder = (input_size + T::block_size()) % T::block_size(); | ||||||
|         if (remainder == 0) |             if (remainder == 0) | ||||||
|             return ByteBuffer::create_uninitialized(input_size); |                 return ByteBuffer::create_uninitialized(input_size); | ||||||
|         else |             else | ||||||
|             return ByteBuffer::create_uninitialized(input_size + T::block_size() - remainder); |                 return ByteBuffer::create_uninitialized(input_size + T::block_size() - remainder); | ||||||
|     } |         } | ||||||
| 
 | 
 | ||||||
| protected: |     protected: | ||||||
|     T& cipher() { return m_cipher; } |         T& cipher() { return m_cipher; } | ||||||
| 
 | 
 | ||||||
|     virtual void prune_padding(ByteBuffer& data) |         virtual void prune_padding(ByteBuffer& data) | ||||||
|     { |         { | ||||||
|         auto size = data.size(); |             auto size = data.size(); | ||||||
|         switch (m_cipher.padding_mode()) { |             switch (m_cipher.padding_mode()) { | ||||||
|         case PaddingMode::CMS: { |             case PaddingMode::CMS: { | ||||||
|             auto maybe_padding_length = data[size - 1]; |                 auto maybe_padding_length = data[size - 1]; | ||||||
|             if (maybe_padding_length >= T::block_size()) { |                 if (maybe_padding_length >= T::block_size()) { | ||||||
|                 // cannot be padding (the entire block cannot be padding)
 |                     // cannot be padding (the entire block cannot be padding)
 | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             for (auto i = maybe_padding_length; i > 0; --i) { |  | ||||||
|                 if (data[size - i] != maybe_padding_length) { |  | ||||||
|                     // not padding, part of data
 |  | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  |                 for (auto i = maybe_padding_length; i > 0; --i) { | ||||||
|  |                     if (data[size - i] != maybe_padding_length) { | ||||||
|  |                         // not padding, part of data
 | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 data.trim(size - maybe_padding_length); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             case PaddingMode::Null: { | ||||||
|  |                 while (data[size - 1] == 0) | ||||||
|  |                     --size; | ||||||
|  |                 data.trim(size); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             default: | ||||||
|  |                 // FIXME: support other padding modes
 | ||||||
|  |                 ASSERT_NOT_REACHED(); | ||||||
|  |                 break; | ||||||
|             } |             } | ||||||
|             data.trim(size - maybe_padding_length); |  | ||||||
|             break; |  | ||||||
|         } |         } | ||||||
|         case PaddingMode::Null: { |  | ||||||
|             while (data[size - 1] == 0) |  | ||||||
|                 --size; |  | ||||||
|             data.trim(size); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         default: |  | ||||||
|             // FIXME: support other padding modes
 |  | ||||||
|             ASSERT_NOT_REACHED(); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     // FIXME: Somehow add a reference version of this
 |         // FIXME: Somehow add a reference version of this
 | ||||||
|     template <typename... Args> |         template <typename... Args> | ||||||
|     Mode(Args... args) |         Mode(Args... args) | ||||||
|         : m_cipher(args...) |             : m_cipher(args...) | ||||||
|     { |         { | ||||||
|     } |         } | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  |         T m_cipher; | ||||||
|  |     }; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| private: |  | ||||||
|     T m_cipher; |  | ||||||
| }; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -31,21 +31,24 @@ | ||||||
| #include <AK/Types.h> | #include <AK/Types.h> | ||||||
| 
 | 
 | ||||||
| namespace Crypto { | namespace Crypto { | ||||||
|  | namespace Hash { | ||||||
| 
 | 
 | ||||||
| template<size_t BlockS, typename DigestT> |     template <size_t BlockS, typename DigestT> | ||||||
| class HashFunction { |     class HashFunction { | ||||||
| public: |     public: | ||||||
|     static constexpr auto BlockSize = BlockS; |         static constexpr auto BlockSize = BlockS / 8; | ||||||
|     using DigestType = DigestT; |         static constexpr auto DigestSize = sizeof(DigestT); | ||||||
| 
 | 
 | ||||||
|     static size_t block_size() { return BlockSize; }; |         using DigestType = DigestT; | ||||||
|     static size_t digest_size() { return sizeof(DigestType); }; |  | ||||||
| 
 | 
 | ||||||
|     virtual void update(const u8*, size_t) = 0; |         static size_t block_size() { return BlockSize; }; | ||||||
|     virtual void update(const ByteBuffer& buffer) = 0; |         static size_t digest_size() { return DigestSize; }; | ||||||
|     virtual void update(const StringView& string) = 0; |  | ||||||
| 
 | 
 | ||||||
|     virtual DigestType digest() = 0; |         virtual void update(const u8*, size_t) = 0; | ||||||
| }; |         virtual void update(const ByteBuffer& buffer) = 0; | ||||||
|  |         virtual void update(const StringView& string) = 0; | ||||||
| 
 | 
 | ||||||
|  |         virtual DigestType digest() = 0; | ||||||
|  |     }; | ||||||
|  | } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -65,167 +65,168 @@ static constexpr inline void round_4(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace Crypto { | namespace Crypto { | ||||||
|  | namespace Hash { | ||||||
| 
 | 
 | ||||||
| void MD5::update(const u8* input, size_t length) |     void MD5::update(const u8* input, size_t length) | ||||||
| { |     { | ||||||
|     auto index = (u32)(m_count[0] >> 3) & 0x3f; |         auto index = (u32)(m_count[0] >> 3) & 0x3f; | ||||||
|     size_t offset { 0 }; |         size_t offset { 0 }; | ||||||
|     m_count[0] += (u32)length << 3; |         m_count[0] += (u32)length << 3; | ||||||
|     if (m_count[0] < ((u32)length << 3)) { |         if (m_count[0] < ((u32)length << 3)) { | ||||||
|         ++m_count[1]; |             ++m_count[1]; | ||||||
|  |         } | ||||||
|  |         m_count[1] += (u32)length >> 29; | ||||||
|  | 
 | ||||||
|  |         auto part_length = 64 - index; | ||||||
|  |         if (length >= part_length) { | ||||||
|  |             m_buffer.overwrite(index, input, part_length); | ||||||
|  |             transform(m_buffer.data()); | ||||||
|  | 
 | ||||||
|  |             for (offset = part_length; offset + 63 < length; offset += 64) | ||||||
|  |                 transform(&input[offset]); | ||||||
|  | 
 | ||||||
|  |             index = 0; | ||||||
|  |         } | ||||||
|  |         ASSERT(length < part_length || length - offset <= 64); | ||||||
|  |         m_buffer.overwrite(index, &input[offset], length - offset); | ||||||
|     } |     } | ||||||
|     m_count[1] += (u32)length >> 29; |     MD5::DigestType MD5::digest() | ||||||
|  |     { | ||||||
|  |         DigestType digest; | ||||||
|  |         u8 bits[8]; | ||||||
| 
 | 
 | ||||||
|     auto part_length = 64 - index; |         encode(m_count, bits, 8); | ||||||
|     if (length >= part_length) { |  | ||||||
|         m_buffer.overwrite(index, input, part_length); |  | ||||||
|         transform(m_buffer.data()); |  | ||||||
| 
 | 
 | ||||||
|         for (offset = part_length; offset + 63 < length; offset += 64) |         // pad the data to 56%64
 | ||||||
|             transform(&input[offset]); |         u32 index = (u32)((m_count[0] >> 3) & 0x3f); | ||||||
|  |         u32 pad_length = index < 56 ? 56 - index : 120 - index; | ||||||
|  |         update(MD5Constants::PADDING, pad_length); | ||||||
| 
 | 
 | ||||||
|         index = 0; |         // append length
 | ||||||
|  |         update(bits, 8); | ||||||
|  | 
 | ||||||
|  |         // store state (4 registers ABCD)
 | ||||||
|  |         encode(&m_A, digest.data, 4 * sizeof(m_A)); | ||||||
|  | 
 | ||||||
|  |         reset(); | ||||||
|  | 
 | ||||||
|  |         return digest; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ASSERT(length < part_length || length - offset <= 64); |     void MD5::encode(const u32* from, u8* to, size_t length) | ||||||
|     m_buffer.overwrite(index, &input[offset], length - offset); |     { | ||||||
| } |         for (size_t i = 0, j = 0; j < length; ++i, j += 4) { | ||||||
| MD5::DigestType MD5::digest() |             to[j] = (u8)(from[i] & 0xff); | ||||||
| { |             to[j + 1] = (u8)((from[i] >> 8) & 0xff); | ||||||
|     DigestType digest; |             to[j + 2] = (u8)((from[i] >> 16) & 0xff); | ||||||
|     u8 bits[8]; |             to[j + 3] = (u8)((from[i] >> 24) & 0xff); | ||||||
| 
 |         } | ||||||
|     encode(m_count, bits, 8); |  | ||||||
| 
 |  | ||||||
|     // pad the data to 56%64
 |  | ||||||
|     u32 index = (u32)((m_count[0] >> 3) & 0x3f); |  | ||||||
|     u32 pad_length = index < 56 ? 56 - index : 120 - index; |  | ||||||
|     update(Constants::PADDING, pad_length); |  | ||||||
| 
 |  | ||||||
|     // append length
 |  | ||||||
|     update(bits, 8); |  | ||||||
| 
 |  | ||||||
|     // store state (4 registers ABCD)
 |  | ||||||
|     encode(&m_A, digest.data, 4 * sizeof(m_A)); |  | ||||||
| 
 |  | ||||||
|     reset(); |  | ||||||
| 
 |  | ||||||
|     return digest; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void MD5::encode(const u32* from, u8* to, size_t length) |  | ||||||
| { |  | ||||||
|     for (size_t i = 0, j = 0; j < length; ++i, j += 4) { |  | ||||||
|         to[j] = (u8)(from[i] & 0xff); |  | ||||||
|         to[j + 1] = (u8)((from[i] >> 8) & 0xff); |  | ||||||
|         to[j + 2] = (u8)((from[i] >> 16) & 0xff); |  | ||||||
|         to[j + 3] = (u8)((from[i] >> 24) & 0xff); |  | ||||||
|     } |     } | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| void MD5::decode(const u8* from, u32* to, size_t length) |     void MD5::decode(const u8* from, u32* to, size_t length) | ||||||
| { |     { | ||||||
|     for (size_t i = 0, j = 0; j < length; ++i, j += 4) |         for (size_t i = 0, j = 0; j < length; ++i, j += 4) | ||||||
|         to[i] = (((u32)from[j]) | (((u32)from[j + 1]) << 8) | (((u32)from[j + 2]) << 16) | (((u32)from[j + 3]) << 24)); |             to[i] = (((u32)from[j]) | (((u32)from[j + 1]) << 8) | (((u32)from[j + 2]) << 16) | (((u32)from[j + 3]) << 24)); | ||||||
| } |     } | ||||||
| 
 | 
 | ||||||
| void MD5::transform(const u8* block) |     void MD5::transform(const u8* block) | ||||||
| { |     { | ||||||
|     auto a = m_A; |         auto a = m_A; | ||||||
|     auto b = m_B; |         auto b = m_B; | ||||||
|     auto c = m_C; |         auto c = m_C; | ||||||
|     auto d = m_D; |         auto d = m_D; | ||||||
|     u32 x[16]; |         u32 x[16]; | ||||||
| 
 | 
 | ||||||
|     decode(block, x, 64); |         decode(block, x, 64); | ||||||
| 
 | 
 | ||||||
|     round_1(a, b, c, d, x[0], Constants::S11, 0xd76aa478); // 1
 |         round_1(a, b, c, d, x[0], MD5Constants::S11, 0xd76aa478); // 1
 | ||||||
|     round_1(d, a, b, c, x[1], Constants::S12, 0xe8c7b756); // 2
 |         round_1(d, a, b, c, x[1], MD5Constants::S12, 0xe8c7b756); // 2
 | ||||||
|     round_1(c, d, a, b, x[2], Constants::S13, 0x242070db); // 3
 |         round_1(c, d, a, b, x[2], MD5Constants::S13, 0x242070db); // 3
 | ||||||
|     round_1(b, c, d, a, x[3], Constants::S14, 0xc1bdceee); // 4
 |         round_1(b, c, d, a, x[3], MD5Constants::S14, 0xc1bdceee); // 4
 | ||||||
|     round_1(a, b, c, d, x[4], Constants::S11, 0xf57c0faf); // 5
 |         round_1(a, b, c, d, x[4], MD5Constants::S11, 0xf57c0faf); // 5
 | ||||||
|     round_1(d, a, b, c, x[5], Constants::S12, 0x4787c62a); // 6
 |         round_1(d, a, b, c, x[5], MD5Constants::S12, 0x4787c62a); // 6
 | ||||||
|     round_1(c, d, a, b, x[6], Constants::S13, 0xa8304613); // 7
 |         round_1(c, d, a, b, x[6], MD5Constants::S13, 0xa8304613); // 7
 | ||||||
|     round_1(b, c, d, a, x[7], Constants::S14, 0xfd469501); // 8
 |         round_1(b, c, d, a, x[7], MD5Constants::S14, 0xfd469501); // 8
 | ||||||
|     round_1(a, b, c, d, x[8], Constants::S11, 0x698098d8); // 9
 |         round_1(a, b, c, d, x[8], MD5Constants::S11, 0x698098d8); // 9
 | ||||||
|     round_1(d, a, b, c, x[9], Constants::S12, 0x8b44f7af); // 10
 |         round_1(d, a, b, c, x[9], MD5Constants::S12, 0x8b44f7af); // 10
 | ||||||
|     round_1(c, d, a, b, x[10], Constants::S13, 0xffff5bb1); // 11
 |         round_1(c, d, a, b, x[10], MD5Constants::S13, 0xffff5bb1); // 11
 | ||||||
|     round_1(b, c, d, a, x[11], Constants::S14, 0x895cd7be); // 12
 |         round_1(b, c, d, a, x[11], MD5Constants::S14, 0x895cd7be); // 12
 | ||||||
|     round_1(a, b, c, d, x[12], Constants::S11, 0x6b901122); // 13
 |         round_1(a, b, c, d, x[12], MD5Constants::S11, 0x6b901122); // 13
 | ||||||
|     round_1(d, a, b, c, x[13], Constants::S12, 0xfd987193); // 14
 |         round_1(d, a, b, c, x[13], MD5Constants::S12, 0xfd987193); // 14
 | ||||||
|     round_1(c, d, a, b, x[14], Constants::S13, 0xa679438e); // 15
 |         round_1(c, d, a, b, x[14], MD5Constants::S13, 0xa679438e); // 15
 | ||||||
|     round_1(b, c, d, a, x[15], Constants::S14, 0x49b40821); // 16
 |         round_1(b, c, d, a, x[15], MD5Constants::S14, 0x49b40821); // 16
 | ||||||
| 
 | 
 | ||||||
|     round_2(a, b, c, d, x[1], Constants::S21, 0xf61e2562); // 17
 |         round_2(a, b, c, d, x[1], MD5Constants::S21, 0xf61e2562); // 17
 | ||||||
|     round_2(d, a, b, c, x[6], Constants::S22, 0xc040b340); // 18
 |         round_2(d, a, b, c, x[6], MD5Constants::S22, 0xc040b340); // 18
 | ||||||
|     round_2(c, d, a, b, x[11], Constants::S23, 0x265e5a51); // 19
 |         round_2(c, d, a, b, x[11], MD5Constants::S23, 0x265e5a51); // 19
 | ||||||
|     round_2(b, c, d, a, x[0], Constants::S24, 0xe9b6c7aa); // 20
 |         round_2(b, c, d, a, x[0], MD5Constants::S24, 0xe9b6c7aa); // 20
 | ||||||
|     round_2(a, b, c, d, x[5], Constants::S21, 0xd62f105d); // 21
 |         round_2(a, b, c, d, x[5], MD5Constants::S21, 0xd62f105d); // 21
 | ||||||
|     round_2(d, a, b, c, x[10], Constants::S22, 0x2441453); // 22
 |         round_2(d, a, b, c, x[10], MD5Constants::S22, 0x2441453); // 22
 | ||||||
|     round_2(c, d, a, b, x[15], Constants::S23, 0xd8a1e681); // 23
 |         round_2(c, d, a, b, x[15], MD5Constants::S23, 0xd8a1e681); // 23
 | ||||||
|     round_2(b, c, d, a, x[4], Constants::S24, 0xe7d3fbc8); // 24
 |         round_2(b, c, d, a, x[4], MD5Constants::S24, 0xe7d3fbc8); // 24
 | ||||||
|     round_2(a, b, c, d, x[9], Constants::S21, 0x21e1cde6); // 25
 |         round_2(a, b, c, d, x[9], MD5Constants::S21, 0x21e1cde6); // 25
 | ||||||
|     round_2(d, a, b, c, x[14], Constants::S22, 0xc33707d6); // 26
 |         round_2(d, a, b, c, x[14], MD5Constants::S22, 0xc33707d6); // 26
 | ||||||
|     round_2(c, d, a, b, x[3], Constants::S23, 0xf4d50d87); // 27
 |         round_2(c, d, a, b, x[3], MD5Constants::S23, 0xf4d50d87); // 27
 | ||||||
|     round_2(b, c, d, a, x[8], Constants::S24, 0x455a14ed); // 28
 |         round_2(b, c, d, a, x[8], MD5Constants::S24, 0x455a14ed); // 28
 | ||||||
|     round_2(a, b, c, d, x[13], Constants::S21, 0xa9e3e905); // 29
 |         round_2(a, b, c, d, x[13], MD5Constants::S21, 0xa9e3e905); // 29
 | ||||||
|     round_2(d, a, b, c, x[2], Constants::S22, 0xfcefa3f8); // 30
 |         round_2(d, a, b, c, x[2], MD5Constants::S22, 0xfcefa3f8); // 30
 | ||||||
|     round_2(c, d, a, b, x[7], Constants::S23, 0x676f02d9); // 31
 |         round_2(c, d, a, b, x[7], MD5Constants::S23, 0x676f02d9); // 31
 | ||||||
|     round_2(b, c, d, a, x[12], Constants::S24, 0x8d2a4c8a); // 32
 |         round_2(b, c, d, a, x[12], MD5Constants::S24, 0x8d2a4c8a); // 32
 | ||||||
| 
 | 
 | ||||||
|     round_3(a, b, c, d, x[5], Constants::S31, 0xfffa3942); // 33
 |         round_3(a, b, c, d, x[5], MD5Constants::S31, 0xfffa3942); // 33
 | ||||||
|     round_3(d, a, b, c, x[8], Constants::S32, 0x8771f681); // 34
 |         round_3(d, a, b, c, x[8], MD5Constants::S32, 0x8771f681); // 34
 | ||||||
|     round_3(c, d, a, b, x[11], Constants::S33, 0x6d9d6122); // 35
 |         round_3(c, d, a, b, x[11], MD5Constants::S33, 0x6d9d6122); // 35
 | ||||||
|     round_3(b, c, d, a, x[14], Constants::S34, 0xfde5380c); // 36
 |         round_3(b, c, d, a, x[14], MD5Constants::S34, 0xfde5380c); // 36
 | ||||||
|     round_3(a, b, c, d, x[1], Constants::S31, 0xa4beea44); // 37
 |         round_3(a, b, c, d, x[1], MD5Constants::S31, 0xa4beea44); // 37
 | ||||||
|     round_3(d, a, b, c, x[4], Constants::S32, 0x4bdecfa9); // 38
 |         round_3(d, a, b, c, x[4], MD5Constants::S32, 0x4bdecfa9); // 38
 | ||||||
|     round_3(c, d, a, b, x[7], Constants::S33, 0xf6bb4b60); // 39
 |         round_3(c, d, a, b, x[7], MD5Constants::S33, 0xf6bb4b60); // 39
 | ||||||
|     round_3(b, c, d, a, x[10], Constants::S34, 0xbebfbc70); // 40
 |         round_3(b, c, d, a, x[10], MD5Constants::S34, 0xbebfbc70); // 40
 | ||||||
|     round_3(a, b, c, d, x[13], Constants::S31, 0x289b7ec6); // 41
 |         round_3(a, b, c, d, x[13], MD5Constants::S31, 0x289b7ec6); // 41
 | ||||||
|     round_3(d, a, b, c, x[0], Constants::S32, 0xeaa127fa); // 42
 |         round_3(d, a, b, c, x[0], MD5Constants::S32, 0xeaa127fa); // 42
 | ||||||
|     round_3(c, d, a, b, x[3], Constants::S33, 0xd4ef3085); // 43
 |         round_3(c, d, a, b, x[3], MD5Constants::S33, 0xd4ef3085); // 43
 | ||||||
|     round_3(b, c, d, a, x[6], Constants::S34, 0x4881d05); // 44
 |         round_3(b, c, d, a, x[6], MD5Constants::S34, 0x4881d05); // 44
 | ||||||
|     round_3(a, b, c, d, x[9], Constants::S31, 0xd9d4d039); // 45
 |         round_3(a, b, c, d, x[9], MD5Constants::S31, 0xd9d4d039); // 45
 | ||||||
|     round_3(d, a, b, c, x[12], Constants::S32, 0xe6db99e5); // 46
 |         round_3(d, a, b, c, x[12], MD5Constants::S32, 0xe6db99e5); // 46
 | ||||||
|     round_3(c, d, a, b, x[15], Constants::S33, 0x1fa27cf8); // 47
 |         round_3(c, d, a, b, x[15], MD5Constants::S33, 0x1fa27cf8); // 47
 | ||||||
|     round_3(b, c, d, a, x[2], Constants::S34, 0xc4ac5665); // 48
 |         round_3(b, c, d, a, x[2], MD5Constants::S34, 0xc4ac5665); // 48
 | ||||||
| 
 | 
 | ||||||
|     round_4(a, b, c, d, x[0], Constants::S41, 0xf4292244); // 49
 |         round_4(a, b, c, d, x[0], MD5Constants::S41, 0xf4292244); // 49
 | ||||||
|     round_4(d, a, b, c, x[7], Constants::S42, 0x432aff97); // 50
 |         round_4(d, a, b, c, x[7], MD5Constants::S42, 0x432aff97); // 50
 | ||||||
|     round_4(c, d, a, b, x[14], Constants::S43, 0xab9423a7); // 51
 |         round_4(c, d, a, b, x[14], MD5Constants::S43, 0xab9423a7); // 51
 | ||||||
|     round_4(b, c, d, a, x[5], Constants::S44, 0xfc93a039); // 52
 |         round_4(b, c, d, a, x[5], MD5Constants::S44, 0xfc93a039); // 52
 | ||||||
|     round_4(a, b, c, d, x[12], Constants::S41, 0x655b59c3); // 53
 |         round_4(a, b, c, d, x[12], MD5Constants::S41, 0x655b59c3); // 53
 | ||||||
|     round_4(d, a, b, c, x[3], Constants::S42, 0x8f0ccc92); // 54
 |         round_4(d, a, b, c, x[3], MD5Constants::S42, 0x8f0ccc92); // 54
 | ||||||
|     round_4(c, d, a, b, x[10], Constants::S43, 0xffeff47d); // 55
 |         round_4(c, d, a, b, x[10], MD5Constants::S43, 0xffeff47d); // 55
 | ||||||
|     round_4(b, c, d, a, x[1], Constants::S44, 0x85845dd1); // 56
 |         round_4(b, c, d, a, x[1], MD5Constants::S44, 0x85845dd1); // 56
 | ||||||
|     round_4(a, b, c, d, x[8], Constants::S41, 0x6fa87e4f); // 57
 |         round_4(a, b, c, d, x[8], MD5Constants::S41, 0x6fa87e4f); // 57
 | ||||||
|     round_4(d, a, b, c, x[15], Constants::S42, 0xfe2ce6e0); // 58
 |         round_4(d, a, b, c, x[15], MD5Constants::S42, 0xfe2ce6e0); // 58
 | ||||||
|     round_4(c, d, a, b, x[6], Constants::S43, 0xa3014314); // 59
 |         round_4(c, d, a, b, x[6], MD5Constants::S43, 0xa3014314); // 59
 | ||||||
|     round_4(b, c, d, a, x[13], Constants::S44, 0x4e0811a1); // 60
 |         round_4(b, c, d, a, x[13], MD5Constants::S44, 0x4e0811a1); // 60
 | ||||||
|     round_4(a, b, c, d, x[4], Constants::S41, 0xf7537e82); // 61
 |         round_4(a, b, c, d, x[4], MD5Constants::S41, 0xf7537e82); // 61
 | ||||||
|     round_4(d, a, b, c, x[11], Constants::S42, 0xbd3af235); // 62
 |         round_4(d, a, b, c, x[11], MD5Constants::S42, 0xbd3af235); // 62
 | ||||||
|     round_4(c, d, a, b, x[2], Constants::S43, 0x2ad7d2bb); // 63
 |         round_4(c, d, a, b, x[2], MD5Constants::S43, 0x2ad7d2bb); // 63
 | ||||||
|     round_4(b, c, d, a, x[9], Constants::S44, 0xeb86d391); // 64
 |         round_4(b, c, d, a, x[9], MD5Constants::S44, 0xeb86d391); // 64
 | ||||||
| 
 | 
 | ||||||
|     m_A += a; |         m_A += a; | ||||||
|     m_B += b; |         m_B += b; | ||||||
|     m_C += c; |         m_C += c; | ||||||
|     m_D += d; |         m_D += d; | ||||||
| 
 | 
 | ||||||
|     __builtin_memset(x, 0, sizeof(x)); |         __builtin_memset(x, 0, sizeof(x)); | ||||||
| } |     } | ||||||
| 
 | 
 | ||||||
| void MD5::reset() |     void MD5::reset() | ||||||
| { |     { | ||||||
|     m_A = Constants::init_A; |         m_A = MD5Constants::init_A; | ||||||
|     m_B = Constants::init_B; |         m_B = MD5Constants::init_B; | ||||||
|     m_C = Constants::init_C; |         m_C = MD5Constants::init_C; | ||||||
|     m_D = Constants::init_D; |         m_D = MD5Constants::init_D; | ||||||
| 
 | 
 | ||||||
|     m_count[0] = 0; |         m_count[0] = 0; | ||||||
|     m_count[1] = 0; |         m_count[1] = 0; | ||||||
| 
 | 
 | ||||||
|     __builtin_memset(m_data_buffer, 0, sizeof(m_data_buffer)); |         __builtin_memset(m_data_buffer, 0, sizeof(m_data_buffer)); | ||||||
| } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -30,78 +30,78 @@ | ||||||
| #include <LibCrypto/Hash/HashFunction.h> | #include <LibCrypto/Hash/HashFunction.h> | ||||||
| 
 | 
 | ||||||
| namespace Crypto { | namespace Crypto { | ||||||
|  | namespace Hash { | ||||||
| 
 | 
 | ||||||
| struct MD5Digest { |     struct MD5Digest { | ||||||
|     u8 data[16]; |         u8 data[16]; | ||||||
| }; |     }; | ||||||
| 
 | 
 | ||||||
| namespace MD5Constants { |     namespace MD5Constants { | ||||||
| 
 | 
 | ||||||
| constexpr u32 init_A = 0x67452301; |         constexpr u32 init_A = 0x67452301; | ||||||
| constexpr u32 init_B = 0xefcdab89; |         constexpr u32 init_B = 0xefcdab89; | ||||||
| constexpr u32 init_C = 0x98badcfe; |         constexpr u32 init_C = 0x98badcfe; | ||||||
| constexpr u32 init_D = 0x10325476; |         constexpr u32 init_D = 0x10325476; | ||||||
| constexpr u32 S11 = 7; |         constexpr u32 S11 = 7; | ||||||
| constexpr u32 S12 = 12; |         constexpr u32 S12 = 12; | ||||||
| constexpr u32 S13 = 17; |         constexpr u32 S13 = 17; | ||||||
| constexpr u32 S14 = 22; |         constexpr u32 S14 = 22; | ||||||
| constexpr u32 S21 = 5; |         constexpr u32 S21 = 5; | ||||||
| constexpr u32 S22 = 9; |         constexpr u32 S22 = 9; | ||||||
| constexpr u32 S23 = 14; |         constexpr u32 S23 = 14; | ||||||
| constexpr u32 S24 = 20; |         constexpr u32 S24 = 20; | ||||||
| constexpr u32 S31 = 4; |         constexpr u32 S31 = 4; | ||||||
| constexpr u32 S32 = 11; |         constexpr u32 S32 = 11; | ||||||
| constexpr u32 S33 = 16; |         constexpr u32 S33 = 16; | ||||||
| constexpr u32 S34 = 23; |         constexpr u32 S34 = 23; | ||||||
| constexpr u32 S41 = 6; |         constexpr u32 S41 = 6; | ||||||
| constexpr u32 S42 = 10; |         constexpr u32 S42 = 10; | ||||||
| constexpr u32 S43 = 15; |         constexpr u32 S43 = 15; | ||||||
| constexpr u32 S44 = 21; |         constexpr u32 S44 = 21; | ||||||
| constexpr u8 PADDING[] = { |         constexpr u8 PADDING[] = { | ||||||
|     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |             0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||||||
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||||||
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||||||
|     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||||||
|     0 |             0 | ||||||
| }; |         }; | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| class MD5 final : public HashFunction<16, MD5Digest> { |  | ||||||
| public: |  | ||||||
|     MD5() |  | ||||||
|     { |  | ||||||
|         m_buffer = ByteBuffer::wrap(m_data_buffer, sizeof(m_data_buffer)); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     virtual void update(const u8*, size_t) override; |     class MD5 final : public HashFunction<512, MD5Digest> { | ||||||
|     virtual void update(const ByteBuffer& buffer) override { update(buffer.data(), buffer.size()); }; |     public: | ||||||
|     virtual void update(const StringView& string) override { update((const u8*)string.characters_without_null_termination(), string.length()); }; |         MD5() | ||||||
|     virtual DigestType digest() override; |         { | ||||||
|  |             m_buffer = ByteBuffer::wrap(m_data_buffer, sizeof(m_data_buffer)); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     inline static DigestType hash(const u8* data, size_t length) |         virtual void update(const u8*, size_t) override; | ||||||
|     { |         virtual void update(const ByteBuffer& buffer) override { update(buffer.data(), buffer.size()); }; | ||||||
|         MD5 md5; |         virtual void update(const StringView& string) override { update((const u8*)string.characters_without_null_termination(), string.length()); }; | ||||||
|         md5.update(data, length); |         virtual DigestType digest() override; | ||||||
|         return md5.digest(); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     inline static DigestType hash(const ByteBuffer& buffer) { return hash(buffer.data(), buffer.size()); } |         inline static DigestType hash(const u8* data, size_t length) | ||||||
|     inline static DigestType hash(const StringView& buffer) { return hash((const u8*)buffer.characters_without_null_termination(), buffer.length()); } |         { | ||||||
|  |             MD5 md5; | ||||||
|  |             md5.update(data, length); | ||||||
|  |             return md5.digest(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
| private: |         inline static DigestType hash(const ByteBuffer& buffer) { return hash(buffer.data(), buffer.size()); } | ||||||
|     inline void transform(const u8*); |         inline static DigestType hash(const StringView& buffer) { return hash((const u8*)buffer.characters_without_null_termination(), buffer.length()); } | ||||||
|     inline void reset(); |  | ||||||
| 
 | 
 | ||||||
|     static void encode(const u32* from, u8* to, size_t length); |     private: | ||||||
|     static void decode(const u8* from, u32* to, size_t length); |         inline void transform(const u8*); | ||||||
|  |         inline void reset(); | ||||||
| 
 | 
 | ||||||
|     u32 m_A { Constants::init_A }, m_B { Constants::init_B }, m_C { Constants::init_C }, m_D { Constants::init_D }; |         static void encode(const u32* from, u8* to, size_t length); | ||||||
|     u32 m_count[2] { 0, 0 }; |         static void decode(const u8* from, u32* to, size_t length); | ||||||
|     ByteBuffer m_buffer; |  | ||||||
| 
 | 
 | ||||||
|     u8 m_data_buffer[64]; |         u32 m_A { MD5Constants::init_A }, m_B { MD5Constants::init_B }, m_C { MD5Constants::init_C }, m_D { MD5Constants::init_D }; | ||||||
| }; |         u32 m_count[2] { 0, 0 }; | ||||||
|  |         ByteBuffer m_buffer; | ||||||
|  | 
 | ||||||
|  |         u8 m_data_buffer[64]; | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -68,10 +68,10 @@ void aes_cbc(const char* message, size_t len) | ||||||
| { | { | ||||||
|     auto buffer = ByteBuffer::wrap(message, len); |     auto buffer = ByteBuffer::wrap(message, len); | ||||||
|     // FIXME: Take iv as an optional parameter
 |     // FIXME: Take iv as an optional parameter
 | ||||||
|     auto iv = ByteBuffer::create_zeroed(Crypto::AESCipher::block_size()); |     auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size()); | ||||||
| 
 | 
 | ||||||
|     if (encrypting) { |     if (encrypting) { | ||||||
|         Crypto::AESCipher::CBCMode cipher(secret_key, key_bits, Crypto::Intent::Encryption); |         Crypto::Cipher::AESCipher::CBCMode cipher(secret_key, key_bits, Crypto::Cipher::Intent::Encryption); | ||||||
| 
 | 
 | ||||||
|         auto enc = cipher.create_aligned_buffer(buffer.size()); |         auto enc = cipher.create_aligned_buffer(buffer.size()); | ||||||
|         cipher.encrypt(buffer, enc, iv); |         cipher.encrypt(buffer, enc, iv); | ||||||
|  | @ -79,9 +79,9 @@ void aes_cbc(const char* message, size_t len) | ||||||
|         if (binary) |         if (binary) | ||||||
|             printf("%.*s", (int)enc.size(), enc.data()); |             printf("%.*s", (int)enc.size(), enc.data()); | ||||||
|         else |         else | ||||||
|             print_buffer(enc, Crypto::AESCipher::block_size()); |             print_buffer(enc, Crypto::Cipher::AESCipher::block_size()); | ||||||
|     } else { |     } else { | ||||||
|         Crypto::AESCipher::CBCMode cipher(secret_key, key_bits, Crypto::Intent::Decryption); |         Crypto::Cipher::AESCipher::CBCMode cipher(secret_key, key_bits, Crypto::Cipher::Intent::Decryption); | ||||||
|         auto dec = cipher.create_aligned_buffer(buffer.size()); |         auto dec = cipher.create_aligned_buffer(buffer.size()); | ||||||
|         cipher.decrypt(buffer, dec, iv); |         cipher.decrypt(buffer, dec, iv); | ||||||
|         printf("%.*s\n", (int)dec.size(), dec.data()); |         printf("%.*s\n", (int)dec.size(), dec.data()); | ||||||
|  | @ -90,11 +90,21 @@ void aes_cbc(const char* message, size_t len) | ||||||
| 
 | 
 | ||||||
| void md5(const char* message, size_t len) | void md5(const char* message, size_t len) | ||||||
| { | { | ||||||
|     auto digest = Crypto::MD5::hash((const u8*)message, len); |     auto digest = Crypto::Hash::MD5::hash((const u8*)message, len); | ||||||
|     if (binary) |     if (binary) | ||||||
|         printf("%.*s", (int)Crypto::MD5::block_size(), digest.data); |         printf("%.*s", (int)Crypto::Hash::MD5::digest_size(), digest.data); | ||||||
|     else |     else | ||||||
|         print_buffer(ByteBuffer::wrap(digest.data, Crypto::MD5::block_size()), Crypto::MD5::block_size()); |         print_buffer(ByteBuffer::wrap(digest.data, Crypto::Hash::MD5::digest_size()), -1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void hmac_md5(const char* message, size_t len) | ||||||
|  | { | ||||||
|  |     Crypto::Authentication::HMAC<Crypto::Hash::MD5> hmac(secret_key); | ||||||
|  |     auto mac = hmac.process((const u8*)message, len); | ||||||
|  |     if (binary) | ||||||
|  |         printf("%.*s", (int)hmac.DigestSize, mac.data); | ||||||
|  |     else | ||||||
|  |         print_buffer(ByteBuffer::wrap(mac.data, hmac.DigestSize), -1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| auto main(int argc, char** argv) -> int | auto main(int argc, char** argv) -> int | ||||||
|  | @ -103,7 +113,7 @@ auto main(int argc, char** argv) -> int | ||||||
|     Core::ArgsParser parser; |     Core::ArgsParser parser; | ||||||
|     parser.add_positional_argument(mode, "mode to operate in ('list' to see modes and descriptions)", "mode"); |     parser.add_positional_argument(mode, "mode to operate in ('list' to see modes and descriptions)", "mode"); | ||||||
| 
 | 
 | ||||||
|     parser.add_option(secret_key, "Set the secret key (must be key-bits bits)", "secret-key", 'k', "secret key"); |     parser.add_option(secret_key, "Set the secret key", "secret-key", 'k', "secret key"); | ||||||
|     parser.add_option(key_bits, "Size of the key", "key-bits", 'b', "key-bits"); |     parser.add_option(key_bits, "Size of the key", "key-bits", 'b', "key-bits"); | ||||||
|     parser.add_option(filename, "Read from file", "file", 'f', "from file"); |     parser.add_option(filename, "Read from file", "file", 'f', "from file"); | ||||||
|     parser.add_option(binary, "Force binary output", "force-binary", 0); |     parser.add_option(binary, "Force binary output", "force-binary", 0); | ||||||
|  | @ -143,7 +153,7 @@ auto main(int argc, char** argv) -> int | ||||||
|             if (run_tests) |             if (run_tests) | ||||||
|                 return aes_cbc_tests(); |                 return aes_cbc_tests(); | ||||||
| 
 | 
 | ||||||
|             if (!Crypto::AESCipher::KeyType::is_valid_key_size(key_bits)) { |             if (!Crypto::Cipher::AESCipher::KeyType::is_valid_key_size(key_bits)) { | ||||||
|                 printf("Invalid key size for AES: %d\n", key_bits); |                 printf("Invalid key size for AES: %d\n", key_bits); | ||||||
|                 return 1; |                 return 1; | ||||||
|             } |             } | ||||||
|  | @ -199,13 +209,13 @@ void aes_cbc_test_encrypt() | ||||||
|     auto test_it = [](auto& cipher, auto& result) { |     auto test_it = [](auto& cipher, auto& result) { | ||||||
|         auto in = "This is a test! This is another test!"_b; |         auto in = "This is a test! This is another test!"_b; | ||||||
|         auto out = cipher.create_aligned_buffer(in.size()); |         auto out = cipher.create_aligned_buffer(in.size()); | ||||||
|         auto iv = ByteBuffer::create_zeroed(Crypto::AESCipher::block_size()); |         auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size()); | ||||||
|         cipher.encrypt(in, out, iv); |         cipher.encrypt(in, out, iv); | ||||||
|         if (out.size() != sizeof(result)) |         if (out.size() != sizeof(result)) | ||||||
|             FAIL(size mismatch); |             FAIL(size mismatch); | ||||||
|         else if (memcmp(out.data(), result, out.size()) != 0) { |         else if (memcmp(out.data(), result, out.size()) != 0) { | ||||||
|             FAIL(invalid data); |             FAIL(invalid data); | ||||||
|             print_buffer(out, Crypto::AESCipher::block_size()); |             print_buffer(out, Crypto::Cipher::AESCipher::block_size()); | ||||||
|         } else |         } else | ||||||
|             PASS; |             PASS; | ||||||
|     }; |     }; | ||||||
|  | @ -217,7 +227,7 @@ void aes_cbc_test_encrypt() | ||||||
|             0x8b, 0xd3, 0x70, 0x45, 0xf0, 0x79, 0x65, 0xca, 0xb9, 0x03, 0x88, 0x72, 0x1c, 0xdd, 0xab, |             0x8b, 0xd3, 0x70, 0x45, 0xf0, 0x79, 0x65, 0xca, 0xb9, 0x03, 0x88, 0x72, 0x1c, 0xdd, 0xab, | ||||||
|             0x45, 0x6b, 0x1c |             0x45, 0x6b, 0x1c | ||||||
|         }; |         }; | ||||||
|         Crypto::AESCipher::CBCMode cipher("WellHelloFriends", 128, Crypto::Intent::Encryption); |         Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriends", 128, Crypto::Cipher::Intent::Encryption); | ||||||
|         test_it(cipher, result); |         test_it(cipher, result); | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|  | @ -228,7 +238,7 @@ void aes_cbc_test_encrypt() | ||||||
|             0x68, 0x51, 0x09, 0xd7, 0x3b, 0x48, 0x1b, 0x8a, 0xd3, 0x50, 0x09, 0xba, 0xfc, 0xde, 0x11, |             0x68, 0x51, 0x09, 0xd7, 0x3b, 0x48, 0x1b, 0x8a, 0xd3, 0x50, 0x09, 0xba, 0xfc, 0xde, 0x11, | ||||||
|             0xe0, 0x3f, 0xcb |             0xe0, 0x3f, 0xcb | ||||||
|         }; |         }; | ||||||
|         Crypto::AESCipher::CBCMode cipher("Well Hello Friends! whf!", 192, Crypto::Intent::Encryption); |         Crypto::Cipher::AESCipher::CBCMode cipher("Well Hello Friends! whf!", 192, Crypto::Cipher::Intent::Encryption); | ||||||
|         test_it(cipher, result); |         test_it(cipher, result); | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|  | @ -239,7 +249,7 @@ void aes_cbc_test_encrypt() | ||||||
|             0x47, 0x9f, 0xc2, 0x21, 0xe6, 0x19, 0x62, 0xc3, 0x75, 0xca, 0xab, 0x2d, 0x18, 0xa1, 0x54, |             0x47, 0x9f, 0xc2, 0x21, 0xe6, 0x19, 0x62, 0xc3, 0x75, 0xca, 0xab, 0x2d, 0x18, 0xa1, 0x54, | ||||||
|             0xd1, 0x41, 0xe6 |             0xd1, 0x41, 0xe6 | ||||||
|         }; |         }; | ||||||
|         Crypto::AESCipher::CBCMode cipher("WellHelloFriendsWellHelloFriends", 256, Crypto::Intent::Encryption); |         Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriendsWellHelloFriends", 256, Crypto::Cipher::Intent::Encryption); | ||||||
|         test_it(cipher, result); |         test_it(cipher, result); | ||||||
|     } |     } | ||||||
|     // TODO: Test non-CMS padding options
 |     // TODO: Test non-CMS padding options
 | ||||||
|  | @ -250,14 +260,14 @@ void aes_cbc_test_decrypt() | ||||||
|         auto true_value = "This is a test! This is another test!"; |         auto true_value = "This is a test! This is another test!"; | ||||||
|         auto in = ByteBuffer::copy(result, result_len); |         auto in = ByteBuffer::copy(result, result_len); | ||||||
|         auto out = cipher.create_aligned_buffer(in.size()); |         auto out = cipher.create_aligned_buffer(in.size()); | ||||||
|         auto iv = ByteBuffer::create_zeroed(Crypto::AESCipher::block_size()); |         auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size()); | ||||||
|         cipher.decrypt(in, out, iv); |         cipher.decrypt(in, out, iv); | ||||||
|         if (out.size() != strlen(true_value)) { |         if (out.size() != strlen(true_value)) { | ||||||
|             FAIL(size mismatch); |             FAIL(size mismatch); | ||||||
|             printf("Expected %zu bytes but got %zu\n", strlen(true_value), out.size()); |             printf("Expected %zu bytes but got %zu\n", strlen(true_value), out.size()); | ||||||
|         } else if (memcmp(out.data(), true_value, strlen(true_value)) != 0) { |         } else if (memcmp(out.data(), true_value, strlen(true_value)) != 0) { | ||||||
|             FAIL(invalid data); |             FAIL(invalid data); | ||||||
|             print_buffer(out, Crypto::AESCipher::block_size()); |             print_buffer(out, Crypto::Cipher::AESCipher::block_size()); | ||||||
|         } else |         } else | ||||||
|             PASS; |             PASS; | ||||||
|     }; |     }; | ||||||
|  | @ -269,7 +279,7 @@ void aes_cbc_test_decrypt() | ||||||
|             0x8b, 0xd3, 0x70, 0x45, 0xf0, 0x79, 0x65, 0xca, 0xb9, 0x03, 0x88, 0x72, 0x1c, 0xdd, 0xab, |             0x8b, 0xd3, 0x70, 0x45, 0xf0, 0x79, 0x65, 0xca, 0xb9, 0x03, 0x88, 0x72, 0x1c, 0xdd, 0xab, | ||||||
|             0x45, 0x6b, 0x1c |             0x45, 0x6b, 0x1c | ||||||
|         }; |         }; | ||||||
|         Crypto::AESCipher::CBCMode cipher("WellHelloFriends", 128, Crypto::Intent::Decryption); |         Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriends", 128, Crypto::Cipher::Intent::Decryption); | ||||||
|         test_it(cipher, result, 48); |         test_it(cipher, result, 48); | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|  | @ -280,7 +290,7 @@ void aes_cbc_test_decrypt() | ||||||
|             0x68, 0x51, 0x09, 0xd7, 0x3b, 0x48, 0x1b, 0x8a, 0xd3, 0x50, 0x09, 0xba, 0xfc, 0xde, 0x11, |             0x68, 0x51, 0x09, 0xd7, 0x3b, 0x48, 0x1b, 0x8a, 0xd3, 0x50, 0x09, 0xba, 0xfc, 0xde, 0x11, | ||||||
|             0xe0, 0x3f, 0xcb |             0xe0, 0x3f, 0xcb | ||||||
|         }; |         }; | ||||||
|         Crypto::AESCipher::CBCMode cipher("Well Hello Friends! whf!", 192, Crypto::Intent::Decryption); |         Crypto::Cipher::AESCipher::CBCMode cipher("Well Hello Friends! whf!", 192, Crypto::Cipher::Intent::Decryption); | ||||||
|         test_it(cipher, result, 48); |         test_it(cipher, result, 48); | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|  | @ -291,7 +301,7 @@ void aes_cbc_test_decrypt() | ||||||
|             0x47, 0x9f, 0xc2, 0x21, 0xe6, 0x19, 0x62, 0xc3, 0x75, 0xca, 0xab, 0x2d, 0x18, 0xa1, 0x54, |             0x47, 0x9f, 0xc2, 0x21, 0xe6, 0x19, 0x62, 0xc3, 0x75, 0xca, 0xab, 0x2d, 0x18, 0xa1, 0x54, | ||||||
|             0xd1, 0x41, 0xe6 |             0xd1, 0x41, 0xe6 | ||||||
|         }; |         }; | ||||||
|         Crypto::AESCipher::CBCMode cipher("WellHelloFriendsWellHelloFriends", 256, Crypto::Intent::Decryption); |         Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriendsWellHelloFriends", 256, Crypto::Cipher::Intent::Decryption); | ||||||
|         test_it(cipher, result, 48); |         test_it(cipher, result, 48); | ||||||
|     } |     } | ||||||
|     // TODO: Test non-CMS padding options
 |     // TODO: Test non-CMS padding options
 | ||||||
|  | @ -311,11 +321,11 @@ void md5_test_hash() | ||||||
|         u8 result[] { |         u8 result[] { | ||||||
|             0xaf, 0x04, 0x3a, 0x08, 0x94, 0x38, 0x6e, 0x7f, 0xbf, 0x73, 0xe4, 0xaa, 0xf0, 0x8e, 0xee, 0x4c |             0xaf, 0x04, 0x3a, 0x08, 0x94, 0x38, 0x6e, 0x7f, 0xbf, 0x73, 0xe4, 0xaa, 0xf0, 0x8e, 0xee, 0x4c | ||||||
|         }; |         }; | ||||||
|         auto digest = Crypto::MD5::hash("Well hello friends"); |         auto digest = Crypto::Hash::MD5::hash("Well hello friends"); | ||||||
| 
 | 
 | ||||||
|         if (memcmp(result, digest.data, Crypto::MD5::block_size()) != 0) { |         if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { | ||||||
|             FAIL(Invalid hash); |             FAIL(Invalid hash); | ||||||
|             print_buffer(ByteBuffer::wrap(digest.data, Crypto::MD5::block_size()), -1); |             print_buffer(ByteBuffer::wrap(digest.data, Crypto::Hash::MD5::digest_size()), -1); | ||||||
|         } else { |         } else { | ||||||
|             PASS; |             PASS; | ||||||
|         } |         } | ||||||
|  | @ -326,11 +336,11 @@ void md5_test_hash() | ||||||
|         u8 result[] { |         u8 result[] { | ||||||
|             0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e |             0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e | ||||||
|         }; |         }; | ||||||
|         auto digest = Crypto::MD5::hash(""); |         auto digest = Crypto::Hash::MD5::hash(""); | ||||||
| 
 | 
 | ||||||
|         if (memcmp(result, digest.data, Crypto::MD5::block_size()) != 0) { |         if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { | ||||||
|             FAIL(Invalid hash); |             FAIL(Invalid hash); | ||||||
|             print_buffer(ByteBuffer::wrap(digest.data, Crypto::MD5::block_size()), -1); |             print_buffer(ByteBuffer::wrap(digest.data, Crypto::Hash::MD5::digest_size()), -1); | ||||||
|         } else { |         } else { | ||||||
|             PASS; |             PASS; | ||||||
|         } |         } | ||||||
|  | @ -340,11 +350,11 @@ void md5_test_hash() | ||||||
|         u8 result[] { |         u8 result[] { | ||||||
|             0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 |             0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 | ||||||
|         }; |         }; | ||||||
|         auto digest = Crypto::MD5::hash("a"); |         auto digest = Crypto::Hash::MD5::hash("a"); | ||||||
| 
 | 
 | ||||||
|         if (memcmp(result, digest.data, Crypto::MD5::block_size()) != 0) { |         if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { | ||||||
|             FAIL(Invalid hash); |             FAIL(Invalid hash); | ||||||
|             print_buffer(ByteBuffer::wrap(digest.data, Crypto::MD5::block_size()), -1); |             print_buffer(ByteBuffer::wrap(digest.data, Crypto::Hash::MD5::digest_size()), -1); | ||||||
|         } else { |         } else { | ||||||
|             PASS; |             PASS; | ||||||
|         } |         } | ||||||
|  | @ -354,11 +364,11 @@ void md5_test_hash() | ||||||
|         u8 result[] { |         u8 result[] { | ||||||
|             0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b |             0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b | ||||||
|         }; |         }; | ||||||
|         auto digest = Crypto::MD5::hash("abcdefghijklmnopqrstuvwxyz"); |         auto digest = Crypto::Hash::MD5::hash("abcdefghijklmnopqrstuvwxyz"); | ||||||
| 
 | 
 | ||||||
|         if (memcmp(result, digest.data, Crypto::MD5::block_size()) != 0) { |         if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { | ||||||
|             FAIL(Invalid hash); |             FAIL(Invalid hash); | ||||||
|             print_buffer(ByteBuffer::wrap(digest.data, Crypto::MD5::block_size()), -1); |             print_buffer(ByteBuffer::wrap(digest.data, Crypto::Hash::MD5::digest_size()), -1); | ||||||
|         } else { |         } else { | ||||||
|             PASS; |             PASS; | ||||||
|         } |         } | ||||||
|  | @ -368,11 +378,11 @@ void md5_test_hash() | ||||||
|         u8 result[] { |         u8 result[] { | ||||||
|             0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a |             0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a | ||||||
|         }; |         }; | ||||||
|         auto digest = Crypto::MD5::hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); |         auto digest = Crypto::Hash::MD5::hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); | ||||||
| 
 | 
 | ||||||
|         if (memcmp(result, digest.data, Crypto::MD5::block_size()) != 0) { |         if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { | ||||||
|             FAIL(Invalid hash); |             FAIL(Invalid hash); | ||||||
|             print_buffer(ByteBuffer::wrap(digest.data, Crypto::MD5::block_size()), -1); |             print_buffer(ByteBuffer::wrap(digest.data, Crypto::Hash::MD5::digest_size()), -1); | ||||||
|         } else { |         } else { | ||||||
|             PASS; |             PASS; | ||||||
|         } |         } | ||||||
|  | @ -386,21 +396,21 @@ void md5_test_consecutive_updates() | ||||||
|         u8 result[] { |         u8 result[] { | ||||||
|             0xaf, 0x04, 0x3a, 0x08, 0x94, 0x38, 0x6e, 0x7f, 0xbf, 0x73, 0xe4, 0xaa, 0xf0, 0x8e, 0xee, 0x4c |             0xaf, 0x04, 0x3a, 0x08, 0x94, 0x38, 0x6e, 0x7f, 0xbf, 0x73, 0xe4, 0xaa, 0xf0, 0x8e, 0xee, 0x4c | ||||||
|         }; |         }; | ||||||
|         Crypto::MD5 md5; |         Crypto::Hash::MD5 md5; | ||||||
| 
 | 
 | ||||||
|         md5.update("Well"); |         md5.update("Well"); | ||||||
|         md5.update(" hello "); |         md5.update(" hello "); | ||||||
|         md5.update("friends"); |         md5.update("friends"); | ||||||
|         auto digest = md5.digest(); |         auto digest = md5.digest(); | ||||||
| 
 | 
 | ||||||
|         if (memcmp(result, digest.data, Crypto::MD5::block_size()) != 0) |         if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) | ||||||
|             FAIL(Invalid hash); |             FAIL(Invalid hash); | ||||||
|         else |         else | ||||||
|             PASS; |             PASS; | ||||||
|     } |     } | ||||||
|     { |     { | ||||||
|         I_TEST((MD5 Hashing | Reuse)); |         I_TEST((MD5 Hashing | Reuse)); | ||||||
|         Crypto::MD5 md5; |         Crypto::Hash::MD5 md5; | ||||||
| 
 | 
 | ||||||
|         md5.update("Well"); |         md5.update("Well"); | ||||||
|         md5.update(" hello "); |         md5.update(" hello "); | ||||||
|  | @ -412,7 +422,7 @@ void md5_test_consecutive_updates() | ||||||
|         md5.update("friends"); |         md5.update("friends"); | ||||||
|         auto digest1 = md5.digest(); |         auto digest1 = md5.digest(); | ||||||
| 
 | 
 | ||||||
|         if (memcmp(digest0.data, digest1.data, Crypto::MD5::block_size()) != 0) |         if (memcmp(digest0.data, digest1.data, Crypto::Hash::MD5::block_size()) != 0) | ||||||
|             FAIL(Cannot reuse); |             FAIL(Cannot reuse); | ||||||
|         else |         else | ||||||
|             PASS; |             PASS; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 AnotherTest
						AnotherTest