|
5 | 5 | use std::borrow::Cow; |
6 | 6 |
|
7 | 7 | use hex_literal::hex; |
| 8 | +use ron::{extensions::Extensions, Options}; |
8 | 9 | use serde::Deserialize; |
9 | 10 |
|
10 | 11 | // iso7816::Status doesn't support serde |
@@ -34,6 +35,60 @@ enum Status { |
34 | 35 | UnspecifiedCheckingError, |
35 | 36 | } |
36 | 37 |
|
| 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 | + |
37 | 92 | fn serialize_len(len: usize) -> heapless::Vec<u8, 3> { |
38 | 93 | let mut buf = heapless::Vec::new(); |
39 | 94 | if let Ok(len) = u8::try_from(len) { |
@@ -135,7 +190,7 @@ impl Default for Status { |
135 | 190 | } |
136 | 191 | } |
137 | 192 |
|
138 | | -#[derive(Deserialize, Debug)] |
| 193 | +#[derive(Deserialize, Debug, Clone, Copy)] |
139 | 194 | enum KeyType { |
140 | 195 | Sign, |
141 | 196 | Dec, |
@@ -276,7 +331,8 @@ enum IoCmd { |
276 | 331 | VerifyDefaultPw3, |
277 | 332 | ImportKey { |
278 | 333 | key: String, |
279 | | - key_type: KeyType, |
| 334 | + #[serde(default)] |
| 335 | + key_type: Option<KeyType>, |
280 | 336 | key_kind: KeyKind, |
281 | 337 | #[serde(default)] |
282 | 338 | expected_status: Status, |
@@ -340,7 +396,7 @@ impl IoCmd { |
340 | 396 | key_type, |
341 | 397 | key_kind, |
342 | 398 | 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), |
344 | 400 | Self::SetAttributes { key_kind, key_type } => { |
345 | 401 | Self::run_set_attributes(key_kind, key_type, card) |
346 | 402 | } |
@@ -388,24 +444,36 @@ impl IoCmd { |
388 | 444 | Self::run_bytes(&parse_hex(input), output, expected_status, card) |
389 | 445 | } |
390 | 446 |
|
| 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 | + |
391 | 459 | fn run_import<T: trussed::Client>( |
392 | 460 | key: &str, |
393 | | - key_type: &KeyType, |
| 461 | + key_type: Option<KeyType>, |
394 | 462 | key_kind: &KeyKind, |
395 | 463 | expected_status: Status, |
396 | 464 | card: &mut opcard::Card<T>, |
397 | 465 | ) { |
398 | | - let crt = key_type.crt(); |
399 | 466 | let key = parse_hex(key); |
400 | 467 | let mut template; |
401 | 468 | if key_kind.is_ec() { |
402 | 469 | template = vec![0x92]; |
403 | 470 | template.extend_from_slice(&serialize_len(key.len())) |
404 | 471 | } else if key_kind.is_aes() { |
405 | | - todo!() |
| 472 | + return Self::run_put_data(DataObject::PSOEncDecKey, &key, expected_status, card); |
406 | 473 | } else { |
407 | 474 | todo!() |
408 | 475 | } |
| 476 | + let crt = key_type.unwrap().crt(); |
409 | 477 | let mut data = Vec::from(crt); |
410 | 478 | data.extend_from_slice(&tlv(&[0x7F, 0x48], &template)); |
411 | 479 | data.extend_from_slice(&tlv(&[0x5F, 0x48], &key)); |
@@ -495,7 +563,9 @@ impl IoCmd { |
495 | 563 | #[test_log::test] |
496 | 564 | fn command_response() { |
497 | 565 | 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(); |
499 | 569 | for t in tests { |
500 | 570 | println!("\n\n===========================================================",); |
501 | 571 | println!("Running {}", t.name); |
|
0 commit comments