Skip to content

Commit 44e7d1d

Browse files
Add Aes key import helper
1 parent 548e1ce commit 44e7d1d

File tree

2 files changed

+81
-9
lines changed

2 files changed

+81
-9
lines changed

tests/command-response.ron

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
cmd_resp: [
2121
VerifyDefaultPw3,
2222
VerifyDefaultPw1,
23-
// Set aes key
24-
IoData(input: "0C DA 00D5 20 FFEEDDCCBBAA00998877665544332211FFEEDDCCBBAA00998877665544332211"),
23+
ImportKey(
24+
key: "FFEEDDCCBBAA00998877665544332211FFEEDDCCBBAA00998877665544332211",
25+
key_kind: Aes,
26+
),
2527
// Encrypt with AES
2628
IoData(
2729
input: "00 2A 86 80 10 00112233445566778899AABBCCDDEEFF 00",

tests/command-response.rs

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use std::borrow::Cow;
66

77
use hex_literal::hex;
8+
use ron::{extensions::Extensions, Options};
89
use serde::Deserialize;
910

1011
// iso7816::Status doesn't support serde
@@ -34,6 +35,60 @@ enum Status {
3435
UnspecifiedCheckingError,
3536
}
3637

38+
#[derive(Debug, Clone, Copy, Deserialize)]
39+
#[repr(u16)]
40+
enum DataObject {
41+
PrivateUse1 = 0x0101,
42+
PrivateUse2 = 0x0102,
43+
PrivateUse3 = 0x0103,
44+
PrivateUse4 = 0x0104,
45+
ExtendedHeaderList = 0x3FFF,
46+
ApplicationIdentifier = 0x004F,
47+
LoginData = 0x005E,
48+
Url = 0x5F50,
49+
HistoricalBytes = 0x5F52,
50+
CardHolderRelatedData = 0x0065,
51+
CardHolderName = 0x005B,
52+
LanguagePreferences = 0x5F2D,
53+
CardHolderSex = 0x5F35,
54+
ApplicationRelatedData = 0x006E,
55+
GeneralFeatureManagement = 0x7f74,
56+
DiscretionaryDataObjects = 0x0073,
57+
ExtendedCapabilities = 0x00C0,
58+
AlgorithmAttributesSignature = 0x00C1,
59+
AlgorithmAttributesDecryption = 0x00C2,
60+
AlgorithmAttributesAuthentication = 0x00C3,
61+
PwStatusBytes = 0x00C4,
62+
Fingerprints = 0x00C5,
63+
CAFingerprints = 0x00C6,
64+
SignFingerprint = 0x00C7,
65+
DecFingerprint = 0x00C8,
66+
AuthFingerprint = 0x00C9,
67+
CaFingerprint1 = 0x00CA,
68+
CaFingerprint2 = 0x00CB,
69+
CaFingerprint3 = 0x00CC,
70+
KeyGenerationDates = 0x00CD,
71+
SignGenerationDate = 0x00CE,
72+
DecGenerationDate = 0x00CF,
73+
AuthGenerationDate = 0x00D0,
74+
KeyInformation = 0x00DE,
75+
SMkEnc = 0x00D1,
76+
SMkMac = 0x00D2,
77+
ResettingCode = 0x00D3,
78+
PSOEncDecKey = 0x00D5,
79+
SMEncMac = 0x00F4,
80+
UifCds = 0x00D6,
81+
UifDec = 0x00D7,
82+
UifAut = 0x00D8,
83+
SecuritySupportTemplate = 0x007A,
84+
DigitalSignatureCounter = 0x0093,
85+
CardHolderCertificate = 0x7f21,
86+
ExtendedLengthInformation = 0x7f66,
87+
KdfDo = 0x00F9,
88+
AlgorithmInformation = 0x00FA,
89+
SecureMessagingCertificate = 0x00FB,
90+
}
91+
3792
fn serialize_len(len: usize) -> heapless::Vec<u8, 3> {
3893
let mut buf = heapless::Vec::new();
3994
if let Ok(len) = u8::try_from(len) {
@@ -135,7 +190,7 @@ impl Default for Status {
135190
}
136191
}
137192

138-
#[derive(Deserialize, Debug)]
193+
#[derive(Deserialize, Debug, Clone, Copy)]
139194
enum KeyType {
140195
Sign,
141196
Dec,
@@ -276,7 +331,8 @@ enum IoCmd {
276331
VerifyDefaultPw3,
277332
ImportKey {
278333
key: String,
279-
key_type: KeyType,
334+
#[serde(default)]
335+
key_type: Option<KeyType>,
280336
key_kind: KeyKind,
281337
#[serde(default)]
282338
expected_status: Status,
@@ -340,7 +396,7 @@ impl IoCmd {
340396
key_type,
341397
key_kind,
342398
expected_status,
343-
} => Self::run_import(key, key_type, key_kind, *expected_status, card),
399+
} => Self::run_import(key, *key_type, key_kind, *expected_status, card),
344400
Self::SetAttributes { key_kind, key_type } => {
345401
Self::run_set_attributes(key_kind, key_type, card)
346402
}
@@ -388,24 +444,36 @@ impl IoCmd {
388444
Self::run_bytes(&parse_hex(input), output, expected_status, card)
389445
}
390446

447+
fn run_put_data<T: trussed::Client>(
448+
data_object: DataObject,
449+
data: &[u8],
450+
expected_status: Status,
451+
card: &mut opcard::Card<T>,
452+
) {
453+
let [p1, p2] = (data_object as u16).to_be_bytes();
454+
455+
let input = build_command(0x00, 0xDA, p1, p2, data, 0);
456+
Self::run_bytes(&input, &OutputMatcher::Len(0), expected_status, card)
457+
}
458+
391459
fn run_import<T: trussed::Client>(
392460
key: &str,
393-
key_type: &KeyType,
461+
key_type: Option<KeyType>,
394462
key_kind: &KeyKind,
395463
expected_status: Status,
396464
card: &mut opcard::Card<T>,
397465
) {
398-
let crt = key_type.crt();
399466
let key = parse_hex(key);
400467
let mut template;
401468
if key_kind.is_ec() {
402469
template = vec![0x92];
403470
template.extend_from_slice(&serialize_len(key.len()))
404471
} else if key_kind.is_aes() {
405-
todo!()
472+
return Self::run_put_data(DataObject::PSOEncDecKey, &key, expected_status, card);
406473
} else {
407474
todo!()
408475
}
476+
let crt = key_type.unwrap().crt();
409477
let mut data = Vec::from(crt);
410478
data.extend_from_slice(&tlv(&[0x7F, 0x48], &template));
411479
data.extend_from_slice(&tlv(&[0x5F, 0x48], &key));
@@ -495,7 +563,9 @@ impl IoCmd {
495563
#[test_log::test]
496564
fn command_response() {
497565
let data = std::fs::read_to_string("tests/command-response.ron").unwrap();
498-
let tests: Vec<IoTest> = ron::from_str(&data).unwrap();
566+
567+
let ron = Options::default().with_default_extension(Extensions::IMPLICIT_SOME);
568+
let tests: Vec<IoTest> = ron.from_str(&data).unwrap();
499569
for t in tests {
500570
println!("\n\n===========================================================",);
501571
println!("Running {}", t.name);

0 commit comments

Comments
 (0)