1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
// Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Mechanism info and associated flags
#[cfg(doc)]
use crate::session::Session;
use bitflags::bitflags;
use cryptoki_sys::*;
use std::fmt::{Debug, Formatter};
bitflags! {
#[derive(Debug, Clone, Copy)]
struct MechanismInfoFlags: CK_FLAGS {
const HW = CKF_HW;
const ENCRYPT = CKF_ENCRYPT;
const DECRYPT = CKF_DECRYPT;
const DIGEST = CKF_DIGEST;
const SIGN = CKF_SIGN;
const SIGN_RECOVER = CKF_SIGN_RECOVER;
const VERIFY = CKF_VERIFY;
const VERIFY_RECOVER = CKF_VERIFY_RECOVER;
const GENERATE = CKF_GENERATE;
const GENERATE_KEY_PAIR = CKF_GENERATE_KEY_PAIR;
const WRAP = CKF_WRAP;
const UNWRAP = CKF_UNWRAP;
const DERIVE = CKF_DERIVE;
const EXTENSION = CKF_EXTENSION;
const EC_F_P = CKF_EC_F_P;
const EC_F_2M = CKF_EC_F_2M;
const EC_ECPARAMETERS = CKF_EC_ECPARAMETERS;
const EC_OID = CKF_EC_OID;
const EC_UNCOMPRESS = CKF_EC_UNCOMPRESS;
const EC_COMPRESS = CKF_EC_COMPRESS;
const MESSAGE_ENCRYPT = CKF_MESSAGE_ENCRYPT;
const MESSAGE_DECRYPT = CKF_MESSAGE_DECRYPT;
const MULTI_MESSAGE = CKF_MULTI_MESSAGE;
const ENCAPSULATE = CKF_ENCAPSULATE;
const DECAPSULATE = CKF_DECAPSULATE;
}
}
impl MechanismInfoFlags {
/// `CKF_EC_NAMEDCURVE` is deprecated with `PKCS#11 3.00`. It is replaced by [`CKF_EC_OID`](MechanismInfoFlags::EC_OID).
#[deprecated = "use `EC_OID` instead"]
pub const EC_NAMEDCURVE: Self = Self::from_bits_retain(CKF_EC_NAMEDCURVE);
}
/// Information about a particular mechanism
#[derive(Debug, Clone, Copy)]
pub struct MechanismInfo {
min_key_size: usize,
max_key_size: usize,
flags: MechanismInfoFlags,
}
impl MechanismInfo {
/// The minimum size of the key for the mechanism
///
/// **[Conformance](crate#conformance-notes):**
/// Whether this is measured in bits or in bytes is mechanism-dependent.
/// For some mechanisms, this field may be meaningless and take any value.
pub fn min_key_size(&self) -> usize {
self.min_key_size
}
/// The maximum size of the key for the mechanism
///
/// **[Conformance](crate#conformance-notes):**
/// Whether this is measured in bits or in bytes is mechanism-dependent
/// For some mechanisms, this field may be meaningless and take any value.
pub fn max_key_size(&self) -> usize {
self.max_key_size
}
/// True if the mechanism is performed by the device; false if the
/// mechanism is performed in software
pub fn hardware(&self) -> bool {
self.flags.contains(MechanismInfoFlags::HW)
}
/// True if the mechanism can be used to encrypt data
///
/// See [`Session::encrypt`](crate::session::Session::encrypt)
pub fn encrypt(&self) -> bool {
self.flags.contains(MechanismInfoFlags::ENCRYPT)
}
/// True if the mechanism can be used to decrypt encrypted data
///
/// See [`Session::decrypt`](crate::session::Session::decrypt)
pub fn decrypt(&self) -> bool {
self.flags.contains(MechanismInfoFlags::DECRYPT)
}
/// True if the mechanism can be used to digest a message
///
/// See [`Session::digest`]
pub fn digest(&self) -> bool {
self.flags.contains(MechanismInfoFlags::DIGEST)
}
/// True if the mechanism can be used to digitally sign data
///
/// See [`Session::sign`](crate::session::Session::sign)
pub fn sign(&self) -> bool {
self.flags.contains(MechanismInfoFlags::SIGN)
}
/// True if the mechanism can be used to digitally sign data which can be
/// recovered from the signature
///
/// Note: `sign_recover` is not yet implemented in the Session API
pub fn sign_recover(&self) -> bool {
self.flags.contains(MechanismInfoFlags::SIGN_RECOVER)
}
/// True if the mechanism can be used to verify a digital signature
///
/// See [`Session::verify`](crate::session::Session::verify)
pub fn verify(&self) -> bool {
self.flags.contains(MechanismInfoFlags::VERIFY)
}
/// True if the mechanism can be used to verify a digital signature and
/// recover the signed data
///
/// Note: `verify_recover` is not yet implemented in the Session API
pub fn verify_recover(&self) -> bool {
self.flags.contains(MechanismInfoFlags::VERIFY_RECOVER)
}
/// True if the mechanism can be used to generate a secret key
///
/// See [`Session::generate_key`]
pub fn generate(&self) -> bool {
self.flags.contains(MechanismInfoFlags::GENERATE)
}
/// True if the mechanism can be used to generate a public/private key pair
///
/// See [`Session::generate_key_pair`]
pub fn generate_key_pair(&self) -> bool {
self.flags.contains(MechanismInfoFlags::GENERATE_KEY_PAIR)
}
/// True if the mechanism can be used to wrap (encrypt) a key
///
/// See [`Session::wrap_key`]
pub fn wrap(&self) -> bool {
self.flags.contains(MechanismInfoFlags::WRAP)
}
/// True if the mechanism can be used to unwrap (decrypt) a key
///
/// See [`Session::unwrap_key`]
pub fn unwrap(&self) -> bool {
self.flags.contains(MechanismInfoFlags::UNWRAP)
}
/// True if the mechanism can be used to derive a key from a base key
///
/// See [`Session::derive_key`]
pub fn derive(&self) -> bool {
self.flags.contains(MechanismInfoFlags::DERIVE)
}
/// True if there is an extension to the flags; false if no extensions
///
/// **[Conformance](crate#conformance-notes):**
/// This *must* be false for PKCS#11 v2.40
pub fn extension(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EXTENSION)
}
/// True if the mechanism can be used to with elliptic curve domain
/// parameters over ***F<sub>p</sub>***
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_f_p`](Self::ec_f_p) and
/// [`ec_f_2m`](Self::ec_f_2m) must be `true`
pub fn ec_f_p(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_F_P)
}
/// True if the mechanism can be used with elliptic curve domain parameters
/// over ***F<sub>2<sup>m</sup></sub>***
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_f_p`](Self::ec_f_p) and
/// [`ec_f_2m`](Self::ec_f_2m) must be `true`
pub fn ec_f_2m(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_F_2M)
}
/// True if the mechanism supports specifying elliptic curve domain
/// parameters explicitly
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_from_parameters`](Self::ec_from_parameters) and
/// [`ec_from_oid`](Self::ec_from_oid) must be `true`
pub fn ec_from_parameters(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_ECPARAMETERS)
}
/// True if the mechanism supports specifying elliptic curve domain
/// parameters with a named curve
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_from_parameters`](Self::ec_from_parameters) and
/// [`ec_from_named_curve`](Self::ec_from_named_curve) must be `true`
#[deprecated = "use `ec_from_oid` instead"]
pub fn ec_from_named_curve(&self) -> bool {
#[allow(deprecated)]
self.flags.contains(MechanismInfoFlags::EC_NAMEDCURVE)
}
/// True if the mechanism supports specifying elliptic curve domain
/// parameters with an oid
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_from_parameters`](Self::ec_from_parameters) and
/// [`ec_from_oid`](Self::ec_from_oid) must be `true`
pub fn ec_from_oid(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_OID)
}
/// True if the mechanism can be used with elliptic curve points in
/// uncompressed form
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_uncompressed`](Self::ec_uncompressed) and
/// [`ec_compressed`](Self::ec_compressed) must be `true`
pub fn ec_uncompressed(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_UNCOMPRESS)
}
/// True if the mechanism can be used with elliptic curve points in
/// compressed form
///
/// **[Conformance](crate#conformance-notes):**
/// *At least* one of [`ec_uncompressed`](Self::ec_uncompressed) and
/// [`ec_compressed`](Self::ec_compressed) must be `true`
pub fn ec_compressed(&self) -> bool {
self.flags.contains(MechanismInfoFlags::EC_COMPRESS)
}
/// True if the mechanism can be used to encrypt messages
///
/// See [`Session::encrypt_message`](crate::session::Session::encrypt_message)
pub fn message_encrypt(&self) -> bool {
self.flags.contains(MechanismInfoFlags::MESSAGE_ENCRYPT)
}
/// True if the mechanism can be used to decrypt encrypted messages
///
/// See [`Session::decrypt`](crate::session::Session::decrypt_message)
pub fn message_decrypt(&self) -> bool {
self.flags.contains(MechanismInfoFlags::MESSAGE_DECRYPT)
}
/// True if the mechanism can be used with encrypt/decrypt_message_begin API.
/// One of message_* flag must also be set.
///
pub fn multi_message(&self) -> bool {
self.flags.contains(MechanismInfoFlags::MULTI_MESSAGE)
}
/// True if the mechanism can be used to encapsulate other keys
///
/// See [`Session::encapsulate_key`](crate::session::Session::encapsulate_key)
pub fn encapsulate(&self) -> bool {
self.flags.contains(MechanismInfoFlags::ENCAPSULATE)
}
/// True if the mechanism can be used to decapsulate other keys
///
/// See [`Session::decapsulate_key`](crate::session::Session::decapsulate_key)
pub fn decapsulate(&self) -> bool {
self.flags.contains(MechanismInfoFlags::DECAPSULATE)
}
}
impl std::fmt::Display for MechanismInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:#?}", self.flags)?;
if self.min_key_size == 0 && self.max_key_size == 0 {
return Ok(());
}
write!(f, ", min_key_size={}", self.min_key_size)?;
if self.max_key_size != 0 {
write!(f, ", max_key_size={}", self.max_key_size)?;
}
Ok(())
}
}
#[doc(hidden)]
impl From<CK_MECHANISM_INFO> for MechanismInfo {
fn from(val: CK_MECHANISM_INFO) -> Self {
Self {
min_key_size: val.ulMinKeySize as usize,
max_key_size: val.ulMaxKeySize as usize,
flags: MechanismInfoFlags::from_bits_truncate(val.flags),
}
}
}
#[cfg(test)]
mod test {
use super::{MechanismInfo, MechanismInfoFlags};
use cryptoki_sys::CK_FLAGS;
#[test]
fn deprecated_flags() {
let ec_oid_bits: CK_FLAGS = MechanismInfoFlags::EC_OID.bits();
#[allow(deprecated)]
let ec_namedcurve_bits: CK_FLAGS = MechanismInfoFlags::EC_NAMEDCURVE.bits();
assert_eq!(ec_oid_bits, ec_namedcurve_bits);
}
#[test]
fn debug_flags_all() {
let expected = "MechanismInfoFlags(
HW | ENCRYPT | DECRYPT | DIGEST | SIGN | SIGN_RECOVER | VERIFY | \
VERIFY_RECOVER | GENERATE | GENERATE_KEY_PAIR | WRAP | UNWRAP | DERIVE | \
EXTENSION | EC_F_P | EC_F_2M | EC_ECPARAMETERS | EC_OID | EC_UNCOMPRESS | \
EC_COMPRESS | MESSAGE_ENCRYPT | MESSAGE_DECRYPT | MULTI_MESSAGE | ENCAPSULATE | \
DECAPSULATE,
)";
let all = MechanismInfoFlags::all();
let observed = format!("{all:#?}");
println!("{observed}");
assert_eq!(observed, expected);
}
#[test]
fn debug_info() {
let info = MechanismInfo {
min_key_size: 16,
max_key_size: 4096,
flags: MechanismInfoFlags::empty(),
};
let expected = r#"MechanismInfo {
min_key_size: 16,
max_key_size: 4096,
flags: MechanismInfoFlags(
0x0,
),
}"#;
let observed = format!("{info:#?}");
assert_eq!(observed, expected);
}
}