Skip to content

Commit 42255fd

Browse files
committed
kmgmt: Update import function to support loading public keys
The RSA key from x509 certificates will be loaded using the public params modulus and exponent. The import function now is capable of loading RSA public keys. Signed-off-by: Gowtham Suresh Kumar <[email protected]>
1 parent 9f2fbad commit 42255fd

File tree

2 files changed

+91
-24
lines changed

2 files changed

+91
-24
lines changed

parsec-openssl-provider/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ openssl-errors = "0.2.0"
1818
env_logger = "0.10.2"
1919
num-traits = "0.2.18"
2020
num-derive = "0.4.2"
21+
picky-asn1-x509 = "0.12.0"
22+
picky-asn1 = "0.8.0"
23+
picky-asn1-der = "0.4.0"

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

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use crate::{
88
};
99
use parsec_openssl2::types::VOID_PTR;
1010
use parsec_openssl2::*;
11+
use picky_asn1;
12+
use picky_asn1_x509::RsaPublicKey;
13+
use std::slice;
1114
use std::sync::{Arc, RwLock};
1215

1316
pub struct ParsecProviderKeyObject {
@@ -165,6 +168,46 @@ pub unsafe extern "C" fn parsec_provider_kmgmt_has(
165168
}
166169
}
167170

171+
/*
172+
Reads the modulus and exponent components of the RSA key from the parameters and
173+
returns a public key of type RsaPublicKey
174+
*/
175+
unsafe fn parsec_rsa_set_public_params(params: *mut OSSL_PARAM) -> Result<RsaPublicKey, String> {
176+
// Read the modulus
177+
let mod_param: openssl_bindings::OSSL_PARAM =
178+
*openssl_returns_nonnull(openssl_bindings::OSSL_PARAM_locate(
179+
params,
180+
OSSL_PKEY_PARAM_RSA_N.as_ptr() as *const std::os::raw::c_char,
181+
))
182+
.map_err(|_| "OSSL_PKEY_PARAM_RSA_N not found".to_string())?;
183+
184+
let mut modulus =
185+
slice::from_raw_parts(mod_param.data as *const u8, mod_param.data_size).to_vec();
186+
//ToDo: endianess
187+
modulus.reverse();
188+
let modulus = picky_asn1::wrapper::IntegerAsn1::from_bytes_be_unsigned(modulus);
189+
190+
// Read the exponent
191+
let exp_param: openssl_bindings::OSSL_PARAM =
192+
*openssl_returns_nonnull(openssl_bindings::OSSL_PARAM_locate(
193+
params,
194+
OSSL_PKEY_PARAM_RSA_E.as_ptr() as *const std::os::raw::c_char,
195+
))
196+
.map_err(|_| "OSSL_PKEY_PARAM_RSA_E not found".to_string())?;
197+
198+
let mut exp = slice::from_raw_parts(exp_param.data as *const u8, exp_param.data_size).to_vec();
199+
//ToDo: endianess
200+
exp.reverse();
201+
let exp = picky_asn1::wrapper::IntegerAsn1::from_bytes_be_unsigned(exp);
202+
203+
// Create a public key and return
204+
let public_key = RsaPublicKey {
205+
modulus: modulus,
206+
public_exponent: exp,
207+
};
208+
Ok(public_key)
209+
}
210+
168211
/*
169212
should import data indicated by selection into keydata with values taken from the OSSL_PARAM array params
170213
*/
@@ -173,42 +216,63 @@ pub unsafe extern "C" fn parsec_provider_kmgmt_import(
173216
selection: std::os::raw::c_int,
174217
params: *mut OSSL_PARAM,
175218
) -> std::os::raw::c_int {
176-
if selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS as std::os::raw::c_int != 0 {
177-
let result = super::r#catch(Some(|| super::Error::PROVIDER_KEYMGMT_IMPORT), || {
178-
Arc::increment_strong_count(keydata as *const RwLock<ParsecProviderKeyObject>);
179-
let key_data = Arc::from_raw(keydata as *const RwLock<ParsecProviderKeyObject>);
180-
let param: openssl_bindings::OSSL_PARAM =
181-
*openssl_returns_nonnull(openssl_bindings::OSSL_PARAM_locate(
182-
params,
183-
PARSEC_PROVIDER_KEY_NAME.as_ptr() as *const std::os::raw::c_char,
184-
))?;
185-
219+
let result = super::r#catch(Some(|| super::Error::PROVIDER_KEYMGMT_IMPORT), || {
220+
Arc::increment_strong_count(keydata as *const RwLock<ParsecProviderKeyObject>);
221+
let key_data = Arc::from_raw(keydata as *const RwLock<ParsecProviderKeyObject>);
222+
let mut writer_key_data = key_data.write().unwrap();
223+
224+
let provider_key_name = openssl_returns_nonnull(openssl_bindings::OSSL_PARAM_locate(
225+
params,
226+
PARSEC_PROVIDER_KEY_NAME.as_ptr() as *const std::os::raw::c_char,
227+
));
228+
229+
if (selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS as std::os::raw::c_int != 0)
230+
&& provider_key_name.is_ok()
231+
{
232+
let name_param = *provider_key_name.unwrap();
186233
let key_name = std::str::from_utf8_unchecked(core::slice::from_raw_parts(
187-
param.data as *mut u8,
188-
param.data_size,
234+
name_param.data as *mut u8,
235+
name_param.data_size,
189236
));
190237

191-
let reader_key_data = key_data.read().unwrap();
192-
let keys = reader_key_data
238+
let keys = writer_key_data
193239
.provctx
194240
.get_client()
195241
.list_keys()
196242
.map_err(|_| "Failed to list Parsec Provider's Keys".to_string())?;
197243

198244
if keys.iter().any(|kinfo| kinfo.name == key_name) {
199-
Ok(OPENSSL_SUCCESS)
245+
let key_name: &mut [u8] = core::slice::from_raw_parts_mut(
246+
name_param.data as *mut u8,
247+
name_param.data_size,
248+
);
249+
let key_name = std::str::from_utf8(key_name)?;
250+
writer_key_data.key_name = Some(key_name.to_string());
251+
252+
let rsa_bytes = writer_key_data
253+
.provctx
254+
.get_client()
255+
.psa_export_public_key(key_name)
256+
.map_err(|e| format!("Parsec Client failed to sign: {:?}", e))?;
257+
let public_key: RsaPublicKey = picky_asn1_der::from_bytes(&rsa_bytes)
258+
.map_err(|_| "Failed to parse RsaPublicKey data".to_string())?;
259+
writer_key_data.rsa_key = Some(public_key);
200260
} else {
201-
Err("Specified Key not found in the Parsec Provider".into())
261+
return Err("Invalid key name".to_string().into());
202262
}
203-
});
204-
match result {
205-
// Right now, settable params are the same as the import types, so it's ok to use this
206-
// function
207-
Ok(_) => parsec_provider_kmgmt_set_params(keydata, params),
208-
Err(()) => OPENSSL_ERROR,
263+
return Ok(OPENSSL_SUCCESS);
209264
}
210-
} else {
211-
OPENSSL_SUCCESS
265+
266+
if selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY as std::os::raw::c_int != 0 {
267+
let rsa_key = parsec_rsa_set_public_params(params)
268+
.map_err(|_| "Failed to set RSA public keys".to_string())?;
269+
writer_key_data.rsa_key = Some(rsa_key);
270+
}
271+
Ok(OPENSSL_SUCCESS)
272+
});
273+
match result {
274+
Ok(_) => OPENSSL_SUCCESS,
275+
Err(()) => OPENSSL_ERROR,
212276
}
213277
}
214278

0 commit comments

Comments
 (0)