mirror of
https://github.com/Neo-Desktop/WindowsXPKg
synced 2024-11-10 16:01:00 +02:00
standardize using clang-format
This commit is contained in:
parent
8cc691b72f
commit
c0a4c76b54
216
.clang-format
Normal file
216
.clang-format
Normal 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
|
||||||
|
...
|
||||||
|
|
432
src/cli.cpp
432
src/cli.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
25
src/cli.h
25
src/cli.h
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
14
src/main.cpp
14
src/main.cpp
@ -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();
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user