fixed aes auth, change_key_aes, change_key_other_aes

This commit is contained in:
Kai Jan Kriegel 2021-12-25 06:24:45 +01:00
parent a7d0497f1f
commit 7c35d4ce6d
2 changed files with 58 additions and 12 deletions

View File

@ -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()
} }

View File

@ -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.")
} }