Botan 3.0.0-alpha0
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/internal/p11_mechanism.h>
10#include <botan/internal/scan_name.h>
11#include <botan/internal/parsing.h>
12#include <botan/internal/emsa.h>
13
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 =
23 {
30 };
31
32struct MechanismData
33 {
34 explicit MechanismData(MechanismType _type)
35 : type(_type)
36 {}
37
38 MechanismData(const MechanismData& other) = default;
39 MechanismData(MechanismData&& other) = default;
40
41 MechanismData& operator=(const MechanismData& other) = default;
42 MechanismData& operator=(MechanismData&& other) = default;
43
44 virtual ~MechanismData() = default;
45
46 // the mechanism to perform
48 };
49
50struct RSA_SignMechanism final : public MechanismData
51 {
52 explicit RSA_SignMechanism(MechanismType _type)
53 : MechanismData(_type), hash(static_cast<MechanismType>(0)), mgf(static_cast<MGF>(0)), salt_size(0)
54 {
55 auto pss_option = PssOptions.find(type);
56 if(pss_option != PssOptions.end())
57 {
58 hash = std::get<1>(pss_option->second);
59 mgf = std::get<2>(pss_option->second);
60 salt_size = std::get<0>(pss_option->second);
61 }
62 }
63
64 // hash algorithm used in the PSS encoding; if the signature mechanism does not include message hashing,
65 // then this value must be the mechanism used by the application to generate the message hash;
66 // if the signature mechanism includes hashing, then this value must match the hash algorithm indicated by the signature mechanism
68
69 // mask generation function to use on the encoded block
71
72 // length, in bytes, of the salt value used in the PSS encoding; typical values are the length of the message hash and zero
73 size_t salt_size;
74 };
75
76// note: when updating this map, update the documentation for `MechanismWrapper::create_rsa_sign_mechanism`
77const std::map<std::string, RSA_SignMechanism> SignMechanisms =
78 {
79 { "Raw", RSA_SignMechanism(MechanismType::RsaX509) },
80
81 { "EMSA2(Raw)", RSA_SignMechanism(MechanismType::RsaX931) },
82 { "EMSA2(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaX931) },
83
84 // RSASSA PKCS#1 v1.5
85 { "EMSA3(Raw)", RSA_SignMechanism(MechanismType::RsaPkcs) },
86 { "EMSA3(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcs) },
87 { "EMSA3(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcs) },
88 { "EMSA3(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcs) },
89 { "EMSA3(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcs) },
90 { "EMSA3(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcs) },
91
92 { "EMSA_PKCS1(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcs) },
93 { "EMSA_PKCS1(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcs) },
94 { "EMSA_PKCS1(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcs) },
95 { "EMSA_PKCS1(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcs) },
96 { "EMSA_PKCS1(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcs) },
97
98 // RSASSA PKCS#1 PSS
99 { "EMSA4(Raw)", RSA_SignMechanism(MechanismType::RsaPkcsPss) },
100 { "EMSA4(SHA-1)", RSA_SignMechanism(MechanismType::Sha1RsaPkcsPss) },
101 { "EMSA4(SHA-224)", RSA_SignMechanism(MechanismType::Sha224RsaPkcsPss) },
102
103 { "EMSA4(SHA-256)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss) },
104 { "EMSA4(SHA-256,MGF1,32)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss) },
105 { "PSSR(SHA-256,MGF1,32)", RSA_SignMechanism(MechanismType::Sha256RsaPkcsPss) },
106
107 { "EMSA4(SHA-384)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss) },
108 { "EMSA4(SHA-384,MGF1,48)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss) },
109 { "PSSR(SHA-384,MGF1,48)", RSA_SignMechanism(MechanismType::Sha384RsaPkcsPss) },
110
111 { "EMSA4(SHA-512)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss) },
112 { "EMSA4(SHA-512,MGF1,64)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss) },
113 { "PSSR(SHA-512,MGF1,64)", RSA_SignMechanism(MechanismType::Sha512RsaPkcsPss) },
114
115 { "ISO9796", RSA_SignMechanism(MechanismType::Rsa9796) }
116 };
117
118struct RSA_CryptMechanism final : public MechanismData
119 {
120 RSA_CryptMechanism(MechanismType _type, size_t _padding_size, MechanismType _hash, MGF _mgf)
121 : MechanismData(_type), hash(_hash), mgf(_mgf), padding_size(_padding_size)
122 {}
123
124 RSA_CryptMechanism(MechanismType _type, size_t _padding_size)
125 : RSA_CryptMechanism(_type, _padding_size, static_cast<MechanismType>(0), static_cast<MGF>(0))
126 {}
127
128 // mechanism ID of the message digest algorithm used to calculate the digest of the encoding parameter
130
131 // mask generation function to use on the encoded block
132 MGF mgf;
133
134 // number of bytes required for the padding
136 };
137
138// note: when updating this map, update the documentation for `MechanismWrapper::create_rsa_crypt_mechanism`
139const std::map<std::string, RSA_CryptMechanism> CryptMechanisms =
140 {
141 { "Raw", RSA_CryptMechanism(MechanismType::RsaX509, 0) },
142 { "EME-PKCS1-v1_5", RSA_CryptMechanism(MechanismType::RsaPkcs, 11) },
143 { "OAEP(SHA-1)", RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 20, MechanismType::Sha1, MGF::Mgf1Sha1) },
144 { "OAEP(SHA-224)", RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 28, MechanismType::Sha224, MGF::Mgf1Sha224) },
145 { "OAEP(SHA-256)", RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 32, MechanismType::Sha256, MGF::Mgf1Sha256) },
146 { "OAEP(SHA-384)", RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 48, MechanismType::Sha384, MGF::Mgf1Sha384) },
147 { "OAEP(SHA-512)", RSA_CryptMechanism(MechanismType::RsaPkcsOaep, 2 + 2 * 64, MechanismType::Sha512, MGF::Mgf1Sha512) }
148 };
149
150// note: when updating this map, update the documentation for `MechanismWrapper::create_ecdsa_mechanism`
151const std::map<std::string, MechanismType> EcdsaHash =
152 {
153 { "Raw", MechanismType::Ecdsa },
154 { "SHA-160", MechanismType::EcdsaSha1 },
155 { "SHA-224", MechanismType::EcdsaSha224 },
156 { "SHA-256", MechanismType::EcdsaSha256 },
157 { "SHA-384", MechanismType::EcdsaSha384 },
158 { "SHA-512", MechanismType::EcdsaSha512 }
159 };
160
161// note: when updating this map, update the documentation for `MechanismWrapper::create_ecdh_mechanism`
162const std::map<std::string, KeyDerivation> EcdhHash =
163 {
164 { "Raw", KeyDerivation::Null },
165 { "SHA-160", KeyDerivation::Sha1Kdf },
166 { "SHA-224", KeyDerivation::Sha224Kdf },
167 { "SHA-256", KeyDerivation::Sha256Kdf },
168 { "SHA-384", KeyDerivation::Sha384Kdf },
169 { "SHA-512", KeyDerivation::Sha512Kdf }
170 };
171}
172
174 : m_mechanism( { static_cast<CK_MECHANISM_TYPE>(mechanism_type), nullptr, 0 }), m_parameters(nullptr)
175 {}
176
178 {
179 auto mechanism_info_it = CryptMechanisms.find(padding);
180 if(mechanism_info_it == CryptMechanisms.end())
181 {
182 // at this point it would be possible to support additional configurations that are not predefined above by parsing `padding`
183 throw Lookup_Error("PKCS#11 RSA encrypt/decrypt does not support EME " + padding);
184 }
185 RSA_CryptMechanism mechanism_info = mechanism_info_it->second;
186
187 MechanismWrapper mech(mechanism_info.type);
188 if(mechanism_info.type == MechanismType::RsaPkcsOaep)
189 {
190 mech.m_parameters = std::make_shared<MechanismParameters>();
191 mech.m_parameters->oaep_params.hashAlg = static_cast<CK_MECHANISM_TYPE>(mechanism_info.hash);
192 mech.m_parameters->oaep_params.mgf = static_cast<CK_RSA_PKCS_MGF_TYPE>(mechanism_info.mgf);
193 mech.m_parameters->oaep_params.source = CKZ_DATA_SPECIFIED;
194 mech.m_parameters->oaep_params.pSourceData = nullptr;
195 mech.m_parameters->oaep_params.ulSourceDataLen = 0;
196 mech.m_mechanism.pParameter = mech.m_parameters.get();
197 mech.m_mechanism.ulParameterLen = sizeof(RsaPkcsOaepParams);
198 }
199 mech.m_padding_size = mechanism_info.padding_size;
200 return mech;
201 }
202
204 {
205 auto mechanism_info_it = SignMechanisms.find(padding);
206 if(mechanism_info_it == SignMechanisms.end())
207 {
208 // at this point it would be possible to support additional configurations that are not predefined above by parsing `padding`
209 throw Lookup_Error("PKCS#11 RSA sign/verify does not support EMSA " + padding);
210 }
211 RSA_SignMechanism mechanism_info = mechanism_info_it->second;
212
213 MechanismWrapper mech(mechanism_info.type);
214 if(PssOptions.find(mechanism_info.type) != PssOptions.end())
215 {
216 mech.m_parameters = std::make_shared<MechanismParameters>();
217 mech.m_parameters->pss_params.hashAlg = static_cast<CK_MECHANISM_TYPE>(mechanism_info.hash);
218 mech.m_parameters->pss_params.mgf = static_cast<CK_RSA_PKCS_MGF_TYPE>(mechanism_info.mgf);
219 mech.m_parameters->pss_params.sLen = static_cast<Ulong>(mechanism_info.salt_size);
220 mech.m_mechanism.pParameter = mech.m_parameters.get();
221 mech.m_mechanism.ulParameterLen = sizeof(RsaPkcsPssParams);
222 }
223 return mech;
224 }
225
227 {
228 std::string hash_name = hash;
229
230 if(hash_name != "Raw")
231 {
232 hash_name = hash_for_emsa(hash);
233 }
234
235 auto mechanism_type = EcdsaHash.find(hash_name);
236 if(mechanism_type == EcdsaHash.end())
237 {
238 throw Lookup_Error("PKCS#11 ECDSA sign/verify does not support " + hash);
239 }
240 return MechanismWrapper(mechanism_type->second);
241 }
242
244 {
245 std::vector<std::string> param_parts = split_on(params, ',');
246
247 if(param_parts.empty() || param_parts.size() > 2)
248 throw Invalid_Argument("PKCS #11 ECDH key derivation bad params " + params);
249
250 const bool use_cofactor =
251 (param_parts[0] == "Cofactor") ||
252 (param_parts.size() == 2 && param_parts[1] == "Cofactor");
253
254 std::string kdf_name = (param_parts[0] == "Cofactor" ? param_parts[1] : param_parts[0]);
255 std::string hash = kdf_name;
256
257 if(kdf_name != "Raw")
258 {
259 SCAN_Name kdf_hash(kdf_name);
260
261 if(kdf_hash.arg_count() > 0)
262 {
263 hash = kdf_hash.arg(0);
264 }
265 }
266
267 auto kdf = EcdhHash.find(hash);
268 if(kdf == EcdhHash.end())
269 {
270 throw Lookup_Error("PKCS#11 ECDH key derivation does not support KDF " + kdf_name);
271 }
273 mech.m_parameters = std::make_shared<MechanismParameters>();
274 mech.m_parameters->ecdh_params.kdf = static_cast<CK_EC_KDF_TYPE>(kdf->second);
275 mech.m_mechanism.pParameter = mech.m_parameters.get();
276 mech.m_mechanism.ulParameterLen = sizeof(Ecdh1DeriveParams);
277 return mech;
278 }
279
280}
static MechanismWrapper create_ecdh_mechanism(const std::string &params)
static MechanismWrapper create_rsa_sign_mechanism(const std::string &padding)
static MechanismWrapper create_ecdsa_mechanism(const std::string &hash)
static MechanismWrapper create_rsa_crypt_mechanism(const std::string &padding)
MechanismWrapper(MechanismType mechanism_type)
std::string arg(size_t i) const
Definition: scan_name.cpp:129
size_t arg_count() const
Definition: scan_name.h:49
int(* final)(unsigned char *, CTX *)
CK_RSA_PKCS_OAEP_PARAMS RsaPkcsOaepParams
Definition: p11.h:850
CK_RSA_PKCS_PSS_PARAMS RsaPkcsPssParams
Definition: p11.h:851
MechanismType
Definition: p11.h:338
CK_ECDH1_DERIVE_PARAMS Ecdh1DeriveParams
Definition: p11.h:852
CK_ULONG Ulong
Definition: p11.h:838
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:111
std::string hash_for_emsa(const std::string &algo_spec)
Definition: emsa.cpp:197
MGF mgf
MechanismType hash
MechanismType type
size_t padding_size
size_t salt_size
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