standardize using clang-format

This commit is contained in:
Neo-Desktop 2023-12-10 04:06:42 -08:00
parent 8cc691b72f
commit c0a4c76b54
25 changed files with 1155 additions and 826 deletions

216
.clang-format Normal file
View File

@ -0,0 +1,216 @@
---
Language: Cpp
# BasedOnStyle: Microsoft
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: false
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 1000
PenaltyIndentedWhitespace: 0
PointerAlignment: Right
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RequiresClausePosition: OwnLine
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
...

View File

@ -31,22 +31,27 @@ CLI::~CLI()
BN_free(genOrder);
}
bool CLI::loadJSON(const fs::path& filename, json *output) {
if (!filename.empty() && !fs::exists(filename)) {
bool CLI::loadJSON(const fs::path &filename, json *output)
{
if (!filename.empty() && !fs::exists(filename))
{
fmt::print("ERROR: File {} does not exist\n", filename.string());
return false;
}
else if (fs::exists(filename)) {
else if (fs::exists(filename))
{
std::ifstream f(filename);
*output = json::parse(f, nullptr, false, false);
}
else if (filename.empty()) {
else if (filename.empty())
{
cmrc::embedded_filesystem fs = cmrc::umskt::get_filesystem();
cmrc::file keys = fs.open("keys.json");
*output = json::parse(keys, nullptr, false, false);
}
if (output->is_discarded()) {
if (output->is_discarded())
{
fmt::print("ERROR: Unable to parse keys from {}\n", filename.string());
return false;
}
@ -54,16 +59,18 @@ bool CLI::loadJSON(const fs::path& filename, json *output) {
return true;
}
void CLI::showHelp(char *argv[]) {
void CLI::showHelp(char *argv[])
{
fmt::print("usage: {} \n", argv[0]);
fmt::print("\t-h --help\tshow this message\n");
fmt::print("\t-v --verbose\tenable verbose output\n");
fmt::print("\t-n --number\tnumber of keys to generate (defaults to 1)\n");
fmt::print("\t-f --file\tspecify which keys file to load\n");
fmt::print("\t-i --instid\tinstallation ID used to generate confirmation ID\n");
fmt::print("\t-m --mode\tproduct family to activate.\n\t\t\tvalid options are \"WINDOWS\", \"OFFICEXP\", \"OFFICE2K3\", \"OFFICE2K7\" or \"PLUSDME\"\n\t\t\t(defaults to \"WINDOWS\")\n");
fmt::print("\t-p --productid\tthe product ID of the Program to activate. only required for Office 2K3 and Office 2K7 programs\n");
fmt::print("\t-m --mode\tproduct family to activate.\n\t\t\tvalid options are \"WINDOWS\", \"OFFICEXP\", "
"\"OFFICE2K3\", \"OFFICE2K7\" or \"PLUSDME\"\n\t\t\t(defaults to \"WINDOWS\")\n");
fmt::print("\t-p --productid\tthe product ID of the Program to activate. only required for Office 2K3 and Office "
"2K7 programs\n");
fmt::print("\t-b --binkid\tspecify which BINK identifier to load (defaults to 2E)\n");
fmt::print("\t-l --list\tshow which products/binks can be loaded\n");
fmt::print("\t-c --channelid\tspecify which Channel Identifier to use (defaults to 640)\n");
@ -74,186 +81,243 @@ void CLI::showHelp(char *argv[]) {
fmt::print("\n");
}
int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
int CLI::parseCommandLine(int argc, char *argv[], Options *options)
{
// set default options
*options = Options {
"2E",
"",
"",
"",
"",
640,
0,
1,
false,
false,
false,
false,
false,
false,
false,
MODE_BINK1998_GENERATE,
WINDOWS
};
*options = Options{"2E", "", "", "", "", 640, 0, 1,
false, false, false, false, false, false, false, MODE_BINK1998_GENERATE,
WINDOWS};
for (int i = 1; i < argc; i++) {
for (int i = 1; i < argc; i++)
{
std::string arg = argv[i];
if (arg == "-v" || arg == "--verbose") {
if (arg == "-v" || arg == "--verbose")
{
options->verbose = true;
UMSKT::setDebugOutput(stderr);
} else if (arg == "-h" || arg == "--help") {
}
else if (arg == "-h" || arg == "--help")
{
options->help = true;
} else if (arg == "-n" || arg == "--number") {
if (i == argc - 1) {
}
else if (arg == "-n" || arg == "--number")
{
if (i == argc - 1)
{
options->error = true;
break;
}
int nKeys;
if (!sscanf(argv[i+1], "%d", &nKeys)) {
if (!sscanf(argv[i + 1], "%d", &nKeys))
{
options->error = true;
} else {
}
else
{
options->numKeys = nKeys;
}
i++;
} else if (arg == "-b" || arg == "--bink") {
if (i == argc - 1) {
}
else if (arg == "-b" || arg == "--bink")
{
if (i == argc - 1)
{
options->error = true;
break;
}
options->binkid = argv[i+1];
options->binkid = argv[i + 1];
i++;
} else if (arg == "-l" || arg == "--list") {
}
else if (arg == "-l" || arg == "--list")
{
options->list = true;
} else if (arg == "-c" || arg == "--channelid") {
if (i == argc - 1) {
}
else if (arg == "-c" || arg == "--channelid")
{
if (i == argc - 1)
{
options->error = true;
break;
}
int siteID;
if (!sscanf(argv[i+1], "%d", &siteID)) {
if (!sscanf(argv[i + 1], "%d", &siteID))
{
options->error = true;
} else {
}
else
{
options->channelID = siteID;
}
i++;
} else if (arg == "-s" || arg == "--serial") {
if (i == argc - 1) {
}
else if (arg == "-s" || arg == "--serial")
{
if (i == argc - 1)
{
options->error = true;
break;
}
int serial_val;
if (!sscanf(argv[i+1], "%d", &serial_val)) {
if (!sscanf(argv[i + 1], "%d", &serial_val))
{
options->error = true;
} else {
}
else
{
options->serialSet = true;
options->serial = serial_val;
}
i++;
} else if (arg == "-u" || arg == "--upgrade") {
options->upgrade = true;
} else if (arg == "-f" || arg == "--file") {
if (i == argc - 1) {
}
else if (arg == "-u" || arg == "--upgrade")
{
options->upgrade = true;
}
else if (arg == "-f" || arg == "--file")
{
if (i == argc - 1)
{
options->error = true;
break;
}
options->keysFilename = argv[i+1];
options->keysFilename = argv[i + 1];
i++;
} else if (arg == "-i" || arg == "--instid") {
if (i == argc - 1) {
}
else if (arg == "-i" || arg == "--instid")
{
if (i == argc - 1)
{
options->error = true;
break;
}
options->instid = argv[i+1];
options->instid = argv[i + 1];
options->applicationMode = MODE_CONFIRMATION_ID;
i++;
} else if (arg == "-m" || arg == "--mode") {
std::string mode = argv[i+1];
}
else if (arg == "-m" || arg == "--mode")
{
std::string mode = argv[i + 1];
char *p = &mode[0];
for (; *p; p++) {
for (; *p; p++)
{
*p = toupper((unsigned char)*p);
}
}
p = &mode[0];
if (strcmp(p, "WINDOWS") == 0) {
if (strcmp(p, "WINDOWS") == 0)
{
options->activationMode = WINDOWS;
} else if (strcmp(p, "OFFICEXP") == 0) {
}
else if (strcmp(p, "OFFICEXP") == 0)
{
options->activationMode = OFFICE_XP;
} else if (strcmp(p, "OFFICE2K3") == 0) {
}
else if (strcmp(p, "OFFICE2K3") == 0)
{
options->activationMode = OFFICE_2K3;
} else if (strcmp(p, "OFFICE2K7") == 0) {
}
else if (strcmp(p, "OFFICE2K7") == 0)
{
options->activationMode = OFFICE_2K7;
} else if (strcmp(p, "PLUSDME") == 0) {
}
else if (strcmp(p, "PLUSDME") == 0)
{
options->activationMode = PLUS_DME;
}
}
i++;
} else if (arg == "-p" || arg == "--productid") {
if (i == argc -1) {
}
else if (arg == "-p" || arg == "--productid")
{
if (i == argc - 1)
{
options->error = true;
break;
}
options->productid = argv[i+1];
}
options->productid = argv[i + 1];
i++;
} else if (arg == "-V" || arg == "--validate") {
if (i == argc - 1) {
}
else if (arg == "-V" || arg == "--validate")
{
if (i == argc - 1)
{
options->error = true;
break;
}
options->keyToCheck = argv[i+1];
options->keyToCheck = argv[i + 1];
options->applicationMode = MODE_BINK1998_VALIDATE;
i++;
} else if (arg == "-N" || arg == "--nonewlines") {
options->nonewlines = true;
} else {
}
else if (arg == "-N" || arg == "--nonewlines")
{
options->nonewlines = true;
}
else
{
options->error = true;
}
}
// make sure that a product id is entered for OFFICE_2K3 or OFFICE_2K7 IIDs
if ((options->activationMode == OFFICE_2K3 || options->activationMode == OFFICE_2K7) && (options->productid.empty() || options->instid.empty()) ) {
if ((options->activationMode == OFFICE_2K3 || options->activationMode == OFFICE_2K7) &&
(options->productid.empty() || options->instid.empty()))
{
return options->error = true;
}
return !options->error;
}
int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
if (options->help || options->error) {
if (options->error) {
int CLI::validateCommandLine(Options *options, char *argv[], json *keys)
{
if (options->help || options->error)
{
if (options->error)
{
fmt::print("error parsing command line options\n");
}
showHelp(argv);
return 1;
}
if (options->verbose) {
if(options->keysFilename.empty()) {
if (options->verbose)
{
if (options->keysFilename.empty())
{
fmt::print("Loading internal keys file\n");
} else {
}
else
{
fmt::print("Loading keys file {}\n", options->keysFilename);
}
}
if (!loadJSON(options->keysFilename, keys)) {
if (!loadJSON(options->keysFilename, keys))
{
return 2;
}
if (options->verbose) {
if(options->keysFilename.empty()) {
if (options->verbose)
{
if (options->keysFilename.empty())
{
fmt::print("Loaded internal keys file successfully\n");
} else {
fmt::print("Loaded keys from {} successfully\n",options->keysFilename);
}
else
{
fmt::print("Loaded keys from {} successfully\n", options->keysFilename);
}
}
if (options->list) {
for (auto const el : (*keys)["Products"].items()) {
if (options->list)
{
for (auto const el : (*keys)["Products"].items())
{
int id;
sscanf((el.value()["BINK"][0]).get<std::string>().c_str(), "%x", &id);
std::cout << el.key() << ": " << el.value()["BINK"] << std::endl;
@ -269,23 +333,28 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
sscanf(options->binkid.c_str(), "%x", &intBinkID);
// FE and FF are BINK 1998, but do not generate valid keys, so we throw an error
if (intBinkID >= 0xFE) {
if (intBinkID >= 0xFE)
{
fmt::print("ERROR: Terminal Services BINKs (FE and FF) are unsupported at this time\n");
return 1;
}
if (intBinkID >= 0x40) {
if (intBinkID >= 0x40)
{
// set bink2002 validate mode if in bink1998 validate mode, else set bink2002 generate mode
options->applicationMode = (options->applicationMode == MODE_BINK1998_VALIDATE) ? MODE_BINK2002_VALIDATE : MODE_BINK2002_GENERATE;
options->applicationMode =
(options->applicationMode == MODE_BINK1998_VALIDATE) ? MODE_BINK2002_VALIDATE : MODE_BINK2002_GENERATE;
}
if (options->channelID > 999) {
if (options->channelID > 999)
{
fmt::print("ERROR: refusing to create a key with a Channel ID greater than 999\n");
return 1;
}
// don't allow any serial not between 0 and 999999
if (options->serial > 999999 || options->serial < 0) {
if (options->serial > 999999 || options->serial < 0)
{
fmt::print("ERROR: refusing to create a key with a Serial not between 000000 and 999999\n");
return 1;
}
@ -293,7 +362,8 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
return 0;
}
void CLI::printID(DWORD *pid) {
void CLI::printID(DWORD *pid)
{
char raw[12];
char b[6], c[8];
int i, digit = 0;
@ -311,42 +381,51 @@ void CLI::printID(DWORD *pid) {
// Make checksum digit-part {...56X-}
assert(strlen(c) == 6);
for (i = 0; i < 6; i++)
digit -= c[i] - '0'; // Sum digits
{
digit -= c[i] - '0'; // Sum digits
}
while (digit < 0)
{
digit += 7;
}
c[6] = digit + '0';
c[7] = 0;
fmt::print("> Product ID: PPPPP-{}-{}-23xxx\n", b, c);
}
void CLI::printKey(char *pk) {
void CLI::printKey(char *pk)
{
assert(strlen(pk) >= PK_LENGTH);
std::string spk = pk;
fmt::print("{}-{}-{}-{}-{}",
spk.substr(0,5),
spk.substr(5,5),
spk.substr(10,5),
spk.substr(15,5),
spk.substr(20,5));
fmt::print("{}-{}-{}-{}-{}", spk.substr(0, 5), spk.substr(5, 5), spk.substr(10, 5), spk.substr(15, 5),
spk.substr(20, 5));
}
bool CLI::stripKey(const char *in_key, char out_key[PK_LENGTH]) {
bool CLI::stripKey(const char *in_key, char out_key[PK_LENGTH])
{
// copy out the product key stripping out extraneous characters
const char *p = in_key;
size_t i = 0;
for (; *p; p++) {
for (; *p; p++)
{
// strip out space or dash
if (*p == ' ' || *p == '-')
continue;
if (*p == ' ' || *p == '-')
{
continue;
}
// check if we've passed the product key length to avoid overflow
if (i >= PK_LENGTH)
{
return false;
}
// convert to uppercase - if character allowed, copy into array
for (int j = 0; j < strlen(PIDGEN3::pKeyCharset); j++) {
if (toupper(*p) == PIDGEN3::pKeyCharset[j]) {
for (int j = 0; j < strlen(PIDGEN3::pKeyCharset); j++)
{
if (toupper(*p) == PIDGEN3::pKeyCharset[j])
{
out_key[i++] = toupper(*p);
continue;
}
@ -356,7 +435,8 @@ bool CLI::stripKey(const char *in_key, char out_key[PK_LENGTH]) {
return (i == PK_LENGTH);
}
CLI::CLI(Options options, json keys) {
CLI::CLI(Options options, json keys)
{
this->options = options;
this->keys = keys;
@ -371,10 +451,11 @@ CLI::CLI(Options options, json keys) {
this->genOrder = BN_new();
/* Computed data */
BN_dec2bn(&this->genOrder, this->keys["BINK"][this->BINKID]["n"]. get<std::string>().c_str());
BN_dec2bn(&this->genOrder, this->keys["BINK"][this->BINKID]["n"].get<std::string>().c_str());
BN_dec2bn(&this->privateKey, this->keys["BINK"][this->BINKID]["priv"].get<std::string>().c_str());
if (options.verbose) {
if (options.verbose)
{
fmt::print("----------------------------------------------------------- \n");
fmt::print("Loaded the following elliptic curve parameters: BINK[{}]\n", this->BINKID);
fmt::print("----------------------------------------------------------- \n");
@ -390,33 +471,33 @@ CLI::CLI(Options options, json keys) {
fmt::print("\n");
}
eCurve = PIDGEN3::initializeEllipticCurve(
this->keys["BINK"][this->BINKID]["p"].get<std::string>(),
this->keys["BINK"][this->BINKID]["a"].get<std::string>(),
this->keys["BINK"][this->BINKID]["b"].get<std::string>(),
this->keys["BINK"][this->BINKID]["g"]["x"].get<std::string>(),
this->keys["BINK"][this->BINKID]["g"]["y"].get<std::string>(),
this->keys["BINK"][this->BINKID]["pub"]["x"].get<std::string>(),
this->keys["BINK"][this->BINKID]["pub"]["y"].get<std::string>(),
this->genPoint,
this->pubPoint
);
eCurve = PIDGEN3::initializeEllipticCurve(this->keys["BINK"][this->BINKID]["p"].get<std::string>(),
this->keys["BINK"][this->BINKID]["a"].get<std::string>(),
this->keys["BINK"][this->BINKID]["b"].get<std::string>(),
this->keys["BINK"][this->BINKID]["g"]["x"].get<std::string>(),
this->keys["BINK"][this->BINKID]["g"]["y"].get<std::string>(),
this->keys["BINK"][this->BINKID]["pub"]["x"].get<std::string>(),
this->keys["BINK"][this->BINKID]["pub"]["y"].get<std::string>(),
this->genPoint, this->pubPoint);
this->count = 0;
this->total = this->options.numKeys;
}
int CLI::BINK1998Generate() {
int CLI::BINK1998Generate()
{
// raw PID/serial value
DWORD nRaw = this->options.channelID * 1'000'000 ; /* <- change */
DWORD nRaw = this->options.channelID * 1'000'000; /* <- change */
// using user-provided serial
if (this->options.serialSet) {
if (this->options.serialSet)
{
// just in case, make sure it's less than 999999
int serialRnd = (this->options.serial % 999999);
nRaw += serialRnd;
} else {
}
else
{
// generate a random number to use as a serial
BIGNUM *bnrand = BN_new();
BN_rand(bnrand, 19, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY);
@ -426,10 +507,11 @@ int CLI::BINK1998Generate() {
sscanf(cRaw, "%d", &oRaw);
nRaw += (oRaw % 999999); // ensure our serial is less than 999999
BN_free(bnrand);
BN_free(bnrand);
}
if (this->options.verbose) {
if (this->options.verbose)
{
// print the resulting Product ID
// PID value is printed in BINK1998::Generate
printID(&nRaw);
@ -438,22 +520,29 @@ int CLI::BINK1998Generate() {
// generate a key
BN_sub(this->privateKey, this->genOrder, this->privateKey);
for (int i = 0; i < this->total; i++) {
PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw, options.upgrade, this->pKey);
for (int i = 0; i < this->total; i++)
{
PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw,
options.upgrade, this->pKey);
bool isValid = PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey);
if (isValid) {
if (isValid)
{
CLI::printKey(this->pKey);
if (i < this->total - 1 || this->options.verbose) {
if (i < this->total - 1 || this->options.verbose)
{
fmt::print("\n");
}
this->count += isValid;
}
else {
if (this->options.verbose) {
else
{
if (this->options.verbose)
{
CLI::printKey(this->pKey);
fmt::print(" [Invalid]");
if (i < this->total - 1) {
if (i < this->total - 1)
{
fmt::print("\n");
}
}
@ -461,49 +550,61 @@ int CLI::BINK1998Generate() {
}
}
if (this->options.verbose) {
if (this->options.verbose)
{
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
}
if (!options.nonewlines) {
fmt::print("\n");
if (!options.nonewlines)
{
fmt::print("\n");
}
return 0;
}
int CLI::BINK2002Generate() {
int CLI::BINK2002Generate()
{
DWORD pChannelID = this->options.channelID;
if (this->options.verbose) {
if (this->options.verbose)
{
fmt::print("> Channel ID: {:03d}\n", this->options.channelID);
}
// generate a key
for (int i = 0; i < this->total; i++) {
for (int i = 0; i < this->total; i++)
{
DWORD pAuthInfo;
RAND_bytes((BYTE *)&pAuthInfo, 4);
pAuthInfo &= BITMASK(10);
if (this->options.verbose) {
if (this->options.verbose)
{
fmt::print("> AuthInfo: {}\n", pAuthInfo);
}
PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, options.upgrade, this->pKey);
PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID,
pAuthInfo, options.upgrade, this->pKey);
bool isValid = PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey);
if (isValid) {
if (isValid)
{
CLI::printKey(this->pKey);
if (i < this->total - 1 || this->options.verbose) { // check if end of list or verbose
if (i < this->total - 1 || this->options.verbose)
{ // check if end of list or verbose
fmt::print("\n");
}
this->count += isValid; // add to count
}
else {
if (this->options.verbose) {
else
{
if (this->options.verbose)
{
CLI::printKey(this->pKey); // print the key
fmt::print(" [Invalid]"); // and add " [Invalid]" to the key
if (i < this->total - 1) { // check if end of list
fmt::print(" [Invalid]"); // and add " [Invalid]" to the key
if (i < this->total - 1)
{ // check if end of list
fmt::print("\n");
}
}
@ -511,28 +612,33 @@ int CLI::BINK2002Generate() {
}
}
if (this->options.verbose) {
if (this->options.verbose)
{
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
}
if (!this->options.nonewlines) {
fmt::print("\n");
if (!this->options.nonewlines)
{
fmt::print("\n");
}
return 0;
}
int CLI::BINK1998Validate() {
int CLI::BINK1998Validate()
{
char product_key[PK_LENGTH]{};
if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key)) {
if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key))
{
fmt::print("ERROR: Product key is in an incorrect format!\n");
return 1;
}
CLI::printKey(product_key);
fmt::print("\n");
if (!PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key)) {
if (!PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key))
{
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
return 1;
}
@ -541,17 +647,20 @@ int CLI::BINK1998Validate() {
return 0;
}
int CLI::BINK2002Validate() {
int CLI::BINK2002Validate()
{
char product_key[PK_LENGTH]{};
if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key)) {
if (!CLI::stripKey(this->options.keyToCheck.c_str(), product_key))
{
fmt::print("ERROR: Product key is in an incorrect format!\n");
return 1;
}
CLI::printKey(product_key);
fmt::print("\n");
if (!PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key)) {
if (!PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, product_key))
{
fmt::print("ERROR: Product key is invalid! Wrong BINK ID?\n");
return 1;
}
@ -560,46 +669,45 @@ int CLI::BINK2002Validate() {
return 0;
}
int CLI::ConfirmationID() {
int CLI::ConfirmationID()
{
char confirmation_id[49];
int err = ConfirmationID::Generate(this->options.instid.c_str(), confirmation_id, options.activationMode, options.productid);
switch (err) {
case ERR_TOO_SHORT:
fmt::print("ERROR: Installation ID is too short.\n");
return 1;
auto confid = new class ConfirmationID();
int err = confid->Generate(this->options.instid.c_str(), confirmation_id, options.productid);
case ERR_TOO_LARGE:
fmt::print("ERROR: Installation ID is too long.\n");
return 1;
if (err == SUCCESS)
{
fmt::print(confirmation_id);
if (!this->options.nonewlines)
{
fmt::print("\n");
}
return 0;
}
case ERR_INVALID_CHARACTER:
fmt::print("ERROR: Invalid character in installation ID.\n");
return 1;
switch (err)
{
case ERR_TOO_SHORT:
fmt::print("ERROR: Installation ID is too short.\n");
case ERR_INVALID_CHECK_DIGIT:
fmt::print("ERROR: Installation ID checksum failed. Please check that it is typed correctly.\n");
return 1;
case ERR_TOO_LARGE:
fmt::print("ERROR: Installation ID is too long.\n");
case ERR_UNKNOWN_VERSION:
fmt::print("ERROR: Unknown installation ID version.\n");
return 1;
case ERR_INVALID_CHARACTER:
fmt::print("ERROR: Invalid character in installation ID.\n");
case ERR_UNLUCKY:
fmt::print("ERROR: Unable to generate valid confirmation ID.\n");
return 1;
case ERR_INVALID_CHECK_DIGIT:
fmt::print("ERROR: Installation ID checksum failed. Please check that it is typed correctly.\n");
case SUCCESS:
fmt::print(confirmation_id);
if (!this->options.nonewlines) {
fmt::print("\n");
}
return 0;
case ERR_UNKNOWN_VERSION:
fmt::print("ERROR: Unknown installation ID version.\n");
default:
fmt::print("Unknown error occurred during Confirmation ID generation: {}\n", err);
case ERR_UNLUCKY:
fmt::print("ERROR: Unable to generate valid confirmation ID.\n");
default:
fmt::print("Unknown error occurred during Confirmation ID generation: {}\n", err);
}
return 1;
}

View File

@ -27,24 +27,26 @@
#include <cmrc/cmrc.hpp>
#include "libumskt/confid/confid.h"
#include "libumskt/libumskt.h"
#include "libumskt/pidgen2/PIDGEN2.h"
#include "libumskt/pidgen3/PIDGEN3.h"
#include "libumskt/pidgen3/BINK1998.h"
#include "libumskt/pidgen3/BINK2002.h"
#include "libumskt/confid/confid.h"
#include "libumskt/pidgen3/PIDGEN3.h"
CMRC_DECLARE(umskt);
enum MODE {
enum MODE
{
MODE_BINK1998_GENERATE = 0,
MODE_BINK2002_GENERATE = 1,
MODE_CONFIRMATION_ID = 2,
MODE_CONFIRMATION_ID = 2,
MODE_BINK1998_VALIDATE = 3,
MODE_BINK2002_VALIDATE = 4,
};
struct Options {
struct Options
{
std::string binkid;
std::string keysFilename;
std::string instid;
@ -65,24 +67,25 @@ struct Options {
ACTIVATION_ALGORITHM activationMode;
};
class CLI {
class CLI
{
Options options;
json keys;
const char* BINKID;
const char *BINKID;
BIGNUM *privateKey, *genOrder;
EC_POINT *genPoint, *pubPoint;
EC_GROUP *eCurve;
char pKey[25];
int count, total;
public:
public:
CLI(Options options, json keys);
~CLI();
static bool loadJSON(const fs::path& filename, json *output);
static bool loadJSON(const fs::path &filename, json *output);
static void showHelp(char *argv[]);
static int parseCommandLine(int argc, char* argv[], Options *options);
static int validateCommandLine(Options* options, char *argv[], json *keys);
static int parseCommandLine(int argc, char *argv[], Options *options);
static int validateCommandLine(Options *options, char *argv[], json *keys);
static void printID(DWORD *pid);
static void printKey(char *pk);
static bool stripKey(const char *in_key, char out_key[PK_LENGTH]);
@ -94,4 +97,4 @@ public:
int ConfirmationID();
};
#endif //UMSKT_CLI_H
#endif // UMSKT_CLI_H

View File

@ -25,12 +25,12 @@
#include "typedefs.h"
#include <iostream>
#include <fstream>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <vector>
#include <fmt/core.h>
#include <nlohmann/json.hpp>
@ -38,4 +38,4 @@
using json = nlohmann::json;
namespace fs = std::filesystem;
#endif //UMSKT_HEADER_H
#endif // UMSKT_HEADER_H

View File

@ -82,19 +82,18 @@ void ConfirmationID::setFlagVersion(unsigned int flagVersion)
ConfirmationID::flagVersion = flagVersion;
}
int ConfirmationID::calculateCheckDigit(int pid)
{
unsigned int i = 0, j = 0, k = 0;
for (j = pid; j; i += k)
{
k = j % 10;
j /= 10;
}
return ((10 * pid) - (i % 7)) + 7;
unsigned int i = 0, j = 0, k = 0;
for (j = pid; j; i += k)
{
k = j % 10;
j /= 10;
}
return ((10 * pid) - (i % 7)) + 7;
}
void ConfirmationID::decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version)
void ConfirmationID::decode_iid_new_version(unsigned char *iid, unsigned char *hwid, int *version)
{
QWORD buffer[5];
for (int i = 0; i < 5; i++)
@ -113,15 +112,15 @@ void ConfirmationID::decode_iid_new_version(unsigned char* iid, unsigned char* h
*version = buffer[0] & 7;
}
void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize)
void ConfirmationID::Mix(unsigned char *buffer, size_t bufSize, const unsigned char *key, size_t keySize)
{
unsigned char sha1_input[64], sha1_result[20];
size_t half = bufSize / 2;
unsigned char sha1_input[64], sha1_result[20];
size_t half = bufSize / 2;
//assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
for (int external_counter = 0; external_counter < 4; external_counter++)
// assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
for (int external_counter = 0; external_counter < 4; external_counter++)
{
memset(sha1_input, 0, sizeof(sha1_input));
memset(sha1_input, 0, sizeof(sha1_input));
if (isXPBrand)
{
@ -145,30 +144,30 @@ void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned c
SHA1(sha1_input, sizeof(sha1_input), sha1_result);
for (size_t i = half & ~3; i < half; i++)
for (size_t i = half & ~3; i < half; i++)
{
sha1_result[i] = sha1_result[i + 4 - (half & 3)];
}
for (size_t i = 0; i < half; i++)
for (size_t i = 0; i < half; i++)
{
unsigned char tmp = buffer[i + half];
buffer[i + half] = buffer[i] ^ sha1_result[i];
buffer[i] = tmp;
}
}
unsigned char tmp = buffer[i + half];
buffer[i + half] = buffer[i] ^ sha1_result[i];
buffer[i] = tmp;
}
}
}
void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned char key[4], size_t keySize)
void ConfirmationID::Unmix(unsigned char *buffer, size_t bufSize, const unsigned char key[4], size_t keySize)
{
unsigned char sha1_input[64];
unsigned char sha1_result[20];
size_t half = bufSize / 2;
//assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
unsigned char sha1_input[64];
unsigned char sha1_result[20];
size_t half = bufSize / 2;
// assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9);
for (int external_counter = 0; external_counter < 4; external_counter++)
for (int external_counter = 0; external_counter < 4; external_counter++)
{
memset(sha1_input, 0, sizeof(sha1_input));
memset(sha1_input, 0, sizeof(sha1_input));
if (isXPBrand)
{
@ -188,116 +187,117 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned
sha1_input[sizeof(sha1_input) - 2] = (1 + half + keySize) * 8 / 0x100;
}
SHA1(sha1_input, sizeof(sha1_input), sha1_result);
SHA1(sha1_input, sizeof(sha1_input), sha1_result);
for (size_t i = half & ~3; i < half; i++)
for (size_t i = half & ~3; i < half; i++)
{
sha1_result[i] = sha1_result[i + 4 - (half & 3)];
}
for (size_t i = 0; i < half; i++)
for (size_t i = 0; i < half; i++)
{
unsigned char tmp = buffer[i];
buffer[i] = buffer[i + half] ^ sha1_result[i];
buffer[i + half] = tmp;
}
}
unsigned char tmp = buffer[i];
buffer[i] = buffer[i + half] ^ sha1_result[i];
buffer[i + half] = tmp;
}
}
}
int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49], std::string productid)
int ConfirmationID::Generate(const char *installation_id_str, char confirmation_id[49], std::string productid)
{
int version;
unsigned char hardwareID[8];
unsigned char installation_id[19]; // 10**45 < 256**19
int version;
unsigned char hardwareID[8];
unsigned char installation_id[19]; // 10**45 < 256**19
unsigned char productID[4];
size_t installation_id_len = 0;
const char* pid = installation_id_str;
size_t installation_id_len = 0;
const char *pid = installation_id_str;
size_t count = 0, totalCount = 0;
unsigned check = 0;
size_t count = 0, totalCount = 0;
unsigned check = 0;
size_t i;
size_t i;
for (; *pid; pid++)
for (; *pid; pid++)
{
if (*pid == ' ' || *pid == '-')
if (*pid == ' ' || *pid == '-')
{
continue;
}
int d = *pid - '0';
int d = *pid - '0';
if (d < 0 || d > 9)
if (d < 0 || d > 9)
{
return ERR_INVALID_CHARACTER;
}
if (count == 5 || p[1] == 0)
if (count == 5 || p[1] == 0)
{
if (!count)
if (!count)
{
return (totalCount == 45) ? ERR_TOO_LARGE : ERR_TOO_SHORT;
}
if (d != check % 7)
if (d != check % 7)
{
return (count < 5) ? ERR_TOO_SHORT : ERR_INVALID_CHECK_DIGIT;
}
check = 0;
count = 0;
continue;
}
check = 0;
count = 0;
continue;
}
check += (count % 2 ? d * 2 : d);
count++;
check += (count % 2 ? d * 2 : d);
count++;
totalCount++;
if (totalCount > 45)
totalCount++;
if (totalCount > 45)
{
return ERR_TOO_LARGE;
}
unsigned char carry = d;
for (i = 0; i < installation_id_len; i++)
unsigned char carry = d;
for (i = 0; i < installation_id_len; i++)
{
unsigned x = installation_id[i] * 10 + carry;
installation_id[i] = x & 0xFF;
carry = x >> 8;
}
unsigned x = installation_id[i] * 10 + carry;
installation_id[i] = x & 0xFF;
carry = x >> 8;
}
if (carry)
if (carry)
{
assert(installation_id_len < sizeof(installation_id));
installation_id[installation_id_len++] = carry;
}
}
assert(installation_id_len < sizeof(installation_id));
installation_id[installation_id_len++] = carry;
}
}
if (totalCount != 41 && totalCount < 45)
if (totalCount != 41 && totalCount < 45)
{
return ERR_TOO_SHORT;
}
for (; installation_id_len < sizeof(installation_id); installation_id_len++)
for (; installation_id_len < sizeof(installation_id); installation_id_len++)
{
installation_id[installation_id_len] = 0;
}
Unmix(installation_id, totalCount == 41 ? 17 : 19, iid_key, 4);
Unmix(installation_id, totalCount == 41 ? 17 : 19, iid_key, 4);
if (installation_id[18] >= 0x10)
if (installation_id[18] >= 0x10)
{
return ERR_UNKNOWN_VERSION;
}
#pragma pack(push, 1)
struct {
QWORD HardwareID;
QWORD ProductIDLow;
unsigned char ProductIDHigh;
unsigned short KeySHA1;
} parsed;
struct
{
QWORD HardwareID;
QWORD ProductIDLow;
unsigned char ProductIDHigh;
unsigned short KeySHA1;
} parsed;
#pragma pack(pop)
if (isXPBrand)
@ -306,7 +306,7 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
productID[0] = parsed.ProductIDLow & ((1 << 17) - 1);
productID[1] = (parsed.ProductIDLow >> 17) & ((1 << 10) - 1);
productID[2] = (parsed.ProductIDLow >> 27) & ((1 << 24) - 1);
version = (parsed.ProductIDLow >> 51) & 15;
version = (parsed.ProductIDLow >> 51) & 15;
productID[3] = (parsed.ProductIDLow >> 55) | (parsed.ProductIDHigh << 9);
if (flagVersion == 0)
@ -331,9 +331,9 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
}
memcpy(&parsed, hardwareID, 8);
productID[0] = stoi(productid.substr(0,5));
productID[0] = stoi(productid.substr(0, 5));
std::string channelid = productid.substr(6,3);
std::string channelid = productid.substr(6, 3);
char *p = &channelid[0];
for (; *p; p++)
{
@ -342,38 +342,40 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
if (strcmp(&channelid[0], "OEM") == 0)
{
productID[1] = stoi(productid.substr(12,3));
productID[2] = (stoi(productid.substr(15,1)) * 100000) + stoi(productid.substr(18,5));
productID[1] = stoi(productid.substr(12, 3));
productID[2] = (stoi(productid.substr(15, 1)) * 100000) + stoi(productid.substr(18, 5));
productID[2] = calculateCheckDigit(productID[2]);
productID[3] = ((stoi(productid.substr(10,2))) * 1000) + productID[3];
productID[3] = ((stoi(productid.substr(10, 2))) * 1000) + productID[3];
}
else
{
productID[1] = stoi(productid.substr(6,3));
productID[2] = stoi(productid.substr(10,7));
productID[3] = stoi(productid.substr(18,5));
productID[1] = stoi(productid.substr(6, 3));
productID[2] = stoi(productid.substr(10, 7));
productID[3] = stoi(productid.substr(18, 5));
}
//fmt::print("ProductID: {}-{}-{}-{} \n", productID[0], productID[1], productID[2], productID[3]);
// fmt::print("ProductID: {}-{}-{}-{} \n", productID[0], productID[1], productID[2], productID[3]);
}
unsigned char keybuf[16];
memcpy(keybuf, &parsed.HardwareID, 8);
unsigned char keybuf[16];
memcpy(keybuf, &parsed.HardwareID, 8);
QWORD productIdMixed = (QWORD)productID[0] << 41 | (QWORD)productID[1] << 58 | (QWORD)productID[2] << 17 | productID[3];
memcpy(keybuf + 8, &productIdMixed, 8);
QWORD productIdMixed =
(QWORD)productID[0] << 41 | (QWORD)productID[1] << 58 | (QWORD)productID[2] << 17 | productID[3];
memcpy(keybuf + 8, &productIdMixed, 8);
TDivisor d;
unsigned char attempt;
TDivisor d;
unsigned char attempt;
union {
unsigned char buffer[14];
struct {
struct
{
QWORD lo;
QWORD hi;
};
} ulowhi;
for (attempt = 0; attempt <= 0x80; attempt++)
for (attempt = 0; attempt <= 0x80; attempt++)
{
ulowhi.lo = this->u[0];
ulowhi.hi = this->u[1];
@ -387,122 +389,123 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
ulowhi.buffer[6] = attempt;
}
Mix(ulowhi.buffer, 14, keybuf, 16);
QWORD x2 = residue->ui128_quotient_mod(ulowhi.lo, ulowhi.hi);
QWORD x1 = ulowhi.lo - x2 * MOD;
x2++;
Mix(ulowhi.buffer, 14, keybuf, 16);
QWORD x2 = residue->ui128_quotient_mod(ulowhi.lo, ulowhi.hi);
QWORD x1 = ulowhi.lo - x2 * MOD;
x2++;
d.u[0] = residue->sub(residue->mul(x1, x1), residue->mul(NON_RESIDUE, residue->mul(x2, x2)));
d.u[1] = residue->add(x1, x1);
if (divisor->find_divisor_v(&d))
d.u[0] = residue->sub(residue->mul(x1, x1), residue->mul(NON_RESIDUE, residue->mul(x2, x2)));
d.u[1] = residue->add(x1, x1);
if (divisor->find_divisor_v(&d))
{
break;
}
}
}
if (attempt > 0x80)
if (attempt > 0x80)
{
return ERR_UNLUCKY;
}
divisor->mul128(&d, u[0], u[1], &d);
union {
struct {
QWORD encoded_lo, encoded_hi;
};
struct {
uint32_t encoded[4];
};
} e;
union {
struct
{
QWORD encoded_lo, encoded_hi;
};
struct
{
uint32_t encoded[4];
};
} e;
if (d.u[0] == BAD)
if (d.u[0] == BAD)
{
// we can not get the zero divisor, actually...
e.encoded_lo = residue->__umul128(MOD + 2, MOD, &e.encoded_hi);
}
// we can not get the zero divisor, actually...
e.encoded_lo = residue->__umul128(MOD + 2, MOD, &e.encoded_hi);
}
else if (d.u[1] == BAD)
{
// O(1/MOD) chance
//encoded = (unsigned __int128)(MOD + 1) * d.u[0] + MOD; // * MOD + d.u[0] is fine too
e.encoded_lo = residue->__umul128(MOD + 1, d.u[0], &e.encoded_hi);
e.encoded_lo += MOD;
e.encoded_hi += (e.encoded_lo < MOD);
}
// O(1/MOD) chance
// encoded = (unsigned __int128)(MOD + 1) * d.u[0] + MOD; // * MOD + d.u[0] is fine too
e.encoded_lo = residue->__umul128(MOD + 1, d.u[0], &e.encoded_hi);
e.encoded_lo += MOD;
e.encoded_hi += (e.encoded_lo < MOD);
}
else
{
QWORD x1 = (d.u[1] % 2 ? d.u[1] + MOD : d.u[1]) / 2;
QWORD x2sqr = residue->sub(residue->mul(x1, x1), d.u[0]);
QWORD x2 = residue->sqrt(x2sqr);
QWORD x1 = (d.u[1] % 2 ? d.u[1] + MOD : d.u[1]) / 2;
QWORD x2sqr = residue->sub(residue->mul(x1, x1), d.u[0]);
QWORD x2 = residue->sqrt(x2sqr);
if (x2 == BAD)
{
x2 = residue->sqrt(residue->mul(x2sqr, residue->inv(NON_RESIDUE)));
assert(x2 != BAD);
e.encoded_lo = residue->__umul128(MOD + 1, MOD + x2, &e.encoded_hi);
e.encoded_lo += x1;
e.encoded_hi += (e.encoded_lo < x1);
}
x2 = residue->sqrt(residue->mul(x2sqr, residue->inv(NON_RESIDUE)));
assert(x2 != BAD);
e.encoded_lo = residue->__umul128(MOD + 1, MOD + x2, &e.encoded_hi);
e.encoded_lo += x1;
e.encoded_hi += (e.encoded_lo < x1);
}
else
{
// points (-x1+x2, v(-x1+x2)) and (-x1-x2, v(-x1-x2))
QWORD x1a = residue->sub(x1, x2);
QWORD y1 = residue->sub(d.v[0], residue->mul(d.v[1], x1a));
QWORD x2a = residue->add(x1, x2);
QWORD y2 = residue->sub(d.v[0], residue->mul(d.v[1], x2a));
if (x1a > x2a)
// points (-x1+x2, v(-x1+x2)) and (-x1-x2, v(-x1-x2))
QWORD x1a = residue->sub(x1, x2);
QWORD y1 = residue->sub(d.v[0], residue->mul(d.v[1], x1a));
QWORD x2a = residue->add(x1, x2);
QWORD y2 = residue->sub(d.v[0], residue->mul(d.v[1], x2a));
if (x1a > x2a)
{
QWORD tmp = x1a;
x1a = x2a;
x2a = tmp;
}
QWORD tmp = x1a;
x1a = x2a;
x2a = tmp;
}
if ((y1 ^ y2) & 1)
{
QWORD tmp = x1a;
x1a = x2a;
x2a = tmp;
}
QWORD tmp = x1a;
x1a = x2a;
x2a = tmp;
}
e.encoded_lo = residue->__umul128(MOD + 1, x1a, &e.encoded_hi);
e.encoded_lo += x2a;
e.encoded_hi += (e.encoded_lo < x2a);
e.encoded_lo = residue->__umul128(MOD + 1, x1a, &e.encoded_hi);
e.encoded_lo += x2a;
e.encoded_hi += (e.encoded_lo < x2a);
}
}
}
}
unsigned char decimal[35];
for (i = 0; i < 35; i++)
unsigned char decimal[35];
for (i = 0; i < 35; i++)
{
unsigned c = e.encoded[3] % 10;
e.encoded[3] /= 10;
unsigned c2 = ((QWORD)c << 32 | e.encoded[2]) % 10;
e.encoded[2] = ((QWORD)c << 32 | e.encoded[2]) / 10;
unsigned c3 = ((QWORD)c2 << 32 | e.encoded[1]) % 10;
e.encoded[1] = ((QWORD)c2 << 32 | e.encoded[1]) / 10;
unsigned c4 = ((QWORD)c3 << 32 | e.encoded[0]) % 10;
e.encoded[0] = ((QWORD)c3 << 32 | e.encoded[0]) / 10;
decimal[34 - i] = c4;
}
unsigned c = e.encoded[3] % 10;
e.encoded[3] /= 10;
unsigned c2 = ((QWORD)c << 32 | e.encoded[2]) % 10;
e.encoded[2] = ((QWORD)c << 32 | e.encoded[2]) / 10;
unsigned c3 = ((QWORD)c2 << 32 | e.encoded[1]) % 10;
e.encoded[1] = ((QWORD)c2 << 32 | e.encoded[1]) / 10;
unsigned c4 = ((QWORD)c3 << 32 | e.encoded[0]) % 10;
e.encoded[0] = ((QWORD)c3 << 32 | e.encoded[0]) / 10;
decimal[34 - i] = c4;
}
assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0);
char* q = confirmation_id;
for (i = 0; i < 7; i++)
assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0);
char *q = confirmation_id;
for (i = 0; i < 7; i++)
{
if (i)
if (i)
{
*q++ = '-';
}
unsigned char* p = decimal + i*5;
q[0] = p[0] + '0';
q[1] = p[1] + '0';
q[2] = p[2] + '0';
q[3] = p[3] + '0';
q[4] = p[4] + '0';
q[5] = ((p[0]+p[1]*2+p[2]+p[3]*2+p[4]) % 7) + '0';
q += 6;
}
*q++ = 0;
return 0;
unsigned char *p = decimal + i * 5;
q[0] = p[0] + '0';
q[1] = p[1] + '0';
q[2] = p[2] + '0';
q[3] = p[3] + '0';
q[4] = p[4] + '0';
q[5] = ((p[0] + p[1] * 2 + p[2] + p[3] * 2 + p[4]) % 7) + '0';
q += 6;
}
*q++ = 0;
return 0;
}

View File

@ -26,49 +26,53 @@
#include "../libumskt.h"
// Confirmation ID generator constants
enum CONFIRMATION_ID_STATUS {
SUCCESS = 0,
ERR_TOO_SHORT = 1,
ERR_TOO_LARGE = 2,
ERR_INVALID_CHARACTER = 3,
enum CONFIRMATION_ID_STATUS
{
SUCCESS = 0,
ERR_TOO_SHORT = 1,
ERR_TOO_LARGE = 2,
ERR_INVALID_CHARACTER = 3,
ERR_INVALID_CHECK_DIGIT = 4,
ERR_UNKNOWN_VERSION = 5,
ERR_UNLUCKY = 6
ERR_UNKNOWN_VERSION = 5,
ERR_UNLUCKY = 6
};
#define BAD 0xFFFFFFFFFFFFFFFFull
typedef struct {
typedef struct
{
QWORD u[2];
QWORD v[2];
} TDivisor;
enum ACTIVATION_ALGORITHM {
WINDOWS = 0,
OFFICE_XP = 1,
OFFICE_2K3 = 2,
OFFICE_2K7 = 3,
PLUS_DME = 4,
enum ACTIVATION_ALGORITHM
{
WINDOWS = 0,
OFFICE_XP = 1,
OFFICE_2K3 = 2,
OFFICE_2K7 = 3,
PLUS_DME = 4,
};
EXPORT class ConfirmationID {
EXPORT class ConfirmationID
{
QWORD MOD = 0, NON_RESIDUE = 0;
QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
QWORD p[4] = { 0x0, 0x0, 0x0, 0x0 };
QWORD u[2] = { 0x0, 0x0 };
QWORD f[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
QWORD p[4] = {0x0, 0x0, 0x0, 0x0};
QWORD u[2] = {0x0, 0x0};
unsigned char iid_key[4] = { 0x0, 0x0, 0x0, 0x0};
unsigned char iid_key[4] = {0x0, 0x0, 0x0, 0x0};
BOOL isOffice = false, isXPBrand = false;
unsigned flagVersion = 0;
public:
public:
void setFlagVersion(unsigned int flagVersion);
private:
private:
int calculateCheckDigit(int pid);
void decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version);
void Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
void Unmix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
void decode_iid_new_version(unsigned char *iid, unsigned char *hwid, int *version);
void Mix(unsigned char *buffer, size_t bufSize, const unsigned char *key, size_t keySize);
void Unmix(unsigned char *buffer, size_t bufSize, const unsigned char *key, size_t keySize);
friend class Residue;
Residue *residue;
@ -79,8 +83,8 @@ private:
friend class Divisor;
Divisor *divisor;
public:
int Generate(const char* installation_id_str, char confirmation_id[49], std::string productid);
public:
int Generate(const char *installation_id_str, char confirmation_id[49], std::string productid);
void setMod(QWORD mod);
void setNonResidue(QWORD nonResidue);
@ -91,28 +95,32 @@ public:
void setIsOffice(BOOL isOffice);
void setIsXPBrand(BOOL isXpBrand);
ConfirmationID() {
ConfirmationID()
{
residue = new Residue(this);
polynomial = new Polynomial(this);
divisor = new Divisor(this);
}
~ConfirmationID() {
~ConfirmationID()
{
delete residue, polynomial, divisor;
}
};
class Residue {
class Residue
{
ConfirmationID *parent;
public:
explicit Residue(ConfirmationID *in) {
public:
explicit Residue(ConfirmationID *in)
{
parent = in;
}
QWORD add(QWORD x, QWORD y);
QWORD sub(QWORD x, QWORD y);
QWORD __umul128(QWORD a, QWORD b, QWORD* hi);
QWORD __umul128(QWORD a, QWORD b, QWORD *hi);
QWORD ui128_quotient_mod(QWORD lo, QWORD hi);
QWORD mul(QWORD x, QWORD y);
QWORD pow(QWORD x, QWORD y);
@ -121,33 +129,37 @@ public:
QWORD sqrt(QWORD what);
};
class Polynomial {
class Polynomial
{
ConfirmationID *parent;
public:
explicit Polynomial(ConfirmationID *in) {
public:
explicit Polynomial(ConfirmationID *in)
{
parent = in;
}
int mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg, QWORD result[]);
int div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD* quotient);
void xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int* pgcddeg, QWORD gcd[3], int* pmult1deg, QWORD mult1[3], int* pmult2deg, QWORD mult2[3]);
int u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2]);
int div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD *quotient);
void xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int *pgcddeg, QWORD gcd[3], int *pmult1deg,
QWORD mult1[3], int *pmult2deg, QWORD mult2[3]);
int u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2]);
};
class Divisor {
class Divisor
{
ConfirmationID *parent;
public:
explicit Divisor(ConfirmationID *in) {
public:
explicit Divisor(ConfirmationID *in)
{
parent = in;
}
int find_divisor_v(TDivisor* d);
void add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst);
void mul(const TDivisor* src, QWORD mult, TDivisor* dst);
void mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst);
int find_divisor_v(TDivisor *d);
void add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst);
void mul(const TDivisor *src, QWORD mult, TDivisor *dst);
void mul128(const TDivisor *src, QWORD mult_lo, QWORD mult_hi, TDivisor *dst);
};
#endif //UMSKT_CONFID_H
#endif // UMSKT_CONFID_H

View File

@ -22,7 +22,7 @@
#include "confid.h"
int Divisor::find_divisor_v(TDivisor* d)
int Divisor::find_divisor_v(TDivisor *d)
{
// u | v^2 - f
// u = u0 + u1*x + x^2
@ -36,7 +36,7 @@ int Divisor::find_divisor_v(TDivisor* d)
const QWORD u0 = d->u[0];
const QWORD u1 = d->u[1];
for (int j = 4; j--; )
for (int j = 4; j--;)
{
f2[j] = parent->residue->sub(f2[j], parent->residue->mul(u0, f2[j + 2]));
f2[j + 1] = parent->residue->sub(f2[j + 1], parent->residue->mul(u1, f2[j + 2]));
@ -63,11 +63,12 @@ int Divisor::find_divisor_v(TDivisor* d)
if (f1 == 0)
{
// impossible
//printf("bad f(), double root detected\n");
// printf("bad f(), double root detected\n");
}
return 0;
}
QWORD sqr = parent->residue->mul(parent->residue->mul(f1, f1), parent->residue->inv(parent->residue->add(coeff1, coeff1)));
QWORD sqr = parent->residue->mul(parent->residue->mul(f1, f1),
parent->residue->inv(parent->residue->add(coeff1, coeff1)));
v1 = parent->residue->sqrt(sqr);
if (v1 == BAD)
{
@ -76,7 +77,9 @@ int Divisor::find_divisor_v(TDivisor* d)
}
else
{
QWORD d = parent->residue->add(parent->residue->mul(f0, f0), parent->residue->mul(f1, parent->residue->sub(parent->residue->mul(f1, u0), parent->residue->mul(f0, u1))));
QWORD d = parent->residue->add(
parent->residue->mul(f0, f0),
parent->residue->mul(f1, parent->residue->sub(parent->residue->mul(f1, u0), parent->residue->mul(f0, u1))));
d = parent->residue->sqrt(d);
if (d == BAD)
{
@ -98,14 +101,15 @@ int Divisor::find_divisor_v(TDivisor* d)
}
}
QWORD v0 = parent->residue->mul(parent->residue->add(f1, parent->residue->mul(u1, parent->residue->mul(v1, v1))), parent->residue->inv(parent->residue->add(v1, v1)));
QWORD v0 = parent->residue->mul(parent->residue->add(f1, parent->residue->mul(u1, parent->residue->mul(v1, v1))),
parent->residue->inv(parent->residue->add(v1, v1)));
d->v[0] = v0;
d->v[1] = v1;
return 1;
}
int Divisor::u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2])
int Divisor::u2poly(const TDivisor *src, QWORD polyu[3], QWORD polyv[2])
{
if (src->u[1] != BAD)
{
@ -132,7 +136,7 @@ int Divisor::u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2])
return 0;
}
void Divisor::add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst)
void Divisor::add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst)
{
QWORD u1[3], u2[3], v1[2], v2[2];
int u1deg = u2poly(src1, u1, v1);
@ -198,21 +202,25 @@ void Divisor::add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst)
if (ddeg > 0)
{
assert(udeg >= 2*ddeg);
assert(udeg >= 2 * ddeg);
QWORD udiv[5];
parent->polynomial->div_monic(udeg, u, ddeg, d, udiv); udeg -= ddeg;
parent->polynomial->div_monic(udeg, udiv, ddeg, d, u); udeg -= ddeg;
parent->polynomial->div_monic(udeg, u, ddeg, d, udiv);
udeg -= ddeg;
parent->polynomial->div_monic(udeg, udiv, ddeg, d, u);
udeg -= ddeg;
if (vdeg >= 0)
{
assert(vdeg >= ddeg);
parent->polynomial->div_monic(vdeg, v, ddeg, d, udiv); vdeg -= ddeg;
parent->polynomial->div_monic(vdeg, v, ddeg, d, udiv);
vdeg -= ddeg;
memcpy(v, udiv, (vdeg + 1) * sizeof(v[0]));
}
}
vdeg = parent->polynomial->div_monic(vdeg, v, udeg, u, NULL);
while (udeg > 2) {
while (udeg > 2)
{
assert(udeg <= 4);
assert(vdeg <= 3);
// u' = monic((f-v^2)/u), v'=-v mod u'
@ -280,7 +288,7 @@ void Divisor::add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst)
#define divisor_double(src, dst) add(src, src, dst)
void Divisor::mul(const TDivisor* src, QWORD mult, TDivisor* dst)
void Divisor::mul(const TDivisor *src, QWORD mult, TDivisor *dst)
{
if (mult == 0)
{
@ -309,7 +317,7 @@ void Divisor::mul(const TDivisor* src, QWORD mult, TDivisor* dst)
}
}
void Divisor::mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst)
void Divisor::mul128(const TDivisor *src, QWORD mult_lo, QWORD mult_hi, TDivisor *dst)
{
if (mult_lo == 0 && mult_hi == 0)
{
@ -325,7 +333,8 @@ void Divisor::mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor
{
divisor_double(&cur, &cur);
mult_lo >>= 1;
if (mult_hi & 1) {
if (mult_hi & 1)
{
mult_lo |= (1ULL << 63);
}
mult_hi >>= 1;

View File

@ -55,7 +55,7 @@ int Polynomial::mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int re
return resultprevdeg;
}
int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD* quotient)
int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD *quotient)
{
assert(bdeg >= 0);
assert(b[bdeg] == 1);
@ -84,25 +84,32 @@ int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD*
return i;
}
void Polynomial::xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int* pgcddeg, QWORD gcd[3], int* pmult1deg, QWORD mult1[3], int* pmult2deg, QWORD mult2[3])
void Polynomial::xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int *pgcddeg, QWORD gcd[3],
int *pmult1deg, QWORD mult1[3], int *pmult2deg, QWORD mult2[3])
{
int sdeg = -1;
QWORD s[3] = {0, 0, 0};
int mult1deg = 0;
mult1[0] = 1; mult1[1] = 0; mult1[2] = 0;
mult1[0] = 1;
mult1[1] = 0;
mult1[2] = 0;
int tdeg = 0;
QWORD t[3] = {1, 0, 0};
int mult2deg = -1;
mult2[0] = 0; mult2[1] = 0; mult2[2] = 0;
mult2[0] = 0;
mult2[1] = 0;
mult2[2] = 0;
int rdeg = bdeg;
QWORD r[3] = {b[0], b[1], b[2]};
int gcddeg = adeg;
gcd[0] = a[0]; gcd[1] = a[1]; gcd[2] = a[2];
gcd[0] = a[0];
gcd[1] = a[1];
gcd[2] = a[2];
// s*u1 + t*u2 = r
// mult1*u1 + mult2*u2 = gcd
@ -112,19 +119,43 @@ void Polynomial::xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], in
{
unsigned tmp;
int tmpi;
tmp = rdeg; rdeg = gcddeg; gcddeg = tmp;
tmpi = sdeg; sdeg = mult1deg; mult1deg = tmpi;
tmpi = tdeg; tdeg = mult2deg; mult2deg = tmpi;
tmp = rdeg;
rdeg = gcddeg;
gcddeg = tmp;
tmpi = sdeg;
sdeg = mult1deg;
mult1deg = tmpi;
tmpi = tdeg;
tdeg = mult2deg;
mult2deg = tmpi;
QWORD tmp2;
tmp2 = r[0]; r[0] = gcd[0]; gcd[0] = tmp2;
tmp2 = r[1]; r[1] = gcd[1]; gcd[1] = tmp2;
tmp2 = r[2]; r[2] = gcd[2]; gcd[2] = tmp2;
tmp2 = s[0]; s[0] = mult1[0]; mult1[0] = tmp2;
tmp2 = s[1]; s[1] = mult1[1]; mult1[1] = tmp2;
tmp2 = s[2]; s[2] = mult1[2]; mult1[2] = tmp2;
tmp2 = t[0]; t[0] = mult2[0]; mult2[0] = tmp2;
tmp2 = t[1]; t[1] = mult2[1]; mult2[1] = tmp2;
tmp2 = t[2]; t[2] = mult2[2]; mult2[2] = tmp2;
tmp2 = r[0];
r[0] = gcd[0];
gcd[0] = tmp2;
tmp2 = r[1];
r[1] = gcd[1];
gcd[1] = tmp2;
tmp2 = r[2];
r[2] = gcd[2];
gcd[2] = tmp2;
tmp2 = s[0];
s[0] = mult1[0];
mult1[0] = tmp2;
tmp2 = s[1];
s[1] = mult1[1];
mult1[1] = tmp2;
tmp2 = s[2];
s[2] = mult1[2];
mult1[2] = tmp2;
tmp2 = t[0];
t[0] = mult2[0];
mult2[0] = tmp2;
tmp2 = t[1];
t[1] = mult2[1];
mult2[1] = tmp2;
tmp2 = t[2];
t[2] = mult2[2];
mult2[2] = tmp2;
continue;
}

View File

@ -24,11 +24,11 @@
#if defined(__x86_64__) || defined(_M_AMD64) || defined(__aarch64__) || (defined(__arm64__) && defined(__APPLE__))
#ifdef __GNUC__
inline QWORD Residue::__umul128(QWORD a, QWORD b, QWORD* hi)
inline QWORD Residue::__umul128(QWORD a, QWORD b, QWORD *hi)
{
OWORD r = (OWORD)a * (OWORD)b;
*hi = r >> 64;
return (QWORD) r;
return (QWORD)r;
}
#else
#define __umul128 _umul128
@ -44,9 +44,9 @@ inline QWORD Residue::__umul128(QWORD multiplier, QWORD multiplicand, QWORD *pro
QWORD c = multiplicand >> 32;
QWORD d = multiplicand & 0xFFFFFFFF;
//QWORD ac = a * c;
// QWORD ac = a * c;
QWORD ad = a * d;
//QWORD bc = b * c;
// QWORD bc = b * c;
QWORD bd = b * d;
QWORD adbc = ad + (b * c);
@ -91,7 +91,7 @@ QWORD Residue::ui128_quotient_mod(QWORD lo, QWORD hi)
QWORD Residue::mul(QWORD x, QWORD y)
{
// * ceil(2**170/MOD) = 0x2d351 c6d04f8b|604fa6a1 c6346a87 for (p-1)*(p-1) max
// * ceil(2**170/MOD) = 0x2d351 c6d04f8b|604fa6a1 c6346a87 for (p-1)*(p-1) max
QWORD hi;
QWORD lo = __umul128(x, y, &hi);
QWORD quotient = ui128_quotient_mod(lo, hi);
@ -128,7 +128,7 @@ QWORD Residue::pow(QWORD x, QWORD y)
QWORD Residue::add(QWORD x, QWORD y)
{
QWORD z = x + y;
//z = z - (z >= MOD ? MOD : 0);
// z = z - (z >= MOD ? MOD : 0);
if (z >= parent->MOD)
{
z -= parent->MOD;
@ -139,7 +139,7 @@ QWORD Residue::add(QWORD x, QWORD y)
QWORD Residue::sub(QWORD x, QWORD y)
{
QWORD z = x - y;
//z += (x < y ? MOD : 0);
// z += (x < y ? MOD : 0);
if (x < y)
{
z += parent->MOD;
@ -149,15 +149,20 @@ QWORD Residue::sub(QWORD x, QWORD y)
QWORD Residue::inverse(QWORD u, QWORD v)
{
//assert(u);
// assert(u);
int64_t tmp;
int64_t xu = 1, xv = 0;
QWORD v0 = v;
while (u > 1)
{
QWORD d = v / u; QWORD remainder = v % u;
tmp = u; u = remainder; v = tmp;
tmp = xu; xu = xv - d * xu; xv = tmp;
QWORD d = v / u;
QWORD remainder = v % u;
tmp = u;
u = remainder;
v = tmp;
tmp = xu;
xu = xv - d * xu;
xv = tmp;
}
xu += (xu < 0 ? v0 : 0);
return xu;
@ -190,15 +195,15 @@ QWORD Residue::sqrt(QWORD what)
x = pow(what, (q - 1) / 2);
b = mul(mul(what, x), x);
x = mul(what, x);
while (b != 1) {
while (b != 1)
{
QWORD m = 0, b2 = b;
do
{
m++;
b2 = mul(b2, b2);
}
while (b2 != 1);
} while (b2 != 1);
if (m == r)
{
@ -214,7 +219,7 @@ QWORD Residue::sqrt(QWORD what)
if (mul(x, x) != what)
{
//printf("internal error in sqrt\n");
// printf("internal error in sqrt\n");
return BAD;
}

View File

@ -22,14 +22,13 @@
#include "libumskt.h"
#ifdef _WIN32
std::FILE* UMSKT::debug = std::fopen("NUL:", "w");
std::FILE *UMSKT::debug = std::fopen("NUL:", "w");
#else
std::FILE* UMSKT::debug = std::fopen("/dev/null", "w");
std::FILE *UMSKT::debug = std::fopen("/dev/null", "w");
#endif
void UMSKT::setDebugOutput(std::FILE* input) {
void UMSKT::setDebugOutput(std::FILE *input)
{
debug = input;
}

View File

@ -22,39 +22,53 @@
#include "libumskt.h"
#include "confid/confid.h"
#include "pidgen3/PIDGEN3.h"
#include "pidgen2/PIDGEN2.h"
#include "pidgen3/BINK1998.h"
#include "pidgen3/BINK2002.h"
#include "pidgen2/PIDGEN2.h"
#include "pidgen3/PIDGEN3.h"
FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid) {
FNEXPORT int ConfirmationID_Generate(const char *installation_id_str, char confirmation_id[49], int mode,
std::string productid)
{
return ConfirmationID::Generate(installation_id_str, confirmation_id, mode, productid);
}
FNEXPORT EC_GROUP* PIDGEN3_initializeEllipticCurve(char* pSel, char* aSel, char* bSel, char* generatorXSel, char* generatorYSel, char* publicKeyXSel, char* publicKeyYSel, EC_POINT *&genPoint, EC_POINT *&pubPoint) {
return PIDGEN3::initializeEllipticCurve(pSel, aSel, bSel, generatorXSel, generatorYSel, publicKeyXSel, publicKeyYSel, genPoint, pubPoint);
FNEXPORT EC_GROUP *PIDGEN3_initializeEllipticCurve(char *pSel, char *aSel, char *bSel, char *generatorXSel,
char *generatorYSel, char *publicKeyXSel, char *publicKeyYSel,
EC_POINT *&genPoint, EC_POINT *&pubPoint)
{
return PIDGEN3::initializeEllipticCurve(pSel, aSel, bSel, generatorXSel, generatorYSel, publicKeyXSel,
publicKeyYSel, genPoint, pubPoint);
}
FNEXPORT bool PIDGEN3_BINK1998_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25]) {
FNEXPORT bool PIDGEN3_BINK1998_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25])
{
return PIDGEN3::BINK1998::Verify(eCurve, basePoint, publicKey, pKey);
}
FNEXPORT void PIDGEN3_BINK1998_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial, BOOL pUpgrade,char (&pKey)[25]) {
FNEXPORT void PIDGEN3_BINK1998_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
DWORD pSerial, BOOL pUpgrade, char (&pKey)[25])
{
return PIDGEN3::BINK1998::Generate(eCurve, basePoint, genOrder, privateKey, pSerial, pUpgrade, pKey);
}
FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25]) {
FNEXPORT bool PIDGEN3_BINK2002_Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25])
{
return PIDGEN3::BINK2002::Verify(eCurve, basePoint, publicKey, cdKey);
}
FNEXPORT void PIDGEN3_BINK2002_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25]) {
FNEXPORT void PIDGEN3_BINK2002_Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25])
{
return PIDGEN3::BINK2002::Generate(eCurve, basePoint, genOrder, privateKey, pChannelID, pAuthInfo, pUpgrade, pKey);
}
FNEXPORT int PIDGEN2_GenerateRetail(char* channelID, char* &keyout) {
FNEXPORT int PIDGEN2_GenerateRetail(char *channelID, char *&keyout)
{
return PIDGEN2::GenerateRetail(channelID, keyout);
}
FNEXPORT int PIDGEN2_GenerateOEM(char* year, char* day, char* oem, char* keyout) {
FNEXPORT int PIDGEN2_GenerateOEM(char *year, char *day, char *oem, char *keyout)
{
return PIDGEN2::GenerateOEM(year, day, oem, keyout);
}

View File

@ -25,49 +25,49 @@
#include "../typedefs.h"
#include <string>
#include <iostream>
#include <sstream>
#include <string>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <fmt/core.h>
#include <fmt/format.h>
// Algorithm macros
#define PK_LENGTH 25
#define NULL_TERMINATOR 1
#define PK_LENGTH 25
#define NULL_TERMINATOR 1
#define FIELD_BITS 384
#define FIELD_BYTES 48
#define FIELD_BITS_2003 512
#define FIELD_BYTES_2003 64
#define FIELD_BITS 384
#define FIELD_BYTES 48
#define FIELD_BITS_2003 512
#define FIELD_BYTES_2003 64
#define SHA_MSG_LENGTH_XP (4 + 2 * FIELD_BYTES)
#define SHA_MSG_LENGTH_2003 (3 + 2 * FIELD_BYTES_2003)
#define SHA_MSG_LENGTH_XP (4 + 2 * FIELD_BYTES)
#define SHA_MSG_LENGTH_2003 (3 + 2 * FIELD_BYTES_2003)
#define NEXTSNBITS(field, n, offset) (((QWORD)(field) >> (offset)) & ((1ULL << (n)) - 1))
#define FIRSTNBITS(field, n) NEXTSNBITS((field), (n), 0)
#define NEXTSNBITS(field, n, offset) (((QWORD)(field) >> (offset)) & ((1ULL << (n)) - 1))
#define FIRSTNBITS(field, n) NEXTSNBITS((field), (n), 0)
#define HIBYTES(field, bytes) NEXTSNBITS((QWORD)(field), ((bytes) * 8), ((bytes) * 8))
#define LOBYTES(field, bytes) FIRSTNBITS((QWORD)(field), ((bytes) * 8))
#define HIBYTES(field, bytes) NEXTSNBITS((QWORD)(field), ((bytes)*8), ((bytes)*8))
#define LOBYTES(field, bytes) FIRSTNBITS((QWORD)(field), ((bytes)*8))
#define BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24)
#define BITMASK(n) ((1ULL << (n)) - 1)
#define BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24)
#define BITMASK(n) ((1ULL << (n)) - 1)
class UMSKT {
public:
static std::FILE* debug;
class UMSKT
{
public:
static std::FILE *debug;
class PIDGEN2;
class PIDGEN3;
class ConfigurationID;
static void setDebugOutput(std::FILE* input);
static void setDebugOutput(std::FILE *input);
};
#endif //UMSKT_LIBUMSKT_H
#endif // UMSKT_LIBUMSKT_H

View File

@ -22,12 +22,15 @@
#include "PIDGEN2.h"
const char* channelIDBlacklist [7] = {"333", "444", "555", "666", "777", "888", "999"};
const char* validYears[8] = { "95", "96", "97", "98", "99", "00", "01", "02"};
const char *channelIDBlacklist[7] = {"333", "444", "555", "666", "777", "888", "999"};
const char *validYears[8] = {"95", "96", "97", "98", "99", "00", "01", "02"};
bool PIDGEN2::isNumericString(char* input) {
for(int i = 0; i < strlen(input); i++) {
if (input[i] < '0' || input[i] > '9') {
bool PIDGEN2::isNumericString(char *input)
{
for (int i = 0; i < strlen(input); i++)
{
if (input[i] < '0' || input[i] > '9')
{
return false;
}
}
@ -35,27 +38,34 @@ bool PIDGEN2::isNumericString(char* input) {
return true;
}
int PIDGEN2::addDigits(char* input) {
int PIDGEN2::addDigits(char *input)
{
int output = 0;
if (!isNumericString(input)) {
if (!isNumericString(input))
{
return -1;
}
for(int i = 0; i < strlen(input); i++) {
for (int i = 0; i < strlen(input); i++)
{
output += input[i] - '0';
}
return output;
}
bool PIDGEN2::isValidChannelID(char* channelID) {
if (strlen(channelID) > 3) {
bool PIDGEN2::isValidChannelID(char *channelID)
{
if (strlen(channelID) > 3)
{
return false;
}
for (int i = 0; i <= 6; i++) {
if (strcmp(channelID, channelIDBlacklist[i]) != 0) {
for (int i = 0; i <= 6; i++)
{
if (strcmp(channelID, channelIDBlacklist[i]) != 0)
{
return false;
}
}
@ -63,13 +73,17 @@ bool PIDGEN2::isValidChannelID(char* channelID) {
return true;
}
bool PIDGEN2::isValidOEMID(char* OEMID) {
if (!isNumericString(OEMID)) {
bool PIDGEN2::isValidOEMID(char *OEMID)
{
if (!isNumericString(OEMID))
{
return false;
}
if (strlen(OEMID) > 5) {
if (OEMID[0] != '0' || OEMID[1] != '0') {
if (strlen(OEMID) > 5)
{
if (OEMID[0] != '0' || OEMID[1] != '0')
{
return false;
}
}
@ -79,52 +93,65 @@ bool PIDGEN2::isValidOEMID(char* OEMID) {
return (mod % 21 == 0);
}
bool PIDGEN2::isValidYear(char* year) {
for (int i = 0; i <= 7; i++) {
if (year == validYears[i]) {
bool PIDGEN2::isValidYear(char *year)
{
for (int i = 0; i <= 7; i++)
{
if (year == validYears[i])
{
return false;
}
}
return true;
}
bool PIDGEN2::isValidDay(char* day) {
if (!isNumericString(day)) {
bool PIDGEN2::isValidDay(char *day)
{
if (!isNumericString(day))
{
return false;
}
int iDay = std::stoi(day);
if (iDay == 0 || iDay >= 365) {
if (iDay == 0 || iDay >= 365)
{
return false;
}
return true;
}
bool PIDGEN2::isValidRetailProductID(char* productID) {
bool PIDGEN2::isValidRetailProductID(char *productID)
{
return true;
}
int PIDGEN2::GenerateRetail(char* channelID, char* &keyout) {
if (!isValidChannelID(channelID)) {
int PIDGEN2::GenerateRetail(char *channelID, char *&keyout)
{
if (!isValidChannelID(channelID))
{
return 1;
}
return 0;
}
int PIDGEN2::GenerateOEM(char* year, char* day, char* oem, char* &keyout) {
if (!isValidOEMID(oem)) {
int PIDGEN2::GenerateOEM(char *year, char *day, char *oem, char *&keyout)
{
if (!isValidOEMID(oem))
{
int mod = addDigits(oem);
mod += mod % 21;
strcpy(oem, fmt::format("{:07d}", mod).c_str());
}
if (!isValidYear(year)) {
if (!isValidYear(year))
{
strcpy(year, validYears[0]);
}
if (!isValidDay(day)) {
if (!isValidDay(day))
{
int iday = std::stoi(day);
iday = (iday + 1) % 365;
}

View File

@ -25,17 +25,18 @@
#include "../libumskt.h"
EXPORT class PIDGEN2 {
public:
static bool isNumericString(char* input);
static bool isValidChannelID(char* channelID);
static bool isValidOEMID(char* OEMID);
static bool isValidYear(char* year);
static bool isValidDay(char* day);
static bool isValidRetailProductID(char* productID);
static int addDigits(char* input);
static int GenerateRetail(char* channelID, char* &keyout);
static int GenerateOEM(char* year, char* day, char* oem, char* &keyout);
EXPORT class PIDGEN2
{
public:
static bool isNumericString(char *input);
static bool isValidChannelID(char *channelID);
static bool isValidOEMID(char *OEMID);
static bool isValidYear(char *year);
static bool isValidDay(char *day);
static bool isValidRetailProductID(char *productID);
static int addDigits(char *input);
static int GenerateRetail(char *channelID, char *&keyout);
static int GenerateOEM(char *year, char *day, char *oem, char *&keyout);
};
#endif //UMSKT_PIDGEN2_H
#endif // UMSKT_PIDGEN2_H

View File

@ -30,13 +30,8 @@
#include "BINK1998.h"
/* Unpacks a Windows XP-like Product Key. */
void PIDGEN3::BINK1998::Unpack(
QWORD (&pRaw)[2],
BOOL &pUpgrade,
DWORD &pSerial,
DWORD &pHash,
QWORD &pSignature
) {
void PIDGEN3::BINK1998::Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pSerial, DWORD &pHash, QWORD &pSignature)
{
// We're assuming that the quantity of information within the product key is at most 114 bits.
// log2(24^25) = 114.
@ -54,13 +49,8 @@ void PIDGEN3::BINK1998::Unpack(
}
/* Packs a Windows XP-like Product Key. */
void PIDGEN3::BINK1998::Pack(
QWORD (&pRaw)[2],
BOOL pUpgrade,
DWORD pSerial,
DWORD pHash,
QWORD pSignature
) {
void PIDGEN3::BINK1998::Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pSerial, DWORD pHash, QWORD pSignature)
{
// The quantity of information the key provides is 114 bits.
// We're storing it in 2 64-bit quad-words with 14 trailing bits.
// 64 * 2 = 128
@ -71,22 +61,15 @@ void PIDGEN3::BINK1998::Pack(
}
/* Verifies a Windows XP-like Product Key. */
bool PIDGEN3::BINK1998::Verify(
EC_GROUP *eCurve,
EC_POINT *basePoint,
EC_POINT *publicKey,
char (&pKey)[25]
) {
bool PIDGEN3::BINK1998::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25])
{
BN_CTX *numContext = BN_CTX_new();
QWORD pRaw[2]{},
pSignature;
QWORD pRaw[2]{}, pSignature;
DWORD pData,
pSerial,
pHash;
DWORD pData, pSerial, pHash;
BOOL pUpgrade;
BOOL pUpgrade;
// Convert Base24 CD-key to bytecode.
PIDGEN3::unbase24((BYTE *)pRaw, pKey);
@ -119,9 +102,7 @@ bool PIDGEN3::BINK1998::Verify(
*/
BIGNUM *e = BN_lebin2bn((BYTE *)&pHash, sizeof(pHash), nullptr),
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr),
*x = BN_new(),
*y = BN_new();
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr), *x = BN_new(), *y = BN_new();
// Create 2 points on the elliptic curve.
EC_POINT *t = EC_POINT_new(eCurve);
@ -139,10 +120,7 @@ bool PIDGEN3::BINK1998::Verify(
// x = P.x; y = P.y;
EC_POINT_get_affine_coordinates(eCurve, p, x, y, numContext);
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
msgBuffer[SHA_MSG_LENGTH_XP]{},
xBin[FIELD_BYTES]{},
yBin[FIELD_BYTES]{};
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_XP]{}, xBin[FIELD_BYTES]{}, yBin[FIELD_BYTES]{};
// Convert resulting point coordinates to bytes.
BN_bn2lebin(x, xBin, FIELD_BYTES);
@ -175,29 +153,20 @@ bool PIDGEN3::BINK1998::Verify(
}
/* Generates a Windows XP-like Product Key. */
void PIDGEN3::BINK1998::Generate(
EC_GROUP *eCurve,
EC_POINT *basePoint,
BIGNUM *genOrder,
BIGNUM *privateKey,
DWORD pSerial,
BOOL pUpgrade,
char (&pKey)[25]
) {
void PIDGEN3::BINK1998::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
DWORD pSerial, BOOL pUpgrade, char (&pKey)[25])
{
BN_CTX *numContext = BN_CTX_new();
BIGNUM *c = BN_new(),
*s = BN_new(),
*x = BN_new(),
*y = BN_new();
BIGNUM *c = BN_new(), *s = BN_new(), *x = BN_new(), *y = BN_new();
QWORD pRaw[2]{},
pSignature = 0;
QWORD pRaw[2]{}, pSignature = 0;
// Data segment of the RPK.
DWORD pData = pSerial << 1 | pUpgrade;
do {
do
{
EC_POINT *r = EC_POINT_new(eCurve);
// Generate a random number c consisting of 384 bits without any constraints.
@ -211,10 +180,7 @@ void PIDGEN3::BINK1998::Generate(
// x = R.x; y = R.y;
EC_POINT_get_affine_coordinates(eCurve, r, x, y, numContext);
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
msgBuffer[SHA_MSG_LENGTH_XP]{},
xBin[FIELD_BYTES]{},
yBin[FIELD_BYTES]{};
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_XP]{}, xBin[FIELD_BYTES]{}, yBin[FIELD_BYTES]{};
// Convert coordinates to bytes.
BN_bn2lebin(x, xBin, FIELD_BYTES);

View File

@ -25,40 +25,17 @@
#include "PIDGEN3.h"
EXPORT class PIDGEN3::BINK1998 {
public:
static void Unpack(
QWORD (&pRaw)[2],
BOOL &pUpgrade,
DWORD &pSerial,
DWORD &pHash,
QWORD &pSignature
);
EXPORT class PIDGEN3::BINK1998
{
public:
static void Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pSerial, DWORD &pHash, QWORD &pSignature);
static void Pack(
QWORD (&pRaw)[2],
BOOL pUpgrade,
DWORD pSerial,
DWORD pHash,
QWORD pSignature
);
static void Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pSerial, DWORD pHash, QWORD pSignature);
static bool Verify(
EC_GROUP *eCurve,
EC_POINT *basePoint,
EC_POINT *publicKey,
char (&pKey)[25]
);
static bool Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&pKey)[25]);
static void Generate(
EC_GROUP *eCurve,
EC_POINT *basePoint,
BIGNUM *genOrder,
BIGNUM *privateKey,
DWORD pSerial,
BOOL pUpgrade,
char (&pKey)[25]
);
static void Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial,
BOOL pUpgrade, char (&pKey)[25]);
};
#endif //UMSKT_BINK1998_H
#endif // UMSKT_BINK1998_H

View File

@ -30,14 +30,9 @@
#include "BINK2002.h"
/* Unpacks a Windows Server 2003-like Product Key. */
void PIDGEN3::BINK2002::Unpack(
QWORD (&pRaw)[2],
BOOL &pUpgrade,
DWORD &pChannelID,
DWORD &pHash,
QWORD &pSignature,
DWORD &pAuthInfo
) {
void PIDGEN3::BINK2002::Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pChannelID, DWORD &pHash, QWORD &pSignature,
DWORD &pAuthInfo)
{
// We're assuming that the quantity of information within the product key is at most 114 bits.
// log2(24^25) = 114.
@ -60,37 +55,24 @@ void PIDGEN3::BINK2002::Unpack(
}
/* Packs a Windows Server 2003-like Product Key. */
void PIDGEN3::BINK2002::Pack(
QWORD (&pRaw)[2],
BOOL pUpgrade,
DWORD pChannelID,
DWORD pHash,
QWORD pSignature,
DWORD pAuthInfo
) {
void PIDGEN3::BINK2002::Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pChannelID, DWORD pHash, QWORD pSignature,
DWORD pAuthInfo)
{
// AuthInfo [113..104] <- Signature [103..42] <- Hash [41..11] <- Channel ID [10..1] <- Upgrade [0]
pRaw[0] = FIRSTNBITS(pSignature, 22) << 42 | (QWORD)pHash << 11 | pChannelID << 1 | pUpgrade;
pRaw[1] = FIRSTNBITS(pAuthInfo, 10) << 40 | NEXTSNBITS(pSignature, 40, 22);
}
/* Verifies a Windows Server 2003-like Product Key. */
bool PIDGEN3::BINK2002::Verify(
EC_GROUP *eCurve,
EC_POINT *basePoint,
EC_POINT *publicKey,
char (&cdKey)[25]
) {
bool PIDGEN3::BINK2002::Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25])
{
BN_CTX *context = BN_CTX_new();
QWORD bKey[2]{},
pSignature = 0;
QWORD bKey[2]{}, pSignature = 0;
DWORD pData,
pChannelID,
pHash,
pAuthInfo;
DWORD pData, pChannelID, pHash, pAuthInfo;
BOOL pUpgrade;
BOOL pUpgrade;
// Convert Base24 CD-key to bytecode.
unbase24((BYTE *)bKey, cdKey);
@ -108,10 +90,8 @@ bool PIDGEN3::BINK2002::Verify(
fmt::print(UMSKT::debug, " AuthInfo: 0x{:08x}\n", pAuthInfo);
fmt::print(UMSKT::debug, "\n");
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
msgBuffer[SHA_MSG_LENGTH_2003]{},
xBin[FIELD_BYTES_2003]{},
yBin[FIELD_BYTES_2003]{};
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_2003]{}, xBin[FIELD_BYTES_2003]{},
yBin[FIELD_BYTES_2003]{};
// Assemble the first SHA message.
msgBuffer[0x00] = 0x5D;
@ -130,7 +110,8 @@ bool PIDGEN3::BINK2002::Verify(
SHA1(msgBuffer, 11, msgDigest);
// Translate the byte digest into a 64-bit integer - this is our computed intermediate signature.
// As the signature is only 62 bits long at most, we have to truncate it by shifting the high DWORD right 2 bits (per spec).
// As the signature is only 62 bits long at most, we have to truncate it by shifting the high DWORD right 2 bits
// (per spec).
QWORD iSignature = NEXTSNBITS(BYDWORD(&msgDigest[4]), 30, 2) << 32 | BYDWORD(msgDigest);
/*
@ -149,9 +130,7 @@ bool PIDGEN3::BINK2002::Verify(
*/
BIGNUM *e = BN_lebin2bn((BYTE *)&iSignature, sizeof(iSignature), nullptr),
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr),
*x = BN_new(),
*y = BN_new();
*s = BN_lebin2bn((BYTE *)&pSignature, sizeof(pSignature), nullptr), *x = BN_new(), *y = BN_new();
// Create 2 points on the elliptic curve.
EC_POINT *p = EC_POINT_new(eCurve);
@ -206,33 +185,22 @@ bool PIDGEN3::BINK2002::Verify(
}
/* Generates a Windows Server 2003-like Product Key. */
void PIDGEN3::BINK2002::Generate(
EC_GROUP *eCurve,
EC_POINT *basePoint,
BIGNUM *genOrder,
BIGNUM *privateKey,
DWORD pChannelID,
DWORD pAuthInfo,
BOOL pUpgrade,
char (&pKey)[25]
) {
void PIDGEN3::BINK2002::Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey,
DWORD pChannelID, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25])
{
BN_CTX *numContext = BN_CTX_new();
BIGNUM *c = BN_new(),
*e = BN_new(),
*s = BN_new(),
*x = BN_new(),
*y = BN_new();
BIGNUM *c = BN_new(), *e = BN_new(), *s = BN_new(), *x = BN_new(), *y = BN_new();
QWORD pRaw[2]{},
pSignature = 0;
QWORD pRaw[2]{}, pSignature = 0;
// Data segment of the RPK.
DWORD pData = pChannelID << 1 | pUpgrade;
BOOL noSquare;
do {
do
{
EC_POINT *r = EC_POINT_new(eCurve);
// Generate a random number c consisting of 512 bits without any constraints.
@ -245,10 +213,8 @@ void PIDGEN3::BINK2002::Generate(
// x = R.x; y = R.y;
EC_POINT_get_affine_coordinates(eCurve, r, x, y, numContext);
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
msgBuffer[SHA_MSG_LENGTH_2003]{},
xBin[FIELD_BYTES_2003]{},
yBin[FIELD_BYTES_2003]{};
BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_2003]{}, xBin[FIELD_BYTES_2003]{},
yBin[FIELD_BYTES_2003]{};
// Convert resulting point coordinates to bytes.
BN_bn2lebin(x, xBin, FIELD_BYTES_2003);
@ -286,7 +252,8 @@ void PIDGEN3::BINK2002::Generate(
SHA1(msgBuffer, 11, msgDigest);
// Translate the byte digest into a 64-bit integer - this is our computed intermediate signature.
// As the signature is only 62 bits long at most, we have to truncate it by shifting the high DWORD right 2 bits (per spec).
// As the signature is only 62 bits long at most, we have to truncate it by shifting the high DWORD right 2
// bits (per spec).
QWORD iSignature = NEXTSNBITS(BYDWORD(&msgDigest[4]), 30, 2) << 32 | BYDWORD(msgDigest);
BN_lebin2bn((BYTE *)&iSignature, sizeof(iSignature), e);
@ -346,9 +313,11 @@ void PIDGEN3::BINK2002::Generate(
// If s is odd, add order to it.
// The order is a prime, so it can't be even.
if (BN_is_odd(s))
{
// s = -ek + √((ek)² + 4c) + n
BN_add(s, s, genOrder);
}
// s /= 2 (s >>= 1)
BN_rshift1(s, s);

View File

@ -25,43 +25,18 @@
#include "PIDGEN3.h"
EXPORT class PIDGEN3::BINK2002 {
public:
static void Unpack(
QWORD (&pRaw)[2],
BOOL &pUpgrade,
DWORD &pChannelID,
DWORD &pHash,
QWORD &pSignature,
DWORD &pAuthInfo
);
EXPORT class PIDGEN3::BINK2002
{
public:
static void Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pChannelID, DWORD &pHash, QWORD &pSignature,
DWORD &pAuthInfo);
static void Pack(
QWORD (&pRaw)[2],
BOOL pUpgrade,
DWORD pChannelID,
DWORD pHash,
QWORD pSignature,
DWORD pAuthInfo
);
static void Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pChannelID, DWORD pHash, QWORD pSignature, DWORD pAuthInfo);
static bool Verify(
EC_GROUP *eCurve,
EC_POINT *basePoint,
EC_POINT *publicKey,
char (&cdKey)[25]
);
static bool Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25]);
static void Generate(
EC_GROUP *eCurve,
EC_POINT *basePoint,
BIGNUM *genOrder,
BIGNUM *privateKey,
DWORD pChannelID,
DWORD pAuthInfo,
BOOL pUpgrade,
char (&pKey)[25]
);
static void Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID,
DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25]);
};
#endif //UMSKT_BINK2002_H
#endif // UMSKT_BINK2002_H

View File

@ -25,25 +25,20 @@
#include "../libumskt.h"
class PIDGEN3 {
public:
class PIDGEN3
{
public:
class BINK1998;
class BINK2002;
// util.cpp
static int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen); // Hello OpenSSL developers, please tell me, where is this function at?
static int BN_bn2lebin(const BIGNUM *a, unsigned char *to,
int tolen); // Hello OpenSSL developers, please tell me, where is this function at?
static void endian(BYTE *data, int length);
static EC_GROUP* initializeEllipticCurve(
std::string pSel,
std::string aSel,
std::string bSel,
std::string generatorXSel,
std::string generatorYSel,
std::string publicKeyXSel,
std::string publicKeyYSel,
EC_POINT *&genPoint,
EC_POINT *&pubPoint
);
static EC_GROUP *initializeEllipticCurve(std::string pSel, std::string aSel, std::string bSel,
std::string generatorXSel, std::string generatorYSel,
std::string publicKeyXSel, std::string publicKeyYSel, EC_POINT *&genPoint,
EC_POINT *&pubPoint);
// key.cpp
static constexpr char pKeyCharset[] = "BCDFGHJKMPQRTVWXY2346789";
@ -51,4 +46,4 @@ public:
static void base24(char *cdKey, BYTE *byteSeq);
};
#endif //UMSKT_PIDGEN3_H
#endif // UMSKT_PIDGEN3_H

View File

@ -23,16 +23,20 @@
#include "PIDGEN3.h"
/* Converts from CD-key to a byte sequence. */
void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey) {
void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey)
{
BYTE pDecodedKey[PK_LENGTH + NULL_TERMINATOR]{};
BIGNUM *y = BN_new();
BN_zero(y);
// Remove dashes from the CD-key and put it into a Base24 byte array.
for (int i = 0, k = 0; i < strlen(cdKey) && k < PK_LENGTH; i++) {
for (int j = 0; j < 24; j++) {
if (cdKey[i] != '-' && cdKey[i] == pKeyCharset[j]) {
for (int i = 0, k = 0; i < strlen(cdKey) && k < PK_LENGTH; i++)
{
for (int j = 0; j < 24; j++)
{
if (cdKey[i] != '-' && cdKey[i] == pKeyCharset[j])
{
pDecodedKey[k++] = j;
break;
}
@ -43,7 +47,8 @@ void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey) {
memset(byteSeq, 0, 16);
// Calculate the weighed sum of byte array elements.
for (int i = 0; i < PK_LENGTH; i++) {
for (int i = 0; i < PK_LENGTH; i++)
{
BN_mul_word(y, PK_LENGTH - 1);
BN_add_word(y, pDecodedKey[i]);
}
@ -60,7 +65,8 @@ void PIDGEN3::unbase24(BYTE *byteSeq, const char *cdKey) {
}
/* Converts from byte sequence to the CD-key. */
void PIDGEN3::base24(char *cdKey, BYTE *byteSeq) {
void PIDGEN3::base24(char *cdKey, BYTE *byteSeq)
{
BYTE rbyteSeq[16];
BIGNUM *z;
@ -70,7 +76,10 @@ void PIDGEN3::base24(char *cdKey, BYTE *byteSeq) {
// Skip trailing zeroes and reverse y.
int length;
for (length = 15; rbyteSeq[length] == 0; length--);
for (length = 15; rbyteSeq[length] == 0; length--)
{
;
}
endian(rbyteSeq, ++length);
// Convert reversed byte sequence to BigNum z.
@ -80,7 +89,9 @@ void PIDGEN3::base24(char *cdKey, BYTE *byteSeq) {
cdKey[25] = 0;
for (int i = 24; i >= 0; i--)
{
cdKey[i] = pKeyCharset[BN_div_word(z, 24)];
}
BN_free(z);
}

View File

@ -22,14 +22,17 @@
#include "PIDGEN3.h"
int randomRange() {
return 4; // chosen by fair dice roll
// guaranteed to be random
int randomRange()
{
return 4; // chosen by fair dice roll
// guaranteed to be random
}
/* Convert data between endianness types. */
void PIDGEN3::endian(BYTE *data, int length) {
for (int i = 0; i < length / 2; i++) {
void PIDGEN3::endian(BYTE *data, int length)
{
for (int i = 0; i < length / 2; i++)
{
BYTE temp = data[i];
data[i] = data[length - i - 1];
data[length - i - 1] = temp;
@ -37,17 +40,11 @@ void PIDGEN3::endian(BYTE *data, int length) {
}
/* Initializes the elliptic curve. */
EC_GROUP* PIDGEN3::initializeEllipticCurve(
const std::string pSel,
const std::string aSel,
const std::string bSel,
const std::string generatorXSel,
const std::string generatorYSel,
const std::string publicKeyXSel,
const std::string publicKeyYSel,
EC_POINT *&genPoint,
EC_POINT *&pubPoint
) {
EC_GROUP *PIDGEN3::initializeEllipticCurve(const std::string pSel, const std::string aSel, const std::string bSel,
const std::string generatorXSel, const std::string generatorYSel,
const std::string publicKeyXSel, const std::string publicKeyYSel,
EC_POINT *&genPoint, EC_POINT *&pubPoint)
{
// Initialize BIGNUM and BIGNUMCTX structures.
// BIGNUM - Large numbers
// BIGNUMCTX - Context large numbers (temporary)
@ -83,7 +80,8 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
/* Elliptic Curve calculations. */
// The group is defined via Fp = all integers [0; p - 1], where p is prime.
// The function EC_POINT_set_affine_coordinates() sets the x and y coordinates for the point p defined over the curve given in group.
// The function EC_POINT_set_affine_coordinates() sets the x and y coordinates for the point p defined over the
// curve given in group.
EC_GROUP *eCurve = EC_GROUP_new_curve_GFp(p, a, b, context);
// Create new point for the generator on the elliptic curve and set its coordinates to (genX; genY).
@ -94,7 +92,8 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
pubPoint = EC_POINT_new(eCurve);
EC_POINT_set_affine_coordinates(eCurve, pubPoint, publicKeyX, publicKeyY, context);
// If generator and public key points are not on the elliptic curve, either the generator or the public key values are incorrect.
// If generator and public key points are not on the elliptic curve, either the generator or the public key values
// are incorrect.
assert(EC_POINT_is_on_curve(eCurve, genPoint, context) == true);
assert(EC_POINT_is_on_curve(eCurve, pubPoint, context) == true);
@ -111,14 +110,19 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
return eCurve;
}
int PIDGEN3::BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen) {
int PIDGEN3::BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen)
{
if (a == nullptr || to == nullptr)
{
return 0;
}
int len = BN_bn2bin(a, to);
if (len > tolen)
{
return -1;
}
// Choke point inside BN_bn2lebinpad: OpenSSL uses len instead of tolen.
endian(to, tolen);

View File

@ -20,13 +20,15 @@
* @Maintainer Neo
*/
#include "header.h"
#include "cli.h"
#include "header.h"
Options options;
int main(int argc, char *argv[]) {
if (!CLI::parseCommandLine(argc, argv, &options)) {
int main(int argc, char *argv[])
{
if (!CLI::parseCommandLine(argc, argv, &options))
{
fmt::print("error parsing command line options\n");
CLI::showHelp(argv);
return !options.error ? 0 : 1;
@ -35,29 +37,31 @@ int main(int argc, char *argv[]) {
json keys;
int status = CLI::validateCommandLine(&options, argv, &keys);
if (status > 0) {
if (status > 0)
{
return status;
}
CLI run(options, keys);
switch(options.applicationMode) {
case MODE_BINK1998_GENERATE:
return run.BINK1998Generate();
switch (options.applicationMode)
{
case MODE_BINK1998_GENERATE:
return run.BINK1998Generate();
case MODE_BINK2002_GENERATE:
return run.BINK2002Generate();
case MODE_BINK2002_GENERATE:
return run.BINK2002Generate();
case MODE_BINK1998_VALIDATE:
return run.BINK1998Validate();
case MODE_BINK1998_VALIDATE:
return run.BINK1998Validate();
case MODE_BINK2002_VALIDATE:
return run.BINK2002Validate();
case MODE_BINK2002_VALIDATE:
return run.BINK2002Validate();
case MODE_CONFIRMATION_ID:
return run.ConfirmationID();
case MODE_CONFIRMATION_ID:
return run.ConfirmationID();
default:
return 1;
default:
return 1;
}
}

View File

@ -23,8 +23,8 @@
#ifndef UMSKT_TYPEDEFS_H
#define UMSKT_TYPEDEFS_H
#include <cstdint>
#include <cstdbool>
#include <cstdint>
#ifdef DEBUG
#include <cassert>
@ -46,8 +46,8 @@
#endif
// Type definitions
typedef bool BOOL;
typedef uint8_t BYTE;
typedef bool BOOL;
typedef uint8_t BYTE;
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef uint64_t QWORD;
@ -56,4 +56,4 @@ typedef uint64_t QWORD;
typedef unsigned __int128 OWORD;
#endif
#endif //UMSKT_TYPEDEFS_H
#endif // UMSKT_TYPEDEFS_H

View File

@ -21,23 +21,23 @@
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "resource.h"
#include <windows.h>
BOOLEAN WINAPI DllMain( IN HINSTANCE hDllHandle,
IN DWORD nReason,
IN LPVOID Reserved ) {
BOOLEAN WINAPI DllMain(IN HINSTANCE hDllHandle, IN DWORD nReason, IN LPVOID Reserved)
{
BOOLEAN bSuccess = TRUE;
// Perform global initialization.
switch (nReason) {
case DLL_PROCESS_ATTACH:
// For optimization.
DisableThreadLibraryCalls(hDllHandle);
break;
switch (nReason)
{
case DLL_PROCESS_ATTACH:
// For optimization.
DisableThreadLibraryCalls(hDllHandle);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return bSuccess;

View File

@ -24,15 +24,15 @@
// Microsoft Visual C++ generated include file.
// Used by umskt.rc
//
#define IDI_ICON1 101
#define IDI_ICON1 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif