diff --git a/src/ossl/rsa.rs b/src/ossl/rsa.rs index 8ab83ee..26e0636 100644 --- a/src/ossl/rsa.rs +++ b/src/ossl/rsa.rs @@ -228,12 +228,24 @@ impl RsaPKCSOperation { } } + fn get_key_size(key: &Object, info: &CK_MECHANISM_INFO) -> Result { + let modulus = key.get_attr_as_bytes(CKA_MODULUS)?; + let modulus_bits: CK_ULONG = modulus.len() as CK_ULONG * 8; + if modulus_bits < info.ulMinKeySize + || (info.ulMaxKeySize != 0 && modulus_bits > info.ulMaxKeySize) + { + return Err(CKR_KEY_SIZE_RANGE)?; + } + Ok(modulus.len()) + } + fn max_message_len( modulus: usize, mech: CK_MECHANISM_TYPE, 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)?; @@ -243,30 +255,23 @@ impl RsaPKCSOperation { } } - pub fn encrypt_new( + fn encdec_new( mech: &CK_MECHANISM, - key: &Object, - info: &CK_MECHANISM_INFO, + pubkey: Option, + privkey: Option, + keysize: usize, ) -> Result { - let modulus = key.get_attr_as_bytes(CKA_MODULUS)?; - let modulus_bits: CK_ULONG = modulus.len() as CK_ULONG * 8; - if modulus_bits < info.ulMinKeySize - || (info.ulMaxKeySize != 0 && modulus_bits > info.ulMaxKeySize) - { - return Err(CKR_KEY_SIZE_RANGE)?; - } let oaep_params = parse_oaep_params(mech)?; - let pubkey = EvpPkey::pubkey_from_object(key)?; Ok(RsaPKCSOperation { mech: mech.mechanism, max_input: Self::max_message_len( - modulus.len(), + keysize, mech.mechanism, oaep_params.hash, )?, - output_len: modulus.len(), - public_key: Some(pubkey), - private_key: None, + output_len: keysize, + public_key: pubkey, + private_key: privkey, finalized: false, in_use: false, sigctx: None, @@ -277,71 +282,49 @@ impl RsaPKCSOperation { }) } - pub fn decrypt_new( + pub fn encrypt_new( mech: &CK_MECHANISM, key: &Object, info: &CK_MECHANISM_INFO, ) -> Result { - let modulus = key.get_attr_as_bytes(CKA_MODULUS)?; - let modulus_bits: CK_ULONG = modulus.len() as CK_ULONG * 8; - if modulus_bits < info.ulMinKeySize - || (info.ulMaxKeySize != 0 && modulus_bits > info.ulMaxKeySize) - { - return Err(CKR_KEY_SIZE_RANGE)?; - } - let oaep_params = parse_oaep_params(mech)?; + let keysize = Self::get_key_size(key, info)?; let pubkey = EvpPkey::pubkey_from_object(key)?; - let privkey = EvpPkey::privkey_from_object(key)?; - Ok(RsaPKCSOperation { - mech: mech.mechanism, - max_input: modulus.len(), - output_len: Self::max_message_len( - modulus.len(), - mech.mechanism, - oaep_params.hash, - )?, - public_key: Some(pubkey), - private_key: Some(privkey), - finalized: false, - in_use: false, - sigctx: None, - pss: no_pss_params(), - oaep: oaep_params, - #[cfg(feature = "fips")] - fips_approved: None, - }) + Self::encdec_new(mech, Some(pubkey), None, keysize) } - pub fn sign_new( + pub fn decrypt_new( mech: &CK_MECHANISM, key: &Object, info: &CK_MECHANISM_INFO, ) -> Result { - let modulus = key.get_attr_as_bytes(CKA_MODULUS)?; - let modulus_bits: CK_ULONG = modulus.len() as CK_ULONG * 8; - if modulus_bits < info.ulMinKeySize - || (info.ulMaxKeySize != 0 && modulus_bits > info.ulMaxKeySize) - { - return Err(CKR_KEY_SIZE_RANGE)?; - } - - let pss_params = parse_pss_params(mech)?; + let keysize = Self::get_key_size(key, info)?; let pubkey = EvpPkey::pubkey_from_object(key)?; let privkey = EvpPkey::privkey_from_object(key)?; + Self::encdec_new(mech, Some(pubkey), Some(privkey), keysize) + } + + fn sigver_new( + mech: &CK_MECHANISM, + pubkey: Option, + privkey: Option, + keysize: usize, + ) -> Result { + let pss_params = parse_pss_params(mech)?; Ok(RsaPKCSOperation { mech: mech.mechanism, max_input: match mech.mechanism { - CKM_RSA_PKCS => modulus.len() - 11, + CKM_RSA_X_509 => keysize, + CKM_RSA_PKCS => keysize - 11, CKM_RSA_PKCS_PSS => Self::hash_len(pss_params.hash)?, _ => 0, }, - output_len: modulus.len(), - public_key: Some(pubkey), - private_key: Some(privkey), + output_len: keysize, + public_key: pubkey, + private_key: privkey, finalized: false, in_use: false, sigctx: match mech.mechanism { - CKM_RSA_PKCS => None, + CKM_RSA_X_509 | CKM_RSA_PKCS => None, #[cfg(feature = "fips")] _ => Some(ProviderSignatureCtx::new(name_as_char(RSA_NAME))?), #[cfg(not(feature = "fips"))] @@ -354,44 +337,25 @@ impl RsaPKCSOperation { }) } - pub fn verify_new( + pub fn sign_new( mech: &CK_MECHANISM, key: &Object, info: &CK_MECHANISM_INFO, ) -> Result { - let modulus = key.get_attr_as_bytes(CKA_MODULUS)?; - let modulus_bits: CK_ULONG = modulus.len() as CK_ULONG * 8; - if modulus_bits < info.ulMinKeySize - || (info.ulMaxKeySize != 0 && modulus_bits > info.ulMaxKeySize) - { - return Err(CKR_KEY_SIZE_RANGE)?; - } + let keysize = Self::get_key_size(key, info)?; + let pubkey = EvpPkey::pubkey_from_object(key)?; + let privkey = EvpPkey::privkey_from_object(key)?; + Self::sigver_new(mech, Some(pubkey), Some(privkey), keysize) + } - let pss_params = parse_pss_params(mech)?; + pub fn verify_new( + mech: &CK_MECHANISM, + key: &Object, + info: &CK_MECHANISM_INFO, + ) -> Result { + let keysize = Self::get_key_size(key, info)?; let pubkey = EvpPkey::pubkey_from_object(key)?; - Ok(RsaPKCSOperation { - mech: mech.mechanism, - max_input: match mech.mechanism { - CKM_RSA_PKCS => modulus.len() - 11, - _ => 0, - }, - output_len: modulus.len(), - public_key: Some(pubkey), - private_key: None, - 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"))] - _ => Some(EvpMdCtx::new()?), - }, - pss: pss_params, - oaep: no_oaep_params(), - #[cfg(feature = "fips")] - fips_approved: None, - }) + Self::sigver_new(mech, Some(pubkey), None, keysize) } pub fn generate_keypair( @@ -849,10 +813,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 +885,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 +990,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 681935a..4e667c3 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 8778a1d..b11795a 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(); }