mirror of
https://gitlab.com/fabinfra/fabaccess/nfc_rs.git
synced 2025-03-12 14:51:50 +01:00
fixed aes auth, change_key_aes, change_key_other_aes
This commit is contained in:
parent
a7d0497f1f
commit
7c35d4ce6d
@ -6,7 +6,7 @@ use crate::crypto::cipher::aes::AES;
|
|||||||
use crate::crypto::cipher::Cipher;
|
use crate::crypto::cipher::Cipher;
|
||||||
use crate::crypto::util;
|
use crate::crypto::util;
|
||||||
use crate::error::{Result, Error};
|
use crate::error::{Result, Error};
|
||||||
use crate::error::Error::{InvalidApplicationID, InvalidKeyID, InvalidFileID, NumKeys};
|
use crate::error::Error::{InvalidApplicationID, InvalidKeyID, InvalidFileID, NumKeys, InvalidKeyVersion};
|
||||||
use crate::crypto::util::expand_to_blocksize;
|
use crate::crypto::util::expand_to_blocksize;
|
||||||
use crate::desfire::{FileCommunication, ChangeMasterKeySettings, CreateDeleteFile, FileDirectoryAccess, ChangeMasterKey, ChangeApplicationKey, CryptoOperationsType, FileIdentifiers};
|
use crate::desfire::{FileCommunication, ChangeMasterKeySettings, CreateDeleteFile, FileDirectoryAccess, ChangeMasterKey, ChangeApplicationKey, CryptoOperationsType, FileIdentifiers};
|
||||||
use crate::iso7816_4::apduresponse::APDUResponse;
|
use crate::iso7816_4::apduresponse::APDUResponse;
|
||||||
@ -140,8 +140,6 @@ impl Desfire {
|
|||||||
return Err(InvalidKeyID);
|
return Err(InvalidKeyID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let auth_iv: Vec<u8>;
|
|
||||||
|
|
||||||
let cmd_challenge_request = APDUCommand {
|
let cmd_challenge_request = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
@ -149,6 +147,7 @@ impl Desfire {
|
|||||||
data: Option::from(vec!(key_id)),
|
data: Option::from(vec!(key_id)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
println!("CMD_CHALLENGE_REQUEST: {}", cmd_challenge_request);
|
||||||
|
|
||||||
let response = self.card.transmit(cmd_challenge_request).unwrap();
|
let response = self.card.transmit(cmd_challenge_request).unwrap();
|
||||||
|
|
||||||
@ -156,6 +155,7 @@ impl Desfire {
|
|||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => { return Err(e); }
|
Err(e) => { return Err(e); }
|
||||||
}
|
}
|
||||||
|
println!("RESPONSE: {}", response);
|
||||||
|
|
||||||
let rnd_b_response_body = response.body.unwrap();
|
let rnd_b_response_body = response.body.unwrap();
|
||||||
let rnd_b_enc = rnd_b_response_body.as_slice();
|
let rnd_b_enc = rnd_b_response_body.as_slice();
|
||||||
@ -165,8 +165,8 @@ impl Desfire {
|
|||||||
println!("RND_B: {:x?}", rnd_b);
|
println!("RND_B: {:x?}", rnd_b);
|
||||||
|
|
||||||
// auth_iv = rnd_b.clone();
|
// auth_iv = rnd_b.clone();
|
||||||
let rnd_b_rl = rnd_b.clone();
|
let mut rnd_b_rl = rnd_b.clone();
|
||||||
rnd_b.rotate_left(1);
|
rnd_b_rl.rotate_left(1);
|
||||||
println!("RND_B_RL: {:x?}", rnd_b_rl);
|
println!("RND_B_RL: {:x?}", rnd_b_rl);
|
||||||
|
|
||||||
let rnd_a = match rnd_a {
|
let rnd_a = match rnd_a {
|
||||||
@ -175,10 +175,10 @@ impl Desfire {
|
|||||||
};
|
};
|
||||||
println!("RND_A: {:x?}", rnd_a);
|
println!("RND_A: {:x?}", rnd_a);
|
||||||
|
|
||||||
let rnd_ab = [&rnd_a, rnd_b_rl].concat();
|
let rnd_ab = [&rnd_a, rnd_b_rl.as_slice()].concat();
|
||||||
println!("RND_AB: {:x?}", rnd_ab);
|
println!("RND_AB: {:x?}", rnd_ab);
|
||||||
|
|
||||||
let rnd_ab_enc = AES::encrypt(rnd_ab.as_slice(), key, auth_iv.as_slice()).unwrap();
|
let rnd_ab_enc = AES::encrypt(rnd_ab.as_slice(), key, rnd_b_enc).unwrap();
|
||||||
println!("RND_AB_ENC: {:x?}", rnd_ab_enc);
|
println!("RND_AB_ENC: {:x?}", rnd_ab_enc);
|
||||||
|
|
||||||
let cmd_challenge_response = APDUCommand {
|
let cmd_challenge_response = APDUCommand {
|
||||||
@ -188,6 +188,7 @@ impl Desfire {
|
|||||||
data: Some(rnd_ab_enc.clone()),
|
data: Some(rnd_ab_enc.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
println!("CMD_CHALLENGE_RESPONSE: {}", cmd_challenge_response);
|
||||||
|
|
||||||
let response = self.card.transmit(cmd_challenge_response).unwrap();
|
let response = self.card.transmit(cmd_challenge_response).unwrap();
|
||||||
|
|
||||||
@ -195,18 +196,27 @@ impl Desfire {
|
|||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => { return Err(e); }
|
Err(e) => { return Err(e); }
|
||||||
}
|
}
|
||||||
|
println!("RESPONSE: {}", response);
|
||||||
|
|
||||||
let mut rnd_a_rot_from_card = AES::decrypt(response.body.unwrap().as_slice(), key, auth_iv.as_slice()).unwrap();
|
let iv: &[u8] = util::extract_last_block(rnd_ab_enc.as_slice(), 16).unwrap();
|
||||||
|
let rnd_a_enc_from_card = response.body.unwrap();
|
||||||
|
println!("RND_A_ENC_FROM_CARD: {:x?}", rnd_a_enc_from_card.as_slice());
|
||||||
|
let mut rnd_a_rot_from_card = AES::decrypt(rnd_a_enc_from_card.as_slice(), key, iv).unwrap();
|
||||||
rnd_a_rot_from_card.rotate_right(1);
|
rnd_a_rot_from_card.rotate_right(1);
|
||||||
|
println!("RND_A_ROT_FROM_CARD: {:x?}", rnd_a_rot_from_card);
|
||||||
let rnd_a_from_card = rnd_a_rot_from_card.as_slice();
|
let rnd_a_from_card = rnd_a_rot_from_card.as_slice();
|
||||||
|
println!("RND_A_FROM_CARD: {:x?}", rnd_a_from_card);
|
||||||
|
|
||||||
if rnd_a != rnd_a_from_card {
|
if rnd_a != rnd_a_from_card {
|
||||||
return Err(Error::InvalidPICCChallenge);
|
return Err(Error::InvalidPICCChallenge);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.session_key = Some(generate_session_key_aes(&rnd_a, rnd_b.as_slice()).unwrap());
|
self.session_key = Some(generate_session_key_aes(&rnd_a, rnd_b.as_slice()).unwrap());
|
||||||
|
println!("SESSION_KEY: {:x?}", self.session_key.as_ref().unwrap());
|
||||||
|
|
||||||
self.cbc_iv = Some(vec![0 as u8; 16]);
|
self.cbc_iv = Some(vec![0 as u8; 16]);
|
||||||
|
println!("CBC_IV: {:x?}", self.cbc_iv.as_ref().unwrap());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,6 +272,9 @@ impl Desfire {
|
|||||||
if key_id >= 0x0E {
|
if key_id >= 0x0E {
|
||||||
return Err(InvalidKeyID);
|
return Err(InvalidKeyID);
|
||||||
}
|
}
|
||||||
|
if key_version < 0x10 {
|
||||||
|
return Err(InvalidKeyVersion);
|
||||||
|
}
|
||||||
|
|
||||||
let header = vec![0xC4, key_id];
|
let header = vec![0xC4, key_id];
|
||||||
let key_and_version: Vec<u8> = [new_key, &[key_version]].concat();
|
let key_and_version: Vec<u8> = [new_key, &[key_version]].concat();
|
||||||
@ -269,21 +282,29 @@ impl Desfire {
|
|||||||
|
|
||||||
command.extend(&header);
|
command.extend(&header);
|
||||||
command.extend(&key_and_version);
|
command.extend(&key_and_version);
|
||||||
|
println!("HEADER: {:x?}", header);
|
||||||
|
println!("COMMAND: {:x?}", command);
|
||||||
|
|
||||||
let crc = crate::crypto::crc::crc32::calculate(command.as_slice());
|
let crc = crate::crypto::crc::crc32::calculate(command.as_slice());
|
||||||
|
println!("CRC: {:x?}", crc);
|
||||||
|
|
||||||
let mut plaintext: Vec<u8> = vec![];
|
let mut plaintext: Vec<u8> = vec![];
|
||||||
plaintext.extend(key_and_version);
|
plaintext.extend(key_and_version);
|
||||||
plaintext.extend(crc);
|
plaintext.extend(crc);
|
||||||
|
println!("PLAINTEXT: {:x?}", plaintext);
|
||||||
|
|
||||||
let plaintext_pad = expand_to_blocksize(plaintext.as_mut_slice(), 16)?;
|
let plaintext_pad = expand_to_blocksize(plaintext.as_mut_slice(), 16)?;
|
||||||
|
println!("PLAINTEXT_PAD: {:x?}", plaintext_pad);
|
||||||
|
|
||||||
let cryptogram = AES::encrypt(plaintext_pad, self.session_key.as_ref().unwrap(), self.cbc_iv.as_ref().unwrap())?;
|
let cryptogram = AES::encrypt(plaintext_pad.as_slice(), self.session_key.as_ref().unwrap(), self.cbc_iv.as_ref().unwrap())?;
|
||||||
|
println!("CRYPTOGRAM: {:x?}", cryptogram);
|
||||||
|
|
||||||
self.cbc_iv = Some(util::extract_last_block(cryptogram.as_slice(), 16)?.to_vec());
|
self.cbc_iv = Some(util::extract_last_block(cryptogram.as_slice(), 16)?.to_vec());
|
||||||
|
println!("CBC_IV: {:x?}", self.cbc_iv.as_ref().unwrap());
|
||||||
|
|
||||||
let mut data: Vec<u8> = vec![key_id];
|
let mut data: Vec<u8> = vec![key_id];
|
||||||
data.extend(cryptogram);
|
data.extend(cryptogram);
|
||||||
|
println!("DATA: {:x?}", data);
|
||||||
|
|
||||||
let cmd_change_key = APDUCommand {
|
let cmd_change_key = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
@ -292,8 +313,10 @@ impl Desfire {
|
|||||||
data: Option::from(data), //FIXME: Which byteorder?
|
data: Option::from(data), //FIXME: Which byteorder?
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
println!("CMD_CHANGE_KEY: {}", cmd_change_key);
|
||||||
|
|
||||||
let response = self.card.transmit(cmd_change_key).unwrap();
|
let response = self.card.transmit(cmd_change_key).unwrap();
|
||||||
|
println!("RESPONSE: {}", response);
|
||||||
|
|
||||||
response.check()
|
response.check()
|
||||||
}
|
}
|
||||||
@ -309,31 +332,48 @@ impl Desfire {
|
|||||||
if key_id >= 0x0E {
|
if key_id >= 0x0E {
|
||||||
return Err(InvalidKeyID);
|
return Err(InvalidKeyID);
|
||||||
}
|
}
|
||||||
|
if key_version < 0x10 {
|
||||||
|
return Err(InvalidKeyVersion);
|
||||||
|
}
|
||||||
|
|
||||||
let header = vec![0xC4, key_id];
|
let header = vec![0xC4, key_id];
|
||||||
|
println!("HEADER: {:x?}", header);
|
||||||
|
|
||||||
let key_xor: Vec<u8> = new_key.iter().zip(old_key.iter()).map(|(&x1, &x2)| x1 ^ x2).collect();
|
let key_xor: Vec<u8> = new_key.iter().zip(old_key.iter()).map(|(&x1, &x2)| x1 ^ x2).collect();
|
||||||
|
println!("KEY_XOR: {:x?}", key_xor);
|
||||||
|
|
||||||
let key_and_version: Vec<u8> = [key_xor, vec![key_version]].concat();
|
let key_and_version: Vec<u8> = [key_xor, vec![key_version]].concat();
|
||||||
|
println!("KEY_AND_VERSION: {:x?}", key_and_version);
|
||||||
let mut command = vec![];
|
let mut command = vec![];
|
||||||
|
|
||||||
command.extend(&header);
|
command.extend(&header);
|
||||||
command.extend(&key_and_version);
|
command.extend(&key_and_version);
|
||||||
|
println!("COMMAND: {:x?}", command);
|
||||||
|
|
||||||
let crc = crate::crypto::crc::crc32::calculate(command.as_slice());
|
let crc_cmd = crate::crypto::crc::crc32::calculate(command.as_slice());
|
||||||
|
println!("CRC_CMD: {:x?}", crc_cmd);
|
||||||
|
|
||||||
|
let crc_key = crate::crypto::crc::crc32::calculate(new_key);
|
||||||
|
println!("CRC_KEY: {:x?}", crc_key);
|
||||||
|
|
||||||
let mut plaintext: Vec<u8> = vec![];
|
let mut plaintext: Vec<u8> = vec![];
|
||||||
plaintext.extend(key_and_version);
|
plaintext.extend(key_and_version);
|
||||||
plaintext.extend(crc);
|
plaintext.extend(crc_cmd);
|
||||||
|
plaintext.extend(crc_key);
|
||||||
|
println!("PLAINTEXT: {:x?}", plaintext);
|
||||||
|
|
||||||
let plaintext_pad = expand_to_blocksize(plaintext.as_mut_slice(), 16)?;
|
let plaintext_pad = expand_to_blocksize(plaintext.as_mut_slice(), 16)?;
|
||||||
|
println!("PLAINTEXT_PAD: {:x?}", plaintext_pad);
|
||||||
|
|
||||||
let cryptogram = AES::encrypt(plaintext_pad, self.session_key.as_ref().unwrap(), self.cbc_iv.as_ref().unwrap())?;
|
let cryptogram = AES::encrypt(plaintext_pad.as_slice(), self.session_key.as_ref().unwrap(), self.cbc_iv.as_ref().unwrap())?;
|
||||||
|
println!("CRYPTOGRAM: {:x?}", cryptogram);
|
||||||
|
|
||||||
self.cbc_iv = Some(util::extract_last_block(cryptogram.as_slice(), 16)?.to_vec());
|
self.cbc_iv = Some(util::extract_last_block(cryptogram.as_slice(), 16)?.to_vec());
|
||||||
|
println!("CBC_IV: {:x?}", self.cbc_iv.as_ref().unwrap());
|
||||||
|
|
||||||
let mut data: Vec<u8> = vec![key_id];
|
let mut data: Vec<u8> = vec![key_id];
|
||||||
data.extend(cryptogram);
|
data.extend(cryptogram);
|
||||||
|
println!("DATA: {:x?}", data);
|
||||||
|
|
||||||
let cmd_change_key = APDUCommand {
|
let cmd_change_key = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
@ -342,8 +382,10 @@ impl Desfire {
|
|||||||
data: Option::from(data), //FIXME: Which byteorder?
|
data: Option::from(data), //FIXME: Which byteorder?
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
println!("CMD_CHANGE_KEY: {}", cmd_change_key);
|
||||||
|
|
||||||
let response = self.card.transmit(cmd_change_key).unwrap();
|
let response = self.card.transmit(cmd_change_key).unwrap();
|
||||||
|
println!("RESPONSE: {}", response);
|
||||||
|
|
||||||
response.check()
|
response.check()
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ pub enum Error {
|
|||||||
InvalidKeyID,
|
InvalidKeyID,
|
||||||
InvalidPICCChallenge,
|
InvalidPICCChallenge,
|
||||||
InvalidFileID,
|
InvalidFileID,
|
||||||
|
InvalidKeyVersion,
|
||||||
NumKeys,
|
NumKeys,
|
||||||
CardError,
|
CardError,
|
||||||
}
|
}
|
||||||
@ -109,6 +110,9 @@ impl fmt::Display for Error {
|
|||||||
Error::InvalidKeyID => {
|
Error::InvalidKeyID => {
|
||||||
write!(f, "Invalid KeyID: Was larger then 0x0E")
|
write!(f, "Invalid KeyID: Was larger then 0x0E")
|
||||||
}
|
}
|
||||||
|
Error::InvalidKeyVersion => {
|
||||||
|
write!(f, "Invalid KeyVersion: Should be atleast 0x10")
|
||||||
|
}
|
||||||
Error::InvalidPICCChallenge => {
|
Error::InvalidPICCChallenge => {
|
||||||
write!(f, "Authentication failed, PICC Challenge is invalid.")
|
write!(f, "Authentication failed, PICC Challenge is invalid.")
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user