diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e55dcf35..ec537634 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -81,13 +81,13 @@ jobs: 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 @@ -96,16 +96,16 @@ jobs: 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 fe62d4ef..74534fbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,8 @@ zeroize = "1.6.0" [features] aes = [] -ecc = [] +ecdsa = [] +ecdh = [] eddsa = [] ec_montgomery = [] hash = [] @@ -66,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", "ecc", "ec_montgomery", "eddsa", "hash", "hkdf", "rsa", "sp800_108", "sshkdf", "tlskdf"] +standard = [ "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", "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 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 71% rename from src/ecc.rs rename to src/ec/ecdsa.rs index 79a8bb60..a45ea7a5 100644 --- a/src/ecc.rs +++ b/src/ec/ecdsa.rs @@ -4,127 +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; - -// 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)?, - } -} +pub const MIN_EC_SIZE_BITS: usize = BITS_SECP256R1; +pub const MAX_EC_SIZE_BITS: usize = BITS_SECP521R1; #[derive(Debug)] pub struct ECCPubFactory { @@ -234,21 +126,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/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/ec/mod.rs b/src/ec/mod.rs new file mode 100644 index 00000000..e19c6d15 --- /dev/null +++ b/src/ec/mod.rs @@ -0,0 +1,223 @@ +// Copyright 2023 - 2024 Simo Sorce, Jakub Jelen +// See LICENSE.txt file for terms + +use crate::bytes_attr_not_empty; +use crate::error::{device_error, general_error, Result}; +use crate::interface::*; +use crate::kasn1::DerEncOctetString; +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)] +pub enum ECParameters<'a> { + // ecParametdders ECParameters, + OId(asn1::ObjectIdentifier), + ImplicitlyCA(asn1::Null), + CurveName(asn1::PrintableString<'a>), +} + +/// Defined in SECG SEC 1, C.4 +#[derive(asn1::Asn1Read, asn1::Asn1Write)] +pub struct ECPrivateKey<'a> { + version: Version, + pub private_key: DerEncOctetString<'a>, + #[explicit(0)] + parameters: Option>, + #[explicit(1)] + public_key: Option>, +} + +impl ECPrivateKey<'_> { + pub fn new_owned<'a>(private_key: &'a Vec) -> Result> { + Ok(ECPrivateKey { + version: 1, + private_key: DerEncOctetString::new(private_key.as_slice())?, + parameters: None, + public_key: None, + }) + } +} + +pub fn ec_key_check_import(obj: &mut Object) -> Result<()> { + bytes_attr_not_empty!(obj; CKA_EC_PARAMS); + bytes_attr_not_empty!(obj; CKA_VALUE); + Ok(()) +} + +// Bit sized for curves +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; +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"; + +#[cfg(any(test, feature = "fips"))] +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/ec_montgomery.rs b/src/ec/montgomery.rs similarity index 96% rename from src/ec_montgomery.rs rename to src/ec/montgomery.rs index 2623ce20..e609978c 100644 --- a/src/ec_montgomery.rs +++ b/src/ec/montgomery.rs @@ -4,18 +4,19 @@ 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; -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_misc.rs b/src/ecc_misc.rs deleted file mode 100644 index f61c6386..00000000 --- a/src/ecc_misc.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2023 - 2024 Simo Sorce, Jakub Jelen -// See LICENSE.txt file for terms - -use crate::bytes_attr_not_empty; -use crate::error::Result; -use crate::interface::*; -use crate::kasn1::DerEncOctetString; -use crate::object::Object; - -type Version = u64; - -#[derive(asn1::Asn1Read, asn1::Asn1Write)] -pub enum ECParameters<'a> { - // ecParametdders ECParameters, - OId(asn1::ObjectIdentifier), - ImplicitlyCA(asn1::Null), - CurveName(asn1::PrintableString<'a>), -} - -/// Defined in SECG SEC 1, C.4 -#[derive(asn1::Asn1Read, asn1::Asn1Write)] -pub struct ECPrivateKey<'a> { - version: Version, - pub private_key: DerEncOctetString<'a>, - #[explicit(0)] - parameters: Option>, - #[explicit(1)] - public_key: Option>, -} - -impl ECPrivateKey<'_> { - pub fn new_owned<'a>(private_key: &'a Vec) -> Result> { - Ok(ECPrivateKey { - version: 1, - private_key: DerEncOctetString::new(private_key.as_slice())?, - parameters: None, - public_key: None, - }) - } -} - -pub fn ec_key_check_import(obj: &mut Object) -> Result<()> { - bytes_attr_not_empty!(obj; CKA_EC_PARAMS); - bytes_attr_not_empty!(obj; CKA_VALUE); - Ok(()) -} 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/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) +} diff --git a/src/fips/indicators.rs b/src/fips/indicators.rs index 75bdc8e1..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::ec_key_curve_size; +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}; @@ -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 014c6422..a6bdd1eb 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(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; + use zeroize::Zeroize; macro_rules! ptr_wrapper_struct { @@ -261,6 +271,63 @@ 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 = "ecdsa")] + CKK_EC => ecdsa::ecc_object_to_params(obj, class)?, + #[cfg(feature = "eddsa")] + CKK_EC_EDWARDS => eddsa::eddsa_object_to_params(obj, class)?, + #[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)?, + _ => 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) + } + + #[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 { @@ -408,6 +475,7 @@ impl<'a> OsslParam<'a> { Ok(()) } + #[allow(dead_code)] pub fn add_utf8_string( &mut self, key: *const c_char, @@ -498,6 +566,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 deleted file mode 100644 index 1d8d4a16..00000000 --- a/src/ossl/ec_montgomery.rs +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2024 Jakub Jelen -// See LICENSE.txt file for terms - -use std::ffi::{c_char, c_int}; - -use crate::attribute::Attribute; -use crate::ecc_misc::*; -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::*; - -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) -} - -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)?, - } -} - -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)?, - } -} - -pub fn make_ec_montgomery_public_key( - key: &Object, - ec_point: &Vec, -) -> Result { - 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, - ) -} - -/// 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); - - 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, - ) -} - -#[derive(Debug)] -pub struct ECMontgomeryOperation {} - -impl ECMontgomeryOperation { - pub fn generate_keypair( - pubkey: &mut Object, - privkey: &mut Object, - ) -> Result<()> { - let evp_pkey = EvpPkey::generate( - get_ossl_name_from_obj(pubkey)?.as_ptr() as *const c_char, - &OsslParam::empty(), - )?; - - let mut params: *mut OSSL_PARAM = std::ptr::null_mut(); - let res = unsafe { - EVP_PKEY_todata( - evp_pkey.as_ptr(), - c_int::try_from(EVP_PKEY_KEYPAIR)?, - &mut params, - ) - }; - if res != 1 { - return Err(CKR_DEVICE_ERROR)?; - } - let params = OsslParam::from_ptr(params)?; - /* Public Key */ - let point_encoded = match 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 */ - let value = params - .get_octet_string(name_as_char(OSSL_PKEY_PARAM_PRIV_KEY))? - .to_vec(); - privkey.set_attr(Attribute::from_bytes(CKA_VALUE, value))?; - Ok(()) - } -} diff --git a/src/ossl/ecdh.rs b/src/ossl/ecdh.rs index 53a1b4ed..4629f5c4 100644 --- a/src/ossl/ecdh.rs +++ b/src/ossl/ecdh.rs @@ -6,22 +6,13 @@ use std::borrow::Cow; use crate::attribute::CkAttrs; use crate::bytes_to_vec; +use crate::ec::{get_ossl_name_from_obj, EC_NAME}; 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::{ - make_ec_montgomery_public_key, make_output_length_from_montgomery_obj, - montgomery_object_to_ecc_private_key, -}; -#[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, -}; fn kdf_type_to_hash_mech(mech: CK_EC_KDF_TYPE) -> Result { match mech { @@ -38,39 +29,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 { - #[cfg(feature = "ecc")] + let mut params = OsslParam::with_capacity(2); + params.zeroize = true; + + let name = match key.get_attr_as_ulong(CKA_KEY_TYPE)? { + #[cfg(feature = "ecdsa")] CKK_EC => { - make_ecdsa_public_key(&get_curve_name_from_obj(key)?, &ec_point) + params.add_const_c_string( + name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), + name_as_char(get_ossl_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), + #[cfg(feature = "ec_montgomery")] + 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 +120,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 +132,8 @@ impl Derive for ECDHOperation { let factory = objfactories.get_obj_factory_from_key_template(template)?; + let raw_max = 2 * ((pkey.get_bits()? + 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 +187,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 +196,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/ecc.rs b/src/ossl/ecdsa.rs similarity index 82% rename from src/ossl/ecc.rs rename to src/ossl/ecdsa.rs index 83ba8694..4c4211c7 100644 --- a/src/ossl/ecc.rs +++ b/src/ossl/ecdsa.rs @@ -1,11 +1,11 @@ // 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::*; -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; @@ -26,106 +26,42 @@ 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"; -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 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( + + params.add_const_c_string( name_as_char(OSSL_PKEY_PARAM_GROUP_NAME), - curve_name, + name_as_char(get_ossl_name_from_obj(key)?), )?; - 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 +186,13 @@ impl EccOperation { key: &Object, _: &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(ecdsa_object_to_ecc_private_key(key)?), + private_key: Some(privkey), finalized: false, in_use: false, sigctx: match mech.mechanism { @@ -272,10 +210,12 @@ impl EccOperation { key: &Object, _: &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)?, - public_key: Some(object_to_ecc_public_key(key)?), + output_len: outlen, + public_key: Some(pubkey), private_key: None, finalized: false, in_use: false, @@ -293,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/eddsa.rs b/src/ossl/eddsa.rs index dea40ad2..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,88 +19,16 @@ 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"; - -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)?, - } -} +pub const OUTLEN_ED25519: usize = 64; +pub const OUTLEN_ED448: usize = 114; -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) -} - -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,51 +54,39 @@ 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)?, - }; +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 { @@ -180,14 +96,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 @@ -214,7 +122,6 @@ pub struct EddsaOperation { public_key: Option, private_key: Option, params: EddsaParams, - is448: bool, data: Vec, finalized: bool, in_use: bool, @@ -230,14 +137,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(object_to_ecc_private_key(key)?), - params: parse_params(mech, is_448)?, - is448: is_448, + private_key: Some(privkey), + params: parse_params(mech, outlen)?, data: Vec::new(), finalized: false, in_use: false, @@ -250,14 +157,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)?, - public_key: Some(object_to_ecc_public_key(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, @@ -304,50 +211,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 => { - 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() - } - } - }; - 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 { @@ -379,7 +280,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 { @@ -479,7 +380,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 { 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/montgomery.rs b/src/ossl/montgomery.rs new file mode 100644 index 00000000..221a19f5 --- /dev/null +++ b/src/ossl/montgomery.rs @@ -0,0 +1,87 @@ +// Copyright 2024 Jakub Jelen +// See LICENSE.txt file for terms + +use std::ffi::{c_char, c_int}; + +use crate::attribute::Attribute; +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::*; + +pub fn ecm_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; + + let name = get_ossl_name_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_octet_string( + name_as_char(OSSL_PKEY_PARAM_PRIV_KEY), + key.get_attr_as_bytes(CKA_VALUE)?, + )?; + } + + _ => return Err(CKR_KEY_TYPE_INCONSISTENT)?, + } + + params.finalize(); + + Ok((name_as_char(name), params)) +} + +#[derive(Debug)] +pub struct ECMontgomeryOperation {} + +impl ECMontgomeryOperation { + pub fn generate_keypair( + pubkey: &mut Object, + privkey: &mut Object, + ) -> Result<()> { + let evp_pkey = EvpPkey::generate( + get_ossl_name_from_obj(pubkey)?.as_ptr() as *const c_char, + &OsslParam::empty(), + )?; + + let mut params: *mut OSSL_PARAM = std::ptr::null_mut(); + let res = unsafe { + EVP_PKEY_todata( + evp_pkey.as_ptr(), + c_int::try_from(EVP_PKEY_KEYPAIR)?, + &mut params, + ) + }; + if res != 1 { + return Err(CKR_DEVICE_ERROR)?; + } + let params = OsslParam::from_ptr(params)?; + /* Public Key */ + let point_encoded = asn1::write_single( + ¶ms.get_octet_string(name_as_char(OSSL_PKEY_PARAM_PUB_KEY))?, + )?; + pubkey.set_attr(Attribute::from_bytes(CKA_EC_POINT, point_encoded))?; + + /* Private Key */ + let value = params + .get_octet_string(name_as_char(OSSL_PKEY_PARAM_PRIV_KEY))? + .to_vec(); + privkey.set_attr(Attribute::from_bytes(CKA_VALUE, value))?; + Ok(()) + } +} 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, diff --git a/src/tests/ecdh_vectors.rs b/src/tests/ecdh_vectors.rs index 22aaf81e..896864e6 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::ec; 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,12 @@ 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 = ec::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 +88,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 +108,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 ec::curve_name_to_ec_params(curve_name) { Ok(p) => p, Err(_) => continue, /* skip unsupported */ }; @@ -190,12 +189,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 ec::curve_name_to_bits(curve_name) { Ok(l) => l, Err(_) => panic!("Unknown curve given"), }; @@ -222,7 +221,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 +244,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() ) 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() {