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

randombit / botan / 4876456163

03 May 2023 09:27PM UTC coverage: 91.724% (-0.002%) from 91.726%
4876456163

push

github

77612 of 84615 relevant lines covered (91.72%)

11907228.65 hits per line

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

85.19
/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/internal/polyn_gf2m.h>
16
#include <botan/internal/mce_internal.h>
17
#include <botan/internal/bit_ops.h>
18
#include <botan/internal/code_based_util.h>
19
#include <botan/internal/pk_ops_impl.h>
20
#include <botan/internal/loadstor.h>
21
#include <botan/der_enc.h>
22
#include <botan/ber_dec.h>
23
#include <botan/rng.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(polyn_gf2m const& goppa_polyn,
98✔
34
                                         std::vector<uint32_t> const& parity_check_matrix_coeffs,
35
                                         std::vector<polyn_gf2m> const& square_root_matrix,
36
                                         std::vector<gf2m> const& inverse_support,
37
                                         std::vector<uint8_t> const& 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)
98✔
45
   {
46
   }
98✔
47

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

54
const polyn_gf2m& McEliece_PrivateKey::get_goppa_polyn() const
10,584✔
55
   {
56
   return m_g[0];
10,584✔
57
   }
58

59
size_t McEliece_PublicKey::get_message_word_bit_length() const
10,414✔
60
   {
61
   size_t codimension = ceil_log2(m_code_length) * m_t;
10,414✔
62
   return m_code_length - codimension;
10,414✔
63
   }
64

65
secure_vector<uint8_t> McEliece_PublicKey::random_plaintext_element(RandomNumberGenerator& rng) const
2,646✔
66
   {
67
   const size_t bits = get_message_word_bit_length();
2,646✔
68

69
   secure_vector<uint8_t> plaintext((bits+7)/8);
2,646✔
70
   rng.randomize(plaintext.data(), plaintext.size());
2,646✔
71

72
   // unset unused bits in the last plaintext byte
73
   if(uint32_t used = bits % 8)
2,646✔
74
      {
75
      const uint8_t mask = (1 << used) - 1;
1,933✔
76
      plaintext[plaintext.size() - 1] &= mask;
1,933✔
77
      }
78

79
   return plaintext;
2,646✔
80
   }
×
81

82
AlgorithmIdentifier McEliece_PublicKey::algorithm_identifier() const
13✔
83
   {
84
   return AlgorithmIdentifier(object_identifier(), AlgorithmIdentifier::USE_EMPTY_PARAM);
13✔
85
   }
86

87
std::vector<uint8_t> McEliece_PublicKey::public_key_bits() const
267✔
88
   {
89
   std::vector<uint8_t> output;
267✔
90
   DER_Encoder(output)
534✔
91
      .start_sequence()
267✔
92
         .start_sequence()
267✔
93
         .encode(static_cast<size_t>(get_code_length()))
267✔
94
         .encode(static_cast<size_t>(get_t()))
267✔
95
         .end_cons()
267✔
96
      .encode(m_public_matrix, ASN1_Type::OctetString)
267✔
97
      .end_cons();
267✔
98
   return output;
267✔
99
   }
×
100

101
size_t McEliece_PublicKey::key_length() const
×
102
   {
103
   return m_code_length;
×
104
   }
105

106
size_t McEliece_PublicKey::estimated_strength() const
2✔
107
   {
108
   return mceliece_work_factor(m_code_length, m_t);
2✔
109
   }
110

111
McEliece_PublicKey::McEliece_PublicKey(std::span<const uint8_t> key_bits)
86✔
112
   {
113
   BER_Decoder dec(key_bits);
86✔
114
   size_t n;
86✔
115
   size_t t;
86✔
116
   dec.start_sequence()
86✔
117
      .start_sequence()
172✔
118
      .decode(n)
86✔
119
      .decode(t)
86✔
120
      .end_cons()
86✔
121
      .decode(m_public_matrix, ASN1_Type::OctetString)
86✔
122
      .end_cons();
86✔
123
   m_t = t;
86✔
124
   m_code_length = n;
86✔
125
   }
86✔
126

127
secure_vector<uint8_t> McEliece_PrivateKey::private_key_bits() const
270✔
128
   {
129
   DER_Encoder enc;
270✔
130
   enc.start_sequence()
270✔
131
      .start_sequence()
270✔
132
      .encode(static_cast<size_t>(get_code_length()))
270✔
133
      .encode(static_cast<size_t>(get_t()))
270✔
134
      .end_cons()
270✔
135
      .encode(m_public_matrix, ASN1_Type::OctetString)
270✔
136
      .encode(m_g[0].encode(), ASN1_Type::OctetString); // g as octet string
540✔
137
   enc.start_sequence();
270✔
138
   for(size_t i = 0; i < m_sqrtmod.size(); i++)
4,544✔
139
      {
140
      enc.encode(m_sqrtmod[i].encode(), ASN1_Type::OctetString);
12,822✔
141
      }
142
   enc.end_cons();
270✔
143
   secure_vector<uint8_t> enc_support;
270✔
144

145
   for(uint16_t Linv : m_Linv)
387,758✔
146
      {
147
      enc_support.push_back(get_byte<0>(Linv));
387,488✔
148
      enc_support.push_back(get_byte<1>(Linv));
387,488✔
149
      }
150
   enc.encode(enc_support, ASN1_Type::OctetString);
270✔
151
   secure_vector<uint8_t> enc_H;
270✔
152
   for(uint32_t coef : m_coeffs)
8,999,790✔
153
      {
154
      enc_H.push_back(get_byte<0>(coef));
8,999,520✔
155
      enc_H.push_back(get_byte<1>(coef));
8,999,520✔
156
      enc_H.push_back(get_byte<2>(coef));
8,999,520✔
157
      enc_H.push_back(get_byte<3>(coef));
8,999,520✔
158
      }
159
   enc.encode(enc_H, ASN1_Type::OctetString);
270✔
160
   enc.end_cons();
270✔
161
   return enc.get_contents();
540✔
162
   }
540✔
163

164
bool McEliece_PrivateKey::check_key(RandomNumberGenerator& rng, bool /*unused*/) const
85✔
165
   {
166
   const secure_vector<uint8_t> plaintext = this->random_plaintext_element(rng);
85✔
167

168
   secure_vector<uint8_t> ciphertext;
85✔
169
   secure_vector<uint8_t> errors;
85✔
170
   mceliece_encrypt(ciphertext, errors, plaintext, *this, rng);
85✔
171

172
   secure_vector<uint8_t> plaintext_out;
85✔
173
   secure_vector<uint8_t> errors_out;
85✔
174
   mceliece_decrypt(plaintext_out, errors_out, ciphertext, *this);
85✔
175

176
   if(errors != errors_out || plaintext != plaintext_out)
85✔
177
      return false;
×
178

179
   return true;
180
   }
425✔
181

182
McEliece_PrivateKey::McEliece_PrivateKey(std::span<const uint8_t> key_bits)
89✔
183
   {
184
   size_t n, t;
89✔
185
   secure_vector<uint8_t> enc_g;
89✔
186
   BER_Decoder dec_base(key_bits);
89✔
187
   BER_Decoder dec = dec_base.start_sequence()
89✔
188
      .start_sequence()
178✔
189
      .decode(n)
89✔
190
      .decode(t)
89✔
191
      .end_cons()
89✔
192
      .decode(m_public_matrix, ASN1_Type::OctetString)
89✔
193
      .decode(enc_g, ASN1_Type::OctetString);
89✔
194

195
   if(t == 0 || n == 0)
89✔
196
      throw Decoding_Error("invalid McEliece parameters");
×
197

198
   uint32_t ext_deg = ceil_log2(n);
89✔
199
   m_code_length = n;
89✔
200
   m_t = t;
89✔
201
   m_codimension = (ext_deg * t);
89✔
202
   m_dimension = (n - m_codimension);
89✔
203

204
   auto sp_field = std::make_shared<GF2m_Field>(ext_deg);
89✔
205
   m_g = { polyn_gf2m(enc_g, sp_field) };
267✔
206
   if(m_g[0].get_degree() != static_cast<int>(t))
89✔
207
      {
208
      throw Decoding_Error("degree of decoded Goppa polynomial is incorrect");
×
209
      }
210
   BER_Decoder dec2 = dec.start_sequence();
89✔
211
   for(uint32_t i = 0; i < t/2; i++)
1,471✔
212
      {
213
      secure_vector<uint8_t> sqrt_enc;
1,382✔
214
      dec2.decode(sqrt_enc, ASN1_Type::OctetString);
1,382✔
215
      while(sqrt_enc.size() < (t*2))
1,382✔
216
         {
217
         // ensure that the length is always t
218
         sqrt_enc.push_back(0);
×
219
         sqrt_enc.push_back(0);
×
220
         }
221
      if(sqrt_enc.size() != t*2)
1,382✔
222
         {
223
         throw Decoding_Error("length of square root polynomial entry is too large");
×
224
         }
225
      m_sqrtmod.push_back(polyn_gf2m(sqrt_enc, sp_field));
2,764✔
226
      }
1,382✔
227
   secure_vector<uint8_t> enc_support;
89✔
228
   BER_Decoder dec3 = dec2.end_cons()
89✔
229
      .decode(enc_support, ASN1_Type::OctetString);
89✔
230
   if(enc_support.size() % 2)
89✔
231
      {
232
      throw Decoding_Error("encoded support has odd length");
×
233
      }
234
   if(enc_support.size() / 2 != n)
89✔
235
      {
236
      throw Decoding_Error("encoded support has length different from code length");
×
237
      }
238
   for(uint32_t i = 0; i < n*2; i+=2)
124,057✔
239
      {
240
      gf2m el = (enc_support[i] << 8) |  enc_support[i+1];
123,968✔
241
      m_Linv.push_back(el);
123,968✔
242
      }
243
   secure_vector<uint8_t> enc_H;
89✔
244
   dec3.decode(enc_H, ASN1_Type::OctetString)
89✔
245
      .end_cons();
89✔
246
   if(enc_H.size() % 4)
89✔
247
      {
248
      throw Decoding_Error("encoded parity check matrix has length which is not a multiple of four");
×
249
      }
250
   if(enc_H.size() / 4 != bit_size_to_32bit_size(m_codimension) * m_code_length)
89✔
251
      {
252
      throw Decoding_Error("encoded parity check matrix has wrong length");
×
253
      }
254

255
   for(uint32_t i = 0; i < enc_H.size(); i+=4)
2,801,081✔
256
      {
257
      uint32_t coeff = (enc_H[i] << 24) | (enc_H[i+1] << 16) | (enc_H[i+2] << 8) | enc_H[i+3];
2,800,992✔
258
      m_coeffs.push_back(coeff);
2,800,992✔
259
      }
260

261
   }
356✔
262

263
bool McEliece_PrivateKey::operator==(const McEliece_PrivateKey & other) const
×
264
   {
265
   if(*static_cast<const McEliece_PublicKey*>(this) != *static_cast<const McEliece_PublicKey*>(&other))
×
266
      {
267
      return false;
268
      }
269
   if(m_g != other.m_g)
×
270
      {
271
      return false;
272
      }
273

274
   if( m_sqrtmod != other.m_sqrtmod)
×
275
      {
276
      return false;
277
      }
278
   if( m_Linv != other.m_Linv)
×
279
      {
280
      return false;
281
      }
282
   if( m_coeffs != other.m_coeffs)
×
283
      {
284
      return false;
285
      }
286

287
   if(m_codimension != other.m_codimension || m_dimension != other.m_dimension)
×
288
      {
289
      return false;
×
290
      }
291

292
   return true;
293
   }
294

295
std::unique_ptr<Public_Key> McEliece_PrivateKey::public_key() const
2✔
296
   {
297
   return std::make_unique<McEliece_PublicKey>(
4✔
298
      get_public_matrix(), get_t(), get_code_length());
2✔
299
   }
300

301
bool McEliece_PublicKey::operator==(const McEliece_PublicKey& other) const
×
302
   {
303
   if(m_public_matrix != other.m_public_matrix)
×
304
      {
305
      return false;
306
      }
307
   if(m_t != other.m_t)
×
308
      {
309
      return false;
310
      }
311
   if( m_code_length != other.m_code_length)
×
312
      {
313
      return false;
×
314
      }
315
   return true;
316
   }
317

318
namespace {
319

320
class MCE_KEM_Encryptor final : public PK_Ops::KEM_Encryption_with_KDF
321
   {
322
   public:
323

324
      MCE_KEM_Encryptor(const McEliece_PublicKey& key,
96✔
325
                        std::string_view kdf) :
96✔
326
         KEM_Encryption_with_KDF(kdf), m_key(key) {}
96✔
327

328
   private:
329
      size_t raw_kem_shared_key_length() const override
2,561✔
330
         {
331
         const size_t err_sz = (m_key.get_code_length() + 7) / 8;
2,561✔
332
         const size_t ptext_sz = (m_key.get_message_word_bit_length() + 7) / 8;
2,561✔
333
         return ptext_sz + err_sz;
2,561✔
334
         }
335

336
      size_t encapsulated_key_length() const override
2,561✔
337
         {
338
         return (m_key.get_code_length() + 7) / 8;
2,561✔
339
         }
340

341
      void raw_kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
2,561✔
342
                           secure_vector<uint8_t>& raw_shared_key,
343
                           RandomNumberGenerator& rng) override
344
         {
345
         secure_vector<uint8_t> plaintext = m_key.random_plaintext_element(rng);
2,561✔
346

347
         secure_vector<uint8_t> ciphertext, error_mask;
2,561✔
348
         mceliece_encrypt(ciphertext, error_mask, plaintext, m_key, rng);
2,561✔
349

350
         raw_shared_key.clear();
2,561✔
351
         raw_shared_key += plaintext;
2,561✔
352
         raw_shared_key += error_mask;
2,561✔
353

354
         out_encapsulated_key.swap(ciphertext);
2,561✔
355
         }
5,122✔
356

357
      const McEliece_PublicKey& m_key;
358
   };
359

360
class MCE_KEM_Decryptor final : public PK_Ops::KEM_Decryption_with_KDF
361
   {
362
   public:
363

364
      MCE_KEM_Decryptor(const McEliece_PrivateKey& key,
96✔
365
                        std::string_view kdf) :
96✔
366
         KEM_Decryption_with_KDF(kdf), m_key(key) {}
96✔
367

368
   private:
369
      size_t raw_kem_shared_key_length() const override
2,561✔
370
         {
371
         const size_t err_sz = (m_key.get_code_length() + 7) / 8;
2,561✔
372
         const size_t ptext_sz = (m_key.get_message_word_bit_length() + 7) / 8;
2,561✔
373
         return ptext_sz + err_sz;
2,561✔
374
         }
375

376
      secure_vector<uint8_t>
377
      raw_kem_decrypt(const uint8_t encap_key[], size_t len) override
2,561✔
378
         {
379
         secure_vector<uint8_t> plaintext, error_mask;
2,561✔
380
         mceliece_decrypt(plaintext, error_mask, encap_key, len, m_key);
2,561✔
381

382
         secure_vector<uint8_t> output;
2,561✔
383
         output.reserve(plaintext.size() + error_mask.size());
2,561✔
384
         output.insert(output.end(), plaintext.begin(), plaintext.end());
2,561✔
385
         output.insert(output.end(), error_mask.begin(), error_mask.end());
2,561✔
386
         return output;
2,561✔
387
         }
5,122✔
388

389
      const McEliece_PrivateKey& m_key;
390
   };
391

392
}
393

394
std::unique_ptr<PK_Ops::KEM_Encryption>
395
McEliece_PublicKey::create_kem_encryption_op(std::string_view params,
96✔
396
                                             std::string_view provider) const
397
   {
398
   if(provider == "base" || provider.empty())
96✔
399
      return std::make_unique<MCE_KEM_Encryptor>(*this, params);
96✔
400
   throw Provider_Not_Found(algo_name(), provider);
×
401
   }
402

403
std::unique_ptr<PK_Ops::KEM_Decryption>
404
McEliece_PrivateKey::create_kem_decryption_op(RandomNumberGenerator& /*rng*/,
96✔
405
                                              std::string_view params,
406
                                              std::string_view provider) const
407
   {
408
   if(provider == "base" || provider.empty())
96✔
409
      return std::make_unique<MCE_KEM_Decryptor>(*this, params);
96✔
410
   throw Provider_Not_Found(algo_name(), provider);
×
411
   }
412

413
}
414

415

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