/src/serenity/Userland/Libraries/LibCrypto/PK/RSA.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org> |
3 | | * Copyright (c) 2022, the SerenityOS developers. |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #pragma once |
9 | | |
10 | | #include <AK/Span.h> |
11 | | #include <LibCrypto/ASN1/DER.h> |
12 | | #include <LibCrypto/BigInt/UnsignedBigInteger.h> |
13 | | #include <LibCrypto/NumberTheory/ModularFunctions.h> |
14 | | #include <LibCrypto/PK/PK.h> |
15 | | |
16 | | namespace Crypto::PK { |
17 | | |
18 | | template<typename Integer = UnsignedBigInteger> |
19 | | class RSAPublicKey { |
20 | | public: |
21 | | RSAPublicKey(Integer n, Integer e) |
22 | 352 | : m_modulus(move(n)) |
23 | 352 | , m_public_exponent(move(e)) |
24 | 352 | , m_length(m_modulus.trimmed_length() * sizeof(u32)) |
25 | 352 | { |
26 | 352 | } |
27 | | |
28 | | RSAPublicKey() |
29 | 6.72k | : m_modulus(0) |
30 | 6.72k | , m_public_exponent(0) |
31 | 6.72k | { |
32 | 6.72k | } |
33 | | |
34 | 0 | Integer const& modulus() const { return m_modulus; } |
35 | 0 | Integer const& public_exponent() const { return m_public_exponent; } |
36 | 879 | size_t length() const { return m_length; } |
37 | | void set_length(size_t length) { m_length = length; } |
38 | | |
39 | | ErrorOr<ByteBuffer> export_as_der() const |
40 | 0 | { |
41 | 0 | ASN1::Encoder encoder; |
42 | 0 | TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> { |
43 | 0 | TRY(encoder.write(m_modulus)); |
44 | 0 | TRY(encoder.write(m_public_exponent)); |
45 | 0 | return {}; |
46 | 0 | })); |
47 | |
|
48 | 0 | return encoder.finish(); |
49 | 0 | } |
50 | | |
51 | | void set(Integer n, Integer e) |
52 | 432 | { |
53 | 432 | m_modulus = move(n); |
54 | 432 | m_public_exponent = move(e); |
55 | 432 | m_length = (m_modulus.trimmed_length() * sizeof(u32)); |
56 | 432 | } |
57 | | |
58 | | private: |
59 | | Integer m_modulus; |
60 | | Integer m_public_exponent; |
61 | | size_t m_length { 0 }; |
62 | | }; |
63 | | |
64 | | template<typename Integer = UnsignedBigInteger> |
65 | | class RSAPrivateKey { |
66 | | public: |
67 | | RSAPrivateKey(Integer n, Integer d, Integer e, Integer p, Integer q) |
68 | 0 | : m_modulus(move(n)) |
69 | 0 | , m_private_exponent(move(d)) |
70 | 0 | , m_public_exponent(move(e)) |
71 | 0 | , m_prime_1(move(p)) |
72 | 0 | , m_prime_2(move(q)) |
73 | 0 | , m_exponent_1(NumberTheory::Mod(m_private_exponent, m_prime_1.minus(1))) |
74 | 0 | , m_exponent_2(NumberTheory::Mod(m_private_exponent, m_prime_2.minus(1))) |
75 | 0 | , m_coefficient(NumberTheory::ModularInverse(m_prime_2, m_prime_1)) |
76 | 0 | , m_length(m_modulus.trimmed_length() * sizeof(u32)) |
77 | 0 | { |
78 | 0 | } |
79 | | |
80 | | RSAPrivateKey(Integer n, Integer d, Integer e, Integer p, Integer q, Integer dp, Integer dq, Integer qinv) |
81 | 352 | : m_modulus(move(n)) |
82 | 352 | , m_private_exponent(move(d)) |
83 | 352 | , m_public_exponent(move(e)) |
84 | 352 | , m_prime_1(move(p)) |
85 | 352 | , m_prime_2(move(q)) |
86 | 352 | , m_exponent_1(move(dp)) |
87 | 352 | , m_exponent_2(move(dq)) |
88 | 352 | , m_coefficient(move(qinv)) |
89 | 352 | , m_length(m_modulus.trimmed_length() * sizeof(u32)) |
90 | 352 | { |
91 | 352 | } |
92 | | |
93 | 5.64k | RSAPrivateKey() = default; |
94 | | |
95 | | static RSAPrivateKey from_crt(Integer n, Integer e, Integer p, Integer q, Integer dp, Integer dq, Integer qinv) |
96 | | { |
97 | | auto phi = p.minus(1).multiplied_by(q.minus(1)); |
98 | | auto d = NumberTheory::ModularInverse(e, phi); |
99 | | |
100 | | return { n, d, e, p, q, dp, dq, qinv }; |
101 | | } |
102 | | |
103 | 0 | Integer const& modulus() const { return m_modulus; } |
104 | 0 | Integer const& private_exponent() const { return m_private_exponent; } |
105 | 0 | Integer const& public_exponent() const { return m_public_exponent; } |
106 | 0 | Integer const& prime1() const { return m_prime_1; } |
107 | 0 | Integer const& prime2() const { return m_prime_2; } |
108 | 0 | Integer const& exponent1() const { return m_exponent_1; } |
109 | 0 | Integer const& exponent2() const { return m_exponent_2; } |
110 | 0 | Integer const& coefficient() const { return m_coefficient; } |
111 | 0 | size_t length() const { return m_length; } |
112 | | |
113 | | ErrorOr<ByteBuffer> export_as_der() const |
114 | 0 | { |
115 | 0 | ASN1::Encoder encoder; |
116 | 0 | TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> { |
117 | 0 | TRY(encoder.write(0x00u)); // version |
118 | 0 | TRY(encoder.write(m_modulus)); |
119 | 0 | TRY(encoder.write(m_public_exponent)); |
120 | 0 | TRY(encoder.write(m_private_exponent)); |
121 | 0 | TRY(encoder.write(m_prime_1)); |
122 | 0 | TRY(encoder.write(m_prime_2)); |
123 | 0 | TRY(encoder.write(m_exponent_1)); |
124 | 0 | TRY(encoder.write(m_exponent_2)); |
125 | 0 | TRY(encoder.write(m_coefficient)); |
126 | 0 | return {}; |
127 | 0 | })); |
128 | |
|
129 | 0 | return encoder.finish(); |
130 | 0 | } |
131 | | |
132 | | private: |
133 | | Integer m_modulus; |
134 | | Integer m_private_exponent; |
135 | | Integer m_public_exponent; |
136 | | Integer m_prime_1; |
137 | | Integer m_prime_2; |
138 | | Integer m_exponent_1; // d mod (p-1) |
139 | | Integer m_exponent_2; // d mod (q-1) |
140 | | Integer m_coefficient; // q^-1 mod p |
141 | | size_t m_length { 0 }; |
142 | | }; |
143 | | |
144 | | template<typename PubKey, typename PrivKey> |
145 | | struct RSAKeyPair { |
146 | | PubKey public_key; |
147 | | PrivKey private_key; |
148 | | }; |
149 | | |
150 | | using IntegerType = UnsignedBigInteger; |
151 | | class RSA : public PKSystem<RSAPrivateKey<IntegerType>, RSAPublicKey<IntegerType>> { |
152 | | public: |
153 | | using KeyPairType = RSAKeyPair<PublicKeyType, PrivateKeyType>; |
154 | | |
155 | | static KeyPairType parse_rsa_key(ReadonlyBytes der); |
156 | | static KeyPairType generate_key_pair(size_t bits = 256, IntegerType e = 65537) |
157 | 0 | { |
158 | 0 | IntegerType p; |
159 | 0 | IntegerType q; |
160 | 0 | IntegerType lambda; |
161 | 0 |
|
162 | 0 | do { |
163 | 0 | p = NumberTheory::random_big_prime(bits / 2); |
164 | 0 | q = NumberTheory::random_big_prime(bits / 2); |
165 | 0 | lambda = NumberTheory::LCM(p.minus(1), q.minus(1)); |
166 | 0 | } while (!(NumberTheory::GCD(e, lambda) == 1)); |
167 | 0 |
|
168 | 0 | auto n = p.multiplied_by(q); |
169 | 0 |
|
170 | 0 | auto d = NumberTheory::ModularInverse(e, lambda); |
171 | 0 | RSAKeyPair<PublicKeyType, PrivateKeyType> keys { |
172 | 0 | { n, e }, |
173 | 0 | { n, d, e, p, q } |
174 | 0 | }; |
175 | 0 | return keys; |
176 | 0 | } |
177 | | |
178 | | RSA(IntegerType n, IntegerType d, IntegerType e) |
179 | 0 | { |
180 | 0 | m_public_key.set(n, e); |
181 | 0 | m_private_key = { n, d, e, 0, 0, 0, 0, 0 }; |
182 | 0 | } |
183 | | |
184 | | RSA(PublicKeyType& pubkey, PrivateKeyType& privkey) |
185 | | : PKSystem<RSAPrivateKey<IntegerType>, RSAPublicKey<IntegerType>>(pubkey, privkey) |
186 | 0 | { |
187 | 0 | } |
188 | | |
189 | | RSA(ByteBuffer const& publicKeyPEM, ByteBuffer const& privateKeyPEM) |
190 | 0 | { |
191 | 0 | import_public_key(publicKeyPEM); |
192 | 0 | import_private_key(privateKeyPEM); |
193 | 0 | } |
194 | | |
195 | | RSA(StringView privKeyPEM) |
196 | 0 | { |
197 | 0 | import_private_key(privKeyPEM.bytes()); |
198 | 0 | m_public_key.set(m_private_key.modulus(), m_private_key.public_exponent()); |
199 | 0 | } |
200 | | |
201 | | // create our own keys |
202 | | RSA() |
203 | 0 | { |
204 | 0 | auto pair = generate_key_pair(); |
205 | 0 | m_public_key = pair.public_key; |
206 | 0 | m_private_key = pair.private_key; |
207 | 0 | } |
208 | | |
209 | | virtual void encrypt(ReadonlyBytes in, Bytes& out) override; |
210 | | virtual void decrypt(ReadonlyBytes in, Bytes& out) override; |
211 | | |
212 | | virtual void sign(ReadonlyBytes in, Bytes& out) override; |
213 | | virtual void verify(ReadonlyBytes in, Bytes& out) override; |
214 | | |
215 | | #ifndef KERNEL |
216 | | virtual ByteString class_name() const override |
217 | 0 | { |
218 | 0 | return "RSA"; |
219 | 0 | } |
220 | | #endif |
221 | | |
222 | | virtual size_t output_size() const override |
223 | 0 | { |
224 | 0 | return m_public_key.length(); |
225 | 0 | } |
226 | | |
227 | | void import_public_key(ReadonlyBytes, bool pem = true); |
228 | | void import_private_key(ReadonlyBytes, bool pem = true); |
229 | | |
230 | 0 | PrivateKeyType const& private_key() const { return m_private_key; } |
231 | 0 | PublicKeyType const& public_key() const { return m_public_key; } |
232 | | |
233 | 0 | void set_public_key(PublicKeyType const& key) { m_public_key = key; } |
234 | 0 | void set_private_key(PrivateKeyType const& key) { m_private_key = key; } |
235 | | }; |
236 | | |
237 | | class RSA_PKCS1_EME : public RSA { |
238 | | public: |
239 | | // forward all constructions to RSA |
240 | | template<typename... Args> |
241 | | RSA_PKCS1_EME(Args... args) |
242 | | : RSA(args...) |
243 | | { |
244 | | } |
245 | | |
246 | | ~RSA_PKCS1_EME() = default; |
247 | | |
248 | | virtual void encrypt(ReadonlyBytes in, Bytes& out) override; |
249 | | virtual void decrypt(ReadonlyBytes in, Bytes& out) override; |
250 | | |
251 | | virtual void sign(ReadonlyBytes, Bytes&) override; |
252 | | virtual void verify(ReadonlyBytes, Bytes&) override; |
253 | | |
254 | | #ifndef KERNEL |
255 | | virtual ByteString class_name() const override |
256 | 0 | { |
257 | 0 | return "RSA_PKCS1-EME"; |
258 | 0 | } |
259 | | #endif |
260 | | virtual size_t output_size() const override |
261 | 0 | { |
262 | 0 | return m_public_key.length(); |
263 | 0 | } |
264 | | }; |
265 | | } |