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

View File

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

View File

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

View File

@ -82,7 +82,6 @@ void ConfirmationID::setFlagVersion(unsigned int flagVersion)
ConfirmationID::flagVersion = flagVersion; ConfirmationID::flagVersion = flagVersion;
} }
int ConfirmationID::calculateCheckDigit(int pid) int ConfirmationID::calculateCheckDigit(int pid)
{ {
unsigned int i = 0, j = 0, k = 0; unsigned int i = 0, j = 0, k = 0;
@ -94,7 +93,7 @@ int ConfirmationID::calculateCheckDigit(int pid)
return ((10 * pid) - (i % 7)) + 7; 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]; QWORD buffer[5];
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
@ -113,12 +112,12 @@ void ConfirmationID::decode_iid_new_version(unsigned char* iid, unsigned char* h
*version = buffer[0] & 7; *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]; unsigned char sha1_input[64], sha1_result[20];
size_t half = bufSize / 2; size_t half = bufSize / 2;
//assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9); // 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));
@ -159,12 +158,12 @@ void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned c
} }
} }
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_input[64];
unsigned char sha1_result[20]; unsigned char sha1_result[20];
size_t half = bufSize / 2; size_t half = bufSize / 2;
//assert(half <= sizeof(sha1_result) && half + keySize <= sizeof(sha1_input) - 9); // 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++)
{ {
@ -204,7 +203,7 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned
} }
} }
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; int version;
unsigned char hardwareID[8]; unsigned char hardwareID[8];
@ -212,7 +211,7 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
unsigned char productID[4]; unsigned char productID[4];
size_t installation_id_len = 0; size_t installation_id_len = 0;
const char* pid = installation_id_str; const char *pid = installation_id_str;
size_t count = 0, totalCount = 0; size_t count = 0, totalCount = 0;
unsigned check = 0; unsigned check = 0;
@ -292,7 +291,8 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
} }
#pragma pack(push, 1) #pragma pack(push, 1)
struct { struct
{
QWORD HardwareID; QWORD HardwareID;
QWORD ProductIDLow; QWORD ProductIDLow;
unsigned char ProductIDHigh; unsigned char ProductIDHigh;
@ -331,9 +331,9 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
} }
memcpy(&parsed, hardwareID, 8); 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]; char *p = &channelid[0];
for (; *p; p++) for (; *p; p++)
{ {
@ -342,24 +342,25 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
if (strcmp(&channelid[0], "OEM") == 0) if (strcmp(&channelid[0], "OEM") == 0)
{ {
productID[1] = stoi(productid.substr(12,3)); productID[1] = stoi(productid.substr(12, 3));
productID[2] = (stoi(productid.substr(15,1)) * 100000) + stoi(productid.substr(18,5)); productID[2] = (stoi(productid.substr(15, 1)) * 100000) + stoi(productid.substr(18, 5));
productID[2] = calculateCheckDigit(productID[2]); 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 else
{ {
productID[1] = stoi(productid.substr(6,3)); productID[1] = stoi(productid.substr(6, 3));
productID[2] = stoi(productid.substr(10,7)); productID[2] = stoi(productid.substr(10, 7));
productID[3] = stoi(productid.substr(18,5)); 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]; unsigned char keybuf[16];
memcpy(keybuf, &parsed.HardwareID, 8); memcpy(keybuf, &parsed.HardwareID, 8);
QWORD productIdMixed = (QWORD)productID[0] << 41 | (QWORD)productID[1] << 58 | (QWORD)productID[2] << 17 | productID[3]; QWORD productIdMixed =
(QWORD)productID[0] << 41 | (QWORD)productID[1] << 58 | (QWORD)productID[2] << 17 | productID[3];
memcpy(keybuf + 8, &productIdMixed, 8); memcpy(keybuf + 8, &productIdMixed, 8);
TDivisor d; TDivisor d;
@ -367,7 +368,8 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
union { union {
unsigned char buffer[14]; unsigned char buffer[14];
struct { struct
{
QWORD lo; QWORD lo;
QWORD hi; QWORD hi;
}; };
@ -408,10 +410,12 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
divisor->mul128(&d, u[0], u[1], &d); divisor->mul128(&d, u[0], u[1], &d);
union { union {
struct { struct
{
QWORD encoded_lo, encoded_hi; QWORD encoded_lo, encoded_hi;
}; };
struct { struct
{
uint32_t encoded[4]; uint32_t encoded[4];
}; };
} e; } e;
@ -424,7 +428,7 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
else if (d.u[1] == BAD) else if (d.u[1] == BAD)
{ {
// O(1/MOD) chance // O(1/MOD) chance
//encoded = (unsigned __int128)(MOD + 1) * d.u[0] + MOD; // * MOD + d.u[0] is fine too // 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 = residue->__umul128(MOD + 1, d.u[0], &e.encoded_hi);
e.encoded_lo += MOD; e.encoded_lo += MOD;
e.encoded_hi += (e.encoded_lo < MOD); e.encoded_hi += (e.encoded_lo < MOD);
@ -467,7 +471,6 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
e.encoded_lo = residue->__umul128(MOD + 1, x1a, &e.encoded_hi); e.encoded_lo = residue->__umul128(MOD + 1, x1a, &e.encoded_hi);
e.encoded_lo += x2a; e.encoded_lo += x2a;
e.encoded_hi += (e.encoded_lo < x2a); e.encoded_hi += (e.encoded_lo < x2a);
} }
} }
@ -486,7 +489,7 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
} }
assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0); assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0);
char* q = confirmation_id; char *q = confirmation_id;
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
{ {
if (i) if (i)
@ -494,13 +497,13 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
*q++ = '-'; *q++ = '-';
} }
unsigned char* p = decimal + i*5; unsigned char *p = decimal + i * 5;
q[0] = p[0] + '0'; q[0] = p[0] + '0';
q[1] = p[1] + '0'; q[1] = p[1] + '0';
q[2] = p[2] + '0'; q[2] = p[2] + '0';
q[3] = p[3] + '0'; q[3] = p[3] + '0';
q[4] = p[4] + '0'; q[4] = p[4] + '0';
q[5] = ((p[0]+p[1]*2+p[2]+p[3]*2+p[4]) % 7) + '0'; q[5] = ((p[0] + p[1] * 2 + p[2] + p[3] * 2 + p[4]) % 7) + '0';
q += 6; q += 6;
} }
*q++ = 0; *q++ = 0;

View File

@ -26,7 +26,8 @@
#include "../libumskt.h" #include "../libumskt.h"
// Confirmation ID generator constants // Confirmation ID generator constants
enum CONFIRMATION_ID_STATUS { enum CONFIRMATION_ID_STATUS
{
SUCCESS = 0, SUCCESS = 0,
ERR_TOO_SHORT = 1, ERR_TOO_SHORT = 1,
ERR_TOO_LARGE = 2, ERR_TOO_LARGE = 2,
@ -38,12 +39,14 @@ enum CONFIRMATION_ID_STATUS {
#define BAD 0xFFFFFFFFFFFFFFFFull #define BAD 0xFFFFFFFFFFFFFFFFull
typedef struct { typedef struct
{
QWORD u[2]; QWORD u[2];
QWORD v[2]; QWORD v[2];
} TDivisor; } TDivisor;
enum ACTIVATION_ALGORITHM { enum ACTIVATION_ALGORITHM
{
WINDOWS = 0, WINDOWS = 0,
OFFICE_XP = 1, OFFICE_XP = 1,
OFFICE_2K3 = 2, OFFICE_2K3 = 2,
@ -51,24 +54,25 @@ enum ACTIVATION_ALGORITHM {
PLUS_DME = 4, PLUS_DME = 4,
}; };
EXPORT class ConfirmationID { EXPORT class ConfirmationID
{
QWORD MOD = 0, NON_RESIDUE = 0; QWORD MOD = 0, NON_RESIDUE = 0;
QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; QWORD f[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
QWORD p[4] = { 0x0, 0x0, 0x0, 0x0 }; QWORD p[4] = {0x0, 0x0, 0x0, 0x0};
QWORD u[2] = { 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; BOOL isOffice = false, isXPBrand = false;
unsigned flagVersion = 0; unsigned flagVersion = 0;
public:
public:
void setFlagVersion(unsigned int flagVersion); void setFlagVersion(unsigned int flagVersion);
private: private:
int calculateCheckDigit(int pid); int calculateCheckDigit(int pid);
void decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version); 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 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 Unmix(unsigned char *buffer, size_t bufSize, const unsigned char *key, size_t keySize);
friend class Residue; friend class Residue;
Residue *residue; Residue *residue;
@ -79,8 +83,8 @@ private:
friend class Divisor; friend class Divisor;
Divisor *divisor; Divisor *divisor;
public: public:
int Generate(const char* installation_id_str, char confirmation_id[49], std::string productid); int Generate(const char *installation_id_str, char confirmation_id[49], std::string productid);
void setMod(QWORD mod); void setMod(QWORD mod);
void setNonResidue(QWORD nonResidue); void setNonResidue(QWORD nonResidue);
@ -91,28 +95,32 @@ public:
void setIsOffice(BOOL isOffice); void setIsOffice(BOOL isOffice);
void setIsXPBrand(BOOL isXpBrand); void setIsXPBrand(BOOL isXpBrand);
ConfirmationID() { ConfirmationID()
{
residue = new Residue(this); residue = new Residue(this);
polynomial = new Polynomial(this); polynomial = new Polynomial(this);
divisor = new Divisor(this); divisor = new Divisor(this);
} }
~ConfirmationID() { ~ConfirmationID()
{
delete residue, polynomial, divisor; delete residue, polynomial, divisor;
} }
}; };
class Residue { class Residue
{
ConfirmationID *parent; ConfirmationID *parent;
public: public:
explicit Residue(ConfirmationID *in) { explicit Residue(ConfirmationID *in)
{
parent = in; parent = in;
} }
QWORD add(QWORD x, QWORD y); QWORD add(QWORD x, QWORD y);
QWORD sub(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 ui128_quotient_mod(QWORD lo, QWORD hi);
QWORD mul(QWORD x, QWORD y); QWORD mul(QWORD x, QWORD y);
QWORD pow(QWORD x, QWORD y); QWORD pow(QWORD x, QWORD y);
@ -121,33 +129,37 @@ public:
QWORD sqrt(QWORD what); QWORD sqrt(QWORD what);
}; };
class Polynomial { class Polynomial
{
ConfirmationID *parent; ConfirmationID *parent;
public: public:
explicit Polynomial(ConfirmationID *in) { explicit Polynomial(ConfirmationID *in)
{
parent = in; parent = in;
} }
int mul(int adeg, const QWORD a[], int bdeg, const QWORD b[], int resultprevdeg, QWORD result[]); 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); 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]); void xgcd(int adeg, const QWORD a[3], int bdeg, const QWORD b[3], int *pgcddeg, QWORD gcd[3], int *pmult1deg,
int u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2]); 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; ConfirmationID *parent;
public: public:
explicit Divisor(ConfirmationID *in) { explicit Divisor(ConfirmationID *in)
{
parent = in; parent = in;
} }
int find_divisor_v(TDivisor* d); int find_divisor_v(TDivisor *d);
void add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst); void add(const TDivisor *src1, const TDivisor *src2, TDivisor *dst);
void mul(const TDivisor* src, QWORD mult, TDivisor* dst); void mul(const TDivisor *src, QWORD mult, TDivisor *dst);
void mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, 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" #include "confid.h"
int Divisor::find_divisor_v(TDivisor* d) int Divisor::find_divisor_v(TDivisor *d)
{ {
// u | v^2 - f // u | v^2 - f
// u = u0 + u1*x + x^2 // 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 u0 = d->u[0];
const QWORD u1 = d->u[1]; 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] = 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])); 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) if (f1 == 0)
{ {
// impossible // impossible
//printf("bad f(), double root detected\n"); // printf("bad f(), double root detected\n");
} }
return 0; 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); v1 = parent->residue->sqrt(sqr);
if (v1 == BAD) if (v1 == BAD)
{ {
@ -76,7 +77,9 @@ int Divisor::find_divisor_v(TDivisor* d)
} }
else 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); d = parent->residue->sqrt(d);
if (d == BAD) 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[0] = v0;
d->v[1] = v1; d->v[1] = v1;
return 1; 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) if (src->u[1] != BAD)
{ {
@ -132,7 +136,7 @@ int Divisor::u2poly(const TDivisor* src, QWORD polyu[3], QWORD polyv[2])
return 0; 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]; QWORD u1[3], u2[3], v1[2], v2[2];
int u1deg = u2poly(src1, u1, v1); int u1deg = u2poly(src1, u1, v1);
@ -198,21 +202,25 @@ void Divisor::add(const TDivisor* src1, const TDivisor* src2, TDivisor* dst)
if (ddeg > 0) if (ddeg > 0)
{ {
assert(udeg >= 2*ddeg); assert(udeg >= 2 * ddeg);
QWORD udiv[5]; QWORD udiv[5];
parent->polynomial->div_monic(udeg, u, ddeg, d, udiv); udeg -= ddeg; parent->polynomial->div_monic(udeg, u, ddeg, d, udiv);
parent->polynomial->div_monic(udeg, udiv, ddeg, d, u); udeg -= ddeg; udeg -= ddeg;
parent->polynomial->div_monic(udeg, udiv, ddeg, d, u);
udeg -= ddeg;
if (vdeg >= 0) if (vdeg >= 0)
{ {
assert(vdeg >= ddeg); 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])); memcpy(v, udiv, (vdeg + 1) * sizeof(v[0]));
} }
} }
vdeg = parent->polynomial->div_monic(vdeg, v, udeg, u, NULL); vdeg = parent->polynomial->div_monic(vdeg, v, udeg, u, NULL);
while (udeg > 2) { while (udeg > 2)
{
assert(udeg <= 4); assert(udeg <= 4);
assert(vdeg <= 3); assert(vdeg <= 3);
// u' = monic((f-v^2)/u), v'=-v mod u' // 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) #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) 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) 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); divisor_double(&cur, &cur);
mult_lo >>= 1; mult_lo >>= 1;
if (mult_hi & 1) { if (mult_hi & 1)
{
mult_lo |= (1ULL << 63); mult_lo |= (1ULL << 63);
} }
mult_hi >>= 1; 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; 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(bdeg >= 0);
assert(b[bdeg] == 1); assert(b[bdeg] == 1);
@ -84,25 +84,32 @@ int Polynomial::div_monic(int adeg, QWORD a[], int bdeg, const QWORD b[], QWORD*
return i; 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; int sdeg = -1;
QWORD s[3] = {0, 0, 0}; QWORD s[3] = {0, 0, 0};
int mult1deg = 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; int tdeg = 0;
QWORD t[3] = {1, 0, 0}; QWORD t[3] = {1, 0, 0};
int mult2deg = -1; int mult2deg = -1;
mult2[0] = 0; mult2[1] = 0; mult2[2] = 0; mult2[0] = 0;
mult2[1] = 0;
mult2[2] = 0;
int rdeg = bdeg; int rdeg = bdeg;
QWORD r[3] = {b[0], b[1], b[2]}; QWORD r[3] = {b[0], b[1], b[2]};
int gcddeg = adeg; 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 // s*u1 + t*u2 = r
// mult1*u1 + mult2*u2 = gcd // 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; unsigned tmp;
int tmpi; int tmpi;
tmp = rdeg; rdeg = gcddeg; gcddeg = tmp; tmp = rdeg;
tmpi = sdeg; sdeg = mult1deg; mult1deg = tmpi; rdeg = gcddeg;
tmpi = tdeg; tdeg = mult2deg; mult2deg = tmpi; gcddeg = tmp;
tmpi = sdeg;
sdeg = mult1deg;
mult1deg = tmpi;
tmpi = tdeg;
tdeg = mult2deg;
mult2deg = tmpi;
QWORD tmp2; QWORD tmp2;
tmp2 = r[0]; r[0] = gcd[0]; gcd[0] = tmp2; tmp2 = r[0];
tmp2 = r[1]; r[1] = gcd[1]; gcd[1] = tmp2; r[0] = gcd[0];
tmp2 = r[2]; r[2] = gcd[2]; gcd[2] = tmp2; gcd[0] = tmp2;
tmp2 = s[0]; s[0] = mult1[0]; mult1[0] = tmp2; tmp2 = r[1];
tmp2 = s[1]; s[1] = mult1[1]; mult1[1] = tmp2; r[1] = gcd[1];
tmp2 = s[2]; s[2] = mult1[2]; mult1[2] = tmp2; gcd[1] = tmp2;
tmp2 = t[0]; t[0] = mult2[0]; mult2[0] = tmp2; tmp2 = r[2];
tmp2 = t[1]; t[1] = mult2[1]; mult2[1] = tmp2; r[2] = gcd[2];
tmp2 = t[2]; t[2] = mult2[2]; mult2[2] = tmp2; 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; continue;
} }

View File

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

View File

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

View File

@ -22,39 +22,53 @@
#include "libumskt.h" #include "libumskt.h"
#include "confid/confid.h" #include "confid/confid.h"
#include "pidgen3/PIDGEN3.h" #include "pidgen2/PIDGEN2.h"
#include "pidgen3/BINK1998.h" #include "pidgen3/BINK1998.h"
#include "pidgen3/BINK2002.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); 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) { FNEXPORT EC_GROUP *PIDGEN3_initializeEllipticCurve(char *pSel, char *aSel, char *bSel, char *generatorXSel,
return PIDGEN3::initializeEllipticCurve(pSel, aSel, bSel, generatorXSel, generatorYSel, publicKeyXSel, publicKeyYSel, genPoint, pubPoint); 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); 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); 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); 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); 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); 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); return PIDGEN2::GenerateOEM(year, day, oem, keyout);
} }

View File

@ -25,15 +25,15 @@
#include "../typedefs.h" #include "../typedefs.h"
#include <string>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <string>
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/ec.h> #include <openssl/ec.h>
#include <openssl/sha.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/sha.h>
#include <fmt/core.h> #include <fmt/core.h>
#include <fmt/format.h> #include <fmt/format.h>
@ -53,21 +53,21 @@
#define NEXTSNBITS(field, n, offset) (((QWORD)(field) >> (offset)) & ((1ULL << (n)) - 1)) #define NEXTSNBITS(field, n, offset) (((QWORD)(field) >> (offset)) & ((1ULL << (n)) - 1))
#define FIRSTNBITS(field, n) NEXTSNBITS((field), (n), 0) #define FIRSTNBITS(field, n) NEXTSNBITS((field), (n), 0)
#define HIBYTES(field, bytes) NEXTSNBITS((QWORD)(field), ((bytes) * 8), ((bytes) * 8)) #define HIBYTES(field, bytes) NEXTSNBITS((QWORD)(field), ((bytes)*8), ((bytes)*8))
#define LOBYTES(field, bytes) FIRSTNBITS((QWORD)(field), ((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 BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24)
#define BITMASK(n) ((1ULL << (n)) - 1) #define BITMASK(n) ((1ULL << (n)) - 1)
class UMSKT { class UMSKT
public: {
static std::FILE* debug; public:
static std::FILE *debug;
class PIDGEN2; class PIDGEN2;
class PIDGEN3; class PIDGEN3;
class ConfigurationID; 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" #include "PIDGEN2.h"
const char* channelIDBlacklist [7] = {"333", "444", "555", "666", "777", "888", "999"}; 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 *validYears[8] = {"95", "96", "97", "98", "99", "00", "01", "02"};
bool PIDGEN2::isNumericString(char* input) { bool PIDGEN2::isNumericString(char *input)
for(int i = 0; i < strlen(input); i++) { {
if (input[i] < '0' || input[i] > '9') { for (int i = 0; i < strlen(input); i++)
{
if (input[i] < '0' || input[i] > '9')
{
return false; return false;
} }
} }
@ -35,27 +38,34 @@ bool PIDGEN2::isNumericString(char* input) {
return true; return true;
} }
int PIDGEN2::addDigits(char* input) { int PIDGEN2::addDigits(char *input)
{
int output = 0; int output = 0;
if (!isNumericString(input)) { if (!isNumericString(input))
{
return -1; return -1;
} }
for(int i = 0; i < strlen(input); i++) { for (int i = 0; i < strlen(input); i++)
{
output += input[i] - '0'; output += input[i] - '0';
} }
return output; return output;
} }
bool PIDGEN2::isValidChannelID(char* channelID) { bool PIDGEN2::isValidChannelID(char *channelID)
if (strlen(channelID) > 3) { {
if (strlen(channelID) > 3)
{
return false; return false;
} }
for (int i = 0; i <= 6; i++) { for (int i = 0; i <= 6; i++)
if (strcmp(channelID, channelIDBlacklist[i]) != 0) { {
if (strcmp(channelID, channelIDBlacklist[i]) != 0)
{
return false; return false;
} }
} }
@ -63,13 +73,17 @@ bool PIDGEN2::isValidChannelID(char* channelID) {
return true; return true;
} }
bool PIDGEN2::isValidOEMID(char* OEMID) { bool PIDGEN2::isValidOEMID(char *OEMID)
if (!isNumericString(OEMID)) { {
if (!isNumericString(OEMID))
{
return false; return false;
} }
if (strlen(OEMID) > 5) { if (strlen(OEMID) > 5)
if (OEMID[0] != '0' || OEMID[1] != '0') { {
if (OEMID[0] != '0' || OEMID[1] != '0')
{
return false; return false;
} }
} }
@ -79,52 +93,65 @@ bool PIDGEN2::isValidOEMID(char* OEMID) {
return (mod % 21 == 0); return (mod % 21 == 0);
} }
bool PIDGEN2::isValidYear(char* year) { bool PIDGEN2::isValidYear(char *year)
for (int i = 0; i <= 7; i++) { {
if (year == validYears[i]) { for (int i = 0; i <= 7; i++)
{
if (year == validYears[i])
{
return false; return false;
} }
} }
return true; return true;
} }
bool PIDGEN2::isValidDay(char* day) { bool PIDGEN2::isValidDay(char *day)
if (!isNumericString(day)) { {
if (!isNumericString(day))
{
return false; return false;
} }
int iDay = std::stoi(day); int iDay = std::stoi(day);
if (iDay == 0 || iDay >= 365) { if (iDay == 0 || iDay >= 365)
{
return false; return false;
} }
return true; return true;
} }
bool PIDGEN2::isValidRetailProductID(char* productID) { bool PIDGEN2::isValidRetailProductID(char *productID)
{
return true; return true;
} }
int PIDGEN2::GenerateRetail(char* channelID, char* &keyout) { int PIDGEN2::GenerateRetail(char *channelID, char *&keyout)
if (!isValidChannelID(channelID)) { {
if (!isValidChannelID(channelID))
{
return 1; return 1;
} }
return 0; return 0;
} }
int PIDGEN2::GenerateOEM(char* year, char* day, char* oem, char* &keyout) { int PIDGEN2::GenerateOEM(char *year, char *day, char *oem, char *&keyout)
if (!isValidOEMID(oem)) { {
if (!isValidOEMID(oem))
{
int mod = addDigits(oem); int mod = addDigits(oem);
mod += mod % 21; mod += mod % 21;
strcpy(oem, fmt::format("{:07d}", mod).c_str()); strcpy(oem, fmt::format("{:07d}", mod).c_str());
} }
if (!isValidYear(year)) { if (!isValidYear(year))
{
strcpy(year, validYears[0]); strcpy(year, validYears[0]);
} }
if (!isValidDay(day)) { if (!isValidDay(day))
{
int iday = std::stoi(day); int iday = std::stoi(day);
iday = (iday + 1) % 365; iday = (iday + 1) % 365;
} }

View File

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

View File

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

View File

@ -25,43 +25,18 @@
#include "PIDGEN3.h" #include "PIDGEN3.h"
EXPORT class PIDGEN3::BINK2002 { EXPORT class PIDGEN3::BINK2002
public: {
static void Unpack( public:
QWORD (&pRaw)[2], static void Unpack(QWORD (&pRaw)[2], BOOL &pUpgrade, DWORD &pChannelID, DWORD &pHash, QWORD &pSignature,
BOOL &pUpgrade, DWORD &pAuthInfo);
DWORD &pChannelID,
DWORD &pHash,
QWORD &pSignature,
DWORD &pAuthInfo
);
static void Pack( static void Pack(QWORD (&pRaw)[2], BOOL pUpgrade, DWORD pChannelID, DWORD pHash, QWORD pSignature, DWORD pAuthInfo);
QWORD (&pRaw)[2],
BOOL pUpgrade,
DWORD pChannelID,
DWORD pHash,
QWORD pSignature,
DWORD pAuthInfo
);
static bool Verify( static bool Verify(EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, char (&cdKey)[25]);
EC_GROUP *eCurve,
EC_POINT *basePoint,
EC_POINT *publicKey,
char (&cdKey)[25]
);
static void Generate( static void Generate(EC_GROUP *eCurve, EC_POINT *basePoint, BIGNUM *genOrder, BIGNUM *privateKey, DWORD pChannelID,
EC_GROUP *eCurve, DWORD pAuthInfo, BOOL pUpgrade, char (&pKey)[25]);
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" #include "../libumskt.h"
class PIDGEN3 { class PIDGEN3
public: {
public:
class BINK1998; class BINK1998;
class BINK2002; class BINK2002;
// util.cpp // 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 void endian(BYTE *data, int length);
static EC_GROUP* initializeEllipticCurve( static EC_GROUP *initializeEllipticCurve(std::string pSel, std::string aSel, std::string bSel,
std::string pSel, std::string generatorXSel, std::string generatorYSel,
std::string aSel, std::string publicKeyXSel, std::string publicKeyYSel, EC_POINT *&genPoint,
std::string bSel, EC_POINT *&pubPoint);
std::string generatorXSel,
std::string generatorYSel,
std::string publicKeyXSel,
std::string publicKeyYSel,
EC_POINT *&genPoint,
EC_POINT *&pubPoint
);
// key.cpp // key.cpp
static constexpr char pKeyCharset[] = "BCDFGHJKMPQRTVWXY2346789"; static constexpr char pKeyCharset[] = "BCDFGHJKMPQRTVWXY2346789";
@ -51,4 +46,4 @@ public:
static void base24(char *cdKey, BYTE *byteSeq); static void base24(char *cdKey, BYTE *byteSeq);
}; };
#endif //UMSKT_PIDGEN3_H #endif // UMSKT_PIDGEN3_H

View File

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

View File

@ -22,14 +22,17 @@
#include "PIDGEN3.h" #include "PIDGEN3.h"
int randomRange() { int randomRange()
{
return 4; // chosen by fair dice roll return 4; // chosen by fair dice roll
// guaranteed to be random // guaranteed to be random
} }
/* Convert data between endianness types. */ /* Convert data between endianness types. */
void PIDGEN3::endian(BYTE *data, int length) { void PIDGEN3::endian(BYTE *data, int length)
for (int i = 0; i < length / 2; i++) { {
for (int i = 0; i < length / 2; i++)
{
BYTE temp = data[i]; BYTE temp = data[i];
data[i] = data[length - i - 1]; data[i] = data[length - i - 1];
data[length - i - 1] = temp; data[length - i - 1] = temp;
@ -37,17 +40,11 @@ void PIDGEN3::endian(BYTE *data, int length) {
} }
/* Initializes the elliptic curve. */ /* Initializes the elliptic curve. */
EC_GROUP* PIDGEN3::initializeEllipticCurve( EC_GROUP *PIDGEN3::initializeEllipticCurve(const std::string pSel, const std::string aSel, const std::string bSel,
const std::string pSel, const std::string generatorXSel, const std::string generatorYSel,
const std::string aSel, const std::string publicKeyXSel, const std::string publicKeyYSel,
const std::string bSel, EC_POINT *&genPoint, EC_POINT *&pubPoint)
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. // Initialize BIGNUM and BIGNUMCTX structures.
// BIGNUM - Large numbers // BIGNUM - Large numbers
// BIGNUMCTX - Context large numbers (temporary) // BIGNUMCTX - Context large numbers (temporary)
@ -83,7 +80,8 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
/* Elliptic Curve calculations. */ /* Elliptic Curve calculations. */
// The group is defined via Fp = all integers [0; p - 1], where p is prime. // 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); 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). // 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); pubPoint = EC_POINT_new(eCurve);
EC_POINT_set_affine_coordinates(eCurve, pubPoint, publicKeyX, publicKeyY, context); 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, genPoint, context) == true);
assert(EC_POINT_is_on_curve(eCurve, pubPoint, context) == true); assert(EC_POINT_is_on_curve(eCurve, pubPoint, context) == true);
@ -111,14 +110,19 @@ EC_GROUP* PIDGEN3::initializeEllipticCurve(
return eCurve; 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) if (a == nullptr || to == nullptr)
{
return 0; return 0;
}
int len = BN_bn2bin(a, to); int len = BN_bn2bin(a, to);
if (len > tolen) if (len > tolen)
{
return -1; return -1;
}
// Choke point inside BN_bn2lebinpad: OpenSSL uses len instead of tolen. // Choke point inside BN_bn2lebinpad: OpenSSL uses len instead of tolen.
endian(to, tolen); endian(to, tolen);

View File

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

View File

@ -23,8 +23,8 @@
#ifndef UMSKT_TYPEDEFS_H #ifndef UMSKT_TYPEDEFS_H
#define UMSKT_TYPEDEFS_H #define UMSKT_TYPEDEFS_H
#include <cstdint>
#include <cstdbool> #include <cstdbool>
#include <cstdint>
#ifdef DEBUG #ifdef DEBUG
#include <cassert> #include <cassert>
@ -56,4 +56,4 @@ typedef uint64_t QWORD;
typedef unsigned __int128 OWORD; typedef unsigned __int128 OWORD;
#endif #endif
#endif //UMSKT_TYPEDEFS_H #endif // UMSKT_TYPEDEFS_H

View File

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