Skip to content

Commit ecc077c

Browse files
committed
Implement message sign/verify functions
Signed-off-by: Jakub Jelen <[email protected]>
1 parent b6aad9d commit ecc077c

File tree

3 files changed

+264
-1
lines changed

3 files changed

+264
-1
lines changed

cryptoki/src/mechanism/mechanism_info.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ bitflags! {
3131
const EC_COMPRESS = CKF_EC_COMPRESS;
3232
const MESSAGE_ENCRYPT = CKF_MESSAGE_ENCRYPT;
3333
const MESSAGE_DECRYPT = CKF_MESSAGE_DECRYPT;
34+
const MESSAGE_SIGN = CKF_MESSAGE_SIGN;
35+
const MESSAGE_VERIFY = CKF_MESSAGE_VERIFY;
3436
const MULTI_MESSAGE = CKF_MULTI_MESSAGE;
3537
}
3638
}
@@ -246,6 +248,20 @@ impl MechanismInfo {
246248
self.flags.contains(MechanismInfoFlags::MESSAGE_DECRYPT)
247249
}
248250

251+
/// True if the mechanism can be used to sign messages
252+
///
253+
/// See [`Session::sign_message`](crate::session::Session::sign_message)
254+
pub fn message_sign(&self) -> bool {
255+
self.flags.contains(MechanismInfoFlags::MESSAGE_SIGN)
256+
}
257+
258+
/// True if the mechanism can be used to verify signed messages
259+
///
260+
/// See [`Session::decrypt`](crate::session::Session::verify_message)
261+
pub fn message_verify(&self) -> bool {
262+
self.flags.contains(MechanismInfoFlags::MESSAGE_VERIFY)
263+
}
264+
249265
/// True if the mechanism can be used with encrypt/decrypt_message_begin API.
250266
/// One of message_* flag must also be set.
251267
///
@@ -294,7 +310,7 @@ HW | ENCRYPT | DECRYPT | DIGEST | SIGN | SIGN_RECOVER | VERIFY | \
294310
VERIFY_RECOVER | GENERATE | GENERATE_KEY_PAIR | WRAP | UNWRAP | DERIVE | \
295311
EXTENSION | EC_F_P | EC_F_2M | EC_ECPARAMETERS | EC_NAMEDCURVE | \
296312
EC_OID | EC_UNCOMPRESS | EC_COMPRESS | MESSAGE_ENCRYPT | MESSAGE_DECRYPT | \
297-
MULTI_MESSAGE";
313+
MESSAGE_SIGN | MESSAGE_VERIFY | MULTI_MESSAGE";
298314
let all = MechanismInfoFlags::all();
299315
let observed = format!("{all:#?}");
300316
println!("{observed}");
+246
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// Copyright 2025 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
//! Message Signing/Verification and authentication functions
4+
5+
use crate::context::Function;
6+
use crate::error::{Result, Rv};
7+
use crate::mechanism::{Mechanism, MessageParam};
8+
use crate::object::ObjectHandle;
9+
use crate::session::Session;
10+
use cryptoki_sys::*;
11+
use std::convert::TryInto;
12+
13+
impl Session {
14+
/// Prepare a session for one or more Message-based signature using the same mechanism and key
15+
pub fn message_sign_init(&self, mechanism: &Mechanism, key: ObjectHandle) -> Result<()> {
16+
let mut mechanism: CK_MECHANISM = mechanism.into();
17+
18+
unsafe {
19+
Rv::from(get_pkcs11!(self.client(), C_MessageSignInit)(
20+
self.handle(),
21+
&mut mechanism as CK_MECHANISM_PTR,
22+
key.handle(),
23+
))
24+
.into_result(Function::MessageSignInit)?;
25+
}
26+
27+
Ok(())
28+
}
29+
30+
/// Sign a message in single part
31+
pub fn sign_message(&self, param: &MessageParam, data: &[u8]) -> Result<Vec<u8>> {
32+
let mut signature_len = 0;
33+
34+
// Get the output buffer length
35+
unsafe {
36+
Rv::from(get_pkcs11!(self.client(), C_SignMessage)(
37+
self.handle(),
38+
param.as_ptr(),
39+
param.len(),
40+
data.as_ptr() as *mut u8,
41+
data.len().try_into()?,
42+
std::ptr::null_mut(),
43+
&mut signature_len,
44+
))
45+
.into_result(Function::SignMessage)?;
46+
}
47+
48+
let mut signature = vec![0; signature_len.try_into()?];
49+
50+
unsafe {
51+
Rv::from(get_pkcs11!(self.client(), C_SignMessage)(
52+
self.handle(),
53+
param.as_ptr(),
54+
param.len(),
55+
data.as_ptr() as *mut u8,
56+
data.len().try_into()?,
57+
signature.as_mut_ptr(),
58+
&mut signature_len,
59+
))
60+
.into_result(Function::SignMessage)?;
61+
}
62+
63+
signature.resize(signature_len.try_into()?, 0);
64+
65+
Ok(signature)
66+
}
67+
68+
/// Begin multi-part message signature operation
69+
pub fn sign_message_begin(&self, param: MessageParam) -> Result<()> {
70+
unsafe {
71+
Rv::from(get_pkcs11!(self.client(), C_SignMessageBegin)(
72+
self.handle(),
73+
param.as_ptr(),
74+
param.len(),
75+
))
76+
.into_result(Function::SignMessageBegin)
77+
}
78+
}
79+
80+
/// Continue mutli-part message signature operation
81+
pub fn sign_message_next(
82+
&self,
83+
param: MessageParam,
84+
data: &[u8],
85+
end: bool,
86+
) -> Result<Option<Vec<u8>>> {
87+
if !end {
88+
// Just pass in the data
89+
unsafe {
90+
Rv::from(get_pkcs11!(self.client(), C_SignMessageNext)(
91+
self.handle(),
92+
param.as_ptr(),
93+
param.len(),
94+
data.as_ptr() as *mut u8,
95+
data.len().try_into()?,
96+
std::ptr::null_mut(),
97+
std::ptr::null_mut(),
98+
))
99+
.into_result(Function::SignMessageNext)?;
100+
}
101+
return Ok(None);
102+
}
103+
let mut signature_len = 0;
104+
unsafe {
105+
Rv::from(get_pkcs11!(self.client(), C_SignMessageNext)(
106+
self.handle(),
107+
param.as_ptr(),
108+
param.len(),
109+
data.as_ptr() as *mut u8,
110+
data.len().try_into()?,
111+
std::ptr::null_mut(),
112+
&mut signature_len,
113+
))
114+
.into_result(Function::SignMessageNext)?;
115+
}
116+
117+
let mut signature = vec![0; signature_len.try_into()?];
118+
119+
unsafe {
120+
Rv::from(get_pkcs11!(self.client(), C_SignMessageNext)(
121+
self.handle(),
122+
param.as_ptr(),
123+
param.len(),
124+
data.as_ptr() as *mut u8,
125+
data.len().try_into()?,
126+
signature.as_mut_ptr(),
127+
&mut signature_len,
128+
))
129+
.into_result(Function::SignMessageNext)?;
130+
}
131+
132+
signature.resize(signature_len.try_into()?, 0);
133+
134+
Ok(Some(signature))
135+
}
136+
137+
/// Finalize mutli-part message signature process
138+
pub fn message_sign_final(&self) -> Result<()> {
139+
unsafe {
140+
Rv::from(get_pkcs11!(self.client(), C_MessageSignFinal)(
141+
self.handle(),
142+
))
143+
.into_result(Function::MessageSignFinal)
144+
}
145+
}
146+
147+
/// Prepare a session for one or more Message-based verifications using the same mechanism and key
148+
pub fn message_verify_init(&self, mechanism: &Mechanism, key: ObjectHandle) -> Result<()> {
149+
let mut mechanism: CK_MECHANISM = mechanism.into();
150+
151+
unsafe {
152+
Rv::from(get_pkcs11!(self.client(), C_MessageVerifyInit)(
153+
self.handle(),
154+
&mut mechanism as CK_MECHANISM_PTR,
155+
key.handle(),
156+
))
157+
.into_result(Function::MessageVerifyInit)?;
158+
}
159+
160+
Ok(())
161+
}
162+
163+
/// Verify message in single-part
164+
pub fn verify_message(
165+
&self,
166+
param: &MessageParam,
167+
data: &[u8],
168+
signature: &[u8],
169+
) -> Result<()> {
170+
unsafe {
171+
Rv::from(get_pkcs11!(self.client(), C_VerifyMessage)(
172+
self.handle(),
173+
param.as_ptr(),
174+
param.len(),
175+
data.as_ptr() as *mut u8,
176+
data.len().try_into()?,
177+
signature.as_ptr() as *mut u8,
178+
signature.len().try_into()?,
179+
))
180+
.into_result(Function::VerifyMessage)?;
181+
}
182+
Ok(())
183+
}
184+
185+
/// Begin multi-part message signature verification operation
186+
pub fn verify_message_begin(&self, param: MessageParam) -> Result<()> {
187+
unsafe {
188+
Rv::from(get_pkcs11!(self.client(), C_VerifyMessageBegin)(
189+
self.handle(),
190+
param.as_ptr(),
191+
param.len(),
192+
))
193+
.into_result(Function::VerifyMessageBegin)
194+
}
195+
}
196+
197+
/// Continue mutli-part message signature verification operation
198+
pub fn verify_message_next(
199+
&self,
200+
param: MessageParam,
201+
data: &[u8],
202+
signature: Option<&[u8]>,
203+
) -> Result<()> {
204+
match signature {
205+
None => {
206+
// Just pass in the data
207+
unsafe {
208+
Rv::from(get_pkcs11!(self.client(), C_VerifyMessageNext)(
209+
self.handle(),
210+
param.as_ptr(),
211+
param.len(),
212+
data.as_ptr() as *mut u8,
213+
data.len().try_into()?,
214+
std::ptr::null_mut(),
215+
0,
216+
))
217+
.into_result(Function::VerifyMessageNext)?;
218+
}
219+
return Ok(());
220+
}
221+
Some(s) => unsafe {
222+
Rv::from(get_pkcs11!(self.client(), C_VerifyMessageNext)(
223+
self.handle(),
224+
param.as_ptr(),
225+
param.len(),
226+
data.as_ptr() as *mut u8,
227+
data.len().try_into()?,
228+
s.as_ptr() as *mut u8,
229+
s.len().try_into()?,
230+
))
231+
.into_result(Function::VerifyMessageNext)?;
232+
},
233+
}
234+
Ok(())
235+
}
236+
237+
/// Finalize mutli-part message signature verification process
238+
pub fn message_verify_final(&self) -> Result<()> {
239+
unsafe {
240+
Rv::from(get_pkcs11!(self.client(), C_MessageVerifyFinal)(
241+
self.handle(),
242+
))
243+
.into_result(Function::MessageVerifyFinal)
244+
}
245+
}
246+
}

cryptoki/src/session/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod encryption;
1414
mod key_management;
1515
mod message_decryption;
1616
mod message_encryption;
17+
mod message_signing;
1718
mod object_management;
1819
mod random;
1920
mod session_info;

0 commit comments

Comments
 (0)