From 9f2c9f1a8b96524c57e5ff9b54ed9f8962b7d24a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 19 Nov 2024 14:25:20 -0500 Subject: [PATCH 1/6] Add some more generic error handling This allows to map errors when we want to return a generic failure instead of a specific code. Signed-off-by: Simo Sorce --- src/error.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/error.rs b/src/error.rs index 357098e5..c8f8858a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,6 +6,7 @@ use std::fmt; use crate::interface; +use asn1; use serde_json; pub type Result = std::result::Result; @@ -147,6 +148,8 @@ impl fmt::Display for Error { } } +impl std::error::Error for Error {} + impl From for Error { fn from(error: std::io::Error) -> Error { Error::other_error(error) @@ -177,6 +180,18 @@ impl From for Error { } } +impl From for Error { + fn from(error: asn1::ParseError) -> Error { + Error::other_error(error) + } +} + +impl From for Error { + fn from(error: asn1::WriteError) -> Error { + Error::other_error(error) + } +} + #[macro_export] macro_rules! some_or_err { ($action:expr) => { @@ -194,3 +209,17 @@ macro_rules! some_or_err { } }; } + +pub fn general_error(error: E) -> Error +where + E: Into>, +{ + Error::ck_rv_from_error(interface::CKR_GENERAL_ERROR, error) +} + +pub fn device_error(error: E) -> Error +where + E: Into>, +{ + Error::ck_rv_from_error(interface::CKR_DEVICE_ERROR, error) +} From ce7aa739aa6ae35052c2b8d64ba763dc6ff5f1cc Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 19 Nov 2024 16:36:05 -0500 Subject: [PATCH 2/6] More ergonomic conversion from objects to EvpPkey Change how EvpPkeys are obtained from Objects via helper methods on the EvpPkey object itself, as this looks like a more natural interface. It also unifies how this is done across all the Asymmetric Key algorithms so that the code looks more uniform. Signed-off-by: Simo Sorce --- src/ossl/common.rs | 68 ++++++++++++++++++++++ src/ossl/ec_montgomery.rs | 77 +++++++++++-------------- src/ossl/ecc.rs | 68 +++++++++++----------- src/ossl/ecdh.rs | 64 ++++++++------------- src/ossl/eddsa.rs | 79 ++++++++++++------------- src/ossl/rsa.rs | 118 ++++++++++++++++++++------------------ 6 files changed, 260 insertions(+), 214 deletions(-) diff --git a/src/ossl/common.rs b/src/ossl/common.rs index 014c6422..57d757c3 100644 --- a/src/ossl/common.rs +++ b/src/ossl/common.rs @@ -6,10 +6,20 @@ use std::ffi::{c_char, c_int, c_uint, c_void}; use crate::error::Result; use crate::interface::*; +use crate::object; use crate::ossl::bindings::*; use crate::ossl::get_libctx; use crate::{byte_ptr, void_ptr}; +#[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] +use crate::ossl::ec_montgomery as ecm; +#[cfg(feature = "ecc")] +use crate::ossl::ecc; +#[cfg(all(feature = "eddsa", not(feature = "fips")))] +use crate::ossl::eddsa; +#[cfg(feature = "rsa")] +use crate::ossl::rsa; + use zeroize::Zeroize; macro_rules! ptr_wrapper_struct { @@ -261,6 +271,38 @@ impl EvpPkey { pub fn as_mut_ptr(&mut self) -> *mut EVP_PKEY { self.ptr } + + fn from_object( + obj: &object::Object, + class: CK_OBJECT_CLASS, + ) -> Result { + let key_class = match class { + CKO_PUBLIC_KEY => EVP_PKEY_PUBLIC_KEY, + CKO_PRIVATE_KEY => EVP_PKEY_PRIVATE_KEY, + _ => return Err(CKR_GENERAL_ERROR)?, + }; + let key_type = obj.get_attr_as_ulong(CKA_KEY_TYPE)?; + let (name, params) = match key_type { + #[cfg(feature = "ecc")] + CKK_EC => ecc::ecc_object_to_params(obj, class)?, + #[cfg(all(feature = "eddsa", not(feature = "fips")))] + CKK_EC_EDWARDS => eddsa::eddsa_object_to_params(obj, class)?, + #[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] + CKK_EC_MONTGOMERY => ecm::ecm_object_to_params(obj, class)?, + #[cfg(feature = "rsa")] + CKK_RSA => rsa::rsa_object_to_params(obj, class)?, + _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, + }; + Self::fromdata(name, key_class, ¶ms) + } + + pub fn pubkey_from_object(obj: &object::Object) -> Result { + Self::from_object(obj, CKO_PUBLIC_KEY) + } + + pub fn privkey_from_object(obj: &object::Object) -> Result { + Self::from_object(obj, CKO_PRIVATE_KEY) + } } impl Drop for EvpPkey { @@ -498,6 +540,32 @@ impl<'a> OsslParam<'a> { Ok(()) } + #[allow(dead_code)] + pub fn add_owned_octet_string( + &mut self, + key: *const c_char, + v: Vec, + ) -> Result<()> { + if self.finalized { + return Err(CKR_GENERAL_ERROR)?; + } + + if key == std::ptr::null() { + return Err(CKR_GENERAL_ERROR)?; + } + + let param = unsafe { + OSSL_PARAM_construct_octet_string( + key, + void_ptr!(v.as_ptr()), + v.len(), + ) + }; + self.v.push(v); + self.p.to_mut().push(param); + Ok(()) + } + #[allow(dead_code)] pub fn add_size_t( &mut self, diff --git a/src/ossl/ec_montgomery.rs b/src/ossl/ec_montgomery.rs index 1d8d4a16..2dc820ac 100644 --- a/src/ossl/ec_montgomery.rs +++ b/src/ossl/ec_montgomery.rs @@ -5,7 +5,7 @@ use std::ffi::{c_char, c_int}; use crate::attribute::Attribute; use crate::ecc_misc::*; -use crate::error::Result; +use crate::error::{device_error, general_error, Result}; use crate::interface::*; use crate::object::Object; use crate::ossl::bindings::*; @@ -67,7 +67,7 @@ fn make_bits_from_obj(key: &Object) -> Result { Ok(bits) } -fn get_ossl_name_from_obj(key: &Object) -> Result<&'static [u8]> { +pub fn get_ossl_name_from_obj(key: &Object) -> Result<&'static [u8]> { match make_bits_from_obj(key) { Ok(BITS_CURVE25519) => Ok(OSSL_CURVE25519), Ok(BITS_CURVE448) => Ok(OSSL_CURVE448), @@ -75,52 +75,46 @@ fn get_ossl_name_from_obj(key: &Object) -> Result<&'static [u8]> { } } -pub fn make_output_length_from_montgomery_obj(key: &Object) -> Result { - match make_bits_from_obj(key) { - Ok(255) => Ok(64), - Ok(448) => Ok(114), - _ => return Err(CKR_GENERAL_ERROR)?, - } +fn get_ec_point_from_obj(key: &Object) -> Result> { + let point = key.get_attr_as_bytes(CKA_EC_POINT).map_err(general_error)?; + /* [u8] is an octet string for the asn1 library */ + let octet = asn1::parse_single::<&[u8]>(point).map_err(device_error)?; + Ok(octet.to_vec()) } -pub fn make_ec_montgomery_public_key( +pub fn ecm_object_to_params( key: &Object, - ec_point: &Vec, -) -> Result { + class: CK_OBJECT_CLASS, +) -> Result<(*const c_char, OsslParam)> { + let kclass = key.get_attr_as_ulong(CKA_CLASS)?; + if kclass != class { + return Err(CKR_KEY_TYPE_INCONSISTENT)?; + } let mut params = OsslParam::with_capacity(1); params.zeroize = true; - params.add_octet_string(name_as_char(OSSL_PKEY_PARAM_PUB_KEY), ec_point)?; - params.finalize(); - EvpPkey::fromdata( - get_ossl_name_from_obj(key)?.as_ptr() as *const c_char, - EVP_PKEY_PUBLIC_KEY, - ¶ms, - ) -} + let name = get_ossl_name_from_obj(key)?; -/// Convert the PKCS #11 private key object to OpenSSL EVP_PKEY -pub fn montgomery_object_to_ecc_private_key(key: &Object) -> Result { - let priv_key = match key.get_attr_as_bytes(CKA_VALUE) { - Ok(v) => v, - Err(_) => return Err(CKR_DEVICE_ERROR)?, - }; - let mut priv_key_octet: Vec = Vec::with_capacity(priv_key.len() + 2); - priv_key_octet.push(4); /* tag octet string */ - priv_key_octet.push(u8::try_from(priv_key.len())?); /* length */ - priv_key_octet.extend(priv_key); + match kclass { + CKO_PUBLIC_KEY => { + params.add_owned_octet_string( + name_as_char(OSSL_PKEY_PARAM_PUB_KEY), + get_ec_point_from_obj(key)?, + )?; + } + CKO_PRIVATE_KEY => { + params.add_octet_string( + name_as_char(OSSL_PKEY_PARAM_PRIV_KEY), + key.get_attr_as_bytes(CKA_VALUE)?, + )?; + } + + _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, + } - let mut params = OsslParam::with_capacity(1); - params.zeroize = true; - params - .add_octet_string(name_as_char(OSSL_PKEY_PARAM_PRIV_KEY), priv_key)?; params.finalize(); - EvpPkey::fromdata( - get_ossl_name_from_obj(key)?.as_ptr() as *const c_char, - EVP_PKEY_PRIVATE_KEY, - ¶ms, - ) + Ok((name_as_char(name), params)) } #[derive(Debug)] @@ -149,12 +143,9 @@ impl ECMontgomeryOperation { } let params = OsslParam::from_ptr(params)?; /* Public Key */ - let point_encoded = match asn1::write_single( + let point_encoded = asn1::write_single( ¶ms.get_octet_string(name_as_char(OSSL_PKEY_PARAM_PUB_KEY))?, - ) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; + )?; pubkey.set_attr(Attribute::from_bytes(CKA_EC_POINT, point_encoded))?; /* Private Key */ diff --git a/src/ossl/ecc.rs b/src/ossl/ecc.rs index 83ba8694..afde8b5a 100644 --- a/src/ossl/ecc.rs +++ b/src/ossl/ecc.rs @@ -1,7 +1,7 @@ // Copyright 2023 - 2024 Simo Sorce, Jakub Jelen // See LICENSE.txt file for terms -use core::ffi::c_int; +use core::ffi::{c_char, c_int}; use crate::attribute::Attribute; use crate::ecc::*; @@ -26,7 +26,7 @@ use zeroize::Zeroize; /* confusingly enough, this is not EC for FIPS-level operations */ #[cfg(feature = "fips")] static ECDSA_NAME: &[u8; 6] = b"ECDSA\0"; -static EC_NAME: &[u8; 3] = b"EC\0"; +pub static EC_NAME: &[u8; 3] = b"EC\0"; fn make_bits_from_ec_params(key: &Object) -> Result { let x = match key.get_attr_as_bytes(CKA_EC_PARAMS) { @@ -86,46 +86,42 @@ fn get_ec_point_from_obj(key: &Object) -> Result> { Ok(octet.to_vec()) } -pub fn make_ecdsa_public_key( - curve_name: &Vec, - ec_point: &Vec, -) -> Result { +pub fn ecc_object_to_params( + key: &Object, + class: CK_OBJECT_CLASS, +) -> Result<(*const c_char, OsslParam)> { + let kclass = key.get_attr_as_ulong(CKA_CLASS)?; + if kclass != class { + return Err(CKR_KEY_TYPE_INCONSISTENT)?; + } let mut params = OsslParam::with_capacity(2); params.zeroize = true; - params.add_utf8_string( + + let curve_name = get_curve_name_from_obj(key)?; + params.add_owned_utf8_string( name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), curve_name, )?; - params.add_octet_string(name_as_char(OSSL_PKEY_PARAM_PUB_KEY), ec_point)?; - params.finalize(); - EvpPkey::fromdata(name_as_char(EC_NAME), EVP_PKEY_PUBLIC_KEY, ¶ms) -} - -/// Convert the PKCS #11 public key object to OpenSSL EVP_PKEY -fn object_to_ecc_public_key(key: &Object) -> Result { - make_ecdsa_public_key( - &get_curve_name_from_obj(key)?, - &get_ec_point_from_obj(key)?, - ) -} + match kclass { + CKO_PUBLIC_KEY => { + params.add_owned_octet_string( + name_as_char(OSSL_PKEY_PARAM_PUB_KEY), + get_ec_point_from_obj(key)?, + )?; + } + CKO_PRIVATE_KEY => { + params.add_bn( + name_as_char(OSSL_PKEY_PARAM_PRIV_KEY), + key.get_attr_as_bytes(CKA_VALUE)?, + )?; + } + _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, + } -/// Convert the PKCS #11 private key object to OpenSSL EVP_PKEY -pub fn ecdsa_object_to_ecc_private_key(key: &Object) -> Result { - let curve_name = get_curve_name_from_obj(key)?; - let mut params = OsslParam::with_capacity(2); - params.zeroize = true; - params.add_utf8_string( - name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), - &curve_name, - )?; - params.add_bn( - name_as_char(OSSL_PKEY_PARAM_PRIV_KEY), - key.get_attr_as_bytes(CKA_VALUE)?, - )?; params.finalize(); - EvpPkey::fromdata(name_as_char(EC_NAME), EVP_PKEY_PRIVATE_KEY, ¶ms) + Ok((name_as_char(EC_NAME), params)) } #[derive(asn1::Asn1Read, asn1::Asn1Write)] @@ -250,11 +246,12 @@ impl EccOperation { key: &Object, _: &CK_MECHANISM_INFO, ) -> Result { + let privkey = EvpPkey::privkey_from_object(key)?; Ok(EccOperation { mech: mech.mechanism, output_len: make_output_length_from_ecdsa_obj(key)?, public_key: None, - private_key: Some(ecdsa_object_to_ecc_private_key(key)?), + private_key: Some(privkey), finalized: false, in_use: false, sigctx: match mech.mechanism { @@ -272,10 +269,11 @@ impl EccOperation { key: &Object, _: &CK_MECHANISM_INFO, ) -> Result { + let pubkey = EvpPkey::pubkey_from_object(key)?; Ok(EccOperation { mech: mech.mechanism, output_len: make_output_length_from_ecdsa_obj(key)?, - public_key: Some(object_to_ecc_public_key(key)?), + public_key: Some(pubkey), private_key: None, finalized: false, in_use: false, diff --git a/src/ossl/ecdh.rs b/src/ossl/ecdh.rs index 53a1b4ed..2aec1a01 100644 --- a/src/ossl/ecdh.rs +++ b/src/ossl/ecdh.rs @@ -13,15 +13,9 @@ use crate::object::{default_key_attributes, Object, ObjectFactories}; use crate::ossl::bindings::*; use crate::ossl::common::*; #[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] -use crate::ossl::ec_montgomery::{ - make_ec_montgomery_public_key, make_output_length_from_montgomery_obj, - montgomery_object_to_ecc_private_key, -}; +use crate::ossl::ec_montgomery::get_ossl_name_from_obj; #[cfg(feature = "ecc")] -use crate::ossl::ecc::{ - ecdsa_object_to_ecc_private_key, get_curve_name_from_obj, - make_ecdsa_public_key, make_output_length_from_ecdsa_obj, -}; +use crate::ossl::ecc::{get_curve_name_from_obj, EC_NAME}; fn kdf_type_to_hash_mech(mech: CK_EC_KDF_TYPE) -> Result { match mech { @@ -38,39 +32,28 @@ fn kdf_type_to_hash_mech(mech: CK_EC_KDF_TYPE) -> Result { } } -fn make_derive_output_length_from_obj(key: &Object) -> Result { - let key_type = key.get_attr_as_ulong(CKA_KEY_TYPE)?; - match key_type { - #[cfg(feature = "ecc")] - CKK_EC => make_output_length_from_ecdsa_obj(key), - #[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] - CKK_EC_MONTGOMERY => make_output_length_from_montgomery_obj(key), - _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, - } -} - -fn derive_object_to_ecc_private_key(key: &Object) -> Result { - let key_type = key.get_attr_as_ulong(CKA_KEY_TYPE)?; - match key_type { - #[cfg(feature = "ecc")] - CKK_EC => ecdsa_object_to_ecc_private_key(key), - #[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] - CKK_EC_MONTGOMERY => montgomery_object_to_ecc_private_key(key), - _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, - } -} - fn make_peer_key(key: &Object, ec_point: &Vec) -> Result { - let key_type = key.get_attr_as_ulong(CKA_KEY_TYPE)?; - match key_type { + let mut params = OsslParam::with_capacity(2); + params.zeroize = true; + + let name = match key.get_attr_as_ulong(CKA_KEY_TYPE)? { #[cfg(feature = "ecc")] CKK_EC => { - make_ecdsa_public_key(&get_curve_name_from_obj(key)?, &ec_point) + params.add_owned_utf8_string( + name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), + get_curve_name_from_obj(key)?, + )?; + EC_NAME } #[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] - CKK_EC_MONTGOMERY => make_ec_montgomery_public_key(key, ec_point), + CKK_EC_MONTGOMERY => get_ossl_name_from_obj(key)?, _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, - } + }; + + params.add_octet_string(name_as_char(OSSL_PKEY_PARAM_PUB_KEY), ec_point)?; + params.finalize(); + + EvpPkey::fromdata(name_as_char(name), EVP_PKEY_PUBLIC_KEY, ¶ms) } #[derive(Debug)] @@ -140,6 +123,8 @@ impl Derive for ECDHOperation { }; let outlen: c_uint; + let mut pkey = EvpPkey::privkey_from_object(key)?; + let mut params = OsslParam::with_capacity(5); params.zeroize = true; params.add_int( @@ -150,8 +135,11 @@ impl Derive for ECDHOperation { let factory = objfactories.get_obj_factory_from_key_template(template)?; + let raw_max = 2 + * ((usize::try_from(unsafe { EVP_PKEY_get_bits(pkey.as_ptr()) })? + + 7) + / 8); /* the raw ECDH results have length of bit field length */ - let raw_max = make_derive_output_length_from_obj(key)?; let keylen = match template.iter().find(|x| x.type_ == CKA_VALUE_LEN) { Some(a) => { let value_len = usize::try_from(a.to_ulong()?)?; @@ -205,7 +193,6 @@ impl Derive for ECDHOperation { params.finalize(); - let mut pkey = derive_object_to_ecc_private_key(key)?; let mut ctx = pkey.new_ctx()?; let res = unsafe { EVP_PKEY_derive_init_ex(ctx.as_mut_ptr(), params.as_ptr()) @@ -215,8 +202,7 @@ impl Derive for ECDHOperation { } let ec_point = { - let ec_point_size = make_derive_output_length_from_obj(key)? + 1; - if self.public.len() > ec_point_size { + if self.public.len() > raw_max + 1 { /* try to see if it is a DER encoded point */ match asn1::parse_single::<&[u8]>(self.public.as_slice()) { Ok(pt) => Cow::Owned(pt.to_vec()), diff --git a/src/ossl/eddsa.rs b/src/ossl/eddsa.rs index dea40ad2..b56c1d6a 100644 --- a/src/ossl/eddsa.rs +++ b/src/ossl/eddsa.rs @@ -5,7 +5,7 @@ use std::ffi::{c_char, c_int}; use crate::attribute::Attribute; use crate::ecc_misc::*; -use crate::error::Result; +use crate::error::{device_error, general_error, Result}; use crate::interface::*; use crate::mechanism::*; use crate::object::Object; @@ -126,51 +126,46 @@ fn parse_params(mech: &CK_MECHANISM, is_448: bool) -> Result { } } -/// Convert the PKCS #11 public key object to OpenSSL EVP_PKEY -fn object_to_ecc_public_key(key: &Object) -> Result { - let ec_point = match key.get_attr_as_bytes(CKA_EC_POINT) { - Ok(v) => v, - Err(_) => return Err(CKR_DEVICE_ERROR)?, - }; - /* The CKA_EC_POINT should be DER encoded */ - let octet = match asn1::parse_single::<&[u8]>(ec_point) { - Ok(a) => a.to_vec(), - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; +fn get_ec_point_from_obj(key: &Object) -> Result> { + let point = key.get_attr_as_bytes(CKA_EC_POINT).map_err(general_error)?; + /* [u8] is an octet string for the asn1 library */ + let octet = asn1::parse_single::<&[u8]>(point).map_err(device_error)?; + Ok(octet.to_vec()) +} + +pub fn eddsa_object_to_params( + key: &Object, + class: CK_OBJECT_CLASS, +) -> Result<(*const c_char, OsslParam)> { + let kclass = key.get_attr_as_ulong(CKA_CLASS)?; + if kclass != class { + return Err(CKR_KEY_TYPE_INCONSISTENT)?; + } let mut params = OsslParam::with_capacity(1); params.zeroize = true; - params.add_octet_string(name_as_char(OSSL_PKEY_PARAM_PUB_KEY), &octet)?; - params.finalize(); - EvpPkey::fromdata( - get_ossl_name_from_obj(key)?.as_ptr() as *const c_char, - EVP_PKEY_PUBLIC_KEY, - ¶ms, - ) -} + let name = get_ossl_name_from_obj(key)?; -/// Convert the PKCS #11 private key object to OpenSSL EVP_PKEY -fn object_to_ecc_private_key(key: &Object) -> Result { - let priv_key = match key.get_attr_as_bytes(CKA_VALUE) { - Ok(v) => v, - Err(_) => return Err(CKR_DEVICE_ERROR)?, - }; - let mut priv_key_octet: Vec = Vec::with_capacity(priv_key.len() + 2); - priv_key_octet.push(4); /* tag octet string */ - priv_key_octet.push(u8::try_from(priv_key.len())?); /* length */ - priv_key_octet.extend(priv_key); + match kclass { + CKO_PUBLIC_KEY => { + params.add_owned_octet_string( + name_as_char(OSSL_PKEY_PARAM_PUB_KEY), + get_ec_point_from_obj(key)?, + )?; + } + CKO_PRIVATE_KEY => { + params.add_octet_string( + name_as_char(OSSL_PKEY_PARAM_PRIV_KEY), + key.get_attr_as_bytes(CKA_VALUE)?, + )?; + } + + _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, + } - let mut params = OsslParam::with_capacity(1); - params.zeroize = true; - params - .add_octet_string(name_as_char(OSSL_PKEY_PARAM_PRIV_KEY), priv_key)?; params.finalize(); - EvpPkey::fromdata( - get_ossl_name_from_obj(key)?.as_ptr() as *const c_char, - EVP_PKEY_PRIVATE_KEY, - ¶ms, - ) + Ok((name_as_char(name), params)) } fn no_params() -> EddsaParams { @@ -231,11 +226,12 @@ impl EddsaOperation { _: &CK_MECHANISM_INFO, ) -> Result { let is_448 = is_448_curve(key)?; + let privkey = EvpPkey::privkey_from_object(key)?; Ok(EddsaOperation { mech: mech.mechanism, output_len: make_output_length_from_obj(key)?, public_key: None, - private_key: Some(object_to_ecc_private_key(key)?), + private_key: Some(privkey), params: parse_params(mech, is_448)?, is448: is_448, data: Vec::new(), @@ -251,10 +247,11 @@ impl EddsaOperation { _: &CK_MECHANISM_INFO, ) -> Result { let is_448 = is_448_curve(key)?; + let pubkey = EvpPkey::pubkey_from_object(key)?; Ok(EddsaOperation { mech: mech.mechanism, output_len: make_output_length_from_obj(key)?, - public_key: Some(object_to_ecc_public_key(key)?), + public_key: Some(pubkey), private_key: None, params: parse_params(mech, is_448)?, is448: is_448, diff --git a/src/ossl/rsa.rs b/src/ossl/rsa.rs index d4ac2dba..8ab83ee7 100644 --- a/src/ossl/rsa.rs +++ b/src/ossl/rsa.rs @@ -31,24 +31,21 @@ pub const MIN_RSA_SIZE_BYTES: usize = MIN_RSA_SIZE_BITS / 8; static RSA_NAME: &[u8; 4] = b"RSA\0"; -fn object_to_rsa_public_key(key: &Object) -> Result { - let mut params = OsslParam::with_capacity(2); - params.zeroize = true; - params.add_bn( - name_as_char(OSSL_PKEY_PARAM_RSA_N), - key.get_attr_as_bytes(CKA_MODULUS)?, - )?; - params.add_bn( - name_as_char(OSSL_PKEY_PARAM_RSA_E), - key.get_attr_as_bytes(CKA_PUBLIC_EXPONENT)?, - )?; - params.finalize(); - - EvpPkey::fromdata(name_as_char(RSA_NAME), EVP_PKEY_PUBLIC_KEY, ¶ms) -} - -fn object_to_rsa_private_key(key: &Object) -> Result { - let mut params = OsslParam::with_capacity(9); +pub fn rsa_object_to_params( + key: &Object, + class: CK_OBJECT_CLASS, +) -> Result<(*const c_char, OsslParam)> { + let kclass = key.get_attr_as_ulong(CKA_CLASS)?; + let mut params = match class { + CKO_PUBLIC_KEY => OsslParam::with_capacity(2), + CKO_PRIVATE_KEY => { + if kclass == CKO_PUBLIC_KEY { + return Err(CKR_KEY_TYPE_INCONSISTENT)?; + } + OsslParam::with_capacity(9) + } + _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, + }; params.zeroize = true; params.add_bn( name_as_char(OSSL_PKEY_PARAM_RSA_N), @@ -58,45 +55,48 @@ fn object_to_rsa_private_key(key: &Object) -> Result { name_as_char(OSSL_PKEY_PARAM_RSA_E), key.get_attr_as_bytes(CKA_PUBLIC_EXPONENT)?, )?; - params.add_bn( - name_as_char(OSSL_PKEY_PARAM_RSA_D), - key.get_attr_as_bytes(CKA_PRIVATE_EXPONENT)?, - )?; - /* OpenSSL can compute a,b,c with just p,q */ - if key.get_attr(CKA_PRIME_1).is_some() - && key.get_attr(CKA_PRIME_2).is_some() - { + if class == CKO_PRIVATE_KEY { params.add_bn( - name_as_char(OSSL_PKEY_PARAM_RSA_FACTOR1), - key.get_attr_as_bytes(CKA_PRIME_1)?, + name_as_char(OSSL_PKEY_PARAM_RSA_D), + key.get_attr_as_bytes(CKA_PRIVATE_EXPONENT)?, )?; - params.add_bn( - name_as_char(OSSL_PKEY_PARAM_RSA_FACTOR2), - key.get_attr_as_bytes(CKA_PRIME_2)?, - )?; - } - if key.get_attr(CKA_EXPONENT_1).is_some() - && key.get_attr(CKA_EXPONENT_2).is_some() - && key.get_attr(CKA_COEFFICIENT).is_some() - { - params.add_bn( - name_as_char(OSSL_PKEY_PARAM_RSA_EXPONENT1), - key.get_attr_as_bytes(CKA_EXPONENT_1)?, - )?; - params.add_bn( - name_as_char(OSSL_PKEY_PARAM_RSA_EXPONENT2), - key.get_attr_as_bytes(CKA_EXPONENT_2)?, - )?; - params.add_bn( - name_as_char(OSSL_PKEY_PARAM_RSA_COEFFICIENT1), - key.get_attr_as_bytes(CKA_COEFFICIENT)?, - )?; + /* OpenSSL can compute a,b,c with just p,q */ + if key.get_attr(CKA_PRIME_1).is_some() + && key.get_attr(CKA_PRIME_2).is_some() + { + params.add_bn( + name_as_char(OSSL_PKEY_PARAM_RSA_FACTOR1), + key.get_attr_as_bytes(CKA_PRIME_1)?, + )?; + params.add_bn( + name_as_char(OSSL_PKEY_PARAM_RSA_FACTOR2), + key.get_attr_as_bytes(CKA_PRIME_2)?, + )?; + } + + if key.get_attr(CKA_EXPONENT_1).is_some() + && key.get_attr(CKA_EXPONENT_2).is_some() + && key.get_attr(CKA_COEFFICIENT).is_some() + { + params.add_bn( + name_as_char(OSSL_PKEY_PARAM_RSA_EXPONENT1), + key.get_attr_as_bytes(CKA_EXPONENT_1)?, + )?; + params.add_bn( + name_as_char(OSSL_PKEY_PARAM_RSA_EXPONENT2), + key.get_attr_as_bytes(CKA_EXPONENT_2)?, + )?; + params.add_bn( + name_as_char(OSSL_PKEY_PARAM_RSA_COEFFICIENT1), + key.get_attr_as_bytes(CKA_COEFFICIENT)?, + )?; + } } params.finalize(); - EvpPkey::fromdata(name_as_char(RSA_NAME), EVP_PKEY_PRIVATE_KEY, ¶ms) + Ok((name_as_char(RSA_NAME), params)) } fn mgf1_to_digest_name_as_slice(mech: CK_MECHANISM_TYPE) -> &'static [u8] { @@ -256,6 +256,7 @@ impl RsaPKCSOperation { 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( @@ -264,7 +265,7 @@ impl RsaPKCSOperation { oaep_params.hash, )?, output_len: modulus.len(), - public_key: Some(object_to_rsa_public_key(key)?), + public_key: Some(pubkey), private_key: None, finalized: false, in_use: false, @@ -289,6 +290,8 @@ impl RsaPKCSOperation { return Err(CKR_KEY_SIZE_RANGE)?; } let oaep_params = parse_oaep_params(mech)?; + let pubkey = EvpPkey::pubkey_from_object(key)?; + let privkey = EvpPkey::privkey_from_object(key)?; Ok(RsaPKCSOperation { mech: mech.mechanism, max_input: modulus.len(), @@ -297,8 +300,8 @@ impl RsaPKCSOperation { mech.mechanism, oaep_params.hash, )?, - public_key: Some(object_to_rsa_public_key(key)?), - private_key: Some(object_to_rsa_private_key(key)?), + public_key: Some(pubkey), + private_key: Some(privkey), finalized: false, in_use: false, sigctx: None, @@ -323,6 +326,8 @@ impl RsaPKCSOperation { } let pss_params = parse_pss_params(mech)?; + let pubkey = EvpPkey::pubkey_from_object(key)?; + let privkey = EvpPkey::privkey_from_object(key)?; Ok(RsaPKCSOperation { mech: mech.mechanism, max_input: match mech.mechanism { @@ -331,8 +336,8 @@ impl RsaPKCSOperation { _ => 0, }, output_len: modulus.len(), - public_key: Some(object_to_rsa_public_key(key)?), - private_key: Some(object_to_rsa_private_key(key)?), + public_key: Some(pubkey), + private_key: Some(privkey), finalized: false, in_use: false, sigctx: match mech.mechanism { @@ -363,6 +368,7 @@ impl RsaPKCSOperation { } let pss_params = parse_pss_params(mech)?; + let pubkey = EvpPkey::pubkey_from_object(key)?; Ok(RsaPKCSOperation { mech: mech.mechanism, max_input: match mech.mechanism { @@ -370,7 +376,7 @@ impl RsaPKCSOperation { _ => 0, }, output_len: modulus.len(), - public_key: Some(object_to_rsa_public_key(key)?), + public_key: Some(pubkey), private_key: None, finalized: false, in_use: false, From 474b7286017f80ccf00ee4c1f7b5b38ee2efb3d3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 19 Nov 2024 16:58:00 -0500 Subject: [PATCH 3/6] Centralize ECC properties in a single file All of the generic ECC properiets handling, like OIDs, OSSL Names, sizes can be managd in a single place as it does not depend on ossl specific fucntions. This allows to simplify and handle these conversions uniformly across all ECC operations and key types. Signed-off-by: Simo Sorce --- src/ec_montgomery.rs | 4 +- src/ecc.rs | 122 ---------------------------- src/ecc_misc.rs | 165 +++++++++++++++++++++++++++++++++++++- src/fips/indicators.rs | 13 ++- src/ossl/common.rs | 26 ++++++ src/ossl/ec_montgomery.rs | 70 +--------------- src/ossl/ecc.rs | 75 ++--------------- src/ossl/ecdh.rs | 14 +--- src/ossl/eddsa.rs | 143 ++++++--------------------------- src/tests/ecdh_vectors.rs | 59 +++++++------- 10 files changed, 268 insertions(+), 423 deletions(-) diff --git a/src/ec_montgomery.rs b/src/ec_montgomery.rs index 2623ce20..3479c5b2 100644 --- a/src/ec_montgomery.rs +++ b/src/ec_montgomery.rs @@ -14,8 +14,8 @@ use crate::{attr_element, bytes_attr_not_empty}; use once_cell::sync::Lazy; -pub const MIN_EC_MONTGOMERY_SIZE_BITS: usize = BITS_CURVE25519; -pub const MAX_EC_MONTGOMERY_SIZE_BITS: usize = BITS_CURVE448; +pub const MIN_EC_MONTGOMERY_SIZE_BITS: usize = BITS_X25519; +pub const MAX_EC_MONTGOMERY_SIZE_BITS: usize = BITS_X448; #[derive(Debug)] pub struct ECMontgomeryPubFactory { diff --git a/src/ecc.rs b/src/ecc.rs index 79a8bb60..9ffca012 100644 --- a/src/ecc.rs +++ b/src/ecc.rs @@ -19,113 +19,6 @@ use once_cell::sync::Lazy; pub const MIN_EC_SIZE_BITS: usize = 256; pub const MAX_EC_SIZE_BITS: usize = 521; -// ASN.1 encoding of the OID -const OID_SECP256R1: asn1::ObjectIdentifier = - asn1::oid!(1, 2, 840, 10045, 3, 1, 7); -const OID_SECP384R1: asn1::ObjectIdentifier = asn1::oid!(1, 3, 132, 0, 34); -const OID_SECP521R1: asn1::ObjectIdentifier = asn1::oid!(1, 3, 132, 0, 35); - -// ASN.1 encoding of the curve name -const STRING_SECP256R1: &[u8] = &[ - 0x13, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, -]; -const STRING_SECP384R1: &[u8] = &[ - 0x13, 0x09, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, -]; -const STRING_SECP521R1: &[u8] = &[ - 0x13, 0x09, 0x73, 0x65, 0x63, 0x70, 0x35, 0x32, 0x31, 0x72, 0x31, -]; - -pub const NAME_SECP256R1: &str = "prime256v1"; -pub const NAME_SECP384R1: &str = "secp384r1"; -pub const NAME_SECP521R1: &str = "secp521r1"; - -const BITS_SECP256R1: usize = 256; -const BITS_SECP384R1: usize = 384; -const BITS_SECP521R1: usize = 521; - -pub fn oid_to_curve_name(oid: asn1::ObjectIdentifier) -> Result<&'static str> { - match oid { - OID_SECP256R1 => Ok(NAME_SECP256R1), - OID_SECP384R1 => Ok(NAME_SECP384R1), - OID_SECP521R1 => Ok(NAME_SECP521R1), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -#[cfg(test)] -pub fn curve_name_to_ec_params(name: &'static str) -> Result<&'static [u8]> { - match name { - NAME_SECP256R1 => Ok(STRING_SECP256R1), - NAME_SECP384R1 => Ok(STRING_SECP384R1), - NAME_SECP521R1 => Ok(STRING_SECP521R1), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -#[cfg(test)] -pub fn name_to_bits(name: &'static str) -> Result { - match name { - NAME_SECP256R1 => Ok(BITS_SECP256R1), - NAME_SECP384R1 => Ok(BITS_SECP384R1), - NAME_SECP521R1 => Ok(BITS_SECP521R1), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -pub fn oid_to_bits(oid: asn1::ObjectIdentifier) -> Result { - match oid { - OID_SECP256R1 => Ok(BITS_SECP256R1), - OID_SECP384R1 => Ok(BITS_SECP384R1), - OID_SECP521R1 => Ok(BITS_SECP521R1), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -pub fn curve_name_to_bits(name: asn1::PrintableString) -> Result { - let asn1_name = match asn1::write_single(&name) { - Ok(r) => r, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - match asn1_name.as_slice() { - STRING_SECP256R1 => Ok(BITS_SECP256R1), - STRING_SECP384R1 => Ok(BITS_SECP384R1), - STRING_SECP521R1 => Ok(BITS_SECP521R1), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -pub fn curve_name_to_oid( - name: asn1::PrintableString, -) -> Result { - let asn1_name = match asn1::write_single(&name) { - Ok(r) => r, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - Ok(match asn1_name.as_slice() { - STRING_SECP256R1 => OID_SECP256R1, - STRING_SECP384R1 => OID_SECP384R1, - STRING_SECP521R1 => OID_SECP521R1, - _ => return Err(CKR_GENERAL_ERROR)?, - }) -} - -#[cfg(feature = "fips")] -pub fn ec_key_curve_size(key: &Object) -> Result { - let x = match key.get_attr_as_bytes(CKA_EC_PARAMS) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - match asn1::parse_single::(x) { - Ok(a) => match a { - ECParameters::OId(o) => oid_to_bits(o), - ECParameters::CurveName(c) => curve_name_to_bits(c), - _ => return Err(CKR_GENERAL_ERROR)?, - }, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - } -} - #[derive(Debug)] pub struct ECCPubFactory { attributes: Vec, @@ -234,21 +127,6 @@ impl ObjectFactory for ECCPrivFactory { } } -fn get_oid_from_obj(key: &Object) -> Result { - let x = match key.get_attr_as_bytes(CKA_EC_PARAMS) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - match asn1::parse_single::(x) { - Ok(a) => match a { - ECParameters::OId(o) => Ok(o), - ECParameters::CurveName(c) => curve_name_to_oid(c), - _ => return Err(CKR_GENERAL_ERROR)?, - }, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - } -} - impl CommonKeyFactory for ECCPrivFactory {} impl PrivKeyFactory for ECCPrivFactory { diff --git a/src/ecc_misc.rs b/src/ecc_misc.rs index f61c6386..92f20738 100644 --- a/src/ecc_misc.rs +++ b/src/ecc_misc.rs @@ -2,11 +2,13 @@ // See LICENSE.txt file for terms use crate::bytes_attr_not_empty; -use crate::error::Result; +use crate::error::{device_error, general_error, Result}; use crate::interface::*; use crate::kasn1::DerEncOctetString; use crate::object::Object; +use asn1; + type Version = u64; #[derive(asn1::Asn1Read, asn1::Asn1Write)] @@ -44,3 +46,164 @@ pub fn ec_key_check_import(obj: &mut Object) -> Result<()> { bytes_attr_not_empty!(obj; CKA_VALUE); Ok(()) } + +// Bit sized for curves +const BITS_SECP256R1: usize = 256; +const BITS_SECP384R1: usize = 384; +const BITS_SECP521R1: usize = 521; +pub const BITS_ED25519: usize = 256; +pub const BITS_ED448: usize = 448; +pub const BITS_X25519: usize = 256; +pub const BITS_X448: usize = 448; + +// ASN.1 encoding of OIDs +pub const OID_SECP256R1: asn1::ObjectIdentifier = + asn1::oid!(1, 2, 840, 10045, 3, 1, 7); +pub const OID_SECP384R1: asn1::ObjectIdentifier = asn1::oid!(1, 3, 132, 0, 34); +pub const OID_SECP521R1: asn1::ObjectIdentifier = asn1::oid!(1, 3, 132, 0, 35); +pub const OID_ED25519: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 112); +pub const OID_ED448: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 113); +pub const OID_X25519: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 110); +pub const OID_X448: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 111); + +// ASN.1 encoding of curve names +const OCTSTR_SECP256R1: &[u8] = &[ + 0x13, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x32, 0x35, 0x36, 0x76, 0x31, +]; +const OCTSTR_SECP384R1: &[u8] = &[ + 0x13, 0x09, 0x73, 0x65, 0x63, 0x70, 0x33, 0x38, 0x34, 0x72, 0x31, +]; +const OCTSTR_SECP521R1: &[u8] = &[ + 0x13, 0x09, 0x73, 0x65, 0x63, 0x70, 0x35, 0x32, 0x31, 0x72, 0x31, +]; +const OCTSTR_ED25519: &[u8] = &[ + 0x13, 0x0c, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x35, 0x35, + 0x31, 0x39, +]; +const OCTSTR_ED448: &[u8] = &[ + 0x13, 0x0a, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x34, 0x34, 0x38, +]; +const OCTSTR_X25519: &[u8] = &[ + 0x13, 0x0a, 0x63, 0x75, 0x72, 0x76, 0x65, 0x32, 0x35, 0x35, 0x31, 0x39, +]; +const OCTSTR_X448: &[u8] = + &[0x13, 0x08, 0x63, 0x75, 0x72, 0x76, 0x65, 0x34, 0x34, 0x38]; + +const NAME_SECP256R1: &[u8] = b"prime256v1\0"; +const NAME_SECP384R1: &[u8] = b"secp384r1\0"; +const NAME_SECP521R1: &[u8] = b"secp521r1\0"; +const NAME_ED25519: &[u8] = b"ED25519\0"; +const NAME_ED448: &[u8] = b"ED448\0"; +const NAME_X25519: &[u8] = b"X25519\0"; +const NAME_X448: &[u8] = b"X448\0"; + +pub static EC_NAME: &[u8; 3] = b"EC\0"; + +pub fn curve_name_to_bits(name: &[u8]) -> Result { + match name { + NAME_SECP256R1 => Ok(BITS_SECP256R1), + NAME_SECP384R1 => Ok(BITS_SECP384R1), + NAME_SECP521R1 => Ok(BITS_SECP521R1), + NAME_ED25519 => Ok(BITS_ED25519), + NAME_ED448 => Ok(BITS_ED448), + NAME_X25519 => Ok(BITS_X25519), + NAME_X448 => Ok(BITS_X448), + _ => Err(CKR_GENERAL_ERROR)?, + } +} + +fn oid_to_ossl_name(oid: asn1::ObjectIdentifier) -> Result<&'static [u8]> { + match oid { + OID_SECP256R1 => Ok(NAME_SECP256R1), + OID_SECP384R1 => Ok(NAME_SECP384R1), + OID_SECP521R1 => Ok(NAME_SECP521R1), + OID_ED25519 => Ok(NAME_ED25519), + OID_ED448 => Ok(NAME_ED448), + OID_X25519 => Ok(NAME_X25519), + OID_X448 => Ok(NAME_X448), + _ => Err(CKR_GENERAL_ERROR)?, + } +} + +fn curve_to_oid(name: asn1::PrintableString) -> Result { + match asn1::write_single(&name).map_err(general_error)?.as_slice() { + OCTSTR_SECP256R1 => Ok(OID_SECP256R1), + OCTSTR_SECP384R1 => Ok(OID_SECP384R1), + OCTSTR_SECP521R1 => Ok(OID_SECP521R1), + OCTSTR_ED25519 => Ok(OID_ED25519), + OCTSTR_ED448 => Ok(OID_ED448), + OCTSTR_X25519 => Ok(OID_X25519), + OCTSTR_X448 => Ok(OID_X448), + _ => return Err(CKR_GENERAL_ERROR)?, + } +} + +fn curve_to_ossl_name(name: asn1::PrintableString) -> Result<&'static [u8]> { + match asn1::write_single(&name).map_err(general_error)?.as_slice() { + OCTSTR_SECP256R1 => Ok(NAME_SECP256R1), + OCTSTR_SECP384R1 => Ok(NAME_SECP384R1), + OCTSTR_SECP521R1 => Ok(NAME_SECP521R1), + OCTSTR_ED25519 => Ok(NAME_ED25519), + OCTSTR_ED448 => Ok(NAME_ED448), + OCTSTR_X25519 => Ok(NAME_X25519), + OCTSTR_X448 => Ok(NAME_X448), + _ => Err(CKR_GENERAL_ERROR)?, + } +} + +pub fn get_ossl_name_from_obj(key: &Object) -> Result<&'static [u8]> { + let params = key + .get_attr_as_bytes(CKA_EC_PARAMS) + .map_err(general_error)?; + let ecp = + asn1::parse_single::(params).map_err(general_error)?; + match ecp { + ECParameters::OId(oid) => oid_to_ossl_name(oid), + ECParameters::CurveName(curve) => curve_to_ossl_name(curve), + _ => Err(CKR_GENERAL_ERROR)?, + } +} + +pub fn get_oid_from_obj(key: &Object) -> Result { + let params = key + .get_attr_as_bytes(CKA_EC_PARAMS) + .map_err(general_error)?; + let ecp = + asn1::parse_single::(params).map_err(general_error)?; + match ecp { + ECParameters::OId(oid) => Ok(oid), + ECParameters::CurveName(c) => curve_to_oid(c), + _ => return Err(CKR_GENERAL_ERROR)?, + } +} + +pub fn get_ec_point_from_obj(key: &Object) -> Result> { + let point = key.get_attr_as_bytes(CKA_EC_POINT).map_err(general_error)?; + /* [u8] is an octet string for the asn1 library */ + let octet = asn1::parse_single::<&[u8]>(point).map_err(device_error)?; + Ok(octet.to_vec()) +} + +#[cfg(test)] +pub fn map_curve_name(curve: &str) -> Option<&'static [u8]> { + static NAME_SECP224R1: &[u8; 11] = b"prime224v1\0"; + match curve { + "P-224" => Some(NAME_SECP224R1), + "P-256" => Some(NAME_SECP256R1), + "P-384" => Some(NAME_SECP384R1), + "P-521" => Some(NAME_SECP521R1), + _ => None, + } +} + +#[cfg(test)] +pub fn curve_name_to_ec_params(name: &[u8]) -> Result<&'static [u8]> { + match name { + NAME_SECP256R1 => Ok(OCTSTR_SECP256R1), + NAME_SECP384R1 => Ok(OCTSTR_SECP384R1), + NAME_SECP521R1 => Ok(OCTSTR_SECP521R1), + NAME_ED25519 => Ok(OCTSTR_ED25519), + NAME_ED448 => Ok(OCTSTR_ED448), + _ => Err(CKR_GENERAL_ERROR)?, + } +} diff --git a/src/fips/indicators.rs b/src/fips/indicators.rs index 75bdc8e1..ba1d85ec 100644 --- a/src/fips/indicators.rs +++ b/src/fips/indicators.rs @@ -3,7 +3,7 @@ use crate::attr_element; use crate::attribute::Attribute; -use crate::ecc::ec_key_curve_size; +use crate::ecc_misc::*; use crate::error::Result; use crate::interface::*; use crate::object::{OAFlags, Object, ObjectAttr, ObjectFactory}; @@ -900,14 +900,13 @@ fn check_key( Ok(m) => m.len(), Err(_) => return false, }, - CKK_EC => match ec_key_curve_size(obj) { - Ok(s) => btb!(s), + CKK_EC | CKK_EC_EDWARDS => match get_ossl_name_from_obj(obj) { + Ok(s) => match curve_name_to_bits(s) { + Ok(l) => l, + Err(_) => return false, + }, Err(_) => return false, }, - CKK_EC_EDWARDS => { - /* TODO */ - return false; - } _ => { /* assume everything else is a symmetric key */ match obj.get_attr_as_ulong(CKA_VALUE_LEN) { diff --git a/src/ossl/common.rs b/src/ossl/common.rs index 57d757c3..69b1df57 100644 --- a/src/ossl/common.rs +++ b/src/ossl/common.rs @@ -303,6 +303,31 @@ impl EvpPkey { pub fn privkey_from_object(obj: &object::Object) -> Result { Self::from_object(obj, CKO_PRIVATE_KEY) } + + #[cfg(not(feature = "fips"))] + pub fn get_bits(&self) -> Result { + let ret = unsafe { EVP_PKEY_get_bits(self.ptr) }; + if ret == 0 { + return Err(CKR_KEY_INDIGESTIBLE)?; + } + Ok(usize::try_from(ret)?) + } + #[cfg(feature = "fips")] + pub fn get_bits(&self) -> Result { + /* EVP_PKEY_get_bits() not available in libfips.a */ + let mut bits: c_int = 0; + let ret = unsafe { + EVP_PKEY_get_int_param( + self.ptr, + name_as_char(OSSL_PKEY_PARAM_BITS), + &mut bits, + ) + }; + if ret == 0 { + return Err(CKR_KEY_INDIGESTIBLE)?; + } + Ok(usize::try_from(bits)?) + } } impl Drop for EvpPkey { @@ -450,6 +475,7 @@ impl<'a> OsslParam<'a> { Ok(()) } + #[allow(dead_code)] pub fn add_utf8_string( &mut self, key: *const c_char, diff --git a/src/ossl/ec_montgomery.rs b/src/ossl/ec_montgomery.rs index 2dc820ac..1b04f647 100644 --- a/src/ossl/ec_montgomery.rs +++ b/src/ossl/ec_montgomery.rs @@ -5,7 +5,7 @@ use std::ffi::{c_char, c_int}; use crate::attribute::Attribute; use crate::ecc_misc::*; -use crate::error::{device_error, general_error, Result}; +use crate::error::Result; use crate::interface::*; use crate::object::Object; use crate::ossl::bindings::*; @@ -14,74 +14,6 @@ use crate::ossl::common::*; #[cfg(feature = "fips")] use crate::ossl::fips::*; -static OSSL_CURVE25519: &[u8; 7] = b"X25519\0"; -static OSSL_CURVE448: &[u8; 5] = b"X448\0"; - -pub const BITS_CURVE25519: usize = 255; -pub const BITS_CURVE448: usize = 448; - -// ASN.1 encoding of the OID -const OID_CURVE25519: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 110); -const OID_CURVE448: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 111); - -// ASN.1 encoding of the curve name -const STRING_CURVE25519: &[u8] = &[ - 0x13, 0x0a, 0x63, 0x75, 0x72, 0x76, 0x65, 0x32, 0x35, 0x35, 0x31, 0x39, -]; -const STRING_CURVE448: &[u8] = - &[0x13, 0x08, 0x63, 0x75, 0x72, 0x76, 0x65, 0x34, 0x34, 0x38]; - -fn oid_to_bits(oid: asn1::ObjectIdentifier) -> Result { - match oid { - OID_CURVE25519 => Ok(BITS_CURVE25519), - OID_CURVE448 => Ok(BITS_CURVE448), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -fn curve_name_to_bits(name: asn1::PrintableString) -> Result { - let asn1_name = match asn1::write_single(&name) { - Ok(r) => r, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - match asn1_name.as_slice() { - STRING_CURVE25519 => Ok(BITS_CURVE25519), - STRING_CURVE448 => Ok(BITS_CURVE448), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -fn make_bits_from_obj(key: &Object) -> Result { - let x = match key.get_attr_as_bytes(CKA_EC_PARAMS) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - let bits = match asn1::parse_single::(x) { - Ok(a) => match a { - ECParameters::OId(o) => oid_to_bits(o)?, - ECParameters::CurveName(c) => curve_name_to_bits(c)?, - _ => return Err(CKR_GENERAL_ERROR)?, - }, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - Ok(bits) -} - -pub fn get_ossl_name_from_obj(key: &Object) -> Result<&'static [u8]> { - match make_bits_from_obj(key) { - Ok(BITS_CURVE25519) => Ok(OSSL_CURVE25519), - Ok(BITS_CURVE448) => Ok(OSSL_CURVE448), - _ => return Err(CKR_GENERAL_ERROR)?, - } -} - -fn get_ec_point_from_obj(key: &Object) -> Result> { - let point = key.get_attr_as_bytes(CKA_EC_POINT).map_err(general_error)?; - /* [u8] is an octet string for the asn1 library */ - let octet = asn1::parse_single::<&[u8]>(point).map_err(device_error)?; - Ok(octet.to_vec()) -} - pub fn ecm_object_to_params( key: &Object, class: CK_OBJECT_CLASS, diff --git a/src/ossl/ecc.rs b/src/ossl/ecc.rs index afde8b5a..81f7a2fd 100644 --- a/src/ossl/ecc.rs +++ b/src/ossl/ecc.rs @@ -26,65 +26,6 @@ use zeroize::Zeroize; /* confusingly enough, this is not EC for FIPS-level operations */ #[cfg(feature = "fips")] static ECDSA_NAME: &[u8; 6] = b"ECDSA\0"; -pub static EC_NAME: &[u8; 3] = b"EC\0"; - -fn make_bits_from_ec_params(key: &Object) -> Result { - let x = match key.get_attr_as_bytes(CKA_EC_PARAMS) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - let bits = match asn1::parse_single::(x) { - Ok(a) => match a { - ECParameters::OId(o) => oid_to_bits(o)?, - ECParameters::CurveName(c) => curve_name_to_bits(c)?, - _ => return Err(CKR_GENERAL_ERROR)?, - }, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - Ok(bits) -} - -pub fn make_output_length_from_ecdsa_obj(key: &Object) -> Result { - let bits = match make_bits_from_ec_params(key) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - Ok(2 * ((bits + 7) / 8)) -} - -pub fn get_curve_name_from_obj(key: &Object) -> Result> { - let x = match key.get_attr_as_bytes(CKA_EC_PARAMS) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - let name = match asn1::parse_single::(x) { - Ok(a) => match a { - ECParameters::OId(o) => oid_to_curve_name(o)?, - ECParameters::CurveName(c) => c.as_str(), - _ => return Err(CKR_GENERAL_ERROR)?, - }, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - let mut curve_name = Vec::with_capacity(name.len() + 1); - curve_name.extend_from_slice(name.as_bytes()); - /* null byte terminator in c string */ - curve_name.push(0); - Ok(curve_name) -} - -fn get_ec_point_from_obj(key: &Object) -> Result> { - let x = match key.get_attr_as_bytes(CKA_EC_POINT) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - - /* [u8] is an octet string for the asn1 library */ - let octet = match asn1::parse_single::<&[u8]>(x) { - Ok(a) => a, - Err(_) => return Err(CKR_DEVICE_ERROR)?, - }; - Ok(octet.to_vec()) -} pub fn ecc_object_to_params( key: &Object, @@ -97,10 +38,9 @@ pub fn ecc_object_to_params( let mut params = OsslParam::with_capacity(2); params.zeroize = true; - let curve_name = get_curve_name_from_obj(key)?; - params.add_owned_utf8_string( + params.add_const_c_string( name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), - curve_name, + name_as_char(get_ossl_name_from_obj(key)?), )?; match kclass { @@ -247,9 +187,10 @@ impl EccOperation { _: &CK_MECHANISM_INFO, ) -> Result { let privkey = EvpPkey::privkey_from_object(key)?; + let outlen = 2 * ((privkey.get_bits()? + 7) / 8); Ok(EccOperation { mech: mech.mechanism, - output_len: make_output_length_from_ecdsa_obj(key)?, + output_len: outlen, public_key: None, private_key: Some(privkey), finalized: false, @@ -270,9 +211,10 @@ impl EccOperation { _: &CK_MECHANISM_INFO, ) -> Result { let pubkey = EvpPkey::pubkey_from_object(key)?; + let outlen = 2 * ((pubkey.get_bits()? + 7) / 8); Ok(EccOperation { mech: mech.mechanism, - output_len: make_output_length_from_ecdsa_obj(key)?, + output_len: outlen, public_key: Some(pubkey), private_key: None, finalized: false, @@ -291,11 +233,10 @@ impl EccOperation { pubkey: &mut Object, privkey: &mut Object, ) -> Result<()> { - let curve_name = get_curve_name_from_obj(pubkey)?; let mut params = OsslParam::with_capacity(1); - params.add_utf8_string( + params.add_const_c_string( name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), - &curve_name, + name_as_char(get_ossl_name_from_obj(pubkey)?), )?; params.finalize(); diff --git a/src/ossl/ecdh.rs b/src/ossl/ecdh.rs index 2aec1a01..74b352ff 100644 --- a/src/ossl/ecdh.rs +++ b/src/ossl/ecdh.rs @@ -6,16 +6,13 @@ use std::borrow::Cow; use crate::attribute::CkAttrs; use crate::bytes_to_vec; +use crate::ecc_misc::*; use crate::error::Result; use crate::interface::*; use crate::mechanism::*; use crate::object::{default_key_attributes, Object, ObjectFactories}; use crate::ossl::bindings::*; use crate::ossl::common::*; -#[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] -use crate::ossl::ec_montgomery::get_ossl_name_from_obj; -#[cfg(feature = "ecc")] -use crate::ossl::ecc::{get_curve_name_from_obj, EC_NAME}; fn kdf_type_to_hash_mech(mech: CK_EC_KDF_TYPE) -> Result { match mech { @@ -39,9 +36,9 @@ fn make_peer_key(key: &Object, ec_point: &Vec) -> Result { let name = match key.get_attr_as_ulong(CKA_KEY_TYPE)? { #[cfg(feature = "ecc")] CKK_EC => { - params.add_owned_utf8_string( + params.add_const_c_string( name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), - get_curve_name_from_obj(key)?, + name_as_char(get_ossl_name_from_obj(key)?), )?; EC_NAME } @@ -135,10 +132,7 @@ impl Derive for ECDHOperation { let factory = objfactories.get_obj_factory_from_key_template(template)?; - let raw_max = 2 - * ((usize::try_from(unsafe { EVP_PKEY_get_bits(pkey.as_ptr()) })? - + 7) - / 8); + let raw_max = 2 * ((pkey.get_bits()? + 7) / 8); /* the raw ECDH results have length of bit field length */ let keylen = match template.iter().find(|x| x.type_ == CKA_VALUE_LEN) { Some(a) => { diff --git a/src/ossl/eddsa.rs b/src/ossl/eddsa.rs index b56c1d6a..d6cd9440 100644 --- a/src/ossl/eddsa.rs +++ b/src/ossl/eddsa.rs @@ -5,7 +5,7 @@ use std::ffi::{c_char, c_int}; use crate::attribute::Attribute; use crate::ecc_misc::*; -use crate::error::{device_error, general_error, Result}; +use crate::error::Result; use crate::interface::*; use crate::mechanism::*; use crate::object::Object; @@ -23,84 +23,16 @@ use crate::ossl::get_libctx; #[cfg(feature = "fips")] static ECDSA_NAME: &[u8; 6] = b"EDDSA\0"; -static OSSL_ED25519: &[u8; 8] = b"ED25519\0"; -static OSSL_ED448: &[u8; 6] = b"ED448\0"; - -pub const BITS_ED25519: usize = 255; -pub const BITS_ED448: usize = 448; - -// ASN.1 encoding of the OID -const OID_ED25519: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 112); -const OID_ED448: asn1::ObjectIdentifier = asn1::oid!(1, 3, 101, 113); - -// ASN.1 encoding of the curve name -const STRING_ED25519: &[u8] = &[ - 0x13, 0x0c, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x35, 0x35, - 0x31, 0x39, -]; -const STRING_ED448: &[u8] = &[ - 0x13, 0x0a, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x34, 0x34, 0x38, -]; - -fn oid_to_bits(oid: asn1::ObjectIdentifier) -> Result { - match oid { - OID_ED25519 => Ok(BITS_ED25519), - OID_ED448 => Ok(BITS_ED448), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -fn curve_name_to_bits(name: asn1::PrintableString) -> Result { - let asn1_name = match asn1::write_single(&name) { - Ok(r) => r, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - match asn1_name.as_slice() { - STRING_ED25519 => Ok(BITS_ED25519), - STRING_ED448 => Ok(BITS_ED448), - _ => Err(CKR_GENERAL_ERROR)?, - } -} - -fn make_bits_from_ec_params(key: &Object) -> Result { - let x = match key.get_attr_as_bytes(CKA_EC_PARAMS) { - Ok(b) => b, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - let bits = match asn1::parse_single::(x) { - Ok(a) => match a { - ECParameters::OId(o) => oid_to_bits(o)?, - ECParameters::CurveName(c) => curve_name_to_bits(c)?, - _ => return Err(CKR_GENERAL_ERROR)?, - }, - Err(_) => return Err(CKR_GENERAL_ERROR)?, - }; - Ok(bits) -} +pub const OUTLEN_ED25519: usize = 64; +pub const OUTLEN_ED448: usize = 114; -fn get_ossl_name_from_obj(key: &Object) -> Result<&'static [u8]> { - match make_bits_from_ec_params(key) { - Ok(BITS_ED25519) => Ok(OSSL_ED25519), - Ok(BITS_ED448) => Ok(OSSL_ED448), - _ => return Err(CKR_GENERAL_ERROR)?, - } -} - -fn make_output_length_from_obj(key: &Object) -> Result { - match make_bits_from_ec_params(key) { - Ok(255) => Ok(64), - Ok(448) => Ok(114), - _ => return Err(CKR_GENERAL_ERROR)?, - } -} - -fn parse_params(mech: &CK_MECHANISM, is_448: bool) -> Result { +fn parse_params(mech: &CK_MECHANISM, outlen: usize) -> Result { if mech.mechanism != CKM_EDDSA { return Err(CKR_MECHANISM_INVALID)?; } match mech.ulParameterLen { 0 => { - if is_448 { + if outlen == OUTLEN_ED448 { Err(CKR_MECHANISM_PARAM_INVALID)? } else { Ok(no_params()) @@ -126,13 +58,6 @@ fn parse_params(mech: &CK_MECHANISM, is_448: bool) -> Result { } } -fn get_ec_point_from_obj(key: &Object) -> Result> { - let point = key.get_attr_as_bytes(CKA_EC_POINT).map_err(general_error)?; - /* [u8] is an octet string for the asn1 library */ - let octet = asn1::parse_single::<&[u8]>(point).map_err(device_error)?; - Ok(octet.to_vec()) -} - pub fn eddsa_object_to_params( key: &Object, class: CK_OBJECT_CLASS, @@ -175,14 +100,6 @@ fn no_params() -> EddsaParams { } } -fn is_448_curve(key: &Object) -> Result { - match make_bits_from_ec_params(key) { - Ok(BITS_ED25519) => Ok(false), - Ok(BITS_ED448) => Ok(true), - _ => return Err(CKR_GENERAL_ERROR)?, - } -} - macro_rules! get_sig_ctx { ($key:ident) => { /* needless match, but otherwise rust complains about experimental attributes on @@ -209,7 +126,6 @@ pub struct EddsaOperation { public_key: Option, private_key: Option, params: EddsaParams, - is448: bool, data: Vec, finalized: bool, in_use: bool, @@ -225,15 +141,14 @@ impl EddsaOperation { key: &Object, _: &CK_MECHANISM_INFO, ) -> Result { - let is_448 = is_448_curve(key)?; let privkey = EvpPkey::privkey_from_object(key)?; + let outlen = 2 * ((privkey.get_bits()? + 7) / 8); Ok(EddsaOperation { mech: mech.mechanism, - output_len: make_output_length_from_obj(key)?, + output_len: outlen, public_key: None, private_key: Some(privkey), - params: parse_params(mech, is_448)?, - is448: is_448, + params: parse_params(mech, outlen)?, data: Vec::new(), finalized: false, in_use: false, @@ -246,15 +161,14 @@ impl EddsaOperation { key: &Object, _: &CK_MECHANISM_INFO, ) -> Result { - let is_448 = is_448_curve(key)?; let pubkey = EvpPkey::pubkey_from_object(key)?; + let outlen = 2 * ((pubkey.get_bits()? + 7) / 8); Ok(EddsaOperation { mech: mech.mechanism, - output_len: make_output_length_from_obj(key)?, + output_len: outlen, public_key: Some(pubkey), private_key: None, - params: parse_params(mech, is_448)?, - is448: is_448, + params: parse_params(mech, outlen)?, data: Vec::new(), finalized: false, in_use: false, @@ -316,27 +230,20 @@ macro_rules! sig_params { }; let instance = match $op.params.ph_flag { - None => { - if $op.is448 { - return Err(CKR_GENERAL_ERROR)?; - } else { - b"Ed25519\0".to_vec() - } - } - Some(true) => { - if $op.is448 { - b"Ed448ph\0".to_vec() - } else { - b"Ed25519ph\0".to_vec() - } - } - Some(false) => { - if $op.is448 { - b"Ed448\0".to_vec() - } else { - b"Ed25519ctx\0".to_vec() - } - } + None => match $op.output_len { + OUTLEN_ED25519 => b"Ed25519\0".to_vec(), + _ => return Err(CKR_GENERAL_ERROR)?, + }, + Some(true) => match $op.output_len { + OUTLEN_ED448 => b"Ed448ph\0".to_vec(), + OUTLEN_ED25519 => b"Ed25519ph\0".to_vec(), + _ => return Err(CKR_GENERAL_ERROR)?, + }, + Some(false) => match $op.output_len { + OUTLEN_ED448 => b"Ed448\0".to_vec(), + OUTLEN_ED25519 => b"Ed25519ctx\0".to_vec(), + _ => return Err(CKR_GENERAL_ERROR)?, + }, }; params.add_owned_utf8_string( name_as_char(OSSL_SIGNATURE_PARAM_INSTANCE), diff --git a/src/tests/ecdh_vectors.rs b/src/tests/ecdh_vectors.rs index 22aaf81e..24a441b0 100644 --- a/src/tests/ecdh_vectors.rs +++ b/src/tests/ecdh_vectors.rs @@ -3,8 +3,9 @@ use std::io; use std::io::BufRead; +use std::str::from_utf8; -use crate::ecc; +use crate::ecc_misc; use crate::tests::*; use serial_test::parallel; @@ -20,7 +21,7 @@ struct EccKey { struct EcdhTestUnit { line: usize, count: usize, - curve_name: &'static str, + curve_name: &'static [u8], ec_params: &'static [u8], cavs: EccKey, iut: EccKey, @@ -29,19 +30,6 @@ struct EcdhTestUnit { errno: u8, } -// defined here for completing parsing -- not used as this curve is not supported -const NAME_SECP224R1: &str = "prime224v1"; - -fn map_curve(curve: &str) -> Option<&'static str> { - match curve { - "P-224" => Some(NAME_SECP224R1), - "P-256" => Some(ecc::NAME_SECP256R1), - "P-384" => Some(ecc::NAME_SECP384R1), - "P-521" => Some(ecc::NAME_SECP521R1), - _ => None, - } -} - enum EcdhParserState { StateParams, StateCurves, @@ -53,7 +41,7 @@ fn parse_ecdh_vector(filename: &str) -> Vec { let mut data = Vec::::new(); let mut tags = Vec::::new(); - let mut sets = HashMap::::new(); + let mut sets = HashMap::::new(); let mut tag = None; let mut curve = None; let mut tagg = String::new(); @@ -87,9 +75,14 @@ fn parse_ecdh_vector(filename: &str) -> Vec { tag = Some(line.clone()); curve = None; } else if line.starts_with(kw) { - curve = map_curve(&line[kw.len()..line.len() - 1]); + curve = ecc_misc::map_curve_name( + &line[kw.len()..line.len() - 1], + ); if curve != None { - println!(" : {} Matched", curve.unwrap()); + println!( + " : {} Matched", + from_utf8(curve.unwrap()).unwrap() + ); } } @@ -97,7 +90,11 @@ fn parse_ecdh_vector(filename: &str) -> Vec { Some(ref t) => match curve { Some(c) => { sets.insert(t.clone(), c); - println!(" : {} -> {} Mapped", t, c); + println!( + " : {} -> {} Mapped", + t, + from_utf8(c).unwrap() + ); tag = None; } _ => (), @@ -113,11 +110,15 @@ fn parse_ecdh_vector(filename: &str) -> Vec { if line.starts_with("[") { tagg = format!("[{}]", &line[1..3]); } else if line.starts_with("COUNT = ") { - let curve_name = - sets.get(&tagg).expect("Failed to parse tag to string"); - println!(" : curve_name = {}", curve_name); + let curve_name = sets + .get(&tagg) + .expect("Failed to parse tag to curve name"); + println!( + " : curve_name = {}", + from_utf8(curve_name).unwrap() + ); let ec_params = - match ecc::curve_name_to_ec_params(curve_name) { + match ecc_misc::curve_name_to_ec_params(curve_name) { Ok(p) => p, Err(_) => continue, /* skip unsupported */ }; @@ -190,12 +191,12 @@ fn parse_ecdh_vector(filename: &str) -> Vec { data } -fn test_to_ecc_point(key: &EccKey, curve_name: &'static str) -> Vec { +fn test_to_ecc_point(key: &EccKey, curve_name: &'static [u8]) -> Vec { let mut ec_point = Vec::::with_capacity(key.x.len() + key.y.len() + 1); ec_point.push(0x04); /* The P-521 curve points are heavily zero padded so we need to make sure they are well * formatted for OpenSSL -- to the field length boundary */ - let field_len = match ecc::name_to_bits(curve_name) { + let field_len = match ecc_misc::curve_name_to_bits(curve_name) { Ok(l) => l, Err(_) => panic!("Unknown curve given"), }; @@ -222,7 +223,9 @@ fn test_ecdh_units(session: CK_SESSION_HANDLE, test_data: Vec) { CKA_LABEL, format!( "{} private key, COUNT={}, line {}", - unit.curve_name, unit.count, unit.line + from_utf8(unit.curve_name).unwrap(), + unit.count, + unit.line ) .as_bytes() ) @@ -243,7 +246,9 @@ fn test_ecdh_units(session: CK_SESSION_HANDLE, test_data: Vec) { CKA_LABEL, format!( "{} public key, COUNT={}, line {}", - unit.curve_name, unit.count, unit.line + from_utf8(unit.curve_name).unwrap(), + unit.count, + unit.line ) .as_bytes() ) From 27368b3c4bd81092f99ca55743db8c8a613a9129 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 19 Nov 2024 18:36:31 -0500 Subject: [PATCH 4/6] Turn macro into a function Signed-off-by: Simo Sorce --- src/ossl/eddsa.rs | 77 ++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/src/ossl/eddsa.rs b/src/ossl/eddsa.rs index d6cd9440..606ec8a2 100644 --- a/src/ossl/eddsa.rs +++ b/src/ossl/eddsa.rs @@ -215,43 +215,44 @@ impl EddsaOperation { } } -macro_rules! sig_params { - ($op:expr) => {{ - let mut params = OsslParam::with_capacity(2); - params.zeroize = true; - match &$op.params.context_data { - Some(v) => { - params.add_octet_string( - name_as_char(OSSL_SIGNATURE_PARAM_CONTEXT_STRING), - &v, - )?; - } - _ => (), - }; +fn sig_params<'a>( + eddsa_params: &'a EddsaParams, + outlen: usize, +) -> Result> { + let mut params = OsslParam::with_capacity(2); + params.zeroize = true; + match &eddsa_params.context_data { + Some(v) => { + params.add_octet_string( + name_as_char(OSSL_SIGNATURE_PARAM_CONTEXT_STRING), + &v, + )?; + } + _ => (), + }; - let instance = match $op.params.ph_flag { - None => match $op.output_len { - OUTLEN_ED25519 => b"Ed25519\0".to_vec(), - _ => return Err(CKR_GENERAL_ERROR)?, - }, - Some(true) => match $op.output_len { - OUTLEN_ED448 => b"Ed448ph\0".to_vec(), - OUTLEN_ED25519 => b"Ed25519ph\0".to_vec(), - _ => return Err(CKR_GENERAL_ERROR)?, - }, - Some(false) => match $op.output_len { - OUTLEN_ED448 => b"Ed448\0".to_vec(), - OUTLEN_ED25519 => b"Ed25519ctx\0".to_vec(), - _ => return Err(CKR_GENERAL_ERROR)?, - }, - }; - params.add_owned_utf8_string( - name_as_char(OSSL_SIGNATURE_PARAM_INSTANCE), - instance, - )?; - params.finalize(); - params - }}; + let instance = match eddsa_params.ph_flag { + None => match outlen { + OUTLEN_ED25519 => b"Ed25519\0".to_vec(), + _ => return Err(CKR_GENERAL_ERROR)?, + }, + Some(true) => match outlen { + OUTLEN_ED448 => b"Ed448ph\0".to_vec(), + OUTLEN_ED25519 => b"Ed25519ph\0".to_vec(), + _ => return Err(CKR_GENERAL_ERROR)?, + }, + Some(false) => match outlen { + OUTLEN_ED448 => b"Ed448\0".to_vec(), + OUTLEN_ED25519 => b"Ed25519ctx\0".to_vec(), + _ => return Err(CKR_GENERAL_ERROR)?, + }, + }; + params.add_owned_utf8_string( + name_as_char(OSSL_SIGNATURE_PARAM_INSTANCE), + instance, + )?; + params.finalize(); + Ok(params) } impl MechOperation for EddsaOperation { @@ -283,7 +284,7 @@ impl Sign for EddsaOperation { if !self.in_use { self.in_use = true; - let mut params = sig_params!(self); + let mut params = sig_params(&self.params, self.output_len)?; #[cfg(not(feature = "fips"))] if unsafe { @@ -383,7 +384,7 @@ impl Verify for EddsaOperation { if !self.in_use { self.in_use = true; - let mut params = sig_params!(self); + let mut params = sig_params(&self.params, self.output_len)?; #[cfg(not(feature = "fips"))] if unsafe { From 90368a61457f31cddea08f6d14a65031e4310cd5 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 19 Nov 2024 23:27:33 -0500 Subject: [PATCH 5/6] Reorganize EC code to its own directory Also fixes feature detection to be more straightforward Signed-off-by: Simo Sorce --- .github/workflows/build.yml | 4 +-- Cargo.toml | 7 ++-- src/{ => ec}/ecdh.rs | 2 +- src/{ecc.rs => ec/ecdsa.rs} | 9 +++-- src/{ => ec}/eddsa.rs | 2 +- src/{ecc_misc.rs => ec/mod.rs} | 20 +++++++++-- src/{ec_montgomery.rs => ec/montgomery.rs} | 5 +-- src/enabled.rs | 38 +++++++++----------- src/fips/indicators.rs | 2 +- src/ossl/common.rs | 18 +++++----- src/ossl/ecdh.rs | 6 ++-- src/ossl/{ecc.rs => ecdsa.rs} | 4 +-- src/ossl/eddsa.rs | 6 +--- src/ossl/mod.rs | 12 +++---- src/ossl/{ec_montgomery.rs => montgomery.rs} | 5 +-- src/tests/ecdh_vectors.rs | 10 +++--- src/tests/keys.rs | 2 +- src/tests/mod.rs | 10 +++--- src/tests/signatures.rs | 2 +- 19 files changed, 82 insertions(+), 82 deletions(-) rename src/{ => ec}/ecdh.rs (96%) rename src/{ecc.rs => ec/ecdsa.rs} (98%) rename src/{ => ec}/eddsa.rs (99%) rename src/{ecc_misc.rs => ec/mod.rs} (95%) rename src/{ec_montgomery.rs => ec/montgomery.rs} (97%) rename src/ossl/{ecc.rs => ecdsa.rs} (99%) rename src/ossl/{ec_montgomery.rs => montgomery.rs} (96%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e55dcf35..629ebeb1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,7 +78,7 @@ jobs: - name: Build run: | if [ "${{ matrix.name }}" = "fips" ]; then - cargo build -vv --features fips + cargo build -vv --no-default-features --features fips fi if [ "${{ matrix.name }}" = "ossl3" ]; then cargo build -vv @@ -93,7 +93,7 @@ jobs: - name: Test run: | if [ "${{ matrix.name }}" = "fips" ]; then - cargo test --features fips + cargo test --no-default-features --features fips fi if [ "${{ matrix.name }}" = "ossl3" ]; then cargo test diff --git a/Cargo.toml b/Cargo.toml index fe62d4ef..c38b6d87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,8 @@ zeroize = "1.6.0" [features] aes = [] -ecc = [] +ecdsa = [] +ecdh = [] eddsa = [] ec_montgomery = [] hash = [] @@ -70,9 +71,9 @@ basic = [ "aes", "hmac", "pbkdf2", "sqlitedb" ] #select everything by default # Use --no-default-features --features basic, xxx for custom selections -default = [ "basic", "ecc", "ec_montgomery", "eddsa", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] +default = [ "basic", "ecdsa", "ec_montgomery", "eddsa", "ecdh", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] -fips = [ "rusqlite/bundled", "basic", "ecc", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] +fips = [ "rusqlite/bundled", "basic", "ecdsa", "ecdh", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] dynamic = [ ] # Builds against system libcrypto.so diff --git a/src/ecdh.rs b/src/ec/ecdh.rs similarity index 96% rename from src/ecdh.rs rename to src/ec/ecdh.rs index bcdeee2f..3980afe9 100644 --- a/src/ecdh.rs +++ b/src/ec/ecdh.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; -use crate::ecc::*; +use crate::ec::ecdsa::{MAX_EC_SIZE_BITS, MIN_EC_SIZE_BITS}; use crate::error::Result; use crate::interface::*; use crate::mechanism::{Mechanism, Mechanisms, Operation}; diff --git a/src/ecc.rs b/src/ec/ecdsa.rs similarity index 98% rename from src/ecc.rs rename to src/ec/ecdsa.rs index 9ffca012..a45ea7a5 100644 --- a/src/ecc.rs +++ b/src/ec/ecdsa.rs @@ -4,20 +4,19 @@ use std::fmt::Debug; use crate::attribute::Attribute; -use crate::ecc_misc::*; +use crate::ec::*; use crate::error::Result; -use crate::interface::*; use crate::kasn1::PrivateKeyInfo; use crate::mechanism::*; use crate::object::*; -use crate::ossl::ecc::EccOperation; +use crate::ossl::ecdsa::EccOperation; use crate::{attr_element, bytes_attr_not_empty}; use asn1; use once_cell::sync::Lazy; -pub const MIN_EC_SIZE_BITS: usize = 256; -pub const MAX_EC_SIZE_BITS: usize = 521; +pub const MIN_EC_SIZE_BITS: usize = BITS_SECP256R1; +pub const MAX_EC_SIZE_BITS: usize = BITS_SECP521R1; #[derive(Debug)] pub struct ECCPubFactory { diff --git a/src/eddsa.rs b/src/ec/eddsa.rs similarity index 99% rename from src/eddsa.rs rename to src/ec/eddsa.rs index 12dd9c23..986bfa89 100644 --- a/src/eddsa.rs +++ b/src/ec/eddsa.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use crate::attribute::Attribute; -use crate::ecc_misc::*; +use crate::ec::{ec_key_check_import, BITS_ED25519, BITS_ED448}; use crate::error::Result; use crate::interface::*; use crate::mechanism::*; diff --git a/src/ecc_misc.rs b/src/ec/mod.rs similarity index 95% rename from src/ecc_misc.rs rename to src/ec/mod.rs index 92f20738..e19c6d15 100644 --- a/src/ecc_misc.rs +++ b/src/ec/mod.rs @@ -9,6 +9,18 @@ use crate::object::Object; use asn1; +#[cfg(feature = "ecdh")] +pub mod ecdh; + +#[cfg(feature = "ecdsa")] +pub mod ecdsa; + +#[cfg(feature = "eddsa")] +pub mod eddsa; + +#[cfg(feature = "ec_montgomery")] +pub mod montgomery; + type Version = u64; #[derive(asn1::Asn1Read, asn1::Asn1Write)] @@ -48,9 +60,10 @@ pub fn ec_key_check_import(obj: &mut Object) -> Result<()> { } // Bit sized for curves -const BITS_SECP256R1: usize = 256; -const BITS_SECP384R1: usize = 384; -const BITS_SECP521R1: usize = 521; +pub const BITS_SECP256R1: usize = 256; +#[allow(dead_code)] +pub const BITS_SECP384R1: usize = 384; +pub const BITS_SECP521R1: usize = 521; pub const BITS_ED25519: usize = 256; pub const BITS_ED448: usize = 448; pub const BITS_X25519: usize = 256; @@ -99,6 +112,7 @@ const NAME_X448: &[u8] = b"X448\0"; pub static EC_NAME: &[u8; 3] = b"EC\0"; +#[cfg(any(test, feature = "fips"))] pub fn curve_name_to_bits(name: &[u8]) -> Result { match name { NAME_SECP256R1 => Ok(BITS_SECP256R1), diff --git a/src/ec_montgomery.rs b/src/ec/montgomery.rs similarity index 97% rename from src/ec_montgomery.rs rename to src/ec/montgomery.rs index 3479c5b2..e609978c 100644 --- a/src/ec_montgomery.rs +++ b/src/ec/montgomery.rs @@ -4,12 +4,13 @@ use std::fmt::Debug; use crate::attribute::Attribute; -use crate::ecc_misc::*; +use crate::ec::montgomery::montgomery::ECMontgomeryOperation; +use crate::ec::{ec_key_check_import, BITS_X25519, BITS_X448}; use crate::error::Result; use crate::interface::*; use crate::mechanism::*; use crate::object::*; -use crate::ossl::ec_montgomery::*; +use crate::ossl::montgomery; use crate::{attr_element, bytes_attr_not_empty}; use once_cell::sync::Lazy; diff --git a/src/enabled.rs b/src/enabled.rs index c316866c..538b322f 100644 --- a/src/enabled.rs +++ b/src/enabled.rs @@ -4,23 +4,17 @@ #[cfg(all(feature = "dynamic", feature = "fips"))] compile_error!("Feature 'dynamic' and 'fips' are mutually exclusive and cannot be enabled together"); +#[cfg(all( + feature = "ecdh", + not(any(feature = "ecdsa", feature = "ec_montgomery")) +))] +compile_error!("Feature 'ecdh' requires either 'ecdsa' or 'ec_montgomery'"); + #[cfg(feature = "aes")] mod aes; -#[cfg(feature = "ecc")] -mod ecc; - -#[cfg(any(feature = "ecc", feature = "eddsa"))] -mod ecc_misc; - -#[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] -mod ec_montgomery; - -#[cfg(any(feature = "ec_montgomery", feature = "ecc"))] -mod ecdh; - -#[cfg(all(feature = "eddsa", not(feature = "fips")))] -mod eddsa; +#[cfg(any(feature = "ecdsa", feature = "eddsa", feature = "ec_montgomery"))] +mod ec; #[cfg(feature = "hash")] mod hash; @@ -55,17 +49,17 @@ pub fn register_all(mechs: &mut Mechanisms, ot: &mut ObjectFactories) { #[cfg(feature = "aes")] aes::register(mechs, ot); - #[cfg(feature = "ecc")] - ecc::register(mechs, ot); + #[cfg(feature = "ecdsa")] + ec::ecdsa::register(mechs, ot); - #[cfg(any(feature = "ec_montgomery", feature = "ecc"))] - ecdh::register(mechs, ot); + #[cfg(feature = "ecdh")] + ec::ecdh::register(mechs, ot); - #[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] - ec_montgomery::register(mechs, ot); + #[cfg(feature = "ec_montgomery")] + ec::montgomery::register(mechs, ot); - #[cfg(all(feature = "eddsa", not(feature = "fips")))] - eddsa::register(mechs, ot); + #[cfg(feature = "eddsa")] + ec::eddsa::register(mechs, ot); #[cfg(feature = "hash")] hash::register(mechs, ot); diff --git a/src/fips/indicators.rs b/src/fips/indicators.rs index ba1d85ec..ddcf4b4c 100644 --- a/src/fips/indicators.rs +++ b/src/fips/indicators.rs @@ -3,7 +3,7 @@ use crate::attr_element; use crate::attribute::Attribute; -use crate::ecc_misc::*; +use crate::ec::{curve_name_to_bits, get_ossl_name_from_obj}; use crate::error::Result; use crate::interface::*; use crate::object::{OAFlags, Object, ObjectAttr, ObjectFactory}; diff --git a/src/ossl/common.rs b/src/ossl/common.rs index 69b1df57..a6bdd1eb 100644 --- a/src/ossl/common.rs +++ b/src/ossl/common.rs @@ -11,12 +11,12 @@ use crate::ossl::bindings::*; use crate::ossl::get_libctx; use crate::{byte_ptr, void_ptr}; -#[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] -use crate::ossl::ec_montgomery as ecm; -#[cfg(feature = "ecc")] -use crate::ossl::ecc; -#[cfg(all(feature = "eddsa", not(feature = "fips")))] +#[cfg(feature = "ecdsa")] +use crate::ossl::ecdsa; +#[cfg(feature = "eddsa")] use crate::ossl::eddsa; +#[cfg(feature = "ec_montgomery")] +use crate::ossl::montgomery as ecm; #[cfg(feature = "rsa")] use crate::ossl::rsa; @@ -283,11 +283,11 @@ impl EvpPkey { }; let key_type = obj.get_attr_as_ulong(CKA_KEY_TYPE)?; let (name, params) = match key_type { - #[cfg(feature = "ecc")] - CKK_EC => ecc::ecc_object_to_params(obj, class)?, - #[cfg(all(feature = "eddsa", not(feature = "fips")))] + #[cfg(feature = "ecdsa")] + CKK_EC => ecdsa::ecc_object_to_params(obj, class)?, + #[cfg(feature = "eddsa")] CKK_EC_EDWARDS => eddsa::eddsa_object_to_params(obj, class)?, - #[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] + #[cfg(feature = "ec_montgomery")] CKK_EC_MONTGOMERY => ecm::ecm_object_to_params(obj, class)?, #[cfg(feature = "rsa")] CKK_RSA => rsa::rsa_object_to_params(obj, class)?, diff --git a/src/ossl/ecdh.rs b/src/ossl/ecdh.rs index 74b352ff..4629f5c4 100644 --- a/src/ossl/ecdh.rs +++ b/src/ossl/ecdh.rs @@ -6,7 +6,7 @@ use std::borrow::Cow; use crate::attribute::CkAttrs; use crate::bytes_to_vec; -use crate::ecc_misc::*; +use crate::ec::{get_ossl_name_from_obj, EC_NAME}; use crate::error::Result; use crate::interface::*; use crate::mechanism::*; @@ -34,7 +34,7 @@ fn make_peer_key(key: &Object, ec_point: &Vec) -> Result { params.zeroize = true; let name = match key.get_attr_as_ulong(CKA_KEY_TYPE)? { - #[cfg(feature = "ecc")] + #[cfg(feature = "ecdsa")] CKK_EC => { params.add_const_c_string( name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), @@ -42,7 +42,7 @@ fn make_peer_key(key: &Object, ec_point: &Vec) -> Result { )?; EC_NAME } - #[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] + #[cfg(feature = "ec_montgomery")] CKK_EC_MONTGOMERY => get_ossl_name_from_obj(key)?, _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, }; diff --git a/src/ossl/ecc.rs b/src/ossl/ecdsa.rs similarity index 99% rename from src/ossl/ecc.rs rename to src/ossl/ecdsa.rs index 81f7a2fd..4c4211c7 100644 --- a/src/ossl/ecc.rs +++ b/src/ossl/ecdsa.rs @@ -4,8 +4,8 @@ use core::ffi::{c_char, c_int}; use crate::attribute::Attribute; -use crate::ecc::*; -use crate::ecc_misc::*; +use crate::ec::ecdsa::*; +use crate::ec::{get_ec_point_from_obj, get_ossl_name_from_obj, EC_NAME}; use crate::error::Result; use crate::interface::*; use crate::kasn1::DerEncBigUint; diff --git a/src/ossl/eddsa.rs b/src/ossl/eddsa.rs index 606ec8a2..29f429e5 100644 --- a/src/ossl/eddsa.rs +++ b/src/ossl/eddsa.rs @@ -4,7 +4,7 @@ use std::ffi::{c_char, c_int}; use crate::attribute::Attribute; -use crate::ecc_misc::*; +use crate::ec::{get_ec_point_from_obj, get_ossl_name_from_obj}; use crate::error::Result; use crate::interface::*; use crate::mechanism::*; @@ -19,10 +19,6 @@ use crate::ossl::fips::*; #[cfg(not(feature = "fips"))] use crate::ossl::get_libctx; -/* confusingly enough, this is not EC for FIPS-level operations */ -#[cfg(feature = "fips")] -static ECDSA_NAME: &[u8; 6] = b"EDDSA\0"; - pub const OUTLEN_ED25519: usize = 64; pub const OUTLEN_ED448: usize = 114; diff --git a/src/ossl/mod.rs b/src/ossl/mod.rs index e8058125..a87a020f 100644 --- a/src/ossl/mod.rs +++ b/src/ossl/mod.rs @@ -33,16 +33,16 @@ pub mod common; pub mod drbg; // the derive code for both ECDSA and Montgomery curves -#[cfg(any(feature = "ecc", feature = "ec_montgomery"))] +#[cfg(feature = "ecdh")] pub mod ecdh; -#[cfg(feature = "ecc")] -pub mod ecc; +#[cfg(feature = "ecdsa")] +pub mod ecdsa; -#[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] -pub mod ec_montgomery; +#[cfg(feature = "ec_montgomery")] +pub mod montgomery; -#[cfg(all(feature = "eddsa", not(feature = "fips")))] +#[cfg(feature = "eddsa")] pub mod eddsa; #[cfg(feature = "fips")] diff --git a/src/ossl/ec_montgomery.rs b/src/ossl/montgomery.rs similarity index 96% rename from src/ossl/ec_montgomery.rs rename to src/ossl/montgomery.rs index 1b04f647..221a19f5 100644 --- a/src/ossl/ec_montgomery.rs +++ b/src/ossl/montgomery.rs @@ -4,16 +4,13 @@ use std::ffi::{c_char, c_int}; use crate::attribute::Attribute; -use crate::ecc_misc::*; +use crate::ec::{get_ec_point_from_obj, get_ossl_name_from_obj}; use crate::error::Result; use crate::interface::*; use crate::object::Object; use crate::ossl::bindings::*; use crate::ossl::common::*; -#[cfg(feature = "fips")] -use crate::ossl::fips::*; - pub fn ecm_object_to_params( key: &Object, class: CK_OBJECT_CLASS, diff --git a/src/tests/ecdh_vectors.rs b/src/tests/ecdh_vectors.rs index 24a441b0..896864e6 100644 --- a/src/tests/ecdh_vectors.rs +++ b/src/tests/ecdh_vectors.rs @@ -5,7 +5,7 @@ use std::io; use std::io::BufRead; use std::str::from_utf8; -use crate::ecc_misc; +use crate::ec; use crate::tests::*; use serial_test::parallel; @@ -75,9 +75,7 @@ fn parse_ecdh_vector(filename: &str) -> Vec { tag = Some(line.clone()); curve = None; } else if line.starts_with(kw) { - curve = ecc_misc::map_curve_name( - &line[kw.len()..line.len() - 1], - ); + curve = ec::map_curve_name(&line[kw.len()..line.len() - 1]); if curve != None { println!( " : {} Matched", @@ -118,7 +116,7 @@ fn parse_ecdh_vector(filename: &str) -> Vec { from_utf8(curve_name).unwrap() ); let ec_params = - match ecc_misc::curve_name_to_ec_params(curve_name) { + match ec::curve_name_to_ec_params(curve_name) { Ok(p) => p, Err(_) => continue, /* skip unsupported */ }; @@ -196,7 +194,7 @@ fn test_to_ecc_point(key: &EccKey, curve_name: &'static [u8]) -> Vec { ec_point.push(0x04); /* The P-521 curve points are heavily zero padded so we need to make sure they are well * formatted for OpenSSL -- to the field length boundary */ - let field_len = match ecc_misc::curve_name_to_bits(curve_name) { + let field_len = match ec::curve_name_to_bits(curve_name) { Ok(l) => l, Err(_) => panic!("Unknown curve given"), }; diff --git a/src/tests/keys.rs b/src/tests/keys.rs index cc9fdd2a..bd8cd238 100644 --- a/src/tests/keys.rs +++ b/src/tests/keys.rs @@ -340,7 +340,7 @@ fn test_rsa_key() { testtokn.finalize(); } -#[cfg(feature = "ecc")] +#[cfg(feature = "ecdsa")] #[test] #[parallel] fn test_ecc_key() { diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 29e3a146..888980b5 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -250,19 +250,19 @@ mod rsa; mod session; -#[cfg(feature = "ecc")] +#[cfg(feature = "ecdsa")] mod ecc; -#[cfg(all(feature = "ec_montgomery", not(feature = "fips")))] +#[cfg(feature = "ec_montgomery")] mod ec_montgomery; -#[cfg(feature = "ecc")] +#[cfg(feature = "ecdh")] mod ecdh; -#[cfg(feature = "ecc")] +#[cfg(feature = "ecdh")] mod ecdh_vectors; -#[cfg(all(feature = "eddsa", not(feature = "fips")))] +#[cfg(feature = "eddsa")] mod eddsa; #[cfg(feature = "hash")] diff --git a/src/tests/signatures.rs b/src/tests/signatures.rs index 73b4b001..447ce3a7 100644 --- a/src/tests/signatures.rs +++ b/src/tests/signatures.rs @@ -126,7 +126,7 @@ fn test_rsa_signatures() { testtokn.finalize(); } -#[cfg(feature = "ecc")] +#[cfg(feature = "ecdsa")] #[test] #[parallel] fn test_ecc_signatures() { From a7931452030f953ed18c648f8186153f4eebeae5 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 19 Nov 2024 23:57:26 -0500 Subject: [PATCH 6/6] Introduce the "standard" feature The 'default' features are always enabled regardless of which build features are requested, forcing ugly cfg statement to exclude specific features when incompatible ones are selected, like "fips". Instead of always compiling all mechanisms by default, introduce a "standard" features that replaces the old "default". Change packaging and CI to use "standard" everywhere we implied the use the "default" feature set before. Signed-off-by: Simo Sorce --- .github/workflows/build.yml | 18 +++++++++--------- Cargo.toml | 8 +++----- packaging/kryoptic.spec | 12 ++++++------ 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 629ebeb1..ec537634 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,34 +78,34 @@ jobs: - name: Build run: | if [ "${{ matrix.name }}" = "fips" ]; then - cargo build -vv --no-default-features --features fips + cargo build -vv --features fips fi if [ "${{ matrix.name }}" = "ossl3" ]; then - cargo build -vv + cargo build -vv --features standard fi if [ "${{ matrix.name }}" = "release" ]; then - cargo build -vv --release + cargo build -vv --release --features standard fi if [ "${{ matrix.name }}" = "dynamic" ]; then - cargo build -vv --release --features dynamic + cargo build -vv --release --features standard,dynamic fi - name: Test run: | if [ "${{ matrix.name }}" = "fips" ]; then - cargo test --no-default-features --features fips + cargo test --features fips fi if [ "${{ matrix.name }}" = "ossl3" ]; then - cargo test + cargo test --features standard fi if [ "${{ matrix.name }}" = "release" ]; then - cargo test --release + cargo test --release --features standard fi if [ "${{ matrix.name }}" = "dynamic" ]; then - cargo test --release --features dynamic + cargo test --release --features standard,dynamic fi if [ "${{ matrix.name }}" = "i686" ]; then - cargo test --target i686-unknown-linux-gnu --features dynamic + cargo test --target i686-unknown-linux-gnu --features standard,dynamic fi - uses: actions/upload-artifact@v3 diff --git a/Cargo.toml b/Cargo.toml index c38b6d87..74534fbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,13 +67,11 @@ memorydb = [] sqlitedb = ["dep:rusqlite"] # these are always required, so easier to specify this way -basic = [ "aes", "hmac", "pbkdf2", "sqlitedb" ] +default = [ "aes", "hmac", "pbkdf2", "sqlitedb" ] -#select everything by default -# Use --no-default-features --features basic, xxx for custom selections -default = [ "basic", "ecdsa", "ec_montgomery", "eddsa", "ecdh", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] +standard = [ "ecdsa", "ec_montgomery", "eddsa", "ecdh", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] -fips = [ "rusqlite/bundled", "basic", "ecdsa", "ecdh", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] +fips = [ "rusqlite/bundled", "ecdsa", "ecdh", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] dynamic = [ ] # Builds against system libcrypto.so diff --git a/packaging/kryoptic.spec b/packaging/kryoptic.spec index 376041fb..6693a9fb 100644 --- a/packaging/kryoptic.spec +++ b/packaging/kryoptic.spec @@ -44,20 +44,20 @@ A PKCS #11 software token written in Rust.} %cargo_prep %generate_buildrequires -%cargo_generate_buildrequires -f dynamic +%cargo_generate_buildrequires -f standard,dynamic %build -CONFDIR=%{_sysconfdir} %cargo_build -f dynamic -%{cargo_license_summary -f dynamic} -%{cargo_license -f dynamic} > LICENSE.dependencies +CONFDIR=%{_sysconfdir} %cargo_build -f standard,dynamic +%{cargo_license_summary -f standard,dynamic} +%{cargo_license -f standard,dynamic} > LICENSE.dependencies %install -%cargo_install -f dynamic +%cargo_install -f standard,dynamic install -Dp target/rpm/libkryoptic_pkcs11.so $RPM_BUILD_ROOT/%{_libdir}/libkryoptic_pkcs11.so %if %{with check} %check -%cargo_test -f dynamic +%cargo_test -f standard,dynamic %endif %files