Coverage Report

Created: 2025-12-18 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}