|
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