Skip to content

Commit d1b283e

Browse files
simo5Gemini
authored andcommitted
Expose single-part crypto operations
Refactor encryption, decryption, signing, verification, and digesting operations to separate the initialization logic from the single-part execution logic. This exposes `*_single` methods publicly, allowing greater flexibility in operation flows. For example, this supports context-specific user authentication where the operation must be initialized before the authentication step occurs. Co-authored-by: Gemini <gemini@google.com> Signed-off-by: Simo Sorce <simo@redhat.com>
1 parent 1914f61 commit d1b283e

5 files changed

Lines changed: 183 additions & 55 deletions

File tree

cryptoki/src/session/decryption.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@ impl Session {
1818
key: ObjectHandle,
1919
encrypted_data: &[u8],
2020
) -> Result<Vec<u8>> {
21-
let mut mechanism: CK_MECHANISM = mechanism.into();
22-
let mut data_len = 0;
21+
self.decrypt_init(mechanism, key)?;
22+
self.decrypt_single(encrypted_data)
23+
}
2324

24-
unsafe {
25-
Rv::from(get_pkcs11!(self.client(), C_DecryptInit)(
26-
self.handle(),
27-
&mut mechanism as CK_MECHANISM_PTR,
28-
key.handle(),
29-
))
30-
.into_result(Function::DecryptInit)?;
31-
}
25+
/// Single-part decryption operation.
26+
///
27+
/// This function can be used instead of the single shot related decrypt
28+
/// function when the user needs to perform something like
29+
/// context-specific user authentication after [`Session::decrypt_init`]
30+
/// is called.
31+
pub fn decrypt_single(&self, encrypted_data: &[u8]) -> Result<Vec<u8>> {
32+
let mut data_len = 0;
3233

3334
// Get the output buffer length
3435
unsafe {
@@ -61,7 +62,7 @@ impl Session {
6162
Ok(data)
6263
}
6364

64-
/// Starts new multi-part decryption operation
65+
/// Starts new single-part or multi-part decryption operation
6566
pub fn decrypt_init(&self, mechanism: &Mechanism, key: ObjectHandle) -> Result<()> {
6667
let mut mechanism: CK_MECHANISM = mechanism.into();
6768

cryptoki/src/session/digesting.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@ use std::convert::TryInto;
1212

1313
impl Session {
1414
/// Single-part digesting operation
15-
pub fn digest(&self, m: &Mechanism, data: &[u8]) -> Result<Vec<u8>> {
16-
let mut mechanism: CK_MECHANISM = m.into();
17-
let mut digest_len = 0;
15+
pub fn digest(&self, mechanism: &Mechanism, data: &[u8]) -> Result<Vec<u8>> {
16+
self.digest_init(mechanism)?;
17+
self.digest_single(data)
18+
}
1819

19-
unsafe {
20-
Rv::from(get_pkcs11!(self.client(), C_DigestInit)(
21-
self.handle(),
22-
&mut mechanism as CK_MECHANISM_PTR,
23-
))
24-
.into_result(Function::DigestInit)?;
25-
}
20+
/// Digest data in single-part.
21+
///
22+
/// This function can be used instead of the single shot related digest
23+
/// function when the user needs to perform something like
24+
/// context-specific user authentication after [`Session::digest_init`]
25+
/// is called.
26+
pub fn digest_single(&self, data: &[u8]) -> Result<Vec<u8>> {
27+
let mut digest_len = 0;
2628

2729
// Get the output buffer length
2830
unsafe {
@@ -54,7 +56,7 @@ impl Session {
5456
Ok(digest)
5557
}
5658

57-
/// Starts new multi-part digesting operation
59+
/// Starts new single-part or multi-part digesting operation
5860
pub fn digest_init(&self, m: &Mechanism) -> Result<()> {
5961
let mut mechanism: CK_MECHANISM = m.into();
6062

cryptoki/src/session/encryption.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@ impl Session {
1818
key: ObjectHandle,
1919
data: &[u8],
2020
) -> Result<Vec<u8>> {
21-
let mut mechanism: CK_MECHANISM = mechanism.into();
22-
let mut encrypted_data_len = 0;
21+
self.encrypt_init(mechanism, key)?;
22+
self.encrypt_single(data)
23+
}
2324

24-
unsafe {
25-
Rv::from(get_pkcs11!(self.client(), C_EncryptInit)(
26-
self.handle(),
27-
&mut mechanism as CK_MECHANISM_PTR,
28-
key.handle(),
29-
))
30-
.into_result(Function::EncryptInit)?;
31-
}
25+
/// Single-part encryption operation.
26+
///
27+
/// This function can be used instead of the single shot related encrypt
28+
/// function when the user needs to perform something like
29+
/// context-specific user authentication after [`Session::encrypt_init`]
30+
/// is called.
31+
pub fn encrypt_single(&self, data: &[u8]) -> Result<Vec<u8>> {
32+
let mut encrypted_data_len = 0;
3233

3334
// Get the output buffer length
3435
unsafe {
@@ -60,7 +61,7 @@ impl Session {
6061
Ok(encrypted_data)
6162
}
6263

63-
/// Starts new multi-part encryption operation
64+
/// Starts new single-part or multi-part encryption operation
6465
pub fn encrypt_init(&self, mechanism: &Mechanism, key: ObjectHandle) -> Result<()> {
6566
let mut mechanism: CK_MECHANISM = mechanism.into();
6667

cryptoki/src/session/signing_macing.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@ use std::convert::TryInto;
1313
impl Session {
1414
/// Sign data in single-part
1515
pub fn sign(&self, mechanism: &Mechanism, key: ObjectHandle, data: &[u8]) -> Result<Vec<u8>> {
16-
let mut mechanism: CK_MECHANISM = mechanism.into();
17-
let mut signature_len = 0;
16+
self.sign_init(mechanism, key)?;
17+
self.sign_single(data)
18+
}
1819

19-
unsafe {
20-
Rv::from(get_pkcs11!(self.client(), C_SignInit)(
21-
self.handle(),
22-
&mut mechanism as CK_MECHANISM_PTR,
23-
key.handle(),
24-
))
25-
.into_result(Function::SignInit)?;
26-
}
20+
/// Sign data in single-part.
21+
///
22+
/// This function can be used instead of the single shot related sign
23+
/// function when the user needs to perform something like
24+
/// context-specific user authentication after [`Session::sign_init`]
25+
/// is called.
26+
pub fn sign_single(&self, data: &[u8]) -> Result<Vec<u8>> {
27+
let mut signature_len = 0;
2728

2829
// Get the output buffer length
2930
unsafe {
@@ -56,7 +57,7 @@ impl Session {
5657
Ok(signature)
5758
}
5859

59-
/// Starts new multi-part signing operation
60+
/// Starts new single-part or multi-part signing operation
6061
pub fn sign_init(&self, mechanism: &Mechanism, key: ObjectHandle) -> Result<()> {
6162
let mut mechanism: CK_MECHANISM = mechanism.into();
6263

@@ -126,17 +127,17 @@ impl Session {
126127
data: &[u8],
127128
signature: &[u8],
128129
) -> Result<()> {
129-
let mut mechanism: CK_MECHANISM = mechanism.into();
130-
131-
unsafe {
132-
Rv::from(get_pkcs11!(self.client(), C_VerifyInit)(
133-
self.handle(),
134-
&mut mechanism as CK_MECHANISM_PTR,
135-
key.handle(),
136-
))
137-
.into_result(Function::VerifyInit)?;
138-
}
130+
self.verify_init(mechanism, key)?;
131+
self.verify_single(data, signature)
132+
}
139133

134+
/// Verify data in single-part.
135+
///
136+
/// This function can be used instead of the single shot related verify
137+
/// function when the user needs to perform something like
138+
/// context-specific user authentication after [`Session::verify_init`]
139+
/// is called.
140+
pub fn verify_single(&self, data: &[u8], signature: &[u8]) -> Result<()> {
140141
unsafe {
141142
Rv::from(get_pkcs11!(self.client(), C_Verify)(
142143
self.handle(),
@@ -149,7 +150,7 @@ impl Session {
149150
}
150151
}
151152

152-
/// Starts new multi-part verifying operation
153+
/// Starts new single-part or multi-part verifying operation
153154
pub fn verify_init(&self, mechanism: &Mechanism, key: ObjectHandle) -> Result<()> {
154155
let mut mechanism: CK_MECHANISM = mechanism.into();
155156

cryptoki/tests/basic.rs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,56 @@ fn sign_verify_eddsa_with_ed448_schemes() -> TestResult {
239239
Ok(())
240240
}
241241

242+
#[test]
243+
#[serial]
244+
fn sign_verify_single_part() -> TestResult {
245+
let (pkcs11, slot) = init_pins();
246+
247+
// Open a session and log in
248+
let session = pkcs11.open_rw_session(slot)?;
249+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
250+
251+
// Define parameters for keypair
252+
let public_exponent = vec![0x01, 0x00, 0x01];
253+
let modulus_bits = 2048;
254+
255+
let pub_key_template = vec![
256+
Attribute::Token(true),
257+
Attribute::Private(false),
258+
Attribute::PublicExponent(public_exponent),
259+
Attribute::ModulusBits(modulus_bits.into()),
260+
Attribute::Verify(true),
261+
];
262+
let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)];
263+
264+
// Generate keypair
265+
let (pub_key, priv_key) = session.generate_key_pair(
266+
&Mechanism::RsaPkcsKeyPairGen,
267+
&pub_key_template,
268+
&priv_key_template,
269+
)?;
270+
271+
// Data to sign
272+
let data = [0xFF, 0x55, 0xDD, 0x11, 0xBB, 0x33];
273+
274+
// Sign data in a single part using separate init and single call
275+
session.sign_init(&Mechanism::Sha256RsaPkcs, priv_key)?;
276+
let signature = session.sign_single(&data)?;
277+
278+
// Verify signature in a single part using separate init and single call
279+
session.verify_init(&Mechanism::Sha256RsaPkcs, pub_key)?;
280+
session.verify_single(&data, &signature)?;
281+
282+
// Delete keys
283+
session.destroy_object(pub_key)?;
284+
session.destroy_object(priv_key)?;
285+
286+
session.close()?;
287+
pkcs11.finalize()?;
288+
289+
Ok(())
290+
}
291+
242292
#[test]
243293
#[serial]
244294
fn sign_verify_multipart() -> TestResult {
@@ -480,6 +530,50 @@ fn encrypt_decrypt() -> TestResult {
480530
Ok(())
481531
}
482532

533+
#[test]
534+
#[serial]
535+
fn encrypt_decrypt_single_part() -> TestResult {
536+
let (pkcs11, slot) = init_pins();
537+
538+
// Open a session and log in
539+
let session = pkcs11.open_rw_session(slot)?;
540+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
541+
542+
// Generate key
543+
let template = vec![
544+
Attribute::Token(true),
545+
Attribute::Private(false),
546+
Attribute::ValueLen(AES128_BLOCK_SIZE),
547+
Attribute::Encrypt(true),
548+
Attribute::Decrypt(true),
549+
];
550+
let key = session.generate_key(&Mechanism::AesKeyGen, &template)?;
551+
552+
// Data to encrypt
553+
let data = vec![
554+
0xFF, 0x55, 0xDD, 0x11, 0xBB, 0x33, 0x99, 0x77, 0xFF, 0x55, 0xDD, 0x11, 0xBB, 0x33, 0x99,
555+
0x77,
556+
];
557+
558+
// Encrypt data in a single part using separate init and single call
559+
session.encrypt_init(&Mechanism::AesEcb, key)?;
560+
let encrypted_data = session.encrypt_single(&data)?;
561+
562+
// Decrypt data in a single part using separate init and single call
563+
session.decrypt_init(&Mechanism::AesEcb, key)?;
564+
let decrypted_data = session.decrypt_single(&encrypted_data)?;
565+
566+
assert_eq!(data, decrypted_data);
567+
568+
// Delete key
569+
session.destroy_object(key)?;
570+
571+
session.close()?;
572+
pkcs11.finalize()?;
573+
574+
Ok(())
575+
}
576+
483577
#[test]
484578
#[serial]
485579
fn encrypt_decrypt_multipart() -> TestResult {
@@ -2277,6 +2371,35 @@ fn sha256_digest() -> TestResult {
22772371
Ok(())
22782372
}
22792373

2374+
#[test]
2375+
#[serial]
2376+
fn sha256_digest_single_part() -> TestResult {
2377+
let (pkcs11, slot) = init_pins();
2378+
2379+
// open a session
2380+
let session = pkcs11.open_rw_session(slot)?;
2381+
2382+
// log in the session
2383+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
2384+
2385+
// data to digest
2386+
let data = vec![0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
2387+
2388+
let want = [
2389+
0x17, 0x22, 0x6b, 0x1f, 0x68, 0xae, 0xba, 0xcd, 0xef, 0x07, 0x46, 0x45, 0x0f, 0x64, 0x28,
2390+
0x74, 0x63, 0x8b, 0x29, 0x57, 0x07, 0xef, 0x73, 0xfb, 0x2c, 0x6b, 0xb7, 0xf8, 0x8e, 0x89,
2391+
0x92, 0x9f,
2392+
];
2393+
session.digest_init(&Mechanism::Sha256)?;
2394+
let have = session.digest_single(&data)?;
2395+
assert_eq!(want[..], have[..]);
2396+
2397+
session.close()?;
2398+
pkcs11.finalize()?;
2399+
2400+
Ok(())
2401+
}
2402+
22802403
#[test]
22812404
#[serial]
22822405
fn sha256_digest_multipart() -> TestResult {

0 commit comments

Comments
 (0)