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

randombit / botan / 16245054916

13 Jul 2025 03:51AM UTC coverage: 90.581% (+0.009%) from 90.572%
16245054916

Pull #4982

github

web-flow
Merge 11956826b into e87c8e33a
Pull Request #4982: Enable and fix clang-tidy warning cert-err58-cpp

99186 of 109500 relevant lines covered (90.58%)

12549723.2 hits per line

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

91.41
/src/lib/prov/pkcs11/p11_mechanism.cpp
1
/*
2
* PKCS#11 Mechanism
3
* (C) 2016 Daniel Neus, Sirrix AG
4
* (C) 2016 Philipp Weber, Sirrix AG
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/p11_mechanism.h>
10

11
#include <botan/internal/fmt.h>
12
#include <botan/internal/parsing.h>
13
#include <botan/internal/scan_name.h>
14
#include <tuple>
15

16
namespace Botan::PKCS11 {
17

18
namespace {
19
using PSS_Params = std::tuple<size_t, MechanismType, MGF>;
20

21
// maps a PSS mechanism type to the number of bytes used for the salt, the mechanism type of the underlying hash algorithm and the MGF
22
const std::map<MechanismType, PSS_Params>& PssOptions() {
100✔
23
   static const std::map<MechanismType, PSS_Params> pss_options = {
100✔
24
      {MechanismType::RsaPkcsPss, PSS_Params(0, MechanismType::Sha1, MGF::Mgf1Sha1)},
25
      {MechanismType::Sha1RsaPkcsPss, PSS_Params(20, MechanismType::Sha1, MGF::Mgf1Sha1)},
26
      {MechanismType::Sha224RsaPkcsPss, PSS_Params(28, MechanismType::Sha224, MGF::Mgf1Sha224)},
27
      {MechanismType::Sha256RsaPkcsPss, PSS_Params(32, MechanismType::Sha256, MGF::Mgf1Sha256)},
28
      {MechanismType::Sha384RsaPkcsPss, PSS_Params(48, MechanismType::Sha384, MGF::Mgf1Sha384)},
29
      {MechanismType::Sha512RsaPkcsPss, PSS_Params(64, MechanismType::Sha512, MGF::Mgf1Sha512)}};
100✔
30

31
   return pss_options;
100✔
32
}
33

34
class MechanismData {
35
   public:
36
      explicit MechanismData(MechanismType type) : m_type(type) {}
46✔
37

38
      MechanismData(const MechanismData& other) = default;
73✔
39
      MechanismData(MechanismData&& other) = default;
46✔
40

41
      MechanismData& operator=(const MechanismData& other) = default;
42
      MechanismData& operator=(MechanismData&& other) = default;
43

44
      virtual ~MechanismData() = default;
75✔
45

46
      MechanismType type() const { return m_type; }
45✔
47

48
   private:
49
      // the mechanism to perform
50
      MechanismType m_type;
51
};
52

53
class RSA_SignMechanism final : public MechanismData {
45✔
54
   public:
55
      explicit RSA_SignMechanism(MechanismType typ) noexcept :
45✔
56
            MechanismData(typ), m_hash(static_cast<MechanismType>(0)), m_mgf(MGF::MgfUnused), m_salt_size(0) {
45✔
57
         auto pss_option = PssOptions().find(type());
45✔
58
         if(pss_option != PssOptions().end()) {
45✔
59
            m_hash = std::get<1>(pss_option->second);
23✔
60
            m_mgf = std::get<2>(pss_option->second);
23✔
61
            m_salt_size = std::get<0>(pss_option->second);
23✔
62
         }
63
      }
45✔
64

65
      MechanismType hash() const { return m_hash; }
66

67
      MGF mgf() const { return m_mgf; }
68

69
      size_t salt_size() const { return m_salt_size; }
70

71
   private:
72
      /*
73
      hash algorithm used in the PSS encoding; if the signature
74
      mechanism does not include message hashing, then this value must
75
      be the mechanism used by the application to generate the message
76
      hash; if the signature mechanism includes hashing, then this
77
      value must match the hash algorithm indicated by the signature mechanism
78
      */
79
      MechanismType m_hash;
80

81
      // mask generation function to use on the encoded block
82
      MGF m_mgf;
83

84
      // length, in bytes, of the salt value used in the PSS encoding; typical values are the length of the message hash and zero
85
      size_t m_salt_size;
86
};
87

88
struct RSA_CryptMechanism final : public MechanismData {
8✔
89
   public:
90
      RSA_CryptMechanism(MechanismType typ, size_t padding_size, MechanismType hash, MGF mgf) :
1✔
91
            MechanismData(typ), m_hash(hash), m_mgf(mgf), m_padding_size(padding_size) {}
1✔
92

93
      RSA_CryptMechanism(MechanismType typ, size_t padding_size) :
1✔
94
            RSA_CryptMechanism(typ, padding_size, static_cast<MechanismType>(0), MGF::MgfUnused) {}
1✔
95

96
      MechanismType hash() const { return m_hash; }
97

98
      MGF mgf() const { return m_mgf; }
99

100
      size_t padding_size() const { return m_padding_size; }
101

102
   private:
103
      // mechanism ID of the message digest algorithm used to calculate the digest of the encoding parameter
104
      MechanismType m_hash;
105

106
      // mask generation function to use on the encoded block
107
      MGF m_mgf;
108

109
      // number of bytes required for the padding
110
      size_t m_padding_size;
111
};
112

113
}  // namespace
114

115
MechanismWrapper::MechanismWrapper(MechanismType mechanism_type) :
34✔
116
      m_mechanism({static_cast<CK_MECHANISM_TYPE>(mechanism_type), nullptr, 0}), m_parameters(nullptr) {}
34✔
117

118
MechanismWrapper MechanismWrapper::create_rsa_crypt_mechanism(std::string_view padding_view) {
10✔
119
   // note: when updating this map, update the documentation for `MechanismWrapper::create_rsa_crypt_mechanism`
120
   static const std::map<std::string_view, RSA_CryptMechanism> CryptMechanisms = {
10✔
121
      {"Raw", RSA_CryptMechanism(MechanismType::RsaX509, 0)},
2✔
122
      // TODO(Botan4) Remove this
123
      {"EME-PKCS1-v1_5", RSA_CryptMechanism(MechanismType::RsaPkcs, 11)},
2✔
124
      {"PKCS1v15", RSA_CryptMechanism(MechanismType::RsaPkcs, 11)},
2✔
125
      {"OAEP(SHA-1)", RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 20, MechanismType::Sha1, MGF::Mgf1Sha1)},
2✔
126
      {"OAEP(SHA-224)",
127
       RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 28, MechanismType::Sha224, MGF::Mgf1Sha224)},
2✔
128
      {"OAEP(SHA-256)",
129
       RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 32, MechanismType::Sha256, MGF::Mgf1Sha256)},
2✔
130
      {"OAEP(SHA-384)",
131
       RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 48, MechanismType::Sha384, MGF::Mgf1Sha384)},
1✔
132
      {"OAEP(SHA-512)",
133
       RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 64, MechanismType::Sha512, MGF::Mgf1Sha512)}};
10✔
134

135
   const std::string padding(padding_view);
10✔
136
   auto mechanism_info_it = CryptMechanisms.find(padding);
10✔
137
   if(mechanism_info_it == CryptMechanisms.end()) {
10✔
138
      // at this point it would be possible to support additional configurations that are not predefined above by parsing `padding`
139
      throw Lookup_Error("PKCS#11 RSA encrypt/decrypt does not support EME " + padding);
×
140
   }
141
   RSA_CryptMechanism mechanism_info = mechanism_info_it->second;
10✔
142

143
   MechanismWrapper mech(mechanism_info.type());
10✔
144
   if(mechanism_info.type() == MechanismType::RsaPkcsOaep) {
10✔
145
      mech.m_parameters = std::make_shared<MechanismParameters>();
3✔
146
      mech.m_parameters->oaep_params.hashAlg = static_cast<CK_MECHANISM_TYPE>(mechanism_info.hash());
3✔
147
      mech.m_parameters->oaep_params.mgf = static_cast<CK_RSA_PKCS_MGF_TYPE>(mechanism_info.mgf());
3✔
148
      mech.m_parameters->oaep_params.source = CKZ_DATA_SPECIFIED;
3✔
149
      mech.m_parameters->oaep_params.pSourceData = nullptr;
3✔
150
      mech.m_parameters->oaep_params.ulSourceDataLen = 0;
3✔
151
      mech.m_mechanism.pParameter = mech.m_parameters.get();
3✔
152
      mech.m_mechanism.ulParameterLen = sizeof(RsaPkcsOaepParams);
3✔
153
   }
154
   mech.m_padding_size = mechanism_info.padding_size();
10✔
155
   return mech;
20✔
156
}
11✔
157

158
MechanismWrapper MechanismWrapper::create_rsa_sign_mechanism(std::string_view padding_view) {
10✔
159
   // note: when updating this map, update the documentation for `MechanismWrapper::create_rsa_sign_mechanism`
160
   static const std::map<std::string_view, RSA_SignMechanism> SignMechanisms = {
10✔
161
      {"Raw", RSA_SignMechanism(MechanismType::RsaX509)},
1✔
162

163
      // X9.31
164
      {"X9.31(Raw)", RSA_SignMechanism(MechanismType::RsaX931)},
1✔
165
      {"X9.31(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaX931)},
1✔
166

167
      // RSASSA PKCS#1 v1.5
168
      {"PKCS1v15(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcs)},
1✔
169
      {"PKCS1v15(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcs)},
1✔
170
      {"PKCS1v15(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcs)},
1✔
171
      {"PKCS1v15(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcs)},
1✔
172
      {"PKCS1v15(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcs)},
1✔
173

174
      // PSS PKCS#1 v2.0
175
      {"PSS(Raw)", RSA_SignMechanism(MechanismType::RsaPkcsPss)},
1✔
176

177
      {"PSS(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcsPss)},
1✔
178
      {"PSS(SHA-1,MGF1,20)", RSA_SignMechanism(MechanismType::Sha1RsaPkcsPss)},
1✔
179

180
      {"PSS(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcsPss)},
1✔
181
      {"PSS(SHA-224,MGF1,24)", RSA_SignMechanism(MechanismType::Sha224RsaPkcsPss)},
1✔
182

183
      {"PSS(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
1✔
184
      {"PSS(SHA-256,MGF1,32)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
1✔
185

186
      {"PSS(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
1✔
187
      {"PSS(SHA-384,MGF1,48)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
1✔
188

189
      {"PSS(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
1✔
190
      {"PSS(SHA-512,MGF1,64)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
1✔
191

192
      // ISO 9796 - this is the obsolete and insecure DS1 scheme, not the PSS-based DS2/DS3
193
      // TODO(Botan4) remove this
194
      {"ISO9796", RSA_SignMechanism(MechanismType::Rsa9796)},
1✔
195

196
      // Deprecated aliases
197
      // TODO(Botan4) remove these
198
      {"EMSA2(Raw)", RSA_SignMechanism(MechanismType::RsaX931)},
1✔
199
      {"EMSA2(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaX931)},
1✔
200

201
      {"EMSA3(Raw)", RSA_SignMechanism(MechanismType::RsaPkcs)},
1✔
202
      {"EMSA3(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcs)},
1✔
203
      {"EMSA3(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcs)},
1✔
204
      {"EMSA3(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcs)},
1✔
205
      {"EMSA3(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcs)},
1✔
206
      {"EMSA3(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcs)},
1✔
207

208
      {"EMSA_PKCS1(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcs)},
1✔
209
      {"EMSA_PKCS1(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcs)},
1✔
210
      {"EMSA_PKCS1(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcs)},
1✔
211
      {"EMSA_PKCS1(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcs)},
1✔
212
      {"EMSA_PKCS1(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcs)},
1✔
213

214
      {"EMSA4(Raw)", RSA_SignMechanism(MechanismType::RsaPkcsPss)},
1✔
215
      {"EMSA4(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcsPss)},
1✔
216
      {"EMSA4(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcsPss)},
1✔
217

218
      {"EMSA4(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
1✔
219
      {"EMSA4(SHA-256,MGF1,32)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
1✔
220
      {"PSSR(SHA-256,MGF1,32)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
1✔
221

222
      {"EMSA4(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
1✔
223
      {"EMSA4(SHA-384,MGF1,48)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
1✔
224
      {"PSSR(SHA-384,MGF1,48)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
1✔
225

226
      {"EMSA4(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
1✔
227
      {"EMSA4(SHA-512,MGF1,64)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
1✔
228
      {"PSSR(SHA-512,MGF1,64)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
2✔
229
   };
11✔
230

231
   const std::string padding(padding_view);
10✔
232
   auto mechanism_info_it = SignMechanisms.find(padding);
10✔
233
   if(mechanism_info_it == SignMechanisms.end()) {
10✔
234
      // at this point it would be possible to support additional configurations that are not predefined above by parsing `padding`
235
      throw Lookup_Error("PKCS#11 RSA sign/verify does not support EMSA " + padding);
×
236
   }
237
   RSA_SignMechanism mechanism_info = mechanism_info_it->second;
10✔
238

239
   MechanismWrapper mech(mechanism_info.type());
10✔
240
   if(PssOptions().contains(mechanism_info.type())) {
20✔
241
      mech.m_parameters = std::make_shared<MechanismParameters>();
4✔
242
      mech.m_parameters->pss_params.hashAlg = static_cast<CK_MECHANISM_TYPE>(mechanism_info.hash());
4✔
243
      mech.m_parameters->pss_params.mgf = static_cast<CK_RSA_PKCS_MGF_TYPE>(mechanism_info.mgf());
4✔
244
      mech.m_parameters->pss_params.sLen = static_cast<Ulong>(mechanism_info.salt_size());
4✔
245
      mech.m_mechanism.pParameter = mech.m_parameters.get();
4✔
246
      mech.m_mechanism.ulParameterLen = sizeof(RsaPkcsPssParams);
4✔
247
   }
248
   return mech;
20✔
249
}
11✔
250

251
MechanismWrapper MechanismWrapper::create_ecdsa_mechanism(std::string_view hash_spec_view) {
12✔
252
   // note: when updating this map, update the documentation for `MechanismWrapper::create_ecdsa_mechanism`
253
   static const std::map<std::string_view, MechanismType> EcdsaHash = {{"Raw", MechanismType::Ecdsa},
1✔
254
                                                                       {"SHA-1", MechanismType::EcdsaSha1},
1✔
255
                                                                       {"SHA-224", MechanismType::EcdsaSha224},
1✔
256
                                                                       {"SHA-256", MechanismType::EcdsaSha256},
1✔
257
                                                                       {"SHA-384", MechanismType::EcdsaSha384},
1✔
258
                                                                       {"SHA-512", MechanismType::EcdsaSha512}};
12✔
259

260
   const std::string hash_spec(hash_spec_view);
12✔
261
   auto mechanism = EcdsaHash.find(hash_spec);
12✔
262
   if(mechanism != EcdsaHash.end()) {
12✔
263
      return MechanismWrapper(mechanism->second);
12✔
264
   }
265

266
   SCAN_Name req(hash_spec);
×
267

268
   if(req.algo_name() == "EMSA1" && req.arg_count() == 1) {
×
269
      mechanism = EcdsaHash.find(req.arg(0));
×
270
      if(mechanism != EcdsaHash.end()) {
×
271
         return MechanismWrapper(mechanism->second);
×
272
      }
273
   }
274

275
   throw Lookup_Error(fmt("PKCS #11 ECDSA sign/verify does not support {}", hash_spec));
×
276
}
12✔
277

278
MechanismWrapper MechanismWrapper::create_ecdh_mechanism(std::string_view params) {
2✔
279
   // note: when updating this map, update the documentation for `MechanismWrapper::create_ecdh_mechanism`
280
   static const std::map<std::string_view, KeyDerivation> EcdhHash = {{"Raw", KeyDerivation::Null},
1✔
281
                                                                      {"SHA-1", KeyDerivation::Sha1Kdf},
1✔
282
                                                                      {"SHA-224", KeyDerivation::Sha224Kdf},
1✔
283
                                                                      {"SHA-256", KeyDerivation::Sha256Kdf},
1✔
284
                                                                      {"SHA-384", KeyDerivation::Sha384Kdf},
1✔
285
                                                                      {"SHA-512", KeyDerivation::Sha512Kdf}};
2✔
286

287
   std::vector<std::string> param_parts = split_on(params, ',');
2✔
288

289
   if(param_parts.empty() || param_parts.size() > 2) {
2✔
290
      throw Invalid_Argument(fmt("PKCS #11 ECDH key derivation bad params {}", params));
×
291
   }
292

293
   const bool use_cofactor =
2✔
294
      (param_parts[0] == "Cofactor") || (param_parts.size() == 2 && param_parts[1] == "Cofactor");
2✔
295

296
   std::string kdf_name = (param_parts[0] == "Cofactor" ? param_parts[1] : param_parts[0]);
2✔
297
   std::string hash = kdf_name;
2✔
298

299
   if(kdf_name != "Raw") {
2✔
300
      SCAN_Name kdf_hash(kdf_name);
×
301

302
      if(kdf_hash.arg_count() > 0) {
×
303
         hash = kdf_hash.arg(0);
×
304
      }
305
   }
×
306

307
   auto kdf = EcdhHash.find(hash);
2✔
308
   if(kdf == EcdhHash.end()) {
2✔
309
      throw Lookup_Error("PKCS#11 ECDH key derivation does not support KDF " + kdf_name);
×
310
   }
311
   MechanismWrapper mech(use_cofactor ? MechanismType::Ecdh1CofactorDerive : MechanismType::Ecdh1Derive);
4✔
312
   mech.m_parameters = std::make_shared<MechanismParameters>();
2✔
313
   mech.m_parameters->ecdh_params.kdf = static_cast<CK_EC_KDF_TYPE>(kdf->second);
2✔
314
   mech.m_mechanism.pParameter = mech.m_parameters.get();
2✔
315
   mech.m_mechanism.ulParameterLen = sizeof(Ecdh1DeriveParams);
2✔
316
   return mech;
4✔
317
}
2✔
318

319
}  // namespace Botan::PKCS11
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