Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ members = [
"cli",
"ffi/generic",
"ffi/android",
"ffi/dotnet",
]
4 changes: 4 additions & 0 deletions ffi/dotnet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/bin/
/obj/
*.g.cs
*.user
68 changes: 68 additions & 0 deletions ffi/dotnet/Ap/CryptoAp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using Siketyan.Jpki.Native;

namespace Siketyan.Jpki.Ap;

public class CryptoAp
{
private readonly unsafe Native.CryptoAp* _ptr;
private readonly Card _card;

public CryptoAp(Card card)
{
_card = card;

unsafe
{
_ptr = NativeMethods.jpki_new_crypto_ap(card.Ptr);
}
}

~CryptoAp()
{
unsafe
{
NativeMethods.jpki_crypto_ap_close(_ptr);
}
}

public Span<byte> ReadCertificateSign(ReadOnlySpan<byte> pin, bool ca)
{
unsafe
{
fixed (byte* b = pin)
{
return NativeMethods.jpki_crypto_ap_read_certificate_sign(_ptr, b, ca).AsSpan();
}
}
}

public Span<byte> ReadCertificateAuth(bool ca)
{
unsafe
{
return NativeMethods.jpki_crypto_ap_read_certificate_auth(_ptr, ca).AsSpan();
}
}

public Span<byte> Sign(ReadOnlySpan<byte> pin, ReadOnlySpan<byte> digest)
{
unsafe
{
fixed (byte* b = pin)
{
return NativeMethods.jpki_crypto_ap_sign(_ptr, b, ByteArray.FromSpan(digest)).AsSpan();
}
}
}

public Span<byte> Auth(ReadOnlySpan<byte> pin, ReadOnlySpan<byte> digest)
{
unsafe
{
fixed (byte* b = pin)
{
return NativeMethods.jpki_crypto_ap_auth(_ptr, b, ByteArray.FromSpan(digest)).AsSpan();
}
}
}
}
25 changes: 25 additions & 0 deletions ffi/dotnet/Card.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Siketyan.Jpki.Native;

namespace Siketyan.Jpki;

public class Card
{
internal readonly unsafe Native.Card* Ptr;

private readonly NfcCardAdapter _adapter;

public Card(NfcCardAdapter adapter)
{
_adapter = adapter;

unsafe
{
Ptr = NativeMethods.jpki_new_card(adapter.Ptr);
}
}

public Ap.CryptoAp OpenCryptoAp()
{
return new Ap.CryptoAp(this);
}
}
21 changes: 21 additions & 0 deletions ffi/dotnet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "jpki-ffi-dotnet"
description = "FFI binding of jpki-rs for C#, F#, and VB.NET."
version = "0.4.2"
license = "LGPL-2.1-or-later"
homepage = "https://github.com/siketyan/jpki-rs"
repository = "https://github.com/siketyan/jpki-rs.git"
authors = [
# Thank you for your contribution!
# While contributing to this project, feel free to add your name here :)
"Naoki Ikeguchi <me@s6n.jp>",
]
readme = "../../README.md"
edition = "2021"

[dependencies]
jpki = { version = "=0.4.2", path = "../../core" }
jpki-ffi-generic = { version = "=0.4.2", path = "../generic" }

[build-dependencies]
csbindgen = "1.3"
6 changes: 6 additions & 0 deletions ffi/dotnet/INfcCard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Siketyan.Jpki;

public interface INfcCard
{
public Span<byte> Handle(ReadOnlySpan<byte> command);
}
11 changes: 11 additions & 0 deletions ffi/dotnet/Jpki.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Siketyan.Jpki.Native;

namespace Siketyan.Jpki;

public class Jpki
{
static Jpki()
{
NativeMethods.jpki_init();
}
}
43 changes: 43 additions & 0 deletions ffi/dotnet/Native/NativeMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace Siketyan.Jpki.Native;

internal struct Card
{
}

internal struct CryptoAp
{
}

internal partial struct ByteArray
{
public unsafe Span<byte> AsSpan()
{
return new Span<byte>(ptr, (int)len);
}

public static unsafe ByteArray FromSpan(Span<byte> span)
{
fixed (byte* ptr = &span.GetPinnableReference())
{
return new ByteArray
{
cap = (nuint)span.Length,
len = (nuint)span.Length,
ptr = ptr,
};
}
}

public static unsafe ByteArray FromSpan(ReadOnlySpan<byte> span)
{
fixed (byte* ptr = &span.GetPinnableReference())
{
return new ByteArray
{
cap = (nuint)span.Length,
len = (nuint)span.Length,
ptr = ptr,
};
}
}
}
25 changes: 25 additions & 0 deletions ffi/dotnet/NfcCard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Siketyan.Jpki.Native;

namespace Siketyan.Jpki;

public class NfcCardAdapter
{
internal readonly unsafe NfcCard* Ptr;

private readonly INfcCard _inner;

public NfcCardAdapter(INfcCard inner)
{
_inner = inner;

unsafe
{
Ptr = NativeMethods.jpki_new_nfc_card(Handle);
}
}

private ByteArray Handle(ByteArray command)
{
return ByteArray.FromSpan(_inner.Handle(command.AsSpan()));
}
}
9 changes: 9 additions & 0 deletions ffi/dotnet/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn main() {
csbindgen::Builder::default()
.input_extern_file("../generic/src/lib.rs")
.csharp_dll_name("jpki")
.csharp_namespace("Siketyan.Jpki.Native")
.csharp_use_function_pointer(false)
.generate_csharp_file("./Native/NativeMethods.g.cs")
.unwrap();
}
19 changes: 19 additions & 0 deletions ffi/dotnet/dotnet.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyName>Siketyan.Jpki</AssemblyName>
<RootNamespace>Siketyan.Jpki</RootNamespace>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

</Project>
1 change: 1 addition & 0 deletions ffi/dotnet/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

8 changes: 4 additions & 4 deletions ffi/generic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ impl ByteArray {
}

pub struct NfcCard {
delegate: extern "C" fn(ByteArray) -> ByteArray,
delegate_: extern "C" fn(command: ByteArray) -> ByteArray,
}

impl HandlerInCtx for NfcCard {
fn handle_in_ctx(&self, _: (), command: &[u8], response: &mut [u8]) -> NfcResult {
let command = Vec::from(command).into();
let buf = Vec::from((self.delegate)(command));
let buf = Vec::from((self.delegate_)(command));
let len = buf.len();
if response.len() < len {
return Err(HandleError::NotEnoughBuffer(len));
Expand Down Expand Up @@ -116,9 +116,9 @@ pub extern "C" fn jpki_last_error() -> *mut c_char {
/// This provided function will be called on transmitting APDU commands into the card.
#[no_mangle]
pub extern "C" fn jpki_new_nfc_card(
delegate: extern "C" fn(ByteArray) -> ByteArray,
delegate_: extern "C" fn(command: ByteArray) -> ByteArray,
) -> *mut NfcCard {
let card = NfcCard { delegate };
let card = NfcCard { delegate_ };

Box::into_raw(Box::new(card))
}
Expand Down