1 // Copyright 2017 Marcus Heese
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 
16 use std::env;
17 use std::path::PathBuf;
18 
19 /// Tests need to be run with `RUST_TEST_THREADS=1` currently to pass.
20 extern crate num_traits;
21 extern crate hex;
22 
23 use self::num_traits::Num;
24 use self::hex::FromHex;
25 
26 use super::*;
27 use super::types::*;
28 use super::errors::Error;
29 use num_bigint::BigUint;
30 
pkcs11_module_name() -> PathBuf31 fn pkcs11_module_name() -> PathBuf {
32   let default_path = option_env!("PKCS11_SOFTHSM2_MODULE")
33     .unwrap_or("/usr/local/lib/softhsm/libsofthsm2.so");
34   let path = env::var_os("PKCS11_SOFTHSM2_MODULE")
35     .unwrap_or_else(|| default_path.into());
36   let path_buf = PathBuf::from(path);
37 
38   if !path_buf.exists() {
39     panic!(
40       "Could not find SoftHSM2 at `{}`. Set the `PKCS11_SOFTHSM2_MODULE` environment variable to \
41        its location.",
42       path_buf.display());
43   }
44 
45   path_buf
46 }
47 
48 #[test]
49 #[serial]
test_label_from_str()50 fn test_label_from_str() {
51   let s30 = "Löwe 老虎 Léopar虎d虎aaa";
52   let s32 = "Löwe 老虎 Léopar虎d虎aaaö";
53   let s33 = "Löwe 老虎 Léopar虎d虎aaa虎";
54   let s34 = "Löwe 老虎 Léopar虎d虎aaab虎";
55   let l30 = label_from_str(s30);
56   let l32 = label_from_str(s32);
57   let l33 = label_from_str(s33);
58   let l34 = label_from_str(s34);
59   println!("Label l30: {:?}", l30);
60   println!("Label l32: {:?}", l32);
61   println!("Label l33: {:?}", l33);
62   println!("Label l34: {:?}", l34);
63   // now the assertions:
64   // - l30 must have the last 2 as byte 32
65   // - l32 must not have any byte 32 at the end
66   // - l33 must have the last 2 as byte 32 because the trailing '虎' is three bytes
67   // - l34 must have hte last 1 as byte 32
68   assert_ne!(l30[29], 32);
69   assert_eq!(l30[30], 32);
70   assert_eq!(l30[31], 32);
71   assert_ne!(l32[31], 32);
72   assert_ne!(l33[29], 32);
73   assert_eq!(l33[30], 32);
74   assert_eq!(l33[31], 32);
75   assert_ne!(l34[30], 32);
76   assert_eq!(l34[31], 32);
77 }
78 #[test]
79 #[serial]
ctx_new()80 fn ctx_new() {
81   let res = Ctx::new(pkcs11_module_name());
82   assert!(
83     res.is_ok(),
84     "failed to create new context: {}",
85     res.unwrap_err()
86   );
87 }
88 
89 #[test]
90 #[serial]
ctx_initialize()91 fn ctx_initialize() {
92   let mut ctx = Ctx::new(pkcs11_module_name()).unwrap();
93   let res = ctx.initialize(None);
94   assert!(
95     res.is_ok(),
96     "failed to initialize context: {}",
97     res.unwrap_err()
98   );
99   assert!(ctx.is_initialized(), "internal state is not initialized");
100 }
101 
102 #[test]
103 #[serial]
ctx_new_and_initialize()104 fn ctx_new_and_initialize() {
105   let res = Ctx::new_and_initialize(pkcs11_module_name());
106   assert!(
107     res.is_ok(),
108     "failed to create or initialize new context: {}",
109     res.unwrap_err()
110   );
111 }
112 
113 #[test]
114 #[serial]
ctx_finalize()115 fn ctx_finalize() {
116   let mut ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
117   let res = ctx.finalize();
118   assert!(
119     res.is_ok(),
120     "failed to finalize context: {}",
121     res.unwrap_err()
122   );
123 }
124 
125 #[test]
126 #[serial]
ctx_get_info()127 fn ctx_get_info() {
128   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
129   let res = ctx.get_info();
130   assert!(
131     res.is_ok(),
132     "failed to call C_GetInfo: {}",
133     res.unwrap_err()
134   );
135   let info = res.unwrap();
136   println!("{:?}", info);
137 }
138 
139 #[test]
140 #[serial]
ctx_get_function_list()141 fn ctx_get_function_list() {
142   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
143   let res = ctx.get_function_list();
144   assert!(
145     res.is_ok(),
146     "failed to call C_GetFunctionList: {}",
147     res.unwrap_err()
148   );
149   let list = res.unwrap();
150   println!("{:?}", list);
151 }
152 
153 #[test]
154 #[serial]
ctx_get_slot_list()155 fn ctx_get_slot_list() {
156   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
157   let res = ctx.get_slot_list(false);
158   assert!(
159     res.is_ok(),
160     "failed to call C_GetSlotList: {}",
161     res.unwrap_err()
162   );
163   let slots = res.unwrap();
164   println!("Slots: {:?}", slots);
165 }
166 
167 #[test]
168 #[serial]
ctx_get_slot_infos()169 fn ctx_get_slot_infos() {
170   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
171   let slots = ctx.get_slot_list(false).unwrap();
172   for slot in slots[..1].iter() {
173     let slot = *slot;
174     let res = ctx.get_slot_info(slot);
175     assert!(
176       res.is_ok(),
177       "failed to call C_GetSlotInfo({}): {}",
178       slot,
179       res.unwrap_err()
180     );
181     let info = res.unwrap();
182     println!("Slot {} {:?}", slot, info);
183   }
184 }
185 
186 #[test]
187 #[serial]
ctx_get_token_infos()188 fn ctx_get_token_infos() {
189   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
190   let slots = ctx.get_slot_list(false).unwrap();
191   for slot in slots[..1].iter() {
192     let slot = *slot;
193     let res = ctx.get_token_info(slot);
194     assert!(
195       res.is_ok(),
196       "failed to call C_GetTokenInfo({}): {}",
197       slot,
198       res.unwrap_err()
199     );
200     let info = res.unwrap();
201     println!("Slot {} {:?}", slot, info);
202   }
203 }
204 
205 #[test]
206 #[serial]
ctx_get_mechanism_lists()207 fn ctx_get_mechanism_lists() {
208   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
209   let slots = ctx.get_slot_list(false).unwrap();
210   for slot in slots[..1].iter() {
211     let slot = *slot;
212     let res = ctx.get_mechanism_list(slot);
213     assert!(
214       res.is_ok(),
215       "failed to call C_GetMechanismList({}): {}",
216       slot,
217       res.unwrap_err()
218     );
219     let mechs = res.unwrap();
220     println!("Slot {} Mechanisms: {:?}", slot, mechs);
221   }
222 }
223 
224 #[test]
225 #[serial]
ctx_get_mechanism_infos()226 fn ctx_get_mechanism_infos() {
227   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
228   let slots = ctx.get_slot_list(false).unwrap();
229   for slot in slots[..1].iter() {
230     let slot = *slot;
231     let mechanisms = ctx.get_mechanism_list(slot).unwrap();
232     for mechanism in mechanisms {
233       let res = ctx.get_mechanism_info(slot, mechanism);
234       assert!(
235         res.is_ok(),
236         "failed to call C_GetMechanismInfo({}, {}): {}",
237         slot,
238         mechanism,
239         res.unwrap_err()
240       );
241       let info = res.unwrap();
242       println!("Slot {} Mechanism {}: {:?}", slot, mechanism, info);
243     }
244   }
245 }
246 
247 #[test]
248 #[serial]
ctx_init_token()249 fn ctx_init_token() {
250   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
251   let slots = ctx.get_slot_list(false).unwrap();
252   let pin = Some("1234");
253   const LABEL: &str = "rust-unit-test";
254   for slot in slots[..1].iter() {
255     let slot = *slot;
256     let res = ctx.init_token(slot, pin, LABEL);
257     assert!(
258       res.is_ok(),
259       "failed to call C_InitToken({}, {}, {}): {}",
260       slot,
261       pin.unwrap(),
262       LABEL,
263       res.unwrap_err()
264     );
265     println!(
266       "Slot {} C_InitToken successful, PIN: {}",
267       slot,
268       pin.unwrap()
269     );
270   }
271 }
272 
273 #[test]
274 #[serial]
ctx_init_pin()275 fn ctx_init_pin() {
276   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
277   let slots = ctx.get_slot_list(false).unwrap();
278   let pin = Some("1234");
279   const LABEL: &str = "rust-unit-test";
280   for slot in slots[..1].iter() {
281     let slot = *slot;
282     ctx.init_token(slot, pin, LABEL).unwrap();
283     let sh = ctx
284       .open_session(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, None, None)
285       .unwrap();
286     ctx.login(sh, CKU_SO, pin).unwrap();
287     let res = ctx.init_pin(sh, pin);
288     assert!(
289       res.is_ok(),
290       "failed to call C_InitPIN({}, {}): {}",
291       sh,
292       pin.unwrap(),
293       res.unwrap_err()
294     );
295     println!("InitPIN successful");
296   }
297 }
298 
299 #[test]
300 #[serial]
ctx_set_pin()301 fn ctx_set_pin() {
302   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
303   let slots = ctx.get_slot_list(false).unwrap();
304   let pin = Some("1234");
305   let new_pin = Some("1234");
306   const LABEL: &str = "rust-unit-test";
307   for slot in slots[..1].iter() {
308     let slot = *slot;
309     ctx.init_token(slot, pin, LABEL).unwrap();
310     let sh = ctx
311       .open_session(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, None, None)
312       .unwrap();
313     ctx.login(sh, CKU_SO, pin).unwrap();
314     let res = ctx.set_pin(sh, pin, new_pin);
315     assert!(
316       res.is_ok(),
317       "failed to call C_SetPIN({}, {}, {}): {}",
318       sh,
319       pin.unwrap(),
320       new_pin.unwrap(),
321       res.unwrap_err()
322     );
323     println!("SetPIN successful");
324   }
325 }
326 
327 #[test]
328 #[serial]
ctx_open_session()329 fn ctx_open_session() {
330   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
331   let slots = ctx.get_slot_list(false).unwrap();
332   let pin = Some("1234");
333   const LABEL: &str = "rust-unit-test";
334   for slot in slots[..1].iter() {
335     let slot = *slot;
336     ctx.init_token(slot, pin, LABEL).unwrap();
337     let res = ctx.open_session(slot, CKF_SERIAL_SESSION, None, None);
338     assert!(
339       res.is_ok(),
340       "failed to call C_OpenSession({}, CKF_SERIAL_SESSION, None, None): {}",
341       slot,
342       res.unwrap_err()
343     );
344     let sh = res.unwrap();
345     println!("Opened Session on Slot {}: CK_SESSION_HANDLE {}", slot, sh);
346   }
347 }
348 
349 #[test]
350 #[serial]
ctx_close_session()351 fn ctx_close_session() {
352   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
353   let slots = ctx.get_slot_list(false).unwrap();
354   let pin = Some("1234");
355   const LABEL: &str = "rust-unit-test";
356   for slot in slots[..1].iter() {
357     let slot = *slot;
358     ctx.init_token(slot, pin, LABEL).unwrap();
359     let sh = ctx
360       .open_session(slot, CKF_SERIAL_SESSION, None, None)
361       .unwrap();
362     let res = ctx.close_session(sh);
363     assert!(
364       res.is_ok(),
365       "failed to call C_CloseSession({}): {}",
366       sh,
367       res.unwrap_err()
368     );
369     println!("Closed Session with CK_SESSION_HANDLE {}", sh);
370   }
371 }
372 
373 #[test]
374 #[serial]
ctx_close_all_sessions()375 fn ctx_close_all_sessions() {
376   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
377   let slots = ctx.get_slot_list(false).unwrap();
378   let pin = Some("1234");
379   const LABEL: &str = "rust-unit-test";
380   for slot in slots[..1].iter() {
381     let slot = *slot;
382     ctx.init_token(slot, pin, LABEL).unwrap();
383     ctx
384       .open_session(slot, CKF_SERIAL_SESSION, None, None)
385       .unwrap();
386     let res = ctx.close_all_sessions(slot);
387     assert!(
388       res.is_ok(),
389       "failed to call C_CloseAllSessions({}): {}",
390       slot,
391       res.unwrap_err()
392     );
393     println!("Closed All Sessions on Slot {}", slot);
394   }
395 }
396 
397 #[test]
398 #[serial]
ctx_get_session_info()399 fn ctx_get_session_info() {
400   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
401   let slots = ctx.get_slot_list(false).unwrap();
402   let pin = Some("1234");
403   const LABEL: &str = "rust-unit-test";
404   for slot in slots[..1].iter() {
405     let slot = *slot;
406     ctx.init_token(slot, pin, LABEL).unwrap();
407     let sh = ctx
408       .open_session(slot, CKF_SERIAL_SESSION, None, None)
409       .unwrap();
410     let res = ctx.get_session_info(sh);
411     assert!(
412       res.is_ok(),
413       "failed to call C_GetSessionInfo({}): {}",
414       sh,
415       res.unwrap_err()
416     );
417     let info = res.unwrap();
418     println!("{:?}", info);
419   }
420 }
421 
422 #[test]
423 #[serial]
ctx_login()424 fn ctx_login() {
425   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
426   let slots = ctx.get_slot_list(false).unwrap();
427   let pin = Some("1234");
428   const LABEL: &str = "rust-unit-test";
429   for slot in slots[..1].iter() {
430     let slot = *slot;
431     ctx.init_token(slot, pin, LABEL).unwrap();
432     let sh = ctx
433       .open_session(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, None, None)
434       .unwrap();
435     let res = ctx.login(sh, CKU_SO, pin);
436     assert!(
437       res.is_ok(),
438       "failed to call C_Login({}, CKU_SO, {}): {}",
439       sh,
440       pin.unwrap(),
441       res.unwrap_err()
442     );
443     println!("Login successful");
444   }
445 }
446 
447 #[test]
448 #[serial]
ctx_logout()449 fn ctx_logout() {
450   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
451   let slots = ctx.get_slot_list(false).unwrap();
452   let pin = Some("1234");
453   const LABEL: &str = "rust-unit-test";
454   for slot in slots[..1].iter() {
455     let slot = *slot;
456     ctx.init_token(slot, pin, LABEL).unwrap();
457     let sh = ctx
458       .open_session(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, None, None)
459       .unwrap();
460     ctx.login(sh, CKU_SO, pin).unwrap();
461     let res = ctx.logout(sh);
462     assert!(
463       res.is_ok(),
464       "failed to call C_Logout({}): {}",
465       sh,
466       res.unwrap_err()
467     );
468     println!("Logout successful");
469   }
470 }
471 
472 #[test]
attr_bool()473 fn attr_bool() {
474   let b: CK_BBOOL = CK_FALSE;
475   let attr = CK_ATTRIBUTE::new(CKA_OTP_USER_IDENTIFIER).with_bool(&b);
476   println!("{:?}", attr);
477   let ret: bool = attr.get_bool();
478   println!("{}", ret);
479   assert_eq!(false, ret, "attr.get_bool() should have been false");
480 
481   let b: CK_BBOOL = CK_TRUE;
482   let attr = CK_ATTRIBUTE::new(CKA_OTP_USER_IDENTIFIER).with_bool(&b);
483   println!("{:?}", attr);
484   let ret: bool = attr.get_bool();
485   println!("{}", ret);
486   assert_eq!(true, ret, "attr.get_bool() should have been true");
487 }
488 
489 #[test]
attr_ck_ulong()490 fn attr_ck_ulong() {
491   let val: CK_ULONG = 42;
492   let attr = CK_ATTRIBUTE::new(CKA_RESOLUTION).with_ck_ulong(&val);
493   println!("{:?}", attr);
494   let ret: CK_ULONG = attr.get_ck_ulong();
495   println!("{}", ret);
496   assert_eq!(val, ret, "attr.get_ck_ulong() shouls have been {}", val);
497 }
498 
499 #[test]
attr_ck_long()500 fn attr_ck_long() {
501   let val: CK_LONG = -42;
502   let attr = CK_ATTRIBUTE::new(CKA_RESOLUTION).with_ck_long(&val);
503   println!("{:?}", attr);
504   let ret: CK_LONG = attr.get_ck_long();
505   println!("{}", ret);
506   assert_eq!(val, ret, "attr.get_ck_long() shouls have been {}", val);
507 }
508 
509 #[test]
attr_bytes()510 fn attr_bytes() {
511   let val = vec![0, 1, 2, 3, 3, 4, 5];
512   let attr = CK_ATTRIBUTE::new(CKA_VALUE).with_bytes(val.as_slice());
513   println!("{:?}", attr);
514   let ret: Vec<CK_BYTE> = attr.get_bytes();
515   println!("{:?}", ret);
516   assert_eq!(
517     val,
518     ret.as_slice(),
519     "attr.get_bytes() shouls have been {:?}",
520     val
521   );
522 }
523 
524 #[test]
attr_string()525 fn attr_string() {
526   let val = String::from("Löwe 老虎");
527   let attr = CK_ATTRIBUTE::new(CKA_LABEL).with_string(&val);
528   println!("{:?}", attr);
529   let ret = attr.get_string();
530   println!("{:?}", ret);
531   assert_eq!(val, ret, "attr.get_string() shouls have been {}", val);
532 }
533 
534 #[test]
attr_date()535 fn attr_date() {
536   let val: CK_DATE = Default::default();
537   let attr = CK_ATTRIBUTE::new(CKA_LABEL).with_date(&val);
538   println!("{:?}", attr);
539   let ret = attr.get_date();
540   println!("{:?}", ret);
541   assert_eq!(
542     val.day,
543     ret.day,
544     "attr.get_date() should have been {:?}",
545     val
546   );
547   assert_eq!(
548     val.month,
549     ret.month,
550     "attr.get_date() should have been {:?}",
551     val
552   );
553   assert_eq!(
554     val.year,
555     ret.year,
556     "attr.get_date() should have been {:?}",
557     val
558   );
559 }
560 
561 #[test]
attr_biginteger()562 fn attr_biginteger() {
563   let num_str = "123456789012345678901234567890123456789012345678901234567890123456789012345678";
564   let val = BigUint::from_str_radix(num_str, 10).unwrap();
565   let slice = val.to_bytes_le();
566   let attr = CK_ATTRIBUTE::new(CKA_LABEL).with_biginteger(&slice);
567   println!("{:?}", attr);
568   let ret = attr.get_biginteger();
569   println!("{:?}", ret);
570   assert_eq!(ret, val, "attr.get_biginteger() should have been {:?}", val);
571   assert_eq!(
572     ret.to_str_radix(10),
573     num_str,
574     "attr.get_biginteger() should have been {:?}",
575     num_str
576   );
577 }
578 
579 /// This will create and initialize a context, set a SO and USER PIN, and login as the USER.
580 /// This is the starting point for all tests that are acting on the token.
581 /// If you look at the tests here in a "serial" manner, if all the tests are working up until
582 /// here, this will always succeed.
fixture_token() -> Result<(Ctx, CK_SESSION_HANDLE), Error>583 fn fixture_token() -> Result<(Ctx, CK_SESSION_HANDLE), Error> {
584   let ctx = Ctx::new_and_initialize(pkcs11_module_name()).unwrap();
585   let slots = ctx.get_slot_list(false).unwrap();
586   let pin = Some("1234");
587   const LABEL: &str = "rust-unit-test";
588   let slot = *slots.first().ok_or(Error::Module("no slot available"))?;
589   ctx.init_token(slot, pin, LABEL)?;
590   let sh = ctx.open_session(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, None, None)?;
591   ctx.login(sh, CKU_SO, pin)?;
592   ctx.init_pin(sh, pin)?;
593   ctx.logout(sh)?;
594   ctx.login(sh, CKU_USER, pin)?;
595   Ok((ctx, sh))
596 }
597 
598 #[test]
599 #[serial]
ctx_create_object()600 fn ctx_create_object() {
601   /*
602         CKA_CLASS       ck_type  object_class:CKO_DATA
603         CKA_TOKEN       bool      true
604         CKA_PRIVATE     bool      true
605         CKA_MODIFIABLE  bool      true
606         CKA_COPYABLE    bool      true
607         CKA_LABEL       string    e4-example
608         CKA_VALUE       bytes     SGVsbG8gV29ybGQh
609         */
610   let (ctx, sh) = fixture_token().unwrap();
611 
612   let class = CKO_DATA;
613   let token: CK_BBOOL = CK_TRUE;
614   let private: CK_BBOOL = CK_TRUE;
615   let modifiable: CK_BBOOL = CK_TRUE;
616   let copyable: CK_BBOOL = CK_TRUE;
617   let label = String::from("rust-unit-test");
618   let value = b"Hello World!";
619 
620   let template = vec![
621     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&class),
622     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&token),
623     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&private),
624     CK_ATTRIBUTE::new(CKA_MODIFIABLE).with_bool(&modifiable),
625     CK_ATTRIBUTE::new(CKA_COPYABLE).with_bool(&copyable),
626     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label),
627     CK_ATTRIBUTE::new(CKA_VALUE).with_bytes(&value[..]),
628   ];
629   println!("Template: {:?}", template);
630   let res = ctx.create_object(sh, &template);
631   assert!(
632     res.is_ok(),
633     "failed to call C_CreateObject({}, {:?}): {}",
634     sh,
635     &template,
636     res.is_err()
637   );
638   let oh = res.unwrap();
639   println!("Object Handle: {}", oh);
640 }
641 
fixture_token_and_object() -> Result<(Ctx, CK_SESSION_HANDLE, CK_OBJECT_HANDLE), Error>642 fn fixture_token_and_object() -> Result<(Ctx, CK_SESSION_HANDLE, CK_OBJECT_HANDLE), Error> {
643   let (ctx, sh) = fixture_token()?;
644 
645   let class = CKO_DATA;
646   let token: CK_BBOOL = CK_TRUE;
647   let private: CK_BBOOL = CK_TRUE;
648   let modifiable: CK_BBOOL = CK_TRUE;
649   let copyable: CK_BBOOL = CK_TRUE;
650   let label = String::from("rust-unit-test");
651   let value = b"Hello World!";
652 
653   let template = vec![
654     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&class),
655     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&token),
656     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&private),
657     CK_ATTRIBUTE::new(CKA_MODIFIABLE).with_bool(&modifiable),
658     CK_ATTRIBUTE::new(CKA_COPYABLE).with_bool(&copyable),
659     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label),
660     CK_ATTRIBUTE::new(CKA_VALUE).with_bytes(&value[..]),
661   ];
662   let oh = ctx.create_object(sh, &template)?;
663   Ok((ctx, sh, oh))
664 }
665 
666 #[test]
667 #[serial]
ctx_copy_object()668 fn ctx_copy_object() {
669   let (ctx, sh, oh) = fixture_token_and_object().unwrap();
670 
671   let label2 = String::from("rust-unit-test2");
672   let template2 = vec![CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label2)];
673   println!("Template2: {:?}", template2);
674 
675   let res = ctx.copy_object(sh, oh, &template2);
676   assert!(
677     res.is_ok(),
678     "failed to call C_CopyObject({}, {}, {:?}): {}",
679     sh,
680     oh,
681     &template2,
682     res.unwrap_err(),
683   );
684   let oh2 = res.unwrap();
685   println!("Object Handle2: {}", oh2);
686 }
687 
688 #[test]
689 #[serial]
ctx_destroy_object()690 fn ctx_destroy_object() {
691   let (ctx, sh, oh) = fixture_token_and_object().unwrap();
692 
693   let res = ctx.destroy_object(sh, oh);
694   assert!(
695     res.is_ok(),
696     "failed to call C_DestroyObject({}, {}): {})",
697     sh,
698     oh,
699     res.unwrap_err()
700   );
701 }
702 
703 #[test]
704 #[serial]
ctx_get_object_size()705 fn ctx_get_object_size() {
706   let (ctx, sh, oh) = fixture_token_and_object().unwrap();
707 
708   let res = ctx.get_object_size(sh, oh);
709   assert!(
710     res.is_ok(),
711     "failed to call C_GetObjectSize({}, {}): {}",
712     sh,
713     oh,
714     res.unwrap_err()
715   );
716   let size = res.unwrap();
717   println!("Object Size: {}", size);
718 }
719 
720 #[test]
721 #[serial]
ctx_get_attribute_value()722 fn ctx_get_attribute_value() {
723   {
724     let (ctx, sh, oh) = fixture_token_and_object().unwrap();
725 
726     let mut template = vec![
727       CK_ATTRIBUTE::new(CKA_CLASS),
728       CK_ATTRIBUTE::new(CKA_PRIVATE),
729       CK_ATTRIBUTE::new(CKA_LABEL),
730       CK_ATTRIBUTE::new(CKA_VALUE),
731     ];
732     println!("Template: {:?}", template);
733     {
734       let res = ctx.get_attribute_value(sh, oh, &mut template);
735       if !res.is_ok() {
736         // Doing this not as an assert so we can both unwrap_err with the mut template and re-borrow template
737         let err = res.unwrap_err();
738         panic!(
739           "failed to call C_GetAttributeValue({}, {}, {:?}): {}",
740           sh,
741           oh,
742           &template,
743           err
744         );
745       }
746       let (rv, _) = res.unwrap();
747       println!("CK_RV: 0x{:x}, Template: {:?}", rv, &template);
748     }
749 
750     let class: CK_ULONG = 0;
751     let private: CK_BBOOL = 1;
752     let label: String = String::with_capacity(template[2].ulValueLen);
753     let value: Vec<CK_BYTE> = Vec::with_capacity(template[3].ulValueLen);
754     template[0].set_ck_ulong(&class);
755     template[1].set_bool(&private);
756     template[2].set_string(&label);
757     template[3].set_bytes(&value.as_slice());
758 
759     let res = ctx.get_attribute_value(sh, oh, &mut template);
760     if !res.is_ok() {
761         // Doing this not as an assert so we can both unwrap_err with the mut template and re-borrow template
762         let err = res.unwrap_err();
763         panic!(
764           "failed to call C_GetAttributeValue({}, {}, {:?}): {}",
765           sh,
766           oh,
767           &template,
768           err
769         );
770     }
771     let (rv, _) = res.unwrap();
772     println!("CK_RV: 0x{:x}, Retrieved Attributes: {:?}", rv, &template);
773 
774     assert_eq!(CKO_DATA, template[0].get_ck_ulong());
775     assert_eq!(true, template[1].get_bool());
776     assert_eq!(String::from("rust-unit-test"), template[2].get_string());
777     assert_eq!(Vec::from("Hello World!"), template[3].get_bytes());
778   }
779   println!("The end");
780 }
781 
782 #[test]
783 #[serial]
ctx_set_attribute_value()784 fn ctx_set_attribute_value() {
785   let (ctx, sh, oh) = fixture_token_and_object().unwrap();
786 
787   let value = b"Hello New World!";
788   let template = vec![CK_ATTRIBUTE::new(CKA_LABEL).with_bytes(&value[..])];
789 
790   let res = ctx.set_attribute_value(sh, oh, &template);
791   assert!(
792     res.is_ok(),
793     "failed to call C_SetAttributeValue({}, {}, {:?}): {}",
794     sh,
795     oh,
796     &template,
797     res.unwrap_err()
798   );
799 
800   let str: Vec<CK_BYTE> = Vec::from("aaaaaaaaaaaaaaaa");
801   let mut template2 = vec![CK_ATTRIBUTE::new(CKA_LABEL).with_bytes(&str.as_slice())];
802   ctx.get_attribute_value(sh, oh, &mut template2).unwrap();
803   assert_eq!(Vec::from("Hello New World!"), template2[0].get_bytes());
804 }
805 
806 #[test]
807 #[serial]
ctx_find_objects_init()808 fn ctx_find_objects_init() {
809   let (ctx, sh, _) = fixture_token_and_object().unwrap();
810 
811   let label = String::from("rust-unit-test");
812   let template = vec![CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label)];
813 
814   let res = ctx.find_objects_init(sh, &template);
815   assert!(
816     res.is_ok(),
817     "failed to call C_FindObjectsInit({}, {:?}): {}",
818     sh,
819     &template,
820     res.unwrap_err()
821   );
822 }
823 
824 #[test]
825 #[serial]
ctx_find_objects()826 fn ctx_find_objects() {
827   let (ctx, sh, _) = fixture_token_and_object().unwrap();
828 
829   let label = String::from("rust-unit-test");
830   let template = vec![CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label)];
831 
832   ctx.find_objects_init(sh, &template).unwrap();
833 
834   let res = ctx.find_objects(sh, 10);
835   assert!(
836     res.is_ok(),
837     "failed to call C_FindObjects({}, {}): {}",
838     sh,
839     10,
840     res.unwrap_err()
841   );
842   let objs = res.unwrap();
843   assert_eq!(objs.len(), 1);
844 }
845 
846 #[test]
847 #[serial]
ctx_find_objects_final()848 fn ctx_find_objects_final() {
849   let (ctx, sh, _) = fixture_token_and_object().unwrap();
850 
851   let label = String::from("rust-unit-test");
852   let template = vec![CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label)];
853 
854   ctx.find_objects_init(sh, &template).unwrap();
855   ctx.find_objects(sh, 10).unwrap();
856 
857   let res = ctx.find_objects_final(sh);
858   assert!(
859     res.is_ok(),
860     "failed to call C_FindObjectsFinal({}): {}",
861     sh,
862     res.unwrap_err()
863   );
864 }
865 
866 #[test]
867 #[serial]
ctx_generate_key()868 fn ctx_generate_key() {
869   let (ctx, sh) = fixture_token().unwrap();
870 
871   let mechanism = CK_MECHANISM {
872     mechanism: CKM_AES_KEY_GEN,
873     pParameter: ptr::null_mut(),
874     ulParameterLen: 0,
875   };
876 
877   // Wrapping Key Template:
878   // CKA_CLASS        ck_type  object_class:CKO_SECRET_KEY
879   // CKA_KEY_TYPE     ck_type  key_type:CKK_AES
880   // CKA_TOKEN        bool     true
881   // CKA_LABEL        string   wrap1-wrap-key
882   // CKA_ENCRYPT      bool     false
883   // CKA_DECRYPT      bool     false
884   // CKA_VALUE_LEN    uint     32
885   // CKA_PRIVATE      bool     true
886   // CKA_SENSITIVE    bool     false
887   // CKA_EXTRACTABLE  bool     true
888   // CKA_WRAP         bool     true
889   // CKA_UNWRAP       bool     true
890 
891   let class = CKO_SECRET_KEY;
892   let keyType = CKK_AES;
893   let valueLen = 32;
894   let label = String::from("wrap1-wrap-key");
895   let token: CK_BBOOL = CK_TRUE;
896   let private: CK_BBOOL = CK_TRUE;
897   let encrypt: CK_BBOOL = CK_FALSE;
898   let decrypt: CK_BBOOL = CK_FALSE;
899   let sensitive: CK_BBOOL = CK_FALSE;
900   let extractable: CK_BBOOL = CK_TRUE;
901   let wrap: CK_BBOOL = CK_TRUE;
902   let unwrap: CK_BBOOL = CK_TRUE;
903 
904   let template = vec![
905     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&class),
906     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&keyType),
907     CK_ATTRIBUTE::new(CKA_VALUE_LEN).with_ck_ulong(&valueLen),
908     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label),
909     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&token),
910     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&private),
911     CK_ATTRIBUTE::new(CKA_ENCRYPT).with_bool(&encrypt),
912     CK_ATTRIBUTE::new(CKA_DECRYPT).with_bool(&decrypt),
913     CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&sensitive),
914     CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&extractable),
915     CK_ATTRIBUTE::new(CKA_WRAP).with_bool(&wrap),
916     CK_ATTRIBUTE::new(CKA_UNWRAP).with_bool(&unwrap),
917   ];
918 
919   let res = ctx.generate_key(sh, &mechanism, &template);
920   assert!(
921     res.is_ok(),
922     "failed to call C_Generatekey({}, {:?}, {:?}): {}",
923     sh,
924     mechanism,
925     template,
926     res.unwrap_err()
927   );
928   let oh = res.unwrap();
929   assert_ne!(oh, CK_INVALID_HANDLE);
930   println!("Generated Key Object Handle: {}", oh);
931 }
932 
933 #[test]
934 #[serial]
ctx_generate_key_pair()935 fn ctx_generate_key_pair() {
936   let (ctx, sh) = fixture_token().unwrap();
937 
938   let mechanism = CK_MECHANISM {
939     mechanism: CKM_RSA_PKCS_KEY_PAIR_GEN,
940     pParameter: ptr::null_mut(),
941     ulParameterLen: 0,
942   };
943 
944   // Private Key Template
945   // CKA_CLASS         ck_type  object_class:CKO_PRIVATE_KEY
946   // CKA_KEY_TYPE      ck_type  key_type:CKK_RSA
947   // CKA_TOKEN         bool     true
948   // CKA_SENSITIVE     bool     true
949   // CKA_UNWRAP        bool     false
950   // CKA_EXTRACTABLE   bool     false
951   // CKA_LABEL         string   ca-hsm-priv
952   // CKA_SIGN          bool     true
953   // CKA_PRIVATE       bool     true
954 
955   let privClass = CKO_PRIVATE_KEY;
956   let privKeyType = CKK_RSA;
957   let privLabel = String::from("ca-hsm-priv");
958   let privToken = CK_TRUE;
959   let privPrivate = CK_TRUE;
960   let privSensitive = CK_TRUE;
961   let privUnwrap = CK_FALSE;
962   let privExtractable = CK_FALSE;
963   let privSign = CK_TRUE;
964 
965   let privTemplate = vec![
966     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&privClass),
967     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&privKeyType),
968     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&privLabel),
969     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&privToken),
970     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&privPrivate),
971     CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&privSensitive),
972     CK_ATTRIBUTE::new(CKA_UNWRAP).with_bool(&privUnwrap),
973     CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&privExtractable),
974     CK_ATTRIBUTE::new(CKA_SIGN).with_bool(&privSign),
975   ];
976 
977   // Public Key Template
978   // CKA_CLASS             ck_type       object_class:CKO_PUBLIC_KEY
979   // CKA_KEY_TYPE          ck_type       key_type:CKK_RSA
980   // CKA_TOKEN             bool          true
981   // CKA_MODULUS_BITS      uint          4096
982   // CKA_PUBLIC_EXPONENT   big_integer   65537
983   // CKA_LABEL             string        ca-hsm-pub
984   // CKA_WRAP              bool          false
985   // CKA_VERIFY            bool          true
986   // CKA_PRIVATE           bool          true
987 
988   let pubClass = CKO_PUBLIC_KEY;
989   let pubKeyType = CKK_RSA;
990   let pubLabel = String::from("ca-hsm-pub");
991   let pubToken = CK_TRUE;
992   let pubPrivate = CK_TRUE;
993   let pubWrap = CK_FALSE;
994   let pubVerify = CK_TRUE;
995   let pubModulusBits: CK_ULONG = 4096;
996   let pubPublicExponent = BigUint::from(65537u32);
997   let pubPublicExponentSlice = pubPublicExponent.to_bytes_le();
998 
999   let pubTemplate = vec![
1000     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&pubClass),
1001     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&pubKeyType),
1002     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&pubLabel),
1003     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&pubToken),
1004     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&pubPrivate),
1005     CK_ATTRIBUTE::new(CKA_WRAP).with_bool(&pubWrap),
1006     CK_ATTRIBUTE::new(CKA_VERIFY).with_bool(&pubVerify),
1007     CK_ATTRIBUTE::new(CKA_MODULUS_BITS).with_ck_ulong(&pubModulusBits),
1008     CK_ATTRIBUTE::new(CKA_PUBLIC_EXPONENT).with_biginteger(&pubPublicExponentSlice),
1009   ];
1010 
1011   let res = ctx.generate_key_pair(sh, &mechanism, &pubTemplate, &privTemplate);
1012   assert!(
1013     res.is_ok(),
1014     "failed to call C_GenerateKeyPair({}, {:?}, {:?}, {:?}): {}",
1015     sh,
1016     &mechanism,
1017     &pubTemplate,
1018     &privTemplate,
1019     res.unwrap_err()
1020   );
1021   let (pubOh, privOh) = res.unwrap();
1022   println!("Private Key Object Handle: {}", privOh);
1023   println!("Public Key Object Handle: {}", pubOh);
1024 }
1025 
fixture_token_and_secret_keys( ) -> Result<(Ctx, CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), Error>1026 fn fixture_token_and_secret_keys(
1027 ) -> Result<(Ctx, CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), Error> {
1028   let (ctx, sh) = fixture_token()?;
1029 
1030   let wrapOh: CK_OBJECT_HANDLE;
1031   let secOh: CK_OBJECT_HANDLE;
1032   {
1033     let mechanism = CK_MECHANISM {
1034       mechanism: CKM_AES_KEY_GEN,
1035       pParameter: ptr::null_mut(),
1036       ulParameterLen: 0,
1037     };
1038 
1039     let class = CKO_SECRET_KEY;
1040     let keyType = CKK_AES;
1041     let valueLen = 32;
1042     let label = String::from("wrap1-wrap-key");
1043     let token: CK_BBOOL = CK_TRUE;
1044     let private: CK_BBOOL = CK_TRUE;
1045     let encrypt: CK_BBOOL = CK_FALSE;
1046     let decrypt: CK_BBOOL = CK_FALSE;
1047     let sensitive: CK_BBOOL = CK_FALSE;
1048     let extractable: CK_BBOOL = CK_TRUE;
1049     let wrap: CK_BBOOL = CK_TRUE;
1050     let unwrap: CK_BBOOL = CK_TRUE;
1051 
1052     let template = vec![
1053       CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&class),
1054       CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&keyType),
1055       CK_ATTRIBUTE::new(CKA_VALUE_LEN).with_ck_ulong(&valueLen),
1056       CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label),
1057       CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&token),
1058       CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&private),
1059       CK_ATTRIBUTE::new(CKA_ENCRYPT).with_bool(&encrypt),
1060       CK_ATTRIBUTE::new(CKA_DECRYPT).with_bool(&decrypt),
1061       CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&sensitive),
1062       CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&extractable),
1063       CK_ATTRIBUTE::new(CKA_WRAP).with_bool(&wrap),
1064       CK_ATTRIBUTE::new(CKA_UNWRAP).with_bool(&unwrap),
1065     ];
1066 
1067     wrapOh = ctx.generate_key(sh, &mechanism, &template)?;
1068   }
1069 
1070   {
1071     let mechanism = CK_MECHANISM {
1072       mechanism: CKM_AES_KEY_GEN,
1073       pParameter: ptr::null_mut(),
1074       ulParameterLen: 0,
1075     };
1076 
1077     // CKA_CLASS        ck_type  object_class:CKO_SECRET_KEY
1078     // CKA_KEY_TYPE     ck_type  key_type:CKK_AES
1079     // CKA_TOKEN        bool     true
1080     // CKA_LABEL        string   secured-key
1081     // CKA_ENCRYPT      bool     true
1082     // CKA_DECRYPT      bool     true
1083     // CKA_VALUE_LEN    uint     32
1084     // CKA_PRIVATE      bool     true
1085     // CKA_SENSITIVE    bool     true
1086     // CKA_EXTRACTABLE  bool     true
1087     // CKA_WRAP         bool     false
1088     // CKA_UNWRAP       bool     false
1089 
1090     let class = CKO_SECRET_KEY;
1091     let keyType = CKK_AES;
1092     let valueLen = 32;
1093     let label = String::from("secured-key");
1094     let token: CK_BBOOL = CK_TRUE;
1095     let private: CK_BBOOL = CK_TRUE;
1096     let encrypt: CK_BBOOL = CK_TRUE;
1097     let decrypt: CK_BBOOL = CK_TRUE;
1098     let sensitive: CK_BBOOL = CK_TRUE;
1099     let extractable: CK_BBOOL = CK_TRUE;
1100     let wrap: CK_BBOOL = CK_FALSE;
1101     let unwrap: CK_BBOOL = CK_FALSE;
1102 
1103     let template = vec![
1104       CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&class),
1105       CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&keyType),
1106       CK_ATTRIBUTE::new(CKA_VALUE_LEN).with_ck_ulong(&valueLen),
1107       CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label),
1108       CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&token),
1109       CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&private),
1110       CK_ATTRIBUTE::new(CKA_ENCRYPT).with_bool(&encrypt),
1111       CK_ATTRIBUTE::new(CKA_DECRYPT).with_bool(&decrypt),
1112       CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&sensitive),
1113       CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&extractable),
1114       CK_ATTRIBUTE::new(CKA_WRAP).with_bool(&wrap),
1115       CK_ATTRIBUTE::new(CKA_UNWRAP).with_bool(&unwrap),
1116     ];
1117 
1118     secOh = ctx.generate_key(sh, &mechanism, &template)?;
1119   }
1120 
1121   Ok((ctx, sh, wrapOh, secOh))
1122 }
1123 
1124 #[allow(dead_code)]
fixture_key_pair( ctx: &Ctx, sh: CK_SESSION_HANDLE, pubLabel: String, privLabel: String, ) -> Result<(CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), Error>1125 fn fixture_key_pair(
1126   ctx: &Ctx,
1127   sh: CK_SESSION_HANDLE,
1128   pubLabel: String,
1129   privLabel: String,
1130 ) -> Result<(CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), Error> {
1131   let mechanism = CK_MECHANISM {
1132     mechanism: CKM_RSA_PKCS_KEY_PAIR_GEN,
1133     pParameter: ptr::null_mut(),
1134     ulParameterLen: 0,
1135   };
1136 
1137   let privClass = CKO_PRIVATE_KEY;
1138   let privKeyType = CKK_RSA;
1139   let privLabel = privLabel;
1140   let privToken = CK_TRUE;
1141   let privPrivate = CK_TRUE;
1142   let privSensitive = CK_TRUE;
1143   let privUnwrap = CK_FALSE;
1144   let privExtractable = CK_FALSE;
1145   let privSign = CK_TRUE;
1146 
1147   let privTemplate = vec![
1148     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&privClass),
1149     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&privKeyType),
1150     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&privLabel),
1151     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&privToken),
1152     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&privPrivate),
1153     CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&privSensitive),
1154     CK_ATTRIBUTE::new(CKA_UNWRAP).with_bool(&privUnwrap),
1155     CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&privExtractable),
1156     CK_ATTRIBUTE::new(CKA_SIGN).with_bool(&privSign),
1157   ];
1158 
1159   let pubClass = CKO_PUBLIC_KEY;
1160   let pubKeyType = CKK_RSA;
1161   let pubLabel = pubLabel;
1162   let pubToken = CK_TRUE;
1163   let pubPrivate = CK_TRUE;
1164   let pubWrap = CK_FALSE;
1165   let pubVerify = CK_TRUE;
1166   let pubModulusBits: CK_ULONG = 4096;
1167   let pubPublicExponent = BigUint::from(65537u32);
1168   let pubPublicExponentSlice = pubPublicExponent.to_bytes_le();
1169 
1170   let pubTemplate = vec![
1171     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&pubClass),
1172     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&pubKeyType),
1173     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&pubLabel),
1174     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&pubToken),
1175     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&pubPrivate),
1176     CK_ATTRIBUTE::new(CKA_WRAP).with_bool(&pubWrap),
1177     CK_ATTRIBUTE::new(CKA_VERIFY).with_bool(&pubVerify),
1178     CK_ATTRIBUTE::new(CKA_MODULUS_BITS).with_ck_ulong(&pubModulusBits),
1179     CK_ATTRIBUTE::new(CKA_PUBLIC_EXPONENT).with_biginteger(&pubPublicExponentSlice),
1180   ];
1181 
1182   let (pubOh, privOh) = ctx.generate_key_pair(sh, &mechanism, &pubTemplate, &privTemplate)?;
1183   Ok((pubOh, privOh))
1184 }
1185 
fixture_dh_key_pair( ctx: &Ctx, sh: CK_SESSION_HANDLE, pubLabel: String, privLabel: String, ) -> Result<(CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), Error>1186 fn fixture_dh_key_pair(
1187   ctx: &Ctx,
1188   sh: CK_SESSION_HANDLE,
1189   pubLabel: String,
1190   privLabel: String,
1191 ) -> Result<(CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), Error> {
1192   let mechanism = CK_MECHANISM {
1193     mechanism: CKM_DH_PKCS_KEY_PAIR_GEN,
1194     pParameter: ptr::null_mut(),
1195     ulParameterLen: 0,
1196   };
1197   //[]*pkcs11.Attribute{
1198   //	pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
1199   //	pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_DH),
1200   //	pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
1201   //	pkcs11.NewAttribute(pkcs11.CKA_TOKEN, false),
1202   //	pkcs11.NewAttribute(pkcs11.CKA_DERIVE, true),
1203   //},
1204   let privClass = CKO_PRIVATE_KEY;
1205   let privKeyType = CKK_DH;
1206   let privLabel = privLabel;
1207   let privToken = CK_TRUE;
1208   let privPrivate = CK_TRUE;
1209   let privSensitive = CK_TRUE;
1210   let privExtractable = CK_FALSE;
1211   let privDerive = CK_TRUE;
1212 
1213   let privTemplate = vec![
1214     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&privClass),
1215     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&privKeyType),
1216     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&privLabel),
1217     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&privToken),
1218     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&privPrivate),
1219     CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&privSensitive),
1220     CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&privExtractable),
1221     CK_ATTRIBUTE::new(CKA_DERIVE).with_bool(&privDerive),
1222   ];
1223 
1224   /*
1225 			[]*pkcs11.Attribute{
1226 				pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
1227 				pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_DH),
1228 				pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
1229 				pkcs11.NewAttribute(pkcs11.CKA_TOKEN, false),
1230 				pkcs11.NewAttribute(pkcs11.CKA_DERIVE, true),
1231 				pkcs11.NewAttribute(pkcs11.CKA_BASE, domainParamBase.Bytes()),
1232 				pkcs11.NewAttribute(pkcs11.CKA_PRIME, domainParamPrime.Bytes()),
1233 			},
1234   */
1235 
1236   let pubClass = CKO_PUBLIC_KEY;
1237   let pubKeyType = CKK_DH;
1238   let pubLabel = pubLabel;
1239   let pubToken = CK_TRUE;
1240   let pubPrivate = CK_TRUE;
1241   let pubDerive = CK_TRUE;
1242   //  2048-bit MODP Group
1243   let prime: Vec<u8> = Vec::from_hex(
1244     "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF",
1245   ).unwrap();
1246   // 1536-bit MODP Group
1247   //let base: Vec<u8> = Vec::from_hex(
1248   //  "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
1249   //).unwrap();
1250   let base: Vec<u8> = Vec::from_hex("02").unwrap();
1251 
1252   let pubTemplate = vec![
1253     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&pubClass),
1254     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&pubKeyType),
1255     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&pubLabel),
1256     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&pubToken),
1257     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&pubPrivate),
1258     CK_ATTRIBUTE::new(CKA_DERIVE).with_bool(&pubDerive),
1259     CK_ATTRIBUTE::new(CKA_BASE).with_bytes(&base.as_slice()),
1260     CK_ATTRIBUTE::new(CKA_PRIME).with_bytes(&prime.as_slice()),
1261   ];
1262 
1263   let (pubOh, privOh) = ctx.generate_key_pair(sh, &mechanism, &pubTemplate, &privTemplate)?;
1264   Ok((pubOh, privOh))
1265 }
1266 
1267 #[test]
1268 #[serial]
ctx_wrap_key()1269 fn ctx_wrap_key() {
1270   let (ctx, sh, wrapOh, secOh) = fixture_token_and_secret_keys().unwrap();
1271 
1272   // using the default IV
1273   let mechanism = CK_MECHANISM {
1274     mechanism: CKM_AES_KEY_WRAP_PAD,
1275     pParameter: ptr::null_mut(),
1276     ulParameterLen: 0,
1277   };
1278 
1279   let res = ctx.wrap_key(sh, &mechanism, wrapOh, secOh);
1280   assert!(
1281     res.is_ok(),
1282     "failed to call C_WrapKey({}, {:?}, {}, {}) without parameter: {}",
1283     sh,
1284     &mechanism,
1285     wrapOh,
1286     secOh,
1287     res.unwrap_err()
1288   );
1289   let wrappedKey = res.unwrap();
1290   println!(
1291     "Wrapped Key Bytes (Total of {} bytes): {:?}",
1292     wrappedKey.len(),
1293     wrappedKey
1294   );
1295 }
1296 
1297 #[test]
1298 #[serial]
ctx_unwrap_key()1299 fn ctx_unwrap_key() {
1300   let (ctx, sh, wrapOh, secOh) = fixture_token_and_secret_keys().unwrap();
1301 
1302   // using the default IV
1303   let mechanism = CK_MECHANISM {
1304     mechanism: CKM_AES_KEY_WRAP_PAD,
1305     pParameter: ptr::null_mut(),
1306     ulParameterLen: 0,
1307   };
1308 
1309   let wrappedKey = ctx.wrap_key(sh, &mechanism, wrapOh, secOh).unwrap();
1310 
1311   let class = CKO_SECRET_KEY;
1312   let keyType = CKK_AES;
1313   let label = String::from("secured-key-unwrapped");
1314   let token: CK_BBOOL = CK_TRUE;
1315   let private: CK_BBOOL = CK_TRUE;
1316   let encrypt: CK_BBOOL = CK_TRUE;
1317   let decrypt: CK_BBOOL = CK_TRUE;
1318   let sensitive: CK_BBOOL = CK_TRUE;
1319   let extractable: CK_BBOOL = CK_TRUE;
1320   let wrap: CK_BBOOL = CK_FALSE;
1321   let unwrap: CK_BBOOL = CK_FALSE;
1322 
1323   let template = vec![
1324     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&class),
1325     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&keyType),
1326     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label),
1327     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&token),
1328     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&private),
1329     CK_ATTRIBUTE::new(CKA_ENCRYPT).with_bool(&encrypt),
1330     CK_ATTRIBUTE::new(CKA_DECRYPT).with_bool(&decrypt),
1331     CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&sensitive),
1332     CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&extractable),
1333     CK_ATTRIBUTE::new(CKA_WRAP).with_bool(&wrap),
1334     CK_ATTRIBUTE::new(CKA_UNWRAP).with_bool(&unwrap),
1335   ];
1336 
1337   let res = ctx.unwrap_key(sh, &mechanism, wrapOh, &wrappedKey, &template);
1338   assert!(
1339     res.is_ok(),
1340     "failed to call C_UnwrapKey({}, {:?}, {}, {:?}, {:?}): {}",
1341     sh,
1342     &mechanism,
1343     wrapOh,
1344     &wrappedKey,
1345     &template,
1346     res.unwrap_err()
1347   );
1348   let oh = res.unwrap();
1349   println!("New unwrapped key Object Handle: {}", oh);
1350 }
1351 
1352 #[test]
1353 #[serial]
ctx_derive_key()1354 fn ctx_derive_key() {
1355   let (ctx, sh) = fixture_token().unwrap();
1356 
1357   // 1. generate 2 DH KeyPairs
1358   let (pubOh1, privOh1) = fixture_dh_key_pair(
1359     &ctx,
1360     sh,
1361     String::from("label1-pub"),
1362     String::from("label1-priv"),
1363   ).unwrap();
1364   let (pubOh2, privOh2) = fixture_dh_key_pair(
1365     &ctx,
1366     sh,
1367     String::from("label2-pub"),
1368     String::from("label2-priv"),
1369   ).unwrap();
1370 
1371   // 2. retrieve the public key bytes from both
1372   let mut template = vec![CK_ATTRIBUTE::new(CKA_VALUE)];
1373   ctx.get_attribute_value(sh, pubOh1, &mut template).unwrap();
1374   let value: Vec<CK_BYTE> = Vec::with_capacity(template[0].ulValueLen);
1375   template[0].set_bytes(&value.as_slice());
1376   ctx.get_attribute_value(sh, pubOh1, &mut template).unwrap();
1377 
1378   let pub1Bytes = template[0].get_bytes();
1379 
1380   let mut template = vec![CK_ATTRIBUTE::new(CKA_VALUE)];
1381   ctx.get_attribute_value(sh, pubOh2, &mut template).unwrap();
1382   let value: Vec<CK_BYTE> = Vec::with_capacity(template[0].ulValueLen);
1383   template[0].set_bytes(&value.as_slice());
1384   ctx.get_attribute_value(sh, pubOh2, &mut template).unwrap();
1385 
1386   let pub2Bytes = template[0].get_bytes();
1387 
1388   // 3. derive the first secret key
1389   let mechanism = CK_MECHANISM {
1390     mechanism: CKM_DH_PKCS_DERIVE,
1391     pParameter: pub2Bytes.as_slice().as_ptr() as CK_VOID_PTR,
1392     ulParameterLen: pub2Bytes.len(),
1393   };
1394 
1395   let class = CKO_SECRET_KEY;
1396   let keyType = CKK_AES;
1397   let valueLen = 32;
1398   let label = String::from("derived-key-1");
1399   let token: CK_BBOOL = CK_TRUE;
1400   let private: CK_BBOOL = CK_TRUE;
1401   let sensitive: CK_BBOOL = CK_FALSE;
1402   let extractable: CK_BBOOL = CK_TRUE;
1403 
1404   let template = vec![
1405     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&class),
1406     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&keyType),
1407     CK_ATTRIBUTE::new(CKA_VALUE_LEN).with_ck_ulong(&valueLen),
1408     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label),
1409     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&token),
1410     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&private),
1411     CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&sensitive),
1412     CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&extractable),
1413   ];
1414 
1415   let res = ctx.derive_key(sh, &mechanism, privOh1, &template);
1416   assert!(res.is_ok(), "failed to call C_DeriveKey({}, {:?}, {}, {:?}): {}", sh, &mechanism, privOh1, &template, res.unwrap_err());
1417   let secOh1 = res.unwrap();
1418   println!("1st Derived Secret Key Object Handle: {}", secOh1);
1419 
1420   // 4. derive the second secret key
1421   let mechanism = CK_MECHANISM {
1422     mechanism: CKM_DH_PKCS_DERIVE,
1423     pParameter: pub1Bytes.as_slice().as_ptr() as CK_VOID_PTR,
1424     ulParameterLen: pub1Bytes.len(),
1425   };
1426 
1427   let class = CKO_SECRET_KEY;
1428   let keyType = CKK_AES;
1429   let valueLen = 32;
1430   let label = String::from("derived-key-2");
1431   let token: CK_BBOOL = CK_TRUE;
1432   let private: CK_BBOOL = CK_TRUE;
1433   let sensitive: CK_BBOOL = CK_FALSE;
1434   let extractable: CK_BBOOL = CK_TRUE;
1435 
1436   let template = vec![
1437     CK_ATTRIBUTE::new(CKA_CLASS).with_ck_ulong(&class),
1438     CK_ATTRIBUTE::new(CKA_KEY_TYPE).with_ck_ulong(&keyType),
1439     CK_ATTRIBUTE::new(CKA_VALUE_LEN).with_ck_ulong(&valueLen),
1440     CK_ATTRIBUTE::new(CKA_LABEL).with_string(&label),
1441     CK_ATTRIBUTE::new(CKA_TOKEN).with_bool(&token),
1442     CK_ATTRIBUTE::new(CKA_PRIVATE).with_bool(&private),
1443     CK_ATTRIBUTE::new(CKA_SENSITIVE).with_bool(&sensitive),
1444     CK_ATTRIBUTE::new(CKA_EXTRACTABLE).with_bool(&extractable),
1445   ];
1446 
1447   let res = ctx.derive_key(sh, &mechanism, privOh2, &template);
1448   assert!(res.is_ok(), "failed to call C_DeriveKey({}, {:?}, {}, {:?}): {}", sh, &mechanism, privOh2, &template, res.unwrap_err());
1449   let secOh2 = res.unwrap();
1450   println!("2nd Derived Secret Key Object Handle: {}", secOh2);
1451 
1452   // 5. retrieve the derived private keys from both
1453   let mut template = vec![CK_ATTRIBUTE::new(CKA_VALUE)];
1454   ctx.get_attribute_value(sh, secOh1, &mut template).unwrap();
1455   let value: Vec<CK_BYTE> = Vec::with_capacity(template[0].ulValueLen);
1456   template[0].set_bytes(&value.as_slice());
1457   ctx.get_attribute_value(sh, secOh1, &mut template).unwrap();
1458 
1459   let sec1Bytes = template[0].get_bytes();
1460 
1461   let mut template = vec![CK_ATTRIBUTE::new(CKA_VALUE)];
1462   ctx.get_attribute_value(sh, secOh2, &mut template).unwrap();
1463   let value: Vec<CK_BYTE> = Vec::with_capacity(template[0].ulValueLen);
1464   template[0].set_bytes(&value.as_slice());
1465   ctx.get_attribute_value(sh, secOh2, &mut template).unwrap();
1466 
1467   let sec2Bytes = template[0].get_bytes();
1468 
1469   println!("1st Derived Key Bytes: {:?}", sec1Bytes);
1470   println!("2nd Derived Key Bytes: {:?}", sec2Bytes);
1471   assert_eq!(sec1Bytes, sec2Bytes, "Derived Secret Keys don't match");
1472 }
1473 
1474 #[test]
1475 #[serial]
ctx_seed_random()1476 fn ctx_seed_random() {
1477   let (ctx, sh) = fixture_token().unwrap();
1478 
1479   let seed: Vec<CK_BYTE> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
1480   let res = ctx.seed_random(sh, &seed);
1481   assert!(
1482     res.is_ok(),
1483     "failed to call C_SeedRandom({}, {:?}): {}",
1484     sh,
1485     &seed,
1486     res.unwrap_err()
1487   );
1488 }
1489 
1490 #[test]
1491 #[serial]
ctx_generate_random()1492 fn ctx_generate_random() {
1493   let (ctx, sh) = fixture_token().unwrap();
1494   let res = ctx.generate_random(sh, 32);
1495   assert!(
1496     res.is_ok(),
1497     "failed to call C_GenerateRandom({}, {}): {}",
1498     sh,
1499     32,
1500     res.unwrap_err()
1501   );
1502   let randomData = res.unwrap();
1503   println!("Randomly Generated Data: {:?}", randomData);
1504 }
1505 
1506 #[test]
1507 #[serial]
ctx_get_function_status()1508 fn ctx_get_function_status() {
1509   let (ctx, sh) = fixture_token().unwrap();
1510   let res = ctx.get_function_status(sh);
1511   assert!(
1512     res.is_ok(),
1513     "failed to call C_GetFunctionStatus({}): {}",
1514     sh,
1515     res.unwrap_err()
1516   );
1517   let val = res.unwrap();
1518   assert_eq!(val, CKR_FUNCTION_NOT_PARALLEL);
1519 }
1520 
1521 #[test]
1522 #[serial]
ctx_cancel_function()1523 fn ctx_cancel_function() {
1524   let (ctx, sh) = fixture_token().unwrap();
1525   let res = ctx.cancel_function(sh);
1526   assert!(
1527     res.is_ok(),
1528     "failed to call C_CancelFunction({}): {}",
1529     sh,
1530     res.unwrap_err()
1531   );
1532   let val = res.unwrap();
1533   assert_eq!(val, CKR_FUNCTION_NOT_PARALLEL);
1534 }
1535 
1536 #[test]
1537 #[serial]
ctx_wait_for_slot_event()1538 fn ctx_wait_for_slot_event() {
1539   let (ctx, _) = fixture_token().unwrap();
1540   let res = ctx.wait_for_slot_event(CKF_DONT_BLOCK);
1541   if res.is_err() {
1542     // SoftHSM does not support this function, so this is what we should compare against
1543     //assert_eq!(Error::Pkcs11(CKR_FUNCTION_NOT_SUPPORTED), res.unwrap_err());
1544     match res.unwrap_err() {
1545       Error::Pkcs11(CKR_FUNCTION_NOT_SUPPORTED) => {
1546         println!("as expected SoftHSM does not support this function");
1547       }
1548       _ => panic!("ahhh"),
1549     }
1550   } else {
1551     assert!(
1552       res.is_ok(),
1553       "failed to call C_WaitForSlotEvent({}): {}",
1554       CKF_DONT_BLOCK,
1555       res.unwrap_err()
1556     );
1557   }
1558 }
1559