319 lines
7.3 KiB
C++
319 lines
7.3 KiB
C++
/**
|
|
* This file is a part of the UMSKT Project
|
|
*
|
|
* Copyleft (C) 2019-2024 UMSKT Contributors (et.al.)
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* @FileCreated by Neo on 02/18/2024
|
|
* @Maintainer Neo
|
|
*/
|
|
|
|
#include "cli.h"
|
|
|
|
/**
|
|
*
|
|
* @param pidgen3
|
|
* @return success
|
|
*/
|
|
BOOL CLI::InitPIDGEN3(PIDGEN3 *p3)
|
|
{
|
|
auto bink = keys["BINK"][options.binkID];
|
|
|
|
if (options.verbose)
|
|
{
|
|
fmt::print("{:->80}\n", "");
|
|
fmt::print("Loaded the following elliptic curve parameters: BINK[{}]\n", options.binkID);
|
|
fmt::print("{:->80}\n", "");
|
|
fmt::print("{:>6}: {}\n", "P", bink["p"]);
|
|
fmt::print("{:>6}: {}\n", "a", bink["a"]);
|
|
fmt::print("{:>6}: {}\n", "b", bink["b"]);
|
|
fmt::print("{:>6}: [{},\n{:>9}{}]\n", "G[x,y]", bink["g"]["x"], "", bink["g"]["y"]);
|
|
fmt::print("{:>6}: [{},\n{:>9}{}]\n", "K[x,y]", bink["pub"]["x"], "", bink["pub"]["y"]);
|
|
fmt::print("{:>6}: {}\n", "n", bink["n"]);
|
|
fmt::print("{:>6}: {}\n", "k", bink["priv"]);
|
|
fmt::print("\n");
|
|
}
|
|
|
|
p3->LoadEllipticCurve(options.binkID, bink["p"], bink["a"], bink["b"], bink["g"]["x"], bink["g"]["y"],
|
|
bink["pub"]["x"], bink["pub"]["y"], bink["n"], bink["priv"]);
|
|
|
|
if (options.state != Options::APPLICATION_STATE::STATE_PIDGEN_GENERATE)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (options.channelID.IsZero())
|
|
{
|
|
options.channelID.Randomize(UMSKT::rng, sizeof(DWORD32) * 8);
|
|
}
|
|
|
|
options.channelID %= 999;
|
|
p3->info.ChannelID = options.channelID;
|
|
if (options.verbose)
|
|
{
|
|
fmt::print("> Channel ID: {:d}\n", options.channelID);
|
|
}
|
|
|
|
if (options.serial.NotZero() && p3->checkFieldIsBink1998())
|
|
{
|
|
p3->info.Serial = options.serial;
|
|
if (options.verbose)
|
|
{
|
|
fmt::print("> Serial {:d}\n", options.serial);
|
|
}
|
|
}
|
|
else if (options.serial.NotZero() && !p3->checkFieldIsBink1998())
|
|
{
|
|
fmt::print("Warning: Discarding user-supplied serial for BINK2002\n");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param pidgen2
|
|
* @return success
|
|
*/
|
|
BOOL CLI::PIDGEN2Generate(PIDGEN2 &p2)
|
|
{
|
|
p2.info.ChannelID = options.channelID;
|
|
p2.info.Serial = options.serial;
|
|
p2.info.isOEM = options.oem;
|
|
|
|
std::string serial;
|
|
p2.Generate(serial);
|
|
|
|
serial = p2.StringifyKey(serial);
|
|
|
|
fmt::print("{}", serial);
|
|
|
|
auto retval = p2.Validate(serial);
|
|
|
|
if (!retval)
|
|
{
|
|
fmt::print(" [INVALID]");
|
|
}
|
|
|
|
fmt::print("\n");
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param pidgen2
|
|
* @return success
|
|
*/
|
|
BOOL CLI::PIDGEN2Validate(PIDGEN2 &p2)
|
|
{
|
|
std::string product_key;
|
|
|
|
if (!p2.ValidateKeyString(options.keyToCheck, product_key))
|
|
{
|
|
fmt::print("ERROR: Product key is in an incorrect format!\n");
|
|
return false;
|
|
}
|
|
|
|
fmt::print("{}\n", p2.StringifyKey(product_key));
|
|
|
|
if (!p2.Validate(product_key))
|
|
{
|
|
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
|
|
return false;
|
|
}
|
|
|
|
fmt::print("Key validated successfully!\n");
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return success
|
|
*/
|
|
BOOL CLI::PIDGEN3Generate(PIDGEN3 *p3)
|
|
{
|
|
// raw PID/serial value
|
|
Integer serialRnd;
|
|
|
|
if (p3->checkFieldIsBink1998())
|
|
{
|
|
if (options.serial.NotZero())
|
|
{
|
|
// using user-provided serial
|
|
serialRnd = options.serial;
|
|
}
|
|
else
|
|
{
|
|
// generate a random number to use as a serial
|
|
serialRnd.Randomize(UMSKT::rng, sizeof(DWORD32) * 8);
|
|
}
|
|
|
|
// make sure it's less than 999999
|
|
serialRnd %= 999999;
|
|
}
|
|
|
|
p3->info.isOEM = options.oem;
|
|
|
|
for (DWORD32 i = 0; i < total; i++)
|
|
{
|
|
if (!p3->checkFieldIsBink1998())
|
|
{
|
|
if (options.authInfo.empty())
|
|
{
|
|
p3->info.AuthInfo.Randomize(UMSKT::rng, 10);
|
|
}
|
|
else
|
|
{
|
|
p3->info.AuthInfo = CryptoPP::Crop(UMSKT::IntegerS(options.authInfo), 10);
|
|
}
|
|
|
|
if (options.verbose)
|
|
{
|
|
fmt::print("> AuthInfo: {:d}\n", p3->info.AuthInfo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p3->info.Serial = serialRnd;
|
|
}
|
|
|
|
if (options.verbose)
|
|
{
|
|
fmt::print("\n");
|
|
}
|
|
|
|
p3->Generate(pKey);
|
|
|
|
if (options.verbose)
|
|
{
|
|
fmt::print("> Product ID: {}\n\n", p3->StringifyProductID());
|
|
}
|
|
|
|
bool isValid = p3->Validate(pKey);
|
|
if (isValid)
|
|
{
|
|
fmt::print(p3->StringifyKey(pKey));
|
|
if (i <= total - 1 || options.verbose)
|
|
{
|
|
fmt::print("\n");
|
|
}
|
|
count += isValid;
|
|
}
|
|
else
|
|
{
|
|
if (options.verbose)
|
|
{
|
|
fmt::print("{} [Invalid]", p3->StringifyKey(pKey));
|
|
if (i <= total - 1)
|
|
{
|
|
fmt::print("\n");
|
|
}
|
|
}
|
|
total++; // queue a redo, basically
|
|
}
|
|
}
|
|
|
|
if (options.verbose)
|
|
{
|
|
fmt::print("\nSuccess count: {}/{}\n", count, total);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return success
|
|
*/
|
|
BOOL CLI::PIDGEN3Validate(PIDGEN3 *p3)
|
|
{
|
|
std::string product_key;
|
|
|
|
if (!p3->ValidateKeyString(options.keyToCheck, product_key))
|
|
{
|
|
fmt::print("ERROR: Product key is in an incorrect format!\n");
|
|
return false;
|
|
}
|
|
|
|
fmt::print("{}\n", p3->StringifyKey(product_key));
|
|
|
|
if (!p3->Validate(product_key))
|
|
{
|
|
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
|
|
return false;
|
|
}
|
|
|
|
fmt::print("Key validated successfully!\n");
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return success
|
|
*/
|
|
BOOL CLI::PIDGenerate()
|
|
{
|
|
BOOL retval = false;
|
|
|
|
if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_2)
|
|
{
|
|
auto p2 = PIDGEN2();
|
|
retval = PIDGEN2Generate(p2);
|
|
return retval;
|
|
}
|
|
else if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_3)
|
|
{
|
|
auto bink = keys["BINK"][options.binkID];
|
|
|
|
auto p3 = PIDGEN3::Factory(bink["p"]);
|
|
InitPIDGEN3(p3);
|
|
retval = PIDGEN3Generate(p3);
|
|
|
|
delete p3;
|
|
return retval;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return isValid
|
|
*/
|
|
BOOL CLI::PIDValidate()
|
|
{
|
|
BOOL retval = false;
|
|
|
|
if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_2)
|
|
{
|
|
auto p2 = PIDGEN2();
|
|
retval = PIDGEN2Validate(p2);
|
|
return retval;
|
|
}
|
|
else if (options.pidgenversion == Options::PIDGEN_VERSION::PIDGEN_3)
|
|
{
|
|
auto bink = keys["BINK"][options.binkID];
|
|
|
|
auto p3 = PIDGEN3::Factory(bink["p"]);
|
|
InitPIDGEN3(p3);
|
|
retval = PIDGEN3Validate(p3);
|
|
|
|
delete p3;
|
|
return retval;
|
|
}
|
|
|
|
return retval;
|
|
} |