From 17c3f0818753ed06a07e53aa71c93a8ee9397fbd Mon Sep 17 00:00:00 2001 From: Caio Tavares Date: Fri, 5 Mar 2021 15:46:21 -0300 Subject: [PATCH 1/3] Using lib structure --- src/{controller.rs => lib.rs} | 18 ++++++++++++------ src/main.rs | 26 ++++++++++---------------- 2 files changed, 22 insertions(+), 22 deletions(-) rename src/{controller.rs => lib.rs} (91%) diff --git a/src/controller.rs b/src/lib.rs similarity index 91% rename from src/controller.rs rename to src/lib.rs index 44364c0..1e620a7 100644 --- a/src/controller.rs +++ b/src/lib.rs @@ -1,11 +1,17 @@ use structopt::StructOpt; -use crate::apdu::capdu; -use crate::apdu::capdu::{APDU, CryptogramType}; -use crate::apdu::rapdu::{RAPDU, Status}; -use crate::cli::interface::{Command, Emv, Mode}; -use crate::connection::usb; -use crate::tlv::parser::TLV; +use apdu::capdu; +use apdu::capdu::{APDU, CryptogramType}; +use apdu::rapdu::{RAPDU, Status}; +use cli::interface::{Command, Emv, Mode}; +use connection::usb; +use tlv::parser::TLV; + +pub mod apdu; +pub mod cli; +pub mod connection; +pub mod tlv; +pub mod utils; fn send(card: &pcsc::Card, apdu: APDU) { usb::transmit(card, &apdu) diff --git a/src/main.rs b/src/main.rs index 886bf36..9b85d26 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,15 +5,9 @@ use std::process; use structopt::StructOpt; -use crate::cli::interface::{Command, Emv, Mode}; -use crate::connection::usb; - -mod apdu; -mod cli; -mod connection; -mod tlv; -mod utils; -mod controller; +use emv::cli::interface::{Command, Emv, Mode}; +use emv::connection::usb; +use emv::cli; fn main() { let args: Emv = Emv::from_args(); @@ -55,26 +49,26 @@ fn run(input: PathBuf, card: pcsc::Card) { fn execute(command: Command, card: &pcsc::Card) { match command { Command::Select { application } => { - controller::select_application(card, application); + emv::select_application(card, application); } Command::GetProcessingOptions => { - controller::get_processing_options(card); + emv::get_processing_options(card); } Command::GenerateAC { cryptogram_type, cdol } => { let cdol_value = cdol.unwrap_or_else(|| { cli::read_hex_input("Input the CDOL value: ") }); - controller::generate_ac(card, cryptogram_type, cdol_value); + emv::generate_ac(card, cryptogram_type, cdol_value); } Command::PutData { tag, value } => { - controller::put_data(card, tag, value, cli::read_hex_input("Input the MAC: ")); + emv::put_data(card, tag, value, cli::read_hex_input("Input the MAC: ")); } Command::GetData { tag } => { - controller::get_data(card, tag); + emv::get_data(card, tag); } Command::ReadRecord { record, sfi } => { - controller::read_record(&card, record, sfi); + emv::read_record(&card, record, sfi); } Command::PinUnblock => { - controller::unblock_pin(&card, cli::read_hex_input("Input the MAC: ")); + emv::unblock_pin(&card, cli::read_hex_input("Input the MAC: ")); } } } From 79cfed0b6e092220020f6cc5b8c4ed111974e622 Mon Sep 17 00:00:00 2001 From: Caio Tavares Date: Fri, 5 Mar 2021 15:56:29 -0300 Subject: [PATCH 2/3] Colorize inputs/outputs --- Cargo.lock | 37 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/cli/mod.rs | 22 ++++++++++++++++++++++ src/connection/usb.rs | 5 +++-- 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb12cd9..906ccc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,6 +48,7 @@ dependencies = [ "hex", "pcsc", "structopt", + "termion", ] [[package]] @@ -86,6 +87,12 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" + [[package]] name = "pcsc" version = "2.4.0" @@ -153,6 +160,24 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_termios" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" +dependencies = [ + "redox_syscall", +] + [[package]] name = "strsim" version = "0.8.0" @@ -194,6 +219,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "termion" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" +dependencies = [ + "libc", + "numtoa", + "redox_syscall", + "redox_termios", +] + [[package]] name = "textwrap" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 3944a69..df8589f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ edition = "2018" pcsc = { version = "2.4.0" } structopt = "0.3.21" hex = "0.4.2" +termion = "1.5.6" diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 7427274..f16ff22 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,15 +1,37 @@ use std::io; use std::io::Write; +use termion::color; + +use crate::apdu::capdu::APDU; +use crate::apdu::rapdu::RAPDU; use crate::cli::interface::Command; mod banner; pub mod interface; +const INPUT_COLOR: color::Rgb = color::Rgb(245, 181, 71); +const OUTPUT_COLOR: color::Rgb = color::Rgb(77, 128, 247); + pub fn announcement() { println!("{}", banner::BANNER); } +pub fn print_input(apdu: &RAPDU) { + println!("{red}R-APDU: {bytes:02X?}{reset}", + red = color::Fg(INPUT_COLOR), + bytes = apdu, + reset = color::Fg(color::Reset)); +} + +pub fn print_output(apdu: &APDU) { + println!("\n{green}C-APDU: {name}: {bytes:02X?}{reset}", + green = color::Fg(OUTPUT_COLOR), + name = apdu.name, + bytes = apdu.to_array(), + reset = color::Fg(color::Reset)); +} + pub fn read_command() -> Option { let mut buffer = String::new(); print!("> "); diff --git a/src/connection/usb.rs b/src/connection/usb.rs index fac824a..4249db1 100644 --- a/src/connection/usb.rs +++ b/src/connection/usb.rs @@ -2,10 +2,11 @@ use pcsc::*; use crate::apdu::capdu::APDU; use crate::apdu::rapdu::{RAPDU, Status}; +use crate::cli; pub fn transmit(card: &Card, apdu: &APDU) -> Result { let mut buffer = [0; MAX_BUFFER_SIZE]; - println!("\nC-APDU: {}: {:02X?}", apdu.name, apdu.to_array()); + cli::print_output(&apdu); match card.transmit(&apdu.to_array(), &mut buffer) { Ok(response) => { let rapdu; @@ -18,7 +19,7 @@ pub fn transmit(card: &Card, apdu: &APDU) -> Result { else { rapdu = RAPDU::new(Status::new(response[length - 2], response[length - 1]), &response[0..length - 2]); } - println!("R-APDU: {:02X?}", rapdu); + cli::print_input(&rapdu); Ok(rapdu) } Err(err) => { From 71d82d1a93cfb86978f2f1236239e0627f54e591 Mon Sep 17 00:00:00 2001 From: Caio Tavares Date: Fri, 5 Mar 2021 15:58:52 -0300 Subject: [PATCH 3/3] Move Command enum to apdu module --- src/apdu/mod.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/cli/interface.rs | 61 ----------------------------------------- src/cli/mod.rs | 2 +- src/lib.rs | 2 +- src/main.rs | 5 ++-- 5 files changed, 69 insertions(+), 65 deletions(-) diff --git a/src/apdu/mod.rs b/src/apdu/mod.rs index 3e2338f..dfec95c 100644 --- a/src/apdu/mod.rs +++ b/src/apdu/mod.rs @@ -1,2 +1,66 @@ +use crate::apdu::capdu::CryptogramType; +use crate::utils::extension::Hexadecimal; + pub mod capdu; pub mod rapdu; + +#[derive(Debug)] +pub enum Command { + Select { + application: Vec + }, + GetProcessingOptions, + ReadRecord { + record: u8, + sfi: u8, + }, + GenerateAC { + cryptogram_type: CryptogramType, + cdol: Option>, + }, + PutData { + tag: u16, + value: Vec, + }, + GetData { + tag: u16 + }, + PinUnblock, +} + +impl Command { + pub fn from_str(str: String) -> Result { + let parts: Vec<&str> = str.trim().split(' ').collect(); + let name = parts[0].to_lowercase(); + + match name.as_str() { + "select" => Ok(Command::Select { + application: parts[1].to_vec_u8() + }), + "get_processing_options" => Ok(Command::GetProcessingOptions), + "generate_ac" => { + let mut cdol = None; + if parts.len() > 2 { + cdol = Some(parts[2].to_vec_u8()); + } + Ok(Command::GenerateAC { + cryptogram_type: CryptogramType::from_str(parts[1]), + cdol, + }) + } + "get_data" => Ok(Command::GetData { + tag: parts[1].to_u16() + }), + "put_data" => Ok(Command::PutData { + tag: parts[1].to_u16(), + value: parts[2].to_vec_u8(), + }), + "read_record" => Ok(Command::ReadRecord { + record: parts[1].to_u8(), + sfi: parts[2].to_u8(), + }), + "pin_unblock" => Ok(Command::PinUnblock), + _ => Err(name) + } + } +} diff --git a/src/cli/interface.rs b/src/cli/interface.rs index f3005f0..f90543b 100644 --- a/src/cli/interface.rs +++ b/src/cli/interface.rs @@ -20,64 +20,3 @@ pub enum Mode { input: PathBuf }, } - -#[derive(Debug)] -pub enum Command { - Select { - application: Vec - }, - GetProcessingOptions, - ReadRecord { - record: u8, - sfi: u8, - }, - GenerateAC { - cryptogram_type: CryptogramType, - cdol: Option>, - }, - PutData { - tag: u16, - value: Vec, - }, - GetData { - tag: u16 - }, - PinUnblock, -} - -impl Command { - pub fn from_str(str: String) -> Result { - let parts: Vec<&str> = str.trim().split(' ').collect(); - let name = parts[0].to_lowercase(); - - match name.as_str() { - "select" => Ok(Command::Select { - application: parts[1].to_vec_u8() - }), - "get_processing_options" => Ok(Command::GetProcessingOptions), - "generate_ac" => { - let mut cdol = None; - if parts.len() > 2 { - cdol = Some(parts[2].to_vec_u8()); - } - Ok(Command::GenerateAC { - cryptogram_type: CryptogramType::from_str(parts[1]), - cdol, - }) - } - "get_data" => Ok(Command::GetData { - tag: parts[1].to_u16() - }), - "put_data" => Ok(Command::PutData { - tag: parts[1].to_u16(), - value: parts[2].to_vec_u8(), - }), - "read_record" => Ok(Command::ReadRecord { - record: parts[1].to_u8(), - sfi: parts[2].to_u8(), - }), - "pin_unblock" => Ok(Command::PinUnblock), - _ => Err(name) - } - } -} diff --git a/src/cli/mod.rs b/src/cli/mod.rs index f16ff22..baa747d 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -4,8 +4,8 @@ use std::io::Write; use termion::color; use crate::apdu::capdu::APDU; +use crate::apdu::Command; use crate::apdu::rapdu::RAPDU; -use crate::cli::interface::Command; mod banner; pub mod interface; diff --git a/src/lib.rs b/src/lib.rs index 1e620a7..3cdeca3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ use structopt::StructOpt; use apdu::capdu; use apdu::capdu::{APDU, CryptogramType}; use apdu::rapdu::{RAPDU, Status}; -use cli::interface::{Command, Emv, Mode}; +use cli::interface::{Emv, Mode}; use connection::usb; use tlv::parser::TLV; diff --git a/src/main.rs b/src/main.rs index 9b85d26..d560172 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,9 +5,10 @@ use std::process; use structopt::StructOpt; -use emv::cli::interface::{Command, Emv, Mode}; -use emv::connection::usb; +use emv::apdu::Command; use emv::cli; +use emv::cli::interface::{Emv, Mode}; +use emv::connection::usb; fn main() { let args: Emv = Emv::from_args();