diff --git a/src/common/crypto/EmuRsa.cpp b/src/common/crypto/EmuRsa.cpp index a86eaa983..38616e123 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 // * @@ -102,7 +103,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); @@ -151,27 +152,27 @@ 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 RSAdecrypt(unsigned char* c_number, unsigned char* cryptbuffer, RSA_PUBLIC_KEY key) +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 n = newgiant(GIANT_INFINITY); - giant e = newgiant(GIANT_INFINITY); - giant sig = newgiant(GIANT_INFINITY); + 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); - gigimport(sig, c_number, 256); + /* a = b := b^c (mod d). */ + powermodg(b, c, d); - 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); + memcpy(a_number, b->n, d_len); } -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) +{ + 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) { unsigned char cmphash[20]; int a; @@ -236,20 +237,21 @@ 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, 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); 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); } diff --git a/src/common/crypto/EmuRsa.h b/src/common/crypto/EmuRsa.h index 6b67181ac..01204a3a7 100644 --- a/src/common/crypto/EmuRsa.h +++ b/src/common/crypto/EmuRsa.h @@ -47,7 +47,8 @@ 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 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); #endif 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; }