Coverage Report

Created: 2020-09-16 07:52

/src/botan/src/lib/pubkey/mce/mceliece.cpp
Line
Count
Source (jump to first uncovered line)
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
 *
8
 * Botan is released under the Simplified BSD License (see license.txt)
9
 *
10
 */
11
12
#include <botan/internal/mce_internal.h>
13
#include <botan/mceliece.h>
14
#include <botan/internal/code_based_util.h>
15
#include <botan/internal/bit_ops.h>
16
17
namespace Botan {
18
19
namespace {
20
21
secure_vector<uint8_t> concat_vectors(const secure_vector<uint8_t>& a,
22
                                      const secure_vector<uint8_t>& b,
23
                                      size_t dimension,
24
                                      size_t codimension)
25
0
   {
26
0
   secure_vector<uint8_t> x(bit_size_to_byte_size(dimension) + bit_size_to_byte_size(codimension));
27
0
28
0
   const size_t final_bits = dimension % 8;
29
0
30
0
   if(final_bits == 0)
31
0
      {
32
0
      const size_t dim_bytes = bit_size_to_byte_size(dimension);
33
0
      copy_mem(&x[0], a.data(), dim_bytes);
34
0
      copy_mem(&x[dim_bytes], b.data(), bit_size_to_byte_size(codimension));
35
0
      }
36
0
   else
37
0
      {
38
0
      copy_mem(&x[0], a.data(), (dimension / 8));
39
0
      size_t l = dimension / 8;
40
0
      x[l] = static_cast<uint8_t>(a[l] & ((1 << final_bits) - 1));
41
0
42
0
      for(size_t k = 0; k < codimension / 8; ++k)
43
0
         {
44
0
         x[l] ^= static_cast<uint8_t>(b[k] << final_bits);
45
0
         ++l;
46
0
         x[l] = static_cast<uint8_t>(b[k] >> (8 - final_bits));
47
0
         }
48
0
      x[l] ^= static_cast<uint8_t>(b[codimension/8] << final_bits);
49
0
      }
50
0
51
0
   return x;
52
0
   }
53
54
secure_vector<uint8_t> mult_by_pubkey(const secure_vector<uint8_t>& cleartext,
55
                                      std::vector<uint8_t> const& public_matrix,
56
                                      size_t code_length, size_t t)
57
0
   {
58
0
   const size_t ext_deg = ceil_log2(code_length);
59
0
   const size_t codimension = ext_deg * t;
60
0
   const size_t dimension = code_length - codimension;
61
0
   secure_vector<uint8_t> cR(bit_size_to_32bit_size(codimension) * sizeof(uint32_t));
62
0
63
0
   const uint8_t* pt = public_matrix.data();
64
0
65
0
   for(size_t i = 0; i < dimension / 8; ++i)
66
0
      {
67
0
      for(size_t j = 0; j < 8; ++j)
68
0
         {
69
0
         if(cleartext[i] & (1 << j))
70
0
            {
71
0
            xor_buf(cR.data(), pt, cR.size());
72
0
            }
73
0
         pt += cR.size();
74
0
         }
75
0
      }
76
0
77
0
   for(size_t i = 0; i < dimension % 8 ; ++i)
78
0
      {
79
0
      if(cleartext[dimension/8] & (1 << i))
80
0
         {
81
0
         xor_buf(cR.data(), pt, cR.size());
82
0
         }
83
0
      pt += cR.size();
84
0
      }
85
0
86
0
   secure_vector<uint8_t> ciphertext = concat_vectors(cleartext, cR, dimension, codimension);
87
0
   ciphertext.resize((code_length+7)/8);
88
0
   return ciphertext;
89
0
   }
90
91
secure_vector<uint8_t> create_random_error_vector(size_t code_length,
92
                                                  size_t error_weight,
93
                                                  RandomNumberGenerator& rng)
94
0
   {
95
0
   secure_vector<uint8_t> result((code_length+7)/8);
96
0
97
0
   size_t bits_set = 0;
98
0
99
0
   while(bits_set < error_weight)
100
0
      {
101
0
      gf2m x = random_code_element(static_cast<uint16_t>(code_length), rng);
102
0
103
0
      const size_t byte_pos = x / 8;
104
0
      const size_t bit_pos = x % 8;
105
0
106
0
      const uint8_t mask = (1 << bit_pos);
107
0
108
0
      if(result[byte_pos] & mask)
109
0
         continue; // already set this bit
110
0
111
0
      result[byte_pos] |= mask;
112
0
      bits_set++;
113
0
      }
114
0
115
0
   return result;
116
0
   }
117
118
}
119
120
void mceliece_encrypt(secure_vector<uint8_t>& ciphertext_out,
121
                      secure_vector<uint8_t>& error_mask_out,
122
                      const secure_vector<uint8_t>& plaintext,
123
                      const McEliece_PublicKey& key,
124
                      RandomNumberGenerator& rng)
125
0
   {
126
0
   const uint16_t code_length = static_cast<uint16_t>(key.get_code_length());
127
0
128
0
   secure_vector<uint8_t> error_mask = create_random_error_vector(code_length, key.get_t(), rng);
129
0
130
0
   secure_vector<uint8_t> ciphertext = mult_by_pubkey(plaintext, key.get_public_matrix(),
131
0
                                                      key.get_code_length(), key.get_t());
132
0
133
0
   ciphertext ^= error_mask;
134
0
135
0
   ciphertext_out.swap(ciphertext);
136
0
   error_mask_out.swap(error_mask);
137
0
   }
138
139
}