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

randombit / botan / 6538316185

16 Oct 2023 12:59PM UTC coverage: 91.708% (-0.002%) from 91.71%
6538316185

push

github

web-flow
Merge pull request #3759 from randombit/jack/deprecate-buffer-insert

Deprecate buffer_insert and remove final uses of it from the codebase

80088 of 87329 relevant lines covered (91.71%)

8549162.84 hits per line

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

96.21
/src/lib/pubkey/sm2/sm2_enc.cpp
1
/*
2
* SM2 Encryption
3
* (C) 2017 Ribose Inc
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/sm2.h>
9

10
#include <botan/ber_dec.h>
11
#include <botan/der_enc.h>
12
#include <botan/hash.h>
13
#include <botan/kdf.h>
14
#include <botan/internal/fmt.h>
15
#include <botan/internal/pk_ops.h>
16
#include <botan/internal/point_mul.h>
17

18
namespace Botan {
19

20
namespace {
21

22
class SM2_Encryption_Operation final : public PK_Ops::Encryption {
×
23
   public:
24
      SM2_Encryption_Operation(const SM2_Encryption_PublicKey& key,
6✔
25
                               RandomNumberGenerator& rng,
26
                               std::string_view kdf_hash) :
6✔
27
            m_group(key.domain()), m_ws(EC_Point::WORKSPACE_SIZE), m_mul_public_point(key.public_point(), rng, m_ws) {
6✔
28
         m_hash = HashFunction::create_or_throw(kdf_hash);
6✔
29

30
         const std::string kdf_name = fmt("KDF2({})", kdf_hash);
6✔
31
         m_kdf = KDF::create_or_throw(kdf_name);
6✔
32
      }
6✔
33

34
      size_t max_input_bits() const override {
5✔
35
         // This is arbitrary, but assumes SM2 is used for key encapsulation
36
         return 512;
5✔
37
      }
38

39
      size_t ciphertext_length(size_t ptext_len) const override {
6✔
40
         const size_t elem_size = m_group.get_order_bytes();
6✔
41
         const size_t der_overhead = 16;
6✔
42

43
         return der_overhead + 2 * elem_size + m_hash->output_length() + ptext_len;
6✔
44
      }
45

46
      secure_vector<uint8_t> encrypt(const uint8_t msg[], size_t msg_len, RandomNumberGenerator& rng) override {
6✔
47
         const size_t p_bytes = m_group.get_p_bytes();
6✔
48

49
         const BigInt k = m_group.random_scalar(rng);
6✔
50

51
         const EC_Point C1 = m_group.blinded_base_point_multiply(k, rng, m_ws);
6✔
52
         const BigInt x1 = C1.get_affine_x();
6✔
53
         const BigInt y1 = C1.get_affine_y();
6✔
54
         std::vector<uint8_t> x1_bytes(p_bytes);
6✔
55
         std::vector<uint8_t> y1_bytes(p_bytes);
6✔
56
         BigInt::encode_1363(x1_bytes.data(), x1_bytes.size(), x1);
6✔
57
         BigInt::encode_1363(y1_bytes.data(), y1_bytes.size(), y1);
6✔
58

59
         const EC_Point kPB = m_mul_public_point.mul(k, rng, m_group.get_order(), m_ws);
6✔
60

61
         const BigInt x2 = kPB.get_affine_x();
6✔
62
         const BigInt y2 = kPB.get_affine_y();
6✔
63
         std::vector<uint8_t> x2_bytes(p_bytes);
6✔
64
         std::vector<uint8_t> y2_bytes(p_bytes);
6✔
65
         BigInt::encode_1363(x2_bytes.data(), x2_bytes.size(), x2);
6✔
66
         BigInt::encode_1363(y2_bytes.data(), y2_bytes.size(), y2);
6✔
67

68
         secure_vector<uint8_t> kdf_input;
6✔
69
         kdf_input += x2_bytes;
6✔
70
         kdf_input += y2_bytes;
6✔
71

72
         const secure_vector<uint8_t> kdf_output = m_kdf->derive_key(msg_len, kdf_input.data(), kdf_input.size());
6✔
73

74
         secure_vector<uint8_t> masked_msg(msg_len);
6✔
75
         xor_buf(masked_msg.data(), msg, kdf_output.data(), msg_len);
6✔
76

77
         m_hash->update(x2_bytes);
6✔
78
         m_hash->update(msg, msg_len);
6✔
79
         m_hash->update(y2_bytes);
6✔
80
         std::vector<uint8_t> C3(m_hash->output_length());
6✔
81
         m_hash->final(C3.data());
6✔
82

83
         return DER_Encoder()
12✔
84
            .start_sequence()
6✔
85
            .encode(x1)
6✔
86
            .encode(y1)
6✔
87
            .encode(C3, ASN1_Type::OctetString)
6✔
88
            .encode(masked_msg, ASN1_Type::OctetString)
6✔
89
            .end_cons()
6✔
90
            .get_contents();
6✔
91
      }
78✔
92

93
   private:
94
      const EC_Group m_group;
95
      std::unique_ptr<HashFunction> m_hash;
96
      std::unique_ptr<KDF> m_kdf;
97
      std::vector<BigInt> m_ws;
98
      EC_Point_Var_Point_Precompute m_mul_public_point;
99
};
100

101
class SM2_Decryption_Operation final : public PK_Ops::Decryption {
×
102
   public:
103
      SM2_Decryption_Operation(const SM2_Encryption_PrivateKey& key,
6✔
104
                               RandomNumberGenerator& rng,
105
                               std::string_view kdf_hash) :
6✔
106
            m_key(key), m_rng(rng) {
6✔
107
         m_hash = HashFunction::create_or_throw(kdf_hash);
6✔
108

109
         const std::string kdf_name = fmt("KDF2({})", kdf_hash);
6✔
110
         m_kdf = KDF::create_or_throw(kdf_name);
6✔
111
      }
6✔
112

113
      size_t plaintext_length(size_t ptext_len) const override {
5✔
114
         /*
115
         * This ignores the DER encoding and so overestimates the
116
         * plaintext length by 12 bytes or so
117
         */
118
         const size_t elem_size = m_key.domain().get_order_bytes();
5✔
119

120
         if(ptext_len < 2 * elem_size + m_hash->output_length()) {
5✔
121
            return 0;
122
         }
123

124
         return ptext_len - (2 * elem_size + m_hash->output_length());
5✔
125
      }
126

127
      secure_vector<uint8_t> decrypt(uint8_t& valid_mask, const uint8_t ciphertext[], size_t ciphertext_len) override {
106✔
128
         const EC_Group& group = m_key.domain();
106✔
129
         const BigInt& cofactor = group.get_cofactor();
106✔
130
         const size_t p_bytes = group.get_p_bytes();
106✔
131

132
         valid_mask = 0x00;
106✔
133

134
         // Too short to be valid - no timing problem from early return
135
         if(ciphertext_len < 1 + p_bytes * 2 + m_hash->output_length()) {
106✔
136
            return secure_vector<uint8_t>();
×
137
         }
138

139
         BigInt x1, y1;
106✔
140
         secure_vector<uint8_t> C3, masked_msg;
106✔
141

142
         BER_Decoder(ciphertext, ciphertext_len)
116✔
143
            .start_sequence()
214✔
144
            .decode(x1)
102✔
145
            .decode(y1)
102✔
146
            .decode(C3, ASN1_Type::OctetString)
101✔
147
            .decode(masked_msg, ASN1_Type::OctetString)
97✔
148
            .end_cons()
97✔
149
            .verify_end();
97✔
150

151
         std::vector<uint8_t> recode_ctext;
97✔
152
         DER_Encoder(recode_ctext)
195✔
153
            .start_sequence()
97✔
154
            .encode(x1)
97✔
155
            .encode(y1)
97✔
156
            .encode(C3, ASN1_Type::OctetString)
97✔
157
            .encode(masked_msg, ASN1_Type::OctetString)
97✔
158
            .end_cons();
97✔
159

160
         if(recode_ctext.size() != ciphertext_len) {
97✔
161
            return secure_vector<uint8_t>();
×
162
         }
163

164
         if(same_mem(recode_ctext.data(), ciphertext, ciphertext_len) == false) {
194✔
165
            return secure_vector<uint8_t>();
96✔
166
         }
167

168
         EC_Point C1 = group.point(x1, y1);
97✔
169
         C1.randomize_repr(m_rng);
96✔
170

171
         // Here C1 is publically invalid, so no problem with early return:
172
         if(!C1.on_the_curve()) {
96✔
173
            return secure_vector<uint8_t>();
53✔
174
         }
175

176
         if(cofactor > 1 && (C1 * cofactor).is_zero()) {
43✔
177
            return secure_vector<uint8_t>();
×
178
         }
179

180
         const EC_Point dbC1 = group.blinded_var_point_multiply(C1, m_key.private_value(), m_rng, m_ws);
43✔
181

182
         const BigInt x2 = dbC1.get_affine_x();
43✔
183
         const BigInt y2 = dbC1.get_affine_y();
43✔
184

185
         secure_vector<uint8_t> x2_bytes(p_bytes);
43✔
186
         secure_vector<uint8_t> y2_bytes(p_bytes);
43✔
187
         BigInt::encode_1363(x2_bytes.data(), x2_bytes.size(), x2);
43✔
188
         BigInt::encode_1363(y2_bytes.data(), y2_bytes.size(), y2);
43✔
189

190
         secure_vector<uint8_t> kdf_input;
43✔
191
         kdf_input += x2_bytes;
43✔
192
         kdf_input += y2_bytes;
43✔
193

194
         const secure_vector<uint8_t> kdf_output =
43✔
195
            m_kdf->derive_key(masked_msg.size(), kdf_input.data(), kdf_input.size());
43✔
196

197
         xor_buf(masked_msg.data(), kdf_output.data(), kdf_output.size());
43✔
198

199
         m_hash->update(x2_bytes);
43✔
200
         m_hash->update(masked_msg);
43✔
201
         m_hash->update(y2_bytes);
43✔
202
         secure_vector<uint8_t> u = m_hash->final();
43✔
203

204
         if(constant_time_compare(u.data(), C3.data(), m_hash->output_length()) == false) {
43✔
205
            return secure_vector<uint8_t>();
37✔
206
         }
207

208
         valid_mask = 0xFF;
6✔
209
         return masked_msg;
43✔
210
      }
859✔
211

212
   private:
213
      const SM2_Encryption_PrivateKey& m_key;
214
      RandomNumberGenerator& m_rng;
215
      std::vector<BigInt> m_ws;
216
      std::unique_ptr<HashFunction> m_hash;
217
      std::unique_ptr<KDF> m_kdf;
218
};
219

220
}  // namespace
221

222
std::unique_ptr<PK_Ops::Encryption> SM2_PublicKey::create_encryption_op(RandomNumberGenerator& rng,
21✔
223
                                                                        std::string_view params,
224
                                                                        std::string_view provider) const {
225
   if(provider == "base" || provider.empty()) {
26✔
226
      if(params.empty()) {
6✔
227
         return std::make_unique<SM2_Encryption_Operation>(*this, rng, "SM3");
1✔
228
      } else {
229
         return std::make_unique<SM2_Encryption_Operation>(*this, rng, params);
5✔
230
      }
231
   }
232

233
   throw Provider_Not_Found(algo_name(), provider);
30✔
234
}
235

236
std::unique_ptr<PK_Ops::Decryption> SM2_PrivateKey::create_decryption_op(RandomNumberGenerator& rng,
21✔
237
                                                                         std::string_view params,
238
                                                                         std::string_view provider) const {
239
   if(provider == "base" || provider.empty()) {
26✔
240
      if(params.empty()) {
6✔
241
         return std::make_unique<SM2_Decryption_Operation>(*this, rng, "SM3");
1✔
242
      } else {
243
         return std::make_unique<SM2_Decryption_Operation>(*this, rng, params);
5✔
244
      }
245
   }
246

247
   throw Provider_Not_Found(algo_name(), provider);
30✔
248
}
249

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

© 2026 Coveralls, Inc