mirror of
https://github.com/trussed-dev/piv-authenticator.git
synced 2026-06-20 04:16:15 -07:00
Add trussed-auth as backend dependency
This commit is contained in:
+7
-4
@@ -17,7 +17,7 @@ required-features = ["vpicc"]
|
||||
|
||||
[[example]]
|
||||
name = "usbip"
|
||||
required-features = ["apdu-dispatch"]
|
||||
required-features = ["apdu-dispatch", "virt"]
|
||||
|
||||
[dependencies]
|
||||
apdu-dispatch = { version = "0.1", optional = true }
|
||||
@@ -29,6 +29,7 @@ interchange = "0.2.2"
|
||||
iso7816 = "0.1"
|
||||
serde = { version = "1", default-features = false, features = ["derive"] }
|
||||
trussed = { version = "0.1" }
|
||||
trussed-auth = { version = "0.2" }
|
||||
untrusted = "0.9"
|
||||
vpicc = { version = "0.1.0", optional = true }
|
||||
log = "0.4"
|
||||
@@ -52,7 +53,7 @@ stoppable_thread = "0.2.1"
|
||||
expectrl = "0.6.0"
|
||||
|
||||
# Examples
|
||||
trussed-usbip = { git = "https://github.com/trussed-dev/pc-usbip-runner", default-features = false, features = ["ccid"], rev = "d2957b6c24c2b0cafbbfacd6fecd62c80943630b"}
|
||||
trussed-usbip = { git = "https://github.com/trussed-dev/pc-usbip-runner", default-features = false, features = ["ccid"], rev = "f3a680ca4c9a1411838ae0774f1713f79d4c2979"}
|
||||
usbd-ccid = { version = "0.2.0", features = ["highspeed-usb"]}
|
||||
rand = "0.8.5"
|
||||
|
||||
@@ -60,7 +61,8 @@ rand = "0.8.5"
|
||||
default = []
|
||||
strict-pin = []
|
||||
std = []
|
||||
vpicc = ["std", "dep:vpicc", "trussed-rsa-alloc/virt"]
|
||||
vpicc = ["std", "dep:vpicc", "virt"]
|
||||
virt = ["std"]
|
||||
pivy-tests = []
|
||||
opensc-tests = []
|
||||
|
||||
@@ -72,7 +74,8 @@ log-warn = []
|
||||
log-error = []
|
||||
|
||||
[patch.crates-io]
|
||||
trussed = { git = "https://github.com/Nitrokey/trussed", tag = "v0.1.0-nitrokey.8"}
|
||||
trussed = { git = "https://github.com/Nitrokey/trussed", tag = "v0.1.0-nitrokey.8"}
|
||||
trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", tag = "v0.2.1"}
|
||||
littlefs2 = { git = "https://github.com/Nitrokey/littlefs2", tag = "v0.3.2-nitrokey-2" }
|
||||
|
||||
[profile.dev.package.rsa]
|
||||
|
||||
+20
-11
@@ -3,9 +3,15 @@
|
||||
|
||||
use trussed::virt::{self, Ram, UserInterface};
|
||||
use trussed::{ClientImplementation, Platform};
|
||||
use trussed_usbip::ClientBuilder;
|
||||
|
||||
use piv_authenticator as piv;
|
||||
use trussed_usbip::Syscall;
|
||||
use piv_authenticator::{
|
||||
self as piv,
|
||||
virt::dispatch::{self, Dispatch},
|
||||
};
|
||||
|
||||
type VirtClient =
|
||||
ClientImplementation<trussed_usbip::Service<Ram, dispatch::Dispatch>, dispatch::Dispatch>;
|
||||
|
||||
const MANUFACTURER: &str = "Nitrokey";
|
||||
const PRODUCT: &str = "Nitrokey 3";
|
||||
@@ -13,16 +19,17 @@ const VID: u16 = 0x20a0;
|
||||
const PID: u16 = 0x42b2;
|
||||
|
||||
struct PivApp {
|
||||
piv: piv::Authenticator<ClientImplementation<Syscall<virt::Platform<Ram>>>>,
|
||||
piv: piv::Authenticator<VirtClient>,
|
||||
}
|
||||
|
||||
impl trussed_usbip::Apps<ClientImplementation<Syscall<virt::Platform<Ram>>>, ()> for PivApp {
|
||||
fn new(
|
||||
make_client: impl Fn(&str) -> ClientImplementation<Syscall<virt::Platform<Ram>>>,
|
||||
_data: (),
|
||||
) -> Self {
|
||||
impl trussed_usbip::Apps<VirtClient, Dispatch> for PivApp {
|
||||
type Data = ();
|
||||
fn new<B: ClientBuilder<VirtClient, Dispatch>>(builder: &B, _data: ()) -> Self {
|
||||
PivApp {
|
||||
piv: piv::Authenticator::new(make_client("piv"), piv::Options::default()),
|
||||
piv: piv::Authenticator::new(
|
||||
builder.build("piv", dispatch::BACKENDS),
|
||||
piv::Options::default(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +51,13 @@ fn main() {
|
||||
vid: VID,
|
||||
pid: PID,
|
||||
};
|
||||
trussed_usbip::Runner::new(virt::Ram::default(), options)
|
||||
trussed_usbip::Builder::new(virt::Ram::default(), options)
|
||||
.dispatch(Dispatch::new())
|
||||
.init_platform(move |platform| {
|
||||
let ui: Box<dyn trussed::platform::UserInterface + Send + Sync> =
|
||||
Box::new(UserInterface::new());
|
||||
platform.user_interface().set_inner(ui);
|
||||
})
|
||||
.exec::<PivApp, _, _>(|_platform| {});
|
||||
.build::<PivApp>()
|
||||
.exec(|_platform| {});
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,12 +11,12 @@
|
||||
|
||||
// TODO: add CLI
|
||||
|
||||
use piv_authenticator::{Authenticator, Options};
|
||||
use piv_authenticator::{virt::with_ram_client, Authenticator, Options};
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
trussed_rsa_alloc::virt::with_ram_client("piv-authenticator", |client| {
|
||||
with_ram_client("piv-authenticator", |client| {
|
||||
let card = Authenticator::new(client, Options::default());
|
||||
let mut vpicc_card = piv_authenticator::vpicc::VpiccCard::new(card);
|
||||
let vpicc = vpicc::connect().expect("failed to connect to vpicc");
|
||||
|
||||
@@ -28,6 +28,8 @@ mod tlv;
|
||||
|
||||
pub use piv_types::{AsymmetricAlgorithms, Pin, Puk};
|
||||
|
||||
#[cfg(feature = "virt")]
|
||||
pub mod virt;
|
||||
#[cfg(feature = "vpicc")]
|
||||
pub mod vpicc;
|
||||
|
||||
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
// Copyright (C) 2022 Nitrokey GmbH
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
//! Virtual trussed client (mostly for testing)
|
||||
|
||||
pub mod dispatch {
|
||||
|
||||
use trussed::{
|
||||
api::{reply, request, Reply, Request},
|
||||
backend::{Backend as _, BackendId},
|
||||
error::Error,
|
||||
platform::Platform,
|
||||
serde_extensions::{ExtensionDispatch, ExtensionId, ExtensionImpl as _},
|
||||
service::ServiceResources,
|
||||
types::{Bytes, Context, Location},
|
||||
};
|
||||
use trussed_auth::{AuthBackend, AuthContext, AuthExtension, MAX_HW_KEY_LEN};
|
||||
|
||||
use trussed_rsa_alloc::SoftwareRsa;
|
||||
|
||||
/// Backends used by opcard
|
||||
pub const BACKENDS: &[BackendId<Backend>] = &[
|
||||
BackendId::Custom(Backend::Auth),
|
||||
BackendId::Custom(Backend::Rsa),
|
||||
BackendId::Core,
|
||||
];
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Backend {
|
||||
Auth,
|
||||
Rsa,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Extension {
|
||||
Auth,
|
||||
}
|
||||
|
||||
impl From<Extension> for u8 {
|
||||
fn from(extension: Extension) -> Self {
|
||||
match extension {
|
||||
Extension::Auth => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for Extension {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(id: u8) -> Result<Self, Self::Error> {
|
||||
match id {
|
||||
0 => Ok(Extension::Auth),
|
||||
_ => Err(Error::InternalError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch implementation with the backends required by opcard
|
||||
#[derive(Debug)]
|
||||
pub struct Dispatch {
|
||||
auth: AuthBackend,
|
||||
}
|
||||
|
||||
/// Dispatch context for the backends required by opcard
|
||||
#[derive(Default, Debug)]
|
||||
pub struct DispatchContext {
|
||||
auth: AuthContext,
|
||||
}
|
||||
|
||||
impl Dispatch {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
auth: AuthBackend::new(Location::Internal),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_hw_key(hw_key: Bytes<MAX_HW_KEY_LEN>) -> Self {
|
||||
Self {
|
||||
auth: AuthBackend::with_hw_key(Location::Internal, hw_key),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Dispatch {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionDispatch for Dispatch {
|
||||
type BackendId = Backend;
|
||||
type Context = DispatchContext;
|
||||
type ExtensionId = Extension;
|
||||
|
||||
fn core_request<P: Platform>(
|
||||
&mut self,
|
||||
backend: &Self::BackendId,
|
||||
ctx: &mut Context<Self::Context>,
|
||||
request: &Request,
|
||||
resources: &mut ServiceResources<P>,
|
||||
) -> Result<Reply, Error> {
|
||||
match backend {
|
||||
Backend::Auth => {
|
||||
self.auth
|
||||
.request(&mut ctx.core, &mut ctx.backends.auth, request, resources)
|
||||
}
|
||||
Backend::Rsa => SoftwareRsa.request(&mut ctx.core, &mut (), request, resources),
|
||||
}
|
||||
}
|
||||
|
||||
fn extension_request<P: Platform>(
|
||||
&mut self,
|
||||
backend: &Self::BackendId,
|
||||
extension: &Self::ExtensionId,
|
||||
ctx: &mut Context<Self::Context>,
|
||||
request: &request::SerdeExtension,
|
||||
resources: &mut ServiceResources<P>,
|
||||
) -> Result<reply::SerdeExtension, Error> {
|
||||
match backend {
|
||||
Backend::Auth => match extension {
|
||||
Extension::Auth => self.auth.extension_request_serialized(
|
||||
&mut ctx.core,
|
||||
&mut ctx.backends.auth,
|
||||
request,
|
||||
resources,
|
||||
),
|
||||
},
|
||||
Backend::Rsa => Err(Error::RequestNotAvailable),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionId<AuthExtension> for Dispatch {
|
||||
type Id = Extension;
|
||||
|
||||
const ID: Self::Id = Self::Id::Auth;
|
||||
}
|
||||
}
|
||||
|
||||
use std::path::PathBuf;
|
||||
use trussed::{
|
||||
types::Bytes,
|
||||
virt::{self, Client, Filesystem, Ram, StoreProvider},
|
||||
};
|
||||
|
||||
/// Client type using a dispatcher with the backends required by opcard
|
||||
pub type VirtClient<S> = Client<S, dispatch::Dispatch>;
|
||||
|
||||
/// Run a client using a provided store
|
||||
pub fn with_client<S, R, F>(store: S, client_id: &str, f: F) -> R
|
||||
where
|
||||
F: FnOnce(VirtClient<S>) -> R,
|
||||
S: StoreProvider,
|
||||
{
|
||||
#[allow(clippy::unwrap_used)]
|
||||
virt::with_platform(store, |platform| {
|
||||
platform.run_client_with_backends(
|
||||
client_id,
|
||||
dispatch::Dispatch::with_hw_key(Bytes::from_slice(b"some bytes").unwrap()),
|
||||
dispatch::BACKENDS,
|
||||
f,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Run the backend with the extensions required by opcard
|
||||
/// using storage backed by a file
|
||||
pub fn with_fs_client<P, R, F>(internal: P, client_id: &str, f: F) -> R
|
||||
where
|
||||
F: FnOnce(VirtClient<Filesystem>) -> R,
|
||||
P: Into<PathBuf>,
|
||||
{
|
||||
with_client(Filesystem::new(internal), client_id, f)
|
||||
}
|
||||
|
||||
/// Run the backend with the extensions required by opcard
|
||||
/// using a RAM file storage
|
||||
pub fn with_ram_client<R, F>(client_id: &str, f: F) -> R
|
||||
where
|
||||
F: FnOnce(VirtClient<Ram>) -> R,
|
||||
{
|
||||
with_client(Ram::default(), client_id, f)
|
||||
}
|
||||
+4
-3
@@ -3,7 +3,8 @@
|
||||
|
||||
use iso7816::{command::FromSliceError, Command, Status};
|
||||
use trussed::virt::Ram;
|
||||
use trussed_rsa_alloc::virt::Client;
|
||||
|
||||
use crate::virt::VirtClient;
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
@@ -19,12 +20,12 @@ const RESPONSE_LEN: usize = 7609;
|
||||
pub struct VpiccCard {
|
||||
request_buffer: RequestBuffer<REQUEST_LEN>,
|
||||
response_buffer: ResponseBuffer<RESPONSE_LEN>,
|
||||
card: Authenticator<Client<Ram>>,
|
||||
card: Authenticator<VirtClient<Ram>>,
|
||||
}
|
||||
|
||||
impl VpiccCard {
|
||||
/// Creates a new virtual smart card from the given card.
|
||||
pub fn new(card: Authenticator<Client<Ram>>) -> Self {
|
||||
pub fn new(card: Authenticator<VirtClient<Ram>>) -> Self {
|
||||
Self {
|
||||
request_buffer: Default::default(),
|
||||
response_buffer: Default::default(),
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2022 Nitrokey GmbH
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
use piv_authenticator::{vpicc::VpiccCard, Authenticator, Options};
|
||||
use piv_authenticator::{virt::with_ram_client, vpicc::VpiccCard, Authenticator, Options};
|
||||
|
||||
use std::{sync::mpsc, thread::sleep, time::Duration};
|
||||
use stoppable_thread::spawn;
|
||||
@@ -17,7 +17,7 @@ pub fn with_vsc<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let handle = spawn(move |stopped| {
|
||||
trussed_rsa_alloc::virt::with_ram_client("opcard", |client| {
|
||||
with_ram_client("opcard", |client| {
|
||||
let card = Authenticator::new(client, Options::default());
|
||||
let mut vpicc_card = VpiccCard::new(card);
|
||||
let mut result = Ok(());
|
||||
|
||||
+6
-4
@@ -11,14 +11,16 @@ macro_rules! cmd {
|
||||
};
|
||||
}
|
||||
|
||||
use piv_authenticator::{Authenticator, Options};
|
||||
use piv_authenticator::{
|
||||
virt::{with_ram_client, VirtClient},
|
||||
Authenticator, Options,
|
||||
};
|
||||
use trussed::virt::Ram;
|
||||
use trussed_rsa_alloc::virt::Client;
|
||||
|
||||
pub type Piv = piv_authenticator::Authenticator<Client<Ram>>;
|
||||
pub type Piv = piv_authenticator::Authenticator<VirtClient<Ram>>;
|
||||
|
||||
pub fn piv<R>(test: impl FnOnce(&mut Piv) -> R) -> R {
|
||||
trussed_rsa_alloc::virt::with_ram_client("test", |client| {
|
||||
with_ram_client("test", |client| {
|
||||
let mut piv_app = Authenticator::new(client, Options::default());
|
||||
test(&mut piv_app)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user