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(©able),
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(©able),
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