Skip to content

Commit 59195a7

Browse files
WinSCard FFI implementation (#205)
1 parent 79eef16 commit 59195a7

20 files changed

+1533
-320
lines changed

Cargo.lock

Lines changed: 20 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ffi-types/src/winscard/functions.rs

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,26 @@ use crate::{
88
Handle, LpByte, LpCByte, LpCGuid, LpCStr, LpCVoid, LpCWStr, LpDword, LpGuid, LpStr, LpUuid, LpVoid, LpWStr,
99
};
1010

11-
pub type SCardEstablishContextFn = extern "system" fn(u32, *const c_void, *const c_void, LpScardContext) -> ScardStatus;
12-
pub type SCardReleaseContextFn = extern "system" fn(ScardContext) -> ScardStatus;
13-
pub type SCardIsValidContextFn = extern "system" fn(ScardContext) -> ScardStatus;
11+
pub type SCardEstablishContextFn =
12+
unsafe extern "system" fn(u32, *const c_void, *const c_void, LpScardContext) -> ScardStatus;
13+
pub type SCardReleaseContextFn = unsafe extern "system" fn(ScardContext) -> ScardStatus;
14+
pub type SCardIsValidContextFn = unsafe extern "system" fn(ScardContext) -> ScardStatus;
1415
pub type SCardListReaderGroupsAFn = extern "system" fn(ScardContext, LpStr, LpDword) -> ScardStatus;
1516
pub type SCardListReaderGroupsWFn = extern "system" fn(ScardContext, LpWStr, LpDword) -> ScardStatus;
16-
pub type SCardListReadersAFn = extern "system" fn(ScardContext, LpCStr, LpStr, LpDword) -> ScardStatus;
17-
pub type SCardListReadersWFn = extern "system" fn(ScardContext, LpCWStr, LpWStr, LpDword) -> ScardStatus;
18-
pub type SCardListCardsAFn = extern "system" fn(ScardContext, LpCByte, LpCGuid, u32, *mut u8, LpDword) -> ScardStatus;
19-
pub type SCardListCardsWFn = extern "system" fn(ScardContext, LpCByte, LpCGuid, u32, *mut u16, LpDword) -> ScardStatus;
17+
pub type SCardListReadersAFn = unsafe extern "system" fn(ScardContext, LpCStr, LpStr, LpDword) -> ScardStatus;
18+
pub type SCardListReadersWFn = unsafe extern "system" fn(ScardContext, LpCWStr, LpWStr, LpDword) -> ScardStatus;
19+
pub type SCardListCardsAFn =
20+
unsafe extern "system" fn(ScardContext, LpCByte, LpCGuid, u32, *mut u8, LpDword) -> ScardStatus;
21+
pub type SCardListCardsWFn =
22+
unsafe extern "system" fn(ScardContext, LpCByte, LpCGuid, u32, *mut u16, LpDword) -> ScardStatus;
2023
pub type SCardListInterfacesAFn = extern "system" fn(ScardContext, LpCStr, LpGuid, LpDword) -> ScardStatus;
2124
pub type SCardListInterfacesWFn = extern "system" fn(ScardContext, LpCWStr, LpGuid, LpDword) -> ScardStatus;
2225
pub type SCardGetProviderIdAFn = extern "system" fn(ScardContext, LpCStr, LpGuid) -> ScardStatus;
2326
pub type SCardGetProviderIdWFn = extern "system" fn(ScardContext, LpCWStr, LpGuid) -> ScardStatus;
2427
pub type SCardGetCardTypeProviderNameAFn =
25-
extern "system" fn(ScardContext, LpCStr, u32, *mut u8, LpDword) -> ScardStatus;
28+
unsafe extern "system" fn(ScardContext, LpCStr, u32, *mut u8, LpDword) -> ScardStatus;
2629
pub type SCardGetCardTypeProviderNameWFn =
27-
extern "system" fn(ScardContext, LpCWStr, u32, *mut u16, LpDword) -> ScardStatus;
30+
unsafe extern "system" fn(ScardContext, LpCWStr, u32, *mut u16, LpDword) -> ScardStatus;
2831
pub type SCardIntroduceReaderGroupAFn = extern "system" fn(ScardContext, LpCStr) -> ScardStatus;
2932
pub type SCardIntroduceReaderGroupWFn = extern "system" fn(ScardContext, LpCWStr) -> ScardStatus;
3033
pub type SCardForgetReaderGroupAFn = extern "system" fn(ScardContext, LpCStr) -> ScardStatus;
@@ -45,54 +48,71 @@ pub type SCardSetCardTypeProviderNameAFn = extern "system" fn(ScardContext, LpCS
4548
pub type SCardSetCardTypeProviderNameWFn = extern "system" fn(ScardContext, LpCWStr, u32, LpCWStr) -> ScardStatus;
4649
pub type SCardForgetCardTypeAFn = extern "system" fn(ScardContext, LpCStr) -> ScardStatus;
4750
pub type SCardForgetCardTypeWFn = extern "system" fn(ScardContext, LpCWStr) -> ScardStatus;
48-
pub type SCardFreeMemoryFn = extern "system" fn(ScardContext, LpCVoid) -> ScardStatus;
51+
pub type SCardFreeMemoryFn = unsafe extern "system" fn(ScardContext, LpCVoid) -> ScardStatus;
4952
pub type SCardAccessStartedEventFn = extern "system" fn() -> Handle;
50-
pub type SCardReleaseStartedEventFn = extern "system" fn() -> c_void;
53+
pub type SCardReleaseStartedEventFn = extern "system" fn();
5154
pub type SCardLocateCardsAFn = extern "system" fn(ScardContext, LpCStr, LpScardReaderStateA, u32) -> ScardStatus;
5255
pub type SCardLocateCardsWFn = extern "system" fn(ScardContext, LpCWStr, LpScardReaderStateW, u32) -> ScardStatus;
5356
pub type SCardLocateCardsByATRAFn =
5457
extern "system" fn(ScardContext, LpScardAtrMask, u32, LpScardReaderStateA, u32) -> ScardStatus;
5558
pub type SCardLocateCardsByATRWFn =
5659
extern "system" fn(ScardContext, LpScardAtrMask, u32, LpScardReaderStateW, u32) -> ScardStatus;
57-
pub type SCardGetStatusChangeAFn = extern "system" fn(ScardContext, u32, LpScardReaderStateA, u32) -> ScardStatus;
58-
pub type SCardGetStatusChangeWFn = extern "system" fn(ScardContext, u32, LpScardReaderStateW, u32) -> ScardStatus;
60+
pub type SCardGetStatusChangeAFn =
61+
unsafe extern "system" fn(ScardContext, u32, LpScardReaderStateA, u32) -> ScardStatus;
62+
pub type SCardGetStatusChangeWFn =
63+
unsafe extern "system" fn(ScardContext, u32, LpScardReaderStateW, u32) -> ScardStatus;
5964
pub type SCardCancelFn = extern "system" fn(ScardContext) -> ScardStatus;
60-
pub type SCardReadCacheAFn = extern "system" fn(ScardContext, LpUuid, u32, LpStr, LpByte, LpDword) -> ScardStatus;
61-
pub type SCardReadCacheWFn = extern "system" fn(ScardContext, LpUuid, u32, LpWStr, LpByte, LpDword) -> ScardStatus;
62-
pub type SCardWriteCacheAFn = extern "system" fn(ScardContext, LpUuid, u32, LpStr, LpByte, u32) -> ScardStatus;
63-
pub type SCardWriteCacheWFn = extern "system" fn(ScardContext, LpUuid, u32, LpWStr, LpByte, u32) -> ScardStatus;
64-
pub type SCardGetReaderIconAFn = extern "system" fn(ScardContext, LpCStr, LpByte, LpDword) -> ScardStatus;
65-
pub type SCardGetReaderIconWFn = extern "system" fn(ScardContext, LpCWStr, LpByte, LpDword) -> ScardStatus;
65+
pub type SCardReadCacheAFn =
66+
unsafe extern "system" fn(ScardContext, LpUuid, u32, LpStr, LpByte, LpDword) -> ScardStatus;
67+
pub type SCardReadCacheWFn =
68+
unsafe extern "system" fn(ScardContext, LpUuid, u32, LpWStr, LpByte, LpDword) -> ScardStatus;
69+
pub type SCardWriteCacheAFn = unsafe extern "system" fn(ScardContext, LpUuid, u32, LpStr, LpByte, u32) -> ScardStatus;
70+
pub type SCardWriteCacheWFn = unsafe extern "system" fn(ScardContext, LpUuid, u32, LpWStr, LpByte, u32) -> ScardStatus;
71+
pub type SCardGetReaderIconAFn = unsafe extern "system" fn(ScardContext, LpCStr, LpByte, LpDword) -> ScardStatus;
72+
pub type SCardGetReaderIconWFn = unsafe extern "system" fn(ScardContext, LpCWStr, LpByte, LpDword) -> ScardStatus;
73+
pub type SCardGetDeviceTypeIdAFn = unsafe extern "system" fn(ScardContext, LpCStr, LpDword) -> ScardStatus;
74+
pub type SCardGetDeviceTypeIdWFn = unsafe extern "system" fn(ScardContext, LpCWStr, LpDword) -> ScardStatus;
6675
pub type SCardGetReaderDeviceInstanceIdAFn = extern "system" fn(ScardContext, LpCStr, LpStr, LpDword) -> ScardStatus;
6776
pub type SCardGetReaderDeviceInstanceIdWFn = extern "system" fn(ScardContext, LpCWStr, LpWStr, LpDword) -> ScardStatus;
6877
pub type SCardListReadersWithDeviceInstanceIdAFn =
6978
extern "system" fn(ScardContext, LpCStr, LpStr, LpDword) -> ScardStatus;
7079
pub type SCardListReadersWithDeviceInstanceIdWFn =
7180
extern "system" fn(ScardContext, LpCWStr, LpWStr, LpDword) -> ScardStatus;
7281
pub type SCardAuditFn = extern "system" fn(ScardContext, u32) -> ScardStatus;
73-
pub type SCardConnectAFn = extern "system" fn(ScardContext, LpCStr, u32, u32, LpScardHandle, LpDword) -> ScardStatus;
74-
pub type SCardConnectWFn = extern "system" fn(ScardContext, LpCWStr, u32, u32, LpScardHandle, LpDword) -> ScardStatus;
82+
pub type SCardConnectAFn =
83+
unsafe extern "system" fn(ScardContext, LpCStr, u32, u32, LpScardHandle, LpDword) -> ScardStatus;
84+
pub type SCardConnectWFn =
85+
unsafe extern "system" fn(ScardContext, LpCWStr, u32, u32, LpScardHandle, LpDword) -> ScardStatus;
7586
pub type SCardReconnectFn = extern "system" fn(ScardHandle, u32, u32, u32, LpDword) -> ScardStatus;
76-
pub type SCardDisconnectFn = extern "system" fn(ScardHandle, u32) -> ScardStatus;
77-
pub type SCardBeginTransactionFn = extern "system" fn(ScardHandle) -> ScardStatus;
78-
pub type SCardEndTransactionFn = extern "system" fn(ScardHandle, u32) -> ScardStatus;
87+
pub type SCardDisconnectFn = unsafe extern "system" fn(ScardHandle, u32) -> ScardStatus;
88+
pub type SCardBeginTransactionFn = unsafe extern "system" fn(ScardHandle) -> ScardStatus;
89+
pub type SCardEndTransactionFn = unsafe extern "system" fn(ScardHandle, u32) -> ScardStatus;
7990
pub type SCardCancelTransactionFn = extern "system" fn(ScardHandle) -> ScardStatus;
8091
pub type SCardStateFn = extern "system" fn(ScardHandle, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
8192
pub type SCardStatusAFn =
82-
extern "system" fn(ScardHandle, LpStr, LpDword, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
93+
unsafe extern "system" fn(ScardHandle, LpStr, LpDword, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
8394
pub type SCardStatusWFn =
84-
extern "system" fn(ScardHandle, LpWStr, LpDword, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
85-
pub type SCardTransmitFn =
86-
extern "system" fn(ScardHandle, LpScardIoRequest, LpCByte, u32, LpScardIoRequest, LpByte, LpDword) -> ScardStatus;
95+
unsafe extern "system" fn(ScardHandle, LpWStr, LpDword, LpDword, LpDword, LpByte, LpDword) -> ScardStatus;
96+
pub type SCardTransmitFn = unsafe extern "system" fn(
97+
ScardHandle,
98+
LpScardIoRequest,
99+
LpCByte,
100+
u32,
101+
LpScardIoRequest,
102+
LpByte,
103+
LpDword,
104+
) -> ScardStatus;
87105
pub type SCardGetTransmitCountFn = extern "system" fn(ScardHandle, LpDword) -> ScardStatus;
88-
pub type SCardControlFn = extern "system" fn(ScardHandle, u32, LpCVoid, u32, LpVoid, u32, LpDword) -> ScardStatus;
106+
pub type SCardControlFn =
107+
unsafe extern "system" fn(ScardHandle, u32, LpCVoid, u32, LpVoid, u32, LpDword) -> ScardStatus;
89108
pub type SCardGetAttribFn = extern "system" fn(ScardHandle, u32, LpByte, LpDword) -> ScardStatus;
90109
pub type SCardSetAttribFn = extern "system" fn(ScardHandle, u32, LpCByte, u32) -> ScardStatus;
91110
pub type SCardUIDlgSelectCardAFn = extern "system" fn(LpOpenCardNameExA) -> ScardStatus;
92111
pub type SCardUIDlgSelectCardWFn = extern "system" fn(LpOpenCardNameExW) -> ScardStatus;
93112
pub type GetOpenCardNameAFn = extern "system" fn(LpOpenCardNameA) -> ScardStatus;
94113
pub type GetOpenCardNameWFn = extern "system" fn(LpOpenCardNameW) -> ScardStatus;
95-
pub type SCardDlgExtendedErrorFn = extern "system" fn() -> i32;
114+
// Not a part of the standard winscard.h API
115+
pub type GetSCardApiFunctionTableFn = extern "system" fn() -> PSCardApiFunctionTable;
96116

97117
// https://github.com/FreeRDP/FreeRDP/blob/88f79c5748f4031cb50dfae3ebadcc6619b69f1c/winpr/include/winpr/smartcard.h#L1114
98118
#[repr(C)]
@@ -161,13 +181,14 @@ pub struct SCardApiFunctionTable {
161181
pub SCardUIDlgSelectCardW: SCardUIDlgSelectCardWFn,
162182
pub GetOpenCardNameA: GetOpenCardNameAFn,
163183
pub GetOpenCardNameW: GetOpenCardNameWFn,
164-
pub SCardDlgExtendedError: SCardDlgExtendedErrorFn,
165184
pub SCardReadCacheA: SCardReadCacheAFn,
166185
pub SCardReadCacheW: SCardReadCacheWFn,
167186
pub SCardWriteCacheA: SCardWriteCacheAFn,
168187
pub SCardWriteCacheW: SCardWriteCacheWFn,
169188
pub SCardGetReaderIconA: SCardGetReaderIconAFn,
170189
pub SCardGetReaderIconW: SCardGetReaderIconWFn,
190+
pub SCardGetDeviceTypeIdA: SCardGetDeviceTypeIdAFn,
191+
pub SCardGetDeviceTypeIdW: SCardGetDeviceTypeIdWFn,
171192
pub SCardGetReaderDeviceInstanceIdA: SCardGetReaderDeviceInstanceIdAFn,
172193
pub SCardGetReaderDeviceInstanceIdW: SCardGetReaderDeviceInstanceIdWFn,
173194
pub SCardListReadersWithDeviceInstanceIdA: SCardListReadersWithDeviceInstanceIdAFn,

crates/ffi-types/src/winscard/mod.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ pub type LpOcnDscProc = Option<unsafe extern "system" fn(_: ScardContext, _: Sca
3636
/// ```
3737
#[repr(C)]
3838
pub struct ScardReaderStateA {
39-
sz_reader: LpCStr,
40-
pv_user_data: LpVoid,
41-
dw_current_state: u32,
42-
dw_event_state: u32,
43-
cb_atr: u32,
44-
rgb_atr: [u8; 36],
39+
pub sz_reader: LpCStr,
40+
pub pv_user_data: LpVoid,
41+
pub dw_current_state: u32,
42+
pub dw_event_state: u32,
43+
pub cb_atr: u32,
44+
pub rgb_atr: [u8; 36],
4545
}
4646

4747
pub type LpScardReaderStateA = *mut ScardReaderStateA;
@@ -58,14 +58,15 @@ pub type LpScardReaderStateA = *mut ScardReaderStateA;
5858
/// BYTE rgbAtr[36];
5959
/// } SCARD_READERSTATEW, *PSCARD_READERSTATEW, *LPSCARD_READERSTATEW;
6060
/// ```
61+
#[derive(Debug)]
6162
#[repr(C)]
6263
pub struct ScardReaderStateW {
63-
sz_reader: LpCWStr,
64-
pv_user_data: LpVoid,
65-
dw_current_state: u32,
66-
dw_event_state: u32,
67-
cb_atr: u32,
68-
rgb_atr: [u8; 36],
64+
pub sz_reader: LpCWStr,
65+
pub pv_user_data: LpVoid,
66+
pub dw_current_state: u32,
67+
pub dw_event_state: u32,
68+
pub cb_atr: u32,
69+
pub rgb_atr: [u8; 36],
6970
}
7071

7172
pub type LpScardReaderStateW = *mut ScardReaderStateW;
@@ -98,8 +99,8 @@ pub type LpScardAtrMask = *mut ScardAtrMask;
9899
/// ```
99100
#[repr(C)]
100101
pub struct ScardIoRequest {
101-
dw_protocol: u32,
102-
cb_pci_length: u32,
102+
pub dw_protocol: u32,
103+
pub cb_pci_length: u32,
103104
}
104105

105106
pub type LpScardIoRequest = *mut ScardIoRequest;

crates/winscard/src/env.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// Emulated smart card PIN code.
2+
pub const WINSCARD_PIN_ENV: &str = "WINSCARD_PIN";
3+
/// Path to the user certificate to be used in emulated smart card.
4+
pub const WINSCARD_CERT_PATH_ENV: &str = "WINSCARD_CERT_PATH";
5+
/// Path to the certificate private key.
6+
pub const WINSCARD_PK_PATH_ENV: &str = "WINSCARD_PK_PATH";
7+
/// Emulated smart card container name.
8+
pub const WINSCARD_CONTAINER_NAME_ENV: &str = "WINSCARD_CONTAINER";
9+
/// Emulated smart card reader name.
10+
pub const WINSCARD_READER_NAME_ENV: &str = "WINSCARD_READER";

crates/winscard/src/lib.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55
#[macro_use]
66
extern crate tracing;
77

8+
#[macro_use]
9+
mod macros;
10+
811
mod ber_tlv;
912
mod card_capability_container;
1013
mod chuid;
1114
mod compression;
1215
mod dummy_rng;
16+
/// Contains env variables names that represent smart card credentials.
17+
#[cfg(feature = "std")]
18+
pub mod env;
1319
mod piv_cert;
1420
mod scard;
1521
mod scard_context;
@@ -23,13 +29,14 @@ extern crate alloc;
2329
use alloc::format;
2430
use alloc::string::String;
2531
use alloc::vec::Vec;
32+
use core::num::TryFromIntError;
2633
use core::{fmt, result};
2734

2835
pub use ber_tlv::ber_tlv_length_encoding;
2936
use iso7816_tlv::TlvError;
3037
use picky::key::KeyError;
31-
pub use scard::{SmartCard, PIV_AID};
32-
pub use scard_context::{Reader, ScardContext};
38+
pub use scard::{SmartCard, ATR, PIV_AID};
39+
pub use scard_context::{Reader, ScardContext, SmartCardInfo};
3340

3441
/// The [WinScardResult] type.
3542
pub type WinScardResult<T> = result::Result<T, Error>;
@@ -125,6 +132,15 @@ impl From<TlvError> for Error {
125132
}
126133
}
127134

135+
impl From<TryFromIntError> for Error {
136+
fn from(value: TryFromIntError) -> Self {
137+
Error::new(
138+
ErrorKind::InsufficientBuffer,
139+
format!("error: can not convert integers: {}", value),
140+
)
141+
}
142+
}
143+
128144
/// [Smart Card Return Values](https://learn.microsoft.com/en-us/windows/win32/secauthn/authentication-return-values).
129145
#[derive(Debug, PartialEq)]
130146
#[repr(u32)]

crates/winscard/src/macros.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
macro_rules! env {
2+
($name:expr) => {{
3+
std::env::var($name).map_err(|_| {
4+
crate::Error::new(
5+
crate::ErrorKind::InvalidParameter,
6+
format!("The {} env var is not present or invalid", $name),
7+
)
8+
})
9+
}};
10+
}

0 commit comments

Comments
 (0)