cleanup
Some checks failed
Build and Test / super-mario-maker (push) Failing after 3m5s
Build and Test / wii-u-chat (push) Successful in 4m19s
Build and Test / minecraft-wiiu (push) Successful in 4m37s
Build and Test / fast-racing-neo (push) Successful in 4m38s
Build and Test / friends (push) Successful in 4m37s
Build and Test / wii-sports-club (push) Successful in 4m40s
Build and Test / puyopuyo (push) Successful in 4m42s
Build and Test / mario-tennis (push) Successful in 4m42s
Build and Test / splatoon-testfire (push) Successful in 4m43s
Build and Test / splatoon (push) Successful in 4m43s
Build and Test / sonic-transformed (push) Successful in 4m57s

This commit is contained in:
Maple Nebel 2026-06-22 14:22:53 +02:00
commit 872f41cab2
5 changed files with 44 additions and 61 deletions

View file

@ -28,17 +28,11 @@ pub const SESSION_KEY_LENGTH: usize = SessionLengthTy::USIZE;
type Md5Hmac = Hmac<md5::Md5>;
pub fn derive_key(pid: PID, key: &[u8]) -> [u8; 16] {
pub fn derive_kerberos_key(pid: PID, nex_key: [u8; 16]) -> [u8; 16] {
let iteration_count = pid % 1024;
// we do one iteration out here to ensure the key is always 16 bytes
let mut key = nex_key;
let mut key: [u8; 16] = {
let mut md5 = Md5::new();
md5.update(key);
md5.finalize().try_into().unwrap()
};
for _ in 1..iteration_count {
for _ in 0..iteration_count {
let mut md5 = Md5::new();
md5.update(key);
key = md5.finalize().try_into().unwrap();

View file

@ -1,5 +1,5 @@
use md5::{Digest, Md5};
use macros::RmcSerialize;
use md5::{Digest, Md5};
use rnex_core::PID;
@ -7,7 +7,7 @@ use rnex_core::PID;
pub struct Account {
pub pid: PID,
pub username: String,
pub kerbros_password: Box<[u8]>,
pub nex_key: [u8; 16],
}
impl Account {
@ -28,36 +28,21 @@ impl Account {
}
Self {
kerbros_password: key.into(),
nex_key: key.into(),
username: username.into(),
pid,
}
}
pub fn new_raw_password(pid: PID, username: &str, passwd: &[u8]) -> Self {
let iteration_count = 65000;
// we do one iteration out here to ensure the key is always 16 bytes
let mut key: [u8; 16] = {
let mut md5 = Md5::new();
md5.update(passwd);
md5.finalize().try_into().unwrap()
};
for _ in 1..iteration_count {
let mut md5 = Md5::new();
md5.update(key);
key = md5.finalize().try_into().unwrap();
}
pub fn new_raw_key(pid: PID, username: &str, nex_key: [u8; 16]) -> Self {
Self {
kerbros_password: key.into(),
username: username.into(),
pid,
nex_key,
}
}
pub fn get_login_data(&self) -> (PID, &[u8]) {
(self.pid, &self.kerbros_password)
pub fn get_login_data(&self) -> (PID, [u8; 16]) {
(self.pid, self.nex_key)
}
}

View file

@ -5,7 +5,7 @@ use cfg_if::cfg_if;
use log::{info, warn};
use macros::rmc_struct;
use rnex_core::PID;
use rnex_core::kerberos::{KerberosDateTime, Ticket, derive_key};
use rnex_core::kerberos::{KerberosDateTime, Ticket, derive_kerberos_key};
use rnex_core::nex::account::Account;
use rnex_core::rmc::protocols::OnlyRemote;
use rnex_core::rmc::protocols::auth::{Auth, RawAuth, RawAuthInfo, RemoteAuth};
@ -34,11 +34,11 @@ pub struct AuthHandler {
}
pub fn generate_ticket(
source_act_login_data: (PID, &[u8]),
dest_act_login_data: (PID, &[u8]),
source_act_login_data: (PID, [u8; 16]),
dest_act_login_data: (PID, [u8; 16]),
) -> Box<[u8]> {
let source_key = derive_key(source_act_login_data.0, source_act_login_data.1);
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
let source_key = derive_kerberos_key(source_act_login_data.0, source_act_login_data.1);
let dest_key = derive_kerberos_key(dest_act_login_data.0, dest_act_login_data.1);
let internal_data = kerberos::TicketInternalData::new(source_act_login_data.0);
@ -53,12 +53,12 @@ pub fn generate_ticket(
}
pub fn generate_ticket_with_string_user_key(
source_act: PID,
dest_act_login_data: (PID, &[u8]),
dest_act_login_data: (PID, [u8; 16]),
) -> (String, Box<[u8]>) {
let source_key: [u8; 8] = rand::random();
let key_string = hex::encode(source_key);
let key_data: [u8; 16] = key_string.as_bytes().try_into().unwrap();
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
let dest_key = derive_kerberos_key(dest_act_login_data.0, dest_act_login_data.1);
let internal_data = kerberos::TicketInternalData::new(source_act);
@ -72,11 +72,11 @@ pub fn generate_ticket_with_string_user_key(
(key_string, encrypted_session_ticket)
}
async fn get_login_data_by_pid(pid: PID) -> Option<(PID, Box<[u8]>)> {
async fn get_login_data_by_pid(pid: PID) -> Option<(PID, [u8; 16])> {
if pid == GUEST_ACCOUNT.pid {
let source_login_data = GUEST_ACCOUNT.get_login_data();
return Some((source_login_data.0, source_login_data.1.into()));
return Some((source_login_data.0, source_login_data.1));
}
let Ok(mut client) = account::Client::new().await else {
@ -87,7 +87,7 @@ async fn get_login_data_by_pid(pid: PID) -> Option<(PID, Box<[u8]>)> {
return None;
};
Some((pid, passwd.into()))
Some((pid, passwd))
}
fn station_url_from_sock_addr(sock_addr: SocketAddrV4) -> String {
@ -133,7 +133,7 @@ impl AuthHandler {
return Err(ErrorCode::Core_Exception);
};
let source_login_data = (pid, &passwd[..]);
let source_login_data = (pid, passwd);
println!("{}, {:?}", pid, passwd);
let destination_login_data = self.destination_server_acct.get_login_data();
@ -322,7 +322,7 @@ impl Auth for AuthHandler {
let result = QResult::success(Core_Unknown);
let ticket = generate_ticket((pid, &passwd[..]), desgination_login_data);
let ticket = generate_ticket((pid, passwd), desgination_login_data);
Ok((result, ticket.into()))
}

View file

@ -39,26 +39,30 @@ use std::str::FromStr;
use cfg_if::cfg_if;
use log::{error, info};
use macros::rmc_struct;
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use rnex_core::rmc::protocols::message_delivery::{
MessageDelivery, RawMessageDelivery, RawMessageDeliveryInfo, RemoteMessageDelivery,
use rnex_core::{
prudp::socket_addr::PRUDPSockAddr,
rmc::{
protocols::{
message_delivery::{MessageDelivery, RemoteMessageDeliveryNoResponse},
messaging::UserMessage,
notifications::{NotificationEvent, RemoteNotification},
ranking::{
CompetitionRankingGetParam, CompetitionRankingScoreData,
CompetitionRankingScoreInfo,
},
},
response::ErrorCode::{Core_InvalidArgument, RendezVous_AccountExpired},
structures::{
matchmake::{Gathering, MatchmakeSessionSearchCriteria},
qbuffer::QBuffer,
qresult::QResult,
ranking::UploadCompetitionData,
},
},
};
use rnex_core::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
use rnex_core::rmc::protocols::ranking::{
CompetitionRankingGetParam, CompetitionRankingScoreData, CompetitionRankingScoreInfo,
};
use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_AccountExpired};
use rnex_core::rmc::structures::qbuffer::QBuffer;
use rnex_core::rmc::structures::qresult::QResult;
use rnex_core::rmc::structures::ranking::UploadCompetitionData;
use std::sync::{Arc, Weak};
use tokio::sync::{Mutex, RwLock};
use crate::rmc::protocols::message_delivery::RemoteMessageDeliveryNoResponse;
use crate::rmc::protocols::messaging::UserMessage;
use crate::rmc::structures::matchmake::Gathering;
use crate::rmc::structures::matchmake::MatchmakeSessionSearchCriteria;
cfg_if! {
if #[cfg(feature = "datastore")] {
use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore};

View file

@ -6,7 +6,7 @@ use typenum::U16;
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
use crate::{
kerberos::{SESSION_KEY_LENGTH, SessionLengthTy, TicketInternalData, derive_key},
kerberos::{SESSION_KEY_LENGTH, SessionLengthTy, TicketInternalData, derive_kerberos_key},
nex::account::Account,
rmc::structures::RmcSerialize,
};
@ -26,7 +26,7 @@ pub fn read_secure_connection_data(
let ticket_data = &mut ticket_data[0..ticket_data_size - 0x10];
let server_key = derive_key(act.pid, &act.kerbros_password[..]);
let server_key = derive_kerberos_key(act.pid, act.nex_key);
let mut rc4: StreamCipherCoreWrapper<Rc4Core<U16>> =
Rc4::new_from_slice(&server_key).expect("unable to init rc4 keystream");