|  | 
| 4 | 4 | use crate::keymgmt::ParsecProviderKeyObject; | 
| 5 | 5 | use crate::openssl_bindings::{ | 
| 6 | 6 |     OSSL_ALGORITHM, OSSL_DISPATCH, OSSL_FUNC_SIGNATURE_FREECTX, OSSL_FUNC_SIGNATURE_NEWCTX, | 
| 7 |  | -    OSSL_FUNC_SIGNATURE_SIGN_INIT, OSSL_PARAM, | 
|  | 7 | +    OSSL_FUNC_SIGNATURE_SIGN, OSSL_FUNC_SIGNATURE_SIGN_INIT, OSSL_PARAM, | 
| 8 | 8 | }; | 
| 9 | 9 | use crate::{ | 
| 10 | 10 |     PARSEC_PROVIDER_DESCRIPTION_ECDSA, PARSEC_PROVIDER_DESCRIPTION_RSA, | 
| 11 | 11 |     PARSEC_PROVIDER_DFLT_PROPERTIES, PARSEC_PROVIDER_ECDSA_NAME, PARSEC_PROVIDER_RSA_NAME, | 
| 12 | 12 | }; | 
|  | 13 | +use parsec_client::core::interface::operations::psa_algorithm::Algorithm; | 
|  | 14 | +use parsec_client::core::interface::operations::psa_key_attributes::{Attributes, EccFamily, Type}; | 
| 13 | 15 | use parsec_openssl2::types::VOID_PTR; | 
| 14 | 16 | use parsec_openssl2::*; | 
| 15 | 17 | 
 | 
| @@ -97,20 +99,136 @@ unsafe extern "C" fn parsec_provider_signature_sign_init( | 
| 97 | 99 |     } | 
| 98 | 100 | } | 
| 99 | 101 | 
 | 
|  | 102 | +fn get_signature_len(key_attrs: Attributes) -> Result<usize, String> { | 
|  | 103 | +    match key_attrs.key_type { | 
|  | 104 | +        Type::RsaKeyPair => Ok(key_attrs.bits / 8), | 
|  | 105 | +        Type::EccKeyPair { | 
|  | 106 | +            curve_family: EccFamily::SecpR1, | 
|  | 107 | +        } => { | 
|  | 108 | +            let size_times_two: usize = key_attrs.bits * 2; | 
|  | 109 | +            Ok(size_times_two.div_ceil(8)) | 
|  | 110 | +        } | 
|  | 111 | +        _ => Err("Key type not recognized".to_string()), | 
|  | 112 | +    } | 
|  | 113 | +} | 
|  | 114 | + | 
|  | 115 | +/* | 
|  | 116 | +performs the actual signing itself. A previously initialised signature context is passed in the ctx parameter. The data | 
|  | 117 | +to be signed is pointed to be the tbs parameter which is tbslen bytes long. Unless sig is NULL, the signature should be | 
|  | 118 | +written to the location pointed to by the sig parameter and it should not exceed sigsize bytes in length. The length of | 
|  | 119 | +the signature should be written to *siglen. If sig is NULL then the maximum length of the signature should be written | 
|  | 120 | +to *siglen. | 
|  | 121 | +*/ | 
|  | 122 | +unsafe extern "C" fn parsec_provider_signature_sign( | 
|  | 123 | +    ctx: VOID_PTR, | 
|  | 124 | +    sig: *mut std::os::raw::c_uchar, | 
|  | 125 | +    siglen: *mut std::os::raw::c_uint, | 
|  | 126 | +    sigsize: std::os::raw::c_uint, | 
|  | 127 | +    tbs: *const std::os::raw::c_uchar, | 
|  | 128 | +    tbslen: std::os::raw::c_uint, | 
|  | 129 | +) -> std::os::raw::c_int { | 
|  | 130 | +    let result = super::r#catch(Some(|| super::Error::PROVIDER_SIGNATURE_SIGN), || { | 
|  | 131 | +        if ctx.is_null() || tbs.is_null() || siglen.is_null() { | 
|  | 132 | +            return Err("Received unexpected NULL pointer as an argument.".into()); | 
|  | 133 | +        } | 
|  | 134 | + | 
|  | 135 | +        Arc::increment_strong_count(ctx as *const ParsecProviderSignatureContext); | 
|  | 136 | +        let arc_sig_ctx = Arc::from_raw(ctx as *const ParsecProviderSignatureContext); | 
|  | 137 | + | 
|  | 138 | +        let keyobj = match *arc_sig_ctx.keyobj.lock().unwrap() { | 
|  | 139 | +            None => { | 
|  | 140 | +                return Err("Key Object not set. This should be done through sign_init()".into()) | 
|  | 141 | +            } | 
|  | 142 | +            Some(ref keyobj) => keyobj.clone(), | 
|  | 143 | +        }; | 
|  | 144 | + | 
|  | 145 | +        let key_name_binding = keyobj.get_key_name(); | 
|  | 146 | +        let key_name = match *key_name_binding { | 
|  | 147 | +            None => return Err("Key name not set in the Key Object".into()), | 
|  | 148 | +            Some(ref name) => name, | 
|  | 149 | +        }; | 
|  | 150 | + | 
|  | 151 | +        let key_attributes = keyobj | 
|  | 152 | +            .get_provctx() | 
|  | 153 | +            .get_client() | 
|  | 154 | +            .key_attributes(key_name) | 
|  | 155 | +            .map_err(|e| format!("Failed to get specified key's attributes: {}", e))?; | 
|  | 156 | +        let siglength = get_signature_len(key_attributes).map_err(|e| { | 
|  | 157 | +            format!( | 
|  | 158 | +                "Failed to Get correct signature length for the given key:  {}", | 
|  | 159 | +                e | 
|  | 160 | +            ) | 
|  | 161 | +        })?; | 
|  | 162 | + | 
|  | 163 | +        if sig.is_null() { | 
|  | 164 | +            *siglen = siglength as std::os::raw::c_uint; | 
|  | 165 | +            return Ok(OPENSSL_SUCCESS); | 
|  | 166 | +        } | 
|  | 167 | + | 
|  | 168 | +        if tbs.is_null() { | 
|  | 169 | +            return Err("Received unexpected NULL pointer as an argument.".into()); | 
|  | 170 | +        } | 
|  | 171 | + | 
|  | 172 | +        let tbs_slice: &[u8] = core::slice::from_raw_parts(tbs, tbslen as usize); | 
|  | 173 | + | 
|  | 174 | +        let sign_algorithm = match key_attributes.policy.permitted_algorithms { | 
|  | 175 | +            Algorithm::AsymmetricSignature(signature_algo) => signature_algo, | 
|  | 176 | +            _ => { | 
|  | 177 | +                return Err( | 
|  | 178 | +                    "Specified key does not permit the AsymmetricSignature algorithm".into(), | 
|  | 179 | +                ) | 
|  | 180 | +            } | 
|  | 181 | +        }; | 
|  | 182 | + | 
|  | 183 | +        let sign_res: Vec<u8> = keyobj | 
|  | 184 | +            .get_provctx() | 
|  | 185 | +            .get_client() | 
|  | 186 | +            .psa_sign_hash(key_name, tbs_slice, sign_algorithm) | 
|  | 187 | +            .map_err(|_| "Parsec Client failed to sign".to_string())?; | 
|  | 188 | + | 
|  | 189 | +        if sigsize >= sign_res.len() as u32 { | 
|  | 190 | +            std::ptr::copy(sign_res.as_ptr(), sig, sign_res.len()); | 
|  | 191 | +            *siglen = sign_res.len() as u32; | 
|  | 192 | +            Ok(OPENSSL_SUCCESS) | 
|  | 193 | +        } else { | 
|  | 194 | +            Err(format!( | 
|  | 195 | +                "Signature length is bigger than sigsize. Signature length: {}", | 
|  | 196 | +                sign_res.len() | 
|  | 197 | +            ) | 
|  | 198 | +            .into()) | 
|  | 199 | +        } | 
|  | 200 | +    }); | 
|  | 201 | + | 
|  | 202 | +    match result { | 
|  | 203 | +        Ok(result) => result, | 
|  | 204 | +        Err(()) => OPENSSL_ERROR, | 
|  | 205 | +    } | 
|  | 206 | +} | 
|  | 207 | + | 
| 100 | 208 | pub type SignatureNewCtxPtr = | 
| 101 | 209 |     unsafe extern "C" fn(VOID_PTR, *const std::os::raw::c_char) -> VOID_PTR; | 
| 102 | 210 | pub type SignatureFreeCtxPtr = unsafe extern "C" fn(VOID_PTR); | 
|  | 211 | +pub type SignatureSignPtr = unsafe extern "C" fn( | 
|  | 212 | +    VOID_PTR, | 
|  | 213 | +    *mut std::os::raw::c_uchar, | 
|  | 214 | +    *mut std::os::raw::c_uint, | 
|  | 215 | +    std::os::raw::c_uint, | 
|  | 216 | +    *const std::os::raw::c_uchar, | 
|  | 217 | +    std::os::raw::c_uint, | 
|  | 218 | +) -> std::os::raw::c_int; | 
| 103 | 219 | pub type SignatureSignInitPtr = | 
| 104 | 220 |     unsafe extern "C" fn(VOID_PTR, VOID_PTR, *const OSSL_PARAM) -> std::os::raw::c_int; | 
| 105 | 221 | 
 | 
| 106 | 222 | const OSSL_FUNC_SIGNATURE_NEWCTX_PTR: SignatureNewCtxPtr = parsec_provider_signature_newctx; | 
| 107 | 223 | const OSSL_FUNC_SIGNATURE_FREECTX_PTR: SignatureFreeCtxPtr = parsec_provider_signature_freectx; | 
|  | 224 | +const OSSL_FUNC_SIGNATURE_SIGN_PTR: SignatureSignPtr = parsec_provider_signature_sign; | 
| 108 | 225 | const OSSL_FUNC_SIGNATURE_SIGN_INIT_PTR: SignatureSignInitPtr = parsec_provider_signature_sign_init; | 
| 109 | 226 | 
 | 
| 110 | 227 | const PARSEC_PROVIDER_ECDSA_SIGN_IMPL: [OSSL_DISPATCH; 1] = [ossl_dispatch!()]; | 
| 111 |  | -const PARSEC_PROVIDER_RSA_SIGN_IMPL: [OSSL_DISPATCH; 4] = [ | 
|  | 228 | +const PARSEC_PROVIDER_RSA_SIGN_IMPL: [OSSL_DISPATCH; 5] = [ | 
| 112 | 229 |     unsafe { ossl_dispatch!(OSSL_FUNC_SIGNATURE_NEWCTX, OSSL_FUNC_SIGNATURE_NEWCTX_PTR) }, | 
| 113 | 230 |     unsafe { ossl_dispatch!(OSSL_FUNC_SIGNATURE_FREECTX, OSSL_FUNC_SIGNATURE_FREECTX_PTR) }, | 
|  | 231 | +    unsafe { ossl_dispatch!(OSSL_FUNC_SIGNATURE_SIGN, OSSL_FUNC_SIGNATURE_SIGN_PTR) }, | 
| 114 | 232 |     unsafe { | 
| 115 | 233 |         ossl_dispatch!( | 
| 116 | 234 |             OSSL_FUNC_SIGNATURE_SIGN_INIT, | 
|  | 
0 commit comments