• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 11844561993

14 Nov 2024 07:58PM UTC coverage: 91.178% (+0.1%) from 91.072%
11844561993

Pull #4435

github

web-flow
Merge 81dcb29da into e430f157a
Pull Request #4435: Test duration values ​​are now presented in seconds with six digits of precision. Tests without time measurements have been edited.

91856 of 100744 relevant lines covered (91.18%)

9311006.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.83
/src/tests/test_rsa.cpp
1
/*
2
* (C) 2014,2015 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "test_rng.h"
8
#include "tests.h"
9

10
#if defined(BOTAN_HAS_RSA)
11
   #include "test_pubkey.h"
12
   #include <botan/rsa.h>
13
#endif
14

15
namespace Botan_Tests {
16

17
namespace {
18

19
#if defined(BOTAN_HAS_RSA)
20

21
std::unique_ptr<Botan::Private_Key> load_rsa_private_key(const VarMap& vars) {
425✔
22
   const BigInt p = vars.get_req_bn("P");
425✔
23
   const BigInt q = vars.get_req_bn("Q");
425✔
24
   const BigInt e = vars.get_req_bn("E");
425✔
25

26
   return std::make_unique<Botan::RSA_PrivateKey>(p, q, e);
425✔
27
}
1,275✔
28

29
std::unique_ptr<Botan::Public_Key> load_rsa_public_key(const VarMap& vars) {
503✔
30
   const BigInt n = vars.get_req_bn("N");
503✔
31
   const BigInt e = vars.get_req_bn("E");
503✔
32

33
   return std::make_unique<Botan::RSA_PublicKey>(n, e);
1,006✔
34
}
1,006✔
35

36
class RSA_ES_KAT_Tests final : public PK_Encryption_Decryption_Test {
37
   public:
38
      RSA_ES_KAT_Tests() : PK_Encryption_Decryption_Test("RSA", "pubkey/rsaes.vec", "E,P,Q,Msg,Ciphertext", "Nonce") {}
2✔
39

40
      std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) override {
123✔
41
         return load_rsa_private_key(vars);
123✔
42
      }
43
};
44

45
class RSA_Decryption_KAT_Tests final : public PK_Decryption_Test {
46
   public:
47
      RSA_Decryption_KAT_Tests() : PK_Decryption_Test("RSA", "pubkey/rsa_decrypt.vec", "E,P,Q,Ciphertext,Msg") {}
2✔
48

49
      bool clear_between_callbacks() const override { return false; }
25✔
50

51
      std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) override {
25✔
52
         return load_rsa_private_key(vars);
25✔
53
      }
54
};
55

56
class RSA_KEM_Tests final : public PK_KEM_Test {
57
   public:
58
      RSA_KEM_Tests() : PK_KEM_Test("RSA", "pubkey/rsa_kem.vec", "E,P,Q,R,C0,KDF,K") {}
2✔
59

60
      std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) override {
10✔
61
         return load_rsa_private_key(vars);
10✔
62
      }
63
};
64

65
class RSA_Signature_KAT_Tests final : public PK_Signature_Generation_Test {
66
   public:
67
      RSA_Signature_KAT_Tests() :
1✔
68
            PK_Signature_Generation_Test("RSA", "pubkey/rsa_sig.vec", "E,P,Q,Msg,Signature", "Nonce") {}
2✔
69

70
      std::string default_padding(const VarMap& /*unused*/) const override { return "Raw"; }
×
71

72
      std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) override {
107✔
73
         return load_rsa_private_key(vars);
107✔
74
      }
75
};
76

77
class RSA_PSS_KAT_Tests final : public PK_Signature_Generation_Test {
78
   public:
79
      RSA_PSS_KAT_Tests() :
1✔
80
            PK_Signature_Generation_Test("RSA", "pubkey/rsa_pss.vec", "P,Q,E,Hash,Nonce,Msg,Signature", "") {}
2✔
81

82
      std::string default_padding(const VarMap& vars) const override {
80✔
83
         const std::string hash_name = vars.get_req_str("Hash");
80✔
84
         const size_t salt_size = vars.get_req_bin("Nonce").size();
160✔
85
         return "PSSR(" + hash_name + ",MGF1," + std::to_string(salt_size) + ")";
240✔
86
      }
80✔
87

88
      bool clear_between_callbacks() const override { return false; }
80✔
89

90
      std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) override {
80✔
91
         return load_rsa_private_key(vars);
80✔
92
      }
93
};
94

95
class RSA_PSS_Raw_KAT_Tests final : public PK_Signature_Generation_Test {
96
   public:
97
      RSA_PSS_Raw_KAT_Tests() :
1✔
98
            PK_Signature_Generation_Test("RSA", "pubkey/rsa_pss_raw.vec", "P,Q,E,Hash,Nonce,Msg,Signature", "") {}
2✔
99

100
      std::string default_padding(const VarMap& vars) const override {
80✔
101
         const std::string hash_name = vars.get_req_str("Hash");
80✔
102
         const size_t salt_size = vars.get_req_bin("Nonce").size();
160✔
103
         return "PSSR_Raw(" + hash_name + ",MGF1," + std::to_string(salt_size) + ")";
240✔
104
      }
80✔
105

106
      bool clear_between_callbacks() const override { return false; }
80✔
107

108
      std::unique_ptr<Botan::Private_Key> load_private_key(const VarMap& vars) override {
80✔
109
         return load_rsa_private_key(vars);
80✔
110
      }
111
};
112

113
class RSA_Signature_Verify_Tests final : public PK_Signature_Verification_Test {
114
   public:
115
      RSA_Signature_Verify_Tests() :
1✔
116
            PK_Signature_Verification_Test("RSA", "pubkey/rsa_verify.vec", "E,N,Msg,Signature") {}
2✔
117

118
      std::string default_padding(const VarMap& /*unused*/) const override { return "Raw"; }
×
119

120
      std::unique_ptr<Botan::Public_Key> load_public_key(const VarMap& vars) override {
137✔
121
         return load_rsa_public_key(vars);
137✔
122
      }
123
};
124

125
class RSA_Signature_Verify_Invalid_Tests final : public PK_Signature_NonVerification_Test {
126
   public:
127
      RSA_Signature_Verify_Invalid_Tests() :
1✔
128
            PK_Signature_NonVerification_Test("RSA", "pubkey/rsa_invalid.vec", "E,N,Msg,InvalidSignature") {}
2✔
129

130
      std::string default_padding(const VarMap& /*unused*/) const override { return "Raw"; }
×
131

132
      std::unique_ptr<Botan::Public_Key> load_public_key(const VarMap& vars) override {
366✔
133
         return load_rsa_public_key(vars);
366✔
134
      }
135
};
136

137
class RSA_Keygen_Tests final : public PK_Key_Generation_Test {
×
138
   public:
139
      std::vector<std::string> keygen_params() const override { return {"1024", "1280"}; }
1✔
140

141
      std::unique_ptr<Botan::Public_Key> public_key_from_raw(std::string_view /* keygen_params */,
×
142
                                                             std::string_view /* provider */,
143
                                                             std::span<const uint8_t> /* raw_pk */) const override {
144
         // RSA does not implement raw public key encoding
145
         return nullptr;
×
146
      }
147

148
      std::string algo_name() const override { return "RSA"; }
2✔
149
};
150

151
class RSA_Keygen_Stability_Tests final : public PK_Key_Generation_Stability_Test {
152
   public:
153
      RSA_Keygen_Stability_Tests() : PK_Key_Generation_Stability_Test("RSA", "pubkey/rsa_keygen.vec") {}
2✔
154
};
155

156
class RSA_Keygen_Bad_RNG_Test final : public Test {
×
157
   public:
158
      std::vector<Test::Result> run() override {
1✔
159
         Test::Result result("RSA keygen with bad RNG");
1✔
160
         result.start_timer();
1✔
161

162
         /*
163
         We don't need to count requests here; actually this test
164
         is relying on the fact that the Request_Counting_RNG outputs
165
         repeating 808080...
166
         */
167
         Request_Counting_RNG rng;
1✔
168

169
         try {
1✔
170
            Botan::RSA_PrivateKey rsa(rng, 1024);
1✔
171
            result.test_failure("Generated a key with a bad RNG");
×
172
         } catch(Botan::Internal_Error& e) {
1✔
173
            result.test_success("Key generation with bad RNG failed");
1✔
174
            result.test_eq("Expected message", e.what(), "Internal error: RNG failure during RSA key generation");
1✔
175
         }
1✔
176

177
         result.end_timer();
1✔
178
         return {result};
2✔
179
      }
2✔
180
};
181

182
class RSA_Blinding_Tests final : public Test {
×
183
   public:
184
      std::vector<Test::Result> run() override {
1✔
185
         Test::Result result("RSA blinding");
1✔
186
         result.start_timer();
1✔
187

188
         /* This test makes only sense with the base provider, else skip it. */
189
         if(provider_filter({"base"}).empty()) {
1✔
190
            result.note_missing("base provider");
×
191
            return std::vector<Test::Result>{result};
×
192
         }
193

194
   #if defined(BOTAN_HAS_EMSA_RAW) || defined(BOTAN_HAS_EME_RAW)
195
         Botan::RSA_PrivateKey rsa(this->rng(), 1024);
1✔
196
         Botan::Null_RNG null_rng;
1✔
197
   #endif
198

199
   #if defined(BOTAN_HAS_EMSA_RAW)
200

201
         /*
202
         * The blinder chooses a new starting point BOTAN_BLINDING_REINIT_INTERVAL
203
         * so sign several times that with a single key.
204
         *
205
         * Very small values (padding/hashing disabled, only low byte set on input)
206
         * are used as an additional test on the blinders.
207
         */
208

209
         Botan::PK_Signer signer(
1✔
210
            rsa, this->rng(), "Raw", Botan::Signature_Format::Standard, "base");  // don't try this at home
1✔
211
         Botan::PK_Verifier verifier(rsa, "Raw", Botan::Signature_Format::Standard, "base");
1✔
212

213
         for(size_t i = 1; i <= BOTAN_BLINDING_REINIT_INTERVAL * 6; ++i) {
385✔
214
            std::vector<uint8_t> input(16);
384✔
215
            input[input.size() - 1] = static_cast<uint8_t>(i | 1);
384✔
216

217
            signer.update(input);
384✔
218

219
            // assert RNG is not called in this situation
220
            std::vector<uint8_t> signature = signer.signature(null_rng);
384✔
221

222
            result.test_eq("Signature verifies", verifier.verify_message(input, signature), true);
768✔
223
         }
768✔
224
   #endif
225

226
   #if defined(BOTAN_HAS_EME_RAW)
227

228
         /*
229
         * The blinder chooses a new starting point BOTAN_BLINDING_REINIT_INTERVAL
230
         * so decrypt several times that with a single key.
231
         *
232
         * Very small values (padding/hashing disabled, only low byte set on input)
233
         * are used as an additional test on the blinders.
234
         */
235

236
         Botan::PK_Encryptor_EME encryptor(rsa, this->rng(), "Raw", "base");  // don't try this at home
1✔
237

238
         /*
239
         Test blinding reinit interval
240

241
         Seed Fixed_Output_RNG only with enough bytes for the initial
242
         blinder initialization plus the exponent blinding bits which
243
         is 2*64 bits per operation.
244
         */
245
         const size_t rng_bytes = rsa.get_n().bytes() + (2 * 8 * BOTAN_BLINDING_REINIT_INTERVAL);
1✔
246

247
         Fixed_Output_RNG fixed_rng(this->rng(), rng_bytes);
1✔
248
         Botan::PK_Decryptor_EME decryptor(rsa, fixed_rng, "Raw", "base");
1✔
249

250
         for(size_t i = 1; i <= BOTAN_BLINDING_REINIT_INTERVAL; ++i) {
65✔
251
            std::vector<uint8_t> input(16);
64✔
252
            input[input.size() - 1] = static_cast<uint8_t>(i);
64✔
253

254
            std::vector<uint8_t> ciphertext = encryptor.encrypt(input, null_rng);
64✔
255

256
            std::vector<uint8_t> plaintext = Botan::unlock(decryptor.decrypt(ciphertext));
64✔
257
            plaintext.insert(plaintext.begin(), input.size() - 1, 0);
64✔
258

259
            result.test_eq("Successful decryption", plaintext, input);
128✔
260
         }
192✔
261

262
         result.test_eq("RNG is no longer seeded", fixed_rng.is_seeded(), false);
1✔
263

264
         // one more decryption should trigger a blinder reinitialization
265
         result.test_throws("RSA blinding reinit",
2✔
266
                            "Test error Fixed output RNG ran out of bytes, test bug?",
267
                            [&decryptor, &encryptor, &null_rng]() {
1✔
268
                               std::vector<uint8_t> ciphertext =
1✔
269
                                  encryptor.encrypt(std::vector<uint8_t>(16, 5), null_rng);
1✔
270
                               decryptor.decrypt(ciphertext);
1✔
271
                            });
×
272

273
   #endif
274

275
         result.end_timer();
1✔
276
         return std::vector<Test::Result>{result};
2✔
277
      }
2✔
278
};
279

280
BOTAN_REGISTER_TEST("pubkey", "rsa_encrypt", RSA_ES_KAT_Tests);
281
BOTAN_REGISTER_TEST("pubkey", "rsa_decrypt", RSA_Decryption_KAT_Tests);
282
BOTAN_REGISTER_TEST("pubkey", "rsa_sign", RSA_Signature_KAT_Tests);
283
BOTAN_REGISTER_TEST("pubkey", "rsa_pss", RSA_PSS_KAT_Tests);
284
BOTAN_REGISTER_TEST("pubkey", "rsa_pss_raw", RSA_PSS_Raw_KAT_Tests);
285
BOTAN_REGISTER_TEST("pubkey", "rsa_verify", RSA_Signature_Verify_Tests);
286
BOTAN_REGISTER_TEST("pubkey", "rsa_verify_invalid", RSA_Signature_Verify_Invalid_Tests);
287
BOTAN_REGISTER_TEST("pubkey", "rsa_kem", RSA_KEM_Tests);
288
BOTAN_REGISTER_TEST("pubkey", "rsa_keygen", RSA_Keygen_Tests);
289
BOTAN_REGISTER_TEST("pubkey", "rsa_keygen_stability", RSA_Keygen_Stability_Tests);
290
BOTAN_REGISTER_TEST("pubkey", "rsa_keygen_badrng", RSA_Keygen_Bad_RNG_Test);
291
BOTAN_REGISTER_TEST("pubkey", "rsa_blinding", RSA_Blinding_Tests);
292

293
#endif
294

295
}  // namespace
296

297
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc