Skip to content

Commit 5de9fbf

Browse files
jhshannon17jack-shannon-ripple
authored andcommitted
Add pub unsafe accessors for object/session handles and ObjectHandle new
Signed-off-by: Jack Shannon <[email protected]>
1 parent 3ac2766 commit 5de9fbf

File tree

4 files changed

+215
-2
lines changed

4 files changed

+215
-2
lines changed

cryptoki/src/object.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,9 +1029,23 @@ impl ObjectHandle {
10291029
ObjectHandle { handle }
10301030
}
10311031

1032+
/// Create a new object handle from a raw handle.
1033+
/// # Safety
1034+
/// Considered unsafe due to ability for client to arbitrarily create object handles.
1035+
pub unsafe fn new_from_raw(handle: CK_OBJECT_HANDLE) -> Self {
1036+
ObjectHandle { handle }
1037+
}
1038+
10321039
pub(crate) fn handle(&self) -> CK_OBJECT_HANDLE {
10331040
self.handle
10341041
}
1042+
1043+
/// Get the raw handle of the object.
1044+
/// # Safety
1045+
/// Considered unsafe because of pub access to the underlying handle type.
1046+
pub unsafe fn raw_handle(&self) -> CK_OBJECT_HANDLE {
1047+
self.handle
1048+
}
10351049
}
10361050

10371051
impl std::fmt::Display for ObjectHandle {

cryptoki/src/session/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ impl Session {
8080
self.handle
8181
}
8282

83+
/// Get the raw handle of the session.
84+
/// # Safety
85+
/// Considered unsafe because of pub access to the underlying handle type.
86+
pub unsafe fn raw_handle(&self) -> CK_SESSION_HANDLE {
87+
self.handle
88+
}
89+
8390
pub(crate) fn client(&self) -> &Pkcs11 {
8491
&self.client
8592
}

cryptoki/tests/common/mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub static USER_PIN: &str = "fedcba";
1111
// The default SO pin
1212
pub static SO_PIN: &str = "abcdef";
1313

14-
fn get_pkcs11_path() -> String {
14+
pub fn get_pkcs11_path() -> String {
1515
env::var("TEST_PKCS11_MODULE")
1616
.unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string())
1717
}
@@ -26,13 +26,26 @@ pub fn is_kryoptic() -> bool {
2626
get_pkcs11_path().contains("kryoptic")
2727
}
2828

29+
#[allow(dead_code)]
2930
pub fn get_pkcs11() -> Pkcs11 {
3031
Pkcs11::new(get_pkcs11_path()).unwrap()
3132
}
3233

34+
#[allow(dead_code)]
35+
pub fn get_pkcs11_from_self() -> Pkcs11 {
36+
Pkcs11::new_from_self().unwrap()
37+
}
38+
39+
#[allow(dead_code)]
3340
pub fn init_pins() -> (Pkcs11, Slot) {
3441
let pkcs11 = get_pkcs11();
3542

43+
let slot = init_pins_from_pkcs11(&pkcs11);
44+
45+
(pkcs11, slot)
46+
}
47+
48+
pub fn init_pins_from_pkcs11(pkcs11: &Pkcs11) -> Slot {
3649
// initialize the library
3750
pkcs11.initialize(CInitializeArgs::OsThreads).unwrap();
3851

@@ -50,7 +63,7 @@ pub fn init_pins() -> (Pkcs11, Slot) {
5063
session.init_pin(&AuthPin::new(USER_PIN.into())).unwrap();
5164
}
5265

53-
(pkcs11, slot)
66+
slot
5467
}
5568

5669
#[allow(dead_code)]
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// Copyright 2021 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
#![allow(non_camel_case_types)]
4+
#![allow(non_snake_case)]
5+
6+
mod common;
7+
8+
use crate::common::{get_pkcs11_path, USER_PIN};
9+
use common::{get_pkcs11_from_self, init_pins_from_pkcs11};
10+
use cryptoki::context::Function;
11+
use cryptoki::error::{Result, Rv};
12+
use cryptoki::mechanism::Mechanism;
13+
use cryptoki::object::{Attribute, AttributeType, KeyType, ObjectClass, ObjectHandle};
14+
use cryptoki::session::{Session, UserType};
15+
use cryptoki::types::AuthPin;
16+
use cryptoki_sys::{
17+
CK_ATTRIBUTE, CK_MECHANISM, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_RV, CK_SESSION_HANDLE,
18+
CK_ULONG,
19+
};
20+
use libloading::os::unix::{RTLD_GLOBAL, RTLD_NOW};
21+
use serial_test::serial;
22+
23+
use testresult::TestResult;
24+
25+
type C_DeriveKey = unsafe extern "C" fn(
26+
arg1: CK_SESSION_HANDLE,
27+
arg2: *mut CK_MECHANISM,
28+
arg3: CK_OBJECT_HANDLE,
29+
arg4: *mut CK_ATTRIBUTE,
30+
arg5: CK_ULONG,
31+
arg6: *mut CK_OBJECT_HANDLE,
32+
) -> CK_RV;
33+
34+
#[cfg(not(target_os = "windows"))]
35+
fn load_library(library_path: String) -> libloading::Library {
36+
unsafe {
37+
libloading::os::unix::Library::open(Some(library_path), RTLD_NOW | RTLD_GLOBAL)
38+
.unwrap()
39+
.into()
40+
}
41+
}
42+
43+
#[cfg(target_os = "windows")]
44+
fn load_library(library_path: String) -> libloading::Library {
45+
unsafe { ::libloading::Library::new(library_path).unwrap().into() }
46+
}
47+
48+
fn load_from_library(library_path: String) -> Result<(libloading::Library, C_DeriveKey)> {
49+
let library = load_library(library_path);
50+
51+
let C_DeriveKey = unsafe { library.get(b"C_DeriveKey\0").map(|sym| *sym) }?;
52+
53+
Ok((library, C_DeriveKey))
54+
}
55+
56+
trait VendorDeriveKey {
57+
fn vendor_derive_key(
58+
&self,
59+
vendor_fn: C_DeriveKey,
60+
mechanism: &Mechanism,
61+
base_key: ObjectHandle,
62+
template: &[Attribute],
63+
) -> Result<ObjectHandle>;
64+
}
65+
66+
impl VendorDeriveKey for Session {
67+
/// re-implement derive_key to test unsafe accessors for vendor extensions
68+
fn vendor_derive_key(
69+
&self,
70+
vendor_fn: C_DeriveKey,
71+
mechanism: &Mechanism,
72+
base_key: ObjectHandle,
73+
template: &[Attribute],
74+
) -> Result<ObjectHandle> {
75+
let mut mechanism: CK_MECHANISM = mechanism.into();
76+
let mut template: Vec<CK_ATTRIBUTE> = template.iter().map(|attr| attr.into()).collect();
77+
let mut handle = 0;
78+
unsafe {
79+
Rv::from(vendor_fn(
80+
self.raw_handle(),
81+
&mut mechanism as CK_MECHANISM_PTR,
82+
base_key.raw_handle(),
83+
template.as_mut_ptr(),
84+
template.len().try_into()?,
85+
&mut handle,
86+
))
87+
.into_result(Function::DeriveKey)?;
88+
89+
Ok(ObjectHandle::new_from_raw(handle))
90+
}
91+
}
92+
}
93+
94+
#[test]
95+
#[serial]
96+
fn unsafe_accessors_for_vendor_extension() -> TestResult {
97+
let (_library, C_DeriveKey) = load_from_library(get_pkcs11_path())?;
98+
let pkcs11 = get_pkcs11_from_self();
99+
let slot = init_pins_from_pkcs11(&pkcs11);
100+
101+
// open a session
102+
let session = pkcs11.open_rw_session(slot)?;
103+
104+
// log in the session
105+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
106+
107+
// get mechanism
108+
let mechanism = Mechanism::EccKeyPairGen;
109+
110+
let secp256r1_oid: Vec<u8> = vec![0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
111+
112+
// pub key template
113+
let pub_key_template = vec![
114+
Attribute::Token(true),
115+
Attribute::Private(false),
116+
Attribute::Derive(true),
117+
Attribute::KeyType(KeyType::EC),
118+
Attribute::Verify(true),
119+
Attribute::EcParams(secp256r1_oid),
120+
];
121+
122+
// priv key template
123+
let priv_key_template = vec![
124+
Attribute::Token(true),
125+
Attribute::Private(true),
126+
Attribute::Sensitive(true),
127+
Attribute::Extractable(false),
128+
Attribute::Derive(true),
129+
Attribute::Sign(true),
130+
];
131+
132+
// generate a key pair
133+
let (public, private) =
134+
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
135+
136+
let ec_point_attribute = session
137+
.get_attributes(public, &[AttributeType::EcPoint])?
138+
.remove(0);
139+
140+
let ec_point = if let Attribute::EcPoint(point) = ec_point_attribute {
141+
point
142+
} else {
143+
panic!("Expected EC point attribute.");
144+
};
145+
146+
use cryptoki::mechanism::elliptic_curve::*;
147+
148+
let params = Ecdh1DeriveParams::new(EcKdf::null(), &ec_point);
149+
150+
let shared_secret = session.vendor_derive_key(
151+
C_DeriveKey,
152+
&Mechanism::Ecdh1Derive(params),
153+
private,
154+
&[
155+
Attribute::Class(ObjectClass::SECRET_KEY),
156+
Attribute::KeyType(KeyType::GENERIC_SECRET),
157+
Attribute::Sensitive(false),
158+
Attribute::Extractable(true),
159+
Attribute::Token(false),
160+
],
161+
)?;
162+
163+
let value_attribute = session
164+
.get_attributes(shared_secret, &[AttributeType::Value])?
165+
.remove(0);
166+
let value = if let Attribute::Value(value) = value_attribute {
167+
value
168+
} else {
169+
panic!("Expected value attribute.");
170+
};
171+
172+
assert_eq!(value.len(), 32);
173+
174+
// delete keys
175+
session.destroy_object(public)?;
176+
session.destroy_object(private)?;
177+
178+
Ok(())
179+
}

0 commit comments

Comments
 (0)