basic setup of card internal

This commit is contained in:
nganhkhoa 2024-08-12 10:19:36 +07:00
parent de3b17c7de
commit b78526df9b
11 changed files with 238 additions and 5 deletions

View File

@ -12,6 +12,7 @@ bug-reports: "https://github.com/username/reponame/issues"
depends: [
"ocaml"
"dune" {>= "3.12"}
"hex"
"odoc" {with-doc}
]
build: [

140
bin/card.ml Normal file
View File

@ -0,0 +1,140 @@
open SmartCard
(** This file contains the default card data *)
(* EF.CardAccess *)
let ef_cardacces =
Filesystem.ElementaryFile {
fid = Bytes.of_string "\x01\x1C";
sid = Bytes.of_string "\x1C";
data = Hex.to_bytes (Hex.of_string "3134300d060804007f0007020202020101300f060a04007f000702020302020201013012060a04007f0007020204020202010202010d");
}
(* EF.CardSecurity *)
let ef_cardsecurity =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x1D";
data = Hex.to_bytes (Hex.of_string "");
}
(* EF.DIR *)
let ef_dir =
Filesystem.ElementaryFile {
fid = Bytes.of_string "\x01\x1E";
sid = Bytes.of_string "\x1E";
data = Hex.to_bytes (Hex.of_string "");
}
(* EF.ATR
The EF.ATR/INFO may be called EF.ATR in contact card
standards or specifications, and may be called EF.INFO
in contactless card standards or specifications
The contents of the EF.ATR/INFO can be freely retrieved by using a GET DATA command with
P1-P2 = '2F 01' and a command data field of '5C 00' ('00 CB 2F 01 02 5C 00'). The response data field for
the GET DATA command is the concatenation of all Data Objects (DO) which are present in EF.ATR/INFO.
It contains the BER-TLV content of the EF.ATR/INFO
*)
let ef_atr =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x01";
data = Hex.to_bytes (Hex.of_string "");
}
(* EF.COM *)
let ef_com =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x1E";
data = Bytes.of_string (Base64.decode_exn "");
}
(* EF.DG1 *)
let ef_dg1 =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x01";
data = Bytes.of_string (Base64.decode_exn "");
}
(* EF.DG2 *)
let ef_dg2 =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x02";
data = Bytes.of_string (Base64.decode_exn "");
}
(* EF.DG13 *)
let ef_dg13 =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x0D";
data = Bytes.of_string (Base64.decode_exn "");
}
(* EF.DG14 *)
let ef_dg14 =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x0E";
data = Bytes.of_string (Base64.decode_exn "");
}
(* EF.DG15 *)
let ef_dg15 =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x0F";
data = Bytes.of_string (Base64.decode_exn "");
}
(* EF.SOD *)
let ef_sod =
Filesystem.ElementaryFile {
fid = Bytes.of_string "";
sid = Bytes.of_string "\x1D";
data = Bytes.of_string (Base64.decode_exn "");
}
(* LDS1 eMRTD Application *)
let emrtd_application =
Filesystem.DelicatedFile {
fid = Bytes.of_string "";
aid = Some (Bytes.of_string "\xA0\x00\x00\x02\x47\x10\x01");
files = [
ef_com;
ef_dg1;
ef_dg2;
ef_dg13;
ef_dg14;
ef_dg15;
ef_sod
];
}
(** The masterfile MF for the card *)
let masterfile = Filesystem.DelicatedFile {
fid = Bytes.of_string "\x3F\x00";
aid = None;
files = [
ef_cardacces;
emrtd_application
];
}
(** The card can have multiple files, MF included *)
let allfiles = [masterfile]
let custom : CardState.t = {
masterfile = Some masterfile;
allfiles = allfiles;
sm = None;
current_file = None;
}

View File

@ -1,4 +1,5 @@
(env (dev (flags :standard -warn-error -27-32)))
(executable
(public_name apdu)
(name main)
(libraries apdu))
(libraries SmartCard hex base64))

View File

@ -1 +1,10 @@
let () = print_endline "Hello, World!"
let main =
let f = SmartCard.Filesystem.find_by_fid (Bytes.of_string "\x01\x1C") Card.custom.allfiles
in
match f with
| Some _ -> print_endline "File found"
| None -> print_endline "File not found"
let hmmge =
let command = Bytes.of_string "\x00\x86\x00\x00" in
SmartCard.CardState.process command Card.custom

View File

@ -19,7 +19,7 @@
(name apdu)
(synopsis "A short synopsis")
(description "A longer description")
(depends ocaml dune)
(depends ocaml dune hex)
(tags
(topics "to describe" your project)))

View File

@ -1,2 +0,0 @@
(library
(name apdu))

27
smartcard/CardState.ml Normal file
View File

@ -0,0 +1,27 @@
(**
ICAO 9303 communication is like a state machine,
we can make a state machine initialized and for
each subsequent commands, modifying the state.
So actually we can make an OCAML state machine.
*)
type t = {
(* a MF may not exist *)
masterfile : Filesystem.t option;
(* a list of every files in the card *)
allfiles : Filesystem.t list;
(* encryption scheme *)
sm : SecureMessage.t option;
(* currently selected file *)
current_file : Filesystem.t option;
}
let process command _state =
let cm = Command.parse command in
match cm.ins with
| 0x44 -> print_endline "ACTIVATE FILE"
| 0xE2 -> print_endline "APPEND RECORD"
| 0x82 -> print_endline "EXTERNAL / MUTUAL AUTHENTICATE"
| 0x86 -> print_endline "GENERAL AUTHENTICATE 0x86"
| 0x87 -> print_endline "GENERAL AUTHENTICATE 0x87"
| _ -> print_endline "NOT IMPLEMENTED"

13
smartcard/Command.ml Normal file
View File

@ -0,0 +1,13 @@
type t = {
cla : int;
ins : int;
p1 : int;
p2 : int;
}
let parse command = {
cla = Bytes.get command 0 |> Char.code;
ins = Bytes.get command 1 |> Char.code;
p1 = Bytes.get command 2 |> Char.code;
p2 = Bytes.get command 3 |> Char.code;
}

39
smartcard/Filesystem.ml Normal file
View File

@ -0,0 +1,39 @@
type t
= DelicatedFile of {
fid : Bytes.t;
aid : Bytes.t option;
files : t list;
}
| ElementaryFile of {
fid : Bytes.t;
sid : Bytes.t;
data : Bytes.t;
}
let find_by_fid fid files =
let rec eachfile = fun file ->
match file with
| DelicatedFile df -> if Bytes.equal fid df.fid
then true
else List.exists eachfile df.files
| ElementaryFile ef -> Bytes.equal fid ef.fid
in
List.find_opt eachfile files
let find_by_aid aid files =
let rec eachfile = fun file ->
match file with
| ElementaryFile _ -> false
| DelicatedFile df -> match df.aid with
| Some id -> Bytes.equal aid id
| None -> List.exists eachfile df.files
in
List.find_opt eachfile files
let find_by_sid sid files =
let rec eachfile = fun file ->
match file with
| DelicatedFile df -> List.exists eachfile df.files
| ElementaryFile ef -> Bytes.equal sid ef.sid
in
List.find_opt eachfile files

View File

@ -0,0 +1,3 @@
type t
= TripleDES
| AES

2
smartcard/dune Normal file
View File

@ -0,0 +1,2 @@
(library
(name SmartCard))