Skip to content

Commit 5db2815

Browse files
keymgmt: Implement ECDSA OSSL_FUNC_KEYMGMT_IMPORT
As EcPoint does not implement the clone trait, the current implementation of keymgmt duplication does not work. Signed-off-by: Tomás González <[email protected]>
1 parent d95190b commit 5db2815

File tree

2 files changed

+122
-6
lines changed

2 files changed

+122
-6
lines changed

parsec-openssl-provider/src/keymgmt/mod.rs

Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub struct ParsecProviderKeyObject {
1717
provctx: Arc<ParsecProviderContext>,
1818
key_name: Option<String>,
1919
rsa_key: Option<RsaPublicKey>,
20+
ecdsa_key: Option<openssl::ec::EcPoint>,
2021
}
2122

2223
impl Clone for ParsecProviderKeyObject {
@@ -25,6 +26,7 @@ impl Clone for ParsecProviderKeyObject {
2526
provctx: self.provctx.clone(),
2627
key_name: self.key_name.clone(),
2728
rsa_key: self.rsa_key.clone(),
29+
ecdsa_key: None,
2830
}
2931
}
3032
}
@@ -35,6 +37,7 @@ impl ParsecProviderKeyObject {
3537
provctx: provctx.clone(),
3638
key_name: None,
3739
rsa_key: None,
40+
ecdsa_key: None,
3841
}
3942
}
4043

@@ -49,6 +52,11 @@ impl ParsecProviderKeyObject {
4952
pub fn get_rsa_key(&self) -> &Option<RsaPublicKey> {
5053
&self.rsa_key
5154
}
55+
56+
#[allow(dead_code)]
57+
pub fn get_ecdsa_key(&self) -> &Option<openssl::ec::EcPoint> {
58+
&self.ecdsa_key
59+
}
5260
}
5361

5462
/*
@@ -261,6 +269,113 @@ unsafe fn parsec_rsa_set_public_params(params: *mut OSSL_PARAM) -> Result<RsaPub
261269
Ok(public_key)
262270
}
263271

272+
/*
273+
returns a vector containing an ECDSA public key in form of a vector (Octect string into a vector)
274+
*/
275+
unsafe fn parsec_ecdsa_set_public_params(
276+
params: *mut OSSL_PARAM,
277+
) -> Result<openssl::ec::EcPoint, String> {
278+
let octect_param: openssl_bindings::OSSL_PARAM =
279+
*openssl_returns_nonnull(openssl_bindings::OSSL_PARAM_locate(
280+
params,
281+
OSSL_PKEY_PARAM_PUB_KEY.as_ptr() as *const std::os::raw::c_char,
282+
))
283+
.map_err(|e| format!("Failed to set ECDSA public params (OctetString): {}", e))?;
284+
285+
let octect =
286+
slice::from_raw_parts(octect_param.data as *const u8, octect_param.data_size).to_vec();
287+
288+
let curve = EcCurve::NistP256.as_nid();
289+
let mut group =
290+
openssl::ec::EcGroup::from_curve_name(curve).map_err(|_| "Can't find curve".to_string())?;
291+
group.set_asn1_flag(openssl::ec::Asn1Flag::NAMED_CURVE);
292+
293+
let mut big_num_context =
294+
openssl::bn::BigNumContext::new().map_err(|_| "Can't create context".to_string())?;
295+
let point = openssl::ec::EcPoint::from_bytes(&group, &octect, &mut big_num_context)
296+
.map_err(|e| format!("Can't create ECPOINT: {}", e))?;
297+
298+
Ok(point)
299+
}
300+
301+
/*
302+
should import data indicated by selection into keydata with values taken from the OSSL_PARAM array params
303+
*/
304+
pub unsafe extern "C" fn parsec_provider_ecdsa_kmgmt_import(
305+
keydata: VOID_PTR,
306+
selection: std::os::raw::c_int,
307+
params: *mut OSSL_PARAM,
308+
) -> std::os::raw::c_int {
309+
let result = super::r#catch(Some(|| super::Error::PROVIDER_KEYMGMT_ECDSA_IMPORT), || {
310+
Arc::increment_strong_count(keydata as *const RwLock<ParsecProviderKeyObject>);
311+
let key_data = Arc::from_raw(keydata as *const RwLock<ParsecProviderKeyObject>);
312+
let mut writer_key_data = key_data.write().unwrap();
313+
314+
let provider_key_name = openssl_returns_nonnull(openssl_bindings::OSSL_PARAM_locate(
315+
params,
316+
PARSEC_PROVIDER_KEY_NAME.as_ptr() as *const std::os::raw::c_char,
317+
));
318+
319+
if (selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS as std::os::raw::c_int != 0)
320+
&& provider_key_name.is_ok()
321+
{
322+
let name_param = *provider_key_name.unwrap();
323+
let key_name = std::str::from_utf8_unchecked(core::slice::from_raw_parts(
324+
name_param.data as *mut u8,
325+
name_param.data_size,
326+
));
327+
328+
let keys = writer_key_data
329+
.provctx
330+
.get_client()
331+
.list_keys()
332+
.map_err(|_| "Failed to list Parsec Provider's Keys".to_string())?;
333+
334+
if keys.iter().any(|kinfo| kinfo.name == key_name) {
335+
let key_name: &mut [u8] = core::slice::from_raw_parts_mut(
336+
name_param.data as *mut u8,
337+
name_param.data_size,
338+
);
339+
340+
writer_key_data.key_name = Some(std::str::from_utf8(key_name)?.to_string());
341+
342+
let curve = EcCurve::NistP256.as_nid();
343+
let mut group = openssl::ec::EcGroup::from_curve_name(curve)
344+
.map_err(|_| "Failed to list Parsec Provider's Keys".to_string())?;
345+
group.set_asn1_flag(openssl::ec::Asn1Flag::NAMED_CURVE);
346+
347+
let point = writer_key_data
348+
.provctx
349+
.get_client()
350+
.psa_export_public_key(
351+
std::str::from_utf8(key_name).map_err(|e| format!("{:?}", e))?,
352+
)
353+
.map_err(|e| {
354+
format!("Parsec Client failed to export public key: {:?}", e)
355+
})?;
356+
let mut big_num_context = openssl::bn::BigNumContext::new()?;
357+
let point =
358+
openssl::ec::EcPoint::from_bytes(&group, &point, &mut big_num_context)?;
359+
writer_key_data.ecdsa_key = Some(point);
360+
} else {
361+
return Err("Invalid key name".to_string().into());
362+
}
363+
return Ok(OPENSSL_SUCCESS);
364+
}
365+
366+
if selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY as std::os::raw::c_int != 0 {
367+
let ecdsa_key = parsec_ecdsa_set_public_params(params)
368+
.map_err(|e| format!("Failed to set ECDSA public keys: {}", e))?;
369+
writer_key_data.ecdsa_key = Some(ecdsa_key);
370+
}
371+
Ok(OPENSSL_SUCCESS)
372+
});
373+
match result {
374+
Ok(_) => OPENSSL_SUCCESS,
375+
Err(()) => OPENSSL_ERROR,
376+
}
377+
}
378+
264379
/*
265380
should import data indicated by selection into keydata with values taken from the OSSL_PARAM array params
266381
*/
@@ -269,7 +384,7 @@ pub unsafe extern "C" fn parsec_provider_kmgmt_import(
269384
selection: std::os::raw::c_int,
270385
params: *mut OSSL_PARAM,
271386
) -> std::os::raw::c_int {
272-
let result = super::r#catch(Some(|| super::Error::PROVIDER_KEYMGMT_IMPORT), || {
387+
let result = super::r#catch(Some(|| super::Error::PROVIDER_KEYMGMT_RSA_IMPORT), || {
273388
Arc::increment_strong_count(keydata as *const RwLock<ParsecProviderKeyObject>);
274389
let key_data = Arc::from_raw(keydata as *const RwLock<ParsecProviderKeyObject>);
275390
let mut writer_key_data = key_data.write().unwrap();
@@ -306,7 +421,7 @@ pub unsafe extern "C" fn parsec_provider_kmgmt_import(
306421
.provctx
307422
.get_client()
308423
.psa_export_public_key(key_name)
309-
.map_err(|e| format!("Parsec Client failed to sign: {:?}", e))?;
424+
.map_err(|e| format!("Parsec Client failed to export public key: {:?}", e))?;
310425
let public_key: RsaPublicKey = picky_asn1_der::from_bytes(&rsa_bytes)
311426
.map_err(|_| "Failed to parse RsaPublicKey data".to_string())?;
312427
writer_key_data.rsa_key = Some(public_key);
@@ -481,6 +596,7 @@ const OSSL_FUNC_KEYMGMT_NEW_PTR: KeyMgmtNewPtr = parsec_provider_kmgmt_new;
481596
const OSSL_FUNC_KEYMGMT_FREE_PTR: KeyMgmtFreePtr = parsec_provider_kmgmt_free;
482597
const OSSL_FUNC_KEYMGMT_HAS_PTR: KeyMgmtHasPtr = parsec_provider_kmgmt_has;
483598
const OSSL_FUNC_KEYMGMT_IMPORT_PTR: KeyMgmtImportPtr = parsec_provider_kmgmt_import;
599+
const OSSL_FUNC_KEYMGMT_ECDSA_IMPORT_PTR: KeyMgmtImportPtr = parsec_provider_ecdsa_kmgmt_import;
484600
const OSSL_FUNC_KEYMGMT_IMPORT_TYPES_PTR: KeyMgmtImportTypesPtr =
485601
parsec_provider_kmgmt_import_types;
486602
const OSSL_FUNC_KEYMGMT_ECDSA_IMPORT_TYPES_PTR: KeyMgmtImportTypesPtr =
@@ -540,12 +656,11 @@ const PARSEC_PROVIDER_KEYMGMT_IMPL: [OSSL_DISPATCH; 13] = [
540656
ossl_dispatch!(),
541657
];
542658

543-
const PARSEC_PROVIDER_KEYMGMT_ECDSA_IMPL: [OSSL_DISPATCH; 13] = [
544-
unsafe { ossl_dispatch!(OSSL_FUNC_KEYMGMT_DUP, OSSL_FUNC_KEYMGMT_DUP_PTR) },
659+
const PARSEC_PROVIDER_KEYMGMT_ECDSA_IMPL: [OSSL_DISPATCH; 12] = [
545660
unsafe { ossl_dispatch!(OSSL_FUNC_KEYMGMT_NEW, OSSL_FUNC_KEYMGMT_NEW_PTR) },
546661
unsafe { ossl_dispatch!(OSSL_FUNC_KEYMGMT_FREE, OSSL_FUNC_KEYMGMT_FREE_PTR) },
547662
unsafe { ossl_dispatch!(OSSL_FUNC_KEYMGMT_HAS, OSSL_FUNC_KEYMGMT_HAS_PTR) },
548-
unsafe { ossl_dispatch!(OSSL_FUNC_KEYMGMT_IMPORT, OSSL_FUNC_KEYMGMT_IMPORT_PTR) },
663+
unsafe { ossl_dispatch!(OSSL_FUNC_KEYMGMT_IMPORT, OSSL_FUNC_KEYMGMT_ECDSA_IMPORT_PTR) },
549664
unsafe {
550665
ossl_dispatch!(
551666
OSSL_FUNC_KEYMGMT_IMPORT_TYPES,

parsec-openssl-provider/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ openssl_errors::openssl_errors! {
112112
PROVIDER_GETTABLE_PARAMS("parsec_provider_gettable_params");
113113
PROVIDER_GET_PARAMS("parsec_provider_get_params");
114114
PROVIDER_KEYMGMT_HAS("parsec_provider_kmgmt_has");
115-
PROVIDER_KEYMGMT_IMPORT("parsec_provider_kmgmt_import");
115+
PROVIDER_KEYMGMT_RSA_IMPORT("parsec_provider_kmgmt_rsa_import");
116+
PROVIDER_KEYMGMT_ECDSA_IMPORT("parsec_provider_kmgmt_ecdsa_import");
116117
PROVIDER_KEYMGMT_MATCH("parsec_provider_kmgmt_match");
117118
PROVIDER_KEYMGMT_SET_PARAMS("parsec_provider_kmgmt_set_params");
118119
PROVIDER_KEYMGMT_GET_PARAMS("parsec_provider_kmgmt_get_params");

0 commit comments

Comments
 (0)