From 9dddc4f13fb10ec0d12073066da44a32901cc5cf Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 10 Dec 2024 17:44:27 -0500 Subject: [PATCH] Add support for raw RSA signatures. Signed-off-by: Simo Sorce --- src/ossl/rsa.rs | 88 ++++++++++++++++++++++++++---------------------- src/rsa.rs | 25 +++++++------- src/tests/rsa.rs | 64 +++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 52 deletions(-) diff --git a/src/ossl/rsa.rs b/src/ossl/rsa.rs index 8ab83ee7..cf1a8b42 100644 --- a/src/ossl/rsa.rs +++ b/src/ossl/rsa.rs @@ -234,6 +234,7 @@ impl RsaPKCSOperation { hash: CK_MECHANISM_TYPE, ) -> Result { match mech { + CKM_RSA_X_509 => Ok(modulus), CKM_RSA_PKCS => Ok(modulus - 11), CKM_RSA_PKCS_OAEP => { let hs = Self::hash_len(hash)?; @@ -331,6 +332,7 @@ impl RsaPKCSOperation { Ok(RsaPKCSOperation { mech: mech.mechanism, max_input: match mech.mechanism { + CKM_RSA_X_509 => modulus.len(), CKM_RSA_PKCS => modulus.len() - 11, CKM_RSA_PKCS_PSS => Self::hash_len(pss_params.hash)?, _ => 0, @@ -341,7 +343,6 @@ impl RsaPKCSOperation { finalized: false, in_use: false, sigctx: match mech.mechanism { - CKM_RSA_PKCS => None, #[cfg(feature = "fips")] _ => Some(ProviderSignatureCtx::new(name_as_char(RSA_NAME))?), #[cfg(not(feature = "fips"))] @@ -372,6 +373,7 @@ impl RsaPKCSOperation { Ok(RsaPKCSOperation { mech: mech.mechanism, max_input: match mech.mechanism { + CKM_RSA_X_509 => modulus.len(), CKM_RSA_PKCS => modulus.len() - 11, _ => 0, }, @@ -381,7 +383,6 @@ impl RsaPKCSOperation { finalized: false, in_use: false, sigctx: match mech.mechanism { - CKM_RSA_PKCS => None, #[cfg(feature = "fips")] _ => Some(ProviderSignatureCtx::new(name_as_char(RSA_NAME))?), #[cfg(not(feature = "fips"))] @@ -849,10 +850,10 @@ impl Sign for RsaPKCSOperation { return Err(CKR_OPERATION_NOT_INITIALIZED)?; } match self.mech { - CKM_RSA_PKCS | CKM_RSA_PKCS_PSS => { + CKM_RSA_X_509 | CKM_RSA_PKCS | CKM_RSA_PKCS_PSS => { self.finalized = true; if match self.mech { - CKM_RSA_PKCS => data.len() > self.max_input, + CKM_RSA_X_509 | CKM_RSA_PKCS => data.len() > self.max_input, CKM_RSA_PKCS_PSS => data.len() != self.max_input, _ => return Err(CKR_GENERAL_ERROR)?, } { @@ -921,8 +922,11 @@ impl Sign for RsaPKCSOperation { return Err(CKR_OPERATION_NOT_INITIALIZED)?; } if !self.in_use { - if self.mech == CKM_RSA_PKCS || self.mech == CKM_RSA_PKCS_PSS { - return Err(CKR_OPERATION_NOT_INITIALIZED)?; + match self.mech { + CKM_RSA_X_509 | CKM_RSA_PKCS | CKM_RSA_PKCS_PSS => { + return Err(CKR_OPERATION_NOT_INITIALIZED)?; + } + _ => (), } self.in_use = true; @@ -1023,43 +1027,47 @@ impl Verify for RsaPKCSOperation { if self.finalized { return Err(CKR_OPERATION_NOT_INITIALIZED)?; } - if self.mech == CKM_RSA_PKCS { - self.finalized = true; - if data.len() > self.max_input { - return Err(CKR_DATA_LEN_RANGE)?; - } - if signature.len() != self.output_len { - return Err(CKR_GENERAL_ERROR)?; - } - let mut ctx = some_or_err!(mut self.public_key).new_ctx()?; - let res = unsafe { EVP_PKEY_verify_init(ctx.as_mut_ptr()) }; - if res != 1 { - return Err(CKR_DEVICE_ERROR)?; - } - let params = self.rsa_sig_params(); - let res = unsafe { - EVP_PKEY_CTX_set_params(ctx.as_mut_ptr(), params.as_ptr()) - }; - if res != 1 { - return Err(CKR_DEVICE_ERROR)?; - } + match self.mech { + CKM_RSA_X_509 | CKM_RSA_PKCS | CKM_RSA_PKCS_PSS => { + self.finalized = true; + if data.len() > self.max_input { + return Err(CKR_DATA_LEN_RANGE)?; + } + if signature.len() != self.output_len { + return Err(CKR_GENERAL_ERROR)?; + } + let mut ctx = some_or_err!(mut self.public_key).new_ctx()?; + let res = unsafe { EVP_PKEY_verify_init(ctx.as_mut_ptr()) }; + if res != 1 { + return Err(CKR_DEVICE_ERROR)?; + } + let params = self.rsa_sig_params(); + let res = unsafe { + EVP_PKEY_CTX_set_params(ctx.as_mut_ptr(), params.as_ptr()) + }; + if res != 1 { + return Err(CKR_DEVICE_ERROR)?; + } - let res = unsafe { - EVP_PKEY_verify( - ctx.as_mut_ptr(), - signature.as_ptr(), - signature.len(), - data.as_ptr(), - data.len(), - ) - }; - if res != 1 { - return Err(CKR_SIGNATURE_INVALID)?; + let res = unsafe { + EVP_PKEY_verify( + ctx.as_mut_ptr(), + signature.as_ptr(), + signature.len(), + data.as_ptr(), + data.len(), + ) + }; + if res != 1 { + return Err(CKR_SIGNATURE_INVALID)?; + } + Ok(()) + } + _ => { + self.verify_update(data)?; + self.verify_final(signature) } - return Ok(()); } - self.verify_update(data)?; - self.verify_final(signature) } fn verify_update(&mut self, data: &[u8]) -> Result<()> { diff --git a/src/rsa.rs b/src/rsa.rs index 681935a7..4e667c3b 100644 --- a/src/rsa.rs +++ b/src/rsa.rs @@ -374,18 +374,19 @@ impl RsaPKCSMechanism { } pub fn register_mechanisms(mechs: &mut Mechanisms) { - mechs.add_mechanism( - CKM_RSA_PKCS, - Self::new_mechanism( - CKF_ENCRYPT - | CKF_DECRYPT - | CKF_SIGN - | CKF_VERIFY - | CKF_WRAP - | CKF_UNWRAP, - ), - ); - + for ckm in &[CKM_RSA_X_509, CKM_RSA_PKCS] { + mechs.add_mechanism( + *ckm, + Self::new_mechanism( + CKF_ENCRYPT + | CKF_DECRYPT + | CKF_SIGN + | CKF_VERIFY + | CKF_WRAP + | CKF_UNWRAP, + ), + ); + } for ckm in &[ CKM_SHA1_RSA_PKCS, CKM_SHA224_RSA_PKCS, diff --git a/src/tests/rsa.rs b/src/tests/rsa.rs index 8778a1db..b11795af 100644 --- a/src/tests/rsa.rs +++ b/src/tests/rsa.rs @@ -391,5 +391,69 @@ fn test_rsa_operations() { ); assert_eq!(ret, CKR_OK); + #[cfg(not(feature = "fips"))] + { + /* RSA PKCS Sig */ + let pri_key_handle = match get_test_key_handle( + session, + "SigVer15_186-3.rsp [mod = 2048]", + CKO_PRIVATE_KEY, + ) { + Ok(k) => k, + Err(e) => panic!("{}", e), + }; + let pub_key_handle = match get_test_key_handle( + session, + "SigVer15_186-3.rsp [mod = 2048]", + CKO_PUBLIC_KEY, + ) { + Ok(k) => k, + Err(e) => panic!("{}", e), + }; + + /* Test Raw Signature */ + let mut mechanism: CK_MECHANISM = CK_MECHANISM { + mechanism: CKM_RSA_X_509, + pParameter: std::ptr::null_mut(), + ulParameterLen: 0, + }; + + let ret = fn_sign_init(session, &mut mechanism, pri_key_handle); + assert_eq!(ret, CKR_OK); + + let mut sig_len: CK_ULONG = 0; + let data = "check"; + let ret = fn_sign( + session, + byte_ptr!(data.as_ptr()), + data.len() as CK_ULONG, + std::ptr::null_mut(), + &mut sig_len, + ); + assert_eq!(ret, CKR_OK); + + let mut signature = vec![0; sig_len as usize]; + let ret = fn_sign( + session, + byte_ptr!(data.as_ptr()), + data.len() as CK_ULONG, + signature.as_mut_ptr(), + &mut sig_len, + ); + assert_eq!(ret, CKR_OK); + + let ret = fn_verify_init(session, &mut mechanism, pub_key_handle); + assert_eq!(ret, CKR_OK); + + let ret = fn_verify( + session, + byte_ptr!(data.as_ptr()), + data.len() as CK_ULONG, + byte_ptr!(signature.as_ptr()), + signature.len() as CK_ULONG, + ); + assert_eq!(ret, CKR_OK); + } + testtokn.finalize(); }