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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

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

85.92
/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
   return true;
157
}
425✔
158

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

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

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

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

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

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

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

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

248
   return true;
249
}
250

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

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

268
namespace {
269

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

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

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

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

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

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

296
         out_encapsulated_key.swap(ciphertext);
2,561✔
297
      }
5,122✔
298

299
      const McEliece_PublicKey& m_key;
300
};
301

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

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

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

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

325
      const McEliece_PrivateKey& m_key;
326
};
327

328
}
329

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

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

345
}
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

© 2026 Coveralls, Inc