Skip to content

Commit 532416e

Browse files
wiktor-kprobablynachi
authored andcommitted
Fix RSA OKCS OAEP mechanism
Handling of empty data specified was broken. As specified in "2.1.7 PKCS #1 RSA OAEP mechanism parameters" the `CKZ_DATA_SPECIFIED` source: > Array of CK_BYTE containing the value of the encoding parameter. > If the parameter is empty, pSourceData must be NULL and ulSourceDataLen > must be zero. Adjusts by returning `std::ptr::null()` when the source data has not been specified (`PkcsOaepSource::empty()` was used) and adds a tests case for this. One more test case that is ignored is added to handle the case when the data specified is non-empty. Unfortunately this test fails for unknown reasons (I haven't been able to find if SoftHSM supports it or not). Fixes: #163 Fixes: #164 Signed-off-by: Wiktor Kwapisiewicz <[email protected]> Co-authored-by: Nachiketh S Ujjainimath <[email protected]>
1 parent f3f5554 commit 532416e

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

cryptoki/src/mechanism/rsa.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,27 +79,32 @@ impl TryFrom<CK_RSA_PKCS_MGF_TYPE> for PkcsMgfType {
7979
#[derive(Debug, Clone, Copy)]
8080
/// Source of the encoding parameter when formatting a message block for the PKCS #1 OAEP
8181
/// encryption scheme
82-
pub struct PkcsOaepSource<'a>(&'a [u8]);
82+
pub struct PkcsOaepSource<'a>(Option<&'a [u8]>);
8383

8484
impl<'a> PkcsOaepSource<'a> {
8585
/// Construct an empty encoding parameter.
8686
///
8787
/// This is equivalent to `data_specified(&[])`.
8888
pub fn empty() -> Self {
89-
Self(&[])
89+
Self(None)
9090
}
9191

9292
/// Construct an encoding parameter from an array of bytes.
9393
pub fn data_specified(source_data: &'a [u8]) -> Self {
94-
Self(source_data)
94+
Self(Some(source_data))
9595
}
9696

9797
pub(crate) fn source_ptr(&self) -> *const c_void {
98-
self.0.as_ptr() as _
98+
if let Some(source_data) = self.0 {
99+
source_data.as_ptr() as _
100+
} else {
101+
std::ptr::null()
102+
}
99103
}
100104

101105
pub(crate) fn source_len(&self) -> Ulong {
102106
self.0
107+
.unwrap_or_default()
103108
.len()
104109
.try_into()
105110
.expect("usize can not fit in CK_ULONG")

cryptoki/tests/basic.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use crate::common::{get_pkcs11, SO_PIN, USER_PIN};
66
use common::init_pins;
77
use cryptoki::error::{Error, RvError};
88
use cryptoki::mechanism::aead::GcmParams;
9-
use cryptoki::mechanism::Mechanism;
9+
use cryptoki::mechanism::rsa::{PkcsMgfType, PkcsOaepParams, PkcsOaepSource};
10+
use cryptoki::mechanism::{Mechanism, MechanismType};
1011
use cryptoki::object::{Attribute, AttributeInfo, AttributeType, KeyType, ObjectClass};
1112
use cryptoki::session::{SessionState, UserType};
1213
use cryptoki::types::AuthPin;
@@ -1028,6 +1029,57 @@ fn aes_gcm_with_aad() -> TestResult {
10281029
Ok(())
10291030
}
10301031

1032+
#[test]
1033+
#[serial]
1034+
fn rsa_pkcs_oaep_empty() -> TestResult {
1035+
let (pkcs11, slot) = init_pins();
1036+
let session = pkcs11.open_rw_session(slot)?;
1037+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
1038+
1039+
let pub_key_template = [Attribute::ModulusBits(2048.into())];
1040+
let (pubkey, privkey) =
1041+
session.generate_key_pair(&Mechanism::RsaPkcsKeyPairGen, &pub_key_template, &[])?;
1042+
let oaep = PkcsOaepParams::new(
1043+
MechanismType::SHA1,
1044+
PkcsMgfType::MGF1_SHA1,
1045+
PkcsOaepSource::empty(),
1046+
);
1047+
let encrypt_mechanism: Mechanism = Mechanism::RsaPkcsOaep(oaep);
1048+
let encrypted_data = session.encrypt(&encrypt_mechanism, pubkey, b"Hello")?;
1049+
1050+
let decrypted_data = session.decrypt(&encrypt_mechanism, privkey, &encrypted_data)?;
1051+
let decrypted = String::from_utf8(decrypted_data)?;
1052+
assert_eq!("Hello", decrypted);
1053+
1054+
Ok(())
1055+
}
1056+
1057+
#[test]
1058+
#[serial]
1059+
#[ignore] // it's not clear why the test with data specified fails
1060+
fn rsa_pkcs_oaep_with_data() -> TestResult {
1061+
let (pkcs11, slot) = init_pins();
1062+
let session = pkcs11.open_rw_session(slot)?;
1063+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
1064+
1065+
let pub_key_template = [Attribute::ModulusBits(2048.into())];
1066+
let (pubkey, privkey) =
1067+
session.generate_key_pair(&Mechanism::RsaPkcsKeyPairGen, &pub_key_template, &[])?;
1068+
let oaep = PkcsOaepParams::new(
1069+
MechanismType::SHA1,
1070+
PkcsMgfType::MGF1_SHA1,
1071+
PkcsOaepSource::data_specified(&[1, 2, 3, 4, 5, 6, 7, 8]),
1072+
);
1073+
let encrypt_mechanism: Mechanism = Mechanism::RsaPkcsOaep(oaep);
1074+
let encrypted_data = session.encrypt(&encrypt_mechanism, pubkey, b"Hello")?;
1075+
1076+
let decrypted_data = session.decrypt(&encrypt_mechanism, privkey, &encrypted_data)?;
1077+
let decrypted = String::from_utf8(decrypted_data)?;
1078+
assert_eq!("Hello", decrypted);
1079+
1080+
Ok(())
1081+
}
1082+
10311083
#[test]
10321084
#[serial]
10331085
fn get_slot_event() -> TestResult {

0 commit comments

Comments
 (0)