From e0df0d6d9e0df538ce74cf59b6f3b43d17d614dc Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sun, 3 Mar 2019 21:06:55 +0100 Subject: [PATCH 1/3] Use `const` in RSA related pointers --- src/common/crypto/EmuRsa.cpp | 8 ++++---- src/common/crypto/EmuRsa.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/common/crypto/EmuRsa.cpp b/src/common/crypto/EmuRsa.cpp index a86eaa983..0cd833be0 100644 --- a/src/common/crypto/EmuRsa.cpp +++ b/src/common/crypto/EmuRsa.cpp @@ -102,7 +102,7 @@ double* sinCos = NULL; /* Global function declarations */ giant newgiant(int numshorts); -void gigimport(giant g, unsigned char* buff, int len); +void gigimport(giant g, const unsigned char* buff, int len); void auxmulg(giant a, giant b); void normal_subg(giant a, giant b); void reverse_subg(giant a, giant b); @@ -152,7 +152,7 @@ int gsign(giant g); /* Returns the sign of g: -1, 0, 1. */ void absg(giant g); /* g := |g|. */ -void RSAdecrypt(unsigned char* c_number, unsigned char* cryptbuffer, RSA_PUBLIC_KEY key) +void RSAdecrypt(const unsigned char* c_number, unsigned char* cryptbuffer, RSA_PUBLIC_KEY key) { giant n = newgiant(GIANT_INFINITY); giant e = newgiant(GIANT_INFINITY); @@ -171,7 +171,7 @@ void RSAdecrypt(unsigned char* c_number, unsigned char* cryptbuffer, RSA_PUBLIC_ memcpy(cryptbuffer, sig->n, 256); } -bool Verifyhash(unsigned char* hash, unsigned char* decryptBuffer, RSA_PUBLIC_KEY key) +bool Verifyhash(const unsigned char* hash, const unsigned char* decryptBuffer, RSA_PUBLIC_KEY key) { unsigned char cmphash[20]; int a; @@ -241,7 +241,7 @@ giant newgiant(int numshorts) // http://xbox-linux-devel.narkive.com/Qw6o31DP/xbedump-fix-for-array-out-of-bounds-access#post1 // and it has been improved based on JayFoxRox suggestions. See the link below for the details // https://github.com/xqemu/xbedump/pull/5 -void gigimport(giant g, unsigned char *buff, int len) { +void gigimport(giant g, const unsigned char *buff, int len) { // copy buffered 'number' into giant's number buffer memcpy(g->n, buff, len); diff --git a/src/common/crypto/EmuRsa.h b/src/common/crypto/EmuRsa.h index 6b67181ac..dd0afd42a 100644 --- a/src/common/crypto/EmuRsa.h +++ b/src/common/crypto/EmuRsa.h @@ -47,7 +47,7 @@ typedef struct _RSA_PUBLIC_KEY #pragma pack() -void RSAdecrypt(unsigned char* c_number, unsigned char* cryptbuffer, RSA_PUBLIC_KEY key); -bool Verifyhash(unsigned char* hash, unsigned char* decryptBuffer, RSA_PUBLIC_KEY key); +void RSAdecrypt(const unsigned char* c_number, unsigned char* cryptbuffer, RSA_PUBLIC_KEY key); +bool Verifyhash(const unsigned char* hash, const unsigned char* decryptBuffer, RSA_PUBLIC_KEY key); #endif From e1850c427769b91b662661106cd2c3aeffc62916 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 4 Mar 2019 02:28:30 +0100 Subject: [PATCH 2/3] Fix `gigimport` in RSA --- src/common/crypto/EmuRsa.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/common/crypto/EmuRsa.cpp b/src/common/crypto/EmuRsa.cpp index 0cd833be0..36bf27b04 100644 --- a/src/common/crypto/EmuRsa.cpp +++ b/src/common/crypto/EmuRsa.cpp @@ -18,6 +18,7 @@ // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * // * (c) 2018 ergo720 +// * (c) 2019 Jannik Vogel // * // * All rights reserved // * @@ -236,11 +237,6 @@ giant newgiant(int numshorts) return(thegiant); } -// ergo720: there's a bug in the original implementation of gigimport that prevents the rsa algorithm from working correctly on Windows (but -// for some reason it works on Ubuntu). This replacement implementation is taken from -// http://xbox-linux-devel.narkive.com/Qw6o31DP/xbedump-fix-for-array-out-of-bounds-access#post1 -// and it has been improved based on JayFoxRox suggestions. See the link below for the details -// https://github.com/xqemu/xbedump/pull/5 void gigimport(giant g, const unsigned char *buff, int len) { // copy buffered 'number' into giant's number buffer @@ -248,8 +244,14 @@ void gigimport(giant g, const unsigned char *buff, int len) { assert((len % 2) == 0); + // Get number of shorts g->sign = len / 2; + // Only count used shorts + while((g->sign >= 1) && (g->n[g->sign - 1] == 0)) { + g->sign -= 1; + } + assert(g->sign != 0); } From af0c85286f0142a2b9e2921205975d47eb02271e Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sun, 3 Mar 2019 20:58:30 +0100 Subject: [PATCH 3/3] Implement `XcModExp` --- src/common/crypto/EmuRsa.cpp | 30 +++++++++++++-------------- src/common/crypto/EmuRsa.h | 1 + src/core/kernel/exports/EmuKrnlXc.cpp | 11 ++++++---- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/common/crypto/EmuRsa.cpp b/src/common/crypto/EmuRsa.cpp index 36bf27b04..38616e123 100644 --- a/src/common/crypto/EmuRsa.cpp +++ b/src/common/crypto/EmuRsa.cpp @@ -152,24 +152,24 @@ void iaddg(int i, giant g); /* g += i, with i non-negative and < 2^16. */ int gsign(giant g); /* Returns the sign of g: -1, 0, 1. */ void absg(giant g); /* g := |g|. */ +void ModExp(unsigned char* a_number, const unsigned char* b_number, unsigned int b_len, const unsigned char* c_number, unsigned int c_len, const unsigned char* d_number, unsigned int d_len) +{ + giant b = newgiant(GIANT_INFINITY); + giant c = newgiant(GIANT_INFINITY); + giant d = newgiant(GIANT_INFINITY); + gigimport(b, b_number, b_len); + gigimport(c, c_number, c_len); + gigimport(d, d_number, d_len); + + /* a = b := b^c (mod d). */ + powermodg(b, c, d); + + memcpy(a_number, b->n, d_len); +} void RSAdecrypt(const unsigned char* c_number, unsigned char* cryptbuffer, RSA_PUBLIC_KEY key) { - giant n = newgiant(GIANT_INFINITY); - giant e = newgiant(GIANT_INFINITY); - giant sig = newgiant(GIANT_INFINITY); - - gigimport(sig, c_number, 256); - - gigimport(n, key.KeyData.Modulus, 256); - - gigimport(e, key.KeyData.Exponent, 4); - - /* x := x^n (mod z). */ - powermodg(sig, e, n); - - memset(cryptbuffer, 0x00, 256); - memcpy(cryptbuffer, sig->n, 256); + ModExp(cryptbuffer, c_number, 256, key.KeyData.Exponent, 4, key.KeyData.Modulus, 256); } bool Verifyhash(const unsigned char* hash, const unsigned char* decryptBuffer, RSA_PUBLIC_KEY key) diff --git a/src/common/crypto/EmuRsa.h b/src/common/crypto/EmuRsa.h index dd0afd42a..01204a3a7 100644 --- a/src/common/crypto/EmuRsa.h +++ b/src/common/crypto/EmuRsa.h @@ -47,6 +47,7 @@ typedef struct _RSA_PUBLIC_KEY #pragma pack() +void ModExp(unsigned char* a_number, const unsigned char* b_number, unsigned int b_len, const unsigned char* c_number, unsigned int c_len, const unsigned char* d_number, unsigned int d_len); void RSAdecrypt(const unsigned char* c_number, unsigned char* cryptbuffer, RSA_PUBLIC_KEY key); bool Verifyhash(const unsigned char* hash, const unsigned char* decryptBuffer, RSA_PUBLIC_KEY key); diff --git a/src/core/kernel/exports/EmuKrnlXc.cpp b/src/core/kernel/exports/EmuKrnlXc.cpp index 8fe303bc1..2d305ab61 100644 --- a/src/core/kernel/exports/EmuKrnlXc.cpp +++ b/src/core/kernel/exports/EmuKrnlXc.cpp @@ -20,7 +20,8 @@ // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * // * (c) 2002-2003 Aaron Robinson -// * (c) 2016 Patrick van Logchem +// * (c) 2016 Patrick van Logchem +// * (c) 2019 Jannik Vogel // * // * All rights reserved // * @@ -40,6 +41,7 @@ namespace xboxkrnl #include "common\crypto\EmuSha.h" // For A_SHAInit, etc. #include "common\crypto\LibRc4.h" // For RC4 Functions #include "common\crypto\EmuDes.h" // For DES Functions +#include "common\crypto\EmuRSA.h" // For RSA Functions // prevent name collisions namespace NtDll @@ -212,9 +214,10 @@ xboxkrnl::ULONG NTAPI JumpedModExp xboxkrnl::ULONG dwN ) { - ULONG ret = 0; - - LOG_UNIMPLEMENTED(); + ULONG ret = 1; + + unsigned int len = dwN * 4; + ModExp((unsigned char*)pA, (const unsigned char*)pB, len, (const unsigned char*)pC, len, (const unsigned char*)pD, len); return ret; }