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