Serenity Operating System
1/*
2 * Copyright (c) 2021, Peter Bocan <me@pbocan.net>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibCrypto/Authentication/GHash.h>
8#include <LibCrypto/Authentication/HMAC.h>
9#include <LibCrypto/Hash/MD5.h>
10#include <LibCrypto/Hash/SHA1.h>
11#include <LibCrypto/Hash/SHA2.h>
12#include <LibTest/TestCase.h>
13#include <cstring>
14
15TEST_CASE(test_MD5_name)
16{
17 Crypto::Hash::MD5 md5;
18 EXPECT(md5.class_name() == "MD5");
19}
20
21TEST_CASE(test_MD5_hash_string)
22{
23 u8 result[] {
24 0xaf, 0x04, 0x3a, 0x08, 0x94, 0x38, 0x6e, 0x7f, 0xbf, 0x73, 0xe4, 0xaa, 0xf0, 0x8e, 0xee, 0x4c
25 };
26 auto digest = Crypto::Hash::MD5::hash("Well hello friends"sv);
27 EXPECT(memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) == 0);
28}
29
30TEST_CASE(test_MD5_hash_empty_string)
31{
32 u8 result[] {
33 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
34 };
35 auto digest = Crypto::Hash::MD5::hash(""sv);
36 EXPECT(memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) == 0);
37}
38
39TEST_CASE(test_MD5_hash_single_character)
40{
41 u8 result[] {
42 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61
43 };
44 auto digest = Crypto::Hash::MD5::hash("a"sv);
45 EXPECT(memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) == 0);
46}
47
48TEST_CASE(test_MD5_hash_alphabet)
49{
50 u8 result[] {
51 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b
52 };
53 auto digest = Crypto::Hash::MD5::hash("abcdefghijklmnopqrstuvwxyz"sv);
54 EXPECT(memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) == 0);
55}
56
57TEST_CASE(test_MD5_hash_long_sequence)
58{
59 u8 result[] {
60 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a
61 };
62 auto digest = Crypto::Hash::MD5::hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890"sv);
63 EXPECT(memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) == 0);
64}
65
66TEST_CASE(test_MD5_consecutive_multiple_updates)
67{
68 u8 result[] {
69 0xaf, 0x04, 0x3a, 0x08, 0x94, 0x38, 0x6e, 0x7f, 0xbf, 0x73, 0xe4, 0xaa, 0xf0, 0x8e, 0xee, 0x4c
70 };
71 Crypto::Hash::MD5 md5;
72
73 md5.update("Well"sv);
74 md5.update(" hello "sv);
75 md5.update("friends"sv);
76 auto digest = md5.digest();
77
78 EXPECT(memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) == 0);
79}
80
81TEST_CASE(test_MD5_consecutive_updates_reuse)
82{
83 Crypto::Hash::MD5 md5;
84
85 md5.update("Well"sv);
86 md5.update(" hello "sv);
87 md5.update("friends"sv);
88 auto digest0 = md5.digest();
89
90 md5.update("Well"sv);
91 md5.update(" hello "sv);
92 md5.update("friends"sv);
93 auto digest1 = md5.digest();
94
95 EXPECT(memcmp(digest0.data, digest1.data, Crypto::Hash::MD5::digest_size()) == 0);
96}
97
98TEST_CASE(test_SHA1_name)
99{
100 Crypto::Hash::SHA1 sha;
101 EXPECT(sha.class_name() == "SHA1"sv);
102}
103
104TEST_CASE(test_SHA1_hash_empty_string)
105{
106 u8 result[] {
107 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09
108 };
109 auto digest = Crypto::Hash::SHA1::hash(""sv);
110 EXPECT(memcmp(result, digest.data, Crypto::Hash::SHA1::digest_size()) == 0);
111}
112
113TEST_CASE(test_SHA1_hash_long_string)
114{
115 u8 result[] {
116 0x12, 0x15, 0x1f, 0xb1, 0x04, 0x44, 0x93, 0xcc, 0xed, 0x54, 0xa6, 0xb8, 0x7e, 0x93, 0x37, 0x7b, 0xb2, 0x13, 0x39, 0xdb
117 };
118 auto digest = Crypto::Hash::SHA1::hash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"sv);
119 EXPECT(memcmp(result, digest.data, Crypto::Hash::SHA1::digest_size()) == 0);
120}
121
122TEST_CASE(test_SHA1_hash_successive_updates)
123{
124 u8 result[] {
125 0xd6, 0x6e, 0xce, 0xd1, 0xf4, 0x08, 0xc6, 0xd8, 0x35, 0xab, 0xf0, 0xc9, 0x05, 0x26, 0xa4, 0xb2, 0xb8, 0xa3, 0x7c, 0xd3
126 };
127 auto hasher = Crypto::Hash::SHA1 {};
128 hasher.update("aaaaaaaaaaaaaaa"sv);
129 hasher.update("aaaaaaaaaaaaaaa"sv);
130 hasher.update("aaaaaaaaaaaaaaa"sv);
131 hasher.update("aaaaaaaaaaaaaaa"sv);
132 hasher.update("aaaaaaaaaaaaaaa"sv);
133 hasher.update("aaaaaaaaaaaaaaa"sv);
134 hasher.update("aaaaaaaaaaaaaaa"sv);
135 hasher.update("aaaaaaaaaaaaaaa"sv);
136 hasher.update("aaaaaaaaaaaaaaa"sv);
137 hasher.update("aaaaaaaaaaaaaaa"sv);
138 hasher.update("aaaaaaaaaaaaaaa"sv);
139 hasher.update("aaaaaaaaaaaaaaa"sv);
140 hasher.update("aaaaaaaaa"sv);
141 auto digest = hasher.digest();
142 EXPECT(memcmp(result, digest.data, Crypto::Hash::SHA1::digest_size()) == 0);
143}
144
145TEST_CASE(test_SHA256_name)
146{
147 Crypto::Hash::SHA256 sha;
148 EXPECT_EQ(sha.class_name(), "SHA256"sv);
149}
150
151TEST_CASE(test_SHA256_hash_string)
152{
153 u8 result[] {
154 0x9a, 0xcd, 0x50, 0xf9, 0xa2, 0xaf, 0x37, 0xe4, 0x71, 0xf7, 0x61, 0xc3, 0xfe, 0x7b, 0x8d, 0xea, 0x56, 0x17, 0xe5, 0x1d, 0xac, 0x80, 0x2f, 0xe6, 0xc1, 0x77, 0xb7, 0x4a, 0xbf, 0x0a, 0xbb, 0x5a
155 };
156 auto digest = Crypto::Hash::SHA256::hash("Well hello friends"sv);
157 EXPECT(memcmp(result, digest.data, Crypto::Hash::SHA256::digest_size()) == 0);
158}
159
160TEST_CASE(test_SHA256_hash_empty_string)
161{
162 u8 result[] {
163 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
164 };
165 auto digest = Crypto::Hash::SHA256::hash(""sv);
166 EXPECT(memcmp(result, digest.data, Crypto::Hash::SHA256::digest_size()) == 0);
167}
168
169TEST_CASE(test_SHA384_name)
170{
171 Crypto::Hash::SHA384 sha;
172 EXPECT_EQ(sha.class_name(), "SHA384"sv);
173}
174
175TEST_CASE(test_SHA384_hash_string)
176{
177 u8 result[] {
178 0x2f, 0x01, 0x8e, 0x9a, 0x4f, 0xd1, 0x36, 0xb9, 0x0f, 0xcc, 0x21, 0xde, 0x1a, 0xd4, 0x49, 0x51, 0x57, 0x82, 0x86, 0x84, 0x54, 0x09, 0x82, 0x7b, 0x54, 0x56, 0x93, 0xac, 0x2c, 0x46, 0x0c, 0x1f, 0x5e, 0xec, 0xe0, 0xf7, 0x8b, 0x0b, 0x84, 0x27, 0xc8, 0xb8, 0xbe, 0x49, 0xce, 0x8f, 0x1c, 0xff
179 };
180 auto digest = Crypto::Hash::SHA384::hash("Well hello friends"sv);
181 EXPECT(memcmp(result, digest.data, Crypto::Hash::SHA384::digest_size()) == 0);
182}
183
184TEST_CASE(test_SHA384_hash_bug)
185{
186 u8 result[] {
187 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39
188 };
189 ReadonlyBytes result_bytes { result, 48 };
190 auto digest = Crypto::Hash::SHA384::hash("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"sv);
191 EXPECT_EQ(result_bytes, digest.bytes());
192}
193
194TEST_CASE(test_SHA512_name)
195{
196 Crypto::Hash::SHA512 sha;
197 EXPECT_EQ(sha.class_name(), "SHA512"sv);
198}
199
200TEST_CASE(test_SHA512_hash_string)
201{
202 u8 result[] {
203 0x00, 0xfe, 0x68, 0x09, 0x71, 0x0e, 0xcb, 0x2b, 0xe9, 0x58, 0x00, 0x13, 0x69, 0x6a, 0x9e, 0x9e, 0xbd, 0x09, 0x1b, 0xfe, 0x14, 0xc9, 0x13, 0x82, 0xc7, 0x40, 0x34, 0xfe, 0xca, 0xe6, 0x87, 0xcb, 0x26, 0x36, 0x92, 0xe6, 0x34, 0x94, 0x3a, 0x11, 0xe5, 0xbb, 0xb5, 0xeb, 0x8e, 0x70, 0xef, 0x64, 0xca, 0xf7, 0x21, 0xb1, 0xde, 0xf2, 0x34, 0x85, 0x6f, 0xa8, 0x56, 0xd8, 0x23, 0xa1, 0x3b, 0x29
204 };
205 auto digest = Crypto::Hash::SHA512::hash("Well hello friends"sv);
206 EXPECT(memcmp(result, digest.data, Crypto::Hash::SHA512::digest_size()) == 0);
207}
208
209TEST_CASE(test_SHA512_hash_bug)
210{
211 u8 result[] {
212 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09
213 };
214 ReadonlyBytes result_bytes { result, 64 };
215 auto digest = Crypto::Hash::SHA512::hash("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"sv);
216 EXPECT_EQ(result_bytes, digest.bytes());
217}
218
219TEST_CASE(test_SHA512_hash_empty_string)
220{
221 u8 result[] {
222 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
223 };
224 auto digest = Crypto::Hash::SHA512::hash(""sv);
225 EXPECT(memcmp(result, digest.data, Crypto::Hash::SHA512::digest_size()) == 0);
226}
227
228TEST_CASE(test_ghash_test_name)
229{
230 Crypto::Authentication::GHash ghash("WellHelloFriends");
231 EXPECT_EQ(ghash.class_name(), "GHash");
232}
233
234TEST_CASE(test_ghash_galois_field_multiply)
235{
236 u32 x[4] { 0x42831ec2, 0x21777424, 0x4b7221b7, 0x84d0d49c },
237 y[4] { 0xb83b5337, 0x08bf535d, 0x0aa6e529, 0x80d53b78 }, z[4] { 0, 0, 0, 0 };
238 static constexpr u32 result[4] { 0x59ed3f2b, 0xb1a0aaa0, 0x7c9f56c6, 0xa504647b };
239
240 Crypto::Authentication::galois_multiply(z, x, y);
241 EXPECT(memcmp(result, z, 4 * sizeof(u32)) == 0);
242}
243
244TEST_CASE(test_ghash_galois_field_multiply2)
245{
246 u32 x[4] { 59300558, 1622582162, 4079534777, 1907555960 },
247 y[4] { 1726565332, 4018809915, 2286746201, 3392416558 }, z[4];
248 constexpr static u32 result[4] { 1580123974, 2440061576, 746958952, 1398005431 };
249
250 Crypto::Authentication::galois_multiply(z, x, y);
251 EXPECT(memcmp(result, z, 4 * sizeof(u32)) == 0);
252}