641 lines
19 KiB
C++
641 lines
19 KiB
C++
#include "appleauth/iauth.h"
|
|
#include "tier2/fileformats/plist.h"
|
|
#include "http/http.h"
|
|
#include "openssl/srp.h"
|
|
#include "openssl/evp.h"
|
|
#include "openssl/sha.h"
|
|
#include "tier0/rand.h"
|
|
|
|
IHTTPClientManager *g_pHttpClientMgr = NULL;
|
|
static int base64_decode(const char *b64, unsigned char *pOut) {
|
|
int len = strlen(b64);
|
|
if (pOut == NULL)
|
|
return (len*3)/4;
|
|
int out_len = EVP_DecodeBlock(pOut,
|
|
(const unsigned char *)b64,
|
|
len);
|
|
if (out_len < 0)
|
|
return -1;
|
|
|
|
while (len > 0 && b64[len - 1] == '=') {
|
|
out_len--;
|
|
len--;
|
|
}
|
|
|
|
return out_len;
|
|
}
|
|
|
|
// autogenerated
|
|
#define APPLE_LOCAL_USER "e2e70285da39596ef06153b9c4e1e5dc8d2f983bc5cd63f5b1e292207060d931"
|
|
#define APPLE_HTTP_HEADER \
|
|
{ \
|
|
{"X-Apple-I-Client-Time", "2026-1-9T12:00:00"}, \
|
|
{"X-Apple-Locale", "en_US"}, \
|
|
{"X-Apple-I-TimeZone", "Europe/Kyiv"}, \
|
|
{"X-Mme-Client-Info", "<MacBookPro13,2> <macOS;13.1;22C65> <com.apple.AuthKit/1 (com.apple.dt.Xcode/3594.4.19)>"}, \
|
|
{"User-Agent", "akd/1.0 CFNetwork/808.1.4"}, \
|
|
{"X-Apple-I-MD-LU", APPLE_LOCAL_USER}, \
|
|
{"X-Apple-I-MD-M", "0"}, \
|
|
{"X-Apple-I-SRL-NO", "0"}, \
|
|
{"X-Mme-Device-Id", "0"}, \
|
|
{"Content-Type", "text/x-xml-plist"}, \
|
|
{"Accept", "*/*"}, \
|
|
};
|
|
|
|
#define N2048 "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73"
|
|
#define G2048 "2"
|
|
enum EPasswordType
|
|
{
|
|
PASSWORD_TYPE_S2K,
|
|
PASSWORD_TYPE_S2K_FO,
|
|
};
|
|
|
|
class CAppleAuth: public IAppleAuth
|
|
{
|
|
public:
|
|
virtual void Init() override;
|
|
virtual void Shutdown() override;
|
|
virtual void LaunchLoginDaemon() override;
|
|
virtual EAppleAuthDaemonStatus GetStatus() override;
|
|
virtual EAppleAuthStatus SubmitLoginData( const char *szEmail, const char *szPassword ) override;
|
|
virtual EAppleAuthStatus Submit2FA( const char *szCode ) override;
|
|
virtual CUtlString EncryptPassword( const char *szPassword, CUtlString szSalt, uint32_t uIters, EPasswordType eType );
|
|
void ComputeM1( unsigned char M1[SHA256_DIGEST_LENGTH], const BIGNUM *N, const BIGNUM *g, const char *username, const char *password, const unsigned char *salt, size_t salt_len, const BIGNUM *A, const BIGNUM *B, const BIGNUM *a );
|
|
|
|
CUtlString FetchADIPB();
|
|
void FetchHeaders( CUtlString szAdiPb );
|
|
|
|
IHTTPClient *m_pANIClient;
|
|
IHTTPClient *m_pGrandSlamClient;
|
|
|
|
CUtlString m_szProvisionStart = "/grandslam/MidService/startMachineProvisioning";
|
|
CUtlString m_szProvisionFinish = "/grandslam/MidService/finishMachineProvisioning";
|
|
IJSONObject *pHeader;
|
|
|
|
CUtlString m_szAppleIMD;
|
|
CUtlString m_szAppleIMDM;
|
|
CUtlString m_szAppleIMDRINFO;
|
|
|
|
};
|
|
|
|
CUtlString CAppleAuth::FetchADIPB()
|
|
{
|
|
|
|
CUtlString szProvisionExpectedInputRaw = NULL;
|
|
IJSONObject *pObject = NULL;
|
|
IJSONObject *pPlistObject = NULL;
|
|
CUtlString szProvisionExpectedInput = NULL;
|
|
CUtlString szAdiPb = NULL;
|
|
|
|
m_pANIClient = g_pHttpClientMgr->Connect("ani.sidestore.io", true, NULL);
|
|
|
|
{
|
|
HTTPHeaderParam_t params[] = APPLE_HTTP_HEADER;
|
|
HTTPHeader_t header = {
|
|
sizeof(params)/sizeof(HTTPHeaderParam_t),
|
|
params,
|
|
};
|
|
m_pGrandSlamClient->Get("/grandslam/GsService2/lookup", &header);
|
|
HTTPResponse_t r = m_pGrandSlamClient->GetResponse();
|
|
if ( r.m_uCode != 200 )
|
|
{
|
|
g_pHttpClientMgr->Disconnect(m_pANIClient);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if ( !m_pANIClient->WebSocket_Connect("/v3/provisioning_session") )
|
|
Plat_FatalErrorFunc("Failed to init AppleAuth websocket\n");
|
|
|
|
// Getting adipb
|
|
while ( ( szProvisionExpectedInputRaw = m_pANIClient->WebSocket_RecvText() ) != NULL )
|
|
{
|
|
pObject = JSONManager()->ReadString(szProvisionExpectedInputRaw);
|
|
szProvisionExpectedInput = pObject->GetValue("result")->GetStringValue();
|
|
V_printf("%s\n",szProvisionExpectedInput.GetString());
|
|
if ( szProvisionExpectedInput == "GiveIdentifier" )
|
|
{
|
|
m_pANIClient->WebSocket_SendText("{\"identifier\": \"" APPLE_LOCAL_USER "\"}");
|
|
continue;
|
|
}
|
|
if ( szProvisionExpectedInput == "GiveStartProvisioningData" )
|
|
{
|
|
const char *plist =
|
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
|
|
"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
|
"<plist version=\"1.0\">\n"
|
|
"<dict>\n"
|
|
"\t<key>Header</key>\n"
|
|
"\t<dict/>\n"
|
|
"\t<key>Request</key>\n"
|
|
"\t<dict/>\n"
|
|
"</dict>\n"
|
|
"</plist>\n";
|
|
|
|
HTTPHeaderParam_t params[] = APPLE_HTTP_HEADER;
|
|
HTTPHeader_t header = {
|
|
sizeof(params)/sizeof(HTTPHeaderParam_t),
|
|
params,
|
|
};
|
|
m_pGrandSlamClient->Post(m_szProvisionStart, &header, V_strlen(plist), plist);
|
|
HTTPResponse_t r = m_pGrandSlamClient->GetResponse();
|
|
if ( r.m_uCode != 200 )
|
|
{
|
|
g_pHttpClientMgr->Disconnect(m_pANIClient);
|
|
return NULL;
|
|
}
|
|
IJSONObject *pObject = PropertyListManager()->ReadString(r.m_message);
|
|
CUtlString spim = pObject->GetValue("Response")->GetObject()->GetValue("spim")->GetStringValue();
|
|
m_pANIClient->WebSocket_SendText(CUtlString("{\"spim\": \"%s\"}", spim.GetString()));
|
|
|
|
continue;
|
|
}
|
|
if ( szProvisionExpectedInput == "GiveEndProvisioningData" )
|
|
{
|
|
CUtlString cpim = pObject->GetValue("cpim")->GetStringValue();
|
|
|
|
CUtlString plist = CUtlString(
|
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
|
|
"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
|
"<plist version=\"1.0\">\n"
|
|
"<dict>\n"
|
|
"\t<key>Header</key>\n"
|
|
"\t<dict/>\n"
|
|
"\t<key>Request</key>\n"
|
|
"\t<dict>\n"
|
|
"\t<key>cpim</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
"\t</dict>\n"
|
|
"</dict>\n"
|
|
"</plist>\n", cpim.GetString());
|
|
|
|
HTTPHeaderParam_t params[] = APPLE_HTTP_HEADER;
|
|
HTTPHeader_t header = {
|
|
sizeof(params)/sizeof(HTTPHeaderParam_t),
|
|
params,
|
|
};
|
|
m_pGrandSlamClient->Post(m_szProvisionFinish, &header, V_strlen(plist), plist);
|
|
HTTPResponse_t r = m_pGrandSlamClient->GetResponse();
|
|
if ( r.m_uCode != 200 )
|
|
{
|
|
g_pHttpClientMgr->Disconnect(m_pANIClient);
|
|
return NULL;
|
|
}
|
|
IJSONObject *pObject = PropertyListManager()->ReadString(r.m_message);
|
|
CUtlString tk = pObject->GetValue("Response")->GetObject()->GetValue("tk")->GetStringValue();
|
|
CUtlString ptm = pObject->GetValue("Response")->GetObject()->GetValue("ptm")->GetStringValue();
|
|
|
|
V_printf("%s\n",CUtlString("{\"tk\": \"%s\", \"ptm\": \"%s\"}", tk.GetString(), ptm.GetString()).GetString());
|
|
m_pANIClient->WebSocket_SendText(CUtlString("{\"tk\": \"%s\", \"ptm\": \"%s\"}", tk.GetString(), ptm.GetString()));
|
|
|
|
continue;
|
|
}
|
|
if ( szProvisionExpectedInput == "ProvisioningSuccess" )
|
|
{
|
|
szAdiPb = pObject->GetValue("adi_pb")->GetStringValue();
|
|
g_pHttpClientMgr->Disconnect(m_pANIClient);
|
|
break;
|
|
}
|
|
if ( szProvisionExpectedInput == "Timeout" )
|
|
{
|
|
break;
|
|
}
|
|
g_pHttpClientMgr->Disconnect(m_pANIClient);
|
|
return NULL;
|
|
}
|
|
g_pHttpClientMgr->Disconnect(m_pANIClient);
|
|
return szAdiPb;
|
|
}
|
|
void CAppleAuth::FetchHeaders( CUtlString szAdiPb )
|
|
{
|
|
// Get header
|
|
HTTPHeaderParam_t params[] = {
|
|
"Content-Type", "application/json",
|
|
};
|
|
HTTPHeader_t header = {
|
|
sizeof(params)/sizeof(HTTPHeaderParam_t),
|
|
params,
|
|
};
|
|
m_pANIClient = g_pHttpClientMgr->Connect("ani.sidestore.io", true, NULL);
|
|
CUtlString szPostData = CUtlString("{\"identifier\": \"" APPLE_LOCAL_USER "\", \"adi_pb\": \"%s\"}", szAdiPb.GetString());
|
|
V_printf("%s\n",szPostData.GetString());
|
|
m_pANIClient->Post("/v3/get_headers", &header, V_strlen(szPostData), szPostData);
|
|
HTTPResponse_t r = m_pANIClient->GetResponse();
|
|
V_printf("%i\n",r.m_uCode);
|
|
if ( r.m_uCode == 200 )
|
|
{
|
|
V_printf("%s\n",r.m_message.GetMemory());
|
|
pHeader = JSONManager()->ReadString(r.m_message);
|
|
m_szAppleIMD = pHeader->GetValue("X-Apple-I-MD")->GetStringValue();
|
|
m_szAppleIMDM = pHeader->GetValue("X-Apple-I-MD-M")->GetStringValue();
|
|
m_szAppleIMDRINFO = pHeader->GetValue("X-Apple-I-MD-RINFO")->GetStringValue();
|
|
JSONManager()->FreeObject(pHeader);
|
|
}
|
|
g_pHttpClientMgr->Disconnect(m_pANIClient);
|
|
}
|
|
|
|
void CAppleAuth::Init()
|
|
{
|
|
CreateInterfaceFn fnHttpFactory = Sys_GetFactory("funnyhttp");
|
|
|
|
g_pHttpClientMgr = (IHTTPClientManager*)fnHttpFactory(HTTP_CLIENT_INTERFACE_VERSION, NULL);
|
|
|
|
m_pGrandSlamClient = g_pHttpClientMgr->Connect("gsa.apple.com", true, NULL);
|
|
|
|
CUtlString szAdiPb = FetchADIPB();
|
|
FetchHeaders(szAdiPb);
|
|
|
|
|
|
|
|
}
|
|
|
|
void CAppleAuth::Shutdown()
|
|
{
|
|
|
|
}
|
|
|
|
void CAppleAuth::LaunchLoginDaemon()
|
|
{
|
|
|
|
|
|
}
|
|
|
|
EAppleAuthDaemonStatus CAppleAuth::GetStatus()
|
|
{
|
|
return APPLE_AUTH_DAEMON_NOT_LOGGED_IN;
|
|
}
|
|
|
|
|
|
EAppleAuthStatus CAppleAuth::SubmitLoginData( const char *szEmail, const char *szPassword )
|
|
{
|
|
const char *pszUser = szEmail;
|
|
const char *pszPass = szPassword;
|
|
|
|
BIGNUM* pN = BN_new();
|
|
BIGNUM* pG = BN_new();
|
|
BIGNUM* pa = BN_new();
|
|
BIGNUM* pA = BN_new();
|
|
BN_CTX *pbnCtx = BN_CTX_new();
|
|
|
|
SHA256_CTX pSha;
|
|
unsigned char pK[SHA256_DIGEST_LENGTH];
|
|
BN_hex2bn(&pN, N2048);
|
|
BN_hex2bn(&pG, G2048);
|
|
CUtlBuffer<unsigned char> bN;
|
|
CUtlBuffer<unsigned char> bG;
|
|
bN = CUtlBuffer<unsigned char>(BN_num_bytes(pN));
|
|
bG = CUtlBuffer<unsigned char>(BN_num_bytes(pG));
|
|
BN_bn2bin(pN, bN.GetMemory());
|
|
SHA256_Init(&pSha);
|
|
SHA256_Update(&pSha, bN.GetMemory(), bN.GetSize());
|
|
SHA256_Update(&pSha, bG.GetMemory(), bG.GetSize());
|
|
SHA256_Final(pK, &pSha);
|
|
|
|
BN_rand(pa, 256, 0, 0);
|
|
BN_set_flags(pa, BN_FLG_CONSTTIME);
|
|
BN_mod_exp(pA, pG, pa, pN, pbnCtx);
|
|
|
|
char *pszA = BN_bn2hex(pA);
|
|
|
|
CUtlString plist = CUtlString(
|
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
|
|
"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
|
"<plist version=\"1.0\">\n"
|
|
"<dict>\n"
|
|
"\t<key>Header</key>\n"
|
|
"\t<dict>\n"
|
|
"\t<key>Version</key>\n"
|
|
"\t<string>1.0.1</string>\n"
|
|
"\t</dict>\n"
|
|
|
|
"\t<key>Request</key>\n"
|
|
"\t<dict>\n"
|
|
|
|
"\t<key>A2k</key>\n"
|
|
"\t<data>%s</data>\n"
|
|
|
|
"\t<key>ps</key>\n"
|
|
"\t<array><string>s2k</string><string>s2k_fo</string></array>\n"
|
|
|
|
"\t<key>u</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
|
|
"\t<key>o</key>\n"
|
|
"\t<string>init</string>\n"
|
|
|
|
"\t<key>cpd</key>\n"
|
|
"\t<dict>\n"
|
|
|
|
"\t<key>X-Apple-I-Client-Time</key>\n"
|
|
"\t<string>2026-1-9T12:00:00Z</string>\n"
|
|
"\t<key>X-Apple-I-MD</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
"\t<key>X-Apple-I-MD-LU</key>\n"
|
|
"\t<string>" APPLE_LOCAL_USER "</string>\n"
|
|
"\t<key>X-Apple-I-MD-M</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
"\t<key>X-Apple-I-MD-RINFO</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
"\t<key>X-Mme-Client-Info</key>\n"
|
|
"\t<string><MacBookPro13,2> <macOS;13.1;22C65> <com.apple.AuthKit/1 (com.apple.dt.Xcode/3594.4.19)></string>\n"
|
|
"\t<key>X-Apple-I-SRL-NO</key>\n"
|
|
"\t<string>0</string>\n"
|
|
|
|
|
|
"\t<key>bootstrap</key>\n"
|
|
"\t<trur/>\n"
|
|
|
|
"\t<key>icscrec</key>\n"
|
|
"\t<true/>\n"
|
|
|
|
|
|
"\t<key>pbe</key>\n"
|
|
"\t<false/>\n"
|
|
|
|
"\t<key>prkgen</key>\n"
|
|
"\t<true/>\n"
|
|
|
|
"\t<key>svct</key>\n"
|
|
"\t<string>iCloud</string>\n"
|
|
|
|
"\t<key>loc</key>\n"
|
|
"\t<string>en_US</string>\n"
|
|
|
|
"\t</dict>\n"
|
|
|
|
"\t</dict>\n"
|
|
"</dict>\n"
|
|
"</plist>\n", pszA, szEmail, m_szAppleIMD.GetString(), m_szAppleIMDM.GetString(), m_szAppleIMDRINFO.GetString());
|
|
HTTPHeaderParam_t params[] = {
|
|
{"Content-Type", "text/x-xml-plist"},
|
|
{"Accept", "*/*"},
|
|
{"User-Agent", "akd/1.0 CFNetwork/808.1.4"}, \
|
|
{"X-Mme-Client-Info", "<MacBookPro13,2> <macOS;13.1;22C65> <com.apple.AuthKit/1 (com.apple.dt.Xcode/3594.4.19)>"}, \
|
|
};
|
|
HTTPHeader_t header = {
|
|
sizeof(params)/sizeof(HTTPHeaderParam_t),
|
|
params,
|
|
};
|
|
V_printf("%s\n",plist.GetString());
|
|
m_pGrandSlamClient->Post("/grandslam/GsService2", &header, plist.GetLenght(), plist);
|
|
HTTPResponse_t stResponse = m_pGrandSlamClient->GetResponse();
|
|
V_printf("%i %i\n", stResponse.m_uCode, stResponse.m_bIsComplete);
|
|
if (stResponse.m_uCode != 200)
|
|
return APPLE_AUTH_FAILURE;
|
|
V_printf("%s\n",stResponse.m_message.GetMemory());
|
|
IJSONObject *pObject = PropertyListManager()->ReadString(stResponse.m_message);
|
|
IJSONObject *pResponse = pObject->GetValue("Response")->GetObject();
|
|
CUtlString szEncryptedPassword = EncryptPassword(szPassword, pResponse->GetValue("s")->GetStringValue(), pResponse->GetValue("i")->GetNumberValue(), PASSWORD_TYPE_S2K);
|
|
const char *szSalt = pResponse->GetValue("s")->GetStringValue();
|
|
const char *szB = pResponse->GetValue("B")->GetStringValue();
|
|
unsigned char salt[32];
|
|
int iSaltLen = base64_decode(szSalt, salt);
|
|
|
|
int iBLen = base64_decode(szB, NULL);
|
|
CUtlBuffer<unsigned char> BBuffer = CUtlBuffer<unsigned char>(iBLen);
|
|
iBLen = base64_decode(szB, BBuffer.GetMemory());
|
|
BIGNUM *pB = BN_bin2bn(BBuffer.GetMemory(), BBuffer.GetSize(), NULL);
|
|
unsigned char M1[SHA256_DIGEST_LENGTH];
|
|
ComputeM1(M1, pN, pG, szEmail, szPassword, salt, iSaltLen, pA, pB, pa);
|
|
|
|
CUtlString szM1 = {};
|
|
for ( int i = 0; i < SHA256_DIGEST_LENGTH; i++ )
|
|
{
|
|
szM1.AppendTail(CUtlString("%02x", M1[i]));
|
|
}
|
|
|
|
plist = CUtlString(
|
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
|
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
|
|
"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
|
"<plist version=\"1.0\">\n"
|
|
"<dict>\n"
|
|
"\t<key>Header</key>\n"
|
|
"\t<dict>\n"
|
|
"\t<key>Version</key>\n"
|
|
"\t<string>1.0.1</string>\n"
|
|
"\t</dict>\n"
|
|
|
|
"\t<key>Request</key>\n"
|
|
"\t<dict>\n"
|
|
|
|
"\t<key>M1</key>\n"
|
|
"\t<data>%s</data>\n"
|
|
|
|
"\t<key>c</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
|
|
"\t<key>ps</key>\n"
|
|
"\t<array><string>s2k</string><string>s2k_fo</string></array>\n"
|
|
|
|
"\t<key>u</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
|
|
"\t<key>o</key>\n"
|
|
"\t<string>complete</string>\n"
|
|
|
|
"\t<key>cpd</key>\n"
|
|
"\t<dict>\n"
|
|
|
|
"\t<key>X-Apple-I-Client-Time</key>\n"
|
|
"\t<string>2026-1-9T12:00:00Z</string>\n"
|
|
"\t<key>X-Apple-I-MD</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
"\t<key>X-Apple-I-MD-LU</key>\n"
|
|
"\t<string>" APPLE_LOCAL_USER "</string>\n"
|
|
"\t<key>X-Apple-I-MD-M</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
"\t<key>X-Apple-I-MD-RINFO</key>\n"
|
|
"\t<string>%s</string>\n"
|
|
"\t<key>X-Mme-Client-Info</key>\n"
|
|
"\t<string><MacBookPro13,2> <macOS;13.1;22C65> <com.apple.AuthKit/1 (com.apple.dt.Xcode/3594.4.19)></string>\n"
|
|
"\t<key>X-Apple-I-SRL-NO</key>\n"
|
|
"\t<string>0</string>\n"
|
|
|
|
|
|
"\t<key>bootstrap</key>\n"
|
|
"\t<trur/>\n"
|
|
|
|
"\t<key>icscrec</key>\n"
|
|
"\t<true/>\n"
|
|
|
|
|
|
"\t<key>pbe</key>\n"
|
|
"\t<false/>\n"
|
|
|
|
"\t<key>prkgen</key>\n"
|
|
"\t<true/>\n"
|
|
|
|
"\t<key>svct</key>\n"
|
|
"\t<string>iCloud</string>\n"
|
|
|
|
"\t<key>loc</key>\n"
|
|
"\t<string>en_US</string>\n"
|
|
|
|
"\t</dict>\n"
|
|
|
|
"\t</dict>\n"
|
|
"</dict>\n"
|
|
"</plist>\n", szM1.GetString(), pResponse->GetValue("c")->GetStringValue(), szEmail, m_szAppleIMD.GetString(), m_szAppleIMDM.GetString(), m_szAppleIMDRINFO.GetString());
|
|
V_printf("%s\n", plist.GetString());
|
|
m_pGrandSlamClient->Post("/grandslam/GsService2", &header, plist.GetLenght(), plist);
|
|
stResponse = m_pGrandSlamClient->GetResponse();
|
|
V_printf("%i %i\n", stResponse.m_uCode, stResponse.m_bIsComplete);
|
|
if (stResponse.m_uCode != 200)
|
|
return APPLE_AUTH_FAILURE;
|
|
V_printf("%s\n", stResponse.m_message.GetMemory());
|
|
|
|
g_pHttpClientMgr->Disconnect(m_pGrandSlamClient);
|
|
|
|
|
|
OPENSSL_free(pszA);
|
|
return APPLE_AUTH_SUCCESS;
|
|
}
|
|
|
|
static void hash_bn_pad(unsigned char out[SHA256_DIGEST_LENGTH], const BIGNUM *bn)
|
|
{
|
|
unsigned char buf[256];
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
int len = BN_num_bytes(bn);
|
|
BN_bn2bin(bn, buf + (256 - len));
|
|
|
|
SHA256(buf, 256, out);
|
|
}
|
|
|
|
void CAppleAuth::ComputeM1(
|
|
unsigned char M1[SHA256_DIGEST_LENGTH],
|
|
const BIGNUM *N,
|
|
const BIGNUM *g,
|
|
const char *username,
|
|
const char *password,
|
|
const unsigned char *salt, size_t salt_len,
|
|
const BIGNUM *A,
|
|
const BIGNUM *B,
|
|
const BIGNUM *a
|
|
)
|
|
{
|
|
SHA256_CTX ctx;
|
|
unsigned char HN[SHA256_DIGEST_LENGTH], Hg[SHA256_DIGEST_LENGTH], HNxorg[SHA256_DIGEST_LENGTH];
|
|
unsigned char HI[SHA256_DIGEST_LENGTH];
|
|
|
|
/* H(N) xor H(g) */
|
|
hash_bn_pad(HN, N);
|
|
hash_bn_pad(Hg, g);
|
|
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
|
HNxorg[i] = HN[i] ^ Hg[i];
|
|
|
|
/* H(I) */
|
|
SHA256((const unsigned char *)username, strlen(username), HI);
|
|
|
|
/* x = H(s || H(I ":" P)) */
|
|
unsigned char inner_hash[SHA256_DIGEST_LENGTH];
|
|
SHA256_Init(&ctx);
|
|
SHA256_Update(&ctx, (const unsigned char *)username, strlen(username));
|
|
SHA256_Update(&ctx, (const unsigned char *)":", 1);
|
|
SHA256_Update(&ctx, (const unsigned char *)password, strlen(password));
|
|
SHA256_Final(inner_hash, &ctx);
|
|
|
|
unsigned char x_hash[SHA256_DIGEST_LENGTH];
|
|
SHA256_Init(&ctx);
|
|
SHA256_Update(&ctx, salt, salt_len);
|
|
SHA256_Update(&ctx, inner_hash, SHA256_DIGEST_LENGTH);
|
|
SHA256_Final(x_hash, &ctx);
|
|
|
|
BIGNUM *x = BN_bin2bn(x_hash, SHA256_DIGEST_LENGTH, NULL);
|
|
|
|
/* k = H(N || g) */
|
|
unsigned char k_hash[SHA256_DIGEST_LENGTH];
|
|
SHA256_Init(&ctx);
|
|
unsigned char bufN[256], bufg[256];
|
|
memset(bufN, 0, 256); BN_bn2bin(N, bufN + (256 - BN_num_bytes(N)));
|
|
memset(bufg, 0, 256); BN_bn2bin(g, bufg + (256 - BN_num_bytes(g)));
|
|
SHA256_Update(&ctx, bufN, 256);
|
|
SHA256_Update(&ctx, bufg, 256);
|
|
SHA256_Final(k_hash, &ctx);
|
|
BIGNUM *k = BN_bin2bn(k_hash, SHA256_DIGEST_LENGTH, NULL);
|
|
|
|
/* u = H(A || B) */
|
|
unsigned char bufA[256], bufB[256], u_hash[SHA256_DIGEST_LENGTH];
|
|
memset(bufA, 0, 256); BN_bn2bin(A, bufA + (256 - BN_num_bytes(A)));
|
|
memset(bufB, 0, 256); BN_bn2bin(B, bufB + (256 - BN_num_bytes(B)));
|
|
SHA256_Init(&ctx);
|
|
SHA256_Update(&ctx, bufA, 256);
|
|
SHA256_Update(&ctx, bufB, 256);
|
|
SHA256_Final(u_hash, &ctx);
|
|
BIGNUM *u = BN_bin2bn(u_hash, SHA256_DIGEST_LENGTH, NULL);
|
|
|
|
/* S = (B - k * g^x)^(a + u * x) mod N */
|
|
BN_CTX *bn_ctx = BN_CTX_new();
|
|
BIGNUM *gx = BN_new(), *kgx = BN_new(), *B_sub = BN_new();
|
|
BIGNUM *ux = BN_new(), *exp = BN_new(), *S = BN_new();
|
|
|
|
BN_mod_exp(gx, g, x, N, bn_ctx); /* g^x mod N */
|
|
BN_mod_mul(kgx, k, gx, N, bn_ctx); /* k * g^x mod N */
|
|
BN_mod_sub(B_sub, B, kgx, N, bn_ctx); /* B - k*g^x mod N */
|
|
BN_mul(ux, u, x, bn_ctx); /* u*x */
|
|
BN_add(exp, a, ux); /* a + u*x */
|
|
BN_mod_exp(S, B_sub, exp, N, bn_ctx); /* S */
|
|
|
|
/* K = H(S) */
|
|
unsigned char S_bytes[256];
|
|
memset(S_bytes, 0, 256);
|
|
BN_bn2bin(S, S_bytes + (256 - BN_num_bytes(S)));
|
|
unsigned char K[SHA256_DIGEST_LENGTH];
|
|
SHA256(S_bytes, 256, K);
|
|
|
|
/* Compute M1 */
|
|
SHA256_Init(&ctx);
|
|
SHA256_Update(&ctx, HNxorg, SHA256_DIGEST_LENGTH);
|
|
SHA256_Update(&ctx, HI, SHA256_DIGEST_LENGTH);
|
|
SHA256_Update(&ctx, salt, salt_len);
|
|
SHA256_Update(&ctx, bufA, 256);
|
|
SHA256_Update(&ctx, bufB, 256);
|
|
SHA256_Update(&ctx, K, SHA256_DIGEST_LENGTH);
|
|
SHA256_Final(M1, &ctx);
|
|
|
|
/* Cleanup */
|
|
BN_free(x); BN_free(k); BN_free(u);
|
|
BN_free(gx); BN_free(kgx); BN_free(B_sub); BN_free(ux); BN_free(exp); BN_free(S);
|
|
BN_CTX_free(bn_ctx);
|
|
}
|
|
|
|
EAppleAuthStatus CAppleAuth::Submit2FA( const char *szCode )
|
|
{
|
|
|
|
}
|
|
CUtlString CAppleAuth::EncryptPassword( const char *szPassword, CUtlString szSalt, uint32_t uIters, EPasswordType eType )
|
|
{
|
|
|
|
unsigned char hashedPassword[SHA256_DIGEST_LENGTH];
|
|
CUtlString szHashedPasswordHex = "";
|
|
unsigned char encryptedPassword[32];
|
|
CUtlString szEncryptedPasswordHex = "";
|
|
unsigned char salt[32];
|
|
int iSaltLen = base64_decode(szSalt, salt);
|
|
|
|
if ( eType == PASSWORD_TYPE_S2K )
|
|
{
|
|
for ( int i = 0; i < SHA256_DIGEST_LENGTH; i++ )
|
|
{
|
|
szHashedPasswordHex.AppendTail(CUtlString("%02x", hashedPassword[i]));
|
|
}
|
|
PKCS5_PBKDF2_HMAC(szHashedPasswordHex, szHashedPasswordHex.GetLenght(), salt, iSaltLen, uIters, EVP_sha256(), 32, encryptedPassword);
|
|
};
|
|
for ( int i = 0; i < SHA256_DIGEST_LENGTH; i++ )
|
|
{
|
|
szEncryptedPasswordHex.AppendTail(CUtlString("%02x", encryptedPassword[i]));
|
|
}
|
|
V_printf("%s\n",szEncryptedPasswordHex.GetString());
|
|
return szEncryptedPasswordHex;
|
|
|
|
}
|
|
|
|
|
|
static CAppleAuth s_appleAuth;
|
|
EXPOSE_INTERFACE_GLOBALVAR(CAppleAuth, IAppleAuth, APPLE_AUTH_INTERFACE_VERSION, s_appleAuth);
|
|
|