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

randombit / botan / 5124603749

30 May 2023 06:35PM UTC coverage: 91.964% (-0.008%) from 91.972%
5124603749

push

github

randombit
Remove reference to sublime config

75598 of 82204 relevant lines covered (91.96%)

12131188.77 hits per line

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

84.95
/src/lib/pubkey/mce/mceliece_key.cpp
1
/*
2
 * (C) Copyright Projet SECRET, INRIA, Rocquencourt
3
 * (C) Bhaskar Biswas and  Nicolas Sendrier
4
 *
5
 * (C) 2014 cryptosource GmbH
6
 * (C) 2014 Falko Strenzke fstrenzke@cryptosource.de
7
 * (C) 2015 Jack Lloyd
8
 *
9
 * Botan is released under the Simplified BSD License (see license.txt)
10
 *
11
 */
12

13
#include <botan/mceliece.h>
14

15
#include <botan/ber_dec.h>
16
#include <botan/der_enc.h>
17
#include <botan/rng.h>
18
#include <botan/internal/bit_ops.h>
19
#include <botan/internal/code_based_util.h>
20
#include <botan/internal/loadstor.h>
21
#include <botan/internal/mce_internal.h>
22
#include <botan/internal/pk_ops_impl.h>
23
#include <botan/internal/polyn_gf2m.h>
24

25
namespace Botan {
26

27
McEliece_PrivateKey::McEliece_PrivateKey(const McEliece_PrivateKey&) = default;
×
28
McEliece_PrivateKey::McEliece_PrivateKey(McEliece_PrivateKey&&) noexcept = default;
×
29
McEliece_PrivateKey& McEliece_PrivateKey::operator=(const McEliece_PrivateKey&) = default;
×
30
McEliece_PrivateKey& McEliece_PrivateKey::operator=(McEliece_PrivateKey&&) noexcept = default;
98✔
31
McEliece_PrivateKey::~McEliece_PrivateKey() = default;
670✔
32

33
McEliece_PrivateKey::McEliece_PrivateKey(const polyn_gf2m& goppa_polyn,
98✔
34
                                         const std::vector<uint32_t>& parity_check_matrix_coeffs,
35
                                         const std::vector<polyn_gf2m>& square_root_matrix,
36
                                         const std::vector<gf2m>& inverse_support,
37
                                         const std::vector<uint8_t>& public_matrix) :
98✔
38
      McEliece_PublicKey(public_matrix, goppa_polyn.get_degree(), inverse_support.size()),
98✔
39
      m_g{goppa_polyn},
196✔
40
      m_sqrtmod(square_root_matrix),
98✔
41
      m_Linv(inverse_support),
98✔
42
      m_coeffs(parity_check_matrix_coeffs),
98✔
43
      m_codimension(static_cast<size_t>(ceil_log2(inverse_support.size())) * goppa_polyn.get_degree()),
196✔
44
      m_dimension(inverse_support.size() - m_codimension) {}
196✔
45

46
McEliece_PrivateKey::McEliece_PrivateKey(RandomNumberGenerator& rng, size_t code_length, size_t t) {
98✔
47
   uint32_t ext_deg = ceil_log2(code_length);
98✔
48
   *this = generate_mceliece_key(rng, ext_deg, code_length, t);
98✔
49
}
98✔
50

51
const polyn_gf2m& McEliece_PrivateKey::get_goppa_polyn() const { return m_g[0]; }
10,584✔
52

53
size_t McEliece_PublicKey::get_message_word_bit_length() const {
10,414✔
54
   size_t codimension = ceil_log2(m_code_length) * m_t;
10,414✔
55
   return m_code_length - codimension;
10,414✔
56
}
57

58
secure_vector<uint8_t> McEliece_PublicKey::random_plaintext_element(RandomNumberGenerator& rng) const {
2,646✔
59
   const size_t bits = get_message_word_bit_length();
2,646✔
60

61
   secure_vector<uint8_t> plaintext((bits + 7) / 8);
2,646✔
62
   rng.randomize(plaintext.data(), plaintext.size());
2,646✔
63

64
   // unset unused bits in the last plaintext byte
65
   if(uint32_t used = bits % 8) {
2,646✔
66
      const uint8_t mask = (1 << used) - 1;
1,933✔
67
      plaintext[plaintext.size() - 1] &= mask;
1,933✔
68
   }
69

70
   return plaintext;
2,646✔
71
}
×
72

73
AlgorithmIdentifier McEliece_PublicKey::algorithm_identifier() const {
13✔
74
   return AlgorithmIdentifier(object_identifier(), AlgorithmIdentifier::USE_EMPTY_PARAM);
13✔
75
}
76

77
std::vector<uint8_t> McEliece_PublicKey::public_key_bits() const {
267✔
78
   std::vector<uint8_t> output;
267✔
79
   DER_Encoder(output)
534✔
80
      .start_sequence()
267✔
81
      .start_sequence()
267✔
82
      .encode(static_cast<size_t>(get_code_length()))
267✔
83
      .encode(static_cast<size_t>(get_t()))
267✔
84
      .end_cons()
267✔
85
      .encode(m_public_matrix, ASN1_Type::OctetString)
267✔
86
      .end_cons();
267✔
87
   return output;
267✔
88
}
×
89

90
size_t McEliece_PublicKey::key_length() const { return m_code_length; }
×
91

92
size_t McEliece_PublicKey::estimated_strength() const { return mceliece_work_factor(m_code_length, m_t); }
2✔
93

94
McEliece_PublicKey::McEliece_PublicKey(std::span<const uint8_t> key_bits) {
86✔
95
   BER_Decoder dec(key_bits);
86✔
96
   size_t n;
86✔
97
   size_t t;
86✔
98
   dec.start_sequence()
86✔
99
      .start_sequence()
172✔
100
      .decode(n)
86✔
101
      .decode(t)
86✔
102
      .end_cons()
86✔
103
      .decode(m_public_matrix, ASN1_Type::OctetString)
86✔
104
      .end_cons();
86✔
105
   m_t = t;
86✔
106
   m_code_length = n;
86✔
107
}
86✔
108

109
secure_vector<uint8_t> McEliece_PrivateKey::private_key_bits() const {
270✔
110
   DER_Encoder enc;
270✔
111
   enc.start_sequence()
270✔
112
      .start_sequence()
270✔
113
      .encode(static_cast<size_t>(get_code_length()))
270✔
114
      .encode(static_cast<size_t>(get_t()))
270✔
115
      .end_cons()
270✔
116
      .encode(m_public_matrix, ASN1_Type::OctetString)
270✔
117
      .encode(m_g[0].encode(), ASN1_Type::OctetString);  // g as octet string
540✔
118
   enc.start_sequence();
270✔
119
   for(size_t i = 0; i < m_sqrtmod.size(); i++) {
4,544✔
120
      enc.encode(m_sqrtmod[i].encode(), ASN1_Type::OctetString);
12,822✔
121
   }
122
   enc.end_cons();
270✔
123
   secure_vector<uint8_t> enc_support;
270✔
124

125
   for(uint16_t Linv : m_Linv) {
387,758✔
126
      enc_support.push_back(get_byte<0>(Linv));
387,488✔
127
      enc_support.push_back(get_byte<1>(Linv));
387,488✔
128
   }
129
   enc.encode(enc_support, ASN1_Type::OctetString);
270✔
130
   secure_vector<uint8_t> enc_H;
270✔
131
   for(uint32_t coef : m_coeffs) {
8,999,790✔
132
      enc_H.push_back(get_byte<0>(coef));
8,999,520✔
133
      enc_H.push_back(get_byte<1>(coef));
8,999,520✔
134
      enc_H.push_back(get_byte<2>(coef));
8,999,520✔
135
      enc_H.push_back(get_byte<3>(coef));
8,999,520✔
136
   }
137
   enc.encode(enc_H, ASN1_Type::OctetString);
270✔
138
   enc.end_cons();
270✔
139
   return enc.get_contents();
540✔
140
}
540✔
141

142
bool McEliece_PrivateKey::check_key(RandomNumberGenerator& rng, bool /*unused*/) const {
85✔
143
   const secure_vector<uint8_t> plaintext = this->random_plaintext_element(rng);
85✔
144

145
   secure_vector<uint8_t> ciphertext;
85✔
146
   secure_vector<uint8_t> errors;
85✔
147
   mceliece_encrypt(ciphertext, errors, plaintext, *this, rng);
85✔
148

149
   secure_vector<uint8_t> plaintext_out;
85✔
150
   secure_vector<uint8_t> errors_out;
85✔
151
   mceliece_decrypt(plaintext_out, errors_out, ciphertext, *this);
85✔
152

153
   if(errors != errors_out || plaintext != plaintext_out) {
85✔
154
      return false;
×
155
   }
156

157
   return true;
158
}
425✔
159

160
McEliece_PrivateKey::McEliece_PrivateKey(std::span<const uint8_t> key_bits) {
89✔
161
   size_t n, t;
89✔
162
   secure_vector<uint8_t> enc_g;
89✔
163
   BER_Decoder dec_base(key_bits);
89✔
164
   BER_Decoder dec = dec_base.start_sequence()
89✔
165
                        .start_sequence()
178✔
166
                        .decode(n)
89✔
167
                        .decode(t)
89✔
168
                        .end_cons()
89✔
169
                        .decode(m_public_matrix, ASN1_Type::OctetString)
89✔
170
                        .decode(enc_g, ASN1_Type::OctetString);
89✔
171

172
   if(t == 0 || n == 0) {
89✔
173
      throw Decoding_Error("invalid McEliece parameters");
×
174
   }
175

176
   uint32_t ext_deg = ceil_log2(n);
89✔
177
   m_code_length = n;
89✔
178
   m_t = t;
89✔
179
   m_codimension = (ext_deg * t);
89✔
180
   m_dimension = (n - m_codimension);
89✔
181

182
   auto sp_field = std::make_shared<GF2m_Field>(ext_deg);
89✔
183
   m_g = {polyn_gf2m(enc_g, sp_field)};
267✔
184
   if(m_g[0].get_degree() != static_cast<int>(t)) {
89✔
185
      throw Decoding_Error("degree of decoded Goppa polynomial is incorrect");
×
186
   }
187
   BER_Decoder dec2 = dec.start_sequence();
89✔
188
   for(uint32_t i = 0; i < t / 2; i++) {
1,471✔
189
      secure_vector<uint8_t> sqrt_enc;
1,382✔
190
      dec2.decode(sqrt_enc, ASN1_Type::OctetString);
1,382✔
191
      while(sqrt_enc.size() < (t * 2)) {
1,382✔
192
         // ensure that the length is always t
193
         sqrt_enc.push_back(0);
×
194
         sqrt_enc.push_back(0);
×
195
      }
196
      if(sqrt_enc.size() != t * 2) {
1,382✔
197
         throw Decoding_Error("length of square root polynomial entry is too large");
×
198
      }
199
      m_sqrtmod.push_back(polyn_gf2m(sqrt_enc, sp_field));
2,764✔
200
   }
1,382✔
201
   secure_vector<uint8_t> enc_support;
89✔
202
   BER_Decoder dec3 = dec2.end_cons().decode(enc_support, ASN1_Type::OctetString);
89✔
203
   if(enc_support.size() % 2) {
89✔
204
      throw Decoding_Error("encoded support has odd length");
×
205
   }
206
   if(enc_support.size() / 2 != n) {
89✔
207
      throw Decoding_Error("encoded support has length different from code length");
×
208
   }
209
   for(uint32_t i = 0; i < n * 2; i += 2) {
124,057✔
210
      gf2m el = (enc_support[i] << 8) | enc_support[i + 1];
123,968✔
211
      m_Linv.push_back(el);
123,968✔
212
   }
213
   secure_vector<uint8_t> enc_H;
89✔
214
   dec3.decode(enc_H, ASN1_Type::OctetString).end_cons();
89✔
215
   if(enc_H.size() % 4) {
89✔
216
      throw Decoding_Error("encoded parity check matrix has length which is not a multiple of four");
×
217
   }
218
   if(enc_H.size() / 4 != bit_size_to_32bit_size(m_codimension) * m_code_length) {
89✔
219
      throw Decoding_Error("encoded parity check matrix has wrong length");
×
220
   }
221

222
   for(uint32_t i = 0; i < enc_H.size(); i += 4) {
2,801,081✔
223
      uint32_t coeff = (enc_H[i] << 24) | (enc_H[i + 1] << 16) | (enc_H[i + 2] << 8) | enc_H[i + 3];
2,800,992✔
224
      m_coeffs.push_back(coeff);
2,800,992✔
225
   }
226
}
356✔
227

228
bool McEliece_PrivateKey::operator==(const McEliece_PrivateKey& other) const {
×
229
   if(*static_cast<const McEliece_PublicKey*>(this) != *static_cast<const McEliece_PublicKey*>(&other)) {
×
230
      return false;
231
   }
232
   if(m_g != other.m_g) {
×
233
      return false;
234
   }
235

236
   if(m_sqrtmod != other.m_sqrtmod) {
×
237
      return false;
238
   }
239
   if(m_Linv != other.m_Linv) {
×
240
      return false;
241
   }
242
   if(m_coeffs != other.m_coeffs) {
×
243
      return false;
244
   }
245

246
   if(m_codimension != other.m_codimension || m_dimension != other.m_dimension) {
×
247
      return false;
×
248
   }
249

250
   return true;
251
}
252

253
std::unique_ptr<Public_Key> McEliece_PrivateKey::public_key() const {
2✔
254
   return std::make_unique<McEliece_PublicKey>(get_public_matrix(), get_t(), get_code_length());
2✔
255
}
256

257
bool McEliece_PublicKey::operator==(const McEliece_PublicKey& other) const {
×
258
   if(m_public_matrix != other.m_public_matrix) {
×
259
      return false;
260
   }
261
   if(m_t != other.m_t) {
×
262
      return false;
263
   }
264
   if(m_code_length != other.m_code_length) {
×
265
      return false;
×
266
   }
267
   return true;
268
}
269

270
namespace {
271

272
class MCE_KEM_Encryptor final : public PK_Ops::KEM_Encryption_with_KDF {
273
   public:
274
      MCE_KEM_Encryptor(const McEliece_PublicKey& key, std::string_view kdf) :
96✔
275
            KEM_Encryption_with_KDF(kdf), m_key(key) {}
96✔
276

277
   private:
278
      size_t raw_kem_shared_key_length() const override {
2,561✔
279
         const size_t err_sz = (m_key.get_code_length() + 7) / 8;
2,561✔
280
         const size_t ptext_sz = (m_key.get_message_word_bit_length() + 7) / 8;
2,561✔
281
         return ptext_sz + err_sz;
2,561✔
282
      }
283

284
      size_t encapsulated_key_length() const override { return (m_key.get_code_length() + 7) / 8; }
2,561✔
285

286
      void raw_kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
2,561✔
287
                           secure_vector<uint8_t>& raw_shared_key,
288
                           RandomNumberGenerator& rng) override {
289
         secure_vector<uint8_t> plaintext = m_key.random_plaintext_element(rng);
2,561✔
290

291
         secure_vector<uint8_t> ciphertext, error_mask;
2,561✔
292
         mceliece_encrypt(ciphertext, error_mask, plaintext, m_key, rng);
2,561✔
293

294
         raw_shared_key.clear();
2,561✔
295
         raw_shared_key += plaintext;
2,561✔
296
         raw_shared_key += error_mask;
2,561✔
297

298
         out_encapsulated_key.swap(ciphertext);
2,561✔
299
      }
5,122✔
300

301
      const McEliece_PublicKey& m_key;
302
};
303

304
class MCE_KEM_Decryptor final : public PK_Ops::KEM_Decryption_with_KDF {
305
   public:
306
      MCE_KEM_Decryptor(const McEliece_PrivateKey& key, std::string_view kdf) :
96✔
307
            KEM_Decryption_with_KDF(kdf), m_key(key) {}
96✔
308

309
   private:
310
      size_t raw_kem_shared_key_length() const override {
2,561✔
311
         const size_t err_sz = (m_key.get_code_length() + 7) / 8;
2,561✔
312
         const size_t ptext_sz = (m_key.get_message_word_bit_length() + 7) / 8;
2,561✔
313
         return ptext_sz + err_sz;
2,561✔
314
      }
315

316
      secure_vector<uint8_t> raw_kem_decrypt(const uint8_t encap_key[], size_t len) override {
2,561✔
317
         secure_vector<uint8_t> plaintext, error_mask;
2,561✔
318
         mceliece_decrypt(plaintext, error_mask, encap_key, len, m_key);
2,561✔
319

320
         secure_vector<uint8_t> output;
2,561✔
321
         output.reserve(plaintext.size() + error_mask.size());
2,561✔
322
         output.insert(output.end(), plaintext.begin(), plaintext.end());
2,561✔
323
         output.insert(output.end(), error_mask.begin(), error_mask.end());
2,561✔
324
         return output;
2,561✔
325
      }
5,122✔
326

327
      const McEliece_PrivateKey& m_key;
328
};
329

330
}  // namespace
331

332
std::unique_ptr<PK_Ops::KEM_Encryption> McEliece_PublicKey::create_kem_encryption_op(std::string_view params,
96✔
333
                                                                                     std::string_view provider) const {
334
   if(provider == "base" || provider.empty()) {
96✔
335
      return std::make_unique<MCE_KEM_Encryptor>(*this, params);
96✔
336
   }
337
   throw Provider_Not_Found(algo_name(), provider);
×
338
}
339

340
std::unique_ptr<PK_Ops::KEM_Decryption> McEliece_PrivateKey::create_kem_decryption_op(RandomNumberGenerator& /*rng*/,
96✔
341
                                                                                      std::string_view params,
342
                                                                                      std::string_view provider) const {
343
   if(provider == "base" || provider.empty()) {
96✔
344
      return std::make_unique<MCE_KEM_Decryptor>(*this, params);
96✔
345
   }
346
   throw Provider_Not_Found(algo_name(), provider);
×
347
}
348

349
}  // namespace Botan
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