Skip to content

Commit

Permalink
feat(ffi): WinSCard FFI implementation (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBestTvarynka authored and CBenoit committed Feb 15, 2024
1 parent 147ccb4 commit cfc86d6
Show file tree
Hide file tree
Showing 20 changed files with 1,533 additions and 320 deletions.
30 changes: 20 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 52 additions & 31 deletions crates/ffi-types/src/winscard/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,26 @@ use crate::{
Handle, LpByte, LpCByte, LpCGuid, LpCStr, LpCVoid, LpCWStr, LpDword, LpGuid, LpStr, LpUuid, LpVoid, LpWStr,
};

pub type SCardEstablishContextFn = extern "system" fn(u32, *const c_void, *const c_void, LpScardContext) -> ScardStatus;
pub type SCardReleaseContextFn = extern "system" fn(ScardContext) -> ScardStatus;
pub type SCardIsValidContextFn = extern "system" fn(ScardContext) -> ScardStatus;
pub type SCardEstablishContextFn =
unsafe extern "system" fn(u32, *const c_void, *const c_void, LpScardContext) -> ScardStatus;
pub type SCardReleaseContextFn = unsafe extern "system" fn(ScardContext) -> ScardStatus;
pub type SCardIsValidContextFn = unsafe extern "system" fn(ScardContext) -> ScardStatus;
pub type SCardListReaderGroupsAFn = extern "system" fn(ScardContext, LpStr, LpDword) -> ScardStatus;
pub type SCardListReaderGroupsWFn = extern "system" fn(ScardContext, LpWStr, LpDword) -> ScardStatus;
pub type SCardListReadersAFn = extern "system" fn(ScardContext, LpCStr, LpStr, LpDword) -> ScardStatus;
pub type SCardListReadersWFn = extern "system" fn(ScardContext, LpCWStr, LpWStr, LpDword) -> ScardStatus;
pub type SCardListCardsAFn = extern "system" fn(ScardContext, LpCByte, LpCGuid, u32, *mut u8, LpDword) -> ScardStatus;
pub type SCardListCardsWFn = extern "system" fn(ScardContext, LpCByte, LpCGuid, u32, *mut u16, LpDword) -> ScardStatus;
pub type SCardListReadersAFn = unsafe extern "system" fn(ScardContext, LpCStr, LpStr, LpDword) -> ScardStatus;
pub type SCardListReadersWFn = unsafe extern "system" fn(ScardContext, LpCWStr, LpWStr, LpDword) -> ScardStatus;
pub type SCardListCardsAFn =
unsafe extern "system" fn(ScardContext, LpCByte, LpCGuid, u32, *mut u8, LpDword) -> ScardStatus;
pub type SCardListCardsWFn =
unsafe extern "system" fn(ScardContext, LpCByte, LpCGuid, u32, *mut u16, LpDword) -> ScardStatus;
pub type SCardListInterfacesAFn = extern "system" fn(ScardContext, LpCStr, LpGuid, LpDword) -> ScardStatus;
pub type SCardListInterfacesWFn = extern "system" fn(ScardContext, LpCWStr, LpGuid, LpDword) -> ScardStatus;
pub type SCardGetProviderIdAFn = extern "system" fn(ScardContext, LpCStr, LpGuid) -> ScardStatus;
pub type SCardGetProviderIdWFn = extern "system" fn(ScardContext, LpCWStr, LpGuid) -> ScardStatus;
pub type SCardGetCardTypeProviderNameAFn =
extern "system" fn(ScardContext, LpCStr, u32, *mut u8, LpDword) -> ScardStatus;
unsafe extern "system" fn(ScardContext, LpCStr, u32, *mut u8, LpDword) -> ScardStatus;
pub type SCardGetCardTypeProviderNameWFn =
extern "system" fn(ScardContext, LpCWStr, u32, *mut u16, LpDword) -> ScardStatus;
unsafe extern "system" fn(ScardContext, LpCWStr, u32, *mut u16, LpDword) -> ScardStatus;
pub type SCardIntroduceReaderGroupAFn = extern "system" fn(ScardContext, LpCStr) -> ScardStatus;
pub type SCardIntroduceReaderGroupWFn = extern "system" fn(ScardContext, LpCWStr) -> ScardStatus;
pub type SCardForgetReaderGroupAFn = extern "system" fn(ScardContext, LpCStr) -> ScardStatus;
Expand All @@ -45,54 +48,71 @@ pub type SCardSetCardTypeProviderNameAFn = extern "system" fn(ScardContext, LpCS
pub type SCardSetCardTypeProviderNameWFn = extern "system" fn(ScardContext, LpCWStr, u32, LpCWStr) -> ScardStatus;
pub type SCardForgetCardTypeAFn = extern "system" fn(ScardContext, LpCStr) -> ScardStatus;
pub type SCardForgetCardTypeWFn = extern "system" fn(ScardContext, LpCWStr) -> ScardStatus;
pub type SCardFreeMemoryFn = extern "system" fn(ScardContext, LpCVoid) -> ScardStatus;
pub type SCardFreeMemoryFn = unsafe extern "system" fn(ScardContext, LpCVoid) -> ScardStatus;
pub type SCardAccessStartedEventFn = extern "system" fn() -> Handle;
pub type SCardReleaseStartedEventFn = extern "system" fn() -> c_void;
pub type SCardReleaseStartedEventFn = extern "system" fn();
pub type SCardLocateCardsAFn = extern "system" fn(ScardContext, LpCStr, LpScardReaderStateA, u32) -> ScardStatus;
pub type SCardLocateCardsWFn = extern "system" fn(ScardContext, LpCWStr, LpScardReaderStateW, u32) -> ScardStatus;
pub type SCardLocateCardsByATRAFn =
extern "system" fn(ScardContext, LpScardAtrMask, u32, LpScardReaderStateA, u32) -> ScardStatus;
pub type SCardLocateCardsByATRWFn =
extern "system" fn(ScardContext, LpScardAtrMask, u32, LpScardReaderStateW, u32) -> ScardStatus;
pub type SCardGetStatusChangeAFn = extern "system" fn(ScardContext, u32, LpScardReaderStateA, u32) -> ScardStatus;
pub type SCardGetStatusChangeWFn = extern "system" fn(ScardContext, u32, LpScardReaderStateW, u32) -> ScardStatus;
pub type SCardGetStatusChangeAFn =
unsafe extern "system" fn(ScardContext, u32, LpScardReaderStateA, u32) -> ScardStatus;
pub type SCardGetStatusChangeWFn =
unsafe extern "system" fn(ScardContext, u32, LpScardReaderStateW, u32) -> ScardStatus;
pub type SCardCancelFn = extern "system" fn(ScardContext) -> ScardStatus;
pub type SCardReadCacheAFn = extern "system" fn(ScardContext, LpUuid, u32, LpStr, LpByte, LpDword) -> ScardStatus;
pub type SCardReadCacheWFn = extern "system" fn(ScardContext, LpUuid, u32, LpWStr, LpByte, LpDword) -> ScardStatus;
pub type SCardWriteCacheAFn = extern "system" fn(ScardContext, LpUuid, u32, LpStr, LpByte, u32) -> ScardStatus;
pub type SCardWriteCacheWFn = extern "system" fn(ScardContext, LpUuid, u32, LpWStr, LpByte, u32) -> ScardStatus;
pub type SCardGetReaderIconAFn = extern "system" fn(ScardContext, LpCStr, LpByte, LpDword) -> ScardStatus;
pub type SCardGetReaderIconWFn = extern "system" fn(ScardContext, LpCWStr, LpByte, LpDword) -> ScardStatus;
pub type SCardReadCacheAFn =
unsafe extern "system" fn(ScardContext, LpUuid, u32, LpStr, LpByte, LpDword) -> ScardStatus;
pub type SCardReadCacheWFn =
unsafe extern "system" fn(ScardContext, LpUuid, u32, LpWStr, LpByte, LpDword) -> ScardStatus;
pub type SCardWriteCacheAFn = unsafe extern "system" fn(ScardContext, LpUuid, u32, LpStr, LpByte, u32) -> ScardStatus;
pub type SCardWriteCacheWFn = unsafe extern "system" fn(ScardContext, LpUuid, u32, LpWStr, LpByte, u32) -> ScardStatus;
pub type SCardGetReaderIconAFn = unsafe extern "system" fn(ScardContext, LpCStr, LpByte, LpDword) -> ScardStatus;
pub type SCardGetReaderIconWFn = unsafe extern "system" fn(ScardContext, LpCWStr, LpByte, LpDword) -> ScardStatus;
pub type SCardGetDeviceTypeIdAFn = unsafe extern "system" fn(ScardContext, LpCStr, LpDword) -> ScardStatus;
pub type SCardGetDeviceTypeIdWFn = unsafe extern "system" fn(ScardContext, LpCWStr, LpDword) -> ScardStatus;
pub type SCardGetReaderDeviceInstanceIdAFn = extern "system" fn(ScardContext, LpCStr, LpStr, LpDword) -> ScardStatus;
pub type SCardGetReaderDeviceInstanceIdWFn = extern "system" fn(ScardContext, LpCWStr, LpWStr, LpDword) -> ScardStatus;
pub type SCardListReadersWithDeviceInstanceIdAFn =
extern "system" fn(ScardContext, LpCStr, LpStr, LpDword) -> ScardStatus;
pub type SCardListReadersWithDeviceInstanceIdWFn =
extern "system" fn(ScardContext, LpCWStr, LpWStr, LpDword) -> ScardStatus;
pub type SCardAuditFn = extern "system" fn(ScardContext, u32) -> ScardStatus;
pub type SCardConnectAFn = extern "system" fn(ScardContext, LpCStr, u32, u32, LpScardHandle, LpDword) -> ScardStatus;
pub type SCardConnectWFn = extern "system" fn(ScardContext, LpCWStr, u32, u32, LpScardHandle, LpDword) -> ScardStatus;
pub type SCardConnectAFn =
unsafe extern "system" fn(ScardContext, LpCStr, u32, u32, LpScardHandle, LpDword) -> ScardStatus;
pub type SCardConnectWFn =
unsafe extern "system" fn(ScardContext, LpCWStr, u32, u32, LpScardHandle, LpDword) -> ScardStatus;
pub type SCardReconnectFn = extern "system" fn(ScardHandle, u32, u32, u32, LpDword) -> ScardStatus;
pub type SCardDisconnectFn = extern "system" fn(ScardHandle, u32) -> ScardStatus;
pub type SCardBeginTransactionFn = extern "system" fn(ScardHandle) -> ScardStatus;
pub type SCardEndTransactionFn = extern "system" fn(ScardHandle, u32) -> ScardStatus;
pub type SCardDisconnectFn = unsafe extern "system" fn(ScardHandle, u32) -> ScardStatus;
pub type SCardBeginTransactionFn = unsafe extern "system" fn(ScardHandle) -> ScardStatus;
pub type SCardEndTransactionFn = unsafe extern "system" fn(ScardHandle, u32) -> ScardStatus;
pub type SCardCancelTransactionFn = extern "system" fn(ScardHandle) -> ScardStatus;
pub type SCardStateFn = extern "system" fn(ScardHandle, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
pub type SCardStatusAFn =
extern "system" fn(ScardHandle, LpStr, LpDword, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
unsafe extern "system" fn(ScardHandle, LpStr, LpDword, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
pub type SCardStatusWFn =
extern "system" fn(ScardHandle, LpWStr, LpDword, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
pub type SCardTransmitFn =
extern "system" fn(ScardHandle, LpScardIoRequest, LpCByte, u32, LpScardIoRequest, LpByte, LpDword) -> ScardStatus;
unsafe extern "system" fn(ScardHandle, LpWStr, LpDword, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
pub type SCardTransmitFn = unsafe extern "system" fn(
ScardHandle,
LpScardIoRequest,
LpCByte,
u32,
LpScardIoRequest,
LpByte,
LpDword,
) -> ScardStatus;
pub type SCardGetTransmitCountFn = extern "system" fn(ScardHandle, LpDword) -> ScardStatus;
pub type SCardControlFn = extern "system" fn(ScardHandle, u32, LpCVoid, u32, LpVoid, u32, LpDword) -> ScardStatus;
pub type SCardControlFn =
unsafe extern "system" fn(ScardHandle, u32, LpCVoid, u32, LpVoid, u32, LpDword) -> ScardStatus;
pub type SCardGetAttribFn = extern "system" fn(ScardHandle, u32, LpByte, LpDword) -> ScardStatus;
pub type SCardSetAttribFn = extern "system" fn(ScardHandle, u32, LpCByte, u32) -> ScardStatus;
pub type SCardUIDlgSelectCardAFn = extern "system" fn(LpOpenCardNameExA) -> ScardStatus;
pub type SCardUIDlgSelectCardWFn = extern "system" fn(LpOpenCardNameExW) -> ScardStatus;
pub type GetOpenCardNameAFn = extern "system" fn(LpOpenCardNameA) -> ScardStatus;
pub type GetOpenCardNameWFn = extern "system" fn(LpOpenCardNameW) -> ScardStatus;
pub type SCardDlgExtendedErrorFn = extern "system" fn() -> i32;
// Not a part of the standard winscard.h API
pub type GetSCardApiFunctionTableFn = extern "system" fn() -> PSCardApiFunctionTable;

// https://github.com/FreeRDP/FreeRDP/blob/88f79c5748f4031cb50dfae3ebadcc6619b69f1c/winpr/include/winpr/smartcard.h#L1114
#[repr(C)]
Expand Down Expand Up @@ -161,13 +181,14 @@ pub struct SCardApiFunctionTable {
pub SCardUIDlgSelectCardW: SCardUIDlgSelectCardWFn,
pub GetOpenCardNameA: GetOpenCardNameAFn,
pub GetOpenCardNameW: GetOpenCardNameWFn,
pub SCardDlgExtendedError: SCardDlgExtendedErrorFn,
pub SCardReadCacheA: SCardReadCacheAFn,
pub SCardReadCacheW: SCardReadCacheWFn,
pub SCardWriteCacheA: SCardWriteCacheAFn,
pub SCardWriteCacheW: SCardWriteCacheWFn,
pub SCardGetReaderIconA: SCardGetReaderIconAFn,
pub SCardGetReaderIconW: SCardGetReaderIconWFn,
pub SCardGetDeviceTypeIdA: SCardGetDeviceTypeIdAFn,
pub SCardGetDeviceTypeIdW: SCardGetDeviceTypeIdWFn,
pub SCardGetReaderDeviceInstanceIdA: SCardGetReaderDeviceInstanceIdAFn,
pub SCardGetReaderDeviceInstanceIdW: SCardGetReaderDeviceInstanceIdWFn,
pub SCardListReadersWithDeviceInstanceIdA: SCardListReadersWithDeviceInstanceIdAFn,
Expand Down
29 changes: 15 additions & 14 deletions crates/ffi-types/src/winscard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ pub type LpOcnDscProc = Option<unsafe extern "system" fn(_: ScardContext, _: Sca
/// ```
#[repr(C)]
pub struct ScardReaderStateA {
sz_reader: LpCStr,
pv_user_data: LpVoid,
dw_current_state: u32,
dw_event_state: u32,
cb_atr: u32,
rgb_atr: [u8; 36],
pub sz_reader: LpCStr,
pub pv_user_data: LpVoid,
pub dw_current_state: u32,
pub dw_event_state: u32,
pub cb_atr: u32,
pub rgb_atr: [u8; 36],
}

pub type LpScardReaderStateA = *mut ScardReaderStateA;
Expand All @@ -58,14 +58,15 @@ pub type LpScardReaderStateA = *mut ScardReaderStateA;
/// BYTE rgbAtr[36];
/// } SCARD_READERSTATEW, *PSCARD_READERSTATEW, *LPSCARD_READERSTATEW;
/// ```
#[derive(Debug)]
#[repr(C)]
pub struct ScardReaderStateW {
sz_reader: LpCWStr,
pv_user_data: LpVoid,
dw_current_state: u32,
dw_event_state: u32,
cb_atr: u32,
rgb_atr: [u8; 36],
pub sz_reader: LpCWStr,
pub pv_user_data: LpVoid,
pub dw_current_state: u32,
pub dw_event_state: u32,
pub cb_atr: u32,
pub rgb_atr: [u8; 36],
}

pub type LpScardReaderStateW = *mut ScardReaderStateW;
Expand Down Expand Up @@ -98,8 +99,8 @@ pub type LpScardAtrMask = *mut ScardAtrMask;
/// ```
#[repr(C)]
pub struct ScardIoRequest {
dw_protocol: u32,
cb_pci_length: u32,
pub dw_protocol: u32,
pub cb_pci_length: u32,
}

pub type LpScardIoRequest = *mut ScardIoRequest;
Expand Down
10 changes: 10 additions & 0 deletions crates/winscard/src/env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// Emulated smart card PIN code.
pub const WINSCARD_PIN_ENV: &str = "WINSCARD_PIN";
/// Path to the user certificate to be used in emulated smart card.
pub const WINSCARD_CERT_PATH_ENV: &str = "WINSCARD_CERT_PATH";
/// Path to the certificate private key.
pub const WINSCARD_PK_PATH_ENV: &str = "WINSCARD_PK_PATH";
/// Emulated smart card container name.
pub const WINSCARD_CONTAINER_NAME_ENV: &str = "WINSCARD_CONTAINER";
/// Emulated smart card reader name.
pub const WINSCARD_READER_NAME_ENV: &str = "WINSCARD_READER";
20 changes: 18 additions & 2 deletions crates/winscard/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
#[macro_use]
extern crate tracing;

#[macro_use]
mod macros;

mod ber_tlv;
mod card_capability_container;
mod chuid;
mod compression;
mod dummy_rng;
/// Contains env variables names that represent smart card credentials.
#[cfg(feature = "std")]
pub mod env;
mod piv_cert;
mod scard;
mod scard_context;
Expand All @@ -23,13 +29,14 @@ extern crate alloc;
use alloc::format;
use alloc::string::String;
use alloc::vec::Vec;
use core::num::TryFromIntError;
use core::{fmt, result};

pub use ber_tlv::ber_tlv_length_encoding;
use iso7816_tlv::TlvError;
use picky::key::KeyError;
pub use scard::{SmartCard, PIV_AID};
pub use scard_context::{Reader, ScardContext};
pub use scard::{SmartCard, ATR, PIV_AID};
pub use scard_context::{Reader, ScardContext, SmartCardInfo};

/// The [WinScardResult] type.
pub type WinScardResult<T> = result::Result<T, Error>;
Expand Down Expand Up @@ -125,6 +132,15 @@ impl From<TlvError> for Error {
}
}

impl From<TryFromIntError> for Error {
fn from(value: TryFromIntError) -> Self {
Error::new(
ErrorKind::InsufficientBuffer,
format!("error: can not convert integers: {}", value),
)
}
}

/// [Smart Card Return Values](https://learn.microsoft.com/en-us/windows/win32/secauthn/authentication-return-values).
#[derive(Debug, PartialEq)]
#[repr(u32)]
Expand Down
10 changes: 10 additions & 0 deletions crates/winscard/src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
macro_rules! env {
($name:expr) => {{
std::env::var($name).map_err(|_| {
crate::Error::new(
crate::ErrorKind::InvalidParameter,
format!("The {} env var is not present or invalid", $name),
)
})
}};
}
Loading

0 comments on commit cfc86d6

Please sign in to comment.