/src/serenity/Userland/Libraries/LibCrypto/PK/RSA.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <AK/Debug.h> |
8 | | #include <AK/Random.h> |
9 | | #include <AK/ScopeGuard.h> |
10 | | #include <LibCrypto/ASN1/ASN1.h> |
11 | | #include <LibCrypto/ASN1/DER.h> |
12 | | #include <LibCrypto/ASN1/PEM.h> |
13 | | #include <LibCrypto/PK/RSA.h> |
14 | | |
15 | | namespace Crypto::PK { |
16 | | |
17 | | static constexpr Array<int, 7> pkcs8_rsa_key_oid { 1, 2, 840, 113549, 1, 1, 1 }; |
18 | | |
19 | | RSA::KeyPairType RSA::parse_rsa_key(ReadonlyBytes der) |
20 | 3.05k | { |
21 | | // we are going to assign to at least one of these |
22 | 3.05k | KeyPairType keypair; |
23 | | |
24 | 3.05k | ASN1::Decoder decoder(der); |
25 | | // There are four possible (supported) formats: |
26 | | // PKCS#1 private key |
27 | | // PKCS#1 public key |
28 | | // PKCS#8 private key |
29 | | // PKCS#8 public key |
30 | | |
31 | | // They're all a single sequence, so let's check that first |
32 | 3.05k | { |
33 | 3.05k | auto result = decoder.peek(); |
34 | 3.05k | if (result.is_error()) { |
35 | | // Bad data. |
36 | 48 | dbgln_if(RSA_PARSE_DEBUG, "RSA key parse failed: {}", result.error()); |
37 | 48 | return keypair; |
38 | 48 | } |
39 | 3.00k | auto tag = result.value(); |
40 | 3.00k | if (tag.kind != ASN1::Kind::Sequence) { |
41 | 57 | dbgln_if(RSA_PARSE_DEBUG, "RSA key parse failed: Expected a Sequence but got {}", ASN1::kind_name(tag.kind)); |
42 | 57 | return keypair; |
43 | 57 | } |
44 | 3.00k | } |
45 | | |
46 | | // Then enter the sequence |
47 | 2.94k | { |
48 | 2.94k | auto error = decoder.enter(); |
49 | 2.94k | if (error.is_error()) { |
50 | | // Something was weird with the input. |
51 | 151 | dbgln_if(RSA_PARSE_DEBUG, "RSA key parse failed: {}", error.error()); |
52 | 151 | return keypair; |
53 | 151 | } |
54 | 2.94k | } |
55 | | |
56 | 2.79k | bool has_read_error = false; |
57 | | |
58 | 2.79k | auto const check_if_pkcs8_rsa_key = [&] { |
59 | | // see if it's a sequence: |
60 | 2.79k | auto tag_result = decoder.peek(); |
61 | 2.79k | if (tag_result.is_error()) { |
62 | | // Decode error :shrug: |
63 | 242 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 public key parse failed: {}", tag_result.error()); |
64 | 242 | return false; |
65 | 242 | } |
66 | | |
67 | 2.55k | auto tag = tag_result.value(); |
68 | 2.55k | if (tag.kind != ASN1::Kind::Sequence) { |
69 | | // We don't know what this is, but it sure isn't a PKCS#8 key. |
70 | 1.54k | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 public key parse failed: Expected a Sequence but got {}", ASN1::kind_name(tag.kind)); |
71 | 1.54k | return false; |
72 | 1.54k | } |
73 | | |
74 | | // It's a sequence, now let's see if it's actually an RSA key. |
75 | 1.00k | auto error = decoder.enter(); |
76 | 1.00k | if (error.is_error()) { |
77 | | // Shenanigans! |
78 | 50 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 public key parse failed: {}", error.error()); |
79 | 50 | return false; |
80 | 50 | } |
81 | | |
82 | 957 | ScopeGuard leave { [&] { |
83 | 957 | auto error = decoder.leave(); |
84 | 957 | if (error.is_error()) { |
85 | 0 | dbgln_if(RSA_PARSE_DEBUG, "RSA key parse failed: {}", error.error()); |
86 | 0 | has_read_error = true; |
87 | 0 | } |
88 | 957 | } }; |
89 | | |
90 | | // Now let's read the OID. |
91 | 957 | auto oid_result = decoder.read<Vector<int>>(); |
92 | 957 | if (oid_result.is_error()) { |
93 | 347 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 public key parse failed: {}", oid_result.error()); |
94 | 347 | return false; |
95 | 347 | } |
96 | | |
97 | 610 | auto oid = oid_result.release_value(); |
98 | | // Now let's check that the OID matches "RSA key" |
99 | 610 | if (oid != pkcs8_rsa_key_oid) { |
100 | | // Oh well. not an RSA key at all. |
101 | 171 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 public key parse failed: Not an RSA key"); |
102 | 171 | return false; |
103 | 171 | } |
104 | | |
105 | 439 | return true; |
106 | 610 | }; |
107 | | |
108 | 2.79k | auto integer_result = decoder.read<UnsignedBigInteger>(); |
109 | | |
110 | 2.79k | if (!integer_result.is_error()) { |
111 | 1.93k | auto first_integer = integer_result.release_value(); |
112 | | |
113 | | // It's either a PKCS#1 key, or a PKCS#8 private key. |
114 | | // Check for the PKCS#8 private key right away. |
115 | 1.93k | if (check_if_pkcs8_rsa_key()) { |
116 | 299 | if (has_read_error) |
117 | 0 | return keypair; |
118 | | // Now read the private key, which is actually an octet string containing the PKCS#1 encoded private key. |
119 | 299 | auto data_result = decoder.read<StringView>(); |
120 | 299 | if (data_result.is_error()) { |
121 | 29 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 private key parse failed: {}", data_result.error()); |
122 | 29 | return keypair; |
123 | 29 | } |
124 | 270 | return parse_rsa_key(data_result.value().bytes()); |
125 | 299 | } |
126 | | |
127 | 1.63k | if (has_read_error) |
128 | 0 | return keypair; |
129 | | |
130 | | // It's not a PKCS#8 key, so it's a PKCS#1 key (or something we don't support) |
131 | | // if the first integer is zero or one, it's a private key. |
132 | 1.63k | if (first_integer == 0) { |
133 | | // This is a private key, parse the rest. |
134 | 826 | auto modulus_result = decoder.read<UnsignedBigInteger>(); |
135 | 826 | auto public_exponent_result = decoder.read<UnsignedBigInteger>(); |
136 | 826 | auto private_exponent_result = decoder.read<UnsignedBigInteger>(); |
137 | 826 | auto prime1_result = decoder.read<UnsignedBigInteger>(); |
138 | 826 | auto prime2_result = decoder.read<UnsignedBigInteger>(); |
139 | 826 | auto exponent1_result = decoder.read<UnsignedBigInteger>(); |
140 | 826 | auto exponent2_result = decoder.read<UnsignedBigInteger>(); |
141 | 826 | auto coefficient_result = decoder.read<UnsignedBigInteger>(); |
142 | | |
143 | 826 | Array results = { &modulus_result, &public_exponent_result, &private_exponent_result, &prime1_result, &prime2_result, &exponent1_result, &exponent2_result, &coefficient_result }; |
144 | 3.74k | for (auto& result : results) { |
145 | 3.74k | if (result->is_error()) { |
146 | 455 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#1 private key parse failed: {}", result->error()); |
147 | 455 | return keypair; |
148 | 455 | } |
149 | 3.74k | } |
150 | | |
151 | 371 | keypair.private_key = { |
152 | 371 | modulus_result.value(), |
153 | 371 | private_exponent_result.release_value(), |
154 | 371 | public_exponent_result.value(), |
155 | 371 | prime1_result.release_value(), |
156 | 371 | prime2_result.release_value(), |
157 | 371 | exponent1_result.release_value(), |
158 | 371 | exponent2_result.release_value(), |
159 | 371 | coefficient_result.release_value(), |
160 | 371 | }; |
161 | 371 | keypair.public_key = { modulus_result.release_value(), public_exponent_result.release_value() }; |
162 | | |
163 | 371 | return keypair; |
164 | 826 | } |
165 | | |
166 | 809 | if (first_integer == 1) { |
167 | | // This is a multi-prime key, we don't support that. |
168 | 89 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#1 private key parse failed: Multi-prime key not supported"); |
169 | 89 | return keypair; |
170 | 89 | } |
171 | | |
172 | 720 | auto&& modulus = move(first_integer); |
173 | | |
174 | | // Try reading a public key, `first_integer` is the modulus. |
175 | 720 | auto public_exponent_result = decoder.read<UnsignedBigInteger>(); |
176 | 720 | if (public_exponent_result.is_error()) { |
177 | | // Bad public key. |
178 | 358 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#1 public key parse failed: {}", public_exponent_result.error()); |
179 | 358 | return keypair; |
180 | 358 | } |
181 | | |
182 | 362 | auto public_exponent = public_exponent_result.release_value(); |
183 | 362 | keypair.public_key.set(move(modulus), move(public_exponent)); |
184 | | |
185 | 362 | return keypair; |
186 | 720 | } |
187 | | |
188 | | // It wasn't a PKCS#1 key, let's try our luck with PKCS#8. |
189 | 864 | if (!check_if_pkcs8_rsa_key()) |
190 | 724 | return keypair; |
191 | | |
192 | 140 | if (has_read_error) |
193 | 0 | return keypair; |
194 | | |
195 | | // Now we have a bit string, which contains the PKCS#1 encoded public key. |
196 | 140 | auto data_result = decoder.read<BitmapView>(); |
197 | 140 | if (data_result.is_error()) { |
198 | 140 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#8 public key parse failed: {}", data_result.error()); |
199 | 140 | return keypair; |
200 | 140 | } |
201 | | |
202 | | // Now just read it as a PKCS#1 DER. |
203 | 0 | auto data = data_result.release_value(); |
204 | | // FIXME: This is pretty awkward, maybe just generate a zero'd out ByteBuffer from the parser instead? |
205 | 0 | auto padded_data_result = ByteBuffer::create_zeroed(data.size_in_bytes()); |
206 | 0 | if (padded_data_result.is_error()) { |
207 | 0 | dbgln_if(RSA_PARSE_DEBUG, "RSA PKCS#1 key parse failed: Not enough memory"); |
208 | 0 | return keypair; |
209 | 0 | } |
210 | 0 | auto padded_data = padded_data_result.release_value(); |
211 | 0 | padded_data.overwrite(0, data.data(), data.size_in_bytes()); |
212 | |
|
213 | 0 | return parse_rsa_key(padded_data.bytes()); |
214 | 0 | } |
215 | | |
216 | | void RSA::encrypt(ReadonlyBytes in, Bytes& out) |
217 | 0 | { |
218 | 0 | dbgln_if(CRYPTO_DEBUG, "in size: {}", in.size()); |
219 | 0 | auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size()); |
220 | 0 | if (!(in_integer < m_public_key.modulus())) { |
221 | 0 | dbgln("value too large for key"); |
222 | 0 | out = {}; |
223 | 0 | return; |
224 | 0 | } |
225 | 0 | auto exp = NumberTheory::ModularPower(in_integer, m_public_key.public_exponent(), m_public_key.modulus()); |
226 | 0 | auto size = exp.export_data(out); |
227 | 0 | auto outsize = out.size(); |
228 | 0 | if (size != outsize) { |
229 | 0 | dbgln("POSSIBLE RSA BUG!!! Size mismatch: {} requested but {} bytes generated", outsize, size); |
230 | 0 | out = out.slice(outsize - size, size); |
231 | 0 | } |
232 | 0 | } |
233 | | |
234 | | void RSA::decrypt(ReadonlyBytes in, Bytes& out) |
235 | 0 | { |
236 | | // FIXME: Actually use the private key properly |
237 | |
|
238 | 0 | auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size()); |
239 | 0 | auto exp = NumberTheory::ModularPower(in_integer, m_private_key.private_exponent(), m_private_key.modulus()); |
240 | 0 | auto size = exp.export_data(out); |
241 | |
|
242 | 0 | auto align = m_private_key.length(); |
243 | 0 | auto aligned_size = (size + align - 1) / align * align; |
244 | |
|
245 | 0 | for (auto i = size; i < aligned_size; ++i) |
246 | 0 | out[out.size() - i - 1] = 0; // zero the non-aligned values |
247 | 0 | out = out.slice(out.size() - aligned_size, aligned_size); |
248 | 0 | } |
249 | | |
250 | | void RSA::sign(ReadonlyBytes in, Bytes& out) |
251 | 0 | { |
252 | 0 | auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size()); |
253 | 0 | auto exp = NumberTheory::ModularPower(in_integer, m_private_key.private_exponent(), m_private_key.modulus()); |
254 | 0 | auto size = exp.export_data(out); |
255 | 0 | out = out.slice(out.size() - size, size); |
256 | 0 | } |
257 | | |
258 | | void RSA::verify(ReadonlyBytes in, Bytes& out) |
259 | 0 | { |
260 | 0 | auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size()); |
261 | 0 | auto exp = NumberTheory::ModularPower(in_integer, m_public_key.public_exponent(), m_public_key.modulus()); |
262 | 0 | auto size = exp.export_data(out); |
263 | 0 | out = out.slice(out.size() - size, size); |
264 | 0 | } |
265 | | |
266 | | void RSA::import_private_key(ReadonlyBytes bytes, bool pem) |
267 | 0 | { |
268 | 0 | ByteBuffer buffer; |
269 | 0 | if (pem) { |
270 | 0 | buffer = decode_pem(bytes); |
271 | 0 | bytes = buffer; |
272 | 0 | } |
273 | |
|
274 | 0 | auto key = parse_rsa_key(bytes); |
275 | 0 | if (!key.private_key.length()) { |
276 | 0 | dbgln("We expected to see a private key, but we found none"); |
277 | 0 | VERIFY_NOT_REACHED(); |
278 | 0 | } |
279 | 0 | m_private_key = key.private_key; |
280 | 0 | } |
281 | | |
282 | | void RSA::import_public_key(ReadonlyBytes bytes, bool pem) |
283 | 0 | { |
284 | 0 | ByteBuffer buffer; |
285 | 0 | if (pem) { |
286 | 0 | buffer = decode_pem(bytes); |
287 | 0 | bytes = buffer; |
288 | 0 | } |
289 | |
|
290 | 0 | auto key = parse_rsa_key(bytes); |
291 | 0 | if (!key.public_key.length()) { |
292 | 0 | dbgln("We expected to see a public key, but we found none"); |
293 | 0 | VERIFY_NOT_REACHED(); |
294 | 0 | } |
295 | 0 | m_public_key = key.public_key; |
296 | 0 | } |
297 | | |
298 | | void RSA_PKCS1_EME::encrypt(ReadonlyBytes in, Bytes& out) |
299 | 0 | { |
300 | 0 | auto mod_len = (m_public_key.modulus().trimmed_length() * sizeof(u32) * 8 + 7) / 8; |
301 | 0 | dbgln_if(CRYPTO_DEBUG, "key size: {}", mod_len); |
302 | 0 | if (in.size() > mod_len - 11) { |
303 | 0 | dbgln("message too long :("); |
304 | 0 | out = out.trim(0); |
305 | 0 | return; |
306 | 0 | } |
307 | 0 | if (out.size() < mod_len) { |
308 | 0 | dbgln("output buffer too small"); |
309 | 0 | return; |
310 | 0 | } |
311 | | |
312 | 0 | auto ps_length = mod_len - in.size() - 3; |
313 | 0 | Vector<u8, 8096> ps; |
314 | 0 | ps.resize(ps_length); |
315 | |
|
316 | 0 | fill_with_random(ps); |
317 | | // since fill_with_random can create zeros (shocking!) |
318 | | // we have to go through and un-zero the zeros |
319 | 0 | for (size_t i = 0; i < ps_length; ++i) { |
320 | 0 | while (!ps[i]) |
321 | 0 | ps[i] = get_random<u8>(); |
322 | 0 | } |
323 | |
|
324 | 0 | u8 paddings[] { 0x00, 0x02 }; |
325 | |
|
326 | 0 | out.overwrite(0, paddings, 2); |
327 | 0 | out.overwrite(2, ps.data(), ps_length); |
328 | 0 | out.overwrite(2 + ps_length, paddings, 1); |
329 | 0 | out.overwrite(3 + ps_length, in.data(), in.size()); |
330 | 0 | out = out.trim(3 + ps_length + in.size()); // should be a single block |
331 | |
|
332 | 0 | dbgln_if(CRYPTO_DEBUG, "padded output size: {} buffer size: {}", 3 + ps_length + in.size(), out.size()); |
333 | |
|
334 | 0 | RSA::encrypt(out, out); |
335 | 0 | } |
336 | | void RSA_PKCS1_EME::decrypt(ReadonlyBytes in, Bytes& out) |
337 | 0 | { |
338 | 0 | auto mod_len = (m_public_key.modulus().trimmed_length() * sizeof(u32) * 8 + 7) / 8; |
339 | 0 | if (in.size() != mod_len) { |
340 | 0 | dbgln("decryption error: wrong amount of data: {}", in.size()); |
341 | 0 | out = out.trim(0); |
342 | 0 | return; |
343 | 0 | } |
344 | | |
345 | 0 | RSA::decrypt(in, out); |
346 | |
|
347 | 0 | if (out.size() < RSA::output_size()) { |
348 | 0 | dbgln("decryption error: not enough data after decryption: {}", out.size()); |
349 | 0 | out = out.trim(0); |
350 | 0 | return; |
351 | 0 | } |
352 | | |
353 | 0 | if (out[0] != 0x00) { |
354 | 0 | dbgln("invalid padding byte 0 : {}", out[0]); |
355 | 0 | return; |
356 | 0 | } |
357 | | |
358 | 0 | if (out[1] != 0x02) { |
359 | 0 | dbgln("invalid padding byte 1 : {}", out[1]); |
360 | 0 | return; |
361 | 0 | } |
362 | | |
363 | 0 | size_t offset = 2; |
364 | 0 | while (offset < out.size() && out[offset]) |
365 | 0 | ++offset; |
366 | |
|
367 | 0 | if (offset == out.size()) { |
368 | 0 | dbgln("garbage data, no zero to split padding"); |
369 | 0 | return; |
370 | 0 | } |
371 | | |
372 | 0 | ++offset; |
373 | |
|
374 | 0 | if (offset - 3 < 8) { |
375 | 0 | dbgln("PS too small"); |
376 | 0 | return; |
377 | 0 | } |
378 | | |
379 | 0 | out = out.slice(offset, out.size() - offset); |
380 | 0 | } |
381 | | |
382 | | void RSA_PKCS1_EME::sign(ReadonlyBytes, Bytes&) |
383 | 0 | { |
384 | 0 | dbgln("FIXME: RSA_PKCS_EME::sign"); |
385 | 0 | } |
386 | | void RSA_PKCS1_EME::verify(ReadonlyBytes, Bytes&) |
387 | 0 | { |
388 | 0 | dbgln("FIXME: RSA_PKCS_EME::verify"); |
389 | 0 | } |
390 | | } |