1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use alloc::vec::Vec;
pub fn make_apdu(cla: u8, ins: u8, param: (u8, u8), data: &[u8], maxsize: Option<u8>) -> Vec<u8> {
let mut packet_size = 5;
let data_size = data.len();
if data_size == 0 {
packet_size += 0;
} else if data_size <= 0xff {
packet_size += 1 + data_size;
} else if data_size <= 0xffff {
packet_size += 3 + data_size;
} else {
panic!("Data size is too large");
}
let mut buf: Vec<u8> = Vec::with_capacity(packet_size);
buf.push(cla);
buf.push(ins);
buf.push(param.0);
buf.push(param.1);
if data_size == 0 {
} else if data_size <= 0xff {
buf.push(data_size as u8);
} else if data_size <= 0xffff {
buf.push(0);
buf.push(data_size as u8 >> 4);
buf.push(data_size as u8 & 0xff);
}
buf.extend_from_slice(data);
if let Some(max) = maxsize {
buf.push(max);
}
buf
}
const fn is_digit(ch: u8) -> bool {
('0' as u8 <= ch) & (ch <= '9' as u8)
}
pub fn check_pin(pin_str: &str) -> bool {
let pin = pin_str.as_bytes();
pin.len() == 4 && is_digit(pin[0]) && is_digit(pin[1]) && is_digit(pin[2]) && is_digit(pin[3])
}
pub fn check_password(password: &str) -> bool {
unimplemented!()
}
#[cfg(test)]
mod tests {
use super::*;
extern crate hex_literal;
use hex_literal::hex;
#[test]
fn it_makes_apdu() {
assert_eq!(
make_apdu(0x00, 0x0a, (0x0b, 0x00), &[1, 2, 3, 4, 5], Some(0)),
hex!("000a0b0005010203040500")
);
}
#[test]
fn it_makes_apdu_without_le() {
assert_eq!(
make_apdu(0x00, 0x0a, (0x0b, 0x00), &[1, 2, 3, 4, 5], None),
hex!("000a0b00050102030405")
);
}
#[test]
fn it_checks_valid_pin() {
assert_eq!(check_pin("1919"), true);
}
#[test]
fn it_checks_non_digit_pin() {
assert_eq!(check_pin("pien"), false);
}
#[test]
fn it_checks_digit_non_digit_pin() {
assert_eq!(check_pin("pa0n"), false);
}
#[test]
fn it_checks_too_long_pin() {
assert_eq!(check_pin("114514"), false);
}
}