Compare commits

..

No commits in common. "be1a3c445dce8105e01458506ab290cf0008c5da" and "a3a3ee382749c96dd6aa7af555cecfe992eaac2e" have entirely different histories.

2 changed files with 43 additions and 62 deletions

View file

@ -14,6 +14,7 @@ readme = "README.md"
[dependencies] [dependencies]
diacritics = "0.2.0" diacritics = "0.2.0"
encoding_rs = "0.8.33" encoding_rs = "0.8.33"
magic-crypt = "3.1.12"
nofmt = "1.0.0" nofmt = "1.0.0"
once_cell = "1.18.0" once_cell = "1.18.0"
unicode-normalization = "0.1.22" unicode-normalization = "0.1.22"
@ -25,9 +26,6 @@ num-derive = "0.3.3"
num-traits = "0.2.14" num-traits = "0.2.14"
rand = "0.8.5" rand = "0.8.5"
getrandom = { version = "0.2.12", features = ["js"] } getrandom = { version = "0.2.12", features = ["js"] }
des = "0.8.1"
cbc = "0.1.2"
ecb = "0.1.2"
[dependencies.unicode-jp] [dependencies.unicode-jp]
# Relying on this fork for now as it has up-to-date deps # Relying on this fork for now as it has up-to-date deps

View file

@ -5,13 +5,12 @@ use crate::netmd::utils::{
half_width_to_full_width_range, length_after_encoding_to_jis, sanitize_full_width_title, half_width_to_full_width_range, length_after_encoding_to_jis, sanitize_full_width_title,
sanitize_half_width_title, time_to_duration, sanitize_half_width_title, time_to_duration,
}; };
use cbc::cipher::block_padding::NoPadding; use encoding_rs::*;
use cbc::cipher::{KeyIvInit, BlockEncryptMut, BlockDecryptMut, KeyInit}; use hex;
use encoding_rs::SHIFT_JIS; use magic_crypt::{new_magic_crypt, MagicCrypt, MagicCryptTrait, SecureBit};
use rand::RngCore; use rand::RngCore;
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::str::FromStr;
use lazy_static::lazy_static; use lazy_static::lazy_static;
@ -1365,7 +1364,7 @@ impl NetMDInterface {
keychain: [[u8; 16]; 2], keychain: [[u8; 16]; 2],
depth: i32, depth: i32,
ekbsignature: [u8; 24], ekbsignature: [u8; 24],
) -> Result<(), Box<dyn Error>> { ) -> Result<Vec<u8>, Box<dyn Error>> {
let chainlen = keychain.len(); let chainlen = keychain.len();
let databytes = 16 + 16 * chainlen + 24; let databytes = 16 + 16 * chainlen + 24;
@ -1393,12 +1392,12 @@ impl NetMDInterface {
let reply = self.send_query(&mut query, false, false).await?; let reply = self.send_query(&mut query, false, false).await?;
scan_query( let res = scan_query(
reply, reply,
"1800 080046 f0030103 12 01 %?%? %?%?%?%?".to_string(), "1800 080046 f0030103 12 01 %?%? %?%?%?%?".to_string(),
)?; )?;
Ok(()) Ok(res[0].to_vec().unwrap())
} }
pub async fn session_key_exchange( pub async fn session_key_exchange(
@ -1433,7 +1432,7 @@ impl NetMDInterface {
&mut self, &mut self,
contentid: Vec<u8>, contentid: Vec<u8>,
keyenckey: Vec<u8>, keyenckey: Vec<u8>,
hex_session_key: &[u8], hex_session_key: String,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
if contentid.len() != 20 { if contentid.len() != 20 {
return Err("Supplied content ID length wrong".into()); return Err("Supplied content ID length wrong".into());
@ -1445,12 +1444,15 @@ impl NetMDInterface {
return Err("Supplied Session Key length wrong".into()); return Err("Supplied Session Key length wrong".into());
} }
let mut message = [vec![1, 1, 1, 1], contentid, keyenckey].concat(); let message = [vec![1, 1, 1, 1], contentid, keyenckey].concat();
DesCbcEnc::new(hex_session_key.into(), &[0u8; 8].into()).encrypt_padded_mut::<NoPadding>(message.as_mut_slice(), 32).unwrap();
let mc = MagicCrypt::new(hex_session_key, SecureBit::Bit256, None::<String>);
let encryptedarg = mc.decrypt_bytes_to_bytes(&message)?;
let mut query = format_query( let mut query = format_query(
"1800 080046 f0030103 22 ff 0000 %*".to_string(), "1800 080046 f0030103 22 ff 0000 %*".to_string(),
vec![QueryValue::Array(message)], vec![QueryValue::Array(encryptedarg)],
)?; )?;
let reply = self.send_query(&mut query, false, false).await?; let reply = self.send_query(&mut query, false, false).await?;
@ -1463,20 +1465,20 @@ impl NetMDInterface {
pub async fn commit_track( pub async fn commit_track(
&mut self, &mut self,
track_number: u16, track_number: u16,
hex_session_key: &[u8], hex_session_key: String,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
if hex_session_key.len() != 16 { if hex_session_key.len() != 16 {
return Err("Supplied Session Key length wrong".into()); return Err("Supplied Session Key length wrong".into());
} }
let mut message = [0u8; 8]; let mc = new_magic_crypt!(hex::encode(hex_session_key), 256);
DesEcbEnc::new(hex_session_key.into()).encrypt_padded_mut::<NoPadding>(&mut message, 8).unwrap(); let authentication = mc.encrypt_str_to_bytes(hex::encode("0000000000000000"));
let mut query = format_query( let mut query = format_query(
"1800 080046 f0030103 22 ff 0000 %*".to_string(), "1800 080046 f0030103 22 ff 0000 %*".to_string(),
vec![ vec![
QueryValue::Number(track_number as i64), QueryValue::Number(track_number as i64),
QueryValue::Array(Vec::from(message)), QueryValue::Array(authentication),
], ],
)?; )?;
@ -1495,7 +1497,7 @@ impl NetMDInterface {
pkt_size: u32, pkt_size: u32,
// key // iv // data // key // iv // data
packets: Vec<(Vec<u8>, Vec<u8>, Vec<u8>)>, packets: Vec<(Vec<u8>, Vec<u8>, Vec<u8>)>,
hex_session_key: &[u8], hex_session_key: String,
) -> Result<(i64, String, String), Box<dyn Error>> { ) -> Result<(i64, String, String), Box<dyn Error>> {
if hex_session_key.len() != 16 { if hex_session_key.len() != 16 {
return Err("Supplied Session Key length wrong".into()); return Err("Supplied Session Key length wrong".into());
@ -1543,13 +1545,15 @@ impl NetMDInterface {
"1800 080046 f0030103 28 00 000100 1001 %w 00 %?%? %?%?%?%? %?%?%?%? %*".to_string(), "1800 080046 f0030103 28 00 000100 1001 %w 00 %?%? %?%?%?%? %?%?%?%? %*".to_string(),
)?; )?;
let mut encrypted_data = res[1].to_vec().unwrap(); let mc = MagicCrypt::new(hex_session_key, SecureBit::Bit256, Some("0000000000000000"));
DesCbcDec::new(hex_session_key.into(), &[0u8; 8].into()).decrypt_padded_mut::<NoPadding>(&mut encrypted_data).unwrap();
let reply_data = String::from_utf8(encrypted_data)?; let reply_data = String::from_utf8(mc.decrypt_bytes_to_bytes(&res[1].to_vec().unwrap())?)
.unwrap()
.chars()
.collect::<Vec<char>>();
let part1 = String::from_str(&reply_data[0..8]).unwrap(); let part1 = String::from_iter(reply_data.clone()[0..8].iter());
let part2 = String::from_str(&reply_data[12..32]).unwrap(); let part2 = String::from_iter(reply_data.clone()[12..32].iter());
Ok((res[0].to_i64().unwrap(), part1, part2)) Ok((res[0].to_i64().unwrap(), part1, part2))
} }
@ -1573,31 +1577,22 @@ impl NetMDInterface {
Ok(()) Ok(())
} }
} }
type DesEcbEnc = ecb::Encryptor<des::Des>;
type DesCbcEnc = cbc::Encryptor<des::Des>;
type DesCbcDec = cbc::Decryptor<des::Des>;
type TDesCbcEnc = cbc::Encryptor<des::TdesEde3>;
pub fn retailmac(key: &[u8], value: &[u8], iv: &[u8; 8]) -> Vec<u8> { pub fn retailmac(key: Vec<u8>, value: Vec<u8>, iv: Vec<u8>) -> Result<(), Box<dyn Error>> {
let mut subkey_a = [0u8; 8]; let subkey_a = key[0..8].to_vec();
subkey_a.clone_from_slice(&key[0..8]); let beginning = value[0..value.len() - 8].to_vec();
let _end = value[value.len() - 8..].to_vec();
let mut beginning = [0u8; 8]; let mc = MagicCrypt::new(
beginning.clone_from_slice(&value[0..8]); String::from_utf8(subkey_a).unwrap(),
SecureBit::Bit256,
Some(String::from_utf8(iv).unwrap()),
);
let step1 = mc.encrypt_bytes_to_bytes(&beginning);
let mut end = [0u8; 8]; let _iv2 = String::from_utf8(step1);
end.clone_from_slice(&value[8..]);
DesCbcEnc::new(&subkey_a.into(), iv.into()).encrypt_padded_mut::<NoPadding>(&mut beginning, 8).unwrap(); Ok(())
let iv2 = &beginning[beginning.len() - 8..];
let mut wonky_key = [0u8; 24];
wonky_key[0..16].clone_from_slice(&key);
wonky_key[16..].clone_from_slice(&key[0..8]);
TDesCbcEnc::new(&wonky_key.into(), iv2.into()).encrypt_padded_mut::<NoPadding>(&mut end, 8).unwrap();
end[..8].to_vec()
} }
lazy_static! { lazy_static! {
@ -1709,9 +1704,9 @@ impl MDTrack {
} }
pub struct MDSession { pub struct MDSession {
pub md: NetMDInterface, md: NetMDInterface,
pub ekb_object: EKBOpenSource, ekb_object: EKBOpenSource,
pub hex_session_key: Option<Vec<u8>>, hex_session_key: String,
} }
impl MDSession { impl MDSession {
@ -1721,22 +1716,10 @@ impl MDSession {
let ekb = self.ekb_object.ekb_data_for_leaf_id(); let ekb = self.ekb_object.ekb_data_for_leaf_id();
self.md.send_key_data(self.ekb_object.ekb_id(), ekb.chains, ekb.depth, ekb.signature).await?; self.md.send_key_data(self.ekb_object.ekb_id(), ekb.chains, ekb.depth, ekb.signature).await?;
let mut nonce = vec![0u8; 8]; let mut nonce = vec![0u8, 8];
rand::thread_rng().fill_bytes(&mut nonce); rand::thread_rng().fill_bytes(&mut nonce);
let mut devnonce = self.md.session_key_exchange(nonce.clone()).await?; // TODO
nonce.append(&mut devnonce);
self.hex_session_key = Some(retailmac(&self.ekb_object.root_key(), &nonce, &[0u8; 8]));
Ok(())
}
pub async fn close(&mut self) -> Result<(), Box<dyn Error>> {
if let None = self.hex_session_key {
self.md.session_key_forget().await?;
}
self.hex_session_key = None;
Ok(()) Ok(())
} }
} }