// EMV command builders and response templates.
pub fn select_ppse() -> Apdu {
Apdu::new(0x00, 0xa4, 0x04, 0x00, data=ascii_bytes("2PAY.SYS.DDF01"), le=0)
}
pub fn select_aid(aid : Array[Int]) -> Apdu {
Apdu::new(0x00, 0xa4, 0x04, 0x00, data=aid, le=0)
}
pub fn gpo(pdol_data : Array[Int]) -> Apdu {
let data : Array[Int] = [0x83]
data.push(pdol_data.length() & 0xff)
for b in pdol_data {
data.push(b)
}
Apdu::new(0x80, 0xa8, 0x00, 0x00, data=data, le=0)
}
pub fn read_record(record : Int, sfi : Int) -> Apdu {
Apdu::new(0x00, 0xb2, record, ((sfi & 0x1f) << 3) | 4, le=0)
}
pub fn generate_ac(p1 : Int, cdol_data : Array[Int]) -> Apdu {
Apdu::new(0x80, 0xae, p1, 0x00, data=cdol_data, le=0)
}
pub fn verify_pin(pin_block : Array[Int]) -> Apdu {
Apdu::new(0x00, 0x20, 0x00, 0x80, data=pin_block)
}
pub fn get_data(tag : Int) -> Apdu {
Apdu::new(0x80, 0xca, (tag >> 8) & 0xff, tag & 0xff, le=0)
}
pub(all) struct GpoInfo {
aip : Array[Int]
afl : Array[Int]
}
pub fn parse_gpo_response(bytes : Array[Int]) -> GpoInfo? raise TlvError {
let items = parse_tlv(bytes)
match find_tag(items, 0x77) {
Some(template) => {
let aip = match find_tag(template.children, 0x82) {
Some(t) => t.value
None => []
}
let afl = match find_tag(template.children, 0x94) {
Some(t) => t.value
None => []
}
Some({ aip, afl })
}
None =>
match find_tag(items, 0x80) {
Some(t) =>
if t.value.length() >= 2 {
let aip : Array[Int] = [t.value[0], t.value[1]]
let afl : Array[Int] = Array::new()
for i in 2.. None
}
}
}
pub fn parse_record(bytes : Array[Int]) -> Array[Tlv]? raise TlvError {
let items = parse_tlv(bytes)
match find_tag(items, 0x70) {
Some(template) => Some(template.children)
None => Some(items)
}
}
pub(all) struct AflEntry {
sfi : Int
first_record : Int
last_record : Int
oda_count : Int
}
pub fn parse_afl(afl : Array[Int]) -> Array[AflEntry] {
let out : Array[AflEntry] = Array::new()
let mut i = 0
while i + 3 < afl.length() {
out.push({
sfi: (afl[i] >> 3) & 0x1f,
first_record: afl[i + 1],
last_record: afl[i + 2],
oda_count: afl[i + 3],
})
i = i + 4
}
out
}