Botan 3.7.1
Crypto and TLS for C&
p11_mechanism.cpp
Go to the documentation of this file.
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
16namespace Botan::PKCS11 {
17
18namespace {
19using 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
22const std::map<MechanismType, PSS_Params> PssOptions = {
29
30class MechanismData {
31 public:
32 explicit MechanismData(MechanismType type) : m_type(type) {}
33
34 MechanismData(const MechanismData& other) = default;
35 MechanismData(MechanismData&& other) = default;
36
37 MechanismData& operator=(const MechanismData& other) = default;
38 MechanismData& operator=(MechanismData&& other) = default;
39
40 virtual ~MechanismData() = default;
41
42 MechanismType type() const { return m_type; }
43
44 private:
45 // the mechanism to perform
46 MechanismType m_type;
47};
48
49class RSA_SignMechanism final : public MechanismData {
50 public:
51 explicit RSA_SignMechanism(MechanismType typ) :
52 MechanismData(typ), m_hash(static_cast<MechanismType>(0)), m_mgf(MGF::MgfUnused), m_salt_size(0) {
53 auto pss_option = PssOptions.find(type());
54 if(pss_option != PssOptions.end()) {
55 m_hash = std::get<1>(pss_option->second);
56 m_mgf = std::get<2>(pss_option->second);
57 m_salt_size = std::get<0>(pss_option->second);
58 }
59 }
60
61 MechanismType hash() const { return m_hash; }
62
63 MGF mgf() const { return m_mgf; }
64
65 size_t salt_size() const { return m_salt_size; }
66
67 private:
68 /*
69 hash algorithm used in the PSS encoding; if the signature
70 mechanism does not include message hashing, then this value must
71 be the mechanism used by the application to generate the message
72 hash; if the signature mechanism includes hashing, then this
73 value must match the hash algorithm indicated by the signature mechanism
74 */
75 MechanismType m_hash;
76
77 // mask generation function to use on the encoded block
78 MGF m_mgf;
79
80 // length, in bytes, of the salt value used in the PSS encoding; typical values are the length of the message hash and zero
81 size_t m_salt_size;
82};
83
84// note: when updating this map, update the documentation for `MechanismWrapper::create_rsa_sign_mechanism`
85const std::map<std::string, RSA_SignMechanism> SignMechanisms = {
86 {"Raw", RSA_SignMechanism(MechanismType::RsaX509)},
87
88 // X9.31
89 {"X9.31(Raw)", RSA_SignMechanism(MechanismType::RsaX931)},
90 {"X9.31(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaX931)},
91
92 // RSASSA PKCS#1 v1.5
93 {"PKCS1v15(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcs)},
94 {"PKCS1v15(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcs)},
95 {"PKCS1v15(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcs)},
96 {"PKCS1v15(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcs)},
97 {"PKCS1v15(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcs)},
98
99 // PSS PKCS#1 v2.0
100 {"PSS(Raw)", RSA_SignMechanism(MechanismType::RsaPkcsPss)},
101
102 {"PSS(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcsPss)},
103 {"PSS(SHA-1,MGF1,20)", RSA_SignMechanism(MechanismType::Sha1RsaPkcsPss)},
104
105 {"PSS(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcsPss)},
106 {"PSS(SHA-224,MGF1,24)", RSA_SignMechanism(MechanismType::Sha224RsaPkcsPss)},
107
108 {"PSS(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
109 {"PSS(SHA-256,MGF1,32)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
110
111 {"PSS(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
112 {"PSS(SHA-384,MGF1,48)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
113
114 {"PSS(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
115 {"PSS(SHA-512,MGF1,64)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
116
117 // ISO 9796 (TODO is this DS1, DS2, or DS3?)
118 {"ISO9796", RSA_SignMechanism(MechanismType::Rsa9796)},
119
120 // Deprecated aliases
121 // TODO(Botan4) remove these
122 {"EMSA2(Raw)", RSA_SignMechanism(MechanismType::RsaX931)},
123 {"EMSA2(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaX931)},
124
125 {"EMSA3(Raw)", RSA_SignMechanism(MechanismType::RsaPkcs)},
126 {"EMSA3(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcs)},
127 {"EMSA3(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcs)},
128 {"EMSA3(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcs)},
129 {"EMSA3(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcs)},
130 {"EMSA3(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcs)},
131
132 {"EMSA_PKCS1(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcs)},
133 {"EMSA_PKCS1(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcs)},
134 {"EMSA_PKCS1(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcs)},
135 {"EMSA_PKCS1(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcs)},
136 {"EMSA_PKCS1(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcs)},
137
138 {"EMSA4(Raw)", RSA_SignMechanism(MechanismType::RsaPkcsPss)},
139 {"EMSA4(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcsPss)},
140 {"EMSA4(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcsPss)},
141
142 {"EMSA4(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
143 {"EMSA4(SHA-256,MGF1,32)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
144 {"PSSR(SHA-256,MGF1,32)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss)},
145
146 {"EMSA4(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
147 {"EMSA4(SHA-384,MGF1,48)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
148 {"PSSR(SHA-384,MGF1,48)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss)},
149
150 {"EMSA4(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
151 {"EMSA4(SHA-512,MGF1,64)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
152 {"PSSR(SHA-512,MGF1,64)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss)},
153};
154
155struct RSA_CryptMechanism final : public MechanismData {
156 public:
157 RSA_CryptMechanism(MechanismType typ, size_t padding_size, MechanismType hash, MGF mgf) :
158 MechanismData(typ), m_hash(hash), m_mgf(mgf), m_padding_size(padding_size) {}
159
160 RSA_CryptMechanism(MechanismType typ, size_t padding_size) :
161 RSA_CryptMechanism(typ, padding_size, static_cast<MechanismType>(0), MGF::MgfUnused) {}
162
163 MechanismType hash() const { return m_hash; }
164
165 MGF mgf() const { return m_mgf; }
166
167 size_t padding_size() const { return m_padding_size; }
168
169 private:
170 // mechanism ID of the message digest algorithm used to calculate the digest of the encoding parameter
171 MechanismType m_hash;
172
173 // mask generation function to use on the encoded block
174 MGF m_mgf;
175
176 // number of bytes required for the padding
177 size_t m_padding_size;
178};
179
180// note: when updating this map, update the documentation for `MechanismWrapper::create_rsa_crypt_mechanism`
181const std::map<std::string, RSA_CryptMechanism> CryptMechanisms = {
182 {"Raw", RSA_CryptMechanism(MechanismType::RsaX509, 0)},
183 // TODO(Botan4) Remove this
184 {"EME-PKCS1-v1_5", RSA_CryptMechanism(MechanismType::RsaPkcs, 11)},
185 {"PKCS1v15", RSA_CryptMechanism(MechanismType::RsaPkcs, 11)},
186 {"OAEP(SHA-1)", RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 20, MechanismType::Sha1, MGF::Mgf1Sha1)},
187 {"OAEP(SHA-224)",
188 RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 28, MechanismType::Sha224, MGF::Mgf1Sha224)},
189 {"OAEP(SHA-256)",
190 RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 32, MechanismType::Sha256, MGF::Mgf1Sha256)},
191 {"OAEP(SHA-384)",
192 RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 48, MechanismType::Sha384, MGF::Mgf1Sha384)},
193 {"OAEP(SHA-512)",
194 RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 64, MechanismType::Sha512, MGF::Mgf1Sha512)}};
195
196// note: when updating this map, update the documentation for `MechanismWrapper::create_ecdsa_mechanism`
197const std::map<std::string, MechanismType> EcdsaHash = {{"Raw", MechanismType::Ecdsa},
198 {"SHA-1", MechanismType::EcdsaSha1},
199 {"SHA-224", MechanismType::EcdsaSha224},
200 {"SHA-256", MechanismType::EcdsaSha256},
201 {"SHA-384", MechanismType::EcdsaSha384},
202 {"SHA-512", MechanismType::EcdsaSha512}};
203
204// note: when updating this map, update the documentation for `MechanismWrapper::create_ecdh_mechanism`
205const std::map<std::string, KeyDerivation> EcdhHash = {{"Raw", KeyDerivation::Null},
206 {"SHA-1", KeyDerivation::Sha1Kdf},
207 {"SHA-224", KeyDerivation::Sha224Kdf},
208 {"SHA-256", KeyDerivation::Sha256Kdf},
209 {"SHA-384", KeyDerivation::Sha384Kdf},
210 {"SHA-512", KeyDerivation::Sha512Kdf}};
211} // namespace
212
214 m_mechanism({static_cast<CK_MECHANISM_TYPE>(mechanism_type), nullptr, 0}), m_parameters(nullptr) {}
215
217 const std::string padding(padding_view);
218 auto mechanism_info_it = CryptMechanisms.find(padding);
219 if(mechanism_info_it == CryptMechanisms.end()) {
220 // at this point it would be possible to support additional configurations that are not predefined above by parsing `padding`
221 throw Lookup_Error("PKCS#11 RSA encrypt/decrypt does not support EME " + padding);
222 }
223 RSA_CryptMechanism mechanism_info = mechanism_info_it->second;
224
225 MechanismWrapper mech(mechanism_info.type());
226 if(mechanism_info.type() == MechanismType::RsaPkcsOaep) {
227 mech.m_parameters = std::make_shared<MechanismParameters>();
228 mech.m_parameters->oaep_params.hashAlg = static_cast<CK_MECHANISM_TYPE>(mechanism_info.hash());
229 mech.m_parameters->oaep_params.mgf = static_cast<CK_RSA_PKCS_MGF_TYPE>(mechanism_info.mgf());
230 mech.m_parameters->oaep_params.source = CKZ_DATA_SPECIFIED;
231 mech.m_parameters->oaep_params.pSourceData = nullptr;
232 mech.m_parameters->oaep_params.ulSourceDataLen = 0;
233 mech.m_mechanism.pParameter = mech.m_parameters.get();
234 mech.m_mechanism.ulParameterLen = sizeof(RsaPkcsOaepParams);
235 }
236 mech.m_padding_size = mechanism_info.padding_size();
237 return mech;
238}
239
241 const std::string padding(padding_view);
242 auto mechanism_info_it = SignMechanisms.find(padding);
243 if(mechanism_info_it == SignMechanisms.end()) {
244 // at this point it would be possible to support additional configurations that are not predefined above by parsing `padding`
245 throw Lookup_Error("PKCS#11 RSA sign/verify does not support EMSA " + padding);
246 }
247 RSA_SignMechanism mechanism_info = mechanism_info_it->second;
248
249 MechanismWrapper mech(mechanism_info.type());
250 if(PssOptions.find(mechanism_info.type()) != PssOptions.end()) {
251 mech.m_parameters = std::make_shared<MechanismParameters>();
252 mech.m_parameters->pss_params.hashAlg = static_cast<CK_MECHANISM_TYPE>(mechanism_info.hash());
253 mech.m_parameters->pss_params.mgf = static_cast<CK_RSA_PKCS_MGF_TYPE>(mechanism_info.mgf());
254 mech.m_parameters->pss_params.sLen = static_cast<Ulong>(mechanism_info.salt_size());
255 mech.m_mechanism.pParameter = mech.m_parameters.get();
256 mech.m_mechanism.ulParameterLen = sizeof(RsaPkcsPssParams);
257 }
258 return mech;
259}
260
262 const std::string hash_spec(hash_spec_view);
263 auto mechanism = EcdsaHash.find(hash_spec);
264 if(mechanism != EcdsaHash.end()) {
265 return MechanismWrapper(mechanism->second);
266 }
267
268 SCAN_Name req(hash_spec);
269
270 if(req.algo_name() == "EMSA1" && req.arg_count() == 1) {
271 mechanism = EcdsaHash.find(req.arg(0));
272 if(mechanism != EcdsaHash.end()) {
273 return MechanismWrapper(mechanism->second);
274 }
275 }
276
277 throw Lookup_Error(fmt("PKCS #11 ECDSA sign/verify does not support {}", hash_spec));
278}
279
281 std::vector<std::string> param_parts = split_on(params, ',');
282
283 if(param_parts.empty() || param_parts.size() > 2) {
284 throw Invalid_Argument(fmt("PKCS #11 ECDH key derivation bad params {}", params));
285 }
286
287 const bool use_cofactor =
288 (param_parts[0] == "Cofactor") || (param_parts.size() == 2 && param_parts[1] == "Cofactor");
289
290 std::string kdf_name = (param_parts[0] == "Cofactor" ? param_parts[1] : param_parts[0]);
291 std::string hash = kdf_name;
292
293 if(kdf_name != "Raw") {
294 SCAN_Name kdf_hash(kdf_name);
295
296 if(kdf_hash.arg_count() > 0) {
297 hash = kdf_hash.arg(0);
298 }
299 }
300
301 auto kdf = EcdhHash.find(hash);
302 if(kdf == EcdhHash.end()) {
303 throw Lookup_Error("PKCS#11 ECDH key derivation does not support KDF " + kdf_name);
304 }
306 mech.m_parameters = std::make_shared<MechanismParameters>();
307 mech.m_parameters->ecdh_params.kdf = static_cast<CK_EC_KDF_TYPE>(kdf->second);
308 mech.m_mechanism.pParameter = mech.m_parameters.get();
309 mech.m_mechanism.ulParameterLen = sizeof(Ecdh1DeriveParams);
310 return mech;
311}
312
313} // namespace Botan::PKCS11
static MechanismWrapper create_rsa_sign_mechanism(std::string_view padding)
static MechanismWrapper create_ecdh_mechanism(std::string_view params)
MechanismType mechanism_type() const
static MechanismWrapper create_rsa_crypt_mechanism(std::string_view padding)
static MechanismWrapper create_ecdsa_mechanism(std::string_view hash)
MechanismWrapper(MechanismType mechanism_type)
std::string arg(size_t i) const
size_t arg_count() const
Definition scan_name.h:49
const std::string & algo_name() const
Definition scan_name.h:44
int(* final)(unsigned char *, CTX *)
CK_RSA_PKCS_OAEP_PARAMS RsaPkcsOaepParams
Definition p11.h:828
CK_ECDH1_DERIVE_PARAMS Ecdh1DeriveParams
Definition p11.h:830
CK_ULONG Ulong
Definition p11.h:816
CK_RSA_PKCS_PSS_PARAMS RsaPkcsPssParams
Definition p11.h:829
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::vector< std::string > split_on(std::string_view str, char delim)
Definition parsing.cpp:111
CK_ULONG CK_EC_KDF_TYPE
Definition pkcs11t.h:1287
#define CKZ_DATA_SPECIFIED
Definition pkcs11t.h:1261
CK_ULONG CK_RSA_PKCS_MGF_TYPE
Definition pkcs11t.h:1241
CK_ULONG CK_MECHANISM_TYPE
Definition pkcs11t.h:583
CK_VOID_PTR pParameter
Definition pkcs11t.h:985
CK_ULONG ulParameterLen
Definition pkcs11t.h:986